Use a matrix to store the light transform.

This commit is contained in:
Leonardo Zide 2023-09-04 20:53:34 -07:00
parent 86327196c2
commit 6a1df617e8
7 changed files with 211 additions and 635 deletions

View file

@ -652,7 +652,7 @@ void lcModel::LoadLDraw(QIODevice& Device, Project* Project)
else if (Token == QLatin1String("LIGHT"))
{
if (!Light)
Light = new lcLight(lcVector3(0.0f, 0.0f, 0.0f), lcVector3(0.0f, 0.0f, 0.0f), lcLightType::Point);
Light = new lcLight(lcVector3(0.0f, 0.0f, 0.0f), lcLightType::Point);
if (Light->ParseLDrawLine(LineStream))
{
@ -2224,8 +2224,14 @@ lcMatrix33 lcModel::GetRelativeRotation() const
{
const lcObject* Focus = GetFocusObject();
if (Focus && Focus->IsPiece())
if (Focus)
{
if (Focus->IsPiece())
return ((lcPiece*)Focus)->GetRelativeRotation();
if (Focus->IsLight())
return ((lcLight*)Focus)->GetRelativeRotation();
}
}
return lcMatrix33Identity();
@ -2739,6 +2745,16 @@ void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector
Moved = true;
}
}
for (lcLight* Light : mLights)
{
if (Light->IsSelected())
{
Light->MoveSelected(mCurrentStep, gMainWindow->GetAddKeys(), TransformedPieceDistance);
Light->UpdatePosition(mCurrentStep);
Moved = true;
}
}
}
}
@ -2755,16 +2771,6 @@ void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector
Moved = true;
}
}
for (lcLight* Light : mLights)
{
if (Light->IsSelected())
{
Light->MoveSelected(mCurrentStep, gMainWindow->GetAddKeys(), TransformedObjectDistance);
Light->UpdatePosition(mCurrentStep);
Moved = true;
}
}
}
if (Moved && Update)
@ -2842,7 +2848,7 @@ void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool
{
lcLight* Light = (lcLight*)Object;
Light->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, WorldToFocusMatrix);
Light->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, Center, WorldToFocusMatrix);
Light->UpdatePosition(mCurrentStep);
Rotated = true;
}
@ -2896,7 +2902,7 @@ void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool
RelativeRotationMatrix = RotationMatrix;
}
Light->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, WorldToFocusMatrix);
Light->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, Center, WorldToFocusMatrix);
Light->UpdatePosition(mCurrentStep);
Rotated = true;
}
@ -3328,12 +3334,6 @@ bool lcModel::GetMoveRotateTransform(lcVector3& Center, lcMatrix33& RelativeRota
Center += Light->GetSectionPosition(LC_LIGHT_SECTION_POSITION);
NumSelected++;
if (!Light->IsPointLight())
{
Center += Light->GetSectionPosition(LC_LIGHT_SECTION_TARGET);
NumSelected++;
}
}
if (NumSelected)
@ -4250,29 +4250,18 @@ void lcModel::InsertPieceToolClicked(const lcMatrix44& WorldMatrix)
SaveCheckpoint(tr("Insert"));
}
void lcModel::PointLightToolClicked(const lcVector3& Position)
void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType LightType)
{
lcLight* Light = new lcLight(Position, lcVector3(0.0f, 0.0f, 0.0f), lcLightType::Point);
lcLight* Light = new lcLight(Position, LightType);
Light->CreateName(mLights);
mLights.Add(Light);
ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_POSITION, false);
SaveCheckpoint(tr("New Point Light"));
}
void lcModel::BeginDirectionalLightTool(const lcVector3& Position, const lcVector3& Target, lcLightType LightType)
{
lcLight* Light = new lcLight(Position, Target, LightType);
Light->CreateName(mLights);
mLights.Add(Light);
mMouseToolDistance = Target;
ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_TARGET, false);
switch (LightType)
{
case lcLightType::Point:
SaveCheckpoint(tr("New Point Light"));
break;
case lcLightType::Spot:
@ -4292,19 +4281,6 @@ void lcModel::BeginDirectionalLightTool(const lcVector3& Position, const lcVecto
}
}
void lcModel::UpdateDirectionalLightTool(const lcVector3& Position)
{
lcLight* Light = mLights[mLights.GetSize() - 1];
Light->MoveSelected(1, false, Position - mMouseToolDistance);
Light->UpdatePosition(1);
mMouseToolDistance = Position;
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
}
void lcModel::BeginCameraTool(const lcVector3& Position, const lcVector3& Target)
{
lcCamera* Camera = new lcCamera(Position[0], Position[1], Position[2], Target[0], Target[1], Target[2]);

View file

@ -329,10 +329,7 @@ public:
void BeginMouseTool();
void EndMouseTool(lcTool Tool, bool Accept);
void InsertPieceToolClicked(const lcMatrix44& WorldMatrix);
void PointLightToolClicked(const lcVector3& Position);
void BeginDirectionalLightTool(const lcVector3& Position, const lcVector3& Target, lcLightType LightType);
void UpdateDirectionalLightTool(const lcVector3& Position);
void BeginSpotLightTool(const lcVector3& Position, const lcVector3& Target);
void InsertLightToolClicked(const lcVector3& Position, lcLightType LightType);
void BeginCameraTool(const lcVector3& Position, const lcVector3& Target);
void UpdateCameraTool(const lcVector3& Position);
void UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag);

View file

