瀏覽代碼

Fix load with DTS shapes introduced with HW skinning changes

James Urquhart 9 年之前
父節點
當前提交
12019173af

+ 2 - 2
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);

+ 26 - 13
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; i<numMeshes; i++)
    {
@@ -1504,10 +1517,9 @@ void TSShape::assembleShape()
          // decal mesh deprecated
          skip = true;
       TSMesh * mesh = TSMesh::assembleMesh(meshType,skip);
-      if (ptr32)
+      if (ptrmesh)
       {
-         ptr32[i] = skip ?  0 : (intptr_t)mesh; // @todo 64bit
-         meshes.push_back(skip ?  0 : mesh);
+         ptrmesh[i] = skip ?  0 : mesh;
       }
 
       // fill in location of verts, tverts, and normals for detail levels
@@ -1536,6 +1548,7 @@ void TSShape::assembleShape()
          }
       }
    }
+   meshes.set(ptrmesh, numMeshes);
 
    tsalloc.checkGuard();
 

+ 49 - 2
Engine/source/ts/tsShapeEdit.cpp

@@ -742,9 +742,26 @@ void TSShape::removeMeshFromObject(S32 objIndex, S32 meshIndex)
       {
          if (meshIndex < objects[i].numMeshes)
          {
-            meshes.erase(objects[i].startMeshIndex + meshIndex);
+            U32 idxToRemove = objects[i].startMeshIndex + meshIndex;
+            meshes.erase(idxToRemove);
             objects[i].numMeshes--;
 
+            // 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--;
+               }
+            }
+
             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();
 

+ 6 - 1
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;
+}

+ 2 - 0
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