aboutsummaryrefslogtreecommitdiff
path: root/NvBlast/sdk/extensions/physx/source/physics/NvBlastExtPxAssetImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'NvBlast/sdk/extensions/physx/source/physics/NvBlastExtPxAssetImpl.cpp')
-rw-r--r--NvBlast/sdk/extensions/physx/source/physics/NvBlastExtPxAssetImpl.cpp315
1 files changed, 315 insertions, 0 deletions
diff --git a/NvBlast/sdk/extensions/physx/source/physics/NvBlastExtPxAssetImpl.cpp b/NvBlast/sdk/extensions/physx/source/physics/NvBlastExtPxAssetImpl.cpp
new file mode 100644
index 0000000..a0f75fc
--- /dev/null
+++ b/NvBlast/sdk/extensions/physx/source/physics/NvBlastExtPxAssetImpl.cpp
@@ -0,0 +1,315 @@
+/*
+* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "NvBlastExtPxAssetImpl.h"
+#include "NvBlastExtHashMap.h"
+
+#include "NvBlastAssert.h"
+#include "NvBlastIndexFns.h"
+
+#include "NvBlastTkAsset.h"
+
+#include "PxIO.h"
+#include "PxPhysics.h"
+#include "PxFileBuf.h"
+#include "cooking/PxCooking.h"
+
+#include <algorithm>
+
+namespace Nv
+{
+namespace Blast
+{
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Helpers/Wrappers
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class FileBufToPxInputStream final : public PxInputStream
+{
+public:
+ FileBufToPxInputStream(PxFileBuf& filebuf) : m_filebuf(filebuf) {}
+
+ virtual uint32_t read(void* dest, uint32_t count)
+ {
+ return m_filebuf.read(dest, count);
+ }
+
+private:
+ FileBufToPxInputStream& operator=(const FileBufToPxInputStream&);
+
+ PxFileBuf& m_filebuf;
+};
+
+
+class FileBufToPxOutputStream final : public PxOutputStream
+{
+public:
+ FileBufToPxOutputStream(PxFileBuf& filebuf) : m_filebuf(filebuf) {}
+
+ virtual uint32_t write(const void* src, uint32_t count) override
+ {
+ return m_filebuf.write(src, count);
+ }
+
+private:
+ FileBufToPxOutputStream& operator=(const FileBufToPxOutputStream&);
+
+ PxFileBuf& m_filebuf;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// ExtPxAssetImpl Implementation
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ExtPxAssetImpl::ExtPxAssetImpl(const ExtPxAssetDesc& desc, TkFramework& framework)
+{
+ m_tkAsset = framework.createAsset(desc);
+
+ // count subchunks and reserve memory
+ uint32_t subchunkCount = 0;
+ for (uint32_t i = 0; i < desc.chunkCount; ++i)
+ {
+ const auto& chunk = desc.pxChunks[i];
+ subchunkCount += static_cast<uint32_t>(chunk.subchunkCount);
+ }
+ m_subchunks.reserve(subchunkCount);
+
+ // fill chunks and subchunks
+ m_chunks.resize(desc.chunkCount);
+ for (uint32_t i = 0; i < desc.chunkCount; ++i)
+ {
+ const auto& chunk = desc.pxChunks[i];
+ m_chunks[i].isStatic = chunk.isStatic;
+ m_chunks[i].firstSubchunkIndex = m_subchunks.size();
+ m_chunks[i].subchunkCount = chunk.subchunkCount;
+ for (uint32_t k = 0; k < chunk.subchunkCount; ++k)
+ {
+ ExtPxSubchunk subchunk =
+ {
+ chunk.subchunks[k].transform,
+ chunk.subchunks[k].geometry
+ };
+ m_subchunks.pushBack(subchunk);
+ }
+ }
+}
+
+ExtPxAssetImpl::ExtPxAssetImpl(TkAsset* tkAsset):
+ m_tkAsset(tkAsset)
+{
+
+}
+
+ExtPxAssetImpl::~ExtPxAssetImpl()
+{
+ if (m_tkAsset)
+ {
+ m_tkAsset->release();
+ }
+}
+
+void ExtPxAssetImpl::release()
+{
+ NVBLASTEXT_DELETE(this, ExtPxAssetImpl);
+}
+
+NV_INLINE bool serializeConvexMesh(const PxConvexMesh& convexMesh, PxCooking& cooking, ExtArray<uint32_t>::type& indicesScratch,
+ ExtArray<PxHullPolygon>::type hullPolygonsScratch, PxOutputStream& stream)
+{
+ PxConvexMeshDesc desc;
+ desc.points.data = convexMesh.getVertices();
+ desc.points.count = convexMesh.getNbVertices();
+ desc.points.stride = sizeof(PxVec3);
+
+ hullPolygonsScratch.resize(convexMesh.getNbPolygons());
+
+ uint32_t indexCount = 0;
+ for (uint32_t i = 0; i < convexMesh.getNbPolygons(); i++)
+ {
+ PxHullPolygon polygon;
+ convexMesh.getPolygonData(i, polygon);
+ if (polygon.mNbVerts)
+ {
+ indexCount = std::max<uint32_t>(indexCount, polygon.mIndexBase + polygon.mNbVerts);
+ }
+ }
+ indicesScratch.resize(indexCount);
+
+ for (uint32_t i = 0; i < convexMesh.getNbPolygons(); i++)
+ {
+ PxHullPolygon polygon;
+ convexMesh.getPolygonData(i, polygon);
+ for (uint32_t j = 0; j < polygon.mNbVerts; j++)
+ {
+ indicesScratch[polygon.mIndexBase + j] = convexMesh.getIndexBuffer()[polygon.mIndexBase + j];
+ }
+
+ hullPolygonsScratch[i] = polygon;
+ }
+
+ desc.indices.count = indexCount;
+ desc.indices.data = indicesScratch.begin();
+ desc.indices.stride = sizeof(uint32_t);
+
+ desc.polygons.count = convexMesh.getNbPolygons();
+ desc.polygons.data = hullPolygonsScratch.begin();
+ desc.polygons.stride = sizeof(PxHullPolygon);
+
+ return cooking.cookConvexMesh(desc, stream);
+}
+
+bool ExtPxAssetImpl::serialize(PxFileBuf& stream, PxCooking& cooking) const
+{
+ // Header data
+ stream.storeDword(ClassID);
+ stream.storeDword(Version::Current);
+
+ m_tkAsset->serialize(stream);
+
+ // Chunks
+ const uint32_t chunkCount = m_tkAsset->getChunkCount();
+ for (uint32_t i = 0; i < chunkCount; ++i)
+ {
+ const ExtPxChunk& chunk = m_chunks[i];
+ stream.storeDword(chunk.firstSubchunkIndex);
+ stream.storeDword(chunk.subchunkCount);
+ stream.storeDword(chunk.isStatic ? 1 : 0);
+ }
+
+ stream.storeDword(m_subchunks.size());
+
+ ExtArray<uint32_t>::type indicesScratch(512);
+ ExtArray<PxHullPolygon>::type hullPolygonsScratch(512);
+ ExtHashMap<PxConvexMesh*, uint32_t>::type convexReuseMap;
+
+ FileBufToPxOutputStream outputStream(stream);
+ for (uint32_t i = 0; i < m_subchunks.size(); ++i)
+ {
+ auto& subchunk = m_subchunks[i];
+
+ // Subchunk transform
+ stream.storeFloat(subchunk.transform.q.x); stream.storeFloat(subchunk.transform.q.y); stream.storeFloat(subchunk.transform.q.z); stream.storeFloat(subchunk.transform.q.w);
+ stream.storeFloat(subchunk.transform.p.x); stream.storeFloat(subchunk.transform.p.y); stream.storeFloat(subchunk.transform.p.z);
+
+ // Subchunk scale
+ stream.storeFloat(subchunk.geometry.scale.scale.x); stream.storeFloat(subchunk.geometry.scale.scale.y); stream.storeFloat(subchunk.geometry.scale.scale.z);
+ stream.storeFloat(subchunk.geometry.scale.rotation.x); stream.storeFloat(subchunk.geometry.scale.rotation.y); stream.storeFloat(subchunk.geometry.scale.rotation.z); stream.storeFloat(subchunk.geometry.scale.rotation.w);
+
+ auto convexMesh = subchunk.geometry.convexMesh;
+ NVBLASTEXT_CHECK_ERROR(convexMesh != nullptr, "ExtPxAssetImpl::serialize: subchunk convexMesh is nullptr.", return false);
+
+ auto entry = convexReuseMap.find(convexMesh);
+ if (entry)
+ {
+ stream.storeDword(entry->second);
+ }
+ else
+ {
+ stream.storeDword(invalidIndex<uint32_t>());
+ if (!serializeConvexMesh(*convexMesh, cooking, indicesScratch, hullPolygonsScratch, outputStream))
+ {
+ NVBLASTEXT_LOG_ERROR("ExtPxAssetImpl::serialize: subchunk convexMesh cooking/serialization failed.");
+ return false;
+ }
+ convexReuseMap[convexMesh] = i;
+ }
+ }
+
+ return true;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// ExtPxAsset Static
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ExtPxAsset* ExtPxAsset::create(const ExtPxAssetDesc& desc, TkFramework& framework)
+{
+ ExtPxAssetImpl* asset = NVBLASTEXT_NEW(ExtPxAssetImpl)(desc, framework);
+ return asset;
+}
+
+
+Nv::Blast::ExtPxAsset* ExtPxAsset::create(TkAsset* tkAsset)
+{
+ ExtPxAssetImpl* asset = NVBLASTEXT_NEW(ExtPxAssetImpl)(tkAsset);
+
+ // Don't populate the chunks or subchunks!
+
+ return asset;
+}
+
+ExtPxAsset* ExtPxAsset::deserialize(PxFileBuf& stream, TkFramework& framework, PxPhysics& physics)
+{
+ ExtPxAssetImpl::DataHeader header;
+ header.dataType = stream.readDword();
+ header.version = stream.readDword();
+ NVBLASTEXT_CHECK_ERROR(header.dataType == ExtPxAssetImpl::ClassID, "ExtPxAsset::deserialize: wrong data type in filebuf stream.", return nullptr);
+ NVBLASTEXT_CHECK_ERROR(header.version == ExtPxAssetImpl::Version::Current, "ExtPxAsset::deserialize: wrong data version in filebuf stream.", return nullptr);
+
+ TkAsset* tkAsset = static_cast<TkAsset*>(framework.deserialize(stream));
+ NVBLASTEXT_CHECK_ERROR(tkAsset != nullptr, "ExtPxAsset::deserialize: failed to deserialize TkAsset.", return nullptr);
+
+ ExtPxAssetImpl* asset = NVBLASTEXT_NEW(ExtPxAssetImpl)(tkAsset);
+
+ asset->m_chunks.resize(asset->m_tkAsset->getChunkCount());
+
+ const uint32_t chunkCount = asset->m_chunks.size();
+ for (uint32_t i = 0; i < chunkCount; ++i)
+ {
+ ExtPxChunk& chunk = asset->m_chunks[i];
+ chunk.firstSubchunkIndex = stream.readDword();
+ chunk.subchunkCount = stream.readDword();
+ chunk.isStatic = 0 != stream.readDword();
+ }
+
+ const uint32_t subchunkCount = stream.readDword();
+ asset->m_subchunks.resize(subchunkCount);
+
+ FileBufToPxInputStream inputStream(stream);
+ for (uint32_t i = 0; i < asset->m_subchunks.size(); ++i)
+ {
+ ExtPxSubchunk& subChunk = asset->m_subchunks[i];
+
+ // Subchunk transform
+ subChunk.transform.q.x = stream.readFloat(); subChunk.transform.q.y = stream.readFloat(); subChunk.transform.q.z = stream.readFloat(); subChunk.transform.q.w = stream.readFloat();
+ subChunk.transform.p.x = stream.readFloat(); subChunk.transform.p.y = stream.readFloat(); subChunk.transform.p.z = stream.readFloat();
+
+ // Subchunk scale
+ subChunk.geometry.scale.scale.x = stream.readFloat(); subChunk.geometry.scale.scale.y = stream.readFloat(); subChunk.geometry.scale.scale.z = stream.readFloat();
+ subChunk.geometry.scale.rotation.x = stream.readFloat(); subChunk.geometry.scale.rotation.y = stream.readFloat(); subChunk.geometry.scale.rotation.z = stream.readFloat(); subChunk.geometry.scale.rotation.w = stream.readFloat();
+
+ const uint32_t convexReuseIndex = stream.readDword();
+ if (isInvalidIndex(convexReuseIndex))
+ {
+ subChunk.geometry.convexMesh = physics.createConvexMesh(inputStream);
+ }
+ else
+ {
+ NVBLAST_ASSERT_WITH_MESSAGE(convexReuseIndex < i, "ExtPxAsset::deserialize: wrong convexReuseIndex.");
+ subChunk.geometry.convexMesh = asset->m_subchunks[convexReuseIndex].geometry.convexMesh;
+ }
+ if (!subChunk.geometry.convexMesh)
+ {
+ NVBLASTEXT_LOG_ERROR("ExtPxAsset::deserialize: failed to deserialize convex mesh.");
+ asset->release();
+ return nullptr;
+ }
+ }
+
+ return asset;
+}
+
+
+} // namespace Blast
+} // namespace Nv