diff --git a/doc/APIreference/APIglobals.rst b/doc/APIreference/APIglobals.rst index fec3dc6b..b25cb5fd 100644 --- a/doc/APIreference/APIglobals.rst +++ b/doc/APIreference/APIglobals.rst @@ -583,6 +583,9 @@ Defined in `mjrender.h : public WrapperBase { 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); diff --git a/src/render/classic/render_context.c b/src/render/classic/render_context.c index 52402c7f..c7a5dd0b 100644 --- a/src/render/classic/render_context.c +++ b/src/render/classic/render_context.c @@ -14,6 +14,7 @@ #include "render/classic/render_context.h" +#include // IWYU pragma: keep #include #include #include @@ -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); diff --git a/src/render/classic/render_gl3.c b/src/render/classic/render_gl3.c index 402fcc6a..f986c0ff 100644 --- a/src/render/classic/render_gl3.c +++ b/src/render/classic/render_gl3.c @@ -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); }