NVIDIA / warp

A Python framework for high performance GPU simulation and graphics
https://nvidia.github.io/warp/
Other
4.24k stars 241 forks source link

Alternative tetmesh format #198

Closed honglin-c closed 5 months ago

honglin-c commented 7 months ago

Would it be possible to provide an example where the user reads a tetmesh from a .mesh file? Thank you! :)

honglin-c commented 7 months ago

I was using the following code (with libigl python binding) to load the tetmesh, which was unsuccessful so far.

  V, T, F = igl.read_mesh("./data/tetmesh/spot.mesh")

  V = Vt.Vec3fArray.FromNumpy(V)
  T = Vt.IntArray.FromNumpy(T)

  builder.add_soft_mesh(
      pos=wp.vec3(0.0, 2.0, 0.0),
      rot=wp.quat_identity(),
      scale=0.1,
      vel=wp.vec3(0.0, 0.0, 0.0),
      vertices=V, 
      indices=T, 
      density=100.0, 
      k_mu=2000.0, 
      k_lambda=2000.0, 
      k_damp=2.0,
      tri_ke=0.0,
      tri_ka=1e4,
      tri_kd=0.0,
      tri_drag=0.0,
      tri_lift=0.0,
  )

image

mmacklin commented 7 months ago

Hi @honglin-c, could you provide the .mesh file for this example so we can reproduce?

Thanks, Miles

samuelpmish commented 7 months ago

I'm guessing it's this mesh: https://github.com/honglin-c/INSR-PDE/blob/main/elasticity/data/spot.mesh

download link: spot.zip

I tried writing a minimal reproducer with @honglin-c 's approach

import os
import math

import warp as wp
import warp.examples
import warp.sim
import warp.optim
import warp.sim.render

import igl
import scipy as sp
import numpy as np
from pxr import Usd, UsdGeom, Vt

wp.init()

# sim model
builder = wp.sim.ModelBuilder()

V, T, F = igl.read_mesh("/path/to/meshes/spot.mesh")

V = Vt.Vec3fArray.FromNumpy(V)
T = Vt.IntArray.FromNumpy(T)

builder.add_soft_mesh(
    pos=wp.vec3(0.0, 0.0, 0.0),
    rot=wp.quat_identity(),
    scale=2.0,
    vel=wp.vec3(0.0, 0.0, 0.0),
    vertices=V,
    indices=T,
    density=1.0,
    k_mu=2000.0,
    k_lambda=2000.0,
    k_damp=2.0,
    tri_ke=0.0,
    tri_ka=1e-8,
    tri_kd=0.0,
    tri_drag=0.0,
    tri_lift=0.0,
)

# finalize model
model = builder.finalize(requires_grad=False)

model.soft_contact_ke = 2.0e3
model.soft_contact_kd = 0.1
model.soft_contact_kf = 10.0
model.soft_contact_mu = 0.7

model.ground = True

state = model.state(requires_grad=False)

# rendering
renderer = wp.sim.render.SimRenderer(model, "spot.usd")

renderer.begin_frame(0)
renderer.render(state)
renderer.end_frame()

renderer.save()

and it seemed to work: Screenshot from 2024-04-09 08-24-03

But I'm very new to using warp, so I might be doing something wrong!

mmacklin commented 7 months ago

Nice! Thank you @samuelpmish! @honglin-c does this solve your problem?

honglin-c commented 7 months ago

Wowww thank you so much @samuelpmish!! :)))

honglin-c commented 7 months ago

Nice! Thank you @samuelpmish! @honglin-c does this solve your problem?

Sort of but not fully 👀

Actually, I realized the problem was with the simulation and the scale of the tetmesh.

For instance, I will have this problem for the code below. But if I simply change scale=5.0 to scale=10.0 in the parameter list of builder.add_soft_mesh(), the simulation will run without problem.

Still trying to figure out what's going wrong here... 🤔

import math
import os

import warp as wp
import warp.sim
import warp.sim.render

