--- /dev/null
+// Copyright (C) 2002-2012 Nikolaus Gebhardt\r
+// This file is part of the "Irrlicht Engine".\r
+// For conditions of distribution and use, see copyright notice in irrlicht.h\r
+\r
+#include "CLightSceneNode.h"\r
+#include "IVideoDriver.h"\r
+#include "ISceneManager.h"\r
+#include "ICameraSceneNode.h"\r
+\r
+#include "os.h"\r
+\r
+namespace irr\r
+{\r
+namespace scene\r
+{\r
+\r
+//! constructor\r
+CLightSceneNode::CLightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,\r
+ const core::vector3df& position, video::SColorf color, f32 radius)\r
+: ILightSceneNode(parent, mgr, id, position), DriverLightIndex(-1), LightIsOn(true)\r
+{\r
+ #ifdef _DEBUG\r
+ setDebugName("CLightSceneNode");\r
+ #endif\r
+\r
+ LightData.DiffuseColor = color;\r
+ // set some useful specular color\r
+ LightData.SpecularColor = color.getInterpolated(video::SColor(255,255,255,255),0.7f);\r
+\r
+ setRadius(radius);\r
+}\r
+\r
+\r
+//! pre render event\r
+void CLightSceneNode::OnRegisterSceneNode()\r
+{\r
+ doLightRecalc(); // TODO: since doLightRecalc has now been added to updateAbsolutePosition it might be possible to remove this one.\r
+\r
+ if (IsVisible)\r
+ SceneManager->registerNodeForRendering(this, ESNRP_LIGHT);\r
+\r
+ ISceneNode::OnRegisterSceneNode();\r
+}\r
+\r
+\r
+//! render\r
+void CLightSceneNode::render()\r
+{\r
+ video::IVideoDriver* driver = SceneManager->getVideoDriver();\r
+ if (!driver)\r
+ return;\r
+\r
+ if ( DebugDataVisible & scene::EDS_BBOX )\r
+ {\r
+ driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);\r
+ video::SMaterial m;\r
+ m.Lighting = false;\r
+ driver->setMaterial(m);\r
+\r
+ switch ( LightData.Type )\r
+ {\r
+ case video::ELT_POINT:\r
+ case video::ELT_SPOT:\r
+ driver->draw3DBox(BBox, LightData.DiffuseColor.toSColor());\r
+ break;\r
+\r
+ case video::ELT_DIRECTIONAL:\r
+ driver->draw3DLine(core::vector3df(0.f, 0.f, 0.f),\r
+ LightData.Direction * LightData.Radius,\r
+ LightData.DiffuseColor.toSColor());\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+ DriverLightIndex = driver->addDynamicLight(LightData);\r
+ setVisible(LightIsOn);\r
+}\r
+\r
+\r
+//! sets the light data\r
+void CLightSceneNode::setLightData(const video::SLight& light)\r
+{\r
+ LightData = light;\r
+}\r
+\r
+\r
+//! \return Returns the light data.\r
+const video::SLight& CLightSceneNode::getLightData() const\r
+{\r
+ return LightData;\r
+}\r
+\r
+\r
+//! \return Returns the light data.\r
+video::SLight& CLightSceneNode::getLightData()\r
+{\r
+ return LightData;\r
+}\r
+\r
+void CLightSceneNode::setVisible(bool isVisible)\r
+{\r
+ ISceneNode::setVisible(isVisible);\r
+\r
+ if(DriverLightIndex < 0)\r
+ return;\r
+ video::IVideoDriver* driver = SceneManager->getVideoDriver();\r
+ if (!driver)\r
+ return;\r
+\r
+ LightIsOn = isVisible;\r
+ driver->turnLightOn((u32)DriverLightIndex, LightIsOn);\r
+}\r
+\r
+//! returns the axis aligned bounding box of this node\r
+const core::aabbox3d<f32>& CLightSceneNode::getBoundingBox() const\r
+{\r
+ return BBox;\r
+}\r
+\r
+\r
+//! Sets the light's radius of influence.\r
+/** Outside this radius the light won't lighten geometry and cast no\r
+shadows. Setting the radius will also influence the attenuation, setting\r
+it to (0,1/radius,0). If you want to override this behavior, set the\r
+attenuation after the radius.\r
+\param radius The new radius. */\r
+void CLightSceneNode::setRadius(f32 radius)\r
+{\r
+ LightData.Radius=radius;\r
+ LightData.Attenuation.set(0.f, 1.f/radius, 0.f);\r
+ doLightRecalc();\r
+}\r
+\r
+\r
+//! Gets the light's radius of influence.\r
+/** \return The current radius. */\r
+f32 CLightSceneNode::getRadius() const\r
+{\r
+ return LightData.Radius;\r
+}\r
+\r
+\r
+//! Sets the light type.\r
+/** \param type The new type. */\r
+void CLightSceneNode::setLightType(video::E_LIGHT_TYPE type)\r
+{\r
+ LightData.Type=type;\r
+}\r
+\r
+\r
+//! Gets the light type.\r
+/** \return The current light type. */\r
+video::E_LIGHT_TYPE CLightSceneNode::getLightType() const\r
+{\r
+ return LightData.Type;\r
+}\r
+\r
+\r
+//! Sets whether this light casts shadows.\r
+/** Enabling this flag won't automatically cast shadows, the meshes\r
+will still need shadow scene nodes attached. But one can enable or\r
+disable distinct lights for shadow casting for performance reasons.\r
+\param shadow True if this light shall cast shadows. */\r
+void CLightSceneNode::enableCastShadow(bool shadow)\r
+{\r
+ LightData.CastShadows=shadow;\r
+}\r
+\r
+\r
+//! Check whether this light casts shadows.\r
+/** \return True if light would cast shadows, else false. */\r
+bool CLightSceneNode::getCastShadow() const\r
+{\r
+ return LightData.CastShadows;\r
+}\r
+\r
+\r
+void CLightSceneNode::doLightRecalc()\r
+{\r
+ if ((LightData.Type == video::ELT_SPOT) || (LightData.Type == video::ELT_DIRECTIONAL))\r
+ {\r
+ LightData.Direction = core::vector3df(.0f,.0f,1.0f);\r
+ getAbsoluteTransformation().rotateVect(LightData.Direction);\r
+ LightData.Direction.normalize();\r
+ }\r
+ if ((LightData.Type == video::ELT_SPOT) || (LightData.Type == video::ELT_POINT))\r
+ {\r
+ const f32 r = LightData.Radius * LightData.Radius * 0.5f;\r
+ BBox.MaxEdge.set( r, r, r );\r
+ BBox.MinEdge.set( -r, -r, -r );\r
+ //setAutomaticCulling( scene::EAC_BOX );\r
+ setAutomaticCulling( scene::EAC_OFF );\r
+ LightData.Position = getAbsolutePosition();\r
+ }\r
+ if (LightData.Type == video::ELT_DIRECTIONAL)\r
+ {\r
+ BBox.reset( 0, 0, 0 );\r
+ setAutomaticCulling( scene::EAC_OFF );\r
+ }\r
+}\r
+\r
+void CLightSceneNode::updateAbsolutePosition()\r
+{\r
+ ILightSceneNode::updateAbsolutePosition();\r
+ doLightRecalc();\r
+}\r
+\r
+\r
+//! Creates a clone of this scene node and its children.\r
+ISceneNode* CLightSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)\r
+{\r
+ if (!newParent)\r
+ newParent = Parent;\r
+ if (!newManager)\r
+ newManager = SceneManager;\r
+\r
+ CLightSceneNode* nb = new CLightSceneNode(newParent,\r
+ newManager, ID, RelativeTranslation, LightData.DiffuseColor, LightData.Radius);\r
+\r
+ nb->cloneMembers(this, newManager);\r
+ nb->LightData = LightData;\r
+ nb->BBox = BBox;\r
+\r
+ if ( newParent )\r
+ nb->drop();\r
+ return nb;\r
+}\r
+\r
+} // end namespace scene\r
+} // end namespace irr\r
+\r