Advertisement
Guest User

Untitled

a guest
Nov 21st, 2019
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.03 KB | None | 0 0
  1. class DSH_cPoint: object
  2. {
  3. vector3 pos;
  4. static DSH_cPoint init(vector3 pushPos)
  5. {
  6. let p = new("DSH_cPoint");
  7. p.pos = pushPos;
  8. return p;
  9. }
  10. }
  11.  
  12. class DSH_ActorPoint: object
  13. {
  14. color col;
  15. vector3 pos;
  16. vector3 nextpos;
  17. actor act;
  18. static DSH_ActorPoint init(vector3 pushPos)
  19. {
  20.  
  21. let p = new("DSH_actorPoint");
  22. p.pos = pushPos;
  23. p.col = "AAFFFF";
  24. return p;
  25. }
  26. }
  27.  
  28.  
  29. class DSH_kBezier : object play
  30. {
  31. actor spawner;
  32. array<DSH_cPoint> cPoints; //these are the control points for the curves
  33. array<DSH_ActorPoint> actorPoints; //these are were actors will be spawned
  34. array<actor> beamActors; //these are the actual actors
  35.  
  36. //Credits to 3saster for writing this much improved version of the function!
  37. static Vector3 PointOnCurve(double t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, bool unitspeed=false, int prec=50, double arcLength = -1)
  38. {
  39. // based off of this to get unit speed
  40. // https://gamedev.stackexchange.com/a/27138
  41. if(unitspeed) //precise but slow
  42. {
  43. Vector3 v1 = -3*p0 +9*p1 -9*p2 +3*p3;
  44. Vector3 v2 = 6*p0 -12*p1 +6*p2;
  45. Vector3 v3 = -3*p0 +3*p1;
  46.  
  47. double ts = 0;
  48. double L = arcLength >= 0 ? arcLength : CurveLength(p0, p1, p2, p3) * t;
  49. for(int p=0; p<prec; p++)
  50. {
  51. Vector3 scaler = ts*ts*v1+ts*v2+v3;
  52. ts += L/prec/scaler.Length();
  53. }
  54. return PointOnCurve(ts,p0,p1,p2,p3);
  55. }
  56. else //much faster
  57. {
  58. double u = 1 - t;
  59. double tt = t*t;
  60. double uu = u*u;
  61. double uuu = uu * u;
  62. double ttt = tt * t;
  63. Vector3 p = uuu * p0; //first term
  64. p += 3 * uu * t * p1; //second term
  65. p += 3 * u * tt * p2; //third term
  66. p += ttt * p3; //fourth term
  67. return p;
  68. }
  69. }
  70. //Credits to 3saster!
  71. static double CurveLength(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, int prec=5000, double tend=1)
  72. {
  73. Array<double> ds;
  74. double precision = 1./(prec - prec%2);
  75.  
  76. for(double t = 0; t <= tend; t += precision)
  77. {
  78. double u = 1 - t;
  79. double tt = t*t;
  80. double uu = u*u;
  81. Vector3 p = (0,0,0);
  82. p += 3 * uu * 1 * (p1 - p0); //first term
  83. p += 6 * u * t * (p2 - p1); //second term
  84. p += 3 * 1 * tt * (p3 - p2); //third term
  85. ds.push( sqrt(p.x*p.x + p.y*p.y + p.z*p.z) );
  86. }
  87.  
  88. // Simpson's Rule
  89. double arclength = ds[0] + ds[ds.size()-1];
  90. //4's
  91. for(int i = 1; i < ds.Size()-1; i += 1)
  92. {
  93. arclength += 2*ds[i];
  94. }
  95. //2's
  96. for(int i = 2; i < ds.Size()-1; i += 2)
  97. {
  98. arclength += 2*ds[i];
  99. }
  100.  
  101. return arclength*precision/3;
  102. }
  103.  
  104. void SubdivideSingleCurve(int index, double t = 0.5, bool extendcurve = true)
  105. {
  106. vector3 p0 = cPoints[index].pos;
  107. vector3 p1 = cPoints[index+1].pos;
  108. vector3 p2 = cPoints[index+2].pos;
  109. vector3 p3 = cPoints[index+3].pos;
  110.  
  111. vector3 p11 = ((1.0 - t)*p0) + (t*p1);
  112. vector3 p21 = ((1.0 - t)*p1) + (t*p2);
  113. vector3 p31 = ((1.0 - t)*p2) + (t*p3);
  114. vector3 p12 = ((1.0 - t)*p11)+ (t*p21);
  115. vector3 p22 = ((1.0 - t)*p21)+ (t*p31);
  116. vector3 p13 = ((1.0 - t)*p12)+ (t*p22);
  117.  
  118. //overwrite indices for the first part of the new divided curve;
  119. cPoints[index+1].pos = p11;
  120. cPoints[index+2].pos = p12;
  121. cPoints[index+3].pos = p13;
  122. //insert new control points.
  123. if(extendcurve)
  124. {
  125. InsertPoint(p22, index+4);
  126. InsertPoint(p31, index+5);
  127. InsertPoint(p3, index+6); //put the original endpoint back :)
  128. }
  129. else //this would be for when the function is called for repositioning
  130. {
  131. cPoints[index+4].pos = p22;
  132. cPoints[index+5].pos = p31;
  133. cPoints[index+6].pos = p3;
  134. }
  135. }
  136.  
  137. void BeginCurveExplicit(vector3 p0, vector3 p1, vector3 p2, vector3 p3, bool subdivision = false)
  138. {
  139. //the first curve in the spline needs to have 4 control points.
  140. cPoints.Push(DSH_cPoint.init(p0));
  141. cPoints.Push(DSH_cPoint.init(p1));
  142. cPoints.Push(DSH_cPoint.init(p2));
  143. cPoints.Push(DSH_cPoint.init(p3));
  144. if(subdivision)
  145. {
  146. SubdivideSingleCurve(0, 0.5,true);
  147. }
  148. }
  149.  
  150. void InsertPoint(vector3 p,int index)
  151. {
  152. cPoints.insert(index,DSH_cPoint.init(p));
  153. }
  154.  
  155.  
  156. void ExtendCurveExplicit(vector3 p0, vector3 p1, vector3 p2, bool subdivision = false)
  157. {
  158. //the second one and all later ones will share a control point with the last curve.
  159. cPoints.Push(DSH_cPoint.init(p0));
  160. cPoints.Push(DSH_cPoint.init(p1));
  161. cPoints.Push(DSH_cPoint.init(p2));
  162. if(subdivision)
  163. {
  164. SubdivideSingleCurve(cPoints.size()-4, 0.5,true);
  165. }
  166. }
  167.  
  168. void RepositionCurve4(int index, vector3 p0, vector3 p1, vector3 p2, vector3 p3)
  169. {
  170. //the first curve in the spline needs to have 4 control points.
  171. cPoints[index].pos = p0;
  172. cPoints[index-1].pos = p1;
  173. cPoints[index-2].pos = p2;
  174. cPoints[index-3].pos = p3;
  175. }
  176.  
  177. void RepositionCurve3(int index, vector3 p0, vector3 p1, vector3 p2)
  178. {
  179. //the first curve in the spline needs to have 4 control points.
  180. cPoints[index].pos = p0;
  181. cPoints[index-1].pos = p1;
  182. cPoints[index-2].pos = p2;
  183. }
  184.  
  185. void SpawnOrRepositionBeams(int limit = 4, bool Reposition = false)
  186. {
  187. int siz = cPoints.size();
  188. if(true)
  189. {
  190. for(int k = 0; k<siz; k++)
  191. {
  192. actor bleb = DSH_Dot(actor.spawn("DSH_Dot",cPoints[k].pos));
  193. //bleb.SetShade( color(255,int(255*(double(k)/siz)),0,0) );
  194. }
  195. }
  196. if(siz <= 4)
  197. return;
  198. //TODO: will need special case for this
  199.  
  200. limit = max(4, limit);
  201. //TODO - maybe remove this?
  202. int counter = 0;
  203.  
  204. for(int i = 3; i< siz; i+=3)
  205. {
  206. for(int j = 0; j<limit; j++)
  207. {
  208. vector3 startpoint = PointOnCurve(j / double(limit), cPoints[i].pos, cPoints[i-1].pos, cPoints[i-2].pos, cPoints[i-3].pos,false);
  209. vector3 endpoint = PointOnCurve((j+1) / double(limit), cPoints[i].pos, cPoints[i-1].pos, cPoints[i-2].pos, cPoints[i-3].pos,False);
  210.  
  211. actor beam;
  212.  
  213. if(i < (siz*0.5)) //reverse the start/end order at approx the half way mark.
  214. {
  215. vector3 temp = startpoint;
  216. startpoint = endpoint;
  217. endpoint = temp;
  218. }
  219.  
  220. if(!reposition) //if there are no beams already loaded, we spawn one
  221. {
  222. beam = actor.spawn("DSH_BasicBeam",startpoint);
  223. beamActors.push(beam);
  224. }
  225. else //otherwise we pick the right one from the array
  226. {
  227. beam = beamActors[counter];
  228. beam.args[0] = 1; //the beam will remove itself unless we continually refresh this value. Using args[] so they don't have to inherit from anything.
  229. }
  230.  
  231. let p = playerpawn(spawner); //special case for players, to attempt fancy interpolation
  232. if(p)
  233. {
  234. //the below is a bit overengineered atm
  235. vector3 spdif = level.vec3diff((p.pos.xy, p.player.viewz),startpoint);
  236. vector3 spoff = level.vec3offset((p.pos.xy,p.player.viewz),spdif) ;
  237. vector3 dif = level.Vec3Diff(spoff,endpoint);
  238. spoff += (p.vel.xy,0);
  239. beam.SetOrigin(spoff,true);
  240. vector2 angs = DSH_kMath.AnglesFromVec3(dif);
  241. beam.A_SetAngle(angs.x,SPF_INTERPOLATE);
  242. beam.A_SetPitch(angs.y-(reposition*90),SPF_INTERPOLATE);
  243. beam.scale = (1.0,dif.length());
  244. beam.args[0] = 1;
  245. }
  246. counter++;
  247. }
  248. }
  249. //console.PrintF("counter is %i",counter);
  250. }
  251.  
  252.  
  253. void GenerateActorPoints(int pointsPerCurve = 4)
  254. {
  255. //cPoints is an array that contains every control point of the polybezier
  256. int siz = cPoints.size();
  257. int halfway = floor(siz*0.5);
  258.  
  259. //will need special case later on probably.
  260. if(siz <= 4)
  261. return;
  262.  
  263. //not strictly needed perhaps, but cubic curves don't make sense with less than 4 segments per curve imo
  264. pointsPerCurve = max(4, pointsPerCurve);
  265.  
  266. //increased every time we create and actor point
  267. int counter = 0;
  268.  
  269. for(int i = 3; i< siz; i+=3) //three steps forward because we check backwards in the nested loop
  270. {
  271. for(int j = pointsPerCurve; j>=0; j--)
  272. {
  273. vector3 newPoint = PointOnCurve(j / double(pointsPerCurve), cPoints[i].pos, cPoints[i-1].pos, cPoints[i-2].pos, cPoints[i-3].pos,false);
  274.  
  275. //old method. We don't want to have to sample twice per point, since we can set/get from or on previous points.
  276. //vector3 endpoint = PointOnCurve((j+1) / double(pointsPerCurve), cPoints[i].pos, cPoints[i-1].pos, cPoints[i-2].pos, cPoints[i-3].pos,False);
  277.  
  278. DSH_ActorPoint pt = DSH_ActorPoint(DSH_actorPoint.init(newPoint));
  279.  
  280. //the idea of the block below is to orient the pos/nextpos of the
  281. //actor points so their pos (i.e where the real actor will be
  282. //spawned) is oriented outward to the end points from the midddle
  283. //point. Like this: <<<<<<<<middle>>>>>>>>>>
  284.  
  285. //|||||||||||||||||||||||||||
  286. if(i < halfway)
  287. {
  288. pt.pos = newPoint;
  289. if(counter>0)
  290. {
  291. actorPoints[counter-1].nextpos = newPoint;
  292. }
  293. }
  294.  
  295. else if(i <= halfway+1 && j == pointsPerCurve) //this is supposed to happen once, exactly after the halfway mark.
  296. {
  297. actorPoints[counter-1].nextpos = newPoint;
  298. //current actor will be effectively invisible here, but this makes everything work.
  299. //TODO: send halp
  300. pt.pos = newPoint;
  301. pt.nextpos = newPoint;
  302. }
  303. else
  304. {
  305. pt.pos = actorPoints[counter-1].nextPos;
  306. pt.nextPos = newPoint;
  307. }
  308. //|||||||||||||||||||||||||||
  309.  
  310. actorPoints.push(pt);
  311. counter++;
  312. }
  313. }
  314. }
  315.  
  316. void ActorsOnPoints(bool maintain = false)
  317. {
  318. int siz = actorpoints.size();
  319. for(int i = 0; i< siz; i++)
  320. {
  321. actor beam;
  322. vector3 startpoint = actorpoints[i].pos;
  323. vector3 endpoint = actorpoints[i].nextpos;
  324.  
  325. if(!maintain)
  326. {
  327. beam = actor.spawn("DSH_BasicBeam",startpoint);
  328. actorPoints[i].act = beam;
  329. }
  330. else
  331. {
  332. beam = actorPoints[i].act;
  333. }
  334. let p = playerpawn(spawner); //special case for players, to attempt fancy interpolation
  335. if(p)
  336. {
  337. //TODO: the below is a bit overengineered atm
  338. vector3 spdif = level.vec3diff((p.pos.xy, p.player.viewz),startpoint);
  339. vector3 spoff = level.vec3offset((p.pos.xy,p.player.viewz),spdif) ;
  340. vector3 dif = level.Vec3Diff(spoff,endpoint);
  341. spoff += (p.vel.xy,0);
  342. beam.SetOrigin(spoff,true);
  343. vector2 angs = DSH_kMath.AnglesFromVec3(dif);
  344. beam.A_SetAngle(angs.x,SPF_INTERPOLATE);
  345. beam.A_SetPitch(angs.y,SPF_INTERPOLATE);
  346. beam.scale = (1.0,dif.length());
  347. beam.args[0] = 1;
  348. beam.SetShade(actorpoints[i].col);
  349. }
  350. }
  351. }
  352. }
  353.  
  354.  
  355. Class DSH_BasicBeam : actor
  356. {
  357. override void tick()
  358. {
  359. super.tick();
  360. args[0]--;
  361. }
  362.  
  363. default
  364. {
  365. +noblockmap;
  366. +nogravity;
  367. +nointeraction;
  368. renderstyle "addshaded";
  369. StencilColor "aaFFFF";
  370. alpha 2;
  371. }
  372. Override void PostBeginPlay()
  373. {
  374. self.pitch -= 90.0;
  375. }
  376. states
  377. {
  378.  
  379. spawn:
  380. TNT1 A 1 nodelay;
  381. goto beamloop;
  382.  
  383. beamloop:
  384. MODL A 1 bright;
  385. TNT1 A 0 A_JumpIf(args[0] <= 0,"byebyebeam");
  386. loop;
  387.  
  388. byebyebeam:
  389. tnt1 A 0;
  390. stop;
  391. }
  392. }
  393.  
  394. class DSH_Dot : actor
  395. {
  396. default
  397. {
  398. +noblockmap;
  399. +nogravity;
  400. +nointeraction;
  401. renderstyle "addshaded";
  402. StencilColor "FF0000";
  403. scale 0.24;
  404. alpha 2;
  405. }
  406. Override void PostBeginPlay()
  407. {
  408. self.pitch -= 90.0;
  409.  
  410. }
  411. states
  412. {
  413. spawn:
  414. TNT1 A 0 nodelay;
  415. BAL1 A 1 bright;
  416. stop;
  417. }
  418. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement