diff --git a/common/lc_projection.cpp b/common/lc_projection.cpp new file mode 100644 index 00000000..66da154a --- /dev/null +++ b/common/lc_projection.cpp @@ -0,0 +1,49 @@ +#include "lc_global.h" +#include "lc_math.h" +#include "lc_projection.h" +#include "camera.h" + +void lcProjection::setTransformInput(const Camera* pCamera, int width, int height) +{ + mViewPixelWidth = width; + mViewPixelHeight = height; + mCamera = pCamera; + + calculateTransform(); +} + +void lcProjection::calculateTransform() +{ + if (NULL == mCamera) + { + return; + } + + float fAspect = (float)mViewPixelWidth/(float)mViewPixelHeight; + + switch(mType) + { + case Ortho: + { + // Compute the FOV/plane intersection radius. + // d d + // a = 2 atan(------) => ~ a = --- => d = af + // 2f f + float f = (mCamera->mPosition - mCamera->mOrthoTarget).Length(); + float d = ( mCamera->m_fovy * f) * (LC_PI / 180.0f); + float r = d/2; + + float right = r * fAspect; + mTransform = lcMatrix44Ortho(-right, right, -r, r, mCamera->m_zNear, mCamera->m_zFar * 4); + + return; + } + + case Projection: + default: + { + mTransform = lcMatrix44Perspective(mCamera->m_fovy, fAspect, mCamera->m_zNear, mCamera->m_zFar); + return; + } + } +} diff --git a/common/lc_projection.h b/common/lc_projection.h new file mode 100644 index 00000000..ced6e8e6 --- /dev/null +++ b/common/lc_projection.h @@ -0,0 +1,129 @@ +#ifndef _LC_PROJECTION_H_ +#define _LC_PROJECTION_H_ + +#include +#include "opengl.h" +#include "lc_math.h" + +class Camera; + +class lcProjection +{ +public: + + enum Type + { + Ortho = 0, + Projection, + OUT_OF_RANGE, + Cycle, + }; + + lcProjection() + { + mType = Projection; + mTransform = lcMatrix44Identity(); + mCamera = NULL; + } + + inline void SetType(Type type) + { + if (Cycle == type) + { + type = (Type)((int)mType + 1); + if (OUT_OF_RANGE == type) + type = (Type)0; + } + + if (type < OUT_OF_RANGE) + { + mType = type; + } + + calculateTransform(); + } + + inline Type GetType() const + { + return mType; + } + + inline void SetView(const Camera* pCamera, int width, int height) + { + setTransformInput(pCamera, width, height); + } + + inline lcVector3 ProjectPoint(const lcMatrix44 mWorldView, const lcVector3& Point) const + { + int viewport[4] = { 0, 0, mViewPixelWidth, mViewPixelHeight }; + return lcProjectPoint(Point, mWorldView, mTransform, viewport); + } + + inline lcVector3 UnprojectPoint(const lcMatrix44 mWorldView, const lcVector3& Point) const + { + int viewport[4] = { 0, 0, mViewPixelWidth, mViewPixelHeight }; + return lcUnprojectPoint(Point, mWorldView, mTransform, viewport); + } + + inline void UnprojectPoints(const lcMatrix44 mWorldView, lcVector3* Points, int NumPoints) const + { + if (NumPoints > 0) + { + int viewport[4] = { 0, 0, mViewPixelWidth, mViewPixelHeight }; + lcUnprojectPoints(Points, NumPoints, mWorldView, mTransform, viewport); + } + } + + inline int ConstrainX(int x) const + { + if (x >= mViewPixelWidth) + return mViewPixelWidth - 1; + else + if (x <= 0) + return 1; + return x; + } + + inline int ConstrainY(int y) const + { + if (y >= mViewPixelHeight) + return mViewPixelHeight - 1; + else + if (y <= 0) + return 1; + return y; + } + + operator lcMatrix44& () + { + return mTransform; + } + + const char* GetName() const + { + switch(mType) + { + case Ortho: + return "Ortho"; + + case Projection: + return "Projection"; + + default: + return ""; + } + } + +private: + + void calculateTransform(); + void setTransformInput(const Camera* pCamera, int width, int height); + + Type mType; + lcMatrix44 mTransform; + const Camera* mCamera; + int mViewPixelWidth; + int mViewPixelHeight; +}; + +#endif _LC_PROJECTION_H_