123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848 |
- #include "pch.h"
- //////////////////////////////////////////////////////////////////////////////
- //
- // Camera
- //
- //////////////////////////////////////////////////////////////////////////////
- Camera::Camera() :
- Value(
- new VectorValue(
- Vector(
- 0, 0, 0
- )
- ),
- new OrientationValue(
- Orientation(
- Vector(0, 0, -1),
- Vector(0, 1, 0)
- )
- )
- ),
- m_znear(-1),
- m_zfar(1),
- m_focus(0),
- m_bInverseValid(false)
- {
- }
- const Vector& Camera::GetPosition()
- {
- return GetPositionValue()->GetValue();
- }
- const Orientation& Camera::GetOrientation()
- {
- return GetOrientationValue()->GetValue();
- }
- void Camera::Evaluate()
- {
- if (m_focus == 0) {
- //
- // orthoganal projection
- //
- // : what is m_focus for an orthogonal camera?
- //
- // 1) xscreen = x
- // 2) zbuffer = a * z + b
- //
- // 3) 0 = a * znear + b
- // 4) 1 = a * zfar + b
- // 5) 3 => b = -a * znear
- // 6) 4,5 => 1 = a * zfar - a * znear
- // a = 1 / (zfar - znear)
- //
- float a = 1 / (m_zfar - m_znear);
- float b = -a * m_znear;
- m_matPerspective.SetIdentity();
- m_matPerspective.Set(2, 2, a);
- m_matPerspective.Set(2, 3, b);
- } else {
- //
- // perspective projection
- //
- //
- // 1) xscreen = f * x / -z
- // 2) zbuffer = (a * z + b) / -z
- //
- // 3) 0 = (a * znear + b) / -znear
- // 4) 1 = (a * zfar + b) / -zfar
- // 5) 3 => b = -a * znear
- // 6) 4,5 => -zfar = a * zfar - a * znear
- // a = zfar / (znear - zfar)
- //
- //
- float a = m_zfar / (m_znear - m_zfar);
- float b = -a * m_znear;
- m_matPerspective.SetIdentity();
- m_matPerspective.Set(0, 0, m_focus);
- m_matPerspective.Set(1, 1, m_focus);
- m_matPerspective.Set(2, 2, a);
- m_matPerspective.Set(2, 3, b);
- m_matPerspective.Set(3, 2, -1);
- m_matPerspective.Set(3, 3, 0);
- }
- const Vector& v = GetPosition();
- const Orientation& o = GetOrientation();
- m_matModel =
- Matrix(
- o[0][0], o[0][1], o[0][2], 0,
- o[1][0], o[1][1], o[1][2], 0,
- o[2][0], o[2][1], o[2][2], 0
- );
- m_matModel.PreTranslate(-v);
- m_bInverseValid = false;
- }
- void Camera::UpdateInverse()
- {
- if (!m_bInverseValid) {
- m_matInverseModel.SetInverse(m_matModel);
- }
- }
- void Camera::SetPosition(const Vector& vec)
- {
- SetPositionValue(new VectorValue(vec));
- }
- void Camera::SetOrientation(const Orientation& orientation)
- {
- SetOrientationValue(new OrientationValue(orientation));
- }
- void Camera::SetZClip(float znear, float zfar)
- {
- m_znear = -znear;
- m_zfar = -zfar;
- Changed();
- }
- void Camera::SetOrthogonal()
- {
- m_focus = 0;
- Changed();
- }
- void Camera::SetPerspective(float f)
- {
- m_focus = f;
- Changed();
- }
- void Camera::SetFOV(float fov)
- {
- m_fov = fov;
- SetPerspective(cos(0.5f * fov) / sin(0.5f * fov));
- }
- Vector Camera::TransformLocalToEye(const Vector& vec)
- {
- return GetModelMatrix().Transform(vec);
- }
- bool Camera::TransformEyeToImage(const Vector& vecEye, Point& point)
- {
- if (GetFocus() == 0) {
- point = Point(vecEye.X(), vecEye.Y());
- } else {
- if (vecEye.Z() >= 0) {
- return false;
- }
- point = Point(vecEye.X(), vecEye.Y()) * (GetFocus() / -vecEye.Z());
- }
- return true;
- }
- bool Camera::TransformLocalToImage(const Vector& vec, Point& point)
- {
- return TransformEyeToImage(TransformLocalToEye(vec), point);
- }
- bool Camera::TransformDirectionToImage(const Vector& vec, Point& point)
- {
- HVector hvec = GetModelMatrix().Transform(HVector(vec.X(), vec.Y(), vec.Z(), 0));
- return TransformEyeToImage(Vector(hvec.X(), hvec.Y(), hvec.Z()), point);
- }
- Vector Camera::TransformImageToDirection(const Point& point)
- {
- UpdateInverse();
- HVector hvec = m_matInverseModel.Transform(HVector(point.X(), point.Y(), -GetFocus(), 0));
- return Vector(hvec.X(), hvec.Y(), hvec.Z());
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // MotionCamera
- //
- //////////////////////////////////////////////////////////////////////////////
- class MotionCamera : public Value, public IKeyboardInput {
- private:
- //////////////////////////////////////////////////////////////////////////////
- //
- // Types
- //
- //////////////////////////////////////////////////////////////////////////////
- class MotionCameraImage : public Image {
- TRef<MotionCamera> m_pcamera;
- public:
- MotionCameraImage(MotionCamera* pcamera) :
- m_pcamera(pcamera)
- {
- }
- MouseResult HitTest(IInputProvider* pprovider, const Point& point, bool bCaptured)
- {
- return MouseResultHit();
- }
- void MouseMove(IInputProvider* pprovider, const Point& point, bool bCaptured, bool bInside)
- {
- m_pcamera->MouseMove(pprovider, point, bCaptured, bInside);
- }
- MouseResult Button(IInputProvider* pprovider, const Point& point, int button, bool bCaptured, bool bInside, bool bDown)
- {
- return m_pcamera->Button(pprovider, point, button, bCaptured, bInside, bDown);
- }
- //
- // Value members
- //
- ZString GetFunctionName() { return "MotionCameraImage"; }
- };
- class MotionVector : public VectorValue {
- MotionCamera* GetMotionCamera() { return MotionCamera::Cast(GetChild(0)); };
- public:
- MotionVector(MotionCamera* pmotionCamera) :
- VectorValue(pmotionCamera)
- {
- }
- //
- // Value members
- //
- void Evaluate()
- {
- GetValueInternal() = GetMotionCamera()->m_position;
- }
- };
- class MotionOrientation : public OrientationValue {
- MotionCamera* GetMotionCamera() { return MotionCamera::Cast(GetChild(0)); };
- public:
- MotionOrientation(MotionCamera* pmotionCamera) :
- OrientationValue(pmotionCamera)
- {
- }
- //
- // Value members
- //
- void Evaluate()
- {
- GetValueInternal() = GetMotionCamera()->m_orient;
- }
- };
- friend class MotionVector;
- friend class MotionOrientation;
- //////////////////////////////////////////////////////////////////////////////
- //
- // members
- //
- //////////////////////////////////////////////////////////////////////////////
- float m_timeLast;
- Vector m_position;
- Orientation m_orientLast;
- Orientation m_orient;
- float m_speed;
- float m_angleRoll;
- float m_angleYaw;
- float m_anglePitch;
- bool m_bForward;
- bool m_bBackward;
- bool m_bLeft;
- bool m_bRight;
- bool m_bUp;
- bool m_bDown;
- bool m_bAccelerate;
- bool m_bLeftButtonDown;
- bool m_bRightButtonDown;
- Point m_pointStart;
- float GetTime() { return Number::Cast(GetChild(0))->GetValue(); }
- public:
- DefineCastMember(MotionCamera);
- MotionCamera(
- const Vector& vec,
- Number* ptime,
- TRef<Image>& pimage,
- TRef<VectorValue>& pvectorValue,
- TRef<OrientationValue>& porientationValue
- ) :
- Value(ptime),
- m_position(vec)
- {
- pimage = new MotionCameraImage(this);
- pvectorValue = new MotionVector(this);
- porientationValue = new MotionOrientation(this);
- m_timeLast = ptime->GetValue();
- m_anglePitch = 0;
- m_angleYaw = 0;
- m_angleRoll = 0;
- m_speed = 0;
- m_bForward = false;
- m_bBackward = false;
- m_bLeft = false;
- m_bRight = false;
- m_bUp = false;
- m_bDown = false;
- m_bAccelerate = false;
- m_bLeftButtonDown = false;
- m_bRightButtonDown = false;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // IKeboardInput Methods
- //
- //////////////////////////////////////////////////////////////////////////////
- bool OnKey(IInputProvider* pprovider, const KeyState& ks, bool& fForceTranslate)
- {
- switch (ks.vk) {
- case 'W' : m_bForward = ks.bDown; return true;
- case 'S' : m_bBackward = ks.bDown; return true;
- case 'A' : m_bLeft = ks.bDown; return true;
- case 'D' : m_bRight = ks.bDown; return true;
- case 'E' : m_bUp = ks.bDown; return true;
- case 'Q' : m_bDown = ks.bDown; return true;
- case VK_SHIFT : m_bAccelerate = ks.bDown; return true;
- }
- return false;
- }
- void MouseDown(IInputProvider* pprovider, const Point& point)
- {
- ZAssert(m_angleYaw == 0);
- m_angleRoll = 0;
- m_angleYaw = 0;
- m_anglePitch = 0;
- m_pointStart = point;
- //pprovider->ShowCursor(false);
- }
- void MouseUp(IInputProvider* pprovider)
- {
- m_orientLast = m_orient;
- m_bLeftButtonDown = false;
- m_bRightButtonDown = false;
- m_angleRoll = 0;
- m_angleYaw = 0;
- m_anglePitch = 0;
- //pprovider->SetCursorPos(m_pointStart);
- //pprovider->ShowCursor(true);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // IMouseInput Methods
- //
- //////////////////////////////////////////////////////////////////////////////
- void MouseMove(IInputProvider* pprovider, const Point& point, bool bCaptured, bool bInside)
- {
- if (bCaptured) {
- if (point != m_pointStart) {
- float scale = 0.0025f;
- float dx = scale * (point.X() - m_pointStart.X());
- float dy = scale * (point.Y() - m_pointStart.Y());
- if (m_bRightButtonDown) {
- m_angleRoll -= dx;
- } else {
- m_angleYaw -= dx;
- m_anglePitch =
- bound(
- m_anglePitch + dy,
- -pi/2,
- pi/2
- );
- }
- pprovider->SetCursorPos(m_pointStart);
- Changed();
- }
- }
- }
- MouseResult Button(IInputProvider* pprovider, const Point& point, int button, bool bCaptured, bool bInside, bool bDown)
- {
- switch (button) {
- case 0:
- if (bDown) {
- if (!m_bRightButtonDown) {
- m_bLeftButtonDown = true;
- MouseDown(pprovider, point);
- return MouseResultCapture();
- }
- } else {
- if (m_bLeftButtonDown) {
- m_bLeftButtonDown = false;
- MouseUp(pprovider);
- return MouseResultRelease();
- }
- }
- break;
- case 1:
- if (bDown) {
- if (!m_bLeftButtonDown) {
- m_bRightButtonDown = true;
- MouseDown(pprovider, point);
- return MouseResultCapture();
- }
- } else {
- if (m_bRightButtonDown) {
- m_bRightButtonDown = false;
- MouseUp(pprovider);
- return MouseResultRelease();
- }
- }
- break;
- }
- return MouseResult();
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Value methods
- //
- //////////////////////////////////////////////////////////////////////////////
- void Evaluate()
- {
- float time = GetTime();
- float dtime = time - m_timeLast;
- m_timeLast = time;
- //
- // The orientation
- //
- m_orient = m_orientLast;
- if (m_bLeftButtonDown || m_bRightButtonDown) {
- m_orient.Yaw(m_angleYaw);
- m_orient.Pitch(m_anglePitch);
- m_orient.Roll(m_angleRoll);
- }
- //
- // The position
- //
- Vector vecDPos(0, 0, 0);
- if (m_bForward) {
- vecDPos -= m_orient.GetBackward() * dtime;
- }
- if (m_bBackward) {
- vecDPos += m_orient.GetBackward() * dtime;
- }
- if (m_bRight) {
- vecDPos += m_orient.GetRight() * dtime;
- }
- if (m_bLeft) {
- vecDPos -= m_orient.GetRight() * dtime;
- }
- if (m_bUp) {
- vecDPos += m_orient.GetUp() * dtime;
- }
- if (m_bDown) {
- vecDPos -= m_orient.GetUp() * dtime;
- }
- if (
- m_bAccelerate
- && (m_bForward || m_bBackward || m_bRight || m_bLeft || m_bUp || m_bDown)
- ) {
- m_speed *= 1.1f;
- if (m_speed > 100) {
- m_speed = 100;
- }
- } else {
- m_speed = 10;
- }
- //
- // Setup the camera
- //
- m_position += vecDPos * m_speed;
- }
- ZString GetFunctionName() { return "MotionCamera"; }
- };
- //////////////////////////////////////////////////////////////////////////////
- //
- // MotionCamera
- //
- //////////////////////////////////////////////////////////////////////////////
- TRef<Camera> CreateMotionCamera(
- const Vector& vec,
- Number* ptime,
- TRef<Image>& pimage,
- TRef<IKeyboardInput>& pkeyboardInput
- ) {
- TRef<VectorValue> pvectorValue;
- TRef<OrientationValue> porientationValue;
- TRef<MotionCamera> pmotionCamera =
- new MotionCamera(
- vec,
- ptime,
- pimage,
- pvectorValue,
- porientationValue
- );
- pkeyboardInput = pmotionCamera;
- return new Camera(pvectorValue, porientationValue);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // SmoothPosition
- //
- //////////////////////////////////////////////////////////////////////////////
- class SmoothPosition : public ISmoothPosition {
- //////////////////////////////////////////////////////////////////////////////
- //
- // Types
- //
- //////////////////////////////////////////////////////////////////////////////
- class Data : public IObject {
- public:
- Vector m_vec;
- float m_dtime;
- Data(const Vector& vec, float dtime) :
- m_vec(vec),
- m_dtime(dtime)
- {
- }
- };
- typedef TList<TRef<Data> > DataList;
- //////////////////////////////////////////////////////////////////////////////
- //
- // members
- //
- //////////////////////////////////////////////////////////////////////////////
- float GetTime() { return Number::Cast(GetChild(0))->GetValue(); }
- DataList m_listData;
- Vector m_positionStart;
- float m_timeStart;
- public:
- SmoothPosition(
- Number* ptime,
- const Vector& vec
- ) :
- ISmoothPosition(ptime),
- m_positionStart(vec),
- m_timeStart(0)
- {
- GetValueInternal() = m_positionStart;
- }
- void Goto(const Vector& vector, float dtime)
- {
- if (m_listData.IsEmpty()) {
- m_timeStart = GetTime();
- }
- m_listData.PushEnd(new Data(vector, dtime));
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Value members
- //
- //////////////////////////////////////////////////////////////////////////////
- void Evaluate()
- {
- float time = GetTime();
- float dtime = time - m_timeStart;
- Data* pdata;
- while (true) {
- if (m_listData.IsEmpty()) {
- return;
- }
- pdata = m_listData.GetFront();
- if (dtime <= pdata->m_dtime) {
- break;
- }
- GetValueInternal() = pdata->m_vec;
- m_positionStart = pdata->m_vec;
- m_timeStart += pdata->m_dtime;
- dtime -= pdata->m_dtime;
- m_listData.PopFront();
- }
- GetValueInternal() =
- Interpolate(
- m_positionStart,
- pdata->m_vec,
- SmoothInterpolant(dtime / pdata->m_dtime)
- );
- }
- };
- TRef<ISmoothPosition> CreateSmoothPosition(Number* ptime, const Vector& vec)
- {
- return new SmoothPosition(ptime, vec);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // SmoothOrientation
- //
- //////////////////////////////////////////////////////////////////////////////
- class SmoothOrientation : public ISmoothOrientation
- {
- //////////////////////////////////////////////////////////////////////////////
- //
- // Types
- //
- //////////////////////////////////////////////////////////////////////////////
- class Data : public IObject
- {
- public:
- Quaternion m_quaternion;
- float m_dtime;
- Data(const Orientation& orientation, float dtime)
- :
- m_quaternion(orientation),
- m_dtime(dtime)
- {
- }
- };
- typedef TList<TRef<Data> > DataList;
- //////////////////////////////////////////////////////////////////////////////
- //
- // members
- //
- //////////////////////////////////////////////////////////////////////////////
- float GetTime() { return Number::Cast(GetChild(0))->GetValue(); }
- DataList m_listData;
- Quaternion m_qStart;
- float m_timeStart;
- public:
- SmoothOrientation(Number* ptime,
- const Orientation& orientation)
- :
- ISmoothOrientation(ptime),
- m_qStart(orientation),
- m_timeStart(0)
- {
- GetValueInternal() = orientation;
- }
- void Goto(const Orientation& orientation, float dtime)
- {
- if (m_listData.IsEmpty())
- {
- m_timeStart = GetTime();
- }
- m_listData.PushEnd(new Data(orientation, dtime));
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Value members
- //
- //////////////////////////////////////////////////////////////////////////////
- void Evaluate()
- {
- if (m_listData.IsEmpty())
- return;
- float time = GetTime();
- float dtime = time - m_timeStart;
- Data* pdata;
- while (true)
- {
- pdata = m_listData.GetFront();
- if (dtime <= pdata->m_dtime)
- break;
- m_qStart = pdata->m_quaternion;
- m_timeStart += pdata->m_dtime;
- dtime -= pdata->m_dtime;
- m_listData.PopFront();
- if (m_listData.IsEmpty())
- {
- GetValueInternal() = m_qStart;
- return;
- }
- }
- GetValueInternal() = Slerp(m_qStart, pdata->m_quaternion, dtime / pdata->m_dtime);
- }
- };
- TRef<ISmoothOrientation> CreateSmoothOrientation(Number* ptime, const Orientation& o)
- {
- return new SmoothOrientation(ptime, o);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // LookAtOrientation
- //
- //////////////////////////////////////////////////////////////////////////////
- class LookAtOrientation : public OrientationValue {
- //////////////////////////////////////////////////////////////////////////////
- //
- // Arguments
- //
- //////////////////////////////////////////////////////////////////////////////
- const Vector& GetAt() { return VectorValue::Cast(GetChild(0))->GetValue(); }
- const Vector& GetFrom() { return VectorValue::Cast(GetChild(1))->GetValue(); }
- const Vector& GetUp() { return VectorValue::Cast(GetChild(2))->GetValue(); }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Value members
- //
- //////////////////////////////////////////////////////////////////////////////
- void Evaluate()
- {
- const Vector& vecAt = GetAt();
- const Vector& vecFrom = GetFrom();
- const Vector& vecUp = GetUp();
- GetValueInternal().Set(
- (vecAt - vecFrom).Normalize(),
- vecUp
- );
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // members
- //
- //////////////////////////////////////////////////////////////////////////////
- public:
- LookAtOrientation(
- VectorValue* pvectorAt,
- VectorValue* pvectorFrom,
- VectorValue* pvectorUp
- ) :
- OrientationValue(
- pvectorAt,
- pvectorFrom,
- pvectorUp
- )
- {
- }
- };
- TRef<OrientationValue> CreateLookAtOrientation(
- VectorValue* pvectorAt,
- VectorValue* pvectorFrom,
- VectorValue* pvectorUp
- ) {
- return new LookAtOrientation(pvectorAt, pvectorFrom, pvectorUp);
- }
|