@ -2272,29 +2272,13 @@ void lcView::StartTracking(lcTrackButton TrackButton)
lcTool Tool = GetCurrentTool();
lcModel* ActiveModel = GetActiveModel();
auto AddLight = [this, ActiveModel](lcLightType LightType)
{
lcVector3 Position = GetCameraLightInsertPosition();
lcVector3 Target = Position + lcVector3(0.1f, 0.1f, 0.1f);
ActiveModel->BeginDirectionalLightTool(Position, Target, LightType);
};
switch (Tool)
{
case lcTool::Insert:
case lcTool::PointLight:
break;
case lcTool::Spotlight:
AddLight(lcLightType::Spot);
break;
case lcTool::DirectionalLight:
AddLight(lcLightType::Directional);
break;
case lcTool::AreaLight:
AddLight(lcLightType::Area);
break;
case lcTool::Camera:
@ -2448,6 +2432,17 @@ void lcView::OnButtonDown(lcTrackButton TrackButton)
lcModel* ActiveModel = GetActiveModel();
mToolClicked = false;
auto AddLight = [this, ActiveModel](lcLightType LightType)
{
ActiveModel->InsertLightToolClicked(GetCameraLightInsertPosition(), LightType);
if ((mMouseModifiers & Qt::ControlModifier) == 0)
gMainWindow->SetTool(lcTool::Select);
mToolClicked = true;
UpdateTrackTool();
};
switch (mTrackTool)
{
case lcTrackTool::None:
@ -2471,20 +2466,21 @@ void lcView::OnButtonDown(lcTrackButton TrackButton)
break;
case lcTrackTool::PointLight:
{
ActiveModel->PointLightToolClicked(GetCameraLightInsertPosition());
if ((mMouseModifiers & Qt::ControlModifier) == 0)
gMainWindow->SetTool(lcTool::Select);
mToolClicked = true;
UpdateTrackTool();
}
AddLight(lcLightType::Point);
break;
case lcTrackTool::Spotlight:
AddLight(lcLightType::Spot);
break;
case lcTrackTool::DirectionalLight:
AddLight(lcLightType::Directional);
break;
case lcTrackTool::AreaLight:
AddLight(lcLightType::Area);
break;
case lcTrackTool::Camera:
StartTracking(TrackButton);
break;
@ -2719,12 +2715,9 @@ void lcView::OnMouseMove()
case lcTrackTool::None:
case lcTrackTool::Insert:
case lcTrackTool::PointLight:
break;
case lcTrackTool::Spotlight:
case lcTrackTool::DirectionalLight:
case lcTrackTool::AreaLight:
ActiveModel->UpdateDirectionalLightTool(GetCameraLightInsertPosition());
break;
case lcTrackTool::Camera:

View file

@ -9,7 +9,7 @@
#include "lc_context.h"
#define LC_LIGHT_SPHERE_RADIUS 5.0f
#define LC_LIGHT_TARGET_EDGE 5.0f
#define LC_LIGHT_TARGET_EDGE 2.0f
#define LC_LIGHT_SPOT_CONE_HEIGHT 10.0f
#define LC_LIGHT_SPOT_CONE_RADIUS 7.5f
#define LC_LIGHT_DIRECTIONAL_RADIUS 5.0f
@ -19,27 +19,10 @@
static const std::array<QLatin1String, static_cast<int>(lcLightType::Count)> gLightTypes = { QLatin1String("POINT"), QLatin1String("SPOT"), QLatin1String("DIRECTIONAL"), QLatin1String("AREA") };
lcLight::lcLight(const lcVector3& Position, const lcVector3& TargetPosition, lcLightType LightType)
lcLight::lcLight(const lcVector3& Position, lcLightType LightType)
: lcObject(lcObjectType::Light), mLightType(LightType)
{
mState = 0;
mPosition = Position;
mTargetPosition = TargetPosition;
mUpVector = lcVector3(0, 0, 1);
if (IsAreaLight())
{
lcVector3 FrontVector = lcNormalize(TargetPosition - Position), SideVector;
if (FrontVector == mUpVector)
SideVector = lcVector3(1, 0, 0);
else
SideVector = lcCross(FrontVector, mUpVector);
mUpVector = lcCross(SideVector, FrontVector);
mUpVector.Normalize();
}
mWorldMatrix = lcMatrix44Translation(Position);
mPOVRayLight = false;
mEnableCutoff = false;
@ -58,10 +41,10 @@ lcLight::lcLight(const lcVector3& Position, const lcVector3& TargetPosition, lcL
mAreaSize = lcVector2(200.0f, 200.0f);
mLightShape = LC_LIGHT_SHAPE_SQUARE;
mPositionKeys.ChangeKey(mPosition, 1, true);
mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true);
mUpVectorKeys.ChangeKey(mUpVector, 1, true);
mPositionKeys.ChangeKey(mWorldMatrix.GetTranslation(), 1, true);
mRotationKeys.ChangeKey(lcMatrix33(mWorldMatrix), 1, true);
mColorKeys.ChangeKey(mColor, 1, true);
mAttenuationKeys.ChangeKey(mAttenuation, 1, true);
mLightFactorKeys.ChangeKey(mLightFactor, 1, true);
mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true);
@ -109,25 +92,20 @@ void lcLight::SaveLDraw(QTextStream& Stream) const
if (!mCastShadow)
Stream << QLatin1String("0 !LEOCAD LIGHT SHADOWLESS") << LineEnding;
const float* Matrix = mWorldMatrix;
const float Numbers[12] = { Matrix[12], -Matrix[14], Matrix[13], Matrix[0], -Matrix[8], Matrix[4], -Matrix[2], Matrix[10], -Matrix[6], Matrix[1], -Matrix[9], Matrix[5] };
if (mPositionKeys.GetSize() > 1)
mPositionKeys.SaveKeysLDraw(Stream, "LIGHT POSITION_KEY ");
else
Stream << QLatin1String("0 !LEOCAD LIGHT POSITION ") << mPosition[0] << ' ' << mPosition[1] << ' ' << mPosition[2] << LineEnding;
Stream << QLatin1String("0 !LEOCAD LIGHT POSITION ") << Numbers[0] << ' ' << Numbers[1] << ' ' << Numbers[2] << LineEnding;
if (mLightType != lcLightType::Point)
if (!IsPointLight())
{
if (mTargetPositionKeys.GetSize() > 1)
mTargetPositionKeys.SaveKeysLDraw(Stream, "LIGHT TARGET_POSITION_KEY ");
if (mRotationKeys.GetSize() > 1)
mRotationKeys.SaveKeysLDraw(Stream, "LIGHT ROTATION_KEY ");
else
Stream << QLatin1String("0 !LEOCAD LIGHT TARGET_POSITION ") << mTargetPosition[0] << ' ' << mTargetPosition[1] << ' ' << mTargetPosition[2] << LineEnding;
}
if (mLightType == lcLightType::Area)
{
if (mUpVectorKeys.GetSize() > 1)
mUpVectorKeys.SaveKeysLDraw(Stream, "LIGHT UP_VECTOR_KEY ");
else
Stream << QLatin1String("0 !LEOCAD LIGHT UP_VECTOR ") << mUpVector[0] << ' ' << mUpVector[1] << ' ' << mUpVector[2] << LineEnding;
Stream << QLatin1String("0 !LEOCAD LIGHT ROTATION ") << Numbers[3] << ' ' << Numbers[4] << ' ' << Numbers[5] << ' ' << Numbers[6] << ' ' << Numbers[7] << ' ' << Numbers[8] << ' ' << Numbers[9] << ' ' << Numbers[10] << ' ' << Numbers[11] << LineEnding;
}
if (mColorKeys.GetSize() > 1)
@ -345,25 +323,38 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream)
if (Token == QLatin1String("POSITION"))
{
Stream >> mPosition[0] >> mPosition[1] >> mPosition[2];
mPositionKeys.ChangeKey(mPosition, 1, true);
lcVector3 Position;
Stream >> Position[0] >> Position[1] >> Position[2];
Position = lcVector3LDrawToLeoCAD(Position);
mWorldMatrix.SetTranslation(Position);
mPositionKeys.ChangeKey(Position, 1, true);
}
else if (Token == QLatin1String("POSITION_KEY"))
mPositionKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("TARGET_POSITION"))
mPositionKeys.LoadKeysLDraw(Stream); // todo: convert from ldraw
else if (Token == QLatin1String("ROTATION"))
{
Stream >> mTargetPosition[0] >> mTargetPosition[1] >> mTargetPosition[2];
mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true);
float Numbers[9];
for (int TokenIdx = 0; TokenIdx < 9; TokenIdx++)
Stream >> Numbers[TokenIdx];
float* Matrix = mWorldMatrix;
Matrix[0] = Numbers[0];
Matrix[8] = -Numbers[1];
Matrix[4] = Numbers[2];
Matrix[2] = -Numbers[3];
Matrix[10] = Numbers[4];
Matrix[6] = -Numbers[5];
Matrix[1] = Numbers[6];
Matrix[9] = -Numbers[7];
Matrix[5] = Numbers[8];
mRotationKeys.ChangeKey(lcMatrix33(mWorldMatrix), 1, true);
}
else if (Token == QLatin1String("TARGET_POSITION_KEY"))
mTargetPositionKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("UP_VECTOR"))
{
Stream >> mUpVector[0] >> mUpVector[1] >> mUpVector[2];
mUpVectorKeys.ChangeKey(mUpVector, 1, true);
}
else if (Token == QLatin1String("UP_VECTOR_KEY"))
mUpVectorKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("ROTATION_KEY"))
mRotationKeys.LoadKeysLDraw(Stream); // todo: convert from ldraw
else if (Token == QLatin1String("COLOR"))
{
Stream >> mColor[0] >> mColor[1] >> mColor[2];
@ -503,10 +494,6 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream)
mLightSpecularKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("CUTOFF_DISTANCE_KEY"))
mSpotCutoffKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("POSITION_KEY"))
mPositionKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("TARGET_POSITION_KEY"))
mTargetPositionKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("NAME"))
{
mName = Stream.readAll().trimmed();
@ -564,21 +551,13 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream)
void lcLight::CompareBoundingBox(lcVector3& Min, lcVector3& Max)
{
const lcVector3 Points[2] =
{
mPosition, mTargetPosition
};
for (int i = 0; i < (IsPointLight() ? 1 : 2); i++)
{
const lcVector3& Point = Points[i];
const lcVector3 Point = mWorldMatrix.GetTranslation();
// TODO: this should check the entire mesh
Min = lcMin(Point, Min);
Max = lcMax(Point, Max);
}
}
void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property)
{
@ -655,7 +634,7 @@ void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const
{
float Distance;
if (lcSphereRayMinIntersectDistance(mPosition, LC_LIGHT_SPHERE_RADIUS, ObjectRayTest.Start, ObjectRayTest.End, &Distance) && (Distance < ObjectRayTest.Distance))
if (lcSphereRayMinIntersectDistance(mWorldMatrix.GetTranslation(), LC_LIGHT_SPHERE_RADIUS, ObjectRayTest.Start, ObjectRayTest.End, &Distance) && (Distance < ObjectRayTest.Distance))
{
ObjectRayTest.ObjectSection.Object = const_cast<lcLight*>(this);
ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_POSITION;
@ -667,10 +646,11 @@ void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const
if (mLightType == lcLightType::Spot)
{
const lcVector3 Direction = -lcVector3(mWorldMatrix[2]);
const lcVector3 Position = mWorldMatrix.GetTranslation() - Direction * LC_LIGHT_SPOT_CONE_HEIGHT;
float Distance;
lcVector3 Direction = lcNormalize(mTargetPosition - mPosition);
if (lcConeRayMinIntersectDistance(mPosition - Direction * LC_LIGHT_SPOT_CONE_HEIGHT, Direction, LC_LIGHT_SPOT_CONE_RADIUS, LC_LIGHT_SPOT_CONE_HEIGHT, ObjectRayTest.Start, ObjectRayTest.End, &Distance) && (Distance < ObjectRayTest.Distance))
if (lcConeRayMinIntersectDistance(Position, Direction, LC_LIGHT_SPOT_CONE_RADIUS, LC_LIGHT_SPOT_CONE_HEIGHT, ObjectRayTest.Start, ObjectRayTest.End, &Distance) && (Distance < ObjectRayTest.Distance))
{
ObjectRayTest.ObjectSection.Object = const_cast<lcLight*>(this);
ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_POSITION;
@ -679,32 +659,16 @@ void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const
}
else if (mLightType == lcLightType::Area)
{
lcVector3 FrontVector = mTargetPosition - mPosition;
lcVector4 Plane(FrontVector, -lcDot(FrontVector, mPosition));
const lcVector3 Direction = -lcVector3(mWorldMatrix[2]);
const lcVector3 Position = mWorldMatrix.GetTranslation();
const lcVector4 Plane(Direction, -lcDot(Direction, Position));
lcVector3 Intersection;
if (lcLineSegmentPlaneIntersection(&Intersection, ObjectRayTest.Start, ObjectRayTest.End, Plane))
{
lcVector3 UpVector(1, 1, 1);
if (fabs(FrontVector[0]) < fabs(FrontVector[1]))
{
if (fabs(FrontVector[0]) < fabs(FrontVector[2]))
UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]);
else
UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]);
}
else
{
if (fabs(FrontVector[1]) < fabs(FrontVector[2]))
UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]);
else
UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]);
}
lcVector3 XAxis = lcNormalize(lcCross(FrontVector, UpVector));
lcVector3 YAxis = lcNormalize(lcCross(FrontVector, XAxis));
lcVector3 IntersectionDirection = Intersection - mPosition;
const lcVector3 XAxis = lcVector3(mWorldMatrix[0]);
const lcVector3 YAxis = lcVector3(mWorldMatrix[1]);
lcVector3 IntersectionDirection = Intersection - Position;
float x = lcDot(IntersectionDirection, XAxis);
float y = lcDot(IntersectionDirection, YAxis);
@ -723,8 +687,9 @@ void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const
}
}
lcVector3 Start = lcMul31(ObjectRayTest.Start, mWorldLight);
lcVector3 End = lcMul31(ObjectRayTest.End, mWorldLight);
const lcMatrix44 InverseWorldMatrix = lcMatrix44AffineInverse(mWorldMatrix);
lcVector3 Start = lcMul31(ObjectRayTest.Start, InverseWorldMatrix);
lcVector3 End = lcMul31(ObjectRayTest.End, InverseWorldMatrix);
float Distance;
lcVector3 Plane;
@ -739,43 +704,6 @@ void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const
ObjectRayTest.PieceInfoRayTest.Plane = Plane;
}
}
lcVector3 Min = lcVector3(-LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE);
lcVector3 Max = lcVector3( LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE);
lcMatrix44 WorldTarget = mWorldLight;
WorldTarget.SetTranslation(lcMul30(-mTargetPosition, WorldTarget));
Start = lcMul31(ObjectRayTest.Start, WorldTarget);
End = lcMul31(ObjectRayTest.End, WorldTarget);
if (lcBoundingBoxRayIntersectDistance(Min, Max, Start, End, &Distance, nullptr, &Plane) && (Distance < ObjectRayTest.Distance))
{
ObjectRayTest.ObjectSection.Object = const_cast<lcLight*>(this);
ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_TARGET;
ObjectRayTest.Distance = Distance;
ObjectRayTest.PieceInfoRayTest.Plane = Plane;
}
if (IsAreaLight())
{
const lcMatrix44 LightWorld = lcMatrix44AffineInverse(mWorldLight);
const lcVector3 UpVectorPosition = lcMul31(lcVector3(0, 25, 0), LightWorld);
lcMatrix44 WorldLight = mWorldLight;
WorldLight.SetTranslation(lcMul30(-UpVectorPosition, WorldLight));
Start = lcMul31(ObjectRayTest.Start, WorldLight);
End = lcMul31(ObjectRayTest.End, WorldLight);
if (lcBoundingBoxRayIntersectDistance(Min, Max, Start, End, &Distance, nullptr, &Plane) && (Distance < ObjectRayTest.Distance))
{
ObjectRayTest.ObjectSection.Object = const_cast<lcLight*>(this);
ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_UPVECTOR;
ObjectRayTest.Distance = Distance;
ObjectRayTest.PieceInfoRayTest.Plane = Plane;
}
}
}
void lcLight::BoxTest(lcObjectBoxTest& ObjectBoxTest) const
@ -783,7 +711,7 @@ void lcLight::BoxTest(lcObjectBoxTest& ObjectBoxTest) const
if (IsPointLight())
{
for (int PlaneIdx = 0; PlaneIdx < 6; PlaneIdx++)
if (lcDot3(mPosition, ObjectBoxTest.Planes[PlaneIdx]) + ObjectBoxTest.Planes[PlaneIdx][3] > LC_LIGHT_SPHERE_RADIUS)
if (lcDot3(mWorldMatrix.GetTranslation(), ObjectBoxTest.Planes[PlaneIdx]) + ObjectBoxTest.Planes[PlaneIdx][3] > LC_LIGHT_SPHERE_RADIUS)
return;
ObjectBoxTest.Objects.Add(const_cast<lcLight*>(this));
@ -797,26 +725,8 @@ void lcLight::BoxTest(lcObjectBoxTest& ObjectBoxTest) const
for (int PlaneIdx = 0; PlaneIdx < 6; PlaneIdx++)
{
const lcVector3 Normal = lcMul30(ObjectBoxTest.Planes[PlaneIdx], mWorldLight);
LocalPlanes[PlaneIdx] = lcVector4(Normal, ObjectBoxTest.Planes[PlaneIdx][3] - lcDot3(mWorldLight[3], Normal));
}
if (lcBoundingBoxIntersectsVolume(Min, Max, LocalPlanes))
{
ObjectBoxTest.Objects.Add(const_cast<lcLight*>(this));
return;
}
Min = lcVector3(-LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE);
Max = lcVector3(LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE);
lcMatrix44 WorldTarget = mWorldLight;
WorldTarget.SetTranslation(lcMul30(-mTargetPosition, WorldTarget));
for (int PlaneIdx = 0; PlaneIdx < 6; PlaneIdx++)
{
const lcVector3 Normal = lcMul30(ObjectBoxTest.Planes[PlaneIdx], WorldTarget);
LocalPlanes[PlaneIdx] = lcVector4(Normal, ObjectBoxTest.Planes[PlaneIdx][3] - lcDot3(WorldTarget[3], Normal));
const lcVector3 Normal = lcMul30(ObjectBoxTest.Planes[PlaneIdx], mWorldMatrix);
LocalPlanes[PlaneIdx] = lcVector4(Normal, ObjectBoxTest.Planes[PlaneIdx][3] - lcDot3(mWorldMatrix[3], Normal));
}
if (lcBoundingBoxIntersectsVolume(Min, Max, LocalPlanes))
@ -830,36 +740,15 @@ void lcLight::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance)
{
if (IsSelected(LC_LIGHT_SECTION_POSITION))
{
mPosition += Distance;
mPositionKeys.ChangeKey(mPosition, Step, AddKey);
}
const lcVector3 Position = mWorldMatrix.GetTranslation() + Distance;
if (IsSelected(LC_LIGHT_SECTION_TARGET))
{
mTargetPosition += Distance;
mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey);
}
else if (IsSelected(LC_LIGHT_SECTION_UPVECTOR))
{
mUpVector += Distance;
mUpVector.Normalize();
mUpVectorKeys.ChangeKey(mUpVector, Step, AddKey);
}
SetPosition(Position, Step, AddKey);
if (IsAreaLight())
{
const lcVector3 FrontVector(mTargetPosition - mPosition);
lcVector3 SideVector = lcCross(FrontVector, mUpVector);
if (fabsf(lcDot(mUpVector, SideVector)) > 0.99f)
SideVector = lcVector3(1, 0, 0);
mUpVector = lcCross(SideVector, FrontVector);
mUpVector.Normalize();
mWorldMatrix.SetTranslation(Position);
}
}
void lcLight::Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcMatrix33& RotationFrame)
void lcLight::Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcVector3& Center, const lcMatrix33& RotationFrame)
{
if (IsPointLight())
return;
@ -867,38 +756,21 @@ void lcLight::Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix,
if (GetFocusSection() != LC_LIGHT_SECTION_POSITION)
return;
// lcVector3 Direction = mTargetPosition - mPosition;
//
// Direction = lcMul(Direction, RotationMatrix);
//
// mTargetPosition = mPosition + Direction;
// mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey);
const lcMatrix33 LocalToWorldMatrix = lcMatrix33AffineInverse(lcMatrix33(mWorldLight));
lcVector3 Distance = mWorldMatrix.GetTranslation() - Center;
const lcMatrix33 LocalToWorldMatrix = lcMatrix33(mWorldMatrix);
const lcMatrix33 LocalToFocusMatrix = lcMul(LocalToWorldMatrix, RotationFrame);
lcMatrix33 NewLocalToWorldMatrix = lcMul(LocalToFocusMatrix, RotationMatrix);
const lcMatrix33 WorldToLocalMatrix = lcMatrix33AffineInverse(LocalToWorldMatrix);
Distance = lcMul(Distance, WorldToLocalMatrix);
Distance = lcMul(Distance, NewLocalToWorldMatrix);
NewLocalToWorldMatrix.Orthonormalize();
lcVector3 Target = lcMul(lcVector3(0.0f, 0.0f, lcLength(mTargetPosition - mPosition)), NewLocalToWorldMatrix);
mTargetPosition = mPosition - Target;
mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey);
if (IsAreaLight())
{
const lcVector3 FrontVector(mTargetPosition - mPosition);
lcVector3 SideVector = lcCross(FrontVector, mUpVector);
if (fabsf(lcDot(mUpVector, SideVector)) > 0.99f)
SideVector = lcVector3(1, 0, 0);
mUpVector = lcCross(SideVector, FrontVector);
mUpVector.Normalize();
}
SetPosition(Center + Distance, Step, AddKey);
SetRotation(NewLocalToWorldMatrix, Step, AddKey);
}
void lcLight::SetLightType(lcLightType LightType)
@ -922,8 +794,7 @@ void lcLight::SetCastShadow(bool CastShadow)
void lcLight::InsertTime(lcStep Start, lcStep Time)
{
mPositionKeys.InsertTime(Start, Time);
mTargetPositionKeys.InsertTime(Start, Time);
mUpVectorKeys.InsertTime(Start, Time);
mRotationKeys.InsertTime(Start, Time);
mColorKeys.InsertTime(Start, Time);
mAttenuationKeys.InsertTime(Start, Time);
mLightFactorKeys.InsertTime(Start, Time);
@ -940,8 +811,7 @@ void lcLight::InsertTime(lcStep Start, lcStep Time)
void lcLight::RemoveTime(lcStep Start, lcStep Time)
{
mPositionKeys.RemoveTime(Start, Time);
mTargetPositionKeys.RemoveTime(Start, Time);
mUpVectorKeys.RemoveTime(Start, Time);
mRotationKeys.RemoveTime(Start, Time);
mColorKeys.RemoveTime(Start, Time);
mAttenuationKeys.RemoveTime(Start, Time);
mLightFactorKeys.RemoveTime(Start, Time);
@ -957,9 +827,19 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time)
void lcLight::UpdatePosition(lcStep Step)
{
mPosition = mPositionKeys.CalculateKey(Step);
mTargetPosition = mTargetPositionKeys.CalculateKey(Step);
mUpVector = mUpVectorKeys.CalculateKey(Step);
const lcVector3 Position = mPositionKeys.CalculateKey(Step);
if (IsPointLight())
{
mWorldMatrix = lcMatrix44Translation(Position);
}
else
{
const lcMatrix33 Rotation = mRotationKeys.CalculateKey(Step);
mWorldMatrix = lcMatrix44(Rotation, Position);
}
mColor = mColorKeys.CalculateKey(Step);
mAttenuation = mAttenuationKeys.CalculateKey(Step);
mLightFactor = mLightFactorKeys.CalculateKey(Step);
@ -971,48 +851,6 @@ void lcLight::UpdatePosition(lcStep Step)
mSpotFalloff = mSpotFalloffKeys.CalculateKey(Step);
mSpotTightness = mSpotTightnessKeys.CalculateKey(Step);
mAreaGrid = mAreaGridKeys.CalculateKey(Step);
if (IsPointLight())
{
mWorldLight = lcMatrix44Identity();
mWorldLight.SetTranslation(-mPosition);
}
else if (IsAreaLight())
{
lcVector3 UpVector(0, 0, 1), FrontVector(mPosition), SideVector;
FrontVector.Normalize();
if (fabsf(lcDot(UpVector, FrontVector)) > 0.99f)
SideVector = lcVector3(-1, 0, 0);
else
SideVector = lcCross(FrontVector, UpVector);
UpVector = lcCross(SideVector, FrontVector);
UpVector.Normalize();
mUpVector = UpVector;
mWorldLight = lcMatrix44LookAt(mPosition, mTargetPosition, mUpVector);
}
else
{
lcVector3 FrontVector(mTargetPosition - mPosition);
lcVector3 UpVector(1, 1, 1);
if (fabs(FrontVector[0]) < fabs(FrontVector[1]))
{
if (fabs(FrontVector[0]) < fabs(FrontVector[2]))
UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]);
else
UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]);
}
else
{
if (fabs(FrontVector[1]) < fabs(FrontVector[2]))
UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]);
else
UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]);
}
mWorldLight = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector);
}
}
void lcLight::DrawInterface(lcContext* Context, const lcScene& Scene) const
@ -1045,34 +883,16 @@ void lcLight::DrawInterface(lcContext* Context, const lcScene& Scene) const
void lcLight::DrawPointLight(lcContext* Context) const
{
Context->SetWorldMatrix(lcMatrix44Translation(mPosition));
const lcPreferences& Preferences = lcGetPreferences();
if (IsFocused(LC_LIGHT_SECTION_POSITION))
{
const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor);
Context->SetColor(FocusedColor);
}
else if (IsSelected(LC_LIGHT_SECTION_POSITION))
{
const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor);
Context->SetColor(SelectedColor);
}
else
{
const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor);
Context->SetColor(LightColor);
}
SetupLightMatrix(Context);
DrawSphere(Context, LC_LIGHT_SPHERE_RADIUS);
}
void lcLight::DrawSpotLight(lcContext* Context) const
{
constexpr int ConeEdges = 8;
float TargetDistance = SetupLightMatrix(Context);
SetupLightMatrix(Context);
constexpr int ConeEdges = 8;
float Verts[(ConeEdges + 1) * 3];
float* CurVert = Verts;
@ -1103,6 +923,8 @@ void lcLight::DrawSpotLight(lcContext* Context) const
Context->DrawIndexedPrimitives(GL_LINES, (ConeEdges + 4) * 2, GL_UNSIGNED_SHORT, 0);
const float TargetDistance = 25.0f;
DrawTarget(Context, TargetDistance);
if (IsSelected())
@ -1111,16 +933,18 @@ void lcLight::DrawSpotLight(lcContext* Context) const
void lcLight::DrawDirectionalLight(lcContext* Context) const
{
float TargetDistance = SetupLightMatrix(Context);
SetupLightMatrix(Context);
DrawCylinder(Context, LC_LIGHT_DIRECTIONAL_RADIUS, LC_LIGHT_DIRECTIONAL_HEIGHT);
const float TargetDistance = 25.0f;
DrawTarget(Context, TargetDistance);
}
void lcLight::DrawAreaLight(lcContext* Context) const
{
float TargetDistance = SetupLightMatrix(Context);
SetupLightMatrix(Context);
if (mLightShape == LC_LIGHT_SHAPE_SQUARE || mLightShape == LC_LIGHT_SHAPE_RECTANGLE)
{
@ -1188,99 +1012,14 @@ void lcLight::DrawAreaLight(lcContext* Context) const
Context->DrawIndexedPrimitives(GL_LINES, (CircleEdges + 2) * 2, GL_UNSIGNED_SHORT, 0);
}
const float TargetDistance = 25.0f;
DrawTarget(Context, TargetDistance);
float Verts[10 * 3];
float* CurVert = Verts;
*CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = LC_LIGHT_TARGET_EDGE;
*CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = LC_LIGHT_TARGET_EDGE;
*CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = LC_LIGHT_TARGET_EDGE;
*CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = LC_LIGHT_TARGET_EDGE;
*CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = -LC_LIGHT_TARGET_EDGE;
*CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = -LC_LIGHT_TARGET_EDGE;
*CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = -LC_LIGHT_TARGET_EDGE;
*CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = -LC_LIGHT_TARGET_EDGE;
*CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f;
*CurVert++ = 0.0f; *CurVert++ = 25.0f; *CurVert++ = 0.0f;
Context->SetVertexBufferPointer(Verts);
Context->SetVertexFormatPosition(3);
const GLushort Indices[(12 + 1) * 2] =
{
0, 1, 1, 2, 2, 3, 3, 0,
4, 5, 5, 6, 6, 7, 7, 4,
0, 4, 1, 5, 2, 6, 3, 7,
8, 9
};
Context->SetIndexBufferPointer(Indices);
const lcPreferences& Preferences = lcGetPreferences();
const float LineWidth = Preferences.mLineWidth;
const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor);
if (IsSelected(LC_LIGHT_SECTION_UPVECTOR))
{
const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor);
const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor);
Context->SetLineWidth(2.0f * LineWidth);
if (IsFocused(LC_LIGHT_SECTION_UPVECTOR))
Context->SetColor(FocusedColor);
else
Context->SetColor(SelectedColor);
}
else
{
Context->SetLineWidth(LineWidth);
Context->SetColor(LightColor);
}
Context->DrawIndexedPrimitives(GL_LINES, 12 * 2, GL_UNSIGNED_SHORT, 0);
Context->SetLineWidth(LineWidth);
Context->SetColor(LightColor);
Context->DrawIndexedPrimitives(GL_LINES, 2, GL_UNSIGNED_SHORT, 12 * 2 * 2);
}
float lcLight::SetupLightMatrix(lcContext* Context) const
void lcLight::SetupLightMatrix(lcContext* Context) const
{
lcVector3 FrontVector(mTargetPosition - mPosition);
lcVector3 UpVector(1, 1, 1);
if (IsAreaLight())
{
UpVector = mUpVector;
}
else
{
if (fabs(FrontVector[0]) < fabs(FrontVector[1]))
{
if (fabs(FrontVector[0]) < fabs(FrontVector[2]))
UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]);
else
UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]);
}
else
{
if (fabs(FrontVector[1]) < fabs(FrontVector[2]))
UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]);
else
UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]);
}
}
lcMatrix44 LightMatrix = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector);
LightMatrix = lcMatrix44AffineInverse(LightMatrix);
LightMatrix.SetTranslation(lcVector3(0, 0, 0));
const lcMatrix44 LightViewMatrix = lcMul(LightMatrix, lcMatrix44Translation(mPosition));
Context->SetWorldMatrix(LightViewMatrix);
Context->SetWorldMatrix(mWorldMatrix);
const lcPreferences& Preferences = lcGetPreferences();
const float LineWidth = Preferences.mLineWidth;
@ -1304,8 +1043,6 @@ float lcLight::SetupLightMatrix(lcContext* Context) const
Context->SetLineWidth(LineWidth);
Context->SetColor(LightColor);
}
return FrontVector.Length();
}
void lcLight::DrawSphere(lcContext* Context, float Radius) const
@ -1455,34 +1192,7 @@ void lcLight::DrawTarget(lcContext* Context, float TargetDistance) const
Context->SetIndexBufferPointer(Indices);
const lcPreferences& Preferences = lcGetPreferences();
const float LineWidth = Preferences.mLineWidth;
const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor);
if (IsSelected(LC_LIGHT_SECTION_TARGET))
{
const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor);
const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor);
Context->SetLineWidth(2.0f * LineWidth);
if (IsFocused(LC_LIGHT_SECTION_TARGET))
Context->SetColor(FocusedColor);
else
Context->SetColor(SelectedColor);
}
else
{
Context->SetLineWidth(LineWidth);
Context->SetColor(LightColor);
}
Context->DrawIndexedPrimitives(GL_LINES, 12 * 2, GL_UNSIGNED_SHORT, 0);
Context->SetLineWidth(LineWidth);
Context->SetColor(LightColor);
Context->DrawIndexedPrimitives(GL_LINES, 2, GL_UNSIGNED_SHORT, 12 * 2 * 2);
Context->DrawIndexedPrimitives(GL_LINES, (12 + 1) * 2, GL_UNSIGNED_SHORT, 0);
}
void lcLight::DrawCone(lcContext* Context, float TargetDistance) const
@ -1525,13 +1235,10 @@ void lcLight::DrawCone(lcContext* Context, float TargetDistance) const
void lcLight::RemoveKeyFrames()
{
mPositionKeys.RemoveAll();
mPositionKeys.ChangeKey(mPosition, 1, true);
mPositionKeys.ChangeKey(mWorldMatrix.GetTranslation(), 1, true);
mTargetPositionKeys.RemoveAll();
mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true);
mUpVectorKeys.RemoveAll();
mUpVectorKeys.ChangeKey(mUpVector, 1, true);
mRotationKeys.RemoveAll();
mRotationKeys.ChangeKey(lcMatrix33(mWorldMatrix), 1, true);
mColorKeys.RemoveAll();
mColorKeys.ChangeKey(mColor, 1, true);

