Make change non-breaking per haroonq's feedback

This commit is contained in:
Pedro Morais
2026-07-15 11:53:22 -04:00
parent d43c3ed426
commit 0a6b631d4b
7 changed files with 103 additions and 13 deletions
+3
View File
@@ -583,6 +583,9 @@ Defined in `mjrender.h <https://github.com/google-deepmind/mujoco/blob/main/incl
* - ``mjMAXTEXTURE``
- 1000
- Maximum number of textures allowed.
* - ``mjMAXMATERIAL``
- 1000
- Maximum number of materials with textures.
.. _glNumericUI:
+1 -5
View File
@@ -32,15 +32,11 @@ General
exclusively in the compressed sparse row (CSR) format ``mjData.M``.
- :ref:`mju_round` now breaks ties away from zero rather than towards :math:`+\infty`. This only affects
negative half-integers, e.g. ``mju_round(-2.5)`` now returns -3 rather than -2.
- Removed the ``mjMAXMATERIAL`` constant. The classic renderer no longer caps the number of textured materials.
.. admonition:: Breaking ABI changes
:class: attention
- Removed ``mat_texid``, ``mat_texuniform`` and ``mat_texrepeat`` from ``mjrContext``; the equivalent per-geom fields
``texid``, ``texuniform`` and ``texrepeat`` were added to ``mjvGeom``, populated from the model each frame by
:ref:`mjv_updateScene`. The classic renderer now resolves them live, so runtime material changes (e.g. domain
randomization) no longer require rebuilding the render context.
- Added ``texid``, ``texuniform`` and ``texrepeat`` fields to ``mjvGeom``.
Version 3.10.0 (June 22, 2026)
------------------------------
+6
View File
@@ -24,6 +24,7 @@ extern "C" {
#define mjNAUX 10 // number of auxiliary buffers
#define mjMAXTEXTURE 1000 // maximum number of textures
#define mjMAXMATERIAL 1000 // maximum number of materials with textures
//---------------------------------- primitive types (mjt) -----------------------------------------
@@ -169,6 +170,11 @@ typedef struct mjrContext_ { // custom OpenGL context
unsigned int auxColor[mjNAUX]; // auxiliary color buffer
unsigned int auxColor_r[mjNAUX]; // auxiliary color buffer for resolving
// materials with textures
int mat_texid[mjMAXMATERIAL*mjNTEXROLE]; // material texture ids (-1: no texture)
int mat_texuniform[mjMAXMATERIAL]; // uniform cube mapping
float mat_texrepeat[mjMAXMATERIAL*2]; // texture repetition for 2d mapping
// texture objects and info
int ntexture; // number of allocated textures
int textureType[mjMAXTEXTURE]; // type of texture (mjtTexture) (ntexture)
+24
View File
@@ -11196,6 +11196,30 @@ STRUCTS: Mapping[str, StructDecl] = dict([
),
doc='auxiliary color buffer for resolving',
),
StructFieldDecl(
name='mat_texid',
type=ArrayType(
inner_type=ValueType(name='int'),
extents=(10000,),
),
doc='material texture ids (-1: no texture)',
),
StructFieldDecl(
name='mat_texuniform',
type=ArrayType(
inner_type=ValueType(name='int'),
extents=(1000,),
),
doc='uniform cube mapping',
),
StructFieldDecl(
name='mat_texrepeat',
type=ArrayType(
inner_type=ValueType(name='float'),
extents=(2000,),
),
doc='texture repetition for 2d mapping',
),
StructFieldDecl(
name='ntexture',
type=ValueType(name='int'),
+12
View File
@@ -54,6 +54,9 @@ class MjWrapper<raw::MjrContext> : public WrapperBase<raw::MjrContext> {
X(auxFBO_r);
X(auxColor);
X(auxColor_r);
X(mat_texid);
X(mat_texuniform);
X(mat_texrepeat);
X(textureType);
X(texture);
X(skinvertVBO);
@@ -95,6 +98,9 @@ MjrContextWrapper::MjWrapper()
X(auxFBO_r),
X(auxColor),
X(auxColor_r),
X(mat_texid),
X(mat_texuniform),
X(mat_texrepeat),
X(textureType),
X(texture),
X_SKIN(skinvertVBO),
@@ -119,6 +125,9 @@ MjrContextWrapper::MjWrapper(const MjModelWrapper& model, int fontscale)
X(auxFBO_r),
X(auxColor),
X(auxColor_r),
X(mat_texid),
X(mat_texuniform),
X(mat_texrepeat),
X(textureType),
X(texture),
X_SKIN(skinvertVBO),
@@ -219,6 +228,9 @@ PYBIND11_MODULE(_render, pymodule, pybind11::mod_gil_not_used()) {
X(auxFBO_r);
X(auxColor);
X(auxColor_r);
X(mat_texid);
X(mat_texuniform);
X(mat_texrepeat);
X(textureType);
X(texture);
X(skinvertVBO);
+40
View File
@@ -14,6 +14,7 @@
#include "render/classic/render_context.h"
#include <inttypes.h> // IWYU pragma: keep
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
@@ -1298,6 +1299,44 @@ static void makeFont(mjrContext* con, int fontscale) {
}
}
// make materials, just for those that have textures
static void makeMaterial(const mjModel* m, mjrContext* con) {
memset(con->mat_texid, -1, sizeof(con->mat_texid));
memset(con->mat_texuniform, 0, sizeof(con->mat_texuniform));
memset(con->mat_texrepeat, 0, sizeof(con->mat_texrepeat));
// find skybox texture
for (int i=0; i < m->ntex; i++) {
if (m->tex_type[i] == mjTEXTURE_SKYBOX) {
if (m->nmat >= mjMAXMATERIAL-2) {
mju_error("With skybox, maximum number of materials is %d, got %" PRId64,
mjMAXMATERIAL-1, m->nmat);
}
for (int j=0; j < mjNTEXROLE; j++) {
con->mat_texid[mjNTEXROLE * (mjMAXMATERIAL-1) + j] = -1;
}
con->mat_texid[mjNTEXROLE * (mjMAXMATERIAL-1) + mjTEXROLE_RGB] = i;
break;
}
}
if (m->nmat >= mjMAXMATERIAL-1) {
mju_error("Maximum number of materials is %d, got %" PRId64, mjMAXMATERIAL, m->nmat);
}
for (int i=0; i < m->nmat; i++) {
if (m->mat_texid[i*mjNTEXROLE + mjTEXROLE_RGB] >= 0) {
for (int j=0; j < mjNTEXROLE; j++) {
con->mat_texid[i*mjNTEXROLE + j] = m->mat_texid[i*mjNTEXROLE + j];
}
con->mat_texuniform[i] = m->mat_texuniform[i];
con->mat_texrepeat[2*i] = m->mat_texrepeat[2*i];
con->mat_texrepeat[2*i+1] = m->mat_texrepeat[2*i+1];
}
}
}
// make textures
static void makeTexture(const mjModel* m, mjrContext* con) {
// checks size
@@ -1600,6 +1639,7 @@ void mjr_makeContext_offSize(const mjModel* m, mjrContext* con, int fontscale,
// make everything
makeOff(con);
makeShadow(m, con);
makeMaterial(m, con);
makeTexture(m, con);
makePlane(m, con);
makeMesh(m, con);
+17 -8
View File
@@ -61,10 +61,19 @@ enum {
// enable/disable texture mapping
static void settexture(int type, int state, const mjrContext* con, const mjvGeom* geom) {
float plane[4], scl[2];
int texid = -1;
int texid = -1, texuniform = 0;
float texrepeat[2] = {0, 0};
if (geom) {
if (geom->matid >= 0) {
if (geom->texid >= 0) {
texid = geom->texid;
texuniform = geom->texuniform;
texrepeat[0] = geom->texrepeat[0];
texrepeat[1] = geom->texrepeat[1];
} else if (geom->matid >= 0) {
texid = con->mat_texid[mjNTEXROLE * geom->matid + mjTEXROLE_RGB];
texuniform = con->mat_texuniform[geom->matid];
texrepeat[0] = con->mat_texrepeat[geom->matid*2];
texrepeat[1] = con->mat_texrepeat[geom->matid*2+1];
}
}
@@ -119,8 +128,8 @@ static void settexture(int type, int state, const mjrContext* con, const mjvGeom
glBindTexture(GL_TEXTURE_2D, con->texture[texid]);
// determine scaling, adjust for pre-scaled geoms
scl[0] = geom->texrepeat[0];
scl[1] = geom->texrepeat[1];
scl[0] = texrepeat[0];
scl[1] = texrepeat[1];
if (geom->dataid >= 0) {
if (geom->size[0] > 0) {
scl[0] = scl[0] / mju_max(mjMINVAL, geom->size[0]);
@@ -132,7 +141,7 @@ static void settexture(int type, int state, const mjrContext* con, const mjvGeom
}
// uniform: repeat relative to spatial units rather than object
if (geom->texuniform) {
if (texuniform) {
if (geom->size[0] > 0) {
scl[0] = scl[0] * geom->size[0];
}
@@ -171,11 +180,11 @@ static void settexture(int type, int state, const mjrContext* con, const mjvGeom
// set mapping : cube
if (type == mjtexREGULAR) {
mjr_setf4(plane, geom->texuniform ? geom->size[0] : 1, 0, 0, 0);
mjr_setf4(plane, texuniform ? geom->size[0] : 1, 0, 0, 0);
glTexGenfv(GL_S, GL_OBJECT_PLANE, plane);
mjr_setf4(plane, 0, geom->texuniform ? geom->size[1] : 1, 0, 0);
mjr_setf4(plane, 0, texuniform ? geom->size[1] : 1, 0, 0);
glTexGenfv(GL_T, GL_OBJECT_PLANE, plane);
mjr_setf4(plane, 0, 0, geom->texuniform ? geom->size[2] : 1, 0);
mjr_setf4(plane, 0, 0, texuniform ? geom->size[2] : 1, 0);
glTexGenfv(GL_R, GL_OBJECT_PLANE, plane);
}