diff options
| author | mtamis <[email protected]> | 2017-02-15 16:06:25 +0100 |
|---|---|---|
| committer | mtamis <[email protected]> | 2017-02-15 16:06:25 +0100 |
| commit | 85305930aeeb1d513e23522bd91f29ba81aa6d14 (patch) | |
| tree | 45f1bb20a45a300d1fef107e436cac95602a0e57 /NvCloth/src/SwCloth.cpp | |
| download | nvcloth-85305930aeeb1d513e23522bd91f29ba81aa6d14.tar.xz nvcloth-85305930aeeb1d513e23522bd91f29ba81aa6d14.zip | |
NvCloth library v1.0.0
Diffstat (limited to 'NvCloth/src/SwCloth.cpp')
| -rw-r--r-- | NvCloth/src/SwCloth.cpp | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/NvCloth/src/SwCloth.cpp b/NvCloth/src/SwCloth.cpp new file mode 100644 index 0000000..f409ad6 --- /dev/null +++ b/NvCloth/src/SwCloth.cpp @@ -0,0 +1,321 @@ +// 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-2017 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 "SwCloth.h" +#include "SwFabric.h" +#include "SwFactory.h" +#include "TripletScheduler.h" +#include "ClothBase.h" +#include <foundation/PxMat44.h> +#include "NvCloth/Allocator.h" + +using namespace physx; + +namespace nv +{ +namespace cloth +{ +PhaseConfig transform(const PhaseConfig&); // from PhaseConfig.cpp +} +} + +using namespace nv; + +cloth::SwCloth::SwCloth(SwFactory& factory, SwFabric& fabric, Range<const PxVec4> particles) +: mFactory(factory), mFabric(fabric), mNumVirtualParticles(0), mUserData(0) +{ + NV_CLOTH_ASSERT(!particles.empty()); + + initialize(*this, particles.begin(), particles.end()); + +#if PX_WINDOWS_FAMILY + const uint32_t kSimdWidth = 8; // avx +#else + const uint32_t kSimdWidth = 4; // sse +#endif + + NV_CLOTH_ASSERT(particles.size() == fabric.getNumParticles()); + + mCurParticles.reserve(particles.size() + kSimdWidth - 1); + mCurParticles.assign(reinterpret_cast<const PxVec4*>(particles.begin()), + reinterpret_cast<const PxVec4*>(particles.end())); + + // 7 dummy particles used in SIMD solver + mCurParticles.resize(particles.size() + kSimdWidth - 1, PxVec4(0.0f)); + mPrevParticles = mCurParticles; + + mCurParticles.resize(particles.size()); + mPrevParticles.resize(particles.size()); + + mFabric.incRefCount(); +} + +namespace +{ +// copy vector and make same capacity +void copyVector(nv::cloth::Vector<PxVec4>::Type& dst, const nv::cloth::Vector<PxVec4>::Type& src) +{ + dst.reserve(src.capacity()); + dst.assign(src.begin(), src.end()); + + // ensure valid dummy data + dst.resize(src.capacity(), PxVec4(0.0f)); + dst.resize(src.size()); +} +} + +// copy constructor, supports rebinding to a different factory +cloth::SwCloth::SwCloth(SwFactory& factory, const SwCloth& cloth) +: mFactory(factory) +, mFabric(cloth.mFabric) +, mPhaseConfigs(cloth.mPhaseConfigs) +, mCapsuleIndices(cloth.mCapsuleIndices) +, mStartCollisionSpheres(cloth.mStartCollisionSpheres) +, mTargetCollisionSpheres(cloth.mTargetCollisionSpheres) +, mStartCollisionPlanes(cloth.mStartCollisionPlanes) +, mTargetCollisionPlanes(cloth.mTargetCollisionPlanes) +, mStartCollisionTriangles(cloth.mStartCollisionTriangles) +, mTargetCollisionTriangles(cloth.mTargetCollisionTriangles) +, mVirtualParticleIndices(cloth.mVirtualParticleIndices) +, mVirtualParticleWeights(cloth.mVirtualParticleWeights) +, mNumVirtualParticles(cloth.mNumVirtualParticles) +, mSelfCollisionIndices(cloth.mSelfCollisionIndices) +, mRestPositions(cloth.mRestPositions) +{ + copy(*this, cloth); + + // carry over capacity (using as dummy particles) + copyVector(mCurParticles, cloth.mCurParticles); + copyVector(mPrevParticles, cloth.mPrevParticles); + copyVector(mMotionConstraints.mStart, cloth.mMotionConstraints.mStart); + copyVector(mMotionConstraints.mTarget, cloth.mMotionConstraints.mTarget); + copyVector(mSeparationConstraints.mStart, cloth.mSeparationConstraints.mStart); + copyVector(mSeparationConstraints.mTarget, cloth.mSeparationConstraints.mTarget); + copyVector(mParticleAccelerations, cloth.mParticleAccelerations); + + //Both cloth and this have a reference to fabric. The factory that created fabric does not have to be the same as mFactory. + //mFabric needs to outlive both cloth instances. (this is checked with refcount asserts). + mFabric.incRefCount(); +} + +cloth::SwCloth::~SwCloth() +{ + mFabric.decRefCount(); +} + +// bounds = lower[3], upper[3] +void cloth::SwCloth::setParticleBounds(const float* bounds) +{ + for (uint32_t i = 0; i < 3; ++i) + { + array(mParticleBoundsCenter)[i] = (bounds[3 + i] + bounds[i]) * 0.5f; + array(mParticleBoundsHalfExtent)[i] = (bounds[3 + i] - bounds[i]) * 0.5f; + } +} + +cloth::Range<PxVec4> cloth::SwCloth::push(SwConstraints& constraints) +{ + uint32_t n = uint32_t(mCurParticles.size()); + + if (!constraints.mTarget.capacity()) + constraints.mTarget.resize((n + 3) & ~3, PxVec4(0.0f)); // reserve multiple of 4 for SIMD + + constraints.mTarget.resizeUninitialized(n); + PxVec4* data = &constraints.mTarget.front(); + Range<PxVec4> result(data, data + constraints.mTarget.size()); + + if (constraints.mStart.empty()) // initialize start first + constraints.mStart.swap(constraints.mTarget); + + return result; +} + +void cloth::SwCloth::clear(SwConstraints& constraints) +{ + Vector<PxVec4>::Type().swap(constraints.mStart); + Vector<PxVec4>::Type().swap(constraints.mTarget); +} + +cloth::Range<const PxVec3> cloth::SwCloth::clampTriangleCount(Range<const PxVec3> range, uint32_t) +{ + return range; +} + +#include "ClothImpl.h" + +namespace nv +{ +namespace cloth +{ + +template <> +Cloth* ClothImpl<SwCloth>::clone(Factory& factory) const +{ + return factory.clone(*this); +} + +template <> +uint32_t ClothImpl<SwCloth>::getNumParticles() const +{ + return uint32_t(mCloth.mCurParticles.size()); +} + +template <> +void ClothImpl<SwCloth>::lockParticles() const +{ +} + +template <> +void ClothImpl<SwCloth>::unlockParticles() const +{ +} + +template <> +MappedRange<PxVec4> ClothImpl<SwCloth>::getCurrentParticles() +{ + return getMappedParticles(&mCloth.mCurParticles.front()); +} + +template <> +MappedRange<const PxVec4> ClothImpl<SwCloth>::getCurrentParticles() const +{ + return getMappedParticles(&mCloth.mCurParticles.front()); +} + +template <> +MappedRange<PxVec4> ClothImpl<SwCloth>::getPreviousParticles() +{ + return getMappedParticles(&mCloth.mPrevParticles.front()); +} + +template <> +MappedRange<const PxVec4> ClothImpl<SwCloth>::getPreviousParticles() const +{ + return getMappedParticles(&mCloth.mPrevParticles.front()); +} + +template <> +GpuParticles ClothImpl<SwCloth>::getGpuParticles() +{ + GpuParticles result = { 0, 0, 0 }; + return result; +} + +template <> +void ClothImpl<SwCloth>::setPhaseConfig(Range<const PhaseConfig> configs) +{ + mCloth.mPhaseConfigs.resize(0); + + // transform phase config to use in solver + for (; !configs.empty(); configs.popFront()) + if (configs.front().mStiffness > 0.0f) + mCloth.mPhaseConfigs.pushBack(transform(configs.front())); + + mCloth.wakeUp(); +} + +template <> +void ClothImpl<SwCloth>::setSelfCollisionIndices(Range<const uint32_t> indices) +{ + ContextLockType lock(mCloth.mFactory); + mCloth.mSelfCollisionIndices.assign(indices.begin(), indices.end()); + mCloth.notifyChanged(); + mCloth.wakeUp(); +} + +template <> +uint32_t ClothImpl<SwCloth>::getNumVirtualParticles() const +{ + return uint32_t(mCloth.mNumVirtualParticles); +} + +template <> +Range<PxVec4> ClothImpl<SwCloth>::getParticleAccelerations() +{ + if (mCloth.mParticleAccelerations.empty()) + { + uint32_t n = uint32_t(mCloth.mCurParticles.size()); + mCloth.mParticleAccelerations.resize(n, PxVec4(0.0f)); + } + + mCloth.wakeUp(); + + PxVec4* data = &mCloth.mParticleAccelerations.front(); + return Range<PxVec4>(data, data + mCloth.mParticleAccelerations.size()); +} + +template <> +void ClothImpl<SwCloth>::clearParticleAccelerations() +{ + Vector<PxVec4>::Type().swap(mCloth.mParticleAccelerations); + mCloth.wakeUp(); +} + +template <> +void ClothImpl<SwCloth>::setVirtualParticles(Range<const uint32_t[4]> indices, Range<const PxVec3> weights) +{ + mCloth.mNumVirtualParticles = 0; + + // shuffle indices to form independent SIMD sets + uint16_t numParticles = uint16_t(mCloth.mCurParticles.size()); + TripletScheduler scheduler(indices); + scheduler.simd(numParticles, 4); + + // convert indices to byte offset + Vec4us dummy(numParticles, uint16_t(numParticles + 1), uint16_t(numParticles + 2), 0); + Vector<uint32_t>::Type::ConstIterator sIt = scheduler.mSetSizes.begin(); + Vector<uint32_t>::Type::ConstIterator sEnd = scheduler.mSetSizes.end(); + TripletScheduler::ConstTripletIter tIt = scheduler.mTriplets.begin(), tLast; + mCloth.mVirtualParticleIndices.resize(0); + mCloth.mVirtualParticleIndices.reserve(indices.size() + 3 * uint32_t(sEnd - sIt)); + for (; sIt != sEnd; ++sIt) + { + uint32_t setSize = *sIt; + for (tLast = tIt + setSize; tIt != tLast; ++tIt, ++mCloth.mNumVirtualParticles) + mCloth.mVirtualParticleIndices.pushBack(Vec4us(*tIt)); + mCloth.mVirtualParticleIndices.resize((mCloth.mVirtualParticleIndices.size() + 3) & ~3, dummy); + } + Vector<Vec4us>::Type(mCloth.mVirtualParticleIndices.begin(), mCloth.mVirtualParticleIndices.end()) + .swap(mCloth.mVirtualParticleIndices); + + // precompute 1/dot(w,w) + Vector<PxVec4>::Type().swap(mCloth.mVirtualParticleWeights); + mCloth.mVirtualParticleWeights.reserve(weights.size()); + for (; !weights.empty(); weights.popFront()) + { + PxVec3 w = weights.front(); + float scale = 1 / w.magnitudeSquared(); + mCloth.mVirtualParticleWeights.pushBack(PxVec4( w.x, w.y, w.z, scale )); + } + + mCloth.notifyChanged(); +} + +} // namespace cloth +} // namespace nv |