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 <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include "light.h"
|
2014-04-14 05:20:16 +02:00
|
|
|
#include "camera.h"
|
|
|
|
#include "view.h"
|
|
|
|
#include "lc_application.h"
|
|
|
|
#include "lc_context.h"
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
static LC_OBJECT_KEY_INFO light_key_info[LC_LK_COUNT] =
|
|
|
|
{
|
2012-08-17 01:50:40 +02:00
|
|
|
{ "Light Position", 3, LC_LK_POSITION },
|
|
|
|
{ "Light Target", 3, LC_LK_TARGET },
|
|
|
|
{ "Ambient Color", 3, LC_LK_AMBIENT_COLOR },
|
|
|
|
{ "Diffuse Color", 3, LC_LK_DIFFUSE_COLOR },
|
|
|
|
{ "Specular Color", 3, LC_LK_SPECULAR_COLOR },
|
|
|
|
{ "Constant Attenuation", 1, LC_LK_CONSTANT_ATTENUATION },
|
|
|
|
{ "Linear Attenuation", 1, LC_LK_LINEAR_ATTENUATION },
|
|
|
|
{ "Quadratic Attenuation", 1, LC_LK_QUADRATIC_ATTENUATION },
|
|
|
|
{ "Spot Cutoff", 1, LC_LK_SPOT_CUTOFF },
|
|
|
|
{ "Spot Exponent", 1, LC_LK_SPOT_EXPONENT }
|
2011-09-07 23:06:51 +02:00
|
|
|
};
|
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
// New omni light.
|
2014-05-01 20:42:11 +02:00
|
|
|
lcLight::lcLight(float px, float py, float pz)
|
2012-09-10 01:42:57 +02:00
|
|
|
: Object(LC_OBJECT_LIGHT)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-09-10 01:42:57 +02:00
|
|
|
Initialize();
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
float pos[] = { px, py, pz }, target[] = { 0, 0, 0 };
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-01-30 04:13:34 +01:00
|
|
|
ChangeKey(1, true, pos, LC_LK_POSITION);
|
|
|
|
ChangeKey(1, true, target, LC_LK_TARGET);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-01-30 04:13:34 +01:00
|
|
|
UpdatePosition(1);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
// New directional or spot light.
|
2014-05-01 20:42:11 +02:00
|
|
|
lcLight::lcLight(float px, float py, float pz, float tx, float ty, float tz)
|
2012-09-10 01:42:57 +02:00
|
|
|
: Object(LC_OBJECT_LIGHT)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-09-10 01:42:57 +02:00
|
|
|
Initialize();
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
float pos[] = { px, py, pz }, target[] = { tx, ty, tz };
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-01-30 04:13:34 +01:00
|
|
|
ChangeKey(1, true, pos, LC_LK_POSITION);
|
|
|
|
ChangeKey(1, true, target, LC_LK_TARGET);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-01-30 04:13:34 +01:00
|
|
|
UpdatePosition(1);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2014-05-01 20:42:11 +02:00
|
|
|
void lcLight::Initialize()
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2014-05-01 16:55:12 +02:00
|
|
|
mState = 0;
|
2012-09-10 01:42:57 +02:00
|
|
|
memset(m_strName, 0, sizeof(m_strName));
|
2012-08-17 01:50:40 +02:00
|
|
|
|
|
|
|
mAmbientColor[3] = 1.0f;
|
|
|
|
mDiffuseColor[3] = 1.0f;
|
|
|
|
mSpecularColor[3] = 1.0f;
|
|
|
|
|
|
|
|
float *values[] = { mPosition, mTargetPosition, mAmbientColor, mDiffuseColor, mSpecularColor,
|
|
|
|
&mConstantAttenuation, &mLinearAttenuation, &mQuadraticAttenuation, &mSpotCutoff, &mSpotExponent };
|
|
|
|
RegisterKeys(values, light_key_info, LC_LK_COUNT);
|
|
|
|
|
|
|
|
// set the default values
|
|
|
|
float ambient[] = { 0, 0, 0 }, diffuse[] = { 0.8f, 0.8f, 0.8f }, specular[] = { 1, 1, 1 };
|
|
|
|
float constant = 1, linear = 0, quadratic = 0, cutoff = 30, exponent = 0;
|
|
|
|
|
2014-01-30 04:13:34 +01:00
|
|
|
ChangeKey(1, true, ambient, LC_LK_AMBIENT_COLOR);
|
|
|
|
ChangeKey(1, true, diffuse, LC_LK_DIFFUSE_COLOR);
|
|
|
|
ChangeKey(1, true, specular, LC_LK_SPECULAR_COLOR);
|
|
|
|
ChangeKey(1, true, &constant, LC_LK_CONSTANT_ATTENUATION);
|
|
|
|
ChangeKey(1, true, &linear, LC_LK_LINEAR_ATTENUATION);
|
|
|
|
ChangeKey(1, true, &quadratic, LC_LK_QUADRATIC_ATTENUATION);
|
|
|
|
ChangeKey(1, true, &cutoff, LC_LK_SPOT_CUTOFF);
|
|
|
|
ChangeKey(1, true, &exponent, LC_LK_SPOT_EXPONENT);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2014-05-01 20:42:11 +02:00
|
|
|
lcLight::~lcLight()
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-05-18 01:03:05 +02:00
|
|
|
bool lcLight::FileLoad(lcFile& file)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void lcLight::FileSave(lcFile& file) const
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-05-01 20:42:11 +02:00
|
|
|
void lcLight::CreateName(const lcArray<Light*>& Lights)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
int i, max = 0;
|
|
|
|
|
2014-04-09 00:34:50 +02:00
|
|
|
for (int LightIdx = 0; LightIdx < Lights.GetSize(); LightIdx++)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2014-04-09 00:34:50 +02:00
|
|
|
Light* pLight = Lights[LightIdx];
|
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
if (strncmp(pLight->m_strName, "Light ", 6) == 0)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
if (sscanf(pLight->m_strName + 6, " #%d", &i) == 1)
|
|
|
|
{
|
|
|
|
if (i > max)
|
|
|
|
max = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
sprintf(m_strName, "Light #%.2d", max+1);
|
2011-09-07 23:06:51 +02: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
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
if (lcSphereRayMinIntersectDistance(mPosition, 0.2f, ObjectRayTest.Start, ObjectRayTest.End, &Distance))
|
|
|
|
{
|
|
|
|
ObjectRayTest.ObjectSection.Object = const_cast<Light*>(this);
|
|
|
|
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
|
|
|
|
|
|
|
lcVector3 Min = lcVector3(-0.2f, -0.2f, -0.2f);
|
|
|
|
lcVector3 Max = lcVector3(0.2f, 0.2f, 0.2f);
|
|
|
|
|
|
|
|
lcVector3 Start = lcMul31(ObjectRayTest.Start, mWorldLight);
|
|
|
|
lcVector3 End = lcMul31(ObjectRayTest.End, mWorldLight);
|
|
|
|
|
|
|
|
float Distance;
|
|
|
|
if (lcBoundingBoxRayMinIntersectDistance(Min, Max, Start, End, &Distance, NULL) && (Distance < ObjectRayTest.Distance))
|
2012-09-10 01:42:57 +02:00
|
|
|
{
|
2014-05-01 16:55:12 +02:00
|
|
|
ObjectRayTest.ObjectSection.Object = const_cast<Light*>(this);
|
|
|
|
ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_POSITION;
|
|
|
|
ObjectRayTest.Distance = Distance;
|
|
|
|
}
|
|
|
|
|
|
|
|
Min = lcVector3(-0.2f, -0.2f, -0.2f);
|
|
|
|
Max = lcVector3(0.2f, 0.2f, 0.2f);
|
|
|
|
|
|
|
|
lcMatrix44 WorldTarget = mWorldLight;
|
|
|
|
WorldTarget.SetTranslation(lcMul30(-mTargetPosition, WorldTarget));
|
|
|
|
|
|
|
|
Start = lcMul31(ObjectRayTest.Start, WorldTarget);
|
|
|
|
End = lcMul31(ObjectRayTest.End, WorldTarget);
|
|
|
|
|
|
|
|
if (lcBoundingBoxRayMinIntersectDistance(Min, Max, Start, End, &Distance, NULL) && (Distance < ObjectRayTest.Distance))
|
|
|
|
{
|
|
|
|
ObjectRayTest.ObjectSection.Object = const_cast<Light*>(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++)
|
|
|
|
if (lcDot3(mPosition, ObjectBoxTest.Planes[PlaneIdx]) + ObjectBoxTest.Planes[PlaneIdx][3] > 0.2f)
|
|
|
|
return;
|
2012-09-10 01:42:57 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
lcObjectSection& ObjectSection = ObjectBoxTest.ObjectSections.Add();
|
|
|
|
ObjectSection.Object = const_cast<Light*>(this);
|
|
|
|
ObjectSection.Section = LC_LIGHT_SECTION_POSITION;
|
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
|
|
|
|
|
|
|
lcVector3 Min(-0.2f, -0.2f, -0.2f);
|
|
|
|
lcVector3 Max(0.2f, 0.2f, 0.2f);
|
|
|
|
|
|
|
|
lcVector4 LocalPlanes[6];
|
|
|
|
|
|
|
|
for (int PlaneIdx = 0; PlaneIdx < 6; PlaneIdx++)
|
2012-09-10 01:42:57 +02:00
|
|
|
{
|
2014-05-01 16:55:12 +02:00
|
|
|
lcVector3 Normal = lcMul30(ObjectBoxTest.Planes[PlaneIdx], mWorldLight);
|
|
|
|
LocalPlanes[PlaneIdx] = lcVector4(Normal, ObjectBoxTest.Planes[PlaneIdx][3] - lcDot3(mWorldLight[3], Normal));
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
if (lcBoundingBoxIntersectsVolume(Min, Max, LocalPlanes))
|
2012-08-17 01:50:40 +02:00
|
|
|
{
|
2014-05-01 16:55:12 +02:00
|
|
|
lcObjectSection& ObjectSection = ObjectBoxTest.ObjectSections.Add();
|
|
|
|
ObjectSection.Object = const_cast<Light*>(this);
|
|
|
|
ObjectSection.Section = LC_LIGHT_SECTION_POSITION;
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
Min = lcVector3(-0.2f, -0.2f, -0.2f);
|
|
|
|
Max = lcVector3(0.2f, 0.2f, 0.2f);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
lcMatrix44 WorldTarget = mWorldLight;
|
|
|
|
WorldTarget.SetTranslation(lcMul30(-mTargetPosition, WorldTarget));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
for (int PlaneIdx = 0; PlaneIdx < 6; PlaneIdx++)
|
|
|
|
{
|
|
|
|
lcVector3 Normal = lcMul30(ObjectBoxTest.Planes[PlaneIdx], WorldTarget);
|
|
|
|
LocalPlanes[PlaneIdx] = lcVector4(Normal, ObjectBoxTest.Planes[PlaneIdx][3] - lcDot3(WorldTarget[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-05-01 16:55:12 +02:00
|
|
|
lcObjectSection& ObjectSection = ObjectBoxTest.ObjectSections.Add();
|
|
|
|
ObjectSection.Object = const_cast<Light*>(this);
|
|
|
|
ObjectSection.Section = LC_LIGHT_SECTION_TARGET;
|
2012-08-17 01:50:40 +02:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2014-06-22 19:39:15 +02:00
|
|
|
void lcLight::Move(unsigned short nTime, bool AddKey, const lcVector3& Distance)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2014-05-01 16:55:12 +02:00
|
|
|
if (IsSelected(LC_LIGHT_SECTION_POSITION))
|
2012-06-07 02:08:59 +02:00
|
|
|
{
|
2014-06-22 19:39:15 +02:00
|
|
|
mPosition += Distance;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-06-22 19:39:15 +02:00
|
|
|
ChangeKey(nTime, AddKey, mPosition, LC_LK_POSITION);
|
2012-06-07 02:08:59 +02:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
if (IsSelected(LC_LIGHT_SECTION_TARGET))
|
2012-06-07 02:08:59 +02:00
|
|
|
{
|
2014-06-22 19:39:15 +02:00
|
|
|
mTargetPosition += Distance;
|
2012-06-07 02:08:59 +02:00
|
|
|
|
2014-06-22 19:39:15 +02:00
|
|
|
ChangeKey(nTime, AddKey, mTargetPosition, LC_LK_TARGET);
|
2012-06-07 02:08:59 +02:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2014-05-01 20:42:11 +02:00
|
|
|
void lcLight::UpdatePosition(unsigned short nTime)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2014-01-30 04:13:34 +01:00
|
|
|
CalculateKeys(nTime);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
if (IsPointLight())
|
2012-03-29 03:10:55 +02:00
|
|
|
{
|
2014-05-01 16:55:12 +02:00
|
|
|
mWorldLight = lcMatrix44Identity();
|
|
|
|
mWorldLight.SetTranslation(-mPosition);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lcVector3 FrontVector(mTargetPosition - mPosition);
|
|
|
|
lcVector3 UpVector(1, 1, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
if (fabs(FrontVector[0]) < fabs(FrontVector[1]))
|
2012-08-17 01:50:40 +02:00
|
|
|
{
|
2014-05-01 16:55:12 +02:00
|
|
|
if (fabs(FrontVector[0]) < fabs(FrontVector[2]))
|
|
|
|
UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]);
|
2012-08-17 01:50:40 +02:00
|
|
|
else
|
2014-05-01 16:55:12 +02:00
|
|
|
UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]);
|
2012-08-17 01:50:40 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-05-01 16:55:12 +02:00
|
|
|
if (fabs(FrontVector[1]) < fabs(FrontVector[2]))
|
|
|
|
UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]);
|
2012-08-17 01:50:40 +02:00
|
|
|
else
|
2014-05-01 16:55:12 +02:00
|
|
|
UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]);
|
2012-08-17 01:50:40 +02:00
|
|
|
}
|
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
mWorldLight = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector);
|
2012-08-17 01:50:40 +02:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2014-05-01 20:42:11 +02:00
|
|
|
void lcLight::Render(View* View)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2014-04-14 05:20:16 +02:00
|
|
|
float LineWidth = lcGetPreferences().mLineWidth;
|
|
|
|
const lcMatrix44& ViewMatrix = View->mCamera->mWorldView;
|
|
|
|
lcContext* Context = View->mContext;
|
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
if (IsPointLight())
|
|
|
|
{
|
|
|
|
Context->SetWorldViewMatrix(lcMul(lcMatrix44Translation(mPosition), ViewMatrix));
|
|
|
|
|
|
|
|
if (IsSelected(LC_LIGHT_SECTION_POSITION))
|
|
|
|
{
|
|
|
|
if (IsFocused(LC_LIGHT_SECTION_POSITION))
|
|
|
|
lcSetColorFocused();
|
|
|
|
else
|
|
|
|
lcSetColorSelected();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
lcSetColorLight();
|
|
|
|
|
|
|
|
RenderSphere();
|
|
|
|
}
|
|
|
|
else
|
2012-06-07 02:08:59 +02:00
|
|
|
{
|
2014-05-01 16:55:12 +02:00
|
|
|
if (IsSelected(LC_LIGHT_SECTION_POSITION))
|
2012-06-07 02:08:59 +02:00
|
|
|
{
|
2014-04-14 05:20:16 +02:00
|
|
|
Context->SetLineWidth(2.0f * LineWidth);
|
2014-05-01 16:55:12 +02:00
|
|
|
if (IsFocused(LC_LIGHT_SECTION_POSITION))
|
2012-06-07 02:08:59 +02:00
|
|
|
lcSetColorFocused();
|
|
|
|
else
|
|
|
|
lcSetColorSelected();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-04-14 05:20:16 +02:00
|
|
|
Context->SetLineWidth(LineWidth);
|
2012-06-07 02:08:59 +02:00
|
|
|
lcSetColorLight();
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
RenderCone(ViewMatrix);
|
2014-04-14 05:20:16 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
if (IsSelected(LC_LIGHT_SECTION_TARGET))
|
2012-06-07 02:08:59 +02:00
|
|
|
{
|
2014-04-14 05:20:16 +02:00
|
|
|
Context->SetLineWidth(2.0f * LineWidth);
|
2014-05-01 16:55:12 +02:00
|
|
|
if (IsFocused(LC_LIGHT_SECTION_TARGET))
|
2012-06-07 02:08:59 +02:00
|
|
|
lcSetColorFocused();
|
|
|
|
else
|
|
|
|
lcSetColorSelected();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-04-14 05:20:16 +02:00
|
|
|
Context->SetLineWidth(LineWidth);
|
2012-06-07 02:08:59 +02:00
|
|
|
lcSetColorLight();
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
RenderTarget();
|
2014-04-14 05:20:16 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
Context->SetWorldViewMatrix(ViewMatrix);
|
2012-09-10 01:42:57 +02:00
|
|
|
|
2014-04-14 05:20:16 +02:00
|
|
|
Context->SetLineWidth(LineWidth);
|
2012-06-07 02:08:59 +02:00
|
|
|
lcSetColorLight();
|
2012-09-10 01:42:57 +02:00
|
|
|
|
|
|
|
lcVector3 Line[2] = { mPosition, mTargetPosition };
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, Line);
|
|
|
|
|
|
|
|
glDrawArrays(GL_LINES, 0, 2);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-06-07 02:08:59 +02:00
|
|
|
if (IsSelected())
|
|
|
|
{
|
2014-02-16 08:23:55 +01:00
|
|
|
lcMatrix44 ProjectionMatrix, LightMatrix;
|
2012-06-07 02:08:59 +02:00
|
|
|
lcVector3 FrontVector(mTargetPosition - mPosition);
|
|
|
|
lcVector3 UpVector(1, 1, 1);
|
|
|
|
float Length = FrontVector.Length();
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-06-07 02:08:59 +02:00
|
|
|
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]);
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-02-16 08:23:55 +01:00
|
|
|
LightMatrix = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector);
|
|
|
|
LightMatrix = lcMatrix44AffineInverse(LightMatrix);
|
|
|
|
ProjectionMatrix = lcMatrix44Perspective(2 * mSpotCutoff, 1.0f, 0.01f, Length);
|
|
|
|
ProjectionMatrix = lcMatrix44Inverse(ProjectionMatrix);
|
2014-05-01 16:55:12 +02:00
|
|
|
Context->SetWorldViewMatrix(lcMul(ProjectionMatrix, lcMul(LightMatrix, ViewMatrix)));
|
2012-06-07 02:08:59 +02:00
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
// Draw the light cone.
|
|
|
|
float Verts[16][3] =
|
|
|
|
{
|
|
|
|
{ 0.5f, 1.0f, 1.0f },
|
|
|
|
{ 1.0f, 0.5f, 1.0f },
|
|
|
|
{ 1.0f, -0.5f, 1.0f },
|
|
|
|
{ 0.5f, -1.0f, 1.0f },
|
|
|
|
{ -0.5f, -1.0f, 1.0f },
|
|
|
|
{ -1.0f, -0.5f, 1.0f },
|
|
|
|
{ -1.0f, 0.5f, 1.0f },
|
|
|
|
{ -0.5f, 1.0f, 1.0f },
|
|
|
|
{ 1.0f, 1.0f, -1.0f },
|
|
|
|
{ 0.75f, 0.75f, 1.0f },
|
|
|
|
{ -1.0f, 1.0f, -1.0f },
|
|
|
|
{ -0.75f, 0.75f, 1.0f },
|
|
|
|
{ -1.0f, -1.0f, -1.0f },
|
|
|
|
{ -0.75f, -0.75f, 1.0f },
|
|
|
|
{ 1.0f, -1.0f, -1.0f },
|
|
|
|
{ 0.75f, -0.75f, 1.0f }
|
|
|
|
};
|
|
|
|
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, Verts);
|
|
|
|
glDrawArrays(GL_LINE_LOOP, 0, 8);
|
|
|
|
glDrawArrays(GL_LINES, 8, 8);
|
2012-06-07 02:08:59 +02:00
|
|
|
}
|
|
|
|
}
|
2012-09-10 01:42:57 +02:00
|
|
|
}
|
|
|
|
|
2014-05-01 20:42:11 +02:00
|
|
|
void lcLight::RenderCone(const lcMatrix44& ViewMatrix)
|
2012-09-10 01:42:57 +02:00
|
|
|
{
|
|
|
|
lcVector3 FrontVector(mTargetPosition - mPosition);
|
|
|
|
lcVector3 UpVector(1, 1, 1);
|
|
|
|
float Length = FrontVector.Length();
|
|
|
|
|
|
|
|
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]);
|
|
|
|
}
|
|
|
|
|
2014-02-16 08:23:55 +01:00
|
|
|
lcMatrix44 LightMatrix = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector);
|
|
|
|
LightMatrix = lcMatrix44AffineInverse(LightMatrix);
|
|
|
|
LightMatrix.SetTranslation(lcVector3(0, 0, 0));
|
|
|
|
|
|
|
|
lcMatrix44 LightViewMatrix = lcMul(LightMatrix, lcMul(lcMatrix44Translation(mPosition), ViewMatrix));
|
2012-09-10 01:42:57 +02:00
|
|
|
|
2014-02-16 08:23:55 +01:00
|
|
|
glLoadMatrixf(LightViewMatrix);
|
2012-09-10 01:42:57 +02:00
|
|
|
|
|
|
|
float verts[16*3];
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
verts[i*6] = verts[i*6+3] = (float)cos((float)i/4 * LC_PI) * 0.3f;
|
|
|
|
verts[i*6+1] = verts[i*6+4] = (float)sin((float)i/4 * LC_PI) * 0.3f;
|
|
|
|
verts[i*6+2] = 0.3f;
|
|
|
|
verts[i*6+5] = -0.3f;
|
|
|
|
}
|
|
|
|
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, verts);
|
|
|
|
glDrawArrays(GL_LINES, 0, 16);
|
|
|
|
glVertexPointer(3, GL_FLOAT, 6*sizeof(float), verts);
|
|
|
|
glDrawArrays(GL_LINE_LOOP, 0, 8);
|
|
|
|
glVertexPointer(3, GL_FLOAT, 6*sizeof(float), &verts[3]);
|
|
|
|
glDrawArrays(GL_LINE_LOOP, 0, 8);
|
|
|
|
|
|
|
|
float Lines[4][3] =
|
|
|
|
{
|
|
|
|
{ -0.5f, -0.5f, -0.3f },
|
|
|
|
{ 0.5f, -0.5f, -0.3f },
|
|
|
|
{ 0.5f, 0.5f, -0.3f },
|
|
|
|
{ -0.5f, 0.5f, -0.3f }
|
|
|
|
};
|
|
|
|
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, Lines);
|
|
|
|
glDrawArrays(GL_LINE_LOOP, 0, 4);
|
|
|
|
|
2014-02-16 08:23:55 +01:00
|
|
|
glLoadMatrixf(lcMul(lcMatrix44Translation(lcVector3(0, 0, -Length)), LightViewMatrix));
|
2012-09-10 01:42:57 +02:00
|
|
|
}
|
|
|
|
|
2014-05-01 20:42:11 +02:00
|
|
|
void lcLight::RenderTarget()
|
2012-09-10 01:42:57 +02:00
|
|
|
{
|
|
|
|
float box[24][3] =
|
|
|
|
{
|
|
|
|
{ 0.2f, 0.2f, 0.2f }, { -0.2f, 0.2f, 0.2f },
|
|
|
|
{ -0.2f, 0.2f, 0.2f }, { -0.2f, -0.2f, 0.2f },
|
|
|
|
{ -0.2f, -0.2f, 0.2f }, { 0.2f, -0.2f, 0.2f },
|
|
|
|
{ 0.2f, -0.2f, 0.2f }, { 0.2f, 0.2f, 0.2f },
|
|
|
|
{ 0.2f, 0.2f, -0.2f }, { -0.2f, 0.2f, -0.2f },
|
|
|
|
{ -0.2f, 0.2f, -0.2f }, { -0.2f, -0.2f, -0.2f },
|
|
|
|
{ -0.2f, -0.2f, -0.2f }, { 0.2f, -0.2f, -0.2f },
|
|
|
|
{ 0.2f, -0.2f, -0.2f }, { 0.2f, 0.2f, -0.2f },
|
|
|
|
{ 0.2f, 0.2f, 0.2f }, { 0.2f, 0.2f, -0.2f },
|
|
|
|
{ -0.2f, 0.2f, 0.2f }, { -0.2f, 0.2f, -0.2f },
|
|
|
|
{ -0.2f, -0.2f, 0.2f }, { -0.2f, -0.2f, -0.2f },
|
|
|
|
{ 0.2f, -0.2f, 0.2f }, { 0.2f, -0.2f, -0.2f }
|
|
|
|
};
|
|
|
|
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, box);
|
|
|
|
glDrawArrays(GL_LINES, 0, 24);
|
|
|
|
}
|
|
|
|
|
2014-05-01 20:42:11 +02:00
|
|
|
void lcLight::RenderSphere()
|
2012-09-10 01:42:57 +02:00
|
|
|
{
|
|
|
|
const int Slices = 6;
|
|
|
|
const int NumIndices = 3 * Slices + 6 * Slices * (Slices - 2) + 3 * Slices;
|
|
|
|
const int NumVertices = (Slices - 1) * Slices + 2;
|
|
|
|
const float Radius = 0.2f;
|
|
|
|
lcVector3 Vertices[NumVertices];
|
|
|
|
lcuint16 Indices[NumIndices];
|
|
|
|
|
|
|
|
lcVector3* Vertex = Vertices;
|
|
|
|
lcuint16* Index = Indices;
|
|
|
|
|
|
|
|
*Vertex++ = lcVector3(0, 0, Radius);
|
|
|
|
|
|
|
|
for (int i = 1; i < Slices; i++ )
|
|
|
|
{
|
|
|
|
float r0 = Radius * sinf(i * (LC_PI / Slices));
|
|
|
|
float z0 = Radius * cosf(i * (LC_PI / Slices));
|
|
|
|
|
|
|
|
for (int j = 0; j < Slices; j++)
|
|
|
|
{
|
|
|
|
float x0 = r0 * sinf(j * (LC_2PI / Slices));
|
|
|
|
float y0 = r0 * cosf(j * (LC_2PI / Slices));
|
|
|
|
|
|
|
|
*Vertex++ = lcVector3(x0, y0, z0);
|
2012-06-07 02:08:59 +02:00
|
|
|
}
|
2012-09-10 01:42:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
*Vertex++ = lcVector3(0, 0, -Radius);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
for (int i = 0; i < Slices - 1; i++ )
|
|
|
|
{
|
|
|
|
*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;
|
|
|
|
|
|
|
|
for (int i = 0; i < Slices - 2; i++ )
|
|
|
|
{
|
|
|
|
int Row1 = 1 + i * Slices;
|
|
|
|
int Row2 = 1 + (i + 1) * Slices;
|
|
|
|
|
|
|
|
for (int j = 0; j < Slices - 1; j++ )
|
|
|
|
{
|
|
|
|
*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;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < Slices - 1; i++ )
|
|
|
|
{
|
|
|
|
*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);
|
|
|
|
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, Vertices);
|
|
|
|
glDrawElements(GL_TRIANGLES, NumIndices, GL_UNSIGNED_SHORT, Indices);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2014-05-01 20:42:11 +02:00
|
|
|
bool lcLight::Setup(int LightIndex)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2014-05-01 16:55:12 +02:00
|
|
|
GLenum LightName = (GLenum)(GL_LIGHT0 + LightIndex);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
if (mState & LC_LIGHT_DISABLED)
|
|
|
|
return false;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
glEnable(LightName);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
glLightfv(LightName, GL_AMBIENT, mAmbientColor);
|
|
|
|
glLightfv(LightName, GL_DIFFUSE, mDiffuseColor);
|
|
|
|
glLightfv(LightName, GL_SPECULAR, mSpecularColor);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
if (!IsDirectionalLight())
|
2012-08-17 01:50:40 +02:00
|
|
|
{
|
2014-05-01 16:55:12 +02:00
|
|
|
glLightf(LightName, GL_CONSTANT_ATTENUATION, mConstantAttenuation);
|
|
|
|
glLightf(LightName, GL_LINEAR_ATTENUATION, mLinearAttenuation);
|
|
|
|
glLightf(LightName, GL_QUADRATIC_ATTENUATION, mQuadraticAttenuation);
|
2012-08-17 01:50:40 +02:00
|
|
|
|
|
|
|
lcVector4 Position(mPosition, 1.0f);
|
2014-05-01 16:55:12 +02:00
|
|
|
glLightfv(LightName, GL_POSITION, Position);
|
2012-08-17 01:50:40 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lcVector4 Position(mPosition, 0.0f);
|
2014-05-01 16:55:12 +02:00
|
|
|
glLightfv(LightName, GL_POSITION, Position);
|
2012-08-17 01:50:40 +02:00
|
|
|
}
|
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
if (IsPointLight())
|
2012-08-17 01:50:40 +02:00
|
|
|
{
|
2014-05-01 16:55:12 +02:00
|
|
|
glLightf(LightName, GL_SPOT_CUTOFF, 180.0f);
|
2012-08-17 01:50:40 +02:00
|
|
|
}
|
2014-05-01 16:55:12 +02:00
|
|
|
else if (IsSpotLight())
|
2012-06-07 02:08:59 +02:00
|
|
|
{
|
|
|
|
lcVector3 Dir(mTargetPosition - mPosition);
|
|
|
|
Dir.Normalize();
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2014-05-01 16:55:12 +02:00
|
|
|
glLightf(LightName, GL_SPOT_CUTOFF, mSpotCutoff);
|
|
|
|
glLightf(LightName, GL_SPOT_EXPONENT, mSpotExponent);
|
|
|
|
glLightfv(LightName, GL_SPOT_DIRECTION, Dir);
|
2012-06-07 02:08:59 +02:00
|
|
|
}
|
2014-05-01 16:55:12 +02:00
|
|
|
|
|
|
|
return true;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|