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);
        }
    }
}