@ -30,6 +30,7 @@
# include "nel/3d/render_trav.h"
# include "nel/3d/visual_collision_mesh.h"
# include "nel/3d/meshvp_wind_tree.h"
# include "nel/3d/vertex_stream_manager.h"
using namespace std ;
using namespace NLMISC ;
@ -764,9 +765,38 @@ void CMeshGeom::renderSkin(CTransformShape *trans, float alphaMRM)
// NB: the skeleton matrix has already been setuped by CSkeletonModel
// NB: the normalize flag has already been setuped by CSkeletonModel
bool supportVertexStream = ( ( _VBuffer . getVertexFormat ( ) & ~ ( CVertexBuffer : : PaletteSkinFlag | CVertexBuffer : : WeightFlag ) )
= = ( CVertexBuffer : : PositionFlag | CVertexBuffer : : NormalFlag | CVertexBuffer : : TexCoord0Flag ) )
& & ( _VBuffer . getValueType ( CVertexBuffer : : TexCoord0 ) = = CVertexBuffer : : Float2 )
& & ( _OriginalSkinNormals . size ( ) ) & & ( ! _OriginalTGSpace . size ( ) ) ;
CVertexStreamManager * meshSkinManager = renderTrav - > getMeshSkinManager ( ) ;
if ( supportVertexStream )
{
uint maxVertices = meshSkinManager - > getMaxVertices ( ) ;
uint vertexSize = meshSkinManager - > getVertexSize ( ) ;
nlassert ( vertexSize = = 32 ) ;
if ( _OriginalSkinVertices . size ( ) < = maxVertices )
{
// apply the skinning
uint8 * dstVb = meshSkinManager - > lock ( ) ;
applySkin ( dstVb , skeleton ) ;
meshSkinManager - > unlock ( _OriginalSkinVertices . size ( ) ) ;
}
else
{
supportVertexStream = false ;
nlwarning ( " Unable to animate skinned model, too many vertices " ) ;
}
}
else
{
nlwarning ( " Unable to animate skinned model, unsupported vertex format " ) ;
}
// apply the skinning: _VBuffer is modified.
applySkin ( skeleton ) ;
// applySkin(skeleton);
// Setup meshVertexProgram
@ -786,7 +816,14 @@ void CMeshGeom::renderSkin(CTransformShape *trans, float alphaMRM)
// Render the mesh.
//===========
// active VB.
if ( supportVertexStream )
{
meshSkinManager - > activate ( ) ;
}
else
{
drv - > activeVertexBuffer ( _VBuffer ) ;
}
// For all _MatrixBlocks
@ -816,6 +853,11 @@ void CMeshGeom::renderSkin(CTransformShape *trans, float alphaMRM)
}
}
if ( supportVertexStream )
{
meshSkinManager - > swapVBHard ( ) ;
}
// End VertexProgram effect
if ( useMeshVP )
{
@ -1787,7 +1829,7 @@ void CMeshGeom::restoreOriginalSkinVertices()
// ***************************************************************************
void CMeshGeom : : applySkin ( CSkeletonModel * skeleton )
void CMeshGeom : : applySkin ( void * dstVb , CSkeletonModel * skeleton )
{
// init.
//===================
@ -1802,10 +1844,12 @@ void CMeshGeom::applySkin(CSkeletonModel *skeleton)
skinType = SkinWithNormal ;
else
skinType = SkinWithTgSpace ;
nlassert ( skinType = = SkinWithNormal ) ; // Only support the streamable vertex buffer format
// Get VB src/dst info/ptrs.
uint numVertices = ( uint ) _OriginalSkinVertices . size ( ) ;
uint dstStride = _VBuffer . getVertexSize ( ) ;
static const uint dstStride = 32 ; // _VBuffer.getVertexSize();
uint srcStride = _VBuffer . getVertexSize ( ) ;
// Get dst TgSpace.
uint tgSpaceStage = 0 ;
if ( skinType > = SkinWithTgSpace )
@ -1823,6 +1867,10 @@ void CMeshGeom::applySkin(CSkeletonModel *skeleton)
CVertexBufferRead vba ;
_VBuffer . lock ( vba ) ;
uint8 * dstVbPos = ( uint8 * ) dstVb ;
uint8 * dstVbNormal = dstVbPos + 12 ;
uint8 * dstVbUV = dstVbPos + 24 ;
// For all MatrixBlocks
//===================
for ( uint mb = 0 ; mb < _MatrixBlocks . size ( ) ; mb + + )
@ -1839,25 +1887,25 @@ void CMeshGeom::applySkin(CSkeletonModel *skeleton)
CVector * srcVector = & _OriginalSkinVertices [ 0 ] ;
uint8 * srcPal = ( uint8 * ) vba . getPaletteSkinPointer ( 0 ) ;
uint8 * srcWgt = ( uint8 * ) vba . getWeightPointer ( 0 ) ;
uint8 * dstVector = ( uint8 * ) vba . getVertexCoordPointer ( 0 ) ;
uint8 * dstVector = dstVbPos ; // (uint8 *)vba.getVertexCoordPointer(0);
// Normal.
CVector * srcNormal = NULL ;
uint8 * dstNormal = NULL ;
if ( skinType > = SkinWithNormal )
{
srcNormal = & _OriginalSkinNormals [ 0 ] ;
dstNormal = ( uint8 * ) vba . getNormalCoordPointer ( 0 ) ;
dstNormal = dstVbNormal ; // (uint8 *)vba.getNormalCoordPointer(0);
}
// TgSpace.
CVector * srcTgSpace = NULL ;
uint8 * dstTgSpace = NULL ;
if ( skinType > = SkinWithTgSpace )
{
nlassert ( false ) ;
srcTgSpace = & _OriginalTGSpace [ 0 ] ;
dstTgSpace = ( uint8 * ) vba . getTexCoordPointer ( 0 , tgSpaceStage ) ;
}
// For all vertices that need to be computed.
uint size = numVertices ;
for ( ; size > 0 ; size - - )
@ -1895,14 +1943,46 @@ void CMeshGeom::applySkin(CSkeletonModel *skeleton)
srcNormal + + ;
srcTgSpace + + ;
// inc paletteSkin and dst (all whatever skin type used...)
srcPal + = dst Stride;
srcWgt + = dst Stride;
srcPal + = src Stride;
srcWgt + = src Stride;
dstVector + = dstStride ;
dstNormal + = dstStride ;
dstTgSpace + = dstStride ;
}
}
// Remaining vertices
{
uint8 * pFlag = & skinFlags [ 0 ] ;
CVector * srcVector = & _OriginalSkinVertices [ 0 ] ;
uint8 * dstVector = dstVbPos ;
CVector * srcNormal = & _OriginalSkinNormals [ 0 ] ;
uint8 * dstNormal = dstVbNormal ;
uint8 * srcUV = ( uint8 * ) vba . getTexCoordPointer ( 0 , 0 ) ;
uint8 * dstUV = dstVbUV ;
uint srcStride = _VBuffer . getVertexSize ( ) ;
for ( uint i = 0 ; i < numVertices ; + + i )
{
if ( * pFlag ! = NL3D_SOFTSKIN_VCOMPUTED )
{
* ( CVector * ) dstVector = * srcVector ;
* ( CVector * ) dstNormal = * srcNormal ;
}
* ( CVector2f * ) dstUV = * ( CVector2f * ) srcUV ;
// inc flags.
pFlag + + ;
// inc src (all whatever skin type used...)
srcVector + + ;
srcNormal + + ;
srcUV + = srcStride ;
// inc paletteSkin and dst (all whatever skin type used...)
dstVector + = dstStride ;
dstNormal + = dstStride ;
dstUV + = dstStride ;
}
}
// dirt
_OriginalSkinRestored = false ;