diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 6069cfad..56909b48 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3163,7 +3163,7 @@ bool lcModel::GetMoveRotateTransform(lcVector3& Center, lcMatrix33& RelativeRota Center += Light->GetSectionPosition(LC_LIGHT_SECTION_POSITION); NumSelected++; - if (Light->IsSpotLight() || Light->IsDirectionalLight()) + if (Light->IsDirectionalLight()) { Center += Light->GetSectionPosition(LC_LIGHT_SECTION_TARGET); NumSelected++; diff --git a/common/light.cpp b/common/light.cpp index fbf11ec2..6865cd3d 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -11,7 +11,8 @@ #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 +#define LC_LIGHT_SUN_RADIUS 8.5f +#define LC_LIGHT_SPOT_BASE_EDGE 12.5f // New omni light. lcLight::lcLight(float px, float py, float pz) @@ -21,15 +22,11 @@ lcLight::lcLight(float px, float py, float pz) UpdatePosition(1); } -// New directional or spot light. +// New directional light. 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), LightType); - if (LightType == LC_SPOTLIGHT) - mState |= LC_LIGHT_SPOT; - else - mState |= LC_LIGHT_DIRECTIONAL; UpdatePosition(1); } @@ -41,10 +38,8 @@ void lcLight::SetLightState(int LightType) { case LC_AREALIGHT: case LC_SUNLIGHT: - mState |= LC_LIGHT_DIRECTIONAL; - break; case LC_SPOTLIGHT: - mState |= LC_LIGHT_SPOT; + mState |= LC_LIGHT_DIRECTIONAL; break; default: break; @@ -152,10 +147,11 @@ void lcLight::SaveLDraw(QTextStream& Stream) const Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; break; case LC_SPOTLIGHT: - if (mLightFactorKeys.GetSize() > 1) { + if (mLightFactorKeys.GetSize() > 1) mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_AND_SPOT_BLEND_KEY "); - } else { - Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; + else + { + Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << (mPOVRayLight ? SpotRadius : mLightFactor[0]) << LineEnding; Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_BLEND ") << mLightFactor[1] << LineEnding; } if (mLightSpotSizeKeys.GetSize() > 1) @@ -164,17 +160,19 @@ void lcLight::SaveLDraw(QTextStream& Stream) const Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_SIZE ") << mSpotSize << LineEnding; break; case LC_AREALIGHT: - if (mLightFactorKeys.GetSize() > 1) { + if (mLightFactorKeys.GetSize() > 1) mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT SIZE_KEY "); - } else { + 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) { + if (mLightShapeKeys.GetSize() > 1) mLightShapeKeys.SaveKeysLDraw(Stream, "LIGHT SHAPE_KEY "); - } else { + else + { Stream << QLatin1String("0 !LEOCAD LIGHT SHAPE "); QString Shape = QLatin1String("Undefined "); @@ -203,15 +201,14 @@ void lcLight::SaveLDraw(QTextStream& Stream) const } if (mLightTypeKeys.GetSize() > 1) - { mLightTypeKeys.SaveKeysLDraw(Stream, "LIGHT TYPE_KEY "); - } else { Stream << QLatin1String("0 !LEOCAD LIGHT TYPE "); QString Type = QLatin1String("Undefined "); - switch(mLightType){ + switch(mLightType) + { case LC_POINTLIGHT: Type = QLatin1String("Point "); break; @@ -376,24 +373,30 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) mName.replace("\"", ""); // Set default settings per light type - if (mLightType == LC_SPOTLIGHT) { - if (!mSpotBlendSet) { + 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) { + if (!mHeightSet) + { mLightFactor[1] = 0.25f; mLightFactorKeys.ChangeKey(mLightFactor, 1, true); } } - if (mLightType == LC_SUNLIGHT) { - if (!mAngleSet) { + if (mLightType == LC_SUNLIGHT) + { + if (!mAngleSet) + { mLightFactor[0] = 11.4f; mLightFactorKeys.ChangeKey(mLightFactor, 1, true); } - if (!mSpotCutoffSet) { + if (!mSpotCutoffSet) + { mSpotCutoff = 0.0f; mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); } @@ -425,7 +428,8 @@ void lcLight::CompareBoundingBox(lcVector3& Min, lcVector3& Max) void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) { - switch(Property){ + switch(Property) + { case LC_LIGHT_SHAPE: mLightShape = Props.mLightShape; mLightShapeKeys.ChangeKey(mLightShape, Step, false); @@ -664,10 +668,8 @@ void lcLight::DrawInterface(lcContext* Context, const lcScene& Scene) const if (IsPointLight()) DrawPointLight(Context); - else if (IsDirectionalLight()) - DrawDirectionalLight(Context); else - DrawSpotLight(Context); + DrawDirectionalLight(Context); } void lcLight::DrawDirectionalLight(lcContext* Context) const @@ -694,210 +696,250 @@ void lcLight::DrawDirectionalLight(lcContext* Context) const 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); - 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)); - const lcMatrix44 LightViewMatrix = lcMul(LightMatrix, lcMatrix44Translation(mPosition)); Context->SetWorldMatrix(LightViewMatrix); + float Length = FrontVector.Length(); + float Verts[(20 + 8 + 2 + 16) * 3]; float* CurVert = Verts; - for (int EdgeIdx = 0; EdgeIdx < 8; EdgeIdx++) + if (mLightType != LC_SUNLIGHT) { - float c = cosf((float)EdgeIdx / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE; - float s = sinf((float)EdgeIdx / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE; + if (mLightType == LC_SPOTLIGHT) + { + 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; + *CurVert++ = c; + *CurVert++ = s; + *CurVert++ = LC_LIGHT_POSITION_EDGE; + *CurVert++ = c; + *CurVert++ = s; + *CurVert++ = -LC_LIGHT_POSITION_EDGE; + } + + *CurVert++ = -LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = -LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + } + else if (mLightType == LC_AREALIGHT) + { + const float LC_LIGHT_AREA_EDGE = 5.0f; + const float LC_LIGHT_AREA_H_EDGE = 8.5f; + const float LC_LIGHT_AREA_W_EDGE = 17.0f; + + *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_POSITION_EDGE; + *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_POSITION_EDGE; + *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + + *CurVert++ = -LC_LIGHT_AREA_H_EDGE; *CurVert++ = -LC_LIGHT_AREA_W_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_AREA_H_EDGE; *CurVert++ = -LC_LIGHT_AREA_W_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_AREA_H_EDGE; *CurVert++ = LC_LIGHT_AREA_W_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = -LC_LIGHT_AREA_H_EDGE; *CurVert++ = LC_LIGHT_AREA_W_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + } + + *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; + + Context->SetVertexBufferPointer(Verts); + Context->SetVertexFormatPosition(3); } - *CurVert++ = -12.5f; *CurVert++ = -12.5f; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = 12.5f; *CurVert++ = -12.5f; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = 12.5f; *CurVert++ = 12.5f; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = -12.5f; *CurVert++ = 12.5f; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + int BaseIndices = 0; - 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] = + if (mLightType == LC_SPOTLIGHT) { - 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, - 16, 17, 17, 18, 18, 19, 19, 16, - 20, 21, 21, 22, 22, 23, 23, 20, - 24, 25, 25, 26, 26, 27, 27, 24, - 20, 24, 21, 25, 22, 26, 23, 27, - 28, 29, - 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, - 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 30, - 28, 30, 28, 34, 28, 38, 28, 42 - }; + BaseIndices = 56; + 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, + 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13, 15, 15, 1, + 16, 17, 17, 18, 18, 19, 19, 16, + 20, 21, 21, 22, 22, 23, 23, 20, + 24, 25, 25, 26, 26, 27, 27, 24, + 20, 24, 21, 25, 22, 26, 23, 27, + 28, 29, + 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, + 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 30, + 28, 30, 28, 34, 28, 38, 28, 42 + }; - Context->SetVertexBufferPointer(Verts); - Context->SetVertexFormatPosition(3); - Context->SetIndexBufferPointer(Indices); + Context->SetIndexBufferPointer(Indices); + } + else if (mLightType == LC_AREALIGHT) + { + BaseIndices = 32; + const GLushort Indices[32 + 24 + 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, 9, 10, 10, 11, 11, 8, + 12, 13, 13, 14, 14, 15, 15, 12, + 16, 17, 17, 18, 18, 19, 19, 16, + 12, 16, 13, 17, 14, 18, 15, 19, + 20, 21 + }; + + Context->SetIndexBufferPointer(Indices); + } + else if (mLightType == LC_SUNLIGHT) + { + constexpr float Radius = LC_LIGHT_SUN_RADIUS; + constexpr int Slices = 9; // longitude + constexpr int Stacks = 9; // latitude + constexpr int NumSphereVertices = 918; // Slices * 2 * 3 * 3 + (Stacks - 2) * Slices * 4 * 3 + constexpr int NumSphereIndices = 306; // Slices * 2 + (Stacks - 1) * Slices * 2 * 2 + + BaseIndices = NumSphereIndices; + + float Vertices[NumSphereVertices + 24 + 6]; + float *Vert = Vertices; + + quint16 Indices[NumSphereIndices + 24 + 2]; + quint16 *Indx = Indices; + + auto AddVertex = [&](float x, float y, float z) + { + *Vert++ = x; + *Vert++ = y; + *Vert++ = z; + }; + + auto AddLineIndex = [&](quint16 v1, quint16 v2) + { + *Indx++ = v1; + *Indx++ = v2; + }; + + std::vector WrkVertices; + + float Slice = LC_2PI / Slices; + float Stack = LC_PI / Stacks; + float SliceAngle, StackAngle; + + for(int i = 0; i <= Stacks; ++i) + { + StackAngle = LC_PI / 2 - i * Stack; // starting from pi/2 to -pi/2 + float xy = Radius * cosf(StackAngle); + float z = Radius * sinf(StackAngle); + + for(int j = 0; j <= Slices; ++j) // add (Slices+1) vertices per stack + { + SliceAngle = j * Slice; + + lcVector3 Vertex; + Vertex.x = xy * cosf(SliceAngle); + Vertex.y = xy * sinf(SliceAngle); + Vertex.z = z; + + WrkVertices.push_back(Vertex); + } + } + + int Index = 0; + + lcVector3 v1, v2, v3, v4; + + for(int i = 0; i < Stacks; ++i) + { + int vi1 = i * (Slices + 1); + int vi2 = (i + 1) * (Slices + 1); + + for(int j = 0; j < Slices; ++j, ++vi1, ++vi2) + { + // 4 vertices per slice + // v1--v3 + // | | + // v2--v4 + v1 = WrkVertices[vi1]; + v2 = WrkVertices[vi2]; + v3 = WrkVertices[vi1 + 1]; + v4 = WrkVertices[vi2 + 1]; + + // if first stack or last stack, store 1 triangle per slice else, store 2 triangles (1 quad) per slice + if(i == 0) + { + // first stack triangle v1-v2-v4 + AddVertex(v1.x, v1.y, v1.z); + AddVertex(v2.x, v2.y, v2.z); + AddVertex(v4.x, v4.y, v4.z); + + // only vertical lines for first stack) + AddLineIndex(Index, Index+1); + + Index += 3; + } + else if(i == (Stacks-1)) + { + // last stack inverted triangle v1-v2-v3 + AddVertex(v1.x, v1.y, v1.z); + AddVertex(v2.x, v2.y, v2.z); + AddVertex(v3.x, v3.y, v3.z); + + // both vertical and horizontal lines for last stack + AddLineIndex(Index, Index+1); + AddLineIndex(Index, Index+2); + + Index += 3; + } + else + { + // 2 triangles (quad vertices v1-v2-v3-v4) for other stacks + AddVertex(v1.x, v1.y, v1.z); + AddVertex(v2.x, v2.y, v2.z); + AddVertex(v3.x, v3.y, v3.z); + AddVertex(v4.x, v4.y, v4.z); + + // both vertical and horizontal lines for other stacks + AddLineIndex(Index, Index+1); + AddLineIndex(Index, Index+2); + + Index += 4; + } + } + } + + AddVertex( LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE - Length); + AddVertex(-LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE - Length); + AddVertex(-LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE - Length); + AddVertex( LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE - Length); + AddVertex( LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE - Length); + AddVertex(-LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE - Length); + AddVertex(-LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE - Length); + AddVertex( LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE - Length); + AddVertex(0.0f, 0.0f, 0.0f); + AddVertex(0.0f, 0.0f, -Length); + + const int Idx[10] = { Index++, Index++, Index++, Index++, Index++, Index++, Index++, Index++, Index++, Index++ }; + AddLineIndex(Idx[0], Idx[1]); AddLineIndex(Idx[1], Idx[2]); AddLineIndex(Idx[2], Idx[3]); AddLineIndex(Idx[3], Idx[0]); + AddLineIndex(Idx[4], Idx[5]); AddLineIndex(Idx[5], Idx[6]); AddLineIndex(Idx[6], Idx[7]); AddLineIndex(Idx[7], Idx[4]); + AddLineIndex(Idx[0], Idx[4]); AddLineIndex(Idx[1], Idx[5]); AddLineIndex(Idx[2], Idx[6]); AddLineIndex(Idx[3], Idx[7]); + AddLineIndex(Idx[8], Idx[9]); + + Context->SetVertexBufferPointer(Vertices); + Context->SetVertexFormatPosition(3); + Context->SetIndexBufferPointer(Indices); + } const lcPreferences& Preferences = lcGetPreferences(); const float LineWidth = Preferences.mLineWidth; @@ -910,7 +952,7 @@ void lcLight::DrawSpotLight(lcContext* Context) const Context->SetLineWidth(LineWidth); Context->SetColor(LightColor); - Context->DrawIndexedPrimitives(GL_LINES, 56 + 24 + 2, GL_UNSIGNED_SHORT, 0); + Context->DrawIndexedPrimitives(GL_LINES, BaseIndices + 24 + 2, GL_UNSIGNED_SHORT, 0); } else { @@ -928,7 +970,7 @@ void lcLight::DrawSpotLight(lcContext* Context) const Context->SetColor(LightColor); } - Context->DrawIndexedPrimitives(GL_LINES, 56, GL_UNSIGNED_SHORT, 0); + Context->DrawIndexedPrimitives(GL_LINES, BaseIndices, GL_UNSIGNED_SHORT, 0); if (IsSelected(LC_LIGHT_SECTION_TARGET)) { @@ -944,21 +986,28 @@ void lcLight::DrawSpotLight(lcContext* Context) const Context->SetColor(LightColor); } - Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, 56 * 2); + Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, BaseIndices * 2); Context->SetLineWidth(LineWidth); Context->SetColor(LightColor); - float Radius = tanf(LC_DTOR * mSpotCutoff) * Length; + int SpotCone = 0; - for (int EdgeIdx = 0; EdgeIdx < 16; EdgeIdx++) + if (mLightType == LC_SPOTLIGHT) { - *CurVert++ = cosf((float)EdgeIdx / 16 * LC_2PI) * Radius; - *CurVert++ = sinf((float)EdgeIdx / 16 * LC_2PI) * Radius; - *CurVert++ = -Length; + SpotCone = 40; + + float Radius = tanf(LC_DTOR * mSpotCutoff) * Length; + + for (int EdgeIdx = 0; EdgeIdx < 16; EdgeIdx++) + { + *CurVert++ = cosf((float)EdgeIdx / 16 * LC_2PI) * Radius; + *CurVert++ = sinf((float)EdgeIdx / 16 * LC_2PI) * Radius; + *CurVert++ = -Length; + } } - Context->DrawIndexedPrimitives(GL_LINES, 2 + 40, GL_UNSIGNED_SHORT, (56 + 24) * 2); + Context->DrawIndexedPrimitives(GL_LINES, 2 + SpotCone, GL_UNSIGNED_SHORT, (BaseIndices + 24) * 2); } } diff --git a/common/light.h b/common/light.h index 0163d8d2..f440c8dd 100644 --- a/common/light.h +++ b/common/light.h @@ -5,12 +5,11 @@ #define LC_LIGHT_HIDDEN 0x0001 #define LC_LIGHT_DISABLED 0x0002 -#define LC_LIGHT_SPOT 0x0004 -#define LC_LIGHT_DIRECTIONAL 0x0008 -#define LC_LIGHT_POSITION_SELECTED 0x0010 -#define LC_LIGHT_POSITION_FOCUSED 0x0020 -#define LC_LIGHT_TARGET_SELECTED 0x0040 -#define LC_LIGHT_TARGET_FOCUSED 0x0080 +#define LC_LIGHT_DIRECTIONAL 0x0004 +#define LC_LIGHT_POSITION_SELECTED 0x0008 +#define LC_LIGHT_POSITION_FOCUSED 0x0010 +#define LC_LIGHT_TARGET_SELECTED 0x0020 +#define LC_LIGHT_TARGET_FOCUSED 0x0040 #define LC_LIGHT_SELECTION_MASK (LC_LIGHT_POSITION_SELECTED | LC_LIGHT_TARGET_SELECTED) #define LC_LIGHT_FOCUS_MASK (LC_LIGHT_POSITION_FOCUSED | LC_LIGHT_TARGET_FOCUSED) @@ -79,12 +78,7 @@ public: bool IsPointLight() const { - return (mState & (LC_LIGHT_SPOT | LC_LIGHT_DIRECTIONAL)) == 0; - } - - bool IsSpotLight() const - { - return (mState & LC_LIGHT_SPOT) != 0; + return (mState & LC_LIGHT_DIRECTIONAL) == 0; } bool IsDirectionalLight() const @@ -309,7 +303,6 @@ protected: void DrawDirectionalLight(lcContext* Context) const; void DrawPointLight(lcContext* Context) const; - void DrawSpotLight(lcContext* Context) const; void SetLightState(int LightType); quint32 mState;