irrlicht/source/Irrlicht/CLightSceneNode.cpp

272 lines
7.5 KiB
C++
Raw Normal View History

// Copyright (C) 2002-2009 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CLightSceneNode.h"
#include "IVideoDriver.h"
#include "ISceneManager.h"
#include "ICameraSceneNode.h"
#include "os.h"
namespace irr
{
namespace scene
{
//! constructor
CLightSceneNode::CLightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
const core::vector3df& position, video::SColorf color, f32 radius)
: ILightSceneNode(parent, mgr, id, position), DriverLightIndex(-1), LightIsOn(true)
{
#ifdef _DEBUG
setDebugName("CLightSceneNode");
#endif
LightData.DiffuseColor = color;
// set some useful specular color
LightData.SpecularColor = color.getInterpolated(video::SColor(255,255,255,255),0.7f);
setRadius(radius);
}
//! pre render event
void CLightSceneNode::OnRegisterSceneNode()
{
doLightRecalc();
if (IsVisible)
SceneManager->registerNodeForRendering(this, ESNRP_LIGHT);
ISceneNode::OnRegisterSceneNode();
}
//! render
void CLightSceneNode::render()
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
if (!driver)
return;
if ( DebugDataVisible & scene::EDS_BBOX )
{
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
video::SMaterial m;
m.Lighting = false;
driver->setMaterial(m);
switch ( LightData.Type )
{
case video::ELT_POINT:
case video::ELT_SPOT:
driver->draw3DBox(BBox, LightData.DiffuseColor.toSColor());
break;
case video::ELT_DIRECTIONAL:
driver->draw3DLine(core::vector3df(0.f, 0.f, 0.f),
LightData.Direction * LightData.Radius,
LightData.DiffuseColor.toSColor());
break;
}
}
DriverLightIndex = driver->addDynamicLight(LightData);
setVisible(LightIsOn);
}
//! sets the light data
void CLightSceneNode::setLightData(const video::SLight& light)
{
LightData = light;
}
//! \return Returns the light data.
const video::SLight& CLightSceneNode::getLightData() const
{
return LightData;
}
//! \return Returns the light data.
video::SLight& CLightSceneNode::getLightData()
{
return LightData;
}
void CLightSceneNode::setVisible(bool isVisible)
{
ISceneNode::setVisible(isVisible);
if(DriverLightIndex < 0)
return;
video::IVideoDriver* driver = SceneManager->getVideoDriver();
if (!driver)
return;
LightIsOn = isVisible;
driver->turnLightOn((u32)DriverLightIndex, LightIsOn);
}
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CLightSceneNode::getBoundingBox() const
{
return BBox;
}
//! Sets the light's radius of influence.
/** Outside this radius the light won't lighten geometry and cast no
shadows. Setting the radius will also influence the attenuation, setting
it to (0,1/radius,0). If you want to override this behavior, set the
attenuation after the radius.
\param radius The new radius. */
void CLightSceneNode::setRadius(f32 radius)
{
LightData.Radius=radius;
LightData.Attenuation.set(0.f, 1.f/radius, 0.f);
Changes in 1.6 TA - PixelBlend16 and PixelBlend16_simd are working for the new rules. - bugfix. CLightSceneNode didn't correctly update it's attributes Lighting Linear Attenuation. = 1.f / radius The Example loadirr files set the lightscene radius to 1000.f but stays on the previous default attentuation with the older radius 100 -> 1.f / 100 so the examples looks golden-brown. Now the radius is correctly!! set to the attenuation of 1.f/1000.f because the file doesn't have special attenuation. and now it looks more yellow. can anybody show me a correct screenshot for this file;-)? Niko? Or is this behavior the default lighting?. then it would be a fixed constant linear attenuation of 0.01f;-). Please clearify For now i didn't fixed it I encountered this behavior because i ( burning video ) used the original radius for calculations and so i've found that radius != 1.f / linearAttenuation but in the LightSceneNode this formula was used.. confused;-) - vector template and equals tests as working with the test suits i cleaned the template behavior (mixed types are used in the templates) and added all missing special math function with their coressponding type I also set the equal test for s32 to behave like the f32 routine. The function equals always implements a weak test. that means a tolerance MUST always be used if you use the equal function. default is 1. you can set it to zero a==b-> equals ( a, b, 0 ) but do it explicit like you have to for floating compare. This is important when irrlicht is going to use special hardware math acceleration on a per function base, like sse2, or the other way round fixpoint. - VideoDriver drawPixel The HW renderes are using the alpha components for blending. The Software Renderes and image loaders are using CImage::setPixel copy. so setPixel is engaged to either blends or copy the pixel default: false - Burningvideo added RenderMaterial EMT_SPHERE_MAP pushed burningsvideo to 0.43 added RenderMaterial EMT_REFLECTION_2_LAYER pushed burningsvideo to 0.44 set EMT_TRANSPARENT_ALPHA_CHANNEL_REF to use AlphaRef 0.5 like Direct3D One Note: in OpenGL there is know difference between sphere_map and reflection layer both using GL_TEXTURE_GEN_MODE GL_SPHERE_MAP, whereas in d3d one time using camera_normal on sphere and reflection on refletcion_layer. The visual difference is that on sphere map the "image is not moving" when you rotate the viewer. For Buring i took the opengl visual. always moving - rename quake3 SEntity to IEntity to be confom with IShader even IShader and IEntity are none pure virtual interfaces like most irrlicht objects git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2207 dfc29bdd-3216-0410-991c-e03cc46cb475
2009-02-10 07:08:23 -08:00
doLightRecalc();
}
//! Gets the light's radius of influence.
/** \return The current radius. */
f32 CLightSceneNode::getRadius() const
{
return LightData.Radius;
}
//! Sets the light type.
/** \param type The new type. */
void CLightSceneNode::setLightType(video::E_LIGHT_TYPE type)
{
LightData.Type=type;
}
//! Gets the light type.
/** \return The current light type. */
video::E_LIGHT_TYPE CLightSceneNode::getLightType() const
{
return LightData.Type;
}
//! Sets whether this light casts shadows.
/** Enabling this flag won't automatically cast shadows, the meshes
will still need shadow scene nodes attached. But one can enable or
disable distinct lights for shadow casting for performance reasons.
\param shadow True if this light shall cast shadows. */
void CLightSceneNode::enableCastShadow(bool shadow)
{
LightData.CastShadows=shadow;
}
//! Check whether this light casts shadows.
/** \return True if light would cast shadows, else false. */
bool CLightSceneNode::getCastShadow() const
{
return LightData.CastShadows;
}
void CLightSceneNode::doLightRecalc()
{
if ((LightData.Type == video::ELT_SPOT) || (LightData.Type == video::ELT_DIRECTIONAL))
{
LightData.Direction = core::vector3df(.0f,.0f,1.0f);
getAbsoluteTransformation().rotateVect(LightData.Direction);
LightData.Direction.normalize();
}
if ((LightData.Type == video::ELT_SPOT) || (LightData.Type == video::ELT_POINT))
{
const f32 r = LightData.Radius * LightData.Radius * 0.5f;
BBox.MaxEdge.set( r, r, r );
BBox.MinEdge.set( -r, -r, -r );
setAutomaticCulling( scene::EAC_BOX );
LightData.Position = getAbsolutePosition();
}
if (LightData.Type == video::ELT_DIRECTIONAL)
{
BBox.reset( 0, 0, 0 );
setAutomaticCulling( scene::EAC_OFF );
}
}
//! Writes attributes of the scene node.
void CLightSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
{
ILightSceneNode::serializeAttributes(out, options);
out->addColorf ("AmbientColor", LightData.AmbientColor);
out->addColorf ("DiffuseColor", LightData.DiffuseColor);
out->addColorf ("SpecularColor", LightData.SpecularColor);
out->addVector3d("Attenuation", LightData.Attenuation);
out->addFloat ("Radius", LightData.Radius);
out->addFloat ("OuterCone", LightData.OuterCone);
out->addFloat ("InnerCone", LightData.InnerCone);
out->addFloat ("Falloff", LightData.Falloff);
out->addBool ("CastShadows", LightData.CastShadows);
out->addEnum ("LightType", LightData.Type, video::LightTypeNames);
}
//! Reads attributes of the scene node.
void CLightSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
{
LightData.AmbientColor = in->getAttributeAsColorf("AmbientColor");
LightData.DiffuseColor = in->getAttributeAsColorf("DiffuseColor");
LightData.SpecularColor = in->getAttributeAsColorf("SpecularColor");
Changes in 1.6 TA - PixelBlend16 and PixelBlend16_simd are working for the new rules. - bugfix. CLightSceneNode didn't correctly update it's attributes Lighting Linear Attenuation. = 1.f / radius The Example loadirr files set the lightscene radius to 1000.f but stays on the previous default attentuation with the older radius 100 -> 1.f / 100 so the examples looks golden-brown. Now the radius is correctly!! set to the attenuation of 1.f/1000.f because the file doesn't have special attenuation. and now it looks more yellow. can anybody show me a correct screenshot for this file;-)? Niko? Or is this behavior the default lighting?. then it would be a fixed constant linear attenuation of 0.01f;-). Please clearify For now i didn't fixed it I encountered this behavior because i ( burning video ) used the original radius for calculations and so i've found that radius != 1.f / linearAttenuation but in the LightSceneNode this formula was used.. confused;-) - vector template and equals tests as working with the test suits i cleaned the template behavior (mixed types are used in the templates) and added all missing special math function with their coressponding type I also set the equal test for s32 to behave like the f32 routine. The function equals always implements a weak test. that means a tolerance MUST always be used if you use the equal function. default is 1. you can set it to zero a==b-> equals ( a, b, 0 ) but do it explicit like you have to for floating compare. This is important when irrlicht is going to use special hardware math acceleration on a per function base, like sse2, or the other way round fixpoint. - VideoDriver drawPixel The HW renderes are using the alpha components for blending. The Software Renderes and image loaders are using CImage::setPixel copy. so setPixel is engaged to either blends or copy the pixel default: false - Burningvideo added RenderMaterial EMT_SPHERE_MAP pushed burningsvideo to 0.43 added RenderMaterial EMT_REFLECTION_2_LAYER pushed burningsvideo to 0.44 set EMT_TRANSPARENT_ALPHA_CHANNEL_REF to use AlphaRef 0.5 like Direct3D One Note: in OpenGL there is know difference between sphere_map and reflection layer both using GL_TEXTURE_GEN_MODE GL_SPHERE_MAP, whereas in d3d one time using camera_normal on sphere and reflection on refletcion_layer. The visual difference is that on sphere map the "image is not moving" when you rotate the viewer. For Buring i took the opengl visual. always moving - rename quake3 SEntity to IEntity to be confom with IShader even IShader and IEntity are none pure virtual interfaces like most irrlicht objects git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2207 dfc29bdd-3216-0410-991c-e03cc46cb475
2009-02-10 07:08:23 -08:00
//TODO: clearify Radius and Linear Attenuation
#if 0
setRadius ( in->getAttributeAsFloat("Radius") );
#else
LightData.Radius = in->getAttributeAsFloat("Radius");
#endif
if (in->existsAttribute("Attenuation")) // might not exist in older files
LightData.Attenuation = in->getAttributeAsVector3d("Attenuation");
Changes in 1.6 TA - PixelBlend16 and PixelBlend16_simd are working for the new rules. - bugfix. CLightSceneNode didn't correctly update it's attributes Lighting Linear Attenuation. = 1.f / radius The Example loadirr files set the lightscene radius to 1000.f but stays on the previous default attentuation with the older radius 100 -> 1.f / 100 so the examples looks golden-brown. Now the radius is correctly!! set to the attenuation of 1.f/1000.f because the file doesn't have special attenuation. and now it looks more yellow. can anybody show me a correct screenshot for this file;-)? Niko? Or is this behavior the default lighting?. then it would be a fixed constant linear attenuation of 0.01f;-). Please clearify For now i didn't fixed it I encountered this behavior because i ( burning video ) used the original radius for calculations and so i've found that radius != 1.f / linearAttenuation but in the LightSceneNode this formula was used.. confused;-) - vector template and equals tests as working with the test suits i cleaned the template behavior (mixed types are used in the templates) and added all missing special math function with their coressponding type I also set the equal test for s32 to behave like the f32 routine. The function equals always implements a weak test. that means a tolerance MUST always be used if you use the equal function. default is 1. you can set it to zero a==b-> equals ( a, b, 0 ) but do it explicit like you have to for floating compare. This is important when irrlicht is going to use special hardware math acceleration on a per function base, like sse2, or the other way round fixpoint. - VideoDriver drawPixel The HW renderes are using the alpha components for blending. The Software Renderes and image loaders are using CImage::setPixel copy. so setPixel is engaged to either blends or copy the pixel default: false - Burningvideo added RenderMaterial EMT_SPHERE_MAP pushed burningsvideo to 0.43 added RenderMaterial EMT_REFLECTION_2_LAYER pushed burningsvideo to 0.44 set EMT_TRANSPARENT_ALPHA_CHANNEL_REF to use AlphaRef 0.5 like Direct3D One Note: in OpenGL there is know difference between sphere_map and reflection layer both using GL_TEXTURE_GEN_MODE GL_SPHERE_MAP, whereas in d3d one time using camera_normal on sphere and reflection on refletcion_layer. The visual difference is that on sphere map the "image is not moving" when you rotate the viewer. For Buring i took the opengl visual. always moving - rename quake3 SEntity to IEntity to be confom with IShader even IShader and IEntity are none pure virtual interfaces like most irrlicht objects git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2207 dfc29bdd-3216-0410-991c-e03cc46cb475
2009-02-10 07:08:23 -08:00
if (in->existsAttribute("OuterCone")) // might not exist in older files
LightData.OuterCone = in->getAttributeAsFloat("OuterCone");
if (in->existsAttribute("InnerCone")) // might not exist in older files
LightData.InnerCone = in->getAttributeAsFloat("InnerCone");
if (in->existsAttribute("Falloff")) // might not exist in older files
LightData.Falloff = in->getAttributeAsFloat("Falloff");
LightData.CastShadows = in->getAttributeAsBool("CastShadows");
LightData.Type = (video::E_LIGHT_TYPE)in->getAttributeAsEnumeration("LightType", video::LightTypeNames);
Changes in 1.6 TA - PixelBlend16 and PixelBlend16_simd are working for the new rules. - bugfix. CLightSceneNode didn't correctly update it's attributes Lighting Linear Attenuation. = 1.f / radius The Example loadirr files set the lightscene radius to 1000.f but stays on the previous default attentuation with the older radius 100 -> 1.f / 100 so the examples looks golden-brown. Now the radius is correctly!! set to the attenuation of 1.f/1000.f because the file doesn't have special attenuation. and now it looks more yellow. can anybody show me a correct screenshot for this file;-)? Niko? Or is this behavior the default lighting?. then it would be a fixed constant linear attenuation of 0.01f;-). Please clearify For now i didn't fixed it I encountered this behavior because i ( burning video ) used the original radius for calculations and so i've found that radius != 1.f / linearAttenuation but in the LightSceneNode this formula was used.. confused;-) - vector template and equals tests as working with the test suits i cleaned the template behavior (mixed types are used in the templates) and added all missing special math function with their coressponding type I also set the equal test for s32 to behave like the f32 routine. The function equals always implements a weak test. that means a tolerance MUST always be used if you use the equal function. default is 1. you can set it to zero a==b-> equals ( a, b, 0 ) but do it explicit like you have to for floating compare. This is important when irrlicht is going to use special hardware math acceleration on a per function base, like sse2, or the other way round fixpoint. - VideoDriver drawPixel The HW renderes are using the alpha components for blending. The Software Renderes and image loaders are using CImage::setPixel copy. so setPixel is engaged to either blends or copy the pixel default: false - Burningvideo added RenderMaterial EMT_SPHERE_MAP pushed burningsvideo to 0.43 added RenderMaterial EMT_REFLECTION_2_LAYER pushed burningsvideo to 0.44 set EMT_TRANSPARENT_ALPHA_CHANNEL_REF to use AlphaRef 0.5 like Direct3D One Note: in OpenGL there is know difference between sphere_map and reflection layer both using GL_TEXTURE_GEN_MODE GL_SPHERE_MAP, whereas in d3d one time using camera_normal on sphere and reflection on refletcion_layer. The visual difference is that on sphere map the "image is not moving" when you rotate the viewer. For Buring i took the opengl visual. always moving - rename quake3 SEntity to IEntity to be confom with IShader even IShader and IEntity are none pure virtual interfaces like most irrlicht objects git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2207 dfc29bdd-3216-0410-991c-e03cc46cb475
2009-02-10 07:08:23 -08:00
doLightRecalc ();
ILightSceneNode::deserializeAttributes(in, options);
}
//! Creates a clone of this scene node and its children.
ISceneNode* CLightSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
{
if (!newParent)
newParent = Parent;
if (!newManager)
newManager = SceneManager;
CLightSceneNode* nb = new CLightSceneNode(newParent,
newManager, ID, RelativeTranslation, LightData.DiffuseColor, LightData.Radius);
nb->cloneMembers(this, newManager);
nb->LightData = LightData;
nb->BBox = BBox;
nb->drop();
return nb;
}
} // end namespace scene
} // end namespace irr