| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854 |
- /******************************************************************************/
- #include "stdafx.h"
- namespace EE{
- /******************************************************************************/
- Camera Cam;
- C Camera ActiveCam;
- /******************************************************************************/
- Camera::Camera()
- {
- yaw =0;
- pitch=0;
- roll =0;
- dist =1;
- at .zero();
- matrix .setPos(0, 0, -1);
- vel.zero();
- ang_vel.zero();
- _matrix_prev=matrix;
- }
- /******************************************************************************/
- Camera& Camera::set(C MatrixM &matrix)
- {
- T.dist =1;
- T.at =matrix.pos+matrix.z;
- T.matrix=matrix;
- T.yaw =-Angle(matrix.z.zx());
- T.pitch = Asin (matrix.z.y );
- T.roll =0;
- return T;
- }
- Camera& Camera::setAngle(C VecD &pos, Flt yaw, Flt pitch, Flt roll)
- {
- T.yaw =yaw;
- T.pitch=pitch;
- T.roll =roll;
- T.dist =1;
- T.matrix.orn().setRotateZ(-roll).rotateXY(-pitch, -yaw);
- T.matrix.pos=pos;
- T.at=matrix.pos+matrix.z;
- return T;
- }
- Camera& Camera::setSpherical(C VecD &at, Flt yaw, Flt pitch, Flt roll, Flt dist)
- {
- T.at =at;
- T.yaw =yaw;
- T.pitch=pitch;
- T.roll =roll;
- T.dist =dist;
- return setSpherical();
- }
- Camera& Camera::setSpherical()
- {
- matrix.setPos(0, 0, -dist).rotateZ(-roll).rotateXY(-pitch, -yaw).move(at);
- return T;
- }
- Camera& Camera::setFromAt(C VecD &from, C VecD &at, Flt roll)
- {
- matrix.z=at-from; dist=matrix.z.normalize();
- matrix.x=Cross(Vec(0, 1, 0), matrix.z);
- if(!dist || !matrix.x.normalize())matrix.identity();else
- {
- matrix.x*=Matrix3().setRotate(matrix.z, -roll);
- matrix.y=Cross(matrix.z, matrix.x);
- }
- matrix.pos=from;
- T.at =at;
- T.yaw =-Angle(matrix.z.zx());
- T.pitch= Asin (matrix.z.y );
- T.roll =roll;
- return T;
- }
- Camera& Camera::setPosDir(C VecD &pos, C Vec &dir, C Vec &up)
- {
- Vec dir_n= dir ; dist=dir_n.normalize(); if(!dist)dir_n.set(0, 0, 1);
- Vec up_f=PointOnPlane(up, dir_n); if(!up_f.normalize()) up_f=PerpN(dir_n);
- T.matrix.setPosDir(pos, dir_n, up_f);
- T.at =pos+dir;
- T.yaw =-Angle(matrix.z.zx());
- T.pitch= Asin (matrix.z.y );
- T.roll =0;
- return T;
- }
- /******************************************************************************/
- Camera& Camera::teleported()
- {
- _matrix_prev=matrix; // prevents velocity jump
- return T;
- }
- Camera& Camera::updateVelocities(CAM_ATTACHMENT attachment)
- {
- Flt dt=Time.d();
- if(Physics.created())switch(attachment)
- {
- case CAM_ATTACH_CTRL:
- #if !PHYSX // background thread processing (PhysX should always jump to 'CAM_ATTACH_ACTOR')
- {
- if( Game::WorldManager::update_objects_after_physics)goto attach_actor;
- if(!Physics._last_updated)return T;
- dt=Physics._last_updated_time;
- }break;
- attach_actor:
- #endif
- case CAM_ATTACH_ACTOR:
- {
- if(!Physics.updated())return T;
- dt=Physics.updatedTime();
- }break;
- }
- GetVel(vel, ang_vel, _matrix_prev, matrix, dt);
- _matrix_prev=matrix;
- return T;
- }
- /******************************************************************************/
- void SetCam(C MatrixM &matrix, Bool set_frustum)
- {
- CamMatrix=matrix;
- CamMatrix.inverse(CamMatrixInv, true);
- Sh.h_CamMatrix->set(CamMatrix);
- if(set_frustum)Frustum.set();
- }
- void Camera::set()C // this should be called only outside of 'Renderer' rendering
- {
- ConstCast(ActiveCam)=T; // always backup to 'ActiveCam' even if display not yet created, so we can activate it later
- if(D.created()) // do the rest only if display is created because we need some shader handles which could've been null
- {
- Vec eye_ofs=matrix.x*(D.eyeDistance()*0.5f);
- EyeMatrix[0]=matrix; EyeMatrix[0].pos-=eye_ofs;
- EyeMatrix[1]=matrix; EyeMatrix[1].pos+=eye_ofs;
- SetCam(matrix);
- // set velocity related things !! the same must be done below in 'MotionScaleChanged' !!
- CamMatrixInvMotionScale=CamMatrixInv.orn(); CamMatrixInvMotionScale.scale(D.motionScale());
- Sh.h_CamAngVel->set(ang_vel*CamMatrixInvMotionScale);
- }
- }
- void MotionScaleChanged() // !! this must match codes above !!
- {
- Flt l=D.motionScale();
- CamMatrixInvMotionScale.x.setLength(l);
- CamMatrixInvMotionScale.y.setLength(l);
- CamMatrixInvMotionScale.z.setLength(l);
- if(Sh.h_CamAngVel)Sh.h_CamAngVel->set(ActiveCam.ang_vel*CamMatrixInvMotionScale);
- }
- /******************************************************************************/
- Bool Camera::save(File &f)C
- {
- f.putMulti(Byte(0), yaw, pitch, roll, dist, at, matrix, vel, ang_vel); // version
- return f.ok();
- }
- Bool Camera::load(File &f)
- {
- switch(f.decUIntV())
- {
- case 0:
- {
- f.getMulti(yaw, pitch, roll, dist, at, matrix, vel, ang_vel); // version
- _matrix_prev=matrix;
- if(f.ok())return true;
- }break;
- }
- return false;
- }
- /******************************************************************************/
- static Vec ScreenToPosD(C Vec2 &screen_d, Flt z, C Matrix3 &cam_matrix)
- {
- if(FovPerspective(D.viewFovMode()))
- {
- return (screen_d.x*z*D.viewFovTanGui().x)*cam_matrix.x
- +(screen_d.y*z*D.viewFovTanGui().y)*cam_matrix.y;
- }else
- {
- return (screen_d.x*D.viewFovTanGui().x)*cam_matrix.x
- +(screen_d.y*D.viewFovTanGui().y)*cam_matrix.y;
- }
- }
- Camera& Camera::transformByMouse(Flt dist_min, Flt dist_max, UInt flag)
- {
- if(flag&CAMH_ZOOM )Clamp(dist*=ScaleFactor(Ms.wheel()*-0.3f), dist_min, dist_max);
- if(flag&CAMH_ROT_X )yaw -=Ms.d().x;
- if(flag&CAMH_ROT_Y )pitch+=Ms.d().y;
- if(flag&CAMH_MOVE )at -=ScreenToPosD(Ms.d()/D.scale(), dist, matrix);
- if(flag&CAMH_MOVE_XZ)
- {
- Vec x, z;
- CosSin(x.x, x.z, yaw ); x.y=0;
- z.set(-x.z, 0, x.x); // CosSin(z.x, z.z, yaw+PI_2); z.y=0;
- Vec2 mul=D.viewFovTanGui()/D.scale(); if(FovPerspective(D.viewFovMode()))mul*=dist;
- at-=x*(Ms.d().x*mul.x)
- +z*(Ms.d().y*mul.y);
- }
- setSpherical();
- if(!(flag&CAMH_NO_VEL_UPDATE))updateVelocities(CAM_ATTACH_FREE);
- if(!(flag&CAMH_NO_SET ))set();
- return T;
- }
- /******************************************************************************/
- Bool PosToScreen(C Vec &pos, Vec2 &screen)
- {
- Vec v=pos*CamMatrixInv; // no need for 'VecD'
- if(FovPerspective(D.viewFovMode()))
- {
- screen.x=v.x/(v.z*D.viewFovTanGui().x);
- screen.y=v.y/(v.z*D.viewFovTanGui().y);
- }else
- {
- screen.x=v.x/D.viewFovTanGui().x;
- screen.y=v.y/D.viewFovTanGui().y;
- }
- screen+=D.viewCenter();
- return v.z>D.viewFromActual();
- }
- Bool PosToScreen(C VecD &pos, Vec2 &screen)
- {
- Vec v=pos*CamMatrixInv; // no need for 'VecD'
- if(FovPerspective(D.viewFovMode()))
- {
- screen.x=v.x/(v.z*D.viewFovTanGui().x);
- screen.y=v.y/(v.z*D.viewFovTanGui().y);
- }else
- {
- screen.x=v.x/D.viewFovTanGui().x;
- screen.y=v.y/D.viewFovTanGui().y;
- }
- screen+=D.viewCenter();
- return v.z>D.viewFromActual();
- }
- Bool PosToFullScreen(C Vec &pos, Vec2 &screen)
- {
- Vec v=pos*CamMatrixInv; // no need for 'VecD'
- if(FovPerspective(D.viewFovMode()))
- {
- screen.x=v.x/(v.z*D.viewFovTanFull().x);
- screen.y=v.y/(v.z*D.viewFovTanFull().y);
- }else
- {
- screen.x=v.x/D.viewFovTanFull().x;
- screen.y=v.y/D.viewFovTanFull().y;
- }
- screen+=D.viewCenter();
- return v.z>D.viewFromActual();
- }
- Bool PosToFullScreen(C VecD &pos, Vec2 &screen)
- {
- Vec v=pos*CamMatrixInv; // no need for 'VecD'
- if(FovPerspective(D.viewFovMode()))
- {
- screen.x=v.x/(v.z*D.viewFovTanFull().x);
- screen.y=v.y/(v.z*D.viewFovTanFull().y);
- }else
- {
- screen.x=v.x/D.viewFovTanFull().x;
- screen.y=v.y/D.viewFovTanFull().y;
- }
- screen+=D.viewCenter();
- return v.z>D.viewFromActual();
- }
- Bool PosToScreenM(C Vec &pos, Vec2 &screen)
- {
- Vec v=(pos*ObjMatrix)*CamMatrixInv; // no need for 'VecD'
- if(FovPerspective(D.viewFovMode()))
- {
- screen.x=v.x/(v.z*D.viewFovTanGui().x);
- screen.y=v.y/(v.z*D.viewFovTanGui().y);
- }else
- {
- screen.x=v.x/D.viewFovTanGui().x;
- screen.y=v.y/D.viewFovTanGui().y;
- }
- screen+=D.viewCenter();
- return v.z>D.viewFromActual();
- }
- Bool PosToScreenM(C VecD &pos, Vec2 &screen)
- {
- Vec v=(pos*ObjMatrix)*CamMatrixInv; // no need for 'VecD'
- if(FovPerspective(D.viewFovMode()))
- {
- screen.x=v.x/(v.z*D.viewFovTanGui().x);
- screen.y=v.y/(v.z*D.viewFovTanGui().y);
- }else
- {
- screen.x=v.x/D.viewFovTanGui().x;
- screen.y=v.y/D.viewFovTanGui().y;
- }
- screen+=D.viewCenter();
- return v.z>D.viewFromActual();
- }
- Vec ScreenToPosDM(C Vec2 &screen_d, Flt z) {return ScreenToPosD(screen_d, z)/ObjMatrix.orn();}
- Vec ScreenToPosD (C Vec2 &screen_d, Flt z)
- {
- if(FovPerspective(D.viewFovMode()))
- {
- return (screen_d.x*z*D.viewFovTanGui().x)*CamMatrix.x
- +(screen_d.y*z*D.viewFovTanGui().y)*CamMatrix.y;
- }else
- {
- return (screen_d.x*D.viewFovTanGui().x)*CamMatrix.x
- +(screen_d.y*D.viewFovTanGui().y)*CamMatrix.y;
- }
- }
- static INLINE Vec _ScreenToViewPos(C Vec2 &screen, Flt z)
- {
- Vec2 v=screen-D.viewCenter();
- if(FovPerspective(D.viewFovMode()))
- {
- return Vec(v.x*z*D.viewFovTanGui().x,
- v.y*z*D.viewFovTanGui().y,
- z);
- }else
- {
- return Vec(v.x*D.viewFovTanGui().x,
- v.y*D.viewFovTanGui().y,
- z);
- }
- }
- Vec ScreenToViewPos(C Vec2 &screen, Flt z) {return _ScreenToViewPos(screen, z);}
- VecD ScreenToPos (C Vec2 &screen, Flt z) {return _ScreenToViewPos(screen, z)*CamMatrix;}
- VecD ScreenToPosM (C Vec2 &screen, Flt z) {return ScreenToPos (screen, z)/ObjMatrix;}
- static INLINE Vec _FullScreenToViewPos(C Vec2 &screen, Flt z)
- {
- Vec2 v=screen-D.viewCenter();
- if(FovPerspective(D.viewFovMode()))
- {
- return Vec(v.x*z*D.viewFovTanFull().x,
- v.y*z*D.viewFovTanFull().y,
- z);
- }else
- {
- return Vec(v.x*D.viewFovTanFull().x,
- v.y*D.viewFovTanFull().y,
- z);
- }
- }
- Vec FullScreenToViewPos(C Vec2 &screen, Flt z) {return _FullScreenToViewPos(screen, z);}
- VecD FullScreenToPos (C Vec2 &screen, Flt z) {return _FullScreenToViewPos(screen, z)*CamMatrix;}
- Vec2 PosToScreen (C Vec &pos) {Vec2 screen; PosToScreen (pos, screen); return screen;}
- Vec2 PosToScreen (C VecD &pos) {Vec2 screen; PosToScreen (pos, screen); return screen;}
- Vec2 PosToScreenM (C Vec &pos) {Vec2 screen; PosToScreenM (pos, screen); return screen;}
- Vec2 PosToScreenM (C VecD &pos) {Vec2 screen; PosToScreenM (pos, screen); return screen;}
- Vec2 PosToFullScreen(C Vec &pos) {Vec2 screen; PosToFullScreen(pos, screen); return screen;}
- Vec2 PosToFullScreen(C VecD &pos) {Vec2 screen; PosToFullScreen(pos, screen); return screen;}
- /******************************************************************************/
- Vec ScreenToDir(C Vec2 &screen)
- {
- if(FovPerspective(D.viewFovMode()))
- {
- Vec2 v=screen-D.viewCenter();
- return !((v.x*D.viewFovTanGui().x)*CamMatrix.x
- +(v.y*D.viewFovTanGui().y)*CamMatrix.y
- + CamMatrix.z);
- }else
- {
- return CamMatrix.z;
- }
- }
- void ScreenToPosDir(C Vec2 &screen, Vec &pos, Vec &dir)
- {
- Vec2 v=screen-D.viewCenter();
- if(FovPerspective(D.viewFovMode()))
- {
- dir=!((v.x*D.viewFovTanGui().x)*CamMatrix.x
- +(v.y*D.viewFovTanGui().y)*CamMatrix.y
- + CamMatrix.z);
- pos=CamMatrix.pos;
- }else
- {
- pos=(v.x*D.viewFovTanGui().x)*CamMatrix.x
- +(v.y*D.viewFovTanGui().y)*CamMatrix.y
- +CamMatrix.pos;
- dir=CamMatrix.z;
- }
- }
- void ScreenToPosDir(C Vec2 &screen, VecD &pos, Vec &dir)
- {
- Vec2 v=screen-D.viewCenter();
- if(FovPerspective(D.viewFovMode()))
- {
- dir=!((v.x*D.viewFovTanGui().x)*CamMatrix.x
- +(v.y*D.viewFovTanGui().y)*CamMatrix.y
- + CamMatrix.z);
- pos=CamMatrix.pos;
- }else
- {
- pos=(v.x*D.viewFovTanGui().x)*CamMatrix.x
- +(v.y*D.viewFovTanGui().y)*CamMatrix.y
- +CamMatrix.pos;
- dir=CamMatrix.z;
- }
- }
- /******************************************************************************/
- static Bool ToScreenRect(C Vec *point, Int points, Rect &rect)
- {
- Bool in=false;
- Vec2 screen;
- REP(points)if(PosToScreen(point[i], screen))
- {
- if(in)rect|=screen;
- else rect =screen;
- in=true;
- }
- return in;
- }
- static Bool ToScreenRect(C Vec *point, C VecI2 *edge, Int edges, Rect &rect)
- {
- Bool in =false;
- Vec from=CamMatrix.pos+CamMatrix.z*D.viewFromActual();
- REP(edges)
- {
- Edge e(point[edge[i].x], point[edge[i].y]);
- Flt d0=DistPointPlane(e.p[0], from, CamMatrix.z),
- d1=DistPointPlane(e.p[1], from, CamMatrix.z);
- Int s0=Sign(d0),
- s1=Sign(d1);
- if(s0>0 || s1>0)
- {
- if(s0<0)e.p[0]=PointOnPlane(e.p[0], e.p[1], d0, d1);else
- if(s1<0)e.p[1]=PointOnPlane(e.p[0], e.p[1], d0, d1);
- Vec2 screen;
- PosToScreen(e.p[0], screen); if(in)rect|=screen;else rect=screen;
- PosToScreen(e.p[1], screen); rect|=screen;
- in=true;
- }
- }
- return in;
- }
- static Bool ToFullScreenRect(C Vec *point, C VecI2 *edge, Int edges, Rect &rect)
- {
- Bool in =false;
- Vec from=CamMatrix.pos+CamMatrix.z*D.viewFromActual();
- REP(edges)
- {
- Edge e(point[edge[i].x], point[edge[i].y]);
- Flt d0=DistPointPlane(e.p[0], from, CamMatrix.z),
- d1=DistPointPlane(e.p[1], from, CamMatrix.z);
- Int s0=Sign(d0),
- s1=Sign(d1);
- if(s0>0 || s1>0)
- {
- if(s0<0)e.p[0]=PointOnPlane(e.p[0], e.p[1], d0, d1);else
- if(s1<0)e.p[1]=PointOnPlane(e.p[0], e.p[1], d0, d1);
- Vec2 screen;
- PosToFullScreen(e.p[0], screen); if(in)rect|=screen;else rect=screen;
- PosToFullScreen(e.p[1], screen); rect|=screen;
- in=true;
- }
- }
- return in;
- }
- static Bool ToFullScreenRect(C VecD *point, C VecI2 *edge, Int edges, Rect &rect)
- {
- Bool in =false;
- VecD from=CamMatrix.pos+CamMatrix.z*D.viewFromActual();
- REP(edges)
- {
- EdgeD e(point[edge[i].x], point[edge[i].y]);
- Dbl d0=DistPointPlane(e.p[0], from, CamMatrix.z),
- d1=DistPointPlane(e.p[1], from, CamMatrix.z);
- Int s0=Sign(d0),
- s1=Sign(d1);
- if(s0>0 || s1>0)
- {
- if(s0<0)e.p[0]=PointOnPlane(e.p[0], e.p[1], d0, d1);else
- if(s1<0)e.p[1]=PointOnPlane(e.p[0], e.p[1], d0, d1);
- Vec2 screen;
- PosToFullScreen(e.p[0], screen); if(in)rect|=screen;else rect=screen;
- PosToFullScreen(e.p[1], screen); rect|=screen;
- in=true;
- }
- }
- return in;
- }
- static const VecI2 BoxEdges[]=
- {
- VecI2(0|2|4, 1|2|4),
- VecI2(1|2|4, 1|2|0),
- VecI2(1|2|0, 0|2|0),
- VecI2(0|2|0, 0|2|4),
- VecI2(0|0|4, 1|0|4),
- VecI2(1|0|4, 1|0|0),
- VecI2(1|0|0, 0|0|0),
- VecI2(0|0|0, 0|0|4),
- VecI2(1|0|4, 1|2|4),
- VecI2(1|0|0, 1|2|0),
- VecI2(0|0|4, 0|2|4),
- VecI2(0|0|0, 0|2|0),
- };
- Bool ToScreenRect(C Box &box, Rect &rect)
- {
- Vec point[8]; box.toCorners(point);
- #if 0
- return ToScreenRect(point, Elms(point), rect);
- #else
- return ToScreenRect(point, BoxEdges, Elms(BoxEdges), rect);
- #endif
- }
- Bool ToScreenRect(C OBox &obox, Rect &rect)
- {
- Vec point[8]; obox.toCorners(point);
- #if 0
- return ToScreenRect(point, Elms(point), rect);
- #else
- return ToScreenRect(point, BoxEdges, Elms(BoxEdges), rect);
- #endif
- }
- Bool ToScreenRect(C Ball &ball, Rect &rect)
- {
- if(!Frustum(ball))return false;
- if(Cuts(CamMatrix.pos, ball)){rect=D.viewRect(); return true;}
- #if 1
- Flt l, s, c;
- Vec2 screen;
- Vec zd, d, z=ball.pos-CamMatrix.pos; // no need for 'VecD'
- zd=PointOnPlane(z, CamMatrix.y); l=zd.normalize(); s=ball.r/l;
- if(s>=1)rect.setX(D.viewRect().min.x, D.viewRect().max.x);else
- {
- 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();
- rect.setX((PosToScreen(zd-d, screen) ? screen.x : D.viewRect().min.x),
- (PosToScreen(zd+d, screen) ? screen.x : D.viewRect().max.x));
- if(!rect.validX())return false;
- }
- zd=PointOnPlane(z, CamMatrix.x); l=zd.normalize(); s=ball.r/l;
- if(s>=1)rect.setY(D.viewRect().min.y, D.viewRect().max.y);else
- {
- 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();
- rect.setY((PosToScreen(zd+d, screen) ? screen.y : D.viewRect().min.y),
- (PosToScreen(zd-d, screen) ? screen.y : D.viewRect().max.y));
- if(!rect.validY())return false;
- }
- return true;
- #else
- return ToScreenRect(Box(ball), rect);
- #endif
- }
- Bool ToScreenRect(C BallM &ball, Rect &rect)
- {
- if(!Frustum(ball))return false;
- if(Cuts(CamMatrix.pos, ball)){rect=D.viewRect(); return true;}
- #if 1
- Flt l, s, c;
- Vec2 screen;
- Vec zd, d, z=ball.pos-CamMatrix.pos; // no need for 'VecD'
- VecD zp;
- zd=PointOnPlane(z, CamMatrix.y); l=zd.normalize(); s=ball.r/l;
- if(s>=1)rect.setX(D.viewRect().min.x, D.viewRect().max.x);else
- {
- 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();
- rect.setX((PosToScreen(zp-d, screen) ? screen.x : D.viewRect().min.x),
- (PosToScreen(zp+d, screen) ? screen.x : D.viewRect().max.x));
- if(!rect.validX())return false;
- }
- zd=PointOnPlane(z, CamMatrix.x); l=zd.normalize(); s=ball.r/l;
- if(s>=1)rect.setY(D.viewRect().min.y, D.viewRect().max.y);else
- {
- 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();
- rect.setY((PosToScreen(zp+d, screen) ? screen.y : D.viewRect().min.y),
- (PosToScreen(zp-d, screen) ? screen.y : D.viewRect().max.y));
- if(!rect.validY())return false;
- }
- return true;
- #else
- return ToScreenRect(BoxD(ball), rect);
- #endif
- }
- Bool ToFullScreenRect(C Ball &ball, Rect &rect)
- {
- if(!Frustum(ball))return false;
- if(Cuts(CamMatrix.pos, ball)){rect=D.viewRect(); return true;}
- #if 1
- Flt l, s, c;
- Vec2 screen;
- Vec zd, d, z=ball.pos-CamMatrix.pos; // no need for 'VecD'
- zd=PointOnPlane(z, CamMatrix.y); l=zd.normalize(); s=ball.r/l;
- if(s>=1)rect.setX(D.viewRect().min.x, D.viewRect().max.x);else
- {
- 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();
- rect.setX((PosToFullScreen(zd-d, screen) ? screen.x : D.viewRect().min.x),
- (PosToFullScreen(zd+d, screen) ? screen.x : D.viewRect().max.x));
- if(!rect.validX())return false;
- }
- zd=PointOnPlane(z, CamMatrix.x); l=zd.normalize(); s=ball.r/l;
- if(s>=1)rect.setY(D.viewRect().min.y, D.viewRect().max.y);else
- {
- 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();
- rect.setY((PosToFullScreen(zd+d, screen) ? screen.y : D.viewRect().min.y),
- (PosToFullScreen(zd-d, screen) ? screen.y : D.viewRect().max.y));
- if(!rect.validY())return false;
- }
- return true;
- #else
- return ToFullScreenRect(Box(ball), rect);
- #endif
- }
- Bool ToFullScreenRect(C BallM &ball, Rect &rect)
- {
- if(!Frustum(ball))return false;
- if(Cuts(CamMatrix.pos, ball)){rect=D.viewRect(); return true;}
- #if 1
- Flt l, s, c;
- Vec2 screen;
- Vec zd, d, z=ball.pos-CamMatrix.pos; // no need for 'VecD'
- VecD zp;
- zd=PointOnPlane(z, CamMatrix.y); l=zd.normalize(); s=ball.r/l;
- if(s>=1)rect.setX(D.viewRect().min.x, D.viewRect().max.x);else
- {
- 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();
- rect.setX((PosToFullScreen(zp-d, screen) ? screen.x : D.viewRect().min.x),
- (PosToFullScreen(zp+d, screen) ? screen.x : D.viewRect().max.x));
- if(!rect.validX())return false;
- }
- zd=PointOnPlane(z, CamMatrix.x); l=zd.normalize(); s=ball.r/l;
- if(s>=1)rect.setY(D.viewRect().min.y, D.viewRect().max.y);else
- {
- 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();
- rect.setY((PosToFullScreen(zp+d, screen) ? screen.y : D.viewRect().min.y),
- (PosToFullScreen(zp-d, screen) ? screen.y : D.viewRect().max.y));
- if(!rect.validY())return false;
- }
- return true;
- #else
- return ToFullScreenRect(BoxD(ball), rect);
- #endif
- }
- Bool ToScreenRect(C Capsule &capsule, Rect &rect)
- {
- if(!Frustum(capsule))return false;
- if(Cuts(CamMatrix.pos, capsule)){rect=D.viewRect(); return true;}
- #if 1
- Flt l, s, c;
- Vec2 screen;
- Vec z, zd, d;
- Ball ball;
- // upper ball
- {
- ball=capsule.ballU();
- z =ball.pos-CamMatrix.pos; // no need for 'VecD'
- zd=PointOnPlane(z, CamMatrix.y); l=zd.normalize(); s=ball.r/l;
- if(s>=1)rect.setX(D.viewRect().min.x, D.viewRect().max.x);else
- {
- 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();
- rect.setX((PosToScreen(zd-d, screen) ? screen.x : D.viewRect().min.x),
- (PosToScreen(zd+d, screen) ? screen.x : D.viewRect().max.x));
- }
- zd=PointOnPlane(z, CamMatrix.x); l=zd.normalize(); s=ball.r/l;
- if(s>=1)rect.setY(D.viewRect().min.y, D.viewRect().max.y);else
- {
- 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();
- rect.setY((PosToScreen(zd+d, screen) ? screen.y : D.viewRect().min.y),
- (PosToScreen(zd-d, screen) ? screen.y : D.viewRect().max.y));
- }
- }
- // lower ball
- {
- ball=capsule.ballD();
- z =ball.pos-CamMatrix.pos; // no need for 'VecD'
- zd=PointOnPlane(z, CamMatrix.y); l=zd.normalize(); s=ball.r/l;
- if(s>=1)rect.setX(D.viewRect().min.x, D.viewRect().max.x);else
- {
- 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();
- rect.includeX((PosToScreen(zd-d, screen) ? screen.x : D.viewRect().min.x),
- (PosToScreen(zd+d, screen) ? screen.x : D.viewRect().max.x));
- }
- zd=PointOnPlane(z, CamMatrix.x); l=zd.normalize(); s=ball.r/l;
- if(s>=1)rect.setY(D.viewRect().min.y, D.viewRect().max.y);else
- {
- 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();
- rect.includeY((PosToScreen(zd+d, screen) ? screen.y : D.viewRect().min.y),
- (PosToScreen(zd-d, screen) ? screen.y : D.viewRect().max.y));
- }
- }
- return rect.valid();
- #else
- Matrix matrix; matrix.setPosUp(capsule.pos, capsule.up);
- matrix.y*=capsule.h*0.5f;
- matrix.x*=capsule.r;
- matrix.z*=capsule.r;
- return ToScreenRect(OBox(Box(1), matrix));
- #endif
- }
- Bool ToScreenRect(C CapsuleM &capsule, Rect &rect)
- {
- if(!Frustum(capsule))return false;
- if(Cuts(CamMatrix.pos, capsule)){rect=D.viewRect(); return true;}
- Flt l, s, c;
- Vec2 screen;
- Vec z, zd, d;
- VecD zp;
- BallM ball;
- // upper ball
- {
- ball=capsule.ballU();
- z =ball.pos-CamMatrix.pos; // no need for 'VecD'
- zd=PointOnPlane(z, CamMatrix.y); l=zd.normalize(); s=ball.r/l;
- if(s>=1)rect.setX(D.viewRect().min.x, D.viewRect().max.x);else
- {
- 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();
- rect.setX((PosToScreen(zp-d, screen) ? screen.x : D.viewRect().min.x),
- (PosToScreen(zp+d, screen) ? screen.x : D.viewRect().max.x));
- }
- zd=PointOnPlane(z, CamMatrix.x); l=zd.normalize(); s=ball.r/l;
- if(s>=1)rect.setY(D.viewRect().min.y, D.viewRect().max.y);else
- {
- 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();
- rect.setY((PosToScreen(zp+d, screen) ? screen.y : D.viewRect().min.y),
- (PosToScreen(zp-d, screen) ? screen.y : D.viewRect().max.y));
- }
- }
- // lower ball
- {
- ball=capsule.ballD();
- z =ball.pos-CamMatrix.pos; // no need for 'VecD'
- zd=PointOnPlane(z, CamMatrix.y); l=zd.normalize(); s=ball.r/l;
- if(s>=1)rect.setX(D.viewRect().min.x, D.viewRect().max.x);else
- {
- 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();
- rect.includeX((PosToScreen(zp-d, screen) ? screen.x : D.viewRect().min.x),
- (PosToScreen(zp+d, screen) ? screen.x : D.viewRect().max.x));
- }
- zd=PointOnPlane(z, CamMatrix.x); l=zd.normalize(); s=ball.r/l;
- if(s>=1)rect.setY(D.viewRect().min.y, D.viewRect().max.y);else
- {
- 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();
- rect.includeY((PosToScreen(zp+d, screen) ? screen.y : D.viewRect().min.y),
- (PosToScreen(zp-d, screen) ? screen.y : D.viewRect().max.y));
- }
- }
- return rect.valid();
- }
- static const VecI2 PyramidEdges[]=
- {
- VecI2(0, 1),
- VecI2(0, 2),
- VecI2(0, 3),
- VecI2(0, 4),
- VecI2(1, 2),
- VecI2(2, 3),
- VecI2(3, 4),
- VecI2(4, 1),
- };
- Bool ToScreenRect(C Pyramid &pyramid, Rect &rect)
- {
- if(Cuts(CamMatrix.pos, pyramid)){rect=D.viewRect(); return true;}
- Vec point[5], x=pyramid.cross();
- point[0]=pyramid.pos;
- point[1]=pyramid.pos+(pyramid.dir+(-x+pyramid.perp)*pyramid.scale)*pyramid.h;
- point[2]=pyramid.pos+(pyramid.dir+( x+pyramid.perp)*pyramid.scale)*pyramid.h;
- point[3]=pyramid.pos+(pyramid.dir+( x-pyramid.perp)*pyramid.scale)*pyramid.h;
- point[4]=pyramid.pos+(pyramid.dir+(-x-pyramid.perp)*pyramid.scale)*pyramid.h;
- return ToScreenRect(point, PyramidEdges, Elms(PyramidEdges), rect);
- }
- Bool ToFullScreenRect(C Pyramid &pyramid, Rect &rect)
- {
- if(Cuts(CamMatrix.pos, pyramid)){rect=D.viewRect(); return true;}
- Vec point[5], x=pyramid.cross();
- point[0]=pyramid.pos;
- point[1]=pyramid.pos+(pyramid.dir+(-x+pyramid.perp)*pyramid.scale)*pyramid.h;
- point[2]=pyramid.pos+(pyramid.dir+( x+pyramid.perp)*pyramid.scale)*pyramid.h;
- point[3]=pyramid.pos+(pyramid.dir+( x-pyramid.perp)*pyramid.scale)*pyramid.h;
- point[4]=pyramid.pos+(pyramid.dir+(-x-pyramid.perp)*pyramid.scale)*pyramid.h;
- return ToFullScreenRect(point, PyramidEdges, Elms(PyramidEdges), rect);
- }
- Bool ToFullScreenRect(C PyramidM &pyramid, Rect &rect)
- {
- if(Cuts(CamMatrix.pos, pyramid)){rect=D.viewRect(); return true;}
- VecD point[5]; Vec x=pyramid.cross();
- point[0]=pyramid.pos;
- point[1]=pyramid.pos+(pyramid.dir+(-x+pyramid.perp)*pyramid.scale)*pyramid.h;
- point[2]=pyramid.pos+(pyramid.dir+( x+pyramid.perp)*pyramid.scale)*pyramid.h;
- point[3]=pyramid.pos+(pyramid.dir+( x-pyramid.perp)*pyramid.scale)*pyramid.h;
- point[4]=pyramid.pos+(pyramid.dir+(-x-pyramid.perp)*pyramid.scale)*pyramid.h;
- return ToFullScreenRect(point, PyramidEdges, Elms(PyramidEdges), rect);
- }
- Bool ToScreenRect(C Shape &shape, Rect &rect)
- {
- switch(shape.type)
- {
- case SHAPE_BOX : return ToScreenRect(shape.box , rect);
- case SHAPE_OBOX : return ToScreenRect(shape.obox , rect);
- case SHAPE_BALL : return ToScreenRect(shape.ball , rect);
- case SHAPE_CAPSULE: return ToScreenRect(shape.capsule, rect);
- case SHAPE_PYRAMID: return ToScreenRect(shape.pyramid, rect);
- default : return false;
- }
- }
- Bool ToScreenRect(C Shape *shape, Int shapes, Rect &rect)
- {
- Bool in=false;
- REP(shapes)
- {
- Rect r; if(ToScreenRect(shape[i], r))
- {
- if(!in){in=true; rect=r;}else rect|=r;
- }
- }
- return in;
- }
- /******************************************************************************/
- Int CompareTransparencyOrderDepth(C Vec &pos_a, C Vec &pos_b)
- {
- return Sign(Dot(pos_a-pos_b, ActiveCam.matrix.z));
- }
- Int CompareTransparencyOrderDepth(C VecD &pos_a, C VecD &pos_b)
- {
- return Sign(Dot(pos_a-pos_b, ActiveCam.matrix.z));
- }
- Int CompareTransparencyOrderDist(C Vec &pos_a, C Vec &pos_b)
- {
- return Sign(Dist2(pos_a, ActiveCam.matrix.pos)-Dist2(pos_b, ActiveCam.matrix.pos));
- }
- Int CompareTransparencyOrderDist(C VecD &pos_a, C VecD &pos_b)
- {
- return Sign(Dist2(pos_a, ActiveCam.matrix.pos)-Dist2(pos_b, ActiveCam.matrix.pos));
- }
- /******************************************************************************/
- void InitCamera()
- {
- ActiveCam.set(); // put values to shaders
- }
- /******************************************************************************/
- }
- /******************************************************************************/
|