Skip to content

Commit ba9a650

Browse files
haroonqcopybara-github
authored andcommitted
Allow mesh data to be reuploaded without having to recreate the mesh.
Splits mjrfMeshData into config+data parts. PiperOrigin-RevId: 952042545 Change-Id: I19a572a0f591fa0d33bbc2c32b974efc075310f4
1 parent d3166cb commit ba9a650

19 files changed

Lines changed: 452 additions & 304 deletions

File tree

‎doc/APIreference/APItypes.rst‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1452,12 +1452,22 @@ culling. Alternatively, the bounds can be computed at runtime (though there is a
14521452
are provided (or calculated), then frustum culling will not be performed.
14531453

14541454

1455+
.. _mjrfMeshConfig:
1456+
1457+
mjrfMeshConfig
1458+
~~~~~~~~~~~~~~~~~
1459+
1460+
Parameters for creating a :ref:`mesh<mjrfMesh>`.
1461+
1462+
.. mujoco-include:: mjrfMeshConfig
1463+
1464+
14551465
.. _mjrfMeshData:
14561466

14571467
mjrfMeshData
14581468
~~~~~~~~~~~~
14591469

1460-
Binary data used for creating a :ref:`mesh<mjrfMesh>`.
1470+
Binary data for a :ref:`mesh<mjrfMesh>`.
14611471

14621472
.. mujoco-include:: mjrfMeshData
14631473

‎doc/APIreference/functions.rst‎

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3249,14 +3249,14 @@ Returns the height of the texture.
32493249
Returns the sampler type (mjrSamplerType) used by the texture.
32503250
[returns: mjrSamplerType]
32513251

3252-
.. _mjrf_defaultMeshData:
3252+
.. _mjrf_defaultMeshConfig:
32533253

3254-
`mjrf_defaultMeshData <#mjrf_defaultMeshData>`__
3255-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3254+
`mjrf_defaultMeshConfig <#mjrf_defaultMeshConfig>`__
3255+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
32563256

3257-
.. mujoco-include:: mjrf_defaultMeshData
3257+
.. mujoco-include:: mjrf_defaultMeshConfig
32583258

3259-
Initializes the mjrfMeshData to default values.
3259+
Initializes the mjrfMeshConfig to default values.
32603260

32613261
.. _mjrf_createMesh:
32623262

@@ -3265,7 +3265,7 @@ Initializes the mjrfMeshData to default values.
32653265

32663266
.. mujoco-include:: mjrf_createMesh
32673267

3268-
Creates a mesh with the given data.
3268+
Creates an empty mesh with the given config.
32693269

32703270
.. _mjrf_destroyMesh:
32713271

@@ -3276,6 +3276,24 @@ Creates a mesh with the given data.
32763276

32773277
Destroys the mesh.
32783278

3279+
.. _mjrf_defaultMeshData:
3280+
3281+
`mjrf_defaultMeshData <#mjrf_defaultMeshData>`__
3282+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3283+
3284+
.. mujoco-include:: mjrf_defaultMeshData
3285+
3286+
Initializes the mjrfMeshData to default values.
3287+
3288+
.. _mjrf_setMeshData:
3289+
3290+
`mjrf_setMeshData <#mjrf_setMeshData>`__
3291+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3292+
3293+
.. mujoco-include:: mjrf_setMeshData
3294+
3295+
Uploads the given mesh data to the mesh.
3296+
32793297
.. _mjrf_defaultSceneParams:
32803298

32813299
`mjrf_defaultSceneParams <#mjrf_defaultSceneParams>`__

‎doc/changelog.rst‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ Engine
6666
- :ref:`mju_round` now breaks ties away from zero rather than towards :math:`+\infty`. This only affects
6767
negative half-integers, e.g. ``mju_round(-2.5)`` now returns -3 rather than -2.
6868
- Removed unneeded `mjvScene` argument from :ref:`mjv_moveCamera`.
69+
- Split up :ref:`mjrfMeshData` into `mjrfMeshData` and `mjrfMeshConfig` to allow reuploading of mesh data without
70+
having to recreate the mesh object. Introduces :ref:`mjrfDefaultMeshConfig` and :ref:`mjrfSetMeshData` functions.
71+
- Removed `bytes` field from :ref:`mjrVertexAttribute`.
6972

7073
.. admonition:: Breaking ABI changes
7174
:class: caution

‎doc/includes/references.h‎

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,7 +1425,6 @@ typedef struct mjrRendererInfo_ { // active renderer identity
14251425
const char* backend; // graphics backend: opengl, vulkan; empty if uninitialized
14261426
} mjrRendererInfo;
14271427
typedef struct mjrVertexAttribute_ { // vertex attribute format specification
1428-
const void* bytes; // vertex data
14291428
int usage; // position, normal, etc [mjrVertexAttributeUsage]
14301429
int type; // float3, ubyte4, etc. [mjrVertexAttributeType]
14311430
} mjrVertexAttribute;
@@ -1580,15 +1579,20 @@ typedef struct mjrfTextureData_ {
15801579
mjrfCallback release; // callback when data has finished uploading
15811580
void* user_data; // user data for release callback
15821581
} mjrfTextureData;
1583-
typedef struct mjrfMeshData_ {
1584-
mjtSize num_vertices; // number of vertices; all vertex attributes share this size
1585-
int num_attributes; // number of attributes defined
1582+
typedef struct mjrfMeshConfig_ {
1583+
mjtSize max_vertices; // maximum number of vertices
1584+
mjtSize max_indices; // maximum number of indices
1585+
int num_attributes; // number of defined attributes
15861586
mjrVertexAttribute attributes[mjMAX_VERTEX_ATTRIBUTES]; // per-vertex attribute information
15871587
mjtBool interleaved; // true if vertex attributes are interleaved
1588-
mjtSize num_indices; // number of indices
1589-
const void* indices; // indices data array
15901588
int index_type; // index data format (e.g. UINT16 or UINT32) [mjrIndexType]
15911589
int primitive_type; // index interpretation (e.g. TRIANGLES, etc.) [mjrMeshPrimitiveType]
1590+
} mjrfMeshConfig;
1591+
typedef struct mjrfMeshData_ {
1592+
mjtSize num_vertices; // number of vertices
1593+
const void* vertices[mjMAX_VERTEX_ATTRIBUTES]; // per-vertex attribute data arrays
1594+
mjtSize num_indices; // number of indices
1595+
const void* indices; // indices data array
15921596
mjtBool compute_bounds; // if true, compute bounds from vertex positions
15931597
float bounds_min[3]; // min/max bounds; assume unset if bounds_min == bounds_max
15941598
float bounds_max[3];
@@ -3422,9 +3426,11 @@ void mjrf_setTextureData(mjrfTexture* texture, const mjrfTextureData* data);
34223426
int mjrf_getTextureWidth(const mjrfTexture* texture);
34233427
int mjrf_getTextureHeight(const mjrfTexture* texture);
34243428
int mjrf_getTextureSamplerType(const mjrfTexture* texture);
3425-
void mjrf_defaultMeshData(mjrfMeshData* data);
3426-
mjrfMesh* mjrf_createMesh(mjrfContext* ctx, const mjrfMeshData* data);
3429+
void mjrf_defaultMeshConfig(mjrfMeshConfig* config);
3430+
mjrfMesh* mjrf_createMesh(mjrfContext* ctx, const mjrfMeshConfig* config);
34273431
void mjrf_destroyMesh(mjrfMesh* mesh);
3432+
void mjrf_defaultMeshData(mjrfMeshData* data);
3433+
void mjrf_setMeshData(mjrfMesh* mesh, const mjrfMeshData* data);
34283434
void mjrf_defaultSceneParams(mjrfSceneParams* params);
34293435
mjrfScene* mjrf_createScene(mjrfContext* ctx, const mjrfSceneParams* params);
34303436
void mjrf_destroyScene(mjrfScene* scene);

‎include/mujoco/mjrender.h‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ typedef struct mjrRendererInfo_ { // active renderer identity
124124

125125

126126
typedef struct mjrVertexAttribute_ { // vertex attribute format specification
127-
const void* bytes; // vertex data
128127
int usage; // position, normal, etc [mjrVertexAttributeUsage]
129128
int type; // float3, ubyte4, etc. [mjrVertexAttributeType]
130129
} mjrVertexAttribute;

‎include/mujoco/mjrfilament.h‎

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -182,16 +182,32 @@ int mjrf_getTextureSamplerType(const mjrfTexture* texture);
182182
// Maximum number of vertex attributes in a mesh.
183183
enum { mjMAX_VERTEX_ATTRIBUTES = 16 };
184184

185-
// Binary data used for creating a mesh (mjrfMesh).
186-
typedef struct mjrfMeshData_ {
187-
mjtSize num_vertices; // number of vertices; all vertex attributes share this size
188-
int num_attributes; // number of attributes defined
185+
// Parameters describing a mesh (mjrfMesh).
186+
typedef struct mjrfMeshConfig_ {
187+
mjtSize max_vertices; // maximum number of vertices
188+
mjtSize max_indices; // maximum number of indices
189+
int num_attributes; // number of defined attributes
189190
mjrVertexAttribute attributes[mjMAX_VERTEX_ATTRIBUTES]; // per-vertex attribute information
190191
mjtBool interleaved; // true if vertex attributes are interleaved
191-
mjtSize num_indices; // number of indices
192-
const void* indices; // indices data array
193192
int index_type; // index data format (e.g. UINT16 or UINT32) [mjrIndexType]
194193
int primitive_type; // index interpretation (e.g. TRIANGLES, etc.) [mjrMeshPrimitiveType]
194+
} mjrfMeshConfig;
195+
196+
// Initializes the mjrfMeshConfig to default values.
197+
void mjrf_defaultMeshConfig(mjrfMeshConfig* config);
198+
199+
// Creates an empty mesh with the given config.
200+
mjrfMesh* mjrf_createMesh(mjrfContext* ctx, const mjrfMeshConfig* config);
201+
202+
// Destroys the mesh.
203+
void mjrf_destroyMesh(mjrfMesh* mesh);
204+
205+
// Binary data used for creating a mesh (mjrfMesh).
206+
typedef struct mjrfMeshData_ {
207+
mjtSize num_vertices; // number of vertices
208+
const void* vertices[mjMAX_VERTEX_ATTRIBUTES]; // per-vertex attribute data arrays
209+
mjtSize num_indices; // number of indices
210+
const void* indices; // indices data array
195211
mjtBool compute_bounds; // if true, compute bounds from vertex positions
196212
float bounds_min[3]; // min/max bounds; assume unset if bounds_min == bounds_max
197213
float bounds_max[3];
@@ -202,11 +218,8 @@ typedef struct mjrfMeshData_ {
202218
// Initializes the mjrfMeshData to default values.
203219
void mjrf_defaultMeshData(mjrfMeshData* data);
204220

205-
// Creates a mesh with the given data.
206-
mjrfMesh* mjrf_createMesh(mjrfContext* ctx, const mjrfMeshData* data);
207-
208-
// Destroys the mesh.
209-
void mjrf_destroyMesh(mjrfMesh* mesh);
221+
// Uploads the given mesh data to the mesh.
222+
void mjrf_setMeshData(mjrfMesh* mesh, const mjrfMeshData* data);
210223

211224
// Parameters for creating a scene (mjrfScene).
212225
typedef struct mjrfSceneParams_ {

‎python/mujoco/introspect/structs.py‎

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11332,13 +11332,6 @@
1133211332
name='mjrVertexAttribute',
1133311333
declname='struct mjrVertexAttribute_',
1133411334
fields=(
11335-
StructFieldDecl(
11336-
name='bytes',
11337-
type=PointerType(
11338-
inner_type=ValueType(name='void', is_const=True),
11339-
),
11340-
doc='vertex data',
11341-
),
1134211335
StructFieldDecl(
1134311336
name='usage',
1134411337
type=ValueType(name='int'),

‎python/mujoco/structs.cc‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1078,7 +1078,7 @@ This is useful for example when the MJB is not available as a file on disk.)"));
10781078
py::class_<raw::MjrVertexAttribute> mjrVertexAttribute(m,
10791079
"MjrVertexAttribute");
10801080
mjrVertexAttribute.def(py::init([](int usage, int type) {
1081-
return raw::MjrVertexAttribute{nullptr, usage, type};
1081+
return raw::MjrVertexAttribute{usage, type};
10821082
}),
10831083
py::arg("usage") = 0, py::arg("type") = 0);
10841084
mjrVertexAttribute.def("__copy__", [](const raw::MjrVertexAttribute& other) {

‎src/experimental/filament/compat/scene_decorator.cc‎

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -243,27 +243,35 @@ void SceneDecorator::Update(mjData* data, const mjvOption* vis_option,
243243
const float* uvs =
244244
has_uvs ? mjv_scene_.flextexcoord + (6 * addr) : nullptr;
245245

246+
mjrfMeshConfig config;
247+
mjrf_defaultMeshConfig(&config);
248+
config.num_attributes = has_uvs ? 3 : 2;
249+
config.max_vertices = 3 * mjv_scene_.flexfaceused[geom.objid];
250+
config.max_indices = 3 * mjv_scene_.flexfaceused[geom.objid];
251+
config.attributes[0].usage = mjVERTEX_ATTRIBUTE_USAGE_POSITION;
252+
config.attributes[0].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3;
253+
config.attributes[1].usage = mjVERTEX_ATTRIBUTE_USAGE_NORMAL;
254+
config.attributes[1].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3;
255+
config.attributes[2].usage = mjVERTEX_ATTRIBUTE_USAGE_UV;
256+
config.attributes[2].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT2;
257+
config.index_type = mjINDEX_TYPE_U32;
258+
config.primitive_type = mjMESH_PRIMITIVE_TYPE_TRIANGLES;
259+
246260
mjrfMeshData data;
247261
mjrf_defaultMeshData(&data);
248-
data.num_attributes = has_uvs ? 3 : 2;
249-
data.attributes[0].usage = mjVERTEX_ATTRIBUTE_USAGE_POSITION;
250-
data.attributes[0].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3;
251-
data.attributes[0].bytes = positions;
252-
data.attributes[1].usage = mjVERTEX_ATTRIBUTE_USAGE_NORMAL;
253-
data.attributes[1].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3;
254-
data.attributes[1].bytes = normals;
255-
data.attributes[2].usage = mjVERTEX_ATTRIBUTE_USAGE_UV;
256-
data.attributes[2].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT2;
257-
data.attributes[2].bytes = uvs;
262+
data.vertices[0] = positions;
263+
data.vertices[1] = normals;
264+
data.vertices[2] = uvs;
258265
data.num_vertices = 3 * mjv_scene_.flexfaceused[geom.objid];
259266
data.num_indices = 3 * mjv_scene_.flexfaceused[geom.objid];
260267
data.indices = nullptr;
261-
data.index_type = mjINDEX_TYPE_U32;
262-
data.primitive_type = mjMESH_PRIMITIVE_TYPE_TRIANGLES;
263268
data.compute_bounds = true;
264269
data.release = nullptr;
265270
data.user_data = nullptr;
266-
meshes_.push_back(CreateMesh(ctx, data));
271+
272+
auto mesh = CreateMesh(ctx, config);
273+
mjrf_setMeshData(mesh.get(), &data);
274+
meshes_.push_back(std::move(mesh));
267275

268276
auto renderable = CreateRenderable(ctx, params);
269277
mjrf_setRenderableMesh(renderable.get(), meshes_.back().get(), 0, 0);

‎src/experimental/filament/compat/scene_objects.cc‎

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,11 @@ static std::span<const int> GetIndices(const mjModel* model,
103103
}
104104
}
105105

106-
static bool UpdateSkinFlexMeshData(mjrfMeshData* data, const mjModel* model,
107-
const mjvScene* scene, const mjvGeom& geom) {
106+
SceneObjects::SceneObjects(mjrfContext* ctx) : ctx_(ctx) {}
107+
108+
bool SceneObjects::CreateSkinFlexMesh(const mjvScene* scene,
109+
const mjModel* model,
110+
const mjvGeom& geom) {
108111
auto positions = GetPositions(model, scene, geom);
109112
if (positions.empty()) {
110113
return false;
@@ -119,41 +122,44 @@ static bool UpdateSkinFlexMeshData(mjrfMeshData* data, const mjModel* model,
119122
num_indices = 3 * scene->flexfaceused[geom.objid];
120123
}
121124

122-
data->num_attributes = uvs.data() ? 3 : 2;
123-
data->attributes[0].usage = mjVERTEX_ATTRIBUTE_USAGE_POSITION;
124-
data->attributes[0].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3;
125-
data->attributes[0].bytes = positions.data();
126-
data->attributes[1].usage = mjVERTEX_ATTRIBUTE_USAGE_NORMAL;
127-
data->attributes[1].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3;
128-
data->attributes[1].bytes = normals.data();
129-
data->attributes[2].usage = mjVERTEX_ATTRIBUTE_USAGE_UV;
130-
data->attributes[2].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT2;
131-
data->attributes[2].bytes = uvs.data();
132-
data->num_vertices = positions.size() / 3;
133-
data->num_indices = num_indices;
134-
data->indices = indices.data();
135-
data->index_type = mjINDEX_TYPE_U32;
136-
data->primitive_type = mjMESH_PRIMITIVE_TYPE_TRIANGLES;
137-
data->compute_bounds = true;
138-
data->release = nullptr;
139-
data->user_data = nullptr;
140-
return true;
141-
}
142-
143-
SceneObjects::SceneObjects(mjrfContext* ctx) : ctx_(ctx) {}
125+
mjrfMeshConfig config;
126+
mjrf_defaultMeshConfig(&config);
127+
config.num_attributes = uvs.data() ? 3 : 2;
128+
config.attributes[0].usage = mjVERTEX_ATTRIBUTE_USAGE_POSITION;
129+
config.attributes[0].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3;
130+
config.attributes[1].usage = mjVERTEX_ATTRIBUTE_USAGE_NORMAL;
131+
config.attributes[1].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT3;
132+
config.attributes[2].usage = mjVERTEX_ATTRIBUTE_USAGE_UV;
133+
config.attributes[2].type = mjVERTEX_ATTRIBUTE_TYPE_FLOAT2;
134+
config.max_vertices = positions.size() / 3;
135+
config.max_indices = num_indices;
136+
config.index_type = mjINDEX_TYPE_U32;
137+
config.primitive_type = mjMESH_PRIMITIVE_TYPE_TRIANGLES;
144138

145-
bool SceneObjects::CreateSkinFlexMesh(const mjvScene* scene,
146-
const mjModel* model,
147-
const mjvGeom& geom) {
148139
mjrfMeshData data;
149140
mjrf_defaultMeshData(&data);
150-
if (!UpdateSkinFlexMeshData(&data, model, scene, geom)) {
151-
return false;
152-
}
141+
data.vertices[0] = positions.data();
142+
data.vertices[1] = normals.data();
143+
data.vertices[2] = uvs.data();
144+
data.num_vertices = positions.size() / 3;
145+
data.num_indices = num_indices;
146+
data.indices = indices.data();
147+
data.compute_bounds = true;
148+
data.release = nullptr;
149+
data.user_data = nullptr;
150+
153151
if (geom.type == mjGEOM_FLEX) {
154-
flexes_.insert_or_assign(geom.objid, CreateMesh(ctx_, data));
152+
auto iter = flexes_.find(geom.objid);
153+
if (iter == flexes_.end()) {
154+
iter = flexes_.insert({geom.objid, CreateMesh(ctx_, config)}).first;
155+
}
156+
mjrf_setMeshData(iter->second.get(), &data);
155157
} else if (geom.type == mjGEOM_SKIN) {
156-
skins_.insert_or_assign(geom.objid, CreateMesh(ctx_, data));
158+
auto iter = skins_.find(geom.objid);
159+
if (iter == skins_.end()) {
160+
iter = skins_.insert({geom.objid, CreateMesh(ctx_, config)}).first;
161+
}
162+
mjrf_setMeshData(iter->second.get(), &data);
157163
} else {
158164
mju_error("Unsupported dynamic mesh type: %d", geom.type);
159165
}

0 commit comments

Comments
 (0)
⌂ 换网址