Ejemplo n.º 1
0
// ***************************************************************************
void	CMeshMRMGeom::applySkinWithTangentSpace(CLod &lod, const CSkeletonModel *skeleton,
	uint tangentSpaceTexCoord)
{
	nlassert(_Skinned);
	if(_SkinWeights.size()==0)
		return;

	// get vertexPtr / normalOff / tangent space offset.
	//===========================
	CVertexBufferReadWrite vba;
	_VBufferFinal.lock (vba);
	uint8		*destVertexPtr= (uint8*)vba.getVertexCoordPointer();
	uint		flags= _VBufferFinal.getVertexFormat();
	sint32		vertexSize= _VBufferFinal.getVertexSize();
	// must have XYZ.
	// if there's tangent space, there also must be a normal there.
	nlassert((flags & CVertexBuffer::PositionFlag)
			 && (flags & CVertexBuffer::NormalFlag)
			);


	// Compute offset of each component of the VB.
	sint32		normalOff;
	normalOff= _VBufferFinal.getNormalOff();

	// tg space offset
	sint32		tgSpaceOff = _VBufferFinal.getTexCoordOff((uint8) tangentSpaceTexCoord);

	// compute src array.
	CMesh::CSkinWeight	*srcSkinPtr;
	CVector				*srcVertexPtr;
	CVector				*srcNormalPtr;
	CVector				*tgSpacePtr;
	//
	srcSkinPtr= &_SkinWeights[0];
	srcVertexPtr= &_OriginalSkinVertices[0];
	srcNormalPtr= &(_OriginalSkinNormals[0]);
	tgSpacePtr = &(_OriginalTGSpace[0]);



	// Compute useful Matrix for this lod.
	//===========================
	// Those arrays map the array of bones in skeleton.
	static	vector<CMatrix3x4>			boneMat3x4;
	computeBoneMatrixes3x4(boneMat3x4, lod.MatrixInfluences, skeleton);


	// apply skinning (with tangent space added)
	//===========================
	// assert, code below is written especially for 4 per vertex.
	nlassert(NL3D_MESH_SKINNING_MAX_MATRIX==4);
	for(uint i=0;i<NL3D_MESH_SKINNING_MAX_MATRIX;i++)
	{
		uint		nInf= (uint)lod.InfluencedVertices[i].size();
		if( nInf==0 )
			continue;
		uint32		*infPtr= &(lod.InfluencedVertices[i][0]);

		// apply the skin to the vertices
		applyArraySkinTangentSpaceT(i, infPtr, srcSkinPtr, srcVertexPtr, srcNormalPtr, tgSpacePtr,
			normalOff, tgSpaceOff, destVertexPtr,
			boneMat3x4, vertexSize, nInf);
	}
}
Ejemplo n.º 2
0
// ***************************************************************************
void	CMeshMRMGeom::applySkinWithNormal(CLod &lod, const CSkeletonModel *skeleton)
{
	nlassert(_Skinned);
	if(_SkinWeights.size()==0)
		return;

	// get vertexPtr / normalOff.
	//===========================
	CVertexBufferReadWrite vba;
	_VBufferFinal.lock (vba);
	uint8		*destVertexPtr= (uint8*)vba.getVertexCoordPointer();
	uint		flags= _VBufferFinal.getVertexFormat();
	sint32		vertexSize= _VBufferFinal.getVertexSize();
	// must have XYZ and Normal.
	nlassert((flags & CVertexBuffer::PositionFlag)
			 && (flags & CVertexBuffer::NormalFlag)
			);


	// Compute offset of each component of the VB.
	sint32		normalOff;
	normalOff= _VBufferFinal.getNormalOff();


	// compute src array.
	CMesh::CSkinWeight	*srcSkinPtr;
	CVector				*srcVertexPtr;
	CVector				*srcNormalPtr= NULL;
	srcSkinPtr= &_SkinWeights[0];
	srcVertexPtr= &_OriginalSkinVertices[0];
	srcNormalPtr= &(_OriginalSkinNormals[0]);



	// Compute useful Matrix for this lod.
	//===========================
	// Those arrays map the array of bones in skeleton.
	static	vector<CMatrix3x4>			boneMat3x4;
	computeBoneMatrixes3x4(boneMat3x4, lod.MatrixInfluences, skeleton);


	// apply skinning.
	//===========================
	// assert, code below is written especially for 4 per vertex.
	nlassert(NL3D_MESH_SKINNING_MAX_MATRIX==4);
	for(uint i=0;i<NL3D_MESH_SKINNING_MAX_MATRIX;i++)
	{
		uint		nInf= (uint)lod.InfluencedVertices[i].size();
		if( nInf==0 )
			continue;
		uint32		*infPtr= &(lod.InfluencedVertices[i][0]);

		// TestYoyo
		/*extern	uint TESTYOYO_NumStdSkinVertices;
		TESTYOYO_NumStdSkinVertices+= nInf;*/

		// apply the skin to the vertices
		applyArraySkinNormalT(i, infPtr, srcSkinPtr, srcVertexPtr, srcNormalPtr,
			normalOff, destVertexPtr,
			boneMat3x4, vertexSize, nInf);
	}
}
Ejemplo n.º 3
0
// ***************************************************************************
void	CMeshMRMGeom::applySkin(CLod &lod, const CSkeletonModel *skeleton)
{
	nlassert(_Skinned);
	if(_SkinWeights.size()==0)
		return;

	// get vertexPtr.
	//===========================
	CVertexBufferReadWrite vba;
	_VBufferFinal.lock (vba);
	uint8		*destVertexPtr= (uint8*)vba.getVertexCoordPointer();
	uint		flags= _VBufferFinal.getVertexFormat();
	sint32		vertexSize= _VBufferFinal.getVertexSize();
	// must have XYZ.
	nlassert(flags & CVertexBuffer::PositionFlag);


	// compute src array.
	CMesh::CSkinWeight	*srcSkinPtr;
	CVector				*srcVertexPtr;
	srcSkinPtr= &_SkinWeights[0];
	srcVertexPtr= &_OriginalSkinVertices[0];



	// Compute useful Matrix for this lod.
	//===========================
	// Those arrays map the array of bones in skeleton.
	static	vector<CMatrix3x4>			boneMat3x4;
	computeBoneMatrixes3x4(boneMat3x4, lod.MatrixInfluences, skeleton);


	// apply skinning.
	//===========================
	// assert, code below is written especially for 4 per vertex.
	nlassert(NL3D_MESH_SKINNING_MAX_MATRIX==4);
	for(uint i=0;i<NL3D_MESH_SKINNING_MAX_MATRIX;i++)
	{
		uint		nInf= (uint)lod.InfluencedVertices[i].size();
		if( nInf==0 )
			continue;
		uint32		*infPtr= &(lod.InfluencedVertices[i][0]);

		// apply the skin to the vertices
		switch(i)
		{
		//=========
		case 0:
			// Special case for Vertices influenced by one matrix. Just copy result of mul.
			//  for all InfluencedVertices only.
			for(;nInf>0;nInf--, infPtr++)
			{
				uint	index= *infPtr;
				CMesh::CSkinWeight	*srcSkin= srcSkinPtr + index;
				CVector				*srcVertex= srcVertexPtr + index;
				uint8				*dstVertexVB= destVertexPtr + index * vertexSize;
				CVector				*dstVertex= (CVector*)(dstVertexVB);


				// Vertex.
				boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, *dstVertex);
			}
			break;

		//=========
		case 1:
			//  for all InfluencedVertices only.
			for(;nInf>0;nInf--, infPtr++)
			{
				uint	index= *infPtr;
				CMesh::CSkinWeight	*srcSkin= srcSkinPtr + index;
				CVector				*srcVertex= srcVertexPtr + index;
				uint8				*dstVertexVB= destVertexPtr + index * vertexSize;
				CVector				*dstVertex= (CVector*)(dstVertexVB);


				// Vertex.
				boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
				boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
			}
			break;

		//=========
		case 2:
			//  for all InfluencedVertices only.
			for(;nInf>0;nInf--, infPtr++)
			{
				uint	index= *infPtr;
				CMesh::CSkinWeight	*srcSkin= srcSkinPtr + index;
				CVector				*srcVertex= srcVertexPtr + index;
				uint8				*dstVertexVB= destVertexPtr + index * vertexSize;
				CVector				*dstVertex= (CVector*)(dstVertexVB);


				// Vertex.
				boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
				boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
				boneMat3x4[ srcSkin->MatrixId[2] ].mulAddPoint( *srcVertex, srcSkin->Weights[2], *dstVertex);
			}
			break;

		//=========
		case 3:
			//  for all InfluencedVertices only.
			for(;nInf>0;nInf--, infPtr++)
			{
				uint	index= *infPtr;
				CMesh::CSkinWeight	*srcSkin= srcSkinPtr + index;
				CVector				*srcVertex= srcVertexPtr + index;
				uint8				*dstVertexVB= destVertexPtr + index * vertexSize;
				CVector				*dstVertex= (CVector*)(dstVertexVB);


				// Vertex.
				boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
				boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
				boneMat3x4[ srcSkin->MatrixId[2] ].mulAddPoint( *srcVertex, srcSkin->Weights[2], *dstVertex);
				boneMat3x4[ srcSkin->MatrixId[3] ].mulAddPoint( *srcVertex, srcSkin->Weights[3], *dstVertex);
			}
			break;

		}
	}
}
Ejemplo n.º 4
0
// ***************************************************************************
void CMeshMorpher::update (std::vector<CAnimatedMorph> *pBSFactor)
{
	uint32 i, j;

	if (_VBOri == NULL)
		return;
	if (BlendShapes.size() == 0)
		return;

	if (_VBOri->getNumVertices() != _VBDst->getNumVertices())
	{	// Because the original vertex buffer is not initialized by default
		// we must init it here (if there are some blendshapes)
		*_VBOri = *_VBDst;
	}

	// Does the flags are reserved ?
	if (_Flags.size() != _VBOri->getNumVertices())
	{
		_Flags.resize (_VBOri->getNumVertices());
		for (i = 0; i < _Flags.size(); ++i)
			_Flags[i] = Modified; // Modified to update all
	}

	nlassert(_VBOri->getVertexFormat() == _VBDst->getVertexFormat());

	// Cleaning with original vertex buffer
	uint32 VBVertexSize = _VBOri->getVertexSize();
	CVertexBufferRead srcvba;
	_VBOri->lock (srcvba);
	CVertexBufferReadWrite dstvba;
	_VBDst->lock (dstvba);
	const uint8 *pOri = (const uint8*)srcvba.getVertexCoordPointer ();
	uint8 *pDst = (uint8*)dstvba.getVertexCoordPointer ();

	for (i= 0; i < _Flags.size(); ++i)
	if (_Flags[i] >= Modified)
	{
		_Flags[i] = OriginalVBDst;

		for(j = 0; j < VBVertexSize; ++j)
			pDst[j+i*VBVertexSize] = pOri[j+i*VBVertexSize];
	}

	uint tgSpaceStage = 0;
	if (_UseTgSpace)
	{
		tgSpaceStage = _VBDst->getNumTexCoordUsed() - 1;
	}

	// Blending with blendshape
	for (i = 0; i < BlendShapes.size(); ++i)
	{
		CBlendShape &rBS = BlendShapes[i];
		float rFactor = pBSFactor->operator[](i).getFactor()/100.0f;

		// todo hulud check it works
		// if (rFactor > 0.0f)
		if (rFactor != 0.0f)
		for (j = 0; j < rBS.VertRefs.size(); ++j)
		{
			uint32 vp = rBS.VertRefs[j];

			// Modify Pos/Norm/TgSpace.
			//------------
			if (_VBDst->getVertexFormat() & CVertexBuffer::PositionFlag)
			if (rBS.deltaPos.size() > 0)
			{
				CVector *pV = dstvba.getVertexCoordPointer (vp);
				*pV += rBS.deltaPos[j] * rFactor;
			}

			if (_VBDst->getVertexFormat() & CVertexBuffer::NormalFlag)
			if (rBS.deltaNorm.size() > 0)
			{
				CVector *pV = dstvba.getNormalCoordPointer (vp);
				*pV += rBS.deltaNorm[j] * rFactor;
			}

			if (_UseTgSpace)
			if (rBS.deltaTgSpace.size() > 0)
			{
				CVector *pV = (CVector*)dstvba.getTexCoordPointer (vp, tgSpaceStage);
				*pV += rBS.deltaTgSpace[j] * rFactor;
			}

			// Modify UV0 / Color
			//------------
			if (_VBDst->getVertexFormat() & CVertexBuffer::TexCoord0Flag)
			if (rBS.deltaUV.size() > 0)
			{
				CUV *pUV = dstvba.getTexCoordPointer (vp);
				*pUV += rBS.deltaUV[j] * rFactor;
			}

			if (_VBDst->getVertexFormat() & CVertexBuffer::PrimaryColorFlag)
			if (rBS.deltaCol.size() > 0)
			{
				// todo hulud d3d vertex color RGBA / BGRA
				CRGBA *pRGBA = (CRGBA*)dstvba.getColorPointer (vp);
				CRGBAF rgbf(*pRGBA);
				rgbf.R += rBS.deltaCol[j].R * rFactor;
				rgbf.G += rBS.deltaCol[j].G * rFactor;
				rgbf.B += rBS.deltaCol[j].B * rFactor;
				rgbf.A += rBS.deltaCol[j].A * rFactor;
				clamp(rgbf.R, 0.0f, 1.0f);
				clamp(rgbf.G, 0.0f, 1.0f);
				clamp(rgbf.B, 0.0f, 1.0f);
				clamp(rgbf.A, 0.0f, 1.0f);
				*pRGBA = rgbf;
			}

			// Modified
			_Flags[vp] = Modified;
		}
	}
}
Ejemplo n.º 5
0
// ***************************************************************************
void		CVegetableShape::build(CVegetableShapeBuild &vbuild)
{
	// Must have TexCoord0.
	nlassert( vbuild.VB.getVertexFormat() & CVertexBuffer::TexCoord0Flag );

	// Header
	//---------

	// Lighted ?
	if(vbuild.Lighted && ( vbuild.VB.getVertexFormat() & CVertexBuffer::NormalFlag) )
		Lighted= true;
	else
		Lighted= false;

	// DoubleSided
	DoubleSided= vbuild.DoubleSided;

	// PreComputeLighting.
	PreComputeLighting= Lighted && vbuild.PreComputeLighting;

	// AlphaBlend: valid only for 2Sided and Unlit (or similar PreComputeLighting) mode
	AlphaBlend= vbuild.AlphaBlend && DoubleSided && (!Lighted || PreComputeLighting);

	// BestSidedPreComputeLighting
	BestSidedPreComputeLighting= PreComputeLighting && vbuild.BestSidedPreComputeLighting;

	// BendCenterMode
	BendCenterMode= vbuild.BendCenterMode;

	// Format of the VB.
	uint32	format;
	format= CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag | CVertexBuffer::TexCoord1Flag;
	// lighted?
	if(Lighted)
		format|= CVertexBuffer::NormalFlag;
	// set VB.
	VB.setVertexFormat(format);


	// Fill triangles.
	//---------
	uint	i;
	// resisz
	TriangleIndices.resize(vbuild.PB.getNumIndexes());
	CIndexBufferRead ibaRead;
	vbuild.PB.lock (ibaRead);
	const uint32	*srcTri= (const uint32 *) ibaRead.getPtr();
	// fill
	for(i=0; i<vbuild.PB.getNumIndexes()/3; i++)
	{
		TriangleIndices[i*3+0]= *(srcTri++);
		TriangleIndices[i*3+1]= *(srcTri++);
		TriangleIndices[i*3+2]= *(srcTri++);
	}

	// Fill vertices.
	//---------
	// resize
	uint32		nbVerts= vbuild.VB.getNumVertices();
	VB.setNumVertices(nbVerts);

	CVertexBufferRead vba;
	vbuild.VB.lock (vba);
	CVertexBufferReadWrite vbaOut;
	VB.lock (vbaOut);

	// if no vertex color,
	float	maxZ= 0;
	bool	bendFromColor= true;
	if(! (vbuild.VB.getVertexFormat() & CVertexBuffer::PrimaryColorFlag) )
	{
		// must compute bendWeight from z.
		bendFromColor= false;
		// get the maximum Z.
		for(i=0;i<nbVerts;i++)
		{
			float	z= (vba.getVertexCoordPointer(i))->z;
			maxZ= max(z, maxZ);
		}
		// if no positive value, bend will always be 0.
		if(maxZ==0)
			maxZ= 1;
	}

	// For all vertices, fill
	for(i=0;i<nbVerts;i++)
	{
		// Position.
		const CVector		*srcPos= vba.getVertexCoordPointer(i);
		CVector		*dstPos= vbaOut.getVertexCoordPointer(i);
		*dstPos= *srcPos;

		// Normal
		if(Lighted)
		{
			const CVector *srcNormal= vba.getNormalCoordPointer(i);
			CVector		*dstNormal= vbaOut.getNormalCoordPointer(i);
			*dstNormal= *srcNormal;
		}

		// Texture.
		const CUV		*srcUV= vba.getTexCoordPointer(i, 0);
		CUV		*dstUV= vbaOut.getTexCoordPointer(i, 0);
		*dstUV= *srcUV;

		// Bend.
		// copy to texture stage 1.
		CUV		*dstUVBend= vbaOut.getTexCoordPointer(i, 1);
		if(bendFromColor)
		{
			// todo hulud d3d vertex color RGBA / BGRA
			const CRGBA	*srcColor= (const CRGBA*)vba.getColorPointer(i);
			// Copy and scale by MaxBendWeight
			dstUVBend->U= (srcColor->R / 255.f) * vbuild.MaxBendWeight;
		}
		else
		{
			float	w= srcPos->z / maxZ;
			w= max(w, 0.f);
			// Copy and scale by MaxBendWeight
			dstUVBend->U= w * vbuild.MaxBendWeight;
		}
	}


	// Misc.
	//---------
	// prepare for instanciation
	InstanceVertices.resize(VB.getNumVertices());

}
Ejemplo n.º 6
0
// ***************************************************************************
void		CRenderTrav::traverse(UScene::TRenderPart renderPart, bool newRender)
{
#ifdef NL_DEBUG_RENDER_TRAV
    nlwarning("Render trave begin");
#endif
    H_AUTO( NL3D_TravRender );
    if (getDriver()->isLost()) return; // device is lost so no need to render anything
    CTravCameraScene::update();
    // Bind to Driver.
    setupDriverCamera();
    getDriver()->setupViewport(_Viewport);

    // reset the light setup, and set global ambient.
    resetLightSetup();
    if (newRender)
    {

        // reset the Skin manager, if needed
        if(_MeshSkinManager)
        {
            if(Driver!=_MeshSkinManager->getDriver())
            {
                _MeshSkinManager->release();
                _MeshSkinManager->init(Driver,
                                       NL3D_MESH_SKIN_MANAGER_VERTEXFORMAT,
                                       NL3D_MESH_SKIN_MANAGER_MAXVERTICES,
                                       NL3D_MESH_SKIN_MANAGER_NUMVB,
                                       "MRMSkinVB", true);
            }
        }

        // Same For Shadow ones. NB: use AuxDriver here!!!
        if(_ShadowMeshSkinManager)
        {
            if(getAuxDriver()!=_ShadowMeshSkinManager->getDriver())
            {
                _ShadowMeshSkinManager->release();
                _ShadowMeshSkinManager->init(getAuxDriver(),
                                             NL3D_SHADOW_MESH_SKIN_MANAGER_VERTEXFORMAT,
                                             NL3D_SHADOW_MESH_SKIN_MANAGER_MAXVERTICES,
                                             NL3D_SHADOW_MESH_SKIN_MANAGER_NUMVB,
                                             "ShadowSkinVB", true);
            }
        }


        // Fill OT with models, for both Opaque and transparent pass
        // =============================

        // Sort the models by distance from camera
        // This is done here and not in the addRenderModel because of the LoadBalancing traversal which can modify
        // the transparency flag (multi lod for instance)

        // clear the OTs, and prepare to allocate max element space
        OrderOpaqueList.reset(_CurrentNumVisibleModels);
        for(uint k = 0; k <= (uint) _MaxTransparencyPriority; ++k)
        {
            _OrderTransparentListByPriority[k].reset(_CurrentNumVisibleModels);	// all table share the same allocator (CLayeredOrderingTable::shareAllocator has been called)
            // and an object can be only inserted in one table, so we only need to init the main allocator
        }

        // fill the OTs.
        CTransform			**itRdrModel= NULL;
        uint32				nNbModels = _CurrentNumVisibleModels;
        if(nNbModels)
            itRdrModel= &RenderList[0];
        float	rPseudoZ, rPseudoZ2;

        // Some precalc
        float	OOFar= 1.0f / this->Far;
        uint32	opaqueOtSize= OrderOpaqueList.getSize();
        uint32	opaqueOtMax= OrderOpaqueList.getSize()-1;
        uint32	transparentOtSize= _OrderTransparentListByPriority[0].getSize(); // there is at least one list, and all list have the same number of entries
        uint32	transparentOtMax= _OrderTransparentListByPriority[0].getSize()-1;
        uint32	otId;
        // fast floor
        NLMISC::OptFastFloorBegin();
        // For all rdr models
        for( ; nNbModels>0; itRdrModel++, nNbModels-- )
        {
            CTransform			*pTransform = *itRdrModel;

            // if this entry was killed by removeRenderModel(), skip!
            if(!pTransform)
                continue;

            // Yoyo: skins are rendered through skeletons, so models WorldMatrix are all good here (even sticked objects)
            rPseudoZ = (pTransform->getWorldMatrix().getPos() - CamPos).norm();

            // rPseudoZ from 0.0 -> 1.0
            rPseudoZ =  sqrtf( rPseudoZ * OOFar );

            if( pTransform->isOpaque() )
            {
                // since norm, we are sure that rPseudoZ>=0
                rPseudoZ2 = rPseudoZ * opaqueOtSize;
                otId= NLMISC::OptFastFloor(rPseudoZ2);
                otId= min(otId, opaqueOtMax);
                OrderOpaqueList.insert( otId, pTransform );
            }
            if( pTransform->isTransparent() )
            {
                // since norm, we are sure that rPseudoZ>=0
                rPseudoZ2 = rPseudoZ * transparentOtSize;
                otId= NLMISC::OptFastFloor(rPseudoZ2);
                otId= min(otId, transparentOtMax);
                // must invert id, because transparent, sort from back to front
                _OrderTransparentListByPriority[std::min(pTransform->getTransparencyPriority(), _MaxTransparencyPriority)].insert( pTransform->getOrderingLayer(), pTransform, transparentOtMax-otId );
            }

        }
        // fast floor
        NLMISC::OptFastFloorEnd();
    }

    if (renderPart & UScene::RenderOpaque)
    {
        // Render Opaque stuff.
        // =============================

        // TestYoyo
        //OrderOpaqueList.reset(0);
        //OrderTransparentList.reset(0);

        // Clear any landscape
        clearRenderLandscapeList();

        // Start LodCharacter Manager render.
        CLodCharacterManager	*clodMngr= Scene->getLodCharacterManager();
        if(clodMngr)
            clodMngr->beginRender(getDriver(), CamPos);

        // Render the opaque materials
        _CurrentPassOpaque = true;
        OrderOpaqueList.begin();
        while( OrderOpaqueList.get() != NULL )
        {
            CTransform	*tr= OrderOpaqueList.get();
#ifdef NL_DEBUG_RENDER_TRAV
            CTransformShape *trShape = dynamic_cast<CTransformShape *>(tr);
            if (trShape)
            {
                const std::string *shapeName = Scene->getShapeBank()->getShapeNameFromShapePtr(trShape->Shape);
                if (shapeName)
                {
                    nlwarning("Displaying %s", shapeName->c_str());
                }
            }
#endif
            tr->traverseRender();
            OrderOpaqueList.next();
        }

        /* Render MeshBlock Manager.
        	Some Meshs may be render per block. Interesting to remove VertexBuffer and Material setup overhead.
        	Faster if rendered before lods, for ZBuffer optimisation: render first near objects then far.
        	Lods are usually far objects.
        */
        MeshBlockManager.flush(Driver, Scene, this);


        // End LodCharacter Manager render.
        if(clodMngr)
            clodMngr->endRender();


        /* Render Scene CoarseMeshManager.
        	Important to render them at end of Opaque rendering, because coarses instances are created/removed during
        	this model opaque rendering pass.
        */
        if( Scene->getCoarseMeshManager() )
            Scene->getCoarseMeshManager()->flushRender(Driver);

        /* Render ShadowMaps.
        	Important to render them at end of Opaque rendering, because alphaBlended objects must blend with opaque
        	objects shadowed.
        	Therefore, transparent objects neither can't cast or receive shadows...

        	NB: Split in 2 calls and interleave Landscape Rendering between the 2. WHY???
        	Because it is far more efficient for VBLock (but not for ZBuffer optim...) because in renderGenerate()
        	the ShadowMeshSkinManager do lot of VBLocks that really stall (because only 2 VBHard with swap scheme).

        	Therefore the first Lock that stall will wait not only for the first MeshSkin to finish but also for the
        	preceding landscape render to finish too! => big STALL.
        */

        // Generate ShadowMaps
        _ShadowMapManager.renderGenerate(Scene);

        // Render the Landscape
        renderLandscapes();

        // Project ShadowMaps.
        if(Scene->getLandscapePolyDrawingCallback() != NULL)
        {
            Scene->getLandscapePolyDrawingCallback()->beginPolyDrawing();
        }
        _ShadowMapManager.renderProject(Scene);
        if(Scene->getLandscapePolyDrawingCallback())
        {
            Scene->getLandscapePolyDrawingCallback()->endPolyDrawing();
        }

        // Profile this frame?
        if(Scene->isNextRenderProfile())
        {
            OrderOpaqueList.begin();
            while( OrderOpaqueList.get() != NULL )
            {
                OrderOpaqueList.get()->profileRender();
                OrderOpaqueList.next();
            }
        }
    }


    if (renderPart & UScene::RenderTransparent)
    {
        if (_FirstWaterModel) // avoid a lock if no water is to be rendered
        {
            // setup water models
            CWaterModel *curr = _FirstWaterModel;
            uint numWantedVertices = 0;
            while (curr)
            {
                numWantedVertices += curr->getNumWantedVertices();
                curr = curr->_Next;
            }
            if (numWantedVertices != 0)
            {
                CWaterModel::setupVertexBuffer(Scene->getWaterVB(), numWantedVertices, getDriver());
                //
                {
                    CVertexBufferReadWrite vbrw;
                    Scene->getWaterVB().lock(vbrw);
                    CWaterModel *curr = _FirstWaterModel;
                    void *datas = vbrw.getVertexCoordPointer(0);
                    //
                    uint tri = 0;
                    while (curr)
                    {
                        tri = curr->fillVB(datas, tri, *getDriver());
                        nlassert(tri <= numWantedVertices);
                        curr = curr->_Next;
                    }
                    nlassert(tri * 3 == numWantedVertices);
                }
            }
            // Unlink all water model
            clearWaterModelList();
        }
    }

    if ((renderPart & UScene::RenderTransparent) &&
            (renderPart & UScene::RenderFlare)
       )
    {
        // Render all transparent stuffs including flares.
        // =============================
        // Render transparent materials (draw higher priority last, because their appear in front)
        _CurrentPassOpaque = false;
        for(std::vector<CLayeredOrderingTable<CTransform> >::iterator it = _OrderTransparentListByPriority.begin(); it != _OrderTransparentListByPriority.end(); ++it)
        {
            it->begin(_LayersRenderingOrder);
            while( it->get() != NULL )
            {
#ifdef NL_DEBUG_RENDER_TRAV
                CTransformShape *trShape = dynamic_cast<CTransformShape *>(it->get());
                if (trShape)
                {
                    const std::string *shapeName = Scene->getShapeBank()->getShapeNameFromShapePtr(trShape->Shape);
                    if (shapeName)
                    {
                        nlwarning("Displaying %s", shapeName->c_str());
                    }
                }
#endif
                it->get()->traverseRender();
                it->next();
            }
        }

        // Profile this frame?
        if(Scene->isNextRenderProfile())
        {
            for(std::vector<CLayeredOrderingTable<CTransform> >::iterator it = _OrderTransparentListByPriority.begin(); it != _OrderTransparentListByPriority.end(); ++it)
            {
                it->begin();
                while( it->get() != NULL )
                {
                    it->get()->profileRender();
                    it->next();
                }
            }
        }
    }
    else if (renderPart & UScene::RenderTransparent)
    {
        // Render all transparent stuffs, don't render flares
        // =============================
        _CurrentPassOpaque = false;
        for(std::vector<CLayeredOrderingTable<CTransform> >::iterator it = _OrderTransparentListByPriority.begin(); it != _OrderTransparentListByPriority.end(); ++it)
        {
            it->begin(_LayersRenderingOrder);
            while( it->get() != NULL )
            {
                if (!it->get()->isFlare())
                {
#ifdef NL_DEBUG_RENDER_TRAV
                    CTransformShape *trShape = dynamic_cast<CTransformShape *>(it->get());
                    if (trShape)
                    {
                        const std::string *shapeName = Scene->getShapeBank()->getShapeNameFromShapePtr(trShape->Shape);
                        if (shapeName)
                        {
                            nlwarning("Displaying %s", shapeName->c_str());
                        }
                    }
#endif
                    it->get()->traverseRender();
                }
                it->next();
            }
        }

        // Profile this frame?
        if(Scene->isNextRenderProfile())
        {
            for(std::vector<CLayeredOrderingTable<CTransform> >::iterator it = _OrderTransparentListByPriority.begin(); it != _OrderTransparentListByPriority.end(); ++it)
            {
                it->begin();
                while( it->get() != NULL )
                {
                    if (!it->get()->isFlare())
                    {
                        it->get()->profileRender();
                    }
                    it->next();
                }
            }
        }
    }
    else if (renderPart & UScene::RenderFlare)
    {
        // Render flares only
        // =============================
        _CurrentPassOpaque = false;
        for(std::vector<CLayeredOrderingTable<CTransform> >::iterator it = _OrderTransparentListByPriority.begin(); it != _OrderTransparentListByPriority.end(); ++it)
        {
            it->begin(_LayersRenderingOrder);
            while( it->get() != NULL )
            {
                if (it->get()->isFlare())
                {
#ifdef NL_DEBUG_RENDER_TRAV
                    CTransformShape *trShape = dynamic_cast<CTransformShape *>(it->get());
                    if (trShape)
                    {
                        const std::string *shapeName = Scene->getShapeBank()->getShapeNameFromShapePtr(trShape->Shape);
                        if (shapeName)
                        {
                            nlwarning("Displaying %s", shapeName->c_str());
                        }
                    }
#endif
                    it->get()->traverseRender();
                }
                it->next();
            }
        }

        // Profile this frame?
        if(Scene->isNextRenderProfile())
        {
            for(std::vector<CLayeredOrderingTable<CTransform> >::iterator it = _OrderTransparentListByPriority.begin(); it != _OrderTransparentListByPriority.end(); ++it)
            {
                it->begin();
                while( it->get() != NULL )
                {
                    if (it->get()->isFlare())
                    {
                        it->get()->profileRender();
                    }
                    it->next();
                }
            }
        }
    }

    // END!
    // =============================

    // clean: reset the light setup
    resetLightSetup();

}