Files

204 lines
4.1 KiB
C++
Raw Permalink Normal View History

2025-05-13 02:46:21 +03:00
#ifndef Light_h__
#define Light_h__
#include "IGraphicsNode.h"
#include "math/Vector3D.h"
#include "math/Vector4D.h"
#include "camera/Frustum.h"
namespace LifeGraphics
{
enum LIGHT_TYPE
{
LT_POINT = 0,
LT_SPOT = 1,
LT_DIRECTIONAL = 2
};
class Light : public IGraphicsNode
{
public:
Light(LIGHT_TYPE lt)
: range(1), innerAngle(0.5f), outerAngle(0.6f), direction(0.0f, -1.0f, 0.0f),
position(0.0f,0.0f, 0.0f), up(0.0f, 1.0f, 0.0f), color(1.0f, 0.0f, 1.0f),
intensity(1.0f), isMatrixValid(false), castShadows(false)
{
lightType = lt;
}
Light()
: lightType(LT_POINT), range(1), innerAngle(0.5f), outerAngle(0.6f), direction(0.0f, -1.0f, 0.0f),
position(0.0f,0.0f, 0.0f), up(0.0f, 1.0f, 0.0f), color(1.0f, 0.0f, 1.0f),
intensity(1.0f), isMatrixValid(false), castShadows(false)
{
}
~Light()
{
}
NodeType getType()
{
return NT_LIGHT;
}
void setDirection(const LifeMath::float3& dir)
{
direction = dir;
isMatrixValid = false;
//this->bSphere.center = this->_position;
//this->bSphere.radius = this->range;
}
const LifeMath::float4x4& getMatrix()
{
fixupTransform();
return matrix;
}
const LifeMath::float4x4& getView()
{
fixupTransform();
return mView;
}
const LifeMath::float4x4& getProj()
{
fixupTransform();
return mProj;
}
LifeMath::float3 getDirection()
{
fixupTransform();
return direction;
}
LifeMath::float3 getPosition()
{
fixupTransform();
return position;
}
void setInnerAngle(float angle)
{
innerAngle = angle;
if(innerAngle > 3.1415f)
innerAngle = 3.1415f;
isMatrixValid = false;
}
float getInnerAngle()
{
return innerAngle;
}
void setOuterAngle(float angle)
{
outerAngle = angle;
if(outerAngle<innerAngle)
outerAngle = innerAngle;
isMatrixValid = false;
}
float getOuterAngle()
{
return outerAngle;
}
void setRange(float _range)
{
range = _range;
this->bSphere.radius = this->range;
isMatrixValid = false;
}
float getRange()
{
return range;
}
void update(float dt)
{
fixupTransform();
}
LifeMath::float4x4 getMeshMatrix()
{
float baseRadius = tanf(outerAngle * 0.5f) * range * 1.1f;
LifeMath::float4x4 b;
Mat4x4Scaling(baseRadius, baseRadius, range, b);
LifeMath::float3 right;
LifeMath::float3 orthoUp;
LifeMath::float3 dir = direction - position;
LifeMath::Vec3Normalize(&dir);
LifeMath::Vec3Cross(up, dir, right);
LifeMath::Vec3Cross(dir, right, orthoUp);
LifeMath::Vec3Normalize(&orthoUp);
LifeMath::float4x4 r;
Mat4x4Identity(&r);
r.M11 = right.X;
r.M12 = right.Y;
r.M13 = right.Z;
r.M21 = orthoUp.X;
r.M22 = orthoUp.Y;
r.M23 = orthoUp.Z;
r.M31 = dir.X;
r.M32 = dir.Y;
r.M33 = dir.Z;
LifeMath::float3 pos = transform->GetPosition();
r.M41 = pos.X;
r.M42 = pos.Y;
r.M43 = pos.Z;
return b * r;
}
Frustum* getFrustum()
{
if(!isMatrixValid)
computeMatrix();
return &frustum;
}
LIGHT_TYPE lightType;
LifeMath::float3 color;
float specularPower;
float intensity;
bool castShadows;
private:
void fixupTransform()
{
if(position!= transform->GetPosition())
{
position = transform->GetPosition();
isMatrixValid = false;
this->bSphere.center = position;
this->bSphere.radius = range;
}
if(!isMatrixValid)
{
computeMatrix();
}
}
void computeMatrix()
{
LifeMath::float3 dir = direction - position;
LifeMath::Vec3Normalize(&dir);
float angle = LifeMath::Vec3Dot(&up, &dir);
if((angle>0.9f) | (angle<-0.9f))
up = LifeMath::float3(0.0f,0.0f,1.0f);
else
up = LifeMath::float3(0.0f,1.0f,0.0f);
LifeMath::Mat4x4LookAtLH(position,direction,up,mView);
LifeMath::Mat4x4PerspectiveFOV(outerAngle,1.0f,0.1f,range, mProj);
matrix = mView * mProj;
frustum.UpdateFrustum(matrix);
isMatrixValid = true;
}
LifeMath::float3 up;
bool isMatrixValid;
LifeMath::float4x4 matrix;
LifeMath::float4x4 mView;
LifeMath::float4x4 mProj;
float range;
LifeMath::float3 direction;
LifeMath::float3 position;
float innerAngle;
float outerAngle;
Frustum frustum;
};
}
#endif // Light_h__