View file

@ -7,19 +7,13 @@
#define LC_LIGHT_DISABLED 0x0002
#define LC_LIGHT_POSITION_SELECTED 0x0010
#define LC_LIGHT_POSITION_FOCUSED 0x0020
#define LC_LIGHT_TARGET_SELECTED 0x0040
#define LC_LIGHT_TARGET_FOCUSED 0x0080
#define LC_LIGHT_UPVECTOR_SELECTED 0x0100
#define LC_LIGHT_UPVECTOR_FOCUSED 0x0200
#define LC_LIGHT_SELECTION_MASK (LC_LIGHT_POSITION_SELECTED | LC_LIGHT_TARGET_SELECTED | LC_LIGHT_UPVECTOR_SELECTED)
#define LC_LIGHT_FOCUS_MASK (LC_LIGHT_POSITION_FOCUSED | LC_LIGHT_TARGET_FOCUSED | LC_LIGHT_UPVECTOR_FOCUSED)
#define LC_LIGHT_SELECTION_MASK LC_LIGHT_POSITION_SELECTED
#define LC_LIGHT_FOCUS_MASK LC_LIGHT_POSITION_FOCUSED
enum lcLightSection
{
LC_LIGHT_SECTION_POSITION,
LC_LIGHT_SECTION_TARGET,
LC_LIGHT_SECTION_UPVECTOR
LC_LIGHT_SECTION_POSITION
};
enum class lcLightType
@ -77,7 +71,7 @@ struct lcLightProperties
class lcLight : public lcObject
{
public:
lcLight(const lcVector3& Position, const lcVector3& TargetPosition, lcLightType LightType);
lcLight(const lcVector3& Position, lcLightType LightType);
virtual ~lcLight() = default;
lcLight(const lcLight&) = delete;
@ -131,41 +125,15 @@ public:
case LC_LIGHT_SECTION_POSITION:
return (mState & LC_LIGHT_POSITION_SELECTED) != 0;
break;
case LC_LIGHT_SECTION_TARGET:
return (mState & LC_LIGHT_TARGET_SELECTED) != 0;
break;
case LC_LIGHT_SECTION_UPVECTOR:
return (mState & LC_LIGHT_UPVECTOR_SELECTED) != 0;
break;
}
return false;
}
void SetSelected(bool Selected) override
{
if (Selected)
{
switch (mLightType)
{
case lcLightType::Point:
mState |= LC_LIGHT_POSITION_SELECTED;
break;
case lcLightType::Spot:
case lcLightType::Directional:
mState |= LC_LIGHT_POSITION_SELECTED | LC_LIGHT_TARGET_SELECTED;
break;
case lcLightType::Area:
mState |= LC_LIGHT_POSITION_SELECTED | LC_LIGHT_TARGET_SELECTED | LC_LIGHT_UPVECTOR_SELECTED;
break;
case lcLightType::Count:
break;
}
}
else
mState &= ~(LC_LIGHT_SELECTION_MASK | LC_LIGHT_FOCUS_MASK);
}
@ -180,26 +148,6 @@ public:
else
mState &= ~(LC_LIGHT_POSITION_SELECTED | LC_LIGHT_POSITION_FOCUSED);
break;
case LC_LIGHT_SECTION_TARGET:
if (Selected)
{
if (!IsPointLight())
mState |= LC_LIGHT_TARGET_SELECTED;
}
else
mState &= ~(LC_LIGHT_TARGET_SELECTED | LC_LIGHT_TARGET_FOCUSED);
break;
case LC_LIGHT_SECTION_UPVECTOR:
if (Selected)
{
if (IsAreaLight())
mState |= LC_LIGHT_UPVECTOR_SELECTED;
}
else
mState &= ~(LC_LIGHT_UPVECTOR_SELECTED | LC_LIGHT_UPVECTOR_FOCUSED);
break;
}
}
@ -214,15 +162,6 @@ public:
{
case LC_LIGHT_SECTION_POSITION:
return (mState & LC_LIGHT_POSITION_FOCUSED) != 0;
break;
case LC_LIGHT_SECTION_TARGET:
return (mState & LC_LIGHT_TARGET_FOCUSED) != 0;
break;
case LC_LIGHT_SECTION_UPVECTOR:
return (mState & LC_LIGHT_UPVECTOR_FOCUSED) != 0;
break;
}
return false;
@ -238,26 +177,6 @@ public:
else
mState &= ~(LC_LIGHT_POSITION_SELECTED | LC_LIGHT_POSITION_FOCUSED);
break;
case LC_LIGHT_SECTION_TARGET:
if (Focused)
{
if (!IsPointLight())
mState |= LC_LIGHT_TARGET_SELECTED | LC_LIGHT_TARGET_FOCUSED;
}
else
mState &= ~(LC_LIGHT_TARGET_SELECTED | LC_LIGHT_TARGET_FOCUSED);
break;
case LC_LIGHT_SECTION_UPVECTOR:
if (Focused)
{
if (IsAreaLight())
mState |= LC_LIGHT_UPVECTOR_SELECTED | LC_LIGHT_UPVECTOR_FOCUSED;
}
else
mState &= ~(LC_LIGHT_UPVECTOR_SELECTED | LC_LIGHT_UPVECTOR_FOCUSED);
break;
}
}
@ -266,12 +185,6 @@ public:
if (mState & LC_LIGHT_POSITION_FOCUSED)
return LC_LIGHT_SECTION_POSITION;
if (!IsPointLight() && (mState & LC_LIGHT_TARGET_FOCUSED))
return LC_LIGHT_SECTION_TARGET;
if (IsAreaLight() && (mState & LC_LIGHT_UPVECTOR_FOCUSED))
return LC_LIGHT_SECTION_UPVECTOR;
return ~0U;
}
@ -285,9 +198,6 @@ public:
if (Section == LC_LIGHT_SECTION_POSITION)
return LC_OBJECT_TRANSFORM_MOVE_XYZ | LC_OBJECT_TRANSFORM_ROTATE_XYZ;
if (Section == LC_LIGHT_SECTION_TARGET || Section == LC_LIGHT_SECTION_UPVECTOR)
return LC_OBJECT_TRANSFORM_MOVE_XYZ;
return 0;
}
@ -296,47 +206,41 @@ public:
const quint32 Section = GetFocusSection();
if (Section == LC_LIGHT_SECTION_POSITION)
{
return lcMatrix33AffineInverse(lcMatrix33(mWorldLight));
}
return lcMatrix33(mWorldMatrix);
else
{
return lcMatrix33Identity();
}
}
lcVector3 GetSectionPosition(quint32 Section) const override
{
switch (Section)
{
case LC_LIGHT_SECTION_POSITION:
return mPosition;
Q_UNUSED(Section);
case LC_LIGHT_SECTION_TARGET:
return mTargetPosition;
case LC_LIGHT_SECTION_UPVECTOR:
return lcMul31(lcVector3(0, 25, 0), lcMatrix44AffineInverse(mWorldLight));
return mWorldMatrix.GetTranslation();
}
return lcVector3(0.0f, 0.0f, 0.0f);
void SetPosition(const lcVector3& Position, lcStep Step, bool AddKey)
{
mPositionKeys.ChangeKey(Position, Step, AddKey);
}
void SetRotation(const lcMatrix33& Rotation, lcStep Step, bool AddKey)
{
mRotationKeys.ChangeKey(Rotation, Step, AddKey);
}
lcVector3 GetRotationCenter() const
{
const quint32 Section = GetFocusSection();
switch (Section)
{
case LC_LIGHT_SECTION_POSITION:
return mPosition;
case LC_LIGHT_SECTION_TARGET:
case LC_LIGHT_SECTION_UPVECTOR:
return mTargetPosition;
return mWorldMatrix.GetTranslation();
}
return mPosition;
lcVector3 GetPosition() const
{
return mWorldMatrix.GetTranslation();
}
lcVector3 GetDirection() const
{
return -lcVector3(mWorldMatrix[2]);
}
void SaveLDraw(QTextStream& Stream) const;
@ -383,7 +287,7 @@ public:
void CompareBoundingBox(lcVector3& Min, lcVector3& Max);
void UpdatePosition(lcStep Step);
void MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance);
void Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcMatrix33& RotationFrame);
void Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcVector3& Center, const lcMatrix33& RotationFrame);
bool Setup(int LightIndex);
void CreateName(const lcArray<lcLight*>& Lights);
void UpdateLight(lcStep Step, lcLightProperties Props, int Property);
@ -405,10 +309,7 @@ public:
return props;
}
lcMatrix44 mWorldLight;
lcVector3 mPosition;
lcVector3 mTargetPosition;
lcVector3 mUpVector;
lcMatrix44 mWorldMatrix;
lcVector3 mAttenuation;
lcVector2 mLightFactor;
@ -436,21 +337,20 @@ protected:
void DrawDirectionalLight(lcContext* Context) const;
void DrawAreaLight(lcContext* Context) const;
float SetupLightMatrix(lcContext* Context) const;
void SetupLightMatrix(lcContext* Context) const;
void DrawSphere(lcContext* Context, float Radius) const;
void DrawCylinder(lcContext* Context, float Radius, float Height) const;
void DrawTarget(lcContext* Context, float TargetDistance) const;
void DrawCone(lcContext* Context, float TargetDistance) const;
quint32 mState;
quint32 mState = 0;
lcLightType mLightType;
lcVector3 mColor = lcVector3(1.0f, 1.0f, 1.0f);
bool mCastShadow = true;
int mLightShape;
lcObjectKeyArray<lcVector3> mPositionKeys;
lcObjectKeyArray<lcVector3> mTargetPositionKeys;
lcObjectKeyArray<lcVector3> mUpVectorKeys;
lcObjectKeyArray<lcMatrix33> mRotationKeys;
lcObjectKeyArray<lcVector3> mColorKeys;
lcObjectKeyArray<lcVector3> mAttenuationKeys;

