#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(outerAnglebSphere.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__