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`` * - ``mjMAXTEXTURE``
- 1000 - 1000
- Maximum number of textures allowed. - Maximum number of textures allowed.
* - ``mjMAXMATERIAL``
- 1000
- Maximum number of materials with textures.
.. _glNumericUI: .. _glNumericUI:
+1 -5
View File
@@ -32,15 +32,11 @@ General
exclusively in the compressed sparse row (CSR) format ``mjData.M``. 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 - :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. 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 .. admonition:: Breaking ABI changes
:class: attention :class: attention
- Removed ``mat_texid``, ``mat_texuniform`` and ``mat_texrepeat`` from ``mjrContext``; the equivalent per-geom fields - Added ``texid``, ``texuniform`` and ``texrepeat`` fields to ``mjvGeom``.
``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.
Version 3.10.0 (June 22, 2026) Version 3.10.0 (June 22, 2026)
------------------------------ ------------------------------
+6
View File
@@ -24,6 +24,7 @@ extern "C" {
#define mjNAUX 10 // number of auxiliary buffers #define mjNAUX 10 // number of auxiliary buffers
#define mjMAXTEXTURE 1000 // maximum number of textures #define mjMAXTEXTURE 1000 // maximum number of textures
#define mjMAXMATERIAL 1000 // maximum number of materials with textures
//---------------------------------- primitive types (mjt) ----------------------------------------- //---------------------------------- primitive types (mjt) -----------------------------------------
@@ -169,6 +170,11 @@ typedef struct mjrContext_ { // custom OpenGL context
unsigned int auxColor[mjNAUX]; // auxiliary color buffer unsigned int auxColor[mjNAUX]; // auxiliary color buffer
unsigned int auxColor_r[mjNAUX]; // auxiliary color buffer for resolving 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 // texture objects and info
int ntexture; // number of allocated textures int ntexture; // number of allocated textures
int textureType[mjMAXTEXTURE]; // type of texture (mjtTexture) (ntexture) 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', 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( StructFieldDecl(
name='ntexture', name='ntexture',
type=ValueType(name='int'), type=ValueType(name='int'),
+12
View File
@@ -54,6 +54,9 @@ class MjWrapper<raw::MjrContext> : public WrapperBase<raw::MjrContext> {
X(auxFBO_r); X(auxFBO_r);
X(auxColor); X(auxColor);
X(auxColor_r); X(auxColor_r);
X(mat_texid);
X(mat_texuniform);
X(mat_texrepeat);
X(textureType); X(textureType);
X(texture); X(texture);
X(skinvertVBO); X(skinvertVBO);
@@ -95,6 +98,9 @@ MjrContextWrapper::MjWrapper()
X(auxFBO_r), X(auxFBO_r),
X(auxColor), X(auxColor),
X(auxColor_r), X(auxColor_r),
X(mat_texid),
X(mat_texuniform),
X(mat_texrepeat),
X(textureType), X(textureType),
X(texture), X(texture),
X_SKIN(skinvertVBO), X_SKIN(skinvertVBO),
@@ -119,6 +125,9 @@ MjrContextWrapper::MjWrapper(const MjModelWrapper& model, int fontscale)
X(auxFBO_r), X(auxFBO_r),
X(auxColor), X(auxColor),
X(auxColor_r), X(auxColor_r),
X(mat_texid),
X(mat_texuniform),
X(mat_texrepeat),
X(textureType), X(textureType),
X(texture), X(texture),
X_SKIN(skinvertVBO), X_SKIN(skinvertVBO),
@@ -219,6 +228,9 @@ PYBIND11_MODULE(_render, pymodule, pybind11::mod_gil_not_used()) {
X(auxFBO_r); X(auxFBO_r);
X(auxColor); X(auxColor);
X(auxColor_r); X(auxColor_r);
X(mat_texid);
X(mat_texuniform);
X(mat_texrepeat);
X(textureType); X(textureType);
X(texture); X(texture);
X(skinvertVBO); X(skinvertVBO);
+40
View File
@@ -14,6 +14,7 @@
#include "render/classic/render_context.h" #include "render/classic/render_context.h"
#include <inttypes.h> // IWYU pragma: keep
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.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 // make textures
static void makeTexture(const mjModel* m, mjrContext* con) { static void makeTexture(const mjModel* m, mjrContext* con) {
// checks size // checks size
@@ -1600,6 +1639,7 @@ void mjr_makeContext_offSize(const mjModel* m, mjrContext* con, int fontscale,
// make everything // make everything
makeOff(con); makeOff(con);
makeShadow(m, con); makeShadow(m, con);
makeMaterial(m, con);
makeTexture(m, con); makeTexture(m, con);
makePlane(m, con); makePlane(m, con);
makeMesh(m, con); makeMesh(m, con);
+17 -8
View File
@@ -61,10 +61,19 @@ enum {
// enable/disable texture mapping // enable/disable texture mapping
static void settexture(int type, int state, const mjrContext* con, const mjvGeom* geom) { static void settexture(int type, int state, const mjrContext* con, const mjvGeom* geom) {
float plane[4], scl[2]; float plane[4], scl[2];
int texid = -1; int texid = -1, texuniform = 0;
float texrepeat[2] = {0, 0};
if (geom) { if (geom) {
if (geom->matid >= 0) { if (geom->texid >= 0) {
texid = geom->texid; 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]); glBindTexture(GL_TEXTURE_2D, con->texture[texid]);
// determine scaling, adjust for pre-scaled geoms // determine scaling, adjust for pre-scaled geoms
scl[0] = geom->texrepeat[0]; scl[0] = texrepeat[0];
scl[1] = geom->texrepeat[1]; scl[1] = texrepeat[1];
if (geom->dataid >= 0) { if (geom->dataid >= 0) {
if (geom->size[0] > 0) { if (geom->size[0] > 0) {
scl[0] = scl[0] / mju_max(mjMINVAL, geom->size[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 // uniform: repeat relative to spatial units rather than object
if (geom->texuniform) { if (texuniform) {
if (geom->size[0] > 0) { if (geom->size[0] > 0) {
scl[0] = scl[0] * geom->size[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 // set mapping : cube
if (type == mjtexREGULAR) { 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); 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); 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); glTexGenfv(GL_R, GL_OBJECT_PLANE, plane);
} }