]> git.lizzy.rs Git - irrlicht.git/blobdiff - source/Irrlicht/CLightSceneNode.cpp
Add back lighting system
[irrlicht.git] / source / Irrlicht / CLightSceneNode.cpp
diff --git a/source/Irrlicht/CLightSceneNode.cpp b/source/Irrlicht/CLightSceneNode.cpp
new file mode 100644 (file)
index 0000000..ac94508
--- /dev/null
@@ -0,0 +1,233 @@
+// 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