NvidiaWarp-GarmentCode icon indicating copy to clipboard operation
NvidiaWarp-GarmentCode copied to clipboard

About resolving collision only

Open phphuc612 opened this issue 8 months ago • 1 comments

Hi @maria-korosteleva , My case is that I'd like to re-simulate the generated mesh to resolve only the collision between the body and cloth object. I saw that it was fine to re-simulate the generated sim mesh from your GarmentCode. However, when I load my own cloth mesh for simulation, the mesh tends to oscillate. This issue becomes even more severe with high-resolution meshes (e.g., those with over 100k vertices).

My question is: Do I need to modify the cloth .obj file to follow a specific format for simulation? For instance, should all vertices on the panel boundary be placed at the beginning of the file?

My inputs are the simulated cloth mesh and the body mesh. The "re-simulation" process involves two modifications:

FIRST: I loaded directly the mesh (instead of boxmesh) by modifying build_stage function from garment.py. I omitted all related to boxmesh, segmentation files. (Please find CHANGE HERE to get to the modifications)

   def build_stage(self, config):

        builder = wp.sim.ModelBuilder(gravity=0.0)
        # --------------- Load body info -----------------
        body_vertices, body_indices, body_faces = self.load_obj(
            self.body_path)

        body_vertices = body_vertices * self.b_scale
        self.shift_y = self.get_shift_param(body_vertices)

        if self.shift_y:
            body_vertices[:, 1] = body_vertices[:, 1] + self.shift_y

        self.v_body = body_vertices
        self.f_body = body_faces
        self.body_indices = body_indices

        # -------------- Load cloth ------------
        # CHANGE HERE - load simulated mesh instead of boxmesh
        gt_sim_path = Path(self.draped_garment_path)
        cloth_vertices, cloth_indices, cloth_faces = self.load_obj(
            gt_sim_path)
        cloth_vertices = cloth_vertices * self.c_scale
        if self.shift_y:
            cloth_vertices[:, 1] = cloth_vertices[:, 1] + self.shift_y
        self.v_cloth_init = cloth_vertices
        self.f_cloth = cloth_faces

        cloth_pos = (0.0, 0.0, 0.0)
        # no rotation, but orientation of cloth in world space
        cloth_rot = wp.quat_from_axis_angle(
            wp.vec3(0.0, 1.0, 0.0), wp.degrees(0.0))

        builder.add_cloth_mesh_sewing_spring(
            pos=cloth_pos,
            rot=cloth_rot,
            scale=1.0,
            vel=(0.0, 0.0, 0.0),
            vertices=cloth_vertices,
            indices=cloth_indices,
            resolution_scale=config.resolution_scale,
            # orig_lens=orig_lens_dict, # CHANGE HERE
            # stitching_vertices=stitching_vertices, # CHANGE HERE
            stitching_vertices=[], 
            density=config.garment_density,
            edge_ke=config.garment_edge_ke,
            edge_kd=config.garment_edge_kd,
            tri_ke=config.garment_tri_ke,
            tri_ka=config.garment_tri_ka,
            tri_kd=config.garment_tri_kd,
            tri_drag=config.garment_tri_drag,
            tri_lift=config.garment_tri_lift,
            radius=config.garment_radius,
            add_springs=True,
            spring_ke=config.spring_ke,
            spring_kd=config.spring_kd,
        )

        # ------------ Add a body -----------
        self.body_mesh = wp.sim.Mesh(body_vertices, body_indices)

        body_pos = wp.vec3(0.0, 0, 0.0)
        body_rot = wp.quat_from_axis_angle(
            wp.vec3(0.0, 1.0, 0.0), wp.degrees(0.0))

        self.body_shape_index = 0   # Body is the first collider object to be added
        builder.add_shape_mesh(
            body=-1,
            mesh=self.body_mesh,
            pos=body_pos,
            rot=body_rot,
            scale=wp.vec3(1.0, 1.0, 1.0),  # performed body scaling above
            thickness=config.body_thickness,
            mu=config.body_friction,
            face_filters=[[]],
            model_particle_filter_ids=[],
        )

        # ------- Finalize --------------
        # data is transferred to warp tensors, object used in simulation
        self.model: wp.sim.Model = builder.finalize(device=self.device)

SECOND: I turned off enable_global_collision_filter and enable_cloth_reference_drag in the simulation config default_sim_props.yaml.

This is the result I got: Original mesh: Image

Re-simulated mesh Image

The re-simulated mesh (if I increase the resolution of original mesh to 100k vertices) Image

My object file is here: sample.zip

phphuc612 avatar May 10 '25 14:05 phphuc612

@phphuc612, this is quite difficult. Unfortunately, the simulation is very sensitive to various aspects of the setup, so it's hard to immediately suggest which thing (or things) went wrong to give this result. The best I can advise here is to start from the beginning and add your changes one by one, making sure each step yields reasonable behavior.

One thing I see is that you are not using the stitching capabilities of the cloth mesh setup. I'd recommend using the regular add_cloth_mesh function instead of add_cloth_mesh_sewing_spring. We didn't extensively test if the latter works correctly when sewing information is empty, so it could be buggy. Try it, maybe this will be an easy fix =)

And no, there is no specific OBJ format we expect as long as it's readable by libigl, and it's consistent with the labeling (e.g. orig_length), which you don't use anyway

maria-korosteleva avatar May 19 '25 20:05 maria-korosteleva