Use streaming vertex buffer for animating regular skinned meshes, writing to a read locked and shared vertex buffer is illegal, fix kaetemi/ryzomclassic#93

develop
kaetemi 4 years ago
parent 2c167fb360
commit c6f8baa058
No known key found for this signature in database
GPG Key ID: 9873C4D40BB479BC

@ -837,7 +837,7 @@ private:
void restoreOriginalSkinVertices(); void restoreOriginalSkinVertices();
// apply Skin to all vertices from _OriginalSkin* to _VBuffer. // apply Skin to all vertices from _OriginalSkin* to _VBuffer.
void applySkin(CSkeletonModel *skeleton); void applySkin(void *dstVb, CSkeletonModel *skeleton);
void flagSkinVerticesForMatrixBlock(uint8 *skinFlags, CMatrixBlock &mb); void flagSkinVerticesForMatrixBlock(uint8 *skinFlags, CMatrixBlock &mb);

@ -30,6 +30,7 @@
#include "nel/3d/render_trav.h" #include "nel/3d/render_trav.h"
#include "nel/3d/visual_collision_mesh.h" #include "nel/3d/visual_collision_mesh.h"
#include "nel/3d/meshvp_wind_tree.h" #include "nel/3d/meshvp_wind_tree.h"
#include "nel/3d/vertex_stream_manager.h"
using namespace std; using namespace std;
using namespace NLMISC; 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 skeleton matrix has already been setuped by CSkeletonModel
// NB: the normalize flag 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. // apply the skinning: _VBuffer is modified.
applySkin(skeleton); // applySkin(skeleton);
// Setup meshVertexProgram // Setup meshVertexProgram
@ -786,7 +816,14 @@ void CMeshGeom::renderSkin(CTransformShape *trans, float alphaMRM)
// Render the mesh. // Render the mesh.
//=========== //===========
// active VB. // active VB.
if (supportVertexStream)
{
meshSkinManager->activate();
}
else
{
drv->activeVertexBuffer(_VBuffer); drv->activeVertexBuffer(_VBuffer);
}
// For all _MatrixBlocks // For all _MatrixBlocks
@ -816,6 +853,11 @@ void CMeshGeom::renderSkin(CTransformShape *trans, float alphaMRM)
} }
} }
if (supportVertexStream)
{
meshSkinManager->swapVBHard();
}
// End VertexProgram effect // End VertexProgram effect
if(useMeshVP) if(useMeshVP)
{ {
@ -1787,7 +1829,7 @@ void CMeshGeom::restoreOriginalSkinVertices()
// *************************************************************************** // ***************************************************************************
void CMeshGeom::applySkin(CSkeletonModel *skeleton) void CMeshGeom::applySkin(void *dstVb, CSkeletonModel *skeleton)
{ {
// init. // init.
//=================== //===================
@ -1802,10 +1844,12 @@ void CMeshGeom::applySkin(CSkeletonModel *skeleton)
skinType= SkinWithNormal; skinType= SkinWithNormal;
else else
skinType= SkinWithTgSpace; skinType= SkinWithTgSpace;
nlassert(skinType == SkinWithNormal); // Only support the streamable vertex buffer format
// Get VB src/dst info/ptrs. // Get VB src/dst info/ptrs.
uint numVertices= (uint)_OriginalSkinVertices.size(); uint numVertices= (uint)_OriginalSkinVertices.size();
uint dstStride= _VBuffer.getVertexSize(); static const uint dstStride = 32; // _VBuffer.getVertexSize();
uint srcStride = _VBuffer.getVertexSize();
// Get dst TgSpace. // Get dst TgSpace.
uint tgSpaceStage = 0; uint tgSpaceStage = 0;
if( skinType>= SkinWithTgSpace) if( skinType>= SkinWithTgSpace)
@ -1823,6 +1867,10 @@ void CMeshGeom::applySkin(CSkeletonModel *skeleton)
CVertexBufferRead vba; CVertexBufferRead vba;
_VBuffer.lock (vba); _VBuffer.lock (vba);
uint8 *dstVbPos = (uint8 *)dstVb;
uint8 *dstVbNormal = dstVbPos + 12;
uint8 *dstVbUV = dstVbPos + 24;
// For all MatrixBlocks // For all MatrixBlocks
//=================== //===================
for(uint mb= 0; mb<_MatrixBlocks.size();mb++) for(uint mb= 0; mb<_MatrixBlocks.size();mb++)
@ -1839,25 +1887,25 @@ void CMeshGeom::applySkin(CSkeletonModel *skeleton)
CVector *srcVector= &_OriginalSkinVertices[0]; CVector *srcVector= &_OriginalSkinVertices[0];
uint8 *srcPal= (uint8*)vba.getPaletteSkinPointer(0); uint8 *srcPal= (uint8*)vba.getPaletteSkinPointer(0);
uint8 *srcWgt= (uint8*)vba.getWeightPointer(0); uint8 *srcWgt= (uint8*)vba.getWeightPointer(0);
uint8 *dstVector= (uint8*)vba.getVertexCoordPointer(0); uint8 *dstVector = dstVbPos; // (uint8 *)vba.getVertexCoordPointer(0);
// Normal. // Normal.
CVector *srcNormal= NULL; CVector *srcNormal= NULL;
uint8 *dstNormal= NULL; uint8 *dstNormal= NULL;
if(skinType>=SkinWithNormal) if(skinType>=SkinWithNormal)
{ {
srcNormal= &_OriginalSkinNormals[0]; srcNormal= &_OriginalSkinNormals[0];
dstNormal= (uint8*)vba.getNormalCoordPointer(0); dstNormal = dstVbNormal; // (uint8 *)vba.getNormalCoordPointer(0);
} }
// TgSpace. // TgSpace.
CVector *srcTgSpace= NULL; CVector *srcTgSpace= NULL;
uint8 *dstTgSpace= NULL; uint8 *dstTgSpace= NULL;
if(skinType>=SkinWithTgSpace) if(skinType>=SkinWithTgSpace)
{ {
nlassert(false);
srcTgSpace= &_OriginalTGSpace[0]; srcTgSpace= &_OriginalTGSpace[0];
dstTgSpace = (uint8 *)vba.getTexCoordPointer(0, tgSpaceStage); dstTgSpace = (uint8 *)vba.getTexCoordPointer(0, tgSpaceStage);
} }
// For all vertices that need to be computed. // For all vertices that need to be computed.
uint size= numVertices; uint size= numVertices;
for(;size>0;size--) for(;size>0;size--)
@ -1895,14 +1943,46 @@ void CMeshGeom::applySkin(CSkeletonModel *skeleton)
srcNormal++; srcNormal++;
srcTgSpace++; srcTgSpace++;
// inc paletteSkin and dst (all whatever skin type used...) // inc paletteSkin and dst (all whatever skin type used...)
srcPal+= dstStride; srcPal+= srcStride;
srcWgt+= dstStride; srcWgt+= srcStride;
dstVector+= dstStride; dstVector+= dstStride;
dstNormal+= dstStride; dstNormal+= dstStride;
dstTgSpace+= 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 // dirt
_OriginalSkinRestored= false; _OriginalSkinRestored= false;

Loading…
Cancel
Save