From 07a268ed3289673f75dace51f949f11f6a90022e Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Mon, 7 Aug 2023 11:31:33 +0200 Subject: [PATCH] Blender lights - lcLight --- common/lc_global.h | 1 + common/light.cpp | 570 +++++++++++++++++++++++++++++++++++++++++++-- common/light.h | 89 ++++++- common/object.cpp | 14 ++ 4 files changed, 655 insertions(+), 19 deletions(-) diff --git a/common/lc_global.h b/common/lc_global.h index 2452f103..f079df05 100644 --- a/common/lc_global.h +++ b/common/lc_global.h @@ -105,6 +105,7 @@ struct lcMeshSection; struct lcRenderMesh; struct lcObjectSection; struct lcPieceInfoRayTest; +struct lcLightProperties; class lcTexture; class lcScene; class lcViewManipulator; diff --git a/common/light.cpp b/common/light.cpp index 12f01c7d..fbf11ec2 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -11,36 +11,81 @@ #define LC_LIGHT_POSITION_EDGE 7.5f #define LC_LIGHT_TARGET_EDGE 5.0f #define LC_LIGHT_SPHERE_RADIUS 5.0f +#define LC_LIGHT_BASEFACE_EDGE 12.5f // New omni light. lcLight::lcLight(float px, float py, float pz) : lcObject(lcObjectType::Light) { - Initialize(lcVector3(px, py, pz), lcVector3(0.0f, 0.0f, 0.0f)); + Initialize(lcVector3(px, py, pz), lcVector3(0.0f, 0.0f, 0.0f), LC_POINTLIGHT); UpdatePosition(1); } // New directional or spot light. -lcLight::lcLight(float px, float py, float pz, float tx, float ty, float tz) +lcLight::lcLight(float px, float py, float pz, float tx, float ty, float tz, int LightType) : lcObject(lcObjectType::Light) { - Initialize(lcVector3(px, py, pz), lcVector3(tx, ty, tz)); - mState |= LC_LIGHT_SPOT; + Initialize(lcVector3(px, py, pz), lcVector3(tx, ty, tz), LightType); + if (LightType == LC_SPOTLIGHT) + mState |= LC_LIGHT_SPOT; + else + mState |= LC_LIGHT_DIRECTIONAL; UpdatePosition(1); } -void lcLight::Initialize(const lcVector3& Position, const lcVector3& TargetPosition) +void lcLight::SetLightState(int LightType) { mState = 0; - mPositionKeys.ChangeKey(Position, 1, true); - mTargetPositionKeys.ChangeKey(TargetPosition, 1, true); - mAmbientColorKeys.ChangeKey(lcVector4(0.0f, 0.0f, 0.0f, 1.0f), 1, true); - mDiffuseColorKeys.ChangeKey(lcVector4(0.8f, 0.8f, 0.8f, 1.0f), 1, true); - mSpecularColorKeys.ChangeKey(lcVector4(1.0f, 1.0f, 1.0f, 1.0f), 1, true); - mAttenuationKeys.ChangeKey(lcVector3(1.0f, 0.0f, 0.0f), 1, true); - mSpotCutoffKeys.ChangeKey(30.0f, 1, true); - mSpotExponentKeys.ChangeKey(0.0f, 1, true); + switch (LightType) + { + case LC_AREALIGHT: + case LC_SUNLIGHT: + mState |= LC_LIGHT_DIRECTIONAL; + break; + case LC_SPOTLIGHT: + mState |= LC_LIGHT_SPOT; + break; + default: + break; + } +} + +void lcLight::Initialize(const lcVector3& Position, const lcVector3& TargetPosition, int LightType) +{ + SetLightState(LightType); + + mEnableCutoff = false; + mPosition = Position; + mTargetPosition = TargetPosition; + mAmbientColor = lcVector4(0.0f, 0.0f, 0.0f, 1.0f); + mDiffuseColor = lcVector4(0.8f, 0.8f, 0.8f, 1.0f); + mSpecularColor = lcVector4(1.0f, 1.0f, 1.0f, 1.0f); + mAttenuation = lcVector3(1.0f, 0.0f, 0.0f); + mLightColor = lcVector3(1.0f, 1.0f, 1.0f); //RGB - White + mLightType = LightType ? LightType : int(LC_POINTLIGHT); + mLightFactor[0] = LightType ? LightType == LC_SUNLIGHT ? 11.4f : 0.25f : 0.0f; + mLightFactor[1] = LightType == LC_AREALIGHT ? 0.25f : LightType == LC_SPOTLIGHT ? 0.150f : 0.0f; + mLightSpecular = 1.0f; + mSpotSize = 75.0f; + mLightShape = 0 /*Square*/; + mSpotCutoff = LightType ? LightType != LC_SUNLIGHT ? 40.0f : 0.0f : 30.0f; + mSpotExponent = 10.0f; /*Energy/Power*/ + + mPositionKeys.ChangeKey(mPosition, 1, true); + mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true); + mAmbientColorKeys.ChangeKey(mAmbientColor, 1, true); + mDiffuseColorKeys.ChangeKey(mDiffuseColor, 1, true); + mSpecularColorKeys.ChangeKey(mSpecularColor, 1, true); + mAttenuationKeys.ChangeKey(mAttenuation, 1, true); + mLightShapeKeys.ChangeKey(mLightShape, 1, true); + mLightColorKeys.ChangeKey(mLightColor, 1, true); + mLightTypeKeys.ChangeKey(mLightType, 1, true); + mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); + mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); + mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); + mLightSpotSizeKeys.ChangeKey(mSpotSize, 1, true); } lcLight::~lcLight() @@ -49,7 +94,139 @@ lcLight::~lcLight() void lcLight::SaveLDraw(QTextStream& Stream) const { - Q_UNUSED(Stream); + const QLatin1String LineEnding("\r\n"); + + if (mPositionKeys.GetSize() > 1) + mPositionKeys.SaveKeysLDraw(Stream, "LIGHT POSITION_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT POSITION ") << mPosition[0] << ' ' << mPosition[1] << ' ' << mPosition[2] << LineEnding; + + if (mTargetPositionKeys.GetSize() > 1) + mTargetPositionKeys.SaveKeysLDraw(Stream, "LIGHT TARGET_POSITION_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT TARGET_POSITION ") << mTargetPosition[0] << ' ' << mTargetPosition[1] << ' ' << mTargetPosition[2] << LineEnding; + + if (mLightColorKeys.GetSize() > 1) + mLightColorKeys.SaveKeysLDraw(Stream, "LIGHT COLOR_RGB_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT COLOR_RGB ") << mLightColor[0] << ' ' << mLightColor[1] << ' ' << mLightColor[2] << LineEnding; + + if (mLightSpecularKeys.GetSize() > 1) + mLightSpecularKeys.SaveKeysLDraw(Stream, "LIGHT SPECULAR_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT SPECULAR ") << mLightSpecular << LineEnding; + + if (mLightType == LC_SUNLIGHT) + { + if (mSpotExponentKeys.GetSize() > 1) + mSpotExponentKeys.SaveKeysLDraw(Stream, "LIGHT STRENGTH_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT STRENGTH ") << mSpotExponent << LineEnding; + + if (mLightFactorKeys.GetSize() > 1) + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT ANGLE_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT ANGLE ") << mLightFactor[0] << LineEnding; + } + else + { + if (mSpotExponentKeys.GetSize() > 1) + mSpotExponentKeys.SaveKeysLDraw(Stream, "LIGHT POWER_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT POWER ") << mSpotExponent << LineEnding; + + if (mEnableCutoff) + { + if (mSpotCutoffKeys.GetSize() > 1) + mSpotCutoffKeys.SaveKeysLDraw(Stream, "LIGHT CUTOFF_DISTANCE_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT CUTOFF_DISTANCE ") << mSpotCutoff << LineEnding; + } + + switch (mLightType) + { + case LC_POINTLIGHT: + if (mLightFactorKeys.GetSize() > 1) + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; + break; + case LC_SPOTLIGHT: + if (mLightFactorKeys.GetSize() > 1) { + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_AND_SPOT_BLEND_KEY "); + } else { + Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; + Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_BLEND ") << mLightFactor[1] << LineEnding; + } + if (mLightSpotSizeKeys.GetSize() > 1) + mLightSpotSizeKeys.SaveKeysLDraw(Stream, "LIGHT SPOT_SIZE_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_SIZE ") << mSpotSize << LineEnding; + break; + case LC_AREALIGHT: + if (mLightFactorKeys.GetSize() > 1) { + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT SIZE_KEY "); + } else { + if (mLightShape == LC_LIGHT_SHAPE_RECTANGLE || mLightShape == LC_LIGHT_SHAPE_ELLIPSE) + Stream << QLatin1String("0 !LEOCAD LIGHT WIDTH ") << mLightFactor[0] << QLatin1String(" HEIGHT ") << mLightFactor[1] << LineEnding; + else + Stream << QLatin1String("0 !LEOCAD LIGHT SIZE ") << mLightFactor[0] << LineEnding; + } + if (mLightShapeKeys.GetSize() > 1) { + mLightShapeKeys.SaveKeysLDraw(Stream, "LIGHT SHAPE_KEY "); + } else { + Stream << QLatin1String("0 !LEOCAD LIGHT SHAPE "); + + QString Shape = QLatin1String("Undefined "); + switch(mLightShape) + { + case LC_LIGHT_SHAPE_SQUARE: + Shape = QLatin1String("Square "); + break; + case LC_LIGHT_SHAPE_DISK: + Shape = QLatin1String("Disk "); + break; + case LC_LIGHT_SHAPE_RECTANGLE: + Shape = QLatin1String("Rectangle "); + break; + case LC_LIGHT_SHAPE_ELLIPSE: + Shape = QLatin1String("Ellipse "); + break; + default: + break; + } + Stream << QLatin1String(Shape.toLatin1()) << LineEnding; + } + + break; + } + } + + if (mLightTypeKeys.GetSize() > 1) + { + mLightTypeKeys.SaveKeysLDraw(Stream, "LIGHT TYPE_KEY "); + } + else + { + Stream << QLatin1String("0 !LEOCAD LIGHT TYPE "); + + QString Type = QLatin1String("Undefined "); + switch(mLightType){ + case LC_POINTLIGHT: + Type = QLatin1String("Point "); + break; + case LC_SUNLIGHT: + Type = QLatin1String("Sun "); + break; + case LC_AREALIGHT: + Type = QLatin1String("Area "); + break; + case LC_SPOTLIGHT: + Type = QLatin1String("Spot "); + break; + } + Stream << QLatin1String(Type.toLatin1()) << QLatin1String("NAME ") << mName << LineEnding; + } } void lcLight::CreateName(const lcArray& Lights) @@ -72,7 +249,8 @@ void lcLight::CreateName(const lcArray& Lights) } int MaxLightNumber = 0; - const QLatin1String Prefix("Light "); + + const QLatin1String Prefix(mLightType == LC_POINTLIGHT ? "Pointlight " : mLightType == LC_AREALIGHT ? "Arealight " : mLightType == LC_SUNLIGHT ? "Sunlight " : "Spotlight "); for (const lcLight* Light : Lights) { @@ -91,6 +269,142 @@ void lcLight::CreateName(const lcArray& Lights) mName = Prefix + QString::number(MaxLightNumber + 1); } +bool lcLight::ParseLDrawLine(QTextStream& Stream) +{ + while (!Stream.atEnd()) + { + QString Token; + Stream >> Token; + if (Token == QLatin1String("COLOR_RGB")) + { + Stream >> mLightColor[0] >> mLightColor[1] >> mLightColor[2]; + mLightColorKeys.ChangeKey(mLightColor, 1, true); + } + else if (Token == QLatin1String("POWER") || Token == QLatin1String("STRENGTH")) + { + Stream >> mSpotExponent; + mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); + } + else if (Token == QLatin1String("RADIUS") || Token == QLatin1String("SIZE") || Token == QLatin1String("WIDTH") || (mHeightSet = Token == QLatin1String("HEIGHT")) || (mSpotBlendSet = Token == QLatin1String("SPOT_BLEND")) || (mAngleSet = Token == QLatin1String("ANGLE"))) + { + if(Token == QLatin1String("HEIGHT") || Token == QLatin1String("SPOT_BLEND")) + Stream >> mLightFactor[1]; + else + Stream >> mLightFactor[0]; + mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + } + else if (Token == QLatin1String("SPOT_SIZE")) + { + Stream >> mSpotSize; + mLightSpotSizeKeys.ChangeKey(mSpotSize, 1, true); + } + else if (Token == QLatin1String("SHAPE")) + { + QString Shape; + Stream >> Shape; + Shape = Shape.replace("\"", "").toLower(); + if (Shape == QLatin1String("square")) + mLightShape = LC_LIGHT_SHAPE_SQUARE; + else if (Shape == QLatin1String("disk") || Shape == QLatin1String("circle")) + mLightShape = LC_LIGHT_SHAPE_DISK; + else if (Shape == QLatin1String("rectangle")) + mLightShape = LC_LIGHT_SHAPE_RECTANGLE; + else if (Shape == QLatin1String("ellipse")) + mLightShape = LC_LIGHT_SHAPE_ELLIPSE; + mLightShapeKeys.ChangeKey(mLightShape, 1, true); + } + else if (Token == QLatin1String("SPECULAR")) + { + Stream >>mLightSpecular; + mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); + } + else if ((mSpotCutoffSet = Token == QLatin1String("CUTOFF_DISTANCE"))) + { + mEnableCutoff = true; + Stream >> mSpotCutoff; + mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); + } + else if (Token == QLatin1String("TYPE")) + { + QString Type; + Stream >> Type; + Type = Type.replace("\"", "").toLower(); + if (Type == QLatin1String("point")) + mLightType = LC_POINTLIGHT; + else if (Type == QLatin1String("sun")) + mLightType = LC_SUNLIGHT; + else if (Type == QLatin1String("spot")) + mLightType = LC_SPOTLIGHT; + else if (Type == QLatin1String("area")) + mLightType = LC_AREALIGHT; + SetLightState(mLightType); + mLightTypeKeys.ChangeKey(mLightType, 1, true); + } + else if (Token == QLatin1String("POSITION")) + { + Stream >> mPosition[0] >> mPosition[1] >> mPosition[2]; + mPositionKeys.ChangeKey(mPosition, 1, true); + } + else if (Token == QLatin1String("TARGET_POSITION")) + { + Stream >> mTargetPosition[0] >> mTargetPosition[1] >> mTargetPosition[2]; + mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true); + } + else if (Token == QLatin1String("COLOR_RGB_KEY")) + mLightColorKeys.LoadKeysLDraw(Stream); + else if ((Token == QLatin1String("POWER_KEY")) || (Token == QLatin1String("STRENGTH_KEY"))) + mSpotExponentKeys.LoadKeysLDraw(Stream); + else if ((Token == QLatin1String("ANGLE_KEY")) || (Token == QLatin1String("RADIUS_KEY")) || (Token == QLatin1String("SIZE_KEY")) || (Token == QLatin1String("RADIUS_AND_SPOT_BLEND_KEY"))) + mLightFactorKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("SPOT_SIZE_KEY")) + mLightSpotSizeKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("SHAPE_KEY")) + mLightShapeKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("SPECULAR_KEY")) + mLightSpecularKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("CUTOFF_DISTANCE_KEY")) + mSpotCutoffKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("TYPE_KEY")) + mLightTypeKeys.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(); + mName.replace("\"", ""); + + // Set default settings per light type + if (mLightType == LC_SPOTLIGHT) { + if (!mSpotBlendSet) { + mLightFactor[1] = 0.15f; + mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + } + } + if (mLightType == LC_AREALIGHT && (mLightShape == LC_LIGHT_SHAPE_RECTANGLE || mLightShape == LC_LIGHT_SHAPE_ELLIPSE)) { + if (!mHeightSet) { + mLightFactor[1] = 0.25f; + mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + } + } + if (mLightType == LC_SUNLIGHT) { + if (!mAngleSet) { + mLightFactor[0] = 11.4f; + mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + } + if (!mSpotCutoffSet) { + mSpotCutoff = 0.0f; + mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); + } + } + return true; + } + } + + return false; +} + void lcLight::CompareBoundingBox(lcVector3& Min, lcVector3& Max) { const lcVector3 Points[2] = @@ -109,6 +423,44 @@ void lcLight::CompareBoundingBox(lcVector3& Min, lcVector3& Max) } } +void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) +{ + switch(Property){ + case LC_LIGHT_SHAPE: + mLightShape = Props.mLightShape; + mLightShapeKeys.ChangeKey(mLightShape, Step, false); + break; + case LC_LIGHT_COLOR: + mLightColor = Props.mLightColor; + mLightColorKeys.ChangeKey(mLightColor, Step, false); + break; + case LC_LIGHT_FACTOR: + mLightFactor = Props.mLightFactor; + mLightFactorKeys.ChangeKey(mLightFactor, Step, false); + break; + case LC_LIGHT_SPECULAR: + mLightSpecular = Props.mLightSpecular; + mLightSpecularKeys.ChangeKey(mLightSpecular, Step, false); + break; + case LC_LIGHT_EXPONENT: + mSpotExponent = Props.mSpotExponent; + mSpotExponentKeys.ChangeKey(mSpotExponent, Step, false); + break; + case LC_LIGHT_SPOT_SIZE: + mSpotSize = Props.mSpotSize; + mLightSpotSizeKeys.ChangeKey(mSpotSize, Step, false); + break; + case LC_LIGHT_CUTOFF: + mSpotCutoff = Props.mSpotCutoff; + mSpotCutoffKeys.ChangeKey(mSpotCutoff, Step, false); + break; + case LC_LIGHT_USE_CUTOFF: + mEnableCutoff = Props.mEnableCutoff; + break; + } + UpdatePosition(Step); +} + void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const { if (IsPointLight()) @@ -231,6 +583,12 @@ void lcLight::InsertTime(lcStep Start, lcStep Time) mDiffuseColorKeys.InsertTime(Start, Time); mSpecularColorKeys.InsertTime(Start, Time); mAttenuationKeys.InsertTime(Start, Time); + mLightShapeKeys.InsertTime(Start, Time); + mLightColorKeys.InsertTime(Start, Time); + mLightTypeKeys.InsertTime(Start, Time); + mLightFactorKeys.InsertTime(Start, Time); + mLightSpecularKeys.InsertTime(Start, Time); + mLightSpotSizeKeys.InsertTime(Start, Time); mSpotCutoffKeys.InsertTime(Start, Time); mSpotExponentKeys.InsertTime(Start, Time); } @@ -243,6 +601,12 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) mDiffuseColorKeys.RemoveTime(Start, Time); mSpecularColorKeys.RemoveTime(Start, Time); mAttenuationKeys.RemoveTime(Start, Time); + mLightShapeKeys.RemoveTime(Start, Time); + mLightColorKeys.RemoveTime(Start, Time); + mLightTypeKeys.RemoveTime(Start, Time); + mLightFactorKeys.RemoveTime(Start, Time); + mLightSpecularKeys.RemoveTime(Start, Time); + mLightSpotSizeKeys.RemoveTime(Start, Time); mSpotCutoffKeys.RemoveTime(Start, Time); mSpotExponentKeys.RemoveTime(Start, Time); } @@ -255,6 +619,12 @@ void lcLight::UpdatePosition(lcStep Step) mDiffuseColor = mDiffuseColorKeys.CalculateKey(Step); mSpecularColor = mSpecularColorKeys.CalculateKey(Step); mAttenuation = mAttenuationKeys.CalculateKey(Step); + mLightShape = mLightShapeKeys.CalculateKey(Step); + mLightColor = mLightColorKeys.CalculateKey(Step); + mLightType = mLightTypeKeys.CalculateKey(Step); + mLightFactor = mLightFactorKeys.CalculateKey(Step); + mLightSpecular = mLightSpecularKeys.CalculateKey(Step); + mSpotSize = mLightSpotSizeKeys.CalculateKey(Step); mSpotCutoff = mSpotCutoffKeys.CalculateKey(Step); mSpotExponent = mSpotExponentKeys.CalculateKey(Step); @@ -294,10 +664,160 @@ void lcLight::DrawInterface(lcContext* Context, const lcScene& Scene) const if (IsPointLight()) DrawPointLight(Context); + else if (IsDirectionalLight()) + DrawDirectionalLight(Context); else DrawSpotLight(Context); } +void lcLight::DrawDirectionalLight(lcContext* Context) const +{ + 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]); + } + + lcMatrix44 LightMatrix = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector); + LightMatrix = lcMatrix44AffineInverse(LightMatrix); + LightMatrix.SetTranslation(lcVector3(0, 0, 0)); + + lcMatrix44 LightViewMatrix = lcMul(LightMatrix, lcMatrix44Translation(mPosition)); + Context->SetWorldMatrix(LightViewMatrix); + + float Verts[(20 + 8 + 2 + 16) * 3]; + float* CurVert = Verts; + + for (int EdgeIdx = 0; EdgeIdx < 8; EdgeIdx++) + { + float c = cosf(float(EdgeIdx) / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE; + float s = sinf(float(EdgeIdx) / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE; + + *CurVert++ = c; + *CurVert++ = s; + *CurVert++ = LC_LIGHT_POSITION_EDGE; + *CurVert++ = c; + *CurVert++ = s; + *CurVert++ = -LC_LIGHT_POSITION_EDGE; + } + + if (mLightType == LC_SUNLIGHT) { + + // set base face to same size (LC_LIGHT_TARGET_EDGE) as body - was 12.5f + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + + } else { + + *CurVert++ = -LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_BASEFACE_EDGE; *CurVert++ = LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = -LC_LIGHT_BASEFACE_EDGE; *CurVert++ = LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + } + + + float Length = FrontVector.Length(); + + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; + + *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; + *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -Length; + + const GLushort Indices[56 + 24 + 2 + 40] = + { + // base body + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 0, + 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13, 15, 15, 1, + // base face + 16, 17, 17, 18, 18, 19, 19, 16, + // targe box + 20, 21, 21, 22, 22, 23, 23, 20, + 24, 25, 25, 26, 26, 27, 27, 24, + 20, 24, 21, 25, 22, 26, 23, 27, + // target line - from base to target + 28, 29, + }; + + Context->SetVertexBufferPointer(Verts); + Context->SetVertexFormatPosition(3); + Context->SetIndexBufferPointer(Indices); + + const lcPreferences& Preferences = lcGetPreferences(); + const float LineWidth = Preferences.mLineWidth; + const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor); + const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor); + const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor); + + if (!IsSelected()) + { + Context->SetLineWidth(LineWidth); + Context->SetColor(LightColor); + + Context->DrawIndexedPrimitives(GL_LINES, 56 + 24 + 2, GL_UNSIGNED_SHORT, 0); + } + else + { + if (IsSelected(LC_LIGHT_SECTION_POSITION)) + { + Context->SetLineWidth(2.0f * LineWidth); + if (IsFocused(LC_LIGHT_SECTION_POSITION)) + Context->SetColor(FocusedColor); + else + Context->SetColor(SelectedColor); + } + else + { + Context->SetLineWidth(LineWidth); + Context->SetColor(LightColor); + } + + Context->DrawIndexedPrimitives(GL_LINES, 56, GL_UNSIGNED_SHORT, 0); + + if (IsSelected(LC_LIGHT_SECTION_TARGET)) + { + 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, 24, GL_UNSIGNED_SHORT, 56 * 2); + + Context->SetLineWidth(LineWidth); + Context->SetColor(LightColor); + + Context->DrawIndexedPrimitives(GL_LINES, 2 + 40, GL_UNSIGNED_SHORT, (56 + 24) * 2); + } +} + void lcLight::DrawSpotLight(lcContext* Context) const { lcVector3 FrontVector(mTargetPosition - mPosition); @@ -360,7 +880,7 @@ void lcLight::DrawSpotLight(lcContext* Context) const *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -Length; - const GLushort Indices[56 + 24 + 2 + 40] = + const GLushort Indices[56 + 24 + 2 + 40] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 0, @@ -565,6 +1085,24 @@ void lcLight::RemoveKeyFrames() mAttenuationKeys.RemoveAll(); mAttenuationKeys.ChangeKey(mAttenuation, 1, true); + mLightShapeKeys.RemoveAll(); + mLightShapeKeys.ChangeKey(mLightShape, 1, false); + + mLightColorKeys.RemoveAll(); + mLightColorKeys.ChangeKey(mLightColor, 1, true); + + mLightFactorKeys.RemoveAll(); + mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + + mLightTypeKeys.RemoveAll(); + mLightTypeKeys.ChangeKey(mLightType, 1, true); + + mLightSpecularKeys.RemoveAll(); + mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); + + mLightSpotSizeKeys.RemoveAll(); + mLightSpotSizeKeys.ChangeKey(mSpotSize, 1, false); + mSpotCutoffKeys.RemoveAll(); mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); diff --git a/common/light.h b/common/light.h index 78a0cd0d..0163d8d2 100644 --- a/common/light.h +++ b/common/light.h @@ -21,11 +21,55 @@ enum lcLightSection LC_LIGHT_SECTION_TARGET }; +enum lcLightType +{ + LC_UNDEFINED_LIGHT, + LC_POINTLIGHT, + LC_AREALIGHT, + LC_SUNLIGHT, + LC_SPOTLIGHT +}; + +enum lcLightShape +{ + LC_LIGHT_SHAPE_UNDEFINED = -1, + LC_LIGHT_SHAPE_SQUARE, + LC_LIGHT_SHAPE_DISK, + LC_LIGHT_SHAPE_RECTANGLE, + LC_LIGHT_SHAPE_ELLIPSE +}; + +enum lcLightProperty +{ + LC_LIGHT_NONE, + LC_LIGHT_SHAPE, + LC_LIGHT_COLOR, + LC_LIGHT_TYPE, + LC_LIGHT_FACTOR, + LC_LIGHT_SPECULAR, + LC_LIGHT_EXPONENT, + LC_LIGHT_SPOT_SIZE, + LC_LIGHT_CUTOFF, + LC_LIGHT_USE_CUTOFF +}; + +struct lcLightProperties +{ + lcVector3 mLightColor; + lcVector2 mLightFactor; + float mLightSpecular; + float mSpotExponent; + float mSpotCutoff; + float mSpotSize; + bool mEnableCutoff; + int mLightShape; +}; + class lcLight : public lcObject { public: lcLight(float px, float py, float pz); - lcLight(float px, float py, float pz, float tx, float ty, float tz); + lcLight(float px, float py, float pz, float tx, float ty, float tz, int LightType); ~lcLight(); lcLight(const lcLight&) = delete; @@ -178,6 +222,7 @@ public: } void SaveLDraw(QTextStream& Stream) const; + bool ParseLDrawLine(QTextStream& Stream); public: void RayTest(lcObjectRayTest& ObjectRayTest) const override; @@ -191,6 +236,11 @@ public: bool IsVisible() const { return (mState & LC_LIGHT_HIDDEN) == 0; } + void SetName(const QString& Name) + { + mName = Name; + } + QString GetName() const override { return mName; @@ -201,6 +251,20 @@ public: void MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance); bool Setup(int LightIndex); void CreateName(const lcArray& Lights); + void UpdateLight(lcStep Step, lcLightProperties Props, int Property); + lcLightProperties GetLightProperties() const + { + lcLightProperties props; + props.mLightColor = mLightColor; + props.mLightFactor = mLightFactor; + props.mLightSpecular = mLightSpecular; + props.mSpotExponent = mSpotExponent; + props.mSpotCutoff = mSpotCutoff; + props.mSpotSize = mSpotSize; + props.mEnableCutoff = mEnableCutoff; + props.mLightShape = mLightShape; + return props; + } // Temporary parameters lcMatrix44 mWorldLight; @@ -210,8 +274,20 @@ public: lcVector4 mDiffuseColor; lcVector4 mSpecularColor; lcVector3 mAttenuation; + lcVector3 mLightColor; + lcVector2 mLightFactor; + bool mAngleSet; + bool mSpotBlendSet; + bool mSpotCutoffSet; + bool mHeightSet; + bool mEnableCutoff; + int mLightType; + int mLightShape; + float mLightSpecular; + float mSpotSize; float mSpotCutoff; float mSpotExponent; + QString mName; protected: lcObjectKeyArray mPositionKeys; @@ -220,14 +296,21 @@ protected: lcObjectKeyArray mDiffuseColorKeys; lcObjectKeyArray mSpecularColorKeys; lcObjectKeyArray mAttenuationKeys; + lcObjectKeyArray mLightColorKeys; + lcObjectKeyArray mLightFactorKeys; + lcObjectKeyArray mLightTypeKeys; + lcObjectKeyArray mLightShapeKeys; + lcObjectKeyArray mLightSpecularKeys; + lcObjectKeyArray mLightSpotSizeKeys; lcObjectKeyArray mSpotCutoffKeys; lcObjectKeyArray mSpotExponentKeys; - void Initialize(const lcVector3& Position, const lcVector3& TargetPosition); + void Initialize(const lcVector3& Position, const lcVector3& TargetPosition, int LightType); + void DrawDirectionalLight(lcContext* Context) const; void DrawPointLight(lcContext* Context) const; void DrawSpotLight(lcContext* Context) const; + void SetLightState(int LightType); - QString mName; quint32 mState; }; diff --git a/common/object.cpp b/common/object.cpp index 42723094..c8eedc93 100644 --- a/common/object.cpp +++ b/common/object.cpp @@ -38,6 +38,20 @@ template void lcObjectKeyArray::ChangeKey(const lcMatrix33& Value, l template void lcObjectKeyArray::InsertTime(lcStep Start, lcStep Time); template void lcObjectKeyArray::RemoveTime(lcStep Start, lcStep Time); +template void lcObjectKeyArray::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const; +template void lcObjectKeyArray::LoadKeysLDraw(QTextStream& Stream); +template const int& lcObjectKeyArray::CalculateKey(lcStep Step) const; +template void lcObjectKeyArray::ChangeKey(const int& Value, lcStep Step, bool AddKey); +template void lcObjectKeyArray::InsertTime(lcStep Start, lcStep Time); +template void lcObjectKeyArray::RemoveTime(lcStep Start, lcStep Time); + +template void lcObjectKeyArray::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const; +template void lcObjectKeyArray::LoadKeysLDraw(QTextStream& Stream); +template const lcVector2& lcObjectKeyArray::CalculateKey(lcStep Step) const; +template void lcObjectKeyArray::ChangeKey(const lcVector2& Value, lcStep Step, bool AddKey); +template void lcObjectKeyArray::InsertTime(lcStep Start, lcStep Time); +template void lcObjectKeyArray::RemoveTime(lcStep Start, lcStep Time); + template void lcObjectKeyArray::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const {