From 688b5f42e9bfe498d7af7075d4d8f4429867f3a3 Mon Sep 17 00:00:00 2001 From: Miles Macklin Date: Fri, 9 Jun 2017 13:41:15 +1200 Subject: 1.2.0.beta.1 --- include/NvFlex.h | 342 +++++++++++++++++++++++++++++++++++++--------------- include/NvFlexExt.h | 17 ++- 2 files changed, 257 insertions(+), 102 deletions(-) (limited to 'include') diff --git a/include/NvFlex.h b/include/NvFlex.h index a6b305c..8189489 100644 --- a/include/NvFlex.h +++ b/include/NvFlex.h @@ -36,7 +36,7 @@ #endif // least 2 significant digits define minor version, eg: 10 -> version 0.10 -#define NV_FLEX_VERSION 110 +#define NV_FLEX_VERSION 120 //! \endcond @@ -68,7 +68,6 @@ enum NvFlexMapFlags { eNvFlexMapWait = 0, //!< Calling thread will be blocked until buffer is ready for access, default eNvFlexMapDoNotWait = 1, //!< Calling thread will check if buffer is ready for access, if not ready then the method will return NULL immediately - eNvFlexMapDiscard = 2 //!< Buffer contents will be discarded, this allows for efficent buffer reuse }; /** @@ -76,8 +75,8 @@ enum NvFlexMapFlags */ enum NvFlexBufferType { - eNvFlexBufferHost = 0, //!< Host mappable buffer, pinned memory on CUDA, staging buffer on DX - eNvFlexBufferDevice = 1, //!< Device memory buffer, mapping this on CUDA will return a device memory pointer, and will return a buffer pointer on DX + eNvFlexBufferHost = 0, //!< A host mappable buffer, pinned memory on CUDA, staging buffer on DX + eNvFlexBufferDevice = 1, //!< A device memory buffer, mapping this on CUDA will return a device memory pointer, and will return a buffer pointer on DX }; /** @@ -86,7 +85,7 @@ enum NvFlexBufferType enum NvFlexRelaxationMode { eNvFlexRelaxationGlobal = 0, //!< The relaxation factor is a fixed multiplier on each constraint's position delta - eNvFlexRelaxationLocal = 1 //!< The relaxation factor is a fixed multiplier on each constraint's delta divided by the particle's constraint count, convergence will be slower but more reliable + eNvFlexRelaxationLocal = 1 //!< The relaxation factor is a fixed multiplier on each constraint's delta divided by the particle's constraint count, convergence will be slower but more reliable }; @@ -123,7 +122,6 @@ struct NvFlexParams float lift; //!< Lift force applied to particles belonging to dynamic triangles, proportional to velocity^2*area in the direction perpendicular to velocity and (if possible), parallel to the plane normal // fluid params - bool fluid; //!< If true then particles with phase 0 are considered fluid particles and interact using the position based fluids method float cohesion; //!< Control how strongly particles hold each other together, default: 0.025, range [0.0, +inf] float surfaceTension; //!< Controls how strongly particles attempt to minimize surface area, default: 0.0, range: [0.0, +inf] float viscosity; //!< Smoothes particle velocities using XSPH viscosity @@ -141,13 +139,8 @@ struct NvFlexParams float diffuseBuoyancy; //!< Scales force opposing gravity that diffuse particles receive float diffuseDrag; //!< Scales force diffuse particles receive in direction of neighbor fluid particles int diffuseBallistic; //!< The number of neighbors below which a diffuse particle is considered ballistic - float diffuseSortAxis[3]; //!< Diffuse particles will be sorted by depth along this axis if non-zero float diffuseLifetime; //!< Time in seconds that a diffuse particle will live for after being spawned, particles will be spawned with a random lifetime in the range [0, diffuseLifetime] - // rigid params - float plasticThreshold; //!< Particles belonging to rigid shapes that move with a position delta magnitude > threshold will be permanently deformed in the rest pose - float plasticCreep; //!< Controls the rate at which particles in the rest pose are deformed for particles passing the deformation threshold - // collision params float collisionDistance; //!< Distance particles maintain against shapes, note that for robust collision against triangle meshes this distance should be greater than zero float particleCollisionMargin; //!< Increases the radius used during neighbor finding, this is useful if particles are expected to move significantly during a single step to ensure contacts aren't missed on subsequent iterations @@ -160,22 +153,46 @@ struct NvFlexParams float relaxationFactor; //!< Control the convergence rate of the parallel solver, default: 1, values greater than 1 may lead to instability }; + /** - * Flags that control the a particle's behavior and grouping, use NvFlexMakePhase() to construct a valid 32bit phase identifier + * Flags that control a particle's behavior and grouping, use NvFlexMakePhase() to construct a valid 32bit phase identifier */ enum NvFlexPhase { - eNvFlexPhaseGroupMask = 0x00ffffff, //!< Low 24 bits represent the particle group for controlling collisions - - eNvFlexPhaseSelfCollide = 1 << 24, //!< If set this particle will interact with particles of the same group - eNvFlexPhaseSelfCollideFilter = 1 << 25, //!< If set this particle will ignore collisions with particles closer than the radius in the rest pose, this flag should not be specified unless valid rest positions have been specified using NvFlexSetRestParticles() - eNvFlexPhaseFluid = 1 << 26, //!< If set this particle will generate fluid density constraints for its overlapping neighbors + eNvFlexPhaseGroupMask = 0x000fffff, //!< Bits [ 0, 19] represent the particle group for controlling collisions + eNvFlexPhaseFlagsMask = 0x00f00000, //!< Bits [20, 23] hold flags about how the particle behave + eNvFlexPhaseShapeChannelMask = 0xff000000, //!< Bits [24, 31] hold flags representing what shape collision channels particles will collide with, see NvFlexMakeShapeFlags() + + eNvFlexPhaseSelfCollide = 1 << 20, //!< If set this particle will interact with particles of the same group + eNvFlexPhaseSelfCollideFilter = 1 << 21, //!< If set this particle will ignore collisions with particles closer than the radius in the rest pose, this flag should not be specified unless valid rest positions have been specified using NvFlexSetRestParticles() + eNvFlexPhaseFluid = 1 << 22, //!< If set this particle will generate fluid density constraints for its overlapping neighbors + eNvFlexPhaseUnused = 1 << 23, //!< Reserved + + eNvFlexPhaseShapeChannel0 = 1 << 24, //!< Particle will collide with shapes with channel 0 set (see NvFlexMakeShapeFlags()) + eNvFlexPhaseShapeChannel1 = 1 << 25, //!< Particle will collide with shapes with channel 1 set (see NvFlexMakeShapeFlags()) + eNvFlexPhaseShapeChannel2 = 1 << 26, //!< Particle will collide with shapes with channel 2 set (see NvFlexMakeShapeFlags()) + eNvFlexPhaseShapeChannel3 = 1 << 27, //!< Particle will collide with shapes with channel 3 set (see NvFlexMakeShapeFlags()) + eNvFlexPhaseShapeChannel4 = 1 << 28, //!< Particle will collide with shapes with channel 4 set (see NvFlexMakeShapeFlags()) + eNvFlexPhaseShapeChannel5 = 1 << 29, //!< Particle will collide with shapes with channel 5 set (see NvFlexMakeShapeFlags()) + eNvFlexPhaseShapeChannel6 = 1 << 30, //!< Particle will collide with shapes with channel 6 set (see NvFlexMakeShapeFlags()) + eNvFlexPhaseShapeChannel7 = 1 << 31, //!< Particle will collide with shapes with channel 7 set (see NvFlexMakeShapeFlags()) }; + /** - * Generate a bit set for the particle phase, the group should be an integer < 2^24, and the flags should be a combination of FlexPhase enum values + * Generate a bit set for the particle phase, this is a helper method to simply combine the + * group id and bit flags into a single integer. + * + * @param[in] group The index of the group for this particle, should be an integer < 2^20 + * @param[in] particleFlags A combination of the phase flags which should be a combination of eNvFlexPhaseSelfCollide, eNvFlexPhaseSelfCollideFilter, and eNvFlexPhaseFluid + * @param[in] shapeChannels A combination of eNvFlexPhaseShapeChannel* flags that control which shapes will be collided against, particles will only collide against shapes that share at least one set channel, see NvFlexMakeShapeFlagsWithChannels() */ -NV_FLEX_API inline int NvFlexMakePhase(int group, int flags) { return (group & eNvFlexPhaseGroupMask) | flags; } +NV_FLEX_API inline int NvFlexMakePhaseWithChannels(int group, int particleFlags, int shapeChannels) { return (group & eNvFlexPhaseGroupMask) | (particleFlags & eNvFlexPhaseFlagsMask) | (shapeChannels & eNvFlexPhaseShapeChannelMask); } + +/** + * Deprecated helper method to generates a phase with all shape channels set + */ +NV_FLEX_API inline int NvFlexMakePhase(int group, int particleFlags) { return NvFlexMakePhaseWithChannels(group, particleFlags, eNvFlexPhaseShapeChannelMask); } /** @@ -234,14 +251,6 @@ enum NvFlexSolverCallbackStage eNvFlexStageCount, //!< Number of stages }; -/** Defines the different DirectX compute modes that Flex can use -*/ -enum NvFlexComputeType -{ - eNvFlexCUDA, //!< Use CUDA compute for Flex, the application must link against the CUDA libraries - eNvFlexD3D11, //!< Use DirectX 11 compute for Flex, the application must link against the D3D libraries - eNvFlexD3D12, //!< Use DirectX 12 compute for Flex, the application must link against the D3D libraries -}; /** Structure containing pointers to the internal solver data that is passed to each registered solver callback * @@ -272,18 +281,6 @@ struct NvFlexSolverCallbackParams const int* sortedToOriginalMap; //!< Device pointer that maps the original particle index to the index in the callback data structure }; -/** Descriptor used to initialize Flex -*/ -struct NvFlexInitDesc -{ - int deviceIndex; //!< The GPU device index that should be used, if there is already a CUDA context on the calling thread then this parameter will be ignored and the active CUDA context used. Otherwise a new context will be created using the suggested device ordinal. - bool enableExtensions; //!< Enable or disable NVIDIA/AMD extensions in DirectX, can lead to improved performance. - void* renderDevice; //!< Direct3D device to use for simulation, if none is specified a new device and context will be created. - void* renderContext; //!< Direct3D context to use for simulation, if none is specified a new context will be created, in DirectX 12 this should be a pointer to the ID3D12CommandQueue where compute operations will take place. - - NvFlexComputeType computeType; //!< Set to eNvFlexD3D11 if DirectX 11 should be used, eNvFlexD3D12 for DirectX 12, this must match the libraries used to link the application -}; - /** Solver callback definition, see NvFlexRegisterSolverCallback() */ struct NvFlexSolverCallback @@ -300,6 +297,33 @@ struct NvFlexSolverCallback */ typedef void (*NvFlexErrorCallback)(NvFlexErrorSeverity type, const char* msg, const char* file, int line); + + + +/** Defines the different compute backends that Flex can use +*/ +enum NvFlexComputeType +{ + eNvFlexCUDA, //!< Use CUDA compute for Flex, the application must link against the CUDA libraries + eNvFlexD3D11, //!< Use DirectX 11 compute for Flex, the application must link against the D3D libraries + eNvFlexD3D12, //!< Use DirectX 12 compute for Flex, the application must link against the D3D libraries +}; + + +/** Descriptor used to initialize Flex +*/ +struct NvFlexInitDesc +{ + int deviceIndex; //!< The GPU device index that should be used, if there is already a CUDA context on the calling thread then this parameter will be ignored and the active CUDA context used. Otherwise a new context will be created using the suggested device ordinal. + bool enableExtensions; //!< Enable or disable NVIDIA/AMD extensions in DirectX, can lead to improved performance. + void* renderDevice; //!< Direct3D device to use for simulation, if none is specified a new device and context will be created. + void* renderContext; //!< Direct3D context that the app is using for rendering. In DirectX 12 this should be a ID3D12CommandQueue pointer. + void* computeContext; //!< Direct3D context to use for simulation, if none is specified a new context will be created, in DirectX 12 this should be a pointer to the ID3D12CommandQueue where compute operations will take place. + bool runOnRenderContext; //!< If true, run Flex on D3D11 render context, or D3D12 direct queue. If false, run on a D3D12 compute queue, or vendor specific D3D11 compute queue, allowing compute and graphics to run in parallel on some GPUs. + + NvFlexComputeType computeType; //!< Set to eNvFlexD3D11 if DirectX 11 should be used, eNvFlexD3D12 for DirectX 12, this must match the libraries used to link the application +}; + /** * Initialize library, should be called before any other API function. * @@ -309,7 +333,7 @@ typedef void (*NvFlexErrorCallback)(NvFlexErrorSeverity type, const char* msg, c * @param[in] desc The NvFlexInitDesc struct defining the device ordinal, D3D device/context and the type of D3D compute being used * @return A pointer to a library instance that can be used to allocate shared object such as triangle meshes, buffers, etc */ -NV_FLEX_API NvFlexLibrary* NvFlexInit(int version = NV_FLEX_VERSION, NvFlexErrorCallback errorFunc = 0, NvFlexInitDesc * desc = 0); +NV_FLEX_API NvFlexLibrary* NvFlexInit(int version = NV_FLEX_VERSION, NvFlexErrorCallback errorFunc = 0, NvFlexInitDesc* desc = 0); /** * Shutdown library, users should manually destroy any previously created @@ -324,15 +348,41 @@ NV_FLEX_API void NvFlexShutdown(NvFlexLibrary* lib); */ NV_FLEX_API int NvFlexGetVersion(); +/** + * Controls which features are enabled, choosing a simple option will disable features and can lead to better performance and reduced memory usage + */ +enum NvFlexFeatureMode +{ + eNvFlexFeatureModeDefault = 0, //!< All features enabled + eNvFlexFeatureModeSimpleSolids = 1, //!< Simple per-particle collision (no per-particle SDF normals, no fluids) + eNvFlexFeatureModeSimpleFluids = 2, //!< Simple single phase fluid-only particles (no solids) +}; + +/** + * Describes the creation time parameters for the solver + */ +struct NvFlexSolverDesc +{ + NvFlexFeatureMode featureMode; //!< Control which features are enabled + + int maxParticles; //!< Maximum number of regular particles in the solver + int maxDiffuseParticles; //!< Maximum number of diffuse particles in the solver + int maxNeighborsPerParticle; //!< Maximum number of neighbors per-particle, for solids this can be around 32, for fluids up to 128 may be necessary depending on smoothing radius +}; + +/** + * Initialize the solver desc to its default values + * @param[in] desc Pointer to a description structure that will be initialized to default values + */ +NV_FLEX_API void NvFlexSetSolverDescDefaults(NvFlexSolverDesc* desc); + /** * Create a new particle solver * * @param[in] lib The library instance to use - * @param[in] maxParticles Maximum number of simulation particles possible for this solver - * @param[in] maxDiffuseParticles Maximum number of diffuse (non-simulation) particles possible for this solver - * @param[in] maxNeighborsPerParticle Maximum number of neighbors per particle possible for this solver + * @param[in] desc Pointer to a solver description structure used to create the solver */ -NV_FLEX_API NvFlexSolver* NvFlexCreateSolver(NvFlexLibrary* lib, int maxParticles, int maxDiffuseParticles, int maxNeighborsPerParticle = 96); +NV_FLEX_API NvFlexSolver* NvFlexCreateSolver(NvFlexLibrary* lib, const NvFlexSolverDesc* desc); /** * Delete a particle solver * @@ -348,6 +398,14 @@ NV_FLEX_API void NvFlexDestroySolver(NvFlexSolver* solver); */ NV_FLEX_API NvFlexLibrary* NvFlexGetSolverLibrary(NvFlexSolver* solver); +/** + * Return the solver desc that was used to create a solver + * + * @param[in] solver Pointer to a valid Flex solver + * @param[in] desc Pointer to a desc structure + */ +NV_FLEX_API void NvFlexGetSolverDesc(NvFlexSolver* solver, NvFlexSolverDesc* desc); + /** Registers a callback for a solver stage, the callback will be invoked from the same thread that calls NvFlexUpdateSolver(). * * @param[in] solver A valid solver @@ -436,22 +494,41 @@ NV_FLEX_API void NvFlexSetParams(NvFlexSolver* solver, const NvFlexParams* param NV_FLEX_API void NvFlexGetParams(NvFlexSolver* solver, NvFlexParams* params); +/** + * Describes a source and destination buffer region for performing a copy operation. + */ +struct NvFlexCopyDesc +{ + int srcOffset; // struct NvFlexVector { - NvFlexVector(NvFlexLibrary* l, int size=0) : lib(l), buffer(NULL), mappedPtr(NULL), count(0), capacity(0) + NvFlexVector(NvFlexLibrary* l, int size = 0, NvFlexBufferType type = eNvFlexBufferHost) : lib(l), buffer(NULL), mappedPtr(NULL), count(0), capacity(0), type(type) { if (size) { @@ -55,7 +55,7 @@ struct NvFlexVector } } - NvFlexVector(NvFlexLibrary* l, const T* ptr, int size) : lib(l), buffer(NULL), mappedPtr(NULL), count(0), capacity(0) + NvFlexVector(NvFlexLibrary* l, const T* ptr, int size, NvFlexBufferType type = eNvFlexBufferHost) : lib(l), buffer(NULL), mappedPtr(NULL), count(0), capacity(0), type(type) { assign(ptr, size); unmap(); @@ -73,6 +73,7 @@ struct NvFlexVector T* mappedPtr; int count; int capacity; + NvFlexBufferType type; // reinitialize the vector leaving it unmapped void init(int size) @@ -177,7 +178,7 @@ struct NvFlexVector // growth factor of 1.5 const int newCapacity = minCapacity*3/2; - NvFlexBuffer* newBuf = NvFlexAllocBuffer(lib, newCapacity, sizeof(T), eNvFlexBufferHost); + NvFlexBuffer* newBuf = NvFlexAllocBuffer(lib, newCapacity, sizeof(T), type); // copy contents to new buffer void* newPtr = NvFlexMap(newBuf, eNvFlexMapWait); @@ -328,6 +329,10 @@ struct NvFlexExtAsset float* shapeCenters; //!< The position of the center of mass of each shape, an array of vec3s mNumShapes in length int numShapes; //!< The number of shape matching constraints + // plastic deformation + float* shapePlasticThresholds; //!< The plastic threshold coefficient for each shape + float* shapePlasticCreeps; //!< The plastic creep coefficient for each shape + // faces for cloth int* triangleIndices; //!< Indexed triangle mesh indices for clothing int numTriangles; //!< Number of triangles @@ -489,9 +494,11 @@ NV_FLEX_API NvFlexExtAsset* NvFlexExtCreateRigidFromMesh(const float* vertices, * @param[in] linkRadius Any particles below this distance will have additional distance constraints created between them * @param[in] linkStiffness The stiffness of distance links * @param[in] globalStiffness If this parameter is > 0.0f, adds an additional global cluster that consists of all particles in the shape. The stiffness of this cluster is the globalStiffness. +* @param[in] clusterPlasticThreshold Particles belonging to rigid shapes that move with a position delta magnitude > threshold will be permanently deformed in the rest pose, if clusterPlasticCreep > 0.0f +* @param[in] clusterPlasticCreep Controls the rate at which particles in the rest pose are deformed for particles passing the deformation threshold * @return A pointer to an asset structure holding the particles and constraints */ -NV_FLEX_API NvFlexExtAsset* NvFlexExtCreateSoftFromMesh(const float* vertices, int numVertices, const int* indices, int numTriangleIndices, float particleSpacing, float volumeSampling, float surfaceSampling, float clusterSpacing, float clusterRadius, float clusterStiffness, float linkRadius, float linkStiffness, float globalStiffness); +NV_FLEX_API NvFlexExtAsset* NvFlexExtCreateSoftFromMesh(const float* vertices, int numVertices, const int* indices, int numTriangleIndices, float particleSpacing, float volumeSampling, float surfaceSampling, float clusterSpacing, float clusterRadius, float clusterStiffness, float linkRadius, float linkStiffness, float globalStiffness, float clusterPlasticThreshold, float clusterPlasticCreep); /** * Frees all memory associated with an asset created by one of the creation methods @@ -642,7 +649,7 @@ NV_FLEX_API NvFlexExtInstance* NvFlexExtCreateInstance(NvFlexExtContainer* conta NV_FLEX_API void NvFlexExtDestroyInstance(NvFlexExtContainer* container, const NvFlexExtInstance* instance); /** Notifies the container that asset data has changed and needs to be sent to the GPU - * this should be called if the constrains for an existing asset are modified by the user + * this should be called if the constraints for an existing asset are modified by the user * * @param[in] container The container the instance referencing the asset belongs to * @param[in] asset The asset which was modified (can be NULL) -- cgit v1.2.3