PROTGA.PAS 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. Uses UVector, ObjTrace, Gtypes,Objects, Dos;
  2. CONST
  3. TGAHeader : array [1..12] of byte = (0,0,2,0, 0,0,0,0, 0,0,0,0);
  4. MAXRecur = 5;
  5. HeadSize = 18;
  6. PlanesDist = 320;
  7. PlanesFOV = 60;
  8. type
  9. PProTGATrace = ^ProTGATrace;
  10. ProTGATrace = object (TTracer)
  11. outF : FILE;
  12. ver : longint;
  13. Constructor Init(OutPut : string;ResX,ResY:word);
  14. Procedure GetPointColor(var aC:RGB;aRay:TRay);
  15. Procedure GetPointColor2(var aC:RGB;aRay:TRay);
  16. { Использование более "честной" с точки зрения физики формулы
  17. рассчета освещенности (делим коэффициенты на квадрат расстояния)
  18. Требуются источники в 5000-20000 раз мощнее
  19. }
  20. Procedure GetReflPointColor(var aC:RGB;aRay:TRay;Num:word);
  21. {
  22. Работают отражения !!!!
  23. Num - глубина рекурсии (для первого запуска - 1)
  24. }
  25. Procedure Trace(ResX,ResY:longint;BegSet,Increase:longint);
  26. Destructor Done;virtual;
  27. end;
  28. {TGATrace}
  29. Constructor ProTGATrace.Init(OutPut : string;ResX,ResY:word);
  30. var res:word;
  31. begin
  32. Inherited Init;
  33. Ver := CurVer;
  34. Assign(outF,OutPut);
  35. Rewrite(outF,1);
  36. BlockWrite(outF,TGAHeader,12,Res);
  37. if Res <> 12 then
  38. begin
  39. WriteLn('Writing to ',OutPut,' error!');
  40. Halt(255);
  41. end;
  42. ResX:=ResX*2;
  43. ResY:=ResY*2;
  44. BlockWrite(outF,ResX,2);
  45. BlockWrite(outF,ResY,2);
  46. res:=24;
  47. BlockWrite(outF,res,2);
  48. end;
  49. Procedure ProTGATrace.GetPointColor(var aC:RGB;aRay:TRay);
  50. var
  51. Lt : POmni;
  52. Ob : PSurfObj;
  53. oC : RGB;
  54. Norm, Intr,R : tVec;
  55. LRay : TRay;
  56. Dest,tmp : float;
  57. i : word;
  58. begin
  59. SetColor(aC,0,0,0);
  60. oB := PSurfObj(FindISect(aRay,Dest));
  61. if oB = nil then exit;
  62. aC := Ambient;
  63. aRay.GetPoint(Intr,Dest);
  64. oB^.GetNormal(Norm,Intr);
  65. for i := 1 to LightCount do
  66. if Pos('OMNI',Lights^[i]^.OType) <> 0 then
  67. begin
  68. Lt := POmni(Lights^[i]);
  69. LRay.Init(Intr,Intr);
  70. VLinear(LRay.Dir,Lt^.Pos,Intr,1,-1);
  71. if (FindISect(LRay,tmp) = nil) or (tmp>1.0) then
  72. begin
  73. tmp := Vcos(Norm,LRay.Dir) * oB^.Surface^.Kd;
  74. CAddMul(aC,Lt^.Color,tmp);
  75. VLinear(R,Norm,LRay.Dir,-2*VDot(Norm,LRay.Dir),1);
  76. tmp := Pow(VCos(R,aRay.Dir),Ob^.Surface^.Ns)*Ob^.Surface^.Ks;
  77. CAddMul(aC,Lt^.Color,tmp);
  78. end;
  79. end;
  80. Ob^.GetColor(oC,Intr);
  81. aC.R := aC.R * OC.R;
  82. aC.G := aC.G * OC.G;
  83. aC.B := aC.B * OC.B;
  84. end;{TGATrace.GetPointColor}
  85. {-------------------------}
  86. Procedure ProTGATrace.GetPointColor2(var aC:RGB;aRay:TRay);
  87. var
  88. Lt : POmni;
  89. Ob : PSurfObj;
  90. OC : RGB;
  91. Norm, Intr,R : tVec;
  92. LRay : TRay;
  93. Dest,tmp : float;
  94. i : word;
  95. begin
  96. SetColor(aC,0,0,0);
  97. oB := PSurfObj(FindISect(aRay,Dest));
  98. if oB = nil then exit;
  99. aC := Ambient;
  100. aRay.GetPoint(Intr,Dest);
  101. oB^.GetNormal(Norm,Intr);
  102. for i := 1 to LightCount do
  103. if Pos('OMNI',Lights^[i]^.OType) <> 0 then
  104. begin
  105. Lt := POmni(Lights^[i]);
  106. LRay.Init(Intr,Intr);
  107. VLinear(LRay.Dir,Lt^.Pos,Intr,1,-1);
  108. if (FindISect(LRay,tmp) = nil) or (tmp>1.0) then
  109. begin
  110. tmp := Vcos(Norm,LRay.Dir) * oB^.Surface^.Kd
  111. {New 2 Prev} / VDot(LRay.Dir,LRay.Dir); {Делим на квадрат расстояния
  112. до источника}
  113. CAddMul(aC,Lt^.Color,tmp);
  114. VLinear(R,Norm,LRay.Dir,-2*VDot(Norm,LRay.Dir),1);
  115. tmp := Pow(VCos(R,aRay.Dir),Ob^.Surface^.Ns)*Ob^.Surface^.Ks
  116. {New} / VDot(LRay.Dir,LRay.Dir); {Делим на квадрат расстояния
  117. до источника}
  118. CAddMul(aC,Lt^.Color,tmp);
  119. end;
  120. end;
  121. Ob^.GetColor(oC,Intr);
  122. aC.R := aC.R * OC.R;
  123. aC.G := aC.G * OC.G;
  124. aC.B := aC.B * OC.B;
  125. end;{TGATrace.GetPointColor}
  126. {-------------------------}
  127. Procedure ProTGATrace.GetReflPointColor(var aC:RGB;aRay:TRay;Num:word);
  128. var
  129. Lt : POmni;
  130. Ob : PSurfObj;
  131. oC : RGB;
  132. N,P,R : tVec;
  133. ReflCol : RGB;
  134. L,Refl : TRay;
  135. Pd,tmp : float;
  136. i : word;
  137. begin
  138. SetColor(aC,0,0,0);
  139. if Num >= MAXRecur then Exit;
  140. oB := PSurfObj(FindISect(aRay,Pd));
  141. if oB = nil then exit;
  142. aC := Ambient;
  143. aRay.GetPoint(P,Pd);
  144. oB^.GetNormal(N,P);
  145. for i := 1 to LightCount do
  146. if Pos('OMNI',Lights^[i]^.OType) <> 0 then
  147. begin
  148. Lt := POmni(Lights^[i]);
  149. L.Init(P,P);
  150. VLinear(L.Dir,Lt^.Pos,P,1,-1);
  151. if (FindISect(L,tmp) = nil) or (tmp>1.0) then
  152. begin
  153. if OB^.ID in [F_OBJ_SURF_PLANE,F_TRI,F_QUAD] then
  154. tmp := aCos(N,L.Dir) * oB^.Surface^.Kd / VDot(L.Dir,L.Dir)
  155. else
  156. tmp := Vcos(N,L.Dir) * oB^.Surface^.Kd / VDot(L.Dir,L.Dir);
  157. CAddMul(aC,Lt^.Color,tmp);
  158. VLinear(R,N,L.Dir,-2*VDot(N,L.Dir),1);
  159. if OB^.ID in [F_OBJ_SURF_PLANE,F_TRI,F_QUAD] then
  160. tmp := Pow(aCos(R,aRay.Dir),Ob^.Surface^.Ns)*Ob^.Surface^.Ks
  161. / VDot(L.Dir,L.Dir)
  162. else
  163. tmp := Pow(VCos(R,aRay.Dir),Ob^.Surface^.Ns)*Ob^.Surface^.Ks
  164. {New} / VDot(L.Dir,L.Dir); {Делим на квадрат расстояния
  165. до источника}
  166. CAddMul(aC,Lt^.Color,tmp);
  167. end;
  168. end;
  169. {Calculate Reflection vec}
  170. Refl.Init(P,P);
  171. VLinear(Refl.Dir,N,aRay.Dir,-2*VDot(N,aRay.Dir),1);
  172. VNorm(Refl.Dir,1);
  173. GetReflPointColor(ReflCol,Refl,Num+1);
  174. if Pd > VisRange then tmp := VisRange / Pd
  175. else tmp := 1;
  176. CAddMul(aC,ReflCol,Ob^.Surface^.Ks*tmp);
  177. { CAddMul(aC,ReflCol,1);}
  178. Ob^.GetColor(oC,P);
  179. aC.R := aC.R * OC.R;
  180. aC.G := aC.G * OC.G;
  181. aC.B := aC.B * OC.B;
  182. end;{TGATrace.GetPointColor}
  183. {-------------------------}
  184. Procedure ProTGATrace.Trace;
  185. var
  186. Ray : tRay;
  187. i,j : longint;
  188. ColP : LongInt;
  189. DX,DY : tVec;
  190. C : tVec;
  191. T,cur : float;
  192. Col : RGB;
  193. begin
  194. Seek(outF,BegSet);
  195. C := View.LLPos;
  196. VLinear(DX,View.Right,DX,1/ResX,0); {Расчет вектора прироста по X & Y}
  197. VLinear(DY,View.Up, DY,1/ResY,0); {}
  198. for i := ResY-1 downto 0 do
  199. begin
  200. for j:= 0 to ResX-1 do
  201. begin
  202. Ray.Init(View.CamPos,View.CamPos);
  203. VLinear(Ray.Dir,C,View.CamPos,1,-1);
  204. VNorm(Ray.Dir,1);
  205. GetReflPointColor(Col,Ray,1);
  206. { GetPointColor2(Col,Ray);}
  207. { GetPointColor(Col,Ray);}
  208. ColP:=Pack24(Col);
  209. BlockWrite(outF,ColP,3);
  210. VLinear(C,C,DX,1,1);
  211. end;
  212. Seek(outF,FilePos(outF)+Increase);
  213. VLinear(C,C,DX,1,-ResX);
  214. VLinear(C,C,DY,1,1);
  215. Write(#13'Line: ',ResY-i,'/',ResY,' ');
  216. end;
  217. end;{TGATrace.Trace}
  218. {-------------------------}
  219. Destructor ProTGATrace.Done;
  220. begin
  221. Close(outF);
  222. Inherited Done;
  223. end;
  224. {-------------------------}
  225. Var
  226. TGA : ProTGATrace;
  227. fIn,fOut : String;
  228. ResX,ResY : LongInt;
  229. res : integer;
  230. hb,mb,sb,ssb : word;
  231. he,me,se,sse : word;
  232. org,targ : tVec;
  233. begin
  234. if ParamCount < 3 then
  235. begin
  236. WriteLn('Usage: TGA.exe <scene.tra> <ResX> <ResY> [out.tga]');
  237. Halt(255);
  238. end;
  239. fIn := ParamStr(1);
  240. if ParamStr(4) <> '' then fOut := ParamStr(4)
  241. else fOut := Copy(fIn,1,Length(fIn)-3)+'tga';
  242. Val(ParamStr(2),ResX,res);
  243. Val(ParamStr(3),ResY,res);
  244. TGA.Init(fOut,ResX,ResY);
  245. TGA.Load(fIn);
  246. GetTime(hb,mb,sb,ssb);
  247. TGA.Trace(resX,resY,ResX*3+HEADsize,ResX*3); {Our Picture}
  248. VSet(org,0,Planesdist,0);VSet(targ,0,0,0);
  249. TGA.SetCamera(org,targ,0,PlanesFOV,ResX/ResY); {Top projection}
  250. TGA.Trace(resX,ResY,2*ResX*ResY*3+HEADsize,ResX*3);
  251. VSet(org,-Planesdist,0,0);
  252. TGA.SetCamera(org,targ,0,PlanesFOV,ResX/ResY); {Left projection}
  253. TGA.Trace(resX,ResY,(2*ResX*ResY+ResX)*3+HEADsize,ResX*3);
  254. VSet(org,0,0,-Planesdist);
  255. TGA.SetCamera(org,targ,0,PlanesFOV,ResX/ResY); {Forward projection}
  256. TGA.Trace(resX,ResY,HEADsize,ResX*3);
  257. GetTime(he,me,se,sse);
  258. if (sse<ssb) then
  259. begin
  260. dec(se);
  261. Inc(sse,100-ssb);
  262. end
  263. else Dec(sse,ssb);
  264. if (se<sb) then
  265. begin
  266. dec(me);
  267. Inc(se,60-sb);
  268. end
  269. else Dec(se,sb);
  270. if (me<mb) then
  271. begin
  272. dec(he);
  273. Inc(me,60-mb);
  274. end
  275. else Dec(me,mb);
  276. Dec(he,hb);
  277. WriteLn(#13'Elapsed ',he,' hours, ',me,' minutes, ',se,' seconds, ',
  278. sse,' 100th second');
  279. TGA.Done;
  280. { TGA.Load('cool.tra');}
  281. { TGA.Load('planes.tra');}
  282. { TGA.Save('cool.tra',true);}
  283. end.