87 if (
type == StreamType.NORMAL) {
92 }
else if (
type == StreamType.WIDE) {
97 }
else if (
type == StreamType.NARROW) {
266 Vector2f loc =
new Vector2f(
start);
267 Vector2f p0 =
new Vector2f(loc);
268 Vector2f p1 =
new Vector2f(to);
270 float len = Misc.getDistance(p0, p1);
271 Vector2f dir = Misc.getUnitVector(p0, p1);
272 float dirAngle = Misc.getAngleInDegrees(dir);
274 float distSoFar = 0f;
275 float prevAngle = 0f;
276 for (
int i = 0; distSoFar < len; i++) {
285 if (i % 2 == 1) angle = prevAngle;
288 Vector2f add = Misc.getUnitVectorAtDegreeAngle(angle);
289 float length = 3000f +
random.nextInt(2000);
293 Vector2f.add(loc, add, loc);
299 float actualAngle = Misc.getAngleInDegrees(p0, end);
300 float angleDiff = Misc.getAngleDiff(dirAngle, actualAngle);
301 float turnDir = Misc.getClosestTurnDirection(actualAngle, dirAngle);
303 for (SlipstreamSection section :
sections) {
304 section.from = Misc.rotateAroundOrigin(section.from, angleDiff * turnDir, p0);
305 section.to = Misc.rotateAroundOrigin(section.to, angleDiff * turnDir, p0);
309 float actualDist = Misc.getDistance(p0, end);
310 float distToAdd = len - actualDist;
313 if (distToAdd > 1000) {
314 angleDiff = Misc.getAngleDiff(dirAngle, prevAngle);
315 turnDir = Misc.getClosestTurnDirection(actualAngle, dirAngle);
316 float turnAmount = Math.min(30f, angleDiff) * turnDir;
319 Vector2f add = Misc.getUnitVectorAtDegreeAngle(prevAngle + turnAmount);
320 float length = distToAdd;
322 loc = Vector2f.add(end, add, loc);
334 Vector2f loc =
new Vector2f(
start);
337 Vector2f p1 =
new Vector2f(loc);
345 float len = Misc.getDistance(p0, p1);
346 Vector2f dir = Misc.getUnitVector(p0, p1);
347 Vector2f perp =
new Vector2f(-dir.y, dir.x);
349 float averageSection = 4000;
351 int numNoisePoints = 32;
352 while (numNoisePoints < len / averageSection) {
353 numNoisePoints *= 2f;
355 if (numNoisePoints > 2048) numNoisePoints = 2048;
356 float spikes = 0.75f;
359 noise[noise.length - 1] = 0.5f;
364 float startLength = 1500 +
random.nextFloat() * 1500f;
365 float endLength = 1500 +
random.nextFloat() * 1500f;
366 Vector2f curr =
new Vector2f(dir);
367 curr.scale(startLength);
368 Vector2f.add(curr, p0, curr);
372 float mid = len - startLength - endLength;
373 float remaining = mid;
374 float distSoFar = startLength;
378 float maxMag = 500f + mid * 0.01f + 1f * (1000f + mid * 0.025f);
380 while (remaining > 0) {
381 float segLen = 3000f +
random.nextFloat() * 2000f;
382 segLen = Math.min(segLen, remaining);
384 if (remaining < segLen * 0.5f) {
390 float t = (distSoFar - startLength) / mid;
395 }
else if (t > 0.75f) {
396 n *= (1f - t) / 0.25f;
401 curr =
new Vector2f(dir);
402 curr.scale(distSoFar);
403 Vector2f.add(curr, p0, curr);
404 curr.x += perp.x * maxMag * n;
405 curr.y += perp.y * maxMag * n;
416 Vector2f loc =
new Vector2f(
start);
417 Vector2f p0 =
new Vector2f(loc);
418 Vector2f p1 =
new Vector2f(loc);
430 float len = Misc.getDistance(p0, p1);
431 Vector2f dir = Misc.getUnitVector(p0, p1);
432 Vector2f perp =
new Vector2f(-dir.y, dir.x);
433 float dirAngle = Misc.getAngleInDegrees(dir);
435 float distSoFar = 0f;
436 float prevAngle = 0f;
437 for (
int i = 0; distSoFar < len; i++) {
438 float angle =
random.nextFloat() * 60f - 30f;
441 if (i % 2 == 1) angle = prevAngle;
444 Vector2f add = Misc.getUnitVectorAtDegreeAngle(angle);
445 float length = 3000f +
random.nextInt(2000);
449 Vector2f.add(loc, add, loc);
455 float actualAngle = Misc.getAngleInDegrees(p0, end);
456 float angleDiff = Misc.getAngleDiff(dirAngle, actualAngle);
457 float turnDir = Misc.getClosestTurnDirection(actualAngle, dirAngle);
459 for (SlipstreamSection section :
sections) {
460 section.from = Misc.rotateAroundOrigin(section.from, angleDiff * turnDir, p0);
461 section.to = Misc.rotateAroundOrigin(section.to, angleDiff * turnDir, p0);
465 float actualDist = Misc.getDistance(p0, end);
466 float distToAdd = len - actualDist;
468 if (distToAdd > 1000) {
469 angleDiff = Misc.getAngleDiff(dirAngle, prevAngle);
470 turnDir = Misc.getClosestTurnDirection(actualAngle, dirAngle);
471 float turnAmount = Math.min(30f, angleDiff) * turnDir;
474 Vector2f add = Misc.getUnitVectorAtDegreeAngle(prevAngle + turnAmount);
475 float length = distToAdd;
477 loc = Vector2f.add(end, add, loc);
488 Vector2f loc =
new Vector2f(
start);
489 float prevAngle = 0f;
490 for (
int i = 0; i < 20; i++) {
491 float angle =
random.nextFloat() * 60f - 30f;
492 if (i % 2 == 1) angle = prevAngle;
495 Vector2f add = Misc.getUnitVectorAtDegreeAngle(angle);
496 float length = 3000f +
random.nextInt(2000);
499 Vector2f.add(loc, add, loc);
507 Vector2f loc =
new Vector2f(
start);
510 Vector2f p1 =
new Vector2f(loc);
518 float len = Misc.getDistance(p0, p1);
519 Vector2f dir = Misc.getUnitVector(p0, p1);
520 Vector2f perp =
new Vector2f(-dir.y, dir.x);
530 float midLength = len * (0.4f +
random.nextFloat() * 0.2f);
532 Vector2f curr =
new Vector2f(dir);
533 curr.scale(1000f +
random.nextFloat() * 1000f);
534 Vector2f.add(curr, p0, curr);
537 curr =
new Vector2f(dir);
538 curr.scale(midLength);
540 float mag = 0f +
random.nextFloat() * 1000f + len * 0.05f;
541 if (
random.nextFloat() < 0.75f) {
542 if (
random.nextBoolean()) {
545 curr.x += perp.x * mag;
546 curr.y += perp.y * mag;
549 Vector2f.add(curr, p0, curr);
552 float endLength = 1000f +
random.nextFloat() * 1000f;
553 curr =
new Vector2f(dir);
554 curr.scale(len - endLength);
555 Vector2f.add(curr, p0, curr);
566 float startLength = 1500 +
random.nextFloat() * 1500f;
567 float endLength = 1500 +
random.nextFloat() * 1500f;
568 Vector2f curr =
new Vector2f(dir);
569 curr.scale(startLength);
570 Vector2f.add(curr, p0, curr);
573 float remaining = len - startLength - endLength;
574 float distSoFar = startLength;
575 while (remaining > 0) {
576 float lengthForArc = 10000f +
random.nextFloat() * 20000f;
577 lengthForArc = Math.min(lengthForArc, remaining);
578 remaining -= lengthForArc;
579 if (remaining < 10000f) {
580 lengthForArc += remaining;
584 if (
random.nextBoolean()) {
588 float maxMag = 500f +
random.nextFloat() * (2000f + lengthForArc * 0.1f);
592 float perIter = 3000f +
random.nextFloat() * 2000f;
593 float tForIter = perIter / lengthForArc;
595 if (t > 1f - tForIter * 0.5f) {
599 perIter = tForIter * lengthForArc;
600 distSoFar += perIter;
603 curr =
new Vector2f(dir);
604 curr.scale(distSoFar);
605 Vector2f.add(curr, p0, curr);
606 curr.x += perp.x * mag;
607 curr.y += perp.y * mag;
619 Vector2f loc =
new Vector2f(
start);
622 Vector2f p3 =
new Vector2f(loc);
627 float len = Misc.getDistance(p0, p3);
632 Vector2f p1 = Vector2f.add(p0, p3,
new Vector2f());
634 Vector2f p2 =
new Vector2f(p1);
641 float dist1 = len * 0.5f +
random.nextFloat() * len * 0.5f;
642 float dist2 = len * 0.5f +
random.nextFloat() * len * 0.5f;
644 p1 = Misc.getPointAtRadius(p0, dist1,
random);
645 p2 = Misc.getPointAtRadius(p3, dist2,
random);
647 p1 =
new Vector2f(p0.x, p3.y);
648 p2 =
new Vector2f(p3.x, p0.y);
650 if (
random.nextBoolean()) {
656 float veryApproxPathLength = len * 1.5f;
657 float tPerIter = 8000f / (veryApproxPathLength + 1f);
661 t += tPerIter * (0.8f + 0.4f *
random.nextFloat());
662 if (t > 1f - tPerIter * 0.5f) t = 1f;
664 Vector2f curr = Misc.bezierCubic(p0, p1, p2, p3, t);
672 Vector2f loc =
new Vector2f(
start);
675 Vector2f p2 =
new Vector2f(loc);
680 float len = Misc.getDistance(p0, p2);
682 Vector2f p1 = Vector2f.add(p0, p2,
new Vector2f());
688 float tPerIter = 8000f / (approxPathLength + 1f);
692 t += tPerIter * (0.8f + 0.4f *
random.nextFloat());
693 if (t > 1f - tPerIter * 0.5f) t = 1f;
695 Vector2f curr = Misc.bezier(p0, p1, p2, t);
704 Vector2f loc =
new Vector2f(
start);
728 Vector2f loc =
new Vector2f(
start);
729 float prevAngle = 0f;
730 for (
int i = 0; i < 20; i++) {
731 float angle =
random.nextFloat() * 60f - 30f;
732 if (i % 2 == 1) angle = prevAngle;
735 Vector2f add = Misc.getUnitVectorAtDegreeAngle(angle);
736 float length = 3000f +
random.nextInt(2000);
739 Vector2f.add(loc, add, loc);
768 float totalCurveLength = 0f;
769 for (SlipstreamSection curr :
sections) {
770 totalCurveLength += curr.approxCurveLength;
773 int numNoisePoints = 32;
775 numNoisePoints *= 2f;
777 if (numNoisePoints > 2048) numNoisePoints = 2048;
779 float spikes = 0.67f;
781 noiseForWidth[0] = 0.5f;
782 noiseForWidth[noiseForWidth.length - 1] = 0.5f;
791 float curveLengthSoFar = 0f;
792 for (SlipstreamSection curr :
sections) {
798 float startingWidth = width;
808 int segments = (int) (curr.approxCurveLength / desiredSpacing);
809 if (segments < 2) segments = 2;
810 float spacing = curr.approxCurveLength / segments;
812 List<AddedSegment> added =
new ArrayList<AddedSegment>();
815 if (
getPrev(curr) ==
null) startIndex = 0;
816 for (
int i = startIndex; i < segments; i++) {
817 float f = (float)i / ((
float)segments - 1f);
818 float f2 = (float)(i + 0.1f) / ((float)segments - 1f);
820 width = Misc.interpolate(startingWidth, goalWidth, Math.min(1f, f * f * changeRate));
821 float t = (curveLengthSoFar + f * curr.approxCurveLength) / totalCurveLength;
825 width *= (1f + wNoise);
827 Vector2f loc = Misc.bezier(curr.from, curr.control, curr.to, f);
828 Vector2f loc2 = Misc.bezier(curr.from, curr.control, curr.to, f2);
829 Vector2f dir = Vector2f.sub(loc2, loc,
new Vector2f());
831 Vector2f perp =
new Vector2f(-dir.y, dir.x);
834 AddedSegment seg =
new AddedSegment();
836 seg.dir =
new Vector2f(dir);
837 seg.perp =
new Vector2f(perp);
843 float fluctDir = Math.signum(
random.nextFloat() - 0.5f);
844 float distSoFar = 0f;
845 List<AddedSegment> temp =
new ArrayList<AddedSegment>();
846 AddedSegment prev =
null;
847 for (AddedSegment seg : added) {
849 distSoFar += Misc.getDistance(seg.segment.loc, prev.segment.loc);
854 if (distSoFar > distPerFluct && temp.size() >= 4) {
855 for (
int i = 0; i < temp.size(); i++) {
856 float t = i / (temp.size() - 1f);
857 AddedSegment seg2 = temp.get(i);
860 fluctMag *= fluctMult;
863 fluctMag *= fluctAmount * fluctDir;
865 seg2.segment.loc.x += seg2.perp.x * fluctMag;
866 seg2.segment.loc.y += seg2.perp.y * fluctMag;
873 fluctDir = Math.signum(
random.nextFloat() - 0.5f);
877 curveLengthSoFar += curr.approxCurveLength;
882 float fadeDist = 500f;
883 float distSoFar = 0f;
884 SlipstreamSegment prev =
null;
888 distSoFar += Misc.getDistance(prev.loc, curr.loc);
890 if (distSoFar >= fadeDist) {
894 float b = distSoFar / fadeDist;
906 distSoFar += Misc.getDistance(prev.loc, curr.loc);
908 if (distSoFar >= fadeDist) {
912 float b = distSoFar / fadeDist;
1001 float angleLimit = 30f;
1002 for (SlipstreamSection curr :
sections) {
1003 SlipstreamSection prev =
getPrev(curr);
1004 SlipstreamSection next =
getNext(curr);
1007 if (prev ==
null && next ==
null) {
1008 curr.control = Vector2f.add(curr.from, curr.to,
new Vector2f());
1009 curr.control.scale(0.5f);
1010 }
else if (prev ==
null && next !=
null) {
1011 Vector2f p1 = curr.from;
1012 Vector2f p2 = curr.to;
1013 Vector2f p3 = next.to;
1014 float angleP2ToControl = Misc.getAngleInDegrees(p3, p2);
1015 Vector2f dirP2ToControl = Misc.getUnitVectorAtDegreeAngle(angleP2ToControl);
1016 Vector2f p2ToP1 = Vector2f.sub(p1, p2,
new Vector2f());
1017 float angleP2toP1 = Misc.getAngleInDegrees(p2ToP1);
1018 float angleToControlAndP2toP1 = Vector2f.angle(dirP2ToControl, p2ToP1) * Misc.DEG_PER_RAD;
1019 if (angleToControlAndP2toP1 > angleLimit) {
1020 angleToControlAndP2toP1 = angleLimit;
1021 float turnDir = Misc.getClosestTurnDirection(angleP2toP1, angleP2ToControl);
1022 angleP2ToControl = angleP2toP1 + turnDir * angleToControlAndP2toP1;
1023 dirP2ToControl = Misc.getUnitVectorAtDegreeAngle(angleP2ToControl);
1025 float dist = Misc.getDistance(p1, p2);
1027 float h = dist * (float) Math.tan(angleToControlAndP2toP1 * Misc.RAD_PER_DEG);
1028 float b = (float) Math.sqrt(dist * dist + h * h);
1029 dirP2ToControl.scale(b);
1030 Vector2f.add(dirP2ToControl, p2, curr.control);
1032 Vector2f p1 = prev.control;
1033 Vector2f p2 = curr.from;
1034 Vector2f p3 = curr.to;
1035 float angleP2ToControl = Misc.getAngleInDegrees(p1, p2);
1036 Vector2f dirP2ToControl = Misc.getUnitVectorAtDegreeAngle(angleP2ToControl);
1037 Vector2f p2ToP3 = Vector2f.sub(p3, p2,
new Vector2f());
1038 float angleP2ToP3 = Misc.getAngleInDegrees(p2ToP3);
1039 float angleToControlAndP2toP3 = Vector2f.angle(dirP2ToControl, p2ToP3) * Misc.DEG_PER_RAD;
1040 if (angleToControlAndP2toP3 > angleLimit) {
1041 angleToControlAndP2toP3 = angleLimit;
1042 float turnDir = Misc.getClosestTurnDirection(angleP2ToP3, angleP2ToControl);
1043 angleP2ToControl = angleP2ToP3 + turnDir * angleToControlAndP2toP3;
1044 dirP2ToControl = Misc.getUnitVectorAtDegreeAngle(angleP2ToControl);
1047 float dist = Misc.getDistance(p2, p3);
1049 float h = dist * (float) Math.tan(angleToControlAndP2toP3 * Misc.RAD_PER_DEG);
1050 float b = (float) Math.sqrt(dist * dist + h * h);
1051 dirP2ToControl.scale(b);
1052 Vector2f.add(dirP2ToControl, p2, curr.control);
1151 GL11.glDisable(GL11.GL_TEXTURE_2D);
1152 GL11.glEnable(GL11.GL_BLEND);
1153 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1163 Misc.setColor(Color.white);
1164 GL11.glEnable(GL11.GL_LINE_SMOOTH);
1165 GL11.glLineWidth(3f);
1166 GL11.glBegin(GL11.GL_LINE_STRIP);
1167 Vector2f p0 =
new Vector2f(0, 0);
1168 Vector2f p1 =
new Vector2f(10000, 0);
1169 Vector2f p2 =
new Vector2f(0, 10000);
1170 Vector2f p3 =
new Vector2f(10000, 10000);
1171 for (
float t = 0f; t <= 1f; t += 0.02f) {
1172 Vector2f p = Misc.bezierCubic(p0, p1, p2, p3, t);
1173 GL11.glVertex2f(p.x, p.y);
1179 GL11.glEnable(GL11.GL_POINT_SMOOTH);
1180 GL11.glPointSize(10f);
1181 GL11.glBegin(GL11.GL_POINTS);
1182 Misc.setColor(Color.yellow);
1183 for (SlipstreamSection curr :
sections) {
1184 Misc.setColor(Color.yellow);
1185 if (curr.subdivision) {
1186 Misc.setColor(Color.green);
1188 Vector2f p = curr.from;
1189 GL11.glVertex2f(p.x, p.y);
1191 GL11.glVertex2f(p.x, p.y);
1193 Misc.setColor(Color.cyan);
1195 GL11.glVertex2f(p.x, p.y);
1199 Misc.setColor(Color.white);
1200 GL11.glEnable(GL11.GL_LINE_SMOOTH);
1201 GL11.glLineWidth(3f);
1202 GL11.glBegin(GL11.GL_LINE_STRIP);
1203 for (SlipstreamSection curr :
sections) {
1204 for (
float t = 0f; t <= 1f; t += 0.02f) {
1205 Vector2f p = Misc.bezier(curr.from, curr.control, curr.to, t);
1206 GL11.glVertex2f(p.x, p.y);
1213 Misc.setColor(Color.cyan);
1214 GL11.glEnable(GL11.GL_LINE_SMOOTH);
1215 GL11.glLineWidth(3f);
1216 GL11.glBegin(GL11.GL_LINE_LOOP);
1218 for (Vector2f p : box.box) {
1219 GL11.glVertex2f(p.x, p.y);
1228 GL11.glPushMatrix();
1230 GL11.glTranslatef(loc.x - 1000, loc.y + 100, 0f);
1243 Misc.setColor(Color.orange);
1244 GL11.glEnable(GL11.GL_LINE_SMOOTH);
1245 GL11.glLineWidth(3f);
1246 GL11.glBegin(GL11.GL_LINE_STRIP);
1249 for (
int i = 0; i <
buildNoise.length; i++) {
1251 GL11.glVertex2f(i * horz, f * vert);
1261 Misc.setColor(Color.white);
1262 GL11.glBegin(GL11.GL_LINES);
1263 GL11.glVertex2f(0, 0);
1264 GL11.glVertex2f(
buildNoise.length * horz, 0);
1265 GL11.glVertex2f(0, 0);
1266 GL11.glVertex2f(0, vert);