Blender lights - lcLight

This commit is contained in:
Trevor SANDY 2023-08-07 11:31:33 +02:00
parent 1dd08401d7
commit 07a268ed32
4 changed files with 655 additions and 19 deletions

View file

@ -105,6 +105,7 @@ struct lcMeshSection;
struct lcRenderMesh;
struct lcObjectSection;
struct lcPieceInfoRayTest;
struct lcLightProperties;
class lcTexture;
class lcScene;
class lcViewManipulator;

View file

@ -11,36 +11,81 @@
#define LC_LIGHT_POSITION_EDGE 7.5f
#define LC_LIGHT_TARGET_EDGE 5.0f
#define LC_LIGHT_SPHERE_RADIUS 5.0f
#define LC_LIGHT_BASEFACE_EDGE 12.5f
// New omni light.
lcLight::lcLight(float px, float py, float pz)
: lcObject(lcObjectType::Light)
{
Initialize(lcVector3(px, py, pz), lcVector3(0.0f, 0.0f, 0.0f));
Initialize(lcVector3(px, py, pz), lcVector3(0.0f, 0.0f, 0.0f), LC_POINTLIGHT);
UpdatePosition(1);
}
// New directional or spot light.
lcLight::lcLight(float px, float py, float pz, float tx, float ty, float tz)
lcLight::lcLight(float px, float py, float pz, float tx, float ty, float tz, int LightType)
: lcObject(lcObjectType::Light)
{
Initialize(lcVector3(px, py, pz), lcVector3(tx, ty, tz));
mState |= LC_LIGHT_SPOT;
Initialize(lcVector3(px, py, pz), lcVector3(tx, ty, tz), LightType);
if (LightType == LC_SPOTLIGHT)
mState |= LC_LIGHT_SPOT;
else
mState |= LC_LIGHT_DIRECTIONAL;
UpdatePosition(1);
}
void lcLight::Initialize(const lcVector3& Position, const lcVector3& TargetPosition)
void lcLight::SetLightState(int LightType)
{
mState = 0;
mPositionKeys.ChangeKey(Position, 1, true);
mTargetPositionKeys.ChangeKey(TargetPosition, 1, true);
mAmbientColorKeys.ChangeKey(lcVector4(0.0f, 0.0f, 0.0f, 1.0f), 1, true);
mDiffuseColorKeys.ChangeKey(lcVector4(0.8f, 0.8f, 0.8f, 1.0f), 1, true);
mSpecularColorKeys.ChangeKey(lcVector4(1.0f, 1.0f, 1.0f, 1.0f), 1, true);
mAttenuationKeys.ChangeKey(lcVector3(1.0f, 0.0f, 0.0f), 1, true);
mSpotCutoffKeys.ChangeKey(30.0f, 1, true);
mSpotExponentKeys.ChangeKey(0.0f, 1, true);
switch (LightType)
{
case LC_AREALIGHT:
case LC_SUNLIGHT:
mState |= LC_LIGHT_DIRECTIONAL;
break;
case LC_SPOTLIGHT:
mState |= LC_LIGHT_SPOT;
break;
default:
break;
}
}
void lcLight::Initialize(const lcVector3& Position, const lcVector3& TargetPosition, int LightType)
{
SetLightState(LightType);
mEnableCutoff = false;
mPosition = Position;
mTargetPosition = TargetPosition;
mAmbientColor = lcVector4(0.0f, 0.0f, 0.0f, 1.0f);
mDiffuseColor = lcVector4(0.8f, 0.8f, 0.8f, 1.0f);
mSpecularColor = lcVector4(1.0f, 1.0f, 1.0f, 1.0f);
mAttenuation = lcVector3(1.0f, 0.0f, 0.0f);
mLightColor = lcVector3(1.0f, 1.0f, 1.0f); //RGB - White
mLightType = LightType ? LightType : int(LC_POINTLIGHT);
mLightFactor[0] = LightType ? LightType == LC_SUNLIGHT ? 11.4f : 0.25f : 0.0f;
mLightFactor[1] = LightType == LC_AREALIGHT ? 0.25f : LightType == LC_SPOTLIGHT ? 0.150f : 0.0f;
mLightSpecular = 1.0f;
mSpotSize = 75.0f;
mLightShape = 0 /*Square*/;
mSpotCutoff = LightType ? LightType != LC_SUNLIGHT ? 40.0f : 0.0f : 30.0f;
mSpotExponent = 10.0f; /*Energy/Power*/
mPositionKeys.ChangeKey(mPosition, 1, true);
mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true);
mAmbientColorKeys.ChangeKey(mAmbientColor, 1, true);
mDiffuseColorKeys.ChangeKey(mDiffuseColor, 1, true);
mSpecularColorKeys.ChangeKey(mSpecularColor, 1, true);
mAttenuationKeys.ChangeKey(mAttenuation, 1, true);
mLightShapeKeys.ChangeKey(mLightShape, 1, true);
mLightColorKeys.ChangeKey(mLightColor, 1, true);
mLightTypeKeys.ChangeKey(mLightType, 1, true);
mLightFactorKeys.ChangeKey(mLightFactor, 1, true);
mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true);
mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true);
mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true);
mLightSpotSizeKeys.ChangeKey(mSpotSize, 1, true);
}
lcLight::~lcLight()
@ -49,7 +94,139 @@ lcLight::~lcLight()
void lcLight::SaveLDraw(QTextStream& Stream) const
{
Q_UNUSED(Stream);
const QLatin1String LineEnding("\r\n");
if (mPositionKeys.GetSize() > 1)
mPositionKeys.SaveKeysLDraw(Stream, "LIGHT POSITION_KEY ");
else
Stream << QLatin1String("0 !LEOCAD LIGHT POSITION ") << mPosition[0] << ' ' << mPosition[1] << ' ' << mPosition[2] << LineEnding;
if (mTargetPositionKeys.GetSize() > 1)
mTargetPositionKeys.SaveKeysLDraw(Stream, "LIGHT TARGET_POSITION_KEY ");
else
Stream << QLatin1String("0 !LEOCAD LIGHT TARGET_POSITION ") << mTargetPosition[0] << ' ' << mTargetPosition[1] << ' ' << mTargetPosition[2] << LineEnding;
if (mLightColorKeys.GetSize() > 1)
mLightColorKeys.SaveKeysLDraw(Stream, "LIGHT COLOR_RGB_KEY ");
else
Stream << QLatin1String("0 !LEOCAD LIGHT COLOR_RGB ") << mLightColor[0] << ' ' << mLightColor[1] << ' ' << mLightColor[2] << LineEnding;
if (mLightSpecularKeys.GetSize() > 1)
mLightSpecularKeys.SaveKeysLDraw(Stream, "LIGHT SPECULAR_KEY ");
else
Stream << QLatin1String("0 !LEOCAD LIGHT SPECULAR ") << mLightSpecular << LineEnding;
if (mLightType == LC_SUNLIGHT)
{
if (mSpotExponentKeys.GetSize() > 1)
mSpotExponentKeys.SaveKeysLDraw(Stream, "LIGHT STRENGTH_KEY ");
else
Stream << QLatin1String("0 !LEOCAD LIGHT STRENGTH ") << mSpotExponent << LineEnding;
if (mLightFactorKeys.GetSize() > 1)
mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT ANGLE_KEY ");
else
Stream << QLatin1String("0 !LEOCAD LIGHT ANGLE ") << mLightFactor[0] << LineEnding;
}
else
{
if (mSpotExponentKeys.GetSize() > 1)
mSpotExponentKeys.SaveKeysLDraw(Stream, "LIGHT POWER_KEY ");
else
Stream << QLatin1String("0 !LEOCAD LIGHT POWER ") << mSpotExponent << LineEnding;
if (mEnableCutoff)
{
if (mSpotCutoffKeys.GetSize() > 1)
mSpotCutoffKeys.SaveKeysLDraw(Stream, "LIGHT CUTOFF_DISTANCE_KEY ");
else
Stream << QLatin1String("0 !LEOCAD LIGHT CUTOFF_DISTANCE ") << mSpotCutoff << LineEnding;
}
switch (mLightType)
{
case LC_POINTLIGHT:
if (mLightFactorKeys.GetSize() > 1)
mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_KEY ");
else
Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding;
break;
case LC_SPOTLIGHT:
if (mLightFactorKeys.GetSize() > 1) {
mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_AND_SPOT_BLEND_KEY ");
} else {
Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding;
Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_BLEND ") << mLightFactor[1] << LineEnding;
}
if (mLightSpotSizeKeys.GetSize() > 1)
mLightSpotSizeKeys.SaveKeysLDraw(Stream, "LIGHT SPOT_SIZE_KEY ");
else
Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_SIZE ") << mSpotSize << LineEnding;
break;
case LC_AREALIGHT:
if (mLightFactorKeys.GetSize() > 1) {
mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT SIZE_KEY ");
} else {
if (mLightShape == LC_LIGHT_SHAPE_RECTANGLE || mLightShape == LC_LIGHT_SHAPE_ELLIPSE)
Stream << QLatin1String("0 !LEOCAD LIGHT WIDTH ") << mLightFactor[0] << QLatin1String(" HEIGHT ") << mLightFactor[1] << LineEnding;
else
Stream << QLatin1String("0 !LEOCAD LIGHT SIZE ") << mLightFactor[0] << LineEnding;
}
if (mLightShapeKeys.GetSize() > 1) {
mLightShapeKeys.SaveKeysLDraw(Stream, "LIGHT SHAPE_KEY ");
} else {
Stream << QLatin1String("0 !LEOCAD LIGHT SHAPE ");
QString Shape = QLatin1String("Undefined ");
switch(mLightShape)
{
case LC_LIGHT_SHAPE_SQUARE:
Shape = QLatin1String("Square ");
break;
case LC_LIGHT_SHAPE_DISK:
Shape = QLatin1String("Disk ");
break;
case LC_LIGHT_SHAPE_RECTANGLE:
Shape = QLatin1String("Rectangle ");
break;
case LC_LIGHT_SHAPE_ELLIPSE:
Shape = QLatin1String("Ellipse ");
break;
default:
break;
}
Stream << QLatin1String(Shape.toLatin1()) << LineEnding;
}
break;
}
}
if (mLightTypeKeys.GetSize() > 1)
{
mLightTypeKeys.SaveKeysLDraw(Stream, "LIGHT TYPE_KEY ");
}
else
{
Stream << QLatin1String("0 !LEOCAD LIGHT TYPE ");
QString Type = QLatin1String("Undefined ");
switch(mLightType){
case LC_POINTLIGHT:
Type = QLatin1String("Point ");
break;
case LC_SUNLIGHT:
Type = QLatin1String("Sun ");
break;
case LC_AREALIGHT:
Type = QLatin1String("Area ");
break;
case LC_SPOTLIGHT:
Type = QLatin1String("Spot ");
break;
}
Stream << QLatin1String(Type.toLatin1()) << QLatin1String("NAME ") << mName << LineEnding;
}
}
void lcLight::CreateName(const lcArray<lcLight*>& Lights)
@ -72,7 +249,8 @@ void lcLight::CreateName(const lcArray<lcLight*>& Lights)
}
int MaxLightNumber = 0;
const QLatin1String Prefix("Light ");
const QLatin1String Prefix(mLightType == LC_POINTLIGHT ? "Pointlight " : mLightType == LC_AREALIGHT ? "Arealight " : mLightType == LC_SUNLIGHT ? "Sunlight " : "Spotlight ");
for (const lcLight* Light : Lights)
{
@ -91,6 +269,142 @@ void lcLight::CreateName(const lcArray<lcLight*>& Lights)
mName = Prefix + QString::number(MaxLightNumber + 1);
}
bool lcLight::ParseLDrawLine(QTextStream& Stream)
{
while (!Stream.atEnd())
{
QString Token;
Stream >> Token;
if (Token == QLatin1String("COLOR_RGB"))
{
Stream >> mLightColor[0] >> mLightColor[1] >> mLightColor[2];
mLightColorKeys.ChangeKey(mLightColor, 1, true);
}
else if (Token == QLatin1String("POWER") || Token == QLatin1String("STRENGTH"))
{
Stream >> mSpotExponent;
mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true);
}
else if (Token == QLatin1String("RADIUS") || Token == QLatin1String("SIZE") || Token == QLatin1String("WIDTH") || (mHeightSet = Token == QLatin1String("HEIGHT")) || (mSpotBlendSet = Token == QLatin1String("SPOT_BLEND")) || (mAngleSet = Token == QLatin1String("ANGLE")))
{
if(Token == QLatin1String("HEIGHT") || Token == QLatin1String("SPOT_BLEND"))
Stream >> mLightFactor[1];
else
Stream >> mLightFactor[0];
mLightFactorKeys.ChangeKey(mLightFactor, 1, true);
}
else if (Token == QLatin1String("SPOT_SIZE"))
{
Stream >> mSpotSize;
mLightSpotSizeKeys.ChangeKey(mSpotSize, 1, true);
}
else if (Token == QLatin1String("SHAPE"))
{
QString Shape;
Stream >> Shape;
Shape = Shape.replace("\"", "").toLower();
if (Shape == QLatin1String("square"))
mLightShape = LC_LIGHT_SHAPE_SQUARE;
else if (Shape == QLatin1String("disk") || Shape == QLatin1String("circle"))
mLightShape = LC_LIGHT_SHAPE_DISK;
else if (Shape == QLatin1String("rectangle"))
mLightShape = LC_LIGHT_SHAPE_RECTANGLE;
else if (Shape == QLatin1String("ellipse"))
mLightShape = LC_LIGHT_SHAPE_ELLIPSE;
mLightShapeKeys.ChangeKey(mLightShape, 1, true);
}
else if (Token == QLatin1String("SPECULAR"))
{
Stream >>mLightSpecular;
mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true);
}
else if ((mSpotCutoffSet = Token == QLatin1String("CUTOFF_DISTANCE")))
{
mEnableCutoff = true;
Stream >> mSpotCutoff;
mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true);
}
else if (Token == QLatin1String("TYPE"))
{
QString Type;
Stream >> Type;
Type = Type.replace("\"", "").toLower();
if (Type == QLatin1String("point"))
mLightType = LC_POINTLIGHT;
else if (Type == QLatin1String("sun"))
mLightType = LC_SUNLIGHT;
else if (Type == QLatin1String("spot"))
mLightType = LC_SPOTLIGHT;
else if (Type == QLatin1String("area"))
mLightType = LC_AREALIGHT;
SetLightState(mLightType);
mLightTypeKeys.ChangeKey(mLightType, 1, true);
}
else if (Token == QLatin1String("POSITION"))
{
Stream >> mPosition[0] >> mPosition[1] >> mPosition[2];
mPositionKeys.ChangeKey(mPosition, 1, true);
}
else if (Token == QLatin1String("TARGET_POSITION"))
{
Stream >> mTargetPosition[0] >> mTargetPosition[1] >> mTargetPosition[2];
mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true);
}
else if (Token == QLatin1String("COLOR_RGB_KEY"))
mLightColorKeys.LoadKeysLDraw(Stream);
else if ((Token == QLatin1String("POWER_KEY")) || (Token == QLatin1String("STRENGTH_KEY")))
mSpotExponentKeys.LoadKeysLDraw(Stream);
else if ((Token == QLatin1String("ANGLE_KEY")) || (Token == QLatin1String("RADIUS_KEY")) || (Token == QLatin1String("SIZE_KEY")) || (Token == QLatin1String("RADIUS_AND_SPOT_BLEND_KEY")))
mLightFactorKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("SPOT_SIZE_KEY"))
mLightSpotSizeKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("SHAPE_KEY"))
mLightShapeKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("SPECULAR_KEY"))
mLightSpecularKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("CUTOFF_DISTANCE_KEY"))
mSpotCutoffKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("TYPE_KEY"))
mLightTypeKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("POSITION_KEY"))
mPositionKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("TARGET_POSITION_KEY"))
mTargetPositionKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("NAME"))
{
mName = Stream.readAll().trimmed();
mName.replace("\"", "");
// Set default settings per light type
if (mLightType == LC_SPOTLIGHT) {
if (!mSpotBlendSet) {
mLightFactor[1] = 0.15f;
mLightFactorKeys.ChangeKey(mLightFactor, 1, true);
}
}
if (mLightType == LC_AREALIGHT && (mLightShape == LC_LIGHT_SHAPE_RECTANGLE || mLightShape == LC_LIGHT_SHAPE_ELLIPSE)) {
if (!mHeightSet) {
mLightFactor[1] = 0.25f;
mLightFactorKeys.ChangeKey(mLightFactor, 1, true);
}
}
if (mLightType == LC_SUNLIGHT) {
if (!mAngleSet) {
mLightFactor[0] = 11.4f;
mLightFactorKeys.ChangeKey(mLightFactor, 1, true);
}
if (!mSpotCutoffSet) {
mSpotCutoff = 0.0f;
mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true);
}
}
return true;
}
}
return false;
}
void lcLight::CompareBoundingBox(lcVector3& Min, lcVector3& Max)
{
const lcVector3 Points[2] =
@ -109,6 +423,44 @@ void lcLight::CompareBoundingBox(lcVector3& Min, lcVector3& Max)
}
}
void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property)
{
switch(Property){
case LC_LIGHT_SHAPE:
mLightShape = Props.mLightShape;
mLightShapeKeys.ChangeKey(mLightShape, Step, false);
break;
case LC_LIGHT_COLOR:
mLightColor = Props.mLightColor;
mLightColorKeys.ChangeKey(mLightColor, Step, false);
break;
case LC_LIGHT_FACTOR:
mLightFactor = Props.mLightFactor;
mLightFactorKeys.ChangeKey(mLightFactor, Step, false);
break;
case LC_LIGHT_SPECULAR:
mLightSpecular = Props.mLightSpecular;
mLightSpecularKeys.ChangeKey(mLightSpecular, Step, false);
break;
case LC_LIGHT_EXPONENT:
mSpotExponent = Props.mSpotExponent;
mSpotExponentKeys.ChangeKey(mSpotExponent, Step, false);
break;
case LC_LIGHT_SPOT_SIZE:
mSpotSize = Props.mSpotSize;
mLightSpotSizeKeys.ChangeKey(mSpotSize, Step, false);
break;
case LC_LIGHT_CUTOFF:
mSpotCutoff = Props.mSpotCutoff;
mSpotCutoffKeys.ChangeKey(mSpotCutoff, Step, false);
break;
case LC_LIGHT_USE_CUTOFF:
mEnableCutoff = Props.mEnableCutoff;
break;
}
UpdatePosition(Step);
}
void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const
{
if (IsPointLight())
@ -231,6 +583,12 @@ void lcLight::InsertTime(lcStep Start, lcStep Time)
mDiffuseColorKeys.InsertTime(Start, Time);
mSpecularColorKeys.InsertTime(Start, Time);
mAttenuationKeys.InsertTime(Start, Time);
mLightShapeKeys.InsertTime(Start, Time);
mLightColorKeys.InsertTime(Start, Time);
mLightTypeKeys.InsertTime(Start, Time);
mLightFactorKeys.InsertTime(Start, Time);
mLightSpecularKeys.InsertTime(Start, Time);
mLightSpotSizeKeys.InsertTime(Start, Time);
mSpotCutoffKeys.InsertTime(Start, Time);
mSpotExponentKeys.InsertTime(Start, Time);
}
@ -243,6 +601,12 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time)
mDiffuseColorKeys.RemoveTime(Start, Time);
mSpecularColorKeys.RemoveTime(Start, Time);
mAttenuationKeys.RemoveTime(Start, Time);
mLightShapeKeys.RemoveTime(Start, Time);
mLightColorKeys.RemoveTime(Start, Time);
mLightTypeKeys.RemoveTime(Start, Time);
mLightFactorKeys.RemoveTime(Start, Time);
mLightSpecularKeys.RemoveTime(Start, Time);
mLightSpotSizeKeys.RemoveTime(Start, Time);
mSpotCutoffKeys.RemoveTime(Start, Time);
mSpotExponentKeys.RemoveTime(Start, Time);
}
@ -255,6 +619,12 @@ void lcLight::UpdatePosition(lcStep Step)
mDiffuseColor = mDiffuseColorKeys.CalculateKey(Step);
mSpecularColor = mSpecularColorKeys.CalculateKey(Step);
mAttenuation = mAttenuationKeys.CalculateKey(Step);
mLightShape = mLightShapeKeys.CalculateKey(Step);
mLightColor = mLightColorKeys.CalculateKey(Step);
mLightType = mLightTypeKeys.CalculateKey(Step);
mLightFactor = mLightFactorKeys.CalculateKey(Step);
mLightSpecular = mLightSpecularKeys.CalculateKey(Step);
mSpotSize = mLightSpotSizeKeys.CalculateKey(Step);
mSpotCutoff = mSpotCutoffKeys.CalculateKey(Step);
mSpotExponent = mSpotExponentKeys.CalculateKey(Step);
@ -294,10 +664,160 @@ void lcLight::DrawInterface(lcContext* Context, const lcScene& Scene) const
if (IsPointLight())
DrawPointLight(Context);
else if (IsDirectionalLight())
DrawDirectionalLight(Context);
else
DrawSpotLight(Context);
}
void lcLight::DrawDirectionalLight(lcContext* Context) const
{
lcVector3 FrontVector(mTargetPosition - mPosition);
lcVector3 UpVector(1, 1, 1);
if (fabs(FrontVector[0]) < fabs(FrontVector[1]))
{
if (fabs(FrontVector[0]) < fabs(FrontVector[2]))
UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]);
else
UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]);
}
else
{
if (fabs(FrontVector[1]) < fabs(FrontVector[2]))
UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]);
else
UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]);
}
lcMatrix44 LightMatrix = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector);
LightMatrix = lcMatrix44AffineInverse(LightMatrix);
LightMatrix.SetTranslation(lcVector3(0, 0, 0));
lcMatrix44 LightViewMatrix = lcMul(LightMatrix, lcMatrix44Translation(mPosition));
Context->SetWorldMatrix(LightViewMatrix);
float Verts[(20 + 8 + 2 + 16) * 3];
float* CurVert = Verts;
for (int EdgeIdx = 0; EdgeIdx < 8; EdgeIdx++)
{
float c = cosf(float(EdgeIdx) / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE;
float s = sinf(float(EdgeIdx) / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE;
*CurVert++ = c;
*CurVert++ = s;
*CurVert++ = LC_LIGHT_POSITION_EDGE;
*CurVert++ = c;
*CurVert++ = s;
*CurVert++ = -LC_LIGHT_POSITION_EDGE;
}
if (mLightType == LC_SUNLIGHT) {
// set base face to same size (LC_LIGHT_TARGET_EDGE) as body - was 12.5f
*CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE;
*CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE;
*CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE;
*CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE;
} else {
*CurVert++ = -LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE;
*CurVert++ = LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE;
*CurVert++ = LC_LIGHT_BASEFACE_EDGE; *CurVert++ = LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE;
*CurVert++ = -LC_LIGHT_BASEFACE_EDGE; *CurVert++ = LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE;
}
float Length = FrontVector.Length();
*CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length;
*CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length;
*CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length;
*CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length;
*CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length;
*CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length;
*CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length;
*CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length;
*CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f;
*CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -Length;
const GLushort Indices[56 + 24 + 2 + 40] =
{
// base body
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 0,
1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13, 15, 15, 1,
// base face
16, 17, 17, 18, 18, 19, 19, 16,
// targe box
20, 21, 21, 22, 22, 23, 23, 20,
24, 25, 25, 26, 26, 27, 27, 24,
20, 24, 21, 25, 22, 26, 23, 27,
// target line - from base to target
28, 29,
};
Context->SetVertexBufferPointer(Verts);
Context->SetVertexFormatPosition(3);
Context->SetIndexBufferPointer(Indices);
const lcPreferences& Preferences = lcGetPreferences();
const float LineWidth = Preferences.mLineWidth;
const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor);
const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor);
const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor);
if (!IsSelected())
{
Context->SetLineWidth(LineWidth);
Context->SetColor(LightColor);
Context->DrawIndexedPrimitives(GL_LINES, 56 + 24 + 2, GL_UNSIGNED_SHORT, 0);
}
else
{
if (IsSelected(LC_LIGHT_SECTION_POSITION))
{
Context->SetLineWidth(2.0f * LineWidth);
if (IsFocused(LC_LIGHT_SECTION_POSITION))
Context->SetColor(FocusedColor);
else
Context->SetColor(SelectedColor);
}
else
{
Context->SetLineWidth(LineWidth);
Context->SetColor(LightColor);
}
Context->DrawIndexedPrimitives(GL_LINES, 56, GL_UNSIGNED_SHORT, 0);
if (IsSelected(LC_LIGHT_SECTION_TARGET))
{
Context->SetLineWidth(2.0f * LineWidth);
if (IsFocused(LC_LIGHT_SECTION_TARGET))
Context->SetColor(FocusedColor);
else
Context->SetColor(SelectedColor);
}
else
{
Context->SetLineWidth(LineWidth);
Context->SetColor(LightColor);
}
Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, 56 * 2);
Context->SetLineWidth(LineWidth);
Context->SetColor(LightColor);
Context->DrawIndexedPrimitives(GL_LINES, 2 + 40, GL_UNSIGNED_SHORT, (56 + 24) * 2);
}
}
void lcLight::DrawSpotLight(lcContext* Context) const
{
lcVector3 FrontVector(mTargetPosition - mPosition);
@ -360,7 +880,7 @@ void lcLight::DrawSpotLight(lcContext* Context) const
*CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f;
*CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -Length;
const GLushort Indices[56 + 24 + 2 + 40] =
const GLushort Indices[56 + 24 + 2 + 40] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 0,
@ -565,6 +1085,24 @@ void lcLight::RemoveKeyFrames()
mAttenuationKeys.RemoveAll();
mAttenuationKeys.ChangeKey(mAttenuation, 1, true);
mLightShapeKeys.RemoveAll();
mLightShapeKeys.ChangeKey(mLightShape, 1, false);
mLightColorKeys.RemoveAll();
mLightColorKeys.ChangeKey(mLightColor, 1, true);
mLightFactorKeys.RemoveAll();
mLightFactorKeys.ChangeKey(mLightFactor, 1, true);
mLightTypeKeys.RemoveAll();
mLightTypeKeys.ChangeKey(mLightType, 1, true);
mLightSpecularKeys.RemoveAll();
mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true);
mLightSpotSizeKeys.RemoveAll();
mLightSpotSizeKeys.ChangeKey(mSpotSize, 1, false);
mSpotCutoffKeys.RemoveAll();
mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true);

