This commit is contained in:
2025-05-13 02:46:21 +03:00
parent 143e16692e
commit 86914b7fcc
610 changed files with 92343 additions and 2 deletions
+329
View File
@@ -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__
+186
View File
@@ -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__