Starsector API
Loading...
Searching...
No Matches
SlipstreamEntityPlugin2.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.velfield;
2
3import java.awt.Color;
4import java.util.ArrayList;
5import java.util.Iterator;
6import java.util.LinkedHashMap;
7import java.util.LinkedHashSet;
8import java.util.List;
9import java.util.Map;
10import java.util.Set;
11
12import org.lwjgl.input.Mouse;
13import org.lwjgl.opengl.GL11;
14import org.lwjgl.opengl.GL14;
15import org.lwjgl.util.vector.Vector2f;
16
17import com.fs.starfarer.api.Global;
18import com.fs.starfarer.api.campaign.CampaignEngineLayers;
19import com.fs.starfarer.api.campaign.CampaignFleetAPI;
20import com.fs.starfarer.api.campaign.SectorEntityToken;
21import com.fs.starfarer.api.combat.ViewportAPI;
22import com.fs.starfarer.api.fleet.FleetMemberViewAPI;
23import com.fs.starfarer.api.graphics.SpriteAPI;
24import com.fs.starfarer.api.impl.campaign.BaseCustomEntityPlugin;
25import com.fs.starfarer.api.impl.campaign.terrain.HyperspaceTerrainPlugin;
26import com.fs.starfarer.api.util.FaderUtil;
27import com.fs.starfarer.api.util.Misc;
28import com.fs.starfarer.api.util.MutatingVertexUtil;
29import com.fs.starfarer.api.util.WeightedRandomPicker;
30
32
33 public static class SlipstreamSegment {
34 public Vector2f locB = new Vector2f();
35 public Vector2f loc = new Vector2f();
36 public Vector2f dir = new Vector2f();
37 public float width;
38
39 transient public float wobbledWidth;
40 transient public int index = 0;
41 transient public Vector2f normal = new Vector2f();
42 transient public float tx = 0f;
43 transient public float txe1 = 0f;
44 transient public float txe2 = 0f;
45 transient public float totalLength;
46 transient public float lengthToPrev;
47 transient public float lengthToNext;
48
49 public MutatingVertexUtil wobble1;
50 public MutatingVertexUtil wobble2;
51 public FaderUtil fader = new FaderUtil(0f, 1f, 1f);
52 }
53
54 public static class SlipstreamParticle {
55 float speed;
56 float dist;
57 float yPos;
58 Color color;
59 float remaining;
60 float elapsed;
61 }
62
63 public static class SlipstreamParams2 {
64 public String spriteKey1 = "slipstream";
65 public String edgeKey = "slipstream_edge3";
66 public Color spriteColor = new Color(0.3f, 0.5f, 1f, 1f);
67 public Color windGlowColor = new Color(0.3f, 0.5f, 1f, 1f);
68 public Color edgeColor = Color.white;
69 public float edgeWidth = 256;
70 //public float width;
71 public float areaPerParticle = 2875;
72 public int maxParticles = 2000;
73 //public int numParticles;
74 public float minSpeed;
75 public float maxSpeed;
76 public int burnLevel = 30;
77 public Color minColor;
78 public Color maxColor;
79 public float particleFadeInTime = 1f;
80 public float minDur = 0f;
81 public float maxDur = 4f;
82 public float lineLengthFractionOfSpeed = 0.5f;
83 public boolean slowDownInWiderSections = false;
84 public float widthForMaxSpeed = 1f;
85 public float widthForMaxSpeedMinMult = 0.5f;
86 public float widthForMaxSpeedMaxMult = 1.5f;
87 }
88
89 public static int MAX_PARTICLES_ADD_PER_FRAME = 250;
90
91 public static float RAD_PER_DEG = 0.01745329251f;
92 public static Vector2f rotateAroundOrigin(Vector2f v, float cos, float sin) {
93 Vector2f r = new Vector2f();
94 r.x = v.x * cos - v.y * sin;
95 r.y = v.x * sin + v.y * cos;
96 return r;
97 }
98
99
100
101 protected SlipstreamParams2 params = new SlipstreamParams2();
102
103 protected List<SlipstreamSegment> segments = new ArrayList<SlipstreamEntityPlugin2.SlipstreamSegment>();
104 protected float totalLength = 0f;
105
106 protected transient List<SlipstreamParticle> particles = new ArrayList<SlipstreamParticle>();
107 protected transient int [] lengthToIndexMap;
108 protected transient int lengthDivisor;
109
110 protected boolean needsRecompute = true;
111 protected List<BoundingBox> bounds = new ArrayList<BoundingBox>();
112 protected int segmentsPerBox;
113
115 }
116
117 public void setNeedsRecompute() {
118 this.needsRecompute = true;
119 }
120
122 float minSegmentLength = Float.MAX_VALUE;
123 for (SlipstreamSegment curr : segments) {
124 if (curr.lengthToNext > 0 && minSegmentLength > curr.lengthToNext) {
125 minSegmentLength = curr.lengthToNext;
126 }
127 }
128 if (minSegmentLength < 50f) minSegmentLength = 50f;
129
130 lengthDivisor = (int) (minSegmentLength - 1f);
131 int numIndices = (int) (totalLength / lengthDivisor);
132 lengthToIndexMap = new int [numIndices];
133
134 int lengthSoFar = 0;
135 for (int i = 0; i < segments.size(); i++) {
136 SlipstreamSegment curr = segments.get(i);
137 while (lengthSoFar < curr.totalLength + curr.lengthToNext) {
138 int lengthIndex = lengthSoFar / lengthDivisor;
139 if (lengthIndex < lengthToIndexMap.length) {
140 lengthToIndexMap[lengthIndex] = i;
141 }
142 lengthSoFar += lengthDivisor;
143 }
144 }
145 }
146
147 public SlipstreamSegment getSegmentForDist(float distAlongStream) {
148 if (lengthToIndexMap == null) return null;
149 int mapIndex = (int) (distAlongStream / lengthDivisor);
150 if (mapIndex < 0 || mapIndex >= lengthToIndexMap.length) return null;
151 //System.out.println("Index: " + mapIndex + ", dist: " + distAlongStream);
152 int segIndex = lengthToIndexMap[mapIndex];
153 SlipstreamSegment segment = segments.get(segIndex);
154 while (distAlongStream < segment.totalLength) {
155 segIndex--;
156 if (segIndex < 0) return null;
157 segment = segments.get(segIndex);
158 }
159 while (distAlongStream > segment.totalLength + segment.lengthToNext) {
160 segIndex++;
161 if (segIndex >= segments.size()) return null;
162 segment = segments.get(segIndex);
163 }
164 return segment;
165 }
166
167 public void addSegment(Vector2f loc, float width) {
168 SlipstreamSegment s = new SlipstreamSegment();
169 s.loc.set(loc);
170 s.width = width;
171
172 float minRadius = 0f;
173 float maxRadius = s.width * 0.05f;
174 float rate = maxRadius * 0.5f;
175 float angleRate = 50f;
176 s.wobble1 = new MutatingVertexUtil(minRadius, maxRadius, rate, angleRate);
177 s.wobble2 = new MutatingVertexUtil(minRadius, maxRadius, rate, angleRate);
178
179 s.fader.fadeIn();
180
181 segments.add(s);
183 }
184
185 public void init(SectorEntityToken entity, Object pluginParams) {
186 super.init(entity, pluginParams);
187 this.params = (SlipstreamParams2) pluginParams;
188 fader.fadeIn();
189 readResolve();
190 }
191
192 public float getRenderRange() {
193 return totalLength * 0.6f + 1000f;
194 //return totalLength + 1000f;
195 }
196
197 Object readResolve() {
198 if (particles == null) {
199 particles = new ArrayList<SlipstreamParticle>();
200 }
201 return this;
202 }
203
204 public void advance(float amount) {
205 if (!entity.isInCurrentLocation()) return;
206
207 applyEffectToFleets(amount);
208
209 fader.advance(amount);
210
211
212// entity.getLocation().x += Misc.getSpeedForBurnLevel(params.burnLevel) * amount;
213// entity.setFacing(0f);
214// entity.getLocation().set(Global.getSector().getPlayerFleet().getLocation().x + 500,
215// Global.getSector().getPlayerFleet().getLocation().y + 1000f);
216// entity.getLocation().set(Global.getSector().getPlayerFleet().getLocation());
217
218 params.minColor = new Color(0.5f, 0.3f, 0.75f, 0.85f);
219 params.maxColor = new Color(0.5f, 0.6f, 1f, 1f);
220 params.spriteColor = new Color(0.3f, 0.5f, 1f, 1f);
221 params.minDur = 1f;
222 params.maxDur = 4f;
223 params.minSpeed = 700f;
224 params.maxSpeed = 1500f;
225 //params.lineLengthFractionOfSpeed = 0.5f;
226 //params.lineLengthFractionOfSpeed = 1f;
227 //params.lineLengthFractionOfSpeed = 0.15f;
228 params.burnLevel = 30;
229 //params.burnLevel = 1000;
230 //params.particleFadeInTime = 0.01f;
231 params.minSpeed = Misc.getSpeedForBurnLevel(params.burnLevel - 5);
232 params.maxSpeed = Misc.getSpeedForBurnLevel(params.burnLevel + 5);
233 params.lineLengthFractionOfSpeed = 0.25f * Math.max(0.25f, Math.min(1f, 30f / (float) params.burnLevel));
234 //params.burnLevel = 200;
235 //params.numParticles = 2000;
236 //params.numParticles = 1;
237 params.minColor = new Color(0.5f, 0.3f, 0.75f, 0.1f);
238 params.maxColor = new Color(0.5f, 0.6f, 1f, 0.5f);
239
240
241 float width = 512;
242 params.widthForMaxSpeed = width;
243 params.slowDownInWiderSections = true;
244 params.widthForMaxSpeedMinMult = 0.5f;
245
246 params.edgeWidth = 256f;
247 params.spriteColor = new Color(0.3f, 0.5f, 1f, 0.5f);
248 params.edgeColor = new Color(0.3f, 0.5f, 1f, 0.75f);
249 params.edgeColor = Color.white;
250
251 //params.edgeWidth = 128f;
252 //params.minDur = 2f;
253 //params.maxDur = 2f;
254 params.minDur = 2f;
255 params.maxDur = 6f;
256
257 params.areaPerParticle = 10000;
258 //params.areaPerParticle = 10f;
259 //params.maxParticles = 100000;
260 //MAX_PARTICLES_ADD_PER_FRAME = 2000;
261
262
263// params.minSpeed = Misc.getSpeedForBurnLevel(16f);
264// params.maxSpeed = Misc.getSpeedForBurnLevel(16f);
265// params.numParticles = 0;
266
267 //segments.clear();
268// if (segments.isEmpty()) {
269// float currX = entity.getLocation().x + 200f;
270// addSegment(new Vector2f(currX, entity.getLocation().y), 1600f);
271// currX += 200f;
272// addSegment(new Vector2f(currX, entity.getLocation().y), 1200f);
273// currX += 300f;
274// addSegment(new Vector2f(currX, entity.getLocation().y), 800f);
275// currX += 400f;
276// addSegment(new Vector2f(currX, entity.getLocation().y), 700f);
277// currX += 500f;
278// addSegment(new Vector2f(currX, entity.getLocation().y), 600f);
279// currX += 600f;
280// addSegment(new Vector2f(currX, entity.getLocation().y), 512f);
281// }
282 if (segments.isEmpty()) {
283 float spacing = 200f;
284// for (int i = 0; i < 100; i++) {
285// addSegment(new Vector2f(entity.getLocation().x + i * spacing, entity.getLocation().y), params.width);
286// }
287// float x = segments.get(segments.size() - 1).loc.x;
288// float y = segments.get(segments.size() - 1).loc.y;
289// addSegment(new Vector2f(x + 200f, y - 100f), params.width);
290// addSegment(new Vector2f(x + 400f, y - 200f), params.width);
291// addSegment(new Vector2f(x + 600f, y - 300f), params.width);
292// addSegment(new Vector2f(x + 800f, y - 400f), params.width);
293// addSegment(new Vector2f(x + 1000f, y - 500f), params.width);
294// addSegment(new Vector2f(x + 1000f, y - 600f), params.width);
295// addSegment(new Vector2f(x + 800f, y - 700f), params.width);
296// addSegment(new Vector2f(x + 600f, y - 800f), params.width);
297// addSegment(new Vector2f(x + 400f, y - 900f), params.width);
298// addSegment(new Vector2f(x + 200f, y - 1000f), params.width);
299// for (int i = 100; i >= 0; i--) {
300// addSegment(new Vector2f(entity.getLocation().x + i * spacing, entity.getLocation().y - 1100), params.width);
301// }
302
303 int iter = 1000;
304 for (int i = 0; i < iter; i++) {
305 float yOff = (float) Math.sin(i * 0.05f);
306 addSegment(new Vector2f(entity.getLocation().x + i * spacing,
307 //addSegment(new Vector2f(entity.getLocation().x + i * (spacing + (50 - i) * 5),
308 entity.getLocation().y + yOff * 2000f),
309 //width);
310 //width * (0.7f + (float) Math.random() * 0.7f));
311 width + i * 10f);
312 }
313// float spacing = 1000f;
314// for (int i = 0; i < 500; i++) {
315// float yOff = 0f;
316// addSegment(new Vector2f(entity.getLocation().x + i * spacing,
317// //addSegment(new Vector2f(entity.getLocation().x + i * (spacing + (50 - i) * 5),
318// entity.getLocation().y + yOff * 2000f),
319// //width);
320// //width * (0.7f + (float) Math.random() * 0.7f));
321// width + 500f + i * 2f);
322// }
323 }
324
326 advanceNearbySegments(amount);
327
328 addParticles();
329 advanceParticles(amount);
330 }
331
332
333 public void recomputeIfNeeded() {
334 if (!needsRecompute) return;
335 recompute();
336 }
337
338 public void recompute() {
339 needsRecompute = false;
340
341 // compute average location, set segment indices
342 Vector2f avgLoc = new Vector2f();
343 for (int i = 0; i < segments.size(); i++) {
344 SlipstreamSegment curr = segments.get(i);
345 curr.index = i;
346 Vector2f.add(avgLoc, curr.loc, avgLoc);
347 }
348
349 if (segments.size() > 0) {
350 avgLoc.scale(1f / segments.size());
351 entity.setLocation(avgLoc.x, avgLoc.y);
352 }
353
354
355 SpriteAPI sprite = Global.getSettings().getSprite("misc", params.spriteKey1);
356 SpriteAPI edge = Global.getSettings().getSprite("misc", params.edgeKey);
357
358 // compute texture coordinates etc
359 float tx = 0f;
360 float txe1 = 0f;
361 float txe2 = 0f;
362 float totalLength = 0f;
363 for (int i = 0; i < segments.size(); i++) {
364 SlipstreamSegment prev = null;
365 if (i > 0) prev = segments.get(i - 1);
366 SlipstreamSegment curr = segments.get(i);
367 SlipstreamSegment next = null;
368 SlipstreamSegment next2 = null;
369 SlipstreamSegment next3 = null;
370 if (i < segments.size() - 1) {
371 next = segments.get(i + 1);
372 }
373 if (i < segments.size() - 2) {
374 next2 = segments.get(i + 2);
375 }
376 if (i < segments.size() - 3) {
377 next3 = segments.get(i + 3);
378 }
379
380 if (next == null) {
381 if (prev != null) {
382 curr.dir.set(prev.dir);
383 }
384 } else {
385 Vector2f dir = Vector2f.sub(next.loc, curr.loc, new Vector2f());
386 dir = Misc.normalise(dir);
387 curr.dir = dir;
388 }
389
390 Vector2f dir = curr.dir;
391 Vector2f normal = new Vector2f(-dir.y, dir.x);
392 curr.normal.set(normal);
393
394 float length = 0f;
395 float texLength = 0f;
396 float e1TexLength = 0f;
397 float e2TexLength = 0f;
398 if (prev != null) {
399 Vector2f dir2 = Vector2f.sub(curr.loc, prev.loc, new Vector2f());
400 length = dir2.length();
401 texLength = length / sprite.getWidth();
402 texLength = Math.min(texLength, sprite.getHeight() / curr.width);
403
404 Vector2f edgeCurr = new Vector2f(curr.loc);
405 edgeCurr.x += curr.normal.x * curr.width * 0.5f;
406 edgeCurr.y += curr.normal.y * curr.width * 0.5f;
407
408 Vector2f edgePrev = new Vector2f(prev.loc);
409 edgePrev.x += prev.normal.x * prev.width * 0.5f;
410 edgePrev.y += prev.normal.y * prev.width * 0.5f;
411
412 float length2 = Vector2f.sub(edgeCurr, edgePrev, new Vector2f()).length();
413 e1TexLength = length2 / edge.getWidth() * edge.getHeight() / params.edgeWidth;
414
415
416 edgeCurr = new Vector2f(curr.loc);
417 edgeCurr.x -= curr.normal.x * curr.width * 0.5f;
418 edgeCurr.y -= curr.normal.y * curr.width * 0.5f;
419
420 edgePrev = new Vector2f(prev.loc);
421 edgePrev.x -= prev.normal.x * prev.width * 0.5f;
422 edgePrev.y -= prev.normal.y * prev.width * 0.5f;
423
424 length2 = Vector2f.sub(edgeCurr, edgePrev, new Vector2f()).length();
425 e2TexLength = length2 / edge.getWidth() * edge.getHeight() / params.edgeWidth;
426 }
427
428 tx += texLength;
429 txe1 += e1TexLength;
430 txe2 += e2TexLength;
431 curr.tx = tx;
432 curr.txe1 = txe1;
433 curr.txe2 = txe2;
434 curr.lengthToPrev = length;
435
436 totalLength += length;
437 curr.totalLength = totalLength;
438 //curr.lengthToNext = Misc.getDistance(curr.loc, next.loc);
439 if (prev != null) {
440 prev.lengthToNext = length;
441 }
442
443 if (next != null && next2 != null && next3 != null) {
444 Vector2f p0 = curr.loc;
445 Vector2f p1 = next.loc;
446 Vector2f p2 = next2.loc;
447 Vector2f p3 = next3.loc;
448
449 float p1ToP2 = Misc.getAngleInDegrees(p1, p2);
450 float p2ToP3 = Misc.getAngleInDegrees(p2, p3);
451 float diff = Misc.getAngleDiff(p1ToP2, p2ToP3);
452 float adjustment = Math.min(diff, Math.max(diff * 0.25f, diff - 10f));
453 adjustment = diff * 0.5f;
454 //adjustment = diff * 0.25f;
455 float angle = p1ToP2 + Misc.getClosestTurnDirection(p1ToP2, p2ToP3) * adjustment * 1f + 180f;
456 //angle = Misc.getAngleInDegrees(p3, p2);
457 float dist = Misc.getDistance(p2, p1);
458 Vector2f p1Adjusted = Misc.getUnitVectorAtDegreeAngle(angle);
459 p1Adjusted.scale(dist);
460 Vector2f.add(p1Adjusted, p2, p1Adjusted);
461 next.locB = p1Adjusted;
462 } else if (next != null) {
463 next.locB = next.loc;
464 }
465 if (prev == null) {
466 curr.locB = new Vector2f(curr.loc);
467 }
468 }
469 this.totalLength = totalLength;
470
473 }
474
475 protected void updateBoundingBoxes() {
476 segmentsPerBox = (int) Math.sqrt(segments.size()) + 1;
477 if (segmentsPerBox < 20) segmentsPerBox = 20;
478
479 bounds.clear();
480 for (int i = 0; i < segments.size(); i+= segmentsPerBox) {
481 List<SlipstreamSegment> section = new ArrayList<SlipstreamSegment>();
482 for (int j = i; j < i + segmentsPerBox && j < segments.size(); j++) {
483 section.add(segments.get(j));
484 }
485 if (i + segmentsPerBox < segments.size()) {
486 section.add(segments.get(i + segmentsPerBox));
487 }
488 //BoundingBox box = BoundingBox.create(section);
489 //bounds.add(box);
490 }
491 }
492
493 protected void advanceNearbySegments(float amount) {
494 CampaignFleetAPI pf = Global.getSector().getPlayerFleet();
495 if (pf == null || !entity.isInCurrentLocation()) {
496 return;
497 }
498
499 if (segments.size() > 0) {
500 segments.get(0).fader.forceOut();
501 segments.get(segments.size() - 1).fader.fadeOut();
502 }
503
504 ViewportAPI viewport = Global.getSector().getViewport();
505 float viewRadius = new Vector2f(viewport.getVisibleWidth() * 0.5f, viewport.getVisibleHeight() * 0.5f).length();
506 viewRadius = Math.max(6000f, viewRadius);
507 viewRadius += 1000f;
508 List<SlipstreamSegment> near = getSegmentsNear(viewport.getCenter(), viewRadius);
509
510 // advance fader and wobble, compute wobbledWidth
511 for (int i = 0; i < near.size(); i++) {
512 SlipstreamSegment curr = near.get(i);
513
514 curr.fader.advance(amount);
515
516 float r1 = 0.5f + (float) Math.random() * 1f;
517 float r2 = 0.5f + (float) Math.random() * 1f;
518 curr.wobble1.advance(amount * r1);
519 curr.wobble2.advance(amount * r2);
520// curr.wobble1.vector.set(0, 0);
521// curr.wobble2.vector.set(0, 0);
522
523 Vector2f p1 = new Vector2f(curr.loc);
524 Vector2f p2 = new Vector2f(curr.loc);
525 p1.x += curr.normal.x * curr.width * 0.5f;
526 p1.y += curr.normal.y * curr.width * 0.5f;
527 p2.x -= curr.normal.x * curr.width * 0.5f;
528 p2.y -= curr.normal.y * curr.width * 0.5f;
529
530 p1.x += curr.wobble1.vector.x;
531 p1.y += curr.wobble1.vector.y;
532 p2.x += curr.wobble2.vector.x;
533 p2.y += curr.wobble2.vector.y;
534
535 //curr.wobbledWidth = Misc.getDistance(p1, p2);
536 float d = Misc.getDistance(p1, p2);
537 curr.wobbledWidth = d - params.edgeWidth * 2f * 0.5f;
538 if (curr.wobbledWidth < d * 0.5f) curr.wobbledWidth = d * 0.5f;
539 //curr.wobbledWidth = curr.width;
540
541 if (curr.index > 0) {
542 SlipstreamSegment prev = segments.get(curr.index - 1);
543 Vector2f prev1 = new Vector2f(prev.loc);
544 Vector2f prev2 = new Vector2f(prev.loc);
545 prev1.x += curr.normal.x * curr.width * 0.5f;
546 prev1.y += curr.normal.y * curr.width * 0.5f;
547 prev2.x -= curr.normal.x * curr.width * 0.5f;
548 prev2.y -= curr.normal.y * curr.width * 0.5f;
549
550 float maxWobbleRadius = Math.min(prev.width, curr.width) * 0.05f;
551 float maxWobble1 = Misc.getDistance(p1, prev1) * 0.33f;
552 float maxWobble2 = Misc.getDistance(p2, prev2) * 0.33f;
553 maxWobble1 = Math.min(maxWobbleRadius, maxWobble1);
554 maxWobble2 = Math.min(maxWobbleRadius, maxWobble2);
555 prev.wobble1.radius.setMax(maxWobble1);
556 prev.wobble2.radius.setMax(maxWobble2);
557 curr.wobble1.radius.setMax(maxWobble1);
558 curr.wobble2.radius.setMax(maxWobble2);
559 }
560 }
561 }
562
563
564
565 public void addParticles() {
566 if (Global.getSector().getPlayerFleet() == null) {
567 particles.clear();
568 return;
569 }
570
571 boolean useNewSpawnMethod = true;
572 //useNewSpawnMethod = false;
573
574 if (useNewSpawnMethod) {
575 boolean inCurrentLocation = entity.isInCurrentLocation();
576 boolean inHyperspace = entity.isInHyperspace();
577 boolean spawnForAllSegments = false;
578 ViewportAPI viewport = Global.getSector().getViewport();
579 Vector2f locFrom = viewport.getCenter();
580 float viewRadius = new Vector2f(viewport.getVisibleWidth() * 0.5f, viewport.getVisibleHeight() * 0.5f).length();
581 viewRadius += 2000f;
582 viewRadius = Math.max(viewRadius, 10000f);
583 if (!inCurrentLocation) {
584 if (inHyperspace) {
585 viewRadius = 5000f;
586 locFrom = Global.getSector().getPlayerFleet().getLocationInHyperspace();
587 } else {
588 float dist = Misc.getDistanceToPlayerLY(entity);
589 spawnForAllSegments = dist < 2f;
590 }
591 }
592 Set<SlipstreamSegment> veryNearSet = new LinkedHashSet<SlipstreamEntityPlugin2.SlipstreamSegment>();
593 if (inCurrentLocation) {
594 float veryNearRadius = new Vector2f(viewport.getVisibleWidth() * 0.5f, viewport.getVisibleHeight() * 0.5f).length();
595 viewRadius += 500f;
596 veryNearSet = new LinkedHashSet<SlipstreamEntityPlugin2.SlipstreamSegment>(
597 getSegmentsNear(viewport.getCenter(), veryNearRadius));
598 }
599
600 // viewRadius *= 0.5f;
601 // viewRadius = 500f;
602
603 List<SlipstreamSegment> near;
604 if (spawnForAllSegments) {
605 near = new ArrayList<SlipstreamSegment>(segments);
606 } else {
607 near = getSegmentsNear(locFrom, viewRadius);
608 }
609 Set<SlipstreamSegment> nearSet = new LinkedHashSet<SlipstreamSegment>(near);
610
611 Map<SlipstreamSegment, List<SlipstreamParticle>> particleMap = new LinkedHashMap<SlipstreamEntityPlugin2.SlipstreamSegment, List<SlipstreamParticle>>();
612 //for (SlipstreamParticle p : particles) {
613 Iterator<SlipstreamParticle> iter = particles.iterator();
614 while (iter.hasNext()) {
615 SlipstreamParticle p = iter.next();
616 SlipstreamSegment seg = getSegmentForDist(p.dist);
617 if (seg != null) {
618 if (!nearSet.contains(seg)) {
619 iter.remove();
620 continue;
621 }
622
623 List<SlipstreamParticle> list = particleMap.get(seg);
624 if (list == null) {
625 list = new ArrayList<SlipstreamEntityPlugin2.SlipstreamParticle>();
626 particleMap.put(seg, list);
627 }
628 list.add(p);
629 }
630 }
631
632
633 float totalArea = 0f;
634 int nearParticles = 0;
635 WeightedRandomPicker<SlipstreamSegment> segmentPicker = new WeightedRandomPicker<SlipstreamEntityPlugin2.SlipstreamSegment>();
636
637 // figure out how many particles to add total, and also which segments to add them
638 // to to achieve a relatively even distribution
639 for (int i = 0; i < near.size(); i++) {
640 SlipstreamSegment curr = near.get(i);
641 if (curr.lengthToNext <= 0) continue; // last segment, can't have particles in it since the stream is over
642
643 float area = curr.lengthToNext * curr.width;
644 float desiredParticles = area / params.areaPerParticle;
645 if (desiredParticles < 1) desiredParticles = 1;
646
647 float particlesInSegment = 0;
648 List<SlipstreamParticle> list = particleMap.get(curr);
649 if (list != null) {
650 particlesInSegment = list.size();
651 }
652
653 float mult = 1f;
654 // spawn more particles in visible/nearly visible areas
655 // better to have less visible particles when the player zooms out while paused
656 // than to have less visible particles when zoomed in
657 if (veryNearSet.contains(curr)) mult = 10f;
658
659 float w = desiredParticles - particlesInSegment;
660 w *= mult;
661 if (w < 5f) w = 5f;
662 segmentPicker.add(curr, w);
663 //segmentPicker.add(curr, 1f);
664
665 totalArea += area;
666 nearParticles += particlesInSegment;
667 }
668
669
670 int numParticlesBasedOnArea = (int) (totalArea / params.areaPerParticle);
671 int actualDesired = numParticlesBasedOnArea;
672 if (numParticlesBasedOnArea < 10) numParticlesBasedOnArea = 10;
673 if (numParticlesBasedOnArea > params.maxParticles) numParticlesBasedOnArea = params.maxParticles;
674 //System.out.println("Area: " + totalArea/params.numParticles);
675 //numParticlesBasedOnArea = 20000;
676
677
678 int particlesToAdd = numParticlesBasedOnArea - nearParticles;
679 if (particlesToAdd > MAX_PARTICLES_ADD_PER_FRAME) {
680 particlesToAdd = MAX_PARTICLES_ADD_PER_FRAME;
681 }
682 particlesToAdd = Math.min(particlesToAdd, params.maxParticles - particles.size());
683
684 int added = 0;
685 while (added < particlesToAdd) {
686 added++;
687 SlipstreamSegment seg = segmentPicker.pick();
688 if (seg == null) continue;
689
690 SlipstreamParticle p = new SlipstreamParticle();
691 float fLength = (float) Math.random() * 1f;
692 float fWidth = (float) Math.random() * 2f - 1f;
693
694 float speed = params.minSpeed + (params.maxSpeed - params.minSpeed) * (float) Math.random();
695 float dur = params.minDur + (params.maxDur - params.minDur) * (float) Math.random();
696
697 p.yPos = fWidth;
698 //p.dist = totalLength * fLength;
699 p.dist = seg.totalLength + seg.lengthToNext * fLength;
700 p.speed = speed;
701
702 float intensity = getIntensity(p.yPos);
703 float wMult = getWidthBasedSpeedMult(p.dist);
704 // if (wMult <= 0) {
705 // getWidthBasedSpeedMult(p.dist);
706 // }
707 float speedMult = (0.65f + 0.35f * intensity) * wMult;
708 p.speed *= speedMult;
709
710 p.remaining = dur;
711 p.color = getRandomColor();
712
713 particles.add(p);
714 }
715
716 //System.out.println("Particles: " + particles.size() + " desired based on area: " + actualDesired);
717
718 } else {
719 float totalArea = 0f;
720 for (int i = 0; i < segments.size(); i++) {
721 SlipstreamSegment curr = segments.get(i);
722 totalArea += curr.lengthToPrev * curr.width;
723 }
724
725 int numParticlesBasedOnArea = (int) (totalArea / params.areaPerParticle);
726 if (numParticlesBasedOnArea < 10) numParticlesBasedOnArea = 10;
727 if (numParticlesBasedOnArea > params.maxParticles) numParticlesBasedOnArea = params.maxParticles;
728 //System.out.println("Area: " + totalArea/params.numParticles);
729 //numParticlesBasedOnArea = 20000;
730
731
732 int added = 0;
733 //while (particles.size() < params.numParticles && added < MAX_PARTICLES_ADD_PER_FRAME) {
734 while (particles.size() < numParticlesBasedOnArea && added < MAX_PARTICLES_ADD_PER_FRAME) {
735 added++;
736
737 SlipstreamParticle p = new SlipstreamParticle();
738 float fLength = (float) Math.random() * 1f;
739 float fWidth = (float) Math.random() * 2f - 1f;
740
741 float speed = params.minSpeed + (params.maxSpeed - params.minSpeed) * (float) Math.random();
742 float dur = params.minDur + (params.maxDur - params.minDur) * (float) Math.random();
743
744 p.yPos = fWidth;
745 p.dist = totalLength * fLength;
746 p.speed = speed;
747
748 float intensity = getIntensity(p.yPos);
749 float wMult = getWidthBasedSpeedMult(p.dist);
750 // if (wMult <= 0) {
751 // getWidthBasedSpeedMult(p.dist);
752 // }
753 float speedMult = (0.65f + 0.35f * intensity) * wMult;
754 p.speed *= speedMult;
755
756 p.remaining = dur;
757 p.color = getRandomColor();
758
759 particles.add(p);
760 }
761 }
762 }
763
764 public void advanceParticles(float amount) {
765 Iterator<SlipstreamParticle> iter = particles.iterator();
766 while (iter.hasNext()) {
767 SlipstreamParticle p = iter.next();
768 p.remaining -= amount;
769 p.elapsed += amount;
770 if (p.remaining <= 0) {
771 iter.remove();
772 continue;
773 }
774
775 p.dist += p.speed * amount;
776 }
777 }
778
779 public float getWidthBasedSpeedMult(float distAlong) {
780 float mult = 1f;
781 if (params.slowDownInWiderSections) {
782 SlipstreamSegment curr = getSegmentForDist(distAlong);
783 if (curr != null) {
784 float width = curr.width;
785 if (segments.size() > curr.index + 1) {
786 SlipstreamSegment next = segments.get(curr.index + 1);
787 float f = (distAlong - curr.totalLength) / curr.lengthToNext;
788 if (f < 0) f = 0;
789 if (f > 1) f = 1;
790 width = Misc.interpolate(width, next.width, f);
791 mult = Math.min(params.widthForMaxSpeedMaxMult,
792 params.widthForMaxSpeedMinMult + (1f - params.widthForMaxSpeedMinMult) * params.widthForMaxSpeed / width);
793 }
794 }
795 }
796 return mult;
797 }
798 public float getIntensity(float yOff) {
799 yOff = Math.abs(yOff);
800 float intensity = 1f;
801 if (yOff > 0.5f) {
802 intensity = 1f - 1f * (yOff - 0.5f) / 0.5f;
803 }
804 return intensity;
805 }
806
807 public float getFaderBrightness(float distAlong) {
808 SlipstreamSegment curr = getSegmentForDist(distAlong);
809 if (curr != null) {
810 if (segments.size() > curr.index + 1) {
811 SlipstreamSegment next = segments.get(curr.index + 1);
812 float f = (distAlong - curr.totalLength) / curr.lengthToNext;
813 if (f < 0) f = 0;
814 if (f > 1) f = 1;
815 return Misc.interpolate(curr.fader.getBrightness(), next.fader.getBrightness(), f);
816 } else {
817 return 0f;
818 }
819 }
820 return 0f;
821 }
822
823 public void render(CampaignEngineLayers layer, ViewportAPI viewport) {
825 if (lengthToIndexMap == null) return;
826
827
828 if (true && false) {
829 //BoundingBox box = BoundingBox.create(segments);
830 float mx = Mouse.getX();
831 float my = Mouse.getY();
832 float wmx = Global.getSector().getViewport().convertScreenXToWorldX(mx);
833 float wmy = Global.getSector().getViewport().convertScreenYToWorldY(my);
834 boolean inside = false;
835 for (BoundingBox box : bounds) {
836 box.renderDebug(1f);
837 inside |= box.pointNeedsDetailedCheck(new Vector2f(wmx, wmy));
838 }
839
840 GL11.glDisable(GL11.GL_TEXTURE_2D);
841 GL11.glEnable(GL11.GL_BLEND);
842 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
843
844 GL11.glPointSize(20f);
845 GL11.glEnable(GL11.GL_POINT_SMOOTH);
846 if (inside) {
847 Misc.setColor(Color.green);
848 } else {
849 Misc.setColor(Color.gray);
850 }
851
852 GL11.glBegin(GL11.GL_POINTS);
853 GL11.glVertex2f(wmx, wmy);
854 GL11.glEnd();
855 //return;
856 }
857
858
859
860
861 float viewRadius = new Vector2f(viewport.getVisibleWidth() * 0.5f, viewport.getVisibleHeight() * 0.5f).length();
862 viewRadius += 500f;
863
864// viewRadius *= 0.5f;
865// viewRadius = 500f;
866
867 List<SlipstreamSegment> near = getSegmentsNear(viewport.getCenter(), viewRadius);
868 Set<SlipstreamSegment> nearSet = new LinkedHashSet<SlipstreamSegment>(near);
869
870 List<List<SlipstreamSegment>> subsections = new ArrayList<List<SlipstreamSegment>>();
871 int prevIndex = -10;
872 List<SlipstreamSegment> subsection = new ArrayList<SlipstreamSegment>();
873 for (SlipstreamSegment seg : near) {
874 if (prevIndex != seg.index -1) {
875 if (subsection != null && !subsection.isEmpty()) {
876 subsections.add(subsection);
877 }
878 subsection = new ArrayList<SlipstreamSegment>();
879 }
880 subsection.add(seg);
881 prevIndex = seg.index;
882 }
883 if (subsection != null && !subsection.isEmpty()) {
884 subsections.add(subsection);
885 }
886
887 SpriteAPI sprite = Global.getSettings().getSprite("misc", params.spriteKey1);
888 //sprite.setAdditiveBlend();
889 sprite.setNormalBlend();
890 sprite.setColor(params.spriteColor);
891
892 SpriteAPI edge = Global.getSettings().getSprite("misc", params.edgeKey);
893 edge.setNormalBlend();
894 edge.setColor(params.edgeColor);
895
896 //sprite.setColor(Misc.setAlpha(params.spriteColor1, 255));
897 //sprite.setColor(Color.blue);
898 for (List<SlipstreamSegment> subsection2 : subsections) {
899 renderSegments(sprite, edge, viewport.getAlphaMult(), subsection2);
900 }
901
902 //sprite.setColor(Color.red);
903 //renderLayer(sprite, texProgress2, viewport.getAlphaMult());
904 //sprite.setColor(Color.green);
905 //renderLayer(sprite, texProgress3, viewport.getAlphaMult());
906
907// int state = 0;
908// for (int i = 0; i < segments.size() - 4; i += 2) {
909// //GL11.glBegin(GL11.GL_POINTS);
910// SlipstreamSegment prev = null;
911// if (i > 0) {
912// prev = segments.get(i - 1);
913// }
914// SlipstreamSegment curr = segments.get(i);
915// SlipstreamSegment next = segments.get(i + 1);
916// SlipstreamSegment next2 = segments.get(i + 2);
917// SlipstreamSegment next3 = segments.get(i + 3);
918// Vector2f p0 = curr.loc;
919// Vector2f p1 = next.loc;
920// Vector2f p2 = next2.loc;
921// Vector2f p3 = next3.loc;
922//
923// if (state == 0) {
924// state = 1;
925// float p1ToP2 = Misc.getAngleInDegrees(p1, p2);
926// float p2ToP3 = Misc.getAngleInDegrees(p2, p3);
927// float diff = Misc.getAngleDiff(p1ToP2, p2ToP3);
928// float angle = p1ToP2 + Misc.getClosestTurnDirection(p1ToP2, p2ToP3) * diff * 0.5f + 180f;
929// angle = Misc.getAngleInDegrees(p3, p2);
930// float dist = Misc.getDistance(p2, p1);
931// Vector2f p1Adjusted = Misc.getUnitVectorAtDegreeAngle(angle);
932// p1Adjusted.scale(dist);
933// Vector2f.add(p1Adjusted, p2, p1Adjusted);
934// curr.locB.set(p1Adjusted);
935// } else if (state == 1) {
936// curr.locB.set(curr.loc);
937// } else if (state == 2) {
938//
939// }
940// }
941
942
943
944
945
946 GL11.glDisable(GL11.GL_TEXTURE_2D);
947 GL11.glEnable(GL11.GL_BLEND);
948 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
949
950 float zoom = Global.getSector().getViewport().getViewMult();
951
952 //GL11.glLineWidth(2f);
953 //GL11.glLineWidth(Math.max(1f, 2f/zoom));
954 GL11.glLineWidth(Math.max(1f, Math.min(2f, 2f/zoom)));
955 //GL11.glLineWidth(1.5f);
956 GL11.glEnable(GL11.GL_LINE_SMOOTH);
957
958 Misc.setColor(new Color(1f, 1f, 1f, 0.5f));
959 Misc.setColor(Color.white);
960 //GL11.glLineWidth(1f);
961
962// for (SlipstreamSegment seg : segments) {
963// if (seg.totalLength <= 0f && segments.indexOf(seg) > 1) {
964// System.out.println("efwefwefwefe");
965// }
966// }
967
968 // draw bezier lines for debug
969 for (float offset = -1f; false && offset <= 1f; offset += 0.1f) {
970 //for (float offset = 0f; offset <= 0f; offset += 0.1f) {
971 GL11.glBegin(GL11.GL_LINE_STRIP);
972 float incr = 10f;
973 for (float len = 0; len < totalLength; len += incr) {
974// if (len > 10000f) {
975// System.out.println("ewfwefew");
976// }
977 /*
978 SlipstreamSegment curr = getSegmentForDist(len);
979 if (curr == null) continue;
980 int index = curr.index;
981 if (index >= segments.size() - 2) continue;
982 SlipstreamSegment next = segments.get(index + 1);
983 SlipstreamSegment next2 = segments.get(index + 2);
984
985 if (index % 2 != 0) {
986 curr = segments.get(index - 1);
987 next = segments.get(index);
988 next2 = segments.get(index + 1);
989 }
990
991 float lenForT = len - curr.totalLength;
992 float t = lenForT / (curr.lengthToNext + next.lengthToNext);
993
994 //Vector2f p = Misc.bezier(curr.loc, next.loc, next2.loc, t);
995 Vector2f p0 = curr.loc;
996 Vector2f p1 = next.loc;
997 Vector2f p2 = next2.loc;
998
999 p0 = new Vector2f(p0);
1000 p0.x += curr.normal.x * params.width * 0.5f * offset;
1001 p0.y += curr.normal.y * params.width * 0.5f * offset;
1002
1003 p2 = new Vector2f(p2);
1004 p2.x += next2.normal.x * params.width * 0.5f * offset;
1005 p2.y += next2.normal.y * params.width * 0.5f * offset;
1006
1007 p1 = new Vector2f(next.locB);
1008 p1 = new Vector2f(p1);
1009 p1.x += next.normal.x * params.width * 0.5f * offset;
1010 p1.y += next.normal.y * params.width * 0.5f * offset;
1011
1012 Vector2f p = Misc.bezier(p0, p1, p2, t);
1013
1014// float tPrev = (prev.lengthToNext + len) / (prev.lengthToNext + curr.lengthToNext);
1015// Vector2f pPrev = Misc.bezier(prev.loc, curr.loc, next.loc, tPrev);
1016 //curr.lengthToNext + next.lengthToNext
1017// float f = lenForT / curr.lengthToNext;
1018// Vector2f perp;
1019// if (f < 1f) {
1020// perp = Misc.interpolateVector(curr.normal, next.normal, f);
1021// } else {
1022// f = (lenForT - curr.lengthToNext) / next.lengthToNext;
1026// perp = Misc.interpolateVector(next.normal, next2.normal, f);
1027// }
1028// perp.scale(offset * params.width * 0.5f);
1029 //perp.set(0, 0);
1030
1031 //p = Misc.interpolateVector(pPrev, p, 0.5f);
1032 //GL11.glVertex2f(p.x + perp.x, p.y + perp.y);
1033 *
1034 */
1035
1036 Vector2f p = getPointAt(len, offset);
1037 if (p != null) {
1038 GL11.glVertex2f(p.x, p.y);
1039 }
1040 }
1041 if (false) {
1042 Misc.setColor(Color.red);
1043 for (int i = 0; i < segments.size() - 3; i+=2) {
1044 //GL11.glBegin(GL11.GL_POINTS);
1045 SlipstreamSegment prev = null;
1046 if (i > 0) {
1047 prev = segments.get(i - 1);
1048 }
1049 SlipstreamSegment curr = segments.get(i);
1050 SlipstreamSegment next = segments.get(i + 1);
1051 SlipstreamSegment next2 = segments.get(i + 2);
1052 SlipstreamSegment next3 = segments.get(i + 3);
1053
1054 // GL11.glVertex2f(curr.loc.x, curr.loc.y);
1055 // GL11.glVertex2f(next.loc.x, next.loc.y);
1056 // GL11.glVertex2f(next2.loc.x, next2.loc.y);
1057
1058 Vector2f p0 = curr.loc;
1059 Vector2f p1 = next.loc;
1060 Vector2f p2 = next2.loc;
1061 Vector2f p3 = next3.loc;
1062
1063 // float p1ToP2 = Misc.getAngleInDegrees(p1, p2);
1064 // float p2ToP3 = Misc.getAngleInDegrees(p2, p3);
1065 // float diff = Misc.getAngleDiff(p1ToP2, p2ToP3);
1066 // float adjustment = Math.min(diff, Math.max(diff * 0.25f, diff - 10f));
1067 // adjustment = diff * 0.5f;
1068 // //adjustment = diff * 0.25f;
1069 // float angle = p1ToP2 + Misc.getClosestTurnDirection(p1ToP2, p2ToP3) * adjustment * 1f + 180f;
1070 // //angle = Misc.getAngleInDegrees(p3, p2);
1071 // float dist = Misc.getDistance(p2, p1);
1072 // Vector2f p1Adjusted = Misc.getUnitVectorAtDegreeAngle(angle);
1073 // p1Adjusted.scale(dist);
1074 // Vector2f.add(p1Adjusted, p2, p1Adjusted);
1075
1076 //GL11.glVertex2f(p1Adjusted.x, p1Adjusted.y);
1077 //GL11.glVertex2f(p1.x, p1.y);
1078
1079 p0 = new Vector2f(p0);
1080 p0.x += curr.normal.x * curr.width * 0.5f * offset;
1081 p0.y += curr.normal.y * curr.width * 0.5f * offset;
1082
1083 p2 = new Vector2f(p2);
1084 p2.x += next2.normal.x * next2.width * 0.5f * offset;
1085 p2.y += next2.normal.y * next2.width * 0.5f * offset;
1086
1087 p1 = new Vector2f(next.locB);
1088 p1 = new Vector2f(p1);
1089 p1.x += next.normal.x * next.width * 0.5f * offset;
1090 p1.y += next.normal.y * next.width * 0.5f * offset;
1091
1092 // p1ToP2 = Misc.getAngleInDegrees(p1, p2);
1093 // p2ToP3 = Misc.getAngleInDegrees(p2, p3);
1094 // diff = Misc.getAngleDiff(p1ToP2, p2ToP3);
1095 // adjustment = Math.min(diff, Math.max(diff * 0.25f, diff - 10f));
1096 // adjustment = diff * 0.5f;
1097 // //adjustment = diff * 0.25f;
1098 // angle = p1ToP2 + Misc.getClosestTurnDirection(p1ToP2, p2ToP3) * adjustment * 1f + 180f;
1099 // //angle = Misc.getAngleInDegrees(p3, p2);
1100 // dist = Misc.getDistance(p2, p1);
1101 // p1Adjusted = Misc.getUnitVectorAtDegreeAngle(angle);
1102 // p1Adjusted.scale(dist);
1103 // Vector2f.add(p1Adjusted, p2, p1Adjusted);
1104
1105 incr = 10f;
1106 for (float len = 0; len < curr.lengthToNext + next.lengthToNext; len += incr) {
1107 float t = len / (curr.lengthToNext + next.lengthToNext);
1108 //Vector2f p = Misc.bezier(curr.loc, next.loc, next2.loc, t);
1109 Vector2f p = Misc.bezier(p0, p1, p2, t);
1110
1111 // float tPrev = (prev.lengthToNext + len) / (prev.lengthToNext + curr.lengthToNext);
1112 // Vector2f pPrev = Misc.bezier(prev.loc, curr.loc, next.loc, tPrev);
1113
1114 float f = len / curr.lengthToNext;
1115 Vector2f perp;
1116 if (f < 1f) {
1117 perp = Misc.interpolateVector(curr.normal, next.normal, f);
1118 } else {
1119 f = (len - curr.lengthToNext) / next.lengthToNext;
1120 perp = Misc.interpolateVector(next.normal, next2.normal, f);
1121 }
1122 perp.scale(offset * curr.width * 0.5f);
1123 perp.set(0, 0);
1124
1125 //p = Misc.interpolateVector(pPrev, p, 0.5f);
1126 GL11.glVertex2f(p.x, p.y);
1127 //GL11.glVertex2f(p.x + perp.x, p.y + perp.y);
1128 //GL11.glVertex2f(pPrev.x, pPrev.y);
1129 }
1130 //if (i == 4) break;
1131 }
1132 }
1133 GL11.glEnd();
1134 }
1135
1136// GL11.glBegin(GL11.GL_LINES);
1137// for (int i = 0; i < segments.size() - 4; i+=2) {
1138// //GL11.glBegin(GL11.GL_POINTS);
1139// SlipstreamSegment prev = null;
1140// if (i > 0) {
1141// prev = segments.get(i - 1);
1142// }
1143// SlipstreamSegment curr = segments.get(i);
1144// SlipstreamSegment next = segments.get(i + 1);
1145// SlipstreamSegment next2 = segments.get(i + 2);
1146// SlipstreamSegment next3 = segments.get(i + 3);
1147//
1151//
1152// Vector2f p0 = curr.loc;
1153// Vector2f p1 = next.loc;
1154// Vector2f p2 = next2.loc;
1155// Vector2f p3 = next3.loc;
1156//
1157// float p1ToP2 = Misc.getAngleInDegrees(p1, p2);
1158// float p2ToP3 = Misc.getAngleInDegrees(p2, p3);
1159// float diff = Misc.getAngleDiff(p1ToP2, p2ToP3);
1160// float adjustment = Math.min(diff, Math.max(diff * 0.25f, diff - 10f));
1161// adjustment = diff * 0.5f;
1162// //adjustment = diff * 0.25f;
1163// float angle = p1ToP2 + Misc.getClosestTurnDirection(p1ToP2, p2ToP3) * adjustment * 1f + 180f;
1164// //angle = Misc.getAngleInDegrees(p3, p2);
1165// float dist = Misc.getDistance(p2, p1);
1166// Vector2f p1Adjusted = Misc.getUnitVectorAtDegreeAngle(angle);
1167// p1Adjusted.scale(dist);
1168// Vector2f.add(p1Adjusted, p2, p1Adjusted);
1169//
1170// //skip = diff < 30f;
1171// skip = false;
1172// if (skip) p1Adjusted.set(p1);
1173// skip = !skip;
1174//
1175// prevAdjustedP1 = p1Adjusted;
1176// //GL11.glVertex2f(p1Adjusted.x, p1Adjusted.y);
1177// //GL11.glVertex2f(p1.x, p1.y);
1178//
1179// float incr = 10f;
1180// Misc.setColor(new Color(1f, 0.5f, 0f, 1f));
1181// for (float len = 0; len < curr.lengthToNext + next.lengthToNext; len += incr) {
1182// float t = len / (curr.lengthToNext + next.lengthToNext);
1183// //Vector2f p = Misc.bezier(curr.loc, next.loc, next2.loc, t);
1184// Vector2f p = Misc.bezier(curr.loc, p1Adjusted, next2.loc, t);
1187//
1188// float f = len / curr.lengthToNext;
1189// Vector2f perp;
1190// if (f < 1f) {
1191// perp = Misc.interpolateVector(curr.normal, next.normal, f);
1192// } else {
1193// f = (len - curr.lengthToNext) / next.lengthToNext;
1194// perp = Misc.interpolateVector(next.normal, next2.normal, f);
1195// }
1196//
1197//
1198// perp.scale(1f * params.width * 0.5f);
1199//
1200// //p = Misc.interpolateVector(pPrev, p, 0.5f);
1201// //GL11.glVertex2f(p.x, p.y);
1202// GL11.glVertex2f(p.x + perp.x, p.y + perp.y);
1203// GL11.glVertex2f(p.x - perp.x, p.y - perp.y);
1204// //GL11.glVertex2f(pPrev.x, pPrev.y);
1205// }
1206// //if (i == 4) break;
1207// }
1208// GL11.glEnd();
1209
1210// GL11.glPointSize(10);
1211// GL11.glBegin(GL11.GL_POINTS);
1212// for (int i = 0; i < segments.size() - 4; i+=2) {
1213// if (i % 4 == 0) {
1214// Misc.setColor(Color.red);
1215// } else {
1216// Misc.setColor(Color.green);
1217// }
1218// //GL11.glBegin(GL11.GL_POINTS);
1219// //SlipstreamSegment prev = segments.get(i);
1220// SlipstreamSegment curr = segments.get(i);
1221// SlipstreamSegment next = segments.get(i + 1);
1222// SlipstreamSegment next2 = segments.get(i + 2);
1223// SlipstreamSegment next3 = segments.get(i + 3);
1224//
1228//
1229// Vector2f p0 = curr.loc;
1230// Vector2f p1 = next.loc;
1231// Vector2f p2 = next2.loc;
1232// Vector2f p3 = next3.loc;
1233//
1234// float p1ToP2 = Misc.getAngleInDegrees(p1, p2);
1235// float p2ToP3 = Misc.getAngleInDegrees(p2, p3);
1236// float diff = Misc.getAngleDiff(p1ToP2, p2ToP3);
1237// float angle = p1ToP2 + Misc.getClosestTurnDirection(p1ToP2, p2ToP3) * diff * 1f + 180f;
1238// //angle = Misc.getAngleInDegrees(p3, p2);
1239// float dist = Misc.getDistance(p2, p1);
1240// Vector2f p1Adjusted = Misc.getUnitVectorAtDegreeAngle(angle);
1241// p1Adjusted.scale(dist);
1242// Vector2f.add(p1Adjusted, p2, p1Adjusted);
1243// prevAdjustedP1 = p1Adjusted;
1244// //GL11.glVertex2f(p1Adjusted.x, p1Adjusted.y);
1245// //GL11.glVertex2f(p1.x, p1.y);
1246//
1247// GL11.glVertex2f(p0.x, p0.y);
1248// GL11.glVertex2f(p1Adjusted.x, p1Adjusted.y);
1249// GL11.glVertex2f(p2.x, p2.y);
1250// }
1251// GL11.glEnd();
1252
1253 if (false) {
1254 float[] place = getLengthAndWidthFractionWithinStream(Global.getSector().getPlayerFleet().getLocation());
1255 if (place != null) {
1256 Misc.setColor(Color.red);
1257 GL11.glPointSize(40f/zoom);
1258 GL11.glEnable(GL11.GL_POINT_SMOOTH);
1259 GL11.glBegin(GL11.GL_POINTS);
1260 Vector2f p = getPointAt(place[0], place[1]);
1261
1262 GL11.glVertex2f(p.x, p.y);
1263
1264 Misc.setColor(Color.blue);
1265 p = Global.getSector().getPlayerFleet().getLocation();
1266 GL11.glVertex2f(p.x, p.y);
1267
1268 SlipstreamSegment seg = getSegmentForDist(place[0]);
1269 if (seg != null) {
1270 float withinSeg = place[0] - seg.totalLength;
1271 Vector2f p2 = new Vector2f(seg.normal.y, -seg.normal.x);
1272 p2.scale(withinSeg);
1273 Vector2f.add(p2, seg.loc, p2);
1274 float width = seg.wobbledWidth;
1275 if (segments.size() > seg.index + 1) {
1276 SlipstreamSegment next = segments.get(seg.index + 1);
1277 width = Misc.interpolate(seg.wobbledWidth, next.wobbledWidth,
1278 (place[0] - seg.totalLength) / seg.lengthToNext);
1279 }
1280 p2.x += getNormalAt(place[0]).x * place[1] * width * 0.5f;
1281 p2.y += getNormalAt(place[0]).y * place[1] * width * 0.5f;
1282 Misc.setColor(Color.green);
1283 GL11.glVertex2f(p2.x, p2.y);
1284 }
1285 GL11.glEnd();
1286 }
1287 }
1288
1289// GL11.glBegin(GL11.GL_LINE_STRIP);
1290// for (int i = 1; i < segments.size() - 2; i++) {
1291// SlipstreamSegment prev = segments.get(i);
1292// SlipstreamSegment curr = segments.get(i);
1293// SlipstreamSegment next = segments.get(i + 1);
1294// SlipstreamSegment next2 = segments.get(i + 2);
1295//
1296// float incr = 5f;
1297// for (float len = 0; len < curr.lengthToNext; len += incr) {
1298// float t = len / (curr.lengthToNext + next.lengthToNext);
1299// Vector2f p = Misc.bezier(curr.loc, next.loc, next2.loc, t);
1300//
1301// float tPrev = (prev.lengthToNext + len) / (prev.lengthToNext + curr.lengthToNext);
1302// Vector2f pPrev = Misc.bezier(prev.loc, curr.loc, next.loc, tPrev);
1303//
1304// //p = Misc.interpolateVector(pPrev, p, 0.5f);
1305// //GL11.glVertex2f(p.x, p.y);
1306// GL11.glVertex2f(pPrev.x, pPrev.y);
1307// }
1308// if (i == 4) break;
1309// }
1310// GL11.glEnd();
1311
1312 boolean curvedTrails = true;
1313 boolean useTex = false;
1314 //if (zoom > 1.25f) useTex = false;
1315 //useTex = false;
1316 //System.out.println("USETEX = " + useTex);
1317 if (!useTex) {
1318 GL11.glDisable(GL11.GL_TEXTURE_2D);
1319 GL11.glEnable(GL11.GL_BLEND);
1320 GL11.glLineWidth(Math.max(1f, Math.min(2f, 2f/zoom)));
1321 //GL11.glLineWidth(25f);
1322 GL11.glEnable(GL11.GL_LINE_SMOOTH);
1323 GL11.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST);
1324 }
1325
1326 //curvedTrails = false;
1327 if (!curvedTrails) {
1328 GL11.glBegin(GL11.GL_LINES);
1329 }
1330// GL11.glEnable(GL11.GL_POINT_SMOOTH);
1331// GL11.glPointSize(10f);
1332// GL11.glBegin(GL11.GL_POINTS);
1333 //int index = 0;
1334
1335 if (useTex) {
1336 GL11.glEnable(GL11.GL_TEXTURE_2D);
1337 GL11.glEnable(GL11.GL_BLEND);
1338 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
1339
1340 SpriteAPI line = Global.getSettings().getSprite("graphics/hud/line4x4.png");
1341 //line = Global.getSettings().getSprite("graphics/hud/line32x32.png");
1342 line.bindTexture();
1343 }
1344
1345 for (SlipstreamParticle p : particles) {
1346 SlipstreamSegment seg = getSegmentForDist(p.dist);
1347 if (seg == null || !nearSet.contains(seg)) continue;
1348
1349// index++;
1350// if (index > 1) break;
1351 //if (true) break;
1352 float a = viewport.getAlphaMult();
1353 if (p.remaining <= 0.5f) {
1354 a = p.remaining / 0.5f;
1355 } else if (p.elapsed < params.particleFadeInTime) {
1356 a = p.elapsed / params.particleFadeInTime;
1357 }
1358
1359 a *= getFaderBrightness(p.dist);
1360
1361 //a *= 0.5f;
1362 //a *= 0.1f;
1363
1364 //a = 1f;
1365
1366// SlipstreamSegment seg = getSegmentForDist(p.dist);
1367// if (seg == null) continue;
1368 float yPos = p.yPos;
1369 //yPos = 0f;
1370
1371 if (curvedTrails) {
1372 if (useTex) {
1373 GL11.glBegin(GL11.GL_QUAD_STRIP);
1374 Vector2f curr = getPointAt(p.dist, yPos);
1375 if (curr == null || !viewport.isNearViewport(curr, p.speed * params.lineLengthFractionOfSpeed + 50f)) {
1376 GL11.glEnd();
1377 continue;
1378 }
1379 float iter = 5f;
1380 float incr = p.speed * params.lineLengthFractionOfSpeed / iter;
1381 float lw = 1f;
1382 for (float i = 0; i < iter; i++) {
1383 float min = incr * 1f;
1384 float dist = p.dist - i * incr - min;
1385 Vector2f next = getPointAt(dist, yPos);
1386 if (next == null) break;
1387
1388 Vector2f perp = getNormalAt(dist);
1389 if (perp == null) {
1390 GL11.glEnd();
1391 break;
1392 }
1393
1394 float a1 = a * (iter - i) / (iter - 1);
1395 if (i == 0) a1 = 0f;
1396
1397 Misc.setColor(p.color, a1);
1398 GL11.glTexCoord2f(0, 0f);
1399 GL11.glVertex2f(curr.x + perp.x * lw, curr.y + perp.y * lw);
1400 GL11.glTexCoord2f(0, 1f);
1401 GL11.glVertex2f(curr.x - perp.x * lw, curr.y - perp.y * lw);
1402 curr = next;
1403 }
1404 GL11.glEnd();
1405 } else {
1406 GL11.glBegin(GL11.GL_LINE_STRIP);
1407 //GL11.glBegin(GL11.GL_LINES);
1408 Vector2f curr = getPointAt(p.dist, yPos);
1409 if (curr == null || !viewport.isNearViewport(curr, p.speed * params.lineLengthFractionOfSpeed + 50f)) {
1410 GL11.glEnd();
1411 continue;
1412 }
1413 float iter = 5f;
1414 float incr = p.speed * params.lineLengthFractionOfSpeed / iter;
1415 for (float i = 0; i < iter; i++) {
1416
1417 float min = incr * 0.5f;
1418 Vector2f next = getPointAt(p.dist - i * incr - min, yPos);
1419 if (next == null) {
1420 GL11.glEnd();
1421 break;
1422 }
1423
1424 float a1 = a * (iter - i) / (iter - 1);
1425 //float a2 = a * (iter - i - 1) / (iter - 1);
1426 if (i == 0) a1 = 0f;
1427
1428 Misc.setColor(p.color, a1);
1429 GL11.glVertex2f(curr.x, curr.y);
1430 //Misc.setColor(p.color, a2);
1431 //GL11.glVertex2f(next.x, next.y);
1432 curr = next;
1433 }
1434 GL11.glEnd();
1435 }
1436 } else {
1437 Vector2f start = getPointAt(p.dist + p.speed * params.lineLengthFractionOfSpeed * 0.1f, yPos);
1438 if (start == null || !viewport.isNearViewport(start, 500)) continue;
1439
1440 Vector2f mid = getPointAt(p.dist, yPos);
1441 if (mid == null) continue;
1442 Vector2f end = getPointAt(p.dist - p.speed * params.lineLengthFractionOfSpeed * 0.9f, yPos);
1443 if (end == null) continue;
1444
1445 Misc.setColor(p.color, 0f);
1446 GL11.glVertex2f(start.x, start.y);
1447 Misc.setColor(p.color, a);
1448 GL11.glVertex2f(mid.x, mid.y);
1449 GL11.glVertex2f(mid.x, mid.y);
1450 Misc.setColor(p.color, 0f);
1451 GL11.glVertex2f(end.x, end.y);
1452 }
1453//
1454 }
1455 if (!curvedTrails) {
1456 GL11.glEnd();
1457 }
1458 }
1459
1460
1461 protected FaderUtil fader = new FaderUtil(0f, 0.5f, 0.5f);
1462
1463 public void renderSegments(SpriteAPI sprite, SpriteAPI edge, float alpha, List<SlipstreamSegment> segments) {
1464 //if (true) return;
1465 GL11.glEnable(GL11.GL_TEXTURE_2D);
1466 sprite.bindTexture();
1467 GL11.glEnable(GL11.GL_BLEND);
1468 //GL11.glDisable(GL11.GL_BLEND);
1469 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
1470 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1471 Color color = sprite.getColor();
1472 //color = Misc.interpolateColor(color, Color.black, 0.5f);
1473 //color = Color.black;
1474 //color = Misc.scaleColorOnly(color, 0.3f);
1475 //color = Misc.setAlpha(color, 100);
1476
1477 boolean wireframe = false;
1478 //wireframe = true;
1479 if (wireframe) {
1480 GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
1481 GL11.glDisable(GL11.GL_TEXTURE_2D);
1482 GL11.glDisable(GL11.GL_BLEND);
1483 }
1484
1485 boolean subtract = false;
1486 //subtract = true;
1487 if (subtract) {
1488 GL14.glBlendEquation(GL14.GL_FUNC_REVERSE_SUBTRACT);
1489 }
1490
1491 // "channel"
1492 Color c = Color.black;
1493 //c = Misc.setAlpha(c, 255);
1494 GL11.glDisable(GL11.GL_TEXTURE_2D);
1495 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1496
1497 int alphaInDeep = 255;
1498 int alphaOutside = 0;
1499 HyperspaceTerrainPlugin plugin = (HyperspaceTerrainPlugin) Misc.getHyperspaceTerrain().getPlugin();
1500
1501 GL11.glBegin(GL11.GL_QUAD_STRIP);
1502
1503 for (int i = 0; i < segments.size(); i++) {
1504 SlipstreamSegment curr = segments.get(i);
1505 float a = curr.fader.getBrightness();
1506
1507 if (entity.isInHyperspace() && plugin.isInClouds(curr.loc, 100f)) {
1508 c = Misc.setAlpha(c, alphaInDeep);
1509 } else {
1510 c = Misc.setAlpha(c, alphaOutside);
1511 }
1512
1513 Vector2f p1 = new Vector2f(curr.loc);
1514 p1.x += curr.normal.x * curr.width * 0.5f;
1515 p1.y += curr.normal.y * curr.width * 0.5f;
1516 Vector2f p2 = new Vector2f(curr.loc);
1517 p2.x += curr.normal.x * (curr.width * 0.5f - params.edgeWidth);
1518 p2.y += curr.normal.y * (curr.width * 0.5f - params.edgeWidth);
1519
1520 p1.x += curr.wobble1.vector.x;
1521 p1.y += curr.wobble1.vector.y;
1522
1523 Misc.setColor(c, alpha * 0f * a);
1524 GL11.glVertex2f(p1.x, p1.y);
1525 Misc.setColor(c, alpha * 1f * a);
1526 GL11.glVertex2f(p2.x, p2.y);
1527 }
1528 GL11.glEnd();
1529
1530 //edge2.bindTexture();
1531 GL11.glBegin(GL11.GL_QUAD_STRIP);
1532
1533 for (int i = 0; i < segments.size(); i++) {
1534 SlipstreamSegment curr = segments.get(i);
1535 float a = curr.fader.getBrightness();
1536
1537 if (entity.isInHyperspace() && plugin.isInClouds(curr.loc, 100f)) {
1538 c = Misc.setAlpha(c, alphaInDeep);
1539 } else {
1540 c = Misc.setAlpha(c, alphaOutside);
1541 }
1542
1543 Vector2f p1 = new Vector2f(curr.loc);
1544 p1.x -= curr.normal.x * curr.width * 0.5f;
1545 p1.y -= curr.normal.y * curr.width * 0.5f;
1546 Vector2f p2 = new Vector2f(curr.loc);
1547 p2.x -= curr.normal.x * (curr.width * 0.5f - params.edgeWidth);
1548 p2.y -= curr.normal.y * (curr.width * 0.5f - params.edgeWidth);
1549
1550 p1.x += curr.wobble2.vector.x;
1551 p1.y += curr.wobble2.vector.y;
1552
1553 Misc.setColor(c, alpha * 0f * a);
1554 GL11.glVertex2f(p1.x, p1.y);
1555 Misc.setColor(c, alpha * 1f * a);
1556 GL11.glVertex2f(p2.x, p2.y);
1557 }
1558 GL11.glEnd();
1559
1560 GL11.glBegin(GL11.GL_QUAD_STRIP);
1561
1562 for (int i = 0; i < segments.size(); i++) {
1563 SlipstreamSegment curr = segments.get(i);
1564 float a = curr.fader.getBrightness();
1565
1566 if (entity.isInHyperspace() && plugin.isInClouds(curr.loc, 100f)) {
1567 c = Misc.setAlpha(c, alphaInDeep);
1568 } else {
1569 c = Misc.setAlpha(c, alphaOutside);
1570 }
1571
1572 Vector2f p1 = new Vector2f(curr.loc);
1573 p1.x += curr.normal.x * (curr.width * 0.5f - params.edgeWidth);
1574 p1.y += curr.normal.y * (curr.width * 0.5f - params.edgeWidth);
1575 Vector2f p2 = new Vector2f(curr.loc);
1576 p2.x -= curr.normal.x * (curr.width * 0.5f - params.edgeWidth);
1577 p2.y -= curr.normal.y * (curr.width * 0.5f - params.edgeWidth);
1578
1579 Misc.setColor(c, alpha * 1f * a);
1580 GL11.glVertex2f(p1.x, p1.y);
1581 GL11.glVertex2f(p2.x, p2.y);
1582 }
1583 GL11.glEnd();
1584 // end "channel"
1585
1586
1587 // main background
1588 if (!wireframe) {
1589 GL11.glEnable(GL11.GL_TEXTURE_2D);
1590 GL11.glEnable(GL11.GL_BLEND);
1591 }
1592 //GL11.glDisable(GL11.GL_BLEND);
1593 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
1594 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1595
1596 GL11.glBegin(GL11.GL_QUAD_STRIP);
1597 for (int i = 0; i < segments.size(); i++) {
1598 SlipstreamSegment curr = segments.get(i);
1599 float a = curr.fader.getBrightness();
1600
1601 Vector2f p1 = new Vector2f(curr.loc);
1602 p1.x += curr.normal.x * curr.width * 0.5f;
1603 p1.y += curr.normal.y * curr.width * 0.5f;
1604 Vector2f p2 = new Vector2f(curr.loc);
1605 p2.x -= curr.normal.x * curr.width * 0.5f;
1606 p2.y -= curr.normal.y * curr.width * 0.5f;
1607
1608 p1.x += curr.wobble1.vector.x;
1609 p1.y += curr.wobble1.vector.y;
1610 p2.x += curr.wobble2.vector.x;
1611 p2.y += curr.wobble2.vector.y;
1612
1613 Misc.setColor(color, alpha * 1f * a);
1614 GL11.glTexCoord2f(curr.tx, 0f);
1615 GL11.glVertex2f(p1.x, p1.y);
1616 GL11.glTexCoord2f(curr.tx, 1f);
1617 GL11.glVertex2f(p2.x, p2.y);
1618 }
1619 GL11.glEnd();
1620
1621
1622 // edges
1623 color = edge.getColor();
1624 float wobbleMult = 0.5f;
1625 edge.bindTexture();
1626 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
1627 //GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1628
1629 GL11.glBegin(GL11.GL_QUAD_STRIP);
1630
1631 for (int i = 0; i < segments.size(); i++) {
1632 SlipstreamSegment curr = segments.get(i);
1633 float a = curr.fader.getBrightness();
1634
1635 Vector2f p1 = new Vector2f(curr.loc);
1636 p1.x += curr.normal.x * curr.width * 0.5f;
1637 p1.y += curr.normal.y * curr.width * 0.5f;
1638 Vector2f p2 = new Vector2f(curr.loc);
1639 p2.x += curr.normal.x * (curr.width * 0.5f - params.edgeWidth);
1640 p2.y += curr.normal.y * (curr.width * 0.5f - params.edgeWidth);
1641
1642 p1.x += curr.wobble1.vector.x * wobbleMult;
1643 p1.y += curr.wobble1.vector.y * wobbleMult;
1644 p2.x += curr.wobble1.vector.x * wobbleMult;
1645 p2.y += curr.wobble1.vector.y * wobbleMult;
1646
1647 Misc.setColor(color, alpha * 1f * a);
1648 GL11.glTexCoord2f(curr.txe1, 1f);
1649 GL11.glVertex2f(p1.x, p1.y);
1650 GL11.glTexCoord2f(curr.txe1, 0f);
1651 GL11.glVertex2f(p2.x, p2.y);
1652 }
1653 GL11.glEnd();
1654
1655 //edge2.bindTexture();
1656 GL11.glBegin(GL11.GL_QUAD_STRIP);
1657
1658 for (int i = 0; i < segments.size(); i++) {
1659 SlipstreamSegment curr = segments.get(i);
1660 float a = curr.fader.getBrightness();
1661
1662 Vector2f p1 = new Vector2f(curr.loc);
1663 p1.x -= curr.normal.x * curr.width * 0.5f;
1664 p1.y -= curr.normal.y * curr.width * 0.5f;
1665 Vector2f p2 = new Vector2f(curr.loc);
1666 p2.x -= curr.normal.x * (curr.width * 0.5f - params.edgeWidth);
1667 p2.y -= curr.normal.y * (curr.width * 0.5f - params.edgeWidth);
1668
1669 p1.x += curr.wobble2.vector.x * wobbleMult;
1670 p1.y += curr.wobble2.vector.y * wobbleMult;
1671 p2.x += curr.wobble2.vector.x * wobbleMult;
1672 p2.y += curr.wobble2.vector.y * wobbleMult;
1673
1674 Misc.setColor(color, alpha * 1f * a);
1675 GL11.glTexCoord2f(curr.txe2, 1f);
1676 GL11.glVertex2f(p1.x, p1.y);
1677 GL11.glTexCoord2f(curr.txe2, 0f);
1678 GL11.glVertex2f(p2.x, p2.y);
1679 }
1680 GL11.glEnd();
1681
1682
1683 if (subtract) {
1684 GL14.glBlendEquation(GL14.GL_FUNC_ADD);
1685 }
1686
1687 if (wireframe) GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
1688 }
1689
1690
1691
1692
1693
1694 public Color getRandomColor() {
1695 return Misc.interpolateColor(params.minColor, params.maxColor, (float) Math.random());
1696 }
1697
1698
1708 public float [] getLengthAndWidthFractionWithinStream(Vector2f loc) {
1709 float dist = Misc.getDistance(loc, entity.getLocation());
1710 if (dist > getRenderRange()) return null;
1711
1712 List<SlipstreamSegment> near = getSegmentsNear(loc, 0f);
1713
1714 for (SlipstreamSegment curr : near) {
1715 SlipstreamSegment next = null;
1716 if (segments.size() > curr.index + 1) {
1717 next = segments.get(curr.index + 1);
1718 } else {
1719 next = new SlipstreamSegment();
1720 //next2.width = next.width;
1721 next.wobbledWidth = curr.wobbledWidth;
1722
1723 next.normal = curr.normal;
1724 //next2.dir = next.dir;
1725 next.loc = new Vector2f(curr.dir);
1726 next.loc.scale(curr.lengthToPrev);
1727 Vector2f.add(next.loc, curr.loc, next.loc);
1728 //next2.locB = next2.loc;
1729 next.lengthToPrev = curr.lengthToPrev;
1730 //continue;
1731 }
1732
1733 Vector2f p3 = loc;
1734 Vector2f p1 = curr.loc;
1735 Vector2f p2 = next.loc;
1736
1737 Vector2f currNormalP1 = new Vector2f(curr.loc);
1738 Vector2f currNormalP2 = new Vector2f(curr.normal);
1739 currNormalP2.scale(100f);
1740 Vector2f.add(currNormalP2, currNormalP1, currNormalP2);
1741
1742 Vector2f nextNormalP1 = new Vector2f(next.loc);
1743 Vector2f nextNormalP2 = new Vector2f(next.normal);
1744 nextNormalP2.scale(100f);
1745 Vector2f.add(nextNormalP2, nextNormalP1, nextNormalP2);
1746
1747 //Vector2f dir = Misc.getUnitVectorAtDegreeAngle(Misc.getAngleInDegrees(p1, p2));
1748 Vector2f dir = new Vector2f(curr.dir);
1749 dir.scale(100f);
1750 Vector2f p4 = Vector2f.add(p3, dir, new Vector2f());
1751
1752 Vector2f currNormalP = Misc.intersectLines(currNormalP1, currNormalP2, p3, p4);
1753 if (currNormalP == null) continue;
1754 Vector2f nextNormalP = Misc.intersectLines(nextNormalP1, nextNormalP2, p3, p4);
1755 if (nextNormalP == null) continue;
1756
1757 float u = (p3.x - currNormalP.x) * (nextNormalP.x - currNormalP.x) +
1758 (p3.y - currNormalP.y) * (nextNormalP.y - currNormalP.y);
1759 float denom = Vector2f.sub(nextNormalP, currNormalP, new Vector2f()).length();
1760 denom *= denom;
1761 if (denom == 0) continue;
1762 u /= denom;
1763
1764 if (u >= 0 && u <= 1) { // p3 is between the two points on the normals
1765 Vector2f normalAtP3 = Misc.interpolateVector(curr.normal, next.normal, u);
1766 normalAtP3.scale(100f);
1767 Vector2f p3PlusNormal = Vector2f.add(p3, normalAtP3, new Vector2f());
1768
1769 Vector2f intersect = Misc.intersectLines(p1, p2, p3, p3PlusNormal);
1770 if (intersect == null) continue;
1771
1772 float distFromLine = Vector2f.sub(intersect, p3, new Vector2f()).length();
1773 float width = Misc.interpolate(curr.wobbledWidth, next.wobbledWidth, u);
1774 if (distFromLine >= width / 2f) return null;
1775
1776 float [] result = new float[2];
1777 //result[0] = curr.totalLength + u * curr.lengthToNext;
1778 result[0] = curr.totalLength + u * next.lengthToPrev;
1779 result[1] = distFromLine / (width / 2f);
1780
1781 float currToLoc = Misc.getAngleInDegrees(p1, p3);
1782 float segDir = Misc.getAngleInDegrees(p1, p2);
1783 if (Misc.getClosestTurnDirection(segDir, currToLoc) < 0) {
1784 result[1] = -result[1];
1785 }
1786
1787 return result;
1788
1789// float u = (p3.x - p1.x) * (p2.x - p1.x) + (p3.y - p1.y) * (p2.y - p1.y);
1790// float denom = Vector2f.sub(p2, p1, new Vector2f()).length();
1791// denom *= denom;
1792// if (denom == 0) continue;
1793// u /= denom;
1794//
1797//
1798// if (u >= 0 && u <= 1) { // intersection is between p1 and p2
1799// Vector2f intersect = new Vector2f();
1800// intersect.x = p1.x + u * (p2.x - p1.x);
1801// intersect.y = p1.y + u * (p2.y - p1.y);
1802// float distFromLine = Vector2f.sub(intersect, p3, new Vector2f()).length();
1803//
1804// float width = curr.wobbledWidth;
1805// if (next != null) {
1806// width = Misc.interpolate(curr.wobbledWidth, next.wobbledWidth, u);
1807// }
1808//
1809// if (distFromLine >= width / 2f) return null;
1810//
1811// float [] result = new float[2];
1812// result[0] = curr.totalLength + u * curr.lengthToNext;
1813// result[1] = distFromLine / (width / 2f);
1814//
1815// float currToLoc = Misc.getAngleInDegrees(p1, p3);
1816// float segDir = Misc.getAngleInDegrees(p1, p2);
1817// if (Misc.getClosestTurnDirection(segDir, currToLoc) < 0) {
1818// result[1] = -result[1];
1819// }
1820//
1821// return result;
1822 }
1823
1824 }
1825
1826// Vector2f p3 = new Vector2f(loc);
1827// Vector2f p1 = new Vector2f(entity.getLocation());
1828// Vector2f p2 = Misc.getUnitVectorAtDegreeAngle(entity.getFacing() + 180f);
1829// //p2.scale(params.length);
1830// Vector2f.add(p2, p1, p2);
1831//
1832// float u = (p3.x - p1.x) * (p2.x - p1.x) + (p3.y - p1.y) * (p2.y - p1.y);
1833// float denom = Vector2f.sub(p2, p1, new Vector2f()).length();
1834// denom *= denom;
1835// if (denom == 0) return null;
1836// u /= denom;
1837//
1838// if (u >= 0 && u <= 1) { // intersection is between p1 and p2
1839// Vector2f intersect = new Vector2f();
1840// intersect.x = p1.x + u * (p2.x - p1.x);
1841// intersect.y = p1.y + u * (p2.y - p1.y);
1842// float distFromLine = Vector2f.sub(intersect, p3, new Vector2f()).length();
1843// //float distAlongLine = u * params.length;
1844// if (distFromLine >= params.width/2f) return null;
1845//
1846// float [] result = new float[2];
1847// result[0] = u;
1848// result[1] = distFromLine / (params.width / 2f);
1849// return result;
1850// }
1851 return null;
1852 }
1853
1854 public void applyEffectToFleets(float amount) {
1855 float days = Global.getSector().getClock().convertToDays(amount);
1856 for (CampaignFleetAPI fleet : entity.getContainingLocation().getFleets()) {
1857 applyEffect(fleet, days);
1858 }
1859 }
1860
1861 //protected boolean playerWasInSlipstream = false;
1863 public void applyEffect(SectorEntityToken other, float days) {
1864 if (other instanceof CampaignFleetAPI) {
1865 CampaignFleetAPI fleet = (CampaignFleetAPI) other;
1866
1867// if (fleet.isPlayerFleet()) {
1868// if (getLengthAndWidthFractionWithinStream(fleet.getLocation()) == null) {
1869// System.out.println("wefwefwefe");
1870// }
1871// System.out.println("efwefwef");
1872// }
1873
1874 float [] offset = getLengthAndWidthFractionWithinStream(fleet.getLocation());
1875 if (offset == null) {
1876 if (fleet.isPlayerFleet()) {
1878 if (playerWasInSlipstreamFramesAgo > 1000) {
1880 }
1881 }
1882 return;
1883 }
1884
1885// if (fleet.isPlayerFleet()) {
1886// System.out.println("Location in stream: " + offset[0] + ", " + offset[1]);
1887// }
1888
1889 //params.burnLevel = 10;
1890
1891 float distAlong = offset[0];
1892 float yOff = offset[1];
1893
1894// float intensity = 1f;
1895// if (Math.abs(yOff) > 0.5f) {
1896// intensity *= (1f - Math.abs(yOff)) / 0.5f;
1897// }
1898 float intensity = getIntensity(yOff);
1899 float wMult = getWidthBasedSpeedMult(distAlong);
1900 //System.out.println("wMult: " + wMult);
1901 intensity *= wMult;
1902 intensity *= getFaderBrightness(distAlong);
1903 //intensity *= intensity;
1904 //System.out.println(intensity);
1905
1906 if (intensity <= 0) {
1907 if (fleet.isPlayerFleet()) {
1909 if (playerWasInSlipstreamFramesAgo > 1000) {
1911 }
1912 }
1913 return;
1914 }
1915
1916 if (fleet.isPlayerFleet()) {
1917 //if (!playerWasInSlipstream) {
1918 // playerWasInSlipstream = true;
1920 fleet.addFloatingText("Entering slipstream", Misc.setAlpha(fleet.getIndicatorColor(), 255), 0.5f);
1921 }
1923 }
1924
1925 //System.out.println("Intensity: " + intensity);
1926
1927 // "wind" effect - adjust velocity
1928 float maxFleetBurn = fleet.getFleetData().getBurnLevel();
1929 float currFleetBurn = fleet.getCurrBurnLevel();
1930
1931 float maxWindBurn = params.burnLevel * 2f;
1932
1933 float currWindBurn = intensity * maxWindBurn;
1934 float maxFleetBurnIntoWind = maxFleetBurn - Math.abs(currWindBurn);
1935 float seconds = days * Global.getSector().getClock().getSecondsPerDay();
1936
1937// float angle = Misc.getAngleInDegreesStrict(this.entity.getLocation(), fleet.getLocation()) + 180f;
1938// Vector2f windDir = Misc.getUnitVectorAtDegreeAngle(angle);
1939 Vector2f p1 = getPointAt(distAlong, yOff);
1940 Vector2f p2 = getPointAt(distAlong + 1f, yOff);
1941 if (p1 == null || p2 == null) {
1942 if (fleet.isPlayerFleet()) {
1944 if (playerWasInSlipstreamFramesAgo > 1000) {
1946 }
1947 }
1948 return;
1949 }
1950
1951 //Vector2f windDir = Misc.getUnitVectorAtDegreeAngle(entity.getFacing());
1952 Vector2f windDir = Misc.getUnitVectorAtDegreeAngle(Misc.getAngleInDegrees(p1, p2));
1953 if (currWindBurn < 0) {
1954 windDir.negate();
1955 }
1956 Vector2f velDir = Misc.normalise(new Vector2f(fleet.getVelocity()));
1957 //float baseFleetAccel = Misc.getSpeedForBurnLevel(fleet.getFleetData().getMinBurnLevel());
1958 float baseFleetAccel = fleet.getTravelSpeed();
1959 if (baseFleetAccel < 10f) baseFleetAccel = 10f;
1960
1961 boolean fleetTryingToMove = fleet.getMoveDestination() != null &&
1962 Misc.getDistance(fleet.getLocation(), fleet.getMoveDestination()) > fleet.getRadius() + 10f;
1963 if (fleet.isPlayerFleet()) {
1964 fleetTryingToMove &= (
1965 Global.getSector().getCampaignUI().isPlayerFleetFollowingMouse() ||
1966 fleet.wasSlowMoving());
1967 }
1968 float windSpeedReduction = 0f;
1969 if (!fleetTryingToMove) {
1970 Vector2f dest = new Vector2f(windDir);
1971 dest.scale(1000f);
1972 Vector2f.add(dest, fleet.getLocation(), dest);
1973 fleet.setMoveDestination(dest.x, dest.y);
1974 } else {
1975 Vector2f moveDir = Misc.getUnitVectorAtDegreeAngle(
1976 Misc.getAngleInDegrees(fleet.getLocation(), fleet.getMoveDestination()));
1977 float dot = Vector2f.dot(windDir, moveDir);
1978 if (fleet.wasSlowMoving()) dot = -1f;
1979 if (dot < 0) {
1980 float accelBasedMult = fleet.getAcceleration() / baseFleetAccel;
1981 accelBasedMult *= accelBasedMult;
1982 if (accelBasedMult > 1f) accelBasedMult = 1f;
1983 if (accelBasedMult < 0.1f) accelBasedMult = 0.1f;
1984 windSpeedReduction = -dot * fleet.getFleetData().getBurnLevel() * accelBasedMult;
1985 }
1986 }
1987
1988 //float burnBonus = fleet.getFleetData().getBurnLevel() - fleet.getFleetData().getMinBurnLevelUnmodified();
1989 float burnBonus = fleet.getFleetData().getBurnLevel() - fleet.getFleetData().getMinBurnLevel();
1990 if (burnBonus < 0) burnBonus = 0;
1991 //float maxSpeedWithWind = Misc.getSpeedForBurnLevel(params.burnLevel + burnBonus);
1992 float maxSpeedWithWind = Misc.getSpeedForBurnLevel((params.burnLevel * intensity) + burnBonus);
1993 if (windSpeedReduction > 0) {
1994 maxSpeedWithWind = Misc.getSpeedForBurnLevel(
1995 Math.max(params.burnLevel * 0.5f * intensity, params.burnLevel * intensity - windSpeedReduction));
1996 }
1997
1998 float fleetSpeedAlongWind = Vector2f.dot(windDir, fleet.getVelocity());
1999 if (fleetSpeedAlongWind >= maxSpeedWithWind) {
2000// float dotPlayerAndWindVel = Vector2f.dot(windDir, velDir);
2001// if (dotPlayerAndWindVel > 0.98f) {
2002 return;
2003 //}
2004 }
2005
2006 velDir.scale(currFleetBurn);
2007
2008 float fleetBurnAgainstWind = -1f * Vector2f.dot(windDir, velDir);
2009
2010
2011 float windSpeed = Misc.getSpeedForBurnLevel(currWindBurn);
2012 //float fleetSpeed = fleet.getTravelSpeed();
2013 Vector2f windVector = new Vector2f(windDir);
2014 windVector.scale(windSpeed);
2015
2016 Vector2f vel = fleet.getVelocity();
2017 Vector2f diff = Vector2f.sub(windVector, vel, new Vector2f());
2018 //windDir.scale(seconds * fleet.getAcceleration());
2019 float max = diff.length();
2020 diff = Misc.normalise(diff);
2021 //diff.scale(Math.max(windSpeed * seconds, fleet.getAcceleration() * 1f * seconds));
2022 diff.scale(fleet.getAcceleration() * 3f * seconds);
2023 //diff.scale(fleet.getTravelSpeed() * 5f * seconds);
2024 //diff.scale(accelMult);
2025 if (diff.length() > max) {
2026 diff.scale(max / diff.length());
2027 }
2028 //System.out.println("Applying diff: " + diff);
2029 //fleet.setVelocity(vel.x + diff.x, vel.y + diff.y);
2030
2031
2032// Vector2f velDir = Misc.normalise(new Vector2f(fleet.getVelocity()));
2033// velDir.scale(currFleetBurn);
2034//
2035// float fleetBurnAgainstWind = -1f * Vector2f.dot(windDir, velDir);
2036//
2037 float accelMult = 0.5f;
2038 if (fleetBurnAgainstWind > maxFleetBurnIntoWind) {
2039 accelMult += 0.75f + 0.25f * (fleetBurnAgainstWind - maxFleetBurnIntoWind);
2040 }
2041
2042
2043 //Vector2f vel = fleet.getVelocity();
2044 //windDir.scale(seconds * fleet.getAcceleration() * accelMult);
2045 //float baseFleetAccel = Math.max(fleet.getTravelSpeed(), fleet.getAcceleration());
2046
2047 windDir.scale(seconds * baseFleetAccel * accelMult);
2048 fleet.setVelocity(vel.x + windDir.x, vel.y + windDir.y);
2049
2050
2051 boolean withGlow = true;
2052 //withGlow = false;
2053 if (withGlow) {
2054 Color glowColor = params.windGlowColor;
2055 int alpha = glowColor.getAlpha();
2056 if (alpha < 75) {
2057 glowColor = Misc.setAlpha(glowColor, 75);
2058 }
2059 // visual effects - glow, tail
2060
2061 p1 = getNoWobblePointAt(distAlong, yOff);
2062 p2 = getNoWobblePointAt(distAlong + 100f, yOff);
2063 if (p1 != null && p2 != null) {
2064 windDir = Misc.getUnitVectorAtDegreeAngle(Misc.getAngleInDegrees(p1, p2));
2065
2066// float fleetSpeedAlongWind = Vector2f.dot(windDir, fleet.getVelocity());
2067// //float fleetSpeed = fleet.getVelocity().length();
2068//
2069// windSpeed = Misc.getSpeedForBurnLevel(params.burnLevel);
2070// float matchingWindFraction = fleetSpeedAlongWind/windSpeed;
2071// float effectMag = 1f - matchingWindFraction;
2072// if (effectMag < 0f) effectMag = 0f;
2073 //if (effectMag < 0.25f) effectMag = 0.25f;
2074 //effectMag = 0.5f;
2075
2076 String modId = "slipstream_" + entity.getId();
2077 float durIn = 1f;
2078 float durOut = 3f;
2079 //durIn = 0.5f;
2080 //float sizeNormal = (15f + 30f * effectMag * effectMag) * (intensity);
2081 float sizeNormal = 5f + 10f * intensity;
2082 for (FleetMemberViewAPI view : fleet.getViews()) {
2083 view.getWindEffectDirX().shift(modId, windDir.x * sizeNormal, durIn, durOut, 1f);
2084 view.getWindEffectDirY().shift(modId, windDir.y * sizeNormal, durIn, durOut, 1f);
2085 view.getWindEffectColor().shift(modId, glowColor, durIn, durOut, 1f);
2086 }
2087 }
2088 }
2089 }
2090 }
2091
2092
2093 public Vector2f getPointAt(float lengthAlongStream, float offset) {
2094 SlipstreamSegment curr = getSegmentForDist(lengthAlongStream);
2095 if (curr == null) return null;
2096 int index = curr.index;
2097
2098 SlipstreamSegment next = null;
2099 SlipstreamSegment next2 = null;
2100
2101 if (index >= segments.size() - 1) return null;
2102
2103 if (index % 2 == 0) {
2104 next = segments.get(index + 1);
2105 if (index >= segments.size() - 2) {
2106 next2 = new SlipstreamSegment();
2107 //next2.width = next.width;
2108 next2.wobbledWidth = next.wobbledWidth;
2109
2110 next2.normal = next.normal;
2111 //next2.dir = next.dir;
2112 next2.loc = new Vector2f(next.dir);
2113 next2.loc.scale(next.lengthToPrev);
2114 Vector2f.add(next2.loc, next.loc, next2.loc);
2115 //next2.locB = next2.loc;
2116 next2.lengthToPrev = next.lengthToPrev;
2117 } else {
2118 next2 = segments.get(index + 2);
2119 }
2120 }
2121 if (index % 2 != 0) {
2122 if (index >= segments.size() - 1) return null;
2123 curr = segments.get(index - 1);
2124 next = segments.get(index);
2125 next2 = segments.get(index + 1);
2126 }
2127
2128 float lenForT = lengthAlongStream - curr.totalLength;
2129 //float t = lenForT / (curr.lengthToNext + next.lengthToNext);
2130 float t = lenForT / (curr.lengthToNext + next2.lengthToPrev);
2131// if (t < 0) {
2132// System.out.println("wefwefe");
2133// }
2134
2135 Vector2f p0 = new Vector2f(curr.loc);
2136 Vector2f p1 = new Vector2f(next.locB);
2137 Vector2f p2 = new Vector2f(next2.loc);
2138
2139// offset *= 0.7f;
2140// p0.x += curr.normal.x * curr.width * 0.5f * offset;
2141// p0.y += curr.normal.y * curr.width * 0.5f * offset;
2142//
2143// p2.x += next2.normal.x * next2.width * 0.5f * offset;
2144// p2.y += next2.normal.y * next2.width * 0.5f * offset;
2145//
2146// p1.x += next.normal.x * next.width * 0.5f * offset;
2147// p1.y += next.normal.y * next.width * 0.5f * offset;
2148
2149 p0.x += curr.normal.x * curr.wobbledWidth * 0.5f * offset;
2150 p0.y += curr.normal.y * curr.wobbledWidth * 0.5f * offset;
2151
2152 p2.x += next2.normal.x * next2.wobbledWidth * 0.5f * offset;
2153 p2.y += next2.normal.y * next2.wobbledWidth * 0.5f * offset;
2154
2155 p1.x += next.normal.x * next.wobbledWidth * 0.5f * offset;
2156 p1.y += next.normal.y * next.wobbledWidth * 0.5f * offset;
2157
2158 //System.out.println("T: " + t);
2159 Vector2f p = Misc.bezier(p0, p1, p2, t);
2160
2161 return p;
2162 }
2163
2164 public Vector2f getNoWobblePointAt(float lengthAlongStream, float offset) {
2165 SlipstreamSegment curr = getSegmentForDist(lengthAlongStream);
2166 if (curr == null) return null;
2167 int index = curr.index;
2168 if (index >= segments.size() - 2) return null;
2169
2170 SlipstreamSegment next = segments.get(index + 1);
2171 SlipstreamSegment next2 = segments.get(index + 2);
2172
2173 if (index % 2 != 0) {
2174 curr = segments.get(index - 1);
2175 next = segments.get(index);
2176 next2 = segments.get(index + 1);
2177 }
2178
2179 float lenForT = lengthAlongStream - curr.totalLength;
2180 float t = lenForT / (curr.lengthToNext + next.lengthToNext);
2181// if (t < 0) {
2182// System.out.println("wefwefe");
2183// }
2184
2185 Vector2f p0 = new Vector2f(curr.loc);
2186 Vector2f p1 = new Vector2f(next.locB);
2187 Vector2f p2 = new Vector2f(next2.loc);
2188
2189 float edges = params.edgeWidth * 2f * 0.5f;
2190 p0.x += curr.normal.x * (curr.width - edges) * 0.5f * offset;
2191 p0.y += curr.normal.y * (curr.width - edges) * 0.5f * offset;
2192
2193 p2.x += next2.normal.x * (next2.width - edges) * 0.5f * offset;
2194 p2.y += next2.normal.y * (next2.width - edges) * 0.5f * offset;
2195
2196 p1.x += next.normal.x * (next.width - edges) * 0.5f * offset;
2197 p1.y += next.normal.y * (next.width - edges) * 0.5f * offset;
2198
2199 Vector2f p = Misc.bezier(p0, p1, p2, t);
2200
2201 return p;
2202 }
2203
2204
2205 public Vector2f getNormalAt(float lengthAlongStream) {
2206 SlipstreamSegment curr = getSegmentForDist(lengthAlongStream);
2207 if (curr == null) return null;
2208 int index = curr.index;
2209 if (index >= segments.size() - 2) return null;
2210
2211 SlipstreamSegment next = segments.get(index + 1);
2212 SlipstreamSegment next2 = segments.get(index + 2);
2213
2214 if (index % 2 != 0) {
2215 curr = segments.get(index - 1);
2216 next = segments.get(index);
2217 next2 = segments.get(index + 1);
2218 }
2219
2220 float lenForT = lengthAlongStream - curr.totalLength;
2221
2222 float f = lenForT / curr.lengthToNext;
2223 Vector2f perp;
2224 if (f < 1f) {
2225 perp = Misc.interpolateVector(curr.normal, next.normal, f);
2226 } else {
2227 f = (lenForT - curr.lengthToNext) / next.lengthToNext;
2228 perp = Misc.interpolateVector(next.normal, next2.normal, f);
2229 }
2230 return perp;
2231 }
2232
2233 public List<SlipstreamSegment> getSegmentsNear(Vector2f loc, float range) {
2234 //List<SlipstreamSegment> potential = new ArrayList<SlipstreamEntityPlugin2.SlipstreamSegment>();
2235 List<SlipstreamSegment> result = new ArrayList<SlipstreamEntityPlugin2.SlipstreamSegment>();
2236 int boxIndex = 0;
2237 for (BoundingBox box : bounds) {
2238 if (box.pointNeedsDetailedCheck(loc, range)) {
2239 int min = boxIndex * segmentsPerBox;
2240 for (int i = min; i < min + segmentsPerBox && i < segments.size(); i++) {
2241 SlipstreamSegment curr = segments.get(i);
2242 float distSq = Misc.getDistanceSq(curr.loc, loc);
2243 float r = range + curr.width + Math.max(curr.lengthToPrev, curr.lengthToNext);
2244 if (distSq < r * r) {
2245 result.add(curr);
2246 }
2247 }
2248 }
2249 boxIndex++;
2250 }
2251
2252// for (SlipstreamSegment curr : potential) {
2253// float distSq = Misc.getDistanceSq(curr.loc, loc);
2254// float r = range + curr.width + Math.max(curr.lengthToPrev, curr.lengthToNext);
2255// if (distSq < r * r) {
2256// result.add(curr);
2257// }
2258// }
2259// List<SlipstreamSegment> result = new ArrayList<SlipstreamEntityPlugin2.SlipstreamSegment>();
2260// for (SlipstreamSegment curr : segments) {
2261// float distSq = Misc.getDistanceSq(curr.loc, loc);
2262// float r = range + curr.width + Math.max(curr.lengthToPrev, curr.lengthToNext);
2263// if (distSq < r * r) {
2264// result.add(curr);
2265// }
2266// }
2267 return result;
2268 }
2269}
2270
2271
2272
2273
2274
static SettingsAPI getSettings()
Definition Global.java:51
static SectorAPI getSector()
Definition Global.java:59
void render(CampaignEngineLayers layer, ViewportAPI viewport)
static Vector2f rotateAroundOrigin(Vector2f v, float cos, float sin)
void renderSegments(SpriteAPI sprite, SpriteAPI edge, float alpha, List< SlipstreamSegment > segments)
List< SlipstreamSegment > getSegmentsNear(Vector2f loc, float range)
SpriteAPI getSprite(String filename)