*
This commit is contained in:
@@ -0,0 +1,329 @@
|
||||
#ifndef Camera_h__
|
||||
#define Camera_h__
|
||||
|
||||
#include "IGraphicsNode.h"
|
||||
#include "math/LifeMath.h"
|
||||
#include "camera/Frustum.h"
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
class Camera : public IGraphicsNode
|
||||
{
|
||||
private:
|
||||
bool isViewValid;
|
||||
bool isProjValid;
|
||||
float fov;
|
||||
float nearPlane;
|
||||
float farPlane;
|
||||
float viewAspect;
|
||||
LifeMath::float3 right;
|
||||
LifeMath::float3 eye;
|
||||
LifeMath::float3 at;
|
||||
LifeMath::float3 up;
|
||||
float yaw, pitch, roll;
|
||||
Frustum frustum;
|
||||
LifeMath::float3 ViewDirection;
|
||||
LifeMath::float4x4 viewMatrix;
|
||||
LifeMath::float4x4 projectionMatrix;
|
||||
bool freeCam;
|
||||
LifeMath::float3 fDir;
|
||||
NodeType getType()
|
||||
{
|
||||
return NT_CAMERA;
|
||||
}
|
||||
void UpdatePerspectiveMatrix()
|
||||
{
|
||||
Mat4x4PerspectiveFOV(fov, viewAspect, nearPlane, farPlane, projectionMatrix);
|
||||
isProjValid = true;
|
||||
frustum.UpdateFrustum(viewMatrix * projectionMatrix);
|
||||
}
|
||||
|
||||
void ComputeView()
|
||||
{
|
||||
//g_viewMatrix = Matrix4x4.LookAtLH(g_eye, g_at, g_up);
|
||||
|
||||
ViewDirection = at - eye;
|
||||
LifeMath::Vec3Normalize(&ViewDirection, &ViewDirection);
|
||||
|
||||
up = LifeMath::float3(0,1,0);
|
||||
|
||||
//fixup UP vector
|
||||
if(LifeMath::Vec3Dot(&ViewDirection, &up) > 0.998f)
|
||||
{
|
||||
up = LifeMath::float3(0,0,-1);
|
||||
}
|
||||
else if(LifeMath::Vec3Dot(&ViewDirection, &up) < -0.998f)
|
||||
{
|
||||
up = LifeMath::float3(0,0,1);
|
||||
}
|
||||
|
||||
//orthoganalize right vector
|
||||
LifeMath::Vec3Cross(up, ViewDirection, right);
|
||||
LifeMath::Vec3Normalize(&right);
|
||||
|
||||
//orthoganalize up vector
|
||||
LifeMath::Vec3Cross(ViewDirection, right, up);
|
||||
LifeMath::Vec3Normalize(&up);
|
||||
|
||||
//compute view matrix
|
||||
float x = -LifeMath::Vec3Dot(&right, &eye);
|
||||
float y = -LifeMath::Vec3Dot(&up, &eye);
|
||||
float z = -LifeMath::Vec3Dot(&ViewDirection, &eye);
|
||||
|
||||
viewMatrix.M11 = right.X;
|
||||
viewMatrix.M12 = up.X;
|
||||
viewMatrix.M13 = ViewDirection.X;
|
||||
viewMatrix.M14 = 0;
|
||||
|
||||
viewMatrix.M21 = right.Y;
|
||||
viewMatrix.M22 = up.Y;
|
||||
viewMatrix.M23 = ViewDirection.Y;
|
||||
viewMatrix.M24 = 0;
|
||||
|
||||
viewMatrix.M31 = right.Z;
|
||||
viewMatrix.M32 = up.Z;
|
||||
viewMatrix.M33 = ViewDirection.Z;
|
||||
viewMatrix.M34 = 0;
|
||||
|
||||
viewMatrix.M41 = x;
|
||||
viewMatrix.M42 = y;
|
||||
viewMatrix.M43 = z;
|
||||
viewMatrix.M44 = 1.0f;
|
||||
|
||||
isViewValid = true;
|
||||
|
||||
frustum.UpdateFrustum(viewMatrix * projectionMatrix);
|
||||
}
|
||||
|
||||
public:
|
||||
Camera();
|
||||
~Camera();
|
||||
void update(float dt)
|
||||
{
|
||||
}
|
||||
void setAspect(float aspect)
|
||||
{
|
||||
viewAspect = aspect;
|
||||
isProjValid = false;
|
||||
}
|
||||
void setFov(float _fov)
|
||||
{
|
||||
fov = _fov;
|
||||
isProjValid = false;
|
||||
}
|
||||
void setNear(float val)
|
||||
{
|
||||
nearPlane = val;
|
||||
isProjValid = false;
|
||||
}
|
||||
void setFar(float val)
|
||||
{
|
||||
farPlane = val;
|
||||
isProjValid = false;
|
||||
}
|
||||
float getNear() const
|
||||
{
|
||||
return nearPlane;
|
||||
}
|
||||
float getFar() const
|
||||
{
|
||||
return farPlane;
|
||||
}
|
||||
LifeMath::float4x4 getView()
|
||||
{
|
||||
if(isViewValid)
|
||||
{
|
||||
return viewMatrix;
|
||||
}
|
||||
else
|
||||
{
|
||||
ComputeView();
|
||||
isViewValid = true;
|
||||
return viewMatrix;
|
||||
}
|
||||
}
|
||||
LifeMath::float4x4 getProj()
|
||||
{
|
||||
if(isProjValid)
|
||||
{
|
||||
return projectionMatrix;
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdatePerspectiveMatrix();
|
||||
isProjValid = true;
|
||||
return projectionMatrix;
|
||||
}
|
||||
}
|
||||
LifeMath::float3 getDirection()
|
||||
{
|
||||
return ViewDirection;
|
||||
}
|
||||
LifeMath::float3 getRight()
|
||||
{
|
||||
return right;
|
||||
}
|
||||
void setPosition(float x, float y, float z)
|
||||
{
|
||||
eye = LifeMath::float3(x, y, z);
|
||||
isViewValid = false;
|
||||
}
|
||||
void setPosition(const LifeMath::float3& position)
|
||||
{
|
||||
eye = position;
|
||||
isViewValid = false;
|
||||
//ComputeView();
|
||||
/*isViewValid = false;*/
|
||||
}
|
||||
void setDirection(LifeMath::float3& direction)
|
||||
{
|
||||
at = direction;
|
||||
//at = direction - eye;
|
||||
//LifeMath::Vec3Normalize(&at);
|
||||
|
||||
up.X = 0.0f;
|
||||
up.Y = 1.0f;
|
||||
up.Z = 0.0f;
|
||||
isViewValid = false;
|
||||
//LifeMath::Vec3Cross(up, at, right);
|
||||
//ComputeView();
|
||||
}
|
||||
Frustum* getFrustum()
|
||||
{
|
||||
bool updateFrustum = false;
|
||||
if(!isViewValid)
|
||||
{
|
||||
ComputeView();
|
||||
updateFrustum = true;
|
||||
}
|
||||
if(!isProjValid)
|
||||
{
|
||||
UpdatePerspectiveMatrix();
|
||||
updateFrustum = true;
|
||||
}
|
||||
|
||||
return &frustum;
|
||||
}
|
||||
const LifeMath::float3& getPosition() const
|
||||
{
|
||||
return eye;
|
||||
}
|
||||
|
||||
float getFov() const
|
||||
{
|
||||
return fov;
|
||||
}
|
||||
float getAspect() const
|
||||
{
|
||||
return viewAspect;
|
||||
}
|
||||
|
||||
const LifeMath::float3& getUp() const
|
||||
{
|
||||
return up;
|
||||
}
|
||||
|
||||
void Yaw(float angle)
|
||||
{
|
||||
yaw += angle;
|
||||
LifeMath::float3 axis = LifeMath::float3(0.0f, 1.0f, 0.0f);
|
||||
LifeMath::float4x4 r;
|
||||
Mat4x4RotationAxis(&axis, angle, &r);
|
||||
if (freeCam)
|
||||
{
|
||||
Vec3TransformCoordinate(right, r, right);
|
||||
Vec3TransformCoordinate(at, r, at);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec3TransformCoordinate(fDir, r, fDir);
|
||||
Vec3TransformCoordinate(right, r, right);
|
||||
}
|
||||
isViewValid = false;
|
||||
}
|
||||
|
||||
void Pitch(float angle)
|
||||
{
|
||||
pitch += angle;
|
||||
LifeMath::float4x4 r;
|
||||
Mat4x4RotationAxis(&right, angle, &r);
|
||||
if (freeCam)
|
||||
{
|
||||
Vec3TransformCoordinate(up, r, up);
|
||||
Vec3TransformCoordinate(at, r, at);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec3TransformCoordinate(up, r, up);
|
||||
Vec3TransformCoordinate(fDir, r, fDir);
|
||||
}
|
||||
isViewValid = false;
|
||||
}
|
||||
|
||||
void Roll(float angle)
|
||||
{
|
||||
roll += angle;
|
||||
LifeMath::float4x4 r;
|
||||
Mat4x4RotationAxis(&at, angle, &r);
|
||||
Vec3TransformCoordinate(up, r, up);
|
||||
Vec3TransformCoordinate(right, r, at);
|
||||
isViewValid = false;
|
||||
}
|
||||
void GetCorners(LifeMath::float3* corners)
|
||||
{
|
||||
if(!isViewValid)
|
||||
ComputeView();
|
||||
if(!isProjValid)
|
||||
UpdatePerspectiveMatrix();
|
||||
|
||||
LifeMath::float4x4 vp = viewMatrix * projectionMatrix;
|
||||
Mat4x4Invert(&vp);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
corners[i] = Vec3TransformCoordinate(vp, baseCorners[i]);
|
||||
}
|
||||
}
|
||||
void SetupBasis(const LifeMath::float3& _pos, const LifeMath::float3& _front, const LifeMath::float3& _top, const LifeMath::float3& _right)
|
||||
{
|
||||
eye = _pos;
|
||||
right = _right;
|
||||
up = _top;
|
||||
at = _front;
|
||||
ViewDirection = at;
|
||||
|
||||
LifeMath::Vec3Normalize(&right);
|
||||
LifeMath::Vec3Normalize(&at);
|
||||
LifeMath::Vec3Normalize(&up);
|
||||
|
||||
//compute view matrix
|
||||
float x = -LifeMath::Vec3Dot(&right, &eye);
|
||||
float y = -LifeMath::Vec3Dot(&up, &eye);
|
||||
float z = -LifeMath::Vec3Dot(&at, &eye);
|
||||
|
||||
viewMatrix.M11 = right.X;
|
||||
viewMatrix.M12 = up.X;
|
||||
viewMatrix.M13 = at.X;
|
||||
viewMatrix.M14 = 0.0f;
|
||||
|
||||
viewMatrix.M21 = right.Y;
|
||||
viewMatrix.M22 = up.Y;
|
||||
viewMatrix.M23 = at.Y;
|
||||
viewMatrix.M24 = 0.0f;
|
||||
|
||||
viewMatrix.M31 = right.Z;
|
||||
viewMatrix.M32 = up.Z;
|
||||
viewMatrix.M33 = at.Z;
|
||||
viewMatrix.M34 = 0.0f;
|
||||
|
||||
viewMatrix.M41 = x;
|
||||
viewMatrix.M42 = y;
|
||||
viewMatrix.M43 = z;
|
||||
viewMatrix.M44 = 1.0f;
|
||||
|
||||
isViewValid = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // Camera_h__
|
||||
@@ -0,0 +1,186 @@
|
||||
#ifndef Frustum_h__
|
||||
#define Frustum_h__
|
||||
|
||||
#include "math/LifeMath.h"
|
||||
#include <BoundingBox3D.h>
|
||||
#include "BoundingSphere.h"
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
enum BoxIntersectionResult
|
||||
{
|
||||
Inside = 0, Outside = 1, Intersection = 2
|
||||
};
|
||||
|
||||
enum FrustumPlane
|
||||
{
|
||||
Top = 0, Bottom = 0, Left = 0, Right = 0, Near = 0, Far = 0
|
||||
};
|
||||
|
||||
static const LifeMath::float3 baseCorners[] = {
|
||||
//front plane
|
||||
LifeMath::float3(-1.0f, 1.0f, 1.0f),
|
||||
LifeMath::float3(1.0f, 1.0f, 1.0f),
|
||||
LifeMath::float3(1.0f, -1.0f, 1.0f),
|
||||
LifeMath::float3(-1.0f, -1.0f, 1.0f),
|
||||
|
||||
//rear plane
|
||||
LifeMath::float3(-1.0f, 1.0f, -1.0f),
|
||||
LifeMath::float3(1.0f, 1.0f, -1.0f),
|
||||
LifeMath::float3(1.0f, -1.0f, -1.0f),
|
||||
LifeMath::float3(-1.0f, -1.0f, -1.0f)
|
||||
};
|
||||
|
||||
class Frustum
|
||||
{
|
||||
private:
|
||||
|
||||
LifeMath::Plane frustrumPlanes[6];
|
||||
LifeMath::float3 corners[8];
|
||||
LifeMath::float4x4 vp;
|
||||
|
||||
public:
|
||||
Frustum()
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
frustrumPlanes[i] = LifeMath::Plane(LifeMath::float3(0.0f, 0.0f, 0.0f), LifeMath::float3(0.0f, 1.0f, 0.0f));
|
||||
}
|
||||
Frustum(LifeMath::Plane& _near, LifeMath::Plane& _far, LifeMath::Plane& _top, LifeMath::Plane& _bottom,
|
||||
LifeMath::Plane& _left, LifeMath::Plane& _right)
|
||||
{
|
||||
frustrumPlanes[0] = _top;
|
||||
frustrumPlanes[1] = _bottom;
|
||||
frustrumPlanes[2] = _left;
|
||||
frustrumPlanes[3] = _right;
|
||||
frustrumPlanes[4] = _near;
|
||||
frustrumPlanes[5] = _far;
|
||||
}
|
||||
Frustum(const LifeMath::float4x4& viewProjection)
|
||||
{
|
||||
UpdateFrustum(viewProjection);
|
||||
}
|
||||
~Frustum(){}
|
||||
void UpdateFrustum(const LifeMath::float4x4& viewProjection)
|
||||
{
|
||||
vp = viewProjection;
|
||||
// Top plane
|
||||
frustrumPlanes[0] = LifeMath::Plane(
|
||||
viewProjection.M14 - viewProjection.M12,
|
||||
viewProjection.M24 - viewProjection.M22,
|
||||
viewProjection.M34 - viewProjection.M32,
|
||||
viewProjection.M44 - viewProjection.M42);
|
||||
|
||||
// Bottom plane
|
||||
frustrumPlanes[1] = LifeMath::Plane(
|
||||
viewProjection.M14 + viewProjection.M12,
|
||||
viewProjection.M24 + viewProjection.M22,
|
||||
viewProjection.M34 + viewProjection.M32,
|
||||
viewProjection.M44 + viewProjection.M42);
|
||||
|
||||
// Left plane
|
||||
frustrumPlanes[2] = LifeMath::Plane(
|
||||
viewProjection.M14 + viewProjection.M11,
|
||||
viewProjection.M24 + viewProjection.M21,
|
||||
viewProjection.M34 + viewProjection.M31,
|
||||
viewProjection.M44 + viewProjection.M41);
|
||||
|
||||
// Right plane
|
||||
frustrumPlanes[3] = LifeMath::Plane(
|
||||
viewProjection.M14 - viewProjection.M11,
|
||||
viewProjection.M24 - viewProjection.M21,
|
||||
viewProjection.M34 - viewProjection.M31,
|
||||
viewProjection.M44 - viewProjection.M41);
|
||||
|
||||
// Near plane
|
||||
frustrumPlanes[4] = LifeMath::Plane(
|
||||
viewProjection.M13,
|
||||
viewProjection.M23,
|
||||
viewProjection.M33,
|
||||
viewProjection.M43);
|
||||
|
||||
// Far plane
|
||||
frustrumPlanes[5] = LifeMath::Plane(
|
||||
viewProjection.M14 - viewProjection.M13,
|
||||
viewProjection.M24 - viewProjection.M23,
|
||||
viewProjection.M34 - viewProjection.M33,
|
||||
viewProjection.M44 - viewProjection.M43);
|
||||
|
||||
// Normalize planes
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
LifeMath::PlaneNormalize(frustrumPlanes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool SphereInFrustum(const LifeMath::float3& center, float radius) const
|
||||
{
|
||||
LifeMath::float4 position = LifeMath::float4(center.X, center.Y, center.Z, 1.0f);
|
||||
for (int i = 0; i < 6; i++)
|
||||
if(LifeMath::PlaneDot(frustrumPlanes[i], position) + radius < 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SphereInFrustum(const BoundingSphere* sphere) const
|
||||
{
|
||||
LifeMath::float4 position = LifeMath::float4(sphere->center.X, sphere->center.Y, sphere->center.Z, 1.0f);
|
||||
for (int i = 0; i < 6; i++)
|
||||
if(PlaneDot(frustrumPlanes[i], position) + sphere->radius < 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BoxInFrustum(const LifeCore::BoundingBox3D& box) const
|
||||
{
|
||||
LifeMath::float3 corners[8];
|
||||
box.GetCorners(corners);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (PlaneDot(frustrumPlanes[i], corners[0]) < 0 &&
|
||||
PlaneDot(frustrumPlanes[i], corners[1]) < 0 &&
|
||||
PlaneDot(frustrumPlanes[i], corners[2]) < 0 &&
|
||||
PlaneDot(frustrumPlanes[i], corners[3]) < 0 &&
|
||||
PlaneDot(frustrumPlanes[i], corners[4]) < 0 &&
|
||||
PlaneDot(frustrumPlanes[i], corners[5]) < 0 &&
|
||||
PlaneDot(frustrumPlanes[i], corners[6]) < 0 &&
|
||||
PlaneDot(frustrumPlanes[i], corners[7]) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BoxInFrustum(const LifeMath::float3* corners) const
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (PlaneDot(frustrumPlanes[i], corners[0]) < 0 &&
|
||||
PlaneDot(frustrumPlanes[i], corners[1]) < 0 &&
|
||||
PlaneDot(frustrumPlanes[i], corners[2]) < 0 &&
|
||||
PlaneDot(frustrumPlanes[i], corners[3]) < 0 &&
|
||||
PlaneDot(frustrumPlanes[i], corners[4]) < 0 &&
|
||||
PlaneDot(frustrumPlanes[i], corners[5]) < 0 &&
|
||||
PlaneDot(frustrumPlanes[i], corners[6]) < 0 &&
|
||||
PlaneDot(frustrumPlanes[i], corners[7]) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const LifeMath::float3* GetCorners()
|
||||
{
|
||||
LifeMath::float4x4 ivp;
|
||||
ivp = LifeMath::Mat4x4Invert(&vp);
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
LifeMath::Vec3TransformCoordinate(baseCorners[i], ivp, corners[i]);
|
||||
}
|
||||
return corners;
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif // Frustum_h__
|
||||
Reference in New Issue
Block a user