void CShadowVolumeSceneNode::updateShadowVolumes() { const u32 oldIndexCount = IndexCount; const u32 oldVertexCount = VertexCount; VertexCount = 0; IndexCount = 0; ShadowVolumesUsed = 0; const IMesh* const mesh = ShadowMesh; if (!mesh) return; // calculate total amount of vertices and indices 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 if (totalVertices > Vertices.size()) Vertices.set_used(totalVertices); if (totalIndices > Indices.size()) { Indices.set_used(totalIndices); if (UseZFailMethod) 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 && UseZFailMethod) calculateAdjacency(); // create as much shadow volumes as there are lights but // do not ignore the max light settings. const u32 lights = SceneManager->getVideoDriver()->getDynamicLightCount(); core::matrix4 mat = Parent->getAbsoluteTransformation(); mat.makeInverse(); const core::vector3df parentpos = Parent->getAbsolutePosition(); core::vector3df lpos; // TODO: Only correct for point lights. for (i=0; i<lights; ++i) { const video::SLight& dl = SceneManager->getVideoDriver()->getDynamicLight(i); lpos = dl.Position; if (dl.CastShadows && fabs((lpos - parentpos).getLengthSQ()) <= (dl.Radius*dl.Radius*4.0f)) { mat.transformVect(lpos); createShadowVolume(lpos); } } }
//! sets the mesh from which the shadow volume should be generated. void CShadowVolumeSceneNode::setMeshToRenderFrom(IMesh* mesh) { ShadowVolumesUsed = 0; s32 oldIndexCount = IndexCount; s32 oldVertexCount = VertexCount; VertexCount = 0; IndexCount = 0; if (!mesh) return; // calculate total amount of vertices and indices u32 i; s32 totalVertices = 0; s32 totalIndices = 0; u32 bufcnt = mesh->getMeshBufferCount(); IMeshBuffer* b; for (i=0; i<bufcnt; ++i) { b = mesh->getMeshBuffer(i); totalIndices += b->getIndexCount(); totalVertices += b->getVertexCount(); } // allocate memory if nececcary if (totalVertices > VertexCountAllocated) { delete [] Vertices; Vertices = new core::vector3df[totalVertices]; VertexCountAllocated = totalVertices; } if (totalIndices > IndexCountAllocated) { delete [] Indices; Indices = new u16[totalIndices]; IndexCountAllocated = totalIndices; if (UseZFailMethod) { delete [] FaceData; FaceData = new bool[totalIndices / 3]; } } // copy mesh for (i=0; i<bufcnt; ++i) { b = mesh->getMeshBuffer(i); s32 idxcnt = b->getIndexCount(); s32 vtxnow = VertexCount; const u16* idxp = b->getIndices(); const u16* idxpend = idxp + idxcnt; for (; idxp!=idxpend; ++idxp) Indices[IndexCount++] = *idxp + vtxnow; s32 vtxcnt = b->getVertexCount(); switch(b->getVertexType()) { case video::EVT_STANDARD: { const video::S3DVertex* vp = (video::S3DVertex*)b->getVertices(); const video::S3DVertex* vpend = vp + vtxcnt; for (; vp!=vpend; ++vp) Vertices[VertexCount++] = (*vp).Pos; } break; case video::EVT_2TCOORDS: { const video::S3DVertex2TCoords* vp = (video::S3DVertex2TCoords*)b->getVertices(); const video::S3DVertex2TCoords* vpend = vp + vtxcnt; for (; vp!=vpend; ++vp) Vertices[VertexCount++] = (*vp).Pos; } break; case video::EVT_TANGENTS: { const video::S3DVertexTangents* vp = (video::S3DVertexTangents*)b->getVertices(); const video::S3DVertexTangents* vpend = vp + vtxcnt; for (; vp!=vpend; ++vp) Vertices[VertexCount++] = (*vp).Pos; } break; } } // recalculate adjacency if neccessarry if (oldVertexCount != VertexCount && oldIndexCount != IndexCount && UseZFailMethod) calculateAdjacency(); // create as much shadow volumes as there are lights but // do not ignore the max light settings. u32 lights = SceneManager->getVideoDriver()->getDynamicLightCount(); core::matrix4 mat = Parent->getAbsoluteTransformation(); core::vector3df parentpos = Parent->getAbsolutePosition(); core::vector3df lpos; mat.makeInverse(); for (i=0; i<lights; ++i) { const video::SLight& dl = SceneManager->getVideoDriver()->getDynamicLight(i); lpos = dl.Position; if (dl.CastShadows && fabs((lpos - parentpos).getLengthSQ()) <= (dl.Radius*dl.Radius*4.0f)) { mat.transformVect(lpos); createShadowVolume(lpos); } } }