GLES drivers adapted, but only did make compile-tests. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@6038 dfc29bdd-3216-0410-991c-e03cc46cb475
		
			
				
	
	
		
			282 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			282 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright (C) 2002-2012 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();	// TODO: since doLightRecalc has now been added to updateAbsolutePosition it might be possible to remove this one.
 | |
| 
 | |
| 	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;
 | |
| 			default:
 | |
| 				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);
 | |
| 	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 );
 | |
| 		setAutomaticCulling( scene::EAC_OFF );
 | |
| 		LightData.Position = getAbsolutePosition();
 | |
| 	}
 | |
| 	if (LightData.Type == video::ELT_DIRECTIONAL)
 | |
| 	{
 | |
| 		BBox.reset( 0, 0, 0 );
 | |
| 		setAutomaticCulling( scene::EAC_OFF );
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void CLightSceneNode::updateAbsolutePosition()
 | |
| {
 | |
| 	ILightSceneNode::updateAbsolutePosition();
 | |
| 	doLightRecalc();
 | |
| }
 | |
| 
 | |
| 
 | |
| //! 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");
 | |
| 
 | |
| 	//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");
 | |
| 
 | |
| 	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);
 | |
| 
 | |
| 	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;
 | |
| 
 | |
| 	if ( newParent )
 | |
| 		nb->drop();
 | |
| 	return nb;
 | |
| }
 | |
| 
 | |
| } // end namespace scene
 | |
| } // end namespace irr
 | |
| 
 |