Camera.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. Camera Cam;
  6. C Camera ActiveCam;
  7. /******************************************************************************/
  8. Camera::Camera()
  9. {
  10. yaw =0;
  11. pitch=0;
  12. roll =0;
  13. dist =1;
  14. at .zero();
  15. matrix .setPos(0, 0, -1);
  16. vel.zero();
  17. ang_vel.zero();
  18. _matrix_prev=matrix;
  19. }
  20. /******************************************************************************/
  21. Camera& Camera::set(C MatrixM &matrix)
  22. {
  23. T.dist =1;
  24. T.at =matrix.pos+matrix.z;
  25. T.matrix=matrix;
  26. T.yaw =-Angle(matrix.z.zx());
  27. T.pitch = Asin (matrix.z.y );
  28. T.roll =0;
  29. return T;
  30. }
  31. Camera& Camera::setAngle(C VecD &pos, Flt yaw, Flt pitch, Flt roll)
  32. {
  33. T.yaw =yaw;
  34. T.pitch=pitch;
  35. T.roll =roll;
  36. T.dist =1;
  37. T.matrix.orn().setRotateZ(-roll).rotateXY(-pitch, -yaw);
  38. T.matrix.pos=pos;
  39. T.at=matrix.pos+matrix.z;
  40. return T;
  41. }
  42. Camera& Camera::setSpherical(C VecD &at, Flt yaw, Flt pitch, Flt roll, Flt dist)
  43. {
  44. T.at =at;
  45. T.yaw =yaw;
  46. T.pitch=pitch;
  47. T.roll =roll;
  48. T.dist =dist;
  49. return setSpherical();
  50. }
  51. Camera& Camera::setSpherical()
  52. {
  53. matrix.setPos(0, 0, -dist).rotateZ(-roll).rotateXY(-pitch, -yaw).move(at);
  54. return T;
  55. }
  56. Camera& Camera::setFromAt(C VecD &from, C VecD &at, Flt roll)
  57. {
  58. matrix.z=at-from; dist=matrix.z.normalize();
  59. matrix.x=Cross(Vec(0, 1, 0), matrix.z);
  60. if(!dist || !matrix.x.normalize())matrix.identity();else
  61. {
  62. matrix.x*=Matrix3().setRotate(matrix.z, -roll);
  63. matrix.y=Cross(matrix.z, matrix.x);
  64. }
  65. matrix.pos=from;
  66. T.at =at;
  67. T.yaw =-Angle(matrix.z.zx());
  68. T.pitch= Asin (matrix.z.y );
  69. T.roll =roll;
  70. return T;
  71. }
  72. Camera& Camera::setPosDir(C VecD &pos, C Vec &dir, C Vec &up)
  73. {
  74. Vec dir_n= dir ; dist=dir_n.normalize(); if(!dist)dir_n.set(0, 0, 1);
  75. Vec up_f=PointOnPlane(up, dir_n); if(!up_f.normalize()) up_f=PerpN(dir_n);
  76. T.matrix.setPosDir(pos, dir_n, up_f);
  77. T.at =pos+dir;
  78. T.yaw =-Angle(matrix.z.zx());
  79. T.pitch= Asin (matrix.z.y );
  80. T.roll =0;
  81. return T;
  82. }
  83. /******************************************************************************/
  84. Camera& Camera::teleported()
  85. {
  86. _matrix_prev=matrix; // prevents velocity jump
  87. return T;
  88. }
  89. Camera& Camera::updateVelocities(CAM_ATTACHMENT attachment)
  90. {
  91. Flt dt=Time.d();
  92. if(Physics.created())switch(attachment)
  93. {
  94. case CAM_ATTACH_CTRL:
  95. #if !PHYSX // background thread processing (PhysX should always jump to 'CAM_ATTACH_ACTOR')
  96. {
  97. if( Game::WorldManager::update_objects_after_physics)goto attach_actor;
  98. if(!Physics._last_updated)return T;
  99. dt=Physics._last_updated_time;
  100. }break;
  101. attach_actor:
  102. #endif
  103. case CAM_ATTACH_ACTOR:
  104. {
  105. if(!Physics.updated())return T;
  106. dt=Physics.updatedTime();
  107. }break;
  108. }
  109. GetVel(vel, ang_vel, _matrix_prev, matrix, dt);
  110. _matrix_prev=matrix;
  111. return T;
  112. }
  113. /******************************************************************************/
  114. void SetCam(C MatrixM &matrix, Bool set_frustum)
  115. {
  116. CamMatrix=matrix;
  117. CamMatrix.inverse(CamMatrixInv, true);
  118. Sh.h_CamMatrix->set(CamMatrix);
  119. if(set_frustum)Frustum.set();
  120. }
  121. void Camera::set()C // this should be called only outside of 'Renderer' rendering
  122. {
  123. ConstCast(ActiveCam)=T; // always backup to 'ActiveCam' even if display not yet created, so we can activate it later
  124. if(D.created()) // do the rest only if display is created because we need some shader handles which could've been null
  125. {
  126. Vec eye_ofs=matrix.x*(D.eyeDistance()*0.5f);
  127. EyeMatrix[0]=matrix; EyeMatrix[0].pos-=eye_ofs;
  128. EyeMatrix[1]=matrix; EyeMatrix[1].pos+=eye_ofs;
  129. SetCam(matrix);
  130. // set velocity related things !! the same must be done below in 'MotionScaleChanged' !!
  131. CamMatrixInvMotionScale=CamMatrixInv.orn(); CamMatrixInvMotionScale.scale(D.motionScale());
  132. Sh.h_CamAngVel->set(ang_vel*CamMatrixInvMotionScale);
  133. }
  134. }
  135. void MotionScaleChanged() // !! this must match codes above !!
  136. {
  137. Flt l=D.motionScale();
  138. CamMatrixInvMotionScale.x.setLength(l);
  139. CamMatrixInvMotionScale.y.setLength(l);
  140. CamMatrixInvMotionScale.z.setLength(l);
  141. if(Sh.h_CamAngVel)Sh.h_CamAngVel->set(ActiveCam.ang_vel*CamMatrixInvMotionScale);
  142. }
  143. /******************************************************************************/
  144. Bool Camera::save(File &f)C
  145. {
  146. f.putMulti(Byte(0), yaw, pitch, roll, dist, at, matrix, vel, ang_vel); // version
  147. return f.ok();
  148. }
  149. Bool Camera::load(File &f)
  150. {
  151. switch(f.decUIntV())
  152. {
  153. case 0:
  154. {
  155. f.getMulti(yaw, pitch, roll, dist, at, matrix, vel, ang_vel); // version
  156. _matrix_prev=matrix;
  157. if(f.ok())return true;
  158. }break;
  159. }
  160. return false;
  161. }
  162. /******************************************************************************/
  163. static Vec ScreenToPosD(C Vec2 &screen_d, Flt z, C Matrix3 &cam_matrix)
  164. {
  165. if(FovPerspective(D.viewFovMode()))
  166. {
  167. return (screen_d.x*z*D.viewFovTanGui().x)*cam_matrix.x
  168. +(screen_d.y*z*D.viewFovTanGui().y)*cam_matrix.y;
  169. }else
  170. {
  171. return (screen_d.x*D.viewFovTanGui().x)*cam_matrix.x
  172. +(screen_d.y*D.viewFovTanGui().y)*cam_matrix.y;
  173. }
  174. }
  175. Camera& Camera::transformByMouse(Flt dist_min, Flt dist_max, UInt flag)
  176. {
  177. if(flag&CAMH_ZOOM )Clamp(dist*=ScaleFactor(Ms.wheel()*-0.3f), dist_min, dist_max);
  178. if(flag&CAMH_ROT_X )yaw -=Ms.d().x;
  179. if(flag&CAMH_ROT_Y )pitch+=Ms.d().y;
  180. if(flag&CAMH_MOVE )at -=ScreenToPosD(Ms.d()/D.scale(), dist, matrix);
  181. if(flag&CAMH_MOVE_XZ)
  182. {
  183. Vec x, z;
  184. CosSin(x.x, x.z, yaw ); x.y=0;
  185. z.set(-x.z, 0, x.x); // CosSin(z.x, z.z, yaw+PI_2); z.y=0;
  186. Vec2 mul=D.viewFovTanGui()/D.scale(); if(FovPerspective(D.viewFovMode()))mul*=dist;
  187. at-=x*(Ms.d().x*mul.x)
  188. +z*(Ms.d().y*mul.y);
  189. }
  190. setSpherical();
  191. if(!(flag&CAMH_NO_VEL_UPDATE))updateVelocities(CAM_ATTACH_FREE);
  192. if(!(flag&CAMH_NO_SET ))set();
  193. return T;
  194. }
  195. /******************************************************************************/
  196. Bool PosToScreen(C Vec &pos, Vec2 &screen)
  197. {
  198. Vec v=pos*CamMatrixInv; // no need for 'VecD'
  199. if(FovPerspective(D.viewFovMode()))
  200. {
  201. screen.x=v.x/(v.z*D.viewFovTanGui().x);
  202. screen.y=v.y/(v.z*D.viewFovTanGui().y);
  203. }else
  204. {
  205. screen.x=v.x/D.viewFovTanGui().x;
  206. screen.y=v.y/D.viewFovTanGui().y;
  207. }
  208. screen+=D.viewCenter();
  209. return v.z>D.viewFromActual();
  210. }
  211. Bool PosToScreen(C VecD &pos, Vec2 &screen)
  212. {
  213. Vec v=pos*CamMatrixInv; // no need for 'VecD'
  214. if(FovPerspective(D.viewFovMode()))
  215. {
  216. screen.x=v.x/(v.z*D.viewFovTanGui().x);
  217. screen.y=v.y/(v.z*D.viewFovTanGui().y);
  218. }else
  219. {
  220. screen.x=v.x/D.viewFovTanGui().x;
  221. screen.y=v.y/D.viewFovTanGui().y;
  222. }
  223. screen+=D.viewCenter();
  224. return v.z>D.viewFromActual();
  225. }
  226. Bool PosToFullScreen(C Vec &pos, Vec2 &screen)
  227. {
  228. Vec v=pos*CamMatrixInv; // no need for 'VecD'
  229. if(FovPerspective(D.viewFovMode()))
  230. {
  231. screen.x=v.x/(v.z*D.viewFovTanFull().x);
  232. screen.y=v.y/(v.z*D.viewFovTanFull().y);
  233. }else
  234. {
  235. screen.x=v.x/D.viewFovTanFull().x;
  236. screen.y=v.y/D.viewFovTanFull().y;
  237. }
  238. screen+=D.viewCenter();
  239. return v.z>D.viewFromActual();
  240. }
  241. Bool PosToFullScreen(C VecD &pos, Vec2 &screen)
  242. {
  243. Vec v=pos*CamMatrixInv; // no need for 'VecD'
  244. if(FovPerspective(D.viewFovMode()))
  245. {
  246. screen.x=v.x/(v.z*D.viewFovTanFull().x);
  247. screen.y=v.y/(v.z*D.viewFovTanFull().y);
  248. }else
  249. {
  250. screen.x=v.x/D.viewFovTanFull().x;
  251. screen.y=v.y/D.viewFovTanFull().y;
  252. }
  253. screen+=D.viewCenter();
  254. return v.z>D.viewFromActual();
  255. }
  256. Bool PosToScreenM(C Vec &pos, Vec2 &screen)
  257. {
  258. Vec v=(pos*ObjMatrix)*CamMatrixInv; // no need for 'VecD'
  259. if(FovPerspective(D.viewFovMode()))
  260. {
  261. screen.x=v.x/(v.z*D.viewFovTanGui().x);
  262. screen.y=v.y/(v.z*D.viewFovTanGui().y);
  263. }else
  264. {
  265. screen.x=v.x/D.viewFovTanGui().x;
  266. screen.y=v.y/D.viewFovTanGui().y;
  267. }
  268. screen+=D.viewCenter();
  269. return v.z>D.viewFromActual();
  270. }
  271. Bool PosToScreenM(C VecD &pos, Vec2 &screen)
  272. {
  273. Vec v=(pos*ObjMatrix)*CamMatrixInv; // no need for 'VecD'
  274. if(FovPerspective(D.viewFovMode()))
  275. {
  276. screen.x=v.x/(v.z*D.viewFovTanGui().x);
  277. screen.y=v.y/(v.z*D.viewFovTanGui().y);
  278. }else
  279. {
  280. screen.x=v.x/D.viewFovTanGui().x;
  281. screen.y=v.y/D.viewFovTanGui().y;
  282. }
  283. screen+=D.viewCenter();
  284. return v.z>D.viewFromActual();
  285. }
  286. Vec ScreenToPosDM(C Vec2 &screen_d, Flt z) {return ScreenToPosD(screen_d, z)/ObjMatrix.orn();}
  287. Vec ScreenToPosD (C Vec2 &screen_d, Flt z)
  288. {
  289. if(FovPerspective(D.viewFovMode()))
  290. {
  291. return (screen_d.x*z*D.viewFovTanGui().x)*CamMatrix.x
  292. +(screen_d.y*z*D.viewFovTanGui().y)*CamMatrix.y;
  293. }else
  294. {
  295. return (screen_d.x*D.viewFovTanGui().x)*CamMatrix.x
  296. +(screen_d.y*D.viewFovTanGui().y)*CamMatrix.y;
  297. }
  298. }
  299. static INLINE Vec _ScreenToViewPos(C Vec2 &screen, Flt z)
  300. {
  301. Vec2 v=screen-D.viewCenter();
  302. if(FovPerspective(D.viewFovMode()))
  303. {
  304. return Vec(v.x*z*D.viewFovTanGui().x,
  305. v.y*z*D.viewFovTanGui().y,
  306. z);
  307. }else
  308. {
  309. return Vec(v.x*D.viewFovTanGui().x,
  310. v.y*D.viewFovTanGui().y,
  311. z);
  312. }
  313. }
  314. Vec ScreenToViewPos(C Vec2 &screen, Flt z) {return _ScreenToViewPos(screen, z);}
  315. VecD ScreenToPos (C Vec2 &screen, Flt z) {return _ScreenToViewPos(screen, z)*CamMatrix;}
  316. VecD ScreenToPosM (C Vec2 &screen, Flt z) {return ScreenToPos (screen, z)/ObjMatrix;}
  317. static INLINE Vec _FullScreenToViewPos(C Vec2 &screen, Flt z)
  318. {
  319. Vec2 v=screen-D.viewCenter();
  320. if(FovPerspective(D.viewFovMode()))
  321. {
  322. return Vec(v.x*z*D.viewFovTanFull().x,
  323. v.y*z*D.viewFovTanFull().y,
  324. z);
  325. }else
  326. {
  327. return Vec(v.x*D.viewFovTanFull().x,
  328. v.y*D.viewFovTanFull().y,
  329. z);
  330. }
  331. }
  332. Vec FullScreenToViewPos(C Vec2 &screen, Flt z) {return _FullScreenToViewPos(screen, z);}
  333. VecD FullScreenToPos (C Vec2 &screen, Flt z) {return _FullScreenToViewPos(screen, z)*CamMatrix;}
  334. Vec2 PosToScreen (C Vec &pos) {Vec2 screen; PosToScreen (pos, screen); return screen;}
  335. Vec2 PosToScreen (C VecD &pos) {Vec2 screen; PosToScreen (pos, screen); return screen;}
  336. Vec2 PosToScreenM (C Vec &pos) {Vec2 screen; PosToScreenM (pos, screen); return screen;}
  337. Vec2 PosToScreenM (C VecD &pos) {Vec2 screen; PosToScreenM (pos, screen); return screen;}
  338. Vec2 PosToFullScreen(C Vec &pos) {Vec2 screen; PosToFullScreen(pos, screen); return screen;}
  339. Vec2 PosToFullScreen(C VecD &pos) {Vec2 screen; PosToFullScreen(pos, screen); return screen;}
  340. /******************************************************************************/
  341. Vec ScreenToDir(C Vec2 &screen)
  342. {
  343. if(FovPerspective(D.viewFovMode()))
  344. {
  345. Vec2 v=screen-D.viewCenter();
  346. return !((v.x*D.viewFovTanGui().x)*CamMatrix.x
  347. +(v.y*D.viewFovTanGui().y)*CamMatrix.y
  348. + CamMatrix.z);
  349. }else
  350. {
  351. return CamMatrix.z;
  352. }
  353. }
  354. void ScreenToPosDir(C Vec2 &screen, Vec &pos, Vec &dir)
  355. {
  356. Vec2 v=screen-D.viewCenter();
  357. if(FovPerspective(D.viewFovMode()))
  358. {
  359. dir=!((v.x*D.viewFovTanGui().x)*CamMatrix.x
  360. +(v.y*D.viewFovTanGui().y)*CamMatrix.y
  361. + CamMatrix.z);
  362. pos=CamMatrix.pos;
  363. }else
  364. {
  365. pos=(v.x*D.viewFovTanGui().x)*CamMatrix.x
  366. +(v.y*D.viewFovTanGui().y)*CamMatrix.y
  367. +CamMatrix.pos;
  368. dir=CamMatrix.z;
  369. }
  370. }
  371. void ScreenToPosDir(C Vec2 &screen, VecD &pos, Vec &dir)
  372. {
  373. Vec2 v=screen-D.viewCenter();
  374. if(FovPerspective(D.viewFovMode()))
  375. {
  376. dir=!((v.x*D.viewFovTanGui().x)*CamMatrix.x
  377. +(v.y*D.viewFovTanGui().y)*CamMatrix.y
  378. + CamMatrix.z);
  379. pos=CamMatrix.pos;
  380. }else
  381. {
  382. pos=(v.x*D.viewFovTanGui().x)*CamMatrix.x
  383. +(v.y*D.viewFovTanGui().y)*CamMatrix.y
  384. +CamMatrix.pos;
  385. dir=CamMatrix.z;
  386. }
  387. }
  388. /******************************************************************************/
  389. static Bool ToScreenRect(C Vec *point, Int points, Rect &rect)
  390. {
  391. Bool in=false;
  392. Vec2 screen;
  393. REP(points)if(PosToScreen(point[i], screen))
  394. {
  395. if(in)rect|=screen;
  396. else rect =screen;
  397. in=true;
  398. }
  399. return in;
  400. }
  401. static Bool ToScreenRect(C Vec *point, C VecI2 *edge, Int edges, Rect &rect)
  402. {
  403. Bool in =false;
  404. Vec from=CamMatrix.pos+CamMatrix.z*D.viewFromActual();
  405. REP(edges)
  406. {
  407. Edge e(point[edge[i].x], point[edge[i].y]);
  408. Flt d0=DistPointPlane(e.p[0], from, CamMatrix.z),
  409. d1=DistPointPlane(e.p[1], from, CamMatrix.z);
  410. Int s0=Sign(d0),
  411. s1=Sign(d1);
  412. if(s0>0 || s1>0)
  413. {
  414. if(s0<0)e.p[0]=PointOnPlane(e.p[0], e.p[1], d0, d1);else
  415. if(s1<0)e.p[1]=PointOnPlane(e.p[0], e.p[1], d0, d1);
  416. Vec2 screen;
  417. PosToScreen(e.p[0], screen); if(in)rect|=screen;else rect=screen;
  418. PosToScreen(e.p[1], screen); rect|=screen;
  419. in=true;
  420. }
  421. }
  422. return in;
  423. }
  424. static Bool ToFullScreenRect(C Vec *point, C VecI2 *edge, Int edges, Rect &rect)
  425. {
  426. Bool in =false;
  427. Vec from=CamMatrix.pos+CamMatrix.z*D.viewFromActual();
  428. REP(edges)
  429. {
  430. Edge e(point[edge[i].x], point[edge[i].y]);
  431. Flt d0=DistPointPlane(e.p[0], from, CamMatrix.z),
  432. d1=DistPointPlane(e.p[1], from, CamMatrix.z);
  433. Int s0=Sign(d0),
  434. s1=Sign(d1);
  435. if(s0>0 || s1>0)
  436. {
  437. if(s0<0)e.p[0]=PointOnPlane(e.p[0], e.p[1], d0, d1);else
  438. if(s1<0)e.p[1]=PointOnPlane(e.p[0], e.p[1], d0, d1);
  439. Vec2 screen;
  440. PosToFullScreen(e.p[0], screen); if(in)rect|=screen;else rect=screen;
  441. PosToFullScreen(e.p[1], screen); rect|=screen;
  442. in=true;
  443. }
  444. }
  445. return in;
  446. }
  447. static Bool ToFullScreenRect(C VecD *point, C VecI2 *edge, Int edges, Rect &rect)
  448. {
  449. Bool in =false;
  450. VecD from=CamMatrix.pos+CamMatrix.z*D.viewFromActual();
  451. REP(edges)
  452. {
  453. EdgeD e(point[edge[i].x], point[edge[i].y]);
  454. Dbl d0=DistPointPlane(e.p[0], from, CamMatrix.z),
  455. d1=DistPointPlane(e.p[1], from, CamMatrix.z);
  456. Int s0=Sign(d0),
  457. s1=Sign(d1);
  458. if(s0>0 || s1>0)
  459. {
  460. if(s0<0)e.p[0]=PointOnPlane(e.p[0], e.p[1], d0, d1);else
  461. if(s1<0)e.p[1]=PointOnPlane(e.p[0], e.p[1], d0, d1);
  462. Vec2 screen;
  463. PosToFullScreen(e.p[0], screen); if(in)rect|=screen;else rect=screen;
  464. PosToFullScreen(e.p[1], screen); rect|=screen;
  465. in=true;
  466. }
  467. }
  468. return in;
  469. }
  470. static const VecI2 BoxEdges[]=
  471. {
  472. VecI2(0|2|4, 1|2|4),
  473. VecI2(1|2|4, 1|2|0),
  474. VecI2(1|2|0, 0|2|0),
  475. VecI2(0|2|0, 0|2|4),
  476. VecI2(0|0|4, 1|0|4),
  477. VecI2(1|0|4, 1|0|0),
  478. VecI2(1|0|0, 0|0|0),
  479. VecI2(0|0|0, 0|0|4),
  480. VecI2(1|0|4, 1|2|4),
  481. VecI2(1|0|0, 1|2|0),
  482. VecI2(0|0|4, 0|2|4),
  483. VecI2(0|0|0, 0|2|0),
  484. };
  485. Bool ToScreenRect(C Box &box, Rect &rect)
  486. {
  487. Vec point[8]; box.toCorners(point);
  488. #if 0
  489. return ToScreenRect(point, Elms(point), rect);
  490. #else
  491. return ToScreenRect(point, BoxEdges, Elms(BoxEdges), rect);
  492. #endif
  493. }
  494. Bool ToScreenRect(C OBox &obox, Rect &rect)
  495. {
  496. Vec point[8]; obox.toCorners(point);
  497. #if 0
  498. return ToScreenRect(point, Elms(point), rect);
  499. #else
  500. return ToScreenRect(point, BoxEdges, Elms(BoxEdges), rect);
  501. #endif
  502. }
  503. Bool ToScreenRect(C Ball &ball, Rect &rect)
  504. {
  505. if(!Frustum(ball))return false;
  506. if(Cuts(CamMatrix.pos, ball)){rect=D.viewRect(); return true;}
  507. #if 1
  508. Flt l, s, c;
  509. Vec2 screen;
  510. Vec zd, d, z=ball.pos-CamMatrix.pos; // no need for 'VecD'
  511. zd=PointOnPlane(z, CamMatrix.y); l=zd.normalize(); s=ball.r/l;
  512. if(s>=1)rect.setX(D.viewRect().min.x, D.viewRect().max.x);else
  513. {
  514. c=CosSin(s); d=Cross(CamMatrix.y, zd); d.setLength(c*ball.r); zd*=-s*ball.r; zd+=ball.pos; if(Renderer.mirror())d.chs();
  515. rect.setX((PosToScreen(zd-d, screen) ? screen.x : D.viewRect().min.x),
  516. (PosToScreen(zd+d, screen) ? screen.x : D.viewRect().max.x));
  517. if(!rect.validX())return false;
  518. }
  519. zd=PointOnPlane(z, CamMatrix.x); l=zd.normalize(); s=ball.r/l;
  520. if(s>=1)rect.setY(D.viewRect().min.y, D.viewRect().max.y);else
  521. {
  522. c=CosSin(s); d=Cross(CamMatrix.x, zd); d.setLength(c*ball.r); zd*=-s*ball.r; zd+=ball.pos; if(Renderer.mirror())d.chs();
  523. rect.setY((PosToScreen(zd+d, screen) ? screen.y : D.viewRect().min.y),
  524. (PosToScreen(zd-d, screen) ? screen.y : D.viewRect().max.y));
  525. if(!rect.validY())return false;
  526. }
  527. return true;
  528. #else
  529. return ToScreenRect(Box(ball), rect);
  530. #endif
  531. }
  532. Bool ToScreenRect(C BallM &ball, Rect &rect)
  533. {
  534. if(!Frustum(ball))return false;
  535. if(Cuts(CamMatrix.pos, ball)){rect=D.viewRect(); return true;}
  536. #if 1
  537. Flt l, s, c;
  538. Vec2 screen;
  539. Vec zd, d, z=ball.pos-CamMatrix.pos; // no need for 'VecD'
  540. VecD zp;
  541. zd=PointOnPlane(z, CamMatrix.y); l=zd.normalize(); s=ball.r/l;
  542. if(s>=1)rect.setX(D.viewRect().min.x, D.viewRect().max.x);else
  543. {
  544. c=CosSin(s); d=Cross(CamMatrix.y, zd); d.setLength(c*ball.r); zd*=-s*ball.r; zp=zd+ball.pos; if(Renderer.mirror())d.chs();
  545. rect.setX((PosToScreen(zp-d, screen) ? screen.x : D.viewRect().min.x),
  546. (PosToScreen(zp+d, screen) ? screen.x : D.viewRect().max.x));
  547. if(!rect.validX())return false;
  548. }
  549. zd=PointOnPlane(z, CamMatrix.x); l=zd.normalize(); s=ball.r/l;
  550. if(s>=1)rect.setY(D.viewRect().min.y, D.viewRect().max.y);else
  551. {
  552. c=CosSin(s); d=Cross(CamMatrix.x, zd); d.setLength(c*ball.r); zd*=-s*ball.r; zp=zd+ball.pos; if(Renderer.mirror())d.chs();
  553. rect.setY((PosToScreen(zp+d, screen) ? screen.y : D.viewRect().min.y),
  554. (PosToScreen(zp-d, screen) ? screen.y : D.viewRect().max.y));
  555. if(!rect.validY())return false;
  556. }
  557. return true;
  558. #else
  559. return ToScreenRect(BoxD(ball), rect);
  560. #endif
  561. }
  562. Bool ToFullScreenRect(C Ball &ball, Rect &rect)
  563. {
  564. if(!Frustum(ball))return false;
  565. if(Cuts(CamMatrix.pos, ball)){rect=D.viewRect(); return true;}
  566. #if 1
  567. Flt l, s, c;
  568. Vec2 screen;
  569. Vec zd, d, z=ball.pos-CamMatrix.pos; // no need for 'VecD'
  570. zd=PointOnPlane(z, CamMatrix.y); l=zd.normalize(); s=ball.r/l;
  571. if(s>=1)rect.setX(D.viewRect().min.x, D.viewRect().max.x);else
  572. {
  573. c=CosSin(s); d=Cross(CamMatrix.y, zd); d.setLength(c*ball.r); zd*=-s*ball.r; zd+=ball.pos; if(Renderer.mirror())d.chs();
  574. rect.setX((PosToFullScreen(zd-d, screen) ? screen.x : D.viewRect().min.x),
  575. (PosToFullScreen(zd+d, screen) ? screen.x : D.viewRect().max.x));
  576. if(!rect.validX())return false;
  577. }
  578. zd=PointOnPlane(z, CamMatrix.x); l=zd.normalize(); s=ball.r/l;
  579. if(s>=1)rect.setY(D.viewRect().min.y, D.viewRect().max.y);else
  580. {
  581. c=CosSin(s); d=Cross(CamMatrix.x, zd); d.setLength(c*ball.r); zd*=-s*ball.r; zd+=ball.pos; if(Renderer.mirror())d.chs();
  582. rect.setY((PosToFullScreen(zd+d, screen) ? screen.y : D.viewRect().min.y),
  583. (PosToFullScreen(zd-d, screen) ? screen.y : D.viewRect().max.y));
  584. if(!rect.validY())return false;
  585. }
  586. return true;
  587. #else
  588. return ToFullScreenRect(Box(ball), rect);
  589. #endif
  590. }
  591. Bool ToFullScreenRect(C BallM &ball, Rect &rect)
  592. {
  593. if(!Frustum(ball))return false;
  594. if(Cuts(CamMatrix.pos, ball)){rect=D.viewRect(); return true;}
  595. #if 1
  596. Flt l, s, c;
  597. Vec2 screen;
  598. Vec zd, d, z=ball.pos-CamMatrix.pos; // no need for 'VecD'
  599. VecD zp;
  600. zd=PointOnPlane(z, CamMatrix.y); l=zd.normalize(); s=ball.r/l;
  601. if(s>=1)rect.setX(D.viewRect().min.x, D.viewRect().max.x);else
  602. {
  603. c=CosSin(s); d=Cross(CamMatrix.y, zd); d.setLength(c*ball.r); zd*=-s*ball.r; zp=zd+ball.pos; if(Renderer.mirror())d.chs();
  604. rect.setX((PosToFullScreen(zp-d, screen) ? screen.x : D.viewRect().min.x),
  605. (PosToFullScreen(zp+d, screen) ? screen.x : D.viewRect().max.x));
  606. if(!rect.validX())return false;
  607. }
  608. zd=PointOnPlane(z, CamMatrix.x); l=zd.normalize(); s=ball.r/l;
  609. if(s>=1)rect.setY(D.viewRect().min.y, D.viewRect().max.y);else
  610. {
  611. c=CosSin(s); d=Cross(CamMatrix.x, zd); d.setLength(c*ball.r); zd*=-s*ball.r; zp=zd+ball.pos; if(Renderer.mirror())d.chs();
  612. rect.setY((PosToFullScreen(zp+d, screen) ? screen.y : D.viewRect().min.y),
  613. (PosToFullScreen(zp-d, screen) ? screen.y : D.viewRect().max.y));
  614. if(!rect.validY())return false;
  615. }
  616. return true;
  617. #else
  618. return ToFullScreenRect(BoxD(ball), rect);
  619. #endif
  620. }
  621. Bool ToScreenRect(C Capsule &capsule, Rect &rect)
  622. {
  623. if(!Frustum(capsule))return false;
  624. if(Cuts(CamMatrix.pos, capsule)){rect=D.viewRect(); return true;}
  625. #if 1
  626. Flt l, s, c;
  627. Vec2 screen;
  628. Vec z, zd, d;
  629. Ball ball;
  630. // upper ball
  631. {
  632. ball=capsule.ballU();
  633. z =ball.pos-CamMatrix.pos; // no need for 'VecD'
  634. zd=PointOnPlane(z, CamMatrix.y); l=zd.normalize(); s=ball.r/l;
  635. if(s>=1)rect.setX(D.viewRect().min.x, D.viewRect().max.x);else
  636. {
  637. c=CosSin(s); d=Cross(CamMatrix.y, zd); d.setLength(c*ball.r); zd*=-s*ball.r; zd+=ball.pos; if(Renderer.mirror())d.chs();
  638. rect.setX((PosToScreen(zd-d, screen) ? screen.x : D.viewRect().min.x),
  639. (PosToScreen(zd+d, screen) ? screen.x : D.viewRect().max.x));
  640. }
  641. zd=PointOnPlane(z, CamMatrix.x); l=zd.normalize(); s=ball.r/l;
  642. if(s>=1)rect.setY(D.viewRect().min.y, D.viewRect().max.y);else
  643. {
  644. c=CosSin(s); d=Cross(CamMatrix.x, zd); d.setLength(c*ball.r); zd*=-s*ball.r; zd+=ball.pos; if(Renderer.mirror())d.chs();
  645. rect.setY((PosToScreen(zd+d, screen) ? screen.y : D.viewRect().min.y),
  646. (PosToScreen(zd-d, screen) ? screen.y : D.viewRect().max.y));
  647. }
  648. }
  649. // lower ball
  650. {
  651. ball=capsule.ballD();
  652. z =ball.pos-CamMatrix.pos; // no need for 'VecD'
  653. zd=PointOnPlane(z, CamMatrix.y); l=zd.normalize(); s=ball.r/l;
  654. if(s>=1)rect.setX(D.viewRect().min.x, D.viewRect().max.x);else
  655. {
  656. c=CosSin(s); d=Cross(CamMatrix.y, zd); d.setLength(c*ball.r); zd*=-s*ball.r; zd+=ball.pos; if(Renderer.mirror())d.chs();
  657. rect.includeX((PosToScreen(zd-d, screen) ? screen.x : D.viewRect().min.x),
  658. (PosToScreen(zd+d, screen) ? screen.x : D.viewRect().max.x));
  659. }
  660. zd=PointOnPlane(z, CamMatrix.x); l=zd.normalize(); s=ball.r/l;
  661. if(s>=1)rect.setY(D.viewRect().min.y, D.viewRect().max.y);else
  662. {
  663. c=CosSin(s); d=Cross(CamMatrix.x, zd); d.setLength(c*ball.r); zd*=-s*ball.r; zd+=ball.pos; if(Renderer.mirror())d.chs();
  664. rect.includeY((PosToScreen(zd+d, screen) ? screen.y : D.viewRect().min.y),
  665. (PosToScreen(zd-d, screen) ? screen.y : D.viewRect().max.y));
  666. }
  667. }
  668. return rect.valid();
  669. #else
  670. Matrix matrix; matrix.setPosUp(capsule.pos, capsule.up);
  671. matrix.y*=capsule.h*0.5f;
  672. matrix.x*=capsule.r;
  673. matrix.z*=capsule.r;
  674. return ToScreenRect(OBox(Box(1), matrix));
  675. #endif
  676. }
  677. Bool ToScreenRect(C CapsuleM &capsule, Rect &rect)
  678. {
  679. if(!Frustum(capsule))return false;
  680. if(Cuts(CamMatrix.pos, capsule)){rect=D.viewRect(); return true;}
  681. Flt l, s, c;
  682. Vec2 screen;
  683. Vec z, zd, d;
  684. VecD zp;
  685. BallM ball;
  686. // upper ball
  687. {
  688. ball=capsule.ballU();
  689. z =ball.pos-CamMatrix.pos; // no need for 'VecD'
  690. zd=PointOnPlane(z, CamMatrix.y); l=zd.normalize(); s=ball.r/l;
  691. if(s>=1)rect.setX(D.viewRect().min.x, D.viewRect().max.x);else
  692. {
  693. c=CosSin(s); d=Cross(CamMatrix.y, zd); d.setLength(c*ball.r); zd*=-s*ball.r; zp=zd+ball.pos; if(Renderer.mirror())d.chs();
  694. rect.setX((PosToScreen(zp-d, screen) ? screen.x : D.viewRect().min.x),
  695. (PosToScreen(zp+d, screen) ? screen.x : D.viewRect().max.x));
  696. }
  697. zd=PointOnPlane(z, CamMatrix.x); l=zd.normalize(); s=ball.r/l;
  698. if(s>=1)rect.setY(D.viewRect().min.y, D.viewRect().max.y);else
  699. {
  700. c=CosSin(s); d=Cross(CamMatrix.x, zd); d.setLength(c*ball.r); zd*=-s*ball.r; zp=zd+ball.pos; if(Renderer.mirror())d.chs();
  701. rect.setY((PosToScreen(zp+d, screen) ? screen.y : D.viewRect().min.y),
  702. (PosToScreen(zp-d, screen) ? screen.y : D.viewRect().max.y));
  703. }
  704. }
  705. // lower ball
  706. {
  707. ball=capsule.ballD();
  708. z =ball.pos-CamMatrix.pos; // no need for 'VecD'
  709. zd=PointOnPlane(z, CamMatrix.y); l=zd.normalize(); s=ball.r/l;
  710. if(s>=1)rect.setX(D.viewRect().min.x, D.viewRect().max.x);else
  711. {
  712. c=CosSin(s); d=Cross(CamMatrix.y, zd); d.setLength(c*ball.r); zd*=-s*ball.r; zp=zd+ball.pos; if(Renderer.mirror())d.chs();
  713. rect.includeX((PosToScreen(zp-d, screen) ? screen.x : D.viewRect().min.x),
  714. (PosToScreen(zp+d, screen) ? screen.x : D.viewRect().max.x));
  715. }
  716. zd=PointOnPlane(z, CamMatrix.x); l=zd.normalize(); s=ball.r/l;
  717. if(s>=1)rect.setY(D.viewRect().min.y, D.viewRect().max.y);else
  718. {
  719. c=CosSin(s); d=Cross(CamMatrix.x, zd); d.setLength(c*ball.r); zd*=-s*ball.r; zp=zd+ball.pos; if(Renderer.mirror())d.chs();
  720. rect.includeY((PosToScreen(zp+d, screen) ? screen.y : D.viewRect().min.y),
  721. (PosToScreen(zp-d, screen) ? screen.y : D.viewRect().max.y));
  722. }
  723. }
  724. return rect.valid();
  725. }
  726. static const VecI2 PyramidEdges[]=
  727. {
  728. VecI2(0, 1),
  729. VecI2(0, 2),
  730. VecI2(0, 3),
  731. VecI2(0, 4),
  732. VecI2(1, 2),
  733. VecI2(2, 3),
  734. VecI2(3, 4),
  735. VecI2(4, 1),
  736. };
  737. Bool ToScreenRect(C Pyramid &pyramid, Rect &rect)
  738. {
  739. if(Cuts(CamMatrix.pos, pyramid)){rect=D.viewRect(); return true;}
  740. Vec point[5], x=pyramid.cross();
  741. point[0]=pyramid.pos;
  742. point[1]=pyramid.pos+(pyramid.dir+(-x+pyramid.perp)*pyramid.scale)*pyramid.h;
  743. point[2]=pyramid.pos+(pyramid.dir+( x+pyramid.perp)*pyramid.scale)*pyramid.h;
  744. point[3]=pyramid.pos+(pyramid.dir+( x-pyramid.perp)*pyramid.scale)*pyramid.h;
  745. point[4]=pyramid.pos+(pyramid.dir+(-x-pyramid.perp)*pyramid.scale)*pyramid.h;
  746. return ToScreenRect(point, PyramidEdges, Elms(PyramidEdges), rect);
  747. }
  748. Bool ToFullScreenRect(C Pyramid &pyramid, Rect &rect)
  749. {
  750. if(Cuts(CamMatrix.pos, pyramid)){rect=D.viewRect(); return true;}
  751. Vec point[5], x=pyramid.cross();
  752. point[0]=pyramid.pos;
  753. point[1]=pyramid.pos+(pyramid.dir+(-x+pyramid.perp)*pyramid.scale)*pyramid.h;
  754. point[2]=pyramid.pos+(pyramid.dir+( x+pyramid.perp)*pyramid.scale)*pyramid.h;
  755. point[3]=pyramid.pos+(pyramid.dir+( x-pyramid.perp)*pyramid.scale)*pyramid.h;
  756. point[4]=pyramid.pos+(pyramid.dir+(-x-pyramid.perp)*pyramid.scale)*pyramid.h;
  757. return ToFullScreenRect(point, PyramidEdges, Elms(PyramidEdges), rect);
  758. }
  759. Bool ToFullScreenRect(C PyramidM &pyramid, Rect &rect)
  760. {
  761. if(Cuts(CamMatrix.pos, pyramid)){rect=D.viewRect(); return true;}
  762. VecD point[5]; Vec x=pyramid.cross();
  763. point[0]=pyramid.pos;
  764. point[1]=pyramid.pos+(pyramid.dir+(-x+pyramid.perp)*pyramid.scale)*pyramid.h;
  765. point[2]=pyramid.pos+(pyramid.dir+( x+pyramid.perp)*pyramid.scale)*pyramid.h;
  766. point[3]=pyramid.pos+(pyramid.dir+( x-pyramid.perp)*pyramid.scale)*pyramid.h;
  767. point[4]=pyramid.pos+(pyramid.dir+(-x-pyramid.perp)*pyramid.scale)*pyramid.h;
  768. return ToFullScreenRect(point, PyramidEdges, Elms(PyramidEdges), rect);
  769. }
  770. Bool ToScreenRect(C Shape &shape, Rect &rect)
  771. {
  772. switch(shape.type)
  773. {
  774. case SHAPE_BOX : return ToScreenRect(shape.box , rect);
  775. case SHAPE_OBOX : return ToScreenRect(shape.obox , rect);
  776. case SHAPE_BALL : return ToScreenRect(shape.ball , rect);
  777. case SHAPE_CAPSULE: return ToScreenRect(shape.capsule, rect);
  778. case SHAPE_PYRAMID: return ToScreenRect(shape.pyramid, rect);
  779. default : return false;
  780. }
  781. }
  782. Bool ToScreenRect(C Shape *shape, Int shapes, Rect &rect)
  783. {
  784. Bool in=false;
  785. REP(shapes)
  786. {
  787. Rect r; if(ToScreenRect(shape[i], r))
  788. {
  789. if(!in){in=true; rect=r;}else rect|=r;
  790. }
  791. }
  792. return in;
  793. }
  794. /******************************************************************************/
  795. Int CompareTransparencyOrderDepth(C Vec &pos_a, C Vec &pos_b)
  796. {
  797. return Sign(Dot(pos_a-pos_b, ActiveCam.matrix.z));
  798. }
  799. Int CompareTransparencyOrderDepth(C VecD &pos_a, C VecD &pos_b)
  800. {
  801. return Sign(Dot(pos_a-pos_b, ActiveCam.matrix.z));
  802. }
  803. Int CompareTransparencyOrderDist(C Vec &pos_a, C Vec &pos_b)
  804. {
  805. return Sign(Dist2(pos_a, ActiveCam.matrix.pos)-Dist2(pos_b, ActiveCam.matrix.pos));
  806. }
  807. Int CompareTransparencyOrderDist(C VecD &pos_a, C VecD &pos_b)
  808. {
  809. return Sign(Dist2(pos_a, ActiveCam.matrix.pos)-Dist2(pos_b, ActiveCam.matrix.pos));
  810. }
  811. /******************************************************************************/
  812. void InitCamera()
  813. {
  814. ActiveCam.set(); // put values to shaders
  815. }
  816. /******************************************************************************/
  817. }
  818. /******************************************************************************/