Commit 64e4fe57 authored by hybrid's avatar hybrid

Add shadow interface to static meshes

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4333 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 10139e71
...@@ -12,6 +12,7 @@ namespace irr ...@@ -12,6 +12,7 @@ namespace irr
namespace scene namespace scene
{ {
class IShadowVolumeSceneNode;
class IMesh; class IMesh;
...@@ -37,6 +38,25 @@ public: ...@@ -37,6 +38,25 @@ public:
/** \return Pointer to mesh which is displayed by this node. */ /** \return Pointer to mesh which is displayed by this node. */
virtual IMesh* getMesh(void) = 0; virtual IMesh* getMesh(void) = 0;
//! Creates shadow volume scene node as child of this node.
/** The shadow can be rendered using the ZPass or the zfail
method. ZPass is a little bit faster because the shadow volume
creation is easier, but with this method there occur ugly
looking artifacs when the camera is inside the shadow volume.
These error do not occur with the ZFail method.
\param shadowMesh: Optional custom mesh for shadow volume.
\param id: Id of the shadow scene node. This id can be used to
identify the node later.
\param zfailmethod: If set to true, the shadow will use the
zfail method, if not, zpass is used.
\param infinity: Value used by the shadow volume algorithm to
scale the shadow volume.
\return Pointer to the created shadow scene node. This pointer
should not be dropped. See IReferenceCounted::drop() for more
information. */
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh=0,
s32 id=-1, bool zfailmethod=true, f32 infinity=10000.0f) = 0;
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style.
/** In this way it is possible to change the materials of a mesh /** In this way it is possible to change the materials of a mesh
causing all mesh scene nodes referencing this mesh to change, too. causing all mesh scene nodes referencing this mesh to change, too.
......
...@@ -290,7 +290,6 @@ void CAnimatedMeshSceneNode::render() ...@@ -290,7 +290,6 @@ void CAnimatedMeshSceneNode::render()
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
if (Shadow && PassCount==1) if (Shadow && PassCount==1)
Shadow->updateShadowVolumes(); Shadow->updateShadowVolumes();
...@@ -1116,6 +1115,7 @@ ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* ...@@ -1116,6 +1115,7 @@ ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager*
newNode->LoopCallBack = LoopCallBack; newNode->LoopCallBack = LoopCallBack;
newNode->PassCount = PassCount; newNode->PassCount = PassCount;
newNode->Shadow = Shadow; newNode->Shadow = Shadow;
newNode->Shadow->grab();
newNode->JointChildSceneNodes = JointChildSceneNodes; newNode->JointChildSceneNodes = JointChildSceneNodes;
newNode->PretransitingSave = PretransitingSave; newNode->PretransitingSave = PretransitingSave;
newNode->RenderFromIdentity = RenderFromIdentity; newNode->RenderFromIdentity = RenderFromIdentity;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "S3DVertex.h" #include "S3DVertex.h"
#include "SMeshBuffer.h" #include "SMeshBuffer.h"
#include "os.h" #include "os.h"
#include "CShadowVolumeSceneNode.h"
namespace irr namespace irr
{ {
...@@ -32,7 +33,7 @@ CCubeSceneNode::CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr, ...@@ -32,7 +33,7 @@ CCubeSceneNode::CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr,
s32 id, const core::vector3df& position, s32 id, const core::vector3df& position,
const core::vector3df& rotation, const core::vector3df& scale) const core::vector3df& rotation, const core::vector3df& scale)
: IMeshSceneNode(parent, mgr, id, position, rotation, scale), : IMeshSceneNode(parent, mgr, id, position, rotation, scale),
Mesh(0), Size(size) Mesh(0), Shadow(0), Size(size)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CCubeSceneNode"); setDebugName("CCubeSceneNode");
...@@ -44,6 +45,8 @@ CCubeSceneNode::CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr, ...@@ -44,6 +45,8 @@ CCubeSceneNode::CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr,
CCubeSceneNode::~CCubeSceneNode() CCubeSceneNode::~CCubeSceneNode()
{ {
if (Shadow)
Shadow->drop();
if (Mesh) if (Mesh)
Mesh->drop(); Mesh->drop();
} }
...@@ -63,6 +66,9 @@ void CCubeSceneNode::render() ...@@ -63,6 +66,9 @@ void CCubeSceneNode::render()
video::IVideoDriver* driver = SceneManager->getVideoDriver(); video::IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
if (Shadow)
Shadow->updateShadowVolumes();
// for debug purposes only: // for debug purposes only:
video::SMaterial mat = Mesh->getMeshBuffer(0)->getMaterial(); video::SMaterial mat = Mesh->getMeshBuffer(0)->getMaterial();
...@@ -121,6 +127,40 @@ const core::aabbox3d<f32>& CCubeSceneNode::getBoundingBox() const ...@@ -121,6 +127,40 @@ const core::aabbox3d<f32>& CCubeSceneNode::getBoundingBox() const
} }
//! Removes a child from this scene node.
//! Implemented here, to be able to remove the shadow properly, if there is one,
//! or to remove attached childs.
bool CCubeSceneNode::removeChild(ISceneNode* child)
{
if (child && Shadow == child)
{
Shadow->drop();
Shadow = 0;
}
return ISceneNode::removeChild(child);
}
//! Creates shadow volume scene node as child of this node
//! and returns a pointer to it.
IShadowVolumeSceneNode* CCubeSceneNode::addShadowVolumeSceneNode(
const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity)
{
if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER))
return 0;
if (!shadowMesh)
shadowMesh = Mesh; // if null is given, use the mesh of node
if (Shadow)
Shadow->drop();
Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity);
return Shadow;
}
void CCubeSceneNode::OnRegisterSceneNode() void CCubeSceneNode::OnRegisterSceneNode()
{ {
if (IsVisible) if (IsVisible)
...@@ -180,6 +220,8 @@ ISceneNode* CCubeSceneNode::clone(ISceneNode* newParent, ISceneManager* newManag ...@@ -180,6 +220,8 @@ ISceneNode* CCubeSceneNode::clone(ISceneNode* newParent, ISceneManager* newManag
nb->cloneMembers(this, newManager); nb->cloneMembers(this, newManager);
nb->getMaterial(0) = getMaterial(0); nb->getMaterial(0) = getMaterial(0);
nb->Shadow = Shadow;
nb->Shadow->grab();
if ( newParent ) if ( newParent )
nb->drop(); nb->drop();
......
...@@ -45,6 +45,11 @@ namespace scene ...@@ -45,6 +45,11 @@ namespace scene
//! Returns type of the scene node //! Returns type of the scene node
virtual ESCENE_NODE_TYPE getType() const { return ESNT_CUBE; } virtual ESCENE_NODE_TYPE getType() const { return ESNT_CUBE; }
//! Creates shadow volume scene node as child of this node
//! and returns a pointer to it.
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh,
s32 id, bool zfailmethod=true, f32 infinity=10000.0f);
//! Writes attributes of the scene node. //! Writes attributes of the scene node.
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
...@@ -68,10 +73,16 @@ namespace scene ...@@ -68,10 +73,16 @@ namespace scene
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style //! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
virtual bool isReadOnlyMaterials() const { return false; } virtual bool isReadOnlyMaterials() const { return false; }
//! Removes a child from this scene node.
//! Implemented here, to be able to remove the shadow properly, if there is one,
//! or to remove attached childs.
virtual bool removeChild(ISceneNode* child);
private: private:
void setSize(); void setSize();
IMesh* Mesh; IMesh* Mesh;
IShadowVolumeSceneNode* Shadow;
f32 Size; f32 Size;
}; };
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "IAnimatedMesh.h" #include "IAnimatedMesh.h"
#include "IMaterialRenderer.h" #include "IMaterialRenderer.h"
#include "IFileSystem.h" #include "IFileSystem.h"
#include "CShadowVolumeSceneNode.h"
namespace irr namespace irr
{ {
...@@ -23,8 +24,8 @@ namespace scene ...@@ -23,8 +24,8 @@ namespace scene
CMeshSceneNode::CMeshSceneNode(IMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id, CMeshSceneNode::CMeshSceneNode(IMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id,
const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& position, const core::vector3df& rotation,
const core::vector3df& scale) const core::vector3df& scale)
: IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), PassCount(0), : IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), Shadow(0),
ReadOnlyMaterials(false) PassCount(0), ReadOnlyMaterials(false)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CMeshSceneNode"); setDebugName("CMeshSceneNode");
...@@ -37,6 +38,8 @@ CMeshSceneNode::CMeshSceneNode(IMesh* mesh, ISceneNode* parent, ISceneManager* m ...@@ -37,6 +38,8 @@ CMeshSceneNode::CMeshSceneNode(IMesh* mesh, ISceneNode* parent, ISceneManager* m
//! destructor //! destructor
CMeshSceneNode::~CMeshSceneNode() CMeshSceneNode::~CMeshSceneNode()
{ {
if (Shadow)
Shadow->drop();
if (Mesh) if (Mesh)
Mesh->drop(); Mesh->drop();
} }
...@@ -125,6 +128,9 @@ void CMeshSceneNode::render() ...@@ -125,6 +128,9 @@ void CMeshSceneNode::render()
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
Box = Mesh->getBoundingBox(); Box = Mesh->getBoundingBox();
if (Shadow && PassCount==1)
Shadow->updateShadowVolumes();
// for debug purposes only: // for debug purposes only:
bool renderMeshes = true; bool renderMeshes = true;
...@@ -221,6 +227,21 @@ void CMeshSceneNode::render() ...@@ -221,6 +227,21 @@ void CMeshSceneNode::render()
} }
//! Removes a child from this scene node.
//! Implemented here, to be able to remove the shadow properly, if there is one,
//! or to remove attached childs.
bool CMeshSceneNode::removeChild(ISceneNode* child)
{
if (child && Shadow == child)
{
Shadow->drop();
Shadow = 0;
}
return ISceneNode::removeChild(child);
}
//! returns the axis aligned bounding box of this node //! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CMeshSceneNode::getBoundingBox() const const core::aabbox3d<f32>& CMeshSceneNode::getBoundingBox() const
{ {
...@@ -273,6 +294,25 @@ void CMeshSceneNode::setMesh(IMesh* mesh) ...@@ -273,6 +294,25 @@ void CMeshSceneNode::setMesh(IMesh* mesh)
} }
//! Creates shadow volume scene node as child of this node
//! and returns a pointer to it.
IShadowVolumeSceneNode* CMeshSceneNode::addShadowVolumeSceneNode(
const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity)
{
if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER))
return 0;
if (!shadowMesh)
shadowMesh = Mesh; // if null is given, use the mesh of node
if (Shadow)
Shadow->drop();
Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity);
return Shadow;
}
void CMeshSceneNode::copyMaterials() void CMeshSceneNode::copyMaterials()
{ {
Materials.clear(); Materials.clear();
...@@ -392,6 +432,8 @@ ISceneNode* CMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManag ...@@ -392,6 +432,8 @@ ISceneNode* CMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManag
nb->cloneMembers(this, newManager); nb->cloneMembers(this, newManager);
nb->ReadOnlyMaterials = ReadOnlyMaterials; nb->ReadOnlyMaterials = ReadOnlyMaterials;
nb->Materials = Materials; nb->Materials = Materials;
nb->Shadow = Shadow;
nb->Shadow->grab();
if (newParent) if (newParent)
nb->drop(); nb->drop();
......
...@@ -60,6 +60,11 @@ namespace scene ...@@ -60,6 +60,11 @@ namespace scene
//! Returns the current mesh //! Returns the current mesh
virtual IMesh* getMesh(void) { return Mesh; } virtual IMesh* getMesh(void) { return Mesh; }
//! Creates shadow volume scene node as child of this node
//! and returns a pointer to it.
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh,
s32 id, bool zfailmethod=true, f32 infinity=10000.0f);
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style.
/* In this way it is possible to change the materials a mesh causing all mesh scene nodes /* In this way it is possible to change the materials a mesh causing all mesh scene nodes
referencing this mesh to change too. */ referencing this mesh to change too. */
...@@ -71,6 +76,11 @@ namespace scene ...@@ -71,6 +76,11 @@ namespace scene
//! Creates a clone of this scene node and its children. //! Creates a clone of this scene node and its children.
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
//! Removes a child from this scene node.
//! Implemented here, to be able to remove the shadow properly, if there is one,
//! or to remove attached childs.
virtual bool removeChild(ISceneNode* child);
protected: protected:
void copyMaterials(); void copyMaterials();
...@@ -80,6 +90,7 @@ namespace scene ...@@ -80,6 +90,7 @@ namespace scene
video::SMaterial ReadOnlyMaterial; video::SMaterial ReadOnlyMaterial;
IMesh* Mesh; IMesh* Mesh;
IShadowVolumeSceneNode* Shadow;
s32 PassCount; s32 PassCount;
bool ReadOnlyMaterials; bool ReadOnlyMaterials;
......
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
#include "IMeshCache.h" #include "IMeshCache.h"
#include "IAnimatedMesh.h" #include "IAnimatedMesh.h"
#include "IMaterialRenderer.h" #include "IMaterialRenderer.h"
#include "os.h" #include "os.h"
#include "CShadowVolumeSceneNode.h"
namespace irr namespace irr
{ {
...@@ -24,7 +24,7 @@ COctreeSceneNode::COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr, ...@@ -24,7 +24,7 @@ COctreeSceneNode::COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr,
s32 id, s32 minimalPolysPerNode) s32 id, s32 minimalPolysPerNode)
: IMeshSceneNode(parent, mgr, id), StdOctree(0), LightMapOctree(0), : IMeshSceneNode(parent, mgr, id), StdOctree(0), LightMapOctree(0),
TangentsOctree(0), VertexType((video::E_VERTEX_TYPE)-1), TangentsOctree(0), VertexType((video::E_VERTEX_TYPE)-1),
MinimalPolysPerNode(minimalPolysPerNode), Mesh(0), MinimalPolysPerNode(minimalPolysPerNode), Mesh(0), Shadow(0),
UseVBOs(OCTREE_USE_HARDWARE), UseVisibilityAndVBOs(OCTREE_USE_VISIBILITY), UseVBOs(OCTREE_USE_HARDWARE), UseVisibilityAndVBOs(OCTREE_USE_VISIBILITY),
BoxBased(OCTREE_BOX_BASED) BoxBased(OCTREE_BOX_BASED)
{ {
...@@ -37,6 +37,8 @@ COctreeSceneNode::COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr, ...@@ -37,6 +37,8 @@ COctreeSceneNode::COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr,
//! destructor //! destructor
COctreeSceneNode::~COctreeSceneNode() COctreeSceneNode::~COctreeSceneNode()
{ {
if (Shadow)
Shadow->drop();
deleteTree(); deleteTree();
} }
...@@ -102,6 +104,9 @@ void COctreeSceneNode::render() ...@@ -102,6 +104,9 @@ void COctreeSceneNode::render()
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
if (Shadow)
Shadow->updateShadowVolumes();
SViewFrustum frust = *camera->getViewFrustum(); SViewFrustum frust = *camera->getViewFrustum();
//transform the frustum to the current absolute transformation //transform the frustum to the current absolute transformation
...@@ -281,6 +286,40 @@ void COctreeSceneNode::render() ...@@ -281,6 +286,40 @@ void COctreeSceneNode::render()
} }
//! Removes a child from this scene node.
//! Implemented here, to be able to remove the shadow properly, if there is one,
//! or to remove attached childs.
bool COctreeSceneNode::removeChild(ISceneNode* child)
{
if (child && Shadow == child)
{
Shadow->drop();
Shadow = 0;
}
return ISceneNode::removeChild(child);
}
//! Creates shadow volume scene node as child of this node
//! and returns a pointer to it.
IShadowVolumeSceneNode* COctreeSceneNode::addShadowVolumeSceneNode(
const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity)
{
if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER))
return 0;
if (!shadowMesh)
shadowMesh = Mesh; // if null is given, use the mesh of node
if (Shadow)
Shadow->drop();
Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity);
return Shadow;
}
//! returns the axis aligned bounding box of this node //! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& COctreeSceneNode::getBoundingBox() const const core::aabbox3d<f32>& COctreeSceneNode::getBoundingBox() const
{ {
......
...@@ -66,6 +66,16 @@ namespace scene ...@@ -66,6 +66,16 @@ namespace scene
//! Check if the scene node should not copy the materials of the mesh but use them in a read only style //! Check if the scene node should not copy the materials of the mesh but use them in a read only style
virtual bool isReadOnlyMaterials() const; virtual bool isReadOnlyMaterials() const;
//! Creates shadow volume scene node as child of this node
//! and returns a pointer to it.
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh,
s32 id, bool zfailmethod=true, f32 infinity=10000.0f);
//! Removes a child from this scene node.
//! Implemented here, to be able to remove the shadow properly, if there is one,
//! or to remove attached childs.
virtual bool removeChild(ISceneNode* child);
private: private:
void deleteTree(); void deleteTree();
...@@ -89,6 +99,7 @@ namespace scene ...@@ -89,6 +99,7 @@ namespace scene
s32 PassCount; s32 PassCount;
IMesh * Mesh; IMesh * Mesh;
IShadowVolumeSceneNode* Shadow;
//! use VBOs for rendering where possible //! use VBOs for rendering where possible
bool UseVBOs; bool UseVBOs;
//! use visibility information together with VBOs //! use visibility information together with VBOs
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "IMeshManipulator.h" #include "IMeshManipulator.h"
#include "SMesh.h" #include "SMesh.h"
#include "IMaterialRenderer.h" #include "IMaterialRenderer.h"
#include "CShadowVolumeSceneNode.h"
namespace irr namespace irr
{ {
...@@ -33,7 +34,7 @@ CQuake3ShaderSceneNode::CQuake3ShaderSceneNode( ...@@ -33,7 +34,7 @@ CQuake3ShaderSceneNode::CQuake3ShaderSceneNode(
core::vector3df(0.f, 0.f, 0.f), core::vector3df(0.f, 0.f, 0.f),
core::vector3df(0.f, 0.f, 0.f), core::vector3df(0.f, 0.f, 0.f),
core::vector3df(1.f, 1.f, 1.f)), core::vector3df(1.f, 1.f, 1.f)),
Shader(shader), Mesh(0), Original(0), MeshBuffer(0), TimeAbs(0.f) Shader(shader), Mesh(0), Shadow(0), Original(0), MeshBuffer(0), TimeAbs(0.f)
{ {
#ifdef _DEBUG #ifdef _DEBUG
core::stringc dName = "CQuake3ShaderSceneNode "; core::stringc dName = "CQuake3ShaderSceneNode ";
...@@ -71,6 +72,9 @@ CQuake3ShaderSceneNode::CQuake3ShaderSceneNode( ...@@ -71,6 +72,9 @@ CQuake3ShaderSceneNode::CQuake3ShaderSceneNode(
*/ */
CQuake3ShaderSceneNode::~CQuake3ShaderSceneNode() CQuake3ShaderSceneNode::~CQuake3ShaderSceneNode()
{ {
if (Shadow)
Shadow->drop();
if (Mesh) if (Mesh)
Mesh->drop(); Mesh->drop();
...@@ -336,6 +340,8 @@ void CQuake3ShaderSceneNode::render() ...@@ -336,6 +340,8 @@ void CQuake3ShaderSceneNode::render()
} }
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation ); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation );
if (Shadow)
Shadow->updateShadowVolumes();
//! render all stages //! render all stages
u32 drawCount = (pass == ESNRP_TRANSPARENT_EFFECT) ? 1 : 0; u32 drawCount = (pass == ESNRP_TRANSPARENT_EFFECT) ? 1 : 0;
...@@ -490,6 +496,40 @@ void CQuake3ShaderSceneNode::render() ...@@ -490,6 +496,40 @@ void CQuake3ShaderSceneNode::render()
} }
//! Removes a child from this scene node.
//! Implemented here, to be able to remove the shadow properly, if there is one,
//! or to remove attached childs.
bool CQuake3ShaderSceneNode::removeChild(ISceneNode* child)
{
if (child && Shadow == child)
{
Shadow->drop();
Shadow = 0;
}
return ISceneNode::removeChild(child);
}
//! Creates shadow volume scene node as child of this node
//! and returns a pointer to it.
IShadowVolumeSceneNode* CQuake3ShaderSceneNode::addShadowVolumeSceneNode(
const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity)
{
if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER))
return 0;
if (!shadowMesh)
shadowMesh = Mesh; // if null is given, use the mesh of node
if (Shadow)
Shadow->drop();
Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity);
return Shadow;
}
/*! /*!
3.3.1 deformVertexes wave <div> <func> <base> <amplitude> <phase> <freq> 3.3.1 deformVertexes wave <div> <func> <base> <amplitude> <phase> <freq>
Designed for water surfaces, modifying the values differently at each point. Designed for water surfaces, modifying the values differently at each point.
......
...@@ -47,9 +47,20 @@ public: ...@@ -47,9 +47,20 @@ public:
virtual void setReadOnlyMaterials(bool readonly) {} virtual void setReadOnlyMaterials(bool readonly) {}
virtual bool isReadOnlyMaterials() const { return true; } virtual bool isReadOnlyMaterials() const { return true; }
//! Creates shadow volume scene node as child of this node
//! and returns a pointer to it.
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh,
s32 id, bool zfailmethod=true, f32 infinity=10000.0f);
//! Removes a child from this scene node.
//! Implemented here, to be able to remove the shadow properly, if there is one,
//! or to remove attached childs.
virtual bool removeChild(ISceneNode* child);
private: private:
const quake3::IShader* Shader; const quake3::IShader* Shader;
SMesh *Mesh; SMesh *Mesh;
IShadowVolumeSceneNode* Shadow;
const SMeshBufferLightMap* Original; const SMeshBufferLightMap* Original;
SMeshBuffer* MeshBuffer; SMeshBuffer* MeshBuffer;
core::vector3df MeshOffset; core::vector3df MeshOffset;
......
...@@ -203,7 +203,7 @@ u32 CShadowVolumeSceneNode::createEdgesAndCaps(const core::vector3df& light, ...@@ -203,7 +203,7 @@ u32 CShadowVolumeSceneNode::createEdgesAndCaps(const core::vector3df& light,
void CShadowVolumeSceneNode::setShadowMesh(const IMesh* mesh) void CShadowVolumeSceneNode::setShadowMesh(const IMesh* mesh)
{ {
if (ShadowMesh == mesh) if (ShadowMesh == mesh)
return; return;
if (ShadowMesh) if (ShadowMesh)
ShadowMesh->drop(); ShadowMesh->drop();
...@@ -227,8 +227,8 @@ void CShadowVolumeSceneNode::updateShadowVolumes() ...@@ -227,8 +227,8 @@ void CShadowVolumeSceneNode::updateShadowVolumes()
// create as much shadow volumes as there are lights but // create as much shadow volumes as there are lights but
// do not ignore the max light settings. // do not ignore the max light settings.
const u32 lights = SceneManager->getVideoDriver()->getDynamicLightCount(); const u32 lightCount = SceneManager->getVideoDriver()->getDynamicLightCount();
if (!lights) if (!lightCount)
return; return;
// calculate total amount of vertices and indices // calculate total amount of vertices and indices
...@@ -279,7 +279,7 @@ void CShadowVolumeSceneNode::updateShadowVolumes() ...@@ -279,7 +279,7 @@ void CShadowVolumeSceneNode::updateShadowVolumes()
const core::vector3df parentpos = Parent->getAbsolutePosition(); const core::vector3df parentpos = Parent->getAbsolutePosition();
// TODO: Only correct for point lights. // TODO: Only correct for point lights.
for (i=0; i<lights; ++i) for (i=0; i<lightCount; ++i)
{ {
const video::SLight& dl = SceneManager->getVideoDriver()->getDynamicLight(i); const video::SLight& dl = SceneManager->getVideoDriver()->getDynamicLight(i);
core::vector3df lpos = dl.Position; core::vector3df lpos = dl.Position;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "ISceneManager.h" #include "ISceneManager.h"
#include "S3DVertex.h" #include "S3DVertex.h"
#include "os.h" #include "os.h"
#include "CShadowVolumeSceneNode.h"
namespace irr namespace irr
{ {
...@@ -16,7 +17,7 @@ namespace scene ...@@ -16,7 +17,7 @@ namespace scene
//! constructor //! constructor
CSphereSceneNode::CSphereSceneNode(f32 radius, u32 polyCountX, u32 polyCountY, ISceneNode* parent, ISceneManager* mgr, s32 id, CSphereSceneNode::CSphereSceneNode(f32 radius, u32 polyCountX, u32 polyCountY, ISceneNode* parent, ISceneManager* mgr, s32 id,
const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale)
: IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), : IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), Shadow(0),
Radius(radius), PolyCountX(polyCountX), PolyCountY(polyCountY) Radius(radius), PolyCountX(polyCountX), PolyCountY(polyCountY)
{ {
#ifdef _DEBUG #ifdef _DEBUG
...@@ -31,6 +32,8 @@ CSphereSceneNode::CSphereSceneNode(f32 radius, u32 polyCountX, u32 polyCountY, I ...@@ -31,6 +32,8 @@ CSphereSceneNode::CSphereSceneNode(f32 radius, u32 polyCountX, u32 polyCountY, I
//! destructor //! destructor
CSphereSceneNode::~CSphereSceneNode() CSphereSceneNode::~CSphereSceneNode()
{ {
if (Shadow)
Shadow->drop();
if (Mesh) if (Mesh)
Mesh->drop(); Mesh->drop();
} }
...@@ -45,6 +48,9 @@ void CSphereSceneNode::render() ...@@ -45,6 +48,9 @@ void CSphereSceneNode::render()
{ {
driver->setMaterial(Mesh->getMeshBuffer(0)->getMaterial()); driver->setMaterial(Mesh->getMeshBuffer(0)->getMaterial());
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
if (Shadow)
Shadow->updateShadowVolumes();
driver->drawMeshBuffer(Mesh->getMeshBuffer(0)); driver->drawMeshBuffer(Mesh->getMeshBuffer(0));
if ( DebugDataVisible & scene::EDS_BBOX ) if ( DebugDataVisible & scene::EDS_BBOX )
{ {
...@@ -57,6 +63,39 @@ void CSphereSceneNode::render() ...@@ -57,6 +63,39 @@ void CSphereSceneNode::render()
} }
//! Removes a child from this scene node.
//! Implemented here, to be able to remove the shadow properly, if there is one,
//! or to remove attached childs.
bool CSphereSceneNode::removeChild(ISceneNode* child)
{
if (child && Shadow == child)
{
Shadow->drop();
Shadow = 0;
}
return ISceneNode::removeChild(child);
}
//! Creates shadow volume scene node as child of this node
//! and returns a pointer to it.
IShadowVolumeSceneNode* CSphereSceneNode::addShadowVolumeSceneNode(
const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity)
{
if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER))
return 0;
if (!shadowMesh)
shadowMesh = Mesh; // if null is given, use the mesh of node
if (Shadow)
Shadow->drop();
Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity);
return Shadow;
}
//! returns the axis aligned bounding box of this node //! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CSphereSceneNode::getBoundingBox() const const core::aabbox3d<f32>& CSphereSceneNode::getBoundingBox() const
...@@ -146,6 +185,8 @@ ISceneNode* CSphereSceneNode::clone(ISceneNode* newParent, ISceneManager* newMan ...@@ -146,6 +185,8 @@ ISceneNode* CSphereSceneNode::clone(ISceneNode* newParent, ISceneManager* newMan
nb->cloneMembers(this, newManager); nb->cloneMembers(this, newManager);
nb->getMaterial(0) = Mesh->getMeshBuffer(0)->getMaterial(); nb->getMaterial(0) = Mesh->getMeshBuffer(0)->getMaterial();
nb->Shadow = Shadow;
nb->Shadow->grab();
if ( newParent ) if ( newParent )
nb->drop(); nb->drop();
......
...@@ -69,9 +69,20 @@ namespace scene ...@@ -69,9 +69,20 @@ namespace scene
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style //! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
virtual bool isReadOnlyMaterials() const { return false; } virtual bool isReadOnlyMaterials() const { return false; }
//! Creates shadow volume scene node as child of this node
//! and returns a pointer to it.
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh,
s32 id, bool zfailmethod=true, f32 infinity=10000.0f);
//! Removes a child from this scene node.
//! Implemented here, to be able to remove the shadow properly, if there is one,
//! or to remove attached childs.
virtual bool removeChild(ISceneNode* child);
private: private:
IMesh* Mesh; IMesh* Mesh;
IShadowVolumeSceneNode* Shadow;
core::aabbox3d<f32> Box; core::aabbox3d<f32> Box;
f32 Radius; f32 Radius;
u32 PolyCountX; u32 PolyCountX;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment