Update vertex-data of meshes at runtime

Discussion in 'Modeling' started by wilbert pumacay, Jun 2, 2020.

  1. Hello all.
    Thanks for the great software. I'm currently having an issue while trying to update the vertex-data for a group of meshes. I'm trying to reuse the meshes to create some procedural terrain. So far, heightfields work great (I can update its height data and the collider is updated accordingly), but I'm having some issues with meshes when writing to model->mesh_vert and model->mesh_face. Below I've attached the desired result, which currently works ok using Bullet instead of MuJoCo (see results_bullet.gif).
    results_bullet.gif

    Notice that in this example, the single bodies start with some mesh-collider, and once I press some key the vertex-data for all colliders is changed in a round-robin fashion. Unfortunately, I've tried for MuJoCo and still can't make this work. The results I've got so far with MuJoCo are shown below (see results_mujoco.gif)
    results_mujoco.gif

    I thought that the issue might be related to the mesh-geoms having a fixed number of vertices, as the data is preallocated during model compilation. However, I tried a similar example, and instead of changing to vertex-data that had different sizes (different shapes) I changed to the same shape instead, but still got artifacts during simulation. See the gif shown below for the results of this test (see results_mujoco_same_data.gif)
    results_mujoco_same_data.gif

    Notice that two of the mesh-geoms work ok after changing the vertex-data, but the other two just stop working properly, even though I'm updating the same vertex-data to all four of them (writing to mesh_vert and mesh_face). I also notice that the vertices in mesh_vert are different from the vertices I supply during construction (the tetrahedron vertices), which seems to be the results of computing the principal axes of inertia of the mesh-geom, and then transforming the vertices to this frame (should I take into account this transformation while writing to mesh_vert?).

    My question is: Is it possible to change at runtime the vertex-data of mesh-geom colliders?. Perhaps it's possible using mesh_vert and mesh_face with care and maybe I'm making some silly mistakes while writing to these fields, or perhaps it's not possible due to the mesh-geom being preprocessed during model compilation (perhaps I could reproduce the same preprocessing steps to get the behaviour I require?).

    Below is a snippet of the code I'm using to update the mesh_vert and mesh_face fields (vertices and faces are std::vector<float> and std::vector<int> containers with the vertices data and indices data respectively, and the data is stored with the following layout: vertices-> [(v0x v0y v0z) (v1x v1y v1z) ...(tri-verts)...], faces->[(v00 v01 v02) (v10 v11 v12) ...(tri-indices)...]). Notice that I'm also updating the rbound based on the AABB of the mesh-geom :

    Code:
            const ssize_t num_vertices = vertices.size() / 3;
            const ssize_t num_faces = faces.size() / 3;
    
            TVec3 aabb_min = { 1e6f, 1e6f, 1e6f };
            TVec3 aabb_max = { -1e6f, -1e6f, -1e6f };
            m_mjcModelRef->mesh_vertnum[m_mjcGeomMeshId] = num_vertices;
            for ( ssize_t i = 0; i < num_vertices; i++ )
            {
                m_mjcModelRef->mesh_vert[m_mjcGeomMeshVertStartAddr + 3 * i + 0] = vertices[3 * i + 0];
                m_mjcModelRef->mesh_vert[m_mjcGeomMeshVertStartAddr + 3 * i + 1] = vertices[3 * i + 1];
                m_mjcModelRef->mesh_vert[m_mjcGeomMeshVertStartAddr + 3 * i + 2] = vertices[3 * i + 2];
    
                aabb_min.x() = std::min( aabb_min.x(), m_mjcModelRef->mesh_vert[m_mjcGeomMeshVertStartAddr + 3 * i + 0] );
                aabb_min.y() = std::min( aabb_min.y(), m_mjcModelRef->mesh_vert[m_mjcGeomMeshVertStartAddr + 3 * i + 1] );
                aabb_min.z() = std::min( aabb_min.z(), m_mjcModelRef->mesh_vert[m_mjcGeomMeshVertStartAddr + 3 * i + 2] );
    
                aabb_max.x() = std::max( aabb_max.x(), m_mjcModelRef->mesh_vert[m_mjcGeomMeshVertStartAddr + 3 * i + 0] );
                aabb_max.y() = std::max( aabb_max.y(), m_mjcModelRef->mesh_vert[m_mjcGeomMeshVertStartAddr + 3 * i + 1] );
                aabb_max.z() = std::max( aabb_max.z(), m_mjcModelRef->mesh_vert[m_mjcGeomMeshVertStartAddr + 3 * i + 2] );
            }
            m_mjcModelRef->geom_rbound[m_mjcGeomId] = 0.5f * ( aabb_max - aabb_min ).length();
    
            m_mjcModelRef->mesh_facenum[m_mjcGeomMeshId] = num_faces;
            for ( ssize_t i = 0; i < num_faces; i++ )
            { 
                m_mjcModelRef->mesh_face[m_mjcGeomMeshVertStartAddr + 3 * i + 0] = faces[3 * i + 0];
                m_mjcModelRef->mesh_face[m_mjcGeomMeshVertStartAddr + 3 * i + 1] = faces[3 * i + 1];
                m_mjcModelRef->mesh_face[m_mjcGeomMeshVertStartAddr + 3 * i + 2] = faces[3 * i + 2];
            }
    Thanks in advance,
    Wilbert