irrlicht/source/Irrlicht/CLightSceneNode.cpp

263 lines
7.4 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);
doLightRecalc();
}
//! 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);
}
//! 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()
{
Changes in 1.6 TA - fixed createMeshWith2TCoords normals were missing during copy. - addded //! Creates a copy of the mesh, which will only consist of S3DVertex vertices. IMesh* CMeshManipulator::createMeshWith1TCoords(IMesh* mesh) const - added io::IFileSystem* CSceneManager::getFileSystem() for preparing to remove the (mostly) unnecessary double member variables in many loaders - added virtual const c8* ISceneManager::getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type); to the SceneManger Interface. just like getTypeName is public - added CSceneNodeAnimatorFlyCircle::radiusEllipsoid. if radiusEllipsoid == 0 the default circle animation is done else radiusEllipsoid forms the b-axe of the ellipsoid. -> gummiball bouncing - added ISceneManager::createFlyStraightAnimator variable bool ping-pong used in loop mode to device if start from beginning ( default ) or make ping-pong -> straight bouncing - changed IFileSystem::registerFileArchive remove the index of the hiarchy and added a new interface method //! move the hirarchy of the filesystem. moves sourceIndex relative up or down virtual bool moveFileArchive( u32 sourceIndex, s32 relative ) = 0; - bugfix and changes in SViewFrustum::SViewFrustum wrong size of Matrices copy. This bug must be ages old... (typo) detected during resizing the Matrices. removed obsolute Matrices renamed E_TRANSFORMATION_STATE_2 to E_TRANSFORMATION_STATE_FRUSTUM therefore also changed SViewFrustum::setTransformState to not tap in the pitfall again of wrong memory... and renamed it to getTransform, like in the driver and Matrices private - OpenGL: Specular - moved //! EMT_ONETEXTURE_BLEND: has BlendFactor Alphablending inline bool textureBlendFunc_hasAlpha ( E_BLEND_FACTOR factor ) const from the material renderes ( 3x declared ) to SMaterial.h - updated managed light example to use standard driver selection - BurningsVideo - LightModel reworked. Point Light & Direction Light works for Diffuse Color as aspected Specular and Fog still have problems ( needs new pixel shader ) pushed burningsvideo to 0.42 for this major step - removed obsolete matrix transformations renamed E_TRANSFORMATION_STATE_2 to E_TRANSFORMATION_STATE_BURNING - cleaned line3d.h vector3d.h template behavior. many mixed f32/f64 implementations are here. i'm not sure if this should be the default behavior to use f64 for example for 1.0/x value, because they benefit from more precisions, but in my point of view the user is responsible of choosing a vector3d<f32> or vector3d<f64>. - added core::squareroot to irrmath.h -> for having candidates for faster math in the same file - added AllowZWriteOnTransparent from SceneManager to burningsvideo Following SceneManger guideline -added hasAlpha() to ITexture This info can be used for e.q to downgrade a transparent alpha channel blit to add if the texture has no alpha channel. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2199 dfc29bdd-3216-0410-991c-e03cc46cb475
2009-02-05 07:33:55 -08:00
//LightData.Type = video::ELT_DIRECTIONAL;
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");
if (in->existsAttribute("Attenuation")) // might not exist in older files
LightData.Attenuation = in->getAttributeAsVector3d("Attenuation");
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.Radius = in->getAttributeAsFloat("Radius");
LightData.CastShadows = in->getAttributeAsBool("CastShadows");
LightData.Type = (video::E_LIGHT_TYPE)in->getAttributeAsEnumeration("LightType", video::LightTypeNames);
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