Blender lights - merge spot light and directional lights

This commit is contained in:
Trevor SANDY 2023-08-03 18:54:06 +02:00
parent 00a3ad7147
commit 415354bfe8
3 changed files with 285 additions and 243 deletions

View file

@ -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++;

View file

@ -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<lcVector3> 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);
}
}

View file

@ -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;