2012-03-20 01:57:42 +01:00
|
|
|
#include "lc_global.h"
|
2012-03-29 03:10:55 +02:00
|
|
|
#include "lc_math.h"
|
2012-03-25 01:47:53 +01:00
|
|
|
#include "lc_colors.h"
|
2011-09-07 23:06:51 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include "light.h"
|
2014-04-14 05:20:16 +02:00
|
|
|
#include "lc_application.h"
|
|
|
|
#include "lc_context.h"
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-11-24 01:43:13 +01:00
|
|
|
#define LC_LIGHT_SPHERE_RADIUS 5.0f
|
2023-09-24 03:38:03 +02:00
|
|
|
#define LC_LIGHT_TARGET_RADIUS 2.5f
|
2023-08-26 21:41:16 +02:00
|
|
|
#define LC_LIGHT_SPOT_CONE_HEIGHT 10.0f
|
|
|
|
#define LC_LIGHT_SPOT_CONE_RADIUS 7.5f
|
|
|
|
#define LC_LIGHT_DIRECTIONAL_RADIUS 5.0f
|
|
|
|
#define LC_LIGHT_DIRECTIONAL_HEIGHT 7.5f
|
|
|
|
|
|
|
|
#define LC_LIGHT_POSITION_EDGE 7.5f
|
2014-11-24 01:43:13 +01:00
|
|
|
|
2023-09-02 05:46:29 +02:00
|
|
|
static const std::array<QLatin1String, static_cast<int>(lcLightType::Count)> gLightTypes = { QLatin1String("POINT"), QLatin1String("SPOT"), QLatin1String("DIRECTIONAL"), QLatin1String("AREA") };
|
2023-09-17 19:40:23 +02:00
|
|
|
static const std::array<QLatin1String, static_cast<int>(lcLightAreaShape::Count)> gLightAreaShapes = { QLatin1String("RECTANGLE"), QLatin1String("SQUARE"), QLatin1String("DISK"), QLatin1String("ELLIPSE") };
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2023-09-05 05:53:34 +02:00
|
|
|
lcLight::lcLight(const lcVector3& Position, lcLightType LightType)
|
2023-08-27 04:43:08 +02:00
|
|
|
: lcObject(lcObjectType::Light), mLightType(LightType)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2023-12-27 21:03:41 +01:00
|
|
|
mPosition.Reset(Position);
|
2023-08-27 04:43:08 +02:00
|
|
|
|
2023-09-17 20:45:14 +02:00
|
|
|
UpdateLightType();
|
|
|
|
|
2023-08-13 15:15:52 +02:00
|
|
|
UpdatePosition(1);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2023-09-17 20:45:14 +02:00
|
|
|
void lcLight::UpdateLightType()
|
|
|
|
{
|
2023-12-28 20:42:28 +01:00
|
|
|
lcVector2 Size(0.0f, 0.0f);
|
2023-12-27 21:03:41 +01:00
|
|
|
|
2023-09-17 20:45:14 +02:00
|
|
|
switch (mLightType)
|
|
|
|
{
|
|
|
|
case lcLightType::Point:
|
|
|
|
case lcLightType::Spot:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case lcLightType::Directional:
|
2023-12-27 21:03:41 +01:00
|
|
|
Size = lcVector2(0.00918f * LC_DTOR, 0.0f);
|
2023-09-17 20:45:14 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lcLightType::Area:
|
2023-12-27 21:03:41 +01:00
|
|
|
Size = lcVector2(200.0f, 200.0f);
|
2023-09-17 20:45:14 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lcLightType::Count:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-12-27 21:03:41 +01:00
|
|
|
mSize.Reset(Size);
|
2023-09-17 20:45:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QString lcLight::GetLightTypeString(lcLightType LightType)
|
2023-09-02 05:46:29 +02:00
|
|
|
{
|
|
|
|
switch (LightType)
|
|
|
|
{
|
|
|
|
case lcLightType::Point:
|
2023-12-31 21:55:35 +01:00
|
|
|
return QT_TRANSLATE_NOOP("Light Types", "Point Light");
|
2023-09-02 05:46:29 +02:00
|
|
|
|
|
|
|
case lcLightType::Spot:
|
2023-12-31 21:55:35 +01:00
|
|
|
return QT_TRANSLATE_NOOP("Light Types", "Spot Light");
|
2023-09-02 05:46:29 +02:00
|
|
|
|
|
|
|
case lcLightType::Directional:
|
2023-12-31 21:55:35 +01:00
|
|
|
return QT_TRANSLATE_NOOP("Light Types", "Directional Light");
|
2023-09-02 05:46:29 +02:00
|
|
|
|
|
|
|
case lcLightType::Area:
|
2023-12-31 21:55:35 +01:00
|
|
|
return QT_TRANSLATE_NOOP("Light Types", "Area Light");
|
2023-09-02 05:46:29 +02:00
|
|
|
|
|
|
|
case lcLightType::Count:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2023-12-31 21:55:35 +01:00
|
|
|
QStringList lcLight::GetLightTypeStrings()
|
|
|
|
{
|
|
|
|
QStringList LightTypes;
|
|
|
|
|
|
|
|
for (int LightTypeIndex = 0; LightTypeIndex < static_cast<int>(lcLightType::Count); LightTypeIndex++)
|
|
|
|
LightTypes.push_back(GetLightTypeString(static_cast<lcLightType>(LightTypeIndex)));
|
|
|
|
|
|
|
|
return LightTypes;
|
|
|
|
}
|
|
|
|
|
2023-09-17 19:40:23 +02:00
|
|
|
QString lcLight::GetAreaShapeString(lcLightAreaShape LightAreaShape)
|
|
|
|
{
|
|
|
|
switch (LightAreaShape)
|
|
|
|
{
|
|
|
|
case lcLightAreaShape::Rectangle:
|
|
|
|
return QT_TRANSLATE_NOOP("Light Shapes", "Rectangle");
|
|
|
|
|
|
|
|
case lcLightAreaShape::Square:
|
|
|
|
return QT_TRANSLATE_NOOP("Light Shapes", "Square");
|
|
|
|
|
|
|
|
case lcLightAreaShape::Disk:
|
|
|
|
return QT_TRANSLATE_NOOP("Light Shapes", "Disk");
|
|
|
|
|
|
|
|
case lcLightAreaShape::Ellipse:
|
|
|
|
return QT_TRANSLATE_NOOP("Light Shapes", "Ellipse");
|
|
|
|
|
|
|
|
case lcLightAreaShape::Count:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2023-12-31 21:55:35 +01:00
|
|
|
QStringList lcLight::GetAreaShapeStrings()
|
|
|
|
{
|
|
|
|
QStringList AreaShapes;
|
|
|
|
|
|
|
|
for (int AreaShapeIndex = 0; AreaShapeIndex < static_cast<int>(lcLightAreaShape::Count); AreaShapeIndex++)
|
|
|
|
AreaShapes.push_back(GetAreaShapeString(static_cast<lcLightAreaShape>(AreaShapeIndex)));
|
|
|
|
|
|
|
|
return AreaShapes;
|
|
|
|
}
|
|
|
|
|
2014-09-05 02:24:28 +02:00
|
|
|
void lcLight::SaveLDraw(QTextStream& Stream) const
|
2014-09-02 05:44:51 +02:00
|
|
|
{
|
2023-08-07 11:31:33 +02:00
|
|
|
const QLatin1String LineEnding("\r\n");
|
|
|
|
|
2023-09-02 19:40:52 +02:00
|
|
|
if (!mCastShadow)
|
2023-08-07 13:22:59 +02:00
|
|
|
Stream << QLatin1String("0 !LEOCAD LIGHT SHADOWLESS") << LineEnding;
|
|
|
|
|
2023-12-28 19:21:52 +01:00
|
|
|
mPosition.Save(Stream, "LIGHT", "POSITION");
|
|
|
|
mRotation.Save(Stream, "LIGHT", "ROTATION");
|
2023-12-27 21:03:41 +01:00
|
|
|
mColor.Save(Stream, "LIGHT", "COLOR");
|
|
|
|
mSize.Save(Stream, "LIGHT", "SIZE");
|
|
|
|
mPower.Save(Stream, "LIGHT", "POWER");
|
|
|
|
mAttenuationDistance.Save(Stream, "LIGHT", "ATTENUATION_DISTANCE");
|
|
|
|
mAttenuationPower.Save(Stream, "LIGHT", "ATTENUATION_POWER");
|
2023-09-17 20:45:14 +02:00
|
|
|
|
2023-08-13 15:15:52 +02:00
|
|
|
switch (mLightType)
|
|
|
|
{
|
2023-09-02 05:46:29 +02:00
|
|
|
case lcLightType::Count:
|
2023-08-13 15:15:52 +02:00
|
|
|
case lcLightType::Point:
|
|
|
|
break;
|
2023-08-07 11:31:33 +02:00
|
|
|
|
2023-08-13 15:15:52 +02:00
|
|
|
case lcLightType::Spot:
|
2023-12-27 21:03:41 +01:00
|
|
|
mSpotConeAngle.Save(Stream, "LIGHT", "SPOT_CONE_ANGLE");
|
|
|
|
mSpotPenumbraAngle.Save(Stream, "LIGHT", "SPOT_PENUMBRA_ANGLE");
|
|
|
|
mSpotTightness.Save(Stream, "LIGHT", "SPOT_TIGHTNESS");
|
2023-08-13 15:15:52 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lcLightType::Directional:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case lcLightType::Area:
|
2023-09-17 20:45:14 +02:00
|
|
|
Stream << QLatin1String("0 !LEOCAD LIGHT AREA_SHAPE ") << gLightAreaShapes[static_cast<int>(mAreaShape)] << LineEnding;
|
2023-12-27 21:03:41 +01:00
|
|
|
mAreaGrid.Save(Stream, "LIGHT", "AREA_GRID");
|
2023-08-13 15:15:52 +02:00
|
|
|
break;
|
2023-08-07 11:31:33 +02:00
|
|
|
}
|
2023-08-13 15:15:52 +02:00
|
|
|
|
|
|
|
Stream << QLatin1String("0 !LEOCAD LIGHT TYPE ") << gLightTypes[static_cast<int>(mLightType)] << QLatin1String(" NAME ") << mName << LineEnding;
|
2014-09-02 05:44:51 +02:00
|
|
|
}
|
|
|
|
|
2014-08-07 17:22:33 +02:00
|
|
|
void lcLight::CreateName(const lcArray<lcLight*>& Lights)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2020-12-14 01:27:21 +01:00
|
|
|
if (!mName.isEmpty())
|
2014-12-16 00:55:17 +01:00
|
|
|
{
|
|
|
|
bool Found = false;
|
2019-03-29 01:59:58 +01:00
|
|
|
|
2021-11-15 03:34:24 +01:00
|
|
|
for (const lcLight* Light : Lights)
|
2014-12-16 00:55:17 +01:00
|
|
|
{
|
2020-12-14 01:27:21 +01:00
|
|
|
if (Light->GetName() == mName)
|
2014-12-16 00:55:17 +01:00
|
|
|
{
|
|
|
|
Found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Found)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-12-14 01:27:21 +01:00
|
|
|
int MaxLightNumber = 0;
|
2023-08-07 11:31:33 +02:00
|
|
|
|
2023-08-13 15:15:52 +02:00
|
|
|
QString Prefix;
|
|
|
|
|
|
|
|
switch (mLightType)
|
|
|
|
{
|
|
|
|
case lcLightType::Point:
|
2023-09-02 05:46:29 +02:00
|
|
|
Prefix = QLatin1String("Point Light ");
|
2023-08-13 15:15:52 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lcLightType::Spot:
|
2023-09-10 03:25:34 +02:00
|
|
|
Prefix = QLatin1String("Spot Light ");
|
2023-08-13 15:15:52 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lcLightType::Directional:
|
2023-09-02 05:46:29 +02:00
|
|
|
Prefix = QLatin1String("Directional Light ");
|
2023-08-13 15:15:52 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lcLightType::Area:
|
2023-09-02 05:46:29 +02:00
|
|
|
Prefix = QLatin1String("Area Light ");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case lcLightType::Count:
|
2023-08-13 15:15:52 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2021-11-15 03:34:24 +01:00
|
|
|
for (const lcLight* Light : Lights)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2020-12-14 01:27:21 +01:00
|
|
|
QString LightName = Light->GetName();
|
|
|
|
|
|
|
|
if (LightName.startsWith(Prefix))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2020-12-14 01:27:21 +01:00
|
|
|
bool Ok = false;
|
2021-07-06 02:07:24 +02:00
|
|
|
int LightNumber = LightName.mid(Prefix.size()).toInt(&Ok);
|
2020-12-14 01:27:21 +01:00
|
|
|
|
|
|
|
if (Ok && LightNumber > MaxLightNumber)
|
|
|
|
MaxLightNumber = LightNumber;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-14 01:27:21 +01:00
|
|
|
mName = Prefix + QString::number(MaxLightNumber + 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2023-08-07 11:31:33 +02:00
|
|
|
bool lcLight::ParseLDrawLine(QTextStream& Stream)
|
|
|
|
{
|
|
|
|
while (!Stream.atEnd())
|
|
|
|
{
|
|
|
|
QString Token;
|
|
|
|
Stream >> Token;
|
2023-08-27 04:43:08 +02:00
|
|
|
|
2023-12-28 19:21:52 +01:00
|
|
|
if (mPosition.Load(Stream, Token, "POSITION"))
|
|
|
|
continue;
|
|
|
|
else if (mRotation.Load(Stream, Token, "ROTATION"))
|
|
|
|
continue;
|
2023-12-27 21:03:41 +01:00
|
|
|
else if (mColor.Load(Stream, Token, "COLOR"))
|
|
|
|
continue;
|
|
|
|
else if (mSize.Load(Stream, Token, "SIZE"))
|
2023-10-02 01:24:42 +02:00
|
|
|
continue;
|
2023-12-27 21:03:41 +01:00
|
|
|
else if (mPower.Load(Stream, Token, "POWER"))
|
2023-10-02 01:24:42 +02:00
|
|
|
continue;
|
2023-12-27 21:03:41 +01:00
|
|
|
else if (mAttenuationDistance.Load(Stream, Token, "ATTENUATION_DISTANCE"))
|
2023-10-02 01:24:42 +02:00
|
|
|
continue;
|
2023-12-27 21:03:41 +01:00
|
|
|
else if (mAttenuationPower.Load(Stream, Token, "ATTENUATION_POWER"))
|
2023-12-17 20:37:11 +01:00
|
|
|
continue;
|
2023-12-27 21:03:41 +01:00
|
|
|
else if (mSpotConeAngle.Load(Stream, Token, "SPOT_CONE_ANGLE"))
|
2023-12-17 20:37:11 +01:00
|
|
|
continue;
|
2023-12-27 21:03:41 +01:00
|
|
|
else if (mSpotPenumbraAngle.Load(Stream, Token, "SPOT_PENUMBRA_ANGLE"))
|
2023-10-02 01:24:42 +02:00
|
|
|
continue;
|
2023-12-27 21:03:41 +01:00
|
|
|
else if (mSpotTightness.Load(Stream, Token, "SPOT_TIGHTNESS"))
|
2023-10-02 01:24:42 +02:00
|
|
|
continue;
|
2023-12-27 21:03:41 +01:00
|
|
|
else if (mAreaGrid.Load(Stream, Token, "AREA_GRID"))
|
2023-10-02 01:24:42 +02:00
|
|
|
continue;
|
2023-09-17 20:45:14 +02:00
|
|
|
else if (Token == QLatin1String("AREA_SHAPE"))
|
2023-09-17 19:40:23 +02:00
|
|
|
{
|
|
|
|
QString AreaShape;
|
|
|
|
Stream >> AreaShape;
|
|
|
|
|
|
|
|
for (size_t ShapeIndex = 0; ShapeIndex < gLightAreaShapes.size(); ShapeIndex++)
|
|
|
|
{
|
|
|
|
if (AreaShape == gLightAreaShapes[ShapeIndex])
|
|
|
|
{
|
|
|
|
mAreaShape = static_cast<lcLightAreaShape>(ShapeIndex);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-08-07 11:31:33 +02:00
|
|
|
else if (Token == QLatin1String("TYPE"))
|
|
|
|
{
|
|
|
|
QString Type;
|
|
|
|
Stream >> Type;
|
2023-08-13 15:15:52 +02:00
|
|
|
|
|
|
|
for (size_t TypeIndex = 0; TypeIndex < gLightTypes.size(); TypeIndex++)
|
|
|
|
{
|
|
|
|
if (Type == gLightTypes[TypeIndex])
|
|
|
|
{
|
|
|
|
mLightType = static_cast<lcLightType>(TypeIndex);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2023-08-07 11:31:33 +02:00
|
|
|
}
|
2023-08-07 13:22:59 +02:00
|
|
|
else if (Token == QLatin1String("SHADOWLESS"))
|
|
|
|
{
|
2023-09-02 19:40:52 +02:00
|
|
|
mCastShadow = false;
|
2023-08-07 13:22:59 +02:00
|
|
|
}
|
2023-08-07 11:31:33 +02:00
|
|
|
else if (Token == QLatin1String("NAME"))
|
|
|
|
{
|
|
|
|
mName = Stream.readAll().trimmed();
|
|
|
|
mName.replace("\"", "");
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-02-19 18:53:54 +01:00
|
|
|
void lcLight::CompareBoundingBox(lcVector3& Min, lcVector3& Max)
|
2014-11-10 01:06:11 +01:00
|
|
|
{
|
2023-09-05 05:53:34 +02:00
|
|
|
const lcVector3 Point = mWorldMatrix.GetTranslation();
|
2014-11-10 01:06:11 +01:00
|
|
|
|
2023-09-05 05:53:34 +02:00
|
|
|
// TODO: this should check the entire mesh
|
2014-11-10 01:06:11 +01:00
|
|
|
|
2023-09-05 05:53:34 +02:00
|
|
|
Min = lcMin(Point, Min);
|
|
|
|
Max = lcMax(Point, Max);
|
2014-11-10 01:06:11 +01:00
|
|
|
}
|
|
|
|
|
2014-05-01 20:42:11 +02:00
|
|
|
void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2014-05-01 16:55:12 +02:00
|
|
|
if (IsPointLight())
|
2012-09-10 01:42:57 +02:00
|
|
|
{
|
2014-05-01 16:55:12 +02:00
|
|
|
float Distance;
|
2012-09-10 01:42:57 +02:00
|
|
|
|
2023-09-05 05:53:34 +02:00
|
|
|
if (lcSphereRayMinIntersectDistance(mWorldMatrix.GetTranslation(), LC_LIGHT_SPHERE_RADIUS, ObjectRayTest.Start, ObjectRayTest.End, &Distance) && (Distance < ObjectRayTest.Distance))
|
2014-05-01 16:55:12 +02:00
|
|
|
{
|
2014-08-07 17:22:33 +02:00
|
|
|
ObjectRayTest.ObjectSection.Object = const_cast<lcLight*>(this);
|
2014-05-01 16:55:12 +02:00
|
|
|
ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_POSITION;
|
|
|
|
ObjectRayTest.Distance = Distance;
|
2012-09-10 01:42:57 +02:00
|
|
|
}
|
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
return;
|
2012-09-10 01:42:57 +02:00
|
|
|
}
|
2014-05-01 16:55:12 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
if (mLightType == lcLightType::Spot)
|
|
|
|
{
|
2023-09-05 05:53:34 +02:00
|
|
|
const lcVector3 Direction = -lcVector3(mWorldMatrix[2]);
|
|
|
|
const lcVector3 Position = mWorldMatrix.GetTranslation() - Direction * LC_LIGHT_SPOT_CONE_HEIGHT;
|
2023-08-26 21:41:16 +02:00
|
|
|
float Distance;
|
|
|
|
|
2023-09-05 05:53:34 +02:00
|
|
|
if (lcConeRayMinIntersectDistance(Position, Direction, LC_LIGHT_SPOT_CONE_RADIUS, LC_LIGHT_SPOT_CONE_HEIGHT, ObjectRayTest.Start, ObjectRayTest.End, &Distance) && (Distance < ObjectRayTest.Distance))
|
2023-08-26 21:41:16 +02:00
|
|
|
{
|
|
|
|
ObjectRayTest.ObjectSection.Object = const_cast<lcLight*>(this);
|
|
|
|
ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_POSITION;
|
|
|
|
ObjectRayTest.Distance = Distance;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (mLightType == lcLightType::Area)
|
|
|
|
{
|
2023-09-05 05:53:34 +02:00
|
|
|
const lcVector3 Direction = -lcVector3(mWorldMatrix[2]);
|
|
|
|
const lcVector3 Position = mWorldMatrix.GetTranslation();
|
|
|
|
const lcVector4 Plane(Direction, -lcDot(Direction, Position));
|
2023-08-26 21:41:16 +02:00
|
|
|
lcVector3 Intersection;
|
|
|
|
|
|
|
|
if (lcLineSegmentPlaneIntersection(&Intersection, ObjectRayTest.Start, ObjectRayTest.End, Plane))
|
|
|
|
{
|
2023-09-05 05:53:34 +02:00
|
|
|
const lcVector3 XAxis = lcVector3(mWorldMatrix[0]);
|
|
|
|
const lcVector3 YAxis = lcVector3(mWorldMatrix[1]);
|
|
|
|
lcVector3 IntersectionDirection = Intersection - Position;
|
2023-08-26 21:41:16 +02:00
|
|
|
|
|
|
|
float x = lcDot(IntersectionDirection, XAxis);
|
|
|
|
float y = lcDot(IntersectionDirection, YAxis);
|
2023-12-27 21:03:41 +01:00
|
|
|
const lcVector2& Size = mSize;
|
2023-08-26 21:41:16 +02:00
|
|
|
|
2023-12-27 21:03:41 +01:00
|
|
|
if (fabsf(x) < Size.x / 2.0f && fabsf(y) < Size.y / 2.0f)
|
2023-08-26 21:41:16 +02:00
|
|
|
{
|
|
|
|
float Distance = lcLength(Intersection - ObjectRayTest.Start);
|
|
|
|
|
|
|
|
if (Distance < ObjectRayTest.Distance)
|
|
|
|
{
|
|
|
|
ObjectRayTest.ObjectSection.Object = const_cast<lcLight*>(this);
|
|
|
|
ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_POSITION;
|
|
|
|
ObjectRayTest.Distance = Distance;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-01 16:55:12 +02:00
|
|
|
|
2023-09-05 05:53:34 +02:00
|
|
|
const lcMatrix44 InverseWorldMatrix = lcMatrix44AffineInverse(mWorldMatrix);
|
|
|
|
lcVector3 Start = lcMul31(ObjectRayTest.Start, InverseWorldMatrix);
|
|
|
|
lcVector3 End = lcMul31(ObjectRayTest.End, InverseWorldMatrix);
|
2014-05-01 16:55:12 +02:00
|
|
|
|
|
|
|
float Distance;
|
2021-12-25 00:42:37 +01:00
|
|
|
lcVector3 Plane;
|
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
if (mLightType == lcLightType::Directional)
|
2012-09-10 01:42:57 +02:00
|
|
|
{
|
2023-08-26 21:41:16 +02:00
|
|
|
if (lcCylinderRayMinIntersectDistance(LC_LIGHT_DIRECTIONAL_RADIUS, LC_LIGHT_DIRECTIONAL_HEIGHT, Start, End, &Distance) && (Distance < ObjectRayTest.Distance))
|
|
|
|
{
|
|
|
|
ObjectRayTest.ObjectSection.Object = const_cast<lcLight*>(this);
|
|
|
|
ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_POSITION;
|
|
|
|
ObjectRayTest.Distance = Distance;
|
|
|
|
ObjectRayTest.PieceInfoRayTest.Plane = Plane;
|
|
|
|
}
|
2014-05-01 16:55:12 +02:00
|
|
|
}
|
2023-09-24 03:38:03 +02:00
|
|
|
|
|
|
|
if (IsSelected())
|
|
|
|
{
|
|
|
|
if (lcSphereRayMinIntersectDistance(lcMul31(lcVector3(0,0,-mTargetDistance), mWorldMatrix), LC_LIGHT_TARGET_RADIUS, ObjectRayTest.Start, ObjectRayTest.End, &Distance) && (Distance < ObjectRayTest.Distance))
|
|
|
|
{
|
|
|
|
ObjectRayTest.ObjectSection.Object = const_cast<lcLight*>(this);
|
|
|
|
ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_TARGET;
|
|
|
|
ObjectRayTest.Distance = Distance;
|
|
|
|
}
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2014-05-01 20:42:11 +02:00
|
|
|
void lcLight::BoxTest(lcObjectBoxTest& ObjectBoxTest) const
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2014-05-01 16:55:12 +02:00
|
|
|
if (IsPointLight())
|
2012-09-10 01:42:57 +02:00
|
|
|
{
|
2014-05-01 16:55:12 +02:00
|
|
|
for (int PlaneIdx = 0; PlaneIdx < 6; PlaneIdx++)
|
2023-09-05 05:53:34 +02:00
|
|
|
if (lcDot3(mWorldMatrix.GetTranslation(), ObjectBoxTest.Planes[PlaneIdx]) + ObjectBoxTest.Planes[PlaneIdx][3] > LC_LIGHT_SPHERE_RADIUS)
|
2014-05-01 16:55:12 +02:00
|
|
|
return;
|
2012-09-10 01:42:57 +02:00
|
|
|
|
2014-11-29 03:55:58 +01:00
|
|
|
ObjectBoxTest.Objects.Add(const_cast<lcLight*>(this));
|
2014-05-01 16:55:12 +02:00
|
|
|
return;
|
2012-09-10 01:42:57 +02:00
|
|
|
}
|
2023-09-05 05:53:34 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
lcVector3 Min(-LC_LIGHT_POSITION_EDGE, -LC_LIGHT_POSITION_EDGE, -LC_LIGHT_POSITION_EDGE); // todo: fix light box test
|
2023-09-05 05:53:34 +02:00
|
|
|
lcVector3 Max( LC_LIGHT_POSITION_EDGE, LC_LIGHT_POSITION_EDGE, LC_LIGHT_POSITION_EDGE);
|
2014-05-01 16:55:12 +02:00
|
|
|
|
|
|
|
lcVector4 LocalPlanes[6];
|
|
|
|
|
|
|
|
for (int PlaneIdx = 0; PlaneIdx < 6; PlaneIdx++)
|
2012-09-10 01:42:57 +02:00
|
|
|
{
|
2023-09-05 05:53:34 +02:00
|
|
|
const lcVector3 Normal = lcMul30(ObjectBoxTest.Planes[PlaneIdx], mWorldMatrix);
|
|
|
|
LocalPlanes[PlaneIdx] = lcVector4(Normal, ObjectBoxTest.Planes[PlaneIdx][3] - lcDot3(mWorldMatrix[3], Normal));
|
2012-08-17 01:50:40 +02:00
|
|
|
}
|
2014-05-01 16:55:12 +02:00
|
|
|
|
|
|
|
if (lcBoundingBoxIntersectsVolume(Min, Max, LocalPlanes))
|
2012-08-17 01:50:40 +02:00
|
|
|
{
|
2014-11-29 03:55:58 +01:00
|
|
|
ObjectBoxTest.Objects.Add(const_cast<lcLight*>(this));
|
|
|
|
return;
|
2012-08-17 01:50:40 +02:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2023-09-24 03:38:03 +02:00
|
|
|
void lcLight::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance, bool FirstMove)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2023-09-24 03:38:03 +02:00
|
|
|
const quint32 Section = GetFocusSection();
|
|
|
|
|
|
|
|
if (Section == LC_LIGHT_SECTION_POSITION || Section == LC_LIGHT_SECTION_INVALID)
|
2012-06-07 02:08:59 +02:00
|
|
|
{
|
2023-09-05 05:53:34 +02:00
|
|
|
const lcVector3 Position = mWorldMatrix.GetTranslation() + Distance;
|
2023-08-27 04:43:08 +02:00
|
|
|
|
2023-09-05 05:53:34 +02:00
|
|
|
SetPosition(Position, Step, AddKey);
|
2023-08-27 04:43:08 +02:00
|
|
|
|
2023-09-05 05:53:34 +02:00
|
|
|
mWorldMatrix.SetTranslation(Position);
|
2023-08-27 04:43:08 +02:00
|
|
|
}
|
2023-09-24 03:38:03 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (FirstMove)
|
|
|
|
mTargetMovePosition = lcMul31(lcVector3(0.0f, 0.0f, -mTargetDistance), mWorldMatrix);
|
|
|
|
|
|
|
|
mTargetMovePosition += Distance;
|
|
|
|
|
|
|
|
lcVector3 CurrentDirection = -lcNormalize(mTargetMovePosition - mWorldMatrix.GetTranslation());
|
|
|
|
lcMatrix33 WorldMatrix;
|
|
|
|
|
|
|
|
WorldMatrix.r[0] = lcCross(lcVector3(mWorldMatrix.r[1]), CurrentDirection);
|
|
|
|
WorldMatrix.r[1] = lcCross(CurrentDirection, WorldMatrix.r[0]);
|
|
|
|
WorldMatrix.r[2] = CurrentDirection;
|
|
|
|
|
|
|
|
WorldMatrix.Orthonormalize();
|
|
|
|
|
|
|
|
SetRotation(WorldMatrix, Step, AddKey);
|
|
|
|
|
|
|
|
mWorldMatrix = lcMatrix44(WorldMatrix, mWorldMatrix.GetTranslation());
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2023-09-05 05:53:34 +02:00
|
|
|
void lcLight::Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcVector3& Center, const lcMatrix33& RotationFrame)
|
2023-09-04 19:59:16 +02:00
|
|
|
{
|
|
|
|
if (IsPointLight())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (GetFocusSection() != LC_LIGHT_SECTION_POSITION)
|
|
|
|
return;
|
|
|
|
|
2023-09-05 05:53:34 +02:00
|
|
|
lcVector3 Distance = mWorldMatrix.GetTranslation() - Center;
|
|
|
|
const lcMatrix33 LocalToWorldMatrix = lcMatrix33(mWorldMatrix);
|
2023-09-04 19:59:16 +02:00
|
|
|
|
|
|
|
const lcMatrix33 LocalToFocusMatrix = lcMul(LocalToWorldMatrix, RotationFrame);
|
|
|
|
lcMatrix33 NewLocalToWorldMatrix = lcMul(LocalToFocusMatrix, RotationMatrix);
|
|
|
|
|
|
|
|
const lcMatrix33 WorldToLocalMatrix = lcMatrix33AffineInverse(LocalToWorldMatrix);
|
|
|
|
|
2023-09-05 05:53:34 +02:00
|
|
|
Distance = lcMul(Distance, WorldToLocalMatrix);
|
|
|
|
Distance = lcMul(Distance, NewLocalToWorldMatrix);
|
2023-09-04 19:59:16 +02:00
|
|
|
|
2023-09-05 05:53:34 +02:00
|
|
|
NewLocalToWorldMatrix.Orthonormalize();
|
2023-09-04 19:59:16 +02:00
|
|
|
|
2023-09-05 05:53:34 +02:00
|
|
|
SetPosition(Center + Distance, Step, AddKey);
|
|
|
|
SetRotation(NewLocalToWorldMatrix, Step, AddKey);
|
2023-09-04 19:59:16 +02:00
|
|
|
}
|
|
|
|
|
2023-09-17 19:40:23 +02:00
|
|
|
bool lcLight::SetLightType(lcLightType LightType)
|
2023-09-02 05:46:29 +02:00
|
|
|
{
|
|
|
|
if (static_cast<int>(LightType) < 0 || LightType >= lcLightType::Count)
|
2023-09-17 19:40:23 +02:00
|
|
|
return false;
|
2023-09-02 05:46:29 +02:00
|
|
|
|
2023-09-17 20:45:14 +02:00
|
|
|
if (mLightType == LightType)
|
|
|
|
return false;
|
2023-09-17 19:40:23 +02:00
|
|
|
|
2023-09-17 20:45:14 +02:00
|
|
|
mLightType = LightType;
|
|
|
|
|
|
|
|
UpdateLightType();
|
|
|
|
|
|
|
|
return true;
|
2023-09-02 05:46:29 +02:00
|
|
|
}
|
|
|
|
|
2023-08-27 20:17:07 +02:00
|
|
|
void lcLight::SetColor(const lcVector3& Color, lcStep Step, bool AddKey)
|
|
|
|
{
|
2023-12-28 19:27:00 +01:00
|
|
|
mColor.ChangeKey(Color, Step, AddKey);
|
2023-08-27 20:17:07 +02:00
|
|
|
}
|
|
|
|
|
2023-12-17 20:37:11 +01:00
|
|
|
void lcLight::SetAttenuationDistance(float Distance, lcStep Step, bool AddKey)
|
|
|
|
{
|
2023-12-28 19:27:00 +01:00
|
|
|
mAttenuationDistance.ChangeKey(Distance, Step, AddKey);
|
2023-12-17 20:37:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void lcLight::SetAttenuationPower(float Power, lcStep Step, bool AddKey)
|
|
|
|
{
|
2023-12-28 19:27:00 +01:00
|
|
|
mAttenuationPower.ChangeKey(Power, Step, AddKey);
|
2023-12-17 20:37:11 +01:00
|
|
|
}
|
|
|
|
|
2023-09-10 03:25:34 +02:00
|
|
|
void lcLight::SetSpotConeAngle(float Angle, lcStep Step, bool AddKey)
|
|
|
|
{
|
2023-12-28 19:27:00 +01:00
|
|
|
mSpotConeAngle.ChangeKey(Angle, Step, AddKey);
|
2023-09-10 03:25:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void lcLight::SetSpotPenumbraAngle(float Angle, lcStep Step, bool AddKey)
|
|
|
|
{
|
2023-12-28 19:27:00 +01:00
|
|
|
mSpotPenumbraAngle.ChangeKey(Angle, Step, AddKey);
|
2023-09-10 03:25:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void lcLight::SetSpotTightness(float Tightness, lcStep Step, bool AddKey)
|
|
|
|
{
|
2023-12-28 19:27:00 +01:00
|
|
|
mSpotTightness.ChangeKey(Tightness, Step, AddKey);
|
2023-09-10 03:25:34 +02:00
|
|
|
}
|
|
|
|
|
2023-09-17 19:40:23 +02:00
|
|
|
bool lcLight::SetAreaShape(lcLightAreaShape AreaShape)
|
|
|
|
{
|
|
|
|
if (static_cast<int>(AreaShape) < 0 || AreaShape >= lcLightAreaShape::Count)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (mAreaShape != AreaShape)
|
|
|
|
{
|
|
|
|
mAreaShape = AreaShape;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-11-20 03:05:43 +01:00
|
|
|
bool lcLight::SetAreaGrid(lcVector2i AreaGrid, lcStep Step, bool AddKey)
|
|
|
|
{
|
2023-12-28 19:27:00 +01:00
|
|
|
mAreaGrid.ChangeKey(AreaGrid, Step, AddKey);
|
2023-11-20 03:05:43 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-09-17 20:45:14 +02:00
|
|
|
void lcLight::SetSize(lcVector2 Size, lcStep Step, bool AddKey)
|
2023-09-17 19:40:23 +02:00
|
|
|
{
|
2023-09-17 20:45:14 +02:00
|
|
|
if (mLightType == lcLightType::Area && (mAreaShape == lcLightAreaShape::Square || mAreaShape == lcLightAreaShape::Disk))
|
|
|
|
Size[1] = Size[0];
|
2023-09-17 19:40:23 +02:00
|
|
|
|
2023-12-28 19:27:00 +01:00
|
|
|
mSize.ChangeKey(Size, Step, AddKey);
|
2023-09-17 19:40:23 +02:00
|
|
|
}
|
|
|
|
|
2023-10-01 22:16:26 +02:00
|
|
|
void lcLight::SetPower(float Power, lcStep Step, bool AddKey)
|
|
|
|
{
|
2023-12-28 19:27:00 +01:00
|
|
|
mPower.ChangeKey(Power, Step, AddKey);
|
2023-10-01 22:16:26 +02:00
|
|
|
}
|
|
|
|
|
2023-09-17 19:40:23 +02:00
|
|
|
bool lcLight::SetCastShadow(bool CastShadow)
|
2023-09-02 19:40:52 +02:00
|
|
|
{
|
2023-09-17 19:40:23 +02:00
|
|
|
if (mCastShadow != CastShadow)
|
|
|
|
{
|
|
|
|
mCastShadow = CastShadow;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2023-09-02 19:40:52 +02:00
|
|
|
}
|
|
|
|
|
2014-08-31 02:53:12 +02:00
|
|
|
void lcLight::InsertTime(lcStep Start, lcStep Time)
|
|
|
|
{
|
2023-12-27 21:03:41 +01:00
|
|
|
mPosition.InsertTime(Start, Time);
|
|
|
|
mRotation.InsertTime(Start, Time);
|
|
|
|
mColor.InsertTime(Start, Time);
|
|
|
|
mSpotConeAngle.InsertTime(Start, Time);
|
|
|
|
mSpotPenumbraAngle.InsertTime(Start, Time);
|
|
|
|
mSpotTightness.InsertTime(Start, Time);
|
|
|
|
mAreaGrid.InsertTime(Start, Time);
|
|
|
|
mSize.InsertTime(Start, Time);
|
|
|
|
mPower.InsertTime(Start, Time);
|
|
|
|
mAttenuationDistance.InsertTime(Start, Time);
|
|
|
|
mAttenuationPower.InsertTime(Start, Time);
|
2014-08-31 02:53:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void lcLight::RemoveTime(lcStep Start, lcStep Time)
|
|
|
|
{
|
2023-12-27 21:03:41 +01:00
|
|
|
mPosition.RemoveTime(Start, Time);
|
|
|
|
mRotation.RemoveTime(Start, Time);
|
|
|
|
mColor.RemoveTime(Start, Time);
|
|
|
|
mSpotConeAngle.RemoveTime(Start, Time);
|
|
|
|
mSpotPenumbraAngle.RemoveTime(Start, Time);
|
|
|
|
mSpotTightness.RemoveTime(Start, Time);
|
|
|
|
mAreaGrid.RemoveTime(Start, Time);
|
|
|
|
mSize.RemoveTime(Start, Time);
|
|
|
|
mPower.RemoveTime(Start, Time);
|
|
|
|
mAttenuationDistance.RemoveTime(Start, Time);
|
|
|
|
mAttenuationPower.RemoveTime(Start, Time);
|
2014-08-31 02:53:12 +02:00
|
|
|
}
|
|
|
|
|
2014-07-06 08:04:09 +02:00
|
|
|
void lcLight::UpdatePosition(lcStep Step)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2023-12-27 21:03:41 +01:00
|
|
|
mPosition.Update(Step);
|
|
|
|
mRotation.Update(Step);
|
|
|
|
mColor.Update(Step);
|
|
|
|
mSpotConeAngle.Update(Step);
|
|
|
|
mSpotPenumbraAngle.Update(Step);
|
|
|
|
mSpotTightness.Update(Step);
|
|
|
|
mAreaGrid.Update(Step);
|
|
|
|
mSize.Update(Step);
|
|
|
|
mPower.Update(Step);
|
|
|
|
mAttenuationDistance.Update(Step);
|
|
|
|
mAttenuationPower.Update(Step);
|
2023-09-05 05:53:34 +02:00
|
|
|
|
|
|
|
if (IsPointLight())
|
|
|
|
{
|
2023-12-27 21:03:41 +01:00
|
|
|
mWorldMatrix = lcMatrix44Translation(mPosition);
|
2023-09-05 05:53:34 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-12-27 21:03:41 +01:00
|
|
|
mWorldMatrix = lcMatrix44(mRotation, mPosition);
|
2023-09-05 05:53:34 +02:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2018-04-08 02:17:32 +02:00
|
|
|
void lcLight::DrawInterface(lcContext* Context, const lcScene& Scene) const
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2018-04-08 02:17:32 +02:00
|
|
|
Q_UNUSED(Scene);
|
2020-03-22 21:44:20 +01:00
|
|
|
Context->SetMaterial(lcMaterialType::UnlitColor);
|
2015-12-11 02:46:30 +01:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
switch (mLightType)
|
|
|
|
{
|
|
|
|
case lcLightType::Point:
|
2015-05-17 01:04:35 +02:00
|
|
|
DrawPointLight(Context);
|
2023-08-26 21:41:16 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lcLightType::Spot:
|
|
|
|
DrawSpotLight(Context);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case lcLightType::Directional:
|
2023-08-03 18:54:06 +02:00
|
|
|
DrawDirectionalLight(Context);
|
2023-08-26 21:41:16 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lcLightType::Area:
|
|
|
|
DrawAreaLight(Context);
|
|
|
|
break;
|
2023-09-02 05:46:29 +02:00
|
|
|
|
|
|
|
case lcLightType::Count:
|
|
|
|
break;
|
2023-08-26 21:41:16 +02:00
|
|
|
}
|
2015-04-19 03:10:01 +02:00
|
|
|
}
|
2014-05-01 16:55:12 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
void lcLight::DrawPointLight(lcContext* Context) const
|
2023-08-07 11:31:33 +02:00
|
|
|
{
|
2023-09-05 05:53:34 +02:00
|
|
|
SetupLightMatrix(Context);
|
2023-08-07 11:31:33 +02:00
|
|
|
|
2023-09-24 03:38:03 +02:00
|
|
|
DrawSphere(Context, lcVector3(0.0f, 0.0f, 0.0f), LC_LIGHT_SPHERE_RADIUS);
|
2023-08-26 21:41:16 +02:00
|
|
|
}
|
2023-08-07 11:31:33 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
void lcLight::DrawSpotLight(lcContext* Context) const
|
|
|
|
{
|
2023-09-05 05:53:34 +02:00
|
|
|
SetupLightMatrix(Context);
|
2023-08-03 18:54:06 +02:00
|
|
|
|
2023-09-05 05:53:34 +02:00
|
|
|
constexpr int ConeEdges = 8;
|
2023-08-26 21:41:16 +02:00
|
|
|
float Verts[(ConeEdges + 1) * 3];
|
2023-08-07 11:31:33 +02:00
|
|
|
float* CurVert = Verts;
|
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
for (int EdgeIndex = 0; EdgeIndex < ConeEdges; EdgeIndex++)
|
2023-08-07 11:31:33 +02:00
|
|
|
{
|
2023-08-26 21:41:16 +02:00
|
|
|
float c = cosf((float)EdgeIndex / ConeEdges * LC_2PI) * LC_LIGHT_SPOT_CONE_RADIUS;
|
|
|
|
float s = sinf((float)EdgeIndex / ConeEdges * LC_2PI) * LC_LIGHT_SPOT_CONE_RADIUS;
|
2023-08-07 11:31:33 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
*CurVert++ = c;
|
|
|
|
*CurVert++ = s;
|
|
|
|
*CurVert++ = 0.0f;
|
2023-08-07 11:31:33 +02:00
|
|
|
}
|
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
*CurVert++ = 0.0f;
|
|
|
|
*CurVert++ = 0.0f;
|
|
|
|
*CurVert++ = LC_LIGHT_SPOT_CONE_HEIGHT;
|
2023-08-07 11:31:33 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
Context->SetVertexBufferPointer(Verts);
|
|
|
|
Context->SetVertexFormatPosition(3);
|
2023-08-07 11:31:33 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
const GLushort Indices[(ConeEdges + 4) * 2] =
|
2023-08-07 11:31:33 +02:00
|
|
|
{
|
2023-08-26 21:41:16 +02:00
|
|
|
0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 0,
|
|
|
|
0, 8, 2, 8, 4, 8, 6, 8,
|
|
|
|
};
|
2023-08-07 11:31:33 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
Context->SetIndexBufferPointer(Indices);
|
2023-08-07 11:31:33 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
Context->DrawIndexedPrimitives(GL_LINES, (ConeEdges + 4) * 2, GL_UNSIGNED_SHORT, 0);
|
2023-08-07 11:31:33 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
if (IsSelected())
|
2023-09-24 03:38:03 +02:00
|
|
|
{
|
|
|
|
DrawCone(Context, mTargetDistance);
|
|
|
|
DrawTarget(Context);
|
|
|
|
}
|
2023-08-26 21:41:16 +02:00
|
|
|
}
|
2023-08-03 18:54:06 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
void lcLight::DrawDirectionalLight(lcContext* Context) const
|
|
|
|
{
|
2023-09-05 05:53:34 +02:00
|
|
|
SetupLightMatrix(Context);
|
2023-08-03 18:54:06 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
DrawCylinder(Context, LC_LIGHT_DIRECTIONAL_RADIUS, LC_LIGHT_DIRECTIONAL_HEIGHT);
|
2023-08-07 11:31:33 +02:00
|
|
|
|
2023-09-24 03:38:03 +02:00
|
|
|
if (IsSelected())
|
|
|
|
DrawTarget(Context);
|
2023-08-26 21:41:16 +02:00
|
|
|
}
|
2023-08-07 11:31:33 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
void lcLight::DrawAreaLight(lcContext* Context) const
|
|
|
|
{
|
2023-09-05 05:53:34 +02:00
|
|
|
SetupLightMatrix(Context);
|
2023-08-07 11:31:33 +02:00
|
|
|
|
2023-09-17 19:40:23 +02:00
|
|
|
if (mAreaShape == lcLightAreaShape::Square || mAreaShape == lcLightAreaShape::Rectangle)
|
2023-08-26 21:41:16 +02:00
|
|
|
{
|
|
|
|
float Verts[4 * 3];
|
|
|
|
float* CurVert = Verts;
|
2023-12-27 21:03:41 +01:00
|
|
|
const lcVector2& Size = mSize;
|
2023-08-07 11:31:33 +02:00
|
|
|
|
2023-12-27 21:03:41 +01:00
|
|
|
*CurVert++ = -Size.x / 2.0f;
|
|
|
|
*CurVert++ = -Size.y / 2.0f;
|
2023-08-26 21:41:16 +02:00
|
|
|
*CurVert++ = 0.0f;
|
2015-04-19 03:10:01 +02:00
|
|
|
|
2023-12-27 21:03:41 +01:00
|
|
|
*CurVert++ = Size.x / 2.0f;
|
|
|
|
*CurVert++ = -Size.y / 2.0f;
|
2023-08-26 21:41:16 +02:00
|
|
|
*CurVert++ = 0.0f;
|
2015-04-19 03:10:01 +02:00
|
|
|
|
2023-12-27 21:03:41 +01:00
|
|
|
*CurVert++ = Size.x / 2.0f;
|
|
|
|
*CurVert++ = Size.y / 2.0f;
|
2023-08-26 21:41:16 +02:00
|
|
|
*CurVert++ = 0.0f;
|
2015-04-19 03:10:01 +02:00
|
|
|
|
2023-12-27 21:03:41 +01:00
|
|
|
*CurVert++ = -Size.x / 2.0f;
|
|
|
|
*CurVert++ = Size.y / 2.0f;
|
2023-08-26 21:41:16 +02:00
|
|
|
*CurVert++ = 0.0f;
|
2015-04-19 03:10:01 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
Context->SetVertexBufferPointer(Verts);
|
|
|
|
Context->SetVertexFormatPosition(3);
|
2015-04-19 03:10:01 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
const GLushort Indices[(4 + 2) * 2] =
|
2023-08-03 18:54:06 +02:00
|
|
|
{
|
2023-08-26 21:41:16 +02:00
|
|
|
0, 1, 1, 2, 2, 3, 3, 0,
|
|
|
|
0, 2, 1, 3,
|
|
|
|
};
|
2015-04-19 03:10:01 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
Context->SetIndexBufferPointer(Indices);
|
2015-04-19 03:10:01 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
Context->DrawIndexedPrimitives(GL_LINES, (4 + 2) * 2, GL_UNSIGNED_SHORT, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
constexpr int CircleEdges = 16;
|
2015-04-19 03:10:01 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
float Verts[CircleEdges * 3];
|
|
|
|
float* CurVert = Verts;
|
2015-04-19 03:10:01 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
for (int EdgeIndex = 0; EdgeIndex < CircleEdges; EdgeIndex++)
|
|
|
|
{
|
2023-12-27 21:03:41 +01:00
|
|
|
const lcVector2& Size = mSize;
|
|
|
|
float c = cosf((float)EdgeIndex / CircleEdges * LC_2PI) * Size.x / 2.0f;
|
|
|
|
float s = sinf((float)EdgeIndex / CircleEdges * LC_2PI) * Size.y / 2.0f;
|
2023-08-03 18:54:06 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
*CurVert++ = c;
|
|
|
|
*CurVert++ = s;
|
|
|
|
*CurVert++ = 0.0f;
|
2023-08-03 18:54:06 +02:00
|
|
|
}
|
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
Context->SetVertexBufferPointer(Verts);
|
2023-08-03 18:54:06 +02:00
|
|
|
Context->SetVertexFormatPosition(3);
|
2023-08-26 21:41:16 +02:00
|
|
|
|
|
|
|
const GLushort Indices[(CircleEdges + 2) * 2] =
|
|
|
|
{
|
|
|
|
0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
|
|
|
|
8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 0,
|
|
|
|
0, 8, 4, 12
|
|
|
|
};
|
|
|
|
|
2023-08-03 18:54:06 +02:00
|
|
|
Context->SetIndexBufferPointer(Indices);
|
2023-08-26 21:41:16 +02:00
|
|
|
|
|
|
|
Context->DrawIndexedPrimitives(GL_LINES, (CircleEdges + 2) * 2, GL_UNSIGNED_SHORT, 0);
|
2023-08-03 18:54:06 +02:00
|
|
|
}
|
2014-05-01 16:55:12 +02:00
|
|
|
|
2023-09-24 03:38:03 +02:00
|
|
|
if (IsSelected())
|
|
|
|
DrawTarget(Context);
|
2023-08-26 21:41:16 +02:00
|
|
|
}
|
2015-04-19 03:10:01 +02:00
|
|
|
|
2023-09-05 05:53:34 +02:00
|
|
|
void lcLight::SetupLightMatrix(lcContext* Context) const
|
2023-08-26 21:41:16 +02:00
|
|
|
{
|
2023-09-05 05:53:34 +02:00
|
|
|
Context->SetWorldMatrix(mWorldMatrix);
|
2012-09-10 01:42:57 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
const lcPreferences& Preferences = lcGetPreferences();
|
|
|
|
const float LineWidth = Preferences.mLineWidth;
|
2012-09-10 01:42:57 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
if (IsSelected(LC_LIGHT_SECTION_POSITION))
|
|
|
|
{
|
|
|
|
const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor);
|
|
|
|
const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor);
|
2023-08-03 18:54:06 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
Context->SetLineWidth(2.0f * LineWidth);
|
2023-08-03 18:54:06 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
if (IsFocused(LC_LIGHT_SECTION_POSITION))
|
|
|
|
Context->SetColor(FocusedColor);
|
|
|
|
else
|
|
|
|
Context->SetColor(SelectedColor);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor);
|
2012-09-10 01:42:57 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
Context->SetLineWidth(LineWidth);
|
|
|
|
Context->SetColor(LightColor);
|
2012-09-10 01:42:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-24 03:38:03 +02:00
|
|
|
void lcLight::DrawSphere(lcContext* Context, const lcVector3& Center, float Radius) const
|
2012-09-10 01:42:57 +02:00
|
|
|
{
|
2021-11-15 03:34:24 +01:00
|
|
|
constexpr int Slices = 6;
|
|
|
|
constexpr int NumIndices = 3 * Slices + 6 * Slices * (Slices - 2) + 3 * Slices;
|
|
|
|
constexpr int NumVertices = (Slices - 1) * Slices + 2;
|
2012-09-10 01:42:57 +02:00
|
|
|
lcVector3 Vertices[NumVertices];
|
2017-12-02 21:22:04 +01:00
|
|
|
quint16 Indices[NumIndices];
|
2012-09-10 01:42:57 +02:00
|
|
|
|
|
|
|
lcVector3* Vertex = Vertices;
|
2017-12-02 21:22:04 +01:00
|
|
|
quint16* Index = Indices;
|
2012-09-10 01:42:57 +02:00
|
|
|
|
2023-09-24 03:38:03 +02:00
|
|
|
*Vertex++ = Center + lcVector3(0, 0, Radius);
|
2012-09-10 01:42:57 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
for (int i = 1; i < Slices; i++)
|
2012-09-10 01:42:57 +02:00
|
|
|
{
|
2021-11-15 03:34:24 +01:00
|
|
|
const float r0 = Radius * sinf(i * (LC_PI / Slices));
|
|
|
|
const float z0 = Radius * cosf(i * (LC_PI / Slices));
|
2012-09-10 01:42:57 +02:00
|
|
|
|
|
|
|
for (int j = 0; j < Slices; j++)
|
|
|
|
{
|
2021-11-15 03:34:24 +01:00
|
|
|
const float x0 = r0 * sinf(j * (LC_2PI / Slices));
|
|
|
|
const float y0 = r0 * cosf(j * (LC_2PI / Slices));
|
2012-09-10 01:42:57 +02:00
|
|
|
|
2023-09-24 03:38:03 +02:00
|
|
|
*Vertex++ = Center + lcVector3(x0, y0, z0);
|
2012-06-07 02:08:59 +02:00
|
|
|
}
|
2012-09-10 01:42:57 +02:00
|
|
|
}
|
|
|
|
|
2023-09-24 03:38:03 +02:00
|
|
|
*Vertex++ = Center + lcVector3(0, 0, -Radius);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
for (quint16 i = 0; i < Slices - 1; i++)
|
2012-09-10 01:42:57 +02:00
|
|
|
{
|
|
|
|
*Index++ = 0;
|
|
|
|
*Index++ = 1 + i;
|
|
|
|
*Index++ = 1 + i + 1;
|
2012-06-07 02:08:59 +02:00
|
|
|
}
|
2012-09-10 01:42:57 +02:00
|
|
|
|
|
|
|
*Index++ = 0;
|
|
|
|
*Index++ = 1;
|
|
|
|
*Index++ = 1 + Slices - 1;
|
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
for (quint16 i = 0; i < Slices - 2; i++)
|
2012-09-10 01:42:57 +02:00
|
|
|
{
|
2021-07-06 02:00:41 +02:00
|
|
|
quint16 Row1 = 1 + i * Slices;
|
|
|
|
quint16 Row2 = 1 + (i + 1) * Slices;
|
2012-09-10 01:42:57 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
for (quint16 j = 0; j < Slices - 1; j++)
|
2012-09-10 01:42:57 +02:00
|
|
|
{
|
|
|
|
*Index++ = Row1 + j;
|
|
|
|
*Index++ = Row2 + j + 1;
|
|
|
|
*Index++ = Row2 + j;
|
|
|
|
|
|
|
|
*Index++ = Row1 + j;
|
|
|
|
*Index++ = Row1 + j + 1;
|
|
|
|
*Index++ = Row2 + j + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
*Index++ = Row1 + Slices - 1;
|
|
|
|
*Index++ = Row2 + 0;
|
|
|
|
*Index++ = Row2 + Slices - 1;
|
|
|
|
|
|
|
|
*Index++ = Row1 + Slices - 1;
|
|
|
|
*Index++ = Row2 + 0;
|
|
|
|
*Index++ = Row1 + 0;
|
|
|
|
}
|
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
for (quint16 i = 0; i < Slices - 1; i++)
|
2012-09-10 01:42:57 +02:00
|
|
|
{
|
|
|
|
*Index++ = (Slices - 1) * Slices + 1;
|
|
|
|
*Index++ = (Slices - 1) * (Slices - 1) + i;
|
|
|
|
*Index++ = (Slices - 1) * (Slices - 1) + i + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
*Index++ = (Slices - 1) * Slices + 1;
|
|
|
|
*Index++ = (Slices - 1) * (Slices - 1) + (Slices - 2) + 1;
|
|
|
|
*Index++ = (Slices - 1) * (Slices - 1);
|
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
Context->SetVertexBufferPointer(Vertices);
|
|
|
|
Context->SetVertexFormatPosition(3);
|
|
|
|
Context->SetIndexBufferPointer(Indices);
|
2015-04-19 03:10:01 +02:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLES, NumIndices, GL_UNSIGNED_SHORT, 0);
|
|
|
|
}
|
2021-11-25 00:20:08 +01:00
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
void lcLight::DrawCylinder(lcContext* Context, float Radius, float Height) const
|
|
|
|
{
|
|
|
|
constexpr int Slices = 8;
|
|
|
|
|
|
|
|
float Verts[(Slices * 2) * 3];
|
|
|
|
float* CurVert = Verts;
|
|
|
|
|
|
|
|
for (int EdgeIndex = 0; EdgeIndex < Slices; EdgeIndex++)
|
2021-11-25 00:20:08 +01:00
|
|
|
{
|
2023-08-26 21:41:16 +02:00
|
|
|
float c = cosf((float)EdgeIndex / Slices * LC_2PI) * Radius;
|
|
|
|
float s = sinf((float)EdgeIndex / Slices * LC_2PI) * Radius;
|
|
|
|
|
|
|
|
*CurVert++ = c;
|
|
|
|
*CurVert++ = s;
|
|
|
|
*CurVert++ = Height;
|
|
|
|
*CurVert++ = c;
|
|
|
|
*CurVert++ = s;
|
|
|
|
*CurVert++ = 0.0f;
|
2021-11-25 00:20:08 +01:00
|
|
|
}
|
2023-08-26 21:41:16 +02:00
|
|
|
|
|
|
|
const GLushort Indices[48] =
|
|
|
|
{
|
|
|
|
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,
|
|
|
|
};
|
|
|
|
|
|
|
|
Context->SetVertexBufferPointer(Verts);
|
|
|
|
Context->SetVertexFormatPosition(3);
|
|
|
|
Context->SetIndexBufferPointer(Indices);
|
|
|
|
|
|
|
|
Context->DrawIndexedPrimitives(GL_LINES, 48, GL_UNSIGNED_SHORT, 0);
|
|
|
|
}
|
|
|
|
|
2023-09-24 03:38:03 +02:00
|
|
|
void lcLight::DrawTarget(lcContext* Context) const
|
2023-08-26 21:41:16 +02:00
|
|
|
{
|
2023-09-24 03:38:03 +02:00
|
|
|
float Verts[2 * 3];
|
2023-08-26 21:41:16 +02:00
|
|
|
float* CurVert = Verts;
|
|
|
|
|
|
|
|
*CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f;
|
2023-09-24 03:38:03 +02:00
|
|
|
*CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -mTargetDistance;
|
2023-08-26 21:41:16 +02:00
|
|
|
|
|
|
|
Context->SetVertexBufferPointer(Verts);
|
|
|
|
Context->SetVertexFormatPosition(3);
|
|
|
|
|
2023-09-24 03:38:03 +02:00
|
|
|
const GLushort Indices[2] =
|
2023-08-26 21:41:16 +02:00
|
|
|
{
|
2023-09-24 03:38:03 +02:00
|
|
|
0, 1
|
2023-08-26 21:41:16 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Context->SetIndexBufferPointer(Indices);
|
|
|
|
|
2023-09-24 03:38:03 +02:00
|
|
|
Context->DrawIndexedPrimitives(GL_LINES, 2, GL_UNSIGNED_SHORT, 0);
|
|
|
|
|
|
|
|
const lcPreferences& Preferences = lcGetPreferences();
|
|
|
|
const float LineWidth = Preferences.mLineWidth;
|
|
|
|
|
|
|
|
if (IsSelected(LC_LIGHT_SECTION_TARGET))
|
|
|
|
{
|
|
|
|
const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor);
|
|
|
|
const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor);
|
|
|
|
|
|
|
|
Context->SetLineWidth(2.0f * LineWidth);
|
|
|
|
|
|
|
|
if (IsFocused(LC_LIGHT_SECTION_TARGET))
|
|
|
|
Context->SetColor(FocusedColor);
|
|
|
|
else
|
|
|
|
Context->SetColor(SelectedColor);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor);
|
|
|
|
|
|
|
|
Context->SetLineWidth(LineWidth);
|
|
|
|
Context->SetColor(LightColor);
|
|
|
|
}
|
|
|
|
|
|
|
|
DrawSphere(Context, lcVector3(0.0f, 0.0f, -mTargetDistance), LC_LIGHT_TARGET_RADIUS);
|
2023-08-26 21:41:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void lcLight::DrawCone(lcContext* Context, float TargetDistance) const
|
|
|
|
{
|
|
|
|
constexpr int ConeEdges = 16;
|
2023-09-10 03:25:34 +02:00
|
|
|
const float OuterRadius = tanf(LC_DTOR * mSpotConeAngle / 2.0f) * TargetDistance;
|
2023-08-26 21:41:16 +02:00
|
|
|
|
2023-09-10 03:25:34 +02:00
|
|
|
float Verts[(ConeEdges * 2 + 1) * 3];
|
2023-08-26 21:41:16 +02:00
|
|
|
float* CurVert = Verts;
|
|
|
|
|
|
|
|
for (int EdgeIndex = 0; EdgeIndex < ConeEdges; EdgeIndex++)
|
|
|
|
{
|
2023-09-10 03:25:34 +02:00
|
|
|
const float c = cosf((float)EdgeIndex / ConeEdges * LC_2PI);
|
|
|
|
const float s = sinf((float)EdgeIndex / ConeEdges * LC_2PI);
|
2023-08-26 21:41:16 +02:00
|
|
|
|
2023-09-10 03:25:34 +02:00
|
|
|
*CurVert++ = c * OuterRadius;
|
|
|
|
*CurVert++ = s * OuterRadius;
|
2023-08-26 21:41:16 +02:00
|
|
|
*CurVert++ = -TargetDistance;
|
|
|
|
}
|
|
|
|
|
|
|
|
*CurVert++ = 0.0f;
|
|
|
|
*CurVert++ = 0.0f;
|
|
|
|
*CurVert++ = 0.0f;
|
|
|
|
|
2023-09-10 03:25:34 +02:00
|
|
|
const bool DrawPenumbra = mSpotPenumbraAngle > 1.0f;
|
|
|
|
|
|
|
|
if (DrawPenumbra)
|
|
|
|
{
|
|
|
|
const float InnerRadius = tanf(LC_DTOR * (mSpotConeAngle / 2.0f - mSpotPenumbraAngle)) * TargetDistance;
|
|
|
|
|
|
|
|
for (int EdgeIndex = 0; EdgeIndex < ConeEdges; EdgeIndex++)
|
|
|
|
{
|
|
|
|
const float c = cosf((float)EdgeIndex / ConeEdges * LC_2PI);
|
|
|
|
const float s = sinf((float)EdgeIndex / ConeEdges * LC_2PI);
|
|
|
|
|
|
|
|
*CurVert++ = c * InnerRadius;
|
|
|
|
*CurVert++ = s * InnerRadius;
|
|
|
|
*CurVert++ = -TargetDistance;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-26 21:41:16 +02:00
|
|
|
Context->SetVertexBufferPointer(Verts);
|
2017-03-24 17:34:53 +01:00
|
|
|
Context->SetVertexFormatPosition(3);
|
2023-08-26 21:41:16 +02:00
|
|
|
|
2023-09-10 03:25:34 +02:00
|
|
|
constexpr GLushort Indices[(ConeEdges * 2 + 4) * 2] =
|
2023-08-26 21:41:16 +02:00
|
|
|
{
|
|
|
|
0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
|
|
|
|
8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 0,
|
2023-09-10 03:25:34 +02:00
|
|
|
16, 0, 16, 4, 16, 8, 16, 12,
|
|
|
|
17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25,
|
|
|
|
25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32, 32, 17
|
2023-08-26 21:41:16 +02:00
|
|
|
};
|
|
|
|
|
2015-05-17 01:04:35 +02:00
|
|
|
Context->SetIndexBufferPointer(Indices);
|
2023-08-26 21:41:16 +02:00
|
|
|
|
2023-09-10 03:25:34 +02:00
|
|
|
Context->DrawIndexedPrimitives(GL_LINES, DrawPenumbra ? (ConeEdges * 2 + 4) * 2 : (ConeEdges + 4) * 2, GL_UNSIGNED_SHORT, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2024-01-15 02:41:01 +01:00
|
|
|
bool lcLight::HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const
|
|
|
|
{
|
|
|
|
switch (PropertyId)
|
|
|
|
{
|
|
|
|
case lcObjectPropertyId::PieceId:
|
|
|
|
case lcObjectPropertyId::PieceColor:
|
|
|
|
case lcObjectPropertyId::PieceStepShow:
|
|
|
|
case lcObjectPropertyId::PieceStepHide:
|
|
|
|
case lcObjectPropertyId::CameraName:
|
|
|
|
case lcObjectPropertyId::CameraType:
|
|
|
|
case lcObjectPropertyId::CameraFOV:
|
|
|
|
case lcObjectPropertyId::CameraNear:
|
|
|
|
case lcObjectPropertyId::CameraFar:
|
|
|
|
case lcObjectPropertyId::CameraPositionX:
|
|
|
|
case lcObjectPropertyId::CameraPositionY:
|
|
|
|
case lcObjectPropertyId::CameraPositionZ:
|
|
|
|
case lcObjectPropertyId::CameraTargetX:
|
|
|
|
case lcObjectPropertyId::CameraTargetY:
|
|
|
|
case lcObjectPropertyId::CameraTargetZ:
|
|
|
|
case lcObjectPropertyId::CameraUpX:
|
|
|
|
case lcObjectPropertyId::CameraUpY:
|
|
|
|
case lcObjectPropertyId::CameraUpZ:
|
|
|
|
case lcObjectPropertyId::LightName:
|
|
|
|
case lcObjectPropertyId::LightType:
|
|
|
|
return false;
|
|
|
|
|
|
|
|
case lcObjectPropertyId::LightColor:
|
|
|
|
return mColor.HasKeyFrame(Time);
|
|
|
|
|
|
|
|
case lcObjectPropertyId::LightPower:
|
|
|
|
return mPower.HasKeyFrame(Time);
|
|
|
|
|
|
|
|
case lcObjectPropertyId::LightCastShadow:
|
|
|
|
return false;
|
|
|
|
|
|
|
|
case lcObjectPropertyId::LightAttenuationDistance:
|
|
|
|
return mAttenuationDistance.HasKeyFrame(Time);
|
|
|
|
|
|
|
|
case lcObjectPropertyId::LightAttenuationPower:
|
|
|
|
return mAttenuationPower.HasKeyFrame(Time);
|
|
|
|
|
|
|
|
case lcObjectPropertyId::LightPointSize:
|
|
|
|
case lcObjectPropertyId::LightSpotSize:
|
|
|
|
case lcObjectPropertyId::LightDirectionalSize:
|
|
|
|
case lcObjectPropertyId::LightAreaSize:
|
|
|
|
case lcObjectPropertyId::LightAreaSizeX:
|
|
|
|
case lcObjectPropertyId::LightAreaSizeY:
|
|
|
|
return mSize.HasKeyFrame(Time);
|
|
|
|
|
|
|
|
case lcObjectPropertyId::LightSpotConeAngle:
|
|
|
|
return mSpotConeAngle.HasKeyFrame(Time);
|
|
|
|
|
|
|
|
case lcObjectPropertyId::LightSpotPenumbraAngle:
|
|
|
|
return mSpotPenumbraAngle.HasKeyFrame(Time);
|
|
|
|
|
|
|
|
case lcObjectPropertyId::LightSpotTightness:
|
|
|
|
return mSpotTightness.HasKeyFrame(Time);
|
|
|
|
|
|
|
|
case lcObjectPropertyId::LightAreaShape:
|
|
|
|
return false;
|
|
|
|
|
|
|
|
case lcObjectPropertyId::LightAreaGridX:
|
|
|
|
case lcObjectPropertyId::LightAreaGridY:
|
|
|
|
return mAreaGrid.HasKeyFrame(Time);
|
|
|
|
|
|
|
|
case lcObjectPropertyId::ObjectPositionX:
|
|
|
|
case lcObjectPropertyId::ObjectPositionY:
|
|
|
|
case lcObjectPropertyId::ObjectPositionZ:
|
|
|
|
return mPosition.HasKeyFrame(Time);
|
|
|
|
|
|
|
|
case lcObjectPropertyId::ObjectRotationX:
|
|
|
|
case lcObjectPropertyId::ObjectRotationY:
|
|
|
|
case lcObjectPropertyId::ObjectRotationZ:
|
|
|
|
return mRotation.HasKeyFrame(Time);
|
|
|
|
|
|
|
|
case lcObjectPropertyId::Count:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-02-24 21:47:19 +01:00
|
|
|
void lcLight::RemoveKeyFrames()
|
|
|
|
{
|
2023-12-27 21:03:41 +01:00
|
|
|
mPosition.Reset();
|
|
|
|
mRotation.Reset();
|
|
|
|
mColor.Reset();
|
|
|
|
mSpotConeAngle.Reset();
|
|
|
|
mSpotPenumbraAngle.Reset();
|
|
|
|
mSpotTightness.Reset();
|
|
|
|
mAreaGrid.Reset();
|
|
|
|
mSize.Reset();
|
|
|
|
mPower.Reset();
|
|
|
|
mAttenuationDistance.Reset();
|
|
|
|
mAttenuationPower.Reset();
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|