import numpy as np
from pxr import Usd, UsdGeom, Vt

import igl

wp.init()

class Example:
    def __init__(self, stage):
        sim_fps = 60.0
        self.sim_substeps = 64
        sim_duration = 5.0
        self.sim_frames = int(sim_duration * sim_fps)
        self.frame_dt = 1.0 / sim_fps
        self.sim_dt = (1.0 / sim_fps) / self.sim_substeps
        self.sim_time = 0.0

        # bunny
        builder = wp.sim.ModelBuilder()

        V, T, F = igl.read_mesh("./data/tetmesh/spot.mesh")

        # don't know why warp needs this
        V = Vt.Vec3fArray.FromNumpy(V)
        T = Vt.IntArray.FromNumpy(T)

        builder.add_soft_mesh(
            pos=wp.vec3(0.0, 10.0, 0.0),
            rot=wp.quat_identity(),
            scale=5.0,
            vel=wp.vec3(0.0, 0.0, 0.0),
            vertices=V, 
            indices=T, 
            density=100.0, 
            k_mu=100000.0, 
            k_lambda=100000.0, 
            k_damp=2.0,
            tri_ke=0.0,
            tri_ka=1e4,
            tri_kd=0.0,
            tri_drag=0.0,
            tri_lift=0.0,
        )

        self.model = builder.finalize()
        self.model.ground = True

        self.model.soft_contact_ke = 2.0e3
        self.model.soft_contact_kd = 0.1
        self.model.soft_contact_kf = 10.0
        self.model.soft_contact_mu = 0.7

        self.integrator = wp.sim.SemiImplicitIntegrator()

        self.rest = self.model.state()

        self.state_0 = self.model.state()
        self.state_1 = self.model.state()

        self.volume = wp.zeros(1, dtype=wp.float32)

        self.renderer = None
        if stage:
            self.renderer = wp.sim.render.SimRenderer(self.model, stage)

        self.use_graph = wp.get_device().is_cuda
        if self.use_graph:
            with wp.ScopedCapture() as capture:
                self.simulate()
            self.graph = capture.graph

    def simulate(self):
        for _ in range(self.sim_substeps):
            self.state_0.clear_forces()
            # self.state_1.clear_forces()

            self.integrator.simulate(self.model, self.state_0, self.state_1, self.sim_dt)

            # swap states
            (self.state_0, self.state_1) = (self.state_1, self.state_0)

    def step(self):
        with wp.ScopedTimer("step"):
            if self.use_graph:
                wp.capture_launch(self.graph)
            else:
                self.simulate()

        self.sim_time += self.frame_dt

    def render(self):
        if self.renderer is None:
            return

        with wp.ScopedTimer("render"):
            self.renderer.begin_frame(self.sim_time)
            self.renderer.render(self.state_0)
            self.renderer.end_frame()

if __name__ == "__main__":
    stage_path = os.path.join(os.path.dirname(__file__), "outputs/example_soft_spot.usd")

    example = Example(stage_path)

    for i in range(example.sim_frames):
        example.step()
        example.render()

    if example.renderer:
        example.renderer.save()
honglin-c commented 7 months ago

This is with scale = 5.0:

image

Without the simulation (I commented out example.step()) , the rendering looks fine:

image
honglin-c commented 7 months ago

But if I simply change scale=5.0 to scale=10.0 in builder.add_soft_mesh(), the simulation just runs perfectly! :0

I'm having a mesh colliding with the ground and then bouncing back :

image image image
mmacklin commented 7 months ago

This is probably just a classic example of simulation stability being dependent on the scale, e.g.: by scaling everything down then everything gets lighter while stiffness is staying the same, i.e.: the problem got a lot stiffer, which means you need smaller time-steps to be stable.

If you are reducing scale you generally need to reduce the time-step size (dt) or take more substeps as well.

Cheers, Miles

honglin-c commented 7 months ago

Thank you so much for the explanations! Now I finally understand. :)

shi-eric commented 5 months ago

Resolved by @samuelpmish