Starsector API
Loading...
Searching...
No Matches
TurbulenceCalc2.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.velfield;
2
3import java.util.ArrayList;
4import java.util.List;
5
6import org.lwjgl.util.vector.Vector2f;
7
8import com.fs.starfarer.api.util.Misc;
9
10public class TurbulenceCalc2 {
11
12 public static class TurbulenceParams {
13 public VelocityField field;
14 public float effectWidth;
15 public float effectLength;
16 public float propagationAmount;
17
18 public float maxDispersionAngle = 120f;
19 public float energyTransferMult = 5f; // should be 2 for proper energy conservation, but something's off
20 public float dampenFactor = 0.2f;
21 public float maxVelocity = 1000f;
22 }
23
24 public static class DeltaData {
25 public Vector2f delta;
26 public Vector2f velocity;
27 public Vector2f dir;
28 public float weight;
29 public DeltaData(Vector2f delta, Vector2f velocity, Vector2f dir, float weight) {
30 this.delta = delta;
31 this.velocity = velocity;
32 this.dir = dir;
33 this.weight = weight;
34 }
35 }
36
37
38 public static void advance(TurbulenceParams params) {
39
40 if (params.propagationAmount > 1f) params.propagationAmount = 1f;
41
42 Vector2f[][] f = params.field.getField();
43 float s = params.field.getCellSize();
44
45 float effectWidth = params.effectWidth;
46 float effectLength = params.effectLength;
47
48 Vector2f[][] delta = new Vector2f[f.length][f[0].length];
49 for (int i = 0; i < f.length; i++) {
50 for (int j = 0; j < f[0].length; j++) {
51 delta[i][j] = new Vector2f();
52 }
53 }
54
55
56
57 for (int i = 0; i < f.length; i++) {
58 for (int j = 0; j < f[0].length; j++) {
59
60 float cx = i * s;
61 float cy = j * s;
62 Vector2f v = f[i][j];
63
64 Vector2f dir = Misc.normalise(new Vector2f(v));
65
66 Vector2f p1 = new Vector2f(dir);
67 p1.scale(-effectLength * 0.5f);
68 p1.x += cx;
69 p1.y += cy;
70
71 Vector2f p2 = new Vector2f(dir);
72 p2.scale(effectLength * 0.5f);
73 //p2.scale(effectLength);
74 p2.x += cx;
75 p2.y += cy;
76
77 float minX = Math.min(p1.x - effectWidth * 0.5f, p2.x - effectWidth * 0.5f);
78 float maxX = Math.max(p1.x + effectWidth * 0.5f, p2.x + effectWidth * 0.5f);
79 float minY = Math.min(p1.y - effectLength * 0.5f, p2.y - effectLength * 0.5f);
80 float maxY = Math.max(p1.y + effectLength * 0.5f, p2.y + effectLength * 0.5f);
81
82 int cellX1 = (int) (minX / s);
83 int cellY1 = (int) (minY / s);
84 if (minX < 0) cellX1 = (int) (-1f * Math.abs(minX) / s) - 1;
85 if (minY < 0) cellY1 = (int) (-1f * Math.abs(minY) / s) - 1;
86
87 int cellX2 = (int) (maxX / s);
88 int cellY2 = (int) (maxY / s);
89 if (maxX < 0) cellX2 = (int) (-1f * Math.abs(maxX) / s) - 1;
90 if (maxY < 0) cellY2 = (int) (-1f * Math.abs(maxY) / s) - 1;
91 maxX += 1;
92 maxY += 1;
93
94 float velDir = Misc.getAngleInDegrees(dir);
95 velDir = Misc.normalizeAngle(velDir);
96
97// if (speed > 0) {
98// System.out.println("efwefwef");
99// }
100
101 //if (true) continue;
102 List<DeltaData> deltaData = new ArrayList<TurbulenceCalc2.DeltaData>();
103 for (int a = cellX1; a <= cellX2; a++) {
104 for (int b = cellY1; b <= cellY2; b++) {
105 if (a == i && b == j) continue;
106
107 Vector2f p3 = new Vector2f(a * s, b * s);
108
109 float u = (p3.x - p1.x) * (p2.x - p1.x) + (p3.y - p1.y) * (p2.y - p1.y);
110 float denom = Vector2f.sub(p2, p1, new Vector2f()).length();
111 denom *= denom;
112 if (denom == 0) continue;
113 u /= denom;
114
115 if (u >= 0 && u <= 1) { // intersection is between p1 and p2
116 Vector2f intersect = new Vector2f();
117 intersect.x = p1.x + u * (p2.x - p1.x);
118 intersect.y = p1.y + u * (p2.y - p1.y);
119 float distFromLine = Vector2f.sub(intersect, p3, new Vector2f()).length();
120 float distAlongLine = Math.abs((u - 0.5f) * effectLength);
121 if (distFromLine > effectWidth * 0.5f) continue;
122 if (distAlongLine > effectLength * 0.5f) continue;
123
124 float rateMult = (0.5f * (1f - distFromLine / (effectWidth * 0.5f))) +
125 (0.5f * (1f - distAlongLine / (effectLength * 0.5f)));
126// if (distFromLine <= 0f) {
127// System.out.println("efwfwefwe");
128// }
129 float offsetMult = (distFromLine / (effectWidth * 0.5f)) *
130 (0.5f + 0.5f * distAlongLine / (effectLength * 0.5f));
131 float deltaAngleOffset = offsetMult * params.maxDispersionAngle;
132 //float offsetDir = Misc.getClosestTurnDirection(velDir, Misc.getAngleInDegrees(p1, p3));
133
134 float offsetDir = 0f;
135 float diff = Misc.normalizeAngle(Misc.getAngleInDegrees(p1, p3)) - velDir;
136 //diff = Misc.normalizeAngle(diff);
137 if (diff < 0) diff += 360;
138 if (diff == 0 || diff == 360f) {
139 offsetDir = 0f;
140 } else if (diff > 180) {
141 offsetDir = -1f;
142 } else {
143 offsetDir = 1f;
144 }
145 //offsetDir = Misc.getClosestTurnDirection(velDir, Misc.getAngleInDegrees(p1, p3));
146// float offsetDir2 = Misc.getClosestTurnDirection(velDir, Misc.getAngleInDegrees(p1, p3));
147// if (offsetDir != offsetDir2) {
148// System.out.println("NOT THE SAME");
149// }
150
151
152 Vector2f dv = Misc.getUnitVectorAtDegreeAngle(velDir + deltaAngleOffset * offsetDir);
153 Vector2f d = getCell(delta, a, b);
154 Vector2f destVel = getCell(f, a, b);
155
156 DeltaData data = new DeltaData(d, destVel, dv, rateMult);
157 deltaData.add(data);
158 }
159 }
160 }
161
162 float totalWeight = 0f;
163 for (DeltaData data : deltaData) {
164 totalWeight += data.weight;
165 }
166
167 float speed = v.length();
168 float energy = 0.5f * speed * speed;
169 float energyToTransfer = energy * params.propagationAmount;
170
171 if (totalWeight > 0) {
172 for (DeltaData data : deltaData) {
173 float mult = data.weight / totalWeight;
174 float energyToAdd = energyToTransfer * mult;
175
176 // 0.5 Vold^2 + energyToAdd = 0.5 Vnew^2
177 // Vold^2 + 2 energyToAdd = Vnew^2
178 float speedOther = data.velocity.length();
179 float speedOtherNew = (float) Math.sqrt(speedOther * speedOther + params.energyTransferMult * energyToAdd);
180 float speedAdd = speedOtherNew - speedOther;
181 data.delta.x += data.dir.x * speedAdd;
182 data.delta.y += data.dir.y * speedAdd;
183 }
184// if (speedToTransfer > 0) {
185// System.out.println("To transfer: " + speedToTransfer + ", transferred: " + totalTransferred);
186// }
187 float speedNew = (float) Math.sqrt(speed * speed - 2f * energyToTransfer);
188 float speedAdd = speedNew - speed; // should be a negative number
189 Vector2f deltaForCurrCell = getCell(delta, i, j);
190 deltaForCurrCell.x += dir.x * speedAdd;
191 deltaForCurrCell.y += dir.y * speedAdd;
192 }
193 }
194 }
195
196 float maxVel = params.maxVelocity;
197 for (int i = 0; i < f.length; i++) {
198 for (int j = 0; j < f[0].length; j++) {
199 Vector2f.add(f[i][j], delta[i][j], f[i][j]);
200 float len = f[i][j].length();
201 if (len > maxVel) {
202 f[i][j].scale(maxVel/len);
203 }
204 }
205 }
206
207 // dapmen by a fraction of the propagation rate
208 float dampenFraction = params.dampenFactor;
209 //dampenFraction = 0f;
210 if (dampenFraction > 0) {
211 for (int i = 0; i < f.length; i++) {
212 for (int j = 0; j < f[0].length; j++) {
213 Vector2f v = f[i][j];
214 //Vector2f dv = getCell(delta, i, j);
215
216 float speed = v.length();
217 float dampen = speed * params.propagationAmount * dampenFraction;
218 if (speed > 0f) {
219 v.scale((speed - dampen) / speed);
220 }
221 }
222 }
223 }
224
225 }
226
227 public static Vector2f getCell(Vector2f [][] data, int i, int j) {
228 if (i < 0 || j < 0) return new Vector2f();
229 if (i >= data.length || j >= data[0].length) return new Vector2f();
230 return data[i][j];
231 }
232
233 public static void addCell(Vector2f[][] field, Vector2f[][] delta, int fromX, int fromY, int x, int y, Vector2f dir, float propagationMult) {
234 Vector2f cell = getCell(field, fromX, fromY);
235 Vector2f d = getCell(delta, x, y);
236 Vector2f dFrom = getCell(delta, fromX, fromY);
237 float dot = Vector2f.dot(cell, dir);
238
239 d.x += dir.x * dot * propagationMult;
240 d.y += dir.y * dot * propagationMult;
241
242 dFrom.x -= dir.x * dot * propagationMult;
243 dFrom.y -= dir.y * dot * propagationMult;
244 }
245
246 public static void addCell(Vector2f cell, Vector2f dir, Vector2f delta) {
247 float dot = Vector2f.dot(cell, dir);
248 delta.x += dir.x * dot;
249 delta.y += dir.y * dot;
250 }
251}
252
253
254
255
256
257
258
static void addCell(Vector2f[][] field, Vector2f[][] delta, int fromX, int fromY, int x, int y, Vector2f dir, float propagationMult)
static Vector2f getCell(Vector2f[][] data, int i, int j)
static void addCell(Vector2f cell, Vector2f dir, Vector2f delta)