diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/PhysXExtensions/src | |
| download | physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip | |
Initial commit:
PhysX 3.4.0 Update @ 21294896
APEX 1.4.0 Update @ 21275617
[CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/PhysXExtensions/src')
101 files changed, 26136 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtBroadPhase.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtBroadPhase.cpp new file mode 100644 index 00000000..0e079323 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtBroadPhase.cpp @@ -0,0 +1,74 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "foundation/PxBounds3.h" +#include "PxBroadPhaseExt.h" +#include "PsFoundation.h" +#include "CmPhysXCommon.h" + +using namespace physx; + +PxU32 PxBroadPhaseExt::createRegionsFromWorldBounds(PxBounds3* regions, const PxBounds3& globalBounds, PxU32 nbSubdiv, PxU32 upAxis) +{ + PX_CHECK_MSG(globalBounds.isValid(), "PxBroadPhaseExt::createRegionsFromWorldBounds(): invalid bounds provided!"); + PX_CHECK_MSG(upAxis<3, "PxBroadPhaseExt::createRegionsFromWorldBounds(): invalid up-axis provided!"); + + const PxVec3& min = globalBounds.minimum; + const PxVec3& max = globalBounds.maximum; + const float dx = (max.x - min.x) / float(nbSubdiv); + const float dy = (max.y - min.y) / float(nbSubdiv); + const float dz = (max.z - min.z) / float(nbSubdiv); + PxU32 nbRegions = 0; + PxVec3 currentMin, currentMax; + for(PxU32 j=0;j<nbSubdiv;j++) + { + for(PxU32 i=0;i<nbSubdiv;i++) + { + if(upAxis==0) + { + currentMin = PxVec3(min.x, min.y + dy * float(i), min.z + dz * float(j)); + currentMax = PxVec3(max.x, min.y + dy * float(i+1), min.z + dz * float(j+1)); + } + else if(upAxis==1) + { + currentMin = PxVec3(min.x + dx * float(i), min.y, min.z + dz * float(j)); + currentMax = PxVec3(min.x + dx * float(i+1), max.y, min.z + dz * float(j+1)); + } + else if(upAxis==2) + { + currentMin = PxVec3(min.x + dx * float(i), min.y + dy * float(j), min.z); + currentMax = PxVec3(min.x + dx * float(i+1), min.y + dy * float(j+1), max.z); + } + + regions[nbRegions++] = PxBounds3(currentMin, currentMax); + } + } + return nbRegions; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtClothFabricCooker.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtClothFabricCooker.cpp new file mode 100644 index 00000000..f59f26b2 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtClothFabricCooker.cpp @@ -0,0 +1,648 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PxPhysXConfig.h" +#if PX_USE_CLOTH_API + +#include "foundation/PxVec4.h" +#include "foundation/PxIO.h" +#include "foundation/PxStrideIterator.h" +#include "extensions/PxClothFabricCooker.h" +#include "extensions/PxClothTetherCooker.h" +#include "PxPhysics.h" +#include "PsFoundation.h" +#include "PsArray.h" +#include "PsHashMap.h" +#include "PsSort.h" + +using namespace physx; + +struct physx::PxFabricCookerImpl +{ + bool cook(const PxClothMeshDesc& desc, PxVec3 gravity, bool useGeodesicTether); + + PxClothFabricDesc getDescriptor() const; + void save(PxOutputStream& stream, bool platformMismatch) const; + +public: + PxU32 mNumParticles; + + shdfnd::Array<PxClothFabricPhase> mPhases; + shdfnd::Array<PxU32> mSets; // with 0 prefix + shdfnd::Array<PxReal> mRestvalues; + shdfnd::Array<PxU32> mIndices; + + shdfnd::Array<PxU32> mTetherAnchors; + shdfnd::Array<PxReal> mTetherLengths; + + shdfnd::Array<PxU32> mTriangles; +}; + +PxClothFabricCooker::PxClothFabricCooker(const PxClothMeshDesc& desc, const PxVec3& gravity, bool useGeodesicTether) +: mImpl(new PxFabricCookerImpl()) +{ + mImpl->cook(desc, gravity, useGeodesicTether); +} + +PxClothFabricCooker::~PxClothFabricCooker() +{ + delete mImpl; +} + +PxClothFabricDesc PxClothFabricCooker::getDescriptor() const +{ + return mImpl->getDescriptor(); +} + +void PxClothFabricCooker::save(PxOutputStream& stream, bool platformMismatch) const +{ + mImpl->save(stream, platformMismatch); +} + + +PxClothFabric* physx::PxClothFabricCreate( PxPhysics& physics, const PxClothMeshDesc& desc, const PxVec3& gravity, bool useGeodesicTether ) +{ + PxFabricCookerImpl impl; + + if(!impl.cook(desc, gravity, useGeodesicTether)) + return 0; + + return physics.createClothFabric(impl.getDescriptor()); +} + +namespace +{ + // calculate the inclusive prefix sum, equivalent of std::partial_sum + template <typename T> + void prefixSum(const T* first, const T* last, T* dest) + { + if (first != last) + { + *(dest++) = *(first++); + for (; first != last; ++first, ++dest) + *dest = *(dest-1) + *first; + } + } + + template <typename T> + void gatherAdjacencies(shdfnd::Array<PxU32>& valency, shdfnd::Array<PxU32>& adjacencies, + const PxBoundedData& triangles, const PxBoundedData& quads) + { + // count number of edges per vertex + PxStrideIterator<const T> tIt, qIt; + tIt = PxMakeIterator(reinterpret_cast<const T*>(triangles.data), triangles.stride); + for(PxU32 i=0; i<triangles.count; ++i, ++tIt, ++qIt) + { + for(PxU32 j=0; j<3; ++j) + valency[tIt.ptr()[j]] += 2; + } + qIt = PxMakeIterator(reinterpret_cast<const T*>(quads.data), quads.stride); + for(PxU32 i=0; i<quads.count; ++i, ++tIt, ++qIt) + { + for(PxU32 j=0; j<4; ++j) + valency[qIt.ptr()[j]] += 2; + } + + prefixSum(valency.begin(), valency.end(), valency.begin()); + adjacencies.resize(valency.back()); + + // gather adjacent vertices + tIt = PxMakeIterator(reinterpret_cast<const T*>(triangles.data), triangles.stride); + for(PxU32 i=0; i<triangles.count; ++i, ++tIt) + { + for(PxU32 j=0; j<3; ++j) + { + adjacencies[--valency[tIt.ptr()[j]]] = tIt.ptr()[(j+1)%3]; + adjacencies[--valency[tIt.ptr()[j]]] = tIt.ptr()[(j+2)%3]; + } + } + qIt = PxMakeIterator(reinterpret_cast<const T*>(quads.data), quads.stride); + for(PxU32 i=0; i<quads.count; ++i, ++qIt) + { + for(PxU32 j=0; j<4; ++j) + { + adjacencies[--valency[qIt.ptr()[j]]] = qIt.ptr()[(j+1)%4]; + adjacencies[--valency[qIt.ptr()[j]]] = qIt.ptr()[(j+3)%4]; + } + } + } + + template <typename T> + void gatherTriangles(shdfnd::Array<PxU32>& indices, const PxBoundedData& triangles, const PxBoundedData& quads) + { + indices.reserve(triangles.count * 3 + quads.count * 6); + + PxStrideIterator<const T> tIt, qIt; + tIt = PxMakeIterator(reinterpret_cast<const T*>(triangles.data), triangles.stride); + for (PxU32 i = 0; i<triangles.count; ++i, ++tIt, ++qIt) + { + for (PxU32 j = 0; j<3; ++j) + indices.pushBack(tIt.ptr()[j]); + } + qIt = PxMakeIterator(reinterpret_cast<const T*>(quads.data), quads.stride); + for (PxU32 i = 0; i<quads.count; ++i, ++tIt, ++qIt) + { + indices.pushBack(qIt.ptr()[0]); + indices.pushBack(qIt.ptr()[1]); + indices.pushBack(qIt.ptr()[2]); + indices.pushBack(qIt.ptr()[2]); + indices.pushBack(qIt.ptr()[3]); + indices.pushBack(qIt.ptr()[0]); + } + } + + + struct Edge + { + Edge() : mStretching(0.0f), mBending(0.0f), mShearing(0.0f) {} + + void classify() + { + mStretching += 0.1f; + } + + // classify v0-v2 edge based on alternative v0-v1-v2 path + void classify(const PxVec4& v0, const PxVec4& v1, const PxVec4& v2) + { + const PxVec3& p0 = reinterpret_cast<const PxVec3&>(v0); + const PxVec3& p1 = reinterpret_cast<const PxVec3&>(v1); + const PxVec3& p2 = reinterpret_cast<const PxVec3&>(v2); + + PxReal area = (p1-p0).cross(p2-p1).magnitude(); + // triangle height / base length + // 1.0 = quad edge, 0.2 = quad diagonal + quad edge, + PxReal ratio = area / (p2-p0).magnitudeSquared(); + + // 0.5 = quad diagonal + mShearing += PxMax(0.0f, 0.15f - fabsf(0.45f - ratio)); + // 0.0 = collinear points + mBending += PxMax(0.0f, 0.1f - ratio) * 3; + } + + PxReal mStretching; + PxReal mBending; + PxReal mShearing; + }; + + typedef shdfnd::Pair<PxU32, PxU32> Pair; + typedef shdfnd::Pair<Pair, PxClothFabricPhaseType::Enum> Entry; + + // maintain heap status after elements have been pushed (heapify) + template<typename T> + void pushHeap(shdfnd::Array<T> &heap, const T &value) + { + heap.pushBack(value); + T* begin = heap.begin(); + T* end = heap.end(); + + if (end <= begin) + return; + + PxU32 current = PxU32(end - begin) - 1; + while (current > 0) + { + const PxU32 parent = (current - 1) / 2; + if (!(begin[parent] < begin[current])) + break; + + shdfnd::swap(begin[parent], begin[current]); + current = parent; + } + } + + // pop one element from the heap + template<typename T> + T popHeap(shdfnd::Array<T> &heap) + { + T* begin = heap.begin(); + T* end = heap.end(); + + shdfnd::swap(begin[0], end[-1]); // exchange elements + + // shift down + end--; + + PxU32 current = 0; + while (begin + (current * 2 + 1) < end) + { + PxU32 child = current * 2 + 1; + if (begin + child + 1 < end && begin[child] < begin[child + 1]) + ++child; + + if (!(begin[current] < begin[child])) + break; + + shdfnd::swap(begin[current], begin[child]); + current = child; + } + + return heap.popBack(); + } + + // --------------------------------------------------------------------------------------- + // Heap element to sort constraint based on graph color count + struct ConstraintGraphColorCount + { + ConstraintGraphColorCount(PxU32 cid, PxU32 count) + : constraint(cid), colorCount(count) {} + + PxU32 constraint; + PxU32 colorCount; + + bool operator < (const ConstraintGraphColorCount& c) const + { + return colorCount < c.colorCount; + } + }; + + struct ConstraintSorter + { + public: + + ConstraintSorter(PxU32* constraints_) : constraints(constraints_) {} + + bool operator()(PxU32 i, PxU32 j) const + { + PxU32 ci = i*2; + PxU32 cj = j*2; + + if (constraints[ci] == constraints[cj]) + return constraints[ci+1] < constraints[cj+1]; + else + return constraints[ci] < constraints[cj]; + } + + PxU32* constraints; + }; + +} // anonymous namespace + +bool PxFabricCookerImpl::cook(const PxClothMeshDesc& desc, PxVec3 gravity, bool useGeodesicTether) +{ + if(!desc.isValid()) + { + shdfnd::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "PxFabricCookerImpl::cook: desc.isValid() failed!"); + return false; + } + + gravity = gravity.getNormalized(); + + mNumParticles = desc.points.count; + + // assemble points + shdfnd::Array<PxVec4> particles; + particles.reserve(mNumParticles); + PxStrideIterator<const PxVec3> pIt(reinterpret_cast<const PxVec3*>(desc.points.data), desc.points.stride); + PxStrideIterator<const PxReal> wIt(reinterpret_cast<const PxReal*>(desc.invMasses.data), desc.invMasses.stride); + for(PxU32 i=0; i<mNumParticles; ++i) + particles.pushBack(PxVec4(*pIt++, wIt.ptr() ? *wIt++ : 1.0f)); + + // build adjacent vertex list + shdfnd::Array<PxU32> valency(mNumParticles+1, 0); + shdfnd::Array<PxU32> adjacencies; + if (desc.flags & PxMeshFlag::e16_BIT_INDICES) + { + gatherTriangles<PxU16>(mTriangles, desc.triangles, desc.quads); + gatherAdjacencies<PxU16>(valency, adjacencies, desc.triangles, desc.quads); + } + else + { + gatherTriangles<PxU32>(mTriangles, desc.triangles, desc.quads); + gatherAdjacencies<PxU32>(valency, adjacencies, desc.triangles, desc.quads); + } + + // build unique neighbors from adjacencies + shdfnd::Array<PxU32> mark(valency.size(), 0); + shdfnd::Array<PxU32> neighbors; neighbors.reserve(adjacencies.size()); + for(PxU32 i=1, j=0; i<valency.size(); ++i) + { + for(; j<valency[i]; ++j) + { + PxU32 k = adjacencies[j]; + if(mark[k] != i) + { + mark[k] = i; + neighbors.pushBack(k); + } + } + valency[i] = neighbors.size(); + } + + // build map of unique edges and classify + shdfnd::HashMap<Pair, Edge> edges; + for(PxU32 i=0; i<mNumParticles; ++i) + { + PxReal wi = particles[i].w; + // iterate all neighbors + PxU32 jlast = valency[i+1]; + for(PxU32 j=valency[i]; j<jlast; ++j) + { + // add 1-ring edge + PxU32 m = neighbors[j]; + if(wi + particles[m].w > 0.0f) + edges[Pair(PxMin(i, m), PxMax(i, m))].classify(); + + // iterate all neighbors of neighbor + PxU32 klast = valency[m+1]; + for(PxU32 k=valency[m]; k<klast; ++k) + { + PxU32 n = neighbors[k]; + if(n != i && wi + particles[n].w > 0.0f) + { + // add 2-ring edge + edges[Pair(PxMin(i, n), PxMax(i, n))].classify( + particles[i], particles[m], particles[n]); + } + } + } + } + + // copy classified edges to constraints array + // build histogram of constraints per vertex + shdfnd::Array<Entry> constraints; + constraints.reserve(edges.size()); + valency.resize(0); valency.resize(mNumParticles+1, 0); + + const PxReal sqrtHalf = PxSqrt(0.4f); + for(shdfnd::HashMap<Pair, Edge>::Iterator eIt = edges.getIterator(); !eIt.done(); ++eIt) + { + const Edge& edge = eIt->second; + const Pair& pair = eIt->first; + if((edge.mStretching + edge.mBending + edge.mShearing) > 0.0f) + { + PxClothFabricPhaseType::Enum type = PxClothFabricPhaseType::eINVALID; + if(edge.mBending > PxMax(edge.mStretching, edge.mShearing)) + type = PxClothFabricPhaseType::eBENDING; + else if(edge.mShearing > PxMax(edge.mStretching, edge.mBending)) + type = PxClothFabricPhaseType::eSHEARING; + else + { + PxVec4 diff = particles[pair.first]-particles[pair.second]; + PxReal dot = gravity.dot(reinterpret_cast<const PxVec3&>(diff).getNormalized()); + type = fabsf(dot) < sqrtHalf ? PxClothFabricPhaseType::eHORIZONTAL : PxClothFabricPhaseType::eVERTICAL; + } + ++valency[pair.first]; + ++valency[pair.second]; + constraints.pushBack(Entry(pair, type)); + } + } + + prefixSum(valency.begin(), valency.end(), valency.begin()); + + PxU32 numConstraints = constraints.size(); + + // build adjacent constraint list + adjacencies.resize(0); adjacencies.resize(valency.back(), 0); + for(PxU32 i=0; i<numConstraints; ++i) + { + adjacencies[--valency[constraints[i].first.first]] = i; + adjacencies[--valency[constraints[i].first.second]] = i; + } + + shdfnd::Array<PxU32>::ConstIterator aFirst = adjacencies.begin(); + shdfnd::Array<PxU32> colors(numConstraints, numConstraints); // constraint -> color, initialily not colored + mark.resize(0); mark.resize(numConstraints+1, PX_MAX_U32); // color -> constraint index + shdfnd::Array<PxU32> adjColorCount(numConstraints, 0); // # of neighbors that are already colored + + shdfnd::Array<ConstraintGraphColorCount> constraintHeap; + constraintHeap.reserve(numConstraints); // set of constraints to color (added in edge distance order) + + // Do graph coloring based on edge distance. + // For each constraint, we add its uncolored neighbors to the heap + // ,and we pick the constraint with most colored neighbors from the heap. + for(;;) + { + PxU32 constraint = 0; + while ( (constraint < numConstraints) && (colors[constraint] != numConstraints)) + constraint++; // start with the first uncolored constraint + + if (constraint >= numConstraints) + break; + + constraintHeap.clear(); + pushHeap(constraintHeap, ConstraintGraphColorCount(constraint, adjColorCount[constraint])); + PxClothFabricPhaseType::Enum type = constraints[constraint].second; + + while (!constraintHeap.empty()) + { + ConstraintGraphColorCount heapItem = popHeap(constraintHeap); + constraint = heapItem.constraint; + if (colors[constraint] != numConstraints) + continue; // skip if already colored + + const Pair& pair = constraints[constraint].first; + for(PxU32 j=0; j<2; ++j) + { + PxU32 index = j ? pair.first : pair.second; + if(particles[index].w == 0.0f) + continue; // don't mark adjacent particles if attached + + for(shdfnd::Array<PxU32>::ConstIterator aIt = aFirst + valency[index], aEnd = aFirst + valency[index+1]; aIt != aEnd; ++aIt) + { + PxU32 adjacentConstraint = *aIt; + if ((constraints[adjacentConstraint].second != type) || (adjacentConstraint == constraint)) + continue; + + mark[colors[adjacentConstraint]] = constraint; + ++adjColorCount[adjacentConstraint]; + pushHeap(constraintHeap, ConstraintGraphColorCount(adjacentConstraint, adjColorCount[adjacentConstraint])); + } + } + + // find smallest color with matching type + PxU32 color = 0; + while((color < mPhases.size() && mPhases[color].phaseType != type) || mark[color] == constraint) + ++color; + + // create a new color set + if(color == mPhases.size()) + { + PxClothFabricPhase phase(type, mPhases.size()); + mPhases.pushBack(phase); + mSets.pushBack(0); + } + + colors[constraint] = color; + ++mSets[color]; + } + } + +#if 0 // PX_DEBUG + printf("set[%u] = ", mSets.size()); + for(PxU32 i=0; i<mSets.size(); ++i) + printf("%u ", mSets[i]); +#endif + + prefixSum(mSets.begin(), mSets.end(), mSets.begin()); + +#if 0 // PX_DEBUG + printf(" = %u\n", mSets.back()); +#endif + + // write indices and rest lengths + // convert mSets to exclusive sum + PxU32 back = mSets.back(); + mSets.pushBack(back); + mIndices.resize(numConstraints*2); + mRestvalues.resize(numConstraints); + for(PxU32 i=0; i<numConstraints; ++i) + { + PxU32 first = constraints[i].first.first; + PxU32 second = constraints[i].first.second; + + PxU32 index = --mSets[colors[i]]; + + mIndices[2*index ] = first; + mIndices[2*index+1] = second; + + PxVec4 diff = particles[second] - particles[first]; + mRestvalues[index] = reinterpret_cast< + const PxVec3&>(diff).magnitude(); + } + + // reorder constraints and rest values for more efficient cache access (linear) + shdfnd::Array<PxU32> newIndices(mIndices.size()); + shdfnd::Array<PxF32> newRestValues(mRestvalues.size()); + + // sort each constraint set in vertex order + for (PxU32 i=0; i < mSets.size()-1; ++i) + { + // create a re-ordering list + shdfnd::Array<PxU32> reorder(mSets[i+1]-mSets[i]); + + for (PxU32 r=0; r < reorder.size(); ++r) + reorder[r] = r; + + const PxU32 indicesOffset = mSets[i]*2; + const PxU32 restOffset = mSets[i]; + + ConstraintSorter predicate(&mIndices[indicesOffset]); + shdfnd::sort(&reorder[0], reorder.size(), predicate); + + for (PxU32 r=0; r < reorder.size(); ++r) + { + newIndices[indicesOffset + r*2] = mIndices[indicesOffset + reorder[r]*2]; + newIndices[indicesOffset + r*2+1] = mIndices[indicesOffset + reorder[r]*2+1]; + newRestValues[restOffset + r] = mRestvalues[restOffset + reorder[r]]; + } + } + + mIndices = newIndices; + mRestvalues = newRestValues; + + PX_ASSERT(mIndices.size() == mRestvalues.size()*2); + PX_ASSERT(mRestvalues.size() == mSets.back()); + +#if 0 // PX_DEBUG + for (PxU32 i = 1; i < mSets.size(); i++) + { + PxClothFabricPhase phase = mPhases[i-1]; + printf("%d : type %d, size %d\n", + i-1, phase.phaseType, mSets[i] - mSets[i-1]); + } +#endif + + if (useGeodesicTether) + { + PxClothGeodesicTetherCooker tetherCooker(desc); + if (tetherCooker.getCookerStatus() == 0) + { + PxU32 numTethersPerParticle = tetherCooker.getNbTethersPerParticle(); + PxU32 tetherSize = mNumParticles * numTethersPerParticle; + mTetherAnchors.resize(tetherSize); + mTetherLengths.resize(tetherSize); + tetherCooker.getTetherData(mTetherAnchors.begin(), mTetherLengths.begin()); + } + else + useGeodesicTether = false; + } + + if (!useGeodesicTether) + { + PxClothSimpleTetherCooker tetherCooker(desc); + mTetherAnchors.resize(mNumParticles); + mTetherLengths.resize(mNumParticles); + tetherCooker.getTetherData(mTetherAnchors.begin(), mTetherLengths.begin()); + } + + return true; +} + +physx::PxClothFabricDesc physx::PxFabricCookerImpl::getDescriptor() const +{ + PxClothFabricDesc result; + + result.nbParticles = mNumParticles; + result.nbPhases = mPhases.size(); + result.phases = mPhases.begin(); + result.nbSets = mSets.size()-1; + result.sets = mSets.begin()+1; + result.restvalues = mRestvalues.begin(); + result.indices = mIndices.begin(); + result.nbTethers = mTetherAnchors.size(); + result.tetherAnchors = mTetherAnchors.begin(); + result.tetherLengths = mTetherLengths.begin(); + result.nbTriangles = mTriangles.size() / 3; + result.triangles = mTriangles.begin(); + + return result; +} + +void physx::PxFabricCookerImpl::save( PxOutputStream& stream, bool /*platformMismatch*/ ) const +{ + // version 1 is equivalent to 0x030300 and 0x030301 (PX_PHYSICS_VERSION of 3.3.0 and 3.3.1). + // If the stream format changes, the loader code in ScClothFabricCore.cpp + // and the version number need to change too. + PxU32 version = 1; + stream.write(&version, sizeof(PxU32)); + + PxClothFabricDesc desc = getDescriptor(); + + // write explicit sizes, others are implicit + stream.write(&mNumParticles, sizeof(PxU32)); + stream.write(&desc.nbPhases, sizeof(PxU32)); + stream.write(&desc.nbSets, sizeof(PxU32)); + stream.write(&desc.nbTethers, sizeof(PxU32)); + + PxU32 nbConstraints = desc.sets[desc.nbSets-1]; + + // write actual data + PX_COMPILE_TIME_ASSERT(sizeof(PxClothFabricPhaseType::Enum) == sizeof(PxU32)); + stream.write(desc.phases, desc.nbPhases*sizeof(PxClothFabricPhase)); + stream.write(desc.sets, desc.nbSets*sizeof(PxU32)); + + stream.write(desc.restvalues, nbConstraints*sizeof(PxReal)); + stream.write(desc.indices, nbConstraints*2*sizeof(PxU32)); + + stream.write(desc.tetherAnchors, desc.nbTethers*sizeof(PxU32)); + stream.write(desc.tetherLengths, desc.nbTethers*sizeof(PxReal)); +} + +#endif //PX_USE_CLOTH_API diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtClothGeodesicTetherCooker.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtClothGeodesicTetherCooker.cpp new file mode 100644 index 00000000..c4338f53 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtClothGeodesicTetherCooker.cpp @@ -0,0 +1,1022 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PxPhysXConfig.h" +#if PX_USE_CLOTH_API + +#include "foundation/PxVec4.h" +#include "foundation/PxMemory.h" +#include "foundation/PxStrideIterator.h" +#include "extensions/PxClothTetherCooker.h" + +// from shared foundation +#include <PsFoundation.h> +#include <PsSort.h> +#include <Ps.h> +#include <PsMathUtils.h> +#include "PsArray.h" + +using namespace physx; + + +namespace +{ + // calculate the inclusive prefix sum, equivalent of std::partial_sum + template <typename T> + void prefixSum(const T* first, const T* last, T* dest) + { + if (first != last) + { + *(dest++) = *(first++); + for (; first != last; ++first, ++dest) + *dest = *(dest-1) + *first; + } + } + + template <typename T> + void gatherAdjacencies(shdfnd::Array<PxU32>& valency, shdfnd::Array<PxU32>& adjacencies, + const PxBoundedData& triangles, const PxBoundedData& quads) + { + // count number of edges per vertex + PxStrideIterator<const T> tIt, qIt; + tIt = PxMakeIterator(reinterpret_cast<const T*>(triangles.data), triangles.stride); + for(PxU32 i=0; i<triangles.count; ++i, ++tIt, ++qIt) + { + for(PxU32 j=0; j<3; ++j) + valency[tIt.ptr()[j]] += 2; + } + qIt = PxMakeIterator(reinterpret_cast<const T*>(quads.data), quads.stride); + for(PxU32 i=0; i<quads.count; ++i, ++tIt, ++qIt) + { + for(PxU32 j=0; j<4; ++j) + valency[qIt.ptr()[j]] += 2; + } + + prefixSum(valency.begin(), valency.end(), valency.begin()); + adjacencies.resize(valency.back()); + + // gather adjacent vertices + tIt = PxMakeIterator(reinterpret_cast<const T*>(triangles.data), triangles.stride); + for(PxU32 i=0; i<triangles.count; ++i, ++tIt) + { + for(PxU32 j=0; j<3; ++j) + { + adjacencies[--valency[tIt.ptr()[j]]] = tIt.ptr()[(j+1)%3]; + adjacencies[--valency[tIt.ptr()[j]]] = tIt.ptr()[(j+2)%3]; + } + } + qIt = PxMakeIterator(reinterpret_cast<const T*>(quads.data), quads.stride); + for(PxU32 i=0; i<quads.count; ++i, ++qIt) + { + for(PxU32 j=0; j<4; ++j) + { + adjacencies[--valency[qIt.ptr()[j]]] = qIt.ptr()[(j+1)%4]; + adjacencies[--valency[qIt.ptr()[j]]] = qIt.ptr()[(j+3)%4]; + } + } + } + + template <typename T> + void gatherIndices(shdfnd::Array<PxU32>& indices, + const PxBoundedData& triangles, const PxBoundedData& quads) + { + PxStrideIterator<const T> tIt, qIt; + + indices.reserve(triangles.count * 3 + quads.count * 6); + + tIt = PxMakeIterator(reinterpret_cast<const T*>(triangles.data), triangles.stride); + for(PxU32 i=0; i<triangles.count; ++i, ++tIt) + { + indices.pushBack(tIt.ptr()[0]); + indices.pushBack(tIt.ptr()[1]); + indices.pushBack(tIt.ptr()[2]); + } + qIt = PxMakeIterator(reinterpret_cast<const T*>(quads.data), quads.stride); + for(PxU32 i=0; i<quads.count; ++i, ++qIt) + { + indices.pushBack(qIt.ptr()[0]); + indices.pushBack(qIt.ptr()[1]); + indices.pushBack(qIt.ptr()[2]); + indices.pushBack(qIt.ptr()[0]); + indices.pushBack(qIt.ptr()[2]); + indices.pushBack(qIt.ptr()[3]); + } + } + + // maintain heap status after elements have been pushed (heapify) + template<typename T> + void pushHeap(shdfnd::Array<T> &heap, const T &value) + { + heap.pushBack(value); + T* begin = heap.begin(); + T* end = heap.end(); + + if (end <= begin) + return; + + PxU32 current = PxU32(end - begin) - 1; + while (current > 0) + { + const PxU32 parent = (current - 1) / 2; + if (!(begin[parent] < begin[current])) + break; + + shdfnd::swap(begin[parent], begin[current]); + current = parent; + } + } + + // pop one element from the heap + template<typename T> + T popHeap(shdfnd::Array<T> &heap) + { + T* begin = heap.begin(); + T* end = heap.end(); + + shdfnd::swap(begin[0], end[-1]); // exchange elements + + // shift down + end--; + + PxU32 current = 0; + while (begin + (current * 2 + 1) < end) + { + PxU32 child = current * 2 + 1; + if (begin + child + 1 < end && begin[child] < begin[child + 1]) + ++child; + + if (!(begin[current] < begin[child])) + break; + + shdfnd::swap(begin[current], begin[child]); + current = child; + } + + return heap.popBack(); + } + + // --------------------------------------------------------------------------------------- + struct VertexDistanceCount + { + VertexDistanceCount(int vert, float dist, int count) + : vertNr(vert), distance(dist), edgeCount(count) {} + + int vertNr; + float distance; + int edgeCount; + bool operator < (const VertexDistanceCount& v) const + { + return v.distance < distance; + } + }; + + // --------------------------------------------------------------------------------------- + struct PathIntersection + { + PxU32 vertOrTriangle; + PxU32 index; // vertex id or triangle edge id + float s; // only used for edge intersection + float distance; // computed distance + + public: + PathIntersection() {} + + PathIntersection(PxU32 vort, PxU32 in_index, float in_distance, float in_s = 0.0f) + : vertOrTriangle(vort), index(in_index), s(in_s), distance(in_distance) + { + } + }; + + //--------------------------------------------------------------------------------------- + struct VertTriangle + { + VertTriangle(int vert, int triangle) + : mVertIndex(vert), mTriangleIndex(triangle) + { + } + + bool operator<(const VertTriangle &vt) const + { + return mVertIndex == vt.mVertIndex ? + mTriangleIndex < vt.mTriangleIndex : mVertIndex < vt.mVertIndex; + } + + int mVertIndex; + int mTriangleIndex; + }; + + // --------------------------------------------------------------------------------------- + struct MeshEdge + { + MeshEdge(int v0, int v1, int halfEdgeIndex) + : mFromVertIndex(v0), mToVertIndex(v1), mHalfEdgeIndex(halfEdgeIndex) + { + if(mFromVertIndex > mToVertIndex) + shdfnd::swap(mFromVertIndex, mToVertIndex); + } + + bool operator<(const MeshEdge& e) const + { + return mFromVertIndex == e.mFromVertIndex ? + mToVertIndex < e.mToVertIndex : mFromVertIndex < e.mFromVertIndex; + } + + bool operator==(const MeshEdge& e) const + { + return mFromVertIndex == e.mFromVertIndex + && mToVertIndex == e.mToVertIndex; + } + + int mFromVertIndex, mToVertIndex; + int mHalfEdgeIndex; + }; + + // check if the edge is following triangle order or not + bool checkEdgeOrientation(const MeshEdge &e, const shdfnd::Array<PxU32> &indices) + { + int offset0 = e.mHalfEdgeIndex % 3; + int offset1 = (offset0 < 2) ? 1 : -2; + + int v0 = int(indices[PxU32(e.mHalfEdgeIndex)]); + int v1 = int(indices[PxU32(e.mHalfEdgeIndex + offset1)]); + + if ((e.mFromVertIndex == v0) && (e.mToVertIndex == v1)) + return true; + + return false; + } + + // check if two index pairs represent same edge regardless of order. + inline bool checkEdge(int ei0, int ei1, int ej0, int ej1) + { + return ( (ei0 == ej0) && (ei1 == ej1) ) || + ( (ei0 == ej1) && (ei1 == ej0) ); + } + + // compute ray edge intersection + bool intersectRayEdge(const PxVec3 &O, const PxVec3 &D, const PxVec3 &A, const PxVec3 &B, float &s, float &t) + { + // point on edge P = A + s * AB + // point on ray R = o + t * d + // for this two points to intersect, we have + // |AB -d| | s t | = o - A + const float eps = 1e-4; + + PxVec3 OA = O - A; + PxVec3 AB = B - A; + + float a = AB.dot(AB), b = -AB.dot(D); + float c = b, d = D.dot(D); + + float e = AB.dot(OA); + float f = -D.dot(OA); + + float det = a * d - b * c; + if (PxAbs(det) < eps) // coplanar case + return false; + + float inv_det = 1.0f / det; + + s = (d * inv_det) * e + (-b * inv_det) * f; + t = (-c * inv_det) * e + (a * inv_det) * f; + + return true; + } +} + + +struct physx::PxClothGeodesicTetherCookerImpl +{ + + PxClothGeodesicTetherCookerImpl(const PxClothMeshDesc& desc); + + PxU32 getCookerStatus() const; + PxU32 getNbTethersPerParticle() const; + void getTetherData(PxU32* userTetherAnchors, PxReal* userTetherLengths) const; + +public: + // input + const PxClothMeshDesc& mDesc; + + // internal variables + PxU32 mNumParticles; + shdfnd::Array<PxVec3> mVertices; + shdfnd::Array<PxU32> mIndices; + shdfnd::Array<PxU8> mAttached; + shdfnd::Array<PxU32> mFirstVertTriAdj; + shdfnd::Array<PxU32> mVertTriAdjs; + shdfnd::Array<PxU32> mTriNeighbors; // needs changing for non-manifold support + + // error status + PxU32 mCookerStatus; + + // output + shdfnd::Array<PxU32> mTetherAnchors; + shdfnd::Array<PxReal> mTetherLengths; + +protected: + void createTetherData(const PxClothMeshDesc &desc); + int computeVertexIntersection(PxU32 parent, PxU32 src, PathIntersection &path); + int computeEdgeIntersection(PxU32 parent, PxU32 edge, float in_s, PathIntersection &path); + float computeGeodesicDistance(PxU32 i, PxU32 parent, int &errorCode); + PxU32 findTriNeighbors(); + void findVertTriNeighbors(); + +private: + PxClothGeodesicTetherCookerImpl& operator=(const PxClothGeodesicTetherCookerImpl&); +}; + +PxClothGeodesicTetherCooker::PxClothGeodesicTetherCooker(const PxClothMeshDesc& desc) +: mImpl(new PxClothGeodesicTetherCookerImpl(desc)) +{ +} + +PxClothGeodesicTetherCooker::~PxClothGeodesicTetherCooker() +{ + delete mImpl; +} + +PxU32 PxClothGeodesicTetherCooker::getCookerStatus() const +{ + return mImpl->getCookerStatus(); +} + +PxU32 PxClothGeodesicTetherCooker::getNbTethersPerParticle() const +{ + return mImpl->getNbTethersPerParticle(); +} + +void PxClothGeodesicTetherCooker::getTetherData(PxU32* userTetherAnchors, PxReal* userTetherLengths) const +{ + mImpl->getTetherData(userTetherAnchors, userTetherLengths); +} + +/////////////////////////////////////////////////////////////////////////////// +PxClothGeodesicTetherCookerImpl::PxClothGeodesicTetherCookerImpl(const PxClothMeshDesc &desc) + :mDesc(desc), + mCookerStatus(0) +{ + createTetherData(desc); +} + +/////////////////////////////////////////////////////////////////////////////// +void PxClothGeodesicTetherCookerImpl::createTetherData(const PxClothMeshDesc &desc) +{ + mNumParticles = desc.points.count; + + if (!desc.invMasses.data) + return; + + // assemble points + mVertices.resize(mNumParticles); + mAttached.resize(mNumParticles); + PxStrideIterator<const PxVec3> pIt(reinterpret_cast<const PxVec3*>(desc.points.data), desc.points.stride); + PxStrideIterator<const PxReal> wIt(reinterpret_cast<const PxReal*>(desc.invMasses.data), desc.invMasses.stride); + for(PxU32 i=0; i<mNumParticles; ++i) + { + mVertices[i] = *pIt++; + mAttached[i] = PxU8(wIt.ptr() ? (*wIt++ == 0.0f) : 0); + } + + // build triangle indices + if(desc.flags & PxMeshFlag::e16_BIT_INDICES) + gatherIndices<PxU16>(mIndices, desc.triangles, desc.quads); + else + gatherIndices<PxU32>(mIndices, desc.triangles, desc.quads); + + // build vertex-triangle adjacencies + findVertTriNeighbors(); + + // build triangle-triangle adjacencies + mCookerStatus = findTriNeighbors(); + if (mCookerStatus != 0) + return; + + // build adjacent vertex list + shdfnd::Array<PxU32> valency(mNumParticles+1, 0); + shdfnd::Array<PxU32> adjacencies; + if(desc.flags & PxMeshFlag::e16_BIT_INDICES) + gatherAdjacencies<PxU16>(valency, adjacencies, desc.triangles, desc.quads); + else + gatherAdjacencies<PxU32>(valency, adjacencies, desc.triangles, desc.quads); + + // build unique neighbors from adjacencies + shdfnd::Array<PxU32> mark(valency.size(), 0); + shdfnd::Array<PxU32> neighbors; neighbors.reserve(adjacencies.size()); + for(PxU32 i=1, j=0; i<valency.size(); ++i) + { + for(; j<valency[i]; ++j) + { + PxU32 k = adjacencies[j]; + if(mark[k] != i) + { + mark[k] = i; + neighbors.pushBack(k); + } + } + valency[i] = neighbors.size(); + } + + // create islands of attachment points + shdfnd::Array<PxU32> vertexIsland(mNumParticles); + shdfnd::Array<VertexDistanceCount> vertexIslandHeap; + + // put all the attachments in heap + for (PxU32 i = 0; i < mNumParticles; ++i) + { + // we put each attached point with large distance so that + // we can prioritize things that are added during mesh traversal. + vertexIsland[i] = PxU32(-1); + if (mAttached[i]) + vertexIslandHeap.pushBack(VertexDistanceCount(int(i), FLT_MAX, 0)); + } + PxU32 attachedCnt = vertexIslandHeap.size(); + + // no attached vertices + if (vertexIslandHeap.empty()) + return; + + // identify islands of attached vertices + shdfnd::Array<PxU32> islandIndices; + shdfnd::Array<PxU32> islandFirst; + PxU32 islandCnt = 0; + PxU32 islandIndexCnt = 0; + + islandIndices.reserve(attachedCnt); + islandFirst.reserve(attachedCnt+1); + + // while the island heap is not empty + while (!vertexIslandHeap.empty()) + { + // pop vi from heap + VertexDistanceCount vi = popHeap(vertexIslandHeap); + + // new cluster + if (vertexIsland[PxU32(vi.vertNr)] == PxU32(-1)) + { + islandFirst.pushBack(islandIndexCnt++); + vertexIsland[PxU32(vi.vertNr)] = islandCnt++; + vi.distance = 0; + islandIndices.pushBack(PxU32(vi.vertNr)); + } + + // for each adjacent vj that's not visited + const PxU32 begin = PxU32(valency[PxU32(vi.vertNr)]); + const PxU32 end = PxU32(valency[PxU32(vi.vertNr + 1)]); + for (PxU32 j = begin; j < end; ++j) + { + const PxU32 vj = neighbors[j]; + + // do not expand unattached vertices + if (!mAttached[vj]) + continue; + + // already visited + if (vertexIsland[vj] != PxU32(-1)) + continue; + + islandIndices.pushBack(vj); + islandIndexCnt++; + vertexIsland[vj] = vertexIsland[PxU32(vi.vertNr)]; + pushHeap(vertexIslandHeap, VertexDistanceCount(int(vj), vi.distance + 1.0f, 0)); + } + } + + islandFirst.pushBack(islandIndexCnt); + + PX_ASSERT(islandCnt == (islandFirst.size() - 1)); + + ///////////////////////////////////////////////////////// + PxU32 bufferSize = mNumParticles * islandCnt; + PX_ASSERT(bufferSize > 0); + + shdfnd::Array<float> vertexDistanceBuffer(bufferSize, PX_MAX_F32); + shdfnd::Array<PxU32> vertexParentBuffer(bufferSize, 0); + shdfnd::Array<VertexDistanceCount> vertexHeap; + + // now process each island + for (PxU32 i = 0; i < islandCnt; i++) + { + vertexHeap.clear(); + float* vertexDistance = &vertexDistanceBuffer[0] + (i * mNumParticles); + PxU32* vertexParent = &vertexParentBuffer[0] + (i * mNumParticles); + + // initialize parent and distance + for (PxU32 j = 0; j < mNumParticles; ++j) + { + vertexParent[j] = j; + vertexDistance[j] = PX_MAX_F32; + } + + // put all the attached vertices in this island to heap + const PxU32 beginIsland = islandFirst[i]; + const PxU32 endIsland = islandFirst[i+1]; + for (PxU32 j = beginIsland; j < endIsland; j++) + { + PxU32 vj = islandIndices[j]; + vertexDistance[vj] = 0.0f; + vertexHeap.pushBack(VertexDistanceCount(int(vj), 0.0f, 0)); + } + + // no attached vertices in this island (error?) + PX_ASSERT(vertexHeap.empty() == false); + if (vertexHeap.empty()) + continue; + + // while heap is not empty + while (!vertexHeap.empty()) + { + // pop vi from heap + VertexDistanceCount vi = popHeap(vertexHeap); + + // obsolete entry ( we already found better distance) + if (vi.distance > vertexDistance[vi.vertNr]) + continue; + + // for each adjacent vj that's not visited + const PxI32 begin = PxI32(valency[PxU32(vi.vertNr)]); + const PxI32 end = PxI32(valency[PxU32(vi.vertNr + 1)]); + for (PxI32 j = begin; j < end; ++j) + { + const PxI32 vj = PxI32(neighbors[PxU32(j)]); + PxVec3 edge = mVertices[PxU32(vj)] - mVertices[PxU32(vi.vertNr)]; + const PxF32 edgeLength = edge.magnitude(); + float newDistance = vi.distance + edgeLength; + + if (newDistance < vertexDistance[vj]) + { + vertexDistance[vj] = newDistance; + vertexParent[vj] = vertexParent[vi.vertNr]; + + pushHeap(vertexHeap, VertexDistanceCount(vj, newDistance, 0)); + } + } + } + } + + const PxU32 maxTethersPerParticle = 4; // max tethers + const PxU32 nbTethersPerParticle = (islandCnt > maxTethersPerParticle) ? maxTethersPerParticle : islandCnt; + + PxU32 nbTethers = nbTethersPerParticle * mNumParticles; + mTetherAnchors.resize(nbTethers); + mTetherLengths.resize(nbTethers); + + // now process the parent and distance and add to fibers + for (PxU32 i = 0; i < mNumParticles; i++) + { + // we use the heap to sort out N-closest island + vertexHeap.clear(); + for (PxU32 j = 0; j < islandCnt; j++) + { + int parent = int(vertexParentBuffer[j * mNumParticles + i]); + float edgeDistance = vertexDistanceBuffer[j * mNumParticles + i]; + pushHeap(vertexHeap, VertexDistanceCount(parent, edgeDistance, 0)); + } + + // take out N-closest island from the heap + for (PxU32 j = 0; j < nbTethersPerParticle; j++) + { + VertexDistanceCount vi = popHeap(vertexHeap); + PxU32 parent = PxU32(vi.vertNr); + float distance = 0.0f; + + if (parent != i) + { + float euclideanDistance = (mVertices[i] - mVertices[parent]).magnitude(); + float dijkstraDistance = vi.distance; + int errorCode = 0; + float geodesicDistance = computeGeodesicDistance(i,parent, errorCode); + if (errorCode < 0) + geodesicDistance = dijkstraDistance; + distance = PxMax(euclideanDistance, geodesicDistance); + } + + PxU32 tetherLoc = j * mNumParticles + i; + mTetherAnchors[ tetherLoc ] = parent; + mTetherLengths[ tetherLoc ] = distance; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +PxU32 PxClothGeodesicTetherCookerImpl::getCookerStatus() const +{ + return mCookerStatus; +} + +/////////////////////////////////////////////////////////////////////////////// +PxU32 PxClothGeodesicTetherCookerImpl::getNbTethersPerParticle() const +{ + return mTetherAnchors.size() / mNumParticles; +} + +/////////////////////////////////////////////////////////////////////////////// +void +PxClothGeodesicTetherCookerImpl::getTetherData(PxU32* userTetherAnchors, PxReal* userTetherLengths) const +{ + PxMemCopy(userTetherAnchors, mTetherAnchors.begin(), mTetherAnchors.size() * sizeof(PxU32)); + PxMemCopy(userTetherLengths, mTetherLengths.begin(), mTetherLengths.size() * sizeof(PxReal)); +} + +/////////////////////////////////////////////////////////////////////////////// +// find triangle-triangle adjacency (return non-zero if there is an error) +PxU32 PxClothGeodesicTetherCookerImpl::findTriNeighbors() +{ + shdfnd::Array<MeshEdge> edges; + + mTriNeighbors.resize(mIndices.size(), PxU32(-1)); + + // assemble all edges + PxU32 numTriangles = mIndices.size() / 3; + for (PxU32 i = 0; i < numTriangles; ++i) + { + PxU32 i0 = mIndices[3 * i]; + PxU32 i1 = mIndices[3 * i + 1]; + PxU32 i2 = mIndices[3 * i + 2]; + edges.pushBack(MeshEdge(int(i0), int(i1), int(3*i))); + edges.pushBack(MeshEdge(int(i1), int(i2), int(3*i+1))); + edges.pushBack(MeshEdge(int(i2), int(i0), int(3*i+2))); + } + + shdfnd::sort(edges.begin(), edges.size()); + + int numEdges = int(edges.size()); + for(int i=0; i < numEdges; ) + { + const MeshEdge& e0 = edges[PxU32(i)]; + bool orientation0 = checkEdgeOrientation(e0, mIndices); + + int j = i; + while(++i < numEdges && edges[PxU32(i)] == e0) + ; + + if(i - j > 2) + return 1; // non-manifold + + while(++j < i) + { + const MeshEdge& e1 = edges[PxU32(j)]; + bool orientation1 = checkEdgeOrientation(e1, mIndices); + mTriNeighbors[PxU32(e0.mHalfEdgeIndex)] = PxU32(e1.mHalfEdgeIndex/3); + mTriNeighbors[PxU32(e1.mHalfEdgeIndex)] = PxU32(e0.mHalfEdgeIndex/3); + + if (orientation0 == orientation1) + return 2; // bad winding + } + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// find vertex triangle adjacency information +void PxClothGeodesicTetherCookerImpl::findVertTriNeighbors() +{ + shdfnd::Array<VertTriangle> vertTriangles; + vertTriangles.reserve(mIndices.size()); + + int numTriangles = int(mIndices.size() / 3); + for (int i = 0; i < numTriangles; ++i) + { + vertTriangles.pushBack(VertTriangle(int(mIndices[PxU32(3*i)]), i)); + vertTriangles.pushBack(VertTriangle(int(mIndices[PxU32(3*i+1)]), i)); + vertTriangles.pushBack(VertTriangle(int(mIndices[PxU32(3*i+2)]), i)); + } + + shdfnd::sort(vertTriangles.begin(), vertTriangles.size(), shdfnd::Less<VertTriangle>()); + mFirstVertTriAdj.resize(mNumParticles); + mVertTriAdjs.reserve(mIndices.size()); + + for (PxU32 i = 0; i < PxU32(vertTriangles.size()); ) + { + int v = vertTriangles[i].mVertIndex; + + mFirstVertTriAdj[PxU32(v)] = i; + + while ((i < mIndices.size()) && (vertTriangles[i].mVertIndex == v)) + { + int t = vertTriangles[i].mTriangleIndex; + mVertTriAdjs.pushBack(PxU32(t)); + i++; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// compute intersection of a ray from a source vertex in direction toward parent +int PxClothGeodesicTetherCookerImpl::computeVertexIntersection(PxU32 parent, PxU32 src, PathIntersection &path) +{ + if (src == parent) + { + path = PathIntersection(true, src, 0.0); + return 0; + } + + float maxdot = -1.0f; + int closestVert = -1; + + // gradient is toward the parent vertex + PxVec3 g = (mVertices[parent] - mVertices[src]).getNormalized(); + + // for every triangle incident on this vertex, we intersect against opposite edge of the triangle + PxU32 sfirst = mFirstVertTriAdj[src]; + PxU32 slast = (src < (PxU32(mNumParticles-1))) ? mFirstVertTriAdj[src+1] : PxU32(mVertTriAdjs.size()); + for (PxU32 adj = sfirst; adj < slast; adj++) + { + PxU32 tid = mVertTriAdjs[adj]; + + PxU32 i0 = mIndices[tid*3]; + PxU32 i1 = mIndices[tid*3+1]; + PxU32 i2 = mIndices[tid*3+2]; + + int eid = 0; + if (i0 == src) eid = 1; + else if (i1 == src) eid = 2; + else if (i2 == src) eid = 0; + else continue; // error + + // reshuffle so that src is located at i2 + i0 = mIndices[tid*3 + eid]; + i1 = mIndices[tid*3 + (eid+1)%3]; + i2 = src; + + PxVec3 p0 = mVertices[i0]; + PxVec3 p1 = mVertices[i1]; + PxVec3 p2 = mVertices[i2]; + + // check if we hit source immediately from this triangle + if (i0 == parent) + { + path = PathIntersection(true, parent, (p0 - p2).magnitude()); + return 1; + } + + if (i1 == parent) + { + path = PathIntersection(true, parent, (p1 - p2).magnitude()); + return 1; + } + + // ray direction is the gradient projected on the plane of this triangle + PxVec3 n = ((p0 - p2).cross(p1 - p2)).getNormalized(); + PxVec3 d = (g - g.dot(n) * n).getNormalized(); + + // find intersection of ray (p2, d) against the edge (p0,p1) + float s, t; + bool result = intersectRayEdge(p2, d, p0, p1, s, t); + if (result == false) + continue; + + // t should be positive, otherwise we just hit the triangle in opposite direction, so ignore + const float eps = 1e-5; + if (t > -eps) + { + PxVec3 ip; // intersection point + if (( s > -eps ) && (s < (1.0f + eps))) + { + // if intersection point is too close to each vertex, we record a vertex intersection + if ( ( s < eps) || (s > (1.0f-eps))) + { + path.vertOrTriangle = true; + path.index = (s < eps) ? i0 : i1; + path.distance = (p2 - mVertices[path.index]).magnitude(); + } + else // found an edge instersection + { + ip = p0 + s * (p1 - p0); + path = PathIntersection(false, tid*3 + eid, (p2 - ip).magnitude(), s); + } + return 1; + } + } + + // for fall back (see below) + PxVec3 d0 = (p0 - p2).getNormalized(); + PxVec3 d1 = (p1 - p2).getNormalized(); + float d0dotg = d0.dot(d); + float d1dotg = d1.dot(d); + + if (d0dotg > maxdot) + { + closestVert = int(i0); + maxdot = d0dotg; + } + if (d1dotg > maxdot) + { + closestVert = int(i1); + maxdot = d1dotg; + } + } // end for (PxU32 adj = sfirst... + + // Fall back to use greedy (Dijkstra-like) path selection. + // This happens as triangles are curved and we may not find intersection on any triangle. + // In this case, we choose a vertex closest to the gradient direction. + if (closestVert > 0) + { + path = PathIntersection(true, PxU32(closestVert), (mVertices[src] - mVertices[PxU32(closestVert)]).magnitude()); + return 1; + } + + // Error, (possibly dangling vertex) + return -1; +} + +/////////////////////////////////////////////////////////////////////////////// +// compute intersection of a ray from a source vertex in direction toward parent +int PxClothGeodesicTetherCookerImpl::computeEdgeIntersection(PxU32 parent, PxU32 edge, float in_s, PathIntersection &path) +{ + int tid = int(edge / 3); + int eid = int(edge % 3); + + PxU32 e0 = mIndices[PxU32(tid*3 + eid)]; + PxU32 e1 = mIndices[PxU32(tid*3 + (eid+1)%3)]; + + PxVec3 v0 = mVertices[e0]; + PxVec3 v1 = mVertices[e1]; + + PxVec3 v = v0 + in_s * (v1 - v0); + PxVec3 g = mVertices[parent] - v; + + PxU32 triNbr = mTriNeighbors[edge]; + + if (triNbr == PxU32(-1)) // boundary edge + { + float dir = g.dot(v1-v0); + PxU32 vid = (dir > 0) ? e1 : e0; + path = PathIntersection(true, vid, (mVertices[vid] - v).magnitude()); + return 1; + } + + PxU32 i0 = mIndices[triNbr*3]; + PxU32 i1 = mIndices[triNbr*3+1]; + PxU32 i2 = mIndices[triNbr*3+2]; + + // vertex is sorted s.t i0,i1 contains the edge point + if ( checkEdge(int(i0), int(i1), int(e0), int(e1))) { + eid = 0; + } + else if ( checkEdge(int(i1), int(i2), int(e0), int(e1))) { + eid = 1; + PxU32 tmp = i2; + i2 = i0; + i0 = i1; + i1 = tmp; + } + else if ( checkEdge(int(i2), int(i0), int(e0), int(e1))) + { + eid = 2; + PxU32 tmp = i0; + i0 = i2; + i2 = i1; + i1 = tmp; + } + + // we hit the parent + if (i2 == parent) + { + path = PathIntersection(true, i2, (mVertices[i2] - v).magnitude()); + return 1; + } + + PxVec3 p0 = mVertices[i0]; + PxVec3 p1 = mVertices[i1]; + PxVec3 p2 = mVertices[i2]; + + // project gradient vector on the plane of the triangle + PxVec3 n = ((p0 - p2).cross(p1 - p2)).getNormalized(); + g = (g - g.dot(n) * n).getNormalized(); + + float s = 0.0f, t = 0.0f; + const float eps = 1e-5; + PxVec3 ip; + + // intersect against edge form p2 to p0 + if (intersectRayEdge(v, g, p2, p0, s, t) && ( s >= -eps) && ( s <= (1.0f+eps) ) && (t > -eps)) + { + if ( ( s < eps) || (s > (1.0f-eps))) + { + path.vertOrTriangle = true; + path.index = (s < eps) ? i2 : i0; + path.distance = (mVertices[path.index] - v).magnitude(); + } + else + { + ip = p2 + s * (p0 - p2); + path = PathIntersection(false, triNbr*3 + (eid + 2) % 3, (ip - v).magnitude(), s); + + } + + return 1; + } + + // intersect against edge form p1 to p2 + if (intersectRayEdge(v, g, p1, p2, s, t) && ( s >= -eps) && ( s <= (1.0f+eps) ) && (t > -eps)) + { + if ( ( s < eps) || (s > (1.0f-eps))) + { + path.vertOrTriangle = true; + path.index = (s < eps) ? i1 : i2; + path.distance = (mVertices[path.index] - v).magnitude(); + } + else + { + ip = p1 + s * (p2 - p1); + path = PathIntersection(false, triNbr*3 + (eid + 1) % 3, (ip - v).magnitude(), s); + } + + return 1; + } + + // fallback to pick closer vertex when no edges intersect + float dir = g.dot(v1-v0); + path.vertOrTriangle = true; + path.index = (dir > 0) ? e1 : e0; + path.distance = (mVertices[path.index] - v).magnitude(); + + return 1; +} + + +/////////////////////////////////////////////////////////////////////////////// +// compute geodesic distance and path from vertex i to its parent +float PxClothGeodesicTetherCookerImpl::computeGeodesicDistance(PxU32 i, PxU32 parent, int &errorCode) +{ + if (i == parent) + return 0.0f; + + PathIntersection path; + + errorCode = 0; + + // find intial intersection + int status = computeVertexIntersection(parent, i, path); + if (status < 0) + { + errorCode = -1; + return 0; + } + + int pathcnt = 0; + float geodesicDistance = 0; + + while (status > 0) + { + geodesicDistance += path.distance; + + if (path.vertOrTriangle) + status = computeVertexIntersection(parent, path.index, path); + else + status = computeEdgeIntersection(parent, path.index, path.s, path); + + // cannot find valid path + if (status < 0) + { + errorCode = -2; + return 0.0f; + } + + // possibly cycles, too many path + if (pathcnt > 1000) + { + errorCode = -3; + return 0.0f; + } + + pathcnt++; + } + + return geodesicDistance; +} + + + + +#endif //PX_USE_CLOTH_API + + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtClothMeshQuadifier.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtClothMeshQuadifier.cpp new file mode 100644 index 00000000..cb2392d3 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtClothMeshQuadifier.cpp @@ -0,0 +1,441 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PxPhysXConfig.h" +#if PX_USE_CLOTH_API + +#include "foundation/PxStrideIterator.h" +#include "extensions/PxClothMeshQuadifier.h" + +// from shared foundation +#include <PsFoundation.h> +#include <PsSort.h> +#include <Ps.h> +#include <PsMathUtils.h> +#include <PsArray.h> + +using namespace physx; + +struct physx::PxClothMeshQuadifierImpl +{ + PxClothMeshQuadifierImpl(const PxClothMeshDesc& desc); + PxClothMeshDesc getDescriptor() const; + +public: + PxClothMeshDesc mDesc; + shdfnd::Array<PxU32> mQuads; + shdfnd::Array<PxU32> mTriangles; +}; + +PxClothMeshQuadifier::PxClothMeshQuadifier(const PxClothMeshDesc& desc) +: mImpl(new PxClothMeshQuadifierImpl(desc)) +{ +} + +PxClothMeshQuadifier::~PxClothMeshQuadifier() +{ + delete mImpl; +} + +PxClothMeshDesc PxClothMeshQuadifier::getDescriptor() const +{ + return mImpl->getDescriptor(); +} + +namespace +{ + struct UniqueEdge + { + PX_FORCE_INLINE bool operator()(const UniqueEdge& e1, const UniqueEdge& e2) const + { + return e1 < e2; + } + + PX_FORCE_INLINE bool operator==(const UniqueEdge& other) const + { + return vertex0 == other.vertex0 && vertex1 == other.vertex1; + } + PX_FORCE_INLINE bool operator<(const UniqueEdge& other) const + { + if (vertex0 != other.vertex0) + { + return vertex0 < other.vertex0; + } + + return vertex1 < other.vertex1; + } + + /////////////////////////////////////////////////////////////////////////////// + UniqueEdge() + : vertex0(0), vertex1(0), vertex2(0), vertex3(0xffffffff), + maxAngle(0.0f), isQuadDiagonal(false), isUsed(false) {} + + UniqueEdge(PxU32 v0, PxU32 v1, PxU32 v2) + : vertex0(PxMin(v0, v1)), vertex1(PxMax(v0, v1)), vertex2(v2), vertex3(0xffffffff), + maxAngle(0.0f), isQuadDiagonal(false), isUsed(false) {} + + + PxU32 vertex0, vertex1; + PxU32 vertex2, vertex3; + PxF32 maxAngle; + bool isQuadDiagonal; + bool isUsed; + }; + + struct SortHiddenEdges + { + SortHiddenEdges(shdfnd::Array<UniqueEdge>& uniqueEdges) : mUniqueEdges(uniqueEdges) {} + + bool operator()(PxU32 a, PxU32 b) const + { + return mUniqueEdges[a].maxAngle < mUniqueEdges[b].maxAngle; + } + + private: + SortHiddenEdges& operator=(const SortHiddenEdges&); + shdfnd::Array<UniqueEdge>& mUniqueEdges; + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + template <typename T> + void copyIndices(const PxClothMeshDesc &desc, shdfnd::Array<PxU32> &triangles, shdfnd::Array<PxU32> &quads) + { + triangles.resize(desc.triangles.count*3); + PxStrideIterator<const T> tIt = PxMakeIterator(reinterpret_cast<const T*>(desc.triangles.data), desc.triangles.stride); + for(PxU32 i=0; i<desc.triangles.count; ++i, ++tIt) + for(PxU32 j=0; j<3; ++j) + triangles[i*3+j] = tIt.ptr()[j]; + + quads.resize(desc.quads.count*4); + PxStrideIterator<const T> qIt = PxMakeIterator(reinterpret_cast<const T*>(desc.quads.data), desc.quads.stride); + for(PxU32 i=0; i<desc.quads.count; ++i, ++qIt) + for(PxU32 j=0; j<4; ++j) + quads[i*4+j] = qIt.ptr()[j]; + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void computeUniqueEdges(shdfnd::Array<UniqueEdge> &uniqueEdges, const PxVec3* positions, const shdfnd::Array<PxU32>& triangles) + { + uniqueEdges.resize(0); + uniqueEdges.reserve(triangles.size()); + + PxU32 indexMap[3][3] = { { 0, 1, 2 }, { 1, 2, 0 }, { 0, 2, 1 } }; + + const PxF32 rightAngle = PxCos(shdfnd::degToRad(85.0f)); + + for(PxU32 i=0; i<triangles.size(); i+=3) + { + UniqueEdge edges[3]; + PxF32 edgeLengths[3]; + PxF32 edgeAngles[3]; + + for (PxU32 j = 0; j < 3; j++) + { + edges[j] = UniqueEdge(triangles[i+indexMap[j][0]], triangles[i+indexMap[j][1]], triangles[i+indexMap[j][2]]); + edgeLengths[j] = (positions[edges[j].vertex0] - positions[edges[j].vertex1]).magnitude(); + const PxVec3 v1 = positions[edges[j].vertex2] - positions[edges[j].vertex0]; + const PxVec3 v2 = positions[edges[j].vertex2] - positions[edges[j].vertex1]; + edgeAngles[j] = PxAbs(v1.dot(v2)) / (v1.magnitude() * v2.magnitude()); + } + + // find the longest edge + PxU32 longest = 0; + for (PxU32 j = 1; j < 3; j++) + { + if (edgeLengths[j] > edgeLengths[longest]) + longest = j; + } + + // check it's angle + if (edgeAngles[longest] < rightAngle) + edges[longest].isQuadDiagonal = true; + + for (PxU32 j = 0; j < 3; j++) + uniqueEdges.pushBack(edges[j]); + } + + shdfnd::sort(uniqueEdges.begin(), uniqueEdges.size(), UniqueEdge(0, 0, 0)); + + PxU32 writeIndex = 0, readStart = 0, readEnd = 0; + PxU32 numQuadEdges = 0; + while (readEnd < uniqueEdges.size()) + { + while (readEnd < uniqueEdges.size() && uniqueEdges[readStart] == uniqueEdges[readEnd]) + readEnd++; + + const PxU32 count = readEnd - readStart; + + UniqueEdge uniqueEdge = uniqueEdges[readStart]; + + if (count == 2) + // know the other diagonal + uniqueEdge.vertex3 = uniqueEdges[readStart + 1].vertex2; + else + uniqueEdge.isQuadDiagonal = false; + + for (PxU32 i = 1; i < count; i++) + uniqueEdge.isQuadDiagonal &= uniqueEdges[readStart + i].isQuadDiagonal; + + numQuadEdges += uniqueEdge.isQuadDiagonal ? 1 : 0; + + uniqueEdges[writeIndex] = uniqueEdge; + + writeIndex++; + readStart = readEnd; + } + + uniqueEdges.resize(writeIndex, UniqueEdge(0, 0, 0)); + } + + /////////////////////////////////////////////////////////////////////////////// + PxU32 findUniqueEdge(const shdfnd::Array<UniqueEdge> &uniqueEdges, PxU32 index1, PxU32 index2) + { + UniqueEdge searchFor(index1, index2, 0); + + PxU32 curMin = 0; + PxU32 curMax = uniqueEdges.size(); + while (curMax > curMin) + { + PxU32 middle = (curMin + curMax) >> 1; + + const UniqueEdge& probe = uniqueEdges[middle]; + if (probe < searchFor) + curMin = middle + 1; + else + curMax = middle; + } + + return curMin; + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void refineUniqueEdges(shdfnd::Array<UniqueEdge> &uniqueEdges, const PxVec3* positions) + { + shdfnd::Array<PxU32> hideEdges; + hideEdges.reserve(uniqueEdges.size()); + + for (PxU32 i = 0; i < uniqueEdges.size(); i++) + { + UniqueEdge& uniqueEdge = uniqueEdges[i]; + uniqueEdge.maxAngle = 0.0f; + uniqueEdge.isQuadDiagonal = false; // just to be sure + + if (uniqueEdge.vertex3 != 0xffffffff) + { + PxU32 indices[4] = { uniqueEdge.vertex0, uniqueEdge.vertex2, uniqueEdge.vertex1, uniqueEdge.vertex3 }; + + // compute max angle of the quad + for (PxU32 j = 0; j < 4; j++) + { + PxVec3 e0 = positions[indices[ j + 0 ]] - positions[indices[(j + 1) % 4]]; + PxVec3 e1 = positions[indices[(j + 1) % 4]] - positions[indices[(j + 2) % 4]]; + + PxF32 cosAngle = PxAbs(e0.dot(e1)) / (e0.magnitude() * e1.magnitude()); + uniqueEdge.maxAngle = PxMax(uniqueEdge.maxAngle, cosAngle); + } + + hideEdges.pushBack(i); + } + } + + shdfnd::sort(hideEdges.begin(), hideEdges.size(), SortHiddenEdges(uniqueEdges)); + + const PxF32 maxAngle = PxSin(shdfnd::degToRad(60.0f)); + + PxU32 numHiddenEdges = 0; + + for (PxU32 i = 0; i < hideEdges.size(); i++) + { + UniqueEdge& uniqueEdge = uniqueEdges[hideEdges[i]]; + + // find some stop criterion + if (uniqueEdge.maxAngle > maxAngle) + break; + + // check if all four adjacent edges are still visible? + PxU32 indices[5] = { uniqueEdge.vertex0, uniqueEdge.vertex2, uniqueEdge.vertex1, uniqueEdge.vertex3, uniqueEdge.vertex0 }; + + PxU32 numVisible = 0; + for (PxU32 j = 0; j < 4; j++) + { + const PxU32 edgeIndex = findUniqueEdge(uniqueEdges, indices[j], indices[j + 1]); + PX_ASSERT(edgeIndex < uniqueEdges.size()); + + numVisible += uniqueEdges[edgeIndex].isQuadDiagonal ? 0 : 1; + } + + if (numVisible == 4) + { + uniqueEdge.isQuadDiagonal = true; + numHiddenEdges++; + } + } + } + + + // calculate the inclusive prefix sum, equivalent of std::partial_sum + template <typename T> + void prefixSum(const T* first, const T* last, T* dest) + { + if (first != last) + { + *(dest++) = *(first++); + for (; first != last; ++first, ++dest) + *dest = *(dest-1) + *first; + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void quadifyTriangles(const shdfnd::Array<UniqueEdge> &uniqueEdges, shdfnd::Array<PxU32>& triangles, shdfnd::Array<PxU32> &quads) + { + shdfnd::Array<PxU32> valency(uniqueEdges.size()+1, 0); // edge valency + shdfnd::Array<PxU32> adjacencies; // adjacency from unique edge to triangles + PxU32 numTriangles = triangles.size() / 3; + + // compute edge valency w.r.t triangles + for(PxU32 i=0; i<numTriangles; ++i) + { + for (PxU32 j=0; j < 3; j++) + { + PxU32 uniqueEdgeIndex = findUniqueEdge(uniqueEdges, triangles[i*3+j], triangles[i*3+(j+1)%3]); + ++valency[uniqueEdgeIndex]; + } + } + + // compute adjacency from each edge to triangle, the value also encodes which side of the triangle this edge belongs to + prefixSum(valency.begin(), valency.end(), valency.begin()); + adjacencies.resize(valency.back()); + for(PxU32 i=0; i<numTriangles; ++i) + { + for (PxU32 j=0; j < 3; j++) + { + PxU32 uniqueEdgeIndex = findUniqueEdge(uniqueEdges, triangles[i*3+j], triangles[i*3+(j+1)%3]); + adjacencies[--valency[uniqueEdgeIndex]] = i*3+j; + } + } + + // now go through unique edges that are identified as diagonal, and build a quad out of two adjacent triangles + shdfnd::Array<PxU32> mark(numTriangles, 0); + for (PxU32 i = 0; i < uniqueEdges.size(); i++) + { + const UniqueEdge& edge = uniqueEdges[i]; + if (edge.isQuadDiagonal) + { + PxU32 vi = valency[i]; + if ((valency[i+1]-vi) != 2) + continue; // we do not quadify around non-manifold edges + + PxU32 adj0 = adjacencies[vi], adj1 = adjacencies[vi+1]; + PxU32 tid0 = adj0 / 3, tid1 = adj1 / 3; + PxU32 eid0 = adj0 % 3, eid1 = adj1 % 3; + + quads.pushBack(triangles[tid0 * 3 + eid0]); + quads.pushBack(triangles[tid1 * 3 + (eid1+2)%3]); + quads.pushBack(triangles[tid0 * 3 + (eid0+1)%3]); + quads.pushBack(triangles[tid0 * 3 + (eid0+2)%3]); + + mark[tid0] = 1; + mark[tid1] = 1; +#if 0 // PX_DEBUG + printf("Deleting %d, %d, %d - %d, %d, %d, creating %d, %d, %d, %d\n", + triangles[tid0*3],triangles[tid0*3+1],triangles[tid0*3+2], + triangles[tid1*3],triangles[tid1*3+1],triangles[tid1*3+2], + v0,v3,v1,v2); +#endif + } + } + + // add remaining triangles that are not marked as already quadified + shdfnd::Array<PxU32> oldTriangles = triangles; + triangles.resize(0); + for (PxU32 i = 0; i < numTriangles; i++) + { + if (mark[i]) continue; + + triangles.pushBack(oldTriangles[i*3]); + triangles.pushBack(oldTriangles[i*3+1]); + triangles.pushBack(oldTriangles[i*3+2]); + } + } + +} // namespace + + +/////////////////////////////////////////////////////////////////////////////// +PxClothMeshQuadifierImpl::PxClothMeshQuadifierImpl(const PxClothMeshDesc &desc) + :mDesc(desc) +{ + shdfnd::Array<PxVec3> particles(desc.points.count); + PxStrideIterator<const PxVec3> pIt(reinterpret_cast<const PxVec3*>(desc.points.data), desc.points.stride); + for(PxU32 i=0; i<desc.points.count; ++i) + particles[i] = *pIt++; + + // copy triangle indices + if(desc.flags & PxMeshFlag::e16_BIT_INDICES) + copyIndices<PxU16>(desc, mTriangles, mQuads); + else + copyIndices<PxU32>(desc, mTriangles, mQuads); + + shdfnd::Array<UniqueEdge> uniqueEdges; + + computeUniqueEdges(uniqueEdges, particles.begin(), mTriangles); + + refineUniqueEdges(uniqueEdges, particles.begin()); + +// printf("before %d triangles, %d quads\n", mTriangles.size()/3, mQuads.size()/4); + quadifyTriangles(uniqueEdges, mTriangles, mQuads); + +// printf("after %d triangles, %d quads\n", mTriangles.size()/3, mQuads.size()/4); +} + +/////////////////////////////////////////////////////////////////////////////// +PxClothMeshDesc +PxClothMeshQuadifierImpl::getDescriptor() const +{ + // copy points and other data + PxClothMeshDesc desc = mDesc; + + // for now use only 32 bit for temporary indices out of quadifier + desc.flags &= ~PxMeshFlag::e16_BIT_INDICES; + + desc.triangles.count = mTriangles.size() / 3; + desc.triangles.data = mTriangles.begin(); + desc.triangles.stride = 3 * sizeof(PxU32); + + desc.quads.count = mQuads.size() / 4; + desc.quads.data = mQuads.begin(); + desc.quads.stride = 4 * sizeof(PxU32); + + PX_ASSERT(desc.isValid()); + + return desc; +} +#endif //PX_USE_CLOTH_API + + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtClothSimpleTetherCooker.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtClothSimpleTetherCooker.cpp new file mode 100644 index 00000000..b89dd507 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtClothSimpleTetherCooker.cpp @@ -0,0 +1,141 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PxPhysXConfig.h" +#if PX_USE_CLOTH_API + +#include "foundation/PxVec4.h" +#include "foundation/PxMemory.h" +#include "foundation/PxStrideIterator.h" +#include "extensions/PxClothTetherCooker.h" +#include "PsArray.h" +// from shared foundation +#include <PsFoundation.h> + +using namespace physx; + +struct physx::PxClothSimpleTetherCookerImpl +{ + PxClothSimpleTetherCookerImpl(const PxClothMeshDesc& desc); + + void getTetherData(PxU32* userTetherAnchors, PxReal* userTetherLengths) const; + +public: + // output + shdfnd::Array<PxU32> mTetherAnchors; + shdfnd::Array<PxReal> mTetherLengths; + +protected: + void createTetherData(const PxClothMeshDesc &desc); +}; + +PxClothSimpleTetherCooker::PxClothSimpleTetherCooker(const PxClothMeshDesc& desc) +: mImpl(new PxClothSimpleTetherCookerImpl(desc)) +{ +} + +PxClothSimpleTetherCooker::~PxClothSimpleTetherCooker() +{ + delete mImpl; +} + +void PxClothSimpleTetherCooker::getTetherData(PxU32* userTetherAnchors, PxReal* userTetherLengths) const +{ + mImpl->getTetherData(userTetherAnchors, userTetherLengths); +} + +/////////////////////////////////////////////////////////////////////////////// +PxClothSimpleTetherCookerImpl::PxClothSimpleTetherCookerImpl(const PxClothMeshDesc &desc) +{ + createTetherData(desc); +} + +/////////////////////////////////////////////////////////////////////////////// +void PxClothSimpleTetherCookerImpl::createTetherData(const PxClothMeshDesc &desc) +{ + PxU32 numParticles = desc.points.count; + + if (!desc.invMasses.data) + return; + + // assemble points + shdfnd::Array<PxVec4> particles; + particles.reserve(numParticles); + PxStrideIterator<const PxVec3> pIt(reinterpret_cast<const PxVec3*>(desc.points.data), desc.points.stride); + PxStrideIterator<const PxReal> wIt(reinterpret_cast<const PxReal*>(desc.invMasses.data), desc.invMasses.stride); + for(PxU32 i=0; i<numParticles; ++i) + particles.pushBack(PxVec4(*pIt++, wIt.ptr() ? *wIt++ : 1.0f)); + + // compute tether data + shdfnd::Array<PxU32> attachedIndices; + for(PxU32 i=0; i < numParticles; ++i) + if(particles[i].w == 0.0f) + attachedIndices.pushBack(i); + + PxU32 n = attachedIndices.empty() ? 0 : numParticles; + for(PxU32 i=0; i < n; ++i) + { + mTetherAnchors.reserve(numParticles); + mTetherLengths.reserve(numParticles); + + PxVec3 position = reinterpret_cast<const PxVec3&>(particles[i]); + float minSqrDist = FLT_MAX; + PxU32 minIndex = numParticles; + const PxU32 *aIt, *aEnd = attachedIndices.end(); + for(aIt = attachedIndices.begin(); aIt != aEnd; ++aIt) + { + float sqrDist = (reinterpret_cast<const PxVec3&>( + particles[*aIt]) - position).magnitudeSquared(); + if(minSqrDist > sqrDist) + { + minSqrDist = sqrDist; + minIndex = *aIt; + } + } + + mTetherAnchors.pushBack(minIndex); + mTetherLengths.pushBack(PxSqrt(minSqrDist)); + } + + PX_ASSERT(mTetherAnchors.size() == mTetherLengths.size()); + +} + +/////////////////////////////////////////////////////////////////////////////// +void +PxClothSimpleTetherCookerImpl::getTetherData(PxU32* userTetherAnchors, PxReal* userTetherLengths) const +{ + PxMemCopy(userTetherAnchors, mTetherAnchors.begin(), mTetherAnchors.size() * sizeof(PxU32)); + PxMemCopy(userTetherLengths, mTetherLengths.begin(), mTetherLengths.size() * sizeof(PxReal)); +} + + +#endif //PX_USE_CLOTH_API + + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtCollection.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtCollection.cpp new file mode 100644 index 00000000..0a768d8e --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtCollection.cpp @@ -0,0 +1,252 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PxBase.h" +#include "PsArray.h" +#include "PxShape.h" +#include "PxConvexMesh.h" +#include "PxTriangleMesh.h" +#include "PxHeightField.h" +#include "PxMaterial.h" +#include "PxJoint.h" +#include "PxConstraintExt.h" +#include "PxArticulation.h" +#include "PxAggregate.h" +#include "PxPhysics.h" +#include "PxScene.h" +#include "PxPruningStructure.h" +#include "PxCollectionExt.h" + + +using namespace physx; + +void PxCollectionExt::releaseObjects(PxCollection& collection, bool releaseExclusiveShapes) +{ + shdfnd::Array<PxBase*> releasableObjects; + + for (PxU32 i = 0; i < collection.getNbObjects(); ++i) + { + PxBase* s = &collection.getObject(i); + // pruning structure must be released before its actors + if(s->is<PxPruningStructure>()) + { + if(!releasableObjects.empty()) + { + PxBase* first = releasableObjects[0]; + releasableObjects.pushBack(first); + releasableObjects[0] = s; + } + } + else + { + if (s->isReleasable() && (releaseExclusiveShapes || !s->is<PxShape>() || !s->is<PxShape>()->isExclusive())) + releasableObjects.pushBack(s); + } + } + + for (PxU32 i = 0; i < releasableObjects.size(); ++i) + releasableObjects[i]->release(); + + while (collection.getNbObjects() > 0) + collection.remove(collection.getObject(0)); +} + + +void PxCollectionExt::remove(PxCollection& collection, PxType concreteType, PxCollection* to) +{ + shdfnd::Array<PxBase*> removeObjects; + + for (PxU32 i = 0; i < collection.getNbObjects(); i++) + { + PxBase& object = collection.getObject(i); + if(concreteType == object.getConcreteType()) + { + if(to) + to->add(object); + + removeObjects.pushBack(&object); + } + } + + for (PxU32 i = 0; i < removeObjects.size(); ++i) + collection.remove(*removeObjects[i]); +} + +PxCollection* PxCollectionExt::createCollection(PxPhysics& physics) +{ + PxCollection* collection = PxCreateCollection(); + if (!collection) + return NULL; + + // Collect convexes + { + shdfnd::Array<PxConvexMesh*> objects(physics.getNbConvexMeshes()); + const PxU32 nb = physics.getConvexMeshes(objects.begin(), objects.size()); + PX_ASSERT(nb == objects.size()); + PX_UNUSED(nb); + + for(PxU32 i=0;i<objects.size();i++) + collection->add(*objects[i]); + } + + // Collect triangle meshes + { + shdfnd::Array<PxTriangleMesh*> objects(physics.getNbTriangleMeshes()); + const PxU32 nb = physics.getTriangleMeshes(objects.begin(), objects.size()); + + PX_ASSERT(nb == objects.size()); + PX_UNUSED(nb); + + for(PxU32 i=0;i<objects.size();i++) + collection->add(*objects[i]); + } + + // Collect heightfields + { + shdfnd::Array<PxHeightField*> objects(physics.getNbHeightFields()); + const PxU32 nb = physics.getHeightFields(objects.begin(), objects.size()); + + PX_ASSERT(nb == objects.size()); + PX_UNUSED(nb); + + for(PxU32 i=0;i<objects.size();i++) + collection->add(*objects[i]); + } + + // Collect materials + { + shdfnd::Array<PxMaterial*> objects(physics.getNbMaterials()); + const PxU32 nb = physics.getMaterials(objects.begin(), objects.size()); + + PX_ASSERT(nb == objects.size()); + PX_UNUSED(nb); + + for(PxU32 i=0;i<objects.size();i++) + collection->add(*objects[i]); + } + +#if PX_USE_CLOTH_API + // Collect cloth fabrics + { + shdfnd::Array<PxClothFabric*> objects(physics.getNbClothFabrics()); + const PxU32 nb = physics.getClothFabrics(objects.begin(), objects.size()); + + PX_ASSERT(nb == objects.size()); + PX_UNUSED(nb); + + for(PxU32 i=0;i<objects.size();i++) + collection->add(*objects[i]); + } +#endif + + // Collect shapes + { + shdfnd::Array<PxShape*> objects(physics.getNbShapes()); + const PxU32 nb = physics.getShapes(objects.begin(), objects.size()); + + PX_ASSERT(nb == objects.size()); + PX_UNUSED(nb); + + for(PxU32 i=0;i<objects.size();i++) + collection->add(*objects[i]); + } + return collection; +} + +PxCollection* PxCollectionExt::createCollection(PxScene& scene) +{ + PxCollection* collection = PxCreateCollection(); + if (!collection) + return NULL; + + // Collect actors + { + PxActorTypeFlags selectionFlags = PxActorTypeFlag::eRIGID_STATIC | PxActorTypeFlag::eRIGID_DYNAMIC; + +#if PX_USE_PARTICLE_SYSTEM_API + selectionFlags |= PxActorTypeFlag::ePARTICLE_SYSTEM | PxActorTypeFlag::ePARTICLE_FLUID; +#endif +#if PX_USE_CLOTH_API + selectionFlags |= PxActorTypeFlag::eCLOTH; +#endif + + shdfnd::Array<PxActor*> objects(scene.getNbActors(selectionFlags)); + const PxU32 nb = scene.getActors(selectionFlags, objects.begin(), objects.size()); + + PX_ASSERT(nb==objects.size()); + PX_UNUSED(nb); + + for(PxU32 i=0;i<objects.size();i++) + collection->add(*objects[i]); + } + + + // Collect constraints + { + shdfnd::Array<PxConstraint*> objects(scene.getNbConstraints()); + const PxU32 nb = scene.getConstraints(objects.begin(), objects.size()); + + PX_ASSERT(nb==objects.size()); + PX_UNUSED(nb); + + for(PxU32 i=0;i<objects.size();i++) + { + PxU32 typeId; + PxJoint* joint = reinterpret_cast<PxJoint*>(objects[i]->getExternalReference(typeId)); + if(typeId == PxConstraintExtIDs::eJOINT) + collection->add(*joint); + } + } + + // Collect articulations + { + shdfnd::Array<PxArticulation*> objects(scene.getNbArticulations()); + const PxU32 nb = scene.getArticulations(objects.begin(), objects.size()); + + PX_ASSERT(nb==objects.size()); + PX_UNUSED(nb); + + for(PxU32 i=0;i<objects.size();i++) + collection->add(*objects[i]); + } + + // Collect aggregates + { + shdfnd::Array<PxAggregate*> objects(scene.getNbAggregates()); + const PxU32 nb = scene.getAggregates(objects.begin(), objects.size()); + + PX_ASSERT(nb==objects.size()); + PX_UNUSED(nb); + + for(PxU32 i=0;i<objects.size();i++) + collection->add(*objects[i]); + } + + return collection; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtConstraintHelper.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtConstraintHelper.h new file mode 100644 index 00000000..b742434d --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtConstraintHelper.h @@ -0,0 +1,378 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef NP_CONSTRAINT_HELPER_H +#define NP_CONSTRAINT_HELPER_H + +#include "foundation/PxAssert.h" +#include "foundation/PxTransform.h" +#include "foundation/PxMat33.h" +#include "PxJointLimit.h" +#include "ExtJoint.h" + +namespace physx +{ +namespace Ext +{ + namespace joint + { + PX_INLINE void computeDerived(const JointData& data, + const PxTransform& bA2w, + const PxTransform& bB2w, + PxTransform& cA2w, + PxTransform& cB2w, + PxTransform& cB2cA) + { + PX_ASSERT(bA2w.isValid() && bB2w.isValid()); + + cA2w = bA2w.transform(data.c2b[0]); + cB2w = bB2w.transform(data.c2b[1]); + + if(cA2w.q.dot(cB2w.q)<0) // minimum error quat + cB2w.q = -cB2w.q; + + cB2cA = cA2w.transformInv(cB2w); + + PX_ASSERT(cA2w.isValid() && cB2w.isValid() && cB2cA.isValid()); + } + + PX_INLINE PxVec3 truncateLinear(const PxVec3& in, PxReal tolerance, bool& truncated) + { + PxReal m = in.magnitudeSquared(); + truncated = m>tolerance * tolerance; + return truncated ? in * PxRecipSqrt(m) * tolerance : in; + } + + PX_INLINE PxQuat truncateAngular(const PxQuat& in, PxReal sinHalfTol, PxReal cosHalfTol, bool& truncated) + { + truncated = false; + + if(sinHalfTol > 0.9999f) // fixes numerical tolerance issue of projecting because quat is not exactly normalized + return in; + + PxQuat q = in.w>=0 ? in : -in; + + const PxVec3& im = q.getImaginaryPart(); + PxReal m = im.magnitudeSquared(); + truncated = m>sinHalfTol*sinHalfTol; + if(!truncated) + return in; + + PxVec3 outV = im * sinHalfTol * PxRecipSqrt(m); + return PxQuat(outV.x, outV.y, outV.z, cosHalfTol); + } + + PX_FORCE_INLINE void projectTransforms(PxTransform& bA2w, PxTransform& bB2w, + const PxTransform& cA2w, const PxTransform& cB2w, + const PxTransform& cB2cA, const JointData& data, bool projectToA) + { + PX_ASSERT(cB2cA.isValid()); + + // normalization here is unfortunate: long chains of projected constraints can result in + // accumulation of error in the quaternion which eventually leaves the quaternion + // magnitude outside the validation range. The approach here is slightly overconservative + // in that we could just normalize the quaternions which are out of range, but since we + // regard projection as an occasional edge case it shouldn't be perf-sensitive, and + // this way we maintain the invariant (also maintained by the dynamics integrator) that + // body quats are properly normalized up to FP error. + + if (projectToA) + { + bB2w = cA2w.transform(cB2cA.transform(data.c2b[1].getInverse())); + bB2w.q.normalize(); + } + else + { + bA2w = cB2w.transform(cB2cA.transformInv(data.c2b[0].getInverse())); + bA2w.q.normalize(); + } + + + PX_ASSERT(bA2w.isValid()); + PX_ASSERT(bB2w.isValid()); + } + + + + PX_INLINE void computeJacobianAxes(PxVec3 row[3], const PxQuat& qa, const PxQuat& qb) + { + // Compute jacobian matrix for (qa* qb) [[* means conjugate in this expr]] + // d/dt (qa* qb) = 1/2 L(qa*) R(qb) (omega_b - omega_a) + // result is L(qa*) R(qb), where L(q) and R(q) are left/right q multiply matrix + + PxReal wa = qa.w, wb = qb.w; + const PxVec3 va(qa.x,qa.y,qa.z), vb(qb.x,qb.y,qb.z); + + const PxVec3 c = vb*wa + va*wb; + const PxReal d0 = wa*wb; + const PxReal d1 = va.dot(vb); + const PxReal d = d0 - d1; + + row[0] = (va * vb.x + vb * va.x + PxVec3(d, c.z, -c.y)) * 0.5f; + row[1] = (va * vb.y + vb * va.y + PxVec3(-c.z, d, c.x)) * 0.5f; + row[2] = (va * vb.z + vb * va.z + PxVec3(c.y, -c.x, d)) * 0.5f; + + if ((d0 + d1) != 0.0f) // check if relative rotation is 180 degrees which can lead to singular matrix + return; + else + { + row[0].x += PX_EPS_F32; + row[1].y += PX_EPS_F32; + row[2].z += PX_EPS_F32; + } + } + + class ConstraintHelper + { + Px1DConstraint* mConstraints; + Px1DConstraint* mCurrent; + PxVec3 mRa, mRb; + + public: + ConstraintHelper(Px1DConstraint* c, const PxVec3& ra, const PxVec3& rb) + : mConstraints(c), mCurrent(c), mRa(ra), mRb(rb) {} + + + // hard linear & angular + PX_FORCE_INLINE void linearHard(const PxVec3& axis, PxReal posErr) + { + Px1DConstraint *c = linear(axis, posErr, PxConstraintSolveHint::eEQUALITY); + c->flags |= Px1DConstraintFlag::eOUTPUT_FORCE; + } + + PX_FORCE_INLINE void angularHard(const PxVec3& axis, PxReal posErr) + { + Px1DConstraint *c = angular(axis, posErr, PxConstraintSolveHint::eEQUALITY); + c->flags |= Px1DConstraintFlag::eOUTPUT_FORCE; + } + + // limited linear & angular + PX_FORCE_INLINE void linearLimit(const PxVec3& axis, PxReal ordinate, PxReal limitValue, const PxJointLimitParameters& limit) + { + PxReal pad = limit.isSoft() ? 0 : limit.contactDistance; + + if(ordinate + pad > limitValue) + addLimit(linear(axis,limitValue - ordinate, PxConstraintSolveHint::eNONE),limit); + } + + PX_FORCE_INLINE void angularLimit(const PxVec3& axis, PxReal ordinate, PxReal limitValue, PxReal pad, const PxJointLimitParameters& limit) + { + if(limit.isSoft()) + pad = 0; + + if(ordinate + pad > limitValue) + addLimit(angular(axis,limitValue - ordinate, PxConstraintSolveHint::eNONE),limit); + } + + + PX_FORCE_INLINE void angularLimit(const PxVec3& axis, PxReal error, const PxJointLimitParameters& limit) + { + addLimit(angular(axis,error, PxConstraintSolveHint::eNONE),limit); + } + + PX_FORCE_INLINE void halfAnglePair(PxReal halfAngle, PxReal lower, PxReal upper, PxReal pad, const PxVec3& axis, const PxJointLimitParameters& limit) + { + PX_ASSERT(lower<upper); + if(limit.isSoft()) + pad = 0; + + if(halfAngle < lower+pad) + angularLimit(-axis, -(lower - halfAngle)*2,limit); + if(halfAngle > upper-pad) + angularLimit(axis, (upper - halfAngle)*2, limit); + } + + PX_FORCE_INLINE void quarterAnglePair(PxReal quarterAngle, PxReal lower, PxReal upper, PxReal pad, const PxVec3& axis, const PxJointLimitParameters& limit) + { + if(limit.isSoft()) + pad = 0; + + PX_ASSERT(lower<upper); + if(quarterAngle < lower+pad) + angularLimit(-axis, -(lower - quarterAngle)*4,limit); + if(quarterAngle > upper-pad) + angularLimit(axis, (upper - quarterAngle)*4, limit); + } + + // driven linear & angular + + PX_FORCE_INLINE void linear(const PxVec3& axis, PxReal velTarget, PxReal error, const PxD6JointDrive& drive) + { + addDrive(linear(axis,error,PxConstraintSolveHint::eNONE),velTarget,drive); + } + + PX_FORCE_INLINE void angular(const PxVec3& axis, PxReal velTarget, PxReal error, const PxD6JointDrive& drive, PxConstraintSolveHint::Enum hint = PxConstraintSolveHint::eNONE) + { + addDrive(angular(axis,error,hint),velTarget,drive); + } + + + PX_FORCE_INLINE PxU32 getCount() { return PxU32(mCurrent - mConstraints); } + + void prepareLockedAxes(const PxQuat& qA, const PxQuat& qB, const PxVec3& cB2cAp, PxU32 lin, PxU32 ang) + { + Px1DConstraint* current = mCurrent; + if(ang) + { + PxQuat qB2qA = qA.getConjugate() * qB; + + PxVec3 row[3]; + computeJacobianAxes(row, qA, qB); + PxVec3 imp = qB2qA.getImaginaryPart(); + if(ang&1) angular(row[0], -imp.x, PxConstraintSolveHint::eEQUALITY, current++); + if(ang&2) angular(row[1], -imp.y, PxConstraintSolveHint::eEQUALITY, current++); + if(ang&4) angular(row[2], -imp.z, PxConstraintSolveHint::eEQUALITY, current++); + } + + if(lin) + { + PxMat33 axes(qA); + if(lin&1) linear(axes[0], -cB2cAp[0], PxConstraintSolveHint::eEQUALITY, current++); + if(lin&2) linear(axes[1], -cB2cAp[1], PxConstraintSolveHint::eEQUALITY, current++); + if(lin&4) linear(axes[2], -cB2cAp[2], PxConstraintSolveHint::eEQUALITY, current++); + } + + for(Px1DConstraint* front = mCurrent; front < current; front++) + front->flags = Px1DConstraintFlag::eOUTPUT_FORCE; + + mCurrent = current; + } + + Px1DConstraint *getConstraintRow() + { + return mCurrent++; + } + + private: + PX_FORCE_INLINE Px1DConstraint* linear(const PxVec3& axis, PxReal posErr, PxConstraintSolveHint::Enum hint) + { + Px1DConstraint* c = mCurrent++; + + c->solveHint = PxU16(hint); + c->linear0 = axis; c->angular0 = mRa.cross(axis); + c->linear1 = axis; c->angular1 = mRb.cross(axis); + PX_ASSERT(c->linear0.isFinite()); + PX_ASSERT(c->linear1.isFinite()); + PX_ASSERT(c->angular0.isFinite()); + PX_ASSERT(c->angular1.isFinite()); + + c->geometricError = posErr; + + return c; + } + + PX_FORCE_INLINE Px1DConstraint* angular(const PxVec3& axis, PxReal posErr, PxConstraintSolveHint::Enum hint) + { + Px1DConstraint* c = mCurrent++; + + c->solveHint = PxU16(hint); + c->linear0 = PxVec3(0); c->angular0 = axis; + c->linear1 = PxVec3(0); c->angular1 = axis; + + c->geometricError = posErr; + return c; + } + + PX_FORCE_INLINE Px1DConstraint* linear(const PxVec3& axis, PxReal posErr, PxConstraintSolveHint::Enum hint, Px1DConstraint* c) + { + c->solveHint = PxU16(hint); + c->linear0 = axis; c->angular0 = mRa.cross(axis); + c->linear1 = axis; c->angular1 = mRb.cross(axis); + PX_ASSERT(c->linear0.isFinite()); + PX_ASSERT(c->linear1.isFinite()); + PX_ASSERT(c->angular0.isFinite()); + PX_ASSERT(c->angular1.isFinite()); + + c->geometricError = posErr; + + + return c; + } + + PX_FORCE_INLINE Px1DConstraint* angular(const PxVec3& axis, PxReal posErr, PxConstraintSolveHint::Enum hint, Px1DConstraint* c) + { + c->solveHint = PxU16(hint); + c->linear0 = PxVec3(0.f); c->angular0 = axis; + c->linear1 = PxVec3(0.f); c->angular1 = axis; + + c->geometricError = posErr; + + return c; + } + + void addLimit(Px1DConstraint* c, const PxJointLimitParameters& limit) + { + PxU16 flags = PxU16(c->flags | Px1DConstraintFlag::eOUTPUT_FORCE); + + if(limit.isSoft()) + { + flags |= Px1DConstraintFlag::eSPRING; + c->mods.spring.stiffness = limit.stiffness; + c->mods.spring.damping = limit.damping; + } + else + { + c->solveHint = PxConstraintSolveHint::eINEQUALITY; + c->mods.bounce.restitution = limit.restitution; + c->mods.bounce.velocityThreshold = limit.bounceThreshold; + if(c->geometricError>0) + flags |= Px1DConstraintFlag::eKEEPBIAS; + if(limit.restitution>0) + flags |= Px1DConstraintFlag::eRESTITUTION; + } + + c->flags = flags; + c->minImpulse = 0; + } + + void addDrive(Px1DConstraint* c, PxReal velTarget, const PxD6JointDrive& drive) + { + c->velocityTarget = velTarget; + + PxU16 flags = PxU16(c->flags | Px1DConstraintFlag::eSPRING | Px1DConstraintFlag::eHAS_DRIVE_LIMIT); + if(drive.flags & PxD6JointDriveFlag::eACCELERATION) + flags |= Px1DConstraintFlag::eACCELERATION_SPRING; + c->flags = flags; + c->mods.spring.stiffness = drive.stiffness; + c->mods.spring.damping = drive.damping; + + c->minImpulse = -drive.forceLimit; + c->maxImpulse = drive.forceLimit; + + PX_ASSERT(c->linear0.isFinite()); + PX_ASSERT(c->angular0.isFinite()); + } + }; + } +} // namespace + +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtConvexMeshExt.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtConvexMeshExt.cpp new file mode 100644 index 00000000..ef0aab39 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtConvexMeshExt.cpp @@ -0,0 +1,91 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "PxConvexMeshExt.h" +#include "PxConvexMeshGeometry.h" +#include "PxConvexMesh.h" +#include "foundation/PxTransform.h" + +using namespace physx; + +static const PxReal gEpsilon = .01f; + +PxU32 physx::PxFindFaceIndex(const PxConvexMeshGeometry& convexGeom, const PxTransform& pose, + const PxVec3& impactPos, const PxVec3& unitDir) +{ + PX_ASSERT(unitDir.isFinite()); + PX_ASSERT(unitDir.isNormalized()); + PX_ASSERT(impactPos.isFinite()); + PX_ASSERT(pose.isFinite()); + + const PxVec3 impact = impactPos - unitDir * gEpsilon; + + const PxVec3 localPoint = pose.transformInv(impact); + const PxVec3 localDir = pose.rotateInv(unitDir); + + // Create shape to vertex scale transformation matrix + const PxMeshScale& meshScale = convexGeom.scale; + const PxMat33 rot(meshScale.rotation); + PxMat33 shape2VertexSkew = rot.getTranspose(); + const PxMat33 diagonal = PxMat33::createDiagonal(PxVec3(1.0f / meshScale.scale.x, 1.0f / meshScale.scale.y, 1.0f / meshScale.scale.z)); + shape2VertexSkew = shape2VertexSkew * diagonal; + shape2VertexSkew = shape2VertexSkew * rot; + + const PxU32 nbPolys = convexGeom.convexMesh->getNbPolygons(); + PxU32 minIndex = 0; + PxReal minD = PX_MAX_REAL; + for (PxU32 j = 0; j < nbPolys; j++) + { + PxHullPolygon hullPolygon; + convexGeom.convexMesh->getPolygonData(j, hullPolygon); + + // transform hull plane into shape space + PxPlane plane; + const PxVec3 tmp = shape2VertexSkew.transformTranspose(PxVec3(hullPolygon.mPlane[0],hullPolygon.mPlane[1],hullPolygon.mPlane[2])); + const PxReal denom = 1.0f / tmp.magnitude(); + plane.n = tmp * denom; + plane.d = hullPolygon.mPlane[3] * denom; + + PxReal d = plane.distance(localPoint); + if (d < 0.0f) + continue; + + const PxReal tweak = plane.n.dot(localDir) * gEpsilon; + d += tweak; + + if (d < minD) + { + minIndex = j; + minD = d; + } + } + return minIndex; +} + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtCpuWorkerThread.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtCpuWorkerThread.cpp new file mode 100644 index 00000000..fb977c36 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtCpuWorkerThread.cpp @@ -0,0 +1,106 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "task/PxTask.h" +#include "ExtCpuWorkerThread.h" +#include "ExtDefaultCpuDispatcher.h" +#include "ExtTaskQueueHelper.h" +#include "PsFPU.h" + +using namespace physx; + +Ext::CpuWorkerThread::CpuWorkerThread() +: mQueueEntryPool(EXT_TASK_QUEUE_ENTRY_POOL_SIZE), + mThreadId(0) +{ +} + + +Ext::CpuWorkerThread::~CpuWorkerThread() +{ +} + + +void Ext::CpuWorkerThread::initialize(DefaultCpuDispatcher* ownerDispatcher) +{ + mOwner = ownerDispatcher; +} + + +bool Ext::CpuWorkerThread::tryAcceptJobToLocalQueue(PxBaseTask& task, Ps::Thread::Id taskSubmitionThread) +{ + if(taskSubmitionThread == mThreadId) + { + SharedQueueEntry* entry = mQueueEntryPool.getEntry(&task); + if (entry) + { + mLocalJobList.push(*entry); + return true; + } + else + return false; + } + + return false; +} + + +PxBaseTask* Ext::CpuWorkerThread::giveUpJob() +{ + return TaskQueueHelper::fetchTask(mLocalJobList, mQueueEntryPool); +} + + +void Ext::CpuWorkerThread::execute() +{ + mThreadId = getId(); + + while (!quitIsSignalled()) + { + mOwner->resetWakeSignal(); + + PxBaseTask* task = TaskQueueHelper::fetchTask(mLocalJobList, mQueueEntryPool); + + if(!task) + task = mOwner->fetchNextTask(); + + if (task) + { + mOwner->runTask(*task); + task->release(); + } + else + { + mOwner->waitForWork(); + } + } + + quit(); +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtCpuWorkerThread.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtCpuWorkerThread.h new file mode 100644 index 00000000..e1f1c82d --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtCpuWorkerThread.h @@ -0,0 +1,79 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_NP_CPU_WORKER_THREAD_H +#define PX_PHYSICS_EXTENSIONS_NP_CPU_WORKER_THREAD_H + +#include "CmPhysXCommon.h" +#include "PsThread.h" +#include "ExtDefaultCpuDispatcher.h" +#include "ExtSharedQueueEntryPool.h" + + +namespace physx +{ +namespace Ext +{ +class DefaultCpuDispatcher; + + +#if PX_VC +#pragma warning(push) +#pragma warning(disable:4324) // Padding was added at the end of a structure because of a __declspec(align) value. +#endif // Because of the SList member I assume + + class CpuWorkerThread : public Ps::Thread + { + public: + CpuWorkerThread(); + ~CpuWorkerThread(); + + void initialize(DefaultCpuDispatcher* ownerDispatcher); + void execute(); + bool tryAcceptJobToLocalQueue(PxBaseTask& task, Ps::Thread::Id taskSubmitionThread); + PxBaseTask* giveUpJob(); + Ps::Thread::Id getWorkerThreadId() const { return mThreadId; } + + protected: + SharedQueueEntryPool<> mQueueEntryPool; + DefaultCpuDispatcher* mOwner; + Ps::SList mLocalJobList; + Ps::Thread::Id mThreadId; + }; + +#if PX_VC +#pragma warning(pop) +#endif + +} // namespace Ext + +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtD6Joint.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtD6Joint.cpp new file mode 100644 index 00000000..5fdad2e7 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtD6Joint.cpp @@ -0,0 +1,564 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "ExtD6Joint.h" +#include "ExtConstraintHelper.h" +#include "CmRenderOutput.h" +#include "CmConeLimitHelper.h" +#include "PxTolerancesScale.h" +#include "CmUtils.h" +#include "PxConstraint.h" + +#include "common/PxSerialFramework.h" + +using namespace physx; +using namespace Ext; + +PxD6Joint* physx::PxD6JointCreate(PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) +{ + PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxD6JointCreate: local frame 0 is not a valid transform"); + PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxD6JointCreate: local frame 1 is not a valid transform"); + PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxD6JointCreate: actors must be different"); + PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxD6JointCreate: at least one actor must be dynamic"); + + D6Joint *j; + PX_NEW_SERIALIZED(j,D6Joint)(physics.getTolerancesScale(), actor0, localFrame0, actor1, localFrame1); + if(j->attach(physics, actor0, actor1)) + return j; + + PX_DELETE(j); + return NULL; +} + + + +D6Joint::D6Joint(const PxTolerancesScale& scale, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) +: D6JointT(PxJointConcreteType::eD6, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE) +, mRecomputeMotion(true) +, mRecomputeLimits(true) +{ + D6JointData* data = reinterpret_cast<D6JointData*>(PX_ALLOC(sizeof(D6JointData), "D6JointData")); + Cm::markSerializedMem(data, sizeof(D6JointData)); + mData = data; + + initCommonData(*data,actor0, localFrame0, actor1, localFrame1); + for(PxU32 i=0;i<6;i++) + data->motion[i] = PxD6Motion::eLOCKED; + + data->twistLimit = PxJointAngularLimitPair(-PxPi/2, PxPi/2); + data->swingLimit = PxJointLimitCone(PxPi/2, PxPi/2); + data->linearLimit = PxJointLinearLimit(scale, PX_MAX_F32); + data->linearMinDist = 1e-6f*scale.length; + + for(PxU32 i=0;i<PxD6Drive::eCOUNT;i++) + data->drive[i] = PxD6JointDrive(); + + data->drivePosition = PxTransform(PxIdentity); + data->driveLinearVelocity = PxVec3(0); + data->driveAngularVelocity = PxVec3(0); + + data->projectionLinearTolerance = 1e10; + data->projectionAngularTolerance = PxPi; +} + +PxD6Motion::Enum D6Joint::getMotion(PxD6Axis::Enum index) const +{ + return data().motion[index]; +} + +void D6Joint::setMotion(PxD6Axis::Enum index, PxD6Motion::Enum t) +{ + data().motion[index] = t; + mRecomputeMotion = true; + markDirty(); +} + +PxReal D6Joint::getTwist() const +{ + PxQuat q = getRelativeTransform().q, swing, twist; + Ps::separateSwingTwist(q, swing, twist); + if (twist.x < 0) + twist = -twist; + PxReal angle = twist.getAngle(); // angle is in range [0, 2pi] + return angle < PxPi ? angle : angle - PxTwoPi; +} + +PxReal D6Joint::getSwingYAngle() const +{ + PxQuat q = getRelativeTransform().q, swing, twist; + Ps::separateSwingTwist(q, swing, twist); + if (swing.w < 0) // choose the shortest rotation + swing = -swing; + + PxReal angle = 4 * PxAtan2(swing.y, 1 + swing.w); // tan (t/2) = sin(t)/(1+cos t), so this is the quarter angle + PX_ASSERT(angle>-PxPi && angle<=PxPi); // since |y| < w+1, the atan magnitude is < PI/4 + return angle; +} + +PxReal D6Joint::getSwingZAngle() const +{ + PxQuat q = getRelativeTransform().q, swing, twist; + Ps::separateSwingTwist(q, swing, twist); + if (swing.w < 0) // choose the shortest rotation + swing = -swing; + + PxReal angle = 4 * PxAtan2(swing.z, 1 + swing.w); // tan (t/2) = sin(t)/(1+cos t), so this is the quarter angle + PX_ASSERT(angle>-PxPi && angle <= PxPi); // since |y| < w+1, the atan magnitude is < PI/4 + return angle; +} + + +PxD6JointDrive D6Joint::getDrive(PxD6Drive::Enum index) const +{ + return data().drive[index]; +} + +void D6Joint::setDrive(PxD6Drive::Enum index, const PxD6JointDrive& d) +{ + PX_CHECK_AND_RETURN(d.isValid(), "PxD6Joint::setDrive: drive is invalid"); + + data().drive[index] = d; + mRecomputeMotion = true; + markDirty(); +} + +PxJointLinearLimit D6Joint::getLinearLimit() const +{ + + return data().linearLimit; +} + +void D6Joint::setLinearLimit(const PxJointLinearLimit& l) +{ + PX_CHECK_AND_RETURN(l.isValid(), "PxD6Joint::setLinearLimit: limit invalid"); + data().linearLimit = l; + mRecomputeLimits = true; + markDirty(); +} + +PxJointAngularLimitPair D6Joint::getTwistLimit() const +{ + return data().twistLimit; +} + +void D6Joint::setTwistLimit(const PxJointAngularLimitPair& l) +{ + PX_CHECK_AND_RETURN(l.isValid(), "PxD6Joint::setTwistLimit: limit invalid"); + PX_CHECK_AND_RETURN(l.lower>-PxTwoPi && l.upper<PxTwoPi , "PxD6Joint::twist limit must be strictly -2*PI and 2*PI"); + PX_CHECK_AND_RETURN(l.upper - l.lower < PxTwoPi, "PxD6Joint::twist limit range must be strictly less than 2*PI"); + + data().twistLimit = l; + mRecomputeLimits = true; + markDirty(); +} + +PxJointLimitCone D6Joint::getSwingLimit() const +{ + return data().swingLimit; +} + +void D6Joint::setSwingLimit(const PxJointLimitCone& l) +{ + PX_CHECK_AND_RETURN(l.isValid(), "PxD6Joint::setSwingLimit: limit invalid"); + + data().swingLimit = l; + mRecomputeLimits = true; + markDirty(); +} + +PxTransform D6Joint::getDrivePosition() const +{ + return data().drivePosition; +} + +void D6Joint::setDrivePosition(const PxTransform& pose) +{ + PX_CHECK_AND_RETURN(pose.isSane(), "PxD6Joint::setDrivePosition: pose invalid"); + data().drivePosition = pose.getNormalized(); + markDirty(); +} + +void D6Joint::getDriveVelocity(PxVec3& linear, PxVec3& angular) const +{ + linear = data().driveLinearVelocity; + angular = data().driveAngularVelocity; +} + +void D6Joint::setDriveVelocity(const PxVec3& linear, + const PxVec3& angular) +{ + PX_CHECK_AND_RETURN(linear.isFinite() && angular.isFinite(), "PxD6Joint::setDriveVelocity: velocity invalid"); + data().driveLinearVelocity = linear; + data().driveAngularVelocity = angular; + markDirty(); +} + +void D6Joint::setProjectionAngularTolerance(PxReal tolerance) +{ + PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance >=0 && tolerance <= PxPi, "PxD6Joint::setProjectionAngularTolerance: tolerance invalid"); + data().projectionAngularTolerance = tolerance; + markDirty(); +} + +PxReal D6Joint::getProjectionAngularTolerance() const +{ + return data().projectionAngularTolerance; +} + +void D6Joint::setProjectionLinearTolerance(PxReal tolerance) +{ + PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance >=0, "PxD6Joint::setProjectionLinearTolerance: invalid parameter"); + data().projectionLinearTolerance = tolerance; + markDirty(); +} + +PxReal D6Joint::getProjectionLinearTolerance() const +{ + return data().projectionLinearTolerance; +} + + + +void* D6Joint::prepareData() +{ + D6JointData& d = data(); + + if(mRecomputeLimits) + { + d.thSwingY = PxTan(d.swingLimit.yAngle/2); + d.thSwingZ = PxTan(d.swingLimit.zAngle/2); + d.thSwingPad = PxTan(d.swingLimit.contactDistance/2); + + d.tqSwingY = PxTan(d.swingLimit.yAngle/4); + d.tqSwingZ = PxTan(d.swingLimit.zAngle/4); + d.tqSwingPad = PxTan(d.swingLimit.contactDistance/4); + + d.tqTwistLow = PxTan(d.twistLimit.lower/4); + d.tqTwistHigh = PxTan(d.twistLimit.upper/4); + d.tqTwistPad = PxTan(d.twistLimit.contactDistance/4); + mRecomputeLimits = false; + } + + if(mRecomputeMotion) + { + d.driving = 0; + d.limited = 0; + d.locked = 0; + + for(PxU32 i=0;i<PxD6Axis::eCOUNT;i++) + { + if(d.motion[i] == PxD6Motion::eLIMITED) + d.limited |= 1<<i; + else if(d.motion[i] == PxD6Motion::eLOCKED) + d.locked |= 1<<i; + } + + // a linear direction isn't driven if it's locked + if(active(PxD6Drive::eX) && d.motion[PxD6Axis::eX]!=PxD6Motion::eLOCKED) d.driving |= 1<< PxD6Drive::eX; + if(active(PxD6Drive::eY) && d.motion[PxD6Axis::eY]!=PxD6Motion::eLOCKED) d.driving |= 1<< PxD6Drive::eY; + if(active(PxD6Drive::eZ) && d.motion[PxD6Axis::eZ]!=PxD6Motion::eLOCKED) d.driving |= 1<< PxD6Drive::eZ; + + // SLERP drive requires all angular dofs unlocked, and inhibits swing/twist + + bool swing1Locked = d.motion[PxD6Axis::eSWING1] == PxD6Motion::eLOCKED; + bool swing2Locked = d.motion[PxD6Axis::eSWING2] == PxD6Motion::eLOCKED; + bool twistLocked = d.motion[PxD6Axis::eTWIST] == PxD6Motion::eLOCKED; + + if(active(PxD6Drive::eSLERP) && !swing1Locked && !swing2Locked && !twistLocked) + d.driving |= 1<<PxD6Drive::eSLERP; + else + { + if(active(PxD6Drive::eTWIST) && !twistLocked) + d.driving |= 1<<PxD6Drive::eTWIST; + if(active(PxD6Drive::eSWING) && (!swing1Locked || !swing2Locked)) + d.driving |= 1<< PxD6Drive::eSWING; + } + + mRecomputeMotion = false; + } + + this->D6JointT::prepareData(); + + return mData; +} + +// Notes: +/* + +This used to be in the linear drive model: + + if(motion[PxD6Axis::eX+i] == PxD6Motion::eLIMITED) + { + if(data.driveLinearVelocity[i] < 0.0f && cB2cA.p[i] < -mLimits[PxD6Limit::eLINEAR].mValue || + data.driveLinearVelocity[i] > 0.0f && cB2cA.p[i] > mLimits[PxD6Limit::eLINEAR].mValue) + continue; + } + +it doesn't seem like a good idea though, because it turns off drive altogether, despite the fact that positional +drive might pull us back in towards the limit. Might be better to make the drive unilateral so it can only pull +us in from the limit + +This used to be in angular locked: + + // Angular locked + //TODO fix this properly. + if(PxAbs(cB2cA.q.x) < 0.0001f) cB2cA.q.x = 0; + if(PxAbs(cB2cA.q.y) < 0.0001f) cB2cA.q.y = 0; + if(PxAbs(cB2cA.q.z) < 0.0001f) cB2cA.q.z = 0; + if(PxAbs(cB2cA.q.w) < 0.0001f) cB2cA.q.w = 0; + + +*/ + +namespace +{ +PxReal tanHalfFromSin(PxReal sin) +{ + return Ps::tanHalf(sin, 1 - sin*sin); +} + +PxQuat truncate(const PxQuat& qIn, PxReal minCosHalfTol, bool& truncated) +{ + PxQuat q = qIn.w >= 0 ? qIn : -qIn; + truncated = q.w < minCosHalfTol; + if (!truncated) + return q; + PxVec3 v = q.getImaginaryPart().getNormalized() * PxSqrt(1 - minCosHalfTol * minCosHalfTol); + return PxQuat(v.x, v.y, v.z, minCosHalfTol); +} + +// we decompose the quaternion as q1 * q2, where q1 is a rotation orthogonal to the unit axis, and q2 a rotation around it. +// (so for example if 'axis' is the twist axis, this is separateSwingTwist). + +PxQuat project(const PxQuat& q, const PxVec3& axis, PxReal cosHalfTol, bool& truncated) +{ + PxReal a = q.getImaginaryPart().dot(axis); + PxQuat q2 = PxAbs(a) >= 1e-6f ? PxQuat(a*axis.x, a*axis.y, a*axis.z, q.w).getNormalized() : PxQuat(PxIdentity); + PxQuat q1 = q * q2.getConjugate(); + + PX_ASSERT(PxAbs(q1.getImaginaryPart().dot(q2.getImaginaryPart())) < 1e-6f); + + return truncate(q1, cosHalfTol, truncated) * q2; +} +} + +namespace physx +{ +// Here's how the angular part works: +// * if no DOFs are locked, there's nothing to do. +// * if all DOFs are locked, we just truncate the rotation +// * if two DOFs are locked +// * we decompose the rotation into swing * twist, where twist is a rotation around the free DOF and swing is a rotation around an axis orthogonal to the free DOF +// * then we truncate swing +// The case of one locked DOF is currently unimplemented, but one option would be: +// * if one DOF is locked (the tricky case), we define the 'free' axis as follows (as the velocity solver prep function does) +// TWIST: cB[0] +// SWING1: cB[0].cross(cA[2]) +// SWING2: cB[0].cross(cA[1]) +// then, as above, we decompose into swing * free, and truncate the free rotation + +//export this in the physx namespace so we can unit test it +PxQuat angularProject(PxU32 lockedDofs, const PxQuat& q, PxReal cosHalfTol, bool& truncated) +{ + PX_ASSERT(lockedDofs <= 7); + truncated = false; + + switch (lockedDofs) + { + case 0: return q; + case 1: return q; // currently unimplemented + case 2: return q; // currently unimplemented + case 3: return project(q, PxVec3(0.0f, 0.0f, 1.0f), cosHalfTol, truncated); + case 4: return q; // currently unimplemented + case 5: return project(q, PxVec3(0.0f, 1.0f, 0.0f), cosHalfTol, truncated); + case 6: return project(q, PxVec3(1.0f, 0.0f, 0.0f), cosHalfTol, truncated); + case 7: return truncate(q, cosHalfTol, truncated); + default: return PxQuat(PxIdentity); + } +} +} + +namespace +{ +void D6JointProject(const void* constantBlock, + PxTransform& bodyAToWorld, + PxTransform& bodyBToWorld, + bool projectToA) +{ + using namespace joint; + const D6JointData &data = *reinterpret_cast<const D6JointData*>(constantBlock); + + PxTransform cA2w, cB2w, cB2cA, projected; + computeDerived(data, bodyAToWorld, bodyBToWorld, cA2w, cB2w, cB2cA); + + PxVec3 v(data.locked & 1 ? cB2cA.p.x : 0, + data.locked & 2 ? cB2cA.p.y : 0, + data.locked & 4 ? cB2cA.p.z : 0); + + bool linearTrunc, angularTrunc = false; + projected.p = truncateLinear(v, data.projectionLinearTolerance, linearTrunc) + (cB2cA.p - v); + + projected.q = angularProject(data.locked >> 3, cB2cA.q, PxCos(data.projectionAngularTolerance / 2), angularTrunc); + + if (linearTrunc || angularTrunc) + projectTransforms(bodyAToWorld, bodyBToWorld, cA2w, cB2w, projected, data, projectToA); +} + + +void D6JointVisualize(PxConstraintVisualizer &viz, + const void* constantBlock, + const PxTransform& body0Transform, + const PxTransform& body1Transform, + PxU32 /*flags*/) +{ + using namespace joint; + + const PxU32 SWING1_FLAG = 1<<PxD6Axis::eSWING1, + SWING2_FLAG = 1<<PxD6Axis::eSWING2, + TWIST_FLAG = 1<<PxD6Axis::eTWIST; + + const PxU32 ANGULAR_MASK = SWING1_FLAG | SWING2_FLAG | TWIST_FLAG; + const PxU32 LINEAR_MASK = 1<<PxD6Axis::eX | 1<<PxD6Axis::eY | 1<<PxD6Axis::eZ; + + PX_UNUSED(ANGULAR_MASK); + PX_UNUSED(LINEAR_MASK); + + const D6JointData & data = *reinterpret_cast<const D6JointData*>(constantBlock); + + PxTransform cA2w = body0Transform * data.c2b[0]; + PxTransform cB2w = body1Transform * data.c2b[1]; + + viz.visualizeJointFrames(cA2w, cB2w); + + if(cA2w.q.dot(cB2w.q)<0) + cB2w.q = -cB2w.q; + + PxTransform cB2cA = cA2w.transformInv(cB2w); + + PxQuat swing, twist; + Ps::separateSwingTwist(cB2cA.q,swing,twist); + + PxMat33 cA2w_m(cA2w.q), cB2w_m(cB2w.q); + PxVec3 bX = cB2w_m[0], aY = cA2w_m[1], aZ = cA2w_m[2]; + + if(data.limited&TWIST_FLAG) + { + PxReal tqPhi = Ps::tanHalf(twist.x, twist.w); // always support (-pi, +pi) + viz.visualizeAngularLimit(cA2w, data.twistLimit.lower, data.twistLimit.upper, + PxAbs(tqPhi) > data.tqTwistHigh + data.tqSwingPad); + } + + bool swing1Limited = (data.limited & SWING1_FLAG)!=0, swing2Limited = (data.limited & SWING2_FLAG)!=0; + + if(swing1Limited && swing2Limited) + { + PxVec3 tanQSwing = PxVec3(0, Ps::tanHalf(swing.z,swing.w), -Ps::tanHalf(swing.y,swing.w)); + Cm::ConeLimitHelper coneHelper(data.tqSwingZ, data.tqSwingY, data.tqSwingPad); + viz.visualizeLimitCone(cA2w, data.tqSwingZ, data.tqSwingY, + !coneHelper.contains(tanQSwing)); + } + else if(swing1Limited ^ swing2Limited) + { + PxTransform yToX = PxTransform(PxVec3(0), PxQuat(-PxPi/2, PxVec3(0,0,1.f))); + PxTransform zToX = PxTransform(PxVec3(0), PxQuat(PxPi/2, PxVec3(0,1.f,0))); + + if(swing1Limited) + { + if(data.locked & SWING2_FLAG) + viz.visualizeAngularLimit(cA2w * yToX, -data.swingLimit.yAngle, data.swingLimit.yAngle, + PxAbs(Ps::tanHalf(swing.y, swing.w)) > data.tqSwingY - data.tqSwingPad); + else + viz.visualizeDoubleCone(cA2w * zToX, data.swingLimit.yAngle, + PxAbs(tanHalfFromSin(aZ.dot(bX)))> data.thSwingY - data.thSwingPad); + } + else + { + if(data.locked & SWING1_FLAG) + viz.visualizeAngularLimit(cA2w * zToX, -data.swingLimit.zAngle, data.swingLimit.zAngle, + PxAbs(Ps::tanHalf(swing.z, swing.w)) > data.tqSwingZ - data.tqSwingPad); + else + viz.visualizeDoubleCone(cA2w * yToX, data.swingLimit.zAngle, + PxAbs(tanHalfFromSin(aY.dot(bX)))> data.thSwingZ - data.thSwingPad); + } + } +} +} + +bool D6Joint::attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1) +{ + mPxConstraint = physics.createConstraint(actor0, actor1, *this, sShaders, sizeof(D6JointData)); + return mPxConstraint!=NULL; +} + +void D6Joint::exportExtraData(PxSerializationContext& stream) +{ + if(mData) + { + stream.alignData(PX_SERIAL_ALIGN); + stream.writeData(mData, sizeof(D6JointData)); + } + stream.writeName(mName); +} + +void D6Joint::importExtraData(PxDeserializationContext& context) +{ + if(mData) + mData = context.readExtraData<D6JointData, PX_SERIAL_ALIGN>(); + + context.readName(mName); +} + +void D6Joint::resolveReferences(PxDeserializationContext& context) +{ + setPxConstraint(resolveConstraintPtr(context, getPxConstraint(), getConnector(), sShaders)); +} + +D6Joint* D6Joint::createObject(PxU8*& address, PxDeserializationContext& context) +{ + D6Joint* obj = new (address) D6Joint(PxBaseFlag::eIS_RELEASABLE); + address += sizeof(D6Joint); + obj->importExtraData(context); + obj->resolveReferences(context); + return obj; +} + +// global function to share the joint shaders with API capture +const PxConstraintShaderTable* Ext::GetD6JointShaderTable() +{ + return &D6Joint::getConstraintShaderTable(); +} + +//~PX_SERIALIZATION +PxConstraintShaderTable Ext::D6Joint::sShaders = { Ext::D6JointSolverPrep, D6JointProject, D6JointVisualize, PxConstraintFlag::eGPU_COMPATIBLE }; + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtD6Joint.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtD6Joint.h new file mode 100644 index 00000000..b789c688 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtD6Joint.h @@ -0,0 +1,207 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef NP_D6JOINTCONSTRAINT_H +#define NP_D6JOINTCONSTRAINT_H + +#include "ExtJoint.h" +#include "PxD6Joint.h" + +namespace physx +{ +struct PxD6JointGeneratedValues; +namespace Ext +{ + struct D6JointData : public JointData + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + + PxD6Motion::Enum motion[6]; + PxJointLinearLimit linearLimit; + PxJointAngularLimitPair twistLimit; + PxJointLimitCone swingLimit; + + PxD6JointDrive drive[PxD6Drive::eCOUNT]; + + PxTransform drivePosition; + PxVec3 driveLinearVelocity; + PxVec3 driveAngularVelocity; + + // derived quantities + + PxU32 locked; // bitmap of locked DOFs + PxU32 limited; // bitmap of limited DOFs + PxU32 driving; // bitmap of active drives (implies driven DOFs not locked) + + // tan-half and tan-quarter angles + + PxReal thSwingY; + PxReal thSwingZ; + PxReal thSwingPad; + + PxReal tqSwingY; + PxReal tqSwingZ; + PxReal tqSwingPad; + + PxReal tqTwistLow; + PxReal tqTwistHigh; + PxReal tqTwistPad; + + PxReal linearMinDist; // linear limit minimum distance to get a good direction + + // projection quantities + PxReal projectionLinearTolerance; + PxReal projectionAngularTolerance; + + // forestall compiler complaints about not being able to generate a constructor + private: + D6JointData(const PxJointLinearLimit& linear, const PxJointAngularLimitPair& twist, const PxJointLimitCone& swing): + linearLimit(linear), twistLimit(twist), swingLimit(swing) {} + }; + + typedef Joint<PxD6Joint, PxD6JointGeneratedValues> D6JointT; + + class D6Joint : public Joint<PxD6Joint, PxD6JointGeneratedValues> + { + public: +// PX_SERIALIZATION + D6Joint(PxBaseFlags baseFlags) : D6JointT(baseFlags) {} + virtual void exportExtraData(PxSerializationContext& context); + void importExtraData(PxDeserializationContext& context); + void resolveReferences(PxDeserializationContext& context); + static D6Joint* createObject(PxU8*& address, PxDeserializationContext& context); + static void getBinaryMetaData(PxOutputStream& stream); +//~PX_SERIALIZATION + virtual ~D6Joint() + { + if(getBaseFlags()&PxBaseFlag::eOWNS_MEMORY) + PX_FREE(mData); + } + + D6Joint(const PxTolerancesScale& scale, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1); + + + PxReal getTwist() const; + PxReal getSwingYAngle() const; + PxReal getSwingZAngle() const; + + + PxD6Motion::Enum getMotion(PxD6Axis::Enum index) const; + void setMotion(PxD6Axis::Enum index, PxD6Motion::Enum t); + + PxD6JointDrive getDrive(PxD6Drive::Enum index) const; + void setDrive(PxD6Drive::Enum index, const PxD6JointDrive& d); + + PxJointLinearLimit getLinearLimit() const; + void setLinearLimit(const PxJointLinearLimit& l); + + PxJointAngularLimitPair getTwistLimit() const; + void setTwistLimit(const PxJointAngularLimitPair& l); + + PxJointLimitCone getSwingLimit() const; + void setSwingLimit(const PxJointLimitCone& l); + + PxTransform getDrivePosition() const; + void setDrivePosition(const PxTransform& pose); + + void getDriveVelocity(PxVec3& linear, + PxVec3& angular) const; + + void setDriveVelocity(const PxVec3& linear, + const PxVec3& angular); + + void setProjectionAngularTolerance(PxReal tolerance); + PxReal getProjectionAngularTolerance() const; + + void setProjectionLinearTolerance(PxReal tolerance); + PxReal getProjectionLinearTolerance() const; + + void visualize(PxRenderBuffer& out, + const void* constantBlock, + const PxTransform& body0Transform, + const PxTransform& body1Transform, + PxReal frameScale, + PxReal limitScale, + PxU32 flags) const; + + bool attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1); + + static const PxConstraintShaderTable& getConstraintShaderTable() { return sShaders; } + + virtual PxConstraintSolverPrep getPrep() const { return sShaders.solverPrep; } + + private: + + static PxConstraintShaderTable sShaders; + + D6JointData& data() const + { + return *static_cast<D6JointData*>(mData); + } + + bool active(const PxD6Drive::Enum index) const + { + PxD6JointDrive& d = data().drive[index]; + return d.stiffness!=0 || d.damping != 0; + } + + void* prepareData(); + + bool mRecomputeMotion; + bool mRecomputeLimits; + bool mPadding[2]; // PT: padding from prev bools + }; + +} // namespace Ext + +namespace Ext +{ + extern "C" PxU32 D6JointSolverPrep(Px1DConstraint* constraints, + PxVec3& body0WorldOffset, + PxU32 maxConstraints, + PxConstraintInvMassScale& invMassScale, + const void* constantBlock, + const PxTransform& bA2w, + const PxTransform& bB2w); + + // global function to share the joint shaders with API capture + extern "C" const PxConstraintShaderTable* GetD6JointShaderTable(); +} + +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtD6JointSolverPrep.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtD6JointSolverPrep.cpp new file mode 100644 index 00000000..498bb0e4 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtD6JointSolverPrep.cpp @@ -0,0 +1,232 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "ExtD6Joint.h" +#include "ExtConstraintHelper.h" +#include "CmConeLimitHelper.h" + +namespace physx +{ +namespace Ext +{ + PxU32 D6JointSolverPrep(Px1DConstraint* constraints, + PxVec3& body0WorldOffset, + PxU32 maxConstraints, + PxConstraintInvMassScale& invMassScale, + const void* constantBlock, + const PxTransform& bA2w, + const PxTransform& bB2w) + { + PX_UNUSED(maxConstraints); + + using namespace joint; + + PX_UNUSED(maxConstraints); + const D6JointData& data = + *reinterpret_cast<const D6JointData*>(constantBlock); + + invMassScale = data.invMassScale; + + const PxU32 SWING1_FLAG = 1<<PxD6Axis::eSWING1, + SWING2_FLAG = 1<<PxD6Axis::eSWING2, + TWIST_FLAG = 1<<PxD6Axis::eTWIST; + + const PxU32 ANGULAR_MASK = SWING1_FLAG | SWING2_FLAG | TWIST_FLAG; + const PxU32 LINEAR_MASK = 1<<PxD6Axis::eX | 1<<PxD6Axis::eY | 1<<PxD6Axis::eZ; + + const PxD6JointDrive* drives = data.drive; + PxU32 locked = data.locked, limited = data.limited, driving = data.driving; + + PxTransform cA2w = bA2w.transform(data.c2b[0]); + PxTransform cB2w = bB2w.transform(data.c2b[1]); + + body0WorldOffset = cB2w.p-bA2w.p; + ConstraintHelper g(constraints, cB2w.p-bA2w.p, cB2w.p-bB2w.p); + + if(cA2w.q.dot(cB2w.q)<0) // minimum dist quat (equiv to flipping cB2bB.q, which we don't use anywhere) + cB2w.q = -cB2w.q; + + PxTransform cB2cA = cA2w.transformInv(cB2w); + + PX_ASSERT(data.c2b[0].isValid()); + PX_ASSERT(data.c2b[1].isValid()); + PX_ASSERT(cA2w.isValid()); + PX_ASSERT(cB2w.isValid()); + PX_ASSERT(cB2cA.isValid()); + + PxMat33 cA2w_m(cA2w.q), cB2w_m(cB2w.q); + + // handy for swing computation + PxVec3 bX = cB2w_m[0], aY = cA2w_m[1], aZ = cA2w_m[2]; + + if(driving & ((1<<PxD6Drive::eX)|(1<<PxD6Drive::eY)|(1<<PxD6Drive::eZ))) + { + // TODO: make drive unilateral if we are outside the limit + PxVec3 posErr = data.drivePosition.p - cB2cA.p; + for(PxU32 i = 0; i < 3; i++) + { + // -driveVelocity because velTarget is child (body1) - parent (body0) and Jacobian is 1 for body0 and -1 for parent + if(driving & (1<<(PxD6Drive::eX+i))) + g.linear(cA2w_m[i], -data.driveLinearVelocity[i], posErr[i], drives[PxD6Drive::eX+i]); + } + } + + if(driving & ((1<<PxD6Drive::eSLERP)|(1<<PxD6Drive::eSWING)|(1<<PxD6Drive::eTWIST))) + { + PxQuat d2cA_q = cB2cA.q.dot(data.drivePosition.q)>0 ? data.drivePosition.q : -data.drivePosition.q; + + const PxVec3& v = data.driveAngularVelocity; + PxQuat delta = d2cA_q.getConjugate() * cB2cA.q; + + if(driving & (1<<PxD6Drive::eSLERP)) + { + PxVec3 velTarget = -cA2w.rotate(data.driveAngularVelocity); + + PxVec3 axis[3] = { PxVec3(1.f,0,0), PxVec3(0,1.f,0), PxVec3(0,0,1.f) }; + + if(drives[PxD6Drive::eSLERP].stiffness!=0) + computeJacobianAxes(axis, cA2w.q * d2cA_q, cB2w.q); // converges faster if there is only velocity drive + + for(PxU32 i = 0; i < 3; i++) + g.angular(axis[i], axis[i].dot(velTarget), -delta.getImaginaryPart()[i], drives[PxD6Drive::eSLERP], PxConstraintSolveHint::eSLERP_SPRING); + } + else + { + if(driving & (1<<PxD6Drive::eTWIST)) + g.angular(bX, v.x, -2.0f * delta.x, drives[PxD6Drive::eTWIST]); + + if(driving & (1<<PxD6Drive::eSWING)) + { + PxVec3 err = delta.rotate(PxVec3(1.f,0,0)); + + if(!(locked & SWING1_FLAG)) + g.angular(cB2w_m[1], v.y, err.z, drives[PxD6Drive::eSWING]); + + if(!(locked & SWING2_FLAG)) + g.angular(cB2w_m[2], v.z, -err.y, drives[PxD6Drive::eSWING]); + } + } + } + + if (limited & ANGULAR_MASK) + { + PxQuat swing, twist; + Ps::separateSwingTwist(cB2cA.q,swing,twist); + + // swing limits: if just one is limited: if the other is free, we support + // (-pi/2, +pi/2) limit, using tan of the half-angle as the error measure parameter. + // If the other is locked, we support (-pi, +pi) limits using the tan of the quarter-angle + // Notation: th == Ps::tanHalf, tq = tanQuarter + + if(limited & SWING1_FLAG && limited & SWING2_FLAG) + { + Cm::ConeLimitHelper coneHelper(data.tqSwingZ, data.tqSwingY, data.tqSwingPad); + + PxVec3 axis; + PxReal error; + if(coneHelper.getLimit(swing, axis, error)) + g.angularLimit(cA2w.rotate(axis),error,data.swingLimit); + } + else + { + const PxJointLimitCone &limit = data.swingLimit; + + PxReal tqPad = data.tqSwingPad, thPad = data.thSwingPad; + + if(limited & SWING1_FLAG) + { + if(locked & SWING2_FLAG) + { + g.quarterAnglePair(Ps::tanHalf(swing.y, swing.w), -data.tqSwingY, data.tqSwingY, tqPad, aY, limit); + } + else + { + PxReal dot=-aZ.dot(bX); + g.halfAnglePair(Ps::tanHalf(dot, 1-dot*dot), -data.thSwingY, data.thSwingY, thPad, aZ.cross(bX), limit); + } + } + if(limited & SWING2_FLAG) + { + if(locked & SWING1_FLAG) + { + g.quarterAnglePair(Ps::tanHalf(swing.z, swing.w), -data.tqSwingZ, data.tqSwingZ, tqPad, aZ, limit); + } + else + { + PxReal dot=aY.dot(bX); + g.halfAnglePair(Ps::tanHalf(dot, 1-dot*dot), -data.thSwingZ, data.thSwingZ, thPad, -aY.cross(bX), limit); + } + } + } + + if(limited & TWIST_FLAG) + { + g.quarterAnglePair(Ps::tanHalf(twist.x, twist.w), data.tqTwistLow, data.tqTwistHigh, data.tqTwistPad, + cB2w_m[0], data.twistLimit); + } + } + + if(limited & LINEAR_MASK) + { + PxVec3 limitDir = PxVec3(0); + + for(PxU32 i = 0; i < 3; i++) + { + if(limited & (1<<(PxD6Axis::eX+i))) + limitDir += cA2w_m[i] * cB2cA.p[i]; + } + + PxReal distance = limitDir.magnitude(); + if(distance > data.linearMinDist) + g.linearLimit(limitDir * (1.0f/distance), distance, data.linearLimit.value, data.linearLimit); + } + + // we handle specially the case of just one swing dof locked + + PxU32 angularLocked = locked & ANGULAR_MASK; + + if(angularLocked == SWING1_FLAG) + { + g.angularHard(bX.cross(aZ), -bX.dot(aZ)); + locked &= ~SWING1_FLAG; + } + else if(angularLocked == SWING2_FLAG) + { + locked &= ~SWING2_FLAG; + g.angularHard(bX.cross(aY), -bX.dot(aY)); + } + + g.prepareLockedAxes(cA2w.q, cB2w.q, cB2cA.p,locked&7, locked>>3); + + return g.getCount(); + } +}//namespace + +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultCpuDispatcher.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultCpuDispatcher.cpp new file mode 100644 index 00000000..aef580b3 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultCpuDispatcher.cpp @@ -0,0 +1,236 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "task/PxTask.h" +#include "ExtDefaultCpuDispatcher.h" +#include "ExtCpuWorkerThread.h" +#include "ExtTaskQueueHelper.h" +#include "PsString.h" + +using namespace physx; + +namespace physx +{ + PxDefaultCpuDispatcher* PxDefaultCpuDispatcherCreate(PxU32 numThreads, PxU32* affinityMasks); +} + +PxDefaultCpuDispatcher* physx::PxDefaultCpuDispatcherCreate(PxU32 numThreads, PxU32* affinityMasks) +{ + return PX_NEW(Ext::DefaultCpuDispatcher)(numThreads, affinityMasks); +} + +#if !PX_PS4 && !PX_XBOXONE +void Ext::DefaultCpuDispatcher::getAffinityMasks(PxU32* affinityMasks, PxU32 threadCount) +{ + for(PxU32 i=0; i < threadCount; i++) + { + affinityMasks[i] = 0; + } +} +#endif + +Ext::DefaultCpuDispatcher::DefaultCpuDispatcher(PxU32 numThreads, PxU32* affinityMasks) + : mQueueEntryPool(EXT_TASK_QUEUE_ENTRY_POOL_SIZE, "QueueEntryPool"), mNumThreads(numThreads), mShuttingDown(false) +#if PX_PROFILE + ,mRunProfiled(true) +#else + ,mRunProfiled(false) +#endif +{ + PxU32* defaultAffinityMasks = NULL; + + if(!affinityMasks) + { + defaultAffinityMasks = reinterpret_cast<PxU32*>(PX_ALLOC(numThreads * sizeof(PxU32), "ThreadAffinityMasks")); + getAffinityMasks(defaultAffinityMasks, numThreads); + affinityMasks = defaultAffinityMasks; + } + + // initialize threads first, then start + + mWorkerThreads = reinterpret_cast<CpuWorkerThread*>(PX_ALLOC(numThreads * sizeof(CpuWorkerThread), "CpuWorkerThread")); + const PxU32 nameLength = 32; + mThreadNames = reinterpret_cast<PxU8*>(PX_ALLOC(nameLength * numThreads, "CpuWorkerThreadName")); + + if (mWorkerThreads) + { + for(PxU32 i = 0; i < numThreads; ++i) + { + PX_PLACEMENT_NEW(mWorkerThreads+i, CpuWorkerThread)(); + mWorkerThreads[i].initialize(this); + } + + for(PxU32 i = 0; i < numThreads; ++i) + { + mWorkerThreads[i].setAffinityMask(affinityMasks[i]); + mWorkerThreads[i].start(Ps::Thread::getDefaultStackSize()); + + if (mThreadNames) + { + char* threadName = reinterpret_cast<char*>(mThreadNames + (i*nameLength)); + Ps::snprintf(threadName, nameLength, "PxWorker%02d", i); + mWorkerThreads[i].setName(threadName); + } + } + + if (defaultAffinityMasks) + PX_FREE(defaultAffinityMasks); + } + else + { + mNumThreads = 0; + } +} + + +Ext::DefaultCpuDispatcher::~DefaultCpuDispatcher() +{ + for(PxU32 i = 0; i < mNumThreads; ++i) + mWorkerThreads[i].signalQuit(); + + mShuttingDown = true; + mWorkReady.set(); + for(PxU32 i = 0; i < mNumThreads; ++i) + mWorkerThreads[i].waitForQuit(); + + for(PxU32 i = 0; i < mNumThreads; ++i) + mWorkerThreads[i].~CpuWorkerThread(); + + PX_FREE(mWorkerThreads); + + if (mThreadNames) + PX_FREE(mThreadNames); +} + + +void Ext::DefaultCpuDispatcher::submitTask(PxBaseTask& task) +{ + Ps::Thread::Id currentThread = Ps::Thread::getId(); + if(!mNumThreads) + { + // no worker threads, run directly + if(mRunProfiled) + task.runProfiled(PxU32(currentThread)); + else + task.run(); + task.release(); + return; + } + + // TODO: Could use TLS to make this more efficient + for(PxU32 i = 0; i < mNumThreads; ++i) + { + if(mWorkerThreads[i].tryAcceptJobToLocalQueue(task, currentThread)) + return mWorkReady.set(); + } + + SharedQueueEntry* entry = mQueueEntryPool.getEntry(&task); + if (entry) + { + mJobList.push(*entry); + mWorkReady.set(); + } +} + +PxBaseTask* Ext::DefaultCpuDispatcher::fetchNextTask() +{ + PxBaseTask* task = getJob(); + + if(!task) + task = stealJob(); + + return task; +} + +void Ext::DefaultCpuDispatcher::runTask(PxBaseTask& task) +{ + if(mRunProfiled) + { + const PxU32 threadId = PxU32(Ps::Thread::getId()); + task.runProfiled(threadId); + } + else + task.run(); +} + +PxU32 Ext::DefaultCpuDispatcher::getWorkerCount() const +{ + return mNumThreads; +} + +void Ext::DefaultCpuDispatcher::release() +{ + PX_DELETE(this); +} + + +PxBaseTask* Ext::DefaultCpuDispatcher::getJob(void) +{ + return TaskQueueHelper::fetchTask(mJobList, mQueueEntryPool); +} + + +PxBaseTask* Ext::DefaultCpuDispatcher::stealJob() +{ + PxBaseTask* ret = NULL; + + for(PxU32 i = 0; i < mNumThreads; ++i) + { + ret = mWorkerThreads[i].giveUpJob(); + + if(ret != NULL) + break; + } + + return ret; +} + + +void Ext::DefaultCpuDispatcher::resetWakeSignal() +{ + mWorkReady.reset(); + + // The code below is necessary to avoid deadlocks on shut down. + // A thread usually loops as follows: + // while quit is not signaled + // 1) reset wake signal + // 2) fetch work + // 3) if work -> process + // 4) else -> wait for wake signal + // + // If a thread reaches 1) after the thread pool signaled wake up, + // the wake up sync gets reset and all other threads which have not + // passed 4) already will wait forever. + // The code below makes sure that on shutdown, the wake up signal gets + // sent again after it was reset + // + if (mShuttingDown) + mWorkReady.set(); +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultCpuDispatcher.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultCpuDispatcher.h new file mode 100644 index 00000000..ca9595c5 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultCpuDispatcher.h @@ -0,0 +1,111 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_NP_DEFAULT_CPU_DISPATCHER_H +#define PX_PHYSICS_EXTENSIONS_NP_DEFAULT_CPU_DISPATCHER_H + +#include "CmPhysXCommon.h" +#include "PsUserAllocated.h" +#include "PsSync.h" +#include "PsSList.h" +#include "PxDefaultCpuDispatcher.h" +#include "ExtSharedQueueEntryPool.h" + +namespace physx +{ + +namespace Ext +{ + class CpuWorkerThread; + +#if PX_VC +#pragma warning(push) +#pragma warning(disable:4324) // Padding was added at the end of a structure because of a __declspec(align) value. +#endif // Because of the SList member I assume + + class DefaultCpuDispatcher : public PxDefaultCpuDispatcher, public Ps::UserAllocated + { + friend class TaskQueueHelper; + + private: + DefaultCpuDispatcher() : mQueueEntryPool(0) {} + ~DefaultCpuDispatcher(); + + public: + DefaultCpuDispatcher(PxU32 numThreads, PxU32* affinityMasks); + + //--------------------------------------------------------------------------------- + // physx::CpuDispatcher implementation + //--------------------------------------------------------------------------------- + virtual void submitTask(PxBaseTask& task); + virtual PxU32 getWorkerCount() const; + + //--------------------------------------------------------------------------------- + // PxDefaultCpuDispatcher implementation + //--------------------------------------------------------------------------------- + virtual void release(); + + virtual void setRunProfiled(bool runProfiled) { mRunProfiled = runProfiled; } + + virtual bool getRunProfiled() const { return mRunProfiled; } + + //--------------------------------------------------------------------------------- + // DefaultCpuDispatcher + //--------------------------------------------------------------------------------- + PxBaseTask* getJob(); + PxBaseTask* stealJob(); + PxBaseTask* fetchNextTask(); + void runTask(PxBaseTask& task); + + void waitForWork() { mWorkReady.wait(); } + void resetWakeSignal(); + + static void getAffinityMasks(PxU32* affinityMasks, PxU32 threadCount); + + + protected: + CpuWorkerThread* mWorkerThreads; + SharedQueueEntryPool<> mQueueEntryPool; + Ps::SList mJobList; + Ps::Sync mWorkReady; + PxU8* mThreadNames; + PxU32 mNumThreads; + bool mShuttingDown; + bool mRunProfiled; + }; + +#if PX_VC +#pragma warning(pop) +#endif + +} // namespace Ext +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultErrorCallback.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultErrorCallback.cpp new file mode 100644 index 00000000..68ca7747 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultErrorCallback.cpp @@ -0,0 +1,104 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "foundation/PxAssert.h" +#include "PxDefaultErrorCallback.h" +#include "PsString.h" +#include "PsThread.h" +#include <stdio.h> + +using namespace physx; + + +PxDefaultErrorCallback::PxDefaultErrorCallback() +{ +} + +PxDefaultErrorCallback::~PxDefaultErrorCallback() +{ +} + +void PxDefaultErrorCallback::reportError(PxErrorCode::Enum e, const char* message, const char* file, int line) +{ + const char* errorCode = NULL; + + switch (e) + { + case PxErrorCode::eNO_ERROR: + errorCode = "no error"; + break; + case PxErrorCode::eINVALID_PARAMETER: + errorCode = "invalid parameter"; + break; + case PxErrorCode::eINVALID_OPERATION: + errorCode = "invalid operation"; + break; + case PxErrorCode::eOUT_OF_MEMORY: + errorCode = "out of memory"; + break; + case PxErrorCode::eDEBUG_INFO: + errorCode = "info"; + break; + case PxErrorCode::eDEBUG_WARNING: + errorCode = "warning"; + break; + case PxErrorCode::ePERF_WARNING: + errorCode = "performance warning"; + break; + case PxErrorCode::eABORT: + errorCode = "abort"; + break; + case PxErrorCode::eINTERNAL_ERROR: + errorCode = "internal error"; + break; + case PxErrorCode::eMASK_ALL: + errorCode = "unknown error"; + break; + } + + PX_ASSERT(errorCode); + if(errorCode) + { + char buffer[1024]; + sprintf(buffer, "%s (%d) : %s : %s\n", file, line, errorCode, message); + + physx::shdfnd::printString(buffer); + + // in debug builds halt execution for abort codes + PX_ASSERT(e != PxErrorCode::eABORT); + + // in release builds we also want to halt execution + // and make sure that the error message is flushed + while (e == PxErrorCode::eABORT) + { + physx::shdfnd::printString(buffer); + physx::shdfnd::Thread::sleep(1000); + } + } +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultSimulationFilterShader.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultSimulationFilterShader.cpp new file mode 100644 index 00000000..317b9696 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultSimulationFilterShader.cpp @@ -0,0 +1,386 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "PxDefaultSimulationFilterShader.h" +#include "PsIntrinsics.h" +#include "particles/PxParticleBase.h" +#include "cloth/PxCloth.h" +#include "PxRigidActor.h" +#include "PxShape.h" +#include "PsAllocator.h" +#include "CmPhysXCommon.h" +#include "PsInlineArray.h" +#include "PsFoundation.h" + +using namespace physx; + +namespace +{ + #define GROUP_SIZE 32 + + struct PxCollisionBitMap + { + PX_INLINE PxCollisionBitMap() : enable(true) {} + + bool operator()() const { return enable; } + bool& operator= (const bool &v) { enable = v; return enable; } + + private: + bool enable; + }; + + PxCollisionBitMap gCollisionTable[GROUP_SIZE][GROUP_SIZE]; + + PxFilterOp::Enum gFilterOps[3] = { PxFilterOp::PX_FILTEROP_AND, PxFilterOp::PX_FILTEROP_AND, PxFilterOp::PX_FILTEROP_AND }; + + PxGroupsMask gFilterConstants[2]; + + bool gFilterBool = false; + + static void gAND(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1) + { + results.bits0 = PxU16(mask0.bits0 & mask1.bits0); + results.bits1 = PxU16(mask0.bits1 & mask1.bits1); + results.bits2 = PxU16(mask0.bits2 & mask1.bits2); + results.bits3 = PxU16(mask0.bits3 & mask1.bits3); + } + static void gOR(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1) + { + results.bits0 = PxU16(mask0.bits0 | mask1.bits0); + results.bits1 = PxU16(mask0.bits1 | mask1.bits1); + results.bits2 = PxU16(mask0.bits2 | mask1.bits2); + results.bits3 = PxU16(mask0.bits3 | mask1.bits3); + } + static void gXOR(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1) + { + results.bits0 = PxU16(mask0.bits0 ^ mask1.bits0); + results.bits1 = PxU16(mask0.bits1 ^ mask1.bits1); + results.bits2 = PxU16(mask0.bits2 ^ mask1.bits2); + results.bits3 = PxU16(mask0.bits3 ^ mask1.bits3); + } + static void gNAND(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1) + { + results.bits0 = PxU16(~(mask0.bits0 & mask1.bits0)); + results.bits1 = PxU16(~(mask0.bits1 & mask1.bits1)); + results.bits2 = PxU16(~(mask0.bits2 & mask1.bits2)); + results.bits3 = PxU16(~(mask0.bits3 & mask1.bits3)); + } + static void gNOR(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1) + { + results.bits0 = PxU16(~(mask0.bits0 | mask1.bits0)); + results.bits1 = PxU16(~(mask0.bits1 | mask1.bits1)); + results.bits2 = PxU16(~(mask0.bits2 | mask1.bits2)); + results.bits3 = PxU16(~(mask0.bits3 | mask1.bits3)); + } + static void gNXOR(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1) + { + results.bits0 = PxU16(~(mask0.bits0 ^ mask1.bits0)); + results.bits1 = PxU16(~(mask0.bits1 ^ mask1.bits1)); + results.bits2 = PxU16(~(mask0.bits2 ^ mask1.bits2)); + results.bits3 = PxU16(~(mask0.bits3 ^ mask1.bits3)); + } + + static void gSWAP_AND(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1) + { + results.bits0 = PxU16(mask0.bits0 & mask1.bits2); + results.bits1 = PxU16(mask0.bits1 & mask1.bits3); + results.bits2 = PxU16(mask0.bits2 & mask1.bits0); + results.bits3 = PxU16(mask0.bits3 & mask1.bits1); + } + + typedef void (*FilterFunction) (PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1); + + FilterFunction const gTable[] = { gAND, gOR, gXOR, gNAND, gNOR, gNXOR, gSWAP_AND }; + + static PxFilterData convert(const PxGroupsMask& mask) + { + PxFilterData fd; + + fd.word2 = PxU32(mask.bits0 | (mask.bits1 << 16)); + fd.word3 = PxU32(mask.bits2 | (mask.bits3 << 16)); + + return fd; + } + + static PxGroupsMask convert(const PxFilterData& fd) + { + PxGroupsMask mask; + + mask.bits0 = PxU16((fd.word2 & 0xffff)); + mask.bits1 = PxU16((fd.word2 >> 16)); + mask.bits2 = PxU16((fd.word3 & 0xffff)); + mask.bits3 = PxU16((fd.word3 >> 16)); + + return mask; + } + + static bool getFilterData(const PxActor& actor, PxFilterData& fd) + { + PxActorType::Enum aType = actor.getType(); + switch (aType) + { + case PxActorType::eRIGID_DYNAMIC: + case PxActorType::eRIGID_STATIC: + case PxActorType::eARTICULATION_LINK: + { + const PxRigidActor& rActor = static_cast<const PxRigidActor&>(actor); + PX_CHECK_AND_RETURN_VAL(rActor.getNbShapes() >= 1,"There must be a shape in actor", false); + + PxShape* shape = NULL; + rActor.getShapes(&shape, 1); + + fd = shape->getSimulationFilterData(); + } + break; + +#if PX_USE_PARTICLE_SYSTEM_API + case PxActorType::ePARTICLE_FLUID: + case PxActorType::ePARTICLE_SYSTEM: + { + const PxParticleBase& pActor = static_cast<const PxParticleBase&>(actor); + fd = pActor.getSimulationFilterData(); + } + break; +#endif + +#if PX_USE_CLOTH_API + case PxActorType::eCLOTH: + { + const PxCloth& cActor = static_cast<const PxCloth&>(actor); + fd = cActor.getSimulationFilterData(); + } + break; +#endif + case PxActorType::eACTOR_COUNT: + case PxActorType::eACTOR_FORCE_DWORD: + break; + } + + return true; + } + + PX_FORCE_INLINE static void adjustFilterData(bool groupsMask, const PxFilterData& src, PxFilterData& dst) + { + if (groupsMask) + { + dst.word2 = src.word2; + dst.word3 = src.word3; + } + else + dst.word0 = src.word0; + } + + template<bool TGroupsMask> + static void setFilterData(PxActor& actor, const PxFilterData& fd) + { + PxActorType::Enum aType = actor.getType(); + switch (aType) + { + case PxActorType::eRIGID_DYNAMIC: + case PxActorType::eRIGID_STATIC: + case PxActorType::eARTICULATION_LINK: + { + const PxRigidActor& rActor = static_cast<const PxRigidActor&>(actor); + + PxShape* shape; + for(PxU32 i=0; i < rActor.getNbShapes(); i++) + { + rActor.getShapes(&shape, 1, i); + + // retrieve current group mask + PxFilterData resultFd = shape->getSimulationFilterData(); + + adjustFilterData(TGroupsMask, fd, resultFd); + + // set new filter data + shape->setSimulationFilterData(resultFd); + } + } + break; + +#if PX_USE_PARTICLE_SYSTEM_API + case PxActorType::ePARTICLE_FLUID: + case PxActorType::ePARTICLE_SYSTEM: + { + PxParticleBase& pActor = static_cast<PxParticleBase&>(actor); + + PxFilterData resultFd = pActor.getSimulationFilterData(); + + adjustFilterData(TGroupsMask, fd, resultFd); + + pActor.setSimulationFilterData(resultFd); + } + break; +#endif + +#if PX_USE_CLOTH_API + case PxActorType::eCLOTH: + { + PxCloth& cActor = static_cast<PxCloth&>(actor); + + PxFilterData resultFd = cActor.getSimulationFilterData(); + + adjustFilterData(TGroupsMask, fd, resultFd); + + cActor.setSimulationFilterData(resultFd); + } + break; +#endif + + case PxActorType::eACTOR_COUNT: + case PxActorType::eACTOR_FORCE_DWORD: + break; + } + } +} + +PxFilterFlags physx::PxDefaultSimulationFilterShader( + PxFilterObjectAttributes attributes0, + PxFilterData filterData0, + PxFilterObjectAttributes attributes1, + PxFilterData filterData1, + PxPairFlags& pairFlags, + const void* constantBlock, + PxU32 constantBlockSize) +{ + PX_UNUSED(constantBlock); + PX_UNUSED(constantBlockSize); + + // let triggers through + if(PxFilterObjectIsTrigger(attributes0) || PxFilterObjectIsTrigger(attributes1)) + { + pairFlags = PxPairFlag::eTRIGGER_DEFAULT; + return PxFilterFlags(); + } + + // Collision Group + if (!gCollisionTable[filterData0.word0][filterData1.word0]()) + { + return PxFilterFlag::eSUPPRESS; + } + + // Filter function + PxGroupsMask g0 = convert(filterData0); + PxGroupsMask g1 = convert(filterData1); + + PxGroupsMask g0k0; gTable[gFilterOps[0]](g0k0, g0, gFilterConstants[0]); + PxGroupsMask g1k1; gTable[gFilterOps[1]](g1k1, g1, gFilterConstants[1]); + PxGroupsMask final; gTable[gFilterOps[2]](final, g0k0, g1k1); + + bool r = final.bits0 || final.bits1 || final.bits2 || final.bits3; + if (r != gFilterBool) + { + return PxFilterFlag::eSUPPRESS; + } + + pairFlags = PxPairFlag::eCONTACT_DEFAULT; + + return PxFilterFlags(); +} + +bool physx::PxGetGroupCollisionFlag(const PxU16 group1, const PxU16 group2) +{ + PX_CHECK_AND_RETURN_NULL(group1 < 32 && group2 < 32, "Group must be less than 32"); + + return gCollisionTable[group1][group2](); +} + +void physx::PxSetGroupCollisionFlag(const PxU16 group1, const PxU16 group2, const bool enable) +{ + PX_CHECK_AND_RETURN(group1 < 32 && group2 < 32, "Group must be less than 32"); + + gCollisionTable[group1][group2] = enable; + gCollisionTable[group2][group1] = enable; +} + +PxU16 physx::PxGetGroup(const PxActor& actor) +{ + PxFilterData fd; + getFilterData(actor, fd); + return PxU16(fd.word0); +} + +void physx::PxSetGroup(PxActor& actor, const PxU16 collisionGroup) +{ + PX_CHECK_AND_RETURN(collisionGroup < 32,"Collision group must be less than 32"); + PxFilterData fd(collisionGroup, 0, 0, 0); + setFilterData<false>(actor, fd); +} + +void physx::PxGetFilterOps(PxFilterOp::Enum& op0, PxFilterOp::Enum& op1, PxFilterOp::Enum& op2) +{ + op0 = gFilterOps[0]; + op1 = gFilterOps[1]; + op2 = gFilterOps[2]; +} + +void physx::PxSetFilterOps(const PxFilterOp::Enum& op0, const PxFilterOp::Enum& op1, const PxFilterOp::Enum& op2) +{ + gFilterOps[0] = op0; + gFilterOps[1] = op1; + gFilterOps[2] = op2; +} + +bool physx::PxGetFilterBool() +{ + return gFilterBool; +} + +void physx::PxSetFilterBool(const bool enable) +{ + gFilterBool = enable; +} + +void physx::PxGetFilterConstants(PxGroupsMask& c0, PxGroupsMask& c1) +{ + c0 = gFilterConstants[0]; + c1 = gFilterConstants[1]; +} + +void physx::PxSetFilterConstants(const PxGroupsMask& c0, const PxGroupsMask& c1) +{ + gFilterConstants[0] = c0; + gFilterConstants[1] = c1; +} + +PxGroupsMask physx::PxGetGroupsMask(const PxActor& actor) +{ + PxFilterData fd; + if (getFilterData(actor, fd)) + return convert(fd); + else + return PxGroupsMask(); +} + +void physx::PxSetGroupsMask(PxActor& actor, const PxGroupsMask& mask) +{ + PxFilterData fd = convert(mask); + setFilterData<true>(actor, fd); +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultStreams.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultStreams.cpp new file mode 100644 index 00000000..49b55f56 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultStreams.cpp @@ -0,0 +1,193 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "foundation/PxPreprocessor.h" +#include "foundation/PxAssert.h" +#include "foundation/PxAllocatorCallback.h" + +#include <errno.h> +#include "PsFoundation.h" +#include "PxDefaultStreams.h" +#include "SnFile.h" +#include "CmPhysXCommon.h" +#include "PsUtilities.h" +#include "PsBitUtils.h" + +using namespace physx; + +PxDefaultMemoryOutputStream::PxDefaultMemoryOutputStream(PxAllocatorCallback &allocator) +: mAllocator (allocator) +, mData (NULL) +, mSize (0) +, mCapacity (0) +{ +} + +PxDefaultMemoryOutputStream::~PxDefaultMemoryOutputStream() +{ + if(mData) + mAllocator.deallocate(mData); +} + +PxU32 PxDefaultMemoryOutputStream::write(const void* src, PxU32 size) +{ + PxU32 expectedSize = mSize + size; + if(expectedSize > mCapacity) + { + mCapacity = PxMax(Ps::nextPowerOfTwo(expectedSize), 4096u); + + PxU8* newData = reinterpret_cast<PxU8*>(mAllocator.allocate(mCapacity,"PxDefaultMemoryOutputStream",__FILE__,__LINE__)); + PX_ASSERT(newData!=NULL); + + memcpy(newData, mData, mSize); + if(mData) + mAllocator.deallocate(mData); + + mData = newData; + } + memcpy(mData+mSize, src, size); + mSize += size; + return size; +} + +/////////////////////////////////////////////////////////////////////////////// + +PxDefaultMemoryInputData::PxDefaultMemoryInputData(PxU8* data, PxU32 length) : + mSize (length), + mData (data), + mPos (0) +{ +} + +PxU32 PxDefaultMemoryInputData::read(void* dest, PxU32 count) +{ + PxU32 length = PxMin<PxU32>(count, mSize-mPos); + memcpy(dest, mData+mPos, length); + mPos += length; + return length; +} + +PxU32 PxDefaultMemoryInputData::getLength() const +{ + return mSize; +} + +void PxDefaultMemoryInputData::seek(PxU32 offset) +{ + mPos = PxMin<PxU32>(mSize, offset); +} + +PxU32 PxDefaultMemoryInputData::tell() const +{ + return mPos; +} + +PxDefaultFileOutputStream::PxDefaultFileOutputStream(const char* filename) +{ + mFile = NULL; + sn::fopen_s(&mFile, filename, "wb"); + // PT: when this fails, check that: + // - the path is correct + // - the file does not already exist. If it does, check that it is not write protected. + if(NULL == mFile) + { + Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, + "Unable to open file %s, errno 0x%x\n",filename,errno); + } + PX_ASSERT(mFile); +} + +PxDefaultFileOutputStream::~PxDefaultFileOutputStream() +{ + if(mFile) + fclose(mFile); +} + +PxU32 PxDefaultFileOutputStream::write(const void* src, PxU32 count) +{ + return mFile ? PxU32(fwrite(src, 1, count, mFile)) : 0; +} + +bool PxDefaultFileOutputStream::isValid() +{ + return mFile != NULL; +} + +/////////////////////////////////////////////////////////////////////////////// + +PxDefaultFileInputData::PxDefaultFileInputData(const char* filename) +{ + mFile = NULL; + sn::fopen_s(&mFile, filename, "rb"); + + if(mFile) + { + fseek(mFile, 0, SEEK_END); + mLength = PxU32(ftell(mFile)); + fseek(mFile, 0, SEEK_SET); + } + else + { + mLength = 0; + } +} + +PxDefaultFileInputData::~PxDefaultFileInputData() +{ + if(mFile) + fclose(mFile); +} + +PxU32 PxDefaultFileInputData::read(void* dest, PxU32 count) +{ + PX_ASSERT(mFile); + const size_t size = fread(dest, 1, count, mFile); + // there should be no assert here since by spec of PxInputStream we can read fewer bytes than expected + return PxU32(size); +} + +PxU32 PxDefaultFileInputData::getLength() const +{ + return mLength; +} + +void PxDefaultFileInputData::seek(PxU32 pos) +{ + fseek(mFile, long(pos), SEEK_SET); +} + +PxU32 PxDefaultFileInputData::tell() const +{ + return PxU32(ftell(mFile)); +} + +bool PxDefaultFileInputData::isValid() const +{ + return mFile != NULL; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJoint.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJoint.cpp new file mode 100644 index 00000000..6e6e69bd --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJoint.cpp @@ -0,0 +1,215 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "ExtDistanceJoint.h" +#include "common/PxSerialFramework.h" + +using namespace physx; +using namespace Ext; + +namespace physx +{ + PxDistanceJoint* PxDistanceJointCreate(PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1); +} + +PxDistanceJoint* physx::PxDistanceJointCreate(PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) +{ + PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxDistanceJointCreate: local frame 0 is not a valid transform"); + PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxDistanceJointCreate: local frame 1 is not a valid transform"); + PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxDistanceJointCreate: actors must be different"); + PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxD6JointCreate: at least one actor must be dynamic"); + + DistanceJoint* j; + PX_NEW_SERIALIZED(j,DistanceJoint)(physics.getTolerancesScale(), actor0, localFrame0, actor1, localFrame1); + if(j->attach(physics, actor0, actor1)) + return j; + + PX_DELETE(j); + return NULL; +} + +PxReal DistanceJoint::getDistance() const +{ + return getRelativeTransform().p.magnitudeSquared(); +} + +void DistanceJoint::setMinDistance(PxReal distance) +{ + PX_CHECK_AND_RETURN(PxIsFinite(distance), "PxDistanceJoint::setMinDistance: invalid parameter"); + data().minDistance = distance; + markDirty(); +} + +PxReal DistanceJoint::getMinDistance() const +{ + return data().minDistance; +} + +void DistanceJoint::setMaxDistance(PxReal distance) +{ + PX_CHECK_AND_RETURN(PxIsFinite(distance), "PxDistanceJoint::setMaxDistance: invalid parameter"); + data().maxDistance = distance; + markDirty(); +} + +PxReal DistanceJoint::getMaxDistance() const +{ + return data().maxDistance; +} + +void DistanceJoint::setTolerance(PxReal tolerance) +{ + PX_CHECK_AND_RETURN(PxIsFinite(tolerance), "PxDistanceJoint::setTolerance: invalid parameter"); + data().tolerance = tolerance; + markDirty(); +} + +PxReal DistanceJoint::getTolerance() const +{ + return data().tolerance; +} + +void DistanceJoint::setStiffness(PxReal stiffness) +{ + PX_CHECK_AND_RETURN(PxIsFinite(stiffness), "PxDistanceJoint::setStiffness: invalid parameter"); + data().stiffness = stiffness; + markDirty(); +} + +PxReal DistanceJoint::getStiffness() const +{ + return data().stiffness; +} + +void DistanceJoint::setDamping(PxReal damping) +{ + PX_CHECK_AND_RETURN(PxIsFinite(damping), "PxDistanceJoint::setDamping: invalid parameter"); + data().damping = damping; + markDirty(); +} + +PxReal DistanceJoint::getDamping() const +{ + return data().damping; +} + +PxDistanceJointFlags DistanceJoint::getDistanceJointFlags(void) const +{ + return data().jointFlags; +} + +void DistanceJoint::setDistanceJointFlags(PxDistanceJointFlags flags) +{ + data().jointFlags = flags; + markDirty(); +} + +void DistanceJoint::setDistanceJointFlag(PxDistanceJointFlag::Enum flag, bool value) +{ + if(value) + data().jointFlags |= flag; + else + data().jointFlags &= ~flag; + markDirty(); +} + + + +namespace +{ +void DistanceJointVisualize(PxConstraintVisualizer& /*viz*/, + const void* /*constantBlock*/, + const PxTransform& /*body0Transform*/, + const PxTransform& /*body1Transform*/, + PxU32 /*flags*/) +{ +} + +void DistanceJointProject(const void* /*constantBlock*/, + PxTransform& /*bodyAToWorld*/, + PxTransform& /*bodyBToWorld*/, + bool /*projectToA*/) +{ + // TODO +} + + +} + +bool Ext::DistanceJoint::attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1) +{ + mPxConstraint = physics.createConstraint(actor0, actor1, *this, sShaders, sizeof(DistanceJointData)); + return mPxConstraint!=NULL; +} + +void DistanceJoint::exportExtraData(PxSerializationContext& stream) +{ + if(mData) + { + stream.alignData(PX_SERIAL_ALIGN); + stream.writeData(mData, sizeof(DistanceJointData)); + } + stream.writeName(mName); +} + +void DistanceJoint::importExtraData(PxDeserializationContext& context) +{ + if(mData) + mData = context.readExtraData<DistanceJointData, PX_SERIAL_ALIGN>(); + + context.readName(mName); +} + +void DistanceJoint::resolveReferences(PxDeserializationContext& context) +{ + setPxConstraint(resolveConstraintPtr(context, getPxConstraint(), getConnector(), sShaders)); +} + +DistanceJoint* DistanceJoint::createObject(PxU8*& address, PxDeserializationContext& context) +{ + DistanceJoint* obj = new (address) DistanceJoint(PxBaseFlag::eIS_RELEASABLE); + address += sizeof(DistanceJoint); + obj->importExtraData(context); + obj->resolveReferences(context); + return obj; +} + +// global function to share the joint shaders with API capture +const PxConstraintShaderTable* Ext::GetDistanceJointShaderTable() +{ + return &DistanceJoint::getConstraintShaderTable(); +} + +//~PX_SERIALIZATION +PxConstraintShaderTable Ext::DistanceJoint::sShaders = { Ext::DistanceJointSolverPrep, DistanceJointProject, DistanceJointVisualize, PxConstraintFlag::Enum(0) }; diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJoint.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJoint.h new file mode 100644 index 00000000..593b2ee2 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJoint.h @@ -0,0 +1,162 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef NP_DISTANCEJOINTCONSTRAINT_H +#define NP_DISTANCEJOINTCONSTRAINT_H + +#include "PsUserAllocated.h" +#include "ExtJoint.h" +#include "PxDistanceJoint.h" +#include "PxTolerancesScale.h" +#include "CmUtils.h" + +namespace physx +{ +struct PxDistanceJointGeneratedValues; +namespace Ext +{ + + struct DistanceJointData : public JointData + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + + PxReal minDistance; + PxReal maxDistance; + PxReal tolerance; + PxReal stiffness; + PxReal damping; + + PxDistanceJointFlags jointFlags; + }; + + typedef Joint<PxDistanceJoint, PxDistanceJointGeneratedValues> DistanceJointT; + class DistanceJoint : public DistanceJointT + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + public: + // PX_SERIALIZATION + DistanceJoint(PxBaseFlags baseFlags) : DistanceJointT(baseFlags) {} + virtual void exportExtraData(PxSerializationContext& context); + void importExtraData(PxDeserializationContext& context); + void resolveReferences(PxDeserializationContext& context); + static DistanceJoint* createObject(PxU8*& address, PxDeserializationContext& context); + static void getBinaryMetaData(PxOutputStream& stream); + //~PX_SERIALIZATION + virtual ~DistanceJoint() + { + if (getBaseFlags()&PxBaseFlag::eOWNS_MEMORY) + PX_FREE(mData); + } + + DistanceJoint(const PxTolerancesScale& scale, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) + : DistanceJointT(PxJointConcreteType::eDISTANCE, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE) + { + DistanceJointData* data = reinterpret_cast<DistanceJointData*>(PX_ALLOC(sizeof(DistanceJointData), "DistanceJointData")); + Cm::markSerializedMem(data, sizeof(DistanceJointData)); + mData = data; + + initCommonData(*data, actor0, localFrame0, actor1, localFrame1); + + data->stiffness = 0; + data->damping = 0; + data->minDistance = 0; + data->maxDistance = 0; + data->tolerance = 0.025f * scale.length; + data->jointFlags = PxDistanceJointFlag::eMAX_DISTANCE_ENABLED; + } + + PxReal getDistance() const; + + void setMinDistance(PxReal distance); + PxReal getMinDistance() const; + + void setMaxDistance(PxReal distance); + PxReal getMaxDistance() const; + + void setTolerance(PxReal tolerance); + PxReal getTolerance() const; + + void setStiffness(PxReal spring); + PxReal getStiffness() const; + + void setDamping(PxReal damping); + PxReal getDamping() const; + + PxDistanceJointFlags getDistanceJointFlags(void) const; + void setDistanceJointFlags(PxDistanceJointFlags flags); + void setDistanceJointFlag(PxDistanceJointFlag::Enum flag, bool value); + + bool attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1); + + static const PxConstraintShaderTable& getConstraintShaderTable() { return sShaders; } + + virtual PxConstraintSolverPrep getPrep()const {return sShaders.solverPrep;} + + private: + + static PxConstraintShaderTable sShaders; + + PX_FORCE_INLINE DistanceJointData& data() const + { + return *static_cast<DistanceJointData*>(mData); + } + }; + +} // namespace Ext + +namespace Ext +{ + extern "C" PxU32 DistanceJointSolverPrep(Px1DConstraint* constraints, + PxVec3& body0WorldOffset, + PxU32 maxConstraints, + PxConstraintInvMassScale& invMassScale, + const void* constantBlock, + const PxTransform& bA2w, + const PxTransform& bB2w); + + // global function to share the joint shaders with API capture + extern "C" const PxConstraintShaderTable* GetDistanceJointShaderTable(); +} + +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJointSolverPrep.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJointSolverPrep.cpp new file mode 100644 index 00000000..c0b8797d --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJointSolverPrep.cpp @@ -0,0 +1,111 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "foundation/PxSimpleTypes.h" +#include "ExtDistanceJoint.h" + +namespace physx +{ +namespace Ext +{ + PxU32 DistanceJointSolverPrep(Px1DConstraint* constraints, + PxVec3& body0WorldOffset, + PxU32 maxConstraints, + PxConstraintInvMassScale &invMassScale, + const void* constantBlock, + const PxTransform& bA2w, + const PxTransform& bB2w) + { + PX_UNUSED(maxConstraints); + + const DistanceJointData& data = *reinterpret_cast<const DistanceJointData*>(constantBlock); + invMassScale = data.invMassScale; + + PxTransform cA2w = bA2w.transform(data.c2b[0]); + PxTransform cB2w = bB2w.transform(data.c2b[1]); + + body0WorldOffset = cB2w.p - bA2w.p; + + PxVec3 direction = cA2w.p - cB2w.p; + PxReal distance = direction.normalize(); + + bool enforceMax = (data.jointFlags & PxDistanceJointFlag::eMAX_DISTANCE_ENABLED); + bool enforceMin = (data.jointFlags & PxDistanceJointFlag::eMIN_DISTANCE_ENABLED); + + if((!enforceMax || distance<=data.maxDistance) && (!enforceMin || distance>=data.minDistance)) + return 0; + +#define EPS_REAL 1.192092896e-07F + + if (distance < EPS_REAL) + direction = PxVec3(1.f,0,0); + + Px1DConstraint *c = constraints; + + // constraint is breakable, so we need to output forces + + c->flags = Px1DConstraintFlag::eOUTPUT_FORCE; + + c->linear0 = direction; c->angular0 = (cA2w.p - bA2w.p).cross(c->linear0); + c->linear1 = direction; c->angular1 = (cB2w.p - bB2w.p).cross(c->linear1); + + if (data.jointFlags & PxDistanceJointFlag::eSPRING_ENABLED) + { + c->flags |= Px1DConstraintFlag::eSPRING; + c->mods.spring.stiffness= data.stiffness; + c->mods.spring.damping = data.damping; + } + + //add tolerance so we don't have contact-style jitter problem. + + if (data.minDistance == data.maxDistance && enforceMin && enforceMax) + { + PxReal error = distance - data.maxDistance; + c->geometricError = error > data.tolerance ? error - data.tolerance : + error < -data.tolerance ? error + data.tolerance : 0; + } + else if (enforceMax && distance > data.maxDistance) + { + c->geometricError = distance - data.maxDistance - data.tolerance; + c->maxImpulse = 0; + } + else if (enforceMin && distance < data.minDistance) + { + c->geometricError = distance - data.minDistance + data.tolerance; + c->minImpulse = 0; + } + + return 1; + } +}//namespace + +} + +//~PX_SERIALIZATION diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtExtensions.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtExtensions.cpp new file mode 100644 index 00000000..4b1e95ac --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtExtensions.cpp @@ -0,0 +1,212 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "foundation/PxIO.h" +#include "PxExtensionsAPI.h" +#include "PsFoundation.h" +#include "PxMetaData.h" +#include "ExtDistanceJoint.h" +#include "ExtD6Joint.h" +#include "ExtFixedJoint.h" +#include "ExtPrismaticJoint.h" +#include "ExtRevoluteJoint.h" +#include "ExtSphericalJoint.h" +#include "PxRepXSerializer.h" +#include "SnRepXCoreSerializer.h" +#include "SnRepXSerializerImpl.h" +#include "PxExtensionMetaDataObjects.h" +#include "PxJointRepXSerializer.h" +#include "PxSerializer.h" +#include "ExtSerialization.h" + +#if PX_SUPPORT_PVD +#include "ExtPvd.h" +#include "PxPvdDataStream.h" +#include "PxPvdClient.h" +#include "PsPvd.h" +#endif + +using namespace physx; +using namespace physx::pvdsdk; + +#if PX_SUPPORT_PVD +struct JointConnectionHandler : public PvdClient +{ + JointConnectionHandler() : mPvd(NULL),mConnected(false){} + + PvdDataStream* getDataStream() + { + return NULL; + } + PvdUserRenderer* getUserRender() + { + return NULL; + } + + void onPvdConnected() + { + PvdDataStream* stream = PvdDataStream::create(mPvd); + if(stream) + { + mConnected = true; + Ext::Pvd::sendClassDescriptions(*stream); + stream->release(); + } + } + + bool isConnected() const + { + return mConnected; + } + + void onPvdDisconnected() + { + mConnected = false; + } + + void flush() + { + } + + PsPvd* mPvd; + bool mConnected; +}; + +static JointConnectionHandler gPvdHandler; +#endif + +bool PxInitExtensions(PxPhysics& physics, PxPvd* pvd) +{ + PX_ASSERT(static_cast<Ps::Foundation*>(&physics.getFoundation()) == &Ps::Foundation::getInstance()); + PX_UNUSED(physics); + PX_UNUSED(pvd); + Ps::Foundation::incRefCount(); + +#if PX_SUPPORT_PVD + if(pvd) + { + gPvdHandler.mPvd = static_cast<PsPvd*>(pvd); + gPvdHandler.mPvd->addClient(&gPvdHandler); + } +#endif + + return true; +} + +void PxCloseExtensions(void) +{ + Ps::Foundation::decRefCount(); + +#if PX_SUPPORT_PVD + if(gPvdHandler.mConnected) + { + PX_ASSERT(gPvdHandler.mPvd); + gPvdHandler.mPvd->removeClient(&gPvdHandler); + gPvdHandler.mPvd = NULL; + } +#endif +} + +void Ext::RegisterExtensionsSerializers(PxSerializationRegistry& sr) +{ + //for repx serialization + sr.registerRepXSerializer(PxConcreteType::eMATERIAL, PX_NEW_REPX_SERIALIZER( PxMaterialRepXSerializer )); + sr.registerRepXSerializer(PxConcreteType::eSHAPE, PX_NEW_REPX_SERIALIZER( PxShapeRepXSerializer )); +// sr.registerRepXSerializer(PxConcreteType::eTRIANGLE_MESH, PX_NEW_REPX_SERIALIZER( PxTriangleMeshRepXSerializer )); + sr.registerRepXSerializer(PxConcreteType::eTRIANGLE_MESH_BVH33, PX_NEW_REPX_SERIALIZER( PxBVH33TriangleMeshRepXSerializer )); + sr.registerRepXSerializer(PxConcreteType::eTRIANGLE_MESH_BVH34, PX_NEW_REPX_SERIALIZER( PxBVH34TriangleMeshRepXSerializer )); + sr.registerRepXSerializer(PxConcreteType::eHEIGHTFIELD, PX_NEW_REPX_SERIALIZER( PxHeightFieldRepXSerializer )); + sr.registerRepXSerializer(PxConcreteType::eCONVEX_MESH, PX_NEW_REPX_SERIALIZER( PxConvexMeshRepXSerializer )); + sr.registerRepXSerializer(PxConcreteType::eRIGID_STATIC, PX_NEW_REPX_SERIALIZER( PxRigidStaticRepXSerializer )); + sr.registerRepXSerializer(PxConcreteType::eRIGID_DYNAMIC, PX_NEW_REPX_SERIALIZER( PxRigidDynamicRepXSerializer )); + sr.registerRepXSerializer(PxConcreteType::eARTICULATION, PX_NEW_REPX_SERIALIZER( PxArticulationRepXSerializer )); + sr.registerRepXSerializer(PxConcreteType::eAGGREGATE, PX_NEW_REPX_SERIALIZER( PxAggregateRepXSerializer )); + +#if PX_USE_CLOTH_API + sr.registerRepXSerializer(PxConcreteType::eCLOTH_FABRIC, PX_NEW_REPX_SERIALIZER( PxClothFabricRepXSerializer )); + sr.registerRepXSerializer(PxConcreteType::eCLOTH, PX_NEW_REPX_SERIALIZER( PxClothRepXSerializer )); +#endif +#if PX_USE_PARTICLE_SYSTEM_API + sr.registerRepXSerializer(PxConcreteType::ePARTICLE_SYSTEM, PX_NEW_REPX_SERIALIZER( PxParticleRepXSerializer<PxParticleSystem> )); + sr.registerRepXSerializer(PxConcreteType::ePARTICLE_FLUID, PX_NEW_REPX_SERIALIZER( PxParticleRepXSerializer<PxParticleFluid> )); +#endif + + sr.registerRepXSerializer(PxJointConcreteType::eFIXED, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxFixedJoint> )); + sr.registerRepXSerializer(PxJointConcreteType::eDISTANCE, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxDistanceJoint> )); + sr.registerRepXSerializer(PxJointConcreteType::eD6, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxD6Joint> )); + sr.registerRepXSerializer(PxJointConcreteType::ePRISMATIC, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxPrismaticJoint> )); + sr.registerRepXSerializer(PxJointConcreteType::eREVOLUTE, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxRevoluteJoint> )); + sr.registerRepXSerializer(PxJointConcreteType::eSPHERICAL, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxSphericalJoint> )); + + //for binary serialization + sr.registerSerializer(PxJointConcreteType::eFIXED, PX_NEW_SERIALIZER_ADAPTER( FixedJoint )); + sr.registerSerializer(PxJointConcreteType::eDISTANCE, PX_NEW_SERIALIZER_ADAPTER( DistanceJoint )); + sr.registerSerializer(PxJointConcreteType::eD6, PX_NEW_SERIALIZER_ADAPTER( D6Joint) ); + sr.registerSerializer(PxJointConcreteType::ePRISMATIC, PX_NEW_SERIALIZER_ADAPTER( PrismaticJoint )); + sr.registerSerializer(PxJointConcreteType::eREVOLUTE, PX_NEW_SERIALIZER_ADAPTER( RevoluteJoint )); + sr.registerSerializer(PxJointConcreteType::eSPHERICAL, PX_NEW_SERIALIZER_ADAPTER( SphericalJoint )); +} + +void Ext::UnregisterExtensionsSerializers(PxSerializationRegistry& sr) +{ + PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eFIXED)); + PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eDISTANCE)); + PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eD6 )); + PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::ePRISMATIC)); + PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eREVOLUTE)); + PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eSPHERICAL)); + + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eMATERIAL)); + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eSHAPE)); +// PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eTRIANGLE_MESH)); + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eTRIANGLE_MESH_BVH33)); + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eTRIANGLE_MESH_BVH34)); + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eHEIGHTFIELD)); + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eCONVEX_MESH)); + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eRIGID_STATIC)); + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eRIGID_DYNAMIC)); + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eARTICULATION)); + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eAGGREGATE)); + +#if PX_USE_CLOTH_API + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eCLOTH_FABRIC)); + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eCLOTH)); +#endif +#if PX_USE_PARTICLE_SYSTEM_API + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::ePARTICLE_SYSTEM)); + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::ePARTICLE_FLUID)); +#endif + + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::eFIXED)); + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::eDISTANCE)); + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::eD6)); + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::ePRISMATIC)); + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::eREVOLUTE)); + PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::eSPHERICAL)); +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJoint.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJoint.cpp new file mode 100644 index 00000000..55dfd4a4 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJoint.cpp @@ -0,0 +1,173 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "ExtFixedJoint.h" +#include "ExtConstraintHelper.h" +#include "CmVisualization.h" + +#include "common/PxSerialFramework.h" + +using namespace physx; +using namespace Ext; + +namespace physx +{ + PxFixedJoint* PxFixedJointCreate(PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1); +} + +PxFixedJoint* physx::PxFixedJointCreate(PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) +{ + PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxFixedJointCreate: local frame 0 is not a valid transform"); + PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxFixedJointCreate: local frame 1 is not a valid transform"); + PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxFixedJointCreate: at least one actor must be dynamic"); + PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxFixedJointCreate: actors must be different"); + + FixedJoint* j; + PX_NEW_SERIALIZED(j,FixedJoint)(physics.getTolerancesScale(), actor0, localFrame0, actor1, localFrame1); + + if(j->attach(physics, actor0, actor1)) + return j; + + PX_DELETE(j); + return NULL; +} + +PxReal FixedJoint::getProjectionLinearTolerance() const +{ + return data().projectionLinearTolerance; +} + +void FixedJoint::setProjectionLinearTolerance(PxReal tolerance) +{ + PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance >=0, "PxFixedJoint::setProjectionLinearTolerance: invalid parameter"); + data().projectionLinearTolerance = tolerance; + markDirty(); +} + +PxReal FixedJoint::getProjectionAngularTolerance() const +{ + return data().projectionAngularTolerance; +} + +void FixedJoint::setProjectionAngularTolerance(PxReal tolerance) +{ + PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance >=0 && tolerance <= PxPi, "PxFixedJoint::setProjectionAngularTolerance: invalid parameter"); + data().projectionAngularTolerance = tolerance; markDirty(); +} + + +namespace +{ +void FixedJointVisualize(PxConstraintVisualizer& viz, + const void* constantBlock, + const PxTransform& body0Transform, + const PxTransform& body1Transform, + PxU32 /*flags*/) +{ + const FixedJointData& data = *reinterpret_cast<const FixedJointData*>(constantBlock); + + const PxTransform& t0 = body0Transform * data.c2b[0]; + const PxTransform& t1 = body1Transform * data.c2b[1]; + + viz.visualizeJointFrames(t0, t1); +} + + + +void FixedJointProject(const void* constantBlock, + PxTransform& bodyAToWorld, + PxTransform& bodyBToWorld, + bool projectToA) +{ + + using namespace joint; + const FixedJointData &data = *reinterpret_cast<const FixedJointData*>(constantBlock); + + PxTransform cA2w, cB2w, cB2cA, projected; + computeDerived(data, bodyAToWorld, bodyBToWorld, cA2w, cB2w, cB2cA); + + bool linearTrunc, angularTrunc; + projected.p = truncateLinear(cB2cA.p, data.projectionLinearTolerance, linearTrunc); + projected.q = truncateAngular(cB2cA.q, PxSin(data.projectionAngularTolerance/2), PxCos(data.projectionAngularTolerance/2), angularTrunc); + + if(linearTrunc || angularTrunc) + projectTransforms(bodyAToWorld, bodyBToWorld, cA2w, cB2w, projected, data, projectToA); +} +} + +bool Ext::FixedJoint::attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1) +{ + mPxConstraint = physics.createConstraint(actor0, actor1, *this, sShaders, sizeof(FixedJointData)); + return mPxConstraint!=NULL; +} + +void FixedJoint::exportExtraData(PxSerializationContext& stream) const +{ + if(mData) + { + stream.alignData(PX_SERIAL_ALIGN); + stream.writeData(mData, sizeof(FixedJointData)); + } + stream.writeName(mName); +} + +void FixedJoint::importExtraData(PxDeserializationContext& context) +{ + if(mData) + mData = context.readExtraData<FixedJointData, PX_SERIAL_ALIGN>(); + context.readName(mName); +} + +void FixedJoint::resolveReferences(PxDeserializationContext& context) +{ + setPxConstraint(resolveConstraintPtr(context, getPxConstraint(), getConnector(), sShaders)); +} + +FixedJoint* FixedJoint::createObject(PxU8*& address, PxDeserializationContext& context) +{ + FixedJoint* obj = new (address) FixedJoint(PxBaseFlag::eIS_RELEASABLE); + address += sizeof(FixedJoint); + obj->importExtraData(context); + obj->resolveReferences(context); + return obj; +} + +// global function to share the joint shaders with API capture +const PxConstraintShaderTable* Ext::GetFixedJointShaderTable() +{ + return &FixedJoint::getConstraintShaderTable(); +} + +//~PX_SERIALIZATION +PxConstraintShaderTable Ext::FixedJoint::sShaders = { Ext::FixedJointSolverPrep, FixedJointProject, FixedJointVisualize, PxConstraintFlag::Enum(0) }; diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJoint.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJoint.h new file mode 100644 index 00000000..887cb24b --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJoint.h @@ -0,0 +1,135 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef NP_FIXEDJOINTCONSTRAINT_H +#define NP_FIXEDJOINTCONSTRAINT_H + +#include "ExtJoint.h" +#include "PxFixedJoint.h" +#include "CmUtils.h" + +namespace physx +{ +struct PxFixedJointGeneratedValues; +namespace Ext +{ + + struct FixedJointData : public JointData + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + + PxReal projectionLinearTolerance; + PxReal projectionAngularTolerance; + }; + + typedef Joint<PxFixedJoint, PxFixedJointGeneratedValues> FixedJointT; + + class FixedJoint : public FixedJointT + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + public: +// PX_SERIALIZATION + FixedJoint(PxBaseFlags baseFlags) : FixedJointT(baseFlags) {} + virtual void exportExtraData(PxSerializationContext& context) const; + void importExtraData(PxDeserializationContext& context); + void resolveReferences(PxDeserializationContext& context); + static FixedJoint* createObject(PxU8*& address, PxDeserializationContext& context); + static void getBinaryMetaData(PxOutputStream& stream); +//~PX_SERIALIZATION + virtual ~FixedJoint() + { + if(getBaseFlags()&PxBaseFlag::eOWNS_MEMORY) + PX_FREE(mData); + } + + PxReal getProjectionLinearTolerance() const; + void setProjectionLinearTolerance(PxReal tolerance); + + PxReal getProjectionAngularTolerance() const; + void setProjectionAngularTolerance(PxReal tolerance); + + FixedJoint(const PxTolerancesScale& /*scale*/, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) + : FixedJointT(PxJointConcreteType::eFIXED, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE) + { + FixedJointData* data = reinterpret_cast<FixedJointData*>(PX_ALLOC(sizeof(FixedJointData), "FixedJointData")); + Cm::markSerializedMem(data, sizeof(FixedJointData)); + mData = data; + data->projectionLinearTolerance = 1e10f; + data->projectionAngularTolerance = PxPi; + + initCommonData(*data, actor0, localFrame0, actor1, localFrame1); + } + + bool attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1); + + static const PxConstraintShaderTable& getConstraintShaderTable() { return sShaders; } + + virtual PxConstraintSolverPrep getPrep() const { return sShaders.solverPrep; } + + private: + + static PxConstraintShaderTable sShaders; + + PX_FORCE_INLINE FixedJointData& data() const + { + return *static_cast<FixedJointData*>(mData); + } + }; +} // namespace Ext + +namespace Ext +{ + extern "C" PxU32 FixedJointSolverPrep(Px1DConstraint* constraints, + PxVec3& body0WorldOffset, + PxU32 maxConstraints, + PxConstraintInvMassScale& invMassScale, + const void* constantBlock, + const PxTransform& bA2w, + const PxTransform& bB2w); + + // global function to share the joint shaders with API capture + extern "C" const PxConstraintShaderTable* GetFixedJointShaderTable(); +} + +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJointSolverPrep.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJointSolverPrep.cpp new file mode 100644 index 00000000..811d2a11 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJointSolverPrep.cpp @@ -0,0 +1,69 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "ExtFixedJoint.h" +#include "ExtConstraintHelper.h" + +namespace physx +{ +namespace Ext +{ + + PxU32 FixedJointSolverPrep(Px1DConstraint* constraints, + PxVec3& body0WorldOffset, + PxU32 maxConstraints, + PxConstraintInvMassScale &invMassScale, + const void* constantBlock, + const PxTransform& bA2w, + const PxTransform& bB2w) + { + PX_UNUSED(maxConstraints); + + const FixedJointData& data = *reinterpret_cast<const FixedJointData*>(constantBlock); + invMassScale = data.invMassScale; + + PxTransform cA2w = bA2w.transform(data.c2b[0]); + PxTransform cB2w = bB2w.transform(data.c2b[1]); + + PxVec3 bOriginInA = cA2w.transformInv(cB2w.p); + + body0WorldOffset = cB2w.p-bA2w.p; + joint::ConstraintHelper ch(constraints,cB2w.p-bA2w.p, cB2w.p-bB2w.p); + ch.prepareLockedAxes(cA2w.q, cB2w.q, bOriginInA, 7, 7); + + return ch.getCount(); + } + + +}//namespace + +} + +//~PX_SERIALIZATION diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtInertiaTensor.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtInertiaTensor.h new file mode 100644 index 00000000..510e46b7 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtInertiaTensor.h @@ -0,0 +1,404 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_INERTIATENSOR_H +#define PX_PHYSICS_EXTENSIONS_INERTIATENSOR_H + +#include "foundation/PxMat33.h" +#include "foundation/PxMathUtils.h" +#include "CmPhysXCommon.h" +#include "PsMathUtils.h" + +namespace physx +{ +namespace Ext +{ + class InertiaTensorComputer + { + public: + InertiaTensorComputer(bool initTozero = true); + InertiaTensorComputer(const PxMat33& inertia, const PxVec3& com, PxReal mass); + ~InertiaTensorComputer(); + + PX_INLINE void zero(); //sets to zero mass + PX_INLINE void setDiagonal(PxReal mass, const PxVec3& diagonal); //sets as a diagonal tensor + PX_INLINE void rotate(const PxMat33& rot); //rotates the mass + void translate(const PxVec3& t); //translates the mass + PX_INLINE void transform(const PxTransform& transform); //transforms the mass + PX_INLINE void scaleDensity(PxReal densityScale); //scales by a density factor + PX_INLINE void add(const InertiaTensorComputer& it); //adds a mass + PX_INLINE void center(); //recenters inertia around center of mass + + void setBox(const PxVec3& halfWidths); //sets as an axis aligned box + PX_INLINE void setBox(const PxVec3& halfWidths, const PxTransform* pose); //sets as an oriented box + + void setSphere(PxReal radius); + PX_INLINE void setSphere(PxReal radius, const PxTransform* pose); + + void setCylinder(int dir, PxReal r, PxReal l); + PX_INLINE void setCylinder(int dir, PxReal r, PxReal l, const PxTransform* pose); + + void setCapsule(int dir, PxReal r, PxReal l); + PX_INLINE void setCapsule(int dir, PxReal r, PxReal l, const PxTransform* pose); + void addCapsule(PxReal density, int dir, PxReal r, PxReal l, const PxTransform* pose = 0); + + void setEllipsoid(PxReal rx, PxReal ry, PxReal rz); + PX_INLINE void setEllipsoid(PxReal rx, PxReal ry, PxReal rz, const PxTransform* pose); + + PX_INLINE PxVec3 getCenterOfMass() const { return mG; } + PX_INLINE PxReal getMass() const { return mMass; } + PX_INLINE PxMat33 getInertia() const { return mI; } + + private: + PxMat33 mI; + PxVec3 mG; + PxReal mMass; + }; + + + //-------------------------------------------------------------- + // + // Helper routines + // + //-------------------------------------------------------------- + + // Special version allowing 2D quads + PX_INLINE PxReal volume(const PxVec3& extents) + { + PxReal v = 1.0f; + if(extents.x != 0.0f) v*=extents.x; + if(extents.y != 0.0f) v*=extents.y; + if(extents.z != 0.0f) v*=extents.z; + return v; + } + + // Sphere + PX_INLINE PxReal computeSphereRatio(PxReal radius) { return (4.0f/3.0f) * PxPi * radius * radius * radius; } + PxReal computeSphereMass(PxReal radius, PxReal density) { return density * computeSphereRatio(radius); } + PxReal computeSphereDensity(PxReal radius, PxReal mass) { return mass / computeSphereRatio(radius); } + + // Box + PX_INLINE PxReal computeBoxRatio(const PxVec3& extents) { return volume(extents); } + PxReal computeBoxMass(const PxVec3& extents, PxReal density) { return density * computeBoxRatio(extents); } + PxReal computeBoxDensity(const PxVec3& extents, PxReal mass) { return mass / computeBoxRatio(extents); } + + // Ellipsoid + PX_INLINE PxReal computeEllipsoidRatio(const PxVec3& extents) { return (4.0f/3.0f) * PxPi * volume(extents); } + PxReal computeEllipsoidMass(const PxVec3& extents, PxReal density) { return density * computeEllipsoidRatio(extents); } + PxReal computeEllipsoidDensity(const PxVec3& extents, PxReal mass) { return mass / computeEllipsoidRatio(extents); } + + // Cylinder + PX_INLINE PxReal computeCylinderRatio(PxReal r, PxReal l) { return PxPi * r * r * (2.0f*l); } + PxReal computeCylinderMass(PxReal r, PxReal l, PxReal density) { return density * computeCylinderRatio(r, l); } + PxReal computeCylinderDensity(PxReal r, PxReal l, PxReal mass) { return mass / computeCylinderRatio(r, l); } + + // Capsule + PX_INLINE PxReal computeCapsuleRatio(PxReal r, PxReal l) { return computeSphereRatio(r) + computeCylinderRatio(r, l);} + PxReal computeCapsuleMass(PxReal r, PxReal l, PxReal density) { return density * computeCapsuleRatio(r, l); } + PxReal computeCapsuleDensity(PxReal r, PxReal l, PxReal mass) { return mass / computeCapsuleRatio(r, l); } + + // Cone + PX_INLINE PxReal computeConeRatio(PxReal r, PxReal l) { return PxPi * r * r * PxAbs(l)/3.0f; } + PxReal computeConeMass(PxReal r, PxReal l, PxReal density) { return density * computeConeRatio(r, l); } + PxReal computeConeDensity(PxReal r, PxReal l, PxReal mass) { return mass / computeConeRatio(r, l); } + + void computeBoxInertiaTensor(PxVec3& inertia, PxReal mass, PxReal xlength, PxReal ylength, PxReal zlength); + void computeSphereInertiaTensor(PxVec3& inertia, PxReal mass, PxReal radius, bool hollow); + bool jacobiTransform(PxI32 n, PxF64 a[], PxF64 w[]); + bool diagonalizeInertiaTensor(const PxMat33& denseInertia, PxVec3& diagonalInertia, PxMat33& rotation); + +} // namespace Ext + +void Ext::computeBoxInertiaTensor(PxVec3& inertia, PxReal mass, PxReal xlength, PxReal ylength, PxReal zlength) +{ + //to model a hollow block, one would have to multiply coeff by up to two. + const PxReal coeff = mass/12; + inertia.x = coeff * (ylength*ylength + zlength*zlength); + inertia.y = coeff * (xlength*xlength + zlength*zlength); + inertia.z = coeff * (xlength*xlength + ylength*ylength); + + PX_ASSERT(inertia.x != 0.0f); + PX_ASSERT(inertia.y != 0.0f); + PX_ASSERT(inertia.z != 0.0f); + PX_ASSERT(inertia.isFinite()); +} + + +void Ext::computeSphereInertiaTensor(PxVec3& inertia, PxReal mass, PxReal radius, bool hollow) +{ + inertia.x = mass * radius * radius; + if (hollow) + inertia.x *= PxReal(2 / 3.0); + else + inertia.x *= PxReal(2 / 5.0); + + inertia.z = inertia.y = inertia.x; + PX_ASSERT(inertia.isFinite()); +} + +//-------------------------------------------------------------- +// +// InertiaTensorComputer implementation +// +//-------------------------------------------------------------- + +Ext::InertiaTensorComputer::InertiaTensorComputer(bool initTozero) +{ + if (initTozero) + zero(); +} + + +Ext::InertiaTensorComputer::InertiaTensorComputer(const PxMat33& inertia, const PxVec3& com, PxReal mass) : + mI(inertia), + mG(com), + mMass(mass) +{ +} + + +Ext::InertiaTensorComputer::~InertiaTensorComputer() +{ + //nothing +} + + +PX_INLINE void Ext::InertiaTensorComputer::zero() +{ + mMass = 0.0f; + mI = PxMat33(PxZero); + mG = PxVec3(0); +} + + +PX_INLINE void Ext::InertiaTensorComputer::setDiagonal(PxReal mass, const PxVec3& diag) +{ + mMass = mass; + mI = PxMat33::createDiagonal(diag); + mG = PxVec3(0); + PX_ASSERT(mI.column0.isFinite() && mI.column1.isFinite() && mI.column2.isFinite()); + PX_ASSERT(PxIsFinite(mMass)); +} + + +void Ext::InertiaTensorComputer::setBox(const PxVec3& halfWidths) +{ + // Setup inertia tensor for a cube with unit density + const PxReal mass = 8.0f * computeBoxRatio(halfWidths); + const PxReal s =(1.0f/3.0f) * mass; + + const PxReal x = halfWidths.x*halfWidths.x; + const PxReal y = halfWidths.y*halfWidths.y; + const PxReal z = halfWidths.z*halfWidths.z; + + setDiagonal(mass, PxVec3(y+z, z+x, x+y) * s); +} + + +PX_INLINE void Ext::InertiaTensorComputer::rotate(const PxMat33& rot) +{ + //well known inertia tensor rotation expression is: RIR' -- this could be optimized due to symmetry, see code to do that in Body::updateGlobalInverseInertia + mI = rot * mI * rot.getTranspose(); + PX_ASSERT(mI.column0.isFinite() && mI.column1.isFinite() && mI.column2.isFinite()); + //com also needs to be rotated + mG = rot * mG; + PX_ASSERT(mG.isFinite()); +} + + +void Ext::InertiaTensorComputer::translate(const PxVec3& t) +{ + if (!t.isZero()) //its common for this to be zero + { + PxMat33 t1, t2; + + t1.column0 = PxVec3(0, mG.z, -mG.y); + t1.column1 = PxVec3(-mG.z, 0, mG.x); + t1.column2 = PxVec3(mG.y, -mG.x, 0); + + PxVec3 sum = mG + t; + if (sum.isZero()) + { + mI += (t1 * t1)*mMass; + } + else + { + t2.column0 = PxVec3(0, sum.z, -sum.y); + t2.column1 = PxVec3(-sum.z, 0, sum.x); + t2.column2 = PxVec3(sum.y, -sum.x, 0); + mI += (t1 * t1 - t2 * t2)*mMass; + } + + //move center of mass + mG += t; + + PX_ASSERT(mI.column0.isFinite() && mI.column1.isFinite() && mI.column2.isFinite()); + PX_ASSERT(mG.isFinite()); + } +} + + +PX_INLINE void Ext::InertiaTensorComputer::transform(const PxTransform& transform) +{ + rotate(PxMat33(transform.q)); + translate(transform.p); +} + + +PX_INLINE void Ext::InertiaTensorComputer::setBox(const PxVec3& halfWidths, const PxTransform* pose) +{ + setBox(halfWidths); + if (pose) + transform(*pose); + +} + + +PX_INLINE void Ext::InertiaTensorComputer::scaleDensity(PxReal densityScale) +{ + mI *= densityScale; + mMass *= densityScale; + PX_ASSERT(mI.column0.isFinite() && mI.column1.isFinite() && mI.column2.isFinite()); + PX_ASSERT(PxIsFinite(mMass)); +} + + +PX_INLINE void Ext::InertiaTensorComputer::add(const InertiaTensorComputer& it) +{ + const PxReal TotalMass = mMass + it.mMass; + mG = (mG * mMass + it.mG * it.mMass) / TotalMass; + + mMass = TotalMass; + mI += it.mI; + PX_ASSERT(mI.column0.isFinite() && mI.column1.isFinite() && mI.column2.isFinite()); + PX_ASSERT(mG.isFinite()); + PX_ASSERT(PxIsFinite(mMass)); +} + + +PX_INLINE void Ext::InertiaTensorComputer::center() +{ + PxVec3 center = -mG; + translate(center); +} + + +void Ext::InertiaTensorComputer::setSphere(PxReal radius) +{ + // Compute mass of the sphere + const PxReal m = computeSphereRatio(radius); + // Compute moment of inertia + const PxReal s = m * radius * radius * (2.0f/5.0f); + setDiagonal(m,PxVec3(s,s,s)); +} + + +PX_INLINE void Ext::InertiaTensorComputer::setSphere(PxReal radius, const PxTransform* pose) +{ + setSphere(radius); + if (pose) + transform(*pose); +} + + +void Ext::InertiaTensorComputer::setCylinder(int dir, PxReal r, PxReal l) +{ + // Compute mass of cylinder + const PxReal m = computeCylinderRatio(r, l); + + const PxReal i1 = r*r*m/2.0f; + const PxReal i2 = (3.0f*r*r+4.0f*l*l)*m/12.0f; + + switch(dir) + { + case 0: setDiagonal(m,PxVec3(i1,i2,i2)); break; + case 1: setDiagonal(m,PxVec3(i2,i1,i2)); break; + default: setDiagonal(m,PxVec3(i2,i2,i1)); break; + } +} + + +PX_INLINE void Ext::InertiaTensorComputer::setCylinder(int dir, PxReal r, PxReal l, const PxTransform* pose) +{ + setCylinder(dir, r, l); + if (pose) + transform(*pose); +} + + +void Ext::InertiaTensorComputer::setCapsule(int dir, PxReal r, PxReal l) +{ + // Compute mass of capsule + const PxReal m = computeCapsuleRatio(r, l); + + const PxReal t = PxPi * r * r; + const PxReal i1 = t * ((r*r*r * 8.0f/15.0f) + (l*r*r)); + const PxReal i2 = t * ((r*r*r * 8.0f/15.0f) + (l*r*r * 3.0f/2.0f) + (l*l*r * 4.0f/3.0f) + (l*l*l * 2.0f/3.0f)); + + switch(dir) + { + case 0: setDiagonal(m,PxVec3(i1,i2,i2)); break; + case 1: setDiagonal(m,PxVec3(i2,i1,i2)); break; + default: setDiagonal(m,PxVec3(i2,i2,i1)); break; + } +} + + +PX_INLINE void Ext::InertiaTensorComputer::setCapsule(int dir, PxReal r, PxReal l, const PxTransform* pose) +{ + setCapsule(dir, r, l); + if (pose) + transform(*pose); +} + + +void Ext::InertiaTensorComputer::setEllipsoid(PxReal rx, PxReal ry, PxReal rz) +{ + // Compute mass of ellipsoid + const PxReal m = computeEllipsoidRatio(PxVec3(rx, ry, rz)); + + // Compute moment of inertia + const PxReal s = m * (2.0f/5.0f); + + // Setup inertia tensor for an ellipsoid centered at the origin + setDiagonal(m,PxVec3(ry*rz,rz*rx,rx*ry)*s); +} + + +PX_INLINE void Ext::InertiaTensorComputer::setEllipsoid(PxReal rx, PxReal ry, PxReal rz, const PxTransform* pose) +{ + setEllipsoid(rx,ry,rz); + if (pose) + transform(*pose); +} + +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtJoint.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtJoint.cpp new file mode 100644 index 00000000..48b699ab --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtJoint.cpp @@ -0,0 +1,134 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#include "foundation/PxMat33.h" +#include "PxConstraint.h" +#include "PxJoint.h" +#include "ExtJoint.h" + +using namespace physx; +using namespace Ext; + +PxConstraint* physx::resolveConstraintPtr(PxDeserializationContext& v, + PxConstraint* old, + PxConstraintConnector* connector, + PxConstraintShaderTable &shaders) +{ + v.translatePxBase(old); + PxConstraint* new_nx = static_cast<PxConstraint*>(old); + new_nx->setConstraintFunctions(*connector, shaders); + return new_nx; +} +//~PX_SERIALIZATION + + +static void normalToTangents(const PxVec3& n, PxVec3& t1, PxVec3& t2) +{ + const PxReal m_sqrt1_2 = PxReal(0.7071067811865475244008443621048490); + if(fabsf(n.z) > m_sqrt1_2) + { + const PxReal a = n.y*n.y + n.z*n.z; + const PxReal k = PxReal(1.0)/PxSqrt(a); + t1 = PxVec3(0,-n.z*k,n.y*k); + t2 = PxVec3(a*k,-n.x*t1.z,n.x*t1.y); + } + else + { + const PxReal a = n.x*n.x + n.y*n.y; + const PxReal k = PxReal(1.0)/PxSqrt(a); + t1 = PxVec3(-n.y*k,n.x*k,0); + t2 = PxVec3(-n.z*t1.y,n.z*t1.x,a*k); + } + t1.normalize(); + t2.normalize(); +} + +void PxSetJointGlobalFrame(PxJoint& joint, const PxVec3* wsAnchor, const PxVec3* axisIn) +{ + PxRigidActor* actors[2]; + joint.getActors(actors[0], actors[1]); + + PxTransform localPose[2]; + for(PxU32 i=0; i<2; i++) + localPose[i] = PxTransform(PxIdentity); + + // 1) global anchor + if(wsAnchor) + { + //transform anchorPoint to local space + for(PxU32 i=0; i<2; i++) + localPose[i].p = actors[i] ? actors[i]->getGlobalPose().transformInv(*wsAnchor) : *wsAnchor; + } + + // 2) global axis + if(axisIn) + { + PxVec3 localAxis[2], localNormal[2]; + + //find 2 orthogonal vectors. + //gotta do this in world space, if we choose them + //separately in local space they won't match up in worldspace. + PxVec3 axisw = *axisIn; + axisw.normalize(); + + PxVec3 normalw, binormalw; + ::normalToTangents(axisw, binormalw, normalw); + //because axis is supposed to be the Z axis of a frame with the other two being X and Y, we need to negate + //Y to make the frame right handed. Note that the above call makes a right handed frame if we pass X --> Y,Z, so + //it need not be changed. + + for(PxU32 i=0; i<2; i++) + { + if(actors[i]) + { + const PxTransform& m = actors[i]->getGlobalPose(); + PxMat33 mM(m.q); + localAxis[i] = mM.transformTranspose(axisw); + localNormal[i] = mM.transformTranspose(normalw); + } + else + { + localAxis[i] = axisw; + localNormal[i] = normalw; + } + + PxMat33 rot(localAxis[i], localNormal[i], localAxis[i].cross(localNormal[i])); + + localPose[i].q = PxQuat(rot); + localPose[i].q.normalize(); + } + } + + for(PxU32 i=0; i<2; i++) + joint.setLocalPose(static_cast<PxJointActorIndex::Enum>( i ), localPose[i]); +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtJoint.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtJoint.h new file mode 100644 index 00000000..d5ef06ea --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtJoint.h @@ -0,0 +1,500 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef NP_JOINTCONSTRAINT_H +#define NP_JOINTCONSTRAINT_H + +#include "PsAllocator.h" +#include "PsUtilities.h" +#include "PxConstraint.h" +#include "PxConstraintExt.h" +#include "PxJoint.h" +#include "PxD6Joint.h" +#include "PxRigidDynamic.h" +#include "PxRigidStatic.h" +#include "ExtPvd.h" +#include "PxMetaData.h" +#include "CmRenderOutput.h" +#include "PxPhysics.h" +#include "PsFoundation.h" + +#if PX_SUPPORT_PVD +#include "PxScene.h" +#include "PxPvdClient.h" +#include "PxPvdSceneClient.h" +#endif + +// PX_SERIALIZATION + +namespace physx +{ + +PxConstraint* resolveConstraintPtr(PxDeserializationContext& v, + PxConstraint* old, + PxConstraintConnector* connector, + PxConstraintShaderTable& shaders); + +// ~PX_SERIALIZATION + +namespace Ext +{ + struct JointData + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + PxConstraintInvMassScale invMassScale; + PxTransform c2b[2]; + protected: + ~JointData(){} + }; + + template <class Base, class ValueStruct> + class Joint : public Base, + public PxConstraintConnector, + public Ps::UserAllocated + { + + public: +// PX_SERIALIZATION + Joint(PxBaseFlags baseFlags) : Base(baseFlags) {} + virtual void requires(PxProcessPxBaseCallback& c) + { + c.process(*mPxConstraint); + + { + PxRigidActor* a0 = NULL; + PxRigidActor* a1 = NULL; + mPxConstraint->getActors(a0,a1); + + if (a0) + { + c.process(*a0); + } + if (a1) + { + c.process(*a1); + } + } + } +//~PX_SERIALIZATION + +#if PX_SUPPORT_PVD + + virtual bool updatePvdProperties(physx::pvdsdk::PvdDataStream& pvdConnection, const PxConstraint* c, PxPvdUpdateType::Enum updateType) const + { + if(updateType == PxPvdUpdateType::UPDATE_SIM_PROPERTIES) + { + Ext::Pvd::simUpdate<Base>(pvdConnection, *this); + return true; + } + else if(updateType == PxPvdUpdateType::UPDATE_ALL_PROPERTIES) + { + Ext::Pvd::updatePvdProperties<Base, ValueStruct>(pvdConnection, *this); + return true; + } + else if(updateType == PxPvdUpdateType::CREATE_INSTANCE) + { + Ext::Pvd::createPvdInstance<Base>(pvdConnection, *c, *this); + return true; + } + else if(updateType == PxPvdUpdateType::RELEASE_INSTANCE) + { + Ext::Pvd::releasePvdInstance(pvdConnection, *c, *this); + return true; + } + return false; + } +#else + virtual bool updatePvdProperties(physx::pvdsdk::PvdDataStream&, const PxConstraint*, PxPvdUpdateType::Enum) const + { + return false; + } +#endif + + + + void getActors(PxRigidActor*& actor0, PxRigidActor*& actor1) const + { + if ( mPxConstraint ) mPxConstraint->getActors(actor0,actor1); + else + { + actor0 = NULL; + actor1 = NULL; + } + } + + void setActors(PxRigidActor* actor0, PxRigidActor* actor1) + { + //TODO SDK-DEV + //You can get the debugger stream from the NpScene + //Ext::Pvd::setActors( stream, this, mPxConstraint, actor0, actor1 ); + PX_CHECK_AND_RETURN(actor0 != actor1, "PxJoint::setActors: actors must be different"); + PX_CHECK_AND_RETURN((actor0 && !actor0->is<PxRigidStatic>()) || (actor1 && !actor1->is<PxRigidStatic>()), "PxJoint::setActors: at least one actor must be non-static"); + +#if PX_SUPPORT_PVD + PxScene* scene = getScene(); + if(scene) + { + //if pvd not connect data stream is NULL + physx::pvdsdk::PvdDataStream* conn = scene->getScenePvdClient()->getClientInternal()->getDataStream(); + if( conn != NULL ) + Ext::Pvd::setActors( + *conn, + *this, + *mPxConstraint, + actor0, + actor1 + ); + } +#endif + + mPxConstraint->setActors(actor0, actor1); + mData->c2b[0] = getCom(actor0).transformInv(mLocalPose[0]); + mData->c2b[1] = getCom(actor1).transformInv(mLocalPose[1]); + mPxConstraint->markDirty(); + } + + // this is the local pose relative to the actor, and we store internally the local + // pose relative to the body + + PxTransform getLocalPose(PxJointActorIndex::Enum actor) const + { + return mLocalPose[actor]; + } + + void setLocalPose(PxJointActorIndex::Enum actor, const PxTransform& pose) + { + PX_CHECK_AND_RETURN(pose.isSane(), "PxJoint::setLocalPose: transform is invalid"); + PxTransform p = pose.getNormalized(); + mLocalPose[actor] = p; + mData->c2b[actor] = getCom(actor).transformInv(p); + mPxConstraint->markDirty(); + } + + PxTransform getBodyPose(const PxRigidActor* actor) const + { + if(!actor) + return PxTransform(PxIdentity); + else if(actor->is<PxRigidStatic>()) + return actor->getGlobalPose(); + else + return actor->getGlobalPose() * static_cast<const PxRigidBody*>(actor)->getCMassLocalPose(); + } + + + void getActorVelocity(const PxRigidActor* actor, PxVec3& linear, PxVec3& angular) const + { + if(!actor || actor->is<PxRigidStatic>()) + { + linear = angular = PxVec3(0); + return; + } + + linear = static_cast<const PxRigidBody*>(actor)->getLinearVelocity(); + angular = static_cast<const PxRigidBody*>(actor)->getAngularVelocity(); + } + + + PxTransform getRelativeTransform() const + { + PxRigidActor* actor0, * actor1; + mPxConstraint->getActors(actor0, actor1); + PxTransform t0 = getBodyPose(actor0) * mLocalPose[0], + t1 = getBodyPose(actor1) * mLocalPose[1]; + return t0.transformInv(t1); + } + + PxVec3 getRelativeLinearVelocity() const + { + PxRigidActor* actor0, * actor1; + PxVec3 l0, a0, l1, a1; + mPxConstraint->getActors(actor0, actor1); + + PxTransform t0 = getCom(actor0), t1 = getCom(actor1); + getActorVelocity(actor0, l0, a0); + getActorVelocity(actor1, l1, a1); + + PxVec3 p0 = t0.q.rotate(mLocalPose[0].p), + p1 = t1.q.rotate(mLocalPose[1].p); + return t0.transformInv(l1 - a1.cross(p1) - l0 + a0.cross(p0)); + } + + PxVec3 getRelativeAngularVelocity() const + { + PxRigidActor* actor0, * actor1; + PxVec3 l0, a0, l1, a1; + mPxConstraint->getActors(actor0, actor1); + + PxTransform t0 = getCom(actor0); + getActorVelocity(actor0, l0, a0); + getActorVelocity(actor1, l1, a1); + + return t0.transformInv(a1 - a0); + } + + + void getBreakForce(PxReal& force, PxReal& torque) const + { + mPxConstraint->getBreakForce(force,torque); + } + + void setBreakForce(PxReal force, PxReal torque) + { + PX_CHECK_AND_RETURN(PxIsFinite(force) && PxIsFinite(torque), "NpJoint::setBreakForce: invalid float"); + mPxConstraint->setBreakForce(force,torque); + } + + + PxConstraintFlags getConstraintFlags() const + { + return mPxConstraint->getFlags(); + } + + void setConstraintFlags(PxConstraintFlags flags) + { + mPxConstraint->setFlags(flags); + } + + void setConstraintFlag(PxConstraintFlag::Enum flag, bool value) + { + mPxConstraint->setFlag(flag, value); + } + + void setInvMassScale0(PxReal invMassScale) + { + PX_CHECK_AND_RETURN(PxIsFinite(invMassScale) && invMassScale>=0, "PxJoint::setInvMassScale0: scale must be non-negative"); + mData->invMassScale.linear0 = invMassScale; + mPxConstraint->markDirty(); + } + + PxReal getInvMassScale0() const + { + return mData->invMassScale.linear0; + } + + void setInvInertiaScale0(PxReal invInertiaScale) + { + PX_CHECK_AND_RETURN(PxIsFinite(invInertiaScale) && invInertiaScale>=0, "PxJoint::setInvInertiaScale0: scale must be non-negative"); + mData->invMassScale.angular0 = invInertiaScale; + mPxConstraint->markDirty(); + } + + PxReal getInvInertiaScale0() const + { + return mData->invMassScale.angular0; + } + + void setInvMassScale1(PxReal invMassScale) + { + PX_CHECK_AND_RETURN(PxIsFinite(invMassScale) && invMassScale>=0, "PxJoint::setInvMassScale1: scale must be non-negative"); + mData->invMassScale.linear1 = invMassScale; + mPxConstraint->markDirty(); + } + + PxReal getInvMassScale1() const + { + return mData->invMassScale.linear1; + } + + void setInvInertiaScale1(PxReal invInertiaScale) + { + PX_CHECK_AND_RETURN(PxIsFinite(invInertiaScale) && invInertiaScale>=0, "PxJoint::setInvInertiaScale: scale must be non-negative"); + mData->invMassScale.angular1 = invInertiaScale; + mPxConstraint->markDirty(); + } + + PxReal getInvInertiaScale1() const + { + return mData->invMassScale.angular1; + } + + const char* getName() const + { + return mName; + } + + void setName(const char* name) + { + mName = name; + } + + void onComShift(PxU32 actor) + { + mData->c2b[actor] = getCom(actor).transformInv(mLocalPose[actor]); + markDirty(); + } + + void onOriginShift(const PxVec3& shift) + { + PxRigidActor* a[2]; + mPxConstraint->getActors(a[0], a[1]); + + if (!a[0]) + { + mLocalPose[0].p -= shift; + mData->c2b[0].p -= shift; + markDirty(); + } + else if (!a[1]) + { + mLocalPose[1].p -= shift; + mData->c2b[1].p -= shift; + markDirty(); + } + } + + void* prepareData() + { + return mData; + } + + PxJoint* getPxJoint() + { + return this; + } + + void* getExternalReference(PxU32& typeID) + { + typeID = PxConstraintExtIDs::eJOINT; + return static_cast<PxJoint*>( this ); + } + + PxConstraintConnector* getConnector() + { + return this; + } + + PX_INLINE void setPxConstraint(PxConstraint* pxConstraint) + { + mPxConstraint = pxConstraint; + } + + PX_INLINE PxConstraint* getPxConstraint() + { + return mPxConstraint; + } + + PX_INLINE const PxConstraint* getPxConstraint() const + { + return mPxConstraint; + } + + void release() + { + mPxConstraint->release(); + } + + PxBase* getSerializable() + { + return this; + } + + void onConstraintRelease() + { + PX_FREE_AND_RESET(mData); + delete this; + } + + PxScene* getScene() const + { + return mPxConstraint ? mPxConstraint->getScene() : NULL; + } + + private: + PxConstraint* getConstraint() const { return mPxConstraint; } + + protected: + + PxTransform getCom(PxU32 index) const + { + PxRigidActor* a[2]; + mPxConstraint->getActors(a[0],a[1]); + return getCom(a[index]); + } + + PxTransform getCom(PxRigidActor* actor) const + { + if (!actor) + return PxTransform(PxIdentity); + else if (actor->getType() == PxActorType::eRIGID_DYNAMIC || actor->getType() == PxActorType::eARTICULATION_LINK) + return static_cast<PxRigidBody*>(actor)->getCMassLocalPose(); + else + { + PX_ASSERT(actor->getType() == PxActorType::eRIGID_STATIC); + return static_cast<PxRigidStatic*>(actor)->getGlobalPose().getInverse(); + } + } + + void initCommonData(JointData& data, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) + { + mLocalPose[0] = localFrame0.getNormalized(); + mLocalPose[1] = localFrame1.getNormalized(); + data.c2b[0] = getCom(actor0).transformInv(localFrame0); + data.c2b[1] = getCom(actor1).transformInv(localFrame1); + data.invMassScale.linear0 = 1.0f; + data.invMassScale.angular0 = 1.0f; + data.invMassScale.linear1 = 1.0f; + data.invMassScale.angular1 = 1.0f; + } + + + Joint(PxType concreteType, PxBaseFlags baseFlags) + : Base(concreteType, baseFlags) + , mName(NULL) + , mPxConstraint(0) + { + Base::userData = NULL; + } + + + void markDirty() + { + mPxConstraint->markDirty(); + } + + virtual const void* getConstantBlock() const { return mData; } + + const char* mName; + PxTransform mLocalPose[2]; + PxConstraint* mPxConstraint; + JointData* mData; + }; + +} // namespace Ext + +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtJointMetaDataExtensions.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtJointMetaDataExtensions.h new file mode 100644 index 00000000..f3d730fc --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtJointMetaDataExtensions.h @@ -0,0 +1,65 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef EXT_JOINT_META_DATA_EXTENSIONS_H +#define EXT_JOINT_META_DATA_EXTENSIONS_H +#include "PvdMetaDataExtensions.h" + +namespace physx +{ + +namespace pvdsdk +{ + + +struct PxExtensionPvdOnlyProperties +{ + enum Enum + { + FirstProp = PxExtensionsPropertyInfoName::LastPxPropertyInfoName, + DEFINE_ENUM_RANGE( PxJoint_Actors, 2 ), + DEFINE_ENUM_RANGE( PxJoint_BreakForce, 2 ), + DEFINE_ENUM_RANGE( PxD6Joint_DriveVelocity, 2 ), + DEFINE_ENUM_RANGE( PxD6Joint_Motion, PxD6Axis::eCOUNT ), + DEFINE_ENUM_RANGE( PxD6Joint_Drive, PxD6Drive::eCOUNT * ( PxExtensionsPropertyInfoName::PxD6JointDrive_PropertiesStop - PxExtensionsPropertyInfoName::PxD6JointDrive_PropertiesStart ) ), + DEFINE_ENUM_RANGE( PxD6Joint_LinearLimit, 100 ), + DEFINE_ENUM_RANGE( PxD6Joint_SwingLimit, 100 ), + DEFINE_ENUM_RANGE( PxD6Joint_TwistLimit, 100 ), + DEFINE_ENUM_RANGE( PxPrismaticJoint_Limit, 100 ), + DEFINE_ENUM_RANGE( PxRevoluteJoint_Limit, 100 ), + DEFINE_ENUM_RANGE( PxSphericalJoint_LimitCone, 100 ), + DEFINE_ENUM_RANGE( PxJoint_LocalPose, 2 ) + }; +}; + +} + +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtMetaData.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtMetaData.cpp new file mode 100644 index 00000000..4b1ff97a --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtMetaData.cpp @@ -0,0 +1,447 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "foundation/PxIO.h" +#include "PxJoint.h" +#include "ExtJoint.h" +#include "ExtD6Joint.h" +#include "ExtFixedJoint.h" +#include "ExtSphericalJoint.h" +#include "ExtDistanceJoint.h" +#include "ExtSphericalJoint.h" +#include "ExtRevoluteJoint.h" +#include "ExtPrismaticJoint.h" +#include "serialization/SnSerializationRegistry.h" +#include "serialization/Binary/SnSerializationContext.h" + +using namespace physx; +using namespace Cm; +using namespace Ext; + +/////////////////////////////////////////////////////////////////////////////// + + + + +static void getBinaryMetaData_JointData(PxOutputStream& stream) +{ + PX_DEF_BIN_METADATA_CLASS(stream, JointData) + + PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, JointData, PxTransform, c2b, 0) +#ifdef EXPLICIT_PADDING_METADATA + PX_DEF_BIN_METADATA_ITEM(stream, JointData, PxU32, paddingFromFlags, PxMetaDataFlag::ePADDING) +#endif + PX_DEF_BIN_METADATA_ITEM(stream, JointData, PxConstraintInvMassScale, invMassScale, 0) +} + +static void getBinaryMetaData_PxD6JointDrive(PxOutputStream& stream) +{ + PX_DEF_BIN_METADATA_TYPEDEF(stream, PxD6JointDriveFlags, PxU32) + + PX_DEF_BIN_METADATA_CLASS(stream, PxD6JointDrive) + PX_DEF_BIN_METADATA_ITEM(stream, PxD6JointDrive, PxReal, stiffness, 0) + PX_DEF_BIN_METADATA_ITEM(stream, PxD6JointDrive, PxReal, damping, 0) + PX_DEF_BIN_METADATA_ITEM(stream, PxD6JointDrive, PxReal, forceLimit, 0) + PX_DEF_BIN_METADATA_ITEM(stream, PxD6JointDrive, PxD6JointDriveFlags, flags, 0) +} + +static void getBinaryMetaData_PxJointLimitParameters(PxOutputStream& stream) +{ + PX_DEF_BIN_METADATA_CLASS(stream, PxJointLimitParameters) + + PX_DEF_BIN_METADATA_ITEM(stream, PxJointLimitParameters, PxReal, restitution, 0) + PX_DEF_BIN_METADATA_ITEM(stream, PxJointLimitParameters, PxReal, bounceThreshold, 0) + PX_DEF_BIN_METADATA_ITEM(stream, PxJointLimitParameters, PxReal, stiffness, 0) + PX_DEF_BIN_METADATA_ITEM(stream, PxJointLimitParameters, PxReal, damping, 0) + PX_DEF_BIN_METADATA_ITEM(stream, PxJointLimitParameters, PxReal, contactDistance, 0) +} + +static void getBinaryMetaData_PxJointLinearLimit(PxOutputStream& stream) +{ + PX_DEF_BIN_METADATA_CLASS(stream, PxJointLinearLimit) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, PxJointLinearLimit, PxJointLimitParameters) + + PX_DEF_BIN_METADATA_ITEM(stream, PxJointLinearLimit, PxReal, value, 0) +} + +static void getBinaryMetaData_PxJointLinearLimitPair(PxOutputStream& stream) +{ + PX_DEF_BIN_METADATA_CLASS(stream, PxJointLinearLimitPair) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, PxJointLinearLimitPair, PxJointLimitParameters) + + PX_DEF_BIN_METADATA_ITEM(stream, PxJointLinearLimitPair, PxReal, upper, 0) + PX_DEF_BIN_METADATA_ITEM(stream, PxJointLinearLimitPair, PxReal, lower, 0) +} + +static void getBinaryMetaData_PxJointAngularLimitPair(PxOutputStream& stream) +{ + PX_DEF_BIN_METADATA_CLASS(stream, PxJointAngularLimitPair) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, PxJointAngularLimitPair, PxJointLimitParameters) + + PX_DEF_BIN_METADATA_ITEM(stream, PxJointAngularLimitPair, PxReal, upper, 0) + PX_DEF_BIN_METADATA_ITEM(stream, PxJointAngularLimitPair, PxReal, lower, 0) +} + + +static void getBinaryMetaData_PxJointLimitCone(PxOutputStream& stream) +{ + PX_DEF_BIN_METADATA_CLASS(stream, PxJointLimitCone) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, PxJointLimitCone, PxJointLimitParameters) + + PX_DEF_BIN_METADATA_ITEM(stream, PxJointLimitCone, PxReal, yAngle, 0) + PX_DEF_BIN_METADATA_ITEM(stream, PxJointLimitCone, PxReal, zAngle, 0) +} + +void PxJoint::getBinaryMetaData(PxOutputStream& stream) +{ + PX_DEF_BIN_METADATA_VCLASS(stream, PxJoint) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, PxJoint, PxBase) + + PX_DEF_BIN_METADATA_ITEM(stream, PxJoint, void, userData, PxMetaDataFlag::ePTR) +} + +/////////////////////////////////////////////////////////////////////////////// + +static void getBinaryMetaData_RevoluteJointData(PxOutputStream& stream) +{ + PX_DEF_BIN_METADATA_TYPEDEF(stream, PxRevoluteJointFlags, PxU16) + + PX_DEF_BIN_METADATA_CLASS(stream, RevoluteJointData) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, RevoluteJointData, JointData) + + PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxReal, driveVelocity, 0) + PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxReal, driveForceLimit, 0) + PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxReal, driveGearRatio, 0) + + PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxJointAngularLimitPair,limit, 0) + + PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxReal, tqHigh, 0) + PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxReal, tqLow, 0) + PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxReal, tqPad, 0) + + PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxReal, projectionLinearTolerance, 0) + PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxReal, projectionAngularTolerance, 0) + + PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxRevoluteJointFlags, jointFlags, 0) +#ifdef EXPLICIT_PADDING_METADATA + PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxU16, paddingFromFlags, PxMetaDataFlag::ePADDING) +#endif +} + +void RevoluteJoint::getBinaryMetaData(PxOutputStream& stream) +{ + getBinaryMetaData_RevoluteJointData(stream); + + PX_DEF_BIN_METADATA_VCLASS(stream, RevoluteJoint) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, RevoluteJoint, PxJoint) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, RevoluteJoint, PxConstraintConnector) + + PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJoint, char, mName, PxMetaDataFlag::ePTR) + PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, RevoluteJoint, PxTransform, mLocalPose, 0) + PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJoint, PxConstraint, mPxConstraint, PxMetaDataFlag::ePTR) + PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJoint, JointData, mData, PxMetaDataFlag::ePTR) + + //------ Extra-data ------ + + PX_DEF_BIN_METADATA_EXTRA_ITEM(stream, RevoluteJoint, RevoluteJointData, mData, PX_SERIAL_ALIGN) + PX_DEF_BIN_METADATA_EXTRA_NAME(stream, RevoluteJoint, mName, 0) +} + +/////////////////////////////////////////////////////////////////////////////// + +static void getBinaryMetaData_SphericalJointData(PxOutputStream& stream) +{ + PX_DEF_BIN_METADATA_TYPEDEF(stream, PxSphericalJointFlags, PxU16) + + PX_DEF_BIN_METADATA_CLASS(stream, SphericalJointData) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, SphericalJointData, JointData) + + PX_DEF_BIN_METADATA_ITEM(stream, SphericalJointData, PxJointLimitCone, limit, 0) + PX_DEF_BIN_METADATA_ITEM(stream, SphericalJointData, PxReal, tanQYLimit, 0) + PX_DEF_BIN_METADATA_ITEM(stream, SphericalJointData, PxReal, tanQZLimit, 0) + PX_DEF_BIN_METADATA_ITEM(stream, SphericalJointData, PxReal, tanQPad, 0) + + PX_DEF_BIN_METADATA_ITEM(stream, SphericalJointData, PxReal, projectionLinearTolerance, 0) + + PX_DEF_BIN_METADATA_ITEM(stream, SphericalJointData, PxSphericalJointFlags, jointFlags, 0) +#ifdef EXPLICIT_PADDING_METADATA + PX_DEF_BIN_METADATA_ITEM(stream, SphericalJointData, PxU16, paddingFromFlags, PxMetaDataFlag::ePADDING) +#endif +} + +void SphericalJoint::getBinaryMetaData(PxOutputStream& stream) +{ + getBinaryMetaData_SphericalJointData(stream); + + PX_DEF_BIN_METADATA_VCLASS(stream, SphericalJoint) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, SphericalJoint, PxJoint) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, SphericalJoint, PxConstraintConnector) + + PX_DEF_BIN_METADATA_ITEM(stream, SphericalJoint, char, mName, PxMetaDataFlag::ePTR) + PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, SphericalJoint, PxTransform, mLocalPose, 0) + PX_DEF_BIN_METADATA_ITEM(stream, SphericalJoint, PxConstraint, mPxConstraint, PxMetaDataFlag::ePTR) + PX_DEF_BIN_METADATA_ITEM(stream, SphericalJoint, JointData, mData, PxMetaDataFlag::ePTR) + + //------ Extra-data ------ + + PX_DEF_BIN_METADATA_EXTRA_ITEM(stream, SphericalJoint, SphericalJointData, mData, PX_SERIAL_ALIGN) + PX_DEF_BIN_METADATA_EXTRA_NAME(stream, SphericalJoint, mName, 0) +} + +/////////////////////////////////////////////////////////////////////////////// + +static void getBinaryMetaData_DistanceJointData(PxOutputStream& stream) +{ + PX_DEF_BIN_METADATA_TYPEDEF(stream, PxDistanceJointFlags, PxU16) + + PX_DEF_BIN_METADATA_CLASS(stream, DistanceJointData) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, DistanceJointData, JointData) + + PX_DEF_BIN_METADATA_ITEM(stream, DistanceJointData, PxReal, minDistance, 0) + PX_DEF_BIN_METADATA_ITEM(stream, DistanceJointData, PxReal, maxDistance, 0) + PX_DEF_BIN_METADATA_ITEM(stream, DistanceJointData, PxReal, tolerance, 0) + PX_DEF_BIN_METADATA_ITEM(stream, DistanceJointData, PxReal, stiffness, 0) + PX_DEF_BIN_METADATA_ITEM(stream, DistanceJointData, PxReal, damping, 0) + PX_DEF_BIN_METADATA_ITEM(stream, DistanceJointData, PxDistanceJointFlags, jointFlags, 0) +#ifdef EXPLICIT_PADDING_METADATA + PX_DEF_BIN_METADATA_ITEM(stream, DistanceJointData, PxU16, paddingFromFlags, PxMetaDataFlag::ePADDING) +#endif +} + +void DistanceJoint::getBinaryMetaData(PxOutputStream& stream) +{ + getBinaryMetaData_DistanceJointData(stream); + + PX_DEF_BIN_METADATA_VCLASS(stream, DistanceJoint) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, DistanceJoint, PxJoint) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, DistanceJoint, PxConstraintConnector) + + PX_DEF_BIN_METADATA_ITEM(stream, DistanceJoint, char, mName, PxMetaDataFlag::ePTR) + PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, DistanceJoint, PxTransform, mLocalPose, 0) + PX_DEF_BIN_METADATA_ITEM(stream, DistanceJoint, PxConstraint, mPxConstraint, PxMetaDataFlag::ePTR) + PX_DEF_BIN_METADATA_ITEM(stream, DistanceJoint, JointData, mData, PxMetaDataFlag::ePTR) + + //------ Extra-data ------ + + PX_DEF_BIN_METADATA_EXTRA_ITEM(stream, DistanceJoint, DistanceJointData, mData, PX_SERIAL_ALIGN) + PX_DEF_BIN_METADATA_EXTRA_NAME(stream, DistanceJoint, mName, 0) +} + +/////////////////////////////////////////////////////////////////////////////// + +static void getBinaryMetaData_D6JointData(PxOutputStream& stream) +{ + PX_DEF_BIN_METADATA_TYPEDEF(stream, PxD6Motion::Enum, PxU32) + + PX_DEF_BIN_METADATA_CLASS(stream, D6JointData) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, D6JointData, JointData) + + PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, D6JointData, PxD6Motion::Enum, motion, 0) + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxJointLinearLimit, linearLimit, 0) + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxJointLimitCone, swingLimit, 0) + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxJointAngularLimitPair, twistLimit, 0) + + PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, D6JointData, PxD6JointDrive, drive, 0) + + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxTransform, drivePosition, 0) + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxVec3, driveLinearVelocity, 0) + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxVec3, driveAngularVelocity, 0) + + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxU32, locked, 0) + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxU32, limited, 0) + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxU32, driving, 0) + + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, thSwingY, 0) + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, thSwingZ, 0) + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, thSwingPad, 0) + + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, tqSwingY, 0) + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, tqSwingZ, 0) + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, tqSwingPad, 0) + + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, tqTwistLow, 0) + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, tqTwistHigh, 0) + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, tqTwistPad, 0) + + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, linearMinDist, 0) + + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, projectionLinearTolerance, 0) + PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, projectionAngularTolerance, 0) +} + +void D6Joint::getBinaryMetaData(PxOutputStream& stream) +{ + getBinaryMetaData_D6JointData(stream); + + PX_DEF_BIN_METADATA_VCLASS(stream, D6Joint) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, D6Joint, PxJoint) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, D6Joint, PxConstraintConnector) + + PX_DEF_BIN_METADATA_ITEM(stream, D6Joint, char, mName, PxMetaDataFlag::ePTR) + PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, D6Joint, PxTransform, mLocalPose, 0) + PX_DEF_BIN_METADATA_ITEM(stream, D6Joint, PxConstraint, mPxConstraint, PxMetaDataFlag::ePTR) + PX_DEF_BIN_METADATA_ITEM(stream, D6Joint, JointData, mData, PxMetaDataFlag::ePTR) + + PX_DEF_BIN_METADATA_ITEM(stream, D6Joint, bool, mRecomputeMotion, 0) + PX_DEF_BIN_METADATA_ITEM(stream, D6Joint, bool, mRecomputeLimits, 0) + PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, D6Joint, bool, mPadding, PxMetaDataFlag::ePADDING) + + //------ Extra-data ------ + + PX_DEF_BIN_METADATA_EXTRA_ITEM(stream, D6Joint, D6JointData, mData, PX_SERIAL_ALIGN) + PX_DEF_BIN_METADATA_EXTRA_NAME(stream, D6Joint, mName, 0) +} + +/////////////////////////////////////////////////////////////////////////////// + +static void getBinaryMetaData_PrismaticJointData(PxOutputStream& stream) +{ + PX_DEF_BIN_METADATA_TYPEDEF(stream, PxPrismaticJointFlags, PxU16) + + PX_DEF_BIN_METADATA_CLASS(stream, PrismaticJointData) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, PrismaticJointData, JointData) + + PX_DEF_BIN_METADATA_ITEM(stream, PrismaticJointData, PxJointLinearLimitPair, limit, 0) + PX_DEF_BIN_METADATA_ITEM(stream, PrismaticJointData, PxReal, projectionLinearTolerance, 0) + PX_DEF_BIN_METADATA_ITEM(stream, PrismaticJointData, PxReal, projectionAngularTolerance, 0) + PX_DEF_BIN_METADATA_ITEM(stream, PrismaticJointData, PxPrismaticJointFlags, jointFlags, 0) +#ifdef EXPLICIT_PADDING_METADATA + PX_DEF_BIN_METADATA_ITEM(stream, PrismaticJointData, PxU16, paddingFromFlags, PxMetaDataFlag::ePADDING) +#endif +} + +void PrismaticJoint::getBinaryMetaData(PxOutputStream& stream) +{ + getBinaryMetaData_PrismaticJointData(stream); + + PX_DEF_BIN_METADATA_VCLASS(stream, PrismaticJoint) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, PrismaticJoint, PxJoint) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, PrismaticJoint, PxConstraintConnector) + + PX_DEF_BIN_METADATA_ITEM(stream, PrismaticJoint, char, mName, PxMetaDataFlag::ePTR) + PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, PrismaticJoint, PxTransform, mLocalPose, 0) + PX_DEF_BIN_METADATA_ITEM(stream, PrismaticJoint, PxConstraint, mPxConstraint, PxMetaDataFlag::ePTR) + PX_DEF_BIN_METADATA_ITEM(stream, PrismaticJoint, JointData, mData, PxMetaDataFlag::ePTR) + + //------ Extra-data ------ + + PX_DEF_BIN_METADATA_EXTRA_ITEM(stream, PrismaticJoint, PrismaticJointData, mData, PX_SERIAL_ALIGN) + PX_DEF_BIN_METADATA_EXTRA_NAME(stream, PrismaticJoint, mName, 0) +} + +/////////////////////////////////////////////////////////////////////////////// + +static void getBinaryMetaData_FixedJointData(PxOutputStream& stream) +{ + PX_DEF_BIN_METADATA_CLASS(stream, FixedJointData) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, FixedJointData, JointData) + + PX_DEF_BIN_METADATA_ITEM(stream, FixedJointData, PxReal, projectionLinearTolerance, 0) + PX_DEF_BIN_METADATA_ITEM(stream, FixedJointData, PxReal, projectionAngularTolerance, 0) +} + +void FixedJoint::getBinaryMetaData(PxOutputStream& stream) +{ + getBinaryMetaData_FixedJointData(stream); + + PX_DEF_BIN_METADATA_VCLASS(stream, FixedJoint) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, FixedJoint, PxJoint) + PX_DEF_BIN_METADATA_BASE_CLASS(stream, FixedJoint, PxConstraintConnector) + + PX_DEF_BIN_METADATA_ITEM(stream, FixedJoint, char, mName, PxMetaDataFlag::ePTR) + PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, FixedJoint, PxTransform, mLocalPose, 0) + PX_DEF_BIN_METADATA_ITEM(stream, FixedJoint, PxConstraint, mPxConstraint, PxMetaDataFlag::ePTR) + PX_DEF_BIN_METADATA_ITEM(stream, FixedJoint, JointData, mData, PxMetaDataFlag::ePTR) + + //------ Extra-data ------ + + PX_DEF_BIN_METADATA_EXTRA_ITEM(stream, FixedJoint, FixedJointData, mData, PX_SERIAL_ALIGN) + PX_DEF_BIN_METADATA_EXTRA_NAME(stream, FixedJoint, mName, 0) +} + + +void getBinaryMetaData_SerializationContext(PxOutputStream& stream) +{ + PX_DEF_BIN_METADATA_TYPEDEF(stream, PxSerialObjectId, PxU64) + PX_DEF_BIN_METADATA_TYPEDEF(stream, SerialObjectIndex, PxU32) + + PX_DEF_BIN_METADATA_CLASS(stream, Sn::ManifestEntry) + PX_DEF_BIN_METADATA_ITEM(stream, Sn::ManifestEntry, PxU32, offset, 0) + PX_DEF_BIN_METADATA_ITEM(stream, Sn::ManifestEntry, PxType, type, 0) + + PX_DEF_BIN_METADATA_CLASS(stream, Sn::ImportReference) + PX_DEF_BIN_METADATA_ITEM(stream, Sn::ImportReference, PxSerialObjectId, id, 0) + PX_DEF_BIN_METADATA_ITEM(stream, Sn::ImportReference, PxType, type, 0) + + PX_DEF_BIN_METADATA_CLASS(stream, Sn::ExportReference) + PX_DEF_BIN_METADATA_ITEM(stream, Sn::ExportReference, PxSerialObjectId, id, 0) + PX_DEF_BIN_METADATA_ITEM(stream, Sn::ExportReference, SerialObjectIndex, objIndex, 0) + + PX_DEF_BIN_METADATA_CLASS(stream, Sn::InternalReferencePtr) + PX_DEF_BIN_METADATA_ITEM(stream, Sn::InternalReferencePtr, void, reference, PxMetaDataFlag::ePTR) + PX_DEF_BIN_METADATA_ITEM(stream, Sn::InternalReferencePtr, PxU32, kind, 0) + PX_DEF_BIN_METADATA_ITEM(stream, Sn::InternalReferencePtr, SerialObjectIndex, objIndex, 0) + + PX_DEF_BIN_METADATA_CLASS(stream, Sn::InternalReferenceIdx) + PX_DEF_BIN_METADATA_ITEM(stream, Sn::InternalReferenceIdx, PxU32, reference, 0) + PX_DEF_BIN_METADATA_ITEM(stream, Sn::InternalReferenceIdx, PxU32, kind, 0) + PX_DEF_BIN_METADATA_ITEM(stream, Sn::InternalReferenceIdx, SerialObjectIndex, objIndex, 0) +} + +namespace physx +{ +namespace Ext +{ +void GetExtensionsBinaryMetaData(PxOutputStream& stream) +{ + PX_DEF_BIN_METADATA_VCLASS(stream,PxConstraintConnector) + + getBinaryMetaData_JointData(stream); + getBinaryMetaData_PxD6JointDrive(stream); + getBinaryMetaData_PxJointLimitParameters(stream); + getBinaryMetaData_PxJointLimitCone(stream); + getBinaryMetaData_PxJointLinearLimit(stream); + getBinaryMetaData_PxJointLinearLimitPair(stream); + getBinaryMetaData_PxJointAngularLimitPair(stream); + + PxJoint::getBinaryMetaData(stream); + RevoluteJoint::getBinaryMetaData(stream); + SphericalJoint::getBinaryMetaData(stream); + DistanceJoint::getBinaryMetaData(stream); + D6Joint::getBinaryMetaData(stream); + PrismaticJoint::getBinaryMetaData(stream); + FixedJoint::getBinaryMetaData(stream); + + getBinaryMetaData_SerializationContext(stream); +} + +} +} + +/////////////////////////////////////////////////////////////////////////////// diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtParticleExt.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtParticleExt.cpp new file mode 100644 index 00000000..8f6ee803 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtParticleExt.cpp @@ -0,0 +1,356 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "foundation/PxMemory.h" +#include "foundation/PxBounds3.h" + +#include "PxParticleExt.h" +#include "PsUserAllocated.h" +#include "CmPhysXCommon.h" +#include "PsArray.h" +#include "PsHash.h" +#include "PsBitUtils.h" +#include "PsMathUtils.h" +#include "PsIntrinsics.h" +#include "PsFoundation.h" + +using namespace physx; + +//----------------------------------------------------------------------------// + +static const PxU32 sInvalidIndex = 0xffffffff; + +//----------------------------------------------------------------------------// + +struct CellCoords +{ + //! Set grid cell coordinates based on a point in space and a scaling factor + PX_INLINE void set(const PxVec3& realVec, PxReal scale) + { + x = static_cast<PxI16>(Ps::floor(realVec.x * scale)); + y = static_cast<PxI16>(Ps::floor(realVec.y * scale)); + z = static_cast<PxI16>(Ps::floor(realVec.z * scale)); + } + + PX_INLINE bool operator==(const CellCoords& v) const + { + return ((x == v.x) && (y == v.y) && (z == v.z)); + } + + PxI16 x; + PxI16 y; + PxI16 z; +}; + +//----------------------------------------------------------------------------// + +struct Cell +{ + CellCoords coords; + PxBounds3 aabb; + PxU32 start; + PxU32 size; +}; + +//----------------------------------------------------------------------------// + +PxU32 PX_INLINE hashFunction(const CellCoords& coords) +{ + PxU32 mix = PxU32(coords.x) + 101 * PxU32(coords.y) + 7919 * PxU32(coords.z); + PxU32 hash = Ps::hash(mix); + return hash; +} + +//----------------------------------------------------------------------------// + +PxU32 PX_INLINE getEntry(const CellCoords& coords, const PxU32 hashSize, const Cell* cells) +{ + PxU32 hash = hashFunction(coords); + PxU32 index = hash & (hashSize - 1); + for (;;) + { + const Cell& cell = cells[index]; + if (cell.size == sInvalidIndex || cell.coords == coords) + break; + index = (index + 1) & (hashSize - 1); + } + return index; +} + +//----------------------------------------------------------------------------// + +PxU32 PxParticleExt::buildBoundsHash(PxU32* sortedParticleIndices, + ParticleBounds* particleBounds, + const PxStrideIterator<const PxVec3>& positionBuffer, + const PxU32 validParticleRange, + const PxU32* validParticleBitmap, + const PxU32 hashSize, + const PxU32 maxBounds, + const PxReal gridSpacing) +{ + // test if hash size is a multiple of 2 + PX_ASSERT((((hashSize - 1) ^ hashSize) + 1) == (2 * hashSize)); + PX_ASSERT(maxBounds <= hashSize); + + PxReal cellSizeInv = 1.0f / gridSpacing; + + Ps::Array<PxU32> particleToCellMap PX_DEBUG_EXP("buildBoundsHashCellMap"); + particleToCellMap.resize(validParticleRange); + + // initialize cells + Ps::Array<Cell> cells PX_DEBUG_EXP("buildBoundsCells"); + cells.resize(hashSize); + PxMemSet(cells.begin(), sInvalidIndex, sizeof(Cell) * hashSize); + + // count number of particles per cell + PxU32 entryCounter = 0; + + if (validParticleRange > 0) + { + for (PxU32 w = 0; w <= (validParticleRange-1) >> 5; w++) + for (PxU32 b = validParticleBitmap[w]; b; b &= b-1) + { + PxU32 index = (w<<5|Ps::lowestSetBit(b)); + const PxVec3& position = positionBuffer[index]; + + PxU32& cellIndex = particleToCellMap[index]; + cellIndex = sInvalidIndex; // initialize to invalid in case we reach maxBounds + if (entryCounter < maxBounds) + { + CellCoords particleCoords; + particleCoords.set(position, cellSizeInv); + cellIndex = getEntry(particleCoords, hashSize, cells.begin()); + PX_ASSERT(cellIndex != sInvalidIndex); + + Cell& cell = cells[cellIndex]; + if (cell.size == sInvalidIndex) + { + // this is the first particle in this cell + cell.coords = particleCoords; + cell.aabb = PxBounds3(position, position); + cell.size = 1; + ++entryCounter; + } + else + { + // the cell is already occupied + cell.aabb.include(position); + ++cell.size; + } + } + } + } + + + // accumulate start indices from cell size histogram and write to the user's particleBounds buffer + PxU32 numBounds = 0; + for (PxU32 i = 0, counter = 0; i < cells.size(); i++) + { + Cell& cell = cells[i]; + if (cell.size != sInvalidIndex) + { + cell.start = counter; + counter += cell.size; + + PxParticleExt::ParticleBounds& cellBounds = particleBounds[numBounds++]; + PX_ASSERT(cell.aabb.isValid()); + cellBounds.bounds = cell.aabb; + cellBounds.firstParticle = cell.start; + cellBounds.numParticles = cell.size; + + cell.size = 0; + } + } + + // sort output particle indices by cell + if (validParticleRange > 0) + { + for (PxU32 w = 0; w <= (validParticleRange-1) >> 5; w++) + for (PxU32 b = validParticleBitmap[w]; b; b &= b-1) + { + PxU32 index = (w<<5|Ps::lowestSetBit(b)); + PxU32 cellIndex = particleToCellMap[index]; + if (cellIndex != sInvalidIndex) + { + Cell& cell = cells[cellIndex]; + PX_ASSERT(cell.start != sInvalidIndex && cell.size != sInvalidIndex); + sortedParticleIndices[cell.start + cell.size] = index; + ++cell.size; + } + } + } + + return numBounds; +} + +//----------------------------------------------------------------------------// + +class InternalIndexPool : public PxParticleExt::IndexPool, public Ps::UserAllocated +{ +public: + InternalIndexPool(PxU32 maxParticles); + InternalIndexPool(PxU32 maxParticles, PxU32 validParticleRange, const PxU32* validParticleBitmap); + virtual ~InternalIndexPool() {} + + virtual PxU32 allocateIndices(PxU32 num, const PxStrideIterator<PxU32>& indexBuffer); + virtual void freeIndices(PxU32 num, const PxStrideIterator<const PxU32>& indexBuffer); + virtual void freeIndices(); + virtual void release(); + +private: + PxU32 mIndexCount; + Ps::Array<PxU32> mFreeList; +}; + +InternalIndexPool::InternalIndexPool(PxU32 maxParticles) : mIndexCount(0), mFreeList(PX_DEBUG_EXP("InternalIndexPool:mFreeList")) +{ + mFreeList.reserve(maxParticles); +} + +InternalIndexPool::InternalIndexPool(PxU32 maxParticles, PxU32 validParticleRange, const PxU32* validParticleBitmap) : mIndexCount(0), mFreeList() +{ + mFreeList.reserve(maxParticles); + PX_ASSERT(validParticleRange <= maxParticles); + + mIndexCount = validParticleRange; + + if (validParticleRange > 0) + { + //find all the free indices in the valid range (for words fitting into validParticleRangle) + for (PxU32 w = 0; w < (validParticleRange-1) >> 5; w++) + { + for (PxU32 b = ~validParticleBitmap[w]; b; b &= b-1) + { + PxU32 invalidIndex = (w<<5|Ps::lowestSetBit(b)); + PX_ASSERT(invalidIndex < validParticleRange); + mFreeList.pushBack(invalidIndex); + } + } + + //for the last word, we need to make sure the index is in the valid range + { + PxU32 w = (validParticleRange-1) >> 5; + for (PxU32 b = ~validParticleBitmap[w]; b; b &= b-1) + { + PxU32 invalidIndex = (w<<5|Ps::lowestSetBit(b)); + if (invalidIndex >= validParticleRange) + break; + + mFreeList.pushBack(invalidIndex); + } + } + } +} + +PxU32 InternalIndexPool::allocateIndices(PxU32 num, const PxStrideIterator<PxU32>& indexBuffer) +{ + PxU32 numAllocated = mIndexCount - mFreeList.size(); + PxU32 numFree = mFreeList.capacity() - numAllocated; + PxU32 numAccepted = PxMin(num, numFree); + + if (numAccepted < num) + Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "PxParticleExt::IndexPool::allocateIndices: Not all requested indices allocated; maximum reached."); + + PxU32 numAdded = 0; + + PxU32 numToAddFromFreeList = PxMin(numAccepted, mFreeList.size()); + PxU32 numToAddFromFullBlock = numAccepted - numToAddFromFreeList; + + //add from free list + while (numToAddFromFreeList > 0) + { + indexBuffer[numAdded++] = mFreeList.popBack(); + numToAddFromFreeList--; + } + + //add from full block + while (numToAddFromFullBlock > 0) + { + indexBuffer[numAdded++] = mIndexCount++; + numToAddFromFullBlock--; + } + + PX_ASSERT(numAdded == numAccepted); + return numAccepted; +} + +void InternalIndexPool::freeIndices(PxU32 num, const PxStrideIterator<const PxU32>& indexBuffer) +{ + PxU32 numAllocated = mIndexCount - mFreeList.size(); + if (num > numAllocated) + { + Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "PxParticleExt::IndexPool::freeIndices: Provided number of indices exceeds number of actually allocated indices. Call faild."); + return; + } + +#ifdef PX_CHECK + for (PxU32 i = 0; i < num; ++i) + { + if (indexBuffer[i] < mIndexCount) + continue; + + Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "PxParticleExt::IndexPool::freeIndices: Provided indices which where not actually allocated before. Call failed."); + return; + } +#endif + + for (PxU32 i = 0; i < num; ++i) + mFreeList.pushBack(indexBuffer[i]); +} + +void InternalIndexPool::freeIndices() +{ + mIndexCount = 0; + mFreeList.clear(); +} + +void InternalIndexPool::release() +{ + PX_DELETE(this); +} + +//----------------------------------------------------------------------------// + +PxParticleExt::IndexPool* PxParticleExt::createIndexPool(PxU32 maxParticles) +{ + return PX_NEW(InternalIndexPool)(maxParticles); +} + +//----------------------------------------------------------------------------// + +PxParticleExt::IndexPool* PxParticleExt::createIndexPool(PxU32 maxParticles, PxU32 validParticleRange, const PxU32* validParticleBitmap) +{ + return PX_NEW(InternalIndexPool)(maxParticles, validParticleRange, validParticleBitmap); +} + +//----------------------------------------------------------------------------// diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtPlatform.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtPlatform.h new file mode 100644 index 00000000..237ff1e3 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtPlatform.h @@ -0,0 +1,39 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PLATFORM_H +#define PLATFORM_H + +#include <assert.h> +#include "foundation/Px.h" +#include "PsThread.h" +#include "CmPhysXCommon.h" + +#endif
\ No newline at end of file diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJoint.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJoint.cpp new file mode 100644 index 00000000..418fecf3 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJoint.cpp @@ -0,0 +1,219 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "ExtPrismaticJoint.h" +#include "ExtConstraintHelper.h" +#include "CmRenderOutput.h" +#include "CmVisualization.h" + +#include "common/PxSerialFramework.h" + +using namespace physx; +using namespace Ext; + +PxPrismaticJoint* physx::PxPrismaticJointCreate(PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) +{ + PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxPrismaticJointCreate: local frame 0 is not a valid transform"); + PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxPrismaticJointCreate: local frame 1 is not a valid transform"); + PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxPrismaticJointCreate: at least one actor must be dynamic"); + PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxPrismaticJointCreate: actors must be different"); + + PrismaticJoint* j; + PX_NEW_SERIALIZED(j,PrismaticJoint)(physics.getTolerancesScale(), actor0, localFrame0, actor1, localFrame1); + + if(j->attach(physics, actor0, actor1)) + return j; + + PX_DELETE(j); + return NULL; +} + +void PrismaticJoint::setProjectionAngularTolerance(PxReal tolerance) +{ + PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance >=0 && tolerance <= PxPi, "PxPrismaticJoint::setProjectionAngularTolerance: invalid parameter"); + data().projectionAngularTolerance = tolerance; + markDirty(); +} + +PxReal PrismaticJoint::getProjectionAngularTolerance() const +{ + return data().projectionAngularTolerance; +} + +void PrismaticJoint::setProjectionLinearTolerance(PxReal tolerance) +{ + PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance >=0, "PxPrismaticJoint::setProjectionLinearTolerance: invalid parameter"); + data().projectionLinearTolerance = tolerance; + markDirty(); +} + +PxReal PrismaticJoint::getProjectionLinearTolerance() const +{ + return data().projectionLinearTolerance; +} + +PxPrismaticJointFlags PrismaticJoint::getPrismaticJointFlags(void) const +{ + return data().jointFlags; +} + +void PrismaticJoint::setPrismaticJointFlags(PxPrismaticJointFlags flags) +{ + data().jointFlags = flags; markDirty(); +} + +void PrismaticJoint::setPrismaticJointFlag(PxPrismaticJointFlag::Enum flag, bool value) +{ + if(value) + data().jointFlags |= flag; + else + data().jointFlags &= ~flag; + markDirty(); +} + + +PxJointLinearLimitPair PrismaticJoint::getLimit() const +{ + return data().limit; +} + +void PrismaticJoint::setLimit(const PxJointLinearLimitPair& limit) +{ + PX_CHECK_AND_RETURN(limit.isValid(), "PxPrismaticJoint::setLimit: invalid parameter"); + data().limit = limit; + markDirty(); +} + + + +namespace +{ + + +void PrismaticJointVisualize(PxConstraintVisualizer& viz, + const void* constantBlock, + const PxTransform& body0Transform, + const PxTransform& body1Transform, + PxU32 /*flags*/) +{ + const PrismaticJointData& data = *reinterpret_cast<const PrismaticJointData*>(constantBlock); + + const PxTransform& t0 = body0Transform * data.c2b[0]; + const PxTransform& t1 = body1Transform * data.c2b[1]; + + viz.visualizeJointFrames(t0, t1); + + PxVec3 axis = t0.rotate(PxVec3(1.f,0,0)); + PxReal ordinate = axis.dot(t0.transformInv(t1.p)-t0.p); + + if(data.jointFlags & PxPrismaticJointFlag::eLIMIT_ENABLED) + { + viz.visualizeLinearLimit(t0, t1, data.limit.lower, ordinate < data.limit.lower + data.limit.contactDistance); + viz.visualizeLinearLimit(t0, t1, data.limit.upper, ordinate > data.limit.upper - data.limit.contactDistance); + } + +} + + + +void PrismaticJointProject(const void* constantBlock, + PxTransform& bodyAToWorld, + PxTransform& bodyBToWorld, + bool projectToA) +{ + using namespace joint; + + const PrismaticJointData& data = *reinterpret_cast<const PrismaticJointData*>(constantBlock); + + PxTransform cA2w, cB2w, cB2cA, projected; + computeDerived(data, bodyAToWorld, bodyBToWorld, cA2w, cB2w, cB2cA); + + PxVec3 v(0,cB2cA.p.y,cB2cA.p.z); + bool linearTrunc, angularTrunc; + projected.p = truncateLinear(v, data.projectionLinearTolerance, linearTrunc); + projected.q = truncateAngular(cB2cA.q, PxSin(data.projectionAngularTolerance/2), PxCos(data.projectionAngularTolerance/2), angularTrunc); + + if(linearTrunc || angularTrunc) + { + projected.p.x = cB2cA.p.x; + projectTransforms(bodyAToWorld, bodyBToWorld, cA2w, cB2w, projected, data, projectToA); + } +} +} + +bool Ext::PrismaticJoint::attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1) +{ + mPxConstraint = physics.createConstraint(actor0, actor1, *this, sShaders, sizeof(PrismaticJointData)); + return mPxConstraint!=NULL; +} + +void PrismaticJoint::exportExtraData(PxSerializationContext& stream) +{ + if(mData) + { + stream.alignData(PX_SERIAL_ALIGN); + stream.writeData(mData, sizeof(PrismaticJointData)); + } + stream.writeName(mName); +} + +void PrismaticJoint::importExtraData(PxDeserializationContext& context) +{ + if(mData) + mData = context.readExtraData<PrismaticJointData, PX_SERIAL_ALIGN>(); + context.readName(mName); +} + +void PrismaticJoint::resolveReferences(PxDeserializationContext& context) +{ + setPxConstraint(resolveConstraintPtr(context, getPxConstraint(), getConnector(), sShaders)); +} + +PrismaticJoint* PrismaticJoint::createObject(PxU8*& address, PxDeserializationContext& context) +{ + PrismaticJoint* obj = new (address) PrismaticJoint(PxBaseFlag::eIS_RELEASABLE); + address += sizeof(PrismaticJoint); + obj->importExtraData(context); + obj->resolveReferences(context); + return obj; +} + +// global function to share the joint shaders with API capture +const PxConstraintShaderTable* Ext::GetPrismaticJointShaderTable() +{ + return &PrismaticJoint::getConstraintShaderTable(); +} + +//~PX_SERIALIZATION +PxConstraintShaderTable Ext::PrismaticJoint::sShaders = { Ext::PrismaticJointSolverPrep, PrismaticJointProject, PrismaticJointVisualize, PxConstraintFlag::Enum(0) }; + + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJoint.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJoint.h new file mode 100644 index 00000000..79ce5f93 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJoint.h @@ -0,0 +1,155 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef NP_PRISMATICJOINTCONSTRAINT_H +#define NP_PRISMATICJOINTCONSTRAINT_H + +#include "ExtJoint.h" +#include "PxPrismaticJoint.h" +#include "PxTolerancesScale.h" +#include "CmUtils.h" + +namespace physx +{ +struct PxPrismaticJointGeneratedValues; +namespace Ext +{ + struct PrismaticJointData : public JointData + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + + PxJointLinearLimitPair limit; + PxReal projectionLinearTolerance; + PxReal projectionAngularTolerance; + + PxPrismaticJointFlags jointFlags; + // forestall compiler complaints about not being able to generate a constructor + private: + PrismaticJointData(const PxJointLinearLimitPair &pair): + limit(pair) {} + }; + + typedef Joint<PxPrismaticJoint, PxPrismaticJointGeneratedValues> PrismaticJointT; + + class PrismaticJoint : public PrismaticJointT + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + public: +// PX_SERIALIZATION + PrismaticJoint(PxBaseFlags baseFlags) : PrismaticJointT(baseFlags) {} + virtual void exportExtraData(PxSerializationContext& context); + void importExtraData(PxDeserializationContext& context); + void resolveReferences(PxDeserializationContext& context); + static PrismaticJoint* createObject(PxU8*& address, PxDeserializationContext& context); + static void getBinaryMetaData(PxOutputStream& stream); +//~PX_SERIALIZATION + virtual ~PrismaticJoint() + { + if(getBaseFlags()&PxBaseFlag::eOWNS_MEMORY) + PX_FREE(mData); + } + + PrismaticJoint(const PxTolerancesScale& scale, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) + : PrismaticJointT(PxJointConcreteType::ePRISMATIC, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE) + { + PrismaticJointData* data = reinterpret_cast<PrismaticJointData*>(PX_ALLOC(sizeof(PrismaticJointData), "PrismaticJointData")); + Cm::markSerializedMem(data, sizeof(PrismaticJointData)); + mData = data; + + data->limit = PxJointLinearLimitPair(scale, -PX_MAX_F32/3, PX_MAX_F32/3); + data->projectionLinearTolerance = 1e10f; + data->projectionAngularTolerance = PxPi; + data->jointFlags = PxPrismaticJointFlags(); + + initCommonData(*data, actor0, localFrame0, actor1, localFrame1); + } + + PxReal getPosition() const { return getRelativeTransform().p.x; } + PxReal getVelocity() const { return getRelativeLinearVelocity().x; } + + + void setProjectionAngularTolerance(PxReal tolerance); + PxReal getProjectionAngularTolerance() const; + + void setProjectionLinearTolerance(PxReal tolerance); + PxReal getProjectionLinearTolerance() const; + + PxJointLinearLimitPair getLimit() const; + void setLimit(const PxJointLinearLimitPair& limit); + + PxPrismaticJointFlags getPrismaticJointFlags(void) const; + void setPrismaticJointFlags(PxPrismaticJointFlags flags); + void setPrismaticJointFlag(PxPrismaticJointFlag::Enum flag, bool value); + + bool attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1); + + static const PxConstraintShaderTable& getConstraintShaderTable() { return sShaders; } + + virtual PxConstraintSolverPrep getPrep() const { return sShaders.solverPrep; } + + private: + PX_FORCE_INLINE PrismaticJointData& data() const + { + return *static_cast<PrismaticJointData*>(mData); + } + + static PxConstraintShaderTable sShaders; + }; +} // namespace Ext + +namespace Ext +{ + extern "C" PxU32 PrismaticJointSolverPrep(Px1DConstraint* constraints, + PxVec3& body0WorldOffset, + PxU32 maxConstraints, + PxConstraintInvMassScale& invMassScale, + const void* constantBlock, + const PxTransform& bA2w, + const PxTransform& bB2w); + + // global function to share the joint shaders with API capture + extern "C" const PxConstraintShaderTable* GetPrismaticJointShaderTable(); +} + +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJointSolverPrep.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJointSolverPrep.cpp new file mode 100644 index 00000000..64249545 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJointSolverPrep.cpp @@ -0,0 +1,81 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "ExtPrismaticJoint.h" +#include "ExtConstraintHelper.h" +#include "CmRenderOutput.h" + +namespace physx +{ +namespace Ext +{ + PxU32 PrismaticJointSolverPrep(Px1DConstraint* constraints, + PxVec3& body0WorldOffset, + PxU32 maxConstraints, + PxConstraintInvMassScale &invMassScale, + const void* constantBlock, + const PxTransform& bA2w, + const PxTransform& bB2w) + { + PX_UNUSED(maxConstraints); + + const PrismaticJointData& data = *reinterpret_cast<const PrismaticJointData*>(constantBlock); + invMassScale = data.invMassScale; + + PxTransform cA2w = bA2w.transform(data.c2b[0]); + PxTransform cB2w = bB2w.transform(data.c2b[1]); + + bool limitEnabled = data.jointFlags & PxPrismaticJointFlag::eLIMIT_ENABLED; + const PxJointLinearLimitPair &limit = data.limit; + bool limitIsLocked = limitEnabled && limit.lower >= limit.upper; + + PxVec3 bOriginInA = cA2w.transformInv(cB2w.p); + + body0WorldOffset = cB2w.p-bA2w.p; + joint::ConstraintHelper ch(constraints,cB2w.p-bA2w.p, cB2w.p-bB2w.p); + ch.prepareLockedAxes(cA2w.q, cB2w.q, bOriginInA, limitIsLocked ? 7ul : 6ul, 7ul); + + if(limitEnabled && !limitIsLocked) + { + PxVec3 axis = cA2w.rotate(PxVec3(1.f,0,0)); + PxReal ordinate = bOriginInA.x; + + ch.linearLimit(axis, ordinate, limit.upper, limit); + ch.linearLimit(-axis, -ordinate, -limit.lower, limit); + } + + return ch.getCount(); + } +}//namespace + +} + +//~PX_SERIALIZATION + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtPvd.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtPvd.cpp new file mode 100644 index 00000000..c6589a68 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtPvd.cpp @@ -0,0 +1,164 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +// suppress LNK4221 +#include "foundation/PxPreprocessor.h" +PX_DUMMY_SYMBOL + +#if PX_SUPPORT_PVD +#include "ExtPvd.h" +#include "PxExtensionMetaDataObjects.h" + +#include "ExtD6Joint.h" +#include "ExtFixedJoint.h" +#include "ExtSphericalJoint.h" +#include "ExtDistanceJoint.h" +#include "ExtSphericalJoint.h" +#include "ExtRevoluteJoint.h" +#include "ExtPrismaticJoint.h" +#include "ExtJointMetaDataExtensions.h" +#include "PvdMetaDataPropertyVisitor.h" +#include "PvdMetaDataDefineProperties.h" + +namespace physx +{ +namespace Ext +{ + using namespace physx::Vd; + + template<typename TObjType, typename TOperator> + inline void visitPvdInstanceProperties( TOperator inOperator ) + { + PxClassInfoTraits<TObjType>().Info.visitInstanceProperties( makePvdPropertyFilter( inOperator ), 0 ); + } + + template<typename TObjType, typename TOperator> + inline void visitPvdProperties( TOperator inOperator ) + { + PvdPropertyFilter<TOperator> theFilter( makePvdPropertyFilter( inOperator ) ); + PxU32 thePropCount = PxClassInfoTraits<TObjType>().Info.visitBaseProperties( theFilter ); + PxClassInfoTraits<TObjType>().Info.visitInstanceProperties( theFilter, thePropCount ); + } + + Pvd::PvdNameSpace::PvdNameSpace(physx::pvdsdk::PvdDataStream& conn, const char* /*name*/) + : mConnection(conn) + { + } + + Pvd::PvdNameSpace::~PvdNameSpace() + { + } + + void Pvd::releasePvdInstance(physx::pvdsdk::PvdDataStream& pvdConnection, const PxConstraint& c, const PxJoint& joint) + { + if(!pvdConnection.isConnected()) + return; + //remove from scene and from any attached actors. + PxRigidActor* actor0, *actor1; + c.getActors( actor0, actor1 ); + PxScene* scene = c.getScene(); + if(scene) pvdConnection.removeObjectRef( scene, "Joints", &joint ); + if ( actor0 && actor0->getScene() ) pvdConnection.removeObjectRef( actor0, "Joints", &joint ); + if ( actor1 && actor1->getScene()) pvdConnection.removeObjectRef( actor1, "Joints", &joint ); + pvdConnection.destroyInstance(&joint); + } + + template<typename TObjType> + void registerProperties( PvdDataStream& inStream ) + { + inStream.createClass<TObjType>(); + PvdPropertyDefinitionHelper& theHelper( inStream.getPropertyDefinitionHelper() ); + PvdClassInfoDefine theDefinitionObj( theHelper, getPvdNamespacedNameForType<TObjType>() ); + visitPvdInstanceProperties<TObjType>( theDefinitionObj ); + } + + template<typename TObjType, typename TValueStructType> + void registerPropertiesAndValueStruct( PvdDataStream& inStream ) + { + inStream.createClass<TObjType>(); + inStream.deriveClass<PxJoint,TObjType>(); + PvdPropertyDefinitionHelper& theHelper( inStream.getPropertyDefinitionHelper() ); + { + PvdClassInfoDefine theDefinitionObj( theHelper, getPvdNamespacedNameForType<TObjType>() ); + visitPvdInstanceProperties<TObjType>( theDefinitionObj ); + } + { + PvdClassInfoValueStructDefine theDefinitionObj( theHelper ); + visitPvdProperties<TObjType>( theDefinitionObj ); + theHelper.addPropertyMessage<TObjType,TValueStructType>(); + } + } + + void Pvd::sendClassDescriptions(physx::pvdsdk::PvdDataStream& inStream) + { + if (inStream.isClassExist<PxJoint>()) + return; + + { //PxJoint + registerProperties<PxJoint>( inStream ); + inStream.createProperty<PxJoint,ObjectRef>( "Parent", "parents" ); + registerPropertiesAndValueStruct<PxDistanceJoint,PxDistanceJointGeneratedValues>( inStream); + registerPropertiesAndValueStruct<PxFixedJoint,PxFixedJointGeneratedValues>( inStream); + registerPropertiesAndValueStruct<PxPrismaticJoint,PxPrismaticJointGeneratedValues>( inStream); + registerPropertiesAndValueStruct<PxSphericalJoint,PxSphericalJointGeneratedValues>( inStream); + registerPropertiesAndValueStruct<PxRevoluteJoint,PxRevoluteJointGeneratedValues>( inStream); + registerPropertiesAndValueStruct<PxD6Joint,PxD6JointGeneratedValues>( inStream); + } + } + + void Pvd::setActors( physx::pvdsdk::PvdDataStream& inStream, const PxJoint& inJoint, const PxConstraint& c, const PxActor* newActor0, const PxActor* newActor1 ) + { + PxRigidActor* actor0, *actor1; + c.getActors( actor0, actor1 ); + if ( actor0 ) + inStream.removeObjectRef( actor0, "Joints", &inJoint ); + if ( actor1 ) + inStream.removeObjectRef( actor1, "Joints", &inJoint ); + + if ( newActor0 && newActor0->getScene()) + inStream.pushBackObjectRef( newActor0, "Joints", &inJoint ); + if ( newActor1 && newActor1->getScene()) + inStream.pushBackObjectRef( newActor1, "Joints", &inJoint ); + + inStream.setPropertyValue( &inJoint, "Actors.actor0", reinterpret_cast<const void*>(newActor0) ); + inStream.setPropertyValue( &inJoint, "Actors.actor1", reinterpret_cast<const void*>(newActor1) ); + const void* parent = newActor0 ? newActor0 : newActor1; + inStream.setPropertyValue( &inJoint, "Parent", parent ); + + if((newActor0 && !newActor0->getScene()) || (newActor1 && !newActor1->getScene())) + { + inStream.removeObjectRef( c.getScene(), "Joints", &inJoint ); + } + + } +} + +} + +#endif // PX_SUPPORT_PVD diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtPvd.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtPvd.h new file mode 100644 index 00000000..2f3e3cf0 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtPvd.h @@ -0,0 +1,188 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef EXT_PVD_H +#define EXT_PVD_H + +#if PX_SUPPORT_PVD + +#include "CmPhysXCommon.h" +#include "PsUserAllocated.h" +#include "PxJoint.h" +#include "PxPvdDataStream.h" +#include "PxExtensionMetaDataObjects.h" +#include "PvdTypeNames.h" +#include "PxPvdObjectModelBaseTypes.h" + +namespace physx +{ + +class PxJoint; +class PxD6Joint; +class PxDistanceJoint; +class PxFixedJoint; +class PxPrismaticJoint; +class PxRevoluteJoint; +class PxSphericalJoint; +} + +#define JOINT_GROUP 3 +namespace physx +{ +namespace pvdsdk { + #define DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP( type ) DEFINE_PVD_TYPE_NAME_MAP( physx::type, "physx3", #type ) + + DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxJoint) + DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxJointGeneratedValues) + DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxFixedJoint) + DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxFixedJointGeneratedValues) + DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxDistanceJoint) + DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxDistanceJointGeneratedValues) + DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxPrismaticJoint) + DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxPrismaticJointGeneratedValues) + DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxRevoluteJoint) + DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxRevoluteJointGeneratedValues) + DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxSphericalJoint) + DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxSphericalJointGeneratedValues) + DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxD6Joint) + DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxD6JointGeneratedValues) +#undef DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP +} //pvdsdk +} // physx + +namespace physx +{ +namespace Ext +{ + using namespace physx::pvdsdk; + + class Pvd: public physx::shdfnd::UserAllocated + { + Pvd& operator=(const Pvd&); + public: + class PvdNameSpace + { + + public: + PvdNameSpace(PvdDataStream& conn, const char* name); + ~PvdNameSpace(); + private: + PvdNameSpace& operator=(const PvdNameSpace&); + PvdDataStream& mConnection; + }; + + static void setActors( PvdDataStream& PvdDataStream, + const PxJoint& inJoint, const PxConstraint& c, const PxActor* newActor0, const PxActor* newActor1 ); + + template<typename TObjType> + static void createInstance( PvdDataStream& inStream, const PxConstraint& c, const TObjType& inSource ) + { + inStream.createInstance( &inSource ); + inStream.pushBackObjectRef( c.getScene(), "Joints", &inSource ); + + class ConstraintUpdateCmd : public PvdDataStream::PvdCommand + { + ConstraintUpdateCmd &operator=(const ConstraintUpdateCmd&) { PX_ASSERT(0); return *this; } //PX_NOCOPY doesn't work for local classes + public: + + const PxConstraint& mConstraint; + const PxJoint& mJoint; + + PxRigidActor* actor0, *actor1; + ConstraintUpdateCmd(const PxConstraint& constraint, const PxJoint& joint):PvdDataStream::PvdCommand(), mConstraint(constraint), mJoint(joint) + { + mConstraint.getActors( actor0, actor1 ); + } + + //Assigned is needed for copying + ConstraintUpdateCmd(const ConstraintUpdateCmd& cmd) + :PvdDataStream::PvdCommand(), mConstraint(cmd.mConstraint), mJoint(cmd.mJoint) + { + } + + virtual bool canRun(PvdInstanceDataStream &inStream_ ) + { + PX_ASSERT(inStream_.isInstanceValid(&mJoint)); + //When run this command, the constraint maybe buffer removed + return ((actor0 == NULL) || inStream_.isInstanceValid(actor0)) + && ((actor1 == NULL) || inStream_.isInstanceValid(actor1)); + } + virtual void run( PvdInstanceDataStream &inStream_ ) + { + //When run this command, the constraint maybe buffer removed + if(!inStream_.isInstanceValid(&mJoint)) + return; + + PxRigidActor* actor0_, *actor1_; + mConstraint.getActors( actor0_, actor1_ ); + + if ( actor0_ && (inStream_.isInstanceValid(actor0_)) ) + inStream_.pushBackObjectRef( actor0_, "Joints", &mJoint ); + if ( actor1_ && (inStream_.isInstanceValid(actor1_)) ) + inStream_.pushBackObjectRef( actor1_, "Joints", &mJoint ); + const void* parent = actor0_ ? actor0_ : actor1_; + inStream_.setPropertyValue( &mJoint, "Parent", parent ); + } + }; + + ConstraintUpdateCmd* cmd = PX_PLACEMENT_NEW(inStream.allocateMemForCmd(sizeof(ConstraintUpdateCmd)), + ConstraintUpdateCmd)(c, inSource); + + if(cmd->canRun( inStream )) + cmd->run( inStream ); + else + inStream.pushPvdCommand( *cmd ); + } + + template<typename jointtype, typename structValue> + static void updatePvdProperties(PvdDataStream& pvdConnection, const jointtype& joint) + { + structValue theValueStruct( &joint ); + pvdConnection.setPropertyMessage( &joint, theValueStruct ); + } + + template<typename jointtype> + static void simUpdate(PvdDataStream& /*pvdConnection*/, const jointtype& /*joint*/) {} + + template<typename jointtype> + static void createPvdInstance(PvdDataStream& pvdConnection, const PxConstraint& c, const jointtype& joint) + { + createInstance<jointtype>( pvdConnection, c, joint ); + } + + static void releasePvdInstance(PvdDataStream& pvdConnection, const PxConstraint& c, const PxJoint& joint); + static void sendClassDescriptions(PvdDataStream& pvdConnection); + }; +} // ext + +} // physx + +#endif // PX_SUPPORT_PVD +#endif // EXT_PVD_H diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtPxStringTable.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtPxStringTable.cpp new file mode 100644 index 00000000..ac302013 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtPxStringTable.cpp @@ -0,0 +1,99 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "foundation/PxAllocatorCallback.h" +#include "PxStringTableExt.h" +#include "PxProfileAllocatorWrapper.h" //tools for using a custom allocator +#include "PsString.h" +#include "PsUserAllocated.h" +#include "CmPhysXCommon.h" + +namespace physx +{ + using namespace physx::profile; + + class PxStringTableImpl : public PxStringTable, public Ps::UserAllocated + { + typedef PxProfileHashMap<const char*, PxU32> THashMapType; + PxProfileAllocatorWrapper mWrapper; + THashMapType mHashMap; + public: + + PxStringTableImpl( PxAllocatorCallback& inAllocator ) + : mWrapper ( inAllocator ) + , mHashMap ( mWrapper ) + { + } + + virtual ~PxStringTableImpl() + { + for ( THashMapType::Iterator iter = mHashMap.getIterator(); + iter.done() == false; + ++iter ) + PX_PROFILE_DELETE( mWrapper, const_cast<char*>( iter->first ) ); + mHashMap.clear(); + } + + + virtual const char* allocateStr( const char* inSrc ) + { + if ( inSrc == NULL ) + inSrc = ""; + const THashMapType::Entry* existing( mHashMap.find( inSrc ) ); + if ( existing == NULL ) + { + size_t len( strlen( inSrc ) ); + len += 1; + char* newMem = reinterpret_cast<char*>(mWrapper.getAllocator().allocate( len, "PxStringTableImpl: const char*", __FILE__, __LINE__ )); + physx::shdfnd::strlcpy( newMem, len, inSrc ); + mHashMap.insert( newMem, 1 ); + return newMem; + } + else + { + ++const_cast<THashMapType::Entry*>(existing)->second; + return existing->first; + } + } + + /** + * Release the string table and all the strings associated with it. + */ + virtual void release() + { + PX_PROFILE_DELETE( mWrapper.getAllocator(), this ); + } + }; + + PxStringTable& PxStringTableExt::createStringTable( PxAllocatorCallback& inAllocator ) + { + return *PX_PROFILE_NEW( inAllocator, PxStringTableImpl )( inAllocator ); + } +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtRaycastCCD.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtRaycastCCD.cpp new file mode 100644 index 00000000..6122e82a --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtRaycastCCD.cpp @@ -0,0 +1,305 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PxRaycastCCD.h" + +using namespace physx; + +#include "geometry/PxBoxGeometry.h" +#include "geometry/PxSphereGeometry.h" +#include "geometry/PxCapsuleGeometry.h" +#include "geometry/PxConvexMeshGeometry.h" +#include "geometry/PxConvexMesh.h" +#include "PxScene.h" +#include "PxRigidDynamic.h" +#include "extensions/PxShapeExt.h" +#include "PsArray.h" + +namespace physx +{ +class RaycastCCDManagerInternal +{ + PX_NOCOPY(RaycastCCDManagerInternal) + public: + RaycastCCDManagerInternal(PxScene* scene) : mScene(scene) {} + ~RaycastCCDManagerInternal(){} + + bool registerRaycastCCDObject(PxRigidDynamic* actor, PxShape* shape); + + void doRaycastCCD(bool doDynamicDynamicCCD); + + struct CCDObject + { + PX_FORCE_INLINE CCDObject(PxRigidDynamic* actor, PxShape* shape, const PxVec3& witness) : mActor(actor), mShape(shape), mWitness(witness) {} + PxRigidDynamic* mActor; + PxShape* mShape; + PxVec3 mWitness; + }; + + private: + PxScene* mScene; + physx::shdfnd::Array<CCDObject> mObjects; +}; +} + +static PxVec3 getShapeCenter(PxShape* shape, const PxTransform& pose) +{ + PxVec3 offset(0.0f); + if(shape->getGeometryType()==PxGeometryType::eCONVEXMESH) + { + PxConvexMeshGeometry geometry; + bool status = shape->getConvexMeshGeometry(geometry); + PX_UNUSED(status); + PX_ASSERT(status); + + PxReal mass; + PxMat33 localInertia; + PxVec3 localCenterOfMass; + geometry.convexMesh->getMassInformation(mass, localInertia, localCenterOfMass); + + offset += localCenterOfMass; + } + return pose.transform(offset); +} + +static PX_FORCE_INLINE PxVec3 getShapeCenter(PxRigidActor* actor, PxShape* shape) +{ + const PxTransform pose = PxShapeExt::getGlobalPose(*shape, *actor); + return getShapeCenter(shape, pose); +} + +static PxReal computeInternalRadius(PxRigidActor* actor, PxShape* shape, const PxVec3& dir) +{ + const PxBounds3 bounds = PxShapeExt::getWorldBounds(*shape, *actor); + const PxReal diagonal = (bounds.maximum - bounds.minimum).magnitude(); + const PxReal offsetFromOrigin = diagonal * 2.0f; + + PxTransform pose = PxShapeExt::getGlobalPose(*shape, *actor); + + PxReal internalRadius = 0.0f; + const PxReal length = offsetFromOrigin*2.0f; + + switch(shape->getGeometryType()) + { + case PxGeometryType::eSPHERE: + { + PxSphereGeometry geometry; + bool status = shape->getSphereGeometry(geometry); + PX_UNUSED(status); + PX_ASSERT(status); + + internalRadius = geometry.radius; + } + break; + + case PxGeometryType::eBOX: + case PxGeometryType::eCAPSULE: + { + pose.p = PxVec3(0.0f); + const PxVec3 virtualOrigin = pose.p + dir * offsetFromOrigin; + + PxRaycastHit hit; + PxU32 nbHits = PxGeometryQuery::raycast(virtualOrigin, -dir, shape->getGeometry().any(), pose, length, PxHitFlag::eDISTANCE, 1, &hit); + PX_UNUSED(nbHits); + PX_ASSERT(nbHits); + + internalRadius = offsetFromOrigin - hit.distance; + } + break; + + case PxGeometryType::eCONVEXMESH: + { + PxVec3 shapeCenter = getShapeCenter(shape, pose); + shapeCenter -= pose.p; + pose.p = PxVec3(0.0f); + + const PxVec3 virtualOrigin = shapeCenter + dir * offsetFromOrigin; + PxRaycastHit hit; + PxU32 nbHits = PxGeometryQuery::raycast(virtualOrigin, -dir, shape->getGeometry().any(), pose, length, PxHitFlag::eDISTANCE, 1, &hit); + PX_UNUSED(nbHits); + PX_ASSERT(nbHits); + + internalRadius = offsetFromOrigin - hit.distance; + } + break; + + case PxGeometryType::ePLANE: + case PxGeometryType::eHEIGHTFIELD: + case PxGeometryType::eTRIANGLEMESH: + case PxGeometryType::eGEOMETRY_COUNT: + case PxGeometryType::eINVALID: + break; + } + return internalRadius; +} + +class CCDRaycastFilterCallback : public PxQueryFilterCallback +{ +public: + CCDRaycastFilterCallback(PxRigidActor* actor, PxShape* shape) : mActor(actor), mShape(shape){} + + PxRigidActor* mActor; + PxShape* mShape; + + virtual PxQueryHitType::Enum preFilter(const PxFilterData&, const PxShape* shape, const PxRigidActor* actor, PxHitFlags&) + { + if(mActor==actor && mShape==shape) + return PxQueryHitType::eNONE; + return PxQueryHitType::eBLOCK; + } + + virtual PxQueryHitType::Enum postFilter(const PxFilterData&, const PxQueryHit&) + { + return PxQueryHitType::eNONE; + } +}; + +static bool CCDRaycast(PxScene* scene, PxRigidActor* actor, PxShape* shape, const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, PxRaycastHit& hit, bool dyna_dyna) +{ + const PxQueryFlags qf(dyna_dyna ? PxQueryFlags(PxQueryFlag::eSTATIC|PxQueryFlag::eDYNAMIC|PxQueryFlag::ePREFILTER) : PxQueryFlags(PxQueryFlag::eSTATIC)); + const PxQueryFilterData filterData(PxFilterData(), qf); + + CCDRaycastFilterCallback CB(actor, shape); + + PxRaycastBuffer buf1; + scene->raycast(origin, unitDir, distance, buf1, PxHitFlag::eDISTANCE, filterData, &CB); + hit = buf1.block; + return buf1.hasBlock; +} + +static PxRigidDynamic* canDoCCD(PxRigidActor& actor, PxShape* /*shape*/) +{ + if(actor.getConcreteType()!=PxConcreteType::eRIGID_DYNAMIC) + return NULL; // PT: no need to do it for statics + PxRigidDynamic* dyna = static_cast<PxRigidDynamic*>(&actor); + + const PxU32 nbShapes = dyna->getNbShapes(); + if(nbShapes!=1) + return NULL; // PT: only works with simple actors for now + + if(dyna->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC) + return NULL; // PT: no need to do it for kinematics + + return dyna; +} + +static bool doRaycastCCD(PxScene* scene, const RaycastCCDManagerInternal::CCDObject& object, PxTransform& newPose, PxVec3& newShapeCenter, bool dyna_dyna) +{ + PxRigidDynamic* dyna = canDoCCD(*object.mActor, object.mShape); + if(!dyna) + return true; + + bool updateCCDWitness = true; + + const PxVec3 offset = newPose.p - newShapeCenter; + const PxVec3& origin = object.mWitness; + const PxVec3& dest = newShapeCenter; + + PxVec3 dir = dest - origin; + const PxReal length = dir.magnitude(); + if(length!=0.0f) + { + dir /= length; + + const PxReal internalRadius = computeInternalRadius(object.mActor, object.mShape, dir); + + PxRaycastHit hit; + if(internalRadius!=0.0f && CCDRaycast(scene, object.mActor, object.mShape, origin, dir, length, hit, dyna_dyna)) + { + updateCCDWitness = false; + + const PxReal radiusLimit = internalRadius * 0.75f; + if(hit.distance>radiusLimit) + { + newShapeCenter = origin + dir * (hit.distance - radiusLimit); + } + else + { + if(hit.actor->getConcreteType()==PxConcreteType::eRIGID_DYNAMIC) + return true; + + newShapeCenter = origin; + } + + newPose.p = offset + newShapeCenter; + const PxTransform shapeLocalPose = object.mShape->getLocalPose(); + const PxTransform inverseShapeLocalPose = shapeLocalPose.getInverse(); + const PxTransform newGlobalPose = newPose * inverseShapeLocalPose; + dyna->setGlobalPose(newGlobalPose); + } + } + return updateCCDWitness; +} + +bool RaycastCCDManagerInternal::registerRaycastCCDObject(PxRigidDynamic* actor, PxShape* shape) +{ + if(!actor || !shape) + return false; + + mObjects.pushBack(CCDObject(actor, shape, getShapeCenter(actor, shape))); + return true; +} + +void RaycastCCDManagerInternal::doRaycastCCD(bool doDynamicDynamicCCD) +{ + const PxU32 nbObjects = mObjects.size(); + for(PxU32 i=0;i<nbObjects;i++) + { + CCDObject& object = mObjects[i]; + + if(object.mActor->isSleeping()) + continue; + + PxTransform newPose = PxShapeExt::getGlobalPose(*object.mShape, *object.mActor); + PxVec3 newShapeCenter = getShapeCenter(object.mShape, newPose); + + if(::doRaycastCCD(mScene, object, newPose, newShapeCenter, doDynamicDynamicCCD)) + object.mWitness = newShapeCenter; + } +} + +RaycastCCDManager::RaycastCCDManager(PxScene* scene) +{ + mImpl = new RaycastCCDManagerInternal(scene); +} + +RaycastCCDManager::~RaycastCCDManager() +{ + delete mImpl; +} + +bool RaycastCCDManager::registerRaycastCCDObject(PxRigidDynamic* actor, PxShape* shape) +{ + return mImpl->registerRaycastCCDObject(actor, shape); +} + +void RaycastCCDManager::doRaycastCCD(bool doDynamicDynamicCCD) +{ + mImpl->doRaycastCCD(doDynamicDynamicCCD); +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJoint.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJoint.cpp new file mode 100644 index 00000000..2fb85184 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJoint.cpp @@ -0,0 +1,287 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "ExtRevoluteJoint.h" +#include "PsUtilities.h" +#include "ExtConstraintHelper.h" +#include "CmRenderOutput.h" +#include "PsMathUtils.h" +#include "CmVisualization.h" +#include "CmUtils.h" + +#include "common/PxSerialFramework.h" + +using namespace physx; +using namespace Ext; + +namespace physx +{ + PxRevoluteJoint* PxRevoluteJointCreate(PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1); +} + +PxRevoluteJoint* physx::PxRevoluteJointCreate(PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) +{ + PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxRevoluteJointCreate: local frame 0 is not a valid transform"); + PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxRevoluteJointCreate: local frame 1 is not a valid transform"); + PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxRevoluteJointCreate: actors must be different"); + PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxRevoluteJointCreate: at least one actor must be dynamic"); + + RevoluteJoint* j; + PX_NEW_SERIALIZED(j,RevoluteJoint)(physics.getTolerancesScale(), actor0, localFrame0, actor1, localFrame1); + if(j->attach(physics, actor0, actor1)) + return j; + + PX_DELETE(j); + return NULL; +} + + +PxReal RevoluteJoint::getAngle() const +{ + PxQuat q = getRelativeTransform().q, swing, twist; + Ps::separateSwingTwist(q, swing, twist); + PxReal angle = twist.getAngle(); + if(q.x<0) + angle = 2*PxPi - angle; + if(angle>PxPi) + angle-=2*PxPi; + return angle; + +} + +PxReal RevoluteJoint::getVelocity() const +{ + return getRelativeAngularVelocity().x; +} + + + +PxJointAngularLimitPair RevoluteJoint::getLimit() const +{ + return data().limit; +} + +void RevoluteJoint::setLimit(const PxJointAngularLimitPair& limit) +{ + PX_CHECK_AND_RETURN(limit.isValid(), "PxRevoluteJoint::setTwistLimit: limit invalid"); + PX_CHECK_AND_RETURN(limit.lower>-PxPi && limit.upper<PxPi , "PxRevoluteJoint::twist limit must be strictly -*PI and PI"); + PX_CHECK_AND_RETURN(limit.upper - limit.lower < PxTwoPi, "PxRevoluteJoint::twist limit range must be strictly less than 2*PI"); + data().limit = limit; + markDirty(); +} + +PxReal RevoluteJoint::getDriveVelocity() const +{ + return data().driveVelocity; +} + +void RevoluteJoint::setDriveVelocity(PxReal velocity) +{ + PX_CHECK_AND_RETURN(PxIsFinite(velocity), "PxRevoluteJoint::setDriveVelocity: invalid parameter"); + data().driveVelocity = velocity; + markDirty(); +} + +PxReal RevoluteJoint::getDriveForceLimit() const +{ + return data().driveForceLimit; +} + +void RevoluteJoint::setDriveForceLimit(PxReal forceLimit) +{ + PX_CHECK_AND_RETURN(PxIsFinite(forceLimit), "PxRevoluteJoint::setDriveForceLimit: invalid parameter"); + data().driveForceLimit = forceLimit; + markDirty(); +} + +PxReal RevoluteJoint::getDriveGearRatio() const +{ + return data().driveGearRatio; +} + +void RevoluteJoint::setDriveGearRatio(PxReal gearRatio) +{ + PX_CHECK_AND_RETURN(PxIsFinite(gearRatio) && gearRatio>0, "PxRevoluteJoint::setDriveGearRatio: invalid parameter"); + data().driveGearRatio = gearRatio; + markDirty(); +} + +void RevoluteJoint::setProjectionAngularTolerance(PxReal tolerance) +{ + PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance>=0 && tolerance<=PxPi, "PxRevoluteJoint::setProjectionAngularTolerance: invalid parameter"); + data().projectionAngularTolerance = tolerance; + markDirty(); +} + +PxReal RevoluteJoint::getProjectionAngularTolerance() const +{ + return data().projectionAngularTolerance; +} + +void RevoluteJoint::setProjectionLinearTolerance(PxReal tolerance) +{ + PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance >=0, "PxRevoluteJoint::setProjectionLinearTolerance: invalid parameter"); + data().projectionLinearTolerance = tolerance; + markDirty(); +} + +PxReal RevoluteJoint::getProjectionLinearTolerance() const +{ + return data().projectionLinearTolerance; +} + +PxRevoluteJointFlags RevoluteJoint::getRevoluteJointFlags(void) const +{ + return data().jointFlags; +} + +void RevoluteJoint::setRevoluteJointFlags(PxRevoluteJointFlags flags) +{ + data().jointFlags = flags; +} + +void RevoluteJoint::setRevoluteJointFlag(PxRevoluteJointFlag::Enum flag, bool value) +{ + if(value) + data().jointFlags |= flag; + else + data().jointFlags &= ~flag; + markDirty(); +} + + + + +void* Ext::RevoluteJoint::prepareData() +{ + data().tqHigh = PxTan(data().limit.upper/4); + data().tqLow = PxTan(data().limit.lower/4); + data().tqPad = PxTan(data().limit.contactDistance/4); + + return RevoluteJointT::prepareData(); +} + + +namespace +{ + +void RevoluteJointProject(const void* constantBlock, + PxTransform& bodyAToWorld, + PxTransform& bodyBToWorld, + bool projectToA) +{ + using namespace joint; + + const RevoluteJointData& data = *reinterpret_cast<const RevoluteJointData*>(constantBlock); + + PxTransform cA2w, cB2w, cB2cA, projected; + computeDerived(data, bodyAToWorld, bodyBToWorld, cA2w, cB2w, cB2cA); + + bool linearTrunc, angularTrunc; + projected.p = truncateLinear(cB2cA.p, data.projectionLinearTolerance, linearTrunc); + + PxQuat swing, twist, projSwing; + Ps::separateSwingTwist(cB2cA.q,swing,twist); + projSwing = truncateAngular(swing, PxSin(data.projectionAngularTolerance/2), PxCos(data.projectionAngularTolerance/2), angularTrunc); + + if(linearTrunc || angularTrunc) + { + projected.q = projSwing * twist; + projectTransforms(bodyAToWorld, bodyBToWorld, cA2w, cB2w, projected, data, projectToA); + } +} + +void RevoluteJointVisualize(PxConstraintVisualizer& viz, + const void* constantBlock, + const PxTransform& body0Transform, + const PxTransform& body1Transform, + PxU32 /*flags*/) +{ + const RevoluteJointData& data = *reinterpret_cast<const RevoluteJointData*>(constantBlock); + + const PxTransform& t0 = body0Transform * data.c2b[0]; + const PxTransform& t1 = body1Transform * data.c2b[1]; + + viz.visualizeJointFrames(t0, t1); + + if(data.jointFlags & PxRevoluteJointFlag::eLIMIT_ENABLED) + viz.visualizeAngularLimit(t0, data.limit.lower, data.limit.upper, false); +} +} + +bool Ext::RevoluteJoint::attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1) +{ + mPxConstraint = physics.createConstraint(actor0, actor1, *this, sShaders, sizeof(RevoluteJointData)); + return mPxConstraint!=NULL; +} + +void RevoluteJoint::exportExtraData(PxSerializationContext& stream) +{ + if(mData) + { + stream.alignData(PX_SERIAL_ALIGN); + stream.writeData(mData, sizeof(RevoluteJointData)); + } + stream.writeName(mName); +} + +void RevoluteJoint::importExtraData(PxDeserializationContext& context) +{ + if(mData) + mData = context.readExtraData<RevoluteJointData, PX_SERIAL_ALIGN>(); + context.readName(mName); +} + +void RevoluteJoint::resolveReferences(PxDeserializationContext& context) +{ + setPxConstraint(resolveConstraintPtr(context, getPxConstraint(), getConnector(), sShaders)); +} + +RevoluteJoint* RevoluteJoint::createObject(PxU8*& address, PxDeserializationContext& context) +{ + RevoluteJoint* obj = new (address) RevoluteJoint(PxBaseFlag::eIS_RELEASABLE); + address += sizeof(RevoluteJoint); + obj->importExtraData(context); + obj->resolveReferences(context); + return obj; +} + +// global function to share the joint shaders with API capture +const PxConstraintShaderTable* Ext::GetRevoluteJointShaderTable() +{ + return &RevoluteJoint::getConstraintShaderTable(); +} + +//~PX_SERIALIZATION +PxConstraintShaderTable Ext::RevoluteJoint::sShaders = { Ext::RevoluteJointSolverPrep, RevoluteJointProject, RevoluteJointVisualize, PxConstraintFlag::Enum(0) }; diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJoint.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJoint.h new file mode 100644 index 00000000..caf65b3a --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJoint.h @@ -0,0 +1,184 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef NP_REVOLUTEJOINTCONSTRAINT_H +#define NP_REVOLUTEJOINTCONSTRAINT_H + +#include "ExtJoint.h" +#include "PxRevoluteJoint.h" +#include "PsIntrinsics.h" +#include "CmUtils.h" + +namespace physx +{ + +class PxConstraintSolverPrepKernel; +class PxConstraintProjectionKernel; +struct PxRevoluteJointGeneratedValues; + +namespace Ext +{ + struct RevoluteJointData : public JointData + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + + PxReal driveVelocity; + PxReal driveForceLimit; + PxReal driveGearRatio; + + PxJointAngularLimitPair limit; + + PxReal tqHigh; + PxReal tqLow; + PxReal tqPad; + + PxReal projectionLinearTolerance; + PxReal projectionAngularTolerance; + + PxRevoluteJointFlags jointFlags; + // forestall compiler complaints about not being able to generate a constructor + private: + RevoluteJointData(const PxJointAngularLimitPair &pair): + limit(pair) {} + }; + + typedef Joint<PxRevoluteJoint, PxRevoluteJointGeneratedValues> RevoluteJointT; + + class RevoluteJoint : public RevoluteJointT + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + public: +// PX_SERIALIZATION + RevoluteJoint(PxBaseFlags baseFlags) : RevoluteJointT(baseFlags) {} + void resolveReferences(PxDeserializationContext& context); + virtual void exportExtraData(PxSerializationContext& context); + void importExtraData(PxDeserializationContext& context); + static RevoluteJoint* createObject(PxU8*& address, PxDeserializationContext& context); + static void getBinaryMetaData(PxOutputStream& stream); +//~PX_SERIALIZATION + virtual ~RevoluteJoint() + { + if(getBaseFlags()&PxBaseFlag::eOWNS_MEMORY) + PX_FREE(mData); + } + + RevoluteJoint(const PxTolerancesScale& /*scale*/, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) + : RevoluteJointT(PxJointConcreteType::eREVOLUTE, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE) + { + RevoluteJointData* data = reinterpret_cast<RevoluteJointData*>(PX_ALLOC(sizeof(RevoluteJointData), "RevoluteJointData")); + Cm::markSerializedMem(data, sizeof(RevoluteJointData)); + mData = data; + + initCommonData(*data, actor0, localFrame0, actor1, localFrame1); + + data->projectionLinearTolerance = 1e10f; + data->projectionAngularTolerance = PxPi; + data->driveForceLimit = PX_MAX_F32; + data->driveVelocity = 0; + data->driveGearRatio = 1.0f; + data->limit = PxJointAngularLimitPair(-PxPi/2, PxPi/2); + data->jointFlags = PxRevoluteJointFlags(); + } + + PxReal getAngle() const; + PxReal getVelocity() const; + + PxJointAngularLimitPair getLimit() const; + void setLimit(const PxJointAngularLimitPair& limit); + + PxReal getDriveVelocity() const; + void setDriveVelocity(PxReal velocity); + + PxReal getDriveForceLimit() const; + void setDriveForceLimit(PxReal forceLimit); + + PxReal getDriveGearRatio() const; + void setDriveGearRatio(PxReal gearRatio); + + void setProjectionAngularTolerance(PxReal tolerance); + PxReal getProjectionAngularTolerance() const; + + void setProjectionLinearTolerance(PxReal distance); + PxReal getProjectionLinearTolerance() const; + + PxRevoluteJointFlags getRevoluteJointFlags(void) const; + void setRevoluteJointFlags(PxRevoluteJointFlags flags); + void setRevoluteJointFlag(PxRevoluteJointFlag::Enum flag, bool value); + + void* prepareData(); + + bool attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1); + + static const PxConstraintShaderTable& getConstraintShaderTable() { return sShaders; } + + virtual PxConstraintSolverPrep getPrep() const { return sShaders.solverPrep; } + + private: + + static PxConstraintShaderTable sShaders; + + PX_FORCE_INLINE RevoluteJointData& data() const + { + return *static_cast<RevoluteJointData*>(mData); + } + + }; + +} // namespace Ext + +namespace Ext +{ + extern "C" PxU32 RevoluteJointSolverPrep(Px1DConstraint* constraints, + PxVec3& body0WorldOffset, + PxU32 maxConstraints, + PxConstraintInvMassScale& invMassScale, + const void* constantBlock, + const PxTransform& bA2w, + const PxTransform& bB2w); + + // global function to share the joint shaders with API capture + extern "C" const PxConstraintShaderTable* GetRevoluteJointShaderTable(); +} + +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJointSolverPrep.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJointSolverPrep.cpp new file mode 100644 index 00000000..f6e524c5 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJointSolverPrep.cpp @@ -0,0 +1,117 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "ExtRevoluteJoint.h" +#include "PsUtilities.h" +#include "ExtConstraintHelper.h" +#include "CmRenderOutput.h" +#include "PsMathUtils.h" + +namespace physx +{ +namespace Ext +{ + PxU32 RevoluteJointSolverPrep(Px1DConstraint* constraints, + PxVec3& body0WorldOffset, + PxU32 /*maxConstraints*/, + PxConstraintInvMassScale &invMassScale, + const void* constantBlock, + const PxTransform& bA2w, + const PxTransform& bB2w) + { + const RevoluteJointData& data = *reinterpret_cast<const RevoluteJointData*>(constantBlock); + invMassScale = data.invMassScale; + + const PxJointAngularLimitPair& limit = data.limit; + + bool limitEnabled = data.jointFlags & PxRevoluteJointFlag::eLIMIT_ENABLED; + bool limitIsLocked = limitEnabled && limit.lower >= limit.upper; + + PxTransform cA2w = bA2w * data.c2b[0]; + PxTransform cB2w = bB2w * data.c2b[1]; + + if(cB2w.q.dot(cA2w.q)<0.f) + cB2w.q = -cB2w.q; + + body0WorldOffset = cB2w.p-bA2w.p; + Ext::joint::ConstraintHelper ch(constraints, cB2w.p - bA2w.p, cB2w.p - bB2w.p); + + ch.prepareLockedAxes(cA2w.q, cB2w.q, cA2w.transformInv(cB2w.p), 7, PxU32(limitIsLocked ? 7 : 6)); + + if(limitIsLocked) + return ch.getCount(); + + PxVec3 axis = cA2w.rotate(PxVec3(1.f,0,0)); + + if(data.jointFlags & PxRevoluteJointFlag::eDRIVE_ENABLED) + { + Px1DConstraint *c = ch.getConstraintRow(); + + c->solveHint = PxConstraintSolveHint::eNONE; + + c->linear0 = PxVec3(0); + c->angular0 = -axis; + c->linear1 = PxVec3(0); + c->angular1 = -axis * data.driveGearRatio; + + c->velocityTarget = data.driveVelocity; + + c->minImpulse = -data.driveForceLimit; + c->maxImpulse = data.driveForceLimit; + if(data.jointFlags & PxRevoluteJointFlag::eDRIVE_FREESPIN) + { + if(data.driveVelocity > 0) + c->minImpulse = 0; + if(data.driveVelocity < 0) + c->maxImpulse = 0; + } + c->flags |= Px1DConstraintFlag::eHAS_DRIVE_LIMIT; + } + + + if(limitEnabled) + { + PxQuat cB2cAq = cA2w.q.getConjugate() * cB2w.q; + PxQuat twist(cB2cAq.x,0,0,cB2cAq.w); + + PxReal magnitude = twist.normalize(); + PxReal tqPhi = physx::intrinsics::fsel(magnitude - 1e-6f, twist.x / (1.0f + twist.w), 0.f); + + ch.quarterAnglePair(tqPhi, data.tqLow, data.tqHigh, data.tqPad, axis, limit); + } + + return ch.getCount(); + } +}//namespace + +} + +//~PX_SERIALIZATION + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtRigidBodyExt.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtRigidBodyExt.cpp new file mode 100644 index 00000000..a6dc4262 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtRigidBodyExt.cpp @@ -0,0 +1,648 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "PxRigidBodyExt.h" +#include "PxShapeExt.h" +#include "PxMassProperties.h" + +#include "ExtInertiaTensor.h" +#include "PsAllocator.h" +#include "PsFoundation.h" + +#include "PxShape.h" +#include "PxScene.h" + +#include "PxBoxGeometry.h" +#include "PxSphereGeometry.h" +#include "PxCapsuleGeometry.h" +#include "PxPlaneGeometry.h" +#include "PxConvexMeshGeometry.h" +#include "PxTriangleMeshGeometry.h" +#include "PxHeightFieldGeometry.h" +#include "PxGeometryHelpers.h" + +#include "PxConvexMesh.h" + +#include "PxBatchQuery.h" + +#include "PxRigidDynamic.h" +#include "PxRigidStatic.h" +#include "CmUtils.h" + +using namespace physx; +using namespace Cm; + +static bool computeMassAndDiagInertia(Ext::InertiaTensorComputer& inertiaComp, + PxVec3& diagTensor, PxQuat& orient, PxReal& massOut, PxVec3& coM, bool lockCOM, const PxRigidBody& body, const char* errorStr) +{ + // The inertia tensor and center of mass is relative to the actor at this point. Transform to the + // body frame directly if CoM is specified, else use computed center of mass + if (lockCOM) + { + inertiaComp.translate(-coM); // base the tensor on user's desired center of mass. + } + else + { + //get center of mass - has to be done BEFORE centering. + coM = inertiaComp.getCenterOfMass(); + + //the computed result now needs to be centered around the computed center of mass: + inertiaComp.center(); + } + // The inertia matrix is now based on the body's center of mass desc.massLocalPose.p + + massOut = inertiaComp.getMass(); + diagTensor = PxDiagonalize(inertiaComp.getInertia(), orient); + + if ((diagTensor.x > 0.0f) && (diagTensor.y > 0.0f) && (diagTensor.z > 0.0f)) + return true; + else + { + Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "%s: inertia tensor has negative components (ill-conditioned input expected). Approximation for inertia tensor will be used instead.", errorStr); + + // keep center of mass but use the AABB as a crude approximation for the inertia tensor + PxBounds3 bounds = body.getWorldBounds(); + PxTransform pose = body.getGlobalPose(); + bounds = PxBounds3::transformFast(pose.getInverse(), bounds); + Ext::InertiaTensorComputer it(false); + it.setBox(bounds.getExtents()); + it.scaleDensity(massOut / it.getMass()); + PxMat33 inertia = it.getInertia(); + diagTensor = PxVec3(inertia.column0.x, inertia.column1.y, inertia.column2.z); + orient = PxQuat(PxIdentity); + + return true; + } +} + +static bool computeMassAndInertia(bool multipleMassOrDensity, PxRigidBody& body, const PxReal* densities, const PxReal* masses, PxU32 densityOrMassCount, bool includeNonSimShapes, Ext::InertiaTensorComputer& computer) +{ + PX_ASSERT(!densities || !masses); + PX_ASSERT((densities || masses) && (densityOrMassCount > 0)); + + Ext::InertiaTensorComputer inertiaComp(true); + + Ps::InlineArray<PxShape*, 16> shapes("PxShape*"); shapes.resize(body.getNbShapes()); + + body.getShapes(shapes.begin(), shapes.size()); + + PxU32 validShapeIndex = 0; + PxReal currentMassOrDensity; + const PxReal* massOrDensityArray; + if (densities) + { + massOrDensityArray = densities; + currentMassOrDensity = densities[0]; + } + else + { + massOrDensityArray = masses; + currentMassOrDensity = masses[0]; + } + if (!PxIsFinite(currentMassOrDensity)) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "computeMassAndInertia: Provided mass or density has no valid value"); + return false; + } + + for(PxU32 i=0; i < shapes.size(); i++) + { + if ((!(shapes[i]->getFlags() & PxShapeFlag::eSIMULATION_SHAPE)) && (!includeNonSimShapes)) + continue; + + if (multipleMassOrDensity) + { + if (validShapeIndex < densityOrMassCount) + { + currentMassOrDensity = massOrDensityArray[validShapeIndex]; + + if (!PxIsFinite(currentMassOrDensity)) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "computeMassAndInertia: Provided mass or density has no valid value"); + return false; + } + } + else + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "computeMassAndInertia: Not enough mass/density values provided for all (simulation) shapes"); + return false; + } + } + + Ext::InertiaTensorComputer it(false); + + switch(shapes[i]->getGeometryType()) + { + case PxGeometryType::eSPHERE : + { + PxSphereGeometry g; + bool ok = shapes[i]->getSphereGeometry(g); + PX_ASSERT(ok); + PX_UNUSED(ok); + PxTransform temp(shapes[i]->getLocalPose()); + + it.setSphere(g.radius, &temp); + } + break; + + case PxGeometryType::eBOX : + { + PxBoxGeometry g; + bool ok = shapes[i]->getBoxGeometry(g); + PX_ASSERT(ok); + PX_UNUSED(ok); + PxTransform temp(shapes[i]->getLocalPose()); + + it.setBox(g.halfExtents, &temp); + } + break; + + case PxGeometryType::eCAPSULE : + { + PxCapsuleGeometry g; + bool ok = shapes[i]->getCapsuleGeometry(g); + PX_ASSERT(ok); + PX_UNUSED(ok); + PxTransform temp(shapes[i]->getLocalPose()); + + it.setCapsule(0, g.radius, g.halfHeight, &temp); + } + break; + + case PxGeometryType::eCONVEXMESH : + { + PxConvexMeshGeometry g; + bool ok = shapes[i]->getConvexMeshGeometry(g); + PX_ASSERT(ok); + PX_UNUSED(ok); + PxConvexMesh& convMesh = *g.convexMesh; + + PxReal convMass; + PxMat33 convInertia; + PxVec3 convCoM; + convMesh.getMassInformation(convMass, reinterpret_cast<PxMat33&>(convInertia), convCoM); + + if (!g.scale.isIdentity()) + { + //scale the mass properties + convMass *= (g.scale.scale.x * g.scale.scale.y * g.scale.scale.z); + convCoM = g.scale.rotation.rotateInv(g.scale.scale.multiply(g.scale.rotation.rotate(convCoM))); + convInertia = PxMassProperties::scaleInertia(convInertia, g.scale.rotation, g.scale.scale); + } + + it = Ext::InertiaTensorComputer(convInertia, convCoM, convMass); + it.transform(shapes[i]->getLocalPose()); + } + break; + case PxGeometryType::eHEIGHTFIELD: + case PxGeometryType::ePLANE: + case PxGeometryType::eTRIANGLEMESH: + case PxGeometryType::eINVALID: + case PxGeometryType::eGEOMETRY_COUNT: + { + + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "computeMassAndInertia: Dynamic actor with illegal collision shapes"); + return false; + } + } + + if (densities) + it.scaleDensity(currentMassOrDensity); + else if (multipleMassOrDensity) // mass per shape -> need to scale density per shape + it.scaleDensity(currentMassOrDensity / it.getMass()); + + inertiaComp.add(it); + + validShapeIndex++; + } + + if (validShapeIndex && masses && (!multipleMassOrDensity)) // at least one simulation shape and single mass for all shapes -> scale density at the end + { + inertiaComp.scaleDensity(currentMassOrDensity / inertiaComp.getMass()); + } + + computer = inertiaComp; + return true; +} + +static bool updateMassAndInertia(bool multipleMassOrDensity, PxRigidBody& body, const PxReal* densities, PxU32 densityCount, const PxVec3* massLocalPose, bool includeNonSimShapes) +{ + bool success; + + // default values in case there were no shapes + PxReal massOut = 1.0f; + PxVec3 diagTensor(1.f,1.f,1.f); + PxQuat orient = PxQuat(PxIdentity); + bool lockCom = massLocalPose != NULL; + PxVec3 com = lockCom ? *massLocalPose : PxVec3(0); + const char* errorStr = "PxRigidBodyExt::updateMassAndInertia"; + + if (densities && densityCount) + { + Ext::InertiaTensorComputer inertiaComp(true); + if(computeMassAndInertia(multipleMassOrDensity, body, densities, NULL, densityCount, includeNonSimShapes, inertiaComp)) + { + if(inertiaComp.getMass()!=0 && computeMassAndDiagInertia(inertiaComp, diagTensor, orient, massOut, com, lockCom, body, errorStr)) + success = true; + else + success = false; // body with no shapes provided or computeMassAndDiagInertia() failed + } + else + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "%s: Mass and inertia computation failed, setting mass to 1 and inertia to (1,1,1)", errorStr); + + success = false; + } + } + else + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "%s: No density specified, setting mass to 1 and inertia to (1,1,1)", errorStr); + + success = false; + } + + PX_ASSERT(orient.isFinite()); + PX_ASSERT(diagTensor.isFinite()); + PX_ASSERT(PxIsFinite(massOut)); + + body.setMass(massOut); + body.setMassSpaceInertiaTensor(diagTensor); + body.setCMassLocalPose(PxTransform(com, orient)); + + return success; +} + +bool PxRigidBodyExt::updateMassAndInertia(PxRigidBody& body, const PxReal* densities, PxU32 densityCount, const PxVec3* massLocalPose, bool includeNonSimShapes) +{ + return ::updateMassAndInertia(true, body, densities, densityCount, massLocalPose, includeNonSimShapes); +} + +bool PxRigidBodyExt::updateMassAndInertia(PxRigidBody& body, PxReal density, const PxVec3* massLocalPose, bool includeNonSimShapes) +{ + return ::updateMassAndInertia(false, body, &density, 1, massLocalPose, includeNonSimShapes); +} + +static bool setMassAndUpdateInertia(bool multipleMassOrDensity, PxRigidBody& body, const PxReal* masses, PxU32 massCount, const PxVec3* massLocalPose, bool includeNonSimShapes) +{ + bool success; + + // default values in case there were no shapes + PxReal massOut = 1.0f; + PxVec3 diagTensor(1.0f,1.0f,1.0f); + PxQuat orient = PxQuat(PxIdentity); + bool lockCom = massLocalPose != NULL; + PxVec3 com = lockCom ? *massLocalPose : PxVec3(0); + const char* errorStr = "PxRigidBodyExt::setMassAndUpdateInertia"; + + if(masses && massCount) + { + Ext::InertiaTensorComputer inertiaComp(true); + if(computeMassAndInertia(multipleMassOrDensity, body, NULL, masses, massCount, includeNonSimShapes, inertiaComp)) + { + success = true; + + if (inertiaComp.getMass()!=0 && !computeMassAndDiagInertia(inertiaComp, diagTensor, orient, massOut, com, lockCom, body, errorStr)) + success = false; // computeMassAndDiagInertia() failed (mass zero?) + + if (massCount == 1) + massOut = masses[0]; // to cover special case where body has no simulation shape + } + else + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "%s: Mass and inertia computation failed, setting mass to 1 and inertia to (1,1,1)", errorStr); + + success = false; + } + } + else + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "%s: No mass specified, setting mass to 1 and inertia to (1,1,1)", errorStr); + success = false; + } + + PX_ASSERT(orient.isFinite()); + PX_ASSERT(diagTensor.isFinite()); + + body.setMass(massOut); + body.setMassSpaceInertiaTensor(diagTensor); + body.setCMassLocalPose(PxTransform(com, orient)); + + return success; +} + +bool PxRigidBodyExt::setMassAndUpdateInertia(PxRigidBody& body, const PxReal* masses, PxU32 massCount, const PxVec3* massLocalPose, bool includeNonSimShapes) +{ + return ::setMassAndUpdateInertia(true, body, masses, massCount, massLocalPose, includeNonSimShapes); +} + +bool PxRigidBodyExt::setMassAndUpdateInertia(PxRigidBody& body, PxReal mass, const PxVec3* massLocalPose, bool includeNonSimShapes) +{ + return ::setMassAndUpdateInertia(false, body, &mass, 1, massLocalPose, includeNonSimShapes); +} + +PxMassProperties PxRigidBodyExt::computeMassPropertiesFromShapes(const PxShape* const* shapes, PxU32 shapeCount) +{ + Ps::InlineArray<PxMassProperties, 16> massProps; + massProps.reserve(shapeCount); + Ps::InlineArray<PxTransform, 16> localTransforms; + localTransforms.reserve(shapeCount); + + for(PxU32 shapeIdx=0; shapeIdx < shapeCount; shapeIdx++) + { + const PxShape* shape = shapes[shapeIdx]; + PxMassProperties mp(shape->getGeometry().any()); + massProps.pushBack(mp); + localTransforms.pushBack(shape->getLocalPose()); + } + + return PxMassProperties::sum(massProps.begin(), localTransforms.begin(), shapeCount); +} + +PX_INLINE void addForceAtPosInternal(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode, bool wakeup) +{ + if(mode == PxForceMode::eACCELERATION || mode == PxForceMode::eVELOCITY_CHANGE) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "PxRigidBodyExt::addForce methods do not support eACCELERATION or eVELOCITY_CHANGE modes"); + return; + } + + const PxTransform globalPose = body.getGlobalPose(); + const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p); + + const PxVec3 torque = (pos - centerOfMass).cross(force); + body.addForce(force, mode, wakeup); + body.addTorque(torque, mode, wakeup); +} + +void PxRigidBodyExt::addForceAtPos(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode, bool wakeup) +{ + addForceAtPosInternal(body, force, pos, mode, wakeup); +} + +void PxRigidBodyExt::addForceAtLocalPos(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode, bool wakeup) +{ + //transform pos to world space + const PxVec3 globalForcePos = body.getGlobalPose().transform(pos); + + addForceAtPosInternal(body, force, globalForcePos, mode, wakeup); +} + +void PxRigidBodyExt::addLocalForceAtPos(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode, bool wakeup) +{ + const PxVec3 globalForce = body.getGlobalPose().rotate(force); + + addForceAtPosInternal(body, globalForce, pos, mode, wakeup); +} + +void PxRigidBodyExt::addLocalForceAtLocalPos(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode, bool wakeup) +{ + const PxTransform globalPose = body.getGlobalPose(); + const PxVec3 globalForcePos = globalPose.transform(pos); + const PxVec3 globalForce = globalPose.rotate(force); + + addForceAtPosInternal(body, globalForce, globalForcePos, mode, wakeup); +} + +PX_INLINE PxVec3 getVelocityAtPosInternal(const PxRigidBody& body, const PxVec3& point) +{ + PxVec3 velocity = body.getLinearVelocity(); + velocity += body.getAngularVelocity().cross(point); + + return velocity; +} + +PxVec3 PxRigidBodyExt::getVelocityAtPos(const PxRigidBody& body, const PxVec3& point) +{ + const PxTransform globalPose = body.getGlobalPose(); + const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p); + const PxVec3 rpoint = point - centerOfMass; + + return getVelocityAtPosInternal(body, rpoint); +} + +PxVec3 PxRigidBodyExt::getLocalVelocityAtLocalPos(const PxRigidBody& body, const PxVec3& point) +{ + const PxTransform globalPose = body.getGlobalPose(); + const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p); + const PxVec3 rpoint = globalPose.transform(point) - centerOfMass; + + return getVelocityAtPosInternal(body, rpoint); +} + +PxVec3 PxRigidBodyExt::getVelocityAtOffset(const PxRigidBody& body, const PxVec3& point) +{ + const PxTransform globalPose = body.getGlobalPose(); + const PxVec3 centerOfMass = globalPose.rotate(body.getCMassLocalPose().p); + const PxVec3 rpoint = point - centerOfMass; + + return getVelocityAtPosInternal(body, rpoint); +} + +void PxRigidBodyExt::computeVelocityDeltaFromImpulse(const PxRigidBody& body, const PxTransform& globalPose, const PxVec3& point, const PxVec3& impulse, const PxReal invMassScale, + const PxReal invInertiaScale, PxVec3& linearVelocityChange, PxVec3& angularVelocityChange) +{ + const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p); + const PxReal invMass = body.getInvMass() * invMassScale; + const PxVec3 invInertiaMS = body.getMassSpaceInvInertiaTensor() * invInertiaScale; + + PxMat33 invInertia; + transformInertiaTensor(invInertiaMS, PxMat33(globalPose.q), invInertia); + linearVelocityChange = impulse * invMass; + const PxVec3 rXI = (point - centerOfMass).cross(impulse); + angularVelocityChange = invInertia * rXI; +} + +void PxRigidBodyExt::computeLinearAngularImpulse(const PxRigidBody& body, const PxTransform& globalPose, const PxVec3& point, const PxVec3& impulse, const PxReal invMassScale, + const PxReal invInertiaScale, PxVec3& linearImpulse, PxVec3& angularImpulse) +{ + const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p); + linearImpulse = impulse * invMassScale; + angularImpulse = (point - centerOfMass).cross(impulse) * invInertiaScale; +} + + + +//================================================================================= +// Single closest hit compound sweep +bool PxRigidBodyExt::linearSweepSingle( + PxRigidBody& body, PxScene& scene, const PxVec3& unitDir, const PxReal distance, + PxHitFlags outputFlags, PxSweepHit& closestHit, PxU32& shapeIndex, + const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall, + const PxQueryCache* cache, const PxReal inflation) +{ + shapeIndex = 0xFFFFffff; + PxReal closestDist = distance; + PxU32 nbShapes = body.getNbShapes(); + for(PxU32 i=0; i < nbShapes; i++) + { + PxShape* shape = NULL; + body.getShapes(&shape, 1, i); + PX_ASSERT(shape != NULL); + PxTransform pose = PxShapeExt::getGlobalPose(*shape, body); + PxQueryFilterData fd; + fd.flags = filterData.flags; + PxU32 or4 = (filterData.data.word0 | filterData.data.word1 | filterData.data.word2 | filterData.data.word3); + fd.data = or4 ? filterData.data : shape->getQueryFilterData(); + PxGeometryHolder anyGeom = shape->getGeometry(); + + PxSweepBuffer subHit; // touching hits are not allowed to be returned from the filters + scene.sweep(anyGeom.any(), pose, unitDir, distance, subHit, outputFlags, fd, filterCall, cache, inflation); + if (subHit.hasBlock && subHit.block.distance < closestDist) + { + closestDist = subHit.block.distance; + closestHit = subHit.block; + shapeIndex = i; + } + } + + return (shapeIndex != 0xFFFFffff); +} + +//================================================================================= +// Multiple hits compound sweep +// AP: we might be able to improve the return results API but no time for it in 3.3 +PxU32 PxRigidBodyExt::linearSweepMultiple( + PxRigidBody& body, PxScene& scene, const PxVec3& unitDir, const PxReal distance, PxHitFlags outputFlags, + PxSweepHit* hitBuffer, PxU32* hitShapeIndices, PxU32 hitBufferSize, PxSweepHit& block, PxI32& blockingHitShapeIndex, + bool& overflow, const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall, + const PxQueryCache* cache, const PxReal inflation) +{ + overflow = false; + blockingHitShapeIndex = -1; + + for (PxU32 i = 0; i < hitBufferSize; i++) + hitShapeIndices[i] = 0xFFFFffff; + + PxI32 sumNbResults = 0; + + PxU32 nbShapes = body.getNbShapes(); + PxF32 shrunkMaxDistance = distance; + for(PxU32 i=0; i < nbShapes; i++) + { + PxShape* shape = NULL; + body.getShapes(&shape, 1, i); + PX_ASSERT(shape != NULL); + PxTransform pose = PxShapeExt::getGlobalPose(*shape, body); + PxQueryFilterData fd; + fd.flags = filterData.flags; + PxU32 or4 = (filterData.data.word0 | filterData.data.word1 | filterData.data.word2 | filterData.data.word3); + fd.data = or4 ? filterData.data : shape->getQueryFilterData(); + PxGeometryHolder anyGeom = shape->getGeometry(); + + PxU32 bufSizeLeft = hitBufferSize-sumNbResults; + PxSweepHit extraHit; + PxSweepBuffer buffer(bufSizeLeft == 0 ? &extraHit : hitBuffer+sumNbResults, bufSizeLeft == 0 ? 1 : hitBufferSize-sumNbResults); + scene.sweep(anyGeom.any(), pose, unitDir, shrunkMaxDistance, buffer, outputFlags, fd, filterCall, cache, inflation); + + // Check and abort on overflow. Assume overflow if result count is bufSize. + PxU32 nbNewResults = buffer.getNbTouches(); + overflow |= (nbNewResults >= bufSizeLeft); + if (bufSizeLeft == 0) // this is for when we used the extraHit buffer + nbNewResults = 0; + + // set hitShapeIndices for each new non-blocking hit + for (PxU32 j = 0; j < nbNewResults; j++) + if (sumNbResults + PxU32(j) < hitBufferSize) + hitShapeIndices[sumNbResults+j] = i; + + if (buffer.hasBlock) // there's a blocking hit in the most recent sweepMultiple results + { + // overwrite the return result blocking hit with the new blocking hit if under + if (blockingHitShapeIndex == -1 || buffer.block.distance < block.distance) + { + blockingHitShapeIndex = PxI32(i); + block = buffer.block; + } + + // Remove all the old touching hits below the new maxDist + // sumNbResults is not updated yet at this point + // and represents the count accumulated so far excluding the very last query + PxI32 nbNewResultsSigned = PxI32(nbNewResults); // need a signed version, see nbNewResultsSigned-- below + for (PxI32 j = sumNbResults-1; j >= 0; j--) // iterate over "old" hits (up to shapeIndex-1) + if (buffer.block.distance < hitBuffer[j].distance) + { + // overwrite with last "new" hit + PxI32 sourceIndex = PxI32(sumNbResults)+nbNewResultsSigned-1; PX_ASSERT(sourceIndex >= j); + hitBuffer[j] = hitBuffer[sourceIndex]; + hitShapeIndices[j] = hitShapeIndices[sourceIndex]; + nbNewResultsSigned--; // can get negative, that means we are shifting the last results array + } + + sumNbResults += nbNewResultsSigned; + } else // if there was no new blocking hit we don't need to do anything special, simply append all results to touch array + sumNbResults += nbNewResults; + + PX_ASSERT(sumNbResults >= 0 && sumNbResults <= PxI32(hitBufferSize)); + } + + return PxU32(sumNbResults); +} + +void PxRigidBodyExt::computeVelocityDeltaFromImpulse(const PxRigidBody& body, const PxVec3& impulsiveForce, const PxVec3& impulsiveTorque, PxVec3& deltaLinearVelocity, PxVec3& deltaAngularVelocity) +{ + { + const PxF32 recipMass = body.getInvMass(); + deltaLinearVelocity = impulsiveForce*recipMass; + } + + { + const PxTransform globalPose = body.getGlobalPose(); + const PxTransform cmLocalPose = body.getCMassLocalPose(); + const PxTransform body2World = globalPose*cmLocalPose; + PxMat33 M(body2World.q); + + const PxVec3 recipInertiaBodySpace = body.getMassSpaceInvInertiaTensor(); + + PxMat33 recipInertiaWorldSpace; + const float axx = recipInertiaBodySpace.x*M(0,0), axy = recipInertiaBodySpace.x*M(1,0), axz = recipInertiaBodySpace.x*M(2,0); + const float byx = recipInertiaBodySpace.y*M(0,1), byy = recipInertiaBodySpace.y*M(1,1), byz = recipInertiaBodySpace.y*M(2,1); + const float czx = recipInertiaBodySpace.z*M(0,2), czy = recipInertiaBodySpace.z*M(1,2), czz = recipInertiaBodySpace.z*M(2,2); + recipInertiaWorldSpace(0,0) = axx*M(0,0) + byx*M(0,1) + czx*M(0,2); + recipInertiaWorldSpace(1,1) = axy*M(1,0) + byy*M(1,1) + czy*M(1,2); + recipInertiaWorldSpace(2,2) = axz*M(2,0) + byz*M(2,1) + czz*M(2,2); + recipInertiaWorldSpace(0,1) = recipInertiaWorldSpace(1,0) = axx*M(1,0) + byx*M(1,1) + czx*M(1,2); + recipInertiaWorldSpace(0,2) = recipInertiaWorldSpace(2,0) = axx*M(2,0) + byx*M(2,1) + czx*M(2,2); + recipInertiaWorldSpace(1,2) = recipInertiaWorldSpace(2,1) = axy*M(2,0) + byy*M(2,1) + czy*M(2,2); + + deltaAngularVelocity = recipInertiaWorldSpace*(impulsiveTorque); + } +} + + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtSceneQueryExt.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtSceneQueryExt.cpp new file mode 100644 index 00000000..a02c2ed0 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtSceneQueryExt.cpp @@ -0,0 +1,197 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PxSceneQueryExt.h" + +using namespace physx; + +bool PxSceneQueryExt::raycastAny( const PxScene& scene, + const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, + PxSceneQueryHit& hit, const PxSceneQueryFilterData& filterData, + PxSceneQueryFilterCallback* filterCall, const PxSceneQueryCache* cache, + PxClientID queryClient) +{ + PxSceneQueryFilterData fdAny = filterData; + fdAny.flags |= PxQueryFlag::eANY_HIT; + fdAny.clientId = queryClient; + PxRaycastBuffer buf; + scene.raycast(origin, unitDir, distance, buf, PxHitFlags(), fdAny, filterCall, cache); + hit = buf.block; + return buf.hasBlock; +} + +bool PxSceneQueryExt::raycastSingle(const PxScene& scene, + const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, + PxSceneQueryFlags outputFlags, PxRaycastHit& hit, + const PxSceneQueryFilterData& filterData, + PxSceneQueryFilterCallback* filterCall, const PxSceneQueryCache* cache, + PxClientID queryClient) +{ + PxRaycastBuffer buf; + PxQueryFilterData fd1 = filterData; fd1.clientId = queryClient; + scene.raycast(origin, unitDir, distance, buf, outputFlags, fd1, filterCall, cache); + hit = buf.block; + return buf.hasBlock; +} + +PxI32 PxSceneQueryExt::raycastMultiple( const PxScene& scene, + const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, + PxSceneQueryFlags outputFlags, + PxRaycastHit* hitBuffer, PxU32 hitBufferSize, bool& blockingHit, + const PxSceneQueryFilterData& filterData, + PxSceneQueryFilterCallback* filterCall, const PxSceneQueryCache* cache, + PxClientID queryClient) +{ + PxRaycastBuffer buf(hitBuffer, hitBufferSize); + PxQueryFilterData fd1 = filterData; fd1.clientId = queryClient; + scene.raycast(origin, unitDir, distance, buf, outputFlags, fd1, filterCall, cache); + blockingHit = buf.hasBlock; + if(blockingHit) + { + if(buf.nbTouches < hitBufferSize) + { + hitBuffer[buf.nbTouches] = buf.block; + return PxI32(buf.nbTouches+1); + } + else // overflow, drop the last touch + { + hitBuffer[hitBufferSize-1] = buf.block; + return -1; + } + } else + // no block + return PxI32(buf.nbTouches); +} + +bool PxSceneQueryExt::sweepAny( const PxScene& scene, + const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance, + PxSceneQueryFlags queryFlags, + PxSceneQueryHit& hit, + const PxSceneQueryFilterData& filterData, + PxSceneQueryFilterCallback* filterCall, + const PxSceneQueryCache* cache, + PxClientID queryClient, + PxReal inflation) +{ + PxSceneQueryFilterData fdAny = filterData; + fdAny.flags |= PxQueryFlag::eANY_HIT; + fdAny.clientId = queryClient; + PxSweepBuffer buf; + scene.sweep(geometry, pose, unitDir, distance, buf, queryFlags, fdAny, filterCall, cache, inflation); + hit = buf.block; + return buf.hasBlock; +} + +bool PxSceneQueryExt::sweepSingle( const PxScene& scene, + const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance, + PxSceneQueryFlags outputFlags, + PxSweepHit& hit, + const PxSceneQueryFilterData& filterData, + PxSceneQueryFilterCallback* filterCall, + const PxSceneQueryCache* cache, + PxClientID queryClient, PxReal inflation) +{ + PxSweepBuffer buf; + PxQueryFilterData fd1 = filterData; fd1.clientId = queryClient; + scene.sweep(geometry, pose, unitDir, distance, buf, outputFlags, fd1, filterCall, cache, inflation); + hit = buf.block; + return buf.hasBlock; +} + +PxI32 PxSceneQueryExt::sweepMultiple( const PxScene& scene, + const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance, + PxSceneQueryFlags outputFlags, PxSweepHit* hitBuffer, PxU32 hitBufferSize, bool& blockingHit, + const PxSceneQueryFilterData& filterData, + PxSceneQueryFilterCallback* filterCall, const PxSceneQueryCache* cache, + PxClientID queryClient, PxReal inflation) +{ + PxQueryFilterData fd1 = filterData; fd1.clientId = queryClient; + PxSweepBuffer buf(hitBuffer, hitBufferSize); + scene.sweep(geometry, pose, unitDir, distance, buf, outputFlags, fd1, filterCall, cache, inflation); + blockingHit = buf.hasBlock; + if(blockingHit) + { + if(buf.nbTouches < hitBufferSize) + { + hitBuffer[buf.nbTouches] = buf.block; + return PxI32(buf.nbTouches+1); + } + else // overflow, drop the last touch + { + hitBuffer[hitBufferSize-1] = buf.block; + return -1; + } + } else + // no block + return PxI32(buf.nbTouches); +} + +PxI32 PxSceneQueryExt::overlapMultiple( const PxScene& scene, + const PxGeometry& geometry, const PxTransform& pose, + PxOverlapHit* hitBuffer, PxU32 hitBufferSize, + const PxSceneQueryFilterData& filterData, + PxSceneQueryFilterCallback* filterCall, + PxClientID queryClient) +{ + PxQueryFilterData fd1 = filterData; fd1.clientId = queryClient; + fd1.flags |= PxQueryFlag::eNO_BLOCK; + PxOverlapBuffer buf(hitBuffer, hitBufferSize); + scene.overlap(geometry, pose, buf, fd1, filterCall); + if(buf.hasBlock) + { + if(buf.nbTouches < hitBufferSize) + { + hitBuffer[buf.nbTouches] = buf.block; + return PxI32(buf.nbTouches+1); + } + else // overflow, drop the last touch + { + hitBuffer[hitBufferSize-1] = buf.block; + return -1; + } + } else + // no block + return PxI32(buf.nbTouches); +} + +bool PxSceneQueryExt::overlapAny( const PxScene& scene, + const PxGeometry& geometry, const PxTransform& pose, + PxOverlapHit& hit, + const PxSceneQueryFilterData& filterData, + PxSceneQueryFilterCallback* filterCall, + PxClientID queryClient) +{ + PxSceneQueryFilterData fdAny = filterData; + fdAny.flags |= (PxQueryFlag::eANY_HIT | PxQueryFlag::eNO_BLOCK); + fdAny.clientId = queryClient; + PxOverlapBuffer buf; + scene.overlap(geometry, pose, buf, fdAny, filterCall); + hit = buf.block; + return buf.hasBlock; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtSerialization.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtSerialization.h new file mode 100644 index 00000000..390b0ad3 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtSerialization.h @@ -0,0 +1,44 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef EXT_SERIALIZATION_H +#define EXT_SERIALIZATION_H + +namespace physx +{ +namespace Ext +{ + void RegisterExtensionsSerializers(PxSerializationRegistry& sr); + void UnregisterExtensionsSerializers(PxSerializationRegistry& sr); + void GetExtensionsBinaryMetaData(PxOutputStream& stream); +} +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtSharedQueueEntryPool.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtSharedQueueEntryPool.h new file mode 100644 index 00000000..9b01718d --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtSharedQueueEntryPool.h @@ -0,0 +1,156 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_NP_SHARED_QUEUE_ENTRY_POOL_H +#define PX_PHYSICS_EXTENSIONS_NP_SHARED_QUEUE_ENTRY_POOL_H + +#include "CmPhysXCommon.h" +#include "PsAllocator.h" +#include "PsArray.h" +#include "PsSList.h" + +namespace physx +{ +namespace Ext +{ + class SharedQueueEntry : public Ps::SListEntry + { + public: + SharedQueueEntry(void* objectRef) : mObjectRef(objectRef), mPooledEntry(false) {} + SharedQueueEntry() : mObjectRef(NULL), mPooledEntry(true) {} + + public: + void* mObjectRef; + bool mPooledEntry; // True if the entry was preallocated in a pool + }; + +#if PX_VC +#pragma warning(push) +#pragma warning(disable:4324) // Padding was added at the end of a structure because of a __declspec(align) value. +#endif // Because of the SList member I assume*/ + + template<class Alloc = typename Ps::AllocatorTraits<SharedQueueEntry>::Type > + class SharedQueueEntryPool : private Alloc + { + public: + SharedQueueEntryPool(PxU32 poolSize, const Alloc& alloc = Alloc(PX_DEBUG_EXP("SharedQueueEntryPool"))); + ~SharedQueueEntryPool(); + + SharedQueueEntry* getEntry(void* objectRef); + void putEntry(SharedQueueEntry& entry); + + private: + SharedQueueEntry* mTaskEntryPool; + Ps::SList mTaskEntryPtrPool; + }; + +#if PX_VC +#pragma warning(pop) +#endif + +} // namespace Ext + + +template <class Alloc> +Ext::SharedQueueEntryPool<Alloc>::SharedQueueEntryPool(PxU32 poolSize, const Alloc& alloc) + : Alloc(alloc) +{ + Ps::AlignedAllocator<PX_SLIST_ALIGNMENT, Alloc> alignedAlloc("SharedQueueEntryPool"); + + mTaskEntryPool = poolSize ? reinterpret_cast<SharedQueueEntry*>(alignedAlloc.allocate(sizeof(SharedQueueEntry) * poolSize, __FILE__, __LINE__)) : NULL; + + if (mTaskEntryPool) + { + for(PxU32 i=0; i < poolSize; i++) + { + PX_ASSERT((size_t(&mTaskEntryPool[i]) & (PX_SLIST_ALIGNMENT-1)) == 0); // The SList entry must be aligned according to PX_SLIST_ALIGNMENT + + PX_PLACEMENT_NEW(&mTaskEntryPool[i], SharedQueueEntry)(); + PX_ASSERT(mTaskEntryPool[i].mPooledEntry == true); + mTaskEntryPtrPool.push(mTaskEntryPool[i]); + } + } +} + + +template <class Alloc> +Ext::SharedQueueEntryPool<Alloc>::~SharedQueueEntryPool() +{ + if (mTaskEntryPool) + { + Ps::AlignedAllocator<PX_SLIST_ALIGNMENT, Alloc> alignedAlloc("SharedQueueEntryPool"); + alignedAlloc.deallocate(mTaskEntryPool); + } +} + + +template <class Alloc> +Ext::SharedQueueEntry* Ext::SharedQueueEntryPool<Alloc>::getEntry(void* objectRef) +{ + SharedQueueEntry* e = static_cast<SharedQueueEntry*>(mTaskEntryPtrPool.pop()); + if (e) + { + PX_ASSERT(e->mPooledEntry == true); + e->mObjectRef = objectRef; + return e; + } + else + { + Ps::AlignedAllocator<PX_SLIST_ALIGNMENT, Alloc> alignedAlloc; + e = reinterpret_cast<SharedQueueEntry*>(alignedAlloc.allocate(sizeof(SharedQueueEntry), __FILE__, __LINE__)); + if (e) + { + PX_PLACEMENT_NEW(e, SharedQueueEntry)(objectRef); + PX_ASSERT(e->mPooledEntry == false); + } + + return e; + } +} + + +template <class Alloc> +void Ext::SharedQueueEntryPool<Alloc>::putEntry(Ext::SharedQueueEntry& entry) +{ + if (entry.mPooledEntry) + { + entry.mObjectRef = NULL; + mTaskEntryPtrPool.push(entry); + } + else + { + Ps::AlignedAllocator<PX_SLIST_ALIGNMENT, Alloc> alignedAlloc; + alignedAlloc.deallocate(&entry); + } +} + +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtSimpleFactory.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtSimpleFactory.cpp new file mode 100644 index 00000000..41a6176f --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtSimpleFactory.cpp @@ -0,0 +1,385 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "foundation/PxMathUtils.h" +#include "foundation/PxQuat.h" +#include "CmPhysXCommon.h" +#include "PsFoundation.h" +#include "PsUtilities.h" +#include "PsInlineArray.h" +#include "PxSimpleFactory.h" +#include "PxRigidStatic.h" +#include "PxSphereGeometry.h" +#include "PxBoxGeometry.h" +#include "PxCapsuleGeometry.h" +#include "PxConvexMeshGeometry.h" +#include "PxPlaneGeometry.h" +#include "PxRigidBodyExt.h" +#include "PxRigidStatic.h" +#include "PxScene.h" +#include "PxShape.h" +#include "PxRigidDynamic.h" +#include "CmPhysXCommon.h" +#include "PxPhysics.h" + +using namespace physx; +using namespace shdfnd; + +namespace +{ + +bool isDynamicGeometry(PxGeometryType::Enum type) +{ + return type == PxGeometryType::eBOX + || type == PxGeometryType::eSPHERE + || type == PxGeometryType::eCAPSULE + || type == PxGeometryType::eCONVEXMESH; +} +} + +namespace physx +{ +PxRigidDynamic* PxCreateDynamic(PxPhysics& sdk, + const PxTransform& transform, + PxShape& shape, + PxReal density) +{ + PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateDynamic: transform is not valid."); + + PxRigidDynamic* actor = sdk.createRigidDynamic(transform); + if(actor) + { + actor->attachShape(shape); + PxRigidBodyExt::updateMassAndInertia(*actor, density); + } + return actor; +} + +PxRigidDynamic* PxCreateDynamic(PxPhysics& sdk, + const PxTransform& transform, + const PxGeometry& geometry, + PxMaterial& material, + PxReal density, + const PxTransform& shapeOffset) +{ + PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateDynamic: transform is not valid."); + PX_CHECK_AND_RETURN_NULL(shapeOffset.isValid(), "PxCreateDynamic: shapeOffset is not valid."); + + if(!isDynamicGeometry(geometry.getType()) || density <= 0.0f) + return NULL; + + PxShape* shape = sdk.createShape(geometry, material, true); + if(!shape) + return NULL; + + shape->setLocalPose(shapeOffset); + + PxRigidDynamic* body = shape ? PxCreateDynamic(sdk, transform, *shape, density) : NULL; + shape->release(); + return body; +} + + + +PxRigidDynamic* PxCreateKinematic(PxPhysics& sdk, + const PxTransform& transform, + PxShape& shape, + PxReal density) +{ + PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateKinematic: transform is not valid."); + + bool isDynGeom = isDynamicGeometry(shape.getGeometryType()); + if(isDynGeom && density <= 0.0f) + return NULL; + + PxRigidDynamic* actor = sdk.createRigidDynamic(transform); + if(actor) + { + actor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true); + if(!isDynGeom) + shape.setFlag(PxShapeFlag::eSIMULATION_SHAPE, false); + + actor->attachShape(shape); + + if(isDynGeom) + PxRigidBodyExt::updateMassAndInertia(*actor, density); + else + { + actor->setMass(1.f); + actor->setMassSpaceInertiaTensor(PxVec3(1.f,1.f,1.f)); + } + } + + return actor; +} + + +PxRigidDynamic* PxCreateKinematic(PxPhysics& sdk, + const PxTransform& transform, + const PxGeometry& geometry, + PxMaterial& material, + PxReal density, + const PxTransform& shapeOffset) +{ + PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateKinematic: transform is not valid."); + PX_CHECK_AND_RETURN_NULL(shapeOffset.isValid(), "PxCreateKinematic: shapeOffset is not valid."); + + bool isDynGeom = isDynamicGeometry(geometry.getType()); + if(isDynGeom && density <= 0.0f) + return NULL; + + PxShape* shape = sdk.createShape(geometry, material, true); + if(!shape) + return NULL; + + shape->setLocalPose(shapeOffset); + + PxRigidDynamic* body = PxCreateKinematic(sdk, transform, *shape, density); + shape->release(); + return body; +} + + + + +PxRigidStatic* PxCreateStatic(PxPhysics& sdk, + const PxTransform& transform, + PxShape& shape) +{ + PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateStatic: transform is not valid."); + + PxRigidStatic* s = sdk.createRigidStatic(transform); + if(s) + s->attachShape(shape); + return s; +} + +PxRigidStatic* PxCreateStatic(PxPhysics& sdk, + const PxTransform& transform, + const PxGeometry& geometry, + PxMaterial& material, + const PxTransform& shapeOffset) +{ + + PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateStatic: transform is not valid."); + PX_CHECK_AND_RETURN_NULL(shapeOffset.isValid(), "PxCreateStatic: shapeOffset is not valid."); + + PxShape* shape = sdk.createShape(geometry, material, true); + if(!shape) + return NULL; + + shape->setLocalPose(shapeOffset); + + PxRigidStatic* s = PxCreateStatic(sdk, transform, *shape); + shape->release(); + return s; +} + + + + +PxRigidStatic* PxCreatePlane(PxPhysics& sdk, + const PxPlane& plane, + PxMaterial& material) +{ + PX_CHECK_AND_RETURN_NULL(plane.n.isFinite(), "PxCreatePlane: plane normal is not valid."); + + if (!plane.n.isNormalized()) + return NULL; + + return PxCreateStatic(sdk, PxTransformFromPlaneEquation(plane), PxPlaneGeometry(), material); +} + + +PxShape* PxCloneShape(PxPhysics &physics, const PxShape& from, bool isExclusive) +{ + Ps::InlineArray<PxMaterial*, 64> materials; + PxU16 materialCount = from.getNbMaterials(); + materials.resize(materialCount); + from.getMaterials(materials.begin(), materialCount); + + PxShape* to = physics.createShape(from.getGeometry().any(), materials.begin(), materialCount, isExclusive, from.getFlags()); + + to->setLocalPose(from.getLocalPose()); + to->setContactOffset(from.getContactOffset()); + to->setRestOffset(from.getRestOffset()); + to->setSimulationFilterData(from.getSimulationFilterData()); + to->setQueryFilterData(from.getQueryFilterData()); + return to; +} + + +namespace +{ + void copyStaticProperties(PxPhysics& physics, PxRigidActor& to, const PxRigidActor& from) + { + Ps::InlineArray<PxShape*, 64> shapes; + shapes.resize(from.getNbShapes()); + + PxU32 shapeCount = from.getNbShapes(); + from.getShapes(shapes.begin(), shapeCount); + + for(PxU32 i = 0; i < shapeCount; i++) + { + PxShape* s = shapes[i]; + if(!s->isExclusive()) + to.attachShape(*s); + else + { + PxShape* newShape = physx::PxCloneShape(physics, *s, true); + to.attachShape(*newShape); + newShape->release(); + } + } + + to.setActorFlags(from.getActorFlags()); + to.setOwnerClient(from.getOwnerClient()); + to.setClientBehaviorFlags(from.getClientBehaviorFlags()); + to.setDominanceGroup(from.getDominanceGroup()); + } +} + +PxRigidStatic* PxCloneStatic(PxPhysics& physicsSDK, + const PxTransform& transform, + const PxRigidActor& from) +{ + PxRigidStatic* to = physicsSDK.createRigidStatic(transform); + if(!to) + return NULL; + + copyStaticProperties(physicsSDK, *to, from); + + return to; +} + +PxRigidDynamic* PxCloneDynamic(PxPhysics& physicsSDK, + const PxTransform& transform, + const PxRigidDynamic& from) +{ + PxRigidDynamic* to = physicsSDK.createRigidDynamic(transform); + if(!to) + return NULL; + + copyStaticProperties(physicsSDK, *to, from); + + + to->setRigidBodyFlags(from.getRigidBodyFlags()); + + to->setMass(from.getMass()); + to->setMassSpaceInertiaTensor(from.getMassSpaceInertiaTensor()); + to->setCMassLocalPose(from.getCMassLocalPose()); + + to->setLinearVelocity(from.getLinearVelocity()); + to->setAngularVelocity(from.getAngularVelocity()); + + to->setLinearDamping(from.getAngularDamping()); + to->setAngularDamping(from.getAngularDamping()); + + PxU32 posIters, velIters; + from.getSolverIterationCounts(posIters, velIters); + to->setSolverIterationCounts(posIters, velIters); + + to->setMaxAngularVelocity(from.getMaxAngularVelocity()); + to->setMaxDepenetrationVelocity(from.getMaxDepenetrationVelocity()); + to->setSleepThreshold(from.getSleepThreshold()); + to->setStabilizationThreshold(from.getStabilizationThreshold()); + to->setMinCCDAdvanceCoefficient(from.getMinCCDAdvanceCoefficient()); + to->setContactReportThreshold(from.getContactReportThreshold()); + to->setMaxContactImpulse(from.getMaxContactImpulse()); + + return to; +} + +namespace +{ + PxTransform scalePosition(const PxTransform& t, PxReal scale) + { + return PxTransform(t.p*scale, t.q); + } +} + +void PxScaleRigidActor(PxRigidActor& actor, PxReal scale, bool scaleMassProps) +{ + PX_CHECK_AND_RETURN(scale > 0, + "PxScaleRigidActor requires that the scale parameter is greater than zero"); + + Ps::InlineArray<PxShape*, 64> shapes; + shapes.resize(actor.getNbShapes()); + actor.getShapes(shapes.begin(), shapes.size()); + + for(PxU32 i=0;i<shapes.size();i++) + { + shapes[i]->setLocalPose(scalePosition(shapes[i]->getLocalPose(), scale)); + PxGeometryHolder h = shapes[i]->getGeometry(); + + switch(h.getType()) + { + case PxGeometryType::eSPHERE: + h.sphere().radius *= scale; + break; + case PxGeometryType::ePLANE: + break; + case PxGeometryType::eCAPSULE: + h.capsule().halfHeight *= scale; + h.capsule().radius *= scale; + break; + case PxGeometryType::eBOX: + h.box().halfExtents *= scale; + break; + case PxGeometryType::eCONVEXMESH: + h.convexMesh().scale.scale *= scale; + break; + case PxGeometryType::eTRIANGLEMESH: + h.triangleMesh().scale.scale *= scale; + break; + case PxGeometryType::eHEIGHTFIELD: + h.heightField().heightScale *= scale; + h.heightField().rowScale *= scale; + h.heightField().columnScale *= scale; + break; + case PxGeometryType::eINVALID: + case PxGeometryType::eGEOMETRY_COUNT: + PX_ASSERT(0); + } + shapes[i]->setGeometry(h.any()); + } + + if(!scaleMassProps) + return; + + PxRigidDynamic* dynamic = (&actor)->is<PxRigidDynamic>(); + if(!dynamic) + return; + + PxReal scale3 = scale*scale*scale; + dynamic->setMass(dynamic->getMass()*scale3); + dynamic->setMassSpaceInertiaTensor(dynamic->getMassSpaceInertiaTensor()*scale3*scale*scale); + dynamic->setCMassLocalPose(scalePosition(dynamic->getCMassLocalPose(), scale)); +} +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtSmoothNormals.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtSmoothNormals.cpp new file mode 100644 index 00000000..35d511cc --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtSmoothNormals.cpp @@ -0,0 +1,145 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "foundation/PxMemory.h" +#include "PxSmoothNormals.h" +#include "PsMathUtils.h" +#include "PsUserAllocated.h" +#include "PsUtilities.h" +#include "CmPhysXCommon.h" + +using namespace physx; + +static PxReal computeAngle(const PxVec3* verts, const PxU32* refs, PxU32 vref) +{ + PxU32 e0=0,e2=0; + if(vref==refs[0]) + { + e0 = 2; + e2 = 1; + } + else if(vref==refs[1]) + { + e0 = 2; + e2 = 0; + } + else if(vref==refs[2]) + { + e0 = 0; + e2 = 1; + } + else + { + PX_ASSERT(0); + } + const PxVec3 edge0 = verts[refs[e0]] - verts[vref]; + const PxVec3 edge1 = verts[refs[e2]] - verts[vref]; + + return Ps::angle(edge0, edge1); +} + +bool PxBuildSmoothNormals(PxU32 nbTris, PxU32 nbVerts, const PxVec3* verts, const PxU32* dFaces, const PxU16* wFaces, PxVec3* normals, bool flip) +{ + if(!verts || !normals || !nbTris || !nbVerts) + return false; + + // Get correct destination buffers + // - if available, write directly to user-provided buffers + // - else get some ram and keep track of it + PxVec3* FNormals = reinterpret_cast<PxVec3*>(PX_ALLOC_TEMP(sizeof(PxVec3)*nbTris, "PxVec3")); + if(!FNormals) return false; + + // Compute face normals + const PxU32 c = PxU32(flip!=0); + for(PxU32 i=0; i<nbTris; i++) + { + // compute indices outside of array index to workaround + // SNC bug which was generating incorrect addresses + const PxU32 i0 = i*3+0; + const PxU32 i1 = i*3+1+c; + const PxU32 i2 = i*3+2-c; + + const PxU32 Ref0 = dFaces ? dFaces[i0] : wFaces ? wFaces[i0] : 0; + const PxU32 Ref1 = dFaces ? dFaces[i1] : wFaces ? wFaces[i1] : 1; + const PxU32 Ref2 = dFaces ? dFaces[i2] : wFaces ? wFaces[i2] : 2; + + FNormals[i] = (verts[Ref2]-verts[Ref0]).cross(verts[Ref1] - verts[Ref0]); + PX_ASSERT(!FNormals[i].isZero()); + FNormals[i].normalize(); + } + + // Compute vertex normals + PxMemSet(normals, 0, nbVerts*sizeof(PxVec3)); + + // TTP 3751 + PxVec3* TmpNormals = reinterpret_cast<PxVec3*>(PX_ALLOC_TEMP(sizeof(PxVec3)*nbVerts, "PxVec3")); + PxMemSet(TmpNormals, 0, nbVerts*sizeof(PxVec3)); + for(PxU32 i=0;i<nbTris;i++) + { + PxU32 Ref[3]; + Ref[0] = dFaces ? dFaces[i*3+0] : wFaces ? wFaces[i*3+0] : 0; + Ref[1] = dFaces ? dFaces[i*3+1] : wFaces ? wFaces[i*3+1] : 1; + Ref[2] = dFaces ? dFaces[i*3+2] : wFaces ? wFaces[i*3+2] : 2; + + for(PxU32 j=0;j<3;j++) + { + if(TmpNormals[Ref[j]].isZero()) + TmpNormals[Ref[j]] = FNormals[i]; + } + } + //~TTP 3751 + + for(PxU32 i=0;i<nbTris;i++) + { + PxU32 Ref[3]; + Ref[0] = dFaces ? dFaces[i*3+0] : wFaces ? wFaces[i*3+0] : 0; + Ref[1] = dFaces ? dFaces[i*3+1] : wFaces ? wFaces[i*3+1] : 1; + Ref[2] = dFaces ? dFaces[i*3+2] : wFaces ? wFaces[i*3+2] : 2; + + normals[Ref[0]] += FNormals[i] * computeAngle(verts, Ref, Ref[0]); + normals[Ref[1]] += FNormals[i] * computeAngle(verts, Ref, Ref[1]); + normals[Ref[2]] += FNormals[i] * computeAngle(verts, Ref, Ref[2]); + } + + // Normalize vertex normals + for(PxU32 i=0;i<nbVerts;i++) + { + if(normals[i].isZero()) + normals[i] = TmpNormals[i]; +// PX_ASSERT(!normals[i].isZero()); + normals[i].normalize(); + } + + PX_FREE_AND_RESET(TmpNormals); // TTP 3751 + PX_FREE_AND_RESET(FNormals); + + return true; +} + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJoint.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJoint.cpp new file mode 100644 index 00000000..bb7bc10b --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJoint.cpp @@ -0,0 +1,228 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "ExtSphericalJoint.h" +#include "ExtConstraintHelper.h" +#include "CmConeLimitHelper.h" +#include "CmRenderOutput.h" +#include "CmVisualization.h" + +#include "common/PxSerialFramework.h" + +using namespace physx; +using namespace Ext; + +namespace physx +{ + PxSphericalJoint* PxSphericalJointCreate(PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1); +} + +PxSphericalJoint* physx::PxSphericalJointCreate(PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) +{ + PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxSphericalJointCreate: local frame 0 is not a valid transform"); + PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxSphericalJointCreate: local frame 1 is not a valid transform"); + PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxSphericalJointCreate: actors must be different"); + PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxSphericalJointCreate: at least one actor must be dynamic"); + + SphericalJoint* j; + PX_NEW_SERIALIZED(j,SphericalJoint)(physics.getTolerancesScale(), actor0, localFrame0, actor1, localFrame1); + + if(j->attach(physics, actor0, actor1)) + return j; + + PX_DELETE(j); + return NULL; +} + +void SphericalJoint::setProjectionLinearTolerance(PxReal tolerance) +{ + PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance >=0, "PxSphericalJoint::setProjectionLinearTolerance: invalid parameter"); + data().projectionLinearTolerance = tolerance; + markDirty(); +} + +PxReal SphericalJoint::getProjectionLinearTolerance() const +{ + return data().projectionLinearTolerance; +} + +void SphericalJoint::setLimitCone(const PxJointLimitCone &limit) +{ + PX_CHECK_AND_RETURN(limit.isValid(), "PxSphericalJoint::setLimit: invalid parameter"); + data().limit = limit; + markDirty(); +} + +PxJointLimitCone SphericalJoint::getLimitCone() const +{ + return data().limit; +} + + +PxSphericalJointFlags SphericalJoint::getSphericalJointFlags(void) const +{ + return data().jointFlags; +} + +void SphericalJoint::setSphericalJointFlags(PxSphericalJointFlags flags) +{ + data().jointFlags = flags; +} +void SphericalJoint::setSphericalJointFlag(PxSphericalJointFlag::Enum flag, bool value) +{ + if(value) + data().jointFlags |= flag; + else + data().jointFlags &= ~flag; + markDirty(); +} + + +void* Ext::SphericalJoint::prepareData() +{ + SphericalJointData& d = data(); + if(d.jointFlags & PxSphericalJointFlag::eLIMIT_ENABLED) + { + d.tanQYLimit = PxTan(d.limit.yAngle/4); + d.tanQZLimit = PxTan(d.limit.zAngle/4); + d.tanQPad = PxTan(d.limit.contactDistance/4); + } + return SphericalJointT::prepareData(); +} + +namespace +{ + +void SphericalJointVisualize(PxConstraintVisualizer& viz, + const void* constantBlock, + const PxTransform& body0Transform, + const PxTransform& body1Transform, + PxU32 /*flags*/) +{ + using namespace joint; + const SphericalJointData& data = *reinterpret_cast<const SphericalJointData*>(constantBlock); + + PxTransform cA2w = body0Transform * data.c2b[0]; + PxTransform cB2w = body1Transform * data.c2b[1]; + + viz.visualizeJointFrames(cA2w, cB2w); + + + if(data.jointFlags & PxSphericalJointFlag::eLIMIT_ENABLED) + { + if(cA2w.q.dot(cB2w.q)<0) + cB2w.q = -cB2w.q; + + PxTransform cB2cA = cA2w.transformInv(cB2w); + PxQuat swing, twist; + Ps::separateSwingTwist(cB2cA.q,swing,twist); + + PxVec3 tanQSwing = PxVec3(0, Ps::tanHalf(swing.z,swing.w), -Ps::tanHalf(swing.y,swing.w)); + Cm::ConeLimitHelper coneHelper(data.tanQZLimit, data.tanQYLimit, data.tanQPad); + viz.visualizeLimitCone(cA2w, data.tanQZLimit, data.tanQYLimit, + !coneHelper.contains(tanQSwing)); + } +} + + + +void SphericalJointProject(const void* constantBlock, + PxTransform& bodyAToWorld, + PxTransform& bodyBToWorld, + bool projectToA) +{ + using namespace joint; + + const SphericalJointData& data = *reinterpret_cast<const SphericalJointData*>(constantBlock); + + PxTransform cA2w, cB2w, cB2cA, projected; + joint::computeDerived(data, bodyAToWorld, bodyBToWorld, cA2w, cB2w, cB2cA); + + bool linearTrunc; + projected.p = truncateLinear(cB2cA.p, data.projectionLinearTolerance, linearTrunc); + + if(linearTrunc) + { + projected.q = cB2cA.q; + projectTransforms(bodyAToWorld, bodyBToWorld, cA2w, cB2w, projected, data, projectToA); + } +} +} + + +bool Ext::SphericalJoint::attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1) +{ + mPxConstraint = physics.createConstraint(actor0, actor1, *this, sShaders, sizeof(SphericalJointData)); + return mPxConstraint!=NULL; +} + +void SphericalJoint::exportExtraData(PxSerializationContext& stream) +{ + if(mData) + { + stream.alignData(PX_SERIAL_ALIGN); + stream.writeData(mData, sizeof(SphericalJointData)); + } + stream.writeName(mName); +} + +void SphericalJoint::importExtraData(PxDeserializationContext& context) +{ + if(mData) + mData = context.readExtraData<SphericalJointData, PX_SERIAL_ALIGN>(); + context.readName(mName); +} + +void SphericalJoint::resolveReferences(PxDeserializationContext& context) +{ + setPxConstraint(resolveConstraintPtr(context, getPxConstraint(), getConnector(), sShaders)); +} + +SphericalJoint* SphericalJoint::createObject(PxU8*& address, PxDeserializationContext& context) +{ + SphericalJoint* obj = new (address) SphericalJoint(PxBaseFlag::eIS_RELEASABLE); + address += sizeof(SphericalJoint); + obj->importExtraData(context); + obj->resolveReferences(context); + return obj; +} + +// global function to share the joint shaders with API capture +const PxConstraintShaderTable* Ext::GetSphericalJointShaderTable() +{ + return &SphericalJoint::getConstraintShaderTable(); +} + +//~PX_SERIALIZATION +PxConstraintShaderTable Ext::SphericalJoint::sShaders = { Ext::SphericalJointSolverPrep, SphericalJointProject, SphericalJointVisualize, PxConstraintFlag::Enum(0) }; diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJoint.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJoint.h new file mode 100644 index 00000000..cef79293 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJoint.h @@ -0,0 +1,151 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef NP_SPHERICALJOINTCONSTRAINT_H +#define NP_SPHERICALJOINTCONSTRAINT_H + +#include "ExtJoint.h" +#include "PxSphericalJoint.h" +#include "CmUtils.h" + +namespace physx +{ +struct PxSphericalJointGeneratedValues; +namespace Ext +{ + struct SphericalJointData: public JointData + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + PxJointLimitCone limit; + PxReal tanQYLimit; + PxReal tanQZLimit; + PxReal tanQPad; + + PxReal projectionLinearTolerance; + + PxSphericalJointFlags jointFlags; + // forestall compiler complaints about not being able to generate a constructor + private: + SphericalJointData(const PxJointLimitCone &cone): + limit(cone) {} + }; + + typedef Joint<PxSphericalJoint, PxSphericalJointGeneratedValues> SphericalJointT; + + class SphericalJoint : public SphericalJointT + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + public: +// PX_SERIALIZATION + SphericalJoint(PxBaseFlags baseFlags) : SphericalJointT(baseFlags) {} + virtual void exportExtraData(PxSerializationContext& context); + void importExtraData(PxDeserializationContext& context); + void resolveReferences(PxDeserializationContext& context); + static SphericalJoint* createObject(PxU8*& address, PxDeserializationContext& context); + static void getBinaryMetaData(PxOutputStream& stream); +//~PX_SERIALIZATION + virtual ~SphericalJoint() + { + if(getBaseFlags()&PxBaseFlag::eOWNS_MEMORY) + PX_FREE(mData); + } + + SphericalJoint(const PxTolerancesScale& /*scale*/, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) + : SphericalJointT(PxJointConcreteType::eSPHERICAL, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE) + { + SphericalJointData* data = reinterpret_cast<SphericalJointData*>(PX_ALLOC(sizeof(SphericalJointData), "SphericalJointData")); + Cm::markSerializedMem(data, sizeof(SphericalJointData)); + mData = data; + + initCommonData(*data,actor0, localFrame0, actor1, localFrame1); + data->projectionLinearTolerance = 1e10f; + data->limit = PxJointLimitCone(PxPi/2, PxPi/2); + data->jointFlags = PxSphericalJointFlags(); + } + + void setProjectionLinearTolerance(PxReal distance); + PxReal getProjectionLinearTolerance() const; + + void setLimitCone(const PxJointLimitCone &limit); + PxJointLimitCone getLimitCone() const; + + PxSphericalJointFlags getSphericalJointFlags(void) const; + void setSphericalJointFlags(PxSphericalJointFlags flags); + void setSphericalJointFlag(PxSphericalJointFlag::Enum flag, bool value); + + void* prepareData(); + + bool attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1); + + static const PxConstraintShaderTable& getConstraintShaderTable() { return sShaders; } + + virtual PxConstraintSolverPrep getPrep() const { return sShaders.solverPrep; } + + private: + + static PxConstraintShaderTable sShaders; + + PX_FORCE_INLINE SphericalJointData& data() const + { + return *static_cast<SphericalJointData*>(mData); + } + }; + +} // namespace Ext + +namespace Ext +{ + extern "C" PxU32 SphericalJointSolverPrep(Px1DConstraint* constraints, + PxVec3& body0WorldOffset, + PxU32 maxConstraints, + PxConstraintInvMassScale& invMassScale, + const void* constantBlock, + const PxTransform& bA2w, + const PxTransform& bB2w); + + // global function to share the joint shaders with API capture + extern "C" const PxConstraintShaderTable* GetSphericalJointShaderTable(); +} + +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJointSolverPrep.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJointSolverPrep.cpp new file mode 100644 index 00000000..937b8a3b --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJointSolverPrep.cpp @@ -0,0 +1,87 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "ExtSphericalJoint.h" +#include "ExtConstraintHelper.h" +#include "CmConeLimitHelper.h" +#include "CmRenderOutput.h" + +namespace physx +{ +namespace Ext +{ + PxU32 SphericalJointSolverPrep(Px1DConstraint* constraints, + PxVec3& body0WorldOffset, + PxU32 /*maxConstraints*/, + PxConstraintInvMassScale &invMassScale, + const void* constantBlock, + const PxTransform& bA2w, + const PxTransform& bB2w) + { + + using namespace joint; + const SphericalJointData& data = *reinterpret_cast<const SphericalJointData*>(constantBlock); + invMassScale = data.invMassScale; + + + PxTransform cA2w = bA2w * data.c2b[0]; + PxTransform cB2w = bB2w * data.c2b[1]; + + if(cB2w.q.dot(cA2w.q)<0) + cB2w.q = -cB2w.q; + + body0WorldOffset = cB2w.p-bA2w.p; + joint::ConstraintHelper ch(constraints, cB2w.p - bA2w.p, cB2w.p - bB2w.p); + + if(data.jointFlags & PxSphericalJointFlag::eLIMIT_ENABLED) + { + PxQuat swing, twist; + Ps::separateSwingTwist(cA2w.q.getConjugate() * cB2w.q, swing, twist); + PX_ASSERT(PxAbs(swing.x)<1e-6f); + + Cm::ConeLimitHelper coneHelper(data.tanQZLimit, data.tanQYLimit, data.tanQPad); + + PxVec3 axis; + PxReal error; + if(coneHelper.getLimit(swing, axis, error)) + ch.angularLimit(cA2w.rotate(axis),error,data.limit); + + } + + ch.prepareLockedAxes(cA2w.q, cB2w.q, cA2w.transformInv(cB2w.p), 7, 0); + + return ch.getCount(); + } +}//namespace + +} + +//~PX_SERIALIZATION + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtTaskQueueHelper.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtTaskQueueHelper.h new file mode 100644 index 00000000..c5f663f2 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtTaskQueueHelper.h @@ -0,0 +1,66 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_EXTENSIONS_NP_TASK_QUEUE_HELPER_H +#define PX_PHYSICS_EXTENSIONS_NP_TASK_QUEUE_HELPER_H + +#include "task/PxTask.h" +#include "CmPhysXCommon.h" +#include "ExtSharedQueueEntryPool.h" + +namespace physx +{ + +#define EXT_TASK_QUEUE_ENTRY_POOL_SIZE 128 + +namespace Ext +{ + class TaskQueueHelper + { + public: + static PxBaseTask* fetchTask(Ps::SList& taskQueue, Ext::SharedQueueEntryPool<>& entryPool) + { + SharedQueueEntry* entry = static_cast<SharedQueueEntry*>(taskQueue.pop()); + if (entry) + { + PxBaseTask* task = reinterpret_cast<PxBaseTask*>(entry->mObjectRef); + entryPool.putEntry(*entry); + return task; + } + else + return NULL; + } + }; + +} // namespace Ext + +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtTriangleMeshExt.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtTriangleMeshExt.cpp new file mode 100644 index 00000000..92702047 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtTriangleMeshExt.cpp @@ -0,0 +1,183 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "PxTriangleMeshExt.h" +#include "PxMeshQuery.h" +#include "PxGeometryQuery.h" +#include "PxTriangleMeshGeometry.h" +#include "PxHeightFieldGeometry.h" +#include "PxTriangleMesh.h" +#include "PsAllocator.h" + +using namespace physx; + +PxMeshOverlapUtil::PxMeshOverlapUtil() : mResultsMemory(mResults), mNbResults(0), mMaxNbResults(256) +{ +} + +PxMeshOverlapUtil::~PxMeshOverlapUtil() +{ + if(mResultsMemory != mResults) + PX_FREE(mResultsMemory); +} + +PxU32 PxMeshOverlapUtil::findOverlap(const PxGeometry& geom, const PxTransform& geomPose, const PxTriangleMeshGeometry& meshGeom, const PxTransform& meshPose) +{ + bool overflow; + PxU32 nbTouchedTris = PxMeshQuery::findOverlapTriangleMesh(geom, geomPose, meshGeom, meshPose, mResultsMemory, mMaxNbResults, 0, overflow); + + if(overflow) + { + const PxU32 maxNbTris = meshGeom.triangleMesh->getNbTriangles(); + if(!maxNbTris) + { + mNbResults = 0; + return 0; + } + + if(mMaxNbResults<maxNbTris) + { + if(mResultsMemory != mResults) + PX_FREE(mResultsMemory); + + mResultsMemory = reinterpret_cast<PxU32*>(PX_ALLOC(sizeof(PxU32)*maxNbTris, "PxMeshOverlapUtil::findOverlap")); + mMaxNbResults = maxNbTris; + } + nbTouchedTris = PxMeshQuery::findOverlapTriangleMesh(geom, geomPose, meshGeom, meshPose, mResultsMemory, mMaxNbResults, 0, overflow); + PX_ASSERT(nbTouchedTris); + PX_ASSERT(!overflow); + } + mNbResults = nbTouchedTris; + return nbTouchedTris; +} + +PxU32 PxMeshOverlapUtil::findOverlap(const PxGeometry& geom, const PxTransform& geomPose, const PxHeightFieldGeometry& hfGeom, const PxTransform& hfPose) +{ + bool overflow = true; + PxU32 nbTouchedTris = 0; + do + { + nbTouchedTris = PxMeshQuery::findOverlapHeightField(geom, geomPose, hfGeom, hfPose, mResultsMemory, mMaxNbResults, 0, overflow); + if(overflow) + { + const PxU32 maxNbTris = mMaxNbResults * 2; + + if(mResultsMemory != mResults) + PX_FREE(mResultsMemory); + + mResultsMemory = reinterpret_cast<PxU32*>(PX_ALLOC(sizeof(PxU32)*maxNbTris, "PxMeshOverlapUtil::findOverlap")); + mMaxNbResults = maxNbTris; + } + }while(overflow); + + mNbResults = nbTouchedTris; + return nbTouchedTris; +} +namespace +{ +template<typename MeshGeometry> +bool computeMeshPenetrationT(PxVec3& direction, + PxReal& depth, + const PxGeometry& geom, + const PxTransform& geomPose, + const MeshGeometry& meshGeom, + const PxTransform& meshPose, + PxU32 maxIter, + PxU32* nbIterOut) +{ + PxU32 nbIter = 0; + PxTransform pose = geomPose; + for (; nbIter < maxIter; nbIter++) + { + PxVec3 currentDir; + PxF32 currentDepth; + + if (!PxGeometryQuery::computePenetration(currentDir, currentDepth, geom, pose, meshGeom, meshPose)) + break; + + pose.p += currentDir * currentDepth; + } + + if(nbIterOut) + *nbIterOut = nbIter; + + PxVec3 diff = pose.p - geomPose.p; + depth = diff.magnitude(); + + if (depth>0) + direction = diff / depth; + + return nbIter!=0; +} +} + +bool physx::PxComputeTriangleMeshPenetration(PxVec3& direction, + PxReal& depth, + const PxGeometry& geom, + const PxTransform& geomPose, + const PxTriangleMeshGeometry& meshGeom, + const PxTransform& meshPose, + PxU32 maxIter, + PxU32* nbIter) +{ + return computeMeshPenetrationT(direction, depth, geom, geomPose, meshGeom, meshPose, maxIter, nbIter); +} + + +PxVec3 physx::PxComputeMeshPenetration(PxU32 maxIter, const PxGeometry& geom, const PxTransform& geomPose, const PxTriangleMeshGeometry& meshGeom, const PxTransform& meshPose, PxU32& nb) +{ + PxVec3 direction; + PxReal depth; + computeMeshPenetrationT(direction, depth, geom, geomPose, meshGeom, meshPose, maxIter, &nb); + return direction * depth; +} + + +bool physx::PxComputeHeightFieldPenetration(PxVec3& direction, + PxReal& depth, + const PxGeometry& geom, + const PxTransform& geomPose, + const PxHeightFieldGeometry& hfGeom, + const PxTransform& meshPose, + PxU32 maxIter, + PxU32* nbIter) +{ + return computeMeshPenetrationT(direction, depth, geom, geomPose, hfGeom, meshPose, maxIter, nbIter); +} + + +PxVec3 physx::PxComputeHeightFieldPenetration(PxU32 maxIter, const PxGeometry& geom, const PxTransform& geomPose, const PxHeightFieldGeometry& meshGeom, const PxTransform& meshPose, PxU32& nb) +{ + PxVec3 direction; + PxReal depth; + computeMeshPenetrationT(direction, depth, geom, geomPose, meshGeom, meshPose, maxIter, &nb); + return direction * depth; +} + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinaryDeserialization.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinaryDeserialization.cpp new file mode 100644 index 00000000..981cfa2a --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinaryDeserialization.cpp @@ -0,0 +1,305 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PsHash.h" +#include "PsHashMap.h" +#include "PsFoundation.h" +#include "CmIO.h" +#include "SnFile.h" +#include "PsString.h" +#include "extensions/PxSerialization.h" +#include "PxPhysics.h" +#include "PxPhysicsSerialization.h" +#include "SnSerializationContext.h" +#include "PxSerializer.h" +#include "serialization/SnSerializationRegistry.h" +#include "serialization/SnSerialUtils.h" +#include "CmCollection.h" +#include "SnConvX_Align.h" + +using namespace physx; +using namespace Sn; + +namespace +{ + PX_INLINE PxU8* alignPtr(PxU8* ptr, PxU32 alignment = PX_SERIAL_ALIGN) + { + if(!alignment) + return ptr; + + const PxU32 padding = getPadding(size_t(ptr), alignment); + PX_ASSERT(!getPadding(size_t(ptr + padding), alignment)); + return ptr + padding; + } + + PX_FORCE_INLINE PxU32 read32(PxU8*& address) + { + const PxU32 value = *reinterpret_cast<PxU32*>(address); + address += sizeof(PxU32); + return value; + } + + bool readHeader(PxU8*& address, PxU32& version) + { + const PxU32 header = read32(address); + PX_UNUSED(header); + + version = read32(address); + + const PxU32 binaryVersion = read32(address); + PX_UNUSED(binaryVersion); + const PxU32 buildNumber = read32(address); + PX_UNUSED(buildNumber); + const PxU32 platformTag = read32(address); + PX_UNUSED(platformTag); + const PxU32 markedPadding = read32(address); + PX_UNUSED(markedPadding); + +#if PX_CHECKED + if (header != PX_MAKE_FOURCC('S','E','B','D')) + { + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "Buffer contains data with wrong header indicating invalid binary data."); + return false; + } + + if (!checkCompatibility(version, binaryVersion)) + { + char buffer[512]; + getCompatibilityVersionsStr(buffer, 512); + + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "Buffer contains data version (%x-%d) is incompatible with this PhysX sdk.\n These versions would be compatible: %s", + version, binaryVersion, buffer); + return false; + } + + if (platformTag != getBinaryPlatformTag()) + { + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "Buffer contains data with platform mismatch:\nExpected: %s \nActual: %s\n", + getBinaryPlatformName(getBinaryPlatformTag()), + getBinaryPlatformName(platformTag)); + return false; + } +#endif + return true; + } + + bool checkImportReferences(const ImportReference* importReferences, PxU32 nbImportReferences, const Cm::Collection* externalRefs) + { + if (!externalRefs) + { + if (nbImportReferences > 0) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxSerialization::createCollectionFromBinary: External references needed but no externalRefs collection specified."); + return false; + } + } + else + { + for (PxU32 i=0; i<nbImportReferences;i++) + { + PxSerialObjectId id = importReferences[i].id; + PxType type = importReferences[i].type; + + PxBase* referencedObject = externalRefs->find(id); + if (!referencedObject) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxSerialization::createCollectionFromBinary: External reference %" PX_PRIu64 " expected in externalRefs collection but not found.", id); + return false; + } + if (referencedObject->getConcreteType() != type) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxSerialization::createCollectionFromBinary: External reference %d type mismatch. Expected %d but found %d in externalRefs collection.", type, referencedObject->getConcreteType()); + return false; + } + } + } + return true; + } + +} + +PxCollection* PxSerialization::createCollectionFromBinary(void* memBlock, PxSerializationRegistry& sr, const PxCollection* pxExternalRefs) +{ +#if PX_CHECKED + if(size_t(memBlock) & (PX_SERIAL_FILE_ALIGN-1)) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "Buffer must be 128-bytes aligned."); + return NULL; + } +#endif + PxU8* address = reinterpret_cast<PxU8*>(memBlock); + const Cm::Collection* externalRefs = static_cast<const Cm::Collection*>(pxExternalRefs); + + PxU32 version; + if (!readHeader(address, version)) + { + return NULL; + } + + ManifestEntry* manifestTable; + PxU32 nbObjectsInCollection; + PxU32 objectDataEndOffset; + + // read number of objects in collection + address = alignPtr(address); + nbObjectsInCollection = read32(address); + + // read manifest (PxU32 offset, PxConcreteType type) + { + address = alignPtr(address); + PxU32 nbManifestEntries = read32(address); + PX_ASSERT(*reinterpret_cast<PxU32*>(address) == 0); //first offset is always 0 + manifestTable = (nbManifestEntries > 0) ? reinterpret_cast<ManifestEntry*>(address) : NULL; + address += nbManifestEntries*sizeof(ManifestEntry); + objectDataEndOffset = read32(address); + } + + ImportReference* importReferences; + PxU32 nbImportReferences; + // read import references + { + address = alignPtr(address); + nbImportReferences = read32(address); + importReferences = (nbImportReferences > 0) ? reinterpret_cast<ImportReference*>(address) : NULL; + address += nbImportReferences*sizeof(ImportReference); + } + + if (!checkImportReferences(importReferences, nbImportReferences, externalRefs)) + { + return NULL; + } + + ExportReference* exportReferences; + PxU32 nbExportReferences; + // read export references + { + address = alignPtr(address); + nbExportReferences = read32(address); + exportReferences = (nbExportReferences > 0) ? reinterpret_cast<ExportReference*>(address) : NULL; + address += nbExportReferences*sizeof(ExportReference); + } + + // read internal references arrays + PxU32 nbInternalPtrReferences = 0; + PxU32 nbInternalIdxReferences = 0; + InternalReferencePtr* internalPtrReferences = NULL; + InternalReferenceIdx* internalIdxReferences = NULL; + { + address = alignPtr(address); + + nbInternalPtrReferences = read32(address); + internalPtrReferences = (nbInternalPtrReferences > 0) ? reinterpret_cast<InternalReferencePtr*>(address) : NULL; + address += nbInternalPtrReferences*sizeof(InternalReferencePtr); + + nbInternalIdxReferences = read32(address); + internalIdxReferences = (nbInternalIdxReferences > 0) ? reinterpret_cast<InternalReferenceIdx*>(address) : NULL; + address += nbInternalIdxReferences*sizeof(InternalReferenceIdx); + } + + // create internal references map + PxF32 loadFactor = 0.75f; + PxF32 _loadFactor = 1.0f / loadFactor; + PxU32 hashSize = PxU32((nbInternalPtrReferences + nbInternalIdxReferences + 1)*_loadFactor); + InternalRefMap internalReferencesMap(hashSize, loadFactor); + { + //create hash (we should load the hashes directly from memory) + for (PxU32 i=0;i<nbInternalPtrReferences;i++) + { + const InternalReferencePtr& ref = internalPtrReferences[i]; + internalReferencesMap.insertUnique( InternalRefKey(ref.reference, ref.kind), SerialObjectIndex(ref.objIndex)); + } + for (PxU32 i=0;i<nbInternalIdxReferences;i++) + { + const InternalReferenceIdx& ref = internalIdxReferences[i]; + internalReferencesMap.insertUnique(InternalRefKey(ref.reference, ref.kind), SerialObjectIndex(ref.objIndex)); + } + } + + SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr); + Cm::Collection* collection = static_cast<Cm::Collection*>(PxCreateCollection()); + PX_ASSERT(collection); + collection->mObjects.reserve(PxU32(nbObjectsInCollection*_loadFactor) + 1); + if(nbExportReferences > 0) + collection->mIds.reserve(PxU32(nbExportReferences*_loadFactor) + 1); + + PxU8* addressObjectData = alignPtr(address); + PxU8* addressExtraData = alignPtr(addressObjectData + objectDataEndOffset); + + DeserializationContext context(manifestTable, importReferences, addressObjectData, internalReferencesMap, externalRefs, addressExtraData, version); + + // iterate over memory containing PxBase objects, create the instances, resolve the addresses, import the external data, add to collection. + { + PxU32 nbObjects = nbObjectsInCollection; + + while(nbObjects--) + { + address = alignPtr(address); + context.alignExtraData(); + + // read PxBase header with type and get corresponding serializer. + PxBase* header = reinterpret_cast<PxBase*>(address); + const PxType classType = header->getConcreteType(); + const PxSerializer* serializer = sn.getSerializer(classType); + PX_ASSERT(serializer); + + PxBase* instance = serializer->createObject(address, context); + if (!instance) + { + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "Cannot create class instance for concrete type %d.", classType); + collection->release(); + return NULL; + } + + collection->internalAdd(instance); + } + } + + PX_ASSERT(nbObjectsInCollection == collection->internalGetNbObjects()); + + // update new collection with export references + { + PX_ASSERT(addressObjectData != NULL); + for (PxU32 i=0;i<nbExportReferences;i++) + { + bool isExternal; + PxU32 manifestIndex = exportReferences[i].objIndex.getIndex(isExternal); + PX_ASSERT(!isExternal); + PxBase* obj = reinterpret_cast<PxBase*>(addressObjectData + manifestTable[manifestIndex].offset); + collection->mIds.insertUnique(exportReferences[i].id, obj); + collection->mObjects[obj] = exportReferences[i].id; + } + } + + PxAddCollectionToPhysics(*collection); + return collection; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinarySerialization.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinarySerialization.cpp new file mode 100644 index 00000000..f9a8b1b9 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinarySerialization.cpp @@ -0,0 +1,402 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PsHash.h" +#include "PsHashMap.h" +#include "CmIO.h" +#include "SnFile.h" +#include "PsString.h" +#include "PsIntrinsics.h" +#include "extensions/PxSerialization.h" +#include "SnSerializationContext.h" +#include "PxSerializer.h" +#include "serialization/SnSerialUtils.h" +#include "serialization/SnSerializationRegistry.h" +#include "SnConvX_Align.h" +#include "PxDefaultStreams.h" +#include "CmCollection.h" +#include "PxPhysicsVersion.h" +#include "PsUtilities.h" + +using namespace physx; +using namespace Cm; +using namespace Sn; + +//------------------------------------------------------------------------------------ +//// Binary Serialized PxCollection, format documentation +//------------------------------------------------------------------------------------ +// +// +//------------------------------------------------------------------------------------ +//// overview: +//// header information +//// manifest table +//// import references +//// export references +//// internal references +//// object data +//// extra data +//------------------------------------------------------------------------------------ +// +// +//------------------------------------------------------------------------------------ +//// header information: +//// header tag plus various version and platform information +//------------------------------------------------------------------------------------ +// header SEBD +// PX_PHYSICS_VERSION +// PX_BINARY_SERIAL_VERSION +// PX_BUILD_NUMBER (or 0 if not defined) +// platform tag +// markedPadding (on for PX_CHECKED) +// nbObjectsInCollection +// +// +//------------------------------------------------------------------------------------ +//// manifest table: +//// one entry per collected object +//// offsets relative to object data buffer +//------------------------------------------------------------------------------------ +// alignment +// PxU32 size +// (PxU32 offset, PxType type)*size +// PxU32 endOffset +// +// +//------------------------------------------------------------------------------------ +//// import references: +//// one entry per required reference to external collection +//------------------------------------------------------------------------------------ +// alignment +// PxU32 size +// (PxSerialObjectId id, PxType type)*size +// +// +//------------------------------------------------------------------------------------ +//// export references: +//// one entry per object in the collection with id +//// object indices point into the manifest table (objects in the same collection) +//------------------------------------------------------------------------------------ +// alignment +// PxU32 size +// (PxSerialObjectId id, SerialObjectIndex objIndex)*size +// +// +//------------------------------------------------------------------------------------ +//// internal references: +//// one entry per reference, kind pair +//// object indices point either into the manifest table or into the import references +//// depending on whether the entry references the same collection or the external one +//// one section for pointer type references and one for index type references. +//------------------------------------------------------------------------------------ +// alignment +// PxU32 sizePtrs; +// (size_t reference, PxU32 kind, SerialObjectIndex objIndex)*sizePtrs +// PxU32 sizeIdx; +// (PxU32 reference, PxU32 kind, SerialObjectIndex objIndex)*sizePtrs +// +// +//------------------------------------------------------------------------------------ +//// object data: +//// serialized PxBase derived class instances +//// each object size depends on specific class +//// offsets are stored in manifest table +//------------------------------------------------------------------------------------ +// alignment +// (PxConcreteType type, -----) +// alignment +// (PxConcreteType type, --------) +// alignment +// (PxConcreteType type, --) +// . +// . +// +// +// ----------------------------------------------------------------------------------- +//// extra data: +//// extra data memory block +//// serialized and deserialized by PxBase implementations +////---------------------------------------------------------------------------------- +// extra data +// +//------------------------------------------------------------------------------------ + +namespace +{ + + class LegacySerialStream : public PxSerializationContext + { + public: + LegacySerialStream(OutputStreamWriter& writer, + const PxCollection& collection, + bool exportNames) : mWriter(writer), mCollection(collection), mExportNames(exportNames) {} + void writeData(const void* buffer, PxU32 size) { mWriter.write(buffer, size); } + PxU32 getTotalStoredSize() { return mWriter.getStoredSize(); } + void alignData(PxU32 alignment) + { + if(!alignment) + return; + + PxI32 bytesToPad = PxI32(getPadding(getTotalStoredSize(), alignment)); + static const PxI32 BUFSIZE = 64; + char buf[BUFSIZE]; + PxMemSet(buf, 0, bytesToPad < BUFSIZE ? PxU32(bytesToPad) : PxU32(BUFSIZE)); + while(bytesToPad > 0) + { + writeData(buf, bytesToPad < BUFSIZE ? PxU32(bytesToPad) : PxU32(BUFSIZE)); + bytesToPad -= BUFSIZE; + } + PX_ASSERT(!getPadding(getTotalStoredSize(), alignment)); + } + + virtual void registerReference(PxBase&, PxU32, size_t) + { + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, + "Cannot register references during exportData, exportExtraData."); + } + + virtual const PxCollection& getCollection() const + { + return mCollection; + } + virtual void writeName(const char* name) + { + PxU32 len = name && mExportNames ? PxU32(strlen(name)) + 1 : 0; + writeData(&len, sizeof(len)); + if(len) writeData(name, len); + } + + private: + LegacySerialStream& operator=(const LegacySerialStream&); + OutputStreamWriter& mWriter; + const PxCollection& mCollection; + bool mExportNames; + }; + + void writeHeader(PxSerializationContext& stream, bool hasDeserializedAssets) + { + PX_UNUSED(hasDeserializedAssets); + struct Header + { + PxU32 header; + PxU32 version; + PxU32 binaryVersion; + PxU32 buildNumber; + PxU32 platformTag; + PxU32 markedPadding; + PxU32 materialOffset; + }; + + //serialized binary data. + const PxU32 header = PX_MAKE_FOURCC('S','E','B','D'); + stream.writeData(&header, sizeof(PxU32)); + + PxU32 version = PX_PHYSICS_VERSION; + stream.writeData(&version, sizeof(PxU32)); + + PxU32 binaryVersion = PX_BINARY_SERIAL_VERSION; + stream.writeData(&binaryVersion, sizeof(PxU32)); + + PxU32 buildNumber = 0; +#if defined(PX_BUILD_NUMBER) + buildNumber = PX_BUILD_NUMBER; +#endif + stream.writeData(&buildNumber, sizeof(PxU32)); + + PxU32 platformTag = getBinaryPlatformTag(); + stream.writeData(&platformTag, sizeof(PxU32)); + + PxU32 markedPadding = 0; +#if PX_CHECKED + if(!hasDeserializedAssets) + markedPadding = 1; +#endif + stream.writeData(&markedPadding, sizeof(PxU32)); + } +} + +bool PxSerialization::serializeCollectionToBinary(PxOutputStream& outputStream, PxCollection& pxCollection, PxSerializationRegistry& sr, const PxCollection* pxExternalRefs, bool exportNames) +{ + if(!PxSerialization::isSerializable(pxCollection, sr, pxExternalRefs)) + return false; + + Collection& collection = static_cast<Collection&>(pxCollection); + const Collection* externalRefs = static_cast<const Collection*>(pxExternalRefs); + + //temporary memory stream which allows fixing up data up stream + + SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr); + + // sort collection by "order" value (this will be the order in which they get serialized) + sortCollection(collection, sn, false); + + //initialized the context with the sorted collection. + SerializationContext context(collection, externalRefs); + + // gather reference information + bool hasDeserializedAssets = false; + { + const PxU32 nb = collection.internalGetNbObjects(); + for(PxU32 i=0;i<nb;i++) + { + PxBase* s = collection.internalGetObject(i); + PX_ASSERT(s && s->getConcreteType()); +#if PX_CHECKED + //can't guarantee marked padding for deserialized instances + if(!(s->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)) + hasDeserializedAssets = true; +#endif + const PxSerializer* serializer = sn.getSerializer(s->getConcreteType()); + PX_ASSERT(serializer); + serializer->registerReferences(*s, context); + } + } + + // now start the actual serialization into the output stream + OutputStreamWriter writer(outputStream); + LegacySerialStream stream(writer, collection, exportNames); + + writeHeader(stream, hasDeserializedAssets); + + // write size of collection + stream.alignData(PX_SERIAL_ALIGN); + PxU32 nbObjectsInCollection = collection.internalGetNbObjects(); + stream.writeData(&nbObjectsInCollection, sizeof(PxU32)); + + // write the manifest table (PxU32 offset, PxConcreteType type) + { + Ps::Array<ManifestEntry> manifestTable(collection.internalGetNbObjects()); + PxU32 headerOffset = 0; + for(PxU32 i=0;i<collection.internalGetNbObjects();i++) + { + PxBase* s = collection.internalGetObject(i); + PX_ASSERT(s && s->getConcreteType()); + PxType concreteType = s->getConcreteType(); + const PxSerializer* serializer = sn.getSerializer(concreteType); + PX_ASSERT(serializer); + manifestTable[i] = ManifestEntry(headerOffset, concreteType); + PxU32 classSize = PxU32(serializer->getClassSize()); + headerOffset += getPadding(classSize, PX_SERIAL_ALIGN) + classSize; + } + stream.alignData(PX_SERIAL_ALIGN); + const PxU32 nb = manifestTable.size(); + stream.writeData(&nb, sizeof(PxU32)); + stream.writeData(manifestTable.begin(), manifestTable.size()*sizeof(ManifestEntry)); + + //store offset for end of object buffer (PxU32 offset) + stream.writeData(&headerOffset, sizeof(PxU32)); + } + + // write import references + { + const Ps::Array<ImportReference>& importReferences = context.getImportReferences(); + stream.alignData(PX_SERIAL_ALIGN); + const PxU32 nb = importReferences.size(); + stream.writeData(&nb, sizeof(PxU32)); + stream.writeData(importReferences.begin(), importReferences.size()*sizeof(ImportReference)); + } + + // write export references + { + PxU32 nbIds = collection.getNbIds(); + Ps::Array<ExportReference> exportReferences(nbIds); + //we can't get quickly from id to object index in collection. + //if we only need this here, its not worth to build a hash + nbIds = 0; + for (PxU32 i=0;i<collection.getNbObjects();i++) + { + PxBase& obj = collection.getObject(i); + PxSerialObjectId id = collection.getId(obj); + if (id != PX_SERIAL_OBJECT_ID_INVALID) + { + SerialObjectIndex objIndex(i, false); //i corresponds to manifest entry + exportReferences[nbIds++] = ExportReference(id, objIndex); + } + } + stream.alignData(PX_SERIAL_ALIGN); + stream.writeData(&nbIds, sizeof(PxU32)); + stream.writeData(exportReferences.begin(), exportReferences.size()*sizeof(ExportReference)); + } + + // write internal references + { + InternalRefMap& internalReferencesPtrMap = context.getInternalReferencesPtrMap(); + Ps::Array<InternalReferencePtr> internalReferencesPtr(internalReferencesPtrMap.size()); + PxU32 nbInternalPtrReferences = 0; + for(InternalRefMap::Iterator iter = internalReferencesPtrMap.getIterator(); !iter.done(); ++iter) + internalReferencesPtr[nbInternalPtrReferences++] = InternalReferencePtr(iter->first.first, iter->first.second, iter->second); + + InternalRefMap& internalReferencesIdxMap = context.getInternalReferencesIdxMap(); + Ps::Array<InternalReferenceIdx> internalReferencesIdx(internalReferencesIdxMap.size()); + PxU32 nbInternalIdxReferences = 0; + for(InternalRefMap::Iterator iter = internalReferencesIdxMap.getIterator(); !iter.done(); ++iter) + internalReferencesIdx[nbInternalIdxReferences++] = InternalReferenceIdx(Ps::to32(iter->first.first), iter->first.second, iter->second); + + stream.alignData(PX_SERIAL_ALIGN); + + stream.writeData(&nbInternalPtrReferences, sizeof(PxU32)); + stream.writeData(internalReferencesPtr.begin(), internalReferencesPtr.size()*sizeof(InternalReferencePtr)); + + stream.writeData(&nbInternalIdxReferences, sizeof(PxU32)); + stream.writeData(internalReferencesIdx.begin(), internalReferencesIdx.size()*sizeof(InternalReferenceIdx)); + } + + // write object data + { + stream.alignData(PX_SERIAL_ALIGN); + const PxU32 nb = collection.internalGetNbObjects(); + for(PxU32 i=0;i<nb;i++) + { + PxBase* s = collection.internalGetObject(i); + PX_ASSERT(s && s->getConcreteType()); + const PxSerializer* serializer = sn.getSerializer(s->getConcreteType()); + PX_ASSERT(serializer); + stream.alignData(PX_SERIAL_ALIGN); + serializer->exportData(*s, stream); + } + } + + // write extra data + { + const PxU32 nb = collection.internalGetNbObjects(); + for(PxU32 i=0;i<nb;i++) + { + PxBase* s = collection.internalGetObject(i); + PX_ASSERT(s && s->getConcreteType()); + + const PxSerializer* serializer = sn.getSerializer(s->getConcreteType()); + PX_ASSERT(serializer); + + stream.alignData(PX_SERIAL_ALIGN); + serializer->exportExtraData(*s, stream); + } + } + + return true; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.cpp new file mode 100644 index 00000000..ad486c2d --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.cpp @@ -0,0 +1,156 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +/* +- get rid of STL + +- NpArticulationLinkArray with more than 4 entries +- big convexes Xbox => PC + +- put a cache in "convertClass" function +- remove MD one at a time and check what happens in the converter. Make it robust/report errors +- for xbox, compare against source xbox file if it exists +- maybe put some info in the header to display "File generated by ConvX 1.xx" on screen (to debug) +- report inconsistent naming convention in each class!!!! +- try to automatically discover padding bytes? use "0xcd" pattern? +* do last param of XXXX_ITEMS macro automatically +- what if source files are 64bits? can we safely convert a 64bit ptr to 32bit? +*/ + +#include "foundation/PxErrorCallback.h" +#include "foundation/PxAllocatorCallback.h" +#include "foundation/PxIO.h" +#include "SnConvX.h" +#include "serialization/SnSerializationRegistry.h" +#include <assert.h> +#include "PsFoundation.h" + +using namespace physx; + +Sn::ConvX::ConvX() : + mMetaData_Src (NULL), + mMetaData_Dst (NULL), + mOutStream (NULL), + mMustFlip (false), + mOutputSize (0), + mSrcPtrSize (0), + mDstPtrSize (0), + mNullPtr (false), + mNoOutput (false), + mMarkedPadding (false), + mNbErrors (0), + mNbWarnings (0), + mReportMode (PxConverterReportMode::eNORMAL), + mPerformConversion (true) +{ + // memset(mZeros, 0, CONVX_ZERO_BUFFER_SIZE); + memset(mZeros, 0x42, CONVX_ZERO_BUFFER_SIZE); +} + +Sn::ConvX::~ConvX() +{ + resetNbErrors(); + resetConvexFlags(); + releaseMetaData(); + resetUnions(); +} + +void Sn::ConvX::release() +{ + delete this; +} + +bool Sn::ConvX::setMetaData(PxInputStream& inputStream, MetaDataType type) +{ + resetNbErrors(); + return (loadMetaData(inputStream, type) != NULL); +} + +bool Sn::ConvX::setMetaData(PxInputStream& srcMetaData, PxInputStream& dstMetaData) +{ + releaseMetaData(); + resetUnions(); + + if(!setMetaData(srcMetaData, META_DATA_SRC)) + return false; + if(!setMetaData(dstMetaData, META_DATA_DST)) + return false; + + return true; +} + + +bool Sn::ConvX::convert(PxInputStream& srcStream, PxU32 srcSize, PxOutputStream& targetStream) +{ + if(!mMetaData_Src || !mMetaData_Dst) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, + "PxBinaryConverter: metadata not defined. Call PxBinaryConverter::setMetaData first.\n"); + return false; + } + + resetConvexFlags(); + resetNbErrors(); + + bool conversionStatus = false; + if(mPerformConversion) + { + if(srcSize == 0) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "PxBinaryConverter: source serialized data size is zero.\n"); + return false; + } + + void* memory = PX_ALLOC_TEMP(srcSize+ALIGN_FILE, "ConvX source file"); + void* memoryA = reinterpret_cast<void*>((size_t(memory) + ALIGN_FILE)&~(ALIGN_FILE-1)); + + const PxU32 nbBytesRead = srcStream.read(memoryA, srcSize); + if(nbBytesRead != srcSize) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "PxBinaryConverter: failure on reading source serialized data.\n"); + PX_FREE(memory); + return false; + } + + displayMessage(PxErrorCode::eDEBUG_INFO, "\n\nConverting...\n\n"); + + { + if(!initOutput(targetStream)) + { + PX_FREE(memory); + return false; + } + conversionStatus = convert(memoryA, int(srcSize)); + closeOutput(); + } + + PX_FREE(memory); + } + return conversionStatus; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.h new file mode 100644 index 00000000..9ce9d86f --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.h @@ -0,0 +1,182 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PX_CONVX_H +#define PX_CONVX_H + +#include "foundation/PxErrors.h" +#include "PxBinaryConverter.h" +#include "PxTypeInfo.h" +#include "CmPhysXCommon.h" +#include "PsUserAllocated.h" +#include "PsArray.h" +#include "SnConvX_Common.h" +#include "SnConvX_Union.h" +#include "SnConvX_MetaData.h" +#include "SnConvX_Align.h" + +#define CONVX_ZERO_BUFFER_SIZE 256 + +namespace physx { + +class PxSerializationRegistry; + +namespace Sn { + + struct HeightFieldData; + class PointerRemap + { + public: + PointerRemap(); + ~PointerRemap(); + + bool checkRefIsNotUsed(PxU32 ref) const; + void setObjectRef(PxU64 object64, PxU32 ref); + bool getObjectRef(PxU64 object64, PxU32& ref) const; + + struct InternalData + { + PxU64 object; + PxU32 id; + }; + + Ps::Array<InternalData> mData; + }; + + class ConvX : public physx::PxBinaryConverter, public shdfnd::UserAllocated + { + public: + ConvX(); + virtual ~ConvX(); + + virtual void release(); + virtual void setReportMode(PxConverterReportMode::Enum mode) { mReportMode = mode; } + PX_FORCE_INLINE bool silentMode() const { return mReportMode==PxConverterReportMode::eNONE; } + PX_FORCE_INLINE bool verboseMode() const { return mReportMode==PxConverterReportMode::eVERBOSE; } + + virtual bool setMetaData(PxInputStream& srcMetaData, PxInputStream& dstMetaData); + virtual bool convert(PxInputStream& srcStream, PxU32 srcSize, PxOutputStream& targetStream); + + private: + ConvX& operator=(const ConvX&); + bool setMetaData(PxInputStream& inputStream, MetaDataType type); + + // Meta-data + void releaseMetaData(); + const MetaData* loadMetaData(PxInputStream& inputStream, MetaDataType type); + const MetaData* getBinaryMetaData(MetaDataType type); + int getNbMetaClasses(MetaDataType type); + MetaClass* getMetaClass(unsigned int i, MetaDataType type) const; + MetaClass* getMetaClass(const char* name, MetaDataType type) const; + MetaClass* getMetaClass(PxConcreteType::Enum concreteType, MetaDataType type); + MetaData* mMetaData_Src; + MetaData* mMetaData_Dst; + + // Convert + + bool convert(const void* buffer, int fileSize); + void resetConvexFlags(); + void _enumerateFields(const MetaClass* mc, ExtraDataEntry2* entries, int& nb, int baseOffset, MetaDataType type) const; + void _enumerateExtraData(const char* address, const MetaClass* mc, ExtraDataEntry* entries, int& nb, int offset, MetaDataType type) const; + PxU64 read64(const void*& buffer); + int read32(const void*& buffer); + short read16(const void*& buffer); + bool convertClass(const char* buffer, const MetaClass* mc, int offset); + const char* convertExtraData_Array(const char* Address, const char* lastAddress, const char* objectAddress, const ExtraDataEntry& ed); + const char* convertExtraData_Ptr(const char* Address, const char* lastAddress, const PxMetaDataEntry& entry, int count, int ptrSize_Src, int ptrSize_Dst); + int getConcreteType(const char* buffer); + bool convertCollection(const void* buffer, int fileSize, int nbObjects); + const void* convertManifestTable(const void* buffer, int& fileSize); + const void* convertImportReferences(const void* buffer, int& fileSize); + const void* convertExportReferences(const void* buffer, int& fileSize); + const void* convertInternalReferences(const void* buffer, int& fileSize); + const void* convertReferenceTables(const void* buffer, int& fileSize, int& nbObjectsInCollection); + bool checkPaddingBytes(const char* buffer, int byteCount); + + // ---- big convex surgery ---- + PsArray<bool> mConvexFlags; + // Align + const char* alignStream(const char* buffer, int alignment=ALIGN_DEFAULT); + void alignTarget(int alignment); + + char mZeros[CONVX_ZERO_BUFFER_SIZE]; + // Unions + bool registerUnion(const char* name); + bool registerUnionType(const char* unionName, const char* typeName, int typeValue); + const char* getTypeName(const char* unionName, int typeValue); + void resetUnions(); + PsArray<Union> mUnions; + // Output + void setNullPtr(bool); + void setNoOutput(bool); + bool initOutput(PxOutputStream& targetStream); + void closeOutput(); + int getCurrentOutputSize(); + void output(short value); + void output(int value); + void output(PxU64 value); + void output(const char* buffer, int nbBytes); + void convert8 (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry); + void convertPad8 (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry); + void convert16 (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry); + void convert32 (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry); + void convert64 (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry); + void convertFloat(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry); + void convertPtr (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry); + PxOutputStream* mOutStream; + bool mMustFlip; + int mOutputSize; + int mSrcPtrSize; + int mDstPtrSize; + bool mNullPtr; + bool mNoOutput; + bool mMarkedPadding; + + // Errors + void resetNbErrors(); + int getNbErrors() const; + void displayMessage(physx::PxErrorCode::Enum code, const char* format, ...); + int mNbErrors; + int mNbWarnings; + + // Settings + PxConverterReportMode::Enum mReportMode; + bool mPerformConversion; + + // Remap pointers + void exportIntAsPtr(int value); + void exportInt(int value); + void exportInt64(PxU64 value); + PointerRemap mRemap; + PointerRemap* mActiveRemap; + PxU32 mPointerRemapCounter; + + friend class MetaData; + friend struct MetaClass; + }; +} } +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.cpp new file mode 100644 index 00000000..5c576f5c --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.cpp @@ -0,0 +1,63 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#include "SnConvX.h" +#include "SnConvX_Align.h" +#include <assert.h> +using namespace physx; + +void Sn::ConvX::alignTarget(int alignment) +{ + const int outputSize = getCurrentOutputSize(); + const PxU32 outPadding = getPadding(size_t(outputSize), PxU32(alignment)); + if(outPadding) + { + assert(outPadding<CONVX_ZERO_BUFFER_SIZE); + output(mZeros, int(outPadding)); + } +} + +const char* Sn::ConvX::alignStream(const char* buffer, int alignment) +{ + const PxU32 padding = getPadding(size_t(buffer), PxU32(alignment)); + assert(!getPadding(size_t(buffer + padding), PxU32(alignment))); + + const int outputSize = getCurrentOutputSize(); + const PxU32 outPadding = getPadding(size_t(outputSize), PxU32(alignment)); + if(outPadding==padding) + { + assert(outPadding<CONVX_ZERO_BUFFER_SIZE); + output(mZeros, int(outPadding)); + } + else if(outPadding) + { + assert(outPadding<CONVX_ZERO_BUFFER_SIZE); + output(mZeros, int(outPadding)); + } + + return buffer + padding; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.h new file mode 100644 index 00000000..b3ec81c2 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.h @@ -0,0 +1,44 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PX_CONVX_ALIGN_H +#define PX_CONVX_ALIGN_H + +namespace physx { namespace Sn { + #define ALIGN_DEFAULT 16 + #define ALIGN_FILE 128 + + PX_INLINE PxU32 getPadding(size_t value, PxU32 alignment) + { + const PxU32 mask = alignment-1; + const PxU32 overhead = PxU32(value) & mask; + return (alignment - overhead) & mask; + } + +} } + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Common.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Common.h new file mode 100644 index 00000000..677480e4 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Common.h @@ -0,0 +1,43 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PX_CONVX_COMMON_H +#define PX_CONVX_COMMON_H + +#if PX_VC +#pragma warning(disable:4121) // alignment of a member was sensitive to packing +#endif + +#include "common/PxPhysXCommonConfig.h" + +#define DELETESINGLE(x) if(x){ delete x; x = NULL; } +#define DELETEARRAY(x) if(x){ delete []x; x = NULL; } + +#define inline_ PX_FORCE_INLINE +#define PsArray physx::shdfnd::Array + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Convert.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Convert.cpp new file mode 100644 index 00000000..a9fe0b9c --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Convert.cpp @@ -0,0 +1,1434 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#include "foundation/PxErrorCallback.h" +#include "SnConvX.h" +#include "serialization/SnSerialUtils.h" +#include "PsAlloca.h" +#include "CmUtils.h" +#include "PxDefaultStreams.h" +#include <assert.h> + +using namespace physx; +using namespace physx::Sn; +using namespace Cm; + +void Sn::ConvX::resetConvexFlags() +{ + mConvexFlags.clear(); +} + +void Sn::ConvX::_enumerateFields(const MetaClass* mc, ExtraDataEntry2* entries, int& nb, int baseOffset, MetaDataType type) const +{ + PxU32 nbFields = mc->mFields.size(); + int offsetCheck = baseOffset; + for(PxU32 j=0;j<nbFields;j++) + { + const PxMetaDataEntry& entry = mc->mFields[j]; + if(entry.mFlags & PxMetaDataFlag::eCLASS || entry.mFlags & PxMetaDataFlag::eEXTRA_DATA) + continue; + + assert(offsetCheck == baseOffset + entry.mOffset); + + int currentOffset = baseOffset + entry.mOffset; + + //for(int c=0;c<entry.mCount;c++) + { + if(entry.mFlags & PxMetaDataFlag::eUNION) + { + entries[nb].entry = entry; + entries[nb].offset = currentOffset; + entries[nb].cb = 0; + nb++; + } + else if(entry.mFlags & PxMetaDataFlag::ePTR) // This also takes care of the vtable pointer + { + entries[nb].entry = entry; + entries[nb].offset = currentOffset; + entries[nb].cb = &Sn::ConvX::convertPtr; + nb++; + } + else + { + MetaClass* fieldType = getMetaClass(entry.mType, type); + assert(fieldType); + if(fieldType->mCallback) + { + entries[nb].entry = entry; + entries[nb].offset = currentOffset; + entries[nb].cb = fieldType->mCallback; + nb++; + } + else + { + for(int c=0;c<entry.mCount;c++) + { + _enumerateFields(fieldType, entries, nb, currentOffset, type); + currentOffset += entry.mSize/entry.mCount; + } + } + } + } + offsetCheck += entry.mSize; + } +} + +void Sn::ConvX::_enumerateExtraData(const char* address, const MetaClass* mc, ExtraDataEntry* entries, + int& nb, int offset, MetaDataType type) const +{ + PxU32 nbFields = mc->mFields.size(); + for(PxU32 j=0;j<nbFields;j++) + { + const PxMetaDataEntry& entry = mc->mFields[j]; + if(entry.mFlags & PxMetaDataFlag::eCLASS /*|| entry.mFlags & PxMetaDataFlag::ePTR*/ || entry.mFlags & PxMetaDataFlag::eTYPEDEF) + continue; + + const char* entryType = entry.mType; + + // + // Insanely Twisted Shadow GeometryUnion + // + // Special code is needed as long as there are no meta data tags to describe our unions properly. The way it is done here is + // not future-proof at all. There should be a tag to describe where the union type can be found and the number of bytes + // this type id needs. Then a mapping needs to get added from each union type id to the proper meta class name. + // + if (entry.mFlags & PxMetaDataFlag::eUNION) + { + if (!mc->mClassName || strcmp(mc->mClassName, "Gu::GeometryUnion")!=0) + continue; + else + { + // ### hardcoded bit here, will only work when union type is the first int of the struct + const int* tmp = reinterpret_cast<const int*>(address + offset); + const int unionType = *tmp; + + ConvX* tmpConv = const_cast<ConvX*>(this); // ... don't ask + const char* typeName = tmpConv->getTypeName(entry.mType, unionType); + assert(typeName); + + bool isTriMesh = (strcmp(typeName, "PxTriangleMeshGeometryLL") == 0); + bool isHeightField = (strcmp(typeName, "PxHeightFieldGeometryLL") == 0); + if (!isTriMesh && !isHeightField) + { + continue; + } + else + { + entryType = typeName; + } + } + } + + // MetaClass* extraDataType = getMetaClass(entry.mType, type); + // if(!extraDataType) + // continue; + + if(entry.mFlags & PxMetaDataFlag::eEXTRA_DATA) + { + entries[nb].entry = entry; + entries[nb].offset = offset+entry.mOffset; + nb++; + } + else + { + if(entry.mFlags & PxMetaDataFlag::ePTR) + continue; + + MetaClass* extraDataType = getMetaClass(entryType, type); + if(!extraDataType) + continue; + + if(!extraDataType->mCallback) + _enumerateExtraData(address, extraDataType, entries, nb, offset+entry.mOffset, type); + } + } +} + +PxU64 Sn::ConvX::read64(const void*& buffer) +{ + const PxU64* buf64 = reinterpret_cast<const PxU64*>(buffer); + buffer = reinterpret_cast<const void*>(size_t(buffer) + sizeof(PxU64)); + PxU64 value = *buf64; + output(value); + return value; +} + +int Sn::ConvX::read32(const void*& buffer) +{ + const int* buf32 = reinterpret_cast<const int*>(buffer); + buffer = reinterpret_cast<const void*>(size_t(buffer) + sizeof(int)); + int value = *buf32; + output(value); + return value; +} + +short Sn::ConvX::read16(const void*& buffer) +{ + const short* buf16 = reinterpret_cast<const short*>(buffer); + buffer = reinterpret_cast<const void*>(size_t(buffer) + sizeof(short)); + short value = *buf16; + output(value); + return value; +} + +#if PX_CHECKED +extern const char* gVTable; +static bool compareEntries(const ExtraDataEntry2& e0, const ExtraDataEntry2& e1) +{ + if(e0.entry.isVTablePtr() && e1.entry.isVTablePtr()) + return true; + + if((e0.entry.mFlags & PxMetaDataFlag::eUNION) && (e1.entry.mFlags & PxMetaDataFlag::eUNION)) + { + if(e0.entry.mType && e1.entry.mType) + { + // We can't compare the ptrs since they index different string tables + if(strcmp(e0.entry.mType, e1.entry.mType)==0) + return true; + } + return false; + } + + if(e0.entry.mName && e1.entry.mName) + { + // We can't compare the ptrs since they index different string tables + if(strcmp(e0.entry.mName, e1.entry.mName)==0) + return true; + } + return false; +} +#endif + +// TODO: optimize this +bool Sn::ConvX::convertClass(const char* buffer, const MetaClass* mc, int offset) +{ + // ---- big convex surgery ---- + bool convexSurgery = false; + bool foundNbVerts = false; + bool removeBigData = false; + + // force reference + (void)foundNbVerts; + + displayMessage(PxErrorCode::eDEBUG_INFO, "%s\n", mc->mClassName); + displayMessage(PxErrorCode::eDEBUG_INFO, "+++++++++++++++++++++++++++++++++++++++++++++\n"); + + if(strcmp(mc->mClassName, "ConvexMesh")==0) + { + convexSurgery = true; + } + // ---- big convex surgery ---- + + int nbSrcEntries = 0; + PX_ALLOCA(srcEntries, ExtraDataEntry2, 256); // ### painful ctors here + int nbDstEntries = 0; + PX_ALLOCA(dstEntries, ExtraDataEntry2, 256); // ### painful ctors here + // Find corresponding meta-class for target platform + const MetaClass* target_mc = getMetaClass(mc->mClassName, META_DATA_DST); + assert(target_mc); + + if(mc->mCallback) + { + srcEntries[0].cb = mc->mCallback; + srcEntries[0].offset = offset; + srcEntries[0].entry.mType = mc->mClassName; + srcEntries[0].entry.mName = mc->mClassName; + srcEntries[0].entry.mOffset = offset; + srcEntries[0].entry.mSize = mc->mSize; + srcEntries[0].entry.mCount = 1; + srcEntries[0].entry.mFlags = 0; + nbSrcEntries = 1; + + assert(target_mc->mCallback); + dstEntries[0].cb = target_mc->mCallback; + dstEntries[0].offset = offset; + dstEntries[0].entry.mType = target_mc->mClassName; + dstEntries[0].entry.mName = target_mc->mClassName; + dstEntries[0].entry.mOffset = offset; + dstEntries[0].entry.mSize = target_mc->mSize; + dstEntries[0].entry.mCount = 1; + dstEntries[0].entry.mFlags = 0; + nbDstEntries = 1; + } + else + { + nbSrcEntries = 0; + _enumerateFields(mc, srcEntries, nbSrcEntries, 0, META_DATA_SRC); + assert(nbSrcEntries<256); + + nbDstEntries = 0; + _enumerateFields(target_mc, dstEntries, nbDstEntries, 0, META_DATA_DST); + assert(nbDstEntries<256); + + // nb = mc->mNbEntries; + // assert(nb>=0); + // memcpy(entries, mc->mEntries, nb*sizeof(ExtraDataEntry2)); + } + + int srcOffsetCheck = 0; + int dstOffsetCheck = 0; + int j = 0; + // Track cases where the vtable pointer location is different for different platforms. + // The variables indicate whether a platform has a vtable pointer entry that has not been converted yet + // and they will remember the index of the corrssponding entry. This works because there can only + // be one open vtable pointer entry at a time. + int srcOpenVTablePtrEntry = -1; + int dstOpenVTablePtrEntry = -1; + + //if the src and dst platform place the vtable pointers at different locations some fiddling with the iteration count can be necessary. + int addVTablePtrShiftIteration = 0; + const int maxNb = nbSrcEntries > nbDstEntries ? nbSrcEntries : nbDstEntries; + for(int i=0; i < (maxNb + addVTablePtrShiftIteration); i++) + { + + if (i < nbSrcEntries) + { + displayMessage(PxErrorCode::eDEBUG_INFO, "\t0x%p\t%x\t%d\t%d\t%s", buffer + srcOffsetCheck, + buffer[srcOffsetCheck], srcOffsetCheck, srcEntries[i].entry.mOffset, srcEntries[i].entry.mName); + for (int byteCount = 1; byteCount < srcEntries[i].entry.mSize; ++byteCount) + displayMessage(PxErrorCode::eDEBUG_INFO, "\t0x%p\t%x\t%d\t%d\t.", buffer + srcOffsetCheck + byteCount, + buffer[srcOffsetCheck + byteCount], srcOffsetCheck + byteCount, srcEntries[i].entry.mOffset + byteCount); + } + + bool handlePadding = true; + bool skipLoop = false; + while(handlePadding) + { + const int pad0 = i<nbSrcEntries ? srcEntries[i].entry.mFlags & PxMetaDataFlag::ePADDING : 0; + const int pad1 = j<nbDstEntries ? dstEntries[j].entry.mFlags & PxMetaDataFlag::ePADDING : 0; + if(pad0 || pad1) + { + if(pad0) + { +#if PX_CHECKED + if (mMarkedPadding && (strcmp(srcEntries[i].entry.mType, "paddingByte")==0)) + if(!checkPaddingBytes(buffer + srcOffsetCheck, srcEntries[i].entry.mSize)) + { + if(i>0) + { + displayMessage(PxErrorCode::eDEBUG_WARNING, + "PxBinaryConverter warning: Bytes after %s::%s don't look like padding bytes. Likely mismatch between binary data and metadata.\n", + mc->mClassName, srcEntries[i-1].entry.mName ); + } + else + displayMessage(PxErrorCode::eDEBUG_WARNING, + "PxBinaryConverter warning: Bytes after %s don't look like padding bytes. Likely mismatch between binary data and metadata.\n", + mc->mClassName); + + } +#endif + if(pad1) + { + // Both have padding + // ### check sizes, output bytes + if(srcEntries[i].entry.mSize==dstEntries[j].entry.mSize) + { + // I guess we can just go on with the normal code here + handlePadding = false; + } + else + { + // Output padding + assert(srcEntries[i].cb); + assert(srcEntries[i].offset == srcOffsetCheck); + + const int padSize = dstEntries[j].entry.mSize; + char* paddingBytes = reinterpret_cast<char*>(PX_ALLOC(sizeof(char)*padSize, "paddingByte")); + memset(paddingBytes, 0, size_t(padSize)); + assert(dstEntries[j].cb); + (this->*dstEntries[j].cb)(paddingBytes, dstEntries[j].entry, dstEntries[j].entry); + assert(dstOffsetCheck==dstEntries[j].offset); + dstOffsetCheck += padSize; + PX_FREE(paddingBytes); + + // srcEntries[i].cb(buffer+srcOffsetCheck, srcEntries[i].entry, dstEntries[j].entry); + // assert(dstOffsetCheck==dstEntries[j].offset); + // dstOffsetCheck += dstEntries[j].entry.mSize; + srcOffsetCheck += srcEntries[i].entry.mSize; + + // Skip dest padding field + j++; + + // continue; // ### BUG, doesn't go back to the "for" + skipLoop = true; + handlePadding = false; + } + } + else + { + // Src has padding, dst has not => skip conversion + // Don't increase j + skipLoop = true; + handlePadding = false; + srcOffsetCheck += srcEntries[i].entry.mSize; + } + } + else + { + if(pad1) + { + // Dst has padding, src has not + + // Output padding + const int padSize = dstEntries[j].entry.mSize; + char* paddingBytes = reinterpret_cast<char*>(PX_ALLOC(sizeof(char)*padSize, "paddingByte")); + memset(paddingBytes, 0, size_t(padSize)); + assert(dstEntries[j].cb); + (this->*dstEntries[j].cb)(paddingBytes, dstEntries[j].entry, dstEntries[j].entry); + assert(dstOffsetCheck==dstEntries[j].offset); + dstOffsetCheck += padSize; + PX_FREE(paddingBytes); + + // Skip dest padding field, keep same src field + j++; + } + else + { + assert(0); + } + } + } + else handlePadding = false; + } + + if(skipLoop) + continue; + + int modSrcOffsetCheck = srcOffsetCheck; + const ExtraDataEntry2* srcEntryPtr = &srcEntries[i]; + const ExtraDataEntry2* dstEntryPtr = &dstEntries[j]; + + bool isSrcVTablePtr = (i < nbSrcEntries) ? srcEntryPtr->entry.isVTablePtr() : false; + if (isSrcVTablePtr && (dstOpenVTablePtrEntry != -1)) + { + // vtable ptr position mismatch: + // this check is necessary to align src and dst index again when the + // dst vtable pointer has been written already and the src vtable ptr + // element is reached. + // + // i + // src: | a | b | vt-ptr | c | ... + // dst: | vt-ptr | a | b | c | ... + // j + // + // it needs special treatment because the following case fails otherwise + // i + // src: | a | b | vt-ptr | c | vt-ptr | ... + // dst: | vt-ptr | a | b | vt-ptr | c | ... + // j + + // + // This entry has been written already -> advance to next src entry + // + srcOffsetCheck += srcEntryPtr->entry.mSize; + i++; + isSrcVTablePtr = (i < nbSrcEntries) ? srcEntryPtr->entry.isVTablePtr() : false; + PX_ASSERT(dstOpenVTablePtrEntry < nbDstEntries); + PX_ASSERT(dstEntries[dstOpenVTablePtrEntry].entry.isVTablePtr()); + dstOpenVTablePtrEntry = -1; + PX_ASSERT(addVTablePtrShiftIteration == 0); + } + bool isDstVTablePtr = (j < nbDstEntries) ? dstEntryPtr->entry.isVTablePtr() : false; + if (isDstVTablePtr && (srcOpenVTablePtrEntry != -1)) + { + // i + // src: | vt-ptr | a | b | c | ... + // dst: | a | b | vt-ptr | c | ... + // j + + i--; // next iteration the current element should get processed + isSrcVTablePtr = true; + PX_ASSERT(srcOpenVTablePtrEntry < nbSrcEntries); + srcEntryPtr = &srcEntries[srcOpenVTablePtrEntry]; + PX_ASSERT(srcEntryPtr->entry.isVTablePtr()); + modSrcOffsetCheck = srcEntryPtr->offset; + srcOffsetCheck -= srcEntryPtr->entry.mSize; // to make sure total change is 0 after this iteration + srcOpenVTablePtrEntry = -1; + PX_ASSERT(addVTablePtrShiftIteration == 1); + addVTablePtrShiftIteration = 0; + } + + if(i==nbSrcEntries && j==nbDstEntries) + { + PX_ASSERT((srcOpenVTablePtrEntry == -1) && (dstOpenVTablePtrEntry == -1)); + break; + } + + if (isSrcVTablePtr || isDstVTablePtr) + { + if (!isSrcVTablePtr) + { + // i + // src: | a | b | vt-ptr | c | ... + // dst: | vt-ptr | a | b | c | ... + // j + + PX_ASSERT(dstOpenVTablePtrEntry == -1); // the other case should be detected and treated earlier + PX_ASSERT(srcOpenVTablePtrEntry == -1); + PX_ASSERT(addVTablePtrShiftIteration == 0); + + int k; + for(k=i+1; k < nbSrcEntries; k++) + { + if (srcEntries[k].entry.isVTablePtr()) + break; + } + PX_ASSERT(k < nbSrcEntries); + + srcEntryPtr = &srcEntries[k]; + modSrcOffsetCheck = srcEntryPtr->offset; + srcOffsetCheck -= srcEntryPtr->entry.mSize; // to make sure total change is 0 after this iteration + + dstOpenVTablePtrEntry = j; + i--; // to make sure the original entry gets processed in the next iteration + } + else if (!isDstVTablePtr) + { + // i ---> i + // src: | vt-ptr | a | b | c | ... + // dst: | a | b | vt-ptr | c | ... + // j + + PX_ASSERT(srcOpenVTablePtrEntry == -1); // the other case should be detected and treated earlier + PX_ASSERT(dstOpenVTablePtrEntry == -1); + PX_ASSERT(addVTablePtrShiftIteration == 0); + + srcOffsetCheck += srcEntryPtr->entry.mSize; + modSrcOffsetCheck = srcOffsetCheck; + srcOpenVTablePtrEntry = i; + i++; + srcEntryPtr = &srcEntries[i]; + + addVTablePtrShiftIteration = 1; // additional iteration might be needed to process vtable pointer at the end of a class + + PX_ASSERT((i < nbSrcEntries) && ((srcEntryPtr->entry.mFlags & PxMetaDataFlag::ePADDING) == 0)); + // if the second check fails, this whole section might have to be done before the padding bytes get processed. Not sure + // what other consequences that might have though. + } + } +#if PX_CHECKED + else + { + if(!compareEntries(*srcEntryPtr, *dstEntryPtr)) + { + displayMessage(PxErrorCode::eINVALID_PARAMETER, "\rConvX::convertClass: %s, src meta data and dst meta data don't match!", mc->mClassName); + return false; + } + } +#endif + + const ExtraDataEntry2& srcEntry = *srcEntryPtr; + const ExtraDataEntry2& dstEntry = *dstEntryPtr; + + if(srcEntry.entry.mFlags & PxMetaDataFlag::eUNION) + { + // ### hardcoded bit here, will only work when union type is the first int of the struct + const int* tmp = reinterpret_cast<const int*>(buffer + modSrcOffsetCheck); + const int unionType = *tmp; + + const char* typeName = getTypeName(srcEntry.entry.mType, unionType); + assert(typeName); + + MetaClass* unionMC = getMetaClass(typeName, META_DATA_SRC); + assert(unionMC); + + convertClass(buffer + modSrcOffsetCheck, unionMC, 0); // ### recurse + + dstOffsetCheck += dstEntry.entry.mSize; + + MetaClass* targetUnionMC = getMetaClass(typeName, META_DATA_DST); + assert(targetUnionMC); + + const int delta = dstEntry.entry.mSize - targetUnionMC->mSize; + char* deltaBytes = reinterpret_cast<char*>(PX_ALLOC(sizeof(char)*delta, "deltaBytes")); + memset(deltaBytes, 0, size_t(delta)); + output(deltaBytes, delta); // Skip unused bytes at the end of the union + PX_FREE(deltaBytes); + srcOffsetCheck += srcEntry.entry.mSize; // do not use modSrcOffsetCheck here! + } + else + { + assert(srcEntry.cb); + assert(srcEntry.offset == modSrcOffsetCheck); + + // ---- big convex surgery ---- + if(convexSurgery) + { + if(strcmp(srcEntry.entry.mName, "mNbHullVertices")==0) + { + assert(srcEntry.entry.mSize==1); + const int nbVerts = int(*(buffer+modSrcOffsetCheck)); + assert(!foundNbVerts); + foundNbVerts = true; + + const int gaussMapLimit = getBinaryMetaData(META_DATA_DST)->getGaussMapLimit(); + if(nbVerts > gaussMapLimit) + { + // We need a gauss map and we have one => keep it + } + else + { + // We don't need a gauss map and we have one => remove it + removeBigData = true; + } + } + else + { + if(removeBigData) + { + const bool isBigConvexData = strcmp(srcEntry.entry.mType, "BigConvexData")==0 || + strcmp(srcEntry.entry.mType, "BigConvexRawData")==0; + if(isBigConvexData) + { + assert(foundNbVerts); + setNullPtr(true); + } + } + } + } + // ---- big convex surgery ---- + + (this->*srcEntry.cb)(buffer+modSrcOffsetCheck, srcEntry.entry, dstEntry.entry); + assert(dstOffsetCheck==dstEntry.offset); + dstOffsetCheck += dstEntry.entry.mSize; + srcOffsetCheck += srcEntry.entry.mSize; // do not use modSrcOffsetCheck here! + + // ---- big convex surgery ---- + if(convexSurgery && removeBigData) + setNullPtr(false); + // ---- big convex surgery ---- + } + + j++; + } + + displayMessage(PxErrorCode::eDEBUG_INFO, "---------------------------------------------\n"); + + while(j<nbDstEntries) + { + assert(dstEntries[j].entry.mFlags & PxMetaDataFlag::ePADDING); + if(dstEntries[j].entry.mFlags & PxMetaDataFlag::ePADDING) + { + dstOffsetCheck += dstEntries[j].entry.mSize; + } + j++; + } + + assert(j==nbDstEntries); + assert(dstOffsetCheck==target_mc->mSize); + assert(srcOffsetCheck==mc->mSize); + + // ---- big convex surgery ---- + if(convexSurgery) + mConvexFlags.pushBack(removeBigData); + // ---- big convex surgery ---- + + return true; +} + +// Handles data defined with PX_DEF_BIN_METADATA_EXTRA_ARRAY +const char* Sn::ConvX::convertExtraData_Array(const char* Address, const char* lastAddress, const char* objectAddress, + const ExtraDataEntry& ed) +{ + (void)lastAddress; + MetaClass* mc = getMetaClass(ed.entry.mType, META_DATA_SRC); + assert(mc); + + // PT: safe to cast to int here since we're reading a count. + const int count = int(peek(ed.entry.mSize, objectAddress + ed.offset, ed.entry.mFlags)); + + // if(ed.entry.mCount) // Reused as align value + if(ed.entry.mAlignment) + { + Address = alignStream(Address, ed.entry.mAlignment); + // Address = alignStream(Address, ed.entry.mCount); + assert(Address<=lastAddress); + } + + for(int c=0;c<count;c++) + { + convertClass(Address, mc, 0); + Address += mc->mSize; + assert(Address<=lastAddress); + } + return Address; +} + +const char* Sn::ConvX::convertExtraData_Ptr(const char* Address, const char* lastAddress, const PxMetaDataEntry& entry, int count, + int ptrSize_Src, int ptrSize_Dst) +{ + (void)lastAddress; + + PxMetaDataEntry tmpSrc = entry; + tmpSrc.mCount = count; + tmpSrc.mSize = count * ptrSize_Src; + + PxMetaDataEntry tmpDst = entry; + tmpDst.mCount = count; + tmpDst.mSize = count * ptrSize_Dst; + + + displayMessage(PxErrorCode::eDEBUG_INFO, "extra data ptrs\n"); + displayMessage(PxErrorCode::eDEBUG_INFO, "+++++++++++++++++++++++++++++++++++++++++++++\n"); + displayMessage(PxErrorCode::eDEBUG_INFO, "\t0x%p\t%x\t\t\t%s", Address, Address[0], entry.mName); + for (int byteCount = 1; byteCount < ptrSize_Src*count; ++byteCount) + displayMessage(PxErrorCode::eDEBUG_INFO, "\t0x%p\t%x\t\t\t.", Address + byteCount, Address[byteCount]); + + convertPtr(Address, tmpSrc, tmpDst); + Address += count * ptrSize_Src; + assert(Address<=lastAddress); + return Address; +} + +static bool decodeControl(PxU64 control, const ExtraDataEntry& ed, PxU64 controlMask = 0) +{ + if(ed.entry.mFlags & PxMetaDataFlag::eCONTROL_FLIP) + { + if(controlMask) + { + return (control & controlMask) ? false : true; + } + else + { + return control==0; + } + } + else + { + if(controlMask) + { + return (control & controlMask) ? true : false; + } + else + { + return control!=0; + } + } + +} + +// ### currently hardcoded, should change +int Sn::ConvX::getConcreteType(const char* buffer) +{ + MetaClass* mc = getMetaClass("PxBase", META_DATA_SRC); + assert(mc); + PxMetaDataEntry entry; + if(mc->getFieldByType("PxType", entry)) + { + // PT: safe to cast to int here since we're reading our own PxType + return int(peek(entry.mSize, buffer + entry.mOffset)); + } + assert(0); + return 0xffffffff; +} + +struct Item : public shdfnd::UserAllocated +{ + MetaClass* mc; + const char* address; +}; + +bool Sn::ConvX::convertCollection(const void* buffer, int fileSize, int nbObjects) +{ + const char* lastAddress = reinterpret_cast<const char*>(buffer) + fileSize; + const char* Address = alignStream(reinterpret_cast<const char*>(buffer)); + + const int ptrSize_Src = mSrcPtrSize; + const int ptrSize_Dst = mDstPtrSize; + Item* objects = PX_NEW(Item)[PxU32(nbObjects)]; + + for(PxU32 i=0;i<PxU32(nbObjects);i++) + { + const float percents = float(i)/float(nbObjects); + + displayMessage(PxErrorCode::eDEBUG_INFO, "Object conversion: %d%%", int(percents*100.0f)); + + Address = alignStream(Address); + assert(Address<=lastAddress); + + PxConcreteType::Enum classType = PxConcreteType::Enum(getConcreteType(Address)); + MetaClass* metaClass = getMetaClass(classType, META_DATA_SRC); + if(!metaClass) + { + PX_DELETE_ARRAY(objects); + return false; + } + + objects[i].mc = metaClass; + objects[i].address = Address; + + if(!convertClass(Address, metaClass, 0)) + { + PX_DELETE_ARRAY(objects); + return false; + } + + Address += metaClass->mSize; + assert(Address<=lastAddress); + } + + // Fields / extra data + if(1) + { + // ---- big convex surgery ---- + unsigned int nbConvexes = 0; + // ---- big convex surgery ---- + //const char* StartAddress2 = Address; + //int startDstSize2 = getCurrentOutputSize(); + for(int i=0;i<nbObjects;i++) + { + //const char* StartAddress = Address; + //int startDstSize = getCurrentOutputSize(); + + const float percents = float(i)/float(nbObjects); + + displayMessage(PxErrorCode::eDEBUG_INFO, "Extra data conversion: %d%%", int(percents*100.0f)); + + MetaClass* mc0 = objects[i].mc; + const char* objectAddress = objects[i].address; + + // printf("%d: %s\n", i, mc->mClassName); + // if(strcmp(mc->mClassName, "TriangleMesh")==0) + // if(strcmp(mc->mClassName, "NpRigidDynamic")==0) + if(strcmp(mc0->mClassName, "HybridModel")==0) + { + int stop=1; + (void)(stop); + } + + // ### we actually need to collect all extra data for this class, including data from embedded members. + + PX_ALLOCA(entries, ExtraDataEntry, 256); + int nbEntries = 0; + _enumerateExtraData(objectAddress, mc0, entries, nbEntries, 0, META_DATA_SRC); + assert(nbEntries<256); + + Address = alignStream(Address); + assert(Address<=lastAddress); + + for(int j=0;j<nbEntries;j++) + { + const ExtraDataEntry& ed = entries[j]; + assert(ed.entry.mFlags & PxMetaDataFlag::eEXTRA_DATA); + + if(ed.entry.mFlags & PxMetaDataFlag::eEXTRA_ITEM) + { + // ---- big convex surgery ---- + if(1) + { + const bool isBigConvexData = strcmp(ed.entry.mType, "BigConvexData")==0; + if(isBigConvexData) + { + assert(nbConvexes<mConvexFlags.size()); + if(mConvexFlags[nbConvexes++]) + setNoOutput(true); + } + } + // ---- big convex surgery ---- + + MetaClass* extraDataType = getMetaClass(ed.entry.mType, META_DATA_SRC); + assert(extraDataType); + + //sschirm: we used to have ed.entry.mOffset here, but that made cloth deserialization fail. + const char* controlAddress = objectAddress + ed.offset; + const PxU64 controlValue = peek(ed.entry.mOffsetSize, controlAddress); + + if(controlValue) + { + if(ed.entry.mAlignment) + { + Address = alignStream(Address, ed.entry.mAlignment); + assert(Address<=lastAddress); + } + + const char* classAddress = Address; + convertClass(Address, extraDataType, 0); + Address += extraDataType->mSize; + assert(Address<=lastAddress); + + // Enumerate extra data for this optional class, and convert it too. + // This assumes the extra data for the optional class is always appended to the class itself, + // which is something we'll need to enforce in the SDK. So far this is only to handle optional + // inline arrays. + + // ### this should probably be recursive eventually + PX_ALLOCA(entries2, ExtraDataEntry, 256); + int nbEntries2 = 0; + _enumerateExtraData(objectAddress, extraDataType, entries2, nbEntries2, 0, META_DATA_SRC); + assert(nbEntries2<256); + for(int k=0;k<nbEntries2;k++) + { + const ExtraDataEntry& ed2 = entries2[k]; + assert(ed2.entry.mFlags & PxMetaDataFlag::eEXTRA_DATA); + if(ed2.entry.mFlags & PxMetaDataFlag::eEXTRA_ITEMS) + { + const int controlOffset = ed2.entry.mOffset; + const int controlSize = ed2.entry.mSize; + const int countOffset = ed2.entry.mCount; + const int countSize = ed2.entry.mOffsetSize; + + const PxU64 controlValue2 = peek(controlSize, classAddress + controlOffset); + + PxU64 controlMask = 0; + if(ed2.entry.mFlags & PxMetaDataFlag::eCONTROL_MASK) + { + controlMask = PxU64(ed2.entry.mFlags & (PxMetaDataFlag::eCONTROL_MASK_RANGE << 16)); + controlMask = controlMask >> 16; + } + + if(decodeControl(controlValue2, ed2, controlMask)) + { + // PT: safe to cast to int here since we're reading a count + int count = int(peek(countSize, classAddress + countOffset, ed2.entry.mFlags)); + + if(ed2.entry.mAlignment) + { + assert(0); // Never tested + Address = alignStream(Address, ed2.entry.mAlignment); + assert(Address<=lastAddress); + } + + if(ed2.entry.mFlags & PxMetaDataFlag::ePTR) + { + assert(0); // Never tested + } + else + { + MetaClass* mc = getMetaClass(ed2.entry.mType, META_DATA_SRC); + assert(mc); + + while(count--) + { + convertClass(Address, mc, 0); + Address += mc->mSize; + assert(Address<=lastAddress); + } + } + + } + } + else + { + if( (ed2.entry.mFlags & PxMetaDataFlag::eALIGNMENT) && ed2.entry.mAlignment) + { + Address = alignStream(Address, ed2.entry.mAlignment); + assert(Address<=lastAddress); + } + else + { + // We assume it's an normal array, e.g. the ones from "big convexes" + assert(!(ed2.entry.mFlags & PxMetaDataFlag::eEXTRA_ITEM)); + + Address = convertExtraData_Array(Address, lastAddress, classAddress, ed2); + } + } + } + + } + else + { + int stop = 0; + (void)(stop); + } + + // ---- big convex surgery ---- + setNoOutput(false); + // ---- big convex surgery ---- + } + else if(ed.entry.mFlags & PxMetaDataFlag::eEXTRA_ITEMS) + { + // PX_DEF_BIN_METADATA_EXTRA_ITEMS + int reloc = ed.offset - ed.entry.mOffset; // ### because the enum code only fixed the "controlOffset"! + const int controlOffset = ed.entry.mOffset; + const int controlSize = ed.entry.mSize; + const int countOffset = ed.entry.mCount; + const int countSize = ed.entry.mOffsetSize; + + // const int controlValue2 = peek(controlSize, objectAddress + controlOffset); + const PxU64 controlValue2 = peek(controlSize, objectAddress + controlOffset + reloc); + + PxU64 controlMask = 0; + if(ed.entry.mFlags & PxMetaDataFlag::eCONTROL_MASK) + { + controlMask = PxU64(ed.entry.mFlags & (PxMetaDataFlag::eCONTROL_MASK_RANGE << 16)); + controlMask = controlMask >> 16; + } + + if(decodeControl(controlValue2, ed, controlMask)) + { + // PT: safe to cast to int here since we're reading a count + // int count = peek(countSize, objectAddress + countOffset); // ### + int count = int(peek(countSize, objectAddress + countOffset + reloc, ed.entry.mFlags)); // ### + + if(ed.entry.mAlignment) + { + Address = alignStream(Address, ed.entry.mAlignment); + assert(Address<=lastAddress); + } + + if(ed.entry.mFlags & PxMetaDataFlag::ePTR) + { + Address = convertExtraData_Ptr(Address, lastAddress, ed.entry, count, ptrSize_Src, ptrSize_Dst); + } + else + { + MetaClass* mc = getMetaClass(ed.entry.mType, META_DATA_SRC); + assert(mc); + + while(count--) + { + convertClass(Address, mc, 0); + Address += mc->mSize; + assert(Address<=lastAddress); + } + } + } + + } + else if(ed.entry.mFlags & PxMetaDataFlag::eALIGNMENT) + { + if(ed.entry.mAlignment) + { + displayMessage(PxErrorCode::eDEBUG_INFO, " align to %d bytes\n", ed.entry.mAlignment); + displayMessage(PxErrorCode::eDEBUG_INFO, "---------------------------------------------\n"); + + Address = alignStream(Address, ed.entry.mAlignment); + assert(Address<=lastAddress); + } + } + else if(ed.entry.mFlags & PxMetaDataFlag::eEXTRA_NAME) + { + if(ed.entry.mAlignment) + { + Address = alignStream(Address, ed.entry.mAlignment); + assert(Address<=lastAddress); + } + + //get string count + MetaClass* mc = getMetaClass("PxU32", META_DATA_SRC); + assert(mc); + //safe to cast to int here since we're reading a count. + const int count = int(peek(mc->mSize, Address, 0)); + + displayMessage(PxErrorCode::eDEBUG_INFO, " convert %d bytes string\n", count); + + convertClass(Address, mc, 0); + Address += mc->mSize; + + mc = getMetaClass(ed.entry.mType, META_DATA_SRC); + assert(mc); + + for(int c=0;c<count;c++) + { + convertClass(Address, mc, 0); + Address += mc->mSize; + assert(Address<=lastAddress); + } + } + else + { + Address = convertExtraData_Array(Address, lastAddress, objectAddress, ed); + } + } + } + PX_DELETE_ARRAY(objects); + assert(nbConvexes==mConvexFlags.size()); + } + + assert(Address==lastAddress); + + return true; +} + +bool Sn::ConvX::convert(const void* buffer, int fileSize) +{ + // Test initial alignment + if(size_t(buffer) & (ALIGN_DEFAULT-1)) + { + assert(0); + return false; + } + + const int header = read32(buffer); fileSize -= 4; (void)header; + + if (header != PX_MAKE_FOURCC('S','E','B','D')) + { + displayMessage(physx::PxErrorCode::eINVALID_PARAMETER, + "PxBinaryConverter: Buffer contains data with bad header indicating invalid serialized data."); + return false; + } + + const int version = read32(buffer); fileSize -= 4; (void)version; + + const int binaryVersion = read32(buffer); fileSize -= 4; + + if (!checkCompatibility(PxU32(version), PxU32(binaryVersion))) + { + char buf[512]; + getCompatibilityVersionsStr(buf, 512); + + displayMessage(physx::PxErrorCode::eINVALID_PARAMETER, + "PxBinaryConverter: Buffer contains data version (%x-%d) is incompatible with this PhysX sdk.\n These versions would be compatible: %s", + version, binaryVersion, buf); + return false; + } + const int buildNumber = read32(buffer); fileSize -= 4; (void)buildNumber; + + //read src platform tag and write dst platform tag according dst meta data + const int srcPlatformTag = *reinterpret_cast<const int*>(buffer); + buffer = reinterpret_cast<const void*>(size_t(buffer) + 4); + fileSize -= 4; + const int dstPlatformTag = mMetaData_Dst->getPlatformTag(); + output(dstPlatformTag); + + if (srcPlatformTag != mMetaData_Src->getPlatformTag()) + { + displayMessage(physx::PxErrorCode::eINVALID_PARAMETER, + "PxBinaryConverter: Mismatch of platform tags of binary data and metadata:\n Binary Data: %s\n MetaData: %s\n", + getBinaryPlatformName(PxU32(srcPlatformTag)), + getBinaryPlatformName(PxU32(mMetaData_Src->getPlatformTag()))); + return false; + } + + //read whether input data has marked padding, and set it for the output data (since 0xcd is written into pads on conversion) + const int srcMarkedPadding = *reinterpret_cast<const int*>(buffer); + buffer = reinterpret_cast<const void*>(size_t(buffer) + 4); + fileSize -= 4; + mMarkedPadding = srcMarkedPadding != 0; + const int dstMarkedPadding = 1; + output(dstMarkedPadding); + + int nbObjectsInCollection; + + buffer = convertReferenceTables(buffer, fileSize, nbObjectsInCollection); + if(!buffer) + return false; + + bool ret = convertCollection(buffer, fileSize, nbObjectsInCollection); + mMarkedPadding = false; + return ret; +} + +// PT: code below added to support 64bit-to-32bit conversions +void Sn::ConvX::exportIntAsPtr(int value) +{ + const int ptrSize_Src = mSrcPtrSize; + const int ptrSize_Dst = mDstPtrSize; + + PxMetaDataEntry entry; + + const char* address = NULL; + const PxU32 value32 = PxU32(value); + const PxU64 value64 = PxU64(value)&0xffffffff; + + if(ptrSize_Src==4) + { + address = reinterpret_cast<const char*>(&value32); + } + else if(ptrSize_Src==8) + { + address = reinterpret_cast<const char*>(&value64); + } + else assert(0); + + convertExtraData_Ptr(address, address + ptrSize_Src, entry, 1, ptrSize_Src, ptrSize_Dst); +} + +void Sn::ConvX::exportInt(int value) +{ + output(value); +} + +void Sn::ConvX::exportInt64(PxU64 value) +{ + output(value); +} + +PointerRemap::PointerRemap() +{ +} + +PointerRemap::~PointerRemap() +{ +} + +bool PointerRemap::checkRefIsNotUsed(PxU32 ref) const +{ + const PxU32 size = mData.size(); + for(PxU32 i=0;i<size;i++) + { + if(mData[i].id==ref) + return false; + } + return true; +} + +void PointerRemap::setObjectRef(PxU64 object64, PxU32 ref) +{ + const PxU32 size = mData.size(); + for(PxU32 i=0;i<size;i++) + { + if(mData[i].object==object64) + { + mData[i].id = ref; + return; + } + } + InternalData data; + data.object = object64; + data.id = ref; + mData.pushBack(data); +} + +bool PointerRemap::getObjectRef(PxU64 object64, PxU32& ref) const +{ + const PxU32 size = mData.size(); + for(PxU32 i=0;i<size;i++) + { + if(mData[i].object==object64) + { + ref = mData[i].id; + return true; + } + } + return false; +} + +/** +Converting the PxBase object offsets in the manifest table is fairly complicated now. +It would be good to have an easy callback mechanism for custom things like this. +*/ +const void* Sn::ConvX::convertManifestTable(const void* buffer, int& fileSize) +{ + PxU32 padding = getPadding(size_t(buffer), ALIGN_DEFAULT); + buffer = alignStream(reinterpret_cast<const char*>(buffer)); + fileSize -= padding; + int nb = read32(buffer); + fileSize -= 4; + + MetaClass* mc_src = getMetaClass("Sn::ManifestEntry", META_DATA_SRC); + assert(mc_src); + + MetaClass* mc_dst = getMetaClass("Sn::ManifestEntry", META_DATA_DST); + assert(mc_dst); + + bool mdOk; + PxMetaDataEntry srcTypeField; + mdOk = mc_src->getFieldByName("type", srcTypeField); + PX_UNUSED(mdOk); + PX_ASSERT(mdOk); + + PxMetaDataEntry dstOffsetField; + mdOk = mc_dst->getFieldByName("offset", dstOffsetField); + PX_ASSERT(mdOk); + + const char* address = reinterpret_cast<const char*>(buffer); + PxU32 headerOffset = 0; + for(int i=0;i<nb;i++) + { + PxConcreteType::Enum classType = PxConcreteType::Enum(peek(srcTypeField.mSize, address + srcTypeField.mOffset)); + + //convert ManifestEntry but output to tmpStream + PxDefaultMemoryOutputStream tmpStream; + { + //backup output state + PxOutputStream* outStream = mOutStream; + PxU32 outputSize = PxU32(mOutputSize); + + mOutStream = &tmpStream; + mOutputSize = 0; + + convertClass(address, mc_src, 0); + PX_ASSERT(tmpStream.getSize() == PxU32(mc_dst->mSize)); + + //restore output state + mOutStream = outStream; + mOutputSize = int(outputSize); + } + + //output patched offset + PX_ASSERT(dstOffsetField.mOffset == 0); //assuming offset is the first data + output(int(headerOffset)); + + //output rest of ManifestEntry + PxU32 restSize = PxU32(mc_dst->mSize - dstOffsetField.mSize); + mOutStream->write(tmpStream.getData() + dstOffsetField.mSize, restSize); + mOutputSize += restSize; + + //increment source stream + address += mc_src->mSize; + fileSize -= mc_src->mSize; + assert(fileSize>=0); + + //update headerOffset using the type and dst meta data of the type + MetaClass* mc_classType_dst = getMetaClass(classType, META_DATA_DST); + if(!mc_classType_dst) + return NULL; + headerOffset += getPadding(size_t(mc_classType_dst->mSize), PX_SERIAL_ALIGN) + mc_classType_dst->mSize; + } + + output(int(headerOffset)); //endoffset + buffer = address + 4; + fileSize -= 4; + return buffer; +} + +const void* Sn::ConvX::convertImportReferences(const void* buffer, int& fileSize) +{ + PxU32 padding = getPadding(size_t(buffer), ALIGN_DEFAULT); + buffer = alignStream(reinterpret_cast<const char*>(buffer)); + fileSize -= padding; + int nb = read32(buffer); + fileSize -= 4; + + if(!nb) + return buffer; + + MetaClass* mc = getMetaClass("Sn::ImportReference", META_DATA_SRC); + assert(mc); + + const char* address = reinterpret_cast<const char*>(buffer); + for(int i=0;i<nb;i++) + { + convertClass(address, mc, 0); + address += mc->mSize; + fileSize -= mc->mSize; + assert(fileSize>=0); + } + return address; +} + +const void* Sn::ConvX::convertExportReferences(const void* buffer, int& fileSize) +{ + PxU32 padding = getPadding(size_t(buffer), ALIGN_DEFAULT); + buffer = alignStream(reinterpret_cast<const char*>(buffer)); + fileSize -= padding; + int nb = read32(buffer); + fileSize -= 4; + + if(!nb) + return buffer; + + MetaClass* mc = getMetaClass("Sn::ExportReference", META_DATA_SRC); + assert(mc); + + const char* address = reinterpret_cast<const char*>(buffer); + for(int i=0;i<nb;i++) + { + convertClass(address, mc, 0); + address += mc->mSize; + fileSize -= mc->mSize; + assert(fileSize>=0); + } + return address; +} + +const void* Sn::ConvX::convertInternalReferences(const void* buffer, int& fileSize) +{ + PxU32 padding = getPadding(size_t(buffer), ALIGN_DEFAULT); + buffer = alignStream(reinterpret_cast<const char*>(buffer)); + fileSize -= padding; + + //pointer references + int nbPtrReferences = read32(buffer); + fileSize -= 4; + if(nbPtrReferences) + { + const char* address = reinterpret_cast<const char*>(buffer); + MetaClass* mc = getMetaClass("Sn::InternalReferencePtr", META_DATA_SRC); + assert(mc); + for(int i=0;i<nbPtrReferences;i++) + { + convertClass(address, mc, 0); + address += mc->mSize; + fileSize -= mc->mSize; + assert(fileSize>=0); + } + buffer = address; + } + + //index references + int nbIdxReferences = read32(buffer); + fileSize -= 4; + if (nbIdxReferences) + { + const char* address = reinterpret_cast<const char*>(buffer); + MetaClass* mc = getMetaClass("Sn::InternalReferenceIdx", META_DATA_SRC); + assert(mc); + for(int i=0;i<nbIdxReferences;i++) + { + convertClass(address, mc, 0); + address += mc->mSize; + fileSize -= mc->mSize; + assert(fileSize>=0); + } + buffer = address; + } + return buffer; +} + + +const void* Sn::ConvX::convertReferenceTables(const void* buffer, int& fileSize, int& nbObjectsInCollection) +{ + // PT: the map should not be used while creating it, so use one indirection + mActiveRemap = NULL; + mRemap.mData.clear(); + mPointerRemapCounter = 0; + + PxU32 padding = getPadding(size_t(buffer), ALIGN_DEFAULT); + buffer = alignStream(reinterpret_cast<const char*>(buffer)); + fileSize -= padding; + + nbObjectsInCollection = read32(buffer); + if (nbObjectsInCollection == 0) + displayMessage(PxErrorCode::eDEBUG_INFO, "\n\nConverting empty collection!\n\n"); + fileSize -= 4; + + buffer = convertManifestTable(buffer, fileSize); + + if(!buffer) + return NULL; + + buffer = convertImportReferences(buffer, fileSize); + buffer = convertExportReferences(buffer, fileSize); + buffer = convertInternalReferences(buffer, fileSize); + + // PT: the map can now be used + mActiveRemap = &mRemap; + + return buffer; +} + +bool Sn::ConvX::checkPaddingBytes(const char* buffer, int byteCount) +{ + const unsigned char* src = reinterpret_cast<const unsigned char*>(buffer); + + int i = 0; + while ((i < byteCount) && (src[i] == 0xcd)) + i++; + return (i == byteCount); +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Error.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Error.cpp new file mode 100644 index 00000000..9debc679 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Error.cpp @@ -0,0 +1,92 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#include "foundation/PxErrorCallback.h" +#include "SnConvX.h" +#include <stdarg.h> +#include "PsString.h" +#include "PsFoundation.h" + +#define MAX_DISPLAYED_ISSUES 10 + +using namespace physx; + +void Sn::ConvX::resetNbErrors() +{ + mNbErrors = 0; + mNbWarnings = 0; +} + +int Sn::ConvX::getNbErrors() const +{ + return mNbErrors; +} + +void Sn::ConvX::displayMessage(PxErrorCode::Enum code, const char* format, ...) +{ + if(silentMode()) + return; + + int sum = mNbWarnings + mNbErrors; + if(sum >= MAX_DISPLAYED_ISSUES) + return; + + bool display = false; + + if(code==PxErrorCode::eINTERNAL_ERROR || code==PxErrorCode::eINVALID_OPERATION || code==PxErrorCode::eINVALID_PARAMETER) + { + mNbErrors++; + display = true; + } + else if(code == PxErrorCode::eDEBUG_WARNING) + { + mNbWarnings++; + display = true; + } + + if(display || ((sum == 0) && verboseMode()) ) + { + va_list va; + va_start(va, format); + Ps::getFoundation().errorImpl(code, __FILE__, __LINE__, format, va); + va_end(va); + } + + if(display) + { + if( sum == 0) + { + Ps::getFoundation().error(PxErrorCode::eDEBUG_INFO, __FILE__, __LINE__, "Hit warnings or errors: skipping further verbose output.\n"); + } + else if(sum == MAX_DISPLAYED_ISSUES-1) + { + Ps::getFoundation().error(PxErrorCode::eDEBUG_INFO, __FILE__, __LINE__, "Exceeding 10 warnings or errors: skipping further output.\n"); + } + } + + return; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.cpp new file mode 100644 index 00000000..4d2eda22 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.cpp @@ -0,0 +1,840 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#include "foundation/PxIO.h" +#include "SnConvX.h" +#include "common/PxSerialFramework.h" +#include "serialization/SnSerialUtils.h" +#include <assert.h> + +using namespace physx; +using namespace physx::Sn; + +//#define REMOVE_EXPLICIT_PADDING + +static const char gVTablePtr[] = "v-table ptr"; +static const char gAutoPadding[] = "auto-generated padding"; +static const char gByte[] = "paddingByte"; + +/////////////////////////////////////////////////////////////////////////////// + +bool PxMetaDataEntry::isVTablePtr() const +{ + return mType==gVTablePtr; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool MetaClass::getFieldByType(const char* type, PxMetaDataEntry& entry) const +{ + assert(type); + PxU32 nbFields = mFields.size(); + for(PxU32 i=0;i<nbFields;i++) + { + if(strcmp(mFields[i].mType, type)==0) + { + entry = mFields[i]; + return true; + } + } + return false; +} + +bool MetaClass::getFieldByName(const char* name, PxMetaDataEntry& entry) const +{ + assert(name); + PxU32 nbFields = mFields.size(); + for(PxU32 i=0;i<nbFields;i++) + { + if(strcmp(mFields[i].mName, name)==0) + { + entry = mFields[i]; + return true; + } + } + return false; +} + +void MetaClass::checkAndCompleteClass(const MetaData& owner, int& startOffset, int& nbBytes) +{ + if(startOffset!=-1) + { + owner.mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, + "\n Adding %d padding bytes at offset %d in class %s.\n", nbBytes, startOffset, mClassName); + + // Leap of faith: add padding bytes there + PxMetaDataEntry padding; + padding.mType = gByte; + padding.mName = gAutoPadding; + padding.mOffset = startOffset; + padding.mSize = nbBytes; + padding.mCount = nbBytes; + padding.mFlags = PxMetaDataFlag::ePADDING; + mFields.pushBack(padding); + + startOffset = -1; + } +} + +bool MetaClass::check(const MetaData& owner) +{ + owner.mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, "Checking class: %s\n", mClassName); + + if(mCallback) + return true; // Skip atomic types + if(mMaster) + return true; // Skip typedefs + + bool* map = reinterpret_cast<bool*>(PX_ALLOC(sizeof(bool)*mSize, "bool")); + memset(map, 0, size_t(mSize)); + + const PxU32 nbFields = mFields.size(); + for(PxU32 i=0;i<nbFields;i++) + { + const PxMetaDataEntry& field = mFields[i]; + if(field.mFlags & PxMetaDataFlag::eEXTRA_DATA) + continue; +// if((field.mFlags & PxMetaDataFlag::eUNION) && !field.mSize) +// continue; // Union type + assert(field.mSize); + const int byteStart = field.mOffset; + const int byteEnd = field.mOffset + field.mSize; + assert(byteStart>=0 && byteStart<mSize); + assert(byteEnd>=0 && byteEnd<=mSize); + + int startOffset = -1; + int nbBytes = 0; + for(int j=byteStart;j<byteEnd;j++) + { + if(map[j]) + { + if(startOffset==-1) + { + startOffset = int(i); + nbBytes = 0; + } + nbBytes++; +// displayErrorMessage(" %s: found overlapping bytes!\n", mClassName); + } + else + { + if(startOffset!=-1) + { + owner.mConvX.displayMessage(PxErrorCode::eINTERNAL_ERROR, + "PxBinaryConverter: %s: %d overlapping bytes at offset %d!\n", mClassName, nbBytes, startOffset); + startOffset = -1; + PX_ALWAYS_ASSERT_MESSAGE("Overlapping bytes!"); + } + } + map[j] = true; + } + if(startOffset!=-1) + { + owner.mConvX.displayMessage(PxErrorCode::eINTERNAL_ERROR, + "PxBinaryConverter: %s: %d overlapping bytes at offset %d!\n", mClassName, nbBytes, startOffset); + startOffset = -1; + PX_ALWAYS_ASSERT_MESSAGE("Overlapping bytes!"); + } + } + + { + int startOffset = -1; + int nbBytes = 0; + for(int i=0;i<mSize;i++) + { + if(!map[i]) + { + if(startOffset==-1) + { + startOffset = i; + nbBytes = 0; + } + nbBytes++; + } + else + { + checkAndCompleteClass(owner, startOffset, nbBytes); + } + } + checkAndCompleteClass(owner, startOffset, nbBytes); + } + PX_FREE(map); + + + // + for(PxU32 i=0;i<nbFields;i++) + { + const PxMetaDataEntry& current = mFields[i]; + if(current.mFlags & PxMetaDataFlag::ePTR) + continue; + + MetaClass* fieldMetaClass = owner.mConvX.getMetaClass(current.mType, owner.getType()); + if(!fieldMetaClass) + { + owner.mConvX.displayMessage(PxErrorCode::eINTERNAL_ERROR, + "PxBinaryConverter: Missing meta-data for: %s\n", current.mType); + return false; + } + else + { + if(current.mFlags & PxMetaDataFlag::eEXTRA_DATA) + { + owner.mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, "Extra data: %s\n", current.mType); + } + else + { + assert(fieldMetaClass->mSize*current.mCount==current.mSize); + } + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////// + +MetaData::MetaData(ConvX& convx) : + mConvX (convx), + mType (META_DATA_NONE), + mNbEntries (0), + mEntries (NULL), + mStringTable (NULL), + mVersion (0), + mBuildNumber (0), + mSizeOfPtr (0), + mPlatformTag (0), + mGaussMapLimit (0), + mFlip (false) +{ +} + +MetaData::~MetaData() +{ + PxU32 nbMetaClasses = mMetaClasses.size(); + for(PxU32 i=0;i<nbMetaClasses;i++) + { + MetaClass* current = mMetaClasses[i]; + PX_DELETE(current); + } + + PX_FREE(mStringTable); + PX_DELETE_ARRAY(mEntries); +} + +MetaClass* MetaData::getMetaClass(const char* name) const +{ + PxU32 nbMetaClasses = mMetaClasses.size(); + for(PxU32 i=0;i<nbMetaClasses;i++) + { + MetaClass* current = mMetaClasses[i]; + if(strcmp(current->mClassName, name)==0) + { + while(current->mMaster) + current = current->mMaster; + return current; + } + } + return NULL; +} + +MetaClass* MetaData::getMetaClass(PxConcreteType::Enum concreteType) const +{ + for(PxU32 i=0; i< mConcreteTypeTable.size(); i++) + { + if(mConcreteTypeTable[i].first == concreteType) + { + const char* className = offsetToText(reinterpret_cast<const char*>(size_t(mConcreteTypeTable[i].second))); + return getMetaClass(className); + } + } + return NULL; +} + +MetaClass* MetaData::addNewClass(const char* name, int size, MetaClass* master, ConvertCallback callback) +{ + // PT: if you reach this assert, you used PX_DEF_BIN_METADATA_TYPEDEF twice on the same type + assert(!getMetaClass(name)); + MetaClass* mc = PX_NEW(MetaClass); + mc->mCallback = callback; + mc->mMaster = master; + mc->mClassName = name; + mc->mSize = size; + mc->mDepth = 0; + mc->mProcessed = false; +// mc->mNbEntries = -1; + + mMetaClasses.pushBack(mc); + + return mc; +} + +bool MetaData::load(PxInputStream& inputStream, MetaDataType type) +{ + assert(type!=META_DATA_NONE); + + mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, "Loading %s meta-data...\n", type==META_DATA_SRC ? "source" : "target"); + + mType = type; + + mFlip = false; + { + int header; + inputStream.read(&header, 4); + if(header==PX_MAKE_FOURCC('M','E','T','A')) + { + mFlip = false; + } + else if(header==PX_MAKE_FOURCC('A','T','E','M')) + { + mFlip = true; + } + else + { + mConvX.displayMessage(PxErrorCode::eINVALID_PARAMETER, "PxBinaryConverter: invalid meta-data file!\n"); + return false; + } + + if (type == META_DATA_SRC && mFlip) + { + mConvX.displayMessage(PxErrorCode::eINVALID_PARAMETER, + "PxBinaryConverter: source meta data needs to match endianness with current system!"); + return false; + } + + inputStream.read(&mVersion, 4); + inputStream.read(&mBinaryVersion, 4); + if(mFlip) + { + flip(mVersion); + flip(mBinaryVersion); + } + + if (!checkCompatibility(PxU32(mVersion), PxU32(mBinaryVersion))) + { + char buffer[512]; + getCompatibilityVersionsStr(buffer, 512); + + mConvX.displayMessage(PxErrorCode::eINVALID_PARAMETER, + "PxBinaryConverter: data version (%x-%d) is incompatible with this PhysX sdk.\n These versions would be compatible: %s", + mVersion, mBinaryVersion, buffer); + + return false; + } + inputStream.read(&mBuildNumber, 4); + if(mFlip) + flip(mBuildNumber); + + + inputStream.read(&mSizeOfPtr, 4); + if(mFlip) + flip(mSizeOfPtr); + + inputStream.read(&mPlatformTag, 4); + if(mFlip) + flip(mPlatformTag); + + if (!Sn::isBinaryPlatformTagValid(PxU32(mPlatformTag))) + { + mConvX.displayMessage(PxErrorCode::eINVALID_PARAMETER, "PxBinaryConverter: Unknown meta data platform tag"); + return false; + } + + inputStream.read(&mGaussMapLimit, 4); + if(mFlip) + flip(mGaussMapLimit); + + inputStream.read(&mNbEntries, 4); + if(mFlip) + flip(mNbEntries); + + mEntries = PX_NEW(PxMetaDataEntry)[PxU32(mNbEntries)]; + if(mSizeOfPtr==8) + { + for(int i=0;i<mNbEntries;i++) + { + MetaDataEntry64 tmp; + inputStream.read(&tmp, sizeof(MetaDataEntry64)); + if (mFlip) // important to flip them first, else the cast below might destroy information + { + flip(tmp.mType); + flip(tmp.mName); + } + // We can safely cast to 32bits here since we transformed the pointers to offsets in the string table on export + mEntries[i].mType = reinterpret_cast<const char*>(size_t(tmp.mType)); + mEntries[i].mName = reinterpret_cast<const char*>(size_t(tmp.mName)); + mEntries[i].mOffset = tmp.mOffset; + mEntries[i].mSize = tmp.mSize; + mEntries[i].mCount = tmp.mCount; + mEntries[i].mOffsetSize = tmp.mOffsetSize; + mEntries[i].mFlags = tmp.mFlags; + mEntries[i].mAlignment = tmp.mAlignment; + } + } + else + { + assert(mSizeOfPtr==4); +// inputStream.read(mEntries, mNbEntries*sizeof(PxMetaDataEntry)); + for(int i=0;i<mNbEntries;i++) + { + MetaDataEntry32 tmp; + inputStream.read(&tmp, sizeof(MetaDataEntry32)); + if (mFlip) + { + flip(tmp.mType); + flip(tmp.mName); + } + mEntries[i].mType = reinterpret_cast<const char*>(size_t(tmp.mType)); + mEntries[i].mName = reinterpret_cast<const char*>(size_t(tmp.mName)); + mEntries[i].mOffset = tmp.mOffset; + mEntries[i].mSize = tmp.mSize; + mEntries[i].mCount = tmp.mCount; + mEntries[i].mOffsetSize = tmp.mOffsetSize; + mEntries[i].mFlags = tmp.mFlags; + mEntries[i].mAlignment = tmp.mAlignment; + } + } + + if(mFlip) + { + for(int i=0;i<mNbEntries;i++) + { + // mEntries[i].mType and mEntries[i].mName have been flipped already because they need special treatment + // on 64bit to 32bit platform conversions + flip(mEntries[i].mOffset); + flip(mEntries[i].mSize); + flip(mEntries[i].mCount); + flip(mEntries[i].mOffsetSize); + flip(mEntries[i].mFlags); + flip(mEntries[i].mAlignment); + } + } + + int nbConcreteType; + inputStream.read(&nbConcreteType, 4); + if(mFlip) + flip(nbConcreteType); + + for(int i=0; i<nbConcreteType; i++) + { + PxU16 concreteType; + PxU32 nameOffset; + inputStream.read(&concreteType, 2); + inputStream.read(&nameOffset, 4); + if(mFlip) + { + flip(concreteType); + flip(nameOffset); + } + + mConcreteTypeTable.pushBack( Ps::Pair<PxConcreteType::Enum, PxU32>(PxConcreteType::Enum(concreteType), nameOffset) ); + } + + int tableSize; + inputStream.read(&tableSize, 4); + if(mFlip) + flip(tableSize); + + mStringTable = reinterpret_cast<char*>(PX_ALLOC(sizeof(char)*tableSize, "MetaData StringTable")); + inputStream.read(mStringTable, PxU32(tableSize)); + } + + // Register atomic types + { + addNewClass("bool", 1, NULL, &ConvX::convert8); + addNewClass("char", 1, NULL, &ConvX::convert8); + addNewClass("short", 2, NULL, &ConvX::convert16); + addNewClass("int", 4, NULL, &ConvX::convert32); + addNewClass("PxU64", 8, NULL, &ConvX::convert64); + addNewClass("float", 4, NULL, &ConvX::convertFloat); + + addNewClass("paddingByte", 1, NULL, &ConvX::convertPad8); + } + + { + MetaClass* currentClass = NULL; + for(int i=0;i<mNbEntries;i++) + { + mEntries[i].mType = offsetToText(mEntries[i].mType); + mEntries[i].mName = offsetToText(mEntries[i].mName); + + if(mEntries[i].mFlags & PxMetaDataFlag::eTYPEDEF) + { + mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, "Found typedef: %s => %s\n", mEntries[i].mName, mEntries[i].mType); + MetaClass* mc = getMetaClass(mEntries[i].mName); + if(mc) + addNewClass(mEntries[i].mType, mc->mSize, mc, mc->mCallback); + else + mConvX.displayMessage(PxErrorCode::eINTERNAL_ERROR, + "PxBinaryConverter: Invalid typedef - Missing metadata for: %s, please check the source metadata.\n" + , mEntries[i].mName); + } + else if(mEntries[i].mFlags & PxMetaDataFlag::eCLASS) + { + if(!mEntries[i].mName) + { + mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, "Found class: %s\n", mEntries[i].mType); + currentClass = addNewClass(mEntries[i].mType, mEntries[i].mSize); + + if(mEntries[i].mFlags & PxMetaDataFlag::eVIRTUAL) + { + PxMetaDataEntry vtable; + vtable.mType = gVTablePtr; + vtable.mName = gVTablePtr; + vtable.mOffset = 0; + vtable.mSize = mSizeOfPtr; + vtable.mCount = 1; + vtable.mFlags = PxMetaDataFlag::ePTR; + currentClass->mFields.pushBack(vtable); + } + } + else + { + assert(currentClass); + mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, " - inherits from: %s\n", mEntries[i].mName); + currentClass->mBaseClasses.pushBack(mEntries[i]); + } + } + else + { + const int isUnion = mEntries[i].mFlags & PxMetaDataFlag::eUNION; + + if(isUnion && !mEntries[i].mSize) + { + mConvX.registerUnionType(mEntries[i].mType, mEntries[i].mName, mEntries[i].mOffset); + } + else + { + if(isUnion) + { + mConvX.registerUnion(mEntries[i].mType); + } + + const int isPadding = mEntries[i].mFlags & PxMetaDataFlag::ePADDING; + + assert(currentClass); +#ifdef REMOVE_EXPLICIT_PADDING + if(!isPadding) +#endif + currentClass->mFields.pushBack(mEntries[i]); + + if(isPadding) + mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, + " - contains padding: %s - %s\n", mEntries[i].mType, mEntries[i].mName); + else if(mEntries[i].mFlags & PxMetaDataFlag::eEXTRA_DATA) + mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, + " - contains extra data: %s%s\n", mEntries[i].mType, mEntries[i].mFlags & PxMetaDataFlag::ePTR ? "*" : ""); + else + mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, + " - contains field: %s%s\n", mEntries[i].mType, mEntries[i].mFlags & PxMetaDataFlag::ePTR ? "*" : ""); + + } + } + } + } + + // Sort classes by depth + struct Local + { + static bool _computeDepth(const MetaData& md, MetaClass* current, int currentDepth, int& maxDepth) + { + if(currentDepth>maxDepth) + maxDepth = currentDepth; + + PxU32 nbBases = current->mBaseClasses.size(); + for(PxU32 i=0;i<nbBases;i++) + { + const PxMetaDataEntry& baseClassEntry = current->mBaseClasses[i]; + MetaClass* baseClass = md.getMetaClass(baseClassEntry.mName); + if(!baseClass) + { + md.mConvX.displayMessage(PxErrorCode::eINTERNAL_ERROR, + "PxBinaryConverter: Can't find class %s metadata, please check the source metadata.\n", baseClassEntry.mName); + return false; + } + if (!_computeDepth(md, baseClass, currentDepth+1, maxDepth)) + return false; + } + return true; + } + + static int compareClasses(const void* c0, const void* c1) + { + MetaClass** mc0 = reinterpret_cast<MetaClass**>(const_cast<void*>(c0)); + MetaClass** mc1 = reinterpret_cast<MetaClass**>(const_cast<void*>(c1)); +// return (*mc0)->mSize - (*mc1)->mSize; + return (*mc0)->mDepth - (*mc1)->mDepth; + } + + static int compareEntries(const void* c0, const void* c1) + { + PxMetaDataEntry* mc0 = reinterpret_cast<PxMetaDataEntry*>(const_cast<void*>(c0)); + PxMetaDataEntry* mc1 = reinterpret_cast<PxMetaDataEntry*>(const_cast<void*>(c1)); + //mOffset is used to access control information for extra data, and not for offsets of the data itself. + assert(!(mc0->mFlags & PxMetaDataFlag::eEXTRA_DATA)); + assert(!(mc1->mFlags & PxMetaDataFlag::eEXTRA_DATA)); + return mc0->mOffset - mc1->mOffset; + } + }; + { + // Compute depths + const PxU32 nbMetaClasses = mMetaClasses.size(); + for(PxU32 i=0;i<nbMetaClasses;i++) + { + MetaClass* current = mMetaClasses[i]; + int maxDepth = 0; + if(!Local::_computeDepth(*this, current, 0, maxDepth)) + return false; + current->mDepth = maxDepth; + } + + // Sort by depth + MetaClass** metaClasses = &mMetaClasses[0]; + qsort(metaClasses, size_t(nbMetaClasses), sizeof(MetaClass*), Local::compareClasses); + } + + // Replicate fields from base classes + { + PxU32 nbMetaClasses = mMetaClasses.size(); + for(PxU32 k=0;k<nbMetaClasses;k++) + { + MetaClass* current = mMetaClasses[k]; + PxU32 nbBases = current->mBaseClasses.size(); + + // merge entries of base classes and current class in the right order + // this is needed for extra data ordering, which is not covered by the mOffset sort + // in the next stage below + PsArray<PxMetaDataEntry> mergedEntries; + + for(PxU32 i=0;i<nbBases;i++) + { + const PxMetaDataEntry& baseClassEntry = current->mBaseClasses[i]; + MetaClass* baseClass = getMetaClass(baseClassEntry.mName); + assert(baseClass); + assert(baseClass->mBaseClasses.size()==0 || baseClass->mProcessed); + + PxU32 nbBaseFields = baseClass->mFields.size(); + for(PxU32 j=0;j<nbBaseFields;j++) + { + PxMetaDataEntry f = baseClass->mFields[j]; + // Don't merge primary v-tables to avoid redundant v-table entries. + // It means the base v-table won't be inherited & needs to be explicitly defined in the metadata. Seems reasonable. + // Could be done better though. + + if(f.mType==gVTablePtr && !f.mOffset && !baseClassEntry.mOffset) + continue; + + f.mOffset += baseClassEntry.mOffset; + mergedEntries.pushBack(f); + } + current->mProcessed = true; + } + + //append current fields to base class fields + for (PxU32 i = 0; i < current->mFields.size(); i++) + { + mergedEntries.pushBack(current->mFields[i]); + } + current->mFields.clear(); + current->mFields.assign(mergedEntries.begin(), mergedEntries.end()); + } + } + + // Check classes + { + PxU32 nbMetaClasses = mMetaClasses.size(); + for(PxU32 i=0;i<nbMetaClasses;i++) + { + MetaClass* current = mMetaClasses[i]; + if(!current->check(*this)) + return false; + } + } + + // Sort meta-data by offset + { + PxU32 nbMetaClasses = mMetaClasses.size(); + for(PxU32 i=0;i<nbMetaClasses;i++) + { + MetaClass* current = mMetaClasses[i]; + PxU32 nbFields = current->mFields.size(); + if(nbFields<2) + continue; + PxMetaDataEntry* entries = ¤t->mFields[0]; + + PxMetaDataEntry* newEntries = PX_NEW(PxMetaDataEntry)[nbFields]; + PxU32 nb = 0; + for(PxU32 j=0;j<nbFields;j++) + if(!(entries[j].mFlags & PxMetaDataFlag::eEXTRA_DATA)) + newEntries[nb++] = entries[j]; + PxU32 nbToSort = nb; + for(PxU32 j=0;j<nbFields;j++) + if(entries[j].mFlags & PxMetaDataFlag::eEXTRA_DATA) + newEntries[nb++] = entries[j]; + assert(nb==nbFields); + memcpy(entries, newEntries, nb*sizeof(PxMetaDataEntry)); + PX_DELETE_ARRAY(newEntries); + qsort(entries, size_t(nbToSort), sizeof(PxMetaDataEntry), Local::compareEntries); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////// + +void ConvX::releaseMetaData() +{ + DELETESINGLE(mMetaData_Dst); + DELETESINGLE(mMetaData_Src); +} + +const MetaData* ConvX::loadMetaData(PxInputStream& inputStream, MetaDataType type) +{ + if (type != META_DATA_SRC && type != META_DATA_DST) + { + displayMessage(PxErrorCode::eINTERNAL_ERROR, + "PxBinaryConverter: Wrong meta data type, please check the source metadata.\n"); + return NULL; + } + + PX_ASSERT(type == META_DATA_SRC || type == META_DATA_DST); + + MetaData*& metaDataPtr = (type == META_DATA_SRC) ? mMetaData_Src : mMetaData_Dst; + metaDataPtr = PX_NEW(MetaData)(*this); + if(!(metaDataPtr)->load(inputStream, type)) + DELETESINGLE(metaDataPtr); + return metaDataPtr; +} + +const MetaData* ConvX::getBinaryMetaData(MetaDataType type) +{ + if(type==META_DATA_SRC) + return mMetaData_Src; + if(type==META_DATA_DST) + return mMetaData_Dst; + PX_ASSERT(0); + return NULL; +} + +int ConvX::getNbMetaClasses(MetaDataType type) +{ + if(type==META_DATA_SRC) + return mMetaData_Src->getNbMetaClasses(); + if(type==META_DATA_DST) + return mMetaData_Dst->getNbMetaClasses(); + PX_ASSERT(0); + return 0; +} + +MetaClass* ConvX::getMetaClass(unsigned int i, MetaDataType type) const +{ + if(type==META_DATA_SRC) + return mMetaData_Src->getMetaClass(i); + if(type==META_DATA_DST) + return mMetaData_Dst->getMetaClass(i); + PX_ASSERT(0); + return NULL; +} + +MetaClass* ConvX::getMetaClass(const char* name, MetaDataType type) const +{ + if(type==META_DATA_SRC) + return mMetaData_Src->getMetaClass(name); + if(type==META_DATA_DST) + return mMetaData_Dst->getMetaClass(name); + PX_ASSERT(0); + return NULL; +} + +MetaClass* ConvX::getMetaClass(PxConcreteType::Enum concreteType, MetaDataType type) +{ + MetaClass* metaClass = NULL; + if(type==META_DATA_SRC) + metaClass = mMetaData_Src->getMetaClass(concreteType); + if(type==META_DATA_DST) + metaClass = mMetaData_Dst->getMetaClass(concreteType); + + if(!metaClass) + { + displayMessage(PxErrorCode::eINTERNAL_ERROR, + "PxBinaryConverter: Missing concreteType %d metadata! serialized a class without dumping metadata. Please check the metadata.", + concreteType); + return NULL; + } + + return metaClass; +} + +/////////////////////////////////////////////////////////////////////////////// + +// Peek & poke, yes sir. +PxU64 physx::Sn::peek(int size, const char* buffer, int flags) +{ + const int maskMSB = flags & PxMetaDataFlag::eCOUNT_MASK_MSB; + const int skipIfOne = flags & PxMetaDataFlag::eCOUNT_SKIP_IF_ONE; + switch(size) + { + case 1: + { + unsigned char value = *(reinterpret_cast<const unsigned char*>(buffer)); + if(maskMSB) + value &= 0x7f; + if(skipIfOne && value==1) + return 0; + return PxU64(value); + } + case 2: + { + unsigned short value = *(reinterpret_cast<const unsigned short*>(buffer)); + if(maskMSB) + value &= 0x7fff; + if(skipIfOne && value==1) + return 0; + return PxU64(value); + } + case 4: + { + unsigned int value = *(reinterpret_cast<const unsigned int*>(buffer)); + if(maskMSB) + value &= 0x7fffffff; + if(skipIfOne && value==1) + return 0; + return PxU64(value); + } + case 8: + { + PxU64 value = *(reinterpret_cast<const PxU64*>(buffer)); + if(maskMSB) + value &= (PxU64(-1))>>1; + if(skipIfOne && value==1) + return 0; + return value; + } + }; + PX_ASSERT(0); + return PxU64(-1); +} + + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.h new file mode 100644 index 00000000..29597b62 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.h @@ -0,0 +1,186 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PX_CONVX_METADATA_H +#define PX_CONVX_METADATA_H + +#include "SnConvX_Output.h" +#include "PxMetaDataFlags.h" + +namespace physx { namespace Sn { + +#if PX_VC +#pragma warning (push) +#pragma warning (disable : 4371) //layout of class may have changed from a previous version of the compiler due to better packing of member +#endif + + + // PT: beware, must match corresponding structure in PxMetaData.h + struct PxMetaDataEntry : public shdfnd::UserAllocated + { + PxMetaDataEntry() + { + memset(this, 0, sizeof(*this)); + } + bool isVTablePtr() const; + + const char* mType; //!< Field type (bool, byte, quaternion, etc) + const char* mName; //!< Field name (appears exactly as in the source file) + int mOffset; //!< Offset from the start of the class (ie from "this", field is located at "this"+Offset) + int mSize; //!< sizeof(Type) + int mCount; //!< Number of items of type Type (0 for dynamic sizes) + int mOffsetSize; //!< Offset of dynamic size param, for dynamic arrays + int mFlags; //!< Field parameters + int mAlignment; //!< Explicit alignment added for DE1340 + }; + + struct MetaDataEntry32 + { + PxI32 mType; //!< Field type (bool, byte, quaternion, etc) + PxI32 mName; //!< Field name (appears exactly as in the source file) + int mOffset; //!< Offset from the start of the class (ie from "this", field is located at "this"+Offset) + int mSize; //!< sizeof(Type) + int mCount; //!< Number of items of type Type (0 for dynamic sizes) + int mOffsetSize; //!< Offset of dynamic size param, for dynamic arrays + int mFlags; //!< Field parameters + int mAlignment; //!< Explicit alignment added for DE1340 + }; + + struct MetaDataEntry64 + { + PxI64 mType; //!< Field type (bool, byte, quaternion, etc) + PxI64 mName; //!< Field name (appears exactly as in the source file) + int mOffset; //!< Offset from the start of the class (ie from "this", field is located at "this"+Offset) + int mSize; //!< sizeof(Type) + int mCount; //!< Number of items of type Type (0 for dynamic sizes) + int mOffsetSize; //!< Offset of dynamic size param, for dynamic arrays + int mFlags; //!< Field parameters + int mAlignment; //!< Explicit alignment added for DE1340 + }; + + struct ExtraDataEntry + { + PxMetaDataEntry entry; + int offset; + }; + + struct ExtraDataEntry2 : ExtraDataEntry + { + ConvertCallback cb; + }; + + class MetaData; + + struct MetaClass : public shdfnd::UserAllocated + { + bool getFieldByType(const char* type, PxMetaDataEntry& entry) const; + bool getFieldByName(const char* name, PxMetaDataEntry& entry) const; + bool check(const MetaData& owner); + + ConvertCallback mCallback; + MetaClass* mMaster; + const char* mClassName; + int mSize; + int mDepth; + PsArray<PxMetaDataEntry> mBaseClasses; + PsArray<PxMetaDataEntry> mFields; + bool mProcessed; + +// int mNbEntries; +// ExtraDataEntry2 mEntries[256]; + + private: + void checkAndCompleteClass(const MetaData& owner, int& startOffset, int& nbBytes); + }; + + enum MetaDataType + { + META_DATA_NONE, + META_DATA_SRC, + META_DATA_DST + }; + + class ConvX; + class MetaData : public shdfnd::UserAllocated + { + public: + MetaData(Sn::ConvX&); + ~MetaData(); + + bool load(PxInputStream& inputStream, MetaDataType type); + + inline_ MetaDataType getType() const { return mType; } + inline_ int getVersion() const { return mVersion; } + inline_ int getBuildNumber() const { return mBuildNumber; } + inline_ int getPtrSize() const { return mSizeOfPtr; } + inline_ int getPlatformTag() const { return mPlatformTag; } + inline_ int getGaussMapLimit() const { return mGaussMapLimit; } + inline_ int getNbMetaClasses() const { return int(mMetaClasses.size()); } + inline_ MetaClass* getMetaClass(unsigned int i) const { return mMetaClasses[i]; } + inline_ bool getFlip() const { return mFlip; } + + MetaClass* getMetaClass(const char* name) const; + MetaClass* getMetaClass(PxConcreteType::Enum concreteType) const; + MetaClass* addNewClass(const char* name, int size, MetaClass* master=NULL, ConvertCallback callback=NULL); + private: + MetaData& operator=(const MetaData&); + Sn::ConvX& mConvX; + MetaDataType mType; + int mNbEntries; + PxMetaDataEntry* mEntries; + char* mStringTable; + PsArray<MetaClass*> mMetaClasses; + int mVersion; + int mBinaryVersion; + int mBuildNumber; + int mSizeOfPtr; + int mPlatformTag; + int mGaussMapLimit; + bool mFlip; + + PsArray< Ps::Pair<PxConcreteType::Enum, PxU32> > mConcreteTypeTable; + + inline_ const char* offsetToText(const char* text) const + { + const size_t offset = size_t(text); + const PxU32 offset32 = PxU32(offset); +// if(offset==-1) + if(offset32==0xffffffff) + return NULL; + return mStringTable + offset32; + } + friend struct MetaClass; + }; + + PxU64 peek(int size, const char* buffer, int flags=0); + +#if PX_VC +#pragma warning (pop) +#endif +} } + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.cpp new file mode 100644 index 00000000..9eaa601c --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.cpp @@ -0,0 +1,451 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#include "foundation/PxIO.h" +#include "foundation/PxErrorCallback.h" +#include "SnConvX.h" + +#if PX_VC +#pragma warning(disable:4389) // signed/unsigned mismatch +#endif + +using namespace physx; + +void Sn::ConvX::setNullPtr(bool flag) +{ + mNullPtr = flag; +} + +void Sn::ConvX::setNoOutput(bool flag) +{ + mNoOutput = flag; +} + +bool Sn::ConvX::initOutput(PxOutputStream& targetStream) +{ + mOutStream = &targetStream; + + mOutputSize = 0; + mNullPtr = false; + mNoOutput = false; + + const MetaData* srcMetaData = getBinaryMetaData(META_DATA_SRC); + PX_ASSERT(srcMetaData); + const MetaData* dstMetaData = getBinaryMetaData(META_DATA_DST); + PX_ASSERT(dstMetaData); + + mSrcPtrSize = srcMetaData->getPtrSize(); + mDstPtrSize = dstMetaData->getPtrSize(); + + PX_ASSERT(!srcMetaData->getFlip()); + mMustFlip = dstMetaData->getFlip(); + return true; +} + +void Sn::ConvX::closeOutput() +{ + mOutStream = NULL; +} + +int Sn::ConvX::getCurrentOutputSize() +{ + return mOutputSize; +} + +void Sn::ConvX::output(short value) +{ + if(mNoOutput) + return; + + if(mMustFlip) + flip(value); + + PX_ASSERT(mOutStream); + const size_t size = mOutStream->write(&value, 2); + PX_ASSERT(size==2); + mOutputSize += int(size); +} + +void Sn::ConvX::output(int value) +{ + if(mNoOutput) + return; + + if(mMustFlip) + flip(value); + + PX_ASSERT(mOutStream); + const size_t size = mOutStream->write(&value, 4); + PX_ASSERT(size==4); + mOutputSize += int(size); +} + +//ntohll is a macro on apple yosemite +static PxU64 ntohll_internal(const PxU64 value) +{ + union + { + PxU64 ull; + PxU8 c[8]; + } x; + + x.ull = value; + + PxU8 c = 0; + c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c; + c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c; + c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c; + c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c; + + return x.ull; +} + +void Sn::ConvX::output(PxU64 value) +{ + if(mNoOutput) + return; + + if(mMustFlip) +// flip(value); + value = ntohll_internal(value); + + PX_ASSERT(mOutStream); + const size_t size = mOutStream->write(&value, 8); + PX_ASSERT(size==8); + mOutputSize += int(size); +} + +void Sn::ConvX::output(const char* buffer, int nbBytes) +{ + if(mNoOutput) + return; + + if(!nbBytes) + return; + + PX_ASSERT(mOutStream); + const PxU32 size = mOutStream->write(buffer, PxU32(nbBytes)); + PX_ASSERT(size== PxU32(nbBytes)); + mOutputSize += int(size); +} + +void Sn::ConvX::convert8(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry) +{ + (void)dstEntry; + if(mNoOutput) + return; + + PX_ASSERT(entry.mSize==1*entry.mCount); + PX_ASSERT(mOutStream); + PX_ASSERT(entry.mSize==dstEntry.mSize); + + const PxU32 size = mOutStream->write(src, PxU32(entry.mSize)); + PX_ASSERT(size== PxU32(entry.mSize)); + mOutputSize += int(size); +} + +// This is called to convert auto-generated "padding bytes" (or so we think). +// We use a special converter to check the input bytes and issue warnings when it doesn't look like padding +void Sn::ConvX::convertPad8(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry) +{ + (void)dstEntry; + (void)src; + if(mNoOutput) + return; + + PX_ASSERT(entry.mSize); + PX_ASSERT(entry.mSize==1*entry.mCount); + PX_ASSERT(mOutStream); + PX_ASSERT(entry.mSize==dstEntry.mSize); + + // PT: we don't output the source data on purpose, to catch missing meta-data + // sschirm: changed that to 0xcd, so we can mark the output as "having marked pads" + const unsigned char b = 0xcd; + for(int i=0;i<entry.mSize;i++) + { + const size_t size = mOutStream->write(&b, 1); + (void)size; + } + mOutputSize += entry.mSize; +} + +void Sn::ConvX::convert16(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry) +{ + (void)dstEntry; + if(mNoOutput) + return; + + PX_ASSERT(entry.mSize==int(sizeof(short)*entry.mCount)); + PX_ASSERT(mOutStream); + PX_ASSERT(entry.mSize==dstEntry.mSize); + + const short* data = reinterpret_cast<const short*>(src); + for(int i=0;i<entry.mCount;i++) + { + short value = *data++; + if(mMustFlip) + flip(value); + + const size_t size = mOutStream->write(&value, sizeof(short)); + PX_ASSERT(size==sizeof(short)); + mOutputSize += int(size); + } +} + +void Sn::ConvX::convert32(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry) +{ + (void)dstEntry; + if(mNoOutput) + return; + + PX_ASSERT(entry.mSize==int(sizeof(int)*entry.mCount)); + PX_ASSERT(mOutStream); + PX_ASSERT(entry.mSize==dstEntry.mSize); + + const int* data = reinterpret_cast<const int*>(src); + for(int i=0;i<entry.mCount;i++) + { + int value = *data++; + if(mMustFlip) + flip(value); + + const size_t size = mOutStream->write(&value, sizeof(int)); + PX_ASSERT(size==sizeof(int)); + mOutputSize += int(size); + } +} + +void Sn::ConvX::convert64(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry) +{ + (void)dstEntry; + if(mNoOutput) + return; + + PX_ASSERT(entry.mSize==int(sizeof(PxU64)*entry.mCount)); + PX_ASSERT(mOutStream); + PX_ASSERT(entry.mSize==dstEntry.mSize); + + const PxU64* data = reinterpret_cast<const PxU64*>(src); + for(int i=0;i<entry.mCount;i++) + { + PxU64 value = *data++; + if(mMustFlip) + value = ntohll_internal(value); + + const size_t size = mOutStream->write(&value, sizeof(PxU64)); + PX_ASSERT(size==sizeof(PxU64)); + mOutputSize += int(size); + } +} + +void Sn::ConvX::convertFloat(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry) +{ + (void)dstEntry; + if(mNoOutput) + return; + + PX_ASSERT(entry.mSize==int(sizeof(float)*entry.mCount)); + PX_ASSERT(mOutStream); + PX_ASSERT(entry.mSize==dstEntry.mSize); + + const float* data = reinterpret_cast<const float*>(src); + for(int i=0;i<entry.mCount;i++) + { + float value = *data++; + if(mMustFlip) + flip(value); + + const size_t size = mOutStream->write(&value, sizeof(float)); + PX_ASSERT(size==sizeof(float)); + mOutputSize += int(size); + } +} + +void Sn::ConvX::convertPtr(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry) +{ + (void)dstEntry; + if(mNoOutput) + return; + + PX_ASSERT(entry.mSize==mSrcPtrSize*entry.mCount); + PX_ASSERT(mOutStream); + + char buffer[16]; + for(int i=0;i<entry.mCount;i++) + { + PxU64 testValue=0; + // Src pointer can be 4 or 8 bytes so we can't use "void*" here + if(mSrcPtrSize==4) + { + PX_ASSERT(sizeof(PxU32)==4); + const PxU32* data = reinterpret_cast<const PxU32*>(src); + PxU32 value = *data++; + src = reinterpret_cast<const char*>(data); + + if(mActiveRemap) + { + PxU32 ref; + if(mActiveRemap->getObjectRef(value, ref)) + { + value = ref; + } + else if(value) + { + // value = 0; + //We use the pointer of mName for its length + // PT: on serialization mName is transformed to an index by the name manager, so we should not modify its value. + if(!entry.mName || strcmp(entry.mName, "mName")) + value=0x12345678; + } + } + else + { + //we should only get here during convertReferenceTables to build up the pointer map + PxU32 ref; + if (mRemap.getObjectRef(value, ref)) + { + value = ref; + } + else if(value) + { + const PxU32 remappedRef = 0x80000000 | (mPointerRemapCounter++ +1); + mRemap.setObjectRef(value, remappedRef); + value = remappedRef; + } + } + + if(mMustFlip) + flip(value); + + if(mNullPtr) + value = 0; + + *reinterpret_cast<PxU32*>(buffer) = value; + } + else + { + PX_ASSERT(mSrcPtrSize==8); + PX_ASSERT(sizeof(PxU64)==8); + const PxU64* data = reinterpret_cast<const PxU64*>(src); + PxU64 value = *data++; + src = reinterpret_cast<const char*>(data); + + if(mActiveRemap) + { + PxU32 ref; + if(mActiveRemap->getObjectRef(value, ref)) + { + value = ref; + } + else if(value) + { + // value = 0; + //We use the pointer of mName for its length + // PT: on serialization mName is transformed to an index by the name manager, so we should not modify its value. + if(!entry.mName || strcmp(entry.mName, "mName")) + value=0x12345678; + } + } + else + { + //we should only get here during convertReferenceTables to build up the pointer map + PxU32 ref; + if (mRemap.getObjectRef(value, ref)) + { + value = ref; + } + else if(value) + { + const PxU32 remappedRef = 0x80000000 | (mPointerRemapCounter++ +1); + mRemap.setObjectRef(value, remappedRef); + value = remappedRef; + } + } + +// PX_ASSERT(!mMustFlip); +// if(mMustFlip) +// flip(value); + + if(mNullPtr) + value = 0; + + testValue = value; + + *reinterpret_cast<PxU64*>(buffer) = value; + } + + if(mSrcPtrSize==mDstPtrSize) + { + const size_t size = mOutStream->write(buffer, PxU32(mSrcPtrSize)); + PX_ASSERT(size==PxU32(mSrcPtrSize)); + mOutputSize += int(size); + } + else + { + if(mDstPtrSize>mSrcPtrSize) + { + // 32bit to 64bit + PX_ASSERT(mDstPtrSize==8); + PX_ASSERT(mSrcPtrSize==4); + + // We need to output the lower 32bits first for PC. Might be different on a 64bit console.... + + // Output src ptr for the lower 32bits + const size_t size = mOutStream->write(buffer, PxU32(mSrcPtrSize)); + PX_ASSERT(size==PxU32(mSrcPtrSize)); + mOutputSize += int(size); + + // Output zeros for the higher 32bits + const int zero = 0; + const size_t size0 = mOutStream->write(&zero, 4); + PX_ASSERT(size0==4); + mOutputSize += int(size0); + } + else + { + // 64bit to 32bit + PX_ASSERT(mSrcPtrSize==8); + PX_ASSERT(mDstPtrSize==4); + + // Not sure how we can safely convert 64bit ptrs to 32bit... just drop the high 32 bits?!? + + PxU32 ptr32 = *reinterpret_cast<PxU32*>(buffer); + (void)ptr32; + PxU32 ptr32b = PxU32(testValue); + (void)ptr32b; + + if(mMustFlip) + flip(ptr32b); + + // Output src ptr for the lower 32bits + const size_t size = mOutStream->write(&ptr32b, 4); + PX_ASSERT(size==4); + mOutputSize += int(size); + } + } + } +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.h new file mode 100644 index 00000000..6eaf7b99 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.h @@ -0,0 +1,112 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PX_CONVX_OUTPUT_H +#define PX_CONVX_OUTPUT_H + +#include "foundation/PxSimpleTypes.h" + +namespace physx { namespace Sn { + + struct PxMetaDataEntry; + class ConvX; + + typedef void (Sn::ConvX::*ConvertCallback) (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry); + + inline_ void flip(PxI16& v) + { + PxI8* b = reinterpret_cast<PxI8*>(&v); + PxI8 temp = b[0]; + b[0] = b[1]; + b[1] = temp; + } + + inline_ void flip(PxU16& v) + { + flip(reinterpret_cast<PxI16&>(v)); + } + + inline_ void flip32(PxI8* b) + { + PxI8 temp = b[0]; + b[0] = b[3]; + b[3] = temp; + temp = b[1]; + b[1] = b[2]; + b[2] = temp; + } + + inline_ void flip(PxI32& v) + { + PxI8* b = reinterpret_cast<PxI8*>(&v); + flip32(b); + } + + inline_ void flip(PxU32& v) + { + PxI8* b = reinterpret_cast<PxI8*>(&v); + flip32(b); + } + + inline_ void flip(PxI64& v) + { + PxI8* b = reinterpret_cast<PxI8*>(&v); + + PxI8 temp = b[0]; + b[0] = b[7]; + b[7] = temp; + temp = b[1]; + b[1] = b[6]; + b[6] = temp; + temp = b[2]; + b[2] = b[5]; + b[5] = temp; + temp = b[3]; + b[3] = b[4]; + b[4] = temp; + } + + inline_ void flip(PxF32& v) + { + PxI8* b = reinterpret_cast<PxI8*>(&v); + flip32(b); + } + + inline_ void flip(void*& v) + { + PxI8* b = reinterpret_cast<PxI8*>(&v); + flip32(b); + } + + inline_ void flip(const PxI8*& v) + { + PxI8* b = const_cast<PxI8*>(v); + flip32(b); + } +} } + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.cpp new file mode 100644 index 00000000..ddff8df1 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.cpp @@ -0,0 +1,90 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#include "SnConvX.h" +#include <assert.h> + +using namespace physx; + +void Sn::ConvX::resetUnions() +{ + mUnions.clear(); +} + +bool Sn::ConvX::registerUnion(const char* name) +{ + displayMessage(PxErrorCode::eDEBUG_INFO, "Registering union: %s\n", name); + + Sn::Union u; + u.mName = name; + + mUnions.pushBack(u); + return true; +} + +bool Sn::ConvX::registerUnionType(const char* unionName, const char* typeName, int typeValue) +{ + const PxU32 nb = mUnions.size(); + for(PxU32 i=0;i<nb;i++) + { + if(strcmp(mUnions[i].mName, unionName)==0) + { + UnionType t; + t.mTypeName = typeName; + t.mTypeValue = typeValue; + mUnions[i].mTypes.pushBack(t); + displayMessage(PxErrorCode::eDEBUG_INFO, "Registering union type: %s | %s | %d\n", unionName, typeName, typeValue); + return true; + } + } + + displayMessage(PxErrorCode::eINTERNAL_ERROR, "PxBinaryConverter: union not found: %s, please check the source metadata.\n", unionName); + return false; +} + +const char* Sn::ConvX::getTypeName(const char* unionName, int typeValue) +{ + const PxU32 nb = mUnions.size(); + for(PxU32 i=0;i<nb;i++) + { + if(strcmp(mUnions[i].mName, unionName)==0) + { + const PxU32 nbTypes = mUnions[i].mTypes.size(); + for(PxU32 j=0;j<nbTypes;j++) + { + const UnionType& t = mUnions[i].mTypes[j]; + if(t.mTypeValue==typeValue) + return t.mTypeName; + } + break; + } + } + displayMessage(PxErrorCode::eINTERNAL_ERROR, + "PxBinaryConverter: union type not found: %s, type %d, please check the source metadata.\n", unionName, typeValue); + assert(0); + return NULL; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.h new file mode 100644 index 00000000..6c94a12c --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.h @@ -0,0 +1,45 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PX_UNION_H +#define PX_UNION_H + +namespace physx { namespace Sn { + struct UnionType + { + const char* mTypeName; + int mTypeValue; + }; + + struct Union + { + const char* mName; + PsArray<UnionType> mTypes; + }; +} } + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.cpp new file mode 100644 index 00000000..ef46d552 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.cpp @@ -0,0 +1,94 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PxBase.h" +#include "SnSerializationContext.h" +#include "PsFoundation.h" + +using namespace physx; +using namespace Sn; + +PxBase* DeserializationContext::resolveReference(PxU32 kind, size_t reference) const +{ + const InternalRefMap::Entry* entry0 = mInternalReferencesMap.find(InternalRefKey(reference, kind)); + PX_ASSERT(entry0); + SerialObjectIndex objIndex = entry0->second; + bool isExternal; + PxU32 index = objIndex.getIndex(isExternal); + PxBase* base = NULL; + if (isExternal) + { + const ImportReference& entry = mImportReferences[index]; + base = mExternalRefs->find(entry.id); + } + else + { + const ManifestEntry& entry = mManifestTable[index]; + base = reinterpret_cast<PxBase*>(mObjectDataAddress + entry.offset); + } + PX_ASSERT(base); + return base; +} + +void SerializationContext::registerReference(PxBase& serializable, PxU32 kind, size_t reference) +{ +#if PX_CHECKED + if ((kind & PX_SERIAL_REF_KIND_PTR_TYPE_BIT) == 0 && reference > 0xffffffff) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxSerializationContext::registerReference: only 32 bit indices supported."); + return; + } +#endif + + bool isExternal = mExternalRefs && mExternalRefs->contains(serializable); + PxU32 index; + if (isExternal) + { + PxSerialObjectId id = mExternalRefs->getId(serializable); + PX_ASSERT(id != PX_SERIAL_OBJECT_ID_INVALID); + if (const Ps::HashMap<PxSerialObjectId, PxU32>::Entry* entry = mImportReferencesMap.find(id)) + { + index = entry->second; + } + else + { + index = mImportReferences.size(); + mImportReferencesMap.insert(id, index); + mImportReferences.pushBack(ImportReference(id, serializable.getConcreteType())); + } + } + else + { + PX_ASSERT(mCollection.contains(serializable)); + index = mObjToCollectionIndexMap[&serializable]; + } + + InternalRefMap& targetMap = (kind & PX_SERIAL_REF_KIND_PTR_TYPE_BIT) ? mInternalReferencesPtrMap : mInternalReferencesIdxMap; + targetMap[InternalRefKey(reference, kind)] = SerialObjectIndex(index, isExternal); +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.h new file mode 100644 index 00000000..6bfa05e1 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.h @@ -0,0 +1,303 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_SN_SERIALIZATION_CONTEXT +#define PX_PHYSICS_SN_SERIALIZATION_CONTEXT + +#include "foundation/PxAssert.h" +#include "foundation/PxMemory.h" +#include "CmPhysXCommon.h" +#include "PsHash.h" +#include "PsUserAllocated.h" +#include "PxSerialFramework.h" +#include "CmCollection.h" +#include "CmUtils.h" +#include "PxDefaultStreams.h" +#include "PsFoundation.h" +#include "SnConvX_Align.h" + +namespace physx +{ + namespace Sn + { + + struct ManifestEntry + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + + PX_FORCE_INLINE ManifestEntry(PxU32 _offset, PxType _type) + { + Cm::markSerializedMem(this, sizeof(ManifestEntry)); + offset = _offset; + type = _type; + } + PX_FORCE_INLINE ManifestEntry() { Cm::markSerializedMem(this, sizeof(ManifestEntry)); } + PX_FORCE_INLINE void operator =(const ManifestEntry& m) + { + PxMemCopy(this, &m, sizeof(ManifestEntry)); + } + + PxU32 offset; + PxType type; + }; + + struct ImportReference + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + + PX_FORCE_INLINE ImportReference(PxSerialObjectId _id, PxType _type) + { + Cm::markSerializedMem(this, sizeof(ImportReference)); + id = _id; + type = _type; + } + PX_FORCE_INLINE ImportReference() { Cm::markSerializedMem(this, sizeof(ImportReference)); } + PX_FORCE_INLINE void operator =(const ImportReference& m) + { + PxMemCopy(this, &m, sizeof(ImportReference)); + } + PxSerialObjectId id; + PxType type; + }; + +#define SERIAL_OBJECT_INDEX_TYPE_BIT (1u<<31) + struct SerialObjectIndex + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + + PX_FORCE_INLINE SerialObjectIndex(PxU32 index, bool external) { setIndex(index, external); } + PX_FORCE_INLINE SerialObjectIndex(const SerialObjectIndex& objIndex) : mObjIndex(objIndex.mObjIndex) {} + PX_FORCE_INLINE SerialObjectIndex() : mObjIndex(PX_INVALID_U32) {} + + PX_FORCE_INLINE void setIndex(PxU32 index, bool external) + { + PX_ASSERT((index & SERIAL_OBJECT_INDEX_TYPE_BIT) == 0); + mObjIndex = index | (external ? SERIAL_OBJECT_INDEX_TYPE_BIT : 0); + } + + PX_FORCE_INLINE PxU32 getIndex(bool& isExternal) + { + PX_ASSERT(mObjIndex != PX_INVALID_U32); + isExternal = (mObjIndex & SERIAL_OBJECT_INDEX_TYPE_BIT) > 0; + return mObjIndex & ~SERIAL_OBJECT_INDEX_TYPE_BIT; + } + + private: + PxU32 mObjIndex; + }; + + struct ExportReference + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + + PX_FORCE_INLINE ExportReference(PxSerialObjectId _id, SerialObjectIndex _objIndex) + { + Cm::markSerializedMem(this, sizeof(ExportReference)); + id = _id; + objIndex = _objIndex; + } + PX_FORCE_INLINE ExportReference() { Cm::markSerializedMem(this, sizeof(ExportReference)); } + PX_FORCE_INLINE void operator =(const ExportReference& m) + { + PxMemCopy(this, &m, sizeof(ExportReference)); + } + PxSerialObjectId id; + SerialObjectIndex objIndex; + }; + + template<class ReferenceType> + struct InternalReference + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + + PX_FORCE_INLINE InternalReference(ReferenceType _reference, PxU32 _kind, SerialObjectIndex _objIndex) + { + Cm::markSerializedMem(this, sizeof(InternalReference)); + reference = _reference; + kind = _kind; + objIndex = _objIndex; + } + PX_FORCE_INLINE InternalReference() { Cm::markSerializedMem(this, sizeof(InternalReference)); } + PX_FORCE_INLINE void operator =(const InternalReference& m) + { + PxMemCopy(this, &m, sizeof(InternalReference)); + } + ReferenceType reference; + PxU32 kind; + SerialObjectIndex objIndex; + }; + + typedef InternalReference<size_t> InternalReferencePtr; + typedef InternalReference<PxU32> InternalReferenceIdx; + + typedef shdfnd::Pair<size_t, PxU32> InternalRefKey; + typedef Cm::CollectionHashMap<InternalRefKey, SerialObjectIndex> InternalRefMap; + + class DeserializationContext : public PxDeserializationContext, public Ps::UserAllocated + { + PX_NOCOPY(DeserializationContext) + + public: + DeserializationContext(const ManifestEntry* manifestTable, + const ImportReference* importReferences, + PxU8* objectDataAddress, + const InternalRefMap& internalReferencesMap, + const Cm::Collection* externalRefs, + PxU8* extraData, + PxU32 physxVersion) + : mManifestTable(manifestTable) + , mImportReferences(importReferences) + , mObjectDataAddress(objectDataAddress) + , mInternalReferencesMap(internalReferencesMap) + , mExternalRefs(externalRefs) + , mPhysXVersion(physxVersion) + { + mExtraDataAddress = extraData; + } + + virtual PxBase* resolveReference(PxU32 kind, size_t reference) const; + + PxU32 getPhysXVersion() const { return mPhysXVersion; } + private: + //various pointers to deserialized data + const ManifestEntry* mManifestTable; + const ImportReference* mImportReferences; + PxU8* mObjectDataAddress; + + //internal references map for resolving references. + const InternalRefMap& mInternalReferencesMap; + + //external collection for resolving import references. + const Cm::Collection* mExternalRefs; + const PxU32 mPhysXVersion; + }; + + class SerializationContext : public PxSerializationContext, public Ps::UserAllocated + { + PX_NOCOPY(SerializationContext) + public: + SerializationContext(const Cm::Collection& collection, const Cm::Collection* externalRefs) + : mCollection(collection) + , mExternalRefs(externalRefs) + { + // fill object to collection index map (same ordering as manifest) + for (PxU32 i=0;i<mCollection.internalGetNbObjects();i++) + { + mObjToCollectionIndexMap[mCollection.internalGetObject(i)] = i; + } + } + + virtual void writeData(const void* buffer, PxU32 size) { mMemStream.write(buffer, size); } + virtual PxU32 getTotalStoredSize() { return mMemStream.getSize(); } + virtual void alignData(PxU32 alignment = PX_SERIAL_ALIGN) + { + if(!alignment) + return; + + PxI32 bytesToPad = PxI32(getPadding(mMemStream.getSize(), alignment)); + static const PxI32 BUFSIZE = 64; + char buf[BUFSIZE]; + PxMemSet(buf, 0, bytesToPad < BUFSIZE ? PxU32(bytesToPad) : PxU32(BUFSIZE)); + while(bytesToPad > 0) + { + mMemStream.write(buf, bytesToPad < BUFSIZE ? PxU32(bytesToPad) : PxU32(BUFSIZE)); + bytesToPad -= BUFSIZE; + } + PX_ASSERT(!getPadding(getTotalStoredSize(), alignment)); + } + + virtual void writeName(const char*) + { + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, + "Cannot export names during exportData."); + } + + const PxCollection& getCollection() const { return mCollection; } + + virtual void registerReference(PxBase& serializable, PxU32 kind, size_t reference); + + const Ps::Array<ImportReference>& getImportReferences() { return mImportReferences; } + InternalRefMap& getInternalReferencesPtrMap() { return mInternalReferencesPtrMap; } + InternalRefMap& getInternalReferencesIdxMap() { return mInternalReferencesIdxMap; } + + PxU32 getSize() const { return mMemStream.getSize(); } + PxU8* getData() const { return mMemStream.getData(); } + + + + private: + //import reference map for unique registration of import references and corresponding buffer. + Ps::HashMap<PxSerialObjectId, PxU32> mImportReferencesMap; + Ps::Array<ImportReference> mImportReferences; + + //maps for unique registration of internal references + InternalRefMap mInternalReferencesPtrMap; + InternalRefMap mInternalReferencesIdxMap; + + //map for quick lookup of manifest index. + Ps::HashMap<const PxBase*, PxU32> mObjToCollectionIndexMap; + + //collection and externalRefs collection for assigning references. + const Cm::Collection& mCollection; + const Cm::Collection* mExternalRefs; + + PxDefaultMemoryOutputStream mMemStream; + + }; + + } // namespace Sn +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/File/SnFile.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/File/SnFile.h new file mode 100644 index 00000000..0c5a817e --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/File/SnFile.h @@ -0,0 +1,85 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef SN_FILE_H +#define SN_FILE_H + +// fopen_s - returns 0 on success, non-zero on failure + +#if PX_MICROSOFT_FAMILY + +#include <stdio.h> + +namespace physx +{ +namespace sn +{ +PX_INLINE PxI32 fopen_s(FILE** file, const char* name, const char* mode) +{ + static const PxU32 MAX_LEN = 300; + char buf[MAX_LEN+1]; + + PxU32 i; + for(i = 0; i<MAX_LEN && name[i]; i++) + buf[i] = name[i] == '/' ? '\\' : name[i]; + buf[i] = 0; + + return i == MAX_LEN ? -1 : ::fopen_s(file, buf, mode); +}; + +} // namespace sn +} // namespace physx + +#elif PX_UNIX_FAMILY || PX_PS4 + +#include <stdio.h> + +namespace physx +{ +namespace sn +{ +PX_INLINE PxI32 fopen_s(FILE** file, const char* name, const char* mode) +{ + FILE* fp = ::fopen(name, mode); + if(fp) + { + *file = fp; + return PxI32(0); + } + return -1; +} +} // namespace sn +} // namespace physx +#else +#error "Platform not supported!" +#endif + +#endif //SN_FILE_H + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialUtils.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialUtils.cpp new file mode 100644 index 00000000..1a147058 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialUtils.cpp @@ -0,0 +1,151 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "SnSerialUtils.h" +#include "PsString.h" +#include "PxSerialization.h" +#include "PxPhysicsVersion.h" +#include "PsBasicTemplates.h" + +using namespace physx; + +namespace +{ + +#define SN_NUM_BINARY_PLATFORMS 11 +const PxU32 sBinaryPlatformTags[SN_NUM_BINARY_PLATFORMS] = +{ + PX_MAKE_FOURCC('W','_','3','2'), + PX_MAKE_FOURCC('W','_','6','4'), + PX_MAKE_FOURCC('L','_','3','2'), + PX_MAKE_FOURCC('L','_','6','4'), + PX_MAKE_FOURCC('M','_','3','2'), + PX_MAKE_FOURCC('M','_','6','4'), + PX_MAKE_FOURCC('M','O','C','A'), + PX_MAKE_FOURCC('A','N','D','R'), + PX_MAKE_FOURCC('A','I','O','S'), + PX_MAKE_FOURCC('A','A','6','4'), + PX_MAKE_FOURCC('X','O','N','E') +}; + +const char* sBinaryPlatformNames[SN_NUM_BINARY_PLATFORMS] = +{ + "win32", + "win64", + "linux32", + "linux64", + "macOSX32", + "macOSX64", + "ps4", + "android", + "ios", + "ios64", + "xboxone" +}; + +#define SN_NUM_BINARY_COMPATIBLE_VERSIONS 1 + +// +// Important: if you adjust the following structure, please adjust the comment for PX_BINARY_SERIAL_VERSION as well +// +const Ps::Pair<PxU32, PxU32> sBinaryCompatibleVersions[SN_NUM_BINARY_COMPATIBLE_VERSIONS] = +{ + Ps::Pair<PxU32, PxU32>(PX_PHYSICS_VERSION, PX_BINARY_SERIAL_VERSION) +}; + +} + +namespace physx { namespace Sn { + +PxU32 getBinaryPlatformTag() +{ +#if PX_WINDOWS && PX_X86 + return sBinaryPlatformTags[0]; +#elif PX_WINDOWS && PX_X64 + return sBinaryPlatformTags[1]; +#elif PX_LINUX && (PX_X86 || PX_ARM) + return sBinaryPlatformTags[2]; +#elif PX_LINUX && (PX_X64 || PX_A64) + return sBinaryPlatformTags[3]; +#elif PX_OSX && PX_X86 + return sBinaryPlatformTags[4]; +#elif PX_OSX && PX_X64 + return sBinaryPlatformTags[5]; +#elif PX_PS4 + return sBinaryPlatformTags[6]; +#elif PX_ANDROID + return sBinaryPlatformTags[7]; +#elif PX_IOS && PX_ARM + return sBinaryPlatformTags[8]; +#elif PX_IOS && PX_A64 + return sBinaryPlatformTags[9]; +#elif PX_XBOXONE + return sBinaryPlatformTags[10]; +#else + #error Unknown binary platform +#endif +} + +bool isBinaryPlatformTagValid(physx::PxU32 platformTag) +{ + PxU32 platformIndex = 0; + while (platformIndex < SN_NUM_BINARY_PLATFORMS && platformTag != sBinaryPlatformTags[platformIndex]) platformIndex++; + return platformIndex < SN_NUM_BINARY_PLATFORMS; +} + +const char* getBinaryPlatformName(physx::PxU32 platformTag) +{ + PxU32 platformIndex = 0; + while (platformIndex < SN_NUM_BINARY_PLATFORMS && platformTag != sBinaryPlatformTags[platformIndex]) platformIndex++; + return (platformIndex == SN_NUM_BINARY_PLATFORMS) ? "unknown" : sBinaryPlatformNames[platformIndex]; +} + +bool checkCompatibility(const PxU32 version, const PxU32 binaryVersion) +{ + for(PxU32 i =0; i<SN_NUM_BINARY_COMPATIBLE_VERSIONS; i++) + { + if(version == sBinaryCompatibleVersions[i].first && binaryVersion == sBinaryCompatibleVersions[i].second) + return true; + } + return false; +} + +void getCompatibilityVersionsStr(char* buffer, PxU32 lenght) +{ + size_t len = 0; + for(PxU32 i =0; i<SN_NUM_BINARY_COMPATIBLE_VERSIONS; i++) + { + physx::shdfnd::snprintf(buffer + len, lenght - len, "%x-%d\n", sBinaryCompatibleVersions[i].first, sBinaryCompatibleVersions[i].second); + len = strlen(buffer); + } +} + +} // Sn +} // physx + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialUtils.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialUtils.h new file mode 100644 index 00000000..31aa3944 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialUtils.h @@ -0,0 +1,50 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_SN_SERIAL_UTILS +#define PX_PHYSICS_SN_SERIAL_UTILS + +#include "CmPhysXCommon.h" + +namespace physx +{ + +namespace Sn +{ + PxU32 getBinaryPlatformTag(); + bool isBinaryPlatformTagValid(PxU32 platformTag); + const char* getBinaryPlatformName(PxU32 platformTag); + bool checkCompatibility(const PxU32 version, const PxU32 binaryVersion); + void getCompatibilityVersionsStr(char* buffer, PxU32 lenght); +} + +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialization.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialization.cpp new file mode 100644 index 00000000..15edeb46 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialization.cpp @@ -0,0 +1,433 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PxPhysicsAPI.h" +#include "PxConstraintExt.h" +#include "PxPhysicsVersion.h" +#include "PsFoundation.h" +#include "PxMetaData.h" +#include "SnConvX.h" +#include "SnSerializationRegistry.h" +#include "SnSerialUtils.h" +#include "ExtSerialization.h" +#include "PxSerializer.h" +#include "CmCollection.h" + +using namespace physx; +using namespace Sn; + +namespace +{ + struct RequiresCallback : public PxProcessPxBaseCallback + { + RequiresCallback(physx::PxCollection& c) : collection(c) {} + void process(PxBase& base) + { + if(!collection.contains(base)) + collection.add(base); + } + + PxCollection& collection; + PX_NOCOPY(RequiresCallback) + }; + + struct CompleteCallback : public PxProcessPxBaseCallback + { + CompleteCallback(physx::PxCollection& r, physx::PxCollection& c, const physx::PxCollection* e) : + requires(r), complete(c), external(e) {} + void process(PxBase& base) + { + if(complete.contains(base) || (external && external->contains(base))) + return; + if(!requires.contains(base)) + requires.add(base); + } + + PxCollection& requires; + PxCollection& complete; + const PxCollection* external; + PX_NOCOPY(CompleteCallback) + }; + + void getRequiresCollection(PxCollection& requires, PxCollection& collection, PxCollection& complete, const PxCollection* external, PxSerializationRegistry& sr, bool followJoints) + { + CompleteCallback callback(requires, complete, external); + for (PxU32 i = 0; i < collection.getNbObjects(); ++i) + { + PxBase& s = collection.getObject(i); + const PxSerializer* serializer = sr.getSerializer(s.getConcreteType()); + PX_ASSERT(serializer); + serializer->requires(s, callback); + + if(followJoints) + { + PxRigidActor* actor = s.is<PxRigidActor>(); + if(actor) + { + Ps::Array<PxConstraint*> objects(actor->getNbConstraints()); + actor->getConstraints(objects.begin(), objects.size()); + + for(PxU32 j=0;j<objects.size();j++) + { + PxU32 typeId; + PxJoint* joint = reinterpret_cast<PxJoint*>(objects[j]->getExternalReference(typeId)); + if(typeId == PxConstraintExtIDs::eJOINT) + { + const PxSerializer* sj = sr.getSerializer(joint->getConcreteType()); + PX_ASSERT(sj); + sj->requires(*joint, callback); + if(!requires.contains(*joint)) + requires.add(*joint); + } + } + } + } + } + } +} + +bool PxSerialization::isSerializable(PxCollection& collection, PxSerializationRegistry& sr, const PxCollection* externalReferences) +{ + PxCollection* subordinateCollection = PxCreateCollection(); + PX_ASSERT(subordinateCollection); + + for(PxU32 i = 0; i < collection.getNbObjects(); ++i) + { + PxBase& s = collection.getObject(i); + const PxSerializer* serializer = sr.getSerializer(s.getConcreteType()); + PX_ASSERT(serializer); + if(serializer->isSubordinate()) + subordinateCollection->add(s); + + if(externalReferences) + { + PxSerialObjectId id = collection.getId(s); + if(id != PX_SERIAL_OBJECT_ID_INVALID) + { + PxBase* object = externalReferences->find(id); + if(object && (object != &s)) + { + subordinateCollection->release(); + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "PxSerialization::isSerializable: Reference id %" PX_PRIu64 " used both in current collection and in externalReferences. " + "Please use unique identifiers.", id); + return false; + } + } + } + } + + PxCollection* requiresCollection = PxCreateCollection(); + PX_ASSERT(requiresCollection); + + RequiresCallback requiresCallback0(*requiresCollection); + + for (PxU32 i = 0; i < collection.getNbObjects(); ++i) + { + PxBase& s = collection.getObject(i); + const PxSerializer* serializer = sr.getSerializer(s.getConcreteType()); + PX_ASSERT(serializer); + serializer->requires(s, requiresCallback0); + + Cm::Collection* cmRequiresCollection = static_cast<Cm::Collection*>(requiresCollection); + + for(PxU32 j = 0; j < cmRequiresCollection->getNbObjects(); ++j) + { + PxBase& s0 = cmRequiresCollection->getObject(j); + + if(subordinateCollection->contains(s0)) + { + subordinateCollection->remove(s0); + continue; + } + + bool requiredIsInCollection = collection.contains(s0); + if(!requiredIsInCollection) + { + if(externalReferences) + { + if(!externalReferences->contains(s0)) + { + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "PxSerialization::isSerializable: Object of type %s references a missing object of type %s. " + "The missing object needs to be added to either the current collection or the externalReferences collection.", + s.getConcreteTypeName(), s0.getConcreteTypeName()); + } + else if(externalReferences->getId(s0) == PX_SERIAL_OBJECT_ID_INVALID) + { + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "PxSerialization::isSerializable: Object of type %s in externalReferences collection requires an id.", + s0.getConcreteTypeName()); + } + else + continue; + } + else + { + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "PxSerialization::isSerializable: Object of type %s references a missing serial object of type %s. " + "Please completed the collection or specify an externalReferences collection containing the object.", + s.getConcreteTypeName(), s0.getConcreteTypeName()); + } + subordinateCollection->release(); + requiresCollection->release(); + return false; + } + } + cmRequiresCollection->mObjects.clear(); + } + requiresCollection->release(); + + PxU32 numOrphans = subordinateCollection->getNbObjects(); + + for(PxU32 j = 0; j < numOrphans; ++j) + { + PxBase& subordinate = subordinateCollection->getObject(j); + + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "PxSerialization::isSerializable: An object of type %s is subordinate but not required " + "by other objects in the collection (orphan). Please remove the object from the collection or add its owner.", + subordinate.getConcreteTypeName()); + } + + subordinateCollection->release(); + + if(numOrphans>0) + return false; + + if(externalReferences) + { + PxCollection* oppositeRequiresCollection = PxCreateCollection(); + PX_ASSERT(oppositeRequiresCollection); + + RequiresCallback requiresCallback(*oppositeRequiresCollection); + + for (PxU32 i = 0; i < externalReferences->getNbObjects(); ++i) + { + PxBase& s = externalReferences->getObject(i); + const PxSerializer* serializer = sr.getSerializer(s.getConcreteType()); + PX_ASSERT(serializer); + serializer->requires(s, requiresCallback); + + Cm::Collection* cmCollection = static_cast<Cm::Collection*>(oppositeRequiresCollection); + + for(PxU32 j = 0; j < cmCollection->getNbObjects(); ++j) + { + PxBase& s0 = cmCollection->getObject(j); + + if(collection.contains(s0)) + { + oppositeRequiresCollection->release(); + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "PxSerialization::isSerializable: Object of type %s in externalReferences references an object " + "of type %s in collection (circular dependency).", + s.getConcreteTypeName(), s0.getConcreteTypeName()); + return false; + } + } + cmCollection->mObjects.clear(); + } + oppositeRequiresCollection->release(); + } + + return true; +} + +void PxSerialization::complete(PxCollection& collection, PxSerializationRegistry& sr, const PxCollection* exceptFor, bool followJoints) +{ + PxCollection* curCollection = PxCreateCollection(); + PX_ASSERT(curCollection); + curCollection->add(collection); + + PxCollection* requiresCollection = PxCreateCollection(); + PX_ASSERT(requiresCollection); + + do + { + getRequiresCollection(*requiresCollection, *curCollection, collection, exceptFor, sr, followJoints); + + collection.add(*requiresCollection); + PxCollection* swap = curCollection; + curCollection = requiresCollection; + requiresCollection = swap; + (static_cast<Cm::Collection*>(requiresCollection))->mObjects.clear(); + + }while(curCollection->getNbObjects() > 0); + + requiresCollection->release(); + curCollection->release(); + +} + +void PxSerialization::createSerialObjectIds(PxCollection& collection, const PxSerialObjectId base) +{ + PxSerialObjectId localBase = base; + PxU32 nbObjects = collection.getNbObjects(); + + for (PxU32 i = 0; i < nbObjects; ++i) + { + while(collection.find(localBase)) + { + localBase++; + } + + PxBase& s = collection.getObject(i); + if(PX_SERIAL_OBJECT_ID_INVALID == collection.getId(s)) + { + collection.addId(s, localBase); + localBase++; + } + } +} + +namespace physx { namespace Sn +{ + static PxU32 addToStringTable(physx::shdfnd::Array<char>& stringTable, const char* str) + { + if(!str) + return 0xffffffff; + + PxI32 length = PxI32(stringTable.size()); + const char* table = stringTable.begin(); + const char* start = table; + while(length) + { + if(strcmp(table, str)==0) + return PxU32(table - start); + + const char* saved = table; + while(*table++); + length -= PxU32(table - saved); + PX_ASSERT(length>=0); + } + + const PxU32 offset = stringTable.size(); + + while(*str) + stringTable.pushBack(*str++); + stringTable.pushBack(0); + return offset; + } +} } + +void PxSerialization::dumpBinaryMetaData(PxOutputStream& outputStream, PxSerializationRegistry& sr) +{ + class MetaDataStream : public PxOutputStream + { + public: + bool addNewType(const char* typeName) + { + for(PxU32 i=0;i<types.size();i++) + { + if(strcmp(types[i], typeName)==0) + return false; + } + types.pushBack(typeName); + return true; + } + virtual PxU32 write(const void* src, PxU32 count) + { + PX_ASSERT(count==sizeof(PxMetaDataEntry)); + const PxMetaDataEntry* entry = reinterpret_cast<const PxMetaDataEntry*>(src); + if(( entry->flags & PxMetaDataFlag::eTYPEDEF) || ((entry->flags & PxMetaDataFlag::eCLASS) && (!entry->name)) ) + newType = addNewType(entry->type); + if(newType) + metaData.pushBack(*entry); + return count; + } + shdfnd::Array<PxMetaDataEntry> metaData; + shdfnd::Array<const char*> types; + bool newType; + }s; + + SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr); + sn.getBinaryMetaData(s); + + shdfnd::Array<char> stringTable; + + PxU32 nb = s.metaData.size(); + PxMetaDataEntry* entries = s.metaData.begin(); + for(PxU32 i=0;i<nb;i++) + { + entries[i].type = reinterpret_cast<const char*>(size_t(addToStringTable(stringTable, entries[i].type))); + entries[i].name = reinterpret_cast<const char*>(size_t(addToStringTable(stringTable, entries[i].name))); + } + + PxU32 platformTag = getBinaryPlatformTag(); + +#if PX_X64 + const PxU32 gaussMapLimit = PxGetGaussMapVertexLimitForPlatform(PxPlatform::ePC); +#endif +#if PX_X86 || defined(__CYGWIN__) + const PxU32 gaussMapLimit = PxGetGaussMapVertexLimitForPlatform(PxPlatform::ePC); +#endif +#if PX_ARM_FAMILY + const PxU32 gaussMapLimit = PxGetGaussMapVertexLimitForPlatform(PxPlatform::eARM); +#endif + + const PxU32 header = PX_MAKE_FOURCC('M','E','T','A'); + const PxU32 version = PX_PHYSICS_VERSION; + const PxU32 binaryVersion = PX_BINARY_SERIAL_VERSION; + const PxU32 ptrSize = sizeof(void*); + PxU32 buildNumber = 0; +#if defined(PX_BUILD_NUMBER) + buildNumber = PX_BUILD_NUMBER; +#endif + outputStream.write(&header, 4); + outputStream.write(&version, 4); + outputStream.write(&binaryVersion, 4); + outputStream.write(&buildNumber, 4); + outputStream.write(&ptrSize, 4); + outputStream.write(&platformTag, 4); + outputStream.write(&gaussMapLimit, 4); + + outputStream.write(&nb, 4); + outputStream.write(entries, nb*sizeof(PxMetaDataEntry)); + + //concreteTypes to name + PxU32 num = sn.getNbSerializers(); + outputStream.write(&num, 4); + for(PxU32 i=0; i<num; i++) + { + PxU16 type = sn.getSerializerType(i); + PxU32 nameOffset = addToStringTable(stringTable, sn.getSerializerName(i)); + outputStream.write(&type, 2); + outputStream.write(&nameOffset, 4); + } + + PxU32 length = stringTable.size(); + const char* table = stringTable.begin(); + outputStream.write(&length, 4); + outputStream.write(table, length); +} + +PxBinaryConverter* PxSerialization::createBinaryConverter() +{ + return PX_NEW(ConvX)(); +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerializationRegistry.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerializationRegistry.cpp new file mode 100644 index 00000000..091f7e08 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerializationRegistry.cpp @@ -0,0 +1,287 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "SnSerializationRegistry.h" +#include "PxPhysics.h" +#include "PxPhysicsSerialization.h" +#include "ExtSerialization.h" +#include "PxSerializer.h" +#include "CmCollection.h" +#include "PxArticulationLink.h" +#include "PsFoundation.h" +#include "PsString.h" + +using namespace physx; + +namespace +{ + class CollectionSorter : public PxProcessPxBaseCallback + { + typedef Ps::Pair<PxBase*, PxSerialObjectId> Object; + + class Element + { + public: + Object object; + Ps::Array<PxU32> children; + bool isFinished; + + Element(PxBase* obj = NULL) : object(obj, PX_SERIAL_OBJECT_ID_INVALID), isFinished(false) {} + }; + + public: + CollectionSorter(Cm::Collection& collection, Sn::SerializationRegistry& sr, bool isRepx) : mCollection(collection), mSr(sr), mIsRepx(isRepx) {} + virtual ~CollectionSorter(){} + + void process(PxBase& base) + { + addChild(&base); + //ArticulationLink is not a repx serializer, so should require Articulation here + if( mIsRepx && PxConcreteType::eARTICULATION_LINK == base.getConcreteType() ) + { + PxArticulationLink* link = static_cast<PxArticulationLink*>(&base); + PxBase* a = reinterpret_cast<PxBase*>(&link->getArticulation()); + if(mCurElement->object.first != a ) //don't require itself + addChild(a); + } + } + + void sort() + { + Element element; + PxU32 i; + + PxU32 nbObject = mCollection.internalGetNbObjects(); + const Cm::Collection::ObjectToIdMap::Entry* objectdatas = mCollection.internalGetObjects(); + for( i = 0; i < nbObject; ++i ) + { + element.object.first = objectdatas[i].first; + element.object.second = objectdatas[i].second; + mObjToIdMap.insert(objectdatas[i].first, mElements.size()); + mElements.pushBack(element); + } + + for( i = 0; i < nbObject; ++i ) + { + mCurElement = &mElements[i]; + const PxSerializer* serializer = mSr.getSerializer(mCurElement->object.first->getConcreteType()); + PX_ASSERT(serializer); + serializer->requires(*mCurElement->object.first, *this); + } + + for( i = 0; i < nbObject; ++i ) + { + if( mElements[i].isFinished ) + continue; + + AddElement(mElements[i]); + } + + mCollection.mObjects.clear(); + for(Ps::Array<Object>::Iterator o = mSorted.begin(); o != mSorted.end(); ++o ) + { + mCollection.internalAdd(o->first, o->second); + } + } + + void AddElement(Element& e) + { + if( !e.isFinished ) + { + for( Ps::Array<PxU32>::Iterator child = e.children.begin(); child != e.children.end(); ++child ) + { + AddElement(mElements[*child]); + } + mSorted.pushBack(e.object); + e.isFinished = true; + } + } + + private: + PX_INLINE void addChild(PxBase* base) + { + PX_ASSERT(mCurElement); + const Ps::HashMap<PxBase*, PxU32>::Entry* entry = mObjToIdMap.find(base); + if(entry) + mCurElement->children.pushBack(entry->second); + } + + CollectionSorter& operator=(const CollectionSorter&); + Ps::HashMap<PxBase*, PxU32> mObjToIdMap; + Ps::Array<Element> mElements; + Cm::Collection& mCollection; + Sn::SerializationRegistry& mSr; + Ps::Array<Object> mSorted; + Element* mCurElement; + bool mIsRepx; + }; +} + +namespace physx { namespace Sn { + +SerializationRegistry::SerializationRegistry(PxPhysics& physics) + : mPhysics(physics) +{ + PxRegisterPhysicsSerializers(*this); + Ext::RegisterExtensionsSerializers(*this); + + registerBinaryMetaDataCallback(PxGetPhysicsBinaryMetaData); + registerBinaryMetaDataCallback(Ext::GetExtensionsBinaryMetaData); +} + +SerializationRegistry::~SerializationRegistry() +{ + PxUnregisterPhysicsSerializers(*this); + Ext::UnregisterExtensionsSerializers(*this); + + if(mSerializers.size() > 0) + { + shdfnd::getFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "PxSerializationRegistry::release(): some registered PxSerializer instances were not unregistered"); + } + + if(mRepXSerializers.size() > 0) + { + shdfnd::getFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "PxSerializationRegistry::release(): some registered PxRepXSerializer instances were not unregistered"); + } +} + +void SerializationRegistry::registerSerializer(PxType type, PxSerializer& serializer) +{ + if(mSerializers.find(type)) + { + shdfnd::getFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "PxSerializationRegistry::registerSerializer: Type %d has already been registered", type); + } + + mSerializers.insert(type, &serializer); +} + +PxSerializer* SerializationRegistry::unregisterSerializer(PxType type) +{ + const SerializerMap::Entry* e = mSerializers.find(type); + PxSerializer* s = e ? e->second : NULL; + + if(!mSerializers.erase(type)) + { + shdfnd::getFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "PxSerializationRegistry::unregisterSerializer: failed to find PxSerializer instance for type %d", type); + } + return s; +} + +const PxSerializer* SerializationRegistry::getSerializer(PxType type) const +{ + const SerializerMap::Entry* e = mSerializers.find(type); +#if PX_CHECKED + if (!e) + { + shdfnd::getFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "PxSerializationRegistry::getSerializer: failed to find PxSerializer instance for type %d", type); + } +#endif + return e ? e->second : NULL; +} + +PxType SerializationRegistry::getSerializerType(PxU32 index) const +{ + PX_ASSERT(index < mSerializers.size()); + return mSerializers.getEntries()[index].first; +} + +const char* SerializationRegistry::getSerializerName(PxU32 index) const +{ + PX_ASSERT(index < mSerializers.size()); + return mSerializers.getEntries()[index].second->getConcreteTypeName(); +} + +void SerializationRegistry::registerBinaryMetaDataCallback(PxBinaryMetaDataCallback callback) +{ + mMetaDataCallbacks.pushBack(callback); +} + +void SerializationRegistry::getBinaryMetaData(PxOutputStream& stream) const +{ + for(PxU32 i = 0; i < mMetaDataCallbacks.size(); i++) + { + mMetaDataCallbacks[i](stream); + } +} + +void SerializationRegistry::registerRepXSerializer(PxType type, PxRepXSerializer& serializer) +{ + if(mRepXSerializers.find(type)) + { + shdfnd::getFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "PxSerializationRegistry::registerRepXSerializer: Type %d has already been registered", type); + } + + mRepXSerializers.insert(type, &serializer); +} + +PxRepXSerializer* SerializationRegistry::getRepXSerializer(const char* typeName) const +{ + SerializationRegistry* sr = const_cast<SerializationRegistry*>(this); + for( RepXSerializerMap::Iterator iter = sr->mRepXSerializers.getIterator(); !iter.done(); ++iter) + { + if ( physx::shdfnd::stricmp( iter->second->getTypeName(), typeName ) == 0 ) + return iter->second; + } + return NULL; +} + +PxRepXSerializer* SerializationRegistry::unregisterRepXSerializer(PxType type) +{ + const RepXSerializerMap::Entry* e = mRepXSerializers.find(type); + PxRepXSerializer* s = e ? e->second : NULL; + + if(!mRepXSerializers.erase(type)) + { + shdfnd::getFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "PxSerializationRegistry::unregisterRepXSerializer: failed to find PxRepXSerializer instance for type %d", type); + } + return s; +} + +void sortCollection(Cm::Collection& collection, SerializationRegistry& sr, bool isRepx) +{ + CollectionSorter sorter(collection, sr, isRepx); + sorter.sort(); +} + +} // Sn + +PxSerializationRegistry* PxSerialization::createSerializationRegistry(PxPhysics& physics) +{ + return PX_NEW(Sn::SerializationRegistry)(physics); +} + +} // physx + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerializationRegistry.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerializationRegistry.h new file mode 100644 index 00000000..6aa21c24 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerializationRegistry.h @@ -0,0 +1,91 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#ifndef PX_PHYSICS_SN_SERIALIZATION_REGISTRY +#define PX_PHYSICS_SN_SERIALIZATION_REGISTRY + +#include "PxSerialization.h" +#include "PxRepXSerializer.h" +#include "CmPhysXCommon.h" +#include "PsUserAllocated.h" +#include "PsArray.h" +#include "PsHashMap.h" + +namespace physx +{ + +namespace Cm { class Collection; } + +namespace Sn { + + class SerializationRegistry : public PxSerializationRegistry, public Ps::UserAllocated + { + public: + SerializationRegistry(PxPhysics& physics); + virtual ~SerializationRegistry(); + + virtual void release(){ PX_DELETE(this); } + + PxPhysics& getPhysics() const { return mPhysics; } + + //binary + void registerSerializer(PxType type, PxSerializer& serializer); + PxSerializer* unregisterSerializer(PxType type); + void registerBinaryMetaDataCallback(PxBinaryMetaDataCallback callback); + void getBinaryMetaData(PxOutputStream& stream) const; + const PxSerializer* getSerializer(PxType type) const; + const char* getSerializerName(PxU32 index) const; + PxType getSerializerType(PxU32 index) const; + PxU32 getNbSerializers() const { return mSerializers.size(); } + //repx + void registerRepXSerializer(PxType type, PxRepXSerializer& serializer); + PxRepXSerializer* getRepXSerializer(const char* typeName) const; + PxRepXSerializer* unregisterRepXSerializer(PxType type); + + protected: + SerializationRegistry &operator=(const SerializationRegistry &); + private: + typedef Ps::CoalescedHashMap<PxType, PxSerializer*> SerializerMap; + typedef Ps::HashMap<PxType, PxRepXSerializer*> RepXSerializerMap; + + PxPhysics& mPhysics; + SerializerMap mSerializers; + RepXSerializerMap mRepXSerializers; + Ps::Array<PxBinaryMetaDataCallback> mMetaDataCallbacks; + }; + + void sortCollection(Cm::Collection& collection, SerializationRegistry& sr, bool isRepx); +} // Sn + +} // physx + + + +#endif + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnJointRepXSerializer.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnJointRepXSerializer.cpp new file mode 100644 index 00000000..94d60453 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnJointRepXSerializer.cpp @@ -0,0 +1,137 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#include "PxMetaDataObjects.h" +#include "PxExtensionMetaDataObjects.h" +#include "ExtJointMetaDataExtensions.h" +#include "SnRepXSerializerImpl.h" +#include "PxJointRepXSerializer.h" + +namespace physx { + + template<typename TJointType> + inline TJointType* createJoint( PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1 ) + { + PX_UNUSED(physics); + PX_UNUSED(actor0); + PX_UNUSED(actor1); + PX_UNUSED(localFrame0); + PX_UNUSED(localFrame1); + return NULL; + } + + template<> + inline PxD6Joint* createJoint<PxD6Joint>(PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) + { + return PxD6JointCreate( physics, actor0, localFrame0, actor1, localFrame1 ); + } + + template<> + inline PxDistanceJoint* createJoint<PxDistanceJoint>(PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) + { + return PxDistanceJointCreate( physics, actor0, localFrame0, actor1, localFrame1 ); + } + + template<> + inline PxFixedJoint* createJoint<PxFixedJoint>(PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) + { + return PxFixedJointCreate( physics, actor0, localFrame0, actor1, localFrame1 ); + } + + template<> + inline PxPrismaticJoint* createJoint<PxPrismaticJoint>(PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) + { + return PxPrismaticJointCreate( physics, actor0, localFrame0, actor1, localFrame1 ); + } + + template<> + inline PxRevoluteJoint* createJoint<PxRevoluteJoint>(PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) + { + return PxRevoluteJointCreate( physics, actor0, localFrame0, actor1, localFrame1 ); + } + + template<> + inline PxSphericalJoint* createJoint<PxSphericalJoint>(PxPhysics& physics, + PxRigidActor* actor0, const PxTransform& localFrame0, + PxRigidActor* actor1, const PxTransform& localFrame1) + { + return PxSphericalJointCreate( physics, actor0, localFrame0, actor1, localFrame1 ); + } + + template<typename TJointType> + PxRepXObject PxJointRepXSerializer<TJointType>::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection ) + { + PxRigidActor* actor0 = NULL; + PxRigidActor* actor1 = NULL; + PxTransform localPose0 = PxTransform(PxIdentity); + PxTransform localPose1 = PxTransform(PxIdentity); + bool ok = true; + if ( inReader.gotoChild( "Actors" ) ) + { + ok = readReference<PxRigidActor>( inReader, *inCollection, "actor0", actor0 ); + ok &= readReference<PxRigidActor>( inReader, *inCollection, "actor1", actor1 ); + inReader.leaveChild(); + } + TJointType* theJoint = !ok ? NULL : createJoint<TJointType>( inArgs.physics, actor0, localPose0, actor1, localPose1 ); + + if ( theJoint ) + { + PxConstraint* constraint = theJoint->getConstraint(); + PX_ASSERT( constraint ); + inCollection->add( *constraint ); + this->fileToObjectImpl( theJoint, inReader, inAllocator, inArgs, inCollection ); + } + return PxCreateRepXObject(theJoint); + } + + template<typename TJointType> + void PxJointRepXSerializer<TJointType>::objectToFileImpl( const TJointType* inObj, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& ) + { + writeAllProperties( inObj, inWriter, inTempBuffer, *inCollection ); + } + + // explicit instantiations + template struct PxJointRepXSerializer<PxFixedJoint>; + template struct PxJointRepXSerializer<PxDistanceJoint>; + template struct PxJointRepXSerializer<PxD6Joint>; + template struct PxJointRepXSerializer<PxPrismaticJoint>; + template struct PxJointRepXSerializer<PxRevoluteJoint>; + template struct PxJointRepXSerializer<PxSphericalJoint>; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnPxStreamOperators.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnPxStreamOperators.h new file mode 100644 index 00000000..efca5662 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnPxStreamOperators.h @@ -0,0 +1,134 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_PXSTREAMOPERATORS_H +#define PX_PXSTREAMOPERATORS_H + +#include "foundation/PxVec3.h" +#include "foundation/PxTransform.h" +#include "foundation/PxBounds3.h" +#include "PxFiltering.h" + +#include "PsString.h" + +namespace physx +{ + static inline PxU32 strLenght( const char* inStr ) + { + return inStr ? PxU32(strlen(inStr)) : 0; + } +} + +namespace physx // ADL requires we put the operators in the same namespace as the underlying type of PxOutputStream +{ + inline PxOutputStream& operator << ( PxOutputStream& ioStream, const char* inString ) + { + if ( inString && *inString ) + { + ioStream.write( inString, PxU32(strlen(inString)) ); + } + return ioStream; + } + + template<typename TDataType> + inline PxOutputStream& toStream( PxOutputStream& ioStream, const char* inFormat, const TDataType inData ) + { + char buffer[128] = { 0 }; + Ps::snprintf( buffer, 128, inFormat, inData ); + ioStream << buffer; + return ioStream; + } + + struct endl_obj {}; + //static endl_obj endl; + + inline PxOutputStream& operator << ( PxOutputStream& ioStream, bool inData ) { ioStream << (inData ? "true" : "false"); return ioStream; } + inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxI32 inData ) { return toStream( ioStream, "%d", inData ); } + inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxU16 inData ) { return toStream( ioStream, "%u", PxU32(inData) ); } + inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxU8 inData ) { return toStream( ioStream, "%u", PxU32(inData) ); } + inline PxOutputStream& operator << ( PxOutputStream& ioStream, char inData ) { return toStream( ioStream, "%c", inData ); } + inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxU32 inData ) { return toStream( ioStream, "%u", inData ); } + inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxU64 inData ) { return toStream( ioStream, "%" PX_PRIu64, inData ); } + inline PxOutputStream& operator << ( PxOutputStream& ioStream, const void* inData ) { return ioStream << PX_PROFILE_POINTER_TO_U64( inData ); } + inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxF32 inData ) { return toStream( ioStream, "%g", PxF64(inData) ); } + inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxF64 inData ) { return toStream( ioStream, "%g", inData ); } + inline PxOutputStream& operator << ( PxOutputStream& ioStream, endl_obj) { return ioStream << "\n"; } + inline PxOutputStream& operator << ( PxOutputStream& ioStream, const PxVec3& inData ) + { + ioStream << inData[0]; + ioStream << " "; + ioStream << inData[1]; + ioStream << " "; + ioStream << inData[2]; + return ioStream; + } + + inline PxOutputStream& operator << ( PxOutputStream& ioStream, const PxQuat& inData ) + { + ioStream << inData.x; + ioStream << " "; + ioStream << inData.y; + ioStream << " "; + ioStream << inData.z; + ioStream << " "; + ioStream << inData.w; + return ioStream; + } + + inline PxOutputStream& operator << ( PxOutputStream& ioStream, const PxTransform& inData ) + { + ioStream << inData.q; + ioStream << " "; + ioStream << inData.p; + return ioStream; + } + + inline PxOutputStream& operator << ( PxOutputStream& ioStream, const PxBounds3& inData ) + { + ioStream << inData.minimum; + ioStream << " "; + ioStream << inData.maximum; + return ioStream; + } + + inline PxOutputStream& operator << ( PxOutputStream& ioStream, const PxFilterData& inData ) + { + ioStream << inData.word0 << " " << inData.word1 << " " << inData.word2 << " " << inData.word3; + return ioStream; + } + + inline PxOutputStream& operator << ( PxOutputStream& ioStream, struct PxMetaDataPlane& inData ) + { + ioStream << inData.normal; + ioStream << " "; + ioStream << inData.distance; + return ioStream; + } +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX1_0Defaults.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX1_0Defaults.h new file mode 100644 index 00000000..31ad950e --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX1_0Defaults.h @@ -0,0 +1,245 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + DEFINE_REPX_DEFAULT_PROPERTY("PxBoxGeometry.HalfExtents", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphereGeometry.Radius", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Scale", "1 1 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Rotation", "0 0 0 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.ConvexMesh", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Scale", "1 1 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Rotation", "0 0 0 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.MeshFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.TriangleMesh", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightField", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightScale", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.RowScale", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.ColumnScale", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightFieldFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Length", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Mass", "1000" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Speed", "10" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DynamicFriction", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.StaticFriction", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DynamicFrictionV", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.StaticFrictionV", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DirOfAnisotropy", "1 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.FrictionCombineMode", "eAVERAGE" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.RestitutionCombineMode", "eAVERAGE" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.UserData", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.LocalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.SimulationFilterData", "0 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.QueryFilterData", "0 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.ContactOffset", "0.02" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.RestOffset", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Flags", "eSIMULATION_SHAPE|eSCENE_QUERY_SHAPE|eVISUALIZATION" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.UserData", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ActorFlags", "eVISUALIZATION" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.DominanceGroup", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.OwnerClient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ClientBehaviorBits", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.UserData", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.GlobalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ActorFlags", "eVISUALIZATION" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.DominanceGroup", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.OwnerClient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ClientBehaviorBits", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.UserData", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.CMassLocalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Mass", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MassSpaceInertiaTensor", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.GlobalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearVelocity", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularVelocity", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearDamping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularDamping", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MaxAngularVelocity", "7" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SleepEnergyThreshold", "0.005" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minPositionIters", "4" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minVelocityIters", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ContactReportThreshold", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.RigidDynamicFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ParentPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ChildPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetOrientation", "0 0 0 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetVelocity", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.InternalCompliance", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ExternalCompliance", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.yLimit", "0.78539816339" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.zLimit", "0.78539816339" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimitEnabled", "false" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.lower", "-0.78539816339" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.upper", "0.78539816339" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimitEnabled", "false" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ActorFlags", "eVISUALIZATION" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.DominanceGroup", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.OwnerClient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ClientBehaviorBits", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.UserData", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.CMassLocalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Mass", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.MassSpaceInertiaTensor", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.GlobalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.LinearVelocity", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.AngularVelocity", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.MaxProjectionIterations", "4" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SeparationTolerance", "0.1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.InternalDriveIterations", "4" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.ExternalDriveIterations", "4" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minPositionIters", "4" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minVelocityIters", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.UserData", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.UserData", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eX", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eY", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eZ", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eTWIST", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING1", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING2", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.ContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Value", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.ContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Upper", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Lower", "-1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.YAngle", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ZAngle", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DrivePosition", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.linear", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.angular", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionLinearTolerance", "1e+010" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionAngularTolerance", "3.14159" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.UserData", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionLinearTolerance", "1e+010" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionAngularTolerance", "3.14159" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.UserData", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MinDistance", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MaxDistance", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Tolerance", "0.025" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.DistanceJointFlags", "eMAX_DISTANCE_ENABLED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.UserData", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.ContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Upper", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Lower", "-1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveVelocity", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveGearRatio", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.RevoluteJointFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionLinearTolerance", "1e+010" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionAngularTolerance", "3.14159" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.UserData", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.ContactDistance", "0.01" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Upper", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Lower", "-3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.PrismaticJointFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionLinearTolerance", "1e+010" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionAngularTolerance", "3.14159" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.UserData", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.YAngle", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ZAngle", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.SphericalJointFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ProjectionLinearTolerance", "1e+010" ) + DEFINE_REPX_DEFAULT_PROPERTY("THEEND", "false" ) diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX3_1Defaults.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX3_1Defaults.h new file mode 100644 index 00000000..a3e52a73 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX3_1Defaults.h @@ -0,0 +1,274 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Length", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Mass", "1000" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Speed", "10" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxBoxGeometry.HalfExtents", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphereGeometry.Radius", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Scale", "1 1 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Rotation", "0 0 0 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.ConvexMesh", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Scale", "1 1 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Rotation", "0 0 0 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.MeshFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.TriangleMesh", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightField", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightScale", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.RowScale", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.ColumnScale", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightFieldFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DynamicFriction", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.StaticFriction", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DynamicFrictionV", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.StaticFrictionV", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DirOfAnisotropy", "1 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.FrictionCombineMode", "eAVERAGE" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.RestitutionCombineMode", "eAVERAGE" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.LocalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.SimulationFilterData", "0 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.QueryFilterData", "0 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.ContactOffset", "0.02" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.RestOffset", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Flags", "eSIMULATION_SHAPE|eSCENE_QUERY_SHAPE|eVISUALIZATION" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ActorFlags", "eVISUALIZATION" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.DominanceGroup", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.OwnerClient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ClientBehaviorBits", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.GlobalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ActorFlags", "eVISUALIZATION" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.DominanceGroup", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.OwnerClient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ClientBehaviorBits", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.GlobalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.CMassLocalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Mass", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MassSpaceInertiaTensor", "1 1 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearVelocity", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularVelocity", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearDamping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularDamping", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MaxAngularVelocity", "7" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SleepThreshold", "0.005" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minPositionIters", "4" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minVelocityIters", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ContactReportThreshold", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.RigidDynamicFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ParentPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ChildPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetOrientation", "0 0 0 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetVelocity", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.InternalCompliance", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ExternalCompliance", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.yLimit", "0.78539816339" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.zLimit", "0.78539816339" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TangentialSpring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TangentialDamping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimitContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimitEnabled", "false" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.lower", "-0.78539816339" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.upper", "0.78539816339" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimitEnabled", "false" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimitContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ActorFlags", "eVISUALIZATION" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.DominanceGroup", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.OwnerClient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ClientBehaviorBits", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.GlobalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.CMassLocalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Mass", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.MassSpaceInertiaTensor", "1 1 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.LinearVelocity", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.AngularVelocity", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.MaxProjectionIterations", "4" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SeparationTolerance", "0.1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.InternalDriveIterations", "4" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.ExternalDriveIterations", "4" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minPositionIters", "4" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minVelocityIters", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SleepThreshold", "0.005" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Actors.actor0", "8887040" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Actors.actor1", "8887456" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eX", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eY", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eZ", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eTWIST", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING1", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING2", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.ContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Value", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.ContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Upper", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Lower", "-1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.YAngle", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ZAngle", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DrivePosition", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.linear", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.angular", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionLinearTolerance", "1e+010" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionAngularTolerance", "3.14159" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Actors.actor0", "8887040" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Actors.actor1", "8887456" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionLinearTolerance", "1e+010" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionAngularTolerance", "3.14159" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Actors.actor0", "8887040" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Actors.actor1", "8887456" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MinDistance", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MaxDistance", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Tolerance", "0.025" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.DistanceJointFlags", "eMAX_DISTANCE_ENABLED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Actors.actor0", "8887040" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Actors.actor1", "8887456" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.ContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Upper", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Lower", "-1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveVelocity", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveGearRatio", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.RevoluteJointFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionLinearTolerance", "1e+010" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionAngularTolerance", "3.14159" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Actors.actor0", "8887040" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Actors.actor1", "8887456" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.ContactDistance", "0.01" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Upper", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Lower", "-3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.PrismaticJointFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionLinearTolerance", "1e+010" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionAngularTolerance", "3.14159" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Actors.actor0", "8887040" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Actors.actor1", "8887456" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.YAngle", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ZAngle", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.SphericalJointFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ProjectionLinearTolerance", "1e+010" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ActorFlags", "eVISUALIZATION" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.DominanceGroup", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.OwnerClient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ClientBehaviorBits", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.MotionConstraintScaleBias.scale", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.MotionConstraintScaleBias.bias", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.GlobalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ExternalAcceleration", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.DampingCoefficient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.SolverFrequency", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.SleepLinearVelocity", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("THEEND", "false" ) diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX3_2Defaults.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX3_2Defaults.h new file mode 100644 index 00000000..f3959504 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX3_2Defaults.h @@ -0,0 +1,313 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Length", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Mass", "1000" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Speed", "10" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxBoxGeometry.HalfExtents", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphereGeometry.Radius", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Scale", "1 1 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Rotation", "0 0 0 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.ConvexMesh", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Scale", "1 1 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Rotation", "0 0 0 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.MeshFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.TriangleMesh", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightField", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightScale", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.RowScale", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.ColumnScale", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightFieldFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DynamicFriction", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.StaticFriction", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.FrictionCombineMode", "eAVERAGE" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.RestitutionCombineMode", "eAVERAGE" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.LocalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.SimulationFilterData", "0 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.QueryFilterData", "0 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.ContactOffset", "0.02" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.RestOffset", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Flags", "eSIMULATION_SHAPE|eSCENE_QUERY_SHAPE|eVISUALIZATION" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ActorFlags", "eVISUALIZATION" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.DominanceGroup", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.OwnerClient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ClientBehaviorBits", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.GlobalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ActorFlags", "eVISUALIZATION" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.DominanceGroup", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.OwnerClient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ClientBehaviorBits", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.GlobalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.CMassLocalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Mass", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MassSpaceInertiaTensor", "1 1 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearVelocity", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularVelocity", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearDamping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularDamping", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MaxAngularVelocity", "7" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SleepThreshold", "0.005" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minPositionIters", "4" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minVelocityIters", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ContactReportThreshold", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.RigidDynamicFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ParentPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ChildPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetOrientation", "0 0 0 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetVelocity", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.InternalCompliance", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ExternalCompliance", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.yLimit", "0.78539816339" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.zLimit", "0.78539816339" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TangentialSpring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TangentialDamping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimitContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimitEnabled", "false" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.lower", "-0.78539816339" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.upper", "0.78539816339" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimitEnabled", "false" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimitContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ActorFlags", "eVISUALIZATION" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.DominanceGroup", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.OwnerClient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ClientBehaviorBits", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.GlobalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.CMassLocalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Mass", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.MassSpaceInertiaTensor", "1 1 1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.LinearVelocity", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.AngularVelocity", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.MaxProjectionIterations", "4" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SeparationTolerance", "0.1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.InternalDriveIterations", "4" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.ExternalDriveIterations", "4" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minPositionIters", "4" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minVelocityIters", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SleepThreshold", "0.005" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Actors.actor0", "8887040" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Actors.actor1", "8887456" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eX", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eY", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eZ", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eTWIST", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING1", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING2", "eLOCKED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.ContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Value", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.ContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Upper", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Lower", "-1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.YAngle", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ZAngle", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.ForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Flags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DrivePosition", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.linear", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.angular", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionLinearTolerance", "1e+010" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionAngularTolerance", "3.14159" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Actors.actor0", "8887040" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Actors.actor1", "8887456" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionLinearTolerance", "1e+010" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionAngularTolerance", "3.14159" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Actors.actor0", "8887040" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Actors.actor1", "8887456" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MinDistance", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MaxDistance", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Tolerance", "0.025" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.DistanceJointFlags", "eMAX_DISTANCE_ENABLED" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Actors.actor0", "8887040" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Actors.actor1", "8887456" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.ContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Upper", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Lower", "-1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveVelocity", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveForceLimit", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveGearRatio", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.RevoluteJointFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionLinearTolerance", "1e+010" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionAngularTolerance", "3.14159" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Actors.actor0", "8887040" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Actors.actor1", "8887456" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.ContactDistance", "0.01" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Upper", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Lower", "-3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.PrismaticJointFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionLinearTolerance", "1e+010" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionAngularTolerance", "3.14159" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Actors.actor0", "8887040" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Actors.actor1", "8887456" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.force", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.torque", "3.40282e+038" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ConstraintFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Restitution", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Spring", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ContactDistance", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.YAngle", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ZAngle", "1.5708" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.SphericalJointFlags", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ProjectionLinearTolerance", "1e+010" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.Name", "" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ActorFlags", "eVISUALIZATION" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.DominanceGroup", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.OwnerClient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ClientBehaviorBits", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.MotionConstraintScaleBias.scale", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.MotionConstraintScaleBias.bias", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.GlobalPose", "0 0 0 1 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ExternalAcceleration", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.DampingCoefficient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.SolverFrequency", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.SleepLinearVelocity", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.InertiaScale", "1" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.FrictionCoefficient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.DragCoefficient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.CollisionMassScale", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ActorFlags", "eVISUALIZATION" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.DominanceGroup", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.OwnerClient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ExternalAcceleration", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ParticleMass", "0.001" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.Restitution", "0.5" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.DynamicFriction", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.StaticFriction", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.SimulationFilterData", "0 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.MaxMotionDistance", "0.06" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.RestOffset", "0.004" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ContactOffset", "0.008" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.GridSize", "0.96" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ProjectionPlane", "0 0 1 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ParticleReadDataFlags", "ePOSITION_BUFFER|eFLAGS_BUFFER" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ParticleBaseFlags", "eCOLLISION_WITH_DYNAMIC_ACTORS|eENABLED|ePER_PARTICLE_REST_OFFSET|ePER_PARTICLE_COLLISION_CACHE_HINT") + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ActorFlags", "eVISUALIZATION" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.DominanceGroup", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.OwnerClient", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.Damping", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ExternalAcceleration", "0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ParticleMass", "0.001" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.Restitution", "0.5" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.DynamicFriction", "0.05" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.StaticFriction", "0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.SimulationFilterData", "0 0 0 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.MaxMotionDistance", "0.06" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.RestOffset", "0.004" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ContactOffset", "0.008" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.GridSize", "0.64" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ProjectionPlane", "0 0 1 0" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.Stiffness", "20" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.Viscosity", "6" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.RestParticleDistance", "0.02" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ParticleReadDataFlags", "ePOSITION_BUFFER|eFLAGS_BUFFER" ) + DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ParticleBaseFlags", "eCOLLISION_WITH_DYNAMIC_ACTORS|eENABLED|ePER_PARTICLE_REST_OFFSET|ePER_PARTICLE_COLLISION_CACHE_HINT") + DEFINE_REPX_DEFAULT_PROPERTY("PxAggregate.SelfCollision", "false" ) + DEFINE_REPX_DEFAULT_PROPERTY("THEEND", "false" ) diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCollection.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCollection.h new file mode 100644 index 00000000..b479754d --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCollection.h @@ -0,0 +1,173 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_REPXCOLLECTION_H +#define PX_REPXCOLLECTION_H + +#include "common/PxTolerancesScale.h" +#include "PxRepXSerializer.h" + +namespace physx { namespace Sn { + + struct XmlNode; + + struct RepXCollectionItem + { + PxRepXObject liveObject; + XmlNode* descriptor; + RepXCollectionItem( PxRepXObject inItem = PxRepXObject(), XmlNode* inDescriptor = NULL ) + : liveObject( inItem ) + , descriptor( inDescriptor ) + { + } + }; + + struct RepXDefaultEntry + { + const char* name; + const char* value; + RepXDefaultEntry( const char* pn, const char* val ) : name( pn ), value( val ){} + }; + + /** + * The result of adding an object to the collection. + */ + struct RepXAddToCollectionResult + { + enum Enum + { + Success, + SerializerNotFound, + InvalidParameters, //Null data passed in. + AlreadyInCollection + }; + + PxSerialObjectId collectionId; + Enum result; + + RepXAddToCollectionResult( Enum inResult = Success, const PxSerialObjectId inId = 0 ) + : collectionId( inId ) + , result( inResult ) + { + } + bool isValid() { return result == Success && collectionId != 0; } + }; + /** + * A RepX collection contains a set of static data objects that can be transformed + * into live objects. It uses RepX serializer to do two transformations: + * live object <-> collection object (descriptor) + * collection object <-> file system. + * + * A live object is considered to be something live in the physics + * world such as a material or a rigidstatic. + * + * A collection object is a piece of data from which a live object + * of identical characteristics can be created. + * + * Clients need to pass PxCollection so that objects can resolve + * references. In addition, objects must be added in an order such that + * references can be resolved in the first place. So objects must be added + * to the collection *after* objects they are dependent upon. + * + * When deserializing from a file, the collection will allocate char*'s that will + * not be freed when the collection itself is freed. The user must be responsible + * for these character allocations. + */ + class RepXCollection + { + protected: + virtual ~RepXCollection(){} + + public: + virtual void destroy() = 0; + + /** + * Set the scale on this collection. The scale is saved with the collection. + * + * If the scale wasn't set, it will be invalid. + */ + virtual void setTolerancesScale( const PxTolerancesScale& inScale ) = 0; + + /** + * Get the scale that was set at collection creation time or at load time. + * If this is a loaded file and the source data does not contain a scale + * this value will be invalid (PxTolerancesScale::isValid()). + */ + virtual PxTolerancesScale getTolerancesScale() const = 0; + + /** + * Set the up vector on this collection. The up vector is saved with the collection. + * + * If the up vector wasn't set, it will be (0,0,0). + */ + virtual void setUpVector( const PxVec3& inUpVector ) = 0; + + /** + * If the up vector wasn't set, it will be (0,0,0). Else this will be the up vector + * optionally set when the collection was created. + */ + virtual PxVec3 getUpVector() const = 0; + + virtual const char* getVersion() = 0; + static const char* getLatestVersion(); + + //Necessary accessor functions for translation/upgrading. + virtual const RepXCollectionItem* begin() const = 0; + virtual const RepXCollectionItem* end() const = 0; + + + //Performs a deep copy of the repx node. + virtual XmlNode* copyRepXNode( const XmlNode* srcNode ) = 0; + + virtual void addCollectionItem( RepXCollectionItem inItem ) = 0; + + //Create a new repx node with this name. Its value is unset. + virtual XmlNode& createRepXNode( const char* name ) = 0; + + virtual RepXCollection& createCollection( const char* inVersionStr ) = 0; + //Release this when finished. + virtual XmlReaderWriter& createNodeEditor() = 0; + + virtual PxAllocatorCallback& getAllocator() = 0; + + virtual bool instantiateCollection( PxRepXInstantiationArgs& inArgs, PxCollection& inPxCollection ) = 0; + + + virtual RepXAddToCollectionResult addRepXObjectToCollection( const PxRepXObject& inObject, PxCollection* inCollection, PxRepXInstantiationArgs& inArgs ) = 0; + + /** + * Save this collection out to a file stream. Uses the RepX serialize to perform + * collection object->file conversions. + * + * /param[in] inStream Write-only stream to save collection out to. + */ + virtual void save( PxOutputStream& inStream ) = 0; + }; +} } + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCoreSerializer.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCoreSerializer.cpp new file mode 100644 index 00000000..104e521c --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCoreSerializer.cpp @@ -0,0 +1,1158 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PxPhysicsAPI.h" +#include "PxMetaDataObjects.h" +#include "CmIO.h" +#include "SnPxStreamOperators.h" +#include "PsUtilities.h" +#include "SnXmlImpl.h" +#include "SnXmlSerializer.h" +#include "SnXmlDeserializer.h" +#include "SnRepXCoreSerializer.h" + +using namespace physx::Sn; +namespace physx { + typedef PxProfileHashMap< const PxSerialObjectId, const PxArticulationLink* > TArticulationLinkLinkMap; + typedef PxReadOnlyPropertyInfo<PxPropertyInfoName::PxArticulationLink_InboundJoint, PxArticulationLink, PxArticulationJoint *> TIncomingJointPropType; + + //************************************************************* + // Actual RepXSerializer implementations for PxMaterial + //************************************************************* + PxMaterial* PxMaterialRepXSerializer::allocateObject( PxRepXInstantiationArgs& inArgs ) + { + return inArgs.physics.createMaterial(0, 0, 0); + } + + PxRepXObject PxShapeRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection ) + { + PxProfileAllocatorWrapper wrapper( inAllocator.getAllocator() ); + TReaderNameStack names( wrapper ); + PxProfileArray<PxU32> contexts( wrapper ); + bool hadError = false; + RepXVisitorReader<PxShape> theVisitor( names, contexts, inArgs, inReader, NULL, inAllocator, *inCollection, hadError ); + + Ps::Array<PxMaterial*> materials; + PxGeometry* geometry = NULL; + parseShape( theVisitor, geometry, materials ); + if(hadError) + return PxRepXObject(); + PxShape *theShape = inArgs.physics.createShape( *geometry, materials.begin(), Ps::to16(materials.size()) ); + + switch(geometry->getType()) + { + case PxGeometryType::eSPHERE : + static_cast<PxSphereGeometry*>(geometry)->~PxSphereGeometry(); + break; + case PxGeometryType::ePLANE : + static_cast<PxPlaneGeometry*>(geometry)->~PxPlaneGeometry(); + break; + case PxGeometryType::eCAPSULE : + static_cast<PxCapsuleGeometry*>(geometry)->~PxCapsuleGeometry(); + break; + case PxGeometryType::eBOX : + static_cast<PxBoxGeometry*>(geometry)->~PxBoxGeometry(); + break; + case PxGeometryType::eCONVEXMESH : + static_cast<PxConvexMeshGeometry*>(geometry)->~PxConvexMeshGeometry(); + break; + case PxGeometryType::eTRIANGLEMESH : + static_cast<PxTriangleMeshGeometry*>(geometry)->~PxTriangleMeshGeometry(); + break; + case PxGeometryType::eHEIGHTFIELD : + static_cast<PxHeightFieldGeometry*>(geometry)->~PxHeightFieldGeometry(); + break; + + case PxGeometryType::eGEOMETRY_COUNT: + case PxGeometryType::eINVALID: + PX_ASSERT(0); + } + inAllocator.getAllocator().deallocate(geometry); + + bool ret = readAllProperties( inArgs, inReader, theShape, inAllocator, *inCollection ); + + return ret ? PxCreateRepXObject(theShape) : PxRepXObject(); + } + + //************************************************************* + // Actual RepXSerializer implementations for PxTriangleMesh + //************************************************************* + + template<typename TTriIndexElem> + inline void writeTriangle( MemoryBuffer& inTempBuffer, const Triangle<TTriIndexElem>& inTriangle ) + { + inTempBuffer << inTriangle.mIdx0 + << " " << inTriangle.mIdx1 + << " " << inTriangle.mIdx2; + } + + PxU32 materialAccess( const PxTriangleMesh* inMesh, PxU32 inIndex ) { return inMesh->getTriangleMaterialIndex( inIndex ); } + template<typename TDataType> + void writeDatatype( MemoryBuffer& inTempBuffer, const TDataType& inType ) { inTempBuffer << inType; } + + void PxBVH33TriangleMeshRepXSerializer::objectToFileImpl( const PxBVH33TriangleMesh* mesh, PxCollection* /*inCollection*/, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& inArgs ) + { + bool hasMatIndex = mesh->getTriangleMaterialIndex(0) != 0xffff; + PxU32 numVertices = mesh->getNbVertices(); + const PxVec3* vertices = mesh->getVertices(); + writeBuffer( inWriter, inTempBuffer, 2, vertices, numVertices, "Points", writePxVec3 ); + bool isU16 = mesh->getTriangleMeshFlags() & PxTriangleMeshFlag::e16_BIT_INDICES ? true : false; + PxU32 triCount = mesh->getNbTriangles(); + const void* indices = mesh->getTriangles(); + if ( isU16 ) + writeBuffer( inWriter, inTempBuffer, 2, reinterpret_cast<const Triangle<PxU16>* >( indices ), triCount, "Triangles", writeTriangle<PxU16> ); + else + writeBuffer( inWriter, inTempBuffer, 2, reinterpret_cast<const Triangle<PxU32>* >( indices ), triCount, "Triangles", writeTriangle<PxU32> ); + if ( hasMatIndex ) + writeBuffer( inWriter, inTempBuffer, 6, mesh, materialAccess, triCount, "materialIndices", writeDatatype<PxU32> ); + + //Cooked stream + PxTriangleMeshDesc meshDesc; + meshDesc.points.count = numVertices; + meshDesc.points.data = vertices; + meshDesc.points.stride = sizeof(PxVec3); + meshDesc.triangles.count = triCount; + meshDesc.triangles.data = indices; + meshDesc.triangles.stride = isU16?3*sizeof(PxU16):3*sizeof(PxU32); + + if(isU16) + { + meshDesc.triangles.stride = sizeof(PxU16)*3; + meshDesc.flags |= PxMeshFlag::e16_BIT_INDICES; + } + else + { + meshDesc.triangles.stride = sizeof(PxU32)*3; + } + + if(hasMatIndex) + { + PxMaterialTableIndex* materialIndices = new PxMaterialTableIndex[triCount]; + for(PxU32 i = 0; i < triCount; i++) + materialIndices[i] = mesh->getTriangleMaterialIndex(i); + + meshDesc.materialIndices.data = materialIndices; + meshDesc.materialIndices.stride = sizeof(PxMaterialTableIndex); + + } + + if(inArgs.cooker != NULL) + { + TMemoryPoolManager theManager(mAllocator); + MemoryBuffer theTempBuf( &theManager ); + theTempBuf.clear(); + inArgs.cooker->cookTriangleMesh( meshDesc, theTempBuf ); + + writeBuffer( inWriter, inTempBuffer, 16, theTempBuf.mBuffer, theTempBuf.mWriteOffset, "CookedData", writeDatatype<PxU8> ); + } + + delete []meshDesc.materialIndices.data; + } + + PxRepXObject PxBVH33TriangleMeshRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* /*inCollection*/ ) + { + //We can't do a simple inverse; we *have* to cook data to get a mesh. + PxTriangleMeshDesc theDesc; + readStridedBufferProperty<PxVec3>( inReader, "points", theDesc.points, inAllocator); + readStridedBufferProperty<Triangle<PxU32> >( inReader, "triangles", theDesc.triangles, inAllocator); + PxU32 triCount; + readStridedBufferProperty<PxMaterialTableIndex>( inReader, "materialIndices", theDesc.materialIndices, triCount, inAllocator); + PxStridedData cookedData; + cookedData.stride = sizeof(PxU8); + PxU32 dataSize; + readStridedBufferProperty<PxU8>( inReader, "CookedData", cookedData, dataSize, inAllocator); + + TMemoryPoolManager theManager(inAllocator.getAllocator()); + MemoryBuffer theTempBuf( &theManager ); + +// PxTriangleMesh* theMesh = NULL; + PxBVH33TriangleMesh* theMesh = NULL; + + if(dataSize != 0) + { + theTempBuf.write(cookedData.data, dataSize*sizeof(PxU8)); +// theMesh = inArgs.physics.createTriangleMesh( theTempBuf ); + theMesh = static_cast<PxBVH33TriangleMesh*>(inArgs.physics.createTriangleMesh( theTempBuf )); + } + + if(theMesh == NULL) + { + PX_ASSERT(inArgs.cooker); + theTempBuf.clear(); + + { + PxCookingParams params = inArgs.cooker->getParams(); + params.midphaseDesc = PxMeshMidPhase::eBVH33; + inArgs.cooker->setParams(params); + } + + inArgs.cooker->cookTriangleMesh( theDesc, theTempBuf ); +// theMesh = inArgs.physics.createTriangleMesh( theTempBuf ); + theMesh = static_cast<PxBVH33TriangleMesh*>(inArgs.physics.createTriangleMesh( theTempBuf )); + } + + return PxCreateRepXObject( theMesh ); + } + + void PxBVH34TriangleMeshRepXSerializer::objectToFileImpl( const PxBVH34TriangleMesh* mesh, PxCollection* /*inCollection*/, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& inArgs ) + { + bool hasMatIndex = mesh->getTriangleMaterialIndex(0) != 0xffff; + PxU32 numVertices = mesh->getNbVertices(); + const PxVec3* vertices = mesh->getVertices(); + writeBuffer( inWriter, inTempBuffer, 2, vertices, numVertices, "Points", writePxVec3 ); + bool isU16 = mesh->getTriangleMeshFlags() & PxTriangleMeshFlag::e16_BIT_INDICES ? true : false; + PxU32 triCount = mesh->getNbTriangles(); + const void* indices = mesh->getTriangles(); + if ( isU16 ) + writeBuffer( inWriter, inTempBuffer, 2, reinterpret_cast<const Triangle<PxU16>* >( indices ), triCount, "Triangles", writeTriangle<PxU16> ); + else + writeBuffer( inWriter, inTempBuffer, 2, reinterpret_cast<const Triangle<PxU32>* >( indices ), triCount, "Triangles", writeTriangle<PxU32> ); + if ( hasMatIndex ) + writeBuffer( inWriter, inTempBuffer, 6, mesh, materialAccess, triCount, "materialIndices", writeDatatype<PxU32> ); + + //Cooked stream + PxTriangleMeshDesc meshDesc; + meshDesc.points.count = numVertices; + meshDesc.points.data = vertices; + meshDesc.points.stride = sizeof(PxVec3); + meshDesc.triangles.count = triCount; + meshDesc.triangles.data = indices; + meshDesc.triangles.stride = isU16?3*sizeof(PxU16):3*sizeof(PxU32); + + if(isU16) + { + meshDesc.triangles.stride = sizeof(PxU16)*3; + meshDesc.flags |= PxMeshFlag::e16_BIT_INDICES; + } + else + { + meshDesc.triangles.stride = sizeof(PxU32)*3; + } + + if(hasMatIndex) + { + PxMaterialTableIndex* materialIndices = new PxMaterialTableIndex[triCount]; + for(PxU32 i = 0; i < triCount; i++) + materialIndices[i] = mesh->getTriangleMaterialIndex(i); + + meshDesc.materialIndices.data = materialIndices; + meshDesc.materialIndices.stride = sizeof(PxMaterialTableIndex); + + } + + if(inArgs.cooker != NULL) + { + TMemoryPoolManager theManager(mAllocator); + MemoryBuffer theTempBuf( &theManager ); + theTempBuf.clear(); + inArgs.cooker->cookTriangleMesh( meshDesc, theTempBuf ); + + writeBuffer( inWriter, inTempBuffer, 16, theTempBuf.mBuffer, theTempBuf.mWriteOffset, "CookedData", writeDatatype<PxU8> ); + } + + delete []meshDesc.materialIndices.data; + } + + PxRepXObject PxBVH34TriangleMeshRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* /*inCollection*/ ) + { + //We can't do a simple inverse; we *have* to cook data to get a mesh. + PxTriangleMeshDesc theDesc; + readStridedBufferProperty<PxVec3>( inReader, "points", theDesc.points, inAllocator); + readStridedBufferProperty<Triangle<PxU32> >( inReader, "triangles", theDesc.triangles, inAllocator); + PxU32 triCount; + readStridedBufferProperty<PxMaterialTableIndex>( inReader, "materialIndices", theDesc.materialIndices, triCount, inAllocator); + PxStridedData cookedData; + cookedData.stride = sizeof(PxU8); + PxU32 dataSize; + readStridedBufferProperty<PxU8>( inReader, "CookedData", cookedData, dataSize, inAllocator); + + TMemoryPoolManager theManager(inAllocator.getAllocator()); + MemoryBuffer theTempBuf( &theManager ); + +// PxTriangleMesh* theMesh = NULL; + PxBVH34TriangleMesh* theMesh = NULL; + + if(dataSize != 0) + { + theTempBuf.write(cookedData.data, dataSize*sizeof(PxU8)); +// theMesh = inArgs.physics.createTriangleMesh( theTempBuf ); + theMesh = static_cast<PxBVH34TriangleMesh*>(inArgs.physics.createTriangleMesh( theTempBuf )); + } + + if(theMesh == NULL) + { + PX_ASSERT(inArgs.cooker); + theTempBuf.clear(); + + { + PxCookingParams params = inArgs.cooker->getParams(); + params.midphaseDesc = PxMeshMidPhase::eBVH34; + inArgs.cooker->setParams(params); + } + + inArgs.cooker->cookTriangleMesh( theDesc, theTempBuf ); +// theMesh = inArgs.physics.createTriangleMesh( theTempBuf ); + theMesh = static_cast<PxBVH34TriangleMesh*>(inArgs.physics.createTriangleMesh( theTempBuf )); + } + + return PxCreateRepXObject(theMesh); + } + + + //************************************************************* + // Actual RepXSerializer implementations for PxHeightField + //************************************************************* + void PxHeightFieldRepXSerializer::objectToFileImpl( const PxHeightField* inHeightField, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/) + { + PxHeightFieldDesc theDesc; + + theDesc.nbRows = inHeightField->getNbRows(); + theDesc.nbColumns = inHeightField->getNbColumns(); + theDesc.format = inHeightField->getFormat(); + theDesc.samples.stride = inHeightField->getSampleStride(); + theDesc.samples.data = NULL; + theDesc.thickness = inHeightField->getThickness(); + theDesc.convexEdgeThreshold = inHeightField->getConvexEdgeThreshold(); + theDesc.flags = inHeightField->getFlags(); + + PxU32 theCellCount = inHeightField->getNbRows() * inHeightField->getNbColumns(); + PxU32 theSampleStride = sizeof( PxHeightFieldSample ); + PxU32 theSampleBufSize = theCellCount * theSampleStride; + PxHeightFieldSample* theSamples = reinterpret_cast< PxHeightFieldSample*> ( inTempBuffer.mManager->allocate( theSampleBufSize ) ); + inHeightField->saveCells( theSamples, theSampleBufSize ); + theDesc.samples.data = theSamples; + writeAllProperties( &theDesc, inWriter, inTempBuffer, *inCollection ); + writeStridedBufferProperty<PxHeightFieldSample>( inWriter, inTempBuffer, "samples", theDesc.samples, theDesc.nbRows * theDesc.nbColumns, 6, writeHeightFieldSample); + inTempBuffer.mManager->deallocate( reinterpret_cast<PxU8*>(theSamples) ); + } + + PxRepXObject PxHeightFieldRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection ) + { + PX_ASSERT(inArgs.cooker); + PxHeightFieldDesc theDesc; + readAllProperties( inArgs, inReader, &theDesc, inAllocator, *inCollection ); + //Now read the data... + PxU32 count = 0; //ignored becaues numRows and numColumns tells the story + readStridedBufferProperty<PxHeightFieldSample>( inReader, "samples", theDesc.samples, count, inAllocator); + PxHeightField* retval = inArgs.cooker->createHeightField( theDesc, inArgs.physics.getPhysicsInsertionCallback() ); + return PxCreateRepXObject(retval); + } + + //************************************************************* + // Actual RepXSerializer implementations for PxConvexMesh + //************************************************************* + void PxConvexMeshRepXSerializer::objectToFileImpl( const PxConvexMesh* mesh, PxCollection* /*inCollection*/, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& inArgs ) + { + writeBuffer( inWriter, inTempBuffer, 2, mesh->getVertices(), mesh->getNbVertices(), "points", writePxVec3 ); + + if(inArgs.cooker != NULL) + { + //Cache cooked Data + PxConvexMeshDesc theDesc; + theDesc.points.data = mesh->getVertices(); + theDesc.points.stride = sizeof(PxVec3); + theDesc.points.count = mesh->getNbVertices(); + + theDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX; + TMemoryPoolManager theManager(mAllocator); + MemoryBuffer theTempBuf( &theManager ); + inArgs.cooker->cookConvexMesh( theDesc, theTempBuf ); + + writeBuffer( inWriter, inTempBuffer, 16, theTempBuf.mBuffer, theTempBuf.mWriteOffset, "CookedData", writeDatatype<PxU8> ); + } + + } + + //Conversion from scene object to descriptor. + PxRepXObject PxConvexMeshRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* /*inCollection*/) + { + PxConvexMeshDesc theDesc; + readStridedBufferProperty<PxVec3>( inReader, "points", theDesc.points, inAllocator); + theDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX; + + PxStridedData cookedData; + cookedData.stride = sizeof(PxU8); + PxU32 dataSize; + readStridedBufferProperty<PxU8>( inReader, "CookedData", cookedData, dataSize, inAllocator); + + TMemoryPoolManager theManager(inAllocator.getAllocator()); + MemoryBuffer theTempBuf( &theManager ); + + PxConvexMesh* theMesh = NULL; + + if(dataSize != 0) + { + theTempBuf.write(cookedData.data, dataSize*sizeof(PxU8)); + theMesh = inArgs.physics.createConvexMesh( theTempBuf ); + } + + if(theMesh == NULL) + { + PX_ASSERT(inArgs.cooker); + theTempBuf.clear(); + + inArgs.cooker->cookConvexMesh( theDesc, theTempBuf ); + theMesh = inArgs.physics.createConvexMesh( theTempBuf ); + } + + return PxCreateRepXObject(theMesh); + } + + //************************************************************* + // Actual RepXSerializer implementations for PxRigidStatic + //************************************************************* + PxRigidStatic* PxRigidStaticRepXSerializer::allocateObject( PxRepXInstantiationArgs& inArgs ) + { + return inArgs.physics.createRigidStatic( PxTransform(PxIdentity) ); + } + + //************************************************************* + // Actual RepXSerializer implementations for PxRigidDynamic + //************************************************************* + PxRigidDynamic* PxRigidDynamicRepXSerializer::allocateObject( PxRepXInstantiationArgs& inArgs ) + { + return inArgs.physics.createRigidDynamic( PxTransform(PxIdentity) ); + } + + //************************************************************* + // Actual RepXSerializer implementations for PxArticulation + //************************************************************* + void PxArticulationRepXSerializer::objectToFileImpl( const PxArticulation* inObj, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/) + { + TNameStack nameStack( inTempBuffer.mManager->mWrapper ); + Sn::TArticulationLinkLinkMap linkMap( inTempBuffer.mManager->mWrapper ); + RepXVisitorWriter<PxArticulation> writer( nameStack, inWriter, inObj, inTempBuffer, *inCollection, &linkMap ); + RepXPropertyFilter<RepXVisitorWriter<PxArticulation> > theOp( writer ); + visitAllProperties<PxArticulation>( theOp ); + } + PxArticulation* PxArticulationRepXSerializer::allocateObject( PxRepXInstantiationArgs& inArgs ) { return inArgs.physics.createArticulation(); } + + //************************************************************* + // Actual RepXSerializer implementations for PxAggregate + //************************************************************* + void PxAggregateRepXSerializer::objectToFileImpl( const PxAggregate* data, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/) + { + PxArticulationLink *link = NULL; + inWriter.addAndGotoChild( "Actors" ); + for(PxU32 i = 0; i < data->getNbActors(); ++i) + { + PxActor* actor; + + if(data->getActors(&actor, 1, i)) + { + link = actor->is<PxArticulationLink>(); + } + + if(link && !link->getInboundJoint() ) + { + writeProperty( inWriter, *inCollection, inTempBuffer, "PxArticulationRef", &link->getArticulation()); + } + else if( !link ) + { + PxSerialObjectId theId = 0; + + theId = inCollection->getId( *actor ); + if( theId == 0 ) + theId = PX_PROFILE_POINTER_TO_U64( actor ); + + writeProperty( inWriter, *inCollection, inTempBuffer, "PxActorRef", theId ); + } + } + + inWriter.leaveChild( ); + + writeProperty( inWriter, *inCollection, inTempBuffer, "NumActors", data->getNbActors() ); + writeProperty( inWriter, *inCollection, inTempBuffer, "MaxNbActors", data->getMaxNbActors() ); + writeProperty( inWriter, *inCollection, inTempBuffer, "SelfCollision", data->getSelfCollision() ); + + writeAllProperties( data, inWriter, inTempBuffer, *inCollection ); + } + + PxRepXObject PxAggregateRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection ) + { + PxU32 numActors; + readProperty( inReader, "NumActors", numActors ); + PxU32 maxNbActors; + readProperty( inReader, "MaxNbActors", maxNbActors ); + + bool selfCollision; + bool ret = readProperty( inReader, "SelfCollision", selfCollision ); + + PxAggregate* theAggregate = inArgs.physics.createAggregate(maxNbActors, selfCollision); + ret &= readAllProperties( inArgs, inReader, theAggregate, inAllocator, *inCollection ); + + inReader.pushCurrentContext(); + if ( inReader.gotoChild( "Actors" ) ) + { + inReader.pushCurrentContext(); + for( bool matSuccess = inReader.gotoFirstChild(); matSuccess; + matSuccess = inReader.gotoNextSibling() ) + { + const char* actorType = inReader.getCurrentItemName(); + if ( 0 == physx::shdfnd::stricmp( actorType, "PxActorRef" ) ) + { + PxActor *actor = NULL; + ret &= readReference<PxActor>( inReader, *inCollection, actor ); + + if(actor) + { + PxScene *currScene = actor->getScene(); + if(currScene) + { + currScene->removeActor(*actor); + } + theAggregate->addActor(*actor); + } + } + else if ( 0 == physx::shdfnd::stricmp( actorType, "PxArticulationRef" ) ) + { + PxArticulation* articulation = NULL; + ret &= readReference<PxArticulation>( inReader, *inCollection, articulation ); + if(articulation) + { + PxScene *currScene = articulation->getScene(); + if(currScene) + { + currScene->removeArticulation(*articulation); + } + theAggregate->addArticulation(*articulation); + } + } + } + inReader.popCurrentContext(); + inReader.leaveChild(); + } + inReader.popCurrentContext(); + + return ret ? PxCreateRepXObject(theAggregate) : PxRepXObject(); + } + + //************************************************************* + // Actual RepXSerializer implementations for PxClothFabric + //************************************************************* +#if PX_USE_CLOTH_API + + void writeFabricPhase( PxOutputStream& stream, const PxClothFabricPhase& phase ) + { + const PxU32ToName* conv = PxEnumTraits<PxClothFabricPhaseType::Enum>().NameConversion; + for ( ; conv->mName != NULL; ++conv ) + if ( conv->mValue == PxU32(phase.phaseType) ) + stream << conv->mName; + stream << " " << phase.setIndex; + } + + namespace Sn { + template<> struct StrToImpl<PxClothFabricPhase> + { + void strto( PxClothFabricPhase& datatype, const char*& ioData ) + { + char buffer[512]; + eatwhite( ioData ); + nullTerminateWhite(ioData, buffer, 512 ); + + const PxU32ToName* conv = PxEnumTraits<PxClothFabricPhaseType::Enum>().NameConversion; + for ( ; conv->mName != NULL; ++conv ) + if ( 0 == physx::shdfnd::stricmp( buffer, conv->mName ) ) + datatype = static_cast<PxClothFabricPhaseType::Enum>( conv->mValue ); + + StrToImpl<PxU32>().strto( datatype.setIndex, ioData ); + } + }; + } + + void PxClothFabricRepXSerializer::objectToFileImpl( const PxClothFabric* data, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/) + { + + PxProfileAllocatorWrapper& wrapper( inTempBuffer.mManager->getWrapper() ); + PxU32 numParticles = data->getNbParticles(); + PxU32 numPhases = data->getNbPhases(); + PxU32 numRestvalues = data->getNbRestvalues(); + PxU32 numSets = data->getNbSets(); + PxU32 numIndices = data->getNbParticleIndices(); + PxU32 numTethers = data->getNbTethers(); + + PxProfileArray<PxU8> dataBuffer( wrapper ); + PxU32 numInts = PxMax(PxMax(numIndices, numRestvalues), numTethers); + dataBuffer.resize( PxU32(PxMax( PxMax( numInts * sizeof(PxU32), numTethers * sizeof(PxReal) ), + numPhases * sizeof(PxClothFabricPhase)) ) ); + + PxClothFabricPhase* phasePtr( reinterpret_cast<PxClothFabricPhase*>( dataBuffer.begin() ) ); + PxU32* indexPtr( reinterpret_cast<PxU32*>( dataBuffer.begin() ) ); + + writeProperty( inWriter, *inCollection, inTempBuffer, "NbParticles", numParticles ); + + data->getPhases( phasePtr, numPhases ); + writeBuffer( inWriter, inTempBuffer, 18, phasePtr, PtrAccess<PxClothFabricPhase>, numPhases, "Phases", writeFabricPhase ); + + PX_COMPILE_TIME_ASSERT( sizeof( PxReal ) == sizeof( PxU32 ) ); + PxReal* realPtr = reinterpret_cast< PxReal* >( indexPtr ); + data->getRestvalues( realPtr, numRestvalues ); + writeBuffer( inWriter, inTempBuffer, 18, realPtr, PtrAccess<PxReal>, numRestvalues, "Restvalues", BasicDatatypeWrite<PxReal> ); + + data->getSets( indexPtr, numSets ); + writeBuffer( inWriter, inTempBuffer, 18, indexPtr, PtrAccess<PxU32>, numSets, "Sets", BasicDatatypeWrite<PxU32> ); + + data->getParticleIndices( indexPtr, numIndices ); + writeBuffer( inWriter, inTempBuffer, 18, indexPtr, PtrAccess<PxU32>, numIndices, "ParticleIndices", BasicDatatypeWrite<PxU32> ); + + data->getTetherAnchors( indexPtr, numTethers ); + writeBuffer( inWriter, inTempBuffer, 18, indexPtr, PtrAccess<PxU32>, numTethers, "TetherAnchors", BasicDatatypeWrite<PxU32> ); + + data->getTetherLengths( realPtr, numTethers ); + writeBuffer( inWriter, inTempBuffer, 18, realPtr, PtrAccess<PxReal>, numTethers, "TetherLengths", BasicDatatypeWrite<PxReal> ); + } + + //Conversion from scene object to descriptor. + PxRepXObject PxClothFabricRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* /*inCollection*/) + { + PxU32 strideIgnored = 0; + + PxClothFabricDesc desc; + + readProperty( inReader, "NbParticles", desc.nbParticles ); + + readStridedBufferProperty<PxClothFabricPhase>( inReader, "Phases", const_cast<PxClothFabricPhase*&>(desc.phases), strideIgnored, desc.nbPhases, inAllocator ); + + PxU32 numRestvalues = 0; + readStridedBufferProperty<PxF32>( inReader, "Restvalues", const_cast<PxF32*&>(desc.restvalues), strideIgnored, numRestvalues, inAllocator ); + + readStridedBufferProperty<PxU32>( inReader, "Sets", const_cast<PxU32*&>(desc.sets), strideIgnored, desc.nbSets, inAllocator ); + + PxU32 numIndices = 0; + readStridedBufferProperty<PxU32>( inReader, "ParticleIndices", const_cast<PxU32*&>(desc.indices), strideIgnored, numIndices, inAllocator ); + + readStridedBufferProperty<PxU32>( inReader, "TetherAnchors", const_cast<PxU32*&>(desc.tetherAnchors), strideIgnored, desc.nbTethers, inAllocator ); + readStridedBufferProperty<PxF32>( inReader, "TetherLengths", const_cast<PxF32*&>(desc.tetherLengths), strideIgnored, desc.nbTethers, inAllocator ); + + PxClothFabric* newFabric = inArgs.physics.createClothFabric( desc ); + + PX_ASSERT( newFabric ); + return PxCreateRepXObject(newFabric); + } + + //************************************************************* + // Actual RepXSerializer implementations for PxCloth + //************************************************************* + void clothParticleWriter( PxOutputStream& stream, const PxClothParticle& particle ) + { + stream << particle.pos << " " << particle.invWeight; + } + + namespace Sn { + template<> struct StrToImpl<PxClothParticle> + { + void strto( PxClothParticle& datatype, const char*& ioData ) + { + StrToImpl<PxF32>().strto( datatype.pos[0], ioData ); + StrToImpl<PxF32>().strto( datatype.pos[1], ioData ); + StrToImpl<PxF32>().strto( datatype.pos[2], ioData ); + StrToImpl<PxF32>().strto( datatype.invWeight, ioData ); + } + }; + + template<> struct StrToImpl<PxClothCollisionSphere> + { + void strto( PxClothCollisionSphere& datatype, const char*& ioData ) + { + StrToImpl<PxF32>().strto( datatype.pos[0], ioData ); + StrToImpl<PxF32>().strto( datatype.pos[1], ioData ); + StrToImpl<PxF32>().strto( datatype.pos[2], ioData ); + StrToImpl<PxF32>().strto( datatype.radius, ioData ); + } + }; + + template<> struct StrToImpl<PxClothCollisionPlane> + { + void strto( PxClothCollisionPlane& datatype, const char*& ioData ) + { + StrToImpl<PxF32>().strto( datatype.normal[0], ioData ); + StrToImpl<PxF32>().strto( datatype.normal[1], ioData ); + StrToImpl<PxF32>().strto( datatype.normal[2], ioData ); + StrToImpl<PxF32>().strto( datatype.distance, ioData ); + } + }; + + template<> struct StrToImpl<PxClothCollisionTriangle> + { + void strto( PxClothCollisionTriangle& datatype, const char*& ioData ) + { + StrToImpl<PxVec3>().strto( datatype.vertex0, ioData ); + StrToImpl<PxVec3>().strto( datatype.vertex1, ioData ); + StrToImpl<PxVec3>().strto( datatype.vertex2, ioData ); + } + }; + + template<> struct StrToImpl<PxVec4> + { + void strto( PxVec4& datatype, const char*& ioData ) + { + StrToImpl<PxF32>().strto( datatype.x, ioData ); + StrToImpl<PxF32>().strto( datatype.y, ioData ); + StrToImpl<PxF32>().strto( datatype.z, ioData ); + StrToImpl<PxF32>().strto( datatype.w, ioData ); + } + }; + + template<> struct StrToImpl<PxClothParticleMotionConstraint> + { + void strto( PxClothParticleMotionConstraint& datatype, const char*& ioData ) + { + StrToImpl<PxVec3>().strto( datatype.pos, ioData ); + StrToImpl<PxF32>().strto( datatype.radius, ioData ); + } + }; + + template<> struct StrToImpl<PxClothParticleSeparationConstraint> + { + void strto( PxClothParticleSeparationConstraint& datatype, const char*& ioData ) + { + StrToImpl<PxVec3>().strto( datatype.pos, ioData ); + StrToImpl<PxF32>().strto( datatype.radius, ioData ); + } + }; + + } + + void clothSphereWriter( PxOutputStream& stream, const PxClothCollisionSphere& sphere ) + { + stream << sphere.pos << " " << sphere.radius; + } + + void clothPlaneWriter( PxOutputStream& stream, const PxClothCollisionPlane& plane ) + { + stream << plane.normal << " " << plane.distance; + } + + void clothTriangleWriter( PxOutputStream& stream, const PxClothCollisionTriangle& triangle ) + { + stream << triangle.vertex0 << " " << triangle.vertex1 << " " << triangle.vertex2; + } + + void PxClothRepXSerializer::objectToFileImpl( const PxCloth* data, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/) + { + PxClothParticleData* readData( data->lockParticleData() ); + writeBuffer( inWriter, inTempBuffer, 4, readData->particles, PtrAccess<PxClothParticle>, data->getNbParticles(), "Particles", clothParticleWriter ); + readData->unlock(); + + writeReference( inWriter, *inCollection, "Fabric", data->getFabric() ); + + PxProfileArray<PxU8> dataBuffer( inTempBuffer.mManager->getWrapper() ); + + // collision data + const PxCloth& cloth = *data; + PxU32 numSpheres = cloth.getNbCollisionSpheres(); + PxU32 numIndices = 2*cloth.getNbCollisionCapsules(); + PxU32 numPlanes = cloth.getNbCollisionPlanes(); + PxU32 numConvexes = cloth.getNbCollisionConvexes(); + PxU32 numTriangles = cloth.getNbCollisionTriangles(); + + PxU32 sphereBytes = numSpheres * sizeof( PxClothCollisionSphere ); + PxU32 pairBytes = numIndices * sizeof( PxU32 ); + PxU32 planesBytes = numPlanes * sizeof(PxClothCollisionPlane); + PxU32 convexBytes = numConvexes * sizeof(PxU32); + PxU32 triangleBytes = numTriangles * sizeof(PxClothCollisionTriangle); + + dataBuffer.resize( sphereBytes + pairBytes + planesBytes + convexBytes + triangleBytes); + PxClothCollisionSphere* spheresBuffer = reinterpret_cast<PxClothCollisionSphere*>( dataBuffer.begin() ); + PxU32* indexBuffer = reinterpret_cast<PxU32*>(spheresBuffer + numSpheres); + PxClothCollisionPlane* planeBuffer = reinterpret_cast<PxClothCollisionPlane*>(indexBuffer + numIndices); + PxU32* convexBuffer = reinterpret_cast<PxU32*>(planeBuffer + numPlanes); + PxClothCollisionTriangle* trianglesBuffer = reinterpret_cast<PxClothCollisionTriangle*>(convexBuffer + numConvexes); + + data->getCollisionData( spheresBuffer, indexBuffer, planeBuffer, convexBuffer, trianglesBuffer ); + writeBuffer( inWriter, inTempBuffer, 4, spheresBuffer, PtrAccess<PxClothCollisionSphere>, numSpheres, "CollisionSpheres", clothSphereWriter ); + writeBuffer( inWriter, inTempBuffer, 18, indexBuffer, PtrAccess<PxU32>, numIndices, "CollisionSpherePairs", BasicDatatypeWrite<PxU32> ); + writeBuffer( inWriter, inTempBuffer, 4, planeBuffer, PtrAccess<PxClothCollisionPlane>, numPlanes, "CollisionPlanes", clothPlaneWriter ); + writeBuffer( inWriter, inTempBuffer, 18, convexBuffer, PtrAccess<PxU32>, numConvexes, "CollisionConvexMasks", BasicDatatypeWrite<PxU32> ); + writeBuffer( inWriter, inTempBuffer, 4, trianglesBuffer, PtrAccess<PxClothCollisionTriangle>, numTriangles, "CollisionTriangles", clothTriangleWriter ); + + // particle accelerations + PxU32 numParticleAccelerations = cloth.getNbParticleAccelerations(); + PxU32 sizeParticleAccelerations = sizeof(PxVec4)*numParticleAccelerations; + if (dataBuffer.size() < sizeParticleAccelerations) + dataBuffer.resize(sizeof(PxClothParticle)*numParticleAccelerations); + + PxVec4* particleAccelerations = reinterpret_cast<PxVec4*>(dataBuffer.begin()); + cloth.getParticleAccelerations(particleAccelerations); + writeBuffer (inWriter, inTempBuffer, 4, reinterpret_cast<PxClothParticle*>(particleAccelerations), PtrAccess<PxClothParticle>, numParticleAccelerations, "ParticleAccelerations", clothParticleWriter ); + + //self collision indices + PxU32* particleCollisionIndices = reinterpret_cast<PxU32*>(dataBuffer.begin()); + PxU32 numSelfCollisionIndices = cloth.getNbSelfCollisionIndices(); + PxU32 sizeSelfCollisionIndices = sizeof(PxU32)*numSelfCollisionIndices; + if (dataBuffer.size() < sizeSelfCollisionIndices) + dataBuffer.resize(sizeSelfCollisionIndices); + data->getSelfCollisionIndices( particleCollisionIndices ); + writeBuffer( inWriter, inTempBuffer, 18, particleCollisionIndices, PtrAccess<PxU32>, numSelfCollisionIndices, "SelfCollisionIndices", BasicDatatypeWrite<PxU32> ); + + // motion constraints + PxClothParticleMotionConstraint* motionConstraints = reinterpret_cast<PxClothParticleMotionConstraint*>(dataBuffer.begin()); + PxU32 numMotionConstraints = cloth.getNbMotionConstraints(); + PxU32 sizeMotionConstraints = sizeof(PxVec4)*numMotionConstraints; + if (dataBuffer.size() < sizeMotionConstraints) + dataBuffer.resize(sizeof(PxClothParticle)*numMotionConstraints); + data->getMotionConstraints( motionConstraints ); + writeBuffer (inWriter, inTempBuffer, 4, reinterpret_cast<PxClothParticle*>(motionConstraints), PtrAccess<PxClothParticle>, numMotionConstraints, "MotionConstraints", clothParticleWriter ); + + // separation positions + PxU32 numSeparationConstraints= cloth.getNbSeparationConstraints(); + PxU32 restSeparationConstraints = sizeof(PxVec4)*numSeparationConstraints; + if (dataBuffer.size() < restSeparationConstraints) + dataBuffer.resize(sizeof(PxClothParticle)*numSeparationConstraints); + PxClothParticleSeparationConstraint* separationConstraints = reinterpret_cast<PxClothParticleSeparationConstraint*>(dataBuffer.begin()); + cloth.getSeparationConstraints(separationConstraints); + writeBuffer (inWriter, inTempBuffer, 4, reinterpret_cast<PxClothParticle*>(separationConstraints), PtrAccess<PxClothParticle>, numSeparationConstraints, "SeparationConstraints", clothParticleWriter ); + + // rest positions + PxU32 numRestPositions = cloth.getNbRestPositions(); + PxU32 restPositionSize = sizeof(PxVec4)*numRestPositions; + if (dataBuffer.size() < restPositionSize) + dataBuffer.resize(sizeof(PxClothParticle)*numRestPositions); + + PxVec4* restPositions = reinterpret_cast<PxVec4*>(dataBuffer.begin()); + cloth.getRestPositions(restPositions); + writeBuffer (inWriter, inTempBuffer, 4, reinterpret_cast<PxClothParticle*>(restPositions), PtrAccess<PxClothParticle>, numRestPositions, "RestPositions", clothParticleWriter ); + + // virtual particles + PxU32 numVirtualParticles = data->getNbVirtualParticles(); + PxU32 numWeightTableEntries = data->getNbVirtualParticleWeights(); + + PxU32 totalNeeded = static_cast<PxU32>( PxMax( numWeightTableEntries * sizeof( PxVec3 ), numVirtualParticles * 4 * sizeof( PxU32 ) ) ); + if ( dataBuffer.size() < totalNeeded ) + dataBuffer.resize( totalNeeded ); + + PxVec3* weightTableEntries = reinterpret_cast<PxVec3*>( dataBuffer.begin() ); + data->getVirtualParticleWeights( weightTableEntries ); + writeBuffer( inWriter, inTempBuffer, 6, weightTableEntries, PtrAccess<PxVec3>, numWeightTableEntries, "VirtualParticleWeights", BasicDatatypeWrite<PxVec3> ); + PxU32* virtualParticles = reinterpret_cast<PxU32*>( dataBuffer.begin() ); + data->getVirtualParticles( virtualParticles ); + writeBuffer( inWriter, inTempBuffer, 18, virtualParticles, PtrAccess<PxU32>, numVirtualParticles * 4, "VirtualParticles", BasicDatatypeWrite<PxU32> ); + + // Now write the rest of the object data that the meta data generator got. + writeAllProperties( data, inWriter, inTempBuffer, *inCollection ); + } + + PxRepXObject PxClothRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection ) + { + PxU32 strideIgnored; + PxU32 numParticles; + PxClothParticle* particles = NULL; + + PxU32 numSpheres; + PxClothCollisionSphere* spheres = NULL; + PxU32 numCapsules; + PxU32* capsules = NULL; + PxU32 numPlanes; + PxClothCollisionPlane* planes = NULL; + PxU32 numConvexMasks; + PxU32* convexMasks = NULL; + PxU32 numTriangles; + PxClothCollisionTriangle* triangles = NULL; + + PxVec4* particleAccelerations = NULL; + PxU32 numParticleAccelerations = 0; + PxU32* selfCollisionIndices = NULL; + PxU32 numSelfCollisionIndices = 0; + PxClothParticleMotionConstraint* particleMotionConstraint = NULL; + PxU32 numParticleMotionConstraint = 0; + PxClothParticleSeparationConstraint* separationConstraints = NULL; + PxU32 numSeparationConstraints = 0; + + PxVec4* restPositions = NULL; + PxU32 numRestPositions; + PxU32 numVirtualParticleWeights; + PxU32 numParticleIndices = 0; + PxVec3* virtualParticleWeights = NULL; + PxU32* virtualParticles = NULL; + PxClothFlags flags; + PxClothFabric* fabric = NULL; + + readReference<PxClothFabric>( inReader, *inCollection, "Fabric", fabric ); + + if ( fabric == NULL ) + return PxRepXObject(); + + readStridedBufferProperty<PxClothParticle>( inReader, "Particles", particles, strideIgnored, numParticles, inAllocator ); + + readStridedBufferProperty<PxClothCollisionSphere>( inReader, "CollisionSpheres", spheres, strideIgnored, numSpheres, inAllocator ); + readStridedBufferProperty<PxU32>( inReader, "CollisionSpherePairs", capsules, strideIgnored, numCapsules, inAllocator ); + readStridedBufferProperty<PxClothCollisionPlane>( inReader, "CollisionPlanes", planes, strideIgnored, numPlanes, inAllocator ); + readStridedBufferProperty<PxU32>( inReader, "CollisionConvexMasks", convexMasks, strideIgnored, numConvexMasks, inAllocator ); + readStridedBufferProperty<PxClothCollisionTriangle>( inReader, "CollisionTriangles", triangles, strideIgnored, numTriangles, inAllocator ); + + readFlagsProperty( inReader, inAllocator, "ClothFlags", PxEnumTraits<PxClothFlag::Enum>().NameConversion, flags ); + + readStridedBufferProperty<PxVec4>( inReader, "ParticleAccelerations", particleAccelerations, strideIgnored, numParticleAccelerations, inAllocator ); + readStridedBufferProperty<PxU32>( inReader, "SelfCollisionIndices", selfCollisionIndices, strideIgnored, numSelfCollisionIndices, inAllocator ); + readStridedBufferProperty<PxClothParticleMotionConstraint>( inReader, "MotionConstraints", particleMotionConstraint, strideIgnored, numParticleMotionConstraint, inAllocator ); + readStridedBufferProperty<PxClothParticleSeparationConstraint>( inReader, "SeparationConstraints", separationConstraints, strideIgnored, numSeparationConstraints, inAllocator ); + readStridedBufferProperty<PxVec4>( inReader, "RestPositions", restPositions, strideIgnored, numRestPositions, inAllocator ); + + readStridedBufferProperty<PxVec3>( inReader, "VirtualParticleWeights", virtualParticleWeights, strideIgnored, numVirtualParticleWeights, inAllocator ); + readStridedBufferProperty<PxU32>( inReader, "VirtualParticles", virtualParticles, strideIgnored, numParticleIndices, inAllocator ); + + PxTransform initialPose( PxIdentity ); + PxCloth* cloth = inArgs.physics.createCloth( initialPose, *fabric, reinterpret_cast<PxClothParticle*>( particles ), flags ); + bool ret = readAllProperties( inArgs, inReader, cloth, inAllocator, *inCollection ); + + if( numSelfCollisionIndices ) + { + cloth->setSelfCollisionIndices( selfCollisionIndices, numSelfCollisionIndices ); + } + if( numParticleMotionConstraint ) + { + cloth->setMotionConstraints( particleMotionConstraint ); + } + if( numSeparationConstraints ) + { + cloth->setSeparationConstraints( separationConstraints ); + } + if( numParticleAccelerations ) + { + cloth->setParticleAccelerations(particleAccelerations); + } + + cloth->setCollisionSpheres(spheres, numSpheres); + while(numCapsules > 0) + { + PxU32 first = *capsules++, second = *capsules++; + cloth->addCollisionCapsule(first, second); + numCapsules -= 2; + } + + cloth->setCollisionPlanes(planes, numPlanes); + while(numConvexMasks-- > 0) + { + cloth->addCollisionConvex(*convexMasks++); + } + + cloth->setCollisionTriangles(triangles, numTriangles); + + if (numRestPositions) + cloth->setRestPositions(restPositions); + + PxU32 numVirtualParticles = numParticleIndices /4; + if ( numVirtualParticles && numVirtualParticleWeights ) + { + cloth->setVirtualParticles( numVirtualParticles, reinterpret_cast<PxU32*>( virtualParticles ), + numVirtualParticleWeights, reinterpret_cast<PxVec3*>( virtualParticleWeights ) ); + } + + return ret ? PxCreateRepXObject(cloth) : PxRepXObject(); + } +#endif // PX_USE_CLOTH_API + +#if PX_USE_PARTICLE_SYSTEM_API + template<typename TParticleType> + inline TParticleType* createParticles( PxPhysics& physics, PxU32 maxParticles, bool perParticleRestOffset ) + { + PX_UNUSED(physics); + PX_UNUSED(maxParticles); + PX_UNUSED(perParticleRestOffset); + return NULL; + } + + template<> + inline PxParticleSystem* createParticles<PxParticleSystem>(PxPhysics& physics, PxU32 maxParticles, bool perParticleRestOffset) + { + return physics.createParticleSystem( maxParticles, perParticleRestOffset ); + } + + template<> + inline PxParticleFluid* createParticles<PxParticleFluid>(PxPhysics& physics, PxU32 maxParticles, bool perParticleRestOffset) + { + return physics.createParticleFluid( maxParticles, perParticleRestOffset ); + } + + //************************************************************* + // Actual RepXSerializer implementations for PxParticleSystem & PxParticleFluid + //************************************************************* + template<typename TParticleType> + void PxParticleRepXSerializer<TParticleType>::objectToFileImpl( const TParticleType* data, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/) + { + PxParticleReadData* readData( const_cast<TParticleType*>( data )->lockParticleReadData() ); + writeProperty( inWriter, *inCollection, inTempBuffer, "NbParticles", readData->nbValidParticles ); + writeProperty( inWriter, *inCollection, inTempBuffer, "ValidParticleRange", readData->validParticleRange ); + PxParticleReadDataFlags readFlags(data->getParticleReadDataFlags()); + + if(readData->validParticleRange > 0) + { + writeBuffer( inWriter, inTempBuffer, 8 , readData->validParticleBitmap, PtrAccess<PxU32>, ((readData->validParticleRange-1) >> 5) + 1 ,"ValidParticleBitmap", BasicDatatypeWrite<PxU32> ); + + writeStridedBufferProperty<PxVec3>( inWriter, inTempBuffer, "Positions", readData->positionBuffer, readData->nbValidParticles, 6, writePxVec3); + + if(readFlags & PxParticleReadDataFlag::eVELOCITY_BUFFER) + { + writeStridedBufferProperty<PxVec3>( inWriter, inTempBuffer, "Velocities", readData->velocityBuffer, readData->nbValidParticles, 6, writePxVec3); + } + if(readFlags & PxParticleReadDataFlag::eREST_OFFSET_BUFFER) + { + writeStridedBufferProperty<PxF32>( inWriter, inTempBuffer, "RestOffsets", readData->restOffsetBuffer, readData->nbValidParticles, 6, BasicDatatypeWrite<PxF32>); + } + if(readFlags & PxParticleReadDataFlag::eFLAGS_BUFFER) + { + writeStridedFlagsProperty<PxParticleFlags>( inWriter, inTempBuffer, "Flags", readData->flagsBuffer, readData->nbValidParticles, 6, PxEnumTraits<PxParticleFlag::Enum>().NameConversion); + } + } + readData->unlock(); + + writeProperty( inWriter, *inCollection, inTempBuffer, "MaxParticles", data->getMaxParticles() ); + + PxParticleBaseFlags baseFlags(data->getParticleBaseFlags()); + writeFlagsProperty( inWriter, inTempBuffer, "ParticleBaseFlags", baseFlags, PxEnumTraits<PxParticleBaseFlag::Enum>().NameConversion ); + + writeFlagsProperty( inWriter, inTempBuffer, "ParticleReadDataFlags", readFlags, PxEnumTraits<PxParticleReadDataFlag::Enum>().NameConversion ); + + PxVec3 normal; + PxReal distance; + data->getProjectionPlane(normal, distance); + PxMetaDataPlane plane(normal, distance); + writeProperty( inWriter, *inCollection, inTempBuffer, "ProjectionPlane", plane); + + writeAllProperties( data, inWriter, inTempBuffer, *inCollection ); + } + + template<typename TParticleType> + PxRepXObject PxParticleRepXSerializer<TParticleType>::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection ) + { + PxU32 strideIgnored = 0; + PxU32 numParticles = 0; + readProperty( inReader, "NbParticles", numParticles ); + + PxU32 validParticleRange = 0; + readProperty( inReader, "ValidParticleRange", validParticleRange ); + + PxU32 numWrite; + PxU32* tempValidParticleBitmap = NULL; + readStridedBufferProperty<PxU32>( inReader, "ValidParticleBitmap", tempValidParticleBitmap, strideIgnored, numWrite, inAllocator ); + PxU32 *validParticleBitmap = reinterpret_cast<PxU32*>( tempValidParticleBitmap ); + + PxVec3* tempPosBuf = NULL; + readStridedBufferProperty<PxVec3>( inReader, "Positions", tempPosBuf, strideIgnored, numWrite, inAllocator ); + PxStrideIterator<const PxVec3> posBuffer(reinterpret_cast<const PxVec3*> (tempPosBuf)); + + PxVec3* tempVelBuf = NULL; + readStridedBufferProperty<PxVec3>( inReader, "Velocities", tempVelBuf, strideIgnored, numWrite, inAllocator ); + PxStrideIterator<const PxVec3> velBuffer(reinterpret_cast<const PxVec3*> (tempVelBuf)); + + PxF32* tempRestBuf = NULL; + readStridedBufferProperty<PxF32>( inReader, "RestOffsets", tempRestBuf, strideIgnored, numWrite, inAllocator ); + PxStrideIterator<const PxF32> restBuffer(reinterpret_cast<const PxF32*> (tempRestBuf)); + + PxU32* tempFlagBuf = NULL; + readStridedFlagsProperty<PxU32>( inReader, "Flags", tempFlagBuf, strideIgnored, numWrite, inAllocator , PxEnumTraits<PxParticleFlag::Enum>().NameConversion); + PxStrideIterator<const PxU32> flagBuffer(reinterpret_cast<const PxU32*> (tempFlagBuf)); + + Ps::Array<PxU32> validIndexBuf; + Ps::Array<PxVec3> validPosBuf, validVelBuf; + Ps::Array<PxF32> validRestBuf; + Ps::Array<PxU32> validFlagBuf; + + bool perParticleRestOffset = !!tempRestBuf; + bool bVelBuff = !!tempVelBuf; + bool bFlagBuff = !!tempFlagBuf; + + if (validParticleRange > 0) + { + for (PxU32 w = 0; w <= (validParticleRange-1) >> 5; w++) + { + for (PxU32 b = validParticleBitmap[w]; b; b &= b-1) + { + PxU32 index = (w<<5|physx::shdfnd::lowestSetBit(b)); + validIndexBuf.pushBack(index); + validPosBuf.pushBack(posBuffer[index]); + if(bVelBuff) + validVelBuf.pushBack(velBuffer[index]); + if(perParticleRestOffset) + validRestBuf.pushBack(restBuffer[index]); + if(bFlagBuff) + validFlagBuf.pushBack(flagBuffer[index]); + } + } + + PX_ASSERT(validIndexBuf.size() == numParticles); + + PxU32 maxParticleNum; + bool ret = readProperty( inReader, "MaxParticles", maxParticleNum ); + TParticleType* theParticle( createParticles<TParticleType>( inArgs.physics, maxParticleNum, perParticleRestOffset ) ); + PX_ASSERT( theParticle ); + ret &= readAllProperties( inArgs, inReader, theParticle, inAllocator, *inCollection ); + + PxParticleBaseFlags baseFlags; + ret &= readFlagsProperty( inReader, inAllocator, "ParticleBaseFlags", PxEnumTraits<PxParticleBaseFlag::Enum>().NameConversion, baseFlags ); + + PxU32 flagData = 1; + for(PxU32 i = 0; i < 16; i++) + { + flagData = PxU32(1 << i); + if( !(flagData & PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET) && (!!(PxU32(baseFlags) & flagData)) ) + { + theParticle->setParticleBaseFlag(PxParticleBaseFlag::Enum(flagData), true); + } + } + + PxParticleReadDataFlags readFlags; + ret &= readFlagsProperty( inReader, inAllocator, "ParticleReadDataFlags", PxEnumTraits<PxParticleReadDataFlag::Enum>().NameConversion, readFlags ); + for(PxU32 i = 0; i < 16; i++) + { + flagData = PxU32(1 << i); + if( !!(PxU32(readFlags) & flagData) ) + { + theParticle->setParticleReadDataFlag(PxParticleReadDataFlag::Enum(flagData), true); + } + } + + PxParticleCreationData creationData; + creationData.numParticles = numParticles; + creationData.indexBuffer = PxStrideIterator<const PxU32>(validIndexBuf.begin()); + creationData.positionBuffer = PxStrideIterator<const PxVec3>(validPosBuf.begin()); + if(bVelBuff) + creationData.velocityBuffer = PxStrideIterator<const PxVec3>(validVelBuf.begin()); + if(perParticleRestOffset) + creationData.restOffsetBuffer = PxStrideIterator<const PxF32>(validRestBuf.begin()); + if(bFlagBuff) + creationData.flagBuffer = PxStrideIterator<const PxU32>(validFlagBuf.begin()); + + theParticle->createParticles(creationData); + + return ret ? PxCreateRepXObject(theParticle) : PxRepXObject(); + } + else + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "PxSerialization::createCollectionFromXml: PxParticleRepXSerializer: " + "Xml field \"ValidParticleRange\" is zero!"); + return PxRepXObject(); + } + } + // explicit instantiations + template struct PxParticleRepXSerializer<PxParticleSystem>; + template struct PxParticleRepXSerializer<PxParticleFluid>; +#endif // #if PX_USE_PARTICLE_SYSTEM_API +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCoreSerializer.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCoreSerializer.h new file mode 100644 index 00000000..edd61210 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCoreSerializer.h @@ -0,0 +1,156 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef SN_REPX_CORE_SERIALIZER_H +#define SN_REPX_CORE_SERIALIZER_H +/** \addtogroup RepXSerializers + @{ +*/ +#include "foundation/PxSimpleTypes.h" +#include "SnRepXSerializerImpl.h" + +#if !PX_DOXYGEN +namespace physx +{ +#endif + + template<typename TLiveType> + struct RepXSerializerImpl; + + class XmlReader; + class XmlMemoryAllocator; + class XmlWriter; + class MemoryBuffer; + + struct PxMaterialRepXSerializer : RepXSerializerImpl<PxMaterial> + { + PxMaterialRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxMaterial>( inCallback ) {} + virtual PxMaterial* allocateObject( PxRepXInstantiationArgs& ); + }; + + struct PxShapeRepXSerializer : public RepXSerializerImpl<PxShape> + { + PxShapeRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxShape>( inCallback ) {} + virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* ); + virtual PxShape* allocateObject( PxRepXInstantiationArgs& ) { return NULL; } + }; + + struct PxBVH33TriangleMeshRepXSerializer : public RepXSerializerImpl<PxBVH33TriangleMesh> + { + PxBVH33TriangleMeshRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxBVH33TriangleMesh>( inCallback ) {} + virtual void objectToFileImpl( const PxBVH33TriangleMesh*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& ); + virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* ); + virtual PxBVH33TriangleMesh* allocateObject( PxRepXInstantiationArgs& ) { return NULL; } + }; + struct PxBVH34TriangleMeshRepXSerializer : public RepXSerializerImpl<PxBVH34TriangleMesh> + { + PxBVH34TriangleMeshRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxBVH34TriangleMesh>( inCallback ) {} + virtual void objectToFileImpl( const PxBVH34TriangleMesh*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& ); + virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* ); + virtual PxBVH34TriangleMesh* allocateObject( PxRepXInstantiationArgs& ) { return NULL; } + }; + + struct PxHeightFieldRepXSerializer : public RepXSerializerImpl<PxHeightField> + { + PxHeightFieldRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxHeightField>( inCallback ) {} + virtual void objectToFileImpl( const PxHeightField*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& ); + virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* ); + virtual PxHeightField* allocateObject( PxRepXInstantiationArgs& ) { return NULL; } + }; + + struct PxConvexMeshRepXSerializer : public RepXSerializerImpl<PxConvexMesh> + { + PxConvexMeshRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxConvexMesh>( inCallback ) {} + virtual void objectToFileImpl( const PxConvexMesh*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& ); + virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* ); + virtual PxConvexMesh* allocateObject( PxRepXInstantiationArgs& ) { return NULL; } + }; + + struct PxRigidStaticRepXSerializer : public RepXSerializerImpl<PxRigidStatic> + { + PxRigidStaticRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxRigidStatic>( inCallback ) {} + virtual PxRigidStatic* allocateObject( PxRepXInstantiationArgs& ); + }; + + struct PxRigidDynamicRepXSerializer : public RepXSerializerImpl<PxRigidDynamic> + { + PxRigidDynamicRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxRigidDynamic>( inCallback ) {} + virtual PxRigidDynamic* allocateObject( PxRepXInstantiationArgs& ); + }; + + struct PxArticulationRepXSerializer : public RepXSerializerImpl<PxArticulation> + { + PxArticulationRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxArticulation>( inCallback ) {} + virtual void objectToFileImpl( const PxArticulation*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& ); + virtual PxArticulation* allocateObject( PxRepXInstantiationArgs& ); + }; + + struct PxAggregateRepXSerializer : public RepXSerializerImpl<PxAggregate> + { + PxAggregateRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxAggregate>( inCallback ) {} + virtual void objectToFileImpl( const PxAggregate*, PxCollection*, XmlWriter& , MemoryBuffer&, PxRepXInstantiationArgs& ); + virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* ); + virtual PxAggregate* allocateObject( PxRepXInstantiationArgs& ) { return NULL; } + }; + +#if PX_USE_CLOTH_API + struct PxClothFabricRepXSerializer : public RepXSerializerImpl<PxClothFabric> + { + PxClothFabricRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxClothFabric>( inCallback ) {} + virtual void objectToFileImpl( const PxClothFabric*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& ); + virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* ); + virtual PxClothFabric* allocateObject( PxRepXInstantiationArgs& ) { return NULL; } + }; + + struct PxClothRepXSerializer : public RepXSerializerImpl<PxCloth> + { + PxClothRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxCloth>( inCallback ) {} + virtual void objectToFileImpl( const PxCloth*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& ); + virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* ); + virtual PxCloth* allocateObject( PxRepXInstantiationArgs& ) { return NULL; } + }; +#endif + +#if PX_USE_PARTICLE_SYSTEM_API + template<typename TParticleType> + struct PxParticleRepXSerializer : RepXSerializerImpl<TParticleType> + { + PxParticleRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<TParticleType>( inCallback ) {} + virtual void objectToFileImpl( const TParticleType*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& ); + virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* ); + virtual TParticleType* allocateObject( PxRepXInstantiationArgs& ) { return NULL; } + }; +#endif + +#if !PX_DOXYGEN +} // namespace physx +#endif + +#endif +/** @} */ + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXSerializerImpl.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXSerializerImpl.h new file mode 100644 index 00000000..08fe861a --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXSerializerImpl.h @@ -0,0 +1,90 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_REPX_SERIALIZER_IMPL_H +#define PX_REPX_SERIALIZER_IMPL_H + +#include "PsUserAllocated.h" +#include "SnXmlVisitorWriter.h" +#include "SnXmlVisitorReader.h" + +namespace physx { + using namespace Sn; + + /** + * The repx serializer impl takes the raw, untyped repx extension interface + * and implements the simpler functions plus does the reinterpret-casts required + * for any object to implement the serializer safely. + */ + template<typename TLiveType> + struct RepXSerializerImpl : public PxRepXSerializer, shdfnd::UserAllocated + { + protected: + RepXSerializerImpl( const RepXSerializerImpl& inOther ); + RepXSerializerImpl& operator=( const RepXSerializerImpl& inOther ); + + public: + PxAllocatorCallback& mAllocator; + + RepXSerializerImpl( PxAllocatorCallback& inAllocator ) + : mAllocator( inAllocator ) + { + } + + virtual const char* getTypeName() { return PxTypeInfo<TLiveType>::name(); } + + virtual void objectToFile( const PxRepXObject& inLiveObject, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& inArgs ) + { + const TLiveType* theObj = reinterpret_cast<const TLiveType*>( inLiveObject.serializable ); + objectToFileImpl( theObj, inCollection, inWriter, inTempBuffer, inArgs ); + } + + virtual PxRepXObject fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection ) + { + TLiveType* theObj( allocateObject( inArgs ) ); + if ( theObj ) + if(fileToObjectImpl( theObj, inReader, inAllocator, inArgs, inCollection )) + return PxCreateRepXObject(theObj); + return PxRepXObject(); + } + + virtual void objectToFileImpl( const TLiveType* inObj, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/) + { + writeAllProperties( inObj, inWriter, inTempBuffer, *inCollection ); + } + + virtual bool fileToObjectImpl( TLiveType* inObj, XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection ) + { + return readAllProperties( inArgs, inReader, inObj, inAllocator, *inCollection ); + } + + virtual TLiveType* allocateObject( PxRepXInstantiationArgs& inArgs ) = 0; + }; +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXUpgrader.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXUpgrader.cpp new file mode 100644 index 00000000..5eb2f40e --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXUpgrader.cpp @@ -0,0 +1,444 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "CmPhysXCommon.h" +#include "SnXmlImpl.h" +#include "SnXmlReader.h" +#include "SnXmlMemoryAllocator.h" +#include "PsFoundation.h" +#include "SnRepXCollection.h" +#include "SnRepXUpgrader.h" + +using namespace physx::profile; + +namespace physx { namespace Sn { + + #define DEFINE_REPX_DEFAULT_PROPERTY( name, val ) RepXDefaultEntry( name, val ), + + static RepXDefaultEntry gRepX1_0Defaults[] = { + #include "SnRepX1_0Defaults.h" + }; + static PxU32 gNumRepX1_0Default = sizeof( gRepX1_0Defaults ) / sizeof ( *gRepX1_0Defaults ); + + static RepXDefaultEntry gRepX3_1Defaults[] = { + #include "SnRepX3_1Defaults.h" + }; + static PxU32 gNumRepX3_1Defaults = sizeof( gRepX3_1Defaults ) / sizeof ( *gRepX3_1Defaults ); + + static RepXDefaultEntry gRepX3_2Defaults[] = { + #include "SnRepX3_2Defaults.h" + }; + static PxU32 gNumRepX3_2Defaults = sizeof( gRepX3_2Defaults ) / sizeof ( *gRepX3_2Defaults ); + + inline const char* nextPeriod( const char* str ) + { + for( ++str; str && *str && *str != '.'; ++str ); //empty loop intentional + return str; + } + + inline bool safeStrEq(const char* lhs, const char* rhs) + { + if (lhs == rhs) + return true; + //If they aren't equal, and one of them is null, + //then they can't be equal. + //This is assuming that the null char* is not equal to + //the empty "" char*. + if (!lhs || !rhs) + return false; + + return ::strcmp(lhs, rhs) == 0; + } + + typedef PxProfileHashMap<const char*, PxU32> TNameOffsetMap; + + void setMissingPropertiesToDefault( XmlNode* topNode, XmlReaderWriter& editor, const RepXDefaultEntry* defaults, PxU32 numDefaults, TNameOffsetMap& map ) + { + for ( XmlNode* child = topNode->mFirstChild; child != NULL; child = child->mNextSibling ) + setMissingPropertiesToDefault( child, editor, defaults, numDefaults, map ); + + const TNameOffsetMap::Entry* entry( map.find( topNode->mName ) ); + if ( entry ) + { + XmlReaderWriter& theReader( editor ); + theReader.setNode( *topNode ); + char nameBuffer[512] = {0}; + size_t nameLen = strlen( topNode->mName ); + //For each default property entry for this node type. + for ( const RepXDefaultEntry* item = defaults + entry->second; strncmp( item->name, topNode->mName, nameLen ) == 0; ++item ) + { + bool childAdded = false; + const char* nameStart = item->name + nameLen; + ++nameStart; + theReader.pushCurrentContext(); + const char* str = nameStart; + while( *str ) + { + const char *period = nextPeriod( str ); + size_t len = size_t(PxMin( period - str, ptrdiff_t(1023) )); //can't be too careful these days. + memcpy( nameBuffer, str, len ); + nameBuffer[len] = 0; + if ( theReader.gotoChild( nameBuffer ) == false ) + { + childAdded = true; + theReader.addOrGotoChild( nameBuffer ); + } + if (*period ) + str = period + 1; + else + str = period; + } + if ( childAdded ) + theReader.setCurrentItemValue( item->value ); + theReader.popCurrentContext(); + } + } + } + + + static void setMissingPropertiesToDefault( RepXCollection& collection, XmlReaderWriter& editor, const RepXDefaultEntry* defaults, PxU32 numDefaults ) + { + PxProfileAllocatorWrapper wrapper( collection.getAllocator() ); + //Release all strings at once, instead of piece by piece + XmlMemoryAllocatorImpl alloc( collection.getAllocator() ); + //build a hashtable of the initial default value strings. + TNameOffsetMap nameOffsets( wrapper ); + for ( PxU32 idx = 0; idx < numDefaults; ++idx ) + { + const RepXDefaultEntry& item( defaults[idx] ); + size_t nameLen = 0; + const char* periodPtr = nextPeriod (item.name); + for ( ; periodPtr && *periodPtr; ++periodPtr ) if( *periodPtr == '.' ) break; + if ( periodPtr == NULL || *periodPtr != '.' ) continue; + nameLen = size_t(periodPtr - item.name); + char* newMem = reinterpret_cast<char*>(alloc.allocate( PxU32(nameLen + 1) )); + memcpy( newMem, item.name, nameLen ); + newMem[nameLen] = 0; + + if ( nameOffsets.find( newMem ) ) + alloc.deallocate( reinterpret_cast<PxU8*>(newMem) ); + else + nameOffsets.insert( newMem, idx ); + } + //Run through each collection item, and recursively find it and its children + //If an object's name is in the hash map, check and add any properties that don't exist. + //else return. + for ( const RepXCollectionItem* item = collection.begin(), *end = collection.end(); item != end; ++ item ) + { + RepXCollectionItem theItem( *item ); + setMissingPropertiesToDefault( theItem.descriptor, editor, defaults, numDefaults, nameOffsets ); + } + } + + struct RecursiveTraversal + { + RecursiveTraversal(XmlReaderWriter& editor): mEditor(editor) {} + void traverse() + { + mEditor.pushCurrentContext(); + updateNode(); + for(bool exists = mEditor.gotoFirstChild(); exists; exists = mEditor.gotoNextSibling()) + traverse(); + mEditor.popCurrentContext(); + } + virtual void updateNode() = 0; + virtual ~RecursiveTraversal() {} + XmlReaderWriter& mEditor; + protected: + RecursiveTraversal& operator=(const RecursiveTraversal&){return *this;} + }; + + + RepXCollection& RepXUpgrader::upgrade10CollectionTo3_1Collection(RepXCollection& src) + { + XmlReaderWriter& editor( src.createNodeEditor() ); + setMissingPropertiesToDefault(src, editor, gRepX1_0Defaults, gNumRepX1_0Default ); + + + RepXCollection* dest = &src.createCollection("3.1.1"); + + for ( const RepXCollectionItem* item = src.begin(), *end = src.end(); item != end; ++ item ) + { + //either src or dest could do the copy operation, it doesn't matter who does it. + RepXCollectionItem newItem( item->liveObject, src.copyRepXNode( item->descriptor ) ); + editor.setNode( *const_cast<XmlNode*>( newItem.descriptor ) ); + //Some old files have this name in their system. + editor.renameProperty( "MassSpaceInertia", "MassSpaceInertiaTensor" ); + editor.renameProperty( "SleepEnergyThreshold", "SleepThreshold" ); + + if ( strstr( newItem.liveObject.typeName, "Joint" ) || strstr( newItem.liveObject.typeName, "joint" ) ) + { + //Joints changed format a bit. old joints looked like: + /* + <Actor0 >1627536</Actor0> + <Actor1 >1628368</Actor1> + <LocalPose0 >0 0 0 1 0.5 0.5 0.5</LocalPose0> + <LocalPose1 >0 0 0 1 0.3 0.3 0.3</LocalPose1>*/ + //New joints look like: + /* + <Actors > + <actor0 >58320336</actor0> + <actor1 >56353568</actor1> + </Actors> + <LocalPose > + <eACTOR0 >0 0 0 1 0.5 0.5 0.5</eACTOR0> + <eACTOR1 >0 0 0 1 0.3 0.3 0.3</eACTOR1> + </LocalPose> + */ + const char* actor0, *actor1, *lp0, *lp1; + editor.readAndRemoveProperty( "Actor0", actor0 ); + editor.readAndRemoveProperty( "Actor1", actor1 ); + editor.readAndRemoveProperty( "LocalPose0", lp0 ); + editor.readAndRemoveProperty( "LocalPose1", lp1 ); + + editor.addOrGotoChild( "Actors" ); + editor.writePropertyIfNotEmpty( "actor0", actor0 ); + editor.writePropertyIfNotEmpty( "actor1", actor1 ); + editor.leaveChild(); + + editor.addOrGotoChild( "LocalPose" ); + editor.writePropertyIfNotEmpty( "eACTOR0", lp0 ); + editor.writePropertyIfNotEmpty( "eACTOR1", lp1 ); + editor.leaveChild(); + } + + + + //now desc owns the new node. Collections share a single allocation pool, however, + //which will get destroyed when all the collections referencing it are destroyed themselves. + //Data on nodes is shared between nodes, but the node structure itself is allocated. + dest->addCollectionItem( newItem ); + } + editor.release(); + src.destroy(); + return *dest; + } + + RepXCollection& RepXUpgrader::upgrade3_1CollectionTo3_2Collection(RepXCollection& src) + { + XmlReaderWriter& editor( src.createNodeEditor() ); + setMissingPropertiesToDefault(src, editor, gRepX3_1Defaults, gNumRepX3_1Defaults ); + + RepXCollection* dest = &src.createCollection("3.2.0"); + + for ( const RepXCollectionItem* item = src.begin(), *end = src.end(); item != end; ++ item ) + { + //either src or dest could do the copy operation, it doesn't matter who does it. + RepXCollectionItem newItem( item->liveObject, src.copyRepXNode( item->descriptor ) ); + editor.setNode( *const_cast<XmlNode*>( newItem.descriptor ) ); + + if ( strstr( newItem.liveObject.typeName, "PxMaterial" ) ) + { + editor.removeChild( "DynamicFrictionV" ); + editor.removeChild( "StaticFrictionV" ); + editor.removeChild( "dirOfAnisotropy" ); + } + //now desc owns the new node. Collections share a single allocation pool, however, + //which will get destroyed when all the collections referencing it are destroyed themselves. + //Data on nodes is shared between nodes, but the node structure itself is allocated. + dest->addCollectionItem( newItem ); + } + editor.release(); + src.destroy(); + return *dest; + } + + RepXCollection& RepXUpgrader::upgrade3_2CollectionTo3_3Collection(RepXCollection& src) + { + XmlReaderWriter& editor( src.createNodeEditor() ); + setMissingPropertiesToDefault(src, editor, gRepX3_2Defaults, gNumRepX3_2Defaults ); + + RepXCollection* dest = &src.createCollection("3.3.0"); + + + + struct RenameSpringToStiffness : public RecursiveTraversal + { + RenameSpringToStiffness(XmlReaderWriter& editor_): RecursiveTraversal(editor_) {} + + void updateNode() + { + mEditor.renameProperty("Spring", "Stiffness"); + mEditor.renameProperty("TangentialSpring", "TangentialStiffness"); + } + }; + + + struct UpdateArticulationSwingLimit : public RecursiveTraversal + { + UpdateArticulationSwingLimit(XmlReaderWriter& editor_): RecursiveTraversal(editor_) {} + + void updateNode() + { + if(!Ps::stricmp(mEditor.getCurrentItemName(), "yLimit") && !Ps::stricmp(mEditor.getCurrentItemValue(), "0")) + mEditor.setCurrentItemValue("0.785398"); + + if(!Ps::stricmp(mEditor.getCurrentItemName(), "zLimit") && !Ps::stricmp(mEditor.getCurrentItemValue(), "0")) + mEditor.setCurrentItemValue("0.785398"); + + if(!Ps::stricmp(mEditor.getCurrentItemName(), "TwistLimit")) + { + mEditor.gotoFirstChild(); + PxReal lower = PxReal(strtod(mEditor.getCurrentItemValue(), NULL)); + mEditor.gotoNextSibling(); + PxReal upper = PxReal(strtod(mEditor.getCurrentItemValue(), NULL)); + mEditor.leaveChild(); + if(lower>=upper) + { + mEditor.writePropertyIfNotEmpty("lower", "-0.785398"); + mEditor.writePropertyIfNotEmpty("upper", "0.785398"); + } + } + } + }; + + + for ( const RepXCollectionItem* item = src.begin(), *end = src.end(); item != end; ++ item ) + { + //either src or dest could do the copy operation, it doesn't matter who does it. + RepXCollectionItem newItem( item->liveObject, src.copyRepXNode( item->descriptor ) ); + + + if ( strstr( newItem.liveObject.typeName, "PxCloth" ) || strstr( newItem.liveObject.typeName, "PxClothFabric" ) ) + { + physx::shdfnd::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "Didn't suppot PxCloth upgrate from 3.2 to 3.3! "); + continue; + } + + if ( strstr( newItem.liveObject.typeName, "PxParticleSystem" ) || strstr( newItem.liveObject.typeName, "PxParticleFluid" ) ) + { + editor.setNode( *const_cast<XmlNode*>( newItem.descriptor ) ); + editor.renameProperty( "PositionBuffer", "Positions" ); + editor.renameProperty( "VelocityBuffer", "Velocities" ); + editor.renameProperty( "RestOffsetBuffer", "RestOffsets" ); + } + + if(strstr(newItem.liveObject.typeName, "PxPrismaticJoint" ) + || strstr(newItem.liveObject.typeName, "PxRevoluteJoint") + || strstr(newItem.liveObject.typeName, "PxSphericalJoint") + || strstr(newItem.liveObject.typeName, "PxD6Joint") + || strstr(newItem.liveObject.typeName, "PxArticulation")) + { + editor.setNode( *const_cast<XmlNode*>( newItem.descriptor ) ); + RenameSpringToStiffness(editor).traverse(); + } + + if(strstr(newItem.liveObject.typeName, "PxArticulation")) + { + editor.setNode( *const_cast<XmlNode*>( newItem.descriptor ) ); + UpdateArticulationSwingLimit(editor).traverse(); + } + + + + //now dest owns the new node. Collections share a single allocation pool, however, + //which will get destroyed when all the collections referencing it are destroyed themselves. + //Data on nodes is shared between nodes, but the node structure itself is allocated. + + dest->addCollectionItem( newItem ); + + } + editor.release(); + src.destroy(); + + return *dest; + } + + RepXCollection& RepXUpgrader::upgrade3_3CollectionTo3_4Collection(RepXCollection& src) + { + RepXCollection* dest = &src.createCollection("3.4.0"); + + for ( const RepXCollectionItem* item = src.begin(), *end = src.end(); item != end; ++ item ) + { + if(strstr(item->liveObject.typeName, "PxTriangleMesh")) + { + PxRepXObject newMeshRepXObj("PxBVH33TriangleMesh", item->liveObject.serializable, item->liveObject.id); + XmlNode* newMeshNode = src.copyRepXNode( item->descriptor ); + newMeshNode->mName = "PxBVH33TriangleMesh"; + RepXCollectionItem newMeshItem(newMeshRepXObj, newMeshNode); + dest->addCollectionItem( newMeshItem ); + continue; + } + + RepXCollectionItem newItem( item->liveObject, src.copyRepXNode( item->descriptor ) ); + dest->addCollectionItem( newItem ); + } + src.destroy(); + return *dest; + } + + RepXCollection& RepXUpgrader::upgradeCollection(RepXCollection& src) + { + const char* srcVersion = src.getVersion(); + if( safeStrEq( srcVersion, RepXCollection::getLatestVersion() )) + return src; + + static const char* oldVersions[] = {"1.0", + "3.1", + "3.1.1", + "3.2.0", + "3.3.0", + "3.3.1", + "3.3.2" + };//should be increase order + + PxU32 grade = UINT16_MAX; + const PxU32 count = sizeof(oldVersions)/sizeof(oldVersions[0]); + for (PxU32 i=0; i<count; i++) + { + if( safeStrEq( srcVersion, oldVersions[i] )) + { + grade = i; + break; + } + } + + typedef RepXCollection& (*UPGRADE_FUNCTION)(RepXCollection& src); + + UPGRADE_FUNCTION procs[count] = + { + upgrade10CollectionTo3_1Collection, + NULL, + upgrade3_1CollectionTo3_2Collection, + upgrade3_2CollectionTo3_3Collection, + NULL, + NULL, + upgrade3_3CollectionTo3_4Collection, + }; + + RepXCollection* dest = &src; + for( PxU32 j = grade; j < count; j++ ) + { + if( procs[j] ) + dest = &(procs[j])(*dest); + } + + return *dest; + } +} } diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXUpgrader.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXUpgrader.h new file mode 100644 index 00000000..9baf270c --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXUpgrader.h @@ -0,0 +1,53 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_REPX_UPGRADER_H +#define PX_REPX_UPGRADER_H + +#include "foundation/PxSimpleTypes.h" + +namespace physx { namespace Sn { + class RepXCollection; + + class RepXUpgrader + { + public: + //If a new collection is created, the source collection is destroyed. + //Thus you only need to release the new collection. + //This holds for all of the upgrade functions. + //So be aware, that the argument to these functions may not be valid + //after they are called, but the return value always will be valid. + static RepXCollection& upgradeCollection( RepXCollection& src ); + static RepXCollection& upgrade10CollectionTo3_1Collection( RepXCollection& src ); + static RepXCollection& upgrade3_1CollectionTo3_2Collection( RepXCollection& src ); + static RepXCollection& upgrade3_2CollectionTo3_3Collection( RepXCollection& src ); + static RepXCollection& upgrade3_3CollectionTo3_4Collection( RepXCollection& src ); + }; +} } + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnSimpleXmlWriter.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnSimpleXmlWriter.h new file mode 100644 index 00000000..6f63fefc --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnSimpleXmlWriter.h @@ -0,0 +1,257 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_SIMPLEXMLWRITER_H +#define PX_SIMPLEXMLWRITER_H + +#include "PsArray.h" +#include "SnXmlMemoryPoolStreams.h" +#include "CmPhysXCommon.h" + +namespace physx { namespace Sn { + class SimpleXmlWriter + { + public: + + struct STagWatcher + { + typedef SimpleXmlWriter TXmlWriterType; + TXmlWriterType& mWriter; + STagWatcher( const STagWatcher& inOther ); + STagWatcher& operator-( const STagWatcher& inOther ); + STagWatcher( TXmlWriterType& inWriter, const char* inTagName ) + : mWriter( inWriter ) + { + mWriter.beginTag( inTagName ); + } + ~STagWatcher() { mWriter.endTag(); } + protected: + STagWatcher& operator=(const STagWatcher&); + }; + + virtual ~SimpleXmlWriter(){} + virtual void beginTag( const char* inTagname ) = 0; + virtual void endTag() = 0; + virtual void addAttribute( const char* inName, const char* inValue ) = 0; + virtual void writeContentTag( const char* inTag, const char* inContent ) = 0; + virtual void addContent( const char* inContent ) = 0; + virtual PxU32 tabCount() = 0; + private: + SimpleXmlWriter& operator=(const SimpleXmlWriter&); + }; + + template<typename TStreamType> + class SimpleXmlWriterImpl : public SimpleXmlWriter + { + PxProfileAllocatorWrapper mWrapper; + TStreamType& mStream; + SimpleXmlWriterImpl( const SimpleXmlWriterImpl& inOther ); + SimpleXmlWriterImpl& operator=( const SimpleXmlWriterImpl& inOther ); + PxProfileArray<const char*> mTags; + bool mTagOpen; + PxU32 mInitialTagDepth; + public: + + SimpleXmlWriterImpl( TStreamType& inStream, PxAllocatorCallback& inAllocator, PxU32 inInitialTagDepth = 0 ) + : mWrapper( inAllocator ) + , mStream( inStream ) + , mTags( mWrapper ) + , mTagOpen( false ) + , mInitialTagDepth( inInitialTagDepth ) + { + } + virtual ~SimpleXmlWriterImpl() + { + while( mTags.size() ) + endTag(); + } + PxU32 tabCount() { return mTags.size() + mInitialTagDepth; } + + void writeTabs( PxU32 inSize ) + { + inSize += mInitialTagDepth; + for ( PxU32 idx =0; idx < inSize; ++idx ) + mStream << "\t"; + } + void beginTag( const char* inTagname ) + { + closeTag(); + writeTabs(mTags.size()); + mTags.pushBack( inTagname ); + mStream << "<" << inTagname; + mTagOpen = true; + } + void addAttribute( const char* inName, const char* inValue ) + { + PX_ASSERT( mTagOpen ); + mStream << " " << inName << "=" << "\"" << inValue << "\""; + } + void closeTag(bool useNewline = true) + { + if ( mTagOpen ) + { + mStream << " " << ">"; + if (useNewline ) + mStream << "\n"; + } + mTagOpen = false; + } + void doEndOpenTag() + { + mStream << "</" << mTags.back() << ">" << "\n"; + } + void endTag() + { + PX_ASSERT( mTags.size() ); + if ( mTagOpen ) + mStream << " " << "/>" << "\n"; + else + { + writeTabs(mTags.size()-1); + doEndOpenTag(); + } + mTagOpen = false; + mTags.popBack(); + } + + static bool IsNormalizableWhitespace(char c) { return c == 0x9 || c == 0xA || c == 0xD; } + static bool IsValidXmlCharacter(char c) { return IsNormalizableWhitespace(c) || c >= 0x20; } + + void addContent( const char* inContent ) + { + closeTag(false); + //escape xml + for( ; *inContent; inContent++ ) + { + switch (*inContent) + { + case '<': + mStream << "<"; + break; + case '>': + mStream << ">"; + break; + case '&': + mStream << "&"; + break; + case '\'': + mStream << "'"; + break; + case '"': + mStream << """; + break; + default: + if (IsValidXmlCharacter(*inContent)) { + if (IsNormalizableWhitespace(*inContent)) + { + char s[32]; + Ps::snprintf(s, 32, "&#x%02X;", unsigned(*inContent)); + mStream << s; + } + else + mStream << *inContent; + } + break; + } + } + } + + void writeContentTag( const char* inTag, const char* inContent ) + { + beginTag( inTag ); + addContent( inContent ); + doEndOpenTag(); + mTags.popBack(); + } + void insertXml( const char* inXml ) + { + closeTag(); + mStream << inXml; + } + }; + + struct BeginTag + { + const char* mTagName; + BeginTag( const char* inTagName ) + : mTagName( inTagName ) { } + }; + + struct EndTag + { + EndTag() {} + }; + + struct Att + { + const char* mAttName; + const char* mAttValue; + Att( const char* inAttName, const char* inAttValue ) + : mAttName( inAttName ) + , mAttValue( inAttValue ) { } + }; + + struct Content + { + const char* mContent; + Content( const char* inContent ) + : mContent( inContent ) { } + }; + + + struct ContentTag + { + const char* mTagName; + const char* mContent; + ContentTag( const char* inTagName, const char* inContent ) + : mTagName( inTagName ) + , mContent( inContent ) { } + }; + + inline SimpleXmlWriter& operator<<( SimpleXmlWriter& inWriter, const BeginTag& inTag ) { inWriter.beginTag( inTag.mTagName ); return inWriter; } + inline SimpleXmlWriter& operator<<( SimpleXmlWriter& inWriter, const EndTag& inTag ) { PX_UNUSED(inTag); inWriter.endTag(); return inWriter; } + inline SimpleXmlWriter& operator<<( SimpleXmlWriter& inWriter, const Att& inTag ) { inWriter.addAttribute(inTag.mAttName, inTag.mAttValue); return inWriter; } + inline SimpleXmlWriter& operator<<( SimpleXmlWriter& inWriter, const Content& inTag ) { inWriter.addContent(inTag.mContent); return inWriter; } + inline SimpleXmlWriter& operator<<( SimpleXmlWriter& inWriter, const ContentTag& inTag ) { inWriter.writeContentTag(inTag.mTagName, inTag.mContent); return inWriter; } + + inline void writeProperty( SimpleXmlWriter& inWriter, MemoryBuffer& tempBuffer, const char* inPropName ) + { + PxU8 data = 0; + tempBuffer.write( &data, sizeof(PxU8) ); + inWriter.writeContentTag( inPropName, reinterpret_cast<const char*>( tempBuffer.mBuffer ) ); + tempBuffer.clear(); + } + + template<typename TDataType> + inline void writeProperty( SimpleXmlWriter& inWriter, MemoryBuffer& tempBuffer, const char* inPropName, TDataType inValue ) + { + tempBuffer << inValue; + writeProperty( inWriter, tempBuffer, inPropName ); + } +} } +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlDeserializer.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlDeserializer.h new file mode 100644 index 00000000..fdb29359 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlDeserializer.h @@ -0,0 +1,188 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_XML_DESERIALIZER_H +#define PX_XML_DESERIALIZER_H + +#include "SnXmlVisitorReader.h" + +namespace physx { namespace Sn { + + //Definitions needed internally in the Serializer headers. + template<typename TTriIndexElem> + struct Triangle + { + TTriIndexElem mIdx0; + TTriIndexElem mIdx1; + TTriIndexElem mIdx2; + Triangle( TTriIndexElem inIdx0 = 0, TTriIndexElem inIdx1 = 0, TTriIndexElem inIdx2 = 0) + : mIdx0( inIdx0 ) + , mIdx1( inIdx1 ) + , mIdx2( inIdx2 ) + { + } + }; + + struct XmlMemoryAllocateMemoryPoolAllocator + { + XmlMemoryAllocator* mAllocator; + XmlMemoryAllocateMemoryPoolAllocator( XmlMemoryAllocator* inAlloc ) : mAllocator( inAlloc ) {} + + PxU8* allocate( PxU32 inSize ) { return mAllocator->allocate( inSize ); } + void deallocate( PxU8* inMem ) { mAllocator->deallocate( inMem ); } + }; + + inline void strtoLong( Triangle<PxU32>& ioDatatype,const char*& ioData ) + { + strto( ioDatatype.mIdx0, ioData ); + strto( ioDatatype.mIdx1, ioData ); + strto( ioDatatype.mIdx2, ioData ); + } + + inline void strtoLong( PxHeightFieldSample& ioDatatype,const char*& ioData ) + { + PxU32 tempData; + strto( tempData, ioData ); + if ( isBigEndian() ) + { + PxU32& theItem(tempData); + PxU32 theDest = 0; + PxU8* theReadPtr( reinterpret_cast< PxU8* >( &theItem ) ); + PxU8* theWritePtr( reinterpret_cast< PxU8* >( &theDest ) ); + //A height field sample is a 16 bit number + //followed by two bytes. + + //We write this out as a 32 bit integer, LE. + //Thus, on a big endian, we need to move the bytes + //around a bit. + //LE - 1 2 3 4 + //BE - 4 3 2 1 - after convert from xml number + //Correct BE - 2 1 3 4, just like LE but with the 16 number swapped + theWritePtr[0] = theReadPtr[2]; + theWritePtr[1] = theReadPtr[3]; + theWritePtr[2] = theReadPtr[1]; + theWritePtr[3] = theReadPtr[0]; + theItem = theDest; + } + ioDatatype = *reinterpret_cast<PxHeightFieldSample*>( &tempData ); + } + + template<typename TDataType> + inline void readStridedFlagsProperty( XmlReader& ioReader, const char* inPropName, TDataType*& outData, PxU32& outStride, PxU32& outCount, XmlMemoryAllocator& inAllocator, + const PxU32ToName* inConversions) + { + const char* theSrcData; + outStride = sizeof( TDataType ); + outData = NULL; + outCount = 0; + if ( ioReader.read( inPropName, theSrcData ) ) + { + XmlMemoryAllocateMemoryPoolAllocator tempAllocator( &inAllocator ); + MemoryBufferBase<XmlMemoryAllocateMemoryPoolAllocator> tempBuffer( &tempAllocator ); + + if ( theSrcData ) + { + static PxU32 theCount = 0; + ++theCount; + char* theStartData = const_cast< char*>( copyStr( &tempAllocator, theSrcData ) ); + char* aData = strtok(theStartData, " \n"); + while( aData ) + { + TDataType tempValue; + stringToFlagsType( aData, inAllocator, tempValue, inConversions ); + aData = strtok(NULL," \n"); + tempBuffer.write( &tempValue, sizeof(TDataType) ); + } + outData = reinterpret_cast< TDataType* >( tempBuffer.mBuffer ); + outCount = tempBuffer.mWriteOffset / sizeof( TDataType ); + tempAllocator.deallocate( reinterpret_cast<PxU8*>(theStartData) ); + } + tempBuffer.releaseBuffer(); + } + } + + template<typename TDataType> + inline void readStridedBufferProperty( XmlReader& ioReader, const char* inPropName, TDataType*& outData, PxU32& outStride, PxU32& outCount, XmlMemoryAllocator& inAllocator) + { + const char* theSrcData; + outStride = sizeof( TDataType ); + outData = NULL; + outCount = 0; + if ( ioReader.read( inPropName, theSrcData ) ) + { + XmlMemoryAllocateMemoryPoolAllocator tempAllocator( &inAllocator ); + MemoryBufferBase<XmlMemoryAllocateMemoryPoolAllocator> tempBuffer( &tempAllocator ); + + if ( theSrcData ) + { + static PxU32 theCount = 0; + ++theCount; + char* theStartData = const_cast< char*>( copyStr( &tempAllocator, theSrcData ) ); + const char* theData = theStartData; + PxU32 theLen = strLenght( theData ); + const char* theEndData = theData + theLen; + while( theData < theEndData ) + { + //These buffers are whitespace delimited. + TDataType theType; + strtoLong( theType, theData ); + tempBuffer.write( &theType, sizeof(theType) ); + } + outData = reinterpret_cast< TDataType* >( tempBuffer.mBuffer ); + outCount = tempBuffer.mWriteOffset / sizeof( TDataType ); + tempAllocator.deallocate( reinterpret_cast<PxU8*>(theStartData) ); + } + tempBuffer.releaseBuffer(); + } + } + + template<typename TDataType> + inline void readStridedBufferProperty( XmlReader& ioReader, const char* inPropName, PxStridedData& ioData, PxU32& outCount, XmlMemoryAllocator& inAllocator) + { + TDataType* tempData = NULL; + readStridedBufferProperty<TDataType>( ioReader, inPropName, tempData, ioData.stride, outCount, inAllocator ); + ioData.data = tempData; + } + + template<typename TDataType> + inline void readStridedBufferProperty( XmlReader& ioReader, const char* inPropName, PxTypedStridedData<TDataType>& ioData, PxU32& outCount, XmlMemoryAllocator& inAllocator) + { + TDataType* tempData = NULL; + readStridedBufferProperty<TDataType>( ioReader, inPropName, tempData, ioData.stride, outCount, inAllocator ); + ioData.data = reinterpret_cast<PxMaterialTableIndex*>( tempData ); + } + + template<typename TDataType> + inline void readStridedBufferProperty( XmlReader& ioReader, const char* inPropName, PxBoundedData& ioData, XmlMemoryAllocator& inAllocator) + { + return readStridedBufferProperty<TDataType>( ioReader, inPropName, ioData, ioData.count, inAllocator ); + } + +} } + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlImpl.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlImpl.h new file mode 100644 index 00000000..1718cc86 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlImpl.h @@ -0,0 +1,242 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_XML_IMPL_H +#define PX_XML_IMPL_H + +#include "SnXmlMemoryPool.h" +#include "PsString.h" + +namespace physx { namespace Sn { + +typedef CMemoryPoolManager TMemoryPoolManager; + +namespace snXmlImpl { + + inline PxU32 strLen( const char* inStr ) + { + PxU32 len = 0; + if ( inStr ) + { + while ( *inStr ) + { + ++len; + ++inStr; + } + } + return len; + } +} + inline const char* copyStr( PxAllocatorCallback& inAllocator, const char* inStr ) + { + if ( inStr && *inStr ) + { + PxU32 theLen = snXmlImpl::strLen( inStr ); + //The memory will never be released by repx. If you want it released, you need to pass in a custom allocator + //that tracks all allocations and releases unreleased allocations yourself. + char* dest = reinterpret_cast<char* >( inAllocator.allocate( theLen + 1, "Repx::const char*", __FILE__, __LINE__ ) ); + memcpy( dest, inStr, theLen ); + dest[theLen] = 0; + return dest; + } + return ""; + } + + template<typename TManagerType> + inline const char* copyStr( TManagerType* inMgr, const char* inStr ) + { + if ( inStr && *inStr ) + { + PxU32 theLen = snXmlImpl::strLen( inStr ); + char* dest = reinterpret_cast<char* >( inMgr->allocate( theLen + 1 ) ); + memcpy( dest, inStr, theLen ); + dest[theLen] = 0; + return dest; + } + return ""; + } + + inline void releaseStr( TMemoryPoolManager* inMgr, const char* inStr, PxU32 ) + { + if ( inStr && *inStr ) + { + inMgr->deallocate( reinterpret_cast< PxU8* >( const_cast<char*>( inStr ) ) ); + } + } + + inline void releaseStr( TMemoryPoolManager* inMgr, const char* inStr ) + { + if ( inStr && *inStr ) + { + PxU32 theLen = snXmlImpl::strLen( inStr ); + releaseStr( inMgr, inStr, theLen ); + } + } + + struct XmlNode + { + const char* mName; //Never released until all collections are released + const char* mData; //Never released until all collections are released + + XmlNode* mNextSibling; + XmlNode* mPreviousSibling; + XmlNode* mFirstChild; + XmlNode* mParent; + XmlNode( const XmlNode& ); + XmlNode& operator=( const XmlNode& ); + + PX_INLINE void initPtrs() + { + mNextSibling = NULL; + mPreviousSibling = NULL; + mFirstChild = NULL; + mParent = NULL; + } + + PX_INLINE XmlNode( const char* inName = "", const char* inData = "" ) + : mName( inName ) + , mData( inData ) + { initPtrs(); } + + void addChild( XmlNode* inItem ) + { + inItem->mParent = this; + if ( mFirstChild == NULL ) + mFirstChild = inItem; + else + { + XmlNode* theNode = mFirstChild; + //Follow the chain till the end. + while( theNode->mNextSibling != NULL ) + theNode = theNode->mNextSibling; + theNode->mNextSibling = inItem; + inItem->mPreviousSibling = theNode; + } + } + + PX_INLINE XmlNode* findChildByName( const char* inName ) + { + for ( XmlNode* theNode = mFirstChild; theNode; theNode = theNode->mNextSibling ) + { + XmlNode* theRepXNode = theNode; + if ( physx::shdfnd::stricmp( theRepXNode->mName, inName ) == 0 ) + return theNode; + } + return NULL; + } + + PX_INLINE void orphan() + { + if ( mParent ) + { + if ( mParent->mFirstChild == this ) + mParent->mFirstChild = mNextSibling; + } + if ( mPreviousSibling ) + mPreviousSibling->mNextSibling = mNextSibling; + if ( mNextSibling ) + mNextSibling->mPreviousSibling = mPreviousSibling; + if ( mFirstChild ) + mFirstChild->mParent = NULL; + initPtrs(); + } + }; + + inline XmlNode* allocateRepXNode( TMemoryPoolManager* inManager, const char* inName, const char* inData ) + { + XmlNode* retval = inManager->allocate<XmlNode>(); + retval->mName = copyStr( inManager, inName ); + retval->mData = copyStr( inManager, inData ); + return retval; + } + + inline void release( TMemoryPoolManager* inManager, XmlNode* inNode ) + { + //We *don't* release the strings associated with the node + //because they could be shared. Instead, we just let them 'leak' + //in some sense, at least until the memory manager itself is deleted. + //DO NOT UNCOMMENT THE LINES BELOW!! + //releaseStr( inManager, inNode->mName ); + //releaseStr( inManager, inNode->mData ); + inManager->deallocate( inNode ); + } + + static PX_INLINE void releaseNodeAndChildren( TMemoryPoolManager* inManager, XmlNode* inNode ) + { + if ( inNode->mFirstChild ) + { + XmlNode* childNode( inNode->mFirstChild ); + while( childNode ) + { + XmlNode* _node( childNode ); + childNode = _node->mNextSibling; + releaseNodeAndChildren( inManager, _node ); + } + } + inNode->orphan(); + release( inManager, inNode ); + } + + static XmlNode* copyRepXNodeAndSiblings( TMemoryPoolManager* inManager, const XmlNode* inNode, XmlNode* inParent ); + + static XmlNode* copyRepXNode( TMemoryPoolManager* inManager, const XmlNode* inNode, XmlNode* inParent = NULL ) + { + XmlNode* newNode( allocateRepXNode( inManager, NULL, NULL ) ); + newNode->mName = inNode->mName; //Some light structural sharing + newNode->mData = inNode->mData; //Some light structural sharing + newNode->mParent = inParent; + if ( inNode->mFirstChild ) + newNode->mFirstChild = copyRepXNodeAndSiblings( inManager, inNode->mFirstChild, newNode ); + return newNode; + } + + static XmlNode* copyRepXNodeAndSiblings( TMemoryPoolManager* inManager, const XmlNode* inNode, XmlNode* inParent ) + { + XmlNode* sibling = inNode->mNextSibling; + if ( sibling ) sibling = copyRepXNodeAndSiblings( inManager, sibling, inParent ); + XmlNode* newNode = copyRepXNode( inManager, inNode, inParent ); + newNode->mNextSibling = sibling; + if ( sibling ) sibling->mPreviousSibling = newNode; + return newNode; + } + + inline bool isBigEndian() { int i = 1; return *(reinterpret_cast<char*>(&i))==0; } + + + struct NameStackEntry + { + const char* mName; + bool mOpen; + NameStackEntry( const char* nm ) : mName( nm ), mOpen( false ) {} + }; + + typedef PxProfileArray<NameStackEntry> TNameStack; +} } + + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryAllocator.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryAllocator.h new file mode 100644 index 00000000..8172a312 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryAllocator.h @@ -0,0 +1,129 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_XML_MEMORY_ALLOCATOR_H +#define PX_XML_MEMORY_ALLOCATOR_H + +#include "foundation/PxSimpleTypes.h" + +namespace physx { + + class XmlMemoryAllocator + { + protected: + virtual ~XmlMemoryAllocator(){} + public: + virtual PxU8* allocate(PxU32 inSize) = 0; + virtual void deallocate( PxU8* inMem ) = 0; + virtual PxAllocatorCallback& getAllocator() = 0; + template<typename TObjectType> + TObjectType* allocate() + { + TObjectType* retval = reinterpret_cast< TObjectType* >( allocate( sizeof( TObjectType ) ) ); + new (retval) TObjectType(); + return retval; + } + + template<typename TObjectType, typename TArgType> + TObjectType* allocate(const TArgType &arg) + { + TObjectType* retval = reinterpret_cast< TObjectType* >( allocate( sizeof( TObjectType ) ) ); + new (retval) TObjectType(arg); + return retval; + } + + template<typename TObjectType> + void deallocate( TObjectType* inObject ) + { + deallocate( reinterpret_cast<PxU8*>( inObject ) ); + } + template<typename TObjectType> + inline TObjectType* batchAllocate(PxU32 inCount ) + { + TObjectType* retval = reinterpret_cast<TObjectType*>( allocate( sizeof(TObjectType) * inCount ) ); + for ( PxU32 idx = 0; idx < inCount; ++idx ) + { + new (retval + idx) TObjectType(); + } + return retval; + } + + template<typename TObjectType, typename TArgType> + inline TObjectType* batchAllocate(PxU32 inCount, const TArgType &arg) + { + TObjectType* retval = reinterpret_cast<TObjectType*>( allocate( sizeof(TObjectType) * inCount ) ); + for ( PxU32 idx = 0; idx < inCount; ++idx ) + { + new (retval + idx) TObjectType(arg); + } + return retval; + } + + + //Duplicate function definition for gcc. + template<typename TObjectType> + inline TObjectType* batchAllocate(TObjectType*, PxU32 inCount ) + { + TObjectType* retval = reinterpret_cast<TObjectType*>( allocate( sizeof(TObjectType) * inCount ) ); + for ( PxU32 idx = 0; idx < inCount; ++idx ) + { + new (retval + idx) TObjectType(); + } + return retval; + } + }; + + struct XmlMemoryAllocatorImpl : public XmlMemoryAllocator + { + Sn::TMemoryPoolManager mManager; + + XmlMemoryAllocatorImpl( PxAllocatorCallback& inAllocator ) + : mManager( inAllocator ) + { + } + XmlMemoryAllocatorImpl &operator=(const XmlMemoryAllocatorImpl &); + virtual PxAllocatorCallback& getAllocator() + { + return mManager.getWrapper().getAllocator(); + } + + virtual PxU8* allocate(PxU32 inSize ) + { + if ( !inSize ) + return NULL; + + return mManager.allocate( inSize ); + } + virtual void deallocate( PxU8* inMem ) + { + if ( inMem ) + mManager.deallocate( inMem ); + } + }; +} +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryPool.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryPool.h new file mode 100644 index 00000000..2c1177e3 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryPool.h @@ -0,0 +1,373 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_XML_MEMORYPOOL_H +#define PX_XML_MEMORYPOOL_H + +#include "foundation/PxAssert.h" +#include "PsArray.h" +#include "PxProfileAllocatorWrapper.h" + +namespace physx { + + using namespace physx::profile; + + /** + * Linked list used to store next node ptr. + */ + struct SMemPoolNode + { + SMemPoolNode* mNextNode; + }; + + /** + * Template arguments are powers of two. + * A very fast memory pool that is not memory efficient. It contains a vector of pointers + * to blocks of memory along with a linked list of free sections. All sections are + * of the same size so allocating memory is very fast, there isn't a linear search + * through blocks of indeterminate size. It also means there is memory wasted + * when objects aren't sized to powers of two. + */ + template<PxU8 TItemSize + , PxU8 TItemCount > + class CMemoryPool + { + typedef PxProfileArray<PxU8*> TPxU8PtrList; + + PxProfileAllocatorWrapper& mWrapper; + TPxU8PtrList mAllMemory; + SMemPoolNode* mFirstFreeNode; + public: + CMemoryPool(PxProfileAllocatorWrapper& inWrapper) + : mWrapper( inWrapper ) + , mAllMemory( inWrapper ) + , mFirstFreeNode( NULL ) + {} + ~CMemoryPool() + { + TPxU8PtrList::ConstIterator theEnd = mAllMemory.end(); + for ( TPxU8PtrList::ConstIterator theIter = mAllMemory.begin(); + theIter != theEnd; + ++theIter ) + { + PxU8* thePtr = *theIter; + mWrapper.getAllocator().deallocate( thePtr ); + } + mAllMemory.clear(); + mFirstFreeNode = NULL; + } + //Using deallocated memory to hold the pointers to the next amount of memory. + PxU8* allocate() + { + if ( mFirstFreeNode ) + { + PxU8* retval = reinterpret_cast<PxU8*>(mFirstFreeNode); + mFirstFreeNode = mFirstFreeNode->mNextNode; + return retval; + } + PxU32 itemSize = GetItemSize(); + PxU32 itemCount = 1 << TItemCount; + //No free nodes, make some more. + PxU8* retval = reinterpret_cast<PxU8*>(mWrapper.getAllocator().allocate( itemCount * itemSize, "RepX fixed-size memory pool", __FILE__, __LINE__ )); + PxU8* dataPtr = retval + itemSize; + //Free extra chunks + for( PxU32 idx = 1; idx < itemCount; ++idx, dataPtr += itemSize ) + deallocate( dataPtr ); + mAllMemory.pushBack(retval); + return retval; + } + void deallocate( PxU8* inData ) + { + SMemPoolNode* nodePtr = reinterpret_cast<SMemPoolNode*>(inData); + nodePtr->mNextNode = mFirstFreeNode; + mFirstFreeNode = nodePtr; + } + //We have to have at least a pointer's worth of memory + inline PxU32 GetItemSize() { return sizeof(SMemPoolNode) << TItemSize; } + }; + + typedef PxU32 TMemAllocSizeType; + + struct SVariableMemPoolNode : SMemPoolNode + { + TMemAllocSizeType mSize; + SVariableMemPoolNode* NextNode() { return static_cast< SVariableMemPoolNode* >( mNextNode ); } + }; + + /** + * Manages variable sized allocations. + * Keeps track of freed allocations in a insertion sorted + * list. Allocating new memory traverses the list linearly. + * This object will split nodes if the node is more than + * twice as large as the request memory allocation. + */ + class CVariableMemoryPool + { + typedef PxProfileHashMap<TMemAllocSizeType, SVariableMemPoolNode*> TFreeNodeMap; + typedef PxProfileArray<PxU8*> TPxU8PtrList; + PxProfileAllocatorWrapper& mWrapper; + TPxU8PtrList mAllMemory; + TFreeNodeMap mFreeNodeMap; + PxU32 mMinAllocationSize; + + CVariableMemoryPool &operator=(const CVariableMemoryPool &); + + public: + CVariableMemoryPool(PxProfileAllocatorWrapper& inWrapper, PxU32 inMinAllocationSize = 0x20 ) + : mWrapper( inWrapper ) + , mAllMemory( inWrapper ) + , mFreeNodeMap( inWrapper) + , mMinAllocationSize( inMinAllocationSize ) + {} + + ~CVariableMemoryPool() + { + TPxU8PtrList::ConstIterator theEnd = mAllMemory.end(); + for ( TPxU8PtrList::ConstIterator theIter = mAllMemory.begin(); + theIter != theEnd; + ++theIter ) + { + PxU8* thePtr = *theIter; + mWrapper.getAllocator().deallocate( thePtr ); + } + mAllMemory.clear(); + mFreeNodeMap.clear(); + } + PxU8* MarkMem( PxU8* inMem, TMemAllocSizeType inSize ) + { + PX_ASSERT( inSize >= sizeof( SVariableMemPoolNode ) ); + SVariableMemPoolNode* theMem = reinterpret_cast<SVariableMemPoolNode*>( inMem ); + theMem->mSize = inSize; + return reinterpret_cast< PxU8* >( theMem + 1 ); + } + //Using deallocated memory to hold the pointers to the next amount of memory. + PxU8* allocate( PxU32 size ) + { + //Ensure we can place the size of the memory at the start + //of the memory block. + //Kai: to reduce the size of hash map, the requested size is aligned to 128 bytes + PxU32 theRequestedSize = (size + sizeof(SVariableMemPoolNode) + 127) & ~127; + + TFreeNodeMap::Entry* entry = const_cast<TFreeNodeMap::Entry*>( mFreeNodeMap.find( theRequestedSize ) ); + if ( NULL != entry ) + { + SVariableMemPoolNode* theNode = entry->second; + PX_ASSERT( NULL != theNode ); + PX_ASSERT( theNode->mSize == theRequestedSize ); + entry->second = theNode->NextNode(); + if (entry->second == NULL) + mFreeNodeMap.erase( theRequestedSize ); + + return reinterpret_cast< PxU8* >( theNode + 1 ); + } + + if ( theRequestedSize < mMinAllocationSize ) + theRequestedSize = mMinAllocationSize; + + //No large enough free nodes, make some more. + PxU8* retval = reinterpret_cast<PxU8*>(mWrapper.getAllocator().allocate( size_t(theRequestedSize), "RepX variable sized memory pool", __FILE__, __LINE__ )); + //If we allocated it, we free it. + mAllMemory.pushBack( retval ); + return MarkMem( retval, theRequestedSize ); + } + + //The size is stored at the beginning of the memory block. + void deallocate( PxU8* inData ) + { + SVariableMemPoolNode* theData = reinterpret_cast< SVariableMemPoolNode* >( inData ) - 1; + TMemAllocSizeType theSize = theData->mSize; + AddFreeMem( reinterpret_cast< PxU8* >( theData ), theSize ); + } + + void CheckFreeListInvariant( SVariableMemPoolNode* inNode ) + { + if ( inNode && inNode->mNextNode ) + { + PX_ASSERT( inNode->mSize <= inNode->NextNode()->mSize ); + } + } + + void AddFreeMem( PxU8* inMemory, TMemAllocSizeType inSize ) + { + PX_ASSERT( inSize >= sizeof( SVariableMemPoolNode ) ); + SVariableMemPoolNode* theNewNode = reinterpret_cast< SVariableMemPoolNode* >( inMemory ); + theNewNode->mNextNode = NULL; + theNewNode->mSize = inSize; + TFreeNodeMap::Entry* entry = const_cast<TFreeNodeMap::Entry*>( mFreeNodeMap.find( inSize ) ); + if (NULL != entry) + { + theNewNode->mNextNode = entry->second; + entry->second = theNewNode; + } + else + { + mFreeNodeMap.insert( inSize, theNewNode ); + } + } + }; + + /** + * The manager keeps a list of memory pools for different sizes of allocations. + * Anything too large simply gets allocated using the new operator. + * This doesn't mark the memory with the size of the allocated memory thus + * allowing much more efficient allocation of small items. For large enough + * allocations, it does mark the size. + * + * When using as a general memory manager, you need to wrap this class with + * something that actually does mark the returned allocation with the size + * of the allocation. + */ + class CMemoryPoolManager + { + CMemoryPoolManager &operator=(const CMemoryPoolManager &); + + public: + PxProfileAllocatorWrapper mWrapper; + + //CMemoryPool<0,8> m0ItemPool; + //CMemoryPool<1,8> m1ItemPool; + //CMemoryPool<2,8> m2ItemPool; + //CMemoryPool<3,8> m3ItemPool; + //CMemoryPool<4,8> m4ItemPool; + //CMemoryPool<5,8> m5ItemPool; + //CMemoryPool<6,8> m6ItemPool; + //CMemoryPool<7,8> m7ItemPool; + //CMemoryPool<8,8> m8ItemPool; + CVariableMemoryPool mVariablePool; + CMemoryPoolManager( PxAllocatorCallback& inAllocator ) + : mWrapper( inAllocator ) + //, m0ItemPool( mWrapper ) + //, m1ItemPool( mWrapper ) + //, m2ItemPool( mWrapper ) + //, m3ItemPool( mWrapper ) + //, m4ItemPool( mWrapper ) + //, m5ItemPool( mWrapper ) + //, m6ItemPool( mWrapper ) + //, m7ItemPool( mWrapper ) + //, m8ItemPool( mWrapper ) + , mVariablePool( mWrapper ) + { + } + PxProfileAllocatorWrapper& getWrapper() { return mWrapper; } + inline PxU8* allocate( PxU32 inSize ) + { + /* + if ( inSize <= m0ItemPool.GetItemSize() ) + return m0ItemPool.allocate(); + if ( inSize <= m1ItemPool.GetItemSize() ) + return m1ItemPool.allocate(); + if ( inSize <= m2ItemPool.GetItemSize() ) + return m2ItemPool.allocate(); + if ( inSize <= m3ItemPool.GetItemSize() ) + return m3ItemPool.allocate(); + if ( inSize <= m4ItemPool.GetItemSize() ) + return m4ItemPool.allocate(); + if ( inSize <= m5ItemPool.GetItemSize() ) + return m5ItemPool.allocate(); + if ( inSize <= m6ItemPool.GetItemSize() ) + return m6ItemPool.allocate(); + if ( inSize <= m7ItemPool.GetItemSize() ) + return m7ItemPool.allocate(); + if ( inSize <= m8ItemPool.GetItemSize() ) + return m8ItemPool.allocate(); + */ + return mVariablePool.allocate( inSize ); + } + inline void deallocate( PxU8* inMemory ) + { + if ( inMemory == NULL ) + return; + /* + if ( inSize <= m0ItemPool.GetItemSize() ) + m0ItemPool.deallocate(inMemory); + else if ( inSize <= m1ItemPool.GetItemSize() ) + m1ItemPool.deallocate(inMemory); + else if ( inSize <= m2ItemPool.GetItemSize() ) + m2ItemPool.deallocate(inMemory); + else if ( inSize <= m3ItemPool.GetItemSize() ) + m3ItemPool.deallocate(inMemory); + else if ( inSize <= m4ItemPool.GetItemSize() ) + m4ItemPool.deallocate(inMemory); + else if ( inSize <= m5ItemPool.GetItemSize() ) + m5ItemPool.deallocate(inMemory); + else if ( inSize <= m6ItemPool.GetItemSize() ) + m6ItemPool.deallocate(inMemory); + else if ( inSize <= m7ItemPool.GetItemSize() ) + m7ItemPool.deallocate(inMemory); + else if ( inSize <= m8ItemPool.GetItemSize() ) + m8ItemPool.deallocate(inMemory); + else + */ + mVariablePool.deallocate(inMemory); + } + /** + * allocate an object. Calls constructor on the new memory. + */ + template<typename TObjectType> + inline TObjectType* allocate() + { + TObjectType* retval = reinterpret_cast<TObjectType*>( allocate( sizeof(TObjectType) ) ); + new (retval)TObjectType(); + return retval; + } + + /** + * deallocate an object calling the destructor on the object. + * This *must* be the concrete type, it cannot be a generic type. + */ + template<typename TObjectType> + inline void deallocate( TObjectType* inObject ) + { + inObject->~TObjectType(); + deallocate( reinterpret_cast<PxU8*>(inObject) ); + } + + /** + * allocate an object. Calls constructor on the new memory. + */ + template<typename TObjectType> + inline TObjectType* BatchAllocate(PxU32 inCount ) + { + TObjectType* retval = reinterpret_cast<TObjectType*>( allocate( sizeof(TObjectType) * inCount ) ); + return retval; + } + + /** + * deallocate an object calling the destructor on the object. + * This *must* be the concrete type, it cannot be a generic type. + */ + template<typename TObjectType> + inline void BatchDeallocate( TObjectType* inObject, PxU32 inCount ) + { + PX_UNUSED(inCount); + deallocate( reinterpret_cast<PxU8*>(inObject) ); + } + }; +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryPoolStreams.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryPoolStreams.h new file mode 100644 index 00000000..375d1e2d --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryPoolStreams.h @@ -0,0 +1,173 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_XML_MEMORY_POOL_STREAMS_H +#define PX_XML_MEMORY_POOL_STREAMS_H + +#include "foundation/PxTransform.h" +#include "foundation/PxIO.h" +#include "SnXmlMemoryPool.h" +#include "CmPhysXCommon.h" + +namespace physx { + + template<typename TDataType> + struct XmlDefaultValue + { + bool force_compile_error; + }; + + +#define XML_DEFINE_DEFAULT_VALUE(type, defVal ) \ + template<> \ + struct XmlDefaultValue<type> \ + { \ + type getDefaultValue() { return type(defVal); } \ + }; + + XML_DEFINE_DEFAULT_VALUE(PxU8, 0) + XML_DEFINE_DEFAULT_VALUE(PxI8, 0) + XML_DEFINE_DEFAULT_VALUE(PxU16, 0) + XML_DEFINE_DEFAULT_VALUE(PxI16, 0) + XML_DEFINE_DEFAULT_VALUE(PxU32, 0) + XML_DEFINE_DEFAULT_VALUE(PxI32, 0) + XML_DEFINE_DEFAULT_VALUE(PxU64, 0) + XML_DEFINE_DEFAULT_VALUE(PxI64, 0) + XML_DEFINE_DEFAULT_VALUE(PxF32, 0) + XML_DEFINE_DEFAULT_VALUE(PxF64, 0) + +#undef XML_DEFINE_DEFAULT_VALUE + + template<> + struct XmlDefaultValue<PxVec3> + { + PxVec3 getDefaultValue() { return PxVec3( 0,0,0 ); } + }; + + template<> + struct XmlDefaultValue<PxTransform> + { + PxTransform getDefaultValue() { return PxTransform(PxIdentity); } + }; + + template<> + struct XmlDefaultValue<PxQuat> + { + PxQuat getDefaultValue() { return PxQuat(PxIdentity); } + }; + +/** + * Mapping of PxOutputStream to a memory pool manager. + * Allows write-then-read semantics of a set of + * data. Can safely write up to 4GB of data; then you + * will silently fail... + */ + +template<typename TAllocatorType> +struct MemoryBufferBase : public PxOutputStream, public PxInputStream +{ + TAllocatorType* mManager; + mutable PxU32 mWriteOffset; + mutable PxU32 mReadOffset; + PxU8* mBuffer; + PxU32 mCapacity; + + + MemoryBufferBase( TAllocatorType* inManager ) + : mManager( inManager ) + , mWriteOffset( 0 ) + , mReadOffset( 0 ) + , mBuffer( NULL ) + , mCapacity( 0 ) + { + } + virtual ~MemoryBufferBase() + { + mManager->deallocate( mBuffer ); + } + PxU8* releaseBuffer() + { + clear(); + mCapacity = 0; + PxU8* retval(mBuffer); + mBuffer = NULL; + return retval; + } + void clear() + { + mWriteOffset = mReadOffset = 0; + } + + virtual PxU32 read(void* dest, PxU32 count) + { + bool fits = ( mReadOffset + count ) <= mWriteOffset; + PX_ASSERT( fits ); + if ( fits ) + { + memcpy( dest, mBuffer + mReadOffset, count ); + mReadOffset += count; + return count; + } + return 0; + } + + inline void checkCapacity( PxU32 inNewCapacity ) + { + if ( mCapacity < inNewCapacity ) + { + PxU32 newCapacity = 32; + while( newCapacity < inNewCapacity ) + newCapacity = newCapacity << 1; + + PxU8* newData( mManager->allocate( newCapacity ) ); + if ( mWriteOffset ) + memcpy( newData, mBuffer, mWriteOffset ); + mManager->deallocate( mBuffer ); + mBuffer = newData; + mCapacity = newCapacity; + } + } + + virtual PxU32 write(const void* src, PxU32 count) + { + checkCapacity( mWriteOffset + count ); + memcpy( mBuffer + mWriteOffset, src, count ); + mWriteOffset += count; + return count; + } +}; + +class MemoryBuffer : public MemoryBufferBase<CMemoryPoolManager > +{ +public: + MemoryBuffer( CMemoryPoolManager* inManager ) : MemoryBufferBase<CMemoryPoolManager >( inManager ) {} +}; + +} + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlReader.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlReader.h new file mode 100644 index 00000000..88053d96 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlReader.h @@ -0,0 +1,130 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_XML_READER_H +#define PX_XML_READER_H + +#include "foundation/PxSimpleTypes.h" +#include "extensions/PxRepXSimpleType.h" + +namespace physx { + namespace Sn { struct XmlNode; } + + /** + * Reader used to read data out of the repx format. + */ + class XmlReader + { + protected: + virtual ~XmlReader(){} + public: + /** Read a key-value pair out of the database */ + virtual bool read( const char* inName, const char*& outData ) = 0; + /** Read an object id out of the database */ + virtual bool read( const char* inName, PxSerialObjectId& outId ) = 0; + /** Goto a child element by name. That child becomes this reader's context */ + virtual bool gotoChild( const char* inName ) = 0; + /** Goto the first child regardless of name */ + virtual bool gotoFirstChild() = 0; + /** Goto the next sibling regardless of name */ + virtual bool gotoNextSibling() = 0; + /** Count all children of the current object */ + virtual PxU32 countChildren() = 0; + /** Get the name of the current item */ + virtual const char* getCurrentItemName() = 0; + /** Get the value of the current item */ + virtual const char* getCurrentItemValue() = 0; + /** Leave the current child */ + virtual bool leaveChild() = 0; + /** Get reader for the parental object */ + virtual XmlReader* getParentReader() = 0; + + /** + * Ensures we don't leave the reader in an odd state + * due to not leaving a given child + */ + virtual void pushCurrentContext() = 0; + /** Pop the current context back to where it during push*/ + virtual void popCurrentContext() = 0; + }; + + //Used when upgrading a repx collection + class XmlReaderWriter : public XmlReader + { + public: + //Clears the stack of nodes (push/pop current node reset) + //and sets the current node to inNode. + virtual void setNode( Sn::XmlNode& node ) = 0; + //If the child exists, add it. + //the either way goto that child. + virtual void addOrGotoChild( const char* name ) = 0; + //Value is copied into the collection, inValue has no further references + //to it. + virtual void setCurrentItemValue( const char* value ) = 0; + //Removes the child but does not release the char* name or char* data ptrs. + //Those pointers are never released and are shared among collections. + //Thus copying nodes is cheap and safe. + virtual bool removeChild( const char* name ) = 0; + virtual void release() = 0; + + bool renameProperty( const char* oldName, const char* newName ) + { + if ( gotoChild( oldName ) ) + { + const char* value = getCurrentItemValue(); + leaveChild(); + removeChild( oldName ); + addOrGotoChild( newName ); + setCurrentItemValue( value ); + leaveChild(); + return true; + } + return false; + } + bool readAndRemoveProperty( const char* name, const char*& outValue ) + { + bool retval = read( name, outValue ); + if ( retval ) removeChild( name ); + return retval; + } + + bool writePropertyIfNotEmpty( const char* name, const char* value ) + { + if ( value && *value ) + { + addOrGotoChild( name ); + setCurrentItemValue( value ); + leaveChild(); + return true; + } + return false; + } + }; + +} +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSerialization.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSerialization.cpp new file mode 100644 index 00000000..af86eafd --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSerialization.cpp @@ -0,0 +1,834 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#include "SnXmlImpl.h" +#include "PsHash.h" +#include "PsHashMap.h" +#include "SnSimpleXmlWriter.h" +#include "PsSort.h" +#include "PsFastXml.h" +#include "PsString.h" +#include "SnXmlMemoryPool.h" +#include "PxExtensionMetaDataObjects.h" +#include "SnXmlVisitorWriter.h" +#include "SnXmlVisitorReader.h" +#include "SnXmlMemoryAllocator.h" +#include "SnXmlStringToType.h" +#include "PsString.h" +#include "SnRepXCollection.h" +#include "SnRepXUpgrader.h" +#include "../SnSerializationRegistry.h" +#include "PsFoundation.h" +#include "CmCollection.h" + +using namespace physx; +using namespace Sn; + +using namespace physx::profile; //for the foundation wrapper system. + +namespace physx { namespace Sn { + + class XmlNodeWriter : public SimpleXmlWriter + { + XmlMemoryAllocatorImpl& mParseAllocator; + XmlNode* mCurrentNode; + XmlNode* mTopNode; + PxU32 mTabCount; + + public: + XmlNodeWriter( XmlMemoryAllocatorImpl& inAllocator, PxU32 inTabCount = 0 ) + : mParseAllocator( inAllocator ) + , mCurrentNode( NULL ) + , mTopNode( NULL ) + , mTabCount( inTabCount ) + {} + XmlNodeWriter& operator=(const XmlNodeWriter&); + virtual ~XmlNodeWriter(){} + void onNewNode( XmlNode* newNode ) + { + if ( mCurrentNode != NULL ) + mCurrentNode->addChild( newNode ); + if ( mTopNode == NULL ) + mTopNode = newNode; + mCurrentNode = newNode; + ++mTabCount; + } + + XmlNode* getTopNode() const { return mTopNode; } + + virtual void beginTag( const char* inTagname ) + { + onNewNode( allocateRepXNode( &mParseAllocator.mManager, inTagname, NULL ) ); + } + virtual void endTag() + { + if ( mCurrentNode ) + mCurrentNode = mCurrentNode->mParent; + if ( mTabCount ) + --mTabCount; + } + virtual void addAttribute( const char*, const char* ) + { + PX_ASSERT( false ); + } + virtual void writeContentTag( const char* inTag, const char* inContent ) + { + onNewNode( allocateRepXNode( &mParseAllocator.mManager, inTag, inContent ) ); + endTag(); + } + virtual void addContent( const char* inContent ) + { + if ( mCurrentNode->mData ) + releaseStr( &mParseAllocator.mManager, mCurrentNode->mData ); + mCurrentNode->mData = copyStr( &mParseAllocator.mManager, inContent ); + } + virtual PxU32 tabCount() { return mTabCount; } + }; + + struct XmlWriterImpl : public XmlWriter + { + PxU32 mTagDepth; + SimpleXmlWriter* mWriter; + MemoryBuffer* mMemBuffer; + + XmlWriterImpl( SimpleXmlWriter* inWriter, MemoryBuffer* inMemBuffer ) + : mTagDepth( 0 ) + , mWriter( inWriter ) + , mMemBuffer( inMemBuffer ) + { + } + ~XmlWriterImpl() + { + while( mTagDepth ) + { + --mTagDepth; + mWriter->endTag(); + } + } + virtual void write( const char* inName, const char* inData ) + { + mWriter->writeContentTag( inName, inData ); + } + virtual void write( const char* inName, const PxRepXObject& inLiveObject ) + { + (*mMemBuffer) << inLiveObject.id; + writeProperty( *mWriter, *mMemBuffer, inName ); + } + virtual void addAndGotoChild( const char* inName ) + { + mWriter->beginTag( inName ); + mTagDepth++; + } + virtual void leaveChild() + { + if ( mTagDepth ) + { + mWriter->endTag(); + --mTagDepth; + } + } + }; + + struct XmlParseArgs + { + XmlMemoryAllocatorImpl* mAllocator; + PxProfileArray<RepXCollectionItem>* mCollection; + + XmlParseArgs( XmlMemoryAllocatorImpl* inAllocator + , PxProfileArray<RepXCollectionItem>* inCollection) + : mAllocator( inAllocator ) + , mCollection( inCollection ) + { + } + }; + + struct XmlNodeReader : public XmlReaderWriter + { + PxProfileAllocatorWrapper mWrapper; + CMemoryPoolManager& mManager; + XmlNode* mCurrentNode; + XmlNode* mTopNode; + PxProfileArray<XmlNode*> mContext; + XmlNodeReader( XmlNode* inCurrentNode, PxAllocatorCallback& inAllocator, CMemoryPoolManager& nodePoolManager ) + : mWrapper( inAllocator ) + , mManager( nodePoolManager ) + , mCurrentNode( inCurrentNode ) + , mTopNode( inCurrentNode ) + , mContext( mWrapper ) + { + } + + //Does this node exist as data in the format. + virtual bool read( const char* inName, const char*& outData ) + { + XmlNode* theChild( mCurrentNode->findChildByName( inName ) ); + if ( theChild ) + { + outData = theChild->mData; + return outData && *outData; + } + return false; + } + + virtual bool read( const char* inName, PxSerialObjectId& outId ) + { + XmlNode* theChild( mCurrentNode->findChildByName( inName ) ); + if ( theChild ) + { + const char* theValue( theChild->mData ); + strto( outId, theValue ); + return true; + } + return false; + } + + virtual bool gotoChild( const char* inName ) + { + XmlNode* theChild( mCurrentNode->findChildByName( inName ) ); + if ( theChild ) + { + mCurrentNode =theChild; + return true; + } + return false; + } + virtual bool gotoFirstChild() + { + if ( mCurrentNode->mFirstChild ) + { + mCurrentNode = mCurrentNode->mFirstChild; + return true; + } + return false; + } + virtual bool gotoNextSibling() + { + if ( mCurrentNode->mNextSibling ) + { + mCurrentNode = mCurrentNode->mNextSibling; + return true; + } + return false; + } + virtual PxU32 countChildren() + { + PxU32 retval= 0; + for ( XmlNode* theChild = mCurrentNode->mFirstChild; theChild != NULL; theChild = theChild->mNextSibling ) + ++retval; + return retval; + } + virtual const char* getCurrentItemName() + { + return mCurrentNode->mName; + } + virtual const char* getCurrentItemValue() + { + return mCurrentNode->mData; + } + + virtual bool leaveChild() + { + if ( mCurrentNode != mTopNode && mCurrentNode->mParent ) + { + mCurrentNode = mCurrentNode->mParent; + return true; + } + return false; + } + + virtual void pushCurrentContext() + { + mContext.pushBack( mCurrentNode ); + } + virtual void popCurrentContext() + { + if ( mContext.size() ) + { + mCurrentNode = mContext.back(); + mContext.popBack(); + } + } + + virtual void setNode( XmlNode& inNode ) + { + mContext.clear(); + mCurrentNode = &inNode; + mTopNode = mCurrentNode; + } + + virtual XmlReader* getParentReader() + { + XmlReader* retval = PX_PLACEMENT_NEW((mWrapper.getAllocator().allocate(sizeof(XmlNodeReader), "createNodeEditor", __FILE__, __LINE__ )), XmlNodeReader) + ( mTopNode, mWrapper.getAllocator(), mManager ); + return retval; + } + + virtual void addOrGotoChild( const char* inName ) + { + if ( gotoChild( inName )== false ) + { + XmlNode* newNode = allocateRepXNode( &mManager, inName, NULL ); + mCurrentNode->addChild( newNode ); + mCurrentNode = newNode; + } + } + virtual void setCurrentItemValue( const char* inValue ) + { + mCurrentNode->mData = copyStr( &mManager, inValue ); + } + virtual bool removeChild( const char* name ) + { + XmlNode* theChild( mCurrentNode->findChildByName( name ) ); + if ( theChild ) + { + releaseNodeAndChildren( &mManager, theChild ); + return true; + } + return false; + } + virtual void release() { this->~XmlNodeReader(); mWrapper.getAllocator().deallocate(this); } + + private: + XmlNodeReader& operator=(const XmlNodeReader&); + }; + + PX_INLINE void freeNodeAndChildren( XmlNode* tempNode, TMemoryPoolManager& inManager ) + { + for( XmlNode* theNode = tempNode->mFirstChild; theNode != NULL; theNode = theNode->mNextSibling ) + freeNodeAndChildren( theNode, inManager ); + tempNode->orphan(); + release( &inManager, tempNode ); + } + + class XmlParser : public Ps::FastXml::Callback + { + XmlParseArgs mParseArgs; + //For parse time only allocations + XmlMemoryAllocatorImpl& mParseAllocator; + XmlNode* mCurrentNode; + XmlNode* mTopNode; + + public: + XmlParser( XmlParseArgs inArgs, XmlMemoryAllocatorImpl& inParseAllocator ) + : mParseArgs( inArgs ) + , mParseAllocator( inParseAllocator ) + , mCurrentNode( NULL ) + , mTopNode( NULL ) + { + } + + virtual ~XmlParser(){} + + virtual bool processComment(const char* /*comment*/) { return true; } + // 'element' is the name of the element that is being closed. + // depth is the recursion depth of this element. + // Return true to continue processing the XML file. + // Return false to stop processing the XML file; leaves the read pointer of the stream right after this close tag. + // The bool 'isError' indicates whether processing was stopped due to an error, or intentionally canceled early. + virtual bool processClose(const char* /*element*/,physx::PxU32 /*depth*/,bool& /*isError*/) + { + mCurrentNode = mCurrentNode->mParent; + return true; + } + + // return true to continue processing the XML document, false to skip. + virtual bool processElement( + const char *elementName, // name of the element + const char *elementData, // element data, null if none + const Ps::FastXml::AttributePairs& attr, // attributes + PxI32 /*lineno*/) + { + XmlNode* newNode = allocateRepXNode( &mParseAllocator.mManager, elementName, elementData ); + if ( mCurrentNode ) + mCurrentNode->addChild( newNode ); + mCurrentNode = newNode; + //Add the elements as children. + for( PxI32 item = 0; item < attr.getNbAttr(); item ++ ) + { + XmlNode* node = allocateRepXNode( &mParseAllocator.mManager, attr.getKey(PxU32(item)), attr.getValue(PxU32(item)) ); + mCurrentNode->addChild( node ); + } + if ( mTopNode == NULL ) mTopNode = newNode; + return true; + } + + XmlNode* getTopNode() { return mTopNode; } + + virtual void * allocate(PxU32 size) + { + if ( size ) + return mParseAllocator.allocate(size); + return NULL; + } + virtual void deallocate(void *mem) + { + if ( mem ) + mParseAllocator.deallocate(reinterpret_cast<PxU8*>(mem)); + } + + private: + XmlParser& operator=(const XmlParser&); + }; + + struct RepXCollectionSharedData + { + PxProfileAllocatorWrapper mWrapper; + XmlMemoryAllocatorImpl mAllocator; + PxU32 mRefCount; + + RepXCollectionSharedData( PxAllocatorCallback& inAllocator ) + : mWrapper( inAllocator ) + , mAllocator( inAllocator ) + , mRefCount( 0 ) + { + } + ~RepXCollectionSharedData() {} + + void addRef() { ++mRefCount;} + void release() + { + if ( mRefCount ) --mRefCount; + if ( !mRefCount ) { this->~RepXCollectionSharedData(); mWrapper.getAllocator().deallocate(this);} + } + }; + + struct SharedDataPtr + { + RepXCollectionSharedData* mData; + SharedDataPtr( RepXCollectionSharedData* inData ) + : mData( inData ) + { + mData->addRef(); + } + SharedDataPtr( const SharedDataPtr& inOther ) + : mData( inOther.mData ) + { + mData->addRef(); + } + SharedDataPtr& operator=( const SharedDataPtr& inOther ); + ~SharedDataPtr() + { + mData->release(); + mData = NULL; + } + RepXCollectionSharedData* operator->() { return mData; } + const RepXCollectionSharedData* operator->() const { return mData; } + }; + + class RepXCollectionImpl : public RepXCollection, public Ps::UserAllocated + { + SharedDataPtr mSharedData; + + XmlMemoryAllocatorImpl& mAllocator; + PxSerializationRegistry& mSerializationRegistry; + PxProfileArray<RepXCollectionItem> mCollection; + TMemoryPoolManager mSerializationManager; + MemoryBuffer mPropertyBuffer; + PxTolerancesScale mScale; + PxVec3 mUpVector; + const char* mVersionStr; + PxCollection* mPxCollection; + + public: + RepXCollectionImpl( PxSerializationRegistry& inRegistry, PxAllocatorCallback& inAllocator, PxCollection& inPxCollection ) + : mSharedData( &PX_NEW_REPX_SERIALIZER( RepXCollectionSharedData )) + , mAllocator( mSharedData->mAllocator ) + , mSerializationRegistry( inRegistry ) + , mCollection( mSharedData->mWrapper ) + , mSerializationManager( inAllocator ) + , mPropertyBuffer( &mSerializationManager ) + , mUpVector( 0,0,0 ) + , mVersionStr( getLatestVersion() ) + , mPxCollection( &inPxCollection ) + { + memset( &mScale, 0, sizeof( PxTolerancesScale ) ); + PX_ASSERT( mScale.isValid() == false ); + } + + RepXCollectionImpl( PxSerializationRegistry& inRegistry, const RepXCollectionImpl& inSrc, const char* inNewVersion ) + : mSharedData( inSrc.mSharedData ) + , mAllocator( mSharedData->mAllocator ) + , mSerializationRegistry( inRegistry ) + , mCollection( mSharedData->mWrapper ) + , mSerializationManager( mSharedData->mWrapper.getAllocator() ) + , mPropertyBuffer( &mSerializationManager ) + , mScale( inSrc.mScale ) + , mUpVector( inSrc.mUpVector ) + , mVersionStr( inNewVersion ) + , mPxCollection( NULL ) + { + } + + virtual ~RepXCollectionImpl() + { + PxU32 numItems = mCollection.size(); + for ( PxU32 idx = 0; idx < numItems; ++idx ) + { + XmlNode* theNode = mCollection[idx].descriptor; + releaseNodeAndChildren( &mAllocator.mManager, theNode ); + } + } + RepXCollectionImpl& operator=(const RepXCollectionImpl&); + + virtual void destroy() + { + PxProfileAllocatorWrapper tempWrapper( mSharedData->mWrapper.getAllocator() ); + this->~RepXCollectionImpl(); + tempWrapper.getAllocator().deallocate(this); + } + + virtual void setTolerancesScale(const PxTolerancesScale& inScale) { mScale = inScale; } + virtual PxTolerancesScale getTolerancesScale() const { return mScale; } + virtual void setUpVector( const PxVec3& inUpVector ) { mUpVector = inUpVector; } + virtual PxVec3 getUpVector() const { return mUpVector; } + + + PX_INLINE RepXCollectionItem findItemBySceneItem( const PxRepXObject& inObject ) const + { + //See if the object is in the collection + for ( PxU32 idx =0; idx < mCollection.size(); ++idx ) + if ( mCollection[idx].liveObject.serializable == inObject.serializable ) + return mCollection[idx]; + return RepXCollectionItem(); + } + + virtual RepXAddToCollectionResult addRepXObjectToCollection( const PxRepXObject& inObject, PxCollection* inCollection, PxRepXInstantiationArgs& inArgs ) + { + PX_ASSERT( inObject.serializable ); + PX_ASSERT( inObject.id ); + if ( inObject.serializable == NULL || inObject.id == 0 ) + return RepXAddToCollectionResult( RepXAddToCollectionResult::InvalidParameters ); + + PxRepXSerializer* theSerializer = mSerializationRegistry.getRepXSerializer( inObject.typeName ); + if ( theSerializer == NULL ) + return RepXAddToCollectionResult( RepXAddToCollectionResult::SerializerNotFound ); + + RepXCollectionItem existing = findItemBySceneItem( inObject ); + if ( existing.liveObject.serializable ) + return RepXAddToCollectionResult( RepXAddToCollectionResult::AlreadyInCollection, existing.liveObject.id ); + + XmlNodeWriter theXmlWriter( mAllocator, 1 ); + XmlWriterImpl theRepXWriter( &theXmlWriter, &mPropertyBuffer ); + { + SimpleXmlWriter::STagWatcher theWatcher( theXmlWriter, inObject.typeName ); + writeProperty( theXmlWriter, mPropertyBuffer, "Id", inObject.id ); + theSerializer->objectToFile( inObject, inCollection, theRepXWriter, mPropertyBuffer,inArgs ); + } + mCollection.pushBack( RepXCollectionItem( inObject, theXmlWriter.getTopNode() ) ); + return RepXAddToCollectionResult( RepXAddToCollectionResult::Success, inObject.id ); + } + + virtual bool instantiateCollection( PxRepXInstantiationArgs& inArgs, PxCollection& inCollection ) + { + for ( PxU32 idx =0; idx < mCollection.size(); ++idx ) + { + RepXCollectionItem theItem( mCollection[idx] ); + PxRepXSerializer* theSerializer = mSerializationRegistry.getRepXSerializer( theItem.liveObject.typeName ); + if (theSerializer ) + { + XmlNodeReader theReader( theItem.descriptor, mAllocator.getAllocator(), mAllocator.mManager ); + XmlMemoryAllocatorImpl instantiationAllocator( mAllocator.getAllocator() ); + PxRepXObject theLiveObject = theSerializer->fileToObject( theReader, instantiationAllocator, inArgs, &inCollection ); + if (theLiveObject.isValid()) + { + const PxBase* s = reinterpret_cast<const PxBase*>( theLiveObject.serializable ) ; + inCollection.add( *const_cast<PxBase*>(s), PxSerialObjectId( theItem.liveObject.id )); + } + else + return false; + } + else + { + Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, + "PxSerialization::createCollectionFromXml: " + "PxRepXSerializer missing for type %s", theItem.liveObject.typeName); + return false; + } + } + + return true; + } + + void saveXmlNode( XmlNode* inNode, SimpleXmlWriter& inWriter ) + { + XmlNode* theNode( inNode ); + if ( theNode->mData && *theNode->mData && theNode->mFirstChild == NULL ) + inWriter.writeContentTag( theNode->mName, theNode->mData ); + else + { + inWriter.beginTag( theNode->mName ); + if ( theNode->mData && *theNode->mData ) + inWriter.addContent( theNode->mData ); + for ( XmlNode* theChild = theNode->mFirstChild; + theChild != NULL; + theChild = theChild->mNextSibling ) + saveXmlNode( theChild, inWriter ); + inWriter.endTag(); + } + } + + virtual void save( PxOutputStream& inStream ) + { + SimpleXmlWriterImpl<PxOutputStream> theWriter( inStream, mAllocator.getAllocator() ); + theWriter.beginTag( "PhysX30Collection" ); + theWriter.addAttribute( "version", mVersionStr ); + { + XmlWriterImpl theRepXWriter( &theWriter, &mPropertyBuffer ); + writeProperty( theWriter, mPropertyBuffer, "UpVector", mUpVector ); + theRepXWriter.addAndGotoChild( "Scale" ); + writeAllProperties( &mScale, theRepXWriter, mPropertyBuffer, *mPxCollection); + theRepXWriter.leaveChild(); + } + for ( PxU32 idx =0; idx < mCollection.size(); ++idx ) + { + RepXCollectionItem theItem( mCollection[idx] ); + XmlNode* theNode( theItem.descriptor ); + saveXmlNode( theNode, theWriter ); + } + } + + void load( PxInputData& inFileBuf, SerializationRegistry& s ) + { + inFileBuf.seek(0); + XmlParser theParser( XmlParseArgs( &mAllocator, &mCollection ), mAllocator ); + Ps::FastXml* theFastXml = Ps::createFastXml( &theParser ); + theFastXml->processXml( inFileBuf ); + XmlNode* theTopNode = theParser.getTopNode(); + if ( theTopNode != NULL ) + { + { + + XmlMemoryAllocatorImpl instantiationAllocator( mAllocator.getAllocator() ); + XmlNodeReader theReader( theTopNode, mAllocator.getAllocator(), mAllocator.mManager ); + readProperty( theReader, "UpVector", mUpVector ); + if ( theReader.gotoChild( "Scale" ) ) + { + readAllProperties( PxRepXInstantiationArgs( s.getPhysics() ), theReader, &mScale, instantiationAllocator, *mPxCollection); + theReader.leaveChild(); + } + const char* verStr = NULL; + if ( theReader.read( "version", verStr ) ) + mVersionStr = verStr; + } + for ( XmlNode* theChild = theTopNode->mFirstChild; + theChild != NULL; + theChild = theChild->mNextSibling ) + { + if ( physx::shdfnd::stricmp( theChild->mName, "scale" ) == 0 + || physx::shdfnd::stricmp( theChild->mName, "version" ) == 0 + || physx::shdfnd::stricmp( theChild->mName, "upvector" ) == 0 ) + continue; + XmlNodeReader theReader( theChild, mAllocator.getAllocator(), mAllocator.mManager ); + PxRepXObject theObject; + theObject.typeName = theChild->mName; + theObject.serializable = NULL; + PxSerialObjectId theId = 0; + theReader.read( "Id", theId ); + theObject.id = theId; + mCollection.pushBack( RepXCollectionItem( theObject, theChild ) ); + } + } + else + { + Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "Cannot parse any object from the input buffer, please check the input repx data."); + } + theFastXml->release(); + } + + virtual const char* getVersion() { return mVersionStr; } + + virtual const RepXCollectionItem* begin() const + { + return mCollection.begin(); + } + virtual const RepXCollectionItem* end() const + { + return mCollection.end(); + } + + virtual RepXCollection& createCollection( const char* inVersionStr ) + { + PxAllocatorCallback& allocator = mSharedData->mWrapper.getAllocator(); + RepXCollectionImpl* retval = PX_PLACEMENT_NEW((allocator.allocate(sizeof(RepXCollectionImpl), "createCollection", __FILE__, __LINE__ )), RepXCollectionImpl) ( mSerializationRegistry, *this, inVersionStr ); + + return *retval; + } + + //Performs a deep copy of the repx node. + virtual XmlNode* copyRepXNode( const XmlNode* srcNode ) + { + return physx::Sn::copyRepXNode( &mAllocator.mManager, srcNode ); + } + + virtual void addCollectionItem( RepXCollectionItem inItem ) + { + mCollection.pushBack( inItem ); + } + + virtual PxAllocatorCallback& getAllocator() { return mSharedData->mAllocator.getAllocator(); } + //Create a new repx node with this name. Its value is unset. + virtual XmlNode& createRepXNode( const char* name ) + { + XmlNode* newNode = allocateRepXNode( &mSharedData->mAllocator.mManager, name, NULL ); + return *newNode; + } + + //Release this when finished. + virtual XmlReaderWriter& createNodeEditor() + { + PxAllocatorCallback& allocator = mSharedData->mWrapper.getAllocator(); + XmlReaderWriter* retval = PX_PLACEMENT_NEW((allocator.allocate(sizeof(XmlNodeReader), "createNodeEditor", __FILE__, __LINE__ )), XmlNodeReader) ( NULL, allocator, mAllocator.mManager ); + return *retval; + } + }; + + const char* RepXCollection::getLatestVersion() + { +#define TOSTR_(x) #x +#define CONCAT_(a, b, c) TOSTR_(a.##b.##c) +#define MAKE_VERSION_STR(a,b,c) CONCAT_(a, b, c) + + return MAKE_VERSION_STR(PX_PHYSICS_VERSION_MAJOR,PX_PHYSICS_VERSION_MINOR,PX_PHYSICS_VERSION_BUGFIX); + + } + + static RepXCollection* create(SerializationRegistry& s, PxAllocatorCallback& inAllocator, PxCollection& inCollection ) + { + return PX_PLACEMENT_NEW((inAllocator.allocate(sizeof(RepXCollectionImpl), "RepXCollection::create", __FILE__, __LINE__ )), RepXCollectionImpl) ( s, inAllocator, inCollection ); + } + + static RepXCollection* create(SerializationRegistry& s, PxInputData &data, PxAllocatorCallback& inAllocator, PxCollection& inCollection ) + { + RepXCollectionImpl* theCollection = static_cast<RepXCollectionImpl*>( create(s, inAllocator, inCollection ) ); + theCollection->load( data, s ); + return theCollection; + } +} + + bool PxSerialization::serializeCollectionToXml( PxOutputStream& outputStream, PxCollection& collection, PxSerializationRegistry& sr, PxCooking* cooking, const PxCollection* externalRefs, PxXmlMiscParameter* inArgs ) + { + if( !PxSerialization::isSerializable(collection, sr, const_cast<PxCollection*>(externalRefs)) ) + return false; + + bool bRet = true; + + SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr); + PxRepXInstantiationArgs args( sn.getPhysics(), cooking ); + + PxCollection* tmpCollection = PxCreateCollection(); + PX_ASSERT(tmpCollection); + + tmpCollection->add( collection ); + if(externalRefs) + { + tmpCollection->add(*const_cast<PxCollection*>(externalRefs)); + } + + PxAllocatorCallback& allocator = PxGetFoundation().getAllocatorCallback(); + Sn::RepXCollection* theRepXCollection = Sn::create(sn, allocator, *tmpCollection ); + + if(inArgs != NULL) + { + theRepXCollection->setTolerancesScale(inArgs->scale); + theRepXCollection->setUpVector(inArgs->upVector); + } + + PxU32 nbObjects = collection.getNbObjects(); + if( nbObjects ) + { + sortCollection( static_cast<Cm::Collection&>(collection), sn, true); + + for( PxU32 i = 0; i < nbObjects; i++ ) + { + PxBase& s = collection.getObject(i); + if( PxConcreteType::eSHAPE == s.getConcreteType() ) + { + PxShape& shape = static_cast<PxShape&>(s); + if( shape.isExclusive() ) + continue; + } + + PxSerialObjectId id = collection.getId(s); + if(id == PX_SERIAL_OBJECT_ID_INVALID) + id = static_cast<PxSerialObjectId>( reinterpret_cast<size_t>( &s )); + + PxRepXObject ro = PxCreateRepXObject( &s, id ); + if ( ro.serializable == NULL || ro.id == 0 ) + { + bRet = false; + break; + } + + theRepXCollection->addRepXObjectToCollection( ro, tmpCollection, args ); + } + } + tmpCollection->release(); + + theRepXCollection->save(outputStream); + theRepXCollection->destroy(); + + + return bRet; + } + + PxCollection* PxSerialization::createCollectionFromXml(PxInputData& inputData, PxCooking& cooking, PxSerializationRegistry& sr, const PxCollection* externalRefs, PxStringTable* stringTable, PxXmlMiscParameter* outArgs) + { + SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr); + PxCollection* collection = PxCreateCollection(); + PX_ASSERT(collection); + + if( externalRefs ) + collection->add(*const_cast<PxCollection*>(externalRefs)); + + PxAllocatorCallback& allocator = PxGetFoundation().getAllocatorCallback(); + Sn::RepXCollection* theRepXCollection = Sn::create(sn, inputData, allocator, *collection); + theRepXCollection = &Sn::RepXUpgrader::upgradeCollection( *theRepXCollection ); + + PxRepXInstantiationArgs args( sn.getPhysics(), &cooking, stringTable ); + if( !theRepXCollection->instantiateCollection(args, *collection) ) + { + collection->release(); + theRepXCollection->destroy(); + return NULL; + } + + if( externalRefs ) + collection->remove(*const_cast<PxCollection*>(externalRefs)); + + if(outArgs != NULL) + { + outArgs->upVector = theRepXCollection->getUpVector(); + outArgs->scale = theRepXCollection->getTolerancesScale(); + } + + theRepXCollection->destroy(); + + return collection; + } +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSerializer.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSerializer.h new file mode 100644 index 00000000..9effab4f --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSerializer.h @@ -0,0 +1,117 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_XML_SERIALIZER_H +#define PX_XML_SERIALIZER_H + +#include "PxExtensionMetaDataObjects.h" +#include "SnXmlVisitorWriter.h" + +namespace physx { + +namespace Sn { + + void writeHeightFieldSample( PxOutputStream& inStream, const PxHeightFieldSample& inSample ) + { + PxU32 retval = 0; + PxU8* writePtr( reinterpret_cast< PxU8*>( &retval ) ); + const PxU8* inPtr( reinterpret_cast<const PxU8*>( &inSample ) ); + if ( isBigEndian() ) + { + //Height field samples are a + //16 bit integer followed by two bytes. + //right now, data is 2 1 3 4 + //We need a 32 bit integer that + //when read in by a LE system is 4 3 2 1. + //Thus, we need a BE integer that looks like: + //4 3 2 1 + + writePtr[0] = inPtr[3]; + writePtr[1] = inPtr[2]; + writePtr[2] = inPtr[0]; + writePtr[3] = inPtr[1]; + } + else + { + writePtr[0] = inPtr[0]; + writePtr[1] = inPtr[1]; + writePtr[2] = inPtr[2]; + writePtr[3] = inPtr[3]; + } + inStream << retval; + } + + + + template<typename TDataType, typename TWriteOperator> + inline void writeStridedBufferProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, const void* inData, PxU32 inStride, PxU32 inCount, PxU32 inItemsPerLine, TWriteOperator inOperator ) + { + PX_ASSERT( inStride == 0 || inStride == sizeof( TDataType ) ); + PX_UNUSED( inStride ); + writeBuffer( writer, tempBuffer + , inItemsPerLine, reinterpret_cast<const TDataType*>( inData ) + , inCount, inPropName, inOperator ); + } + + template<typename TDataType, typename TWriteOperator> + inline void writeStridedBufferProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, const PxStridedData& inData, PxU32 inCount, PxU32 inItemsPerLine, TWriteOperator inOperator ) + { + writeStridedBufferProperty<TDataType>( writer, tempBuffer, inPropName, inData.data, inData.stride, inCount, inItemsPerLine, inOperator ); + } + + template<typename TDataType, typename TWriteOperator> + inline void writeStridedBufferProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, const PxTypedStridedData<TDataType>& inData, PxU32 inCount, PxU32 inItemsPerLine, TWriteOperator inOperator ) + { + writeStridedBufferProperty<TDataType>( writer, tempBuffer, inPropName, inData.data, inData.stride, inCount, inItemsPerLine, inOperator ); + } + + template<typename TDataType, typename TWriteOperator> + inline void writeStridedBufferProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, const PxBoundedData& inData, PxU32 inItemsPerLine, TWriteOperator inWriteOperator ) + { + writeStridedBufferProperty<TDataType>( writer, tempBuffer, inPropName, inData, inData.count, inItemsPerLine, inWriteOperator ); + } + + template<typename TDataType, typename TWriteOperator> + inline void writeStridedBufferProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, PxStrideIterator<const TDataType>& inData, PxU32 inCount, PxU32 inItemsPerLine, TWriteOperator inWriteOperator ) + { + writeStrideBuffer<TDataType>(writer, tempBuffer + , inItemsPerLine, inData, PtrAccess<TDataType> + , inCount, inPropName, inData.stride(), inWriteOperator ); + } + + template<typename TDataType> + inline void writeStridedFlagsProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, PxStrideIterator<const TDataType>& inData, PxU32 inCount, PxU32 inItemsPerLine, const PxU32ToName* inTable ) + { + writeStrideFlags<TDataType>(writer, tempBuffer + , inItemsPerLine, inData, PtrAccess<TDataType> + , inCount, inPropName, inTable ); + } + +} +} +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSimpleXmlWriter.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSimpleXmlWriter.h new file mode 100644 index 00000000..7ee771b8 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSimpleXmlWriter.h @@ -0,0 +1,215 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_SIMPLEXMLWRITER_H +#define PX_SIMPLEXMLWRITER_H + +#include "PsArray.h" +#include "SnXmlMemoryPoolStreams.h" +#include "CmPhysXCommon.h" + +namespace physx { namespace Sn { + class XmlWriter + { + public: + + struct STagWatcher + { + typedef XmlWriter TXmlWriterType; + TXmlWriterType& mWriter; + STagWatcher( const STagWatcher& inOther ); + STagWatcher& operator-( const STagWatcher& inOther ); + STagWatcher( TXmlWriterType& inWriter, const char* inTagName ) + : mWriter( inWriter ) + { + mWriter.beginTag( inTagName ); + } + ~STagWatcher() { mWriter.endTag(); } + }; + + virtual ~XmlWriter(){} + virtual void beginTag( const char* inTagname ) = 0; + virtual void endTag() = 0; + virtual void addAttribute( const char* inName, const char* inValue ) = 0; + virtual void writeContentTag( const char* inTag, const char* inContent ) = 0; + virtual void addContent( const char* inContent ) = 0; + virtual PxU32 tabCount() = 0; + }; + + template<typename TStreamType> + class XmlWriterImpl : public XmlWriter + { + PxProfileAllocatorWrapper mWrapper; + TStreamType& mStream; + XmlWriterImpl( const XmlWriterImpl& inOther ); + XmlWriterImpl& operator=( const XmlWriterImpl& inOther ); + PxProfileArray<const char*> mTags; + bool mTagOpen; + PxU32 mInitialTagDepth; + public: + + XmlWriterImpl( TStreamType& inStream, PxAllocatorCallback& inAllocator, PxU32 inInitialTagDepth = 0 ) + : mWrapper( inAllocator ) + , mStream( inStream ) + , mTags( mWrapper ) + , mTagOpen( false ) + , mInitialTagDepth( inInitialTagDepth ) + { + } + virtual ~XmlWriterImpl() + { + while( mTags.size() ) + endTag(); + } + PxU32 tabCount() { return mTags.size() + mInitialTagDepth; } + + void writeTabs( PxU32 inSize ) + { + inSize += mInitialTagDepth; + for ( PxU32 idx =0; idx < inSize; ++idx ) + mStream << "\t"; + } + void beginTag( const char* inTagname ) + { + closeTag(); + writeTabs(mTags.size()); + mTags.pushBack( inTagname ); + mStream << "<" << inTagname; + mTagOpen = true; + } + void addAttribute( const char* inName, const char* inValue ) + { + PX_ASSERT( mTagOpen ); + mStream << " " << inName << "=" << "\"" << inValue << "\""; + } + void closeTag(bool useNewline = true) + { + if ( mTagOpen ) + { + mStream << " " << ">"; + if (useNewline ) + mStream << "\n"; + } + mTagOpen = false; + } + void doEndOpenTag() + { + mStream << "</" << mTags.back() << ">" << "\n"; + } + void endTag() + { + PX_ASSERT( mTags.size() ); + if ( mTagOpen ) + mStream << " " << "/>" << "\n"; + else + { + writeTabs(mTags.size()-1); + doEndOpenTag(); + } + mTagOpen = false; + mTags.popBack(); + } + void addContent( const char* inContent ) + { + closeTag(false); + mStream << inContent; + } + void writeContentTag( const char* inTag, const char* inContent ) + { + beginTag( inTag ); + addContent( inContent ); + doEndOpenTag(); + mTags.popBack(); + } + void insertXml( const char* inXml ) + { + closeTag(); + mStream << inXml; + } + }; + + struct BeginTag + { + const char* mTagName; + BeginTag( const char* inTagName ) + : mTagName( inTagName ) { } + }; + + struct EndTag + { + EndTag() {} + }; + + struct Att + { + const char* mAttName; + const char* mAttValue; + Att( const char* inAttName, const char* inAttValue ) + : mAttName( inAttName ) + , mAttValue( inAttValue ) { } + }; + + struct Content + { + const char* mContent; + Content( const char* inContent ) + : mContent( inContent ) { } + }; + + + struct ContentTag + { + const char* mTagName; + const char* mContent; + ContentTag( const char* inTagName, const char* inContent ) + : mTagName( inTagName ) + , mContent( inContent ) { } + }; + + inline XmlWriter& operator<<( XmlWriter& inWriter, const BeginTag& inTag ) { inWriter.beginTag( inTag.mTagName ); return inWriter; } + inline XmlWriter& operator<<( XmlWriter& inWriter, const EndTag& inTag ) { inWriter.endTag(); return inWriter; } + inline XmlWriter& operator<<( XmlWriter& inWriter, const Att& inTag ) { inWriter.addAttribute(inTag.mAttName, inTag.mAttValue); return inWriter; } + inline XmlWriter& operator<<( XmlWriter& inWriter, const Content& inTag ) { inWriter.addContent(inTag.mContent); return inWriter; } + inline XmlWriter& operator<<( XmlWriter& inWriter, const ContentTag& inTag ) { inWriter.writeContentTag(inTag.mTagName, inTag.mContent); return inWriter; } + + inline void writeProperty( XmlWriter& inWriter, MemoryBuffer& tempBuffer, const char* inPropName ) + { + PxU8 data = 0; + tempBuffer.write( &data, sizeof(PxU8) ); + inWriter.writeContentTag( inPropName, reinterpret_cast<const char*>( tempBuffer.mBuffer ) ); + tempBuffer.clear(); + } + + template<typename TDataType> + inline void writeProperty( XmlWriter& inWriter, MemoryBuffer& tempBuffer, const char* inPropName, TDataType inValue ) + { + tempBuffer << inValue; + writeProperty( inWriter, tempBuffer, inPropName ); + } +} } +#endif
\ No newline at end of file diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlStringToType.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlStringToType.h new file mode 100644 index 00000000..0361a2bf --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlStringToType.h @@ -0,0 +1,275 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_XML_STRINGTOTYPE_H +#define PX_XML_STRINGTOTYPE_H + +#include <stdio.h> +#include <ctype.h> +#include "PsString.h" +#include "PxCoreUtilityTypes.h" +#include "PxFiltering.h" + +//Remapping function name for gcc-based systems. +#ifndef _MSC_VER +#define _strtoui64 strtoull +#endif + + +namespace physx { namespace Sn { + + template<typename TDataType> + struct StrToImpl + { + bool compile_error; + }; + + template<> struct StrToImpl<PxU64> { + //Id's (void ptrs) are written to file as unsigned + //64 bit integers, so this method gets called more + //often than one might think. + PX_INLINE void strto( PxU64& ioDatatype,const char*& ioData ) + { + ioDatatype = _strtoui64( ioData, const_cast<char **>(&ioData), 10 ); + } + }; + + PX_INLINE PxF32 strToFloat(const char *str,const char **nextScan) + { + PxF32 ret; + while ( *str && isspace(static_cast<unsigned char>(*str))) str++; // skip leading whitespace + char temp[256] = ""; + char *dest = temp; + char *end = &temp[255]; + const char *begin = str; + while ( *str && !isspace(static_cast<unsigned char>(*str)) && dest < end ) // copy the number up to the first whitespace or eos + { + *dest++ = *str++; + } + *dest = 0; + ret = PxF32(strtod(temp,&end)); + if ( nextScan ) + { + *nextScan = begin+(end-temp); + } + return ret; + } + + + template<> struct StrToImpl<PxU32> { + PX_INLINE void strto( PxU32& ioDatatype,const char*& ioData ) + { + ioDatatype = static_cast<PxU32>( strtoul( ioData,const_cast<char **>(&ioData), 10 ) ); + } + }; + + template<> struct StrToImpl<PxI32> { + PX_INLINE void strto( PxI32& ioDatatype,const char*& ioData ) + { + ioDatatype = static_cast<PxI32>( strtoul( ioData,const_cast<char **>(&ioData), 10 ) ); + } + }; + + + template<> struct StrToImpl<PxU16> { + PX_INLINE void strto( PxU16& ioDatatype,const char*& ioData ) + { + ioDatatype = static_cast<PxU16>( strtoul( ioData,const_cast<char **>(&ioData), 10 ) ); + } + }; + + PX_INLINE void eatwhite(const char*& ioData ) + { + if ( ioData ) + { + while( isspace( static_cast<unsigned char>(*ioData) ) ) + ++ioData; + } + } + + // copy the source data to the dest buffer until the first whitespace is encountered. + // Do not overflow the buffer based on the bufferLen provided. + // Advance the input 'ioData' pointer so that it sits just at the next whitespace + PX_INLINE void nullTerminateWhite(const char*& ioData,char *buffer,PxU32 bufferLen) + { + if ( ioData ) + { + char *eof = buffer+(bufferLen-1); + char *dest = buffer; + while( *ioData && !isspace(static_cast<unsigned char>(*ioData)) && dest < eof ) + { + *dest++ = *ioData++; + } + *dest = 0; + } + } + + inline void nonNullTerminateWhite(const char*& ioData ) + { + if ( ioData ) + { + while( *ioData && !isspace( static_cast<unsigned char>(*ioData) ) ) + ++ioData; + } + } + + template<> struct StrToImpl<PxF32> { + inline void strto( PxF32& ioDatatype,const char*& ioData ) + { + ioDatatype = strToFloat(ioData,&ioData); + } + + }; + + + template<> struct StrToImpl<void*> { + inline void strto( void*& ioDatatype,const char*& ioData ) + { + PxU64 theData; + StrToImpl<PxU64>().strto( theData, ioData ); + ioDatatype = reinterpret_cast<void*>( static_cast<size_t>( theData ) ); + } + }; + + + template<> struct StrToImpl<physx::PxVec3> { + inline void strto( physx::PxVec3& ioDatatype,const char*& ioData ) + { + StrToImpl<PxF32>().strto( ioDatatype[0], ioData ); + StrToImpl<PxF32>().strto( ioDatatype[1], ioData ); + StrToImpl<PxF32>().strto( ioDatatype[2], ioData ); + } + }; + + template<> struct StrToImpl<PxU8*> { + inline void strto( PxU8*& /*ioDatatype*/,const char*& /*ioData*/) + { + } + }; + + template<> struct StrToImpl<bool> { + inline void strto( bool& ioType,const char*& inValue ) + { + ioType = physx::shdfnd::stricmp( inValue, "true" ) == 0 ? true : false; + } + }; + + template<> struct StrToImpl<PxU8> { + PX_INLINE void strto( PxU8& ioType,const char* & inValue) + { + ioType = static_cast<PxU8>( strtoul( inValue,const_cast<char **>(&inValue), 10 ) ); + } + }; + + template<> struct StrToImpl<PxFilterData> { + PX_INLINE void strto( PxFilterData& ioType,const char*& inValue) + { + ioType.word0 = static_cast<PxU32>( strtoul( inValue,const_cast<char **>(&inValue), 10 ) ); + ioType.word1 = static_cast<PxU32>( strtoul( inValue,const_cast<char **>(&inValue), 10 ) ); + ioType.word2 = static_cast<PxU32>( strtoul( inValue,const_cast<char **>(&inValue), 10 ) ); + ioType.word3 = static_cast<PxU32>( strtoul( inValue, NULL, 10 ) ); + } + }; + + + template<> struct StrToImpl<PxQuat> { + PX_INLINE void strto( PxQuat& ioType,const char*& inValue ) + { + ioType.x = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + ioType.y = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + ioType.z = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + ioType.w = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + } + }; + + template<> struct StrToImpl<PxTransform> { + PX_INLINE void strto( PxTransform& ioType,const char*& inValue) + { + ioType.q.x = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + ioType.q.y = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + ioType.q.z = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + ioType.q.w = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + + ioType.p[0] = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + ioType.p[1] = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + ioType.p[2] = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + } + }; + + template<> struct StrToImpl<PxBounds3> { + PX_INLINE void strto( PxBounds3& ioType,const char*& inValue) + { + ioType.minimum[0] = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + ioType.minimum[1] = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + ioType.minimum[2] = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + + ioType.maximum[0] = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + ioType.maximum[1] = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + ioType.maximum[2] = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + } + }; + + template<> struct StrToImpl<PxMetaDataPlane> { + PX_INLINE void strto( PxMetaDataPlane& ioType,const char*& inValue) + { + ioType.normal.x = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + ioType.normal.y = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + ioType.normal.z = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + ioType.distance = static_cast<PxReal>( strToFloat( inValue, &inValue ) ); + } + }; + + + template<> struct StrToImpl<PxRigidDynamic*> { + PX_INLINE void strto( PxRigidDynamic*& /*ioDatatype*/,const char*& /*ioData*/) + { + } + }; + + template<typename TDataType> + inline void strto( TDataType& ioType,const char*& ioData ) + { + if ( ioData && *ioData ) StrToImpl<TDataType>().strto( ioType, ioData ); + } + + template<typename TDataType> + inline void strtoLong( TDataType& ioType,const char*& ioData ) + { + if ( ioData && *ioData ) StrToImpl<TDataType>().strto( ioType, ioData ); + } + + template<typename TDataType> + inline void stringToType( const char* inValue, TDataType& ioType ) + { + const char* theValue( inValue ); + return strto( ioType, theValue ); + } + +} } + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlVisitorReader.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlVisitorReader.h new file mode 100644 index 00000000..e003edf0 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlVisitorReader.h @@ -0,0 +1,889 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_XML_VISITOR_READER_H +#define PX_XML_VISITOR_READER_H + +#include "PsArray.h" +#include "PsUtilities.h" +#include "RepXMetaDataPropertyVisitor.h" +#include "SnPxStreamOperators.h" +#include "SnXmlMemoryPoolStreams.h" +#include "SnXmlReader.h" +#include "SnXmlImpl.h" +#include "SnXmlMemoryAllocator.h" +#include "SnXmlStringToType.h" + +namespace physx { namespace Sn { + + + inline PxU32 findEnumByName( const char* inName, const PxU32ToName* inTable ) + { + for ( PxU32 idx = 0; inTable[idx].mName != NULL; ++idx ) + { + if ( physx::shdfnd::stricmp( inTable[idx].mName, inName ) == 0 ) + return inTable[idx].mValue; + } + return 0; + } + + PX_INLINE void stringToFlagsType( const char* strData, XmlMemoryAllocator& alloc, PxU32& ioType, const PxU32ToName* inTable ) + { + if ( inTable == NULL ) + return; + ioType = 0; + if ( strData && *strData) + { + //Destructively parse the string to get out the different flags. + char* theValue = const_cast<char*>( copyStr( &alloc, strData ) ); + char* theMarker = theValue; + char* theNext = theValue; + while( theNext && *theNext ) + { + ++theNext; + if( *theNext == '|' ) + { + *theNext = 0; + ++theNext; + ioType |= static_cast< PxU32 > ( findEnumByName( theMarker, inTable ) ); + theMarker = theNext; + } + } + if ( theMarker && *theMarker ) + ioType |= static_cast< PxU32 > ( findEnumByName( theMarker, inTable ) ); + alloc.deallocate( reinterpret_cast<PxU8*>( theValue ) ); + } + } + + template<typename TDataType> + PX_INLINE void stringToEnumType( const char* strData, TDataType& ioType, const PxU32ToName* inTable ) + { + ioType = static_cast<TDataType>( findEnumByName( strData, inTable ) ); + } + + template<typename TDataType> + PX_INLINE bool readProperty( XmlReader& inReader, const char* pname, TDataType& ioType ) + { + const char* value; + if ( inReader.read( pname, value ) ) + { + stringToType( value, ioType ); + return true; + } + return false; + } + + template<typename TObjType> + inline TObjType* findReferencedObject( PxCollection& collection, PxSerialObjectId id) + { + PX_ASSERT(id > 0); + TObjType* outObject = static_cast<TObjType*>(const_cast<PxBase*>(collection.find(id))); + if (outObject == NULL) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "PxSerialization::createCollectionFromXml: " + "Reference to ID %d cannot be resolved. Make sure externalRefs collection is specified if required and " + "check Xml file for completeness.", + id); + } + return outObject; + } + + template<typename TObjType> + inline bool readReference( XmlReader& inReader, PxCollection& collection, TObjType*& outObject ) + { + PxSerialObjectId theId; + const char* theValue = inReader.getCurrentItemValue(); + strto( theId, theValue ); + if( theId == 0) + { + // the NULL pointer is a valid pointer if the input id is 0 + outObject = NULL; + return true; + } + else + { + outObject = findReferencedObject<TObjType>(collection, theId); + return outObject != NULL; + } + } + + template<typename TObjType> + inline bool readReference( XmlReader& inReader, PxCollection& inCollection, const char* pname, TObjType*& outObject ) + { + outObject = NULL; + PxSerialObjectId theId = 0; + if (readProperty ( inReader, pname, theId ) && theId ) + { + outObject = findReferencedObject<TObjType>(inCollection, theId); + } + // the NULL pointer is a valid pointer if the input id is 0 + return (outObject != NULL) || 0 == theId; + } + + template<typename TEnumType, typename TStorageType> + inline bool readFlagsProperty( XmlReader& reader, XmlMemoryAllocator& allocator, const char* pname, const PxU32ToName* inConversions, PxFlags<TEnumType,TStorageType>& outFlags ) + { + const char* value; + if ( reader.read( pname, value ) ) + { + PxU32 tempValue = 0; + stringToFlagsType( value, allocator, tempValue, inConversions ); + outFlags = PxFlags<TEnumType,TStorageType>(Ps::to16(tempValue) ); + return true; + } + return false; + } + + template<typename TObjType, typename TReaderType, typename TInfoType> + inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj, TInfoType& info); + template<typename TObjType, typename TReaderType> + inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj); + + template<typename TReaderType, typename TGeomType> + inline PxGeometry* parseGeometry( TReaderType& reader, TGeomType& /*inGeom*/) + { + PxAllocatorCallback& inAllocator = reader.mAllocator.getAllocator(); + + TGeomType* shape = PX_PLACEMENT_NEW((inAllocator.allocate(sizeof(TGeomType), "parseGeometry", __FILE__, __LINE__ )), TGeomType); + PxClassInfoTraits<TGeomType> info; + readComplexObj( reader, shape); + return shape; + } + + + template<typename TReaderType> + inline void parseShape( TReaderType& visitor, PxGeometry*& outResult, Ps::Array<PxMaterial*>& outMaterials) + { + XmlReader& theReader( visitor.mReader ); + PxCollection& collection = visitor.mCollection; + visitor.pushCurrentContext(); + if ( visitor.gotoTopName() ) + { + visitor.pushCurrentContext(); + if ( visitor.gotoChild( "Materials" ) ) + { + for( bool matSuccess = visitor.gotoFirstChild(); matSuccess; + matSuccess = visitor.gotoNextSibling() ) + { + PxMaterial* material = NULL; + if(!readReference<PxMaterial>( theReader, collection, material )) + visitor.mHadError = true; + if ( material ) + outMaterials.pushBack( material ); + } + } + visitor.popCurrentContext(); + visitor.pushCurrentContext(); + + PxPlaneGeometry plane; + PxHeightFieldGeometry heightField; + PxSphereGeometry sphere; + PxTriangleMeshGeometry mesh; + PxConvexMeshGeometry convex; + PxBoxGeometry box; + PxCapsuleGeometry capsule; + if ( visitor.gotoChild( "Geometry" ) ) + { + if ( visitor.gotoFirstChild() ) + { + const char* geomTypeName = visitor.getCurrentItemName(); + + if ( physx::shdfnd::stricmp( geomTypeName, "PxSphereGeometry" ) == 0 ) outResult = parseGeometry(visitor, sphere); + else if ( physx::shdfnd::stricmp( geomTypeName, "PxPlaneGeometry" ) == 0 ) outResult = parseGeometry(visitor, plane); + else if ( physx::shdfnd::stricmp( geomTypeName, "PxCapsuleGeometry" ) == 0 ) outResult = parseGeometry(visitor, capsule); + else if ( physx::shdfnd::stricmp( geomTypeName, "PxBoxGeometry" ) == 0 ) outResult = parseGeometry(visitor, box); + else if ( physx::shdfnd::stricmp( geomTypeName, "PxConvexMeshGeometry" ) == 0 ) outResult = parseGeometry(visitor, convex); + else if ( physx::shdfnd::stricmp( geomTypeName, "PxTriangleMeshGeometry" ) == 0 ) outResult = parseGeometry(visitor, mesh); + else if ( physx::shdfnd::stricmp( geomTypeName, "PxHeightFieldGeometry" ) == 0 ) outResult = parseGeometry(visitor, heightField); + else + PX_ASSERT( false ); + } + } + visitor.popCurrentContext(); + } + visitor.popCurrentContext(); + + return; + } + + template<typename TReaderType, typename TObjType> + inline void readShapesProperty( TReaderType& visitor, TObjType* inObj, const PxRigidActorShapeCollection* inProp = NULL, bool isSharedShape = false ) + { + PX_UNUSED(isSharedShape); + PX_UNUSED(inProp); + + XmlReader& theReader( visitor.mReader ); + PxCollection& collection( visitor.mCollection ); + + visitor.pushCurrentContext(); + if ( visitor.gotoTopName() ) + { + //uggh working around the shape collection api. + //read out materials and geometry + for ( bool success = visitor.gotoFirstChild(); success; + success = visitor.gotoNextSibling() ) + { + if( 0 == physx::shdfnd::stricmp( visitor.getCurrentItemName(), "PxShapeRef" ) ) + { + PxShape* shape = NULL; + if(!readReference<PxShape>( theReader, collection, shape )) + visitor.mHadError = true; + if(shape) + inObj->attachShape( *shape ); + } + else + { + Ps::Array<PxMaterial*> materials; + PxGeometry* geometry = NULL; + parseShape( visitor, geometry, materials); + PxShape* theShape = NULL; + if ( materials.size() ) + { + theShape = visitor.mArgs.physics.createShape( *geometry, materials.begin(), Ps::to16(materials.size()), true ); + if ( theShape ) + { + readComplexObj( visitor, theShape ); + + if(theShape) + { + inObj->attachShape(*theShape); + collection.add( *theShape ); + } + } + } + + switch(geometry->getType()) + { + case PxGeometryType::eSPHERE : + static_cast<PxSphereGeometry*>(geometry)->~PxSphereGeometry(); + break; + case PxGeometryType::ePLANE : + static_cast<PxPlaneGeometry*>(geometry)->~PxPlaneGeometry(); + break; + case PxGeometryType::eCAPSULE : + static_cast<PxCapsuleGeometry*>(geometry)->~PxCapsuleGeometry(); + break; + case PxGeometryType::eBOX : + static_cast<PxBoxGeometry*>(geometry)->~PxBoxGeometry(); + break; + case PxGeometryType::eCONVEXMESH : + static_cast<PxConvexMeshGeometry*>(geometry)->~PxConvexMeshGeometry(); + break; + case PxGeometryType::eTRIANGLEMESH : + static_cast<PxTriangleMeshGeometry*>(geometry)->~PxTriangleMeshGeometry(); + break; + case PxGeometryType::eHEIGHTFIELD : + static_cast<PxHeightFieldGeometry*>(geometry)->~PxHeightFieldGeometry(); + break; + + case PxGeometryType::eGEOMETRY_COUNT: + case PxGeometryType::eINVALID: + PX_ASSERT(0); + } + visitor.mAllocator.getAllocator().deallocate(geometry); + } + } + } + visitor.popCurrentContext(); + } + + struct ReaderNameStackEntry : NameStackEntry + { + bool mValid; + ReaderNameStackEntry( const char* nm, bool valid ) : NameStackEntry(nm), mValid(valid) {} + }; + + typedef PxProfileArray<ReaderNameStackEntry> TReaderNameStack; + + template<typename TObjType> + struct RepXVisitorReaderBase + { + + protected: + RepXVisitorReaderBase<TObjType>& operator=(const RepXVisitorReaderBase<TObjType>&); + public: + TReaderNameStack& mNames; + PxProfileArray<PxU32>& mContexts; + PxRepXInstantiationArgs mArgs; + XmlReader& mReader; + TObjType* mObj; + XmlMemoryAllocator& mAllocator; + PxCollection& mCollection; + bool mValid; + bool& mHadError; + + RepXVisitorReaderBase( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, TObjType* obj + , XmlMemoryAllocator& alloc, PxCollection& collection, bool& hadError ) + : mNames( names ) + , mContexts( contexts ) + , mArgs( args ) + , mReader( reader ) + , mObj( obj ) + , mAllocator( alloc ) + , mCollection( collection ) + , mValid( true ) + , mHadError(hadError) + { + } + RepXVisitorReaderBase( const RepXVisitorReaderBase& other ) + : mNames( other.mNames ) + , mContexts( other.mContexts ) + , mArgs( other.mArgs ) + , mReader( other.mReader ) + , mObj( other.mObj ) + , mAllocator( other.mAllocator ) + , mCollection( other.mCollection ) + , mValid( other.mValid ) + , mHadError( other.mHadError ) + { + } + + + void pushName( const char* name ) + { + gotoTopName(); + mNames.pushBack( ReaderNameStackEntry( name, mValid ) ); + } + void pushBracketedName( const char* name ) { pushName( name ); } + void popName() + { + if ( mNames.size() ) + { + if ( mNames.back().mOpen && mNames.back().mValid ) + mReader.leaveChild(); + mNames.popBack(); + } + mValid =true; + if ( mNames.size() && mNames.back().mValid == false ) + mValid = false; + } + + void pushCurrentContext() + { + mContexts.pushBack( static_cast<PxU32>( mNames.size() ) ); + } + void popCurrentContext() + { + if ( mContexts.size() ) + { + PxU32 depth = mContexts.back(); + PX_ASSERT( mNames.size() >= depth ); + while( mNames.size() > depth ) + popName(); + mContexts.popBack(); + } + } + + bool updateLastEntryAfterOpen() + { + mNames.back().mValid = mValid; + mNames.back().mOpen = mValid; + return mValid; + } + + bool gotoTopName() + { + if ( mNames.size() && mNames.back().mOpen == false ) + { + if ( mValid ) + mValid = mReader.gotoChild( mNames.back().mName ); + updateLastEntryAfterOpen(); + } + return mValid; + } + + bool isValid() const { return mValid; } + + bool gotoChild( const char* name ) + { + pushName( name ); + return gotoTopName(); + } + + bool gotoFirstChild() + { + pushName( "__child" ); + if ( mValid ) mValid = mReader.gotoFirstChild(); + return updateLastEntryAfterOpen(); + } + + bool gotoNextSibling() + { + bool retval = mValid; + if ( mValid ) retval = mReader.gotoNextSibling(); + return retval; + } + + const char* getCurrentItemName() { if (mValid ) return mReader.getCurrentItemName(); return ""; } + + const char* topName() const + { + if ( mNames.size() ) return mNames.back().mName; + PX_ASSERT( false ); + return "bad__repx__name"; + } + + const char* getCurrentValue() + { + const char* value = NULL; + if ( isValid() && mReader.read( topName(), value ) ) + return value; + return NULL; + } + + template<typename TDataType> + bool readProperty(TDataType& outType) + { + const char* value = getCurrentValue(); + if ( value && *value ) + { + stringToType( value, outType ); + return true; + } + return false; + } + + template<typename TDataType> + bool readExtendedIndexProperty(TDataType& outType) + { + const char* value = mReader.getCurrentItemValue(); + if ( value && *value ) + { + stringToType( value, outType ); + return true; + } + return false; + } + + + template<typename TRefType> + bool readReference(TRefType*& outRef) + { + return physx::Sn::readReference<TRefType>( mReader, mCollection, topName(), outRef ); + } + + inline bool readProperty(const char*& outProp ) + { + outProp = ""; + const char* value = getCurrentValue(); + if ( value && *value && mArgs.stringTable ) + { + outProp = mArgs.stringTable->allocateStr( value ); + return true; + } + return false; + } + + inline bool readProperty(PxConvexMesh*& outProp ) + { + return readReference<PxConvexMesh>( outProp ); + } + + inline bool readProperty(PxTriangleMesh*& outProp ) + { + return readReference<PxTriangleMesh>( outProp ); + } + inline bool readProperty(PxBVH33TriangleMesh*& outProp ) + { + return readReference<PxBVH33TriangleMesh>( outProp ); + } + inline bool readProperty(PxBVH34TriangleMesh*& outProp ) + { + return readReference<PxBVH34TriangleMesh>( outProp ); + } + + inline bool readProperty(PxHeightField*& outProp ) + { + return readReference<PxHeightField>( outProp ); + } + + inline bool readProperty( PxRigidActor *& outProp ) + { + return readReference<PxRigidActor>( outProp ); + } + + template<typename TAccessorType> + void simpleProperty( PxU32 /*key*/, TAccessorType& inProp ) + { + typedef typename TAccessorType::prop_type TPropertyType; + TPropertyType value; + if ( readProperty( value ) ) + inProp.set( mObj, value ); + } + + template<typename TAccessorType> + void enumProperty( PxU32 /*key*/, TAccessorType& inProp, const PxU32ToName* inConversions ) + { + typedef typename TAccessorType::prop_type TPropertyType; + const char* strVal = getCurrentValue(); + if ( strVal && *strVal ) + { + TPropertyType pval; + stringToEnumType( strVal, pval, inConversions ); + inProp.set( mObj, pval ); + } + } + + template<typename TAccessorType> + void flagsProperty( PxU32 /*key*/, const TAccessorType& inProp, const PxU32ToName* inConversions ) + { + typedef typename TAccessorType::prop_type TPropertyType; + typedef typename TPropertyType::InternalType TInternalType; + + const char* strVal = getCurrentValue(); + if ( strVal && *strVal ) + { + PxU32 tempValue = 0; + stringToFlagsType( strVal, mAllocator, tempValue, inConversions ); + inProp.set( mObj, TPropertyType(TInternalType( tempValue ))); + } + } + + template<typename TAccessorType, typename TInfoType> + void complexProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo ) + { + typedef typename TAccessorType::prop_type TPropertyType; + if ( gotoTopName() ) + { + TPropertyType propVal = inProp.get( mObj ); + readComplexObj( *this, &propVal, inInfo ); + inProp.set( mObj, propVal ); + } + } + + template<typename TAccessorType, typename TInfoType> + void bufferCollectionProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo ) + { + typedef typename TAccessorType::prop_type TPropertyType; + Ps::InlineArray<TPropertyType,5> theData; + + this->pushCurrentContext(); + if ( this->gotoTopName() ) + { + for ( bool success = this->gotoFirstChild(); success; + success = this->gotoNextSibling() ) + { + TPropertyType propVal; + readComplexObj( *this, &propVal, inInfo ); + theData.pushBack(propVal); + } + } + this->popCurrentContext(); + + inProp.set( mObj, theData.begin(), theData.size() ); + + } + + template<typename TAccessorType, typename TInfoType> + void extendedIndexedProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo ) + { + typedef typename TAccessorType::prop_type TPropertyType; + + this->pushCurrentContext(); + if ( this->gotoTopName() ) + { + PxU32 index = 0; + for ( bool success = this->gotoFirstChild(); success; + success = this->gotoNextSibling() ) + { + TPropertyType propVal; + readComplexObj( *this, &propVal, inInfo ); + inProp.set(mObj, index, propVal); + ++index; + } + } + this->popCurrentContext(); + } + + template<typename TAccessorType, typename TInfoType> + void PxFixedSizeLookupTableProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo ) + { + typedef typename TAccessorType::prop_type TPropertyType; + const_cast<TAccessorType&>(inProp).clear( mObj ); + + this->pushCurrentContext(); + if ( this->gotoTopName() ) + { + for ( bool success = this->gotoFirstChild(); success; + success = this->gotoNextSibling() ) + { + TPropertyType propXVal; + readComplexObj( *this, &propXVal, inInfo ); + + if(this->gotoNextSibling()) + { + TPropertyType propYVal; + readComplexObj( *this, &propYVal, inInfo ); + const_cast<TAccessorType&>(inProp).addPair(mObj, propXVal, propYVal); + } + } + } + this->popCurrentContext(); + } + + void handleShapes( const PxRigidActorShapeCollection& inProp ) + { + physx::Sn::readShapesProperty( *this, mObj, &inProp ); + } + }; + + template<typename TObjType> + struct RepXVisitorReader : public RepXVisitorReaderBase<TObjType> + { + RepXVisitorReader( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, TObjType* obj + , XmlMemoryAllocator& alloc, PxCollection& collection, bool& ret) + : RepXVisitorReaderBase<TObjType>( names, contexts, args, reader, obj, alloc, collection, ret) + { + } + RepXVisitorReader( const RepXVisitorReader<TObjType>& other ) + : RepXVisitorReaderBase<TObjType>( other ) + { + } + }; + + // Specialized template to load dynamic rigid, to determine the kinematic state first + template<> + struct RepXVisitorReader<PxRigidDynamic> : public RepXVisitorReaderBase<PxRigidDynamic> + { + RepXVisitorReader( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, PxRigidDynamic* obj + , XmlMemoryAllocator& alloc, PxCollection& collection, bool& ret) + : RepXVisitorReaderBase<PxRigidDynamic>( names, contexts, args, reader, obj, alloc, collection, ret) + { + } + RepXVisitorReader( const RepXVisitorReader<PxRigidDynamic>& other ) + : RepXVisitorReaderBase<PxRigidDynamic>( other ) + { + } + + void handleShapes( const PxRigidActorShapeCollection& inProp ) + { + // Need to read the parental actor to check if actor is kinematic + // in that case we need to apply the kinematic flag before a shape is set + XmlReaderWriter* parentReader = static_cast<XmlReaderWriter*>(mReader.getParentReader()); + if(mObj) + { + const char* value; + if (parentReader->read( "RigidBodyFlags", value )) + { + if(strstr(value, "eKINEMATIC")) + { + mObj->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true); + } + } + } + physx::Sn::readShapesProperty( *this, mObj, &inProp ); + parentReader->release(); + } + + + template<typename TAccessorType> + void simpleProperty( PxU32 /*key*/, TAccessorType& inProp ) + { + typedef typename TAccessorType::prop_type TPropertyType; + TPropertyType value; + if (readProperty(value)) + { + // If the rigid body is kinematic, we cannot set the LinearVelocity or AngularVelocity + const bool kinematic = (mObj->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC); + if(kinematic && (inProp.mProperty.mKey == PxPropertyInfoName::PxRigidBody_LinearVelocity || inProp.mProperty.mKey == PxPropertyInfoName::PxRigidBody_AngularVelocity)) + return; + + inProp.set(mObj, value ); + } + } + private: + RepXVisitorReader<PxRigidDynamic>& operator=(const RepXVisitorReader<PxRigidDynamic>&); + }; + + template<> + struct RepXVisitorReader<PxShape> : public RepXVisitorReaderBase<PxShape> + { + RepXVisitorReader( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, PxShape* obj + , XmlMemoryAllocator& alloc, PxCollection& collection, bool& ret ) + : RepXVisitorReaderBase<PxShape>( names, contexts, args, reader, obj, alloc, collection, ret ) + { + } + RepXVisitorReader( const RepXVisitorReader<PxShape>& other ) + : RepXVisitorReaderBase<PxShape>( other ) + { + } + void handleShapeMaterials( const PxShapeMaterialsProperty& ) //these were handled during construction. + { + } + void handleGeometryProperty( const PxShapeGeometryProperty& ) + { + } + private: + RepXVisitorReader<PxShape>& operator=(const RepXVisitorReader<PxShape>&); + }; + + template<> + struct RepXVisitorReader<PxArticulationLink> : public RepXVisitorReaderBase<PxArticulationLink> + { + RepXVisitorReader( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, PxArticulationLink* obj + , XmlMemoryAllocator& alloc, PxCollection& collection, bool& ret ) + : RepXVisitorReaderBase<PxArticulationLink>( names, contexts, args, reader, obj, alloc, collection, ret ) + { + } + RepXVisitorReader( const RepXVisitorReader<PxArticulationLink>& other ) + : RepXVisitorReaderBase<PxArticulationLink>( other ) + { + } + void handleIncomingJoint( const TIncomingJointPropType& prop ) + { + pushName( "Joint" ); + if ( gotoTopName() ) + { + PxArticulationJoint* theJoint( prop.get( mObj ) ); + readComplexObj( *this, theJoint ); + + //Add joint to PxCollection, since PxArticulation requires PxArticulationLink and joint. + mCollection.add( *theJoint ); + } + popName(); + } + private: + RepXVisitorReader<PxArticulationLink>& operator=(const RepXVisitorReader<PxArticulationLink>&); + }; + + inline void readProperty( RepXVisitorReaderBase<PxArticulation>& inSerializer, PxArticulation* inObj, const PxArticulationLinkCollectionProp& /*inProp*/) + { + PxProfileAllocatorWrapper theWrapper( inSerializer.mAllocator.getAllocator() ); + PxCollection& collection( inSerializer.mCollection ); + + TArticulationLinkLinkMap linkRemapMap( theWrapper ); + inSerializer.pushCurrentContext(); + if( inSerializer.gotoTopName() ) + { + for ( bool links = inSerializer.gotoFirstChild(); + links != false; + links = inSerializer.gotoNextSibling() ) + { + //Need enough information to create the link... + PxSerialObjectId theParentPtr = 0; + const PxArticulationLink* theParentLink = NULL; + if ( inSerializer.mReader.read( "Parent", theParentPtr ) ) + { + const TArticulationLinkLinkMap::Entry* theRemappedParent( linkRemapMap.find( theParentPtr ) ); + //If we have a valid at write time, we had better have a valid parent at read time. + PX_ASSERT( theRemappedParent ); + theParentLink = theRemappedParent->second; + } + PxArticulationLink* newLink = inObj->createLink( const_cast<PxArticulationLink*>( theParentLink ), PxTransform(PxIdentity) ); + PxSerialObjectId theIdPtr = 0; + inSerializer.mReader.read( "Id", theIdPtr ); + + linkRemapMap.insert( theIdPtr, newLink ); + readComplexObj( inSerializer, newLink ); + + //Add link to PxCollection, since PxArticulation requires PxArticulationLink and joint. + collection.add( *newLink, theIdPtr ); + } + } + inSerializer.popCurrentContext(); + } + + template<> + struct RepXVisitorReader<PxArticulation> : public RepXVisitorReaderBase<PxArticulation> + { + RepXVisitorReader( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, PxArticulation* obj + , XmlMemoryAllocator& alloc, PxCollection& collection, bool& ret) + : RepXVisitorReaderBase<PxArticulation>( names, contexts, args, reader, obj, alloc, collection, ret) + { + } + RepXVisitorReader( const RepXVisitorReader<PxArticulation>& other ) + : RepXVisitorReaderBase<PxArticulation>( other ) + { + } + + void handleArticulationLinks( const PxArticulationLinkCollectionProp& inProp ) + { + physx::Sn::readProperty( *this, mObj, inProp ); + } + }; + + template<typename TObjType, typename TInfoType> + inline bool readAllProperties( PxRepXInstantiationArgs args, TReaderNameStack& names, PxProfileArray<PxU32>& contexts, XmlReader& reader, TObjType* obj, XmlMemoryAllocator& alloc, PxCollection& collection, TInfoType& info ) + { + bool hadError = false; + RepXVisitorReader<TObjType> theReader( names, contexts, args, reader, obj, alloc, collection, hadError); + RepXPropertyFilter<RepXVisitorReader<TObjType> > theOp( theReader ); + info.visitBaseProperties( theOp ); + info.visitInstanceProperties( theOp ); + return !hadError; + } + + + template<typename TObjType> + inline bool readAllProperties( PxRepXInstantiationArgs args, XmlReader& reader, TObjType* obj, XmlMemoryAllocator& alloc, PxCollection& collection ) + { + PxProfileAllocatorWrapper wrapper( alloc.getAllocator() ); + TReaderNameStack names( wrapper ); + PxProfileArray<PxU32> contexts( wrapper ); + PxClassInfoTraits<TObjType> info; + return readAllProperties( args, names, contexts, reader, obj, alloc, collection, info.Info ); + } + + template<typename TObjType, typename TReaderType, typename TInfoType> + inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj, TInfoType& info) + { + if(!readAllProperties( oldVisitor.mArgs, oldVisitor.mNames, oldVisitor.mContexts, oldVisitor.mReader, inObj, oldVisitor.mAllocator, oldVisitor.mCollection, info )) + oldVisitor.mHadError = true; + } + + template<typename TObjType, typename TReaderType, typename TInfoType> + inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj, const TInfoType& info) + { + if(!readAllProperties( oldVisitor.mArgs, oldVisitor.mNames, oldVisitor.mContexts, oldVisitor.mReader, inObj, oldVisitor.mAllocator, oldVisitor.mCollection, info )) + oldVisitor.mHadError = true; + } + + template<typename TObjType, typename TReaderType> + inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj, const PxUnknownClassInfo& /*info*/) + { + const char* value = oldVisitor.mReader.getCurrentItemValue(); + if ( value && *value ) + { + stringToType( value, *inObj ); + return; + } + oldVisitor.mHadError = true; + } + + template<typename TObjType, typename TReaderType> + inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj) + { + PxClassInfoTraits<TObjType> info; + if(!readAllProperties( oldVisitor.mArgs, oldVisitor.mNames, oldVisitor.mContexts, oldVisitor.mReader, inObj, oldVisitor.mAllocator, oldVisitor.mCollection, info.Info )) + oldVisitor.mHadError = true; + } + +} } + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlVisitorWriter.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlVisitorWriter.h new file mode 100644 index 00000000..76bf66cd --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlVisitorWriter.h @@ -0,0 +1,765 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_XML_VISITOR_WRITER_H +#define PX_XML_VISITOR_WRITER_H + +#include "PsInlineArray.h" +#include "CmPhysXCommon.h" +#include "RepXMetaDataPropertyVisitor.h" +#include "SnPxStreamOperators.h" +#include "SnXmlMemoryPoolStreams.h" +#include "SnXmlWriter.h" +#include "SnXmlImpl.h" +#include "PsFoundation.h" + +namespace physx { namespace Sn { + + template<typename TDataType> + inline void writeReference( XmlWriter& writer, PxCollection& inCollection, const char* inPropName, const TDataType* inDatatype ) + { + const PxBase* s = static_cast<const PxBase*>( inDatatype ) ; + if( inDatatype && !inCollection.contains( *const_cast<PxBase*>(s) )) + { + Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, + "PxSerialization::serializeCollectionToXml: Reference \"%s\" could not be resolved.", inPropName); + } + + PxSerialObjectId theId = 0; + if( s ) + { + theId = inCollection.getId( *s ); + if( theId == 0 ) + theId = PX_PROFILE_POINTER_TO_U64( inDatatype ); + } + + writer.write( inPropName, PxCreateRepXObject( inDatatype, theId ) ); + } + + inline void writeProperty( XmlWriter& inWriter, MemoryBuffer& inBuffer, const char* inProp ) + { + PxU8 data = 0; + inBuffer.write( &data, sizeof(PxU8) ); + inWriter.write( inProp, reinterpret_cast<const char*>( inBuffer.mBuffer ) ); + inBuffer.clear(); + } + + template<typename TDataType> + inline void writeProperty( XmlWriter& inWriter, PxCollection&, MemoryBuffer& inBuffer, const char* inPropName, TDataType inValue ) + { + inBuffer << inValue; + writeProperty( inWriter, inBuffer, inPropName ); + } + + inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxConvexMesh* inDatatype ) + { + writeReference( writer, inCollection, inPropName, inDatatype ); + } + + inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxConvexMesh* inDatatype ) + { + writeReference( writer, inCollection, inPropName, inDatatype ); + } +#ifdef REMOVED + inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxTriangleMesh* inDatatype ) + { + writeReference( writer, inCollection, inPropName, inDatatype ); + } + + inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxTriangleMesh* inDatatype ) + { + writeReference( writer, inCollection, inPropName, inDatatype ); + } +#endif + + inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxBVH33TriangleMesh* inDatatype ) + { + writeReference( writer, inCollection, inPropName, inDatatype ); + } + + inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxBVH33TriangleMesh* inDatatype ) + { + writeReference( writer, inCollection, inPropName, inDatatype ); + } + + inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxBVH34TriangleMesh* inDatatype ) + { + writeReference( writer, inCollection, inPropName, inDatatype ); + } + + inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxBVH34TriangleMesh* inDatatype ) + { + writeReference( writer, inCollection, inPropName, inDatatype ); + } + + inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxHeightField* inDatatype ) + { + writeReference( writer, inCollection, inPropName, inDatatype ); + } + + inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxHeightField* inDatatype ) + { + writeReference( writer, inCollection, inPropName, inDatatype ); + } + + inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxRigidActor* inDatatype ) + { + writeReference( writer, inCollection, inPropName, inDatatype ); + } + + inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxArticulation* inDatatype ) + { + writeReference( writer, inCollection, inPropName, inDatatype ); + } + + inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxRigidActor* inDatatype ) + { + writeReference( writer, inCollection, inPropName, inDatatype ); + } + + inline void writeFlagsProperty( XmlWriter& inWriter, MemoryBuffer& tempBuf, const char* inPropName, PxU32 inFlags, const PxU32ToName* inTable ) + { + if ( inTable ) + { + PxU32 flagValue( inFlags ); + if ( flagValue ) + { + for ( PxU32 idx =0; inTable[idx].mName != NULL; ++idx ) + { + if ( (inTable[idx].mValue & flagValue) == inTable[idx].mValue ) + { + if ( tempBuf.mWriteOffset != 0 ) + tempBuf << "|"; + tempBuf << inTable[idx].mName; + } + } + writeProperty( inWriter, tempBuf, inPropName ); + } + } + } + + inline void writeFlagsBuffer( MemoryBuffer& tempBuf, PxU32 flagValue, const PxU32ToName* inTable ) + { + PX_ASSERT(inTable); + bool added = false; + + if ( flagValue ) + { + for ( PxU32 item =0; inTable[item].mName != NULL; ++item ) + { + if ( (inTable[item].mValue & flagValue) != 0 ) + { + if ( added ) + tempBuf << "|"; + tempBuf << inTable[item].mName; + added = true; + } + } + } + } + + inline void writePxVec3( PxOutputStream& inStream, const PxVec3& inVec ) { inStream << inVec; } + + + template<typename TDataType> + inline const TDataType& PtrAccess( const TDataType* inPtr, PxU32 inIndex ) + { + return inPtr[inIndex]; + } + + template<typename TDataType> + inline void BasicDatatypeWrite( PxOutputStream& inStream, const TDataType& item ) { inStream << item; } + + template<typename TObjType, typename TAccessOperator, typename TWriteOperator> + inline void writeBuffer( XmlWriter& inWriter, MemoryBuffer& inTempBuffer + , PxU32 inObjPerLine, const TObjType* inObjType, TAccessOperator inAccessOperator + , PxU32 inBufSize, const char* inPropName, TWriteOperator inOperator ) + { + if ( inBufSize && inObjType ) + { + for ( PxU32 idx = 0; idx < inBufSize; ++idx ) + { + if ( idx && ( idx % inObjPerLine == 0 ) ) + inTempBuffer << "\n\t\t\t"; + else + inTempBuffer << " "; + inOperator( inTempBuffer, inAccessOperator( inObjType, idx ) ); + } + writeProperty( inWriter, inTempBuffer, inPropName ); + } + } + + template<typename TDataType, typename TAccessOperator, typename TWriteOperator> + inline void writeStrideBuffer( XmlWriter& inWriter, MemoryBuffer& inTempBuffer + , PxU32 inObjPerLine, PxStrideIterator<const TDataType>& inData, TAccessOperator inAccessOperator + , PxU32 inBufSize, const char* inPropName, PxU32 /*inStride*/, TWriteOperator inOperator ) + { + if ( inBufSize && &inData[0]) + { + for ( PxU32 idx = 0; idx < inBufSize; ++idx ) + { + if ( idx && ( idx % inObjPerLine == 0 ) ) + inTempBuffer << "\n\t\t\t"; + else + inTempBuffer << " "; + + inOperator( inTempBuffer, inAccessOperator( &inData[idx], 0 ) ); + } + writeProperty( inWriter, inTempBuffer, inPropName ); + } + } + + + template<typename TDataType, typename TAccessOperator> + inline void writeStrideFlags( XmlWriter& inWriter, MemoryBuffer& inTempBuffer + , PxU32 inObjPerLine, PxStrideIterator<const TDataType>& inData, TAccessOperator /*inAccessOperator*/ + , PxU32 inBufSize, const char* inPropName, const PxU32ToName* inTable) + { + if ( inBufSize && &inData[0]) + { + for ( PxU32 idx = 0; idx < inBufSize; ++idx ) + { + writeFlagsBuffer(inTempBuffer, inData[idx], inTable); + + if ( idx && ( idx % inObjPerLine == 0 ) ) + inTempBuffer << "\n\t\t\t"; + else + inTempBuffer << " "; + } + writeProperty( inWriter, inTempBuffer, inPropName ); + } + } + + template<typename TDataType, typename TWriteOperator> + inline void writeBuffer( XmlWriter& inWriter, MemoryBuffer& inTempBuffer + , PxU32 inObjPerLine, const TDataType* inBuffer + , PxU32 inBufSize, const char* inPropName, TWriteOperator inOperator ) + { + writeBuffer( inWriter, inTempBuffer, inObjPerLine, inBuffer, PtrAccess<TDataType>, inBufSize, inPropName, inOperator ); + } + + template<typename TEnumType> + inline void writeEnumProperty( XmlWriter& inWriter, const char* inPropName, TEnumType inEnumValue, const PxU32ToName* inConversions ) + { + PxU32 theValue = static_cast<PxU32>( inEnumValue ); + for ( const PxU32ToName* conv = inConversions; conv->mName != NULL; ++conv ) + if ( conv->mValue == theValue ) inWriter.write( inPropName, conv->mName ); + } + + + + template<typename TObjType, typename TWriterType, typename TInfoType> + inline void handleComplexObj( TWriterType& oldVisitor, const TObjType* inObj, TInfoType& info); + + template<typename TCollectionType, typename TVisitor, typename TPropType, typename TInfoType > + void handleComplexCollection( TVisitor& visitor, const TPropType& inProp, const char* childName, TInfoType& inInfo ) + { + PxU32 count( inProp.size( visitor.mObj ) ); + if ( count ) + { + Ps::InlineArray<TCollectionType*,5> theData; + theData.resize( count ); + inProp.get( visitor.mObj, theData.begin(), count ); + for( PxU32 idx =0; idx < count; ++idx ) + { + visitor.pushName( childName ); + handleComplexObj( visitor, theData[idx], inInfo ); + visitor.popName(); + } + } + } + + template<typename TCollectionType, typename TVisitor, typename TPropType, typename TInfoType > + void handleBufferCollection( TVisitor& visitor, const TPropType& inProp, const char* childName, TInfoType& inInfo ) + { + PxU32 count( inProp.size( visitor.mObj ) ); + if ( count ) + { + Ps::InlineArray<TCollectionType*,5> theData; + theData.resize( count ); + inProp.get( visitor.mObj, theData.begin()); + + for( PxU32 idx =0; idx < count; ++idx ) + { + visitor.pushName( childName ); + handleComplexObj( visitor, theData[idx], inInfo ); + visitor.popName(); + } + } + } + + template<typename TVisitor> + void handleShapes( TVisitor& visitor, const PxRigidActorShapeCollection& inProp ) + { + PxShapeGeneratedInfo theInfo; + + PxU32 count( inProp.size( visitor.mObj ) ); + if ( count ) + { + Ps::InlineArray<PxShape*,5> theData; + theData.resize( count ); + inProp.get( visitor.mObj, theData.begin(), count ); + for( PxU32 idx = 0; idx < count; ++idx ) + { + const PxShape* shape = theData[idx]; + visitor.pushName( "PxShape" ); + + if( !shape->isExclusive() ) + { + writeReference( visitor.mWriter, visitor.mCollection, "PxShapeRef", shape ); + } + else + { + handleComplexObj( visitor, shape, theInfo ); + } + visitor.popName(); + } + } + } + + template<typename TVisitor> + void handleShapeMaterials( TVisitor& visitor, const PxShapeMaterialsProperty& inProp ) + { + PxU32 count( inProp.size( visitor.mObj ) ); + if ( count ) + { + Ps::InlineArray<PxMaterial*,5> theData; + theData.resize( count ); + inProp.get( visitor.mObj, theData.begin(), count ); + visitor.pushName( "PxMaterialRef" ); + + for( PxU32 idx =0; idx < count; ++idx ) + writeReference( visitor.mWriter, visitor.mCollection, "PxMaterialRef", theData[idx] ); + visitor.popName(); + } + } + + template<typename TObjType> + struct RepXVisitorWriterBase + { + TNameStack& mNameStack; + XmlWriter& mWriter; + const TObjType* mObj; + MemoryBuffer& mTempBuffer; + PxCollection& mCollection; + + RepXVisitorWriterBase( TNameStack& ns, XmlWriter& writer, const TObjType* obj, MemoryBuffer& buf, PxCollection& collection ) + : mNameStack( ns ) + , mWriter( writer ) + , mObj( obj ) + , mTempBuffer( buf ) + , mCollection( collection ) + { + } + + RepXVisitorWriterBase( const RepXVisitorWriterBase<TObjType>& other ) + : mNameStack( other.mNameStack ) + , mWriter( other.mWriter ) + , mObj( other.mObj ) + , mTempBuffer( other.mTempBuffer ) + , mCollection( other.mCollection ) + { + } + + RepXVisitorWriterBase& operator=( const RepXVisitorWriterBase& ){ PX_ASSERT( false ); return *this; } + + void gotoTopName() + { + if ( mNameStack.size() && mNameStack.back().mOpen == false ) + { + mWriter.addAndGotoChild( mNameStack.back().mName ); + mNameStack.back().mOpen = true; + } + } + + void pushName( const char* inName ) + { + gotoTopName(); + mNameStack.pushBack( inName ); + } + + void pushBracketedName( const char* inName ) { pushName( inName ); } + void popName() + { + if ( mNameStack.size() ) + { + if ( mNameStack.back().mOpen ) + mWriter.leaveChild(); + mNameStack.popBack(); + } + } + + const char* topName() const + { + if ( mNameStack.size() ) return mNameStack.back().mName; + PX_ASSERT( false ); + return "bad__repx__name"; + } + + template<typename TAccessorType> + void simpleProperty( PxU32 /*key*/, TAccessorType& inProp ) + { + typedef typename TAccessorType::prop_type TPropertyType; + TPropertyType propVal = inProp.get( mObj ); + writeProperty( mWriter, mCollection, mTempBuffer, topName(), propVal ); + } + + template<typename TAccessorType> + void enumProperty( PxU32 /*key*/, TAccessorType& inProp, const PxU32ToName* inConversions ) + { + writeEnumProperty( mWriter, topName(), inProp.get( mObj ), inConversions ); + } + + template<typename TAccessorType> + void flagsProperty( PxU32 /*key*/, const TAccessorType& inProp, const PxU32ToName* inConversions ) + { + writeFlagsProperty( mWriter, mTempBuffer, topName(), inProp.get( mObj ), inConversions ); + } + + template<typename TAccessorType, typename TInfoType> + void complexProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo ) + { + typedef typename TAccessorType::prop_type TPropertyType; + TPropertyType propVal = inProp.get( mObj ); + handleComplexObj( *this, &propVal, inInfo ); + } + + template<typename TAccessorType, typename TInfoType> + void bufferCollectionProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo ) + { + typedef typename TAccessorType::prop_type TPropertyType; + + PxU32 count( inProp.size( mObj ) ); + Ps::InlineArray<TPropertyType,5> theData; + theData.resize( count ); + + PxClassInfoTraits<TInfoType> theTraits; + PX_UNUSED(theTraits); + PxU32 numItems = inProp.get( mObj, theData.begin(), count ); + PX_ASSERT( numItems == count ); + for( PxU32 idx =0; idx < numItems; ++idx ) + { + pushName( inProp.name() ); + handleComplexObj( *this, &theData[idx], inInfo ); + popName(); + } + } + + template<typename TAccessorType, typename TInfoType> + void extendedIndexedProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& /*inInfo */) + { + typedef typename TAccessorType::prop_type TPropertyType; + + PxU32 count( inProp.size( mObj ) ); + Ps::InlineArray<TPropertyType,5> theData; + theData.resize( count ); + + for(PxU32 i = 0; i < count; ++i) + { + char buffer[32] = { 0 }; + sprintf( buffer, "id_%u", i ); + pushName( buffer ); + + TPropertyType propVal = inProp.get( mObj, i ); + TInfoType& infoType = PxClassInfoTraits<TPropertyType>().Info; + handleComplexObj(*this, &propVal, infoType); + popName(); + } + } + + template<typename TAccessorType, typename TInfoType> + void PxFixedSizeLookupTableProperty( PxU32* /*key*/, TAccessorType& inProp, TInfoType& /*inInfo */) + { + typedef typename TAccessorType::prop_type TPropertyType; + PxU32 count( inProp.size( mObj ) ); + + PxU32 index = 0; + for(PxU32 i = 0; i < count; ++i) + { + char buffer[32] = { 0 }; + sprintf( buffer, "id_%u", index++ ); + pushName( buffer ); + TPropertyType propVal = inProp.getX( mObj , i); + writeProperty( mWriter, mCollection, mTempBuffer, topName(), propVal ); + popName(); + + sprintf( buffer, "id_%u", index++ ); + pushName( buffer ); + propVal = inProp.getY( mObj , i); + writeProperty( mWriter, mCollection, mTempBuffer, topName(), propVal ); + popName(); + } + } + + + void handleShapes( const PxRigidActorShapeCollection& inProp ) + { + physx::Sn::handleShapes( *this, inProp ); + } + + void handleShapeMaterials( const PxShapeMaterialsProperty& inProp ) + { + physx::Sn::handleShapeMaterials( *this, inProp ); + } + }; + + template<typename TObjType> + struct RepXVisitorWriter : RepXVisitorWriterBase<TObjType> + { + RepXVisitorWriter( TNameStack& ns, XmlWriter& writer, const TObjType* obj, MemoryBuffer& buf, PxCollection& collection ) + : RepXVisitorWriterBase<TObjType>( ns, writer, obj, buf, collection ) + { + } + + RepXVisitorWriter( const RepXVisitorWriter<TObjType>& other ) + : RepXVisitorWriterBase<TObjType>( other ) + { + } + }; + + template<> + struct RepXVisitorWriter<PxArticulationLink> : RepXVisitorWriterBase<PxArticulationLink> + { + RepXVisitorWriter( TNameStack& ns, XmlWriter& writer, const PxArticulationLink* obj, MemoryBuffer& buf, PxCollection& collection ) + : RepXVisitorWriterBase<PxArticulationLink>( ns, writer, obj, buf, collection ) + { + } + + RepXVisitorWriter( const RepXVisitorWriter<PxArticulationLink>& other ) + : RepXVisitorWriterBase<PxArticulationLink>( other ) + { + } + + void handleIncomingJoint( const TIncomingJointPropType& prop ) + { + const PxArticulationJoint* theJoint( prop.get( mObj ) ); + if ( theJoint ) + { + PxArticulationJointGeneratedInfo info; + pushName( "Joint" ); + handleComplexObj( *this, theJoint, info ); + popName(); + } + } + }; + + typedef PxProfileHashMap< const PxSerialObjectId, const PxArticulationLink* > TArticulationLinkLinkMap; + + template<> + struct RepXVisitorWriter<PxArticulation> : RepXVisitorWriterBase<PxArticulation> + { + TArticulationLinkLinkMap& mArticulationLinkParents; + + RepXVisitorWriter( TNameStack& ns, XmlWriter& writer, const PxArticulation* inArticulation, MemoryBuffer& buf, PxCollection& collection, TArticulationLinkLinkMap* artMap = NULL ) + : RepXVisitorWriterBase<PxArticulation>( ns, writer, inArticulation, buf, collection ) + , mArticulationLinkParents( *artMap ) + { + Ps::InlineArray<PxArticulationLink*, 64, PxProfileWrapperReflectionAllocator<PxArticulationLink*> > linkList( PxProfileWrapperReflectionAllocator<PxArticulationLink*>( buf.mManager->getWrapper() ) ); + PxU32 numLinks = inArticulation->getNbLinks(); + linkList.resize( numLinks ); + inArticulation->getLinks( linkList.begin(), numLinks ); + for ( PxU32 idx = 0; idx < numLinks; ++idx ) + { + const PxArticulationLink* theLink( linkList[idx] ); + + Ps::InlineArray<PxArticulationLink*, 64> theChildList; + PxU32 numChildren = theLink->getNbChildren(); + theChildList.resize( numChildren ); + theLink->getChildren( theChildList.begin(), numChildren ); + for ( PxU32 childIdx = 0; childIdx < numChildren; ++childIdx ) + mArticulationLinkParents.insert( PX_PROFILE_POINTER_TO_U64(theChildList[childIdx]), theLink ); + } + } + + RepXVisitorWriter( const RepXVisitorWriter<PxArticulation>& other ) + : RepXVisitorWriterBase<PxArticulation>( other ) + , mArticulationLinkParents( other.mArticulationLinkParents ) + { + } + template<typename TAccessorType, typename TInfoType> + void complexProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo ) + { + typedef typename TAccessorType::prop_type TPropertyType; + TPropertyType propVal = inProp.get( mObj ); + handleComplexObj( *this, &propVal, inInfo ); + } + + void writeArticulationLink( const PxArticulationLink* inLink ) + { + pushName( "PxArticulationLink" ); + gotoTopName(); + + const TArticulationLinkLinkMap::Entry* theParentPtr = mArticulationLinkParents.find( PX_PROFILE_POINTER_TO_U64(inLink) ); + if ( theParentPtr != NULL ) + writeProperty( mWriter, mCollection, mTempBuffer, "Parent", theParentPtr->second ); + writeProperty( mWriter, mCollection, mTempBuffer, "Id", inLink ); + + PxArticulationLinkGeneratedInfo info; + handleComplexObj( *this, inLink, info ); + popName(); + } + + void recurseAddLinkAndChildren( const PxArticulationLink* inLink, Ps::InlineArray<const PxArticulationLink*, 64>& ioLinks ) + { + ioLinks.pushBack( inLink ); + Ps::InlineArray<PxArticulationLink*, 8> theChildren; + PxU32 childCount( inLink->getNbChildren() ); + theChildren.resize( childCount ); + inLink->getChildren( theChildren.begin(), childCount ); + for ( PxU32 idx = 0; idx < childCount; ++idx ) + recurseAddLinkAndChildren( theChildren[idx], ioLinks ); + } + + void handleArticulationLinks( const PxArticulationLinkCollectionProp& inProp ) + { + //topologically sort the links as per my discussion with Dilip because + //links aren't guaranteed to have the parents before the children in the + //overall link list and it is unlikely to be done by beta 1. + PxU32 count( inProp.size( mObj ) ); + if ( count ) + { + Ps::InlineArray<PxArticulationLink*, 64> theLinks; + theLinks.resize( count ); + inProp.get( mObj, theLinks.begin(), count ); + + Ps::InlineArray<const PxArticulationLink*, 64> theSortedLinks; + for ( PxU32 idx = 0; idx < count; ++idx ) + { + const PxArticulationLink* theLink( theLinks[idx] ); + if ( mArticulationLinkParents.find( PX_PROFILE_POINTER_TO_U64(theLink) ) == NULL ) + recurseAddLinkAndChildren( theLink, theSortedLinks ); + } + PX_ASSERT( theSortedLinks.size() == count ); + for ( PxU32 idx = 0; idx < count; ++idx ) + writeArticulationLink( theSortedLinks[idx] ); + popName(); + } + } + private: + RepXVisitorWriter<PxArticulation>& operator=(const RepXVisitorWriter<PxArticulation>&); + }; + + template<> + struct RepXVisitorWriter<PxShape> : RepXVisitorWriterBase<PxShape> + { + RepXVisitorWriter( TNameStack& ns, XmlWriter& writer, const PxShape* obj, MemoryBuffer& buf, PxCollection& collection ) + : RepXVisitorWriterBase<PxShape>( ns, writer, obj, buf, collection ) + { + } + + RepXVisitorWriter( const RepXVisitorWriter<PxShape>& other ) + : RepXVisitorWriterBase<PxShape>( other ) + { + } + + template<typename GeometryType> + inline void writeGeometryProperty( const PxShapeGeometryProperty& inProp, const char* inTypeName ) + { + pushName( "Geometry" ); + pushName( inTypeName ); + GeometryType theType; + inProp.getGeometry( mObj, theType ); + PxClassInfoTraits<GeometryType> theTraits; + PxU32 count = theTraits.Info.totalPropertyCount(); + if(count) + { + handleComplexObj( *this, &theType, theTraits.Info); + } + else + { + writeProperty(mWriter, mTempBuffer, inTypeName); + } + popName(); + popName(); + } + + void handleGeometryProperty( const PxShapeGeometryProperty& inProp ) + { + switch( mObj->getGeometryType() ) + { + case PxGeometryType::eSPHERE: writeGeometryProperty<PxSphereGeometry>( inProp, "PxSphereGeometry" ); break; + case PxGeometryType::ePLANE: writeGeometryProperty<PxPlaneGeometry>( inProp, "PxPlaneGeometry" ); break; + case PxGeometryType::eCAPSULE: writeGeometryProperty<PxCapsuleGeometry>( inProp, "PxCapsuleGeometry" ); break; + case PxGeometryType::eBOX: writeGeometryProperty<PxBoxGeometry>( inProp, "PxBoxGeometry" ); break; + case PxGeometryType::eCONVEXMESH: writeGeometryProperty<PxConvexMeshGeometry>( inProp, "PxConvexMeshGeometry" ); break; + case PxGeometryType::eTRIANGLEMESH: writeGeometryProperty<PxTriangleMeshGeometry>( inProp, "PxTriangleMeshGeometry" ); break; + case PxGeometryType::eHEIGHTFIELD: writeGeometryProperty<PxHeightFieldGeometry>( inProp, "PxHeightFieldGeometry" ); break; + case PxGeometryType::eINVALID: + case PxGeometryType::eGEOMETRY_COUNT: + PX_ASSERT( false ); + } + } + }; + + template<typename TObjType> + inline void writeAllProperties( TNameStack& inNameStack, const TObjType* inObj, XmlWriter& writer, MemoryBuffer& buffer, PxCollection& collection ) + { + RepXVisitorWriter<TObjType> newVisitor( inNameStack, writer, inObj, buffer, collection ); + RepXPropertyFilter<RepXVisitorWriter<TObjType> > theOp( newVisitor ); + PxClassInfoTraits<TObjType> info; + info.Info.visitBaseProperties( theOp ); + info.Info.visitInstanceProperties( theOp ); + } + + template<typename TObjType> + inline void writeAllProperties( TNameStack& inNameStack, TObjType* inObj, XmlWriter& writer, MemoryBuffer& buffer, PxCollection& collection ) + { + RepXVisitorWriter<TObjType> newVisitor( inNameStack, writer, inObj, buffer, collection ); + RepXPropertyFilter<RepXVisitorWriter<TObjType> > theOp( newVisitor ); + PxClassInfoTraits<TObjType> info; + info.Info.visitBaseProperties( theOp ); + info.Info.visitInstanceProperties( theOp ); + } + + template<typename TObjType> + inline void writeAllProperties( const TObjType* inObj, XmlWriter& writer, MemoryBuffer& buffer, PxCollection& collection ) + { + TNameStack theNames( buffer.mManager->getWrapper() ); + writeAllProperties( theNames, inObj, writer, buffer, collection ); + } + + template<typename TObjType, typename TWriterType, typename TInfoType> + inline void handleComplexObj( TWriterType& oldVisitor, const TObjType* inObj, const TInfoType& /*info*/) + { + writeAllProperties( oldVisitor.mNameStack, inObj, oldVisitor.mWriter, oldVisitor.mTempBuffer, oldVisitor.mCollection ); + } + + template<typename TObjType, typename TWriterType, typename TInfoType> + inline void handleComplexObj( TWriterType& oldVisitor, const TObjType* inObj, TInfoType& /*info*/) + { + writeAllProperties( oldVisitor.mNameStack, inObj, oldVisitor.mWriter, oldVisitor.mTempBuffer, oldVisitor.mCollection ); + } + + template<typename TObjType, typename TWriterType> + inline void handleComplexObj( TWriterType& oldVisitor, const TObjType* inObj, const PxUnknownClassInfo& /*info*/) + { + writeProperty( oldVisitor.mWriter, oldVisitor.mCollection, oldVisitor.mTempBuffer, oldVisitor.topName(), *inObj ); + } + +} } +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlWriter.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlWriter.h new file mode 100644 index 00000000..afea8aa0 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlWriter.h @@ -0,0 +1,57 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and 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. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. +#ifndef PX_XML_WRITER_H +#define PX_XML_WRITER_H + +#include "foundation/PxSimpleTypes.h" + +namespace physx { + + struct PxRepXObject; + + /** + * Writer used by extensions to write elements to a file or database + */ + class XmlWriter + { + protected: + virtual ~XmlWriter(){} + public: + /** Write a key-value pair into the current item */ + virtual void write( const char* inName, const char* inData ) = 0; + /** Write an object id into the current item */ + virtual void write( const char* inName, const PxRepXObject& inLiveObject ) = 0; + /** Add a child that then becomes the current context */ + virtual void addAndGotoChild( const char* inName ) = 0; + /** Leave the current child */ + virtual void leaveChild() = 0; + }; +} + +#endif |