View file

@ -21,11 +21,55 @@ enum lcLightSection
LC_LIGHT_SECTION_TARGET
};
enum lcLightType
{
LC_UNDEFINED_LIGHT,
LC_POINTLIGHT,
LC_AREALIGHT,
LC_SUNLIGHT,
LC_SPOTLIGHT
};
enum lcLightShape
{
LC_LIGHT_SHAPE_UNDEFINED = -1,
LC_LIGHT_SHAPE_SQUARE,
LC_LIGHT_SHAPE_DISK,
LC_LIGHT_SHAPE_RECTANGLE,
LC_LIGHT_SHAPE_ELLIPSE
};
enum lcLightProperty
{
LC_LIGHT_NONE,
LC_LIGHT_SHAPE,
LC_LIGHT_COLOR,
LC_LIGHT_TYPE,
LC_LIGHT_FACTOR,
LC_LIGHT_SPECULAR,
LC_LIGHT_EXPONENT,
LC_LIGHT_SPOT_SIZE,
LC_LIGHT_CUTOFF,
LC_LIGHT_USE_CUTOFF
};
struct lcLightProperties
{
lcVector3 mLightColor;
lcVector2 mLightFactor;
float mLightSpecular;
float mSpotExponent;
float mSpotCutoff;
float mSpotSize;
bool mEnableCutoff;
int mLightShape;
};
class lcLight : public lcObject
{
public:
lcLight(float px, float py, float pz);
lcLight(float px, float py, float pz, float tx, float ty, float tz);
lcLight(float px, float py, float pz, float tx, float ty, float tz, int LightType);
~lcLight();
lcLight(const lcLight&) = delete;
@ -178,6 +222,7 @@ public:
}
void SaveLDraw(QTextStream& Stream) const;
bool ParseLDrawLine(QTextStream& Stream);
public:
void RayTest(lcObjectRayTest& ObjectRayTest) const override;
@ -191,6 +236,11 @@ public:
bool IsVisible() const
{ return (mState & LC_LIGHT_HIDDEN) == 0; }
void SetName(const QString& Name)
{
mName = Name;
}
QString GetName() const override
{
return mName;
@ -201,6 +251,20 @@ public:
void MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance);
bool Setup(int LightIndex);
void CreateName(const lcArray<lcLight*>& Lights);
void UpdateLight(lcStep Step, lcLightProperties Props, int Property);
lcLightProperties GetLightProperties() const
{
lcLightProperties props;
props.mLightColor = mLightColor;
props.mLightFactor = mLightFactor;
props.mLightSpecular = mLightSpecular;
props.mSpotExponent = mSpotExponent;
props.mSpotCutoff = mSpotCutoff;
props.mSpotSize = mSpotSize;
props.mEnableCutoff = mEnableCutoff;
props.mLightShape = mLightShape;
return props;
}
// Temporary parameters
lcMatrix44 mWorldLight;
@ -210,8 +274,20 @@ public:
lcVector4 mDiffuseColor;
lcVector4 mSpecularColor;
lcVector3 mAttenuation;
lcVector3 mLightColor;
lcVector2 mLightFactor;
bool mAngleSet;
bool mSpotBlendSet;
bool mSpotCutoffSet;
bool mHeightSet;
bool mEnableCutoff;
int mLightType;
int mLightShape;
float mLightSpecular;
float mSpotSize;
float mSpotCutoff;
float mSpotExponent;
QString mName;
protected:
lcObjectKeyArray<lcVector3> mPositionKeys;
@ -220,14 +296,21 @@ protected:
lcObjectKeyArray<lcVector4> mDiffuseColorKeys;
lcObjectKeyArray<lcVector4> mSpecularColorKeys;
lcObjectKeyArray<lcVector3> mAttenuationKeys;
lcObjectKeyArray<lcVector3> mLightColorKeys;
lcObjectKeyArray<lcVector2> mLightFactorKeys;
lcObjectKeyArray<int> mLightTypeKeys;
lcObjectKeyArray<int> mLightShapeKeys;
lcObjectKeyArray<float> mLightSpecularKeys;
lcObjectKeyArray<float> mLightSpotSizeKeys;
lcObjectKeyArray<float> mSpotCutoffKeys;
lcObjectKeyArray<float> mSpotExponentKeys;
void Initialize(const lcVector3& Position, const lcVector3& TargetPosition);
void Initialize(const lcVector3& Position, const lcVector3& TargetPosition, int LightType);
void DrawDirectionalLight(lcContext* Context) const;
void DrawPointLight(lcContext* Context) const;
void DrawSpotLight(lcContext* Context) const;
void SetLightState(int LightType);
QString mName;
quint32 mState;
};

