mojo.pp 17 KB

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