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")) else if (Token == QLatin1String("LIGHT"))
{ {
if (!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)) if (Light->ParseLDrawLine(LineStream))
{ {
@ -2224,8 +2224,14 @@ lcMatrix33 lcModel::GetRelativeRotation() const
{ {
const lcObject* Focus = GetFocusObject(); const lcObject* Focus = GetFocusObject();
if (Focus && Focus->IsPiece()) if (Focus)
return ((lcPiece*)Focus)->GetRelativeRotation(); {
if (Focus->IsPiece())
return ((lcPiece*)Focus)->GetRelativeRotation();
if (Focus->IsLight())
return ((lcLight*)Focus)->GetRelativeRotation();
}
} }
return lcMatrix33Identity(); return lcMatrix33Identity();
@ -2739,6 +2745,16 @@ void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector
Moved = true; 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; Moved = true;
} }
} }
for (lcLight* Light : mLights)
{
if (Light->IsSelected())
{
Light->MoveSelected(mCurrentStep, gMainWindow->GetAddKeys(), TransformedObjectDistance);
Light->UpdatePosition(mCurrentStep);
Moved = true;
}
}
} }
if (Moved && Update) if (Moved && Update)
@ -2842,7 +2848,7 @@ void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool
{ {
lcLight* Light = (lcLight*)Object; lcLight* Light = (lcLight*)Object;
Light->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, WorldToFocusMatrix); Light->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, Center, WorldToFocusMatrix);
Light->UpdatePosition(mCurrentStep); Light->UpdatePosition(mCurrentStep);
Rotated = true; Rotated = true;
} }
@ -2896,7 +2902,7 @@ void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool
RelativeRotationMatrix = RotationMatrix; RelativeRotationMatrix = RotationMatrix;
} }
Light->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, WorldToFocusMatrix); Light->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, Center, WorldToFocusMatrix);
Light->UpdatePosition(mCurrentStep); Light->UpdatePosition(mCurrentStep);
Rotated = true; Rotated = true;
} }
@ -3328,12 +3334,6 @@ bool lcModel::GetMoveRotateTransform(lcVector3& Center, lcMatrix33& RelativeRota
Center += Light->GetSectionPosition(LC_LIGHT_SECTION_POSITION); Center += Light->GetSectionPosition(LC_LIGHT_SECTION_POSITION);
NumSelected++; NumSelected++;
if (!Light->IsPointLight())
{
Center += Light->GetSectionPosition(LC_LIGHT_SECTION_TARGET);
NumSelected++;
}
} }
if (NumSelected) if (NumSelected)
@ -4250,29 +4250,18 @@ void lcModel::InsertPieceToolClicked(const lcMatrix44& WorldMatrix)
SaveCheckpoint(tr("Insert")); 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); Light->CreateName(mLights);
mLights.Add(Light); mLights.Add(Light);
ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_POSITION, false); 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) switch (LightType)
{ {
case lcLightType::Point: case lcLightType::Point:
SaveCheckpoint(tr("New Point Light"));
break; break;
case lcLightType::Spot: 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) 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]); 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 BeginMouseTool();
void EndMouseTool(lcTool Tool, bool Accept); void EndMouseTool(lcTool Tool, bool Accept);
void InsertPieceToolClicked(const lcMatrix44& WorldMatrix); void InsertPieceToolClicked(const lcMatrix44& WorldMatrix);
void PointLightToolClicked(const lcVector3& Position); void InsertLightToolClicked(const lcVector3& Position, lcLightType LightType);
void BeginDirectionalLightTool(const lcVector3& Position, const lcVector3& Target, lcLightType LightType);
void UpdateDirectionalLightTool(const lcVector3& Position);
void BeginSpotLightTool(const lcVector3& Position, const lcVector3& Target);
void BeginCameraTool(const lcVector3& Position, const lcVector3& Target); void BeginCameraTool(const lcVector3& Position, const lcVector3& Target);
void UpdateCameraTool(const lcVector3& Position); void UpdateCameraTool(const lcVector3& Position);
void UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag); void UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag);

View file

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

View file

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

View file

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

View file

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

View file

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