From 12019173af2aa17617c1dabffa2e51c769f80417 Mon Sep 17 00:00:00 2001 From: James Urquhart Date: Tue, 30 Aug 2016 19:07:02 +0100 Subject: [PATCH] Fix load with DTS shapes introduced with HW skinning changes --- Engine/source/ts/tsMesh.cpp | 4 +-- Engine/source/ts/tsShape.cpp | 39 ++++++++++++++------- Engine/source/ts/tsShapeEdit.cpp | 51 ++++++++++++++++++++++++++-- Engine/source/ts/tsShapeInstance.cpp | 7 +++- Engine/source/ts/tsShapeInstance.h | 2 ++ 5 files changed, 85 insertions(+), 18 deletions(-) diff --git a/Engine/source/ts/tsMesh.cpp b/Engine/source/ts/tsMesh.cpp index 058e4d826..5353a7471 100644 --- a/Engine/source/ts/tsMesh.cpp +++ b/Engine/source/ts/tsMesh.cpp @@ -3429,8 +3429,8 @@ void TSBasicVertexFormat::addMeshRequirements(TSMesh *mesh) bool hasTexcoord2 = false; bool hasSkin = false; - hasColors = mesh->getHasColor() || (texCoordOffset != -1); - hasTexcoord2 = mesh->getHasTVert2() || (colorOffset != -1); + hasColors = mesh->getHasColor() || (colorOffset != -1); + hasTexcoord2 = mesh->getHasTVert2() || (texCoordOffset != -1); hasSkin = (mesh->getMeshType() == TSMesh::SkinMeshType) || (boneOffset != -1); S32 offset = sizeof(TSMesh::__TSMeshVertexBase); diff --git a/Engine/source/ts/tsShape.cpp b/Engine/source/ts/tsShape.cpp index 969cfa388..ff55766c2 100644 --- a/Engine/source/ts/tsShape.cpp +++ b/Engine/source/ts/tsShape.cpp @@ -576,7 +576,12 @@ void TSShape::init() if (!mesh) continue; - if (mesh->parentMesh >= 0) + if (mesh->parentMesh >= meshes.size()) + { + Con::warnf("Mesh %i has a bad parentMeshObject (%i)", iter - meshes.begin(), mesh->parentMesh); + } + + if (mesh->parentMesh >= 0 && mesh->parentMesh < meshes.size()) { mesh->parentMeshObject = meshes[mesh->parentMesh]; } @@ -736,7 +741,7 @@ void TSShape::initVertexBufferPointers() if (mesh->mVertSize > 0 && !mesh->mVertexData.isReady()) { U32 boneOffset = 0; - U32 colorOffset = 0; + U32 texCoordOffset = 0; AssertFatal(mesh->mVertSize == mVertexFormat.getSizeInBytes(), "mismatch in format size"); if (mBasicVertexFormat.boneOffset >= 0) @@ -744,13 +749,13 @@ void TSShape::initVertexBufferPointers() boneOffset = mBasicVertexFormat.boneOffset; } - if (mBasicVertexFormat.colorOffset >= 0) + if (mBasicVertexFormat.texCoordOffset >= 0) { - colorOffset = mBasicVertexFormat.colorOffset; + texCoordOffset = mBasicVertexFormat.texCoordOffset; } // Initialize the vertex data - mesh->mVertexData.set(mShapeVertexData.base + mesh->mVertOffset, mesh->mVertSize, mesh->mNumVerts, colorOffset, boneOffset, false); + mesh->mVertexData.set(mShapeVertexData.base + mesh->mVertOffset, mesh->mVertSize, mesh->mNumVerts, texCoordOffset, boneOffset, false); mesh->mVertexData.setReady(true); } } @@ -856,6 +861,7 @@ void TSShape::initVertexFeatures() } // Now we can create the VBO + mShapeVertexData.set(NULL, 0); U8 *vertexData = (U8*)dMalloc_aligned(destVertex, 16); U8 *vertexDataPtr = vertexData; mShapeVertexData.set(vertexData, destVertex); @@ -872,7 +878,7 @@ void TSShape::initVertexFeatures() continue; U32 boneOffset = 0; - U32 colorOffset = 0; + U32 texCoordOffset = 0; AssertFatal(mesh->mVertSize == mVertexFormat.getSizeInBytes(), "mismatch in format size"); if (mBasicVertexFormat.boneOffset >= 0) @@ -880,9 +886,9 @@ void TSShape::initVertexFeatures() boneOffset = mBasicVertexFormat.boneOffset; } - if (mBasicVertexFormat.colorOffset >= 0) + if (mBasicVertexFormat.texCoordOffset >= 0) { - colorOffset = mBasicVertexFormat.colorOffset; + texCoordOffset = mBasicVertexFormat.texCoordOffset; } // Dump everything @@ -891,7 +897,14 @@ void TSShape::initVertexFeatures() AssertFatal(mesh->mVertOffset == vertexDataPtr - vertexData, "vertex offset mismatch"); mesh->mNumVerts = mesh->getNumVerts(); - mesh->mVertexData.set(mShapeVertexData.base + mesh->mVertOffset, mesh->mVertSize, mesh->mNumVerts, colorOffset, boneOffset, false); + // Correct bad meshes + if (mesh->mNumVerts != 0 && mesh->vertsPerFrame > mesh->mNumVerts) + { + Con::warnf("Shape mesh has bad vertsPerFrame (%i, should be <= %i)", mesh->vertsPerFrame, mesh->mNumVerts); + mesh->vertsPerFrame = mesh->mNumVerts; + } + + mesh->mVertexData.set(mShapeVertexData.base + mesh->mVertOffset, mesh->mVertSize, mesh->mNumVerts, texCoordOffset, boneOffset, false); mesh->convertToVertexData(); mesh->mVertexData.setReady(true); @@ -1494,7 +1507,7 @@ void TSShape::assembleShape() } // read in the meshes (sans skins)...straightforward read one at a time - ptr32 = tsalloc.allocShape32(numMeshes + numSkins*numDetails); // leave room for skins on old shapes + TSMesh **ptrmesh = (TSMesh**)tsalloc.allocShape32((numMeshes + numSkins*numDetails) * (sizeof(TSMesh*) / 4)); S32 curObject = 0; // for tracking skipped meshes for (i=0; iparentMesh == idxToRemove) + { + meshes[k]->parentMesh = -1; + } + else if (meshes[k]->parentMesh > idxToRemove) + { + meshes[k]->parentMesh--; + } + } + for (S32 j = 0; j < objects.size(); j++) { if (objects[j].startMeshIndex > objects[i].startMeshIndex) @@ -770,7 +787,25 @@ void TSShape::removeMeshFromObject(S32 objIndex, S32 meshIndex) S32 oldNumMeshes = obj.numMeshes; while (obj.numMeshes && !meshes[obj.startMeshIndex + obj.numMeshes - 1]) { - meshes.erase(obj.startMeshIndex + obj.numMeshes - 1); + U32 idxToRemove = obj.startMeshIndex + obj.numMeshes - 1; + meshes.erase(idxToRemove); + + // Clear invalid parent + for (U32 k = 0; k < meshes.size(); k++) + { + if (meshes[k] == NULL) + continue; + + if (meshes[k]->parentMesh == idxToRemove) + { + meshes[k]->parentMesh = -1; + } + else if (meshes[k]->parentMesh > idxToRemove) + { + meshes[k]->parentMesh--; + } + } + obj.numMeshes--; } @@ -858,6 +893,12 @@ bool TSShape::removeObject(const String& name) // Update smallest visible detail updateSmallestVisibleDL(); + // Ensure shape is dirty + if (meshes[0]) + { + meshes[0]->makeEditable(); + } + // Re-initialise the shape init(); @@ -1298,6 +1339,12 @@ bool TSShape::removeDetail( S32 size ) billboardDetails.erase( dl ); } + // Ensure shape is dirty + if (meshes[0]) + { + meshes[0]->makeEditable(); + } + // Update smallest visible detail updateSmallestVisibleDL(); diff --git a/Engine/source/ts/tsShapeInstance.cpp b/Engine/source/ts/tsShapeInstance.cpp index 6d24e49f5..d1a8da382 100644 --- a/Engine/source/ts/tsShapeInstance.cpp +++ b/Engine/source/ts/tsShapeInstance.cpp @@ -169,6 +169,7 @@ void TSShapeInstance::buildInstanceData(TSShape * _shape, bool loadMaterials) // material list... mMaterialList = NULL; mOwnMaterialList = false; + mUseOwnBuffer = false; // mData = 0; @@ -532,7 +533,7 @@ void TSShapeInstance::render( const TSRenderState &rdata, S32 dl, F32 intraDL ) S32 end = rdata.isNoRenderTranslucent() ? mShape->subShapeFirstTranslucentObject[ss] : mShape->subShapeFirstObject[ss] + mShape->subShapeNumObjects[ss]; TSVertexBufferHandle *realBuffer; - if (TSShape::smUseHardwareSkinning) + if (TSShape::smUseHardwareSkinning && !mUseOwnBuffer) { // For hardware skinning, just using the buffer associated with the shape will work fine realBuffer = &mShape->mShapeVertexBuffer; @@ -893,3 +894,7 @@ bool TSShapeInstance::hasAccumulation() return result; } +void TSShapeInstance::setUseOwnBuffer() +{ + mUseOwnBuffer = true; +} diff --git a/Engine/source/ts/tsShapeInstance.h b/Engine/source/ts/tsShapeInstance.h index e133beb00..48b253358 100644 --- a/Engine/source/ts/tsShapeInstance.h +++ b/Engine/source/ts/tsShapeInstance.h @@ -279,6 +279,7 @@ protected: TSVertexBufferHandle mSoftwareVertexBuffer; bool mOwnMaterialList; ///< Does this own the material list pointer? + bool mUseOwnBuffer; ///< Force using our own copy of the vertex buffer bool mAlphaAlways; F32 mAlphaAlwaysValue; @@ -341,6 +342,7 @@ protected: /// an optional feature set. void initMaterialList( const FeatureSet *features = NULL ); + void setUseOwnBuffer(); bool ownMaterialList() const { return mOwnMaterialList; } /// Get the number of material targets in this shape instance