mojo.pp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. {
  2. Ported to FPC by Nikolay Nikolov ([email protected])
  3. }
  4. {
  5. Mojo demo for OpenPTC 1.0 C++ API
  6. Coded by Alex Evans and adapted to OpenPTC 1.0 by Glenn Fiedler
  7. nasty code by alex "statix" evans for ptc. (c) copyright alex evans 1998
  8. time... 02.00 am on 13/1/98.
  9. have fun
  10. it's my take on some classic light mask effect
  11. it's raytracing through properly modelled fog with occlusion, multiple
  12. shadow rays cast back to the light for each pixel ray, and erm, its
  13. s l o w... but it looks nice don't it?
  14. oh and fresnel fall off... or something
  15. UNTESTED! ok?
  16. define inv for interesting fx (not)
  17. }
  18. Program Mojo;
  19. {$MODE objfpc}
  20. Uses
  21. ptc, SysUtils;
  22. { $DEFINE INV}
  23. Const
  24. SC = 12;
  25. MINSEGSIZE = 2.5;
  26. NSEG = 5;
  27. frandtab_seed : Uint16 = 54;
  28. Var
  29. MaskMap : PUint8;
  30. frandtab : Array[0..65535] Of Uint16;
  31. Type
  32. FVector = Object
  33. { Case Boolean Of
  34. False : (X, Y, Z : Single);
  35. True : (R, G, B : Single);}
  36. X, Y, Z : Single;
  37. Constructor Init;
  38. Constructor Init(_x, _y, _z : Single);
  39. Function Magnitude : Single;
  40. Function MagnitudeSq : Single;
  41. Procedure Normalise;
  42. End;
  43. FMatrix = Object
  44. Row : Array[0..2] Of FVector;
  45. Constructor Init;
  46. Constructor Init(a, b, c : FVector);
  47. Function Column0 : FVector;
  48. Function Column1 : FVector;
  49. Function Column2 : FVector;
  50. Procedure MakeXRot(theta : Single);
  51. Procedure MakeYRot(theta : Single);
  52. Procedure MakeZRot(theta : Single);
  53. Procedure MakeID;
  54. Function Transpose : FMatrix;
  55. Procedure TransposeInPlace;
  56. Procedure Normalise;
  57. End;
  58. PRay = ^TRay;
  59. TRay = Object
  60. mPosn : FVector;
  61. mDir : FVector;
  62. Constructor Init(Const p, d : FVector);
  63. End;
  64. VLight = Class(TObject)
  65. mAng : Single;
  66. mPosn : FVector;
  67. mTarget : FVector;
  68. mAxis : FMatrix;
  69. mCol : FVector;
  70. p, p2, _d : FVector; { temp space }
  71. Constructor Create(Const col : FVector);
  72. Procedure Move(Const q : FVector);
  73. Procedure MoveT(Const q : FVector);
  74. Procedure Update;
  75. Function Light(Const ray : TRay) : FVector;
  76. Function CalcLight(t : Single) : Single;
  77. End;
  78. Constructor FVector.Init;
  79. Begin
  80. End;
  81. Constructor FVector.Init(_x, _y, _z : Single);
  82. Begin
  83. X := _x;
  84. Y := _y;
  85. Z := _z;
  86. End;
  87. Function FVector.Magnitude : Single;
  88. Begin
  89. Magnitude := Sqrt(Sqr(X) + Sqr(Y) + Sqr(Z));
  90. End;
  91. Function FVector.MagnitudeSq : Single;
  92. Begin
  93. MagnitudeSq := Sqr(X) + Sqr(Y) + Sqr(Z);
  94. End;
  95. Procedure FVector.Normalise;
  96. Var
  97. l : Single;
  98. Begin
  99. l := 1 / Magnitude;
  100. X *= l;
  101. Y *= l;
  102. Z *= l;
  103. End;
  104. Operator * (a, b : FVector) res : Single;
  105. Begin
  106. res := a.X * b.X + a.Y * b.Y + a.Z * b.Z;
  107. End;
  108. Operator * (a : FVector; b : Single) res : FVector;
  109. Begin
  110. res.X := a.X * b;
  111. res.Y := a.Y * b;
  112. res.Z := a.Z * b;
  113. End;
  114. Operator + (a, b : FVector) res : FVector;
  115. Begin
  116. res.X := a.X + b.X;
  117. res.Y := a.Y + b.Y;
  118. res.Z := a.Z + b.Z;
  119. End;
  120. Operator - (a, b : FVector) res : FVector;
  121. Begin
  122. res.X := a.X - b.X;
  123. res.Y := a.Y - b.Y;
  124. res.Z := a.Z - b.Z;
  125. End;
  126. Operator ** (a, b : FVector) res : FVector;
  127. Begin
  128. res.X := a.Y * b.Z - a.Z * b.Y;
  129. res.Y := a.Z * b.X - a.X * b.Z;
  130. res.Z := a.X * b.Y - a.Y * b.X;
  131. End;
  132. Constructor FMatrix.Init;
  133. Begin
  134. End;
  135. Constructor FMatrix.Init(a, b, c : FVector);
  136. Begin
  137. Row[0] := a;
  138. Row[1] := b;
  139. Row[2] := c;
  140. End;
  141. Function FMatrix.Column0 : FVector;
  142. Var
  143. res : FVector;
  144. Begin
  145. res.Init(Row[0].X, Row[1].X, Row[2].X);
  146. Column0 := res;
  147. End;
  148. Function FMatrix.Column1 : FVector;
  149. Var
  150. res : FVector;
  151. Begin
  152. res.Init(Row[0].Y, Row[1].Y, Row[2].Y);
  153. Column1 := res;
  154. End;
  155. Function FMatrix.Column2 : FVector;
  156. Var
  157. res : FVector;
  158. Begin
  159. res.Init(Row[0].Z, Row[1].Z, Row[2].Z);
  160. Column2 := res;
  161. End;
  162. Procedure FMatrix.MakeXRot(theta : Single);
  163. Var
  164. c, s : Single;
  165. Begin
  166. c := cos(theta);
  167. s := sin(theta);
  168. Row[1].Y := c; Row[1].Z := s; Row[1].X := 0;
  169. Row[2].Y := -s; Row[2].Z := c; Row[2].X := 0;
  170. Row[0].Y := 0; Row[0].Z := 0; Row[0].X := 1;
  171. End;
  172. Procedure FMatrix.MakeYRot(theta : Single);
  173. Var
  174. c, s : Single;
  175. Begin
  176. c := cos(theta);
  177. s := sin(theta);
  178. Row[2].Z := c; Row[2].X := s; Row[2].Y := 0;
  179. Row[0].Z := -s; Row[0].X := c; Row[0].Y := 0;
  180. Row[1].Z := 0; Row[1].X := 0; Row[1].Y := 1;
  181. End;
  182. Procedure FMatrix.MakeZRot(theta : Single);
  183. Var
  184. c, s : Single;
  185. Begin
  186. c := cos(theta);
  187. s := sin(theta);
  188. Row[0].X := c; Row[0].Y := s; Row[0].Z := 0;
  189. Row[1].X := -s; Row[1].Y := c; Row[1].Z := 0;
  190. Row[2].X := 0; Row[2].Y := 0; Row[2].Z := 1;
  191. End;
  192. Procedure FMatrix.MakeID;
  193. Begin
  194. Row[0].Init(1, 0, 0);
  195. Row[1].Init(0, 1, 0);
  196. Row[2].Init(0, 0, 1);
  197. End;
  198. Function FMatrix.Transpose : FMatrix;
  199. Var
  200. res : FMatrix;
  201. Begin
  202. res.Init(Column0, Column1, Column2);
  203. Transpose := res;
  204. End;
  205. Procedure FMatrix.TransposeInPlace;
  206. Begin
  207. Init(Column0, Column1, Column2);
  208. End;
  209. Procedure FMatrix.Normalise;
  210. Begin
  211. Row[2].Normalise;
  212. Row[0] := Row[1]**Row[2];
  213. Row[0].Normalise;
  214. Row[1] := Row[2]**Row[0];
  215. Row[1].Normalise;
  216. End;
  217. Operator * (Const m : FMatrix; Const a : Single) res : FMatrix;
  218. Begin
  219. res.Init(m.Row[0]*a, m.Row[1]*a, m.Row[2]*a);
  220. End;
  221. Operator * (Const m, a : FMatrix) res : FMatrix;
  222. Var
  223. v1, v2, v3 : FVector;
  224. Begin
  225. v1.Init(m.Row[0].X*a.Row[0].X+m.Row[0].Y*a.Row[1].X+m.Row[0].Z*a.Row[2].X,
  226. m.Row[0].X*a.Row[0].Y+m.Row[0].Y*a.Row[1].Y+m.Row[0].Z*a.Row[2].Y,
  227. m.Row[0].X*a.Row[0].Z+m.Row[0].Y*a.Row[1].Z+m.Row[0].Z*a.Row[2].Z);
  228. v2.Init(m.Row[1].X*a.Row[0].X+m.Row[1].Y*a.Row[1].X+m.Row[1].Z*a.Row[2].X,
  229. m.Row[1].X*a.Row[0].Y+m.Row[1].Y*a.Row[1].Y+m.Row[1].Z*a.Row[2].Y,
  230. m.Row[1].X*a.Row[0].Z+m.Row[1].Y*a.Row[1].Z+m.Row[1].Z*a.Row[2].Z);
  231. v3.Init(m.Row[2].X*a.Row[0].X+m.Row[2].Y*a.Row[1].X+m.Row[2].Z*a.Row[2].X,
  232. m.Row[2].X*a.Row[0].Y+m.Row[2].Y*a.Row[1].Y+m.Row[2].Z*a.Row[2].Y,
  233. m.Row[2].X*a.Row[0].Z+m.Row[2].Y*a.Row[1].Z+m.Row[2].Z*a.Row[2].Z);
  234. res.Init(v1, v2, v3);
  235. End;
  236. Operator * (Const m : FMatrix; Const a : FVector) res : FVector;
  237. Begin
  238. res.Init(a*m.Row[0], a*m.Row[1], a*m.Row[2]);
  239. End;
  240. Operator + (Const m, a : FMatrix) res : FMatrix;
  241. Begin
  242. res.Init(m.Row[0]+a.Row[0], m.Row[1]+a.Row[1], m.Row[2]+a.Row[2]);
  243. End;
  244. Operator - (Const m, a : FMatrix) res : FMatrix;
  245. Begin
  246. res.Init(m.Row[0]+a.Row[0], m.Row[1]+a.Row[1], m.Row[2]+a.Row[2]);
  247. End;
  248. Constructor TRay.Init(Const p, d : FVector);
  249. Begin
  250. mPosn := p;
  251. mDir := d;
  252. mDir.Normalise;
  253. End;
  254. Constructor VLight.Create(Const col : FVector);
  255. Begin
  256. mCol := col * 0.9;
  257. mAng := 2.8;
  258. mPosn.Init(0, 0, 20);
  259. mTarget.Init(0, 0, 0.1);
  260. mAxis.MakeID;
  261. Update;
  262. End;
  263. Procedure VLight.Move(Const q : FVector);
  264. Begin
  265. mPosn := q;
  266. Update;
  267. End;
  268. Procedure VLight.MoveT(Const q : FVector);
  269. Begin
  270. mTarget := q;
  271. Update;
  272. End;
  273. Procedure VLight.Update;
  274. Begin
  275. mAxis.Row[2] := (mTarget - mPosn);
  276. mAxis.Normalise;
  277. End;
  278. Function VLight.Light(Const ray : TRay) : FVector;
  279. Var
  280. f, A, B, C, D, t1, t2, t3, fr, l1, l2, t, h : Single;
  281. frc, x, y, q : Integer;
  282. pp : FVector;
  283. res : FVector;
  284. Begin
  285. f := 0;
  286. p2 := ray.mPosn;
  287. p := mAxis * (ray.mPosn - mPosn);
  288. _d := mAxis * ray.mDir;
  289. A := (_d.X*_d.X+_d.Y*_d.Y);
  290. B := 2*(_d.X*p.X+_d.Y*p.Y)-mAng*(_d.Z);
  291. C := (p.X*p.X+p.Y*p.Y)-mAng*(p.Z);
  292. D := B*B-4*A*C;
  293. If D <= 0 Then
  294. Begin
  295. res.Init(0, 0, 0);
  296. Light := res;
  297. Exit;
  298. End;
  299. D := Sqrt(D);
  300. A *= 2;
  301. t1 := (-B-D)/A;
  302. t2 := (-B+D)/A;
  303. frc := 255;
  304. t3 := -ray.mPosn.Z/ray.mDir.Z;
  305. If t2<=0 Then
  306. Begin
  307. res.Init(0, 0, 0);
  308. Light := res;
  309. Exit;
  310. End;
  311. If t1<0 Then
  312. t1 := 0;
  313. If t3>0 Then
  314. Begin
  315. { clip to bitmap plane }
  316. pp := ray.mPosn + ray.mDir*t3;
  317. x := 160+Trunc(SC*pp.X);
  318. {$IFNDEF INV}
  319. If (x>=0) And (x<=319) Then
  320. Begin
  321. y := 100 + Trunc(SC*pp.Y);
  322. If (y>=0) And (y<=199) Then
  323. Begin
  324. {res.Init(0, 0, 1);
  325. Light := res;
  326. Exit;}
  327. frc := MaskMap[y*320+x];
  328. If frc<1 Then
  329. Begin
  330. If t1>t3 Then
  331. t1 := t3;
  332. If t2>t3 Then
  333. t2 := t3;
  334. End;
  335. End
  336. Else
  337. t3 := t2
  338. End
  339. Else
  340. t3 := t2;
  341. {$ELSE}
  342. If (x >= 0) And (x <= 319) Then
  343. Begin
  344. y := 100 + Trunc(SC*pp.Y);
  345. If (y >= 0) And (y <= 199) And (MaskMap[y*320 + x] < 128) Then
  346. t3 := t2;
  347. End;
  348. If t1 > t3 Then
  349. t1 := t3;
  350. If t2 > t3 Then
  351. t2 := t3;
  352. {$ENDIF}
  353. End;
  354. If t1>=t2 Then
  355. Begin
  356. res.Init(0, 0, 0);
  357. Light := res;
  358. Exit;
  359. End;
  360. fr := frc/255;
  361. l1 := CalcLight(t1);
  362. If t1>t3 Then
  363. l1 *= fr;
  364. q := NSEG;
  365. t := t1;
  366. h := (t2-t1)/NSEG;
  367. If h<MINSEGSIZE Then
  368. h := MINSEGSIZE;
  369. While (t<t3) And (q>0) And (t<t2) Do
  370. Begin
  371. t += h;
  372. If (t>t2) Then
  373. Begin
  374. h -= t2-t;
  375. t := t2;
  376. q := 0;
  377. End
  378. Else
  379. Dec(q);
  380. h := (t-t1);
  381. p += _d*h;
  382. p2 += ray.mDir*h;
  383. l2 := CalcLight(t);
  384. f += (l1+l2)*h;
  385. l1 := l2;
  386. t1 := t;
  387. End;
  388. While (q>0) And (t<t2) Do
  389. Begin
  390. t += h;
  391. If t>t2 Then
  392. Begin
  393. h -= t2-t;
  394. t := t2;
  395. q := 0;
  396. End
  397. Else
  398. Dec(q);
  399. p += _d*h;
  400. p2 += ray.mDir*h;
  401. l2 := CalcLight(t);
  402. If t>t3 Then
  403. l2 *= fr;
  404. f += (l1+l2)*h;
  405. l1 := l2;
  406. t1 := t;
  407. End;
  408. Light := mCol*f;
  409. End;
  410. Function VLight.CalcLight(t : Single) : Single;
  411. Var
  412. f : Single;
  413. x, y, c : Integer;
  414. Begin
  415. { trace line to bitmap from mPosn to p2 }
  416. If Not ((mPosn.Z > 0) Xor (p2.Z > 0)) Then
  417. Begin
  418. { fresnel fall off... }
  419. CalcLight := p.Z / p.MagnitudeSq;
  420. Exit;
  421. End;
  422. f := -(mPosn.Z)/(p2.Z - mPosn.Z);
  423. x := 160 + Trunc(SC*((p2.X-mPosn.X)*f+mPosn.X));
  424. {$IFNDEF INV}
  425. If (x < 0) Or (x > 319) Then
  426. Begin
  427. CalcLight := p.Z / p.MagnitudeSq;
  428. Exit;
  429. End;
  430. y := 100 + Trunc(SC*((p2.Y-mPosn.Y)*f+mPosn.Y));
  431. If (y < 0) Or (y > 199) Then
  432. Begin
  433. CalcLight := p.Z / p.MagnitudeSq;
  434. Exit;
  435. End;
  436. c := MaskMap[y * 320 + x];
  437. {$ELSE}
  438. If (x < 0) Or (x > 319) Then
  439. Begin
  440. CalcLight := 0;
  441. Exit;
  442. End;
  443. y := 100 + Trunc(SC*((p2.Y-mPosn.Y)*f+mPosn.Y));
  444. If (y < 0) Or (y > 199) Then
  445. Begin
  446. CalcLight := 0;
  447. Exit;
  448. End;
  449. c := 255 - MaskMap[y * 320 + x];
  450. {$ENDIF}
  451. If c = 0 Then
  452. Begin
  453. CalcLight := 0;
  454. Exit;
  455. End;
  456. CalcLight := (c*(1/255))*p.Z / p.MagnitudeSq;
  457. End;
  458. Function CLIPC(f : Single) : Integer; {Inline;}
  459. Var
  460. a : Integer;
  461. Begin
  462. a := Trunc(f * 255);
  463. If a < 0 Then
  464. a := 0
  465. Else
  466. If a > 255 Then
  467. a := 255;
  468. CLIPC := a;
  469. End;
  470. Procedure initfrand;
  471. Var
  472. s, c1 : Integer;
  473. Begin
  474. FillChar(frandtab, SizeOf(frandtab), 0);
  475. s := 1;
  476. For c1 := 1 To 65535 Do
  477. Begin
  478. frandtab[c1] := s And $FFFF;
  479. s := (((s Shr 4) Xor (s Shr 13) Xor (s Shr 15)) And 1) + (s Shl 1);
  480. End;
  481. End;
  482. Function frand : Integer; {Inline;}
  483. Begin
  484. frand := frandtab[frandtab_seed];
  485. frandtab_seed := (frandtab_seed + 1) And $FFFF;
  486. End;
  487. Procedure VLightPart(console : TPTCConsole; surface : TPTCSurface);
  488. Var
  489. vl, vl2 : VLight;
  490. camposn : FVector;
  491. camaxis : FMatrix;
  492. c1, c2, c3, ti, xx, yy, zz, i, a, x, y : Integer;
  493. idx : Array[0..(200 Div 16) - 1, 0..(320 Div 16) - 1] Of Uint8;
  494. order : Array[0..10*19 - 1, 0..1] Of Integer;
  495. vlightt, t, cz, camf : Single;
  496. col : FVector;
  497. ray : TRay;
  498. oc, c, c2_ : Uint32;
  499. time, delta : Single;
  500. pitch : Integer;
  501. screenbuf, pd : PUint8;
  502. tmp : FVector;
  503. F : File;
  504. Begin
  505. oc := 0;
  506. initfrand;
  507. tmp.Init(0.1, 0.4, 1);
  508. vl := VLight.Create(tmp);
  509. tmp.Init(1, 0.5, 0.2);
  510. vl2 := VLight.Create(tmp);
  511. tmp.Init(0, 0, 20);
  512. vl.Move(tmp);
  513. tmp.Init(0, 6, 30);
  514. vl2.Move(tmp);
  515. camposn.Init(7, 0.5, -10);
  516. camaxis.Init;
  517. camaxis.MakeID;
  518. tmp.Init(0, 0, 0);
  519. camaxis.Row[2] := tmp - camposn;
  520. camaxis.Normalise;
  521. camf := 100;
  522. MaskMap := GetMem(320 * 200);
  523. FillChar(MaskMap^, 320 * 200, 0);
  524. { load mojo.raw }
  525. ASSign(F, 'mojo.raw');
  526. Reset(F, 1);
  527. BlockRead(F, MaskMap^, 320*200);
  528. Close(F);
  529. { build the order of the squares }
  530. For c1 := 0 To 10*19 - 1 Do
  531. Begin
  532. order[c1, 0] := c1 Mod 19;
  533. order[c1, 1] := (c1 Div 19) + 1;
  534. End;
  535. { swap them around }
  536. For c1 := 0 To 9999 Do
  537. Begin
  538. c2 := Random(190);
  539. c3 := Random(190);
  540. ti := order[c2, 0]; order[c2, 0] := order[c3, 0]; order[c3, 0] := ti;
  541. ti := order[c2, 1]; order[c2, 1] := order[c3, 1]; order[c3, 1] := ti;
  542. End;
  543. { time settings }
  544. time := 0;
  545. delta := 0.01; { this controls the speed of the effect }
  546. { main loop }
  547. While Not console.KeyPressed Do
  548. Begin
  549. { get surface data }
  550. pitch := surface.pitch;
  551. { light time (makes the effect loop) }
  552. vlightt := 320 * Abs(Sin(time/5));
  553. t := 13 - 0.1822 * vlightt;
  554. cz := 1 - 0.01 * vlightt;
  555. {tmp.Init(Sin(t)*5, Cos(t*-0.675+4543)*5, 15);
  556. vl.Move(tmp);
  557. tmp.Init(0, 0, -15);
  558. vl.Move(tmp);}
  559. tmp.Init(t, 0, 22);
  560. vl.Move(tmp);
  561. tmp.Init(-t, -7, 28);
  562. vl2.Move(tmp);
  563. camposn.Init(cz*4+9, cz, -t/7-13);
  564. tmp.Init(0, 0, 0);
  565. camaxis.Row[2] := tmp - camposn;
  566. camaxis.Normalise;
  567. FillChar(idx, SizeOf(idx), 25);
  568. { swap them around }
  569. For c1 := 0 To 99 Do
  570. Begin
  571. c2 := Random(190);
  572. c3 := Random(190);
  573. ti := order[c2, 0]; order[c2, 0] := order[c3, 0]; order[c3, 0] := ti;
  574. ti := order[c2, 1]; order[c2, 1] := order[c3, 1]; order[c3, 1] := ti;
  575. End;
  576. For zz := 0 To 189 Do
  577. Begin
  578. xx := order[zz, 0];
  579. yy := order[zz, 1];
  580. i := 0;
  581. { lock surface }
  582. screenbuf := surface.lock;
  583. Try
  584. c2 := idx[yy, xx] Shr 1;
  585. For c1 := 0 To c2 - 1 Do
  586. Begin
  587. a := frand And 255;
  588. x := xx * 16 + (a And 15) + 6 + 4;
  589. y := yy * 16 + (a Shr 4) + 6;
  590. col.Init(0, 0, 0);
  591. ray.Init(camposn, camaxis.Row[2]*camf+camaxis.Row[0]*(x-160)+camaxis.Row[1]*(y-100));
  592. col += vl.Light(ray);
  593. col += vl2.Light(ray);
  594. c := (CLIPC(col.X) Shl 16) + (CLIPC(col.Y) Shl 8) + (CLIPC(col.Z));
  595. pd := screenbuf + x*4 + y*pitch;
  596. Inc(i, Abs(Integer(c And 255)-Integer(pd[321] And 255)) + Abs(Integer(c Shr 16)-Integer(pd[321] Shr 16)));
  597. If c1 <> 0 Then
  598. Inc(i, Abs(Integer(c And 255)-Integer(oc And 255)) + Abs(Integer(c Shr 16)-Integer(oc Shr 16)));
  599. oc := c;
  600. c2_ := (c Shr 1) And $7F7F7F;
  601. PUint32(pd)[1] := ((PUint32(pd)[1]) Shr 1) And $7F7F7F+ c2_;
  602. PUint32(pd)[2] := ((PUint32(pd)[2]) Shr 1) And $7F7F7F+ c2_;
  603. Inc(pd, pitch);
  604. PUint32(pd)[0] := ((PUint32(pd)[0]) Shr 1) And $7F7F7F+ c2_;
  605. PUint32(pd)[1] := c;
  606. PUint32(pd)[2] := c;
  607. PUint32(pd)[3] := ((PUint32(pd)[3]) Shr 1) And $7F7F7F+ c2_;
  608. Inc(pd, pitch);
  609. PUint32(pd)[0] := ((PUint32(pd)[0]) Shr 1) And $7F7F7F+ c2_;
  610. PUint32(pd)[1] := c;
  611. PUint32(pd)[2] := c;
  612. PUint32(pd)[3] := ((PUint32(pd)[3]) Shr 1) And $7F7F7F+ c2_;
  613. Inc(pd, pitch);
  614. PUint32(pd)[1] := ((PUint32(pd)[1]) Shr 1) And $7F7F7F+ c2_;
  615. PUint32(pd)[2] := ((PUint32(pd)[2]) Shr 1) And $7F7F7F+ c2_;
  616. End;
  617. i *= 5;
  618. i := i Div (3*idx[yy, xx]);
  619. If i < 2 Then
  620. i := 2;
  621. If i > {256}255 Then
  622. i := {256}255;
  623. idx[yy, xx] := i;
  624. Finally
  625. { unlock surface }
  626. surface.unlock;
  627. End;
  628. If (zz Mod 95) = 0 Then
  629. Begin
  630. { copy surface to console }
  631. surface.copy(console);
  632. { update console }
  633. console.update;
  634. End;
  635. End;
  636. { update time }
  637. time += delta;
  638. End;
  639. FreeMem(MaskMap);
  640. vl.Free;
  641. vl2.Free;
  642. End;
  643. Var
  644. format : TPTCFormat;
  645. console : TPTCConsole;
  646. surface : TPTCSurface;
  647. Begin
  648. format := Nil;
  649. surface := Nil;
  650. console := Nil;
  651. Try
  652. Try
  653. { create format }
  654. format := TPTCFormat.Create(32, $00FF0000, $0000FF00, $000000FF);
  655. { create console }
  656. console := TPTCConsole.Create;
  657. { open console }
  658. console.open('mojo by statix', 320, 200, format);
  659. { create main drawing surface }
  660. surface := TPTCSurface.Create(320, 200, format);
  661. { do the light effect }
  662. VLightPart(console, surface);
  663. Finally
  664. { close console }
  665. console.close;
  666. console.Free;
  667. surface.Free;
  668. format.Free;
  669. End;
  670. { print message to stdout }
  671. Writeln('mojo by alex "statix" evans');
  672. Writeln('to be used as an example of bad coding and good ptc');
  673. Writeln('no responsibility taken for this!');
  674. Writeln('enjoy ptc! it''s great');
  675. Writeln;
  676. Writeln('-statix 13/1/98');
  677. Except
  678. On error : TPTCError Do
  679. { report error }
  680. error.report;
  681. End;
  682. End.