View file

@ -38,6 +38,20 @@ template void lcObjectKeyArray<lcMatrix33>::ChangeKey(const lcMatrix33& Value, l
template void lcObjectKeyArray<lcMatrix33>::InsertTime(lcStep Start, lcStep Time);
template void lcObjectKeyArray<lcMatrix33>::RemoveTime(lcStep Start, lcStep Time);
template void lcObjectKeyArray<int>::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const;
template void lcObjectKeyArray<int>::LoadKeysLDraw(QTextStream& Stream);
template const int& lcObjectKeyArray<int>::CalculateKey(lcStep Step) const;
template void lcObjectKeyArray<int>::ChangeKey(const int& Value, lcStep Step, bool AddKey);
template void lcObjectKeyArray<int>::InsertTime(lcStep Start, lcStep Time);
template void lcObjectKeyArray<int>::RemoveTime(lcStep Start, lcStep Time);
template void lcObjectKeyArray<lcVector2>::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const;
template void lcObjectKeyArray<lcVector2>::LoadKeysLDraw(QTextStream& Stream);
template const lcVector2& lcObjectKeyArray<lcVector2>::CalculateKey(lcStep Step) const;
template void lcObjectKeyArray<lcVector2>::ChangeKey(const lcVector2& Value, lcStep Step, bool AddKey);
template void lcObjectKeyArray<lcVector2>::InsertTime(lcStep Start, lcStep Time);
template void lcObjectKeyArray<lcVector2>::RemoveTime(lcStep Start, lcStep Time);
template<typename T>
void lcObjectKeyArray<T>::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const
{