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();
// 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);

@ -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+= dstStride;
srcWgt+= dstStride;
srcPal+= srcStride;
srcWgt+= srcStride;
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;

Loading…
Cancel
Save