View file

@ -2139,18 +2139,21 @@ bool Project::ExportPOVRay(const QString& FileName)
(CameraName.isEmpty() ? "Camera" : CameraName.toLatin1().constData()));
POVFile.WriteLine(Line);
lcVector3 LightTarget(0.0f, 0.0f, 0.0f), LightColor(1.0f, 1.0f, 1.0f);
lcVector2 AreaSize(200.0f, 200.0f), AreaGrid(10.0f, 10.0f);
int AreaCircle = 0, Shadowless = 0;
lcLightType LightType = lcLightType::Area;
float Power = 0, SpotRadius = 0, SpotFalloff = 0, SpotTightness = 0;
if (Lights.IsEmpty())
{
const lcVector3 LightTarget(0.0f, 0.0f, 0.0f), LightColor(1.0f, 1.0f, 1.0f);
lcVector3 Location[4];
Location[0] = {0.0f * Radius + Center[0], -1.5f * Radius + Center[1], -1.5f * Radius + Center[2]};
Location[1] = {1.5f * Radius + Center[0], -1.0f * Radius + Center[1], 0.866026f * Radius + Center[2]};
Location[2] = {0.0f * Radius + Center[0], -2.0f * Radius + Center[1], 0.0f * Radius + Center[2]};
Location[3] = {2.0f * Radius + Center[0], 0.0f * Radius + Center[1], -2.0f * Radius + Center[2]};
for (int Idx = 0; Idx < 4; Idx++)
{
Power = Idx < 2 ? 0.75f : 0.5f;
@ -2171,22 +2174,20 @@ bool Project::ExportPOVRay(const QString& FileName)
{
for (const lcLight* Light : Lights)
{
const lcVector3& Location = Light->mPosition;
const lcVector3 LightPosition = Light->GetPosition();
const lcVector3 LightTarget = LightPosition + Light->GetDirection();
const lcVector3 LightColor = Light->GetColor();
const QString LightName = QString(Light->mName).replace(" ","_");
LightType = Light->GetLightType();
Shadowless = Light->GetCastShadow() ? 0 : 1;
LightColor = Light->GetColor();
Power = Light->mPOVRayExponent;
switch(LightType)
{
case lcLightType::Spot:
LightTarget = Light->mTargetPosition;
SpotFalloff = Light->mSpotFalloff;
SpotRadius = Light->mSpotSize - SpotFalloff;
break;
case lcLightType::Directional:
LightTarget = Light->mTargetPosition;
break;
case lcLightType::Area:
AreaCircle = Light->GetLightShape() == LC_LIGHT_SHAPE_DISK ? 1 : 0;
AreaSize = Light->mAreaSize;
@ -2200,7 +2201,7 @@ bool Project::ExportPOVRay(const QString& FileName)
LightName.toLatin1().constData(),
LightType,
Shadowless,
Location[1], Location[0], Location[2],
LightPosition[1], LightPosition[0], LightPosition[2],
LightTarget[1], LightTarget[0], LightTarget[2],
LightColor[0], LightColor[1], LightColor[2],
Power,

View file

@ -868,9 +868,11 @@ void lcQPropertiesTree::slotReturnPressed()
if (Item == lightPositionX || Item == lightPositionY || Item == lightPositionZ)
{
lcVector3 Center = Light->mPosition;
lcVector3 Center = Light->GetPosition();
lcVector3 Position = Center;
float Value = lcParseValueLocalized(Editor->text());
if (Item == lightPositionX)
Position[0] = Value;
else if (Item == lightPositionY)
@ -884,19 +886,19 @@ void lcQPropertiesTree::slotReturnPressed()
}
else if (Item == lightTargetX || Item == lightTargetY || Item == lightTargetZ)
{
lcVector3 Center = Light->mTargetPosition;
lcVector3 Position = Center;
float Value = lcParseValueLocalized(Editor->text());
if (Item == lightTargetX)
Position[0] = Value;
else if (Item == lightTargetY)
Position[1] = Value;
else if (Item == lightTargetZ)
Position[2] = Value;
lcVector3 Distance = Position - Center;
Model->MoveSelectedObjects(Distance, Distance, false, false, true, true);
// lcVector3 Center = Light->mTargetPosition;
// lcVector3 Position = Center;
// float Value = lcParseValueLocalized(Editor->text());
// if (Item == lightTargetX)
// Position[0] = Value;
// else if (Item == lightTargetY)
// Position[1] = Value;
// else if (Item == lightTargetZ)
// Position[2] = Value;
//
// lcVector3 Distance = Position - Center;
//
// Model->MoveSelectedObjects(Distance, Distance, false, false, true, true);
}
else if (Item == lightFactorA || Item == lightFactorB)
{
@ -1466,8 +1468,8 @@ void lcQPropertiesTree::SetLight(lcObject* Focus)
Format = POVRayLight ? QLatin1String("POVRay") : QLatin1String("Blender");
CastShadow = Light->GetCastShadow();
Position = Light->mPosition;
Target = Light->mTargetPosition;
Position = Light->GetPosition();
// Target = Light->mTargetPosition;
Color = lcQColorFromVector3(Light->GetColor());
Factor = Light->mLightFactor;
LightType = Light->GetLightType();