gh_flex is the module that manages NVIDIA FleX engine. Flex is a GPU-based particle simulation library designed for real-time applications. It provides a unified interface that is capable of simulating fluids, clothing, solids, ropes, and more. The FleX module requires a CUDA-capable GPU and is currently available on Windows only (the FleX plugin is also available on Linux but the plugin is not stable and then is not shipped yet with GeeXLab).
Number of functions: 47
Gets the name of the current FleX GPU.
This function has no input parameter(s).
gpu = gh_flex.get_compute_device_name()
Gets the version of FleX.
This function has no input parameter(s).
v = gh_flex.get_version()
Generates a phase for a particle. A phase is a bit-vector that defines the behavior of a particle.
This function has no return value(s).
-- Flags / options
--
eNvFlexPhaseSelfCollide = 1048576 -- If set this particle will interact with particles of the same group
eNvFlexPhaseSelfCollideFilter = 2097152 -- 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 = 4194304 -- If set this particle will generate fluid density constraints for its overlapping neighbors
eNvFlexPhaseGroupMask = 1048575 -- Bits [ 0, 19] represent the particle group for controlling collisions
eNvFlexPhaseFlagsMask = 15728640 -- Bits [20, 23] hold flags about how the particle behave
eNvFlexPhaseShapeChannelMask = 2130706432 -- Bits [24, 30] hold flags representing what shape collision channels particles will collide with, see NvFlexMakeShapeFlags() (highest bit reserved for now)
eNvFlexPhaseShapeChannel0 = 16777216 -- Particle will collide with shapes
with channel 0 set (see NvFlexMakeShapeFlags())
eNvFlexPhaseShapeChannel1 = 33554432
group = 0
particle_flags = eNvFlexPhaseSelfCollide
shape_channels = eNvFlexPhaseShapeChannelMask
phase = gh_flex.make_phase(group, particle_flags, shape_channels)
Performs a fast copy of particles position from FleX buffer to the vertex buffer used in rendering.
This function has no return value(s).
gh_flex.particles_copy_position_to_vb_fast(particles_id, vb_id, num_vertices)
Performs a fast copy of particles from FleX buffer to the vertex buffer used in rendering.
This function has no return value(s).
local vb_start_offset_bytes = 0
local vb_position_stride_bytes = 32
local update_color_alpha = 0
local dt = 0.016
gh_flex.particles_copy_to_vb(particles_id, "position", vb_id, num_vertices, vb_start_offset_bytes, vb_position_stride_bytes, update_color_alpha, dt)
-- particles_copy_to_vb() replaces the following code:
--
--[[
function point(buffer_ptr, index, x, y, z, r, g, b, a)
-- Position
local buffer_offset_bytes = index * vertex_size
gh_utils.buffer_write_4f(buffer_ptr, buffer_offset_bytes, x, y, z, 1.0)
-- Color
buffer_offset_bytes = buffer_offset_bytes + attrib_size
gh_utils.buffer_write_4f(buffer_ptr, buffer_offset_bytes, r, g, b, a)
end
gh_flex.particles_map_position(particles_id)
vb_buffer_ptr, bufsize = gh_vb.map(vb_id, "GL_WRITE_ONLY")
for i = 0, num_vertices - 1 do
x, y, z, w = gh_flex.particles_get_position(particles_id, i)
local alpha = particles[i+1].a
if (update_color_alpha == 1) then
alpha = alpha - dt
if (alpha < 0) then
alpha = 0
end
end
particles[i+1].a = alpha
point(vb_buffer_ptr, i, x, y, z, 1, 1, 1, alpha)
end
gh_vb.unmap(vb_id)
gh_flex.particles_unmap_position(particles_id)
--]]
Creates a set of particles.
num_particles = 1000
particles_id = gh_flex.particles_create(num_particles)
Gets the phase of a particular particle. A phase is a bit-vector that defines the behavior of a particle. See make_phase().
phase = gh_flex.particles_get_phase(particles_id, particle_index)
Gets the position of a particular particle.
x, y, z, w = gh_flex.particles_get_position(particles_id, particle_index)
Gets the velocity of a particular particle.
x, y, z = gh_flex.particles_get_velocity(particles_id, index)
Destroys a set of particles.
This function has no return value(s).
gh_flex.particles_kill(particles_id)
Maps the particles indices buffer. That allows the CPU to writes to this buffer.
This function has no return value(s).
gh_flex.particles_map_active_indices(particles_id)
Maps the particles phase buffer. That allows the CPU to writes to this buffer.
This function has no return value(s).
gh_flex.particles_map_phase(particles_id)
Maps the particles position buffer. That allows the CPU to writes to this buffer.
This function has no return value(s).
gh_flex.particles_map_position(particles_id)
Maps the particles velocity buffer. That allows the CPU to writes to this buffer.
This function has no return value(s).
gh_flex.particles_map_velocity(particles_id)
Sets which particle is active.
This function has no return value(s).
-- All the following code can be replaced by one call to particles_update_active()
-- Usually particles_set_active_index() is used as follows:
--
gh_flex.particles_map_active_indices(particles_id)
for i = 0, num_particles - 1 do
gh_flex.particles_set_active_index(particles_id, i, i)
end
gh_flex.particles_unmap_active_indices(particles_id)
gh_flex.particles_set_num_active_indices(particles_id, num_particles)
-- Upload to GPU
gh_flex.solver_write_particles(solver_id, particles_id)
Sets the number of active particles.
This function has no return value(s).
gh_flex.particles_set_num_active_indices(particles_id, num_active)
Sets the phase of a particle. The phase is a bit-vector that defines the behavior of a particle. Use the function make_phase() to generate a phase.
This function has no return value(s).
gh_flex.particles_map_position(particles_id)
gh_flex.particles_map_velocity(particles_id)
gh_flex.particles_map_phase(particles_id)
phase = gh_flex.make_phase(...)
for i = 0, num_particles - 1 do
x = random(...)
y = random(...)
z = random(...)
-- Mass = 1.0
w = 1.0
gh_flex.particles_set_position(particles_id, i, x, y, z, w)
-- Initial velocity is zero
gh_flex.particles_set_velocity(particles_id, i, 0.0, 0.0, 0.0)
gh_flex.particles_set_phase(particles_id, i, phase)
end
gh_flex.particles_unmap_phase(particles_id)
gh_flex.particles_unmap_velocity(particles_id)
gh_flex.particles_unmap_position(particles_id)
-- Upload to GPU
gh_flex.solver_write_particles(solver_id, particles_id)
Sets the position of a particle.
This function has no return value(s).
gh_flex.particles_map_position(particles_id)
for i = 0, num_particles - 1 do
x = random(...)
y = random(...)
z = random(...)
-- Mass = 1.0
w = 1.0
gh_flex.particles_set_position(particles_id, i, x, y, z, w)
end
gh_flex.particles_unmap_position(particles_id)
-- Upload to GPU
gh_flex.solver_write_particles(solver_id, particles_id)
Sets the velocity of a particle.
This function has no return value(s).
gh_flex.particles_map_position(particles_id)
gh_flex.particles_map_velocity(particles_id)
for i = 0, num_particles - 1 do
x = random(...)
y = random(...)
z = random(...)
-- Mass = 1.0
w = 1.0
gh_flex.particles_set_position(particles_id, i, x, y, z, w)
-- Initial velocity is zero.
gh_flex.particles_set_velocity(particles_id, i, 0.0, 0.0, 0.0)
end
gh_flex.particles_unmap_velocity(particles_id)
gh_flex.particles_unmap_position(particles_id)
-- Upload to GPU
gh_flex.solver_write_particles(solver_id, particles_id)
Unmaps the particles indices buffer.
This function has no return value(s).
gh_flex.particles_unmap_active_indices(particles_id)
Unmaps the particles phase buffer.
This function has no return value(s).
gh_flex.particles_unmap_phase(particles_id)
Unmaps the particles position buffer.
This function has no return value(s).
gh_flex.particles_unmap_position(particles_id)
Unmaps the particles velocity buffer.
This function has no return value(s).
gh_flex.particles_unmap_velocity(particles_id)
Updates all active particles in a single function.
This function has no return value(s).
gh_flex.particles_update_active(particles_id, num_active_particles)
-- particles_update_active() replaces the following code:
--
--[[
gh_flex.particles_set_num_active_indices(particles_id, num_vertices)
gh_flex.particles_map_active_indices(particles_id)
for i = 0, num_vertices - 1 do
gh_flex.particles_set_active_index(particles_id, i, i)
end
gh_flex.particles_unmap_active_indices(particles_id)
--]]
Sets the device index. This function allows to select a particular FleX GPU. Use -1 to auto-select the default PhysX accelerator in NVIDIA control panel.
This function has no return value(s).
gh_flex.set_device_index(-1)
Creates a set of collision shapes.
num_shapes = 2
shapes_id = gh_flex.shapes_create(num_shapes)
Destroys a set of shapes.
This function has no return value(s).
gh_flex.shapes_kill(shapes_id)
Maps a shapes buffer. That allows the CPU to writes to this buffer.
This function has no return value(s).
gh_flex.shapes_map(shapes_id)
Sets a box collision shape.
This function has no return value(s).
gh_flex.shapes_map(shapes_id)
shape_index = 0
shape_channels = eNvFlexPhaseShapeChannel0
width = 2.0
height = 2.0
depth = 2.0
gh_flex.shapes_set_box(shapes_id, shape_index, shape_channels, width, height, depth, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0)
gh_flex.shapes_unmap(shapes_id)
Sets a box collision shape.
This function has no return value(s).
gh_flex.shapes_map(shapes_id)
shape_index = 0
shape_channels = eNvFlexPhaseShapeChannel0
width = 2.0
height = 2.0
depth = 2.0
gh_flex.shapes_set_box_v2(shapes_id, shape_index, shape_channels, width, height, depth, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0)
gh_flex.shapes_unmap(shapes_id)
Sets a mesh collision shape.
This function has no return value(s).
gh_flex.shapes_map(shapes_id)
shape_index = 0
shape_channels = eNvFlexPhaseShapeChannel0
mesh_id = gh_mesh.create_torus(2.0, 0.4, 20)
gh_flex.shapes_set_mesh(shapes_id, shape_index, shape_channels, mesh_id, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0)
gh_flex.shapes_unmap(shapes_id)
Sets a mesh collision shape.
This function has no return value(s).
gh_flex.shapes_map(shapes_id)
shape_index = 0
shape_channels = eNvFlexPhaseShapeChannel0
mesh_id = gh_mesh.create_torus(2.0, 0.4, 20)
gh_flex.shapes_set_mesh_v2(shapes_id, shape_index, shape_channels, mesh_id, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0)
gh_flex.shapes_unmap(shapes_id)
Sets a sphere collision shape.
This function has no return value(s).
gh_flex.shapes_map(shapes_id)
shape_index = 0
shape_channels = eNvFlexPhaseShapeChannel0
radius = 2.0
gh_flex.shapes_set_sphere(shapes_id, shape_index, shape_channels, radius, 0.0, 3.0, 0.0)
gh_flex.shapes_unmap(shapes_id)
Unmaps the shapes buffer.
This function has no return value(s).
gh_flex.shapes_unmap(shapes_id)
Creates a FleX solver.
max_particles = 1000
solver_id = gh_flex.solver_create(max_particles)
Destroys a FleX solver.
This function has no return value(s).
gh_flex.solver_kill(solver_id)
Sets the number of active particles.
This function has no return value(s).
gh_flex.solver_set_num_active_particles(solver_id, num_active_particles)
Set a solver parameter.
This function has no return value(s).
params = [[
float radius; //!< The maximum interaction radius for particles
float solidRestDistance; //!< The distance non-fluid particles attempt to maintain from each other, must be in the range (0, radius]
float fluidRestDistance; //!< The distance fluid particles are spaced at the rest density, must be in the range (0, radius], for fluids this should generally be 50-70% of mRadius, for rigids this can simply be the same as the particle radius
// common params
float dynamicFriction; //!< Coefficient of friction used when colliding against shapes
float staticFriction; //!< Coefficient of static friction used when colliding against shapes
float particleFriction; //!< Coefficient of friction used when colliding particles
float restitution; //!< Coefficient of restitution used when colliding against shapes, particle collisions are always inelastic
float adhesion; //!< Controls how strongly particles stick to surfaces they hit, default 0.0, range [0.0, +inf]
float sleepThreshold; //!< Particles with a velocity magnitude < this threshold will be considered fixed
float maxSpeed; //!< The magnitude of particle velocity will be clamped to this value at the end of each step
float maxAcceleration; //!< The magnitude of particle acceleration will be clamped to this value at the end of each step (limits max velocity change per-second), useful to avoid popping due to large interpenetrations
float shockPropagation; //!< Artificially decrease the mass of particles based on height from a fixed reference point, this makes stacks and piles converge faster
float dissipation; //!< Damps particle velocity based on how many particle contacts it has
float damping; //!< Viscous drag force, applies a force proportional, and opposite to the particle velocity
// cloth params
float drag; //!< Drag force applied to particles belonging to dynamic triangles, proportional to velocity^2*area in the negative velocity direction
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
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
float vorticityConfinement; //!< Increases vorticity by applying rotational forces to particles
float anisotropyScale; //!< Control how much anisotropy is present in resulting ellipsoids for rendering, if zero then anisotropy will not be calculated, see NvFlexGetAnisotropy()
float anisotropyMin; //!< Clamp the anisotropy scale to this fraction of the radius
float anisotropyMax; //!< Clamp the anisotropy scale to this fraction of the radius
float smoothing; //!< Control the strength of Laplacian smoothing in particles for rendering, if zero then smoothed positions will not be calculated, see NvFlexGetSmoothParticles()
float solidPressure; //!< Add pressure from solid surfaces to particles
float freeSurfaceDrag; //!< Drag force applied to boundary fluid particles
float buoyancy; //!< Gravity is scaled by this value for fluid particles
// diffuse params
float diffuseThreshold; //!< Particles with kinetic energy + divergence above this threshold will spawn new diffuse particles
float diffuseBuoyancy; //!< Scales force opposing gravity that diffuse particles receive
float diffuseDrag; //!< Scales force diffuse particles receive in direction of neighbor fluid particles
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]
// 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
float shapeCollisionMargin; //!< Increases the radius used during contact finding against kinematic shapes
float relaxationFactor; //!< Control the convergence rate of the parallel solver, default: 1, values greater than 1 may lead to instability
]]
gh_flex.solver_set_param_1f(solver_id, "radius", 0.1)
gh_flex.solver_set_param_1f(solver_id, "dynamicFriction", 0.15)
Set a solver parameter.
This function has no return value(s).
params = [[
int numIterations; //!< Number of solver iterations to perform per-substep
int diffuseBallistic; //!< The number of neighbors below which a diffuse particle is considered ballistic
int numPlanes; //!< Num collision planes
]]
gh_flex.solver_set_param_1i(solver_id, "numIterations", 2)
Set a solver parameter.
This function has no return value(s).
params = [[
float gravity[3]; //!< Constant acceleration applied to all particles
// cloth params
float wind[3]; //!< Constant acceleration applied to particles that belong to dynamic triangles, drag needs to be > 0 for wind to affect triangles
]]
gh_flex.solver_set_param_1f(solver_id, "gravity", 0.0, -10.0, 0.0)
Set a collision plane (a particular solver parameter). FleX has a max 8 collision planes.
This function has no return value(s).
gh_flex.solver_set_param_1i(solver_id, "numPlanes", 1)
plane_index = 0
gh_flex.solver_set_param_collision_plane(solver_id, plane_index, 0.0, 1.0, 0.0, 0.0)
Updates a solver: runs the simulation.
This function has no return value(s).
substeps = 2
gh_flex.solver_update(solver_id, dt, substeps)
Writes params (update) to GPU.
This function has no return value(s).
gh_flex.solver_update_params(solver_id)
Sets / writes particles to GPU.
This function has no return value(s).
num_particles = 1000
particles_id = gh_flex.particles_create(num_particles)
...
gh_flex.solver_write_particles(solver_id, particles_id)
Sets / writes collision shapes to GPU.
This function has no return value(s).
num_shapes = 2
shapes_id = gh_flex.shapes_create(num_shapes)
...
gh_flex.solver_write_shapes(solver_id, shapes_id)
Starts the FleX engine. Must be called first. No-op if called twice.
This function has no input parameter(s).
flex_ok = gh_flex.start()
if (flex_ok == 0) then
-- error
end
Stops the FleX engine. Must be called at the end of the application (TERMINATE script is a good place).
This function has no input parameter(s).
state = gh_flex.stop()