From 07e68f1daa1a825f8a35d93d4ae77b8fae50961d Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Thu, 13 Jun 2024 22:31:05 -0700 Subject: [PATCH] feat: migrate CombineObjectsAndCreatePhysics with structure view Signed-off-by: Michael Pollind --- HPL2/include/graphics/GraphicsBuffer.h | 2 + HPL2/include/impl/CollideShapeNewton.h | 4 +- HPL2/include/impl/PhysicsWorldNewton.h | 77 +++++++------ HPL2/include/physics/PhysicsWorld.h | 7 +- HPL2/sources/impl/CollideShapeNewton.cpp | 52 --------- HPL2/sources/impl/PhysicsWorldNewton.cpp | 40 +++++++ HPL2/sources/resources/WorldLoaderHplMap.cpp | 113 ++++++------------- 7 files changed, 120 insertions(+), 175 deletions(-) diff --git a/HPL2/include/graphics/GraphicsBuffer.h b/HPL2/include/graphics/GraphicsBuffer.h index ab8075466..8ebd6ede3 100644 --- a/HPL2/include/graphics/GraphicsBuffer.h +++ b/HPL2/include/graphics/GraphicsBuffer.h @@ -135,6 +135,8 @@ namespace hpl { return std::span(reinterpret_cast(reinterpret_cast(m_asset->m_mapped.m_mappedData) + m_byteOffset), (m_asset->m_mapped.m_size - m_byteOffset) / sizeof(T)); } } + return std::span(); + } inline std::span rawByteSpan() { switch(m_asset->m_type) { diff --git a/HPL2/include/impl/CollideShapeNewton.h b/HPL2/include/impl/CollideShapeNewton.h index 82a4f8bbf..dbf345a8c 100644 --- a/HPL2/include/impl/CollideShapeNewton.h +++ b/HPL2/include/impl/CollideShapeNewton.h @@ -60,10 +60,8 @@ namespace hpl { NewtonCollision* GetNewtonCollision(){ return mpNewtonCollision;} - private: - NewtonCollision* mpNewtonCollision; + NewtonCollision* mpNewtonCollision; NewtonWorld *mpNewtonWorld; - tCollideShapeVec mvSubShapes; }; }; diff --git a/HPL2/include/impl/PhysicsWorldNewton.h b/HPL2/include/impl/PhysicsWorldNewton.h index 466a40f01..301449956 100644 --- a/HPL2/include/impl/PhysicsWorldNewton.h +++ b/HPL2/include/impl/PhysicsWorldNewton.h @@ -34,75 +34,80 @@ namespace hpl { cPhysicsWorldNewton(); ~cPhysicsWorldNewton(); - void Simulate(float afTimeStep); + void Simulate(float afTimeStep) override; - void SetMaxTimeStep(float afTimeStep); - float GetMaxTimeStep(); + void SetMaxTimeStep(float afTimeStep) override; + float GetMaxTimeStep() override; - void SetWorldSize(const cVector3f &avMin,const cVector3f &avMax); - cVector3f GetWorldSizeMin(); - cVector3f GetWorldSizeMax(); + void SetWorldSize(const cVector3f &avMin,const cVector3f &avMax) override; + cVector3f GetWorldSizeMin() override; + cVector3f GetWorldSizeMax() override; - void SetGravity(const cVector3f& avGravity); - cVector3f GetGravity(); + void SetGravity(const cVector3f& avGravity) override; + cVector3f GetGravity() override; - void SetAccuracyLevel(ePhysicsAccuracy aAccuracy); - ePhysicsAccuracy GetAccuracyLevel(); + void SetAccuracyLevel(ePhysicsAccuracy aAccuracy) override; + ePhysicsAccuracy GetAccuracyLevel() override; - void SetNumberOfThreads(int alThreads); - int GetNumberOfThreads(); + void SetNumberOfThreads(int alThreads) override; + int GetNumberOfThreads() override; - iCollideShape* CreateNullShape(); - iCollideShape* CreateBoxShape(const cVector3f &avSize, cMatrixf* apOffsetMtx); - iCollideShape* CreateSphereShape(const cVector3f &avRadii, cMatrixf* apOffsetMtx); - iCollideShape* CreateCylinderShape(float afRadius, float afHeight, cMatrixf* apOffsetMtx); - iCollideShape* CreateCapsuleShape(float afRadius, float afHeight, cMatrixf* apOffsetMtx); + iCollideShape* CreateNullShape() override; + iCollideShape* CreateBoxShape(const cVector3f &avSize, cMatrixf* apOffsetMtx) override; + iCollideShape* CreateSphereShape(const cVector3f &avRadii, cMatrixf* apOffsetMtx) override; + iCollideShape* CreateCylinderShape(float afRadius, float afHeight, cMatrixf* apOffsetMtx) override; + iCollideShape* CreateCapsuleShape(float afRadius, float afHeight, cMatrixf* apOffsetMtx) override; - iCollideShape* CreateMeshShape(iVertexBuffer *apVtxBuffer); - iCollideShape* LoadMeshShapeFromBuffer(cBinaryBuffer *apBuffer); - void SaveMeshShapeToBuffer(iCollideShape* apMeshShape, cBinaryBuffer *apBuffer); + iCollideShape* CreateMeshShape(iVertexBuffer *apVtxBuffer) override; + iCollideShape* CreateMeshShape(uint32_t numberIndecies, + uint32_t vertexOffset, uint32_t indexOffset, + GraphicsBuffer::BufferIndexView indexView, + GraphicsBuffer::BufferStructuredView position) override; - iCollideShape* CreateCompundShape(tCollideShapeVec &avShapes); - iCollideShape* CreateStaticSceneShape(tCollideShapeVec &avShapes, tMatrixfVec *apMatrices); + iCollideShape* LoadMeshShapeFromBuffer(cBinaryBuffer *apBuffer) override; + void SaveMeshShapeToBuffer(iCollideShape* apMeshShape, cBinaryBuffer *apBuffer) override; + + iCollideShape* CreateCompundShape(tCollideShapeVec &avShapes) override; + iCollideShape* CreateStaticSceneShape(tCollideShapeVec &avShapes, tMatrixfVec *apMatrices) override; iPhysicsJointBall* CreateJointBall(const tString &asName,const cVector3f& avPivotPoint, const cVector3f& avPinDir, - iPhysicsBody* apParentBody, iPhysicsBody *apChildBody); + iPhysicsBody* apParentBody, iPhysicsBody *apChildBody) override; iPhysicsJointHinge* CreateJointHinge(const tString &asName,const cVector3f& avPivotPoint, const cVector3f& avPinDir, - iPhysicsBody* apParentBody, iPhysicsBody *apChildBody); + iPhysicsBody* apParentBody, iPhysicsBody *apChildBody) override; iPhysicsJointSlider* CreateJointSlider(const tString &asName,const cVector3f& avPivotPoint, const cVector3f& avPinDir, - iPhysicsBody* apParentBody, iPhysicsBody *apChildBody); + iPhysicsBody* apParentBody, iPhysicsBody *apChildBody) override; iPhysicsJointScrew* CreateJointScrew(const tString &asName,const cVector3f& avPivotPoint, const cVector3f& avPinDir, - iPhysicsBody* apParentBody, iPhysicsBody *apChildBody); + iPhysicsBody* apParentBody, iPhysicsBody *apChildBody) override; - iPhysicsBody* CreateBody(const tString &asName,iCollideShape *apShape); + iPhysicsBody* CreateBody(const tString &asName,iCollideShape *apShape) override; - void GetBodiesInBV(cBoundingVolume *apBV, std::vector *apBodyVec); + void GetBodiesInBV(cBoundingVolume *apBV, std::vector *apBodyVec) override; - iCharacterBody *CreateCharacterBody(const tString &asName, const cVector3f &avSize); + iCharacterBody *CreateCharacterBody(const tString &asName, const cVector3f &avSize) override; - iPhysicsMaterial* CreateMaterial(const tString &asName); + iPhysicsMaterial* CreateMaterial(const tString &asName) override; - iPhysicsController *CreateController(const tString &asName); + iPhysicsController *CreateController(const tString &asName) override; - iPhysicsRope* CreateRope(const tString &asName, const cVector3f &avStartPos, const cVector3f &avEndPos); + iPhysicsRope* CreateRope(const tString &asName, const cVector3f &avStartPos, const cVector3f &avEndPos) override; void CastRay(iPhysicsRayCallback *apCallback, const cVector3f &avOrigin, const cVector3f& avEnd, bool abCalcDist, bool abCalcNormal, bool abCalcPoint, - bool abUsePrefilter = false); + bool abUsePrefilter = false) override; bool CheckShapeCollision( iCollideShape* apShapeA, const cMatrixf& a_mtxA, iCollideShape* apShapeB, const cMatrixf& a_mtxB, cCollideData & aCollideData, int alMaxPoints, - bool abCorrectNormalDirection); + bool abCorrectNormalDirection) override; void RenderShapeDebugGeometry( iCollideShape *apShape, const cMatrixf& a_mtxTransform, - DebugDraw *apLowLevel, const cColor& aColor); - void RenderDebugGeometry(DebugDraw *apLowLevel, const cColor& aColor); + DebugDraw *apLowLevel, const cColor& aColor) override; + void RenderDebugGeometry(DebugDraw *apLowLevel, const cColor& aColor) override; NewtonWorld* GetNewtonWorld(){ return mpNewtonWorld;} private: diff --git a/HPL2/include/physics/PhysicsWorld.h b/HPL2/include/physics/PhysicsWorld.h index 4127d153c..360183acc 100644 --- a/HPL2/include/physics/PhysicsWorld.h +++ b/HPL2/include/physics/PhysicsWorld.h @@ -129,9 +129,10 @@ namespace hpl { virtual iCollideShape* CreateCylinderShape(float afRadius, float afHeight, cMatrixf* apOffsetMtx)=0; virtual iCollideShape* CreateCapsuleShape(float afRadius, float afHeight, cMatrixf* apOffsetMtx)=0; virtual iCollideShape* CreateMeshShape(iVertexBuffer *apVtxBuffer)=0; - //virtual iCollideShape* CreateMeshShape(size_t numberVerticies, - // GraphicsBuffer::BufferIndexView indexView, - // GraphicsBuffer::BufferStructuredView position)=0; + virtual iCollideShape* CreateMeshShape(uint32_t numberIndecies, + uint32_t vertexOffset, uint32_t indexOffset, + GraphicsBuffer::BufferIndexView indexView, + GraphicsBuffer::BufferStructuredView position)=0; /** * The buffer position must be pointing to where the data is saved! */ diff --git a/HPL2/sources/impl/CollideShapeNewton.cpp b/HPL2/sources/impl/CollideShapeNewton.cpp index 2c82906ba..3c59a6449 100644 --- a/HPL2/sources/impl/CollideShapeNewton.cpp +++ b/HPL2/sources/impl/CollideShapeNewton.cpp @@ -307,11 +307,7 @@ namespace hpl { int lCount=0; - //unsigned long lStartTime = cPlatform::GetApplicationTime(); - //Log("%d triangles: ", alIndexNum/3); - mpNewtonCollision = NewtonCreateTreeCollision(mpNewtonWorld, 0); - //Log("-- Creating mesh collision.:\n"); NewtonTreeCollisionBeginBuild(mpNewtonCollision); for(int tri = 0; tri < alIndexNum; tri+=3) { @@ -324,54 +320,6 @@ namespace hpl { vTriVec[idx*3 + 1] = apVertexArray[lVtx + 1]; vTriVec[idx*3 + 2] = apVertexArray[lVtx + 2]; } - - //if(alIndexNum<100) - //{ - // for(int i=0;i<3; ++i) Log("%f, %f, %f, ", vTriVec[i*3 + 0],vTriVec[i*3 + 1],vTriVec[i*3 + 2]); - // Log("\n"); - //} - //lCount+=9; - - //cannot allow negative zeros! it is true! - /*for(int i=0;i<9; ++i) - { - if(fabs(vTriVec[i]-0.0f) < 0.000001f) vTriVec[i] = 0; - }*/ - - if(false)//bOptimize==false) - { - cPlanef tempPlane; - cVector3f vP1(vTriVec[0+0],vTriVec[0+1],vTriVec[0+2]); - cVector3f vP2(vTriVec[1*3+0],vTriVec[1*3+1],vTriVec[1*3+2]); - cVector3f vP3(vTriVec[2*3+0],vTriVec[2*3+1],vTriVec[2*3+2]); - - tempPlane.FromPoints(vP1, vP2, vP3); - - //Log("P1: %s P2: %s P3: %s\n",vP1.ToString().c_str(),vP2.ToString().c_str(),vP3.ToString().c_str()); - //Log("Plane: a: %f b: %f c: %f d: %f\n",tempPlane.a,tempPlane.b,tempPlane.c,tempPlane.d); - - ///////////////////////////////// - //Check if the triangles are on the same plane. If so, do not optimize - // Do not check first triangle - if(bCreatedPlane==false) - { - plane = tempPlane; - bCreatedPlane = true; - } - // First plane created. - else - { - //Check the plane equation is different from the first one (allow a small difference thoug). - if( std::abs(plane.a - tempPlane.a) > 0.001f || - std::abs(plane.b - tempPlane.b) > 0.001f || - std::abs(plane.c - tempPlane.c) > 0.001f || - std::abs(plane.d - tempPlane.d) > 0.001f ) - { - bOptimize = true; - } - } - } - NewtonTreeCollisionAddFace(mpNewtonCollision,3,vTriVec,sizeof(float)*3,1); } diff --git a/HPL2/sources/impl/PhysicsWorldNewton.cpp b/HPL2/sources/impl/PhysicsWorldNewton.cpp index e878aa96f..5fd3fd72a 100644 --- a/HPL2/sources/impl/PhysicsWorldNewton.cpp +++ b/HPL2/sources/impl/PhysicsWorldNewton.cpp @@ -286,6 +286,45 @@ namespace hpl { return pShape; } + + iCollideShape* cPhysicsWorldNewton::CreateMeshShape(uint32_t numberIndecies, + uint32_t vertexOffset, uint32_t indexOffset, + GraphicsBuffer::BufferIndexView indexView, + GraphicsBuffer::BufferStructuredView position) { + cCollideShapeNewton* pShape = hplNew(cCollideShapeNewton, (eCollideShapeType_Mesh, 0, NULL, mpNewtonWorld, this)); + + Vector3 minLocal = Vector3(100000, 100000, 100000); + Vector3 maxLocal = Vector3(-100000, -100000, -100000); + pShape->mpNewtonCollision = NewtonCreateTreeCollision(mpNewtonWorld, 0); + NewtonTreeCollisionBeginBuild(pShape->mpNewtonCollision); + for (size_t i = 0; i < numberIndecies; i += 3) { + float3 p1 = position.Get(vertexOffset + indexView.Get(indexOffset + i)); + float3 p2 = position.Get(vertexOffset + indexView.Get(indexOffset + i + 1)); + float3 p3 = position.Get(vertexOffset + indexView.Get(indexOffset + i + 2)); + + maxLocal = maxPerElem(f3Tov3(p1), maxLocal); + minLocal = minPerElem(f3Tov3(p1), minLocal); + + maxLocal = maxPerElem(f3Tov3(p2), maxLocal); + minLocal = minPerElem(f3Tov3(p2), minLocal); + + maxLocal = maxPerElem(f3Tov3(p3), maxLocal); + minLocal = minPerElem(f3Tov3(p3), minLocal); + + float face[3 * 3] = { + p1.x, p1.y, p1.z, + p2.x, p2.y, p2.z, + p3.x, p3.y, p3.z + }; + NewtonTreeCollisionAddFace(pShape->mpNewtonCollision, 3, face, sizeof(float) * 3, 1); + } + NewtonTreeCollisionEndBuild(pShape->mpNewtonCollision, 0); + + pShape->GetBoundingVolume().SetLocalMinMax(cMath::FromForgeVector3(minLocal), cMath::FromForgeVector3(maxLocal)); + mlstShapes.push_back(pShape); + return pShape; + } + //----------------------------------------------------------------------- iCollideShape* cPhysicsWorldNewton::LoadMeshShapeFromBuffer(cBinaryBuffer *apBuffer) @@ -308,6 +347,7 @@ namespace hpl { pNewtonMeshShape->SaveToSerializedData(apBuffer); } + //----------------------------------------------------------------------- iCollideShape* cPhysicsWorldNewton::CreateCompundShape(tCollideShapeVec &avShapes) diff --git a/HPL2/sources/resources/WorldLoaderHplMap.cpp b/HPL2/sources/resources/WorldLoaderHplMap.cpp index 795d7a0ab..9108f5da5 100644 --- a/HPL2/sources/resources/WorldLoaderHplMap.cpp +++ b/HPL2/sources/resources/WorldLoaderHplMap.cpp @@ -21,6 +21,7 @@ #include "Common_3/Graphics/Interfaces/IGraphics.h" #include "Common_3/Utilities/Log/Log.h" +#include "Common_3/Utilities/ThirdParty/OpenSource/ModifiedSonyMath/sse/vectormath.hpp" #include "engine/RTTI.h" #include "graphics/GraphicsBuffer.h" #include "graphics/Image.h" @@ -1412,109 +1413,59 @@ namespace hpl { void cWorldLoaderHplMap::CombineObjectsAndCreatePhysics(std::vector &avObjects, int alFirstIdx, int alLastIdx) { if(gbLog) Log(" Combining objects %d -> %d\n", alFirstIdx, alLastIdx); - const int lMaxIndices= 30; - - /////////////////////////////////////////// - //Iterate objects to get the total amount of vertex data - int lTotalVtxAmount =0; - int lTotalIdxAmount =0; tString sName = "CombinedObjects"+cString::ToString(mlCombinedBodyNameCount); - for(int i=alFirstIdx; i<=alLastIdx; ++i) - { - if(avObjects[i].mpUserData->mbCollides==false) continue; - - iVertexBuffer *pVtxBuffer = avObjects[i].mpObject->GetVertexBuffer(); - - //Do a special debug test and skip highpoly entities, loading the map faster. - if((mlCurrentFlags & eWorldLoadFlag_FastPhysicsLoad) && pVtxBuffer->GetIndexNum() > lMaxIndices) continue; - - - lTotalVtxAmount += pVtxBuffer->GetVertexNum(); - lTotalIdxAmount += pVtxBuffer->GetIndexNum(); - - if(gbLog) Log(" '%s' has %d vtx and %d idx\n",avObjects[i].mpObject->GetName().c_str(),pVtxBuffer->GetVertexNum(),pVtxBuffer->GetIndexNum()); - } - if(gbLog) Log(" Total amount %d vtx and %d idx\n",lTotalVtxAmount, lTotalIdxAmount); + const int lMaxIndices= 30; - /////////////////////////////////////////// - //If no vertex buffers, then just exit - if(lTotalVtxAmount<=0 || lTotalIdxAmount<=0) - { - return; - } mlCombinedBodyNameCount++; + GraphicsBuffer positionBuffer; + GraphicsBuffer indexBuffer; - /////////////////////////////////////////// - //Create the vertex buffer (skipping color!) - auto* targetVertexBuffer = static_cast(mpGraphics->GetLowLevel()->CreateVertexBuffer( eVertexBufferType_Software, eVertexBufferDrawType_Tri, - eVertexBufferUsageType_Dynamic,lTotalVtxAmount, lTotalIdxAmount)); - - targetVertexBuffer->CreateElementArray(eVertexBufferElement_Position,eVertexBufferElementFormat_Float, 4); - targetVertexBuffer->ResizeArray(eVertexBufferElement_Position, lTotalVtxAmount * 4); - auto* targetPositionElement = targetVertexBuffer->GetElement(eVertexBufferElement_Position); - ASSERT(targetPositionElement != nullptr && "positionElement is null"); - - //Set up and get indices - targetVertexBuffer->ResizeIndices(lTotalIdxAmount); - unsigned int* pIndexArray = targetVertexBuffer->GetIndices(); - - /////////////////////////////////////////// + GraphicsBuffer::BufferStructuredView positionView = positionBuffer.CreateStructuredView(); + GraphicsBuffer::BufferIndexView indexView = indexBuffer.CreateIndexView(); + + size_t VertexElementIdx = 0; + size_t indexElementIdx = 0; //Fill vertex buffer with data - int lIdxOffset =0; - size_t targetPositionOffset = 0; for(int vtxbuffer=alFirstIdx; vtxbuffer<=alLastIdx; ++vtxbuffer) { - if(avObjects[vtxbuffer].mpUserData->mbCollides==false) continue; + if(avObjects[vtxbuffer].mpUserData->mbCollides == false) continue; cSubMeshEntity *pObject = avObjects[vtxbuffer].mpObject; - - //////////////////////////// - //Add colliders if any cSubMesh *pSubMesh = avObjects[vtxbuffer].mpObject->GetSubMesh(); + auto& indexStream =pSubMesh->IndexStream(); //Do a special debug test and skip highpoly entities, loading the map faster. - if((mlCurrentFlags & eWorldLoadFlag_FastPhysicsLoad) && pSubMesh->GetVertexBuffer()->GetIndexNum() > lMaxIndices) continue; + if((mlCurrentFlags & eWorldLoadFlag_FastPhysicsLoad) && indexStream.m_numberElements > lMaxIndices) continue; + LOGF_IF(LogLevel::eERROR, gbLog, " Copying position data from '%s'\n", pObject->GetName().c_str()); - if(gbLog) Log(" Copying position data from '%s'\n", pObject->GetName().c_str()); - //////////////////////// - //Get vertex copy and transform - iVertexBuffer *pSubVtxBuffer = pObject->GetVertexBuffer(); - auto* pTransformedVtxBuffer = static_cast(pSubVtxBuffer->CreateCopy( eVertexBufferType_Software, eVertexBufferUsageType_Static, - eVertexElementFlag_Position)); - pTransformedVtxBuffer->Transform(pObject->GetWorldMatrix()); - auto sourceElement = pTransformedVtxBuffer->GetElement(eVertexBufferElement_Position); - ASSERT(targetPositionElement != nullptr && "targetPositionElement != nullptr"); - ASSERT(targetPositionElement->m_type == sourceElement->m_type && "targetPositionElement->m_type == sourceElement->m_type"); - ASSERT(targetPositionElement->m_num == sourceElement->m_num && "targetPositionElement->m_num == sourceElement->m_num"); - - auto elementStart = &(targetPositionElement->Data().data()[targetPositionOffset]); - std::copy(sourceElement->Data().begin(), sourceElement->Data().end(), elementStart); - targetPositionOffset += sourceElement->Data().size(); - - //Copy to index array and increase index pointer - unsigned int* pTransIdxArray = pTransformedVtxBuffer->GetIndices(); - for(int i=0; iGetIndexNum(); ++i) - { - pIndexArray[i] = pTransIdxArray[i] + lIdxOffset; - } - - lIdxOffset += pTransformedVtxBuffer->GetVertexNum(); - pIndexArray += pTransformedVtxBuffer->GetIndexNum(); + const cMatrixf worldTransform = pObject->GetWorldMatrix(); + auto positionStream = pSubMesh->getStreamBySemantic(SEMANTIC_POSITION); + ASSERT(positionStream != pSubMesh->streamBuffers().end()); + auto subIndexView = indexStream.GetView(); + auto subPositionView = positionStream->GetStructuredView(); - hplDelete(pTransformedVtxBuffer); + for (size_t i = 0; i < indexStream.m_numberElements; i++) { + indexView.Write(indexElementIdx++,VertexElementIdx + subIndexView.Get(i)); + } + for (size_t i = 0; i < positionStream->m_numberElements; i++) { + float3 localPos = subPositionView.Get(i); + cVector3f outputPos = cMath::MatrixMul(worldTransform, cVector3f(localPos.x, localPos.y, localPos.z)); + positionView.Write(VertexElementIdx++, float3(outputPos.x, outputPos.y, outputPos.z)); + } + } + if(VertexElementIdx<=0 || indexElementIdx<=0) + { + return; } - - targetVertexBuffer->Compile(0); - /////////////////////////////////////////// //Create the mesh physics body iRenderable *pFirstObject = avObjects[alFirstIdx].mpObject; - iCollideShape *pShape = mpCurrentPhysicsWorld->CreateMeshShape(targetVertexBuffer); - hplDelete(targetVertexBuffer); + iCollideShape *pShape = mpCurrentPhysicsWorld->CreateMeshShape(indexElementIdx, 0, 0, + indexView, positionView); iPhysicsBody *pBody = mpCurrentPhysicsWorld->CreateBody(sName,pShape); pBody->SetMass(0);