From 3b73dfe33bce05cd16a05529e5a589bd7f29e2bc Mon Sep 17 00:00:00 2001 From: Tom Erez Date: Tue, 2 Jul 2024 08:00:06 -0700 Subject: [PATCH] Add textured materials to render context, and refactor mjvGeom to refer to those textures. PiperOrigin-RevId: 648719103 Change-Id: Idb4425bdeea3cbc1133cda3e4366574ed3bb5ccc --- doc/includes/references.h | 132 ++++++++++++++------------- include/mujoco/mjmodel.h | 2 +- include/mujoco/mjrender.h | 128 +++++++++++++------------- include/mujoco/mjvisualize.h | 9 +- introspect/structs.py | 47 ++++++---- python/mujoco/render.cc | 12 +++ python/mujoco/structs.cc | 6 +- python/mujoco/structs.h | 2 +- python/mujoco/usd/component.py | 9 +- python/mujoco/usd/exporter.py | 6 +- src/engine/engine_vis_visualize.c | 17 +--- src/render/render_context.c | 32 +++++++ src/render/render_gl3.c | 34 ++++--- unity/Runtime/Bindings/MjBindings.cs | 11 ++- 14 files changed, 252 insertions(+), 195 deletions(-) diff --git a/doc/includes/references.h b/doc/includes/references.h index ba87e8fa..8d9c3ef7 100644 --- a/doc/includes/references.h +++ b/doc/includes/references.h @@ -1512,92 +1512,97 @@ struct mjrRect_ { // OpenGL rectangle int height; // height (usually buffer height) }; typedef struct mjrRect_ mjrRect; -struct mjrContext_ { // custom OpenGL context +struct mjrContext_ { // custom OpenGL context // parameters copied from mjVisual - float lineWidth; // line width for wireframe rendering - float shadowClip; // clipping radius for directional lights - float shadowScale; // fraction of light cutoff for spot lights - float fogStart; // fog start = stat.extent * vis.map.fogstart - float fogEnd; // fog end = stat.extent * vis.map.fogend - float fogRGBA[4]; // fog rgba - int shadowSize; // size of shadow map texture - int offWidth; // width of offscreen buffer - int offHeight; // height of offscreen buffer - int offSamples; // number of offscreen buffer multisamples + float lineWidth; // line width for wireframe rendering + float shadowClip; // clipping radius for directional lights + float shadowScale; // fraction of light cutoff for spot lights + float fogStart; // fog start = stat.extent * vis.map.fogstart + float fogEnd; // fog end = stat.extent * vis.map.fogend + float fogRGBA[4]; // fog rgba + int shadowSize; // size of shadow map texture + int offWidth; // width of offscreen buffer + int offHeight; // height of offscreen buffer + int offSamples; // number of offscreen buffer multisamples // parameters specified at creation - int fontScale; // font scale - int auxWidth[mjNAUX]; // auxiliary buffer width - int auxHeight[mjNAUX]; // auxiliary buffer height - int auxSamples[mjNAUX]; // auxiliary buffer multisamples + int fontScale; // font scale + int auxWidth[mjNAUX]; // auxiliary buffer width + int auxHeight[mjNAUX]; // auxiliary buffer height + int auxSamples[mjNAUX]; // auxiliary buffer multisamples // offscreen rendering objects - unsigned int offFBO; // offscreen framebuffer object - unsigned int offFBO_r; // offscreen framebuffer for resolving multisamples - unsigned int offColor; // offscreen color buffer - unsigned int offColor_r; // offscreen color buffer for resolving multisamples - unsigned int offDepthStencil; // offscreen depth and stencil buffer - unsigned int offDepthStencil_r; // offscreen depth and stencil buffer for resolving multisamples + unsigned int offFBO; // offscreen framebuffer object + unsigned int offFBO_r; // offscreen framebuffer for resolving multisamples + unsigned int offColor; // offscreen color buffer + unsigned int offColor_r; // offscreen color buffer for resolving multisamples + unsigned int offDepthStencil; // offscreen depth and stencil buffer + unsigned int offDepthStencil_r; // offscreen depth and stencil buffer for multisamples // shadow rendering objects - unsigned int shadowFBO; // shadow map framebuffer object - unsigned int shadowTex; // shadow map texture + unsigned int shadowFBO; // shadow map framebuffer object + unsigned int shadowTex; // shadow map texture // auxiliary buffers - unsigned int auxFBO[mjNAUX]; // auxiliary framebuffer object - unsigned int auxFBO_r[mjNAUX]; // auxiliary framebuffer object for resolving - unsigned int auxColor[mjNAUX]; // auxiliary color buffer - unsigned int auxColor_r[mjNAUX];// auxiliary color buffer for resolving + unsigned int auxFBO[mjNAUX]; // auxiliary framebuffer object + unsigned int auxFBO_r[mjNAUX]; // auxiliary framebuffer object for resolving + unsigned int auxColor[mjNAUX]; // auxiliary color buffer + unsigned int auxColor_r[mjNAUX]; // auxiliary color buffer for resolving + + // materials with textures + int mat_texid[mjMAXMATERIAL*mjNTEXMAT]; // material texture ids (-1: no texture) + int mat_texuniform[mjMAXMATERIAL]; // texture repetition for 2d mapping + int mat_texrepeat[mjMAXMATERIAL*2]; // texture repetition for 2d mapping // texture objects and info - int ntexture; // number of allocated textures - int textureType[100]; // type of texture (mjtTexture) (ntexture) - unsigned int texture[100]; // texture names + int ntexture; // number of allocated textures + int textureType[mjMAXTEXTURE]; // type of texture (mjtTexture) (ntexture) + unsigned int texture[mjMAXTEXTURE]; // texture names // displaylist starting positions - unsigned int basePlane; // all planes from model - unsigned int baseMesh; // all meshes from model - unsigned int baseHField; // all hfields from model - unsigned int baseBuiltin; // all buildin geoms, with quality from model - unsigned int baseFontNormal; // normal font - unsigned int baseFontShadow; // shadow font - unsigned int baseFontBig; // big font + unsigned int basePlane; // all planes from model + unsigned int baseMesh; // all meshes from model + unsigned int baseHField; // all height fields from model + unsigned int baseBuiltin; // all builtin geoms, with quality from model + unsigned int baseFontNormal; // normal font + unsigned int baseFontShadow; // shadow font + unsigned int baseFontBig; // big font // displaylist ranges - int rangePlane; // all planes from model - int rangeMesh; // all meshes from model - int rangeHField; // all hfields from model - int rangeBuiltin; // all builtin geoms, with quality from model - int rangeFont; // all characters in font + int rangePlane; // all planes from model + int rangeMesh; // all meshes from model + int rangeHField; // all hfields from model + int rangeBuiltin; // all builtin geoms, with quality from model + int rangeFont; // all characters in font // skin VBOs - int nskin; // number of skins - unsigned int* skinvertVBO; // skin vertex position VBOs (nskin) - unsigned int* skinnormalVBO; // skin vertex normal VBOs (nskin) - unsigned int* skintexcoordVBO; // skin vertex texture coordinate VBOs (nskin) - unsigned int* skinfaceVBO; // skin face index VBOs (nskin) + int nskin; // number of skins + unsigned int* skinvertVBO; // skin vertex position VBOs (nskin) + unsigned int* skinnormalVBO; // skin vertex normal VBOs (nskin) + unsigned int* skintexcoordVBO; // skin vertex texture coordinate VBOs (nskin) + unsigned int* skinfaceVBO; // skin face index VBOs (nskin) // character info - int charWidth[127]; // character widths: normal and shadow - int charWidthBig[127]; // chacarter widths: big - int charHeight; // character heights: normal and shadow - int charHeightBig; // character heights: big + int charWidth[127]; // character widths: normal and shadow + int charWidthBig[127]; // chacarter widths: big + int charHeight; // character heights: normal and shadow + int charHeightBig; // character heights: big // capabilities - int glInitialized; // is OpenGL initialized - int windowAvailable; // is default/window framebuffer available - int windowSamples; // number of samples for default/window framebuffer - int windowStereo; // is stereo available for default/window framebuffer - int windowDoublebuffer; // is default/window framebuffer double buffered + int glInitialized; // is OpenGL initialized + int windowAvailable; // is default/window framebuffer available + int windowSamples; // number of samples for default/window framebuffer + int windowStereo; // is stereo available for default/window framebuffer + int windowDoublebuffer; // is default/window framebuffer double buffered // framebuffer - int currentBuffer; // currently active framebuffer: mjFB_WINDOW or mjFB_OFFSCREEN + int currentBuffer; // currently active framebuffer: mjFB_WINDOW or mjFB_OFFSCREEN // pixel output format - int readPixelFormat; // default color pixel format for mjr_readPixels + int readPixelFormat; // default color pixel format for mjr_readPixels // depth output format - int readDepthMap; // depth mapping: mjDEPTH_ZERONEAR or mjDEPTH_ZEROFAR + int readDepthMap; // depth mapping: mjDEPTH_ZERONEAR or mjDEPTH_ZEROFAR }; typedef struct mjrContext_ mjrContext; typedef enum mjtGeomInertia_ { // type of inertia inference @@ -2639,21 +2644,22 @@ struct mjvGeom_ { // abstract geom int objtype; // mujoco object type; mjOBJ_UNKNOWN for decor int objid; // mujoco object id; -1 for decor int category; // visual category - int texid; // texture id; -1: no texture - int texuniform; // uniform cube mapping + int matid; // material id; -1: no textured material int texcoord; // mesh or flex geom has texture coordinates int segid; // segmentation id; -1: not shown - // OpenGL info - float texrepeat[2]; // texture repetition for 2D mapping + // spatial transform float size[3]; // size parameters float pos[3]; // Cartesian position float mat[9]; // Cartesian orientation + + // material properties float rgba[4]; // color and transparency float emission; // emission coef float specular; // specular coef float shininess; // shininess coef float reflectance; // reflectance coef + char label[100]; // text label // transparency rendering (set internally) diff --git a/include/mujoco/mjmodel.h b/include/mujoco/mjmodel.h index 72999a31..0c3d9a03 100644 --- a/include/mujoco/mjmodel.h +++ b/include/mujoco/mjmodel.h @@ -44,7 +44,7 @@ #define mjNIMP 5 // number of solver impedance parameters #define mjNSOLVER 200 // size of one mjData.solver array #define mjNISLAND 20 // number of mjData.solver arrays - +#define mjNTEXMAT 6 // number of textures per material //---------------------------------- enum types (mjt) ---------------------------------------------- diff --git a/include/mujoco/mjrender.h b/include/mujoco/mjrender.h index 4a4089d7..098cfa0e 100644 --- a/include/mujoco/mjrender.h +++ b/include/mujoco/mjrender.h @@ -15,14 +15,15 @@ #ifndef MUJOCO_MJRENDER_H_ #define MUJOCO_MJRENDER_H_ +#include #if defined(__cplusplus) extern "C" { #endif #define mjNAUX 10 // number of auxiliary buffers -#define mjMAXTEXTURE 1000 // maximum number of textures - +#define mjMAXTEXTURE 100 // maximum number of textures +#define mjMAXMATERIAL 100 // maximum number of materials with textures //---------------------------------- primitive types (mjt) ----------------------------------------- @@ -76,92 +77,97 @@ typedef struct mjrRect_ mjrRect; //---------------------------------- mjrContext ---------------------------------------------------- -struct mjrContext_ { // custom OpenGL context +struct mjrContext_ { // custom OpenGL context // parameters copied from mjVisual - float lineWidth; // line width for wireframe rendering - float shadowClip; // clipping radius for directional lights - float shadowScale; // fraction of light cutoff for spot lights - float fogStart; // fog start = stat.extent * vis.map.fogstart - float fogEnd; // fog end = stat.extent * vis.map.fogend - float fogRGBA[4]; // fog rgba - int shadowSize; // size of shadow map texture - int offWidth; // width of offscreen buffer - int offHeight; // height of offscreen buffer - int offSamples; // number of offscreen buffer multisamples + float lineWidth; // line width for wireframe rendering + float shadowClip; // clipping radius for directional lights + float shadowScale; // fraction of light cutoff for spot lights + float fogStart; // fog start = stat.extent * vis.map.fogstart + float fogEnd; // fog end = stat.extent * vis.map.fogend + float fogRGBA[4]; // fog rgba + int shadowSize; // size of shadow map texture + int offWidth; // width of offscreen buffer + int offHeight; // height of offscreen buffer + int offSamples; // number of offscreen buffer multisamples // parameters specified at creation - int fontScale; // font scale - int auxWidth[mjNAUX]; // auxiliary buffer width - int auxHeight[mjNAUX]; // auxiliary buffer height - int auxSamples[mjNAUX]; // auxiliary buffer multisamples + int fontScale; // font scale + int auxWidth[mjNAUX]; // auxiliary buffer width + int auxHeight[mjNAUX]; // auxiliary buffer height + int auxSamples[mjNAUX]; // auxiliary buffer multisamples // offscreen rendering objects - unsigned int offFBO; // offscreen framebuffer object - unsigned int offFBO_r; // offscreen framebuffer for resolving multisamples - unsigned int offColor; // offscreen color buffer - unsigned int offColor_r; // offscreen color buffer for resolving multisamples - unsigned int offDepthStencil; // offscreen depth and stencil buffer - unsigned int offDepthStencil_r; // offscreen depth and stencil buffer for resolving multisamples + unsigned int offFBO; // offscreen framebuffer object + unsigned int offFBO_r; // offscreen framebuffer for resolving multisamples + unsigned int offColor; // offscreen color buffer + unsigned int offColor_r; // offscreen color buffer for resolving multisamples + unsigned int offDepthStencil; // offscreen depth and stencil buffer + unsigned int offDepthStencil_r; // offscreen depth and stencil buffer for multisamples // shadow rendering objects - unsigned int shadowFBO; // shadow map framebuffer object - unsigned int shadowTex; // shadow map texture + unsigned int shadowFBO; // shadow map framebuffer object + unsigned int shadowTex; // shadow map texture // auxiliary buffers - unsigned int auxFBO[mjNAUX]; // auxiliary framebuffer object - unsigned int auxFBO_r[mjNAUX]; // auxiliary framebuffer object for resolving - unsigned int auxColor[mjNAUX]; // auxiliary color buffer - unsigned int auxColor_r[mjNAUX];// auxiliary color buffer for resolving + unsigned int auxFBO[mjNAUX]; // auxiliary framebuffer object + unsigned int auxFBO_r[mjNAUX]; // auxiliary framebuffer object for resolving + unsigned int auxColor[mjNAUX]; // auxiliary color buffer + unsigned int auxColor_r[mjNAUX]; // auxiliary color buffer for resolving + + // materials with textures + int mat_texid[mjMAXMATERIAL*mjNTEXMAT]; // material texture ids (-1: no texture) + int mat_texuniform[mjMAXMATERIAL]; // texture repetition for 2d mapping + int mat_texrepeat[mjMAXMATERIAL*2]; // texture repetition for 2d mapping // texture objects and info - int ntexture; // number of allocated textures - int textureType[100]; // type of texture (mjtTexture) (ntexture) - unsigned int texture[100]; // texture names + int ntexture; // number of allocated textures + int textureType[mjMAXTEXTURE]; // type of texture (mjtTexture) (ntexture) + unsigned int texture[mjMAXTEXTURE]; // texture names // displaylist starting positions - unsigned int basePlane; // all planes from model - unsigned int baseMesh; // all meshes from model - unsigned int baseHField; // all hfields from model - unsigned int baseBuiltin; // all buildin geoms, with quality from model - unsigned int baseFontNormal; // normal font - unsigned int baseFontShadow; // shadow font - unsigned int baseFontBig; // big font + unsigned int basePlane; // all planes from model + unsigned int baseMesh; // all meshes from model + unsigned int baseHField; // all height fields from model + unsigned int baseBuiltin; // all builtin geoms, with quality from model + unsigned int baseFontNormal; // normal font + unsigned int baseFontShadow; // shadow font + unsigned int baseFontBig; // big font // displaylist ranges - int rangePlane; // all planes from model - int rangeMesh; // all meshes from model - int rangeHField; // all hfields from model - int rangeBuiltin; // all builtin geoms, with quality from model - int rangeFont; // all characters in font + int rangePlane; // all planes from model + int rangeMesh; // all meshes from model + int rangeHField; // all hfields from model + int rangeBuiltin; // all builtin geoms, with quality from model + int rangeFont; // all characters in font // skin VBOs - int nskin; // number of skins - unsigned int* skinvertVBO; // skin vertex position VBOs (nskin) - unsigned int* skinnormalVBO; // skin vertex normal VBOs (nskin) - unsigned int* skintexcoordVBO; // skin vertex texture coordinate VBOs (nskin) - unsigned int* skinfaceVBO; // skin face index VBOs (nskin) + int nskin; // number of skins + unsigned int* skinvertVBO; // skin vertex position VBOs (nskin) + unsigned int* skinnormalVBO; // skin vertex normal VBOs (nskin) + unsigned int* skintexcoordVBO; // skin vertex texture coordinate VBOs (nskin) + unsigned int* skinfaceVBO; // skin face index VBOs (nskin) // character info - int charWidth[127]; // character widths: normal and shadow - int charWidthBig[127]; // chacarter widths: big - int charHeight; // character heights: normal and shadow - int charHeightBig; // character heights: big + int charWidth[127]; // character widths: normal and shadow + int charWidthBig[127]; // chacarter widths: big + int charHeight; // character heights: normal and shadow + int charHeightBig; // character heights: big // capabilities - int glInitialized; // is OpenGL initialized - int windowAvailable; // is default/window framebuffer available - int windowSamples; // number of samples for default/window framebuffer - int windowStereo; // is stereo available for default/window framebuffer - int windowDoublebuffer; // is default/window framebuffer double buffered + int glInitialized; // is OpenGL initialized + int windowAvailable; // is default/window framebuffer available + int windowSamples; // number of samples for default/window framebuffer + int windowStereo; // is stereo available for default/window framebuffer + int windowDoublebuffer; // is default/window framebuffer double buffered // framebuffer - int currentBuffer; // currently active framebuffer: mjFB_WINDOW or mjFB_OFFSCREEN + int currentBuffer; // currently active framebuffer: mjFB_WINDOW or mjFB_OFFSCREEN // pixel output format - int readPixelFormat; // default color pixel format for mjr_readPixels + int readPixelFormat; // default color pixel format for mjr_readPixels // depth output format - int readDepthMap; // depth mapping: mjDEPTH_ZERONEAR or mjDEPTH_ZEROFAR + int readDepthMap; // depth mapping: mjDEPTH_ZERONEAR or mjDEPTH_ZEROFAR }; typedef struct mjrContext_ mjrContext; diff --git a/include/mujoco/mjvisualize.h b/include/mujoco/mjvisualize.h index 0d23e39a..124a511f 100644 --- a/include/mujoco/mjvisualize.h +++ b/include/mujoco/mjvisualize.h @@ -230,21 +230,22 @@ struct mjvGeom_ { // abstract geom int objtype; // mujoco object type; mjOBJ_UNKNOWN for decor int objid; // mujoco object id; -1 for decor int category; // visual category - int texid; // texture id; -1: no texture - int texuniform; // uniform cube mapping + int matid; // material id; -1: no textured material int texcoord; // mesh or flex geom has texture coordinates int segid; // segmentation id; -1: not shown - // OpenGL info - float texrepeat[2]; // texture repetition for 2D mapping + // spatial transform float size[3]; // size parameters float pos[3]; // Cartesian position float mat[9]; // Cartesian orientation + + // material properties float rgba[4]; // color and transparency float emission; // emission coef float specular; // specular coef float shininess; // shininess coef float reflectance; // reflectance coef + char label[100]; // text label // transparency rendering (set internally) diff --git a/introspect/structs.py b/introspect/structs.py index 3361ba28..be847f78 100644 --- a/introspect/structs.py +++ b/introspect/structs.py @@ -5483,14 +5483,9 @@ STRUCTS: Mapping[str, StructDecl] = dict([ doc='visual category', ), StructFieldDecl( - name='texid', + name='matid', type=ValueType(name='int'), - doc='texture id; -1: no texture', - ), - StructFieldDecl( - name='texuniform', - type=ValueType(name='int'), - doc='uniform cube mapping', + doc='material id; -1: no textured material', ), StructFieldDecl( name='texcoord', @@ -5502,14 +5497,6 @@ STRUCTS: Mapping[str, StructDecl] = dict([ type=ValueType(name='int'), doc='segmentation id; -1: not shown', ), - StructFieldDecl( - name='texrepeat', - type=ArrayType( - inner_type=ValueType(name='float'), - extents=(2,), - ), - doc='texture repetition for 2D mapping', - ), StructFieldDecl( name='size', type=ArrayType( @@ -7957,7 +7944,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([ StructFieldDecl( name='offDepthStencil_r', type=ValueType(name='unsigned int'), - doc='offscreen depth and stencil buffer for resolving multisamples', # pylint: disable=line-too-long + doc='offscreen depth and stencil buffer for multisamples', ), StructFieldDecl( name='shadowFBO', @@ -8001,6 +7988,30 @@ STRUCTS: Mapping[str, StructDecl] = dict([ ), doc='auxiliary color buffer for resolving', ), + StructFieldDecl( + name='mat_texid', + type=ArrayType( + inner_type=ValueType(name='int'), + extents=(600,), + ), + doc='material texture ids (-1: no texture)', + ), + StructFieldDecl( + name='mat_texuniform', + type=ArrayType( + inner_type=ValueType(name='int'), + extents=(100,), + ), + doc='texture repetition for 2d mapping', + ), + StructFieldDecl( + name='mat_texrepeat', + type=ArrayType( + inner_type=ValueType(name='int'), + extents=(200,), + ), + doc='texture repetition for 2d mapping', + ), StructFieldDecl( name='ntexture', type=ValueType(name='int'), @@ -8035,12 +8046,12 @@ STRUCTS: Mapping[str, StructDecl] = dict([ StructFieldDecl( name='baseHField', type=ValueType(name='unsigned int'), - doc='all hfields from model', + doc='all height fields from model', ), StructFieldDecl( name='baseBuiltin', type=ValueType(name='unsigned int'), - doc='all buildin geoms, with quality from model', + doc='all builtin geoms, with quality from model', ), StructFieldDecl( name='baseFontNormal', diff --git a/python/mujoco/render.cc b/python/mujoco/render.cc index 8be1fc69..c621cd0e 100644 --- a/python/mujoco/render.cc +++ b/python/mujoco/render.cc @@ -54,6 +54,9 @@ class MjWrapper : 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), @@ -238,6 +247,9 @@ PYBIND11_MODULE(_render, pymodule) { 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/python/mujoco/structs.cc b/python/mujoco/structs.cc index 12412acb..a0a81a11 100644 --- a/python/mujoco/structs.cc +++ b/python/mujoco/structs.cc @@ -1078,7 +1078,6 @@ MjvGLCameraWrapper::MjWrapper(const MjvGLCameraWrapper& other) #define X(var) var(InitPyArray(ptr_->var, owner_)) MjvGeomWrapper::MjWrapper() : WrapperBase(new raw::MjvGeom{}), - X(texrepeat), X(size), X(pos), mat([this]() { @@ -1091,7 +1090,6 @@ MjvGeomWrapper::MjWrapper() MjvGeomWrapper::MjWrapper(raw::MjvGeom* ptr, py::handle owner) : WrapperBase(ptr, owner), - X(texrepeat), X(size), X(pos), mat([this]() { @@ -2214,8 +2212,7 @@ This is useful for example when the MJB is not available as a file on disk.)")); X(objtype); X(objid); X(category); - X(texid); - X(texuniform); + X(matid); X(texcoord); X(segid); X(emission); @@ -2228,7 +2225,6 @@ This is useful for example when the MJB is not available as a file on disk.)")); #undef X #define X(var) DefinePyArray(mjvGeom, #var, &MjvGeomWrapper::var) - X(texrepeat); X(size); X(pos); X(mat); diff --git a/python/mujoco/structs.h b/python/mujoco/structs.h index 9d3fe2b9..70e399ce 100644 --- a/python/mujoco/structs.h +++ b/python/mujoco/structs.h @@ -734,7 +734,7 @@ class MjWrapper : public WrapperBase { py_array_or_tuple_t< \ std::remove_all_extents_t> \ var - X(texrepeat); + X(matid); X(size); X(pos); X(mat); diff --git a/python/mujoco/usd/component.py b/python/mujoco/usd/component.py index 044689ab..77f3e21e 100644 --- a/python/mujoco/usd/component.py +++ b/python/mujoco/usd/component.py @@ -258,17 +258,10 @@ class USDPrimitiveMesh: assert self.prim_mesh - x_scale, y_scale = self.geom.texrepeat - mesh_texcoord = np.array(self.prim_mesh.triangle_uvs) mesh_facetexcoord = np.asarray(self.prim_mesh.triangles) - x_multiplier, y_multiplier = 1, 1 - if self.geom.texuniform: - x_multiplier, y_multiplier = self.geom.size[:2] - - mesh_texcoord[:, 0] *= x_scale * x_multiplier - mesh_texcoord[:, 1] *= y_scale * y_multiplier + # TODO(etom): bring back support for rescaling the texture coordinates. return mesh_texcoord, mesh_facetexcoord.flatten() diff --git a/python/mujoco/usd/exporter.py b/python/mujoco/usd/exporter.py index 33513ec2..d654b730 100644 --- a/python/mujoco/usd/exporter.py +++ b/python/mujoco/usd/exporter.py @@ -232,7 +232,11 @@ class USDExporter: geom_name = mujoco.mj_id2name(self.model, geom.objtype, geom.objid) assert geom_name not in self.geom_name2usd - texture_file = self.texture_files[geom.texid] if geom.texid != -1 else None + texture_file = ( + self.texture_files[self.model.mat_texid[geom.matid]] + if geom.matid != -1 + else None + ) # handles meshes in scene if geom.type == mujoco.mjtGeom.mjGEOM_MESH: diff --git a/src/engine/engine_vis_visualize.c b/src/engine/engine_vis_visualize.c index ffed1b50..acae774e 100644 --- a/src/engine/engine_vis_visualize.c +++ b/src/engine/engine_vis_visualize.c @@ -302,21 +302,13 @@ static void setMaterial(const mjModel* m, mjvGeom* geom, int matid, const float* const mjtByte* flags) { // set material properties if given if (matid >= 0) { - f2f(geom->texrepeat, m->mat_texrepeat + 2*matid, 2); f2f(geom->rgba, m->mat_rgba + 4*matid, 4); - geom->texuniform = m->mat_texuniform[matid]; geom->emission = m->mat_emission[matid]; geom->specular = m->mat_specular[matid]; geom->shininess = m->mat_shininess[matid]; geom->reflectance = m->mat_reflectance[matid]; } - // otherwise clear texrepeat - else { - geom->texrepeat[0] = 0; - geom->texrepeat[1] = 0; - } - // use rgba if different from default, or no material given if (rgba[0] != 0.5f || rgba[1] != 0.5f || rgba[2] != 0.5f || rgba[3] != 1.0f || matid < 0) { f2f(geom->rgba, rgba, 4); @@ -324,7 +316,7 @@ static void setMaterial(const mjModel* m, mjvGeom* geom, int matid, const float* // set texture if (flags[mjVIS_TEXTURE] && matid >= 0) { - geom->texid = m->mat_texid[matid]; + geom->matid = matid; } // scale alpha for dynamic geoms only @@ -458,11 +450,8 @@ void mjv_initGeom(mjvGeom* geom, int type, const mjtNum* size, // set defaults that cannot be assigned via this function geom->dataid = -1; - geom->texid = -1; - geom->texuniform = 0; + geom->matid = -1; geom->texcoord = 0; - geom->texrepeat[0] = 1; - geom->texrepeat[1] = 1; geom->emission = 0; geom->specular = 0.5; geom->shininess = 0.5; @@ -571,7 +560,7 @@ void mjv_addGeoms(const mjModel* m, mjData* d, const mjvOption* vopt, thisgeom->texcoord = 1; } else { - thisgeom->texid = -1; + thisgeom->matid = -1; } // glow flex if selected diff --git a/src/render/render_context.c b/src/render/render_context.c index ec349b2a..e07535ad 100644 --- a/src/render/render_context.c +++ b/src/render/render_context.c @@ -1294,6 +1294,37 @@ 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)); + if (!m->nmat || !m->ntex) { + return; + } + + if (m->nmat >= mjMAXMATERIAL-1) { + mju_error("Maximum number of materials is %d", mjMAXMATERIAL); + } + for (int i=0; i < m->nmat; i++) { + if (m->mat_texid[i] >= 0) { + con->mat_texid[i*mjNTEXMAT] = m->mat_texid[i]; + 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]; + } + } + // 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", mjMAXMATERIAL); + } + con->mat_texid[mjNTEXMAT * (mjMAXMATERIAL-1)] = i; + break; + } + } +} // make textures @@ -1585,6 +1616,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/render_gl3.c b/src/render/render_gl3.c index 4591c4bb..598161fb 100644 --- a/src/render/render_gl3.c +++ b/src/render/render_gl3.c @@ -61,6 +61,10 @@ 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; + if (geom) { + texid = (geom->matid == -1) ? -1 : con->mat_texid[mjNTEXMAT * geom->matid]; + } // shadow if (type == mjtexSHADOW) { @@ -92,7 +96,7 @@ static void settexture(int type, int state, const mjrContext* con, const mjvGeom if (state) { glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, con->texture[geom->texid]); + glBindTexture(GL_TEXTURE_2D, con->texture[texid]); } // disable @@ -103,18 +107,18 @@ static void settexture(int type, int state, const mjrContext* con, const mjvGeom } // 2D - else if (type == mjtexREGULAR && con->textureType[geom->texid] == mjTEXTURE_2D) { + else if (type == mjtexREGULAR && con->textureType[texid] == mjTEXTURE_2D) { // enable if (state) { glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); - glBindTexture(GL_TEXTURE_2D, con->texture[geom->texid]); + 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] = con->mat_texrepeat[geom->matid*2]; + scl[1] = con->mat_texrepeat[geom->matid*2+1]; if (geom->dataid >= 0) { if (geom->size[0] > 0) { scl[0] = scl[0] / mju_max(mjMINVAL, geom->size[0]); @@ -126,7 +130,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 (con->mat_texuniform[geom->matid]) { if (geom->size[0] > 0) { scl[0] = scl[0] * geom->size[0]; } @@ -161,15 +165,15 @@ static void settexture(int type, int state, const mjrContext* con, const mjvGeom glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_GEN_R); - glBindTexture(GL_TEXTURE_CUBE_MAP, con->texture[geom->texid]); + glBindTexture(GL_TEXTURE_CUBE_MAP, con->texture[texid]); // set mapping : cube if (type == mjtexREGULAR) { - mjr_setf4(plane, geom->texuniform ? geom->size[0] : 1, 0, 0, 0); + mjr_setf4(plane, con->mat_texuniform[geom->matid] ? 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, con->mat_texuniform[geom->matid] ? 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, con->mat_texuniform[geom->matid] ? geom->size[2] : 1, 0); glTexGenfv(GL_R, GL_OBJECT_PLANE, plane); } @@ -232,7 +236,7 @@ static void renderGeom(const mjvGeom* geom, int mode, const float* headpos, behind = isBehind(headpos, geom->pos, geom->mat); // enable texture in normal and shadowmap mode - if (geom->texid >= 0 && con->ntexture > 0 && + if (geom->matid >= 0 && (mode == mjrRND_NORMAL || mode == mjrRND_SHADOWMAP)) { settexture(mjtexREGULAR, 1, con, geom); } @@ -515,14 +519,14 @@ static void renderGeom(const mjvGeom* geom, int mode, const float* headpos, glEnableClientState(GL_NORMAL_ARRAY); glVertexPointer(3, GL_FLOAT, 0, scn->flexface + 9*scn->flexfaceadr[geom->objid]); glNormalPointer(GL_FLOAT, 0, scn->flexnormal + 9*scn->flexfaceadr[geom->objid]); - if (geom->texcoord && geom->texid>=0) { + if (geom->texcoord && geom->matid>=0) { glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, scn->flextexcoord + 6*scn->flexfaceadr[geom->objid]); } glDrawArrays(GL_TRIANGLES, 0, 3*scn->flexfaceused[geom->objid]); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); - if (geom->texcoord && geom->texid>=0) { + if (geom->texcoord && geom->matid>=0) { glDisableClientState(GL_TEXTURE_COORD_ARRAY); } } @@ -568,7 +572,7 @@ static void renderGeom(const mjvGeom* geom, int mode, const float* headpos, glPopMatrix(); // disable texture if enabled - if (geom->texid >= 0 && con->ntexture > 0 && + if (geom->matid >= 0 && (mode == mjrRND_NORMAL || mode == mjrRND_SHADOWMAP)) { settexture(mjtexREGULAR, 0, con, geom); } @@ -1268,7 +1272,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.texid = i; + tempgeom.matid = mjMAXMATERIAL - 1; // modify settings glDisable(GL_LIGHTING); diff --git a/unity/Runtime/Bindings/MjBindings.cs b/unity/Runtime/Bindings/MjBindings.cs index 649005f7..c505449b 100644 --- a/unity/Runtime/Bindings/MjBindings.cs +++ b/unity/Runtime/Bindings/MjBindings.cs @@ -52,11 +52,13 @@ public const int mjNREF = 2; public const int mjNIMP = 5; public const int mjNSOLVER = 200; public const int mjNISLAND = 20; +public const int mjNTEXMAT = 6; public const bool THIRD_PARTY_MUJOCO_INCLUDE_MJPLUGIN_H_ = true; public const bool mjEXTERNC = true; public const bool THIRD_PARTY_MUJOCO_MJRENDER_H_ = true; public const int mjNAUX = 10; -public const int mjMAXTEXTURE = 1000; +public const int mjMAXTEXTURE = 100; +public const int mjMAXMATERIAL = 100; public const bool THIRD_PARTY_MUJOCO_INCLUDE_MJSPEC_H_ = true; public const bool THIRD_PARTY_MUJOCO_INCLUDE_MJTHREAD_H_ = true; public const int mjMAXTHREAD = 128; @@ -5634,6 +5636,9 @@ public unsafe struct mjrContext_ { public fixed uint auxFBO_r[10]; public fixed uint auxColor[10]; public fixed uint auxColor_r[10]; + public fixed int mat_texid[600]; + public fixed int mat_texuniform[100]; + public fixed int mat_texrepeat[200]; public int ntexture; public fixed int textureType[100]; public fixed uint texture[100]; @@ -5901,11 +5906,9 @@ public unsafe struct mjvGeom_ { public int objtype; public int objid; public int category; - public int texid; - public int texuniform; + public int matid; public int texcoord; public int segid; - public fixed float texrepeat[2]; public fixed float size[3]; public fixed float pos[3]; public fixed float mat[9];