From 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 Mon Sep 17 00:00:00 2001 From: git perforce import user Date: Tue, 25 Oct 2016 12:29:14 -0600 Subject: Initial commit: PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167] --- PhysX_3.4/Source/PhysXCooking/src/Quantizer.cpp | 338 ++++++++++++++++++++++++ 1 file changed, 338 insertions(+) create mode 100644 PhysX_3.4/Source/PhysXCooking/src/Quantizer.cpp (limited to 'PhysX_3.4/Source/PhysXCooking/src/Quantizer.cpp') diff --git a/PhysX_3.4/Source/PhysXCooking/src/Quantizer.cpp b/PhysX_3.4/Source/PhysXCooking/src/Quantizer.cpp new file mode 100644 index 00000000..6c68892a --- /dev/null +++ b/PhysX_3.4/Source/PhysXCooking/src/Quantizer.cpp @@ -0,0 +1,338 @@ +// 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 "Quantizer.h" + +#include "foundation/PxVec3.h" +#include "foundation/PxBounds3.h" + +#include "PsUserAllocated.h" +#include "PsAllocator.h" +#include "PsArray.h" + +#include "CmPhysXCommon.h" + +using namespace physx; + +PxU32 kmeans_cluster3d(const PxVec3 *input, // an array of input 3d data points. + PxU32 inputSize, // the number of input data points. + PxU32 clumpCount, // the number of clumps you wish to product. + PxVec3 *outputClusters, // The output array of clumps 3d vectors, should be at least 'clumpCount' in size. + PxU32 *outputIndices, // A set of indices which remaps the input vertices to clumps; should be at least 'inputSize' + float errorThreshold=0.01f, // The error threshold to converge towards before giving up. + float collapseDistance=0.01f); // distance so small it is not worth bothering to create a new clump. + +template +PxU32 kmeans_cluster(const Vec *input, + PxU32 inputCount, + PxU32 clumpCount, + Vec *clusters, + PxU32 *outputIndices, + Type threshold, // controls how long it works to converge towards a least errors solution. + Type collapseDistance) // distance between clumps to consider them to be essentially equal. +{ + PxU32 convergeCount = 64; // maximum number of iterations attempting to converge to a solution.. + PxU32* counts = reinterpret_cast (PX_ALLOC_TEMP(sizeof(PxU32)*clumpCount, "PxU32")); + Type error=0; + if ( inputCount <= clumpCount ) // if the number of input points is less than our clumping size, just return the input points. + { + clumpCount = inputCount; + for (PxU32 i=0; i (PX_ALLOC_TEMP(sizeof(PxVec3)*clumpCount, "PxVec3")); + + // Take a sampling of the input points as initial centroid estimates. + for (PxU32 i=0; i threshold ); // keep going until the error is reduced by this threshold amount. + + PX_FREE(centroids); + } + + // ok..now we prune the clumps if necessary. + // The rules are; first, if a clump has no 'counts' then we prune it as it's unused. + // The second, is if the centroid of this clump is essentially the same (based on the distance tolerance) + // as an existing clump, then it is pruned and all indices which used to point to it, now point to the one + // it is closest too. + PxU32 outCount = 0; // number of clumps output after pruning performed. + Type d2 = collapseDistance*collapseDistance; // squared collapse distance. + for (PxU32 i=0; i(input, inputSize, clumpCount, outputClusters, outputIndices, errorThreshold, collapseDistance); +} + +class QuantizerImpl : public Quantizer, public Ps::UserAllocated +{ +public: + QuantizerImpl(void) + { + mScale = PxVec3(1.0f, 1.0f, 1.0f); + mCenter = PxVec3(0.0f, 0.0f, 0.0f); + } + + // Use the k-means quantizer, similar results, but much slower. + virtual const PxVec3 * kmeansQuantize3D(PxU32 vcount, + const PxVec3 *vertices, + PxU32 stride, + bool denormalizeResults, + PxU32 maxVertices, + PxU32 &outVertsCount) + { + const PxVec3 *ret = NULL; + outVertsCount = 0; + mNormalizedInput.clear(); + mQuantizedOutput.clear(); + + if ( vcount > 0 ) + { + normalizeInput(vcount,vertices, stride); + + PxVec3* quantizedOutput = reinterpret_cast (PX_ALLOC_TEMP(sizeof(PxVec3)*vcount, "PxVec3")); + PxU32* quantizedIndices = reinterpret_cast (PX_ALLOC_TEMP(sizeof(PxU32)*vcount, "PxU32")); + outVertsCount = kmeans_cluster3d(&mNormalizedInput[0], vcount, maxVertices, quantizedOutput, quantizedIndices, 0.01f, 0.0001f ); + if ( outVertsCount > 0 ) + { + if ( denormalizeResults ) + { + for (PxU32 i=0; i (vertices); + mNormalizedInput.clear(); + mQuantizedOutput.clear(); + PxBounds3 bounds; + bounds.setEmpty(); + for (PxU32 i=0; i (vtx); + vtx += stride; + + bounds.include(v); + } + + mCenter = bounds.getCenter(); + + PxVec3 dim = bounds.getDimensions(); + dim *= 1.001f; + mScale = dim*0.5f; + + for (PxU32 i = 0; i < 3; i++) + { + if(dim[i] == 0) + mScale[i] = 1.0f; + } + + PxVec3 recip; + recip.x = 1.0f / mScale.x; + recip.y = 1.0f / mScale.y; + recip.z = 1.0f / mScale.z; + + vtx = reinterpret_cast (vertices); + for (PxU32 i=0; i (vtx); + vtx += stride; + + v = (v - mCenter).multiply(recip); + + mNormalizedInput.pushBack(v); + } + } + + virtual ~QuantizerImpl(void) + { + + } + + private: + PxVec3 mScale; + PxVec3 mCenter; + Ps::Array mNormalizedInput; + Ps::Array mQuantizedOutput; +}; + +Quantizer * physx::createQuantizer(void) +{ + QuantizerImpl *m = PX_NEW(QuantizerImpl); + return static_cast< Quantizer *>(m); +} -- cgit v1.2.3