Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F123455
Light.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Size
18 KB
Referenced Files
None
Subscribers
None
Light.cpp
View Options
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/
Copyright (c) 2000-2009 Torus Knot Software Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#include
<echo/Graphics/Light.h>
#include
<echo/Graphics/Node.h>
#include
<echo/Graphics/Camera.h>
namespace
Echo
{
//-----------------------------------------------------------------------
Light
::
Light
()
:
mLightType
(
LightTypes
::
POINT
),
mPosition
(
Vector3
::
ZERO
),
mDiffuse
(
Colour
()),
mSpecular
(
Colour
(
0
,
0
,
0
,
1.0f
)),
mDirection
(
Vector3
::
UNIT_Z
),
mSpotOuter
(
Degree
(
40.0f
)),
mSpotInner
(
Degree
(
30.0f
)),
mSpotFalloff
(
1.0f
),
mRange
(
100000
),
mAttenuationConst
(
1.0f
),
mAttenuationLinear
(
0.0f
),
mAttenuationQuad
(
0.0f
),
mPowerScale
(
1.0f
),
mIndexInFrame
(
0
),
mOwnShadowFarDist
(
false
),
mShadowFarDist
(
0
),
mShadowFarDistSquared
(
0
),
mShadowNearClipDist
(
-
1
),
mShadowFarClipDist
(
-
1
),
mDerivedPosition
(
Vector3
::
ZERO
),
mDerivedDirection
(
Vector3
::
UNIT_Z
),
mDerivedCamRelativePosition
(
Vector3
::
ZERO
),
mDerivedCamRelativeDirty
(
false
),
mCameraToBeRelativeTo
(
0
),
mDerivedTransformDirty
(
false
)
{
}
Light
::
Light
(
const
std
::
string
&
name
)
:
mLightType
(
LightTypes
::
POINT
),
mPosition
(
Vector3
::
ZERO
),
mDiffuse
(
Colour
()),
mSpecular
(
Colour
(
0.0f
,
0.0f
,
0.0f
,
1.0f
)),
mDirection
(
Vector3
::
UNIT_Z
),
mSpotOuter
(
Degree
(
40.0f
)),
mSpotInner
(
Degree
(
30.0f
)),
mSpotFalloff
(
1.0f
),
mRange
(
100000
),
mAttenuationConst
(
1.0f
),
mAttenuationLinear
(
0.0f
),
mAttenuationQuad
(
0.0f
),
mPowerScale
(
1.0f
),
mIndexInFrame
(
0
),
mOwnShadowFarDist
(
false
),
mShadowFarDist
(
0
),
mShadowFarDistSquared
(
0
),
mShadowNearClipDist
(
-
1
),
mShadowFarClipDist
(
-
1
),
mDerivedPosition
(
Vector3
::
ZERO
),
mDerivedDirection
(
Vector3
::
UNIT_Z
),
mDerivedCamRelativeDirty
(
false
),
mCameraToBeRelativeTo
(
0
),
mDerivedTransformDirty
(
false
)
{
}
//-----------------------------------------------------------------------
Light
::~
Light
()
{
}
//-----------------------------------------------------------------------
void
Light
::
SetType
(
LightType
type
)
{
mLightType
=
type
;
}
//-----------------------------------------------------------------------
Light
::
LightType
Light
::
GetType
(
void
)
const
{
return
mLightType
;
}
//-----------------------------------------------------------------------
void
Light
::
SetPosition
(
f32
x
,
f32
y
,
f32
z
)
{
mPosition
.
x
=
x
;
mPosition
.
y
=
y
;
mPosition
.
z
=
z
;
mDerivedTransformDirty
=
true
;
mDerivedCamRelativeDirty
=
true
;
}
//-----------------------------------------------------------------------
void
Light
::
SetPosition
(
const
Vector3
&
vec
)
{
mPosition
=
vec
;
mDerivedTransformDirty
=
true
;
mDerivedCamRelativeDirty
=
true
;
}
//-----------------------------------------------------------------------
const
Vector3
&
Light
::
GetPosition
(
void
)
const
{
return
mPosition
;
}
//-----------------------------------------------------------------------
void
Light
::
SetDirection
(
f32
x
,
f32
y
,
f32
z
)
{
mDirection
.
x
=
x
;
mDirection
.
y
=
y
;
mDirection
.
z
=
z
;
mDerivedTransformDirty
=
true
;
}
//-----------------------------------------------------------------------
void
Light
::
SetDirection
(
const
Vector3
&
vec
)
{
mDirection
=
vec
;
mDerivedTransformDirty
=
true
;
}
//-----------------------------------------------------------------------
const
Vector3
&
Light
::
GetDirection
(
void
)
const
{
return
mDirection
;
}
//-----------------------------------------------------------------------
void
Light
::
setSpotlightRange
(
const
Radian
&
innerAngle
,
const
Radian
&
outerAngle
,
f32
falloff
)
{
assert
(
mLightType
==
LightTypes
::
SPOTLIGHT
);
mSpotInner
=
innerAngle
;
mSpotOuter
=
outerAngle
;
mSpotFalloff
=
falloff
;
}
//-----------------------------------------------------------------------
void
Light
::
setSpotlightInnerAngle
(
const
Radian
&
val
)
{
mSpotInner
=
val
;
}
//-----------------------------------------------------------------------
void
Light
::
setSpotlightOuterAngle
(
const
Radian
&
val
)
{
mSpotOuter
=
val
;
}
//-----------------------------------------------------------------------
void
Light
::
setSpotlightFalloff
(
f32
val
)
{
mSpotFalloff
=
val
;
}
//-----------------------------------------------------------------------
const
Radian
&
Light
::
getSpotlightInnerAngle
(
void
)
const
{
return
mSpotInner
;
}
//-----------------------------------------------------------------------
const
Radian
&
Light
::
getSpotlightOuterAngle
(
void
)
const
{
return
mSpotOuter
;
}
//-----------------------------------------------------------------------
f32
Light
::
getSpotlightFalloff
(
void
)
const
{
return
mSpotFalloff
;
}
//-----------------------------------------------------------------------
void
Light
::
SetDiffuseColour
(
f32
red
,
f32
green
,
f32
blue
)
{
mDiffuse
.
mRed
=
red
;
mDiffuse
.
mBlue
=
blue
;
mDiffuse
.
mGreen
=
green
;
}
//-----------------------------------------------------------------------
void
Light
::
SetDiffuseColour
(
const
Colour
&
colour
)
{
mDiffuse
=
colour
;
}
//-----------------------------------------------------------------------
const
Colour
&
Light
::
GetDiffuseColour
(
void
)
const
{
return
mDiffuse
;
}
//-----------------------------------------------------------------------
void
Light
::
SetSpecularColour
(
f32
red
,
f32
green
,
f32
blue
)
{
mSpecular
.
mRed
=
red
;
mSpecular
.
mBlue
=
blue
;
mSpecular
.
mGreen
=
green
;
}
//-----------------------------------------------------------------------
void
Light
::
SetSpecularColour
(
const
Colour
&
colour
)
{
mSpecular
=
colour
;
}
//-----------------------------------------------------------------------
const
Colour
&
Light
::
GetSpecularColour
(
void
)
const
{
return
mSpecular
;
}
//-----------------------------------------------------------------------
void
Light
::
SetAttenuation
(
f32
range
,
f32
constant
,
f32
linear
,
f32
quadratic
)
{
mRange
=
range
;
mAttenuationConst
=
constant
;
mAttenuationLinear
=
linear
;
mAttenuationQuad
=
quadratic
;
}
//-----------------------------------------------------------------------
f32
Light
::
GetAttenuationRange
(
void
)
const
{
return
mRange
;
}
//-----------------------------------------------------------------------
f32
Light
::
GetAttenuationConstant
(
void
)
const
{
return
mAttenuationConst
;
}
//-----------------------------------------------------------------------
f32
Light
::
GetAttenuationLinear
(
void
)
const
{
return
mAttenuationLinear
;
}
//-----------------------------------------------------------------------
f32
Light
::
GetAttenuationQuadric
(
void
)
const
{
return
mAttenuationQuad
;
}
//-----------------------------------------------------------------------
void
Light
::
setPowerScale
(
f32
power
)
{
mPowerScale
=
power
;
}
//-----------------------------------------------------------------------
f32
Light
::
getPowerScale
(
void
)
const
{
return
mPowerScale
;
}
//-----------------------------------------------------------------------
void
Light
::
update
(
void
)
const
{
if
(
mDerivedTransformDirty
)
{
mDerivedPosition
=
mPosition
;
mDerivedDirection
=
mDirection
;
mDerivedTransformDirty
=
false
;
}
if
(
mCameraToBeRelativeTo
&&
mDerivedCamRelativeDirty
)
{
mDerivedCamRelativePosition
=
mDerivedPosition
-
mCameraToBeRelativeTo
->
GetDerivedPosition
();
mDerivedCamRelativeDirty
=
false
;
}
}
const
AxisAlignedBox
&
Light
::
getBoundingBox
(
void
)
const
{
// Null, lights are not visible
static
AxisAlignedBox
box
;
return
box
;
}
const
Vector3
&
Light
::
getDerivedPosition
(
bool
cameraRelative
)
const
{
update
();
if
(
cameraRelative
&&
mCameraToBeRelativeTo
)
{
return
mDerivedCamRelativePosition
;
}
else
{
return
mDerivedPosition
;
}
}
//-----------------------------------------------------------------------
const
Vector3
&
Light
::
getDerivedDirection
(
void
)
const
{
update
();
return
mDerivedDirection
;
}
//-----------------------------------------------------------------------
void
Light
::
setVisible
(
bool
visible
)
{
//MovableObject::setVisible(visible);
}
//-----------------------------------------------------------------------
Vector4
Light
::
getAs4DVector
(
bool
cameraRelativeIfSet
)
const
{
Vector4
ret
;
if
(
mLightType
==
LightTypes
::
DIRECTIONAL
)
{
ret
=
-
(
getDerivedDirection
());
// negate direction as 'position'
ret
.
w
=
0.0
;
// infinite distance
}
else
{
ret
=
getDerivedPosition
(
cameraRelativeIfSet
);
ret
.
w
=
1.0
;
}
return
ret
;
}
//-----------------------------------------------------------------------
const
PlaneBoundedVolume
&
Light
::
_getNearClipVolume
(
const
Camera
*
const
cam
)
const
{
// First check if the light is close to the near plane, since
// in this case we have to build a degenerate clip volume
mNearClipVolume
.
planes
.
clear
();
mNearClipVolume
.
outside
=
Plane
::
NEGATIVE_SIDE
;
f32
n
=
cam
->
GetNearPlane
();
// Homogenous position
Vector4
lightPos
=
getAs4DVector
();
// 3D version (not the same as _getDerivedPosition, is -direction for
// directional lights)
Vector3
lightPos3
=
Vector3
(
lightPos
.
x
,
lightPos
.
y
,
lightPos
.
z
);
// Get eye-space light position
// use 4D vector so directional lights still work
Vector4
eyeSpaceLight
=
cam
->
GetViewMatrix
()
*
lightPos
;
// Find distance to light, project onto -Z axis
f32
d
=
eyeSpaceLight
.
dotProduct
(
Vector4
(
0
,
0
,
-
1
,
-
n
));
#define THRESHOLD 1e-6
if
(
d
>
THRESHOLD
||
d
<
-
THRESHOLD
)
{
// light is not too close to the near plane
// First find the worldspace positions of the corners of the viewport
const
Vector3
*
corner
=
cam
->
GetWorldSpaceCorners
();
int
winding
=
(
d
<
0
)
^
cam
->
IsReflected
()
?
+
1
:
-
1
;
// Iterate over world points and form side planes
Vector3
normal
;
Vector3
lightDir
;
for
(
unsigned
int
i
=
0
;
i
<
4
;
++
i
)
{
// Figure out light dir
lightDir
=
lightPos3
-
(
corner
[
i
]
*
lightPos
.
w
);
// Cross with anticlockwise corner, therefore normal points in
normal
=
(
corner
[
i
]
-
corner
[(
i
+
winding
)
%
4
]).
Cross
(
lightDir
);
normal
.
Normalise
();
mNearClipVolume
.
planes
.
push_back
(
Plane
(
normal
,
corner
[
i
]));
}
// Now do the near plane plane
normal
=
cam
->
GetFrustumPlane
(
FrustumPlanes
::
NEAR
).
normal
;
if
(
d
<
0
)
{
// Behind near plane
normal
=
-
normal
;
}
const
Vector3
&
cameraPos
=
cam
->
GetDerivedPosition
();
mNearClipVolume
.
planes
.
push_back
(
Plane
(
normal
,
cameraPos
));
// Finally, for a point/spot light we can add a sixth plane
// This prevents false positives from behind the light
if
(
mLightType
!=
LightTypes
::
DIRECTIONAL
)
{
// Direction from light perpendicular to near plane
mNearClipVolume
.
planes
.
push_back
(
Plane
(
-
normal
,
lightPos3
));
}
}
else
{
// light is close to being on the near plane
// degenerate volume including the entire scene
// we will always require light / dark caps
mNearClipVolume
.
planes
.
push_back
(
Plane
(
Vector3
::
UNIT_Z
,
-
n
));
mNearClipVolume
.
planes
.
push_back
(
Plane
(
-
Vector3
::
UNIT_Z
,
n
));
}
return
mNearClipVolume
;
}
//-----------------------------------------------------------------------
const
PlaneBoundedVolumeList
&
Light
::
_getFrustumClipVolumes
(
const
Camera
*
const
cam
)
const
{
// Homogenous light position
Vector4
lightPos
=
getAs4DVector
();
// 3D version (not the same as _getDerivedPosition, is -direction for
// directional lights)
Vector3
lightPos3
=
Vector3
(
lightPos
.
x
,
lightPos
.
y
,
lightPos
.
z
);
const
Vector3
*
clockwiseVerts
[
4
];
// Get worldspace frustum corners
const
Vector3
*
corners
=
cam
->
GetWorldSpaceCorners
();
int
windingPt0
=
cam
->
IsReflected
()
?
1
:
0
;
int
windingPt1
=
cam
->
IsReflected
()
?
0
:
1
;
bool
infiniteViewDistance
=
(
cam
->
GetFarPlane
()
==
0
);
Vector3
notSoFarCorners
[
4
];
if
(
infiniteViewDistance
)
{
Vector3
camPosition
=
cam
->
GetRealPosition
();
notSoFarCorners
[
0
]
=
corners
[
0
]
+
corners
[
0
]
-
camPosition
;
notSoFarCorners
[
1
]
=
corners
[
1
]
+
corners
[
1
]
-
camPosition
;
notSoFarCorners
[
2
]
=
corners
[
2
]
+
corners
[
2
]
-
camPosition
;
notSoFarCorners
[
3
]
=
corners
[
3
]
+
corners
[
3
]
-
camPosition
;
}
mFrustumClipVolumes
.
clear
();
for
(
unsigned
short
n
=
0
;
n
<
6
;
++
n
)
{
// Skip far plane if infinite view frustum
if
(
infiniteViewDistance
&&
n
==
FrustumPlanes
::
FAR
)
continue
;
const
Plane
&
plane
=
cam
->
GetFrustumPlane
(
n
);
Vector4
planeVec
(
plane
.
normal
.
x
,
plane
.
normal
.
y
,
plane
.
normal
.
z
,
plane
.
d
);
// planes face inwards, we need to know if light is on negative side
f32
d
=
planeVec
.
dotProduct
(
lightPos
);
if
(
d
<
-
1e-06
)
{
// Ok, this is a valid one
// clockwise verts mean we can cross-product and always get normals
// facing into the volume we create
mFrustumClipVolumes
.
push_back
(
PlaneBoundedVolume
());
PlaneBoundedVolume
&
vol
=
mFrustumClipVolumes
.
back
();
switch
(
n
)
{
case
(
FrustumPlanes
::
NEAR
)
:
clockwiseVerts
[
0
]
=
corners
+
3
;
clockwiseVerts
[
1
]
=
corners
+
2
;
clockwiseVerts
[
2
]
=
corners
+
1
;
clockwiseVerts
[
3
]
=
corners
+
0
;
break
;
case
(
FrustumPlanes
::
FAR
)
:
clockwiseVerts
[
0
]
=
corners
+
7
;
clockwiseVerts
[
1
]
=
corners
+
6
;
clockwiseVerts
[
2
]
=
corners
+
5
;
clockwiseVerts
[
3
]
=
corners
+
4
;
break
;
case
(
FrustumPlanes
::
LEFT
)
:
clockwiseVerts
[
0
]
=
infiniteViewDistance
?
notSoFarCorners
+
1
:
corners
+
5
;
clockwiseVerts
[
1
]
=
corners
+
1
;
clockwiseVerts
[
2
]
=
corners
+
2
;
clockwiseVerts
[
3
]
=
infiniteViewDistance
?
notSoFarCorners
+
2
:
corners
+
6
;
break
;
case
(
FrustumPlanes
::
RIGHT
)
:
clockwiseVerts
[
0
]
=
infiniteViewDistance
?
notSoFarCorners
+
3
:
corners
+
7
;
clockwiseVerts
[
1
]
=
corners
+
3
;
clockwiseVerts
[
2
]
=
corners
+
0
;
clockwiseVerts
[
3
]
=
infiniteViewDistance
?
notSoFarCorners
+
0
:
corners
+
4
;
break
;
case
(
FrustumPlanes
::
TOP
)
:
clockwiseVerts
[
0
]
=
infiniteViewDistance
?
notSoFarCorners
+
0
:
corners
+
4
;
clockwiseVerts
[
1
]
=
corners
+
0
;
clockwiseVerts
[
2
]
=
corners
+
1
;
clockwiseVerts
[
3
]
=
infiniteViewDistance
?
notSoFarCorners
+
1
:
corners
+
5
;
break
;
case
(
FrustumPlanes
::
BOTTOM
)
:
clockwiseVerts
[
0
]
=
infiniteViewDistance
?
notSoFarCorners
+
2
:
corners
+
6
;
clockwiseVerts
[
1
]
=
corners
+
2
;
clockwiseVerts
[
2
]
=
corners
+
3
;
clockwiseVerts
[
3
]
=
infiniteViewDistance
?
notSoFarCorners
+
3
:
corners
+
7
;
break
;
};
// Build a volume
// Iterate over world points and form side planes
Vector3
normal
;
Vector3
lightDir
;
unsigned
int
infiniteViewDistanceInt
=
infiniteViewDistance
?
1
:
0
;
for
(
unsigned
int
i
=
0
;
i
<
4
-
infiniteViewDistanceInt
;
++
i
)
{
// Figure out light dir
lightDir
=
lightPos3
-
(
*
(
clockwiseVerts
[
i
])
*
lightPos
.
w
);
Vector3
edgeDir
=
*
(
clockwiseVerts
[(
i
+
windingPt1
)
%
4
])
-
*
(
clockwiseVerts
[(
i
+
windingPt0
)
%
4
]);
// Cross with anticlockwise corner, therefore normal points in
normal
=
edgeDir
.
Cross
(
lightDir
);
normal
.
Normalise
();
vol
.
planes
.
push_back
(
Plane
(
normal
,
*
(
clockwiseVerts
[
i
])));
}
// Now do the near plane (this is the plane of the side we're
// talking about, with the normal inverted (d is already interpreted as -ve)
vol
.
planes
.
push_back
(
Plane
(
-
plane
.
normal
,
plane
.
d
));
// Finally, for a point/spot light we can add a sixth plane
// This prevents false positives from behind the light
if
(
mLightType
!=
LightTypes
::
DIRECTIONAL
)
{
// re-use our own plane normal
vol
.
planes
.
push_back
(
Plane
(
plane
.
normal
,
lightPos3
));
}
}
}
return
mFrustumClipVolumes
;
}
void
Light
::
_calcTempSquareDist
(
const
Vector3
&
worldPos
)
{
if
(
mLightType
==
LightTypes
::
DIRECTIONAL
)
{
tempSquareDist
=
0
;
}
else
{
tempSquareDist
=
(
worldPos
-
getDerivedPosition
()).
LengthSquared
();
}
}
void
Light
::
setShadowFarDistance
(
f32
distance
)
{
mOwnShadowFarDist
=
true
;
mShadowFarDist
=
distance
;
mShadowFarDistSquared
=
distance
*
distance
;
}
//-----------------------------------------------------------------------
void
Light
::
resetShadowFarDistance
(
void
)
{
mOwnShadowFarDist
=
false
;
}
//-----------------------------------------------------------------------
f32
Light
::
getShadowFarDistance
(
void
)
const
{
return
mShadowFarDist
;
}
//-----------------------------------------------------------------------
f32
Light
::
getShadowFarDistanceSquared
(
void
)
const
{
return
mShadowFarDistSquared
;
}
//---------------------------------------------------------------------
void
Light
::
_setCameraRelative
(
Camera
*
cam
)
{
mCameraToBeRelativeTo
=
cam
;
mDerivedCamRelativeDirty
=
true
;
}
//---------------------------------------------------------------------
f32
Light
::
_deriveShadowNearClipDistance
(
const
Camera
*
maincam
)
const
{
if
(
mShadowNearClipDist
>
0
)
return
mShadowNearClipDist
;
else
return
maincam
->
GetNearPlane
();
}
//---------------------------------------------------------------------
f32
Light
::
_deriveShadowFarClipDistance
(
const
Camera
*
maincam
)
const
{
if
(
mShadowFarClipDist
>=
0
)
return
mShadowFarClipDist
;
else
{
if
(
mLightType
==
LightTypes
::
DIRECTIONAL
)
return
0
;
else
return
mRange
;
}
}
//-----------------------------------------------------------------------
void
Light
::
setCustomParameter
(
u16
index
,
const
Vector4
&
value
)
{
mCustomParameters
[
index
]
=
value
;
}
//-----------------------------------------------------------------------
const
Vector4
&
Light
::
getCustomParameter
(
u16
index
)
const
{
CustomParameterMap
::
const_iterator
i
=
mCustomParameters
.
find
(
index
);
if
(
i
!=
mCustomParameters
.
end
())
{
return
i
->
second
;
}
else
{
assert
(
0
);
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Wed, Jan 15, 11:46 PM (12 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
72096
Default Alt Text
Light.cpp (18 KB)
Attached To
Mode
rEE Echo 3
Attached
Detach File
Event Timeline
Log In to Comment