qbhf2's picture
added NvidiaWarp and GarmentCode repos
66c9c8a
# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved.
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, 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.
import warp as wp
from .model import PARTICLE_FLAG_ACTIVE
@wp.func
def particle_force(n: wp.vec3, v: wp.vec3, c: float, k_n: float, k_d: float, k_f: float, k_mu: float):
vn = wp.dot(n, v)
jn = c * k_n
jd = min(vn, 0.0) * k_d
# contact force
fn = jn + jd
# friction force
vt = v - n * vn
vs = wp.length(vt)
if vs > 0.0:
vt = vt / vs
# Coulomb condition
ft = wp.min(vs * k_f, k_mu * wp.abs(fn))
# total force
return -n * fn - vt * ft
@wp.kernel
def eval_particle_forces_kernel(
grid: wp.uint64,
particle_x: wp.array(dtype=wp.vec3),
particle_v: wp.array(dtype=wp.vec3),
particle_radius: wp.array(dtype=float),
particle_flags: wp.array(dtype=wp.uint32),
k_contact: float,
k_damp: float,
k_friction: float,
k_mu: float,
k_cohesion: float,
max_radius: float,
# outputs
particle_f: wp.array(dtype=wp.vec3),
):
tid = wp.tid()
# order threads by cell
i = wp.hash_grid_point_id(grid, tid)
if i == -1:
# hash grid has not been built yet
# if tid == 0:
# print("hash grid has not been built yet")
return
if (particle_flags[i] & PARTICLE_FLAG_ACTIVE) == 0:
return
x = particle_x[i]
v = particle_v[i]
radius = particle_radius[i]
f = wp.vec3()
# particle contact
query = wp.hash_grid_query(grid, x, radius + max_radius + k_cohesion)
index = int(0)
count = int(0)
while wp.hash_grid_query_next(query, index):
if (particle_flags[index] & PARTICLE_FLAG_ACTIVE) != 0 and index != i:
# compute distance to point
n = x - particle_x[index]
d = wp.length(n)
err = d - radius - particle_radius[index]
count += 1
if err <= k_cohesion:
n = n / d
vrel = v - particle_v[index]
f = f + particle_force(n, vrel, err, k_contact, k_damp, k_friction, k_mu)
particle_f[i] = f
def eval_particle_forces(model, state, forces):
if model.particle_max_radius > 0.0:
wp.launch(
kernel=eval_particle_forces_kernel,
dim=model.particle_count,
inputs=[
model.particle_grid.id,
state.particle_q,
state.particle_qd,
model.particle_radius,
model.particle_flags,
model.particle_ke,
model.particle_kd,
model.particle_kf,
model.particle_mu,
model.particle_cohesion,
model.particle_max_radius,
],
outputs=[forces],
device=model.device,
)