diff --git a/common/lc_model.cpp b/common/lc_model.cpp index cb339a65..407b1344 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3185,6 +3185,26 @@ void lcModel::SetLightColor(lcLight* Light, const lcVector3& Color) UpdateAllViews(); } +void lcModel::SetLightAttenuationDistance(lcLight* Light, float Distance) +{ + Light->SetAttenuationDistance(Distance, mCurrentStep, gMainWindow->GetAddKeys()); + Light->UpdatePosition(mCurrentStep); + + SaveCheckpoint(tr("Changing Light Attenuation Distance")); + gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); +} + +void lcModel::SetLightAttenuationPower(lcLight* Light, float Power) +{ + Light->SetAttenuationPower(Power, mCurrentStep, gMainWindow->GetAddKeys()); + Light->UpdatePosition(mCurrentStep); + + SaveCheckpoint(tr("Changing Light Attenuation Power")); + gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); +} + void lcModel::SetSpotLightConeAngle(lcLight* Light, float Angle) { Light->SetSpotConeAngle(Angle, mCurrentStep, gMainWindow->GetAddKeys()); diff --git a/common/lc_model.h b/common/lc_model.h index dd99f74c..144ee9f8 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -370,6 +370,8 @@ public: void SetLightType(lcLight* Light, lcLightType LightType); void SetLightColor(lcLight* Light, const lcVector3& Color); + void SetLightAttenuationDistance(lcLight* Light, float Distance); + void SetLightAttenuationPower(lcLight* Light, float Power); void SetSpotLightConeAngle(lcLight* Light, float Angle); void SetSpotLightPenumbraAngle(lcLight* Light, float Angle); void SetSpotLightTightness(lcLight* Light, float Tightness); diff --git a/common/light.cpp b/common/light.cpp index ccb8819b..f57f7583 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -27,7 +27,6 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mPOVRayLight = false; mEnableCutoff = false; - mAttenuation = lcVector3(1.0f, 0.0f, 0.0f); mLightDiffuse = 1.0f; mLightSpecular = 1.0f; mSpotExponent = 10.0f; @@ -40,12 +39,13 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mRotationKeys.ChangeKey(lcMatrix33(mWorldMatrix), 1, true); mColorKeys.ChangeKey(mColor, 1, true); mPowerKeys.ChangeKey(mPower, 1, true); + mAttenuationDistanceKeys.ChangeKey(mAttenuationDistance, 1, true); + mAttenuationPowerKeys.ChangeKey(mAttenuationPower, 1, true); mSpotConeAngleKeys.ChangeKey(mSpotConeAngle, 1, true); mSpotPenumbraAngleKeys.ChangeKey(mSpotPenumbraAngle, 1, true); mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); - mAttenuationKeys.ChangeKey(mAttenuation, 1, true); mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); @@ -158,6 +158,8 @@ void lcLight::SaveLDraw(QTextStream& Stream) const SaveAttribute(Stream, mColor, mColorKeys, "LIGHT", "COLOR"); SaveAttribute(Stream, mSize, mSizeKeys, "LIGHT", "SIZE"); SaveAttribute(Stream, mPower, mPowerKeys, "LIGHT", "POWER"); + SaveAttribute(Stream, mAttenuationDistance, mAttenuationDistanceKeys, "LIGHT", "ATTENUATION_DISTANCE"); + SaveAttribute(Stream, mAttenuationPower, mAttenuationPowerKeys, "LIGHT", "ATTENUATION_POWER"); if (!mPOVRayLight) { @@ -306,6 +308,10 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) continue; else if (LoadAttribute(Stream, Token, mPower, mPowerKeys, "POWER")) continue; + else if (LoadAttribute(Stream, Token, mAttenuationDistance, mAttenuationDistanceKeys, "ATTENUATION_DISTANCE")) + continue; + else if (LoadAttribute(Stream, Token, mAttenuationPower, mAttenuationPowerKeys, "ATTENUATION_POWER")) + continue; else if (LoadAttribute(Stream, Token, mSpotConeAngle, mSpotConeAngleKeys, "SPOT_CONE_ANGLE")) continue; else if (LoadAttribute(Stream, Token, mSpotPenumbraAngle, mSpotPenumbraAngleKeys, "SPOT_PENUMBRA_ANGLE")) @@ -665,6 +671,16 @@ void lcLight::SetColor(const lcVector3& Color, lcStep Step, bool AddKey) mColorKeys.ChangeKey(Color, Step, AddKey); } +void lcLight::SetAttenuationDistance(float Distance, lcStep Step, bool AddKey) +{ + mAttenuationDistanceKeys.ChangeKey(Distance, Step, AddKey); +} + +void lcLight::SetAttenuationPower(float Power, lcStep Step, bool AddKey) +{ + mAttenuationPowerKeys.ChangeKey(Power, Step, AddKey); +} + void lcLight::SetSpotConeAngle(float Angle, lcStep Step, bool AddKey) { mSpotConeAngleKeys.ChangeKey(Angle, Step, AddKey); @@ -736,8 +752,9 @@ void lcLight::InsertTime(lcStep Start, lcStep Time) mAreaGridKeys.InsertTime(Start, Time); mSizeKeys.InsertTime(Start, Time); mPowerKeys.InsertTime(Start, Time); + mAttenuationDistanceKeys.InsertTime(Start, Time); + mAttenuationPowerKeys.InsertTime(Start, Time); - mAttenuationKeys.InsertTime(Start, Time); mLightDiffuseKeys.InsertTime(Start, Time); mLightSpecularKeys.InsertTime(Start, Time); mSpotCutoffKeys.InsertTime(Start, Time); @@ -755,8 +772,9 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) mAreaGridKeys.RemoveTime(Start, Time); mSizeKeys.RemoveTime(Start, Time); mPowerKeys.RemoveTime(Start, Time); + mAttenuationDistanceKeys.RemoveTime(Start, Time); + mAttenuationPowerKeys.RemoveTime(Start, Time); - mAttenuationKeys.RemoveTime(Start, Time); mLightDiffuseKeys.RemoveTime(Start, Time); mLightSpecularKeys.RemoveTime(Start, Time); mSpotCutoffKeys.RemoveTime(Start, Time); @@ -785,8 +803,9 @@ void lcLight::UpdatePosition(lcStep Step) mAreaGrid = mAreaGridKeys.CalculateKey(Step); mSize = mSizeKeys.CalculateKey(Step); mPower = mPowerKeys.CalculateKey(Step); + mAttenuationDistance = mAttenuationDistanceKeys.CalculateKey(Step); + mAttenuationPower = mAttenuationPowerKeys.CalculateKey(Step); - mAttenuation = mAttenuationKeys.CalculateKey(Step); mLightDiffuse = mLightDiffuseKeys.CalculateKey(Step); mLightSpecular = mLightSpecularKeys.CalculateKey(Step); mSpotCutoff = mSpotCutoffKeys.CalculateKey(Step); @@ -1230,8 +1249,11 @@ void lcLight::RemoveKeyFrames() mPowerKeys.RemoveAll(); mPowerKeys.ChangeKey(mPower, 1, true); - mAttenuationKeys.RemoveAll(); - mAttenuationKeys.ChangeKey(mAttenuation, 1, true); + mAttenuationDistanceKeys.RemoveAll(); + mAttenuationDistanceKeys.ChangeKey(mAttenuationDistance, 1, true); + + mAttenuationPowerKeys.RemoveAll(); + mAttenuationPowerKeys.ChangeKey(mAttenuationPower, 1, true); mLightDiffuseKeys.RemoveAll(); mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); diff --git a/common/light.h b/common/light.h index 3f4faf68..b70435ea 100644 --- a/common/light.h +++ b/common/light.h @@ -248,6 +248,20 @@ public: return mColor; } + void SetAttenuationDistance(float Distance, lcStep Step, bool AddKey); + + float GetAttenuationDistance() const + { + return mAttenuationDistance; + } + + void SetAttenuationPower(float Power, lcStep Step, bool AddKey); + + float GetAttenuationPower() const + { + return mAttenuationPower; + } + void SetSpotConeAngle(float Angle, lcStep Step, bool AddKey); float GetSpotConeAngle() const @@ -336,7 +350,6 @@ public: lcMatrix44 mWorldMatrix; - lcVector3 mAttenuation; bool mSpotBlendSet; bool mSpotCutoffSet; bool mEnableCutoff; @@ -367,6 +380,8 @@ protected: lcVector3 mColor = lcVector3(1.0f, 1.0f, 1.0f); lcVector2 mSize = lcVector2(0.0f, 0.0f); float mPower = 1.0f; + float mAttenuationDistance = 0.0f; + float mAttenuationPower = 0.0f; float mSpotConeAngle = 80.0f; float mSpotPenumbraAngle = 0.0f; float mSpotTightness = 0.0f; @@ -383,12 +398,13 @@ protected: lcObjectKeyArray mColorKeys; lcObjectKeyArray mSizeKeys; lcObjectKeyArray mPowerKeys; + lcObjectKeyArray mAttenuationDistanceKeys; + lcObjectKeyArray mAttenuationPowerKeys; lcObjectKeyArray mSpotConeAngleKeys; lcObjectKeyArray mSpotPenumbraAngleKeys; lcObjectKeyArray mSpotTightnessKeys; lcObjectKeyArray mAreaGridKeys; - lcObjectKeyArray mAttenuationKeys; lcObjectKeyArray mLightSpecularKeys; lcObjectKeyArray mLightDiffuseKeys; lcObjectKeyArray mSpotCutoffKeys; diff --git a/common/project.cpp b/common/project.cpp index d8a6a64c..c83c9a4f 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -2007,7 +2007,7 @@ bool Project::ExportPOVRay(const QString& FileName) sprintf(Line, "#ifndef (SkipWriteLightMacro)\n" - "#macro WriteLight(Type, Shadowless, Location, Target, Color, Power, SpotRadius, SpotFalloff, SpotTightness, AreaCircle, AreaWidth, AreaHeight, AreaRows, AreaColumns)\n" + "#macro WriteLight(Type, Shadowless, Location, Target, Color, Power, FadeDistance, FadePower, SpotRadius, SpotFalloff, SpotTightness, AreaCircle, AreaWidth, AreaHeight, AreaRows, AreaColumns)\n" " #local PointLight = %i;\n" " #local Spotlight = %i;\n" " #local DirectionalLight = %i;\n" @@ -2018,6 +2018,12 @@ bool Project::ExportPOVRay(const QString& FileName) " #if (Shadowless > 0)\n" " shadowless\n" " #end\n" + " #if (FadeDistance > 0)\n" + " fade_distance FadeDistance\n" + " #end\n" + " #if (FadePower > 0)\n" + " fade_power FadePower\n" + " #end\n" " #if (Type = Spotlight)\n" " spotlight\n" " radius SpotRadius\n" @@ -2143,7 +2149,7 @@ bool Project::ExportPOVRay(const QString& FileName) lcVector2i AreaGrid(1, 1); int AreaCircle = 0, Shadowless = 0; lcLightType LightType = lcLightType::Area; - float Power = 0, SpotRadius = 0, SpotFalloff = 0, SpotTightness = 0; + float Power = 0.0f, FadeDistance = 0.0f, FadePower = 0.0f, SpotRadius = 0.0f, SpotFalloff = 0.0f, SpotTightness = 0.0f; if (Lights.IsEmpty()) { @@ -2158,7 +2164,7 @@ bool Project::ExportPOVRay(const QString& FileName) for (int Idx = 0; Idx < 4; Idx++) { Power = Idx < 2 ? 0.75f : 0.5f; - sprintf(Line,"#ifndef (SkipLight%i)\nWriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n", + sprintf(Line,"#ifndef (SkipLight%i)\nWriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n", Idx, LightType, Shadowless, @@ -2166,6 +2172,7 @@ bool Project::ExportPOVRay(const QString& FileName) LightTarget[0], LightTarget[1], LightTarget[2], LightColor[0], LightColor[1], LightColor[2], Power, + FadeDistance, FadePower, SpotRadius, SpotFalloff, SpotTightness, AreaCircle, AreaX[0], AreaX[1], AreaX[2], AreaY[0], AreaY[1], AreaY[2], AreaGrid.x, AreaGrid.y); POVFile.WriteLine(Line); @@ -2182,6 +2189,8 @@ bool Project::ExportPOVRay(const QString& FileName) LightType = Light->GetLightType(); Shadowless = Light->GetCastShadow() ? 0 : 1; Power = Light->mPOVRayExponent; + FadeDistance = Light->GetAttenuationDistance(); + FadePower = Light->GetAttenuationPower(); switch (LightType) { @@ -2207,7 +2216,7 @@ bool Project::ExportPOVRay(const QString& FileName) break; } - sprintf(Line,"#ifndef (Skip%s)\n WriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n", + sprintf(Line,"#ifndef (Skip%s)\n WriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n", LightName.toLatin1().constData(), LightType, Shadowless, @@ -2215,6 +2224,7 @@ bool Project::ExportPOVRay(const QString& FileName) LightTarget[1], LightTarget[0], LightTarget[2], LightColor[0], LightColor[1], LightColor[2], Power, + FadeDistance, FadePower, SpotRadius, SpotFalloff, SpotTightness, AreaCircle, AreaX[0], AreaX[1], AreaX[2], AreaY[0], AreaY[1], AreaY[2], AreaGrid.x, AreaGrid.y); POVFile.WriteLine(Line); diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index 24ff25bb..cf46027b 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -838,7 +838,19 @@ void lcQPropertiesTree::slotReturnPressed() { lcLightProperties Props = Light->GetLightProperties(); - if (Item == mLightSpotConeAngleItem) + if (Item == mLightAttenuationDistanceItem) + { + float Value = lcParseValueLocalized(Editor->text()); + + Model->SetLightAttenuationDistance(Light, Value); + } + else if (Item == mLightAttenuationPowerItem) + { + float Value = lcParseValueLocalized(Editor->text()); + + Model->SetLightAttenuationPower(Light, Value); + } + else if (Item == mLightSpotConeAngleItem) { float Value = lcParseValueLocalized(Editor->text()); @@ -1124,6 +1136,8 @@ void lcQPropertiesTree::SetEmpty() lightExponent = nullptr; mLightTypeItem = nullptr; mLightNameItem = nullptr; + mLightAttenuationDistanceItem = nullptr; + mLightAttenuationPowerItem = nullptr; mLightSpotConeAngleItem = nullptr; mLightSpotPenumbraAngleItem = nullptr; mLightSpotTightnessItem = nullptr; @@ -1387,6 +1401,8 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lcVector2 LightSize(0.0f, 0.0f); lcVector2i AreaGrid(2, 2); float Power = 0.0f; + float AttenuationDistance = 0.0f; + float AttenuationPower = 0.0f; int FormatIndex = 0; float Diffuse = 0.0f; float Specular = 0.0f; @@ -1411,6 +1427,8 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) Position = Light->GetPosition(); Color = lcQColorFromVector3(Light->GetColor()); Power = Light->GetPower(); + AttenuationDistance = Light->GetAttenuationDistance(); + AttenuationPower = Light->GetAttenuationPower(); SpotConeAngle = Light->GetSpotConeAngle(); SpotPenumbraAngle = Light->GetSpotPenumbraAngle(); @@ -1478,6 +1496,12 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) mLightCastShadowItem = addProperty(mLightAttributesItem, tr("Cast Shadows"), PropertyBool); + mLightAttenuationDistanceItem = addProperty(mLightAttributesItem, tr("Attenuation Distance"), PropertyFloat); + mLightAttenuationDistanceItem->setToolTip(1, tr("The distance at which the full light intensity arrives (POV-Ray only).")); + + mLightAttenuationPowerItem = addProperty(mLightAttributesItem, tr("Attenuation Power"), PropertyFloat); + mLightAttenuationPowerItem->setToolTip(1, tr("Light falloff rate (POV-Ray only).")); + switch (LightType) { case lcLightType::Point: @@ -1624,6 +1648,14 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) mLightPowerItem->setText(1, lcFormatValueLocalized(Power)); mLightPowerItem->setData(0, PropertyValueRole, Power); + mLightAttenuationDistanceItem->setText(1, lcFormatValueLocalized(AttenuationDistance)); + mLightAttenuationDistanceItem->setData(0, PropertyValueRole, AttenuationDistance); + mLightAttenuationDistanceItem->setData(0, PropertyRangeRole, QPointF(0.0, FLT_MAX)); + + mLightAttenuationPowerItem->setText(1, lcFormatValueLocalized(AttenuationPower)); + mLightAttenuationPowerItem->setData(0, PropertyValueRole, AttenuationPower); + mLightAttenuationPowerItem->setData(0, PropertyRangeRole, QPointF(0.0, FLT_MAX)); + lightFormat->setText(1, Format); lightFormat->setData(0, PropertyValueRole, FormatIndex); diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index 148d3244..1eabd9ef 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -125,6 +125,8 @@ protected: QTreeWidgetItem* lightEnableCutoff; QTreeWidgetItem* lightExponent; QTreeWidgetItem* mLightTypeItem; + QTreeWidgetItem* mLightAttenuationDistanceItem; + QTreeWidgetItem* mLightAttenuationPowerItem; QTreeWidgetItem* mLightSpotConeAngleItem; QTreeWidgetItem* mLightSpotPenumbraAngleItem; QTreeWidgetItem* mLightSpotTightnessItem;