Move texture block copy out of render context so it can be modified online via mjmodel
This commit is contained in:
@@ -583,9 +583,6 @@ 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:
|
||||
|
||||
@@ -32,6 +32,15 @@ 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.
|
||||
|
||||
Version 3.10.0 (June 22, 2026)
|
||||
------------------------------
|
||||
|
||||
@@ -24,7 +24,6 @@ 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) -----------------------------------------
|
||||
|
||||
@@ -170,11 +169,6 @@ 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)
|
||||
|
||||
@@ -229,6 +229,8 @@ typedef struct mjvGeom_ { // abstract geom
|
||||
int objid; // mujoco object id; -1 for decor
|
||||
int category; // visual category
|
||||
int matid; // material id; -1: no textured material
|
||||
int texid; // texture id; -1: none
|
||||
int texuniform; // uniform cube mapping
|
||||
int texcoord; // mesh or flex geom has texture coordinates
|
||||
int segid; // segmentation id; -1: not shown
|
||||
|
||||
@@ -243,6 +245,7 @@ typedef struct mjvGeom_ { // abstract geom
|
||||
float specular; // specular coef
|
||||
float shininess; // shininess coef
|
||||
float reflectance; // reflectance coef
|
||||
float texrepeat[2]; // texture repetition for 2d mapping
|
||||
|
||||
char label[100]; // text label
|
||||
|
||||
|
||||
@@ -10140,6 +10140,16 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
||||
type=ValueType(name='int'),
|
||||
doc='material id; -1: no textured material',
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='texid',
|
||||
type=ValueType(name='int'),
|
||||
doc='texture id; -1: none',
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='texuniform',
|
||||
type=ValueType(name='int'),
|
||||
doc='uniform cube mapping',
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='texcoord',
|
||||
type=ValueType(name='int'),
|
||||
@@ -10202,6 +10212,14 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
||||
type=ValueType(name='float'),
|
||||
doc='reflectance coef',
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='texrepeat',
|
||||
type=ArrayType(
|
||||
inner_type=ValueType(name='float'),
|
||||
extents=(2,),
|
||||
),
|
||||
doc='texture repetition for 2d mapping',
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='label',
|
||||
type=ArrayType(
|
||||
@@ -11178,30 +11196,6 @@ 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'),
|
||||
|
||||
@@ -54,9 +54,6 @@ 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);
|
||||
@@ -98,9 +95,6 @@ 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),
|
||||
@@ -125,9 +119,6 @@ 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),
|
||||
@@ -228,9 +219,6 @@ 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);
|
||||
|
||||
@@ -1185,6 +1185,8 @@ This is useful for example when the MJB is not available as a file on disk.)"));
|
||||
X(objid);
|
||||
X(category);
|
||||
X(matid);
|
||||
X(texid);
|
||||
X(texuniform);
|
||||
X(texcoord);
|
||||
X(segid);
|
||||
X(emission);
|
||||
@@ -1201,6 +1203,7 @@ This is useful for example when the MJB is not available as a file on disk.)"));
|
||||
X(pos);
|
||||
X(mat);
|
||||
X(rgba);
|
||||
X(texrepeat);
|
||||
#undef X
|
||||
|
||||
DefinePyStr(mjvGeom, "label", &raw::MjvGeom::label);
|
||||
|
||||
@@ -832,6 +832,7 @@ class MjWrapper<raw::MjvGeom> : public WrapperBase<raw::MjvGeom> {
|
||||
X(pos);
|
||||
X(mat);
|
||||
X(rgba);
|
||||
X(texrepeat);
|
||||
#undef X
|
||||
};
|
||||
|
||||
|
||||
@@ -1193,7 +1193,8 @@ MjvGeomWrapper::MjWrapper()
|
||||
static_assert(sizeof(ptr_->mat) == sizeof(ptr_->mat[0]) * 9);
|
||||
return InitPyArray(std::array{3, 3}, ptr_->mat, owner_);
|
||||
}()),
|
||||
X(rgba) {
|
||||
X(rgba),
|
||||
X(texrepeat) {
|
||||
mjv_initGeom(ptr_, mjGEOM_NONE, nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
@@ -1205,7 +1206,8 @@ MjvGeomWrapper::MjWrapper(raw::MjvGeom* ptr, py::handle owner)
|
||||
static_assert(sizeof(ptr_->mat) == sizeof(ptr_->mat[0]) * 9);
|
||||
return InitPyArray(std::array{3, 3}, ptr_->mat, owner_);
|
||||
}()),
|
||||
X(rgba) {}
|
||||
X(rgba),
|
||||
X(texrepeat) {}
|
||||
#undef X
|
||||
|
||||
MjvGeomWrapper::MjWrapper(const MjvGeomWrapper& other) : MjvGeomWrapper() {
|
||||
|
||||
@@ -241,6 +241,10 @@ static void setMaterial(const mjModel* m, mjvGeom* geom, int matid, const float*
|
||||
// set texture
|
||||
if (flags[mjVIS_TEXTURE] && matid >= 0) {
|
||||
geom->matid = matid;
|
||||
geom->texid = m->mat_texid[matid*mjNTEXROLE + mjTEXROLE_RGB];
|
||||
geom->texuniform = m->mat_texuniform[matid];
|
||||
geom->texrepeat[0] = m->mat_texrepeat[2*matid];
|
||||
geom->texrepeat[1] = m->mat_texrepeat[2*matid+1];
|
||||
}
|
||||
|
||||
// scale alpha for dynamic geoms only
|
||||
@@ -379,6 +383,10 @@ void mjv_initGeom(mjvGeom* geom, int type, const mjtNum* size,
|
||||
// set defaults that cannot be assigned via this function
|
||||
geom->dataid = -1;
|
||||
geom->matid = -1;
|
||||
geom->texid = -1;
|
||||
geom->texuniform = 0;
|
||||
geom->texrepeat[0] = 0;
|
||||
geom->texrepeat[1] = 0;
|
||||
geom->texcoord = 0;
|
||||
geom->emission = 0;
|
||||
geom->specular = 0.5;
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include "render/classic/render_context.h"
|
||||
|
||||
#include <inttypes.h> // IWYU pragma: keep
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -1299,44 +1298,6 @@ 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
|
||||
@@ -1639,7 +1600,6 @@ 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);
|
||||
|
||||
@@ -64,7 +64,7 @@ static void settexture(int type, int state, const mjrContext* con, const mjvGeom
|
||||
int texid = -1;
|
||||
if (geom) {
|
||||
if (geom->matid >= 0) {
|
||||
texid = con->mat_texid[mjNTEXROLE * geom->matid + mjTEXROLE_RGB];
|
||||
texid = geom->texid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,8 +119,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] = con->mat_texrepeat[geom->matid*2];
|
||||
scl[1] = con->mat_texrepeat[geom->matid*2+1];
|
||||
scl[0] = geom->texrepeat[0];
|
||||
scl[1] = geom->texrepeat[1];
|
||||
if (geom->dataid >= 0) {
|
||||
if (geom->size[0] > 0) {
|
||||
scl[0] = scl[0] / mju_max(mjMINVAL, geom->size[0]);
|
||||
@@ -132,7 +132,7 @@ static void settexture(int type, int state, const mjrContext* con, const mjvGeom
|
||||
}
|
||||
|
||||
// uniform: repeat relative to spatial units rather than object
|
||||
if (con->mat_texuniform[geom->matid]) {
|
||||
if (geom->texuniform) {
|
||||
if (geom->size[0] > 0) {
|
||||
scl[0] = scl[0] * geom->size[0];
|
||||
}
|
||||
@@ -171,11 +171,11 @@ static void settexture(int type, int state, const mjrContext* con, const mjvGeom
|
||||
|
||||
// set mapping : cube
|
||||
if (type == mjtexREGULAR) {
|
||||
mjr_setf4(plane, con->mat_texuniform[geom->matid] ? geom->size[0] : 1, 0, 0, 0);
|
||||
mjr_setf4(plane, geom->texuniform ? geom->size[0] : 1, 0, 0, 0);
|
||||
glTexGenfv(GL_S, GL_OBJECT_PLANE, plane);
|
||||
mjr_setf4(plane, 0, con->mat_texuniform[geom->matid] ? geom->size[1] : 1, 0, 0);
|
||||
mjr_setf4(plane, 0, geom->texuniform ? geom->size[1] : 1, 0, 0);
|
||||
glTexGenfv(GL_T, GL_OBJECT_PLANE, plane);
|
||||
mjr_setf4(plane, 0, 0, con->mat_texuniform[geom->matid] ? geom->size[2] : 1, 0);
|
||||
mjr_setf4(plane, 0, 0, geom->texuniform ? geom->size[2] : 1, 0);
|
||||
glTexGenfv(GL_R, GL_OBJECT_PLANE, plane);
|
||||
}
|
||||
|
||||
@@ -1317,7 +1317,7 @@ void mjr_render(mjrRect viewport, mjvScene* scn, const mjrContext* con) {
|
||||
if (con->textureType[i] == mjTEXTURE_SKYBOX) {
|
||||
// save first skybox texture id in tempgeom
|
||||
memset(&tempgeom, 0, sizeof(mjvGeom));
|
||||
tempgeom.matid = mjMAXMATERIAL - 1;
|
||||
tempgeom.texid = i;
|
||||
|
||||
// modify settings
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
Reference in New Issue
Block a user