Remove shadow volume code

We use shadowmap
This commit is contained in:
Vincent Lejeune 2015-01-16 01:51:56 +01:00
parent d3708ba798
commit c1d85e8674
16 changed files with 5 additions and 749 deletions

View File

@ -148,7 +148,6 @@ source/Irrlicht/CGUISpinBox.cpp
source/Irrlicht/CReadFile.cpp
source/Irrlicht/CParticleRingEmitter.cpp
source/Irrlicht/CMetaTriangleSelector.cpp
source/Irrlicht/CShadowVolumeSceneNode.cpp
source/Irrlicht/CDefaultSceneNodeFactory.cpp
source/Irrlicht/CGUIImage.cpp
source/Irrlicht/CGUIEnvironment.cpp
@ -233,7 +232,6 @@ source/Irrlicht/CSphereSceneNode.h
source/Irrlicht/CIrrDeviceStub.h
source/Irrlicht/CDummyTransformationSceneNode.h
source/Irrlicht/CParticleBoxEmitter.h
source/Irrlicht/CShadowVolumeSceneNode.h
source/Irrlicht/COctreeSceneNode.h
source/Irrlicht/CReadFile.h
source/Irrlicht/COSOperator.h

View File

@ -94,27 +94,6 @@ namespace scene
/** \return The importance of the animation: 1.f keeps the original animation, 0.f is no animation. */
virtual f32 getAnimationStrength() const =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 (for zfail shadow volume we support only
finite shadows, so camera zfar must be larger than shadow back cap,
which is depend on infinity parameter).
\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=1000.0f) = 0;
//! Get a pointer to a joint in the mesh (if the mesh is a bone based mesh).
/** With this method it is possible to attach scene nodes to

View File

@ -38,27 +38,6 @@ public:
/** \return Pointer to mesh which is displayed by this node. */
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 (for zfail shadow volume we support only
finite shadows, so camera zfar must be larger than shadow back cap,
which is depend on infinity parameter).
\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=1000.0f) = 0;
//! 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
causing all mesh scene nodes referencing this mesh to change, too.

View File

@ -7,7 +7,6 @@
#include "ISceneManager.h"
#include "S3DVertex.h"
#include "os.h"
#include "CShadowVolumeSceneNode.h"
#include "CSkinnedMesh.h"
#include "IDummyTransformationSceneNode.h"
#include "IBoneSceneNode.h"
@ -37,7 +36,7 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh,
TransitionTime(0), Transiting(0.f), TransitingBlend(0.f),
JointMode(EJUOR_NONE), JointsUsed(false),
Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(false),
LoopCallBack(0), PassCount(0), Shadow(0)
LoopCallBack(0), PassCount(0)
{
#ifdef _DEBUG
setDebugName("CAnimatedMeshSceneNode");
@ -53,9 +52,6 @@ CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode()
if (Mesh)
Mesh->drop();
if (Shadow)
Shadow->drop();
if (LoopCallBack)
LoopCallBack->drop();
}
@ -287,9 +283,6 @@ void CAnimatedMeshSceneNode::render()
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
if (Shadow && PassCount==1)
Shadow->updateShadowVolumes();
// for debug purposes only:
bool renderMeshes = true;
@ -523,23 +516,6 @@ u32 CAnimatedMeshSceneNode::getMaterialCount() const
}
//! Creates shadow volume scene node as child of this node
//! and returns a pointer to it.
IShadowVolumeSceneNode* CAnimatedMeshSceneNode::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 a pointer to a child node, which has the same transformation as
//! the corresponding joint, if the mesh in this scene node is a skinned mesh.
@ -644,12 +620,6 @@ ISceneNode* CAnimatedMeshSceneNode::getXJointNode(const c8* jointName)
//! or to remove attached childs.
bool CAnimatedMeshSceneNode::removeChild(ISceneNode* child)
{
if (child && Shadow == child)
{
Shadow->drop();
Shadow = 0;
}
if (ISceneNode::removeChild(child))
{
if (JointsUsed) //stop weird bugs caused while changing parents as the joints are being created
@ -1015,8 +985,6 @@ ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager*
newNode->ReadOnlyMaterials = ReadOnlyMaterials;
newNode->LoopCallBack = LoopCallBack;
newNode->PassCount = PassCount;
newNode->Shadow = Shadow;
newNode->Shadow->grab();
newNode->JointChildSceneNodes = JointChildSceneNodes;
newNode->PretransitingSave = PretransitingSave;
newNode->RenderFromIdentity = RenderFromIdentity;

View File

@ -84,11 +84,6 @@ namespace scene
//! returns amount of materials used by this scene node.
virtual u32 getMaterialCount() 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=1000.0f);
//! Returns a pointer to a child node, which has the same transformation as
//! the corrsesponding joint, if the mesh in this scene node is a skinned mesh.
virtual IBoneSceneNode* getJointNode(const c8* jointName);
@ -199,8 +194,6 @@ namespace scene
IAnimationEndCallBack* LoopCallBack;
s32 PassCount;
IShadowVolumeSceneNode* Shadow;
core::array<IBoneSceneNode* > JointChildSceneNodes;
core::array<core::matrix4> PretransitingSave;
};

View File

@ -8,7 +8,6 @@
#include "S3DVertex.h"
#include "SMeshBuffer.h"
#include "os.h"
#include "CShadowVolumeSceneNode.h"
namespace irr
{
@ -33,7 +32,7 @@ CCubeSceneNode::CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr,
s32 id, const core::vector3df& position,
const core::vector3df& rotation, const core::vector3df& scale)
: IMeshSceneNode(parent, mgr, id, position, rotation, scale),
Mesh(0), Shadow(0), Size(size)
Mesh(0), Size(size)
{
#ifdef _DEBUG
setDebugName("CCubeSceneNode");
@ -45,8 +44,6 @@ CCubeSceneNode::CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr,
CCubeSceneNode::~CCubeSceneNode()
{
if (Shadow)
Shadow->drop();
if (Mesh)
Mesh->drop();
}
@ -66,9 +63,6 @@ void CCubeSceneNode::render()
video::IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
if (Shadow)
Shadow->updateShadowVolumes();
// for debug purposes only:
video::SMaterial mat = Mesh->getMeshBuffer(0)->getMaterial();
@ -132,35 +126,10 @@ const core::aabbox3d<f32>& CCubeSceneNode::getBoundingBox() const
//! 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()
{
if (IsVisible)
@ -220,8 +189,6 @@ ISceneNode* CCubeSceneNode::clone(ISceneNode* newParent, ISceneManager* newManag
nb->cloneMembers(this, newManager);
nb->getMaterial(0) = getMaterial(0);
nb->Shadow = Shadow;
nb->Shadow->grab();
if ( newParent )
nb->drop();

View File

@ -45,11 +45,6 @@ namespace scene
//! Returns type of the scene node
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.
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
@ -82,7 +77,6 @@ namespace scene
void setSize();
IMesh* Mesh;
IShadowVolumeSceneNode* Shadow;
f32 Size;
};

View File

@ -11,7 +11,6 @@
#include "IAnimatedMesh.h"
#include "IMaterialRenderer.h"
#include "IFileSystem.h"
#include "CShadowVolumeSceneNode.h"
namespace irr
{
@ -24,7 +23,7 @@ namespace scene
CMeshSceneNode::CMeshSceneNode(IMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id,
const core::vector3df& position, const core::vector3df& rotation,
const core::vector3df& scale)
: IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), Shadow(0),
: IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0),
PassCount(0), ReadOnlyMaterials(false)
{
#ifdef _DEBUG
@ -38,8 +37,6 @@ CMeshSceneNode::CMeshSceneNode(IMesh* mesh, ISceneNode* parent, ISceneManager* m
//! destructor
CMeshSceneNode::~CMeshSceneNode()
{
if (Shadow)
Shadow->drop();
if (Mesh)
Mesh->drop();
}
@ -128,9 +125,6 @@ void CMeshSceneNode::render()
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
Box = Mesh->getBoundingBox();
if (Shadow && PassCount==1)
Shadow->updateShadowVolumes();
// for debug purposes only:
bool renderMeshes = true;
@ -232,12 +226,6 @@ void CMeshSceneNode::render()
//! or to remove attached childs.
bool CMeshSceneNode::removeChild(ISceneNode* child)
{
if (child && Shadow == child)
{
Shadow->drop();
Shadow = 0;
}
return ISceneNode::removeChild(child);
}
@ -294,25 +282,6 @@ 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()
{
Materials.clear();
@ -432,8 +401,6 @@ ISceneNode* CMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManag
nb->cloneMembers(this, newManager);
nb->ReadOnlyMaterials = ReadOnlyMaterials;
nb->Materials = Materials;
nb->Shadow = Shadow;
nb->Shadow->grab();
if (newParent)
nb->drop();

View File

@ -60,11 +60,6 @@ namespace scene
//! Returns the current 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.
/* In this way it is possible to change the materials a mesh causing all mesh scene nodes
referencing this mesh to change too. */
@ -90,7 +85,6 @@ namespace scene
video::SMaterial ReadOnlyMaterial;
IMesh* Mesh;
IShadowVolumeSceneNode* Shadow;
s32 PassCount;
bool ReadOnlyMaterials;

View File

@ -11,7 +11,6 @@
#include "IAnimatedMesh.h"
#include "IMaterialRenderer.h"
#include "os.h"
#include "CShadowVolumeSceneNode.h"
namespace irr
{
@ -24,7 +23,7 @@ COctreeSceneNode::COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr,
s32 id, s32 minimalPolysPerNode)
: IMeshSceneNode(parent, mgr, id), StdOctree(0), LightMapOctree(0),
TangentsOctree(0), VertexType((video::E_VERTEX_TYPE)-1),
MinimalPolysPerNode(minimalPolysPerNode), Mesh(0), Shadow(0),
MinimalPolysPerNode(minimalPolysPerNode), Mesh(0),
UseVBOs(OCTREE_USE_HARDWARE), UseVisibilityAndVBOs(OCTREE_USE_VISIBILITY),
BoxBased(OCTREE_BOX_BASED)
{
@ -37,8 +36,6 @@ COctreeSceneNode::COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr,
//! destructor
COctreeSceneNode::~COctreeSceneNode()
{
if (Shadow)
Shadow->drop();
deleteTree();
}
@ -104,9 +101,6 @@ void COctreeSceneNode::render()
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
if (Shadow)
Shadow->updateShadowVolumes();
SViewFrustum frust = *camera->getViewFrustum();
//transform the frustum to the current absolute transformation
@ -291,35 +285,10 @@ void COctreeSceneNode::render()
//! 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
const core::aabbox3d<f32>& COctreeSceneNode::getBoundingBox() const
{

View File

@ -66,11 +66,6 @@ namespace scene
//! 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;
//! 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.
@ -99,7 +94,6 @@ namespace scene
s32 PassCount;
IMesh * Mesh;
IShadowVolumeSceneNode* Shadow;
//! use VBOs for rendering where possible
bool UseVBOs;
//! use visibility information together with VBOs

View File

@ -1,419 +0,0 @@
// 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 "CShadowVolumeSceneNode.h"
#include "ISceneManager.h"
#include "IMesh.h"
#include "IVideoDriver.h"
#include "ICameraSceneNode.h"
#include "SViewFrustum.h"
#include "SLight.h"
#include "os.h"
namespace irr
{
namespace scene
{
//! constructor
CShadowVolumeSceneNode::CShadowVolumeSceneNode(const IMesh* shadowMesh, ISceneNode* parent,
ISceneManager* mgr, s32 id, bool zfailmethod, f32 infinity)
: IShadowVolumeSceneNode(parent, mgr, id),
ShadowMesh(0), IndexCount(0), VertexCount(0), ShadowVolumesUsed(0),
Infinity(infinity), UseZFailMethod(zfailmethod)
{
#ifdef _DEBUG
setDebugName("CShadowVolumeSceneNode");
#endif
setShadowMesh(shadowMesh);
setAutomaticCulling(scene::EAC_OFF);
}
//! destructor
CShadowVolumeSceneNode::~CShadowVolumeSceneNode()
{
if (ShadowMesh)
ShadowMesh->drop();
}
void CShadowVolumeSceneNode::createShadowVolume(const core::vector3df& light, bool isDirectional)
{
SShadowVolume* svp = 0;
core::aabbox3d<f32>* bb = 0;
// builds the shadow volume and adds it to the shadow volume list.
if (ShadowVolumes.size() > ShadowVolumesUsed)
{
// get the next unused buffer
svp = &ShadowVolumes[ShadowVolumesUsed];
svp->set_used(0);
bb = &ShadowBBox[ShadowVolumesUsed];
}
else
{
ShadowVolumes.push_back(SShadowVolume());
svp = &ShadowVolumes.getLast();
ShadowBBox.push_back(core::aabbox3d<f32>());
bb = &ShadowBBox.getLast();
}
svp->reallocate(IndexCount*5);
++ShadowVolumesUsed;
// We use triangle lists
Edges.set_used(IndexCount*2);
u32 numEdges = 0;
numEdges=createEdgesAndCaps(light, svp, bb);
// for all edges add the near->far quads
for (u32 i=0; i<numEdges; ++i)
{
const core::vector3df &v1 = Vertices[Edges[2*i+0]];
const core::vector3df &v2 = Vertices[Edges[2*i+1]];
const core::vector3df v3(v1+(v1 - light).normalize()*Infinity);
const core::vector3df v4(v2+(v2 - light).normalize()*Infinity);
// Add a quad (two triangles) to the vertex list
#ifdef _DEBUG
if (svp->size() >= svp->allocated_size()-5)
os::Printer::log("Allocation too small.", ELL_DEBUG);
#endif
svp->push_back(v1);
svp->push_back(v2);
svp->push_back(v3);
svp->push_back(v2);
svp->push_back(v4);
svp->push_back(v3);
}
}
#define IRR_USE_ADJACENCY
#define IRR_USE_REVERSE_EXTRUDED
u32 CShadowVolumeSceneNode::createEdgesAndCaps(const core::vector3df& light,
SShadowVolume* svp, core::aabbox3d<f32>* bb)
{
u32 numEdges=0;
const u32 faceCount = IndexCount / 3;
if(faceCount >= 1)
bb->reset(Vertices[Indices[0]]);
else
bb->reset(0,0,0);
// Check every face if it is front or back facing the light.
for (u32 i=0; i<faceCount; ++i)
{
const core::vector3df v0 = Vertices[Indices[3*i+0]];
const core::vector3df v1 = Vertices[Indices[3*i+1]];
const core::vector3df v2 = Vertices[Indices[3*i+2]];
#ifdef IRR_USE_REVERSE_EXTRUDED
FaceData[i]=core::triangle3df(v0,v1,v2).isFrontFacing(light);
#else
FaceData[i]=core::triangle3df(v2,v1,v0).isFrontFacing(light);
#endif
if (UseZFailMethod && FaceData[i])
{
#ifdef _DEBUG
if (svp->size() >= svp->allocated_size()-5)
os::Printer::log("Allocation too small.", ELL_DEBUG);
#endif
// add front cap from light-facing faces
svp->push_back(v2);
svp->push_back(v1);
svp->push_back(v0);
// add back cap
const core::vector3df i0 = v0+(v0-light).normalize()*Infinity;
const core::vector3df i1 = v1+(v1-light).normalize()*Infinity;
const core::vector3df i2 = v2+(v2-light).normalize()*Infinity;
svp->push_back(i0);
svp->push_back(i1);
svp->push_back(i2);
bb->addInternalPoint(i0);
bb->addInternalPoint(i1);
bb->addInternalPoint(i2);
}
}
// Create edges
for (u32 i=0; i<faceCount; ++i)
{
// check all front facing faces
if (FaceData[i] == true)
{
const u16 wFace0 = Indices[3*i+0];
const u16 wFace1 = Indices[3*i+1];
const u16 wFace2 = Indices[3*i+2];
const u16 adj0 = Adjacency[3*i+0];
const u16 adj1 = Adjacency[3*i+1];
const u16 adj2 = Adjacency[3*i+2];
// add edges if face is adjacent to back-facing face
// or if no adjacent face was found
#ifdef IRR_USE_ADJACENCY
if (adj0 == i || FaceData[adj0] == false)
#endif
{
// add edge v0-v1
Edges[2*numEdges+0] = wFace0;
Edges[2*numEdges+1] = wFace1;
++numEdges;
}
#ifdef IRR_USE_ADJACENCY
if (adj1 == i || FaceData[adj1] == false)
#endif
{
// add edge v1-v2
Edges[2*numEdges+0] = wFace1;
Edges[2*numEdges+1] = wFace2;
++numEdges;
}
#ifdef IRR_USE_ADJACENCY
if (adj2 == i || FaceData[adj2] == false)
#endif
{
// add edge v2-v0
Edges[2*numEdges+0] = wFace2;
Edges[2*numEdges+1] = wFace0;
++numEdges;
}
}
}
return numEdges;
}
void CShadowVolumeSceneNode::setShadowMesh(const IMesh* mesh)
{
if (ShadowMesh == mesh)
return;
if (ShadowMesh)
ShadowMesh->drop();
ShadowMesh = mesh;
if (ShadowMesh)
{
ShadowMesh->grab();
Box = ShadowMesh->getBoundingBox();
}
}
void CShadowVolumeSceneNode::updateShadowVolumes()
{
const u32 oldIndexCount = IndexCount;
const u32 oldVertexCount = VertexCount;
const IMesh* const mesh = ShadowMesh;
if (!mesh)
return;
// create as much shadow volumes as there are lights but
// do not ignore the max light settings.
const u32 lightCount = SceneManager->getVideoDriver()->getDynamicLightCount();
if (!lightCount)
return;
// calculate total amount of vertices and indices
VertexCount = 0;
IndexCount = 0;
ShadowVolumesUsed = 0;
u32 i;
u32 totalVertices = 0;
u32 totalIndices = 0;
const u32 bufcnt = mesh->getMeshBufferCount();
for (i=0; i<bufcnt; ++i)
{
const IMeshBuffer* buf = mesh->getMeshBuffer(i);
totalIndices += buf->getIndexCount();
totalVertices += buf->getVertexCount();
}
// allocate memory if necessary
Vertices.set_used(totalVertices);
Indices.set_used(totalIndices);
FaceData.set_used(totalIndices / 3);
// copy mesh
for (i=0; i<bufcnt; ++i)
{
const IMeshBuffer* buf = mesh->getMeshBuffer(i);
const u16* idxp = buf->getIndices();
const u16* idxpend = idxp + buf->getIndexCount();
for (; idxp!=idxpend; ++idxp)
Indices[IndexCount++] = *idxp + VertexCount;
const u32 vtxcnt = buf->getVertexCount();
for (u32 j=0; j<vtxcnt; ++j)
Vertices[VertexCount++] = buf->getPosition(j);
}
// recalculate adjacency if necessary
if (oldVertexCount != VertexCount || oldIndexCount != IndexCount)
calculateAdjacency();
core::matrix4 mat = Parent->getAbsoluteTransformation();
mat.makeInverse();
const core::vector3df parentpos = Parent->getAbsolutePosition();
// TODO: Only correct for point lights.
for (i=0; i<lightCount; ++i)
{
const video::SLight& dl = SceneManager->getVideoDriver()->getDynamicLight(i);
core::vector3df lpos = dl.Position;
if (dl.CastShadows &&
fabs((lpos - parentpos).getLengthSQ()) <= (dl.Radius*dl.Radius*4.0f))
{
mat.transformVect(lpos);
createShadowVolume(lpos);
}
}
}
//! pre render method
void CShadowVolumeSceneNode::OnRegisterSceneNode()
{
if (IsVisible)
{
SceneManager->registerNodeForRendering(this, scene::ESNRP_SHADOW);
ISceneNode::OnRegisterSceneNode();
}
}
//! renders the node.
void CShadowVolumeSceneNode::render()
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
if (!ShadowVolumesUsed || !driver)
return;
driver->setTransform(video::ETS_WORLD, Parent->getAbsoluteTransformation());
for (u32 i=0; i<ShadowVolumesUsed; ++i)
{
bool drawShadow = true;
if (UseZFailMethod && SceneManager->getActiveCamera())
{
// Disable shadows drawing, when back cap is behind of ZFar plane.
SViewFrustum frust = *SceneManager->getActiveCamera()->getViewFrustum();
core::matrix4 invTrans(Parent->getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE);
frust.transform(invTrans);
core::vector3df edges[8];
ShadowBBox[i].getEdges(edges);
core::vector3df largestEdge = edges[0];
f32 maxDistance = core::vector3df(SceneManager->getActiveCamera()->getPosition() - edges[0]).getLength();
f32 curDistance = 0.f;
for(int j = 1; j < 8; ++j)
{
curDistance = core::vector3df(SceneManager->getActiveCamera()->getPosition() - edges[j]).getLength();
if(curDistance > maxDistance)
{
maxDistance = curDistance;
largestEdge = edges[j];
}
}
if (!(frust.planes[scene::SViewFrustum::VF_FAR_PLANE].classifyPointRelation(largestEdge) != core::ISREL3D_FRONT))
drawShadow = false;
}
if(drawShadow)
driver->drawStencilShadowVolume(ShadowVolumes[i], UseZFailMethod, DebugDataVisible);
else
{
core::array<core::vector3df> triangles;
driver->drawStencilShadowVolume(triangles, UseZFailMethod, DebugDataVisible);
}
}
}
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CShadowVolumeSceneNode::getBoundingBox() const
{
return Box;
}
//! Generates adjacency information based on mesh indices.
void CShadowVolumeSceneNode::calculateAdjacency()
{
Adjacency.set_used(IndexCount);
// go through all faces and fetch their three neighbours
for (u32 f=0; f<IndexCount; f+=3)
{
for (u32 edge = 0; edge<3; ++edge)
{
const core::vector3df& v1 = Vertices[Indices[f+edge]];
const core::vector3df& v2 = Vertices[Indices[f+((edge+1)%3)]];
// now we search an_O_ther _F_ace with these two
// vertices, which is not the current face.
u32 of;
for (of=0; of<IndexCount; of+=3)
{
// only other faces
if (of != f)
{
bool cnt1 = false;
bool cnt2 = false;
for (s32 e=0; e<3; ++e)
{
if (v1.equals(Vertices[Indices[of+e]]))
cnt1=true;
if (v2.equals(Vertices[Indices[of+e]]))
cnt2=true;
}
// one match for each vertex, i.e. edge is the same
if (cnt1 && cnt2)
break;
}
}
// no adjacent edges -> store face number, else store adjacent face
if (of >= IndexCount)
Adjacency[f + edge] = f/3;
else
Adjacency[f + edge] = of/3;
}
}
}
} // end namespace scene
} // end namespace irr

View File

@ -1,87 +0,0 @@
// 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
#ifndef __C_SHADOW_VOLUME_SCENE_NODE_H_INCLUDED__
#define __C_SHADOW_VOLUME_SCENE_NODE_H_INCLUDED__
#include "IShadowVolumeSceneNode.h"
namespace irr
{
namespace scene
{
//! Scene node for rendering a shadow volume into a stencil buffer.
class CShadowVolumeSceneNode : public IShadowVolumeSceneNode
{
public:
//! constructor
CShadowVolumeSceneNode(const IMesh* shadowMesh, ISceneNode* parent, ISceneManager* mgr,
s32 id, bool zfailmethod=true, f32 infinity=10000.0f);
//! destructor
virtual ~CShadowVolumeSceneNode();
//! Sets the mesh from which the shadow volume should be generated.
/** To optimize shadow rendering, use a simpler mesh for shadows.
*/
virtual void setShadowMesh(const IMesh* mesh);
//! Updates the shadow volumes for current light positions.
/** Called each render cycle from Animated Mesh SceneNode render method. */
virtual void updateShadowVolumes();
//! pre render method
virtual void OnRegisterSceneNode();
//! renders the node.
virtual void render();
//! returns the axis aligned bounding box of this node
virtual const core::aabbox3d<f32>& getBoundingBox() const;
//! Returns type of the scene node
virtual ESCENE_NODE_TYPE getType() const { return ESNT_SHADOW_VOLUME; }
private:
typedef core::array<core::vector3df> SShadowVolume;
void createShadowVolume(const core::vector3df& pos, bool isDirectional=false);
u32 createEdgesAndCaps(const core::vector3df& light, SShadowVolume* svp, core::aabbox3d<f32>* bb);
//! Generates adjacency information based on mesh indices.
void calculateAdjacency();
core::aabbox3d<f32> Box;
// a shadow volume for every light
core::array<SShadowVolume> ShadowVolumes;
// a back cap bounding box for every light
core::array<core::aabbox3d<f32> > ShadowBBox;
core::array<core::vector3df> Vertices;
core::array<u16> Indices;
core::array<u16> Adjacency;
core::array<u16> Edges;
// tells if face is front facing
core::array<bool> FaceData;
const scene::IMesh* ShadowMesh;
u32 IndexCount;
u32 VertexCount;
u32 ShadowVolumesUsed;
f32 Infinity;
bool UseZFailMethod;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -7,7 +7,6 @@
#include "ISceneManager.h"
#include "S3DVertex.h"
#include "os.h"
#include "CShadowVolumeSceneNode.h"
namespace irr
{
@ -17,7 +16,7 @@ namespace scene
//! constructor
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)
: IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), Shadow(0),
: IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0),
Radius(radius), PolyCountX(polyCountX), PolyCountY(polyCountY)
{
#ifdef _DEBUG
@ -32,8 +31,6 @@ CSphereSceneNode::CSphereSceneNode(f32 radius, u32 polyCountX, u32 polyCountY, I
//! destructor
CSphereSceneNode::~CSphereSceneNode()
{
if (Shadow)
Shadow->drop();
if (Mesh)
Mesh->drop();
}
@ -48,8 +45,6 @@ void CSphereSceneNode::render()
{
driver->setMaterial(Mesh->getMeshBuffer(0)->getMaterial());
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
if (Shadow)
Shadow->updateShadowVolumes();
driver->drawMeshBuffer(Mesh->getMeshBuffer(0));
if ( DebugDataVisible & scene::EDS_BBOX )
@ -68,35 +63,10 @@ void CSphereSceneNode::render()
//! 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
const core::aabbox3d<f32>& CSphereSceneNode::getBoundingBox() const
{
@ -185,8 +155,6 @@ ISceneNode* CSphereSceneNode::clone(ISceneNode* newParent, ISceneManager* newMan
nb->cloneMembers(this, newManager);
nb->getMaterial(0) = Mesh->getMeshBuffer(0)->getMaterial();
nb->Shadow = Shadow;
nb->Shadow->grab();
if ( newParent )
nb->drop();

View File

@ -69,11 +69,6 @@ namespace scene
//! 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; }
//! 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.
@ -82,7 +77,6 @@ namespace scene
private:
IMesh* Mesh;
IShadowVolumeSceneNode* Shadow;
core::aabbox3d<f32> Box;
f32 Radius;
u32 PolyCountX;

View File

@ -55,8 +55,6 @@ public:
virtual scene::IMesh *getMesh() OVERRIDE { return m_mesh; }
virtual void setReadOnlyMaterials(bool) OVERRIDE {}
virtual bool isReadOnlyMaterials() const OVERRIDE { return false; }
virtual scene::IShadowVolumeSceneNode* addShadowVolumeSceneNode
(const scene::IMesh*, int, bool, f32) OVERRIDE { return NULL; }
protected:
video::SMaterial m_mat;