diff --git a/doc/XMLreference.rst b/doc/XMLreference.rst index bbf794a0..0ff9e211 100644 --- a/doc/XMLreference.rst +++ b/doc/XMLreference.rst @@ -2988,6 +2988,20 @@ and the +Y axis points up. Thus the frame position and orientation are the key a location to save the required resolution. Setting either value larger than 1 enables frustum visualization when the :ref:`mjVIS_CAMERA` visualization flag is active. +.. _body-camera-output: + +:at:`output`: :at-val:`[rgb, depth, distance, normal, segmentation], "rgb"` + Types of output images supported by the camera. + + - :at-val:`rgb`: RGB image. + - :at-val:`depth`: Depth image (distance from camera plane). + - :at-val:`distance`: Distance image (distance from camera origin). + - :at-val:`normal`: Surface normal image. + - :at-val:`segmentation`: Segmentation image. + + This attribute is not used for rendering, but serves as a convenient location to save the output types supported by + the camera. The :at:`output` attribute can contain multiple types, e.g. :at-val:`"rgb normal"`. + .. _body-camera-sensorsize: :at:`sensorsize`: :at-val:`real(2), "0 0"` @@ -8715,6 +8729,8 @@ if omitted. .. _default-camera-resolution: +.. _default-camera-output: + .. _default-camera-ipd: .. _default-camera-pos: diff --git a/doc/XMLschema.rst b/doc/XMLschema.rst index e750334e..e9eca9d5 100755 --- a/doc/XMLschema.rst +++ b/doc/XMLschema.rst @@ -1045,6 +1045,9 @@ .. grid-item:: :ref:`resolution` + .. grid-item:: + :ref:`output` + .. grid-item:: :ref:`pos` @@ -4705,6 +4708,9 @@ .. grid-item:: :ref:`resolution` + .. grid-item:: + :ref:`output` + .. grid-item:: :ref:`pos` diff --git a/doc/changelog.rst b/doc/changelog.rst index edb8faa9..37d7592d 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -30,6 +30,8 @@ General attribute. In this case, the sensor will cast multiple ray, one for each pixel. - Rangefinder sensors can now now report various kinds of information besides ray distances, including surface normals. See :ref:`rangefinder` for details. +- Cameras now have an :ref:`output` attribute, parsed into the ``mjModel.cam_output`` bitfield. + Unused by the renderer, it serves as a convenient location to store a camera's supported output types. - Non-breaking ABI changes: - The type of the ``sig`` (signature) argument of :ref:`mj_stateSize` and related functions has been changed from diff --git a/doc/includes/references.h b/doc/includes/references.h index 519bfe52..10a40eb1 100644 --- a/doc/includes/references.h +++ b/doc/includes/references.h @@ -786,6 +786,15 @@ typedef enum mjtRayDataField_ { // data fields returned by rangefinder sensors mjNRAYDATA // number of rangefinder sensor data fields } mjtRayDataField; +typedef enum mjtCamOutBit_ { // camera output type bitflags + mjCAMOUT_RGB = 1<<0, // RGB image + mjCAMOUT_DEPTH = 1<<1, // depth image (distance from camera plane) + mjCAMOUT_DIST = 1<<2, // distance image (distance from camera origin) + mjCAMOUT_NORMAL = 1<<3, // normal image + mjCAMOUT_SEG = 1<<4, // segmentation image + + mjNCAMOUT = 5 // number of camera output types +} mjtCamOutBit; typedef enum mjtSameFrame_ { // frame alignment of bodies with their children mjSAMEFRAME_NONE = 0, // no alignment mjSAMEFRAME_BODY, // frame is same as body frame @@ -1240,6 +1249,7 @@ struct mjModel_ { mjtNum* cam_fovy; // y field-of-view (ortho ? len : deg) (ncam x 1) mjtNum* cam_ipd; // inter-pupilary distance (ncam x 1) int* cam_resolution; // resolution: pixels [width, height] (ncam x 2) + int* cam_output; // output types (mjtCamOut bit flags) (ncam x 1) float* cam_sensorsize; // sensor size: length [width, height] (ncam x 2) float* cam_intrinsic; // [focal length; principal point] (ncam x 4) mjtNum* cam_user; // user data (ncam x nuser_cam) @@ -2117,6 +2127,7 @@ typedef struct mjsCamera_ { // camera specification // intrinsics mjtProjection proj; // camera projection type int resolution[2]; // resolution (pixel) + int output; // bit flags for output type double fovy; // y-field of view double ipd; // inter-pupillary distance float intrinsic[4]; // camera intrinsics (length) diff --git a/include/mujoco/mjmodel.h b/include/mujoco/mjmodel.h index 64036073..7118ec54 100644 --- a/include/mujoco/mjmodel.h +++ b/include/mujoco/mjmodel.h @@ -416,6 +416,17 @@ typedef enum mjtRayDataField_ { // data fields returned by rangefinder sensors } mjtRayDataField; +typedef enum mjtCamOutBit_ { // camera output type bitflags + mjCAMOUT_RGB = 1<<0, // RGB image + mjCAMOUT_DEPTH = 1<<1, // depth image (distance from camera plane) + mjCAMOUT_DIST = 1<<2, // distance image (distance from camera origin) + mjCAMOUT_NORMAL = 1<<3, // normal image + mjCAMOUT_SEG = 1<<4, // segmentation image + + mjNCAMOUT = 5 // number of camera output types +} mjtCamOutBit; + + typedef enum mjtSameFrame_ { // frame alignment of bodies with their children mjSAMEFRAME_NONE = 0, // no alignment mjSAMEFRAME_BODY, // frame is same as body frame @@ -903,6 +914,7 @@ struct mjModel_ { mjtNum* cam_fovy; // y field-of-view (ortho ? len : deg) (ncam x 1) mjtNum* cam_ipd; // inter-pupilary distance (ncam x 1) int* cam_resolution; // resolution: pixels [width, height] (ncam x 2) + int* cam_output; // output types (mjtCamOut bit flags) (ncam x 1) float* cam_sensorsize; // sensor size: length [width, height] (ncam x 2) float* cam_intrinsic; // [focal length; principal point] (ncam x 4) mjtNum* cam_user; // user data (ncam x nuser_cam) diff --git a/include/mujoco/mjspec.h b/include/mujoco/mjspec.h index 70a0c403..b44a8711 100644 --- a/include/mujoco/mjspec.h +++ b/include/mujoco/mjspec.h @@ -375,6 +375,7 @@ typedef struct mjsCamera_ { // camera specification // intrinsics mjtProjection proj; // camera projection type int resolution[2]; // resolution (pixel) + int output; // bit flags for output type double fovy; // y-field of view double ipd; // inter-pupillary distance float intrinsic[4]; // camera intrinsics (length) diff --git a/include/mujoco/mjxmacro.h b/include/mujoco/mjxmacro.h index 077b44d3..efac7fd1 100644 --- a/include/mujoco/mjxmacro.h +++ b/include/mujoco/mjxmacro.h @@ -306,6 +306,7 @@ X ( mjtNum, cam_fovy, ncam, 1 ) \ X ( mjtNum, cam_ipd, ncam, 1 ) \ X ( int, cam_resolution, ncam, 2 ) \ + X ( int, cam_output, ncam, 1 ) \ X ( float, cam_sensorsize, ncam, 2 ) \ X ( float, cam_intrinsic, ncam, 4 ) \ X ( mjtNum, cam_user, ncam, MJ_M(nuser_cam) ) diff --git a/python/mujoco/introspect/enums.py b/python/mujoco/introspect/enums.py index 9dc5da46..2c0924b1 100644 --- a/python/mujoco/introspect/enums.py +++ b/python/mujoco/introspect/enums.py @@ -430,6 +430,19 @@ ENUMS: Mapping[str, EnumDecl] = dict([ ('mjNRAYDATA', 6), ]), )), + ('mjtCamOutBit', + EnumDecl( + name='mjtCamOutBit', + declname='enum mjtCamOutBit_', + values=dict([ + ('mjCAMOUT_RGB', 1), + ('mjCAMOUT_DEPTH', 2), + ('mjCAMOUT_DIST', 4), + ('mjCAMOUT_NORMAL', 8), + ('mjCAMOUT_SEG', 16), + ('mjNCAMOUT', 5), + ]), + )), ('mjtSameFrame', EnumDecl( name='mjtSameFrame', diff --git a/python/mujoco/introspect/structs.py b/python/mujoco/introspect/structs.py index d45c7582..bf27c58d 100644 --- a/python/mujoco/introspect/structs.py +++ b/python/mujoco/introspect/structs.py @@ -2275,6 +2275,14 @@ STRUCTS: Mapping[str, StructDecl] = dict([ doc='resolution: pixels [width, height]', array_extent=('ncam', 2), ), + StructFieldDecl( + name='cam_output', + type=PointerType( + inner_type=ValueType(name='int'), + ), + doc='output types (mjtCamOut bit flags)', + array_extent=('ncam',), + ), StructFieldDecl( name='cam_sensorsize', type=PointerType( @@ -7578,6 +7586,11 @@ STRUCTS: Mapping[str, StructDecl] = dict([ ), doc='resolution (pixel)', ), + StructFieldDecl( + name='output', + type=ValueType(name='int'), + doc='bit flags for output type', + ), StructFieldDecl( name='fovy', type=ValueType(name='double'), diff --git a/src/user/user_init.c b/src/user/user_init.c index acd9d3dd..82db341b 100644 --- a/src/user/user_init.c +++ b/src/user/user_init.c @@ -21,7 +21,6 @@ #include "user/user_api.h" - // default model attributes void mjs_defaultSpec(mjSpec* spec) { memset(spec, 0, sizeof(mjSpec)); @@ -66,14 +65,12 @@ void mjs_defaultSpec(mjSpec* spec) { } - // default orientation attributes void mjs_defaultOrientation(mjsOrientation* orient) { memset(orient, 0, sizeof(mjsOrientation)); } - // default body attributes void mjs_defaultBody(mjsBody* body) { memset(body, 0, sizeof(mjsBody)); @@ -88,7 +85,6 @@ void mjs_defaultBody(mjsBody* body) { } - // default frame attributes void mjs_defaultFrame(mjsFrame* frame) { memset(frame, 0, sizeof(mjsFrame)); @@ -96,7 +92,6 @@ void mjs_defaultFrame(mjsFrame* frame) { } - // default joint attributes void mjs_defaultJoint(mjsJoint* joint) { memset(joint, 0, sizeof(mjsJoint)); @@ -110,7 +105,6 @@ void mjs_defaultJoint(mjsJoint* joint) { } - // default geom attributes void mjs_defaultGeom(mjsGeom* geom) { memset(geom, 0, sizeof(mjsGeom)); @@ -153,7 +147,6 @@ void mjs_defaultGeom(mjsGeom* geom) { } - // default site attributes void mjs_defaultSite(mjsSite* site) { memset(site, 0, sizeof(mjsSite)); @@ -172,7 +165,6 @@ void mjs_defaultSite(mjsSite* site) { } - // default cam attributes void mjs_defaultCamera(mjsCamera* cam) { memset(cam, 0, sizeof(mjsCamera)); @@ -187,10 +179,10 @@ void mjs_defaultCamera(mjsCamera* cam) { cam->fovy = 45; cam->ipd = 0.068; cam->resolution[0] = cam->resolution[1] = 1; + cam->output = mjCAMOUT_RGB; } - // default light attributes void mjs_defaultLight(mjsLight* light) { memset(light, 0, sizeof(mjsLight)); @@ -215,7 +207,6 @@ void mjs_defaultLight(mjsLight* light) { } - // default flex attributes void mjs_defaultFlex(mjsFlex* flex) { memset(flex, 0, sizeof(mjsFlex)); @@ -242,7 +233,6 @@ void mjs_defaultFlex(mjsFlex* flex) { } - // default mesh attributes void mjs_defaultMesh(mjsMesh* mesh) { memset(mesh, 0, sizeof(mjsMesh)); @@ -253,14 +243,12 @@ void mjs_defaultMesh(mjsMesh* mesh) { } - // default height field attributes void mjs_defaultHField(mjsHField* hfield) { memset(hfield, 0, sizeof(mjsHField)); } - // default skin attributes void mjs_defaultSkin(mjsSkin* skin) { memset(skin, 0, sizeof(mjsSkin)); @@ -269,7 +257,6 @@ void mjs_defaultSkin(mjsSkin* skin) { } - // default texture attributes void mjs_defaultTexture(mjsTexture* texture) { memset(texture, 0, sizeof(mjsTexture)); @@ -285,7 +272,6 @@ void mjs_defaultTexture(mjsTexture* texture) { } - // default material attributes void mjs_defaultMaterial(mjsMaterial* material) { memset(material, 0, sizeof(mjsMaterial)); @@ -298,7 +284,6 @@ void mjs_defaultMaterial(mjsMaterial* material) { } - // default pair attributes void mjs_defaultPair(mjsPair* pair) { memset(pair, 0, sizeof(mjsPair)); @@ -312,7 +297,6 @@ void mjs_defaultPair(mjsPair* pair) { } - // default equality attributes void mjs_defaultEquality(mjsEquality* equality) { memset(equality, 0, sizeof(mjsEquality)); @@ -324,7 +308,6 @@ void mjs_defaultEquality(mjsEquality* equality) { } - // default tendon attributes void mjs_defaultTendon(mjsTendon* tendon) { memset(tendon, 0, sizeof(mjsTendon)); @@ -338,7 +321,6 @@ void mjs_defaultTendon(mjsTendon* tendon) { } - // default actuator attributes void mjs_defaultActuator(mjsActuator* actuator) { memset(actuator, 0, sizeof(mjsActuator)); @@ -364,7 +346,6 @@ void mjs_defaultActuator(mjsActuator* actuator) { } - // default sensor attributes void mjs_defaultSensor(mjsSensor* sensor) { memset(sensor, 0, sizeof(mjsSensor)); @@ -375,35 +356,30 @@ void mjs_defaultSensor(mjsSensor* sensor) { } - // Default numeric attributes. void mjs_defaultNumeric(mjsNumeric* numeric) { memset(numeric, 0, sizeof(mjsNumeric)); } - // Default text attributes. void mjs_defaultText(mjsText* text) { memset(text, 0, sizeof(mjsText)); } - // Default tuple attributes. void mjs_defaultTuple(mjsTuple* tuple) { memset(tuple, 0, sizeof(mjsTuple)); } - // Default keyframe attributes. void mjs_defaultKey(mjsKey* key) { memset(key, 0, sizeof(mjsKey)); } - // default plugin attributes void mjs_defaultPlugin(mjsPlugin* plugin) { memset(plugin, 0, sizeof(mjsPlugin)); diff --git a/src/user/user_model.cc b/src/user/user_model.cc index 4001c5cb..dc1fa88b 100644 --- a/src/user/user_model.cc +++ b/src/user/user_model.cc @@ -2868,6 +2868,7 @@ void mjCModel::CopyTree(mjModel* m) { m->cam_fovy[cid] = (mjtNum)pc->fovy; m->cam_ipd[cid] = (mjtNum)pc->ipd; mjuu_copyvec(m->cam_resolution+2*cid, pc->resolution, 2); + m->cam_output[cid] = pc->output; mjuu_copyvec(m->cam_sensorsize+2*cid, pc->sensor_size, 2); mjuu_copyvec(m->cam_intrinsic+4*cid, pc->intrinsic, 4); mjuu_copyvec(m->cam_user+nuser_cam*cid, pc->get_userdata().data(), nuser_cam); diff --git a/src/xml/xml_base.h b/src/xml/xml_base.h index 4eee0698..3a1bed5b 100644 --- a/src/xml/xml_base.h +++ b/src/xml/xml_base.h @@ -45,6 +45,7 @@ extern const int gain_sz; extern const int bias_sz; extern const int stage_sz; extern const int datatype_sz; +extern const int camout_sz; extern const int reduce_sz; extern const mjMap angle_map[]; extern const mjMap enable_map[]; @@ -77,6 +78,7 @@ extern const mjMap stage_map[]; extern const mjMap datatype_map[]; extern const mjMap condata_map[]; extern const mjMap raydata_map[]; +extern const mjMap camout_map[]; extern const mjMap reduce_map[]; extern const mjMap meshtype_map[]; extern const mjMap meshinertia_map[]; diff --git a/src/xml/xml_native_reader.cc b/src/xml/xml_native_reader.cc index 9c05102d..eb164dd3 100644 --- a/src/xml/xml_native_reader.cc +++ b/src/xml/xml_native_reader.cc @@ -171,7 +171,7 @@ std::vector MJCF[nMJCF] = { "hfield", "mesh", "fitscale", "rgba", "fluidshape", "fluidcoef", "user"}, {"site", "?", "type", "group", "pos", "quat", "material", "size", "fromto", "axisangle", "xyaxes", "zaxis", "euler", "rgba", "user"}, - {"camera", "?", "projection", "fovy", "ipd", "resolution", "pos", "quat", + {"camera", "?", "projection", "fovy", "ipd", "resolution", "output", "pos", "quat", "axisangle", "xyaxes", "zaxis", "euler", "mode", "focal", "focalpixel", "principal", "principalpixel", "sensorsize", "user"}, {"light", "?", "pos", "dir", "bulbradius", "intensity", "range", @@ -285,7 +285,7 @@ std::vector MJCF[nMJCF] = { {"attach", "*", "model", "body", "prefix"}, {"site", "*", "name", "class", "type", "group", "pos", "quat", "material", "size", "fromto", "axisangle", "xyaxes", "zaxis", "euler", "rgba", "user"}, - {"camera", "*", "name", "class", "projection", "fovy", "ipd", "resolution", "pos", + {"camera", "*", "name", "class", "projection", "fovy", "ipd", "resolution", "output", "pos", "quat", "axisangle", "xyaxes", "zaxis", "euler", "mode", "target", "focal", "focalpixel", "principal", "principalpixel", "sensorsize", "user"}, {"light", "*", "name", "class", "directional", "type", "castshadow", "active", @@ -793,6 +793,13 @@ const mjMap raydata_map[mjNRAYDATA] = { {"depth", mjRAYDATA_DEPTH} }; +// camera output type +const int camout_sz = mjNCAMOUT; +const mjMap camout_map[mjNCAMOUT] = {{"rgb", mjCAMOUT_RGB}, + {"depth", mjCAMOUT_DEPTH}, + {"distance", mjCAMOUT_DIST}, + {"normal", mjCAMOUT_NORMAL}, + {"segmentation", mjCAMOUT_SEG}}; // contact reduction type const int reduce_sz = 4; @@ -1953,6 +1960,17 @@ void mjXReader::OneCamera(XMLElement* elem, mjsCamera* camera) { ReadAttr(elem, "focalpixel", 2, camera->focal_pixel, text); ReadAttr(elem, "focal", 2, camera->focal_length, text); ReadAttr(elem, "resolution", 2, camera->resolution, text); + + // read output attribute as space-separated bitflags + std::vector outvals(mjNCAMOUT); + int nout = MapValues(elem, "output", outvals.data(), camout_map, mjNCAMOUT); + if (nout) { + camera->output = 0; + for (int i = 0; i < nout; ++i) { + camera->output |= outvals[i]; + } + } + bool sensorsize = ReadAttr(elem, "sensorsize", 2, camera->sensor_size, text); bool fovy = ReadAttr(elem, "fovy", 1, &camera->fovy, text); if (fovy && sensorsize) { diff --git a/src/xml/xml_native_writer.cc b/src/xml/xml_native_writer.cc index a2bc6961..1840f605 100644 --- a/src/xml/xml_native_writer.cc +++ b/src/xml/xml_native_writer.cc @@ -573,6 +573,19 @@ void mjXWriter::OneCamera(XMLElement* elem, const mjCCamera* camera, mjCDef* def WriteAttr(elem, "ipd", 1, &camera->ipd, &def->Camera().ipd); WriteAttrKey(elem, "mode", camlight_map, camlight_sz, camera->mode, def->Camera().mode); WriteAttr(elem, "resolution", 2, camera->resolution, def->Camera().resolution); + + // write output attribute if different from default + if (camera->output != def->Camera().output) { + int data[mjNCAMOUT]; + int ndata = 0; + for (int i = 0; i < mjNCAMOUT; i++) { + if (camera->output & camout_map[i].value) { + data[ndata++] = camout_map[i].value; + } + } + WriteAttrKeys(elem, "output", camout_map, camout_sz, data, ndata, 0); + } + WriteAttrKey(elem, "projection", projection_map, projection_sz, camera->proj, def->Camera().proj); // camera intrinsics if specified diff --git a/test/xml/xml_native_reader_test.cc b/test/xml/xml_native_reader_test.cc index 862c1743..0932f1d3 100644 --- a/test/xml/xml_native_reader_test.cc +++ b/test/xml/xml_native_reader_test.cc @@ -3244,5 +3244,51 @@ TEST_F(XMLReaderTest, LightRadius) { mj_deleteModel(model); } +TEST_F(XMLReaderTest, CameraOutput) { + static constexpr char xml[] = R"( + + + + + + + + )"; + std::array error; + mjModel* model = LoadModelFromString(xml, error.data(), error.size()); + ASSERT_THAT(model, NotNull()) << error.data(); + EXPECT_EQ(model->ncam, 3); + EXPECT_EQ(model->cam_output[0], mjCAMOUT_RGB); // default + EXPECT_EQ(model->cam_output[1], mjCAMOUT_DEPTH); + EXPECT_EQ(model->cam_output[2], + mjCAMOUT_RGB | mjCAMOUT_NORMAL | mjCAMOUT_SEG); + mj_deleteModel(model); +} + +TEST_F(XMLReaderTest, CameraOutputDefault) { + static constexpr char xml[] = R"( + + + + + + + + + + + + + )"; + std::array error; + mjModel* model = LoadModelFromString(xml, error.data(), error.size()); + ASSERT_THAT(model, NotNull()) << error.data(); + EXPECT_EQ(model->ncam, 3); + EXPECT_EQ(model->cam_output[0], mjCAMOUT_RGB); // main default + EXPECT_EQ(model->cam_output[1], mjCAMOUT_DEPTH | mjCAMOUT_DIST); + EXPECT_EQ(model->cam_output[2], mjCAMOUT_NORMAL); + mj_deleteModel(model); +} + } // namespace } // namespace mujoco diff --git a/test/xml/xml_native_writer_test.cc b/test/xml/xml_native_writer_test.cc index 82bafd81..d5181652 100644 --- a/test/xml/xml_native_writer_test.cc +++ b/test/xml/xml_native_writer_test.cc @@ -1672,5 +1672,53 @@ TEST_F(XMLWriterTest, ExpandAttach) { mj_deleteVFS(vfs.get()); } +TEST_F(XMLWriterTest, WritesCameraOutput) { + static constexpr char xml[] = R"( + + + + + + + )"; + mjModel* model = LoadModelFromString(xml); + ASSERT_THAT(model, NotNull()); + std::string saved_xml = SaveAndReadXml(model); + // default output="rgb" should not be written + EXPECT_THAT(saved_xml, Not(HasSubstr("output=\"rgb\""))); + // non-default output should be written + EXPECT_THAT(saved_xml, HasSubstr("output=\"depth normal\"")); + mj_deleteModel(model); +} + +TEST_F(XMLWriterTest, WritesCameraOutputDefault) { + static constexpr char xml[] = R"( + + + + + + + + + + + + + )"; + mjModel* model = LoadModelFromString(xml); + ASSERT_THAT(model, NotNull()); + std::string saved_xml = SaveAndReadXml(model); + // save and reload to verify round-trip + mjModel* mtemp = LoadModelFromString(saved_xml); + ASSERT_THAT(mtemp, NotNull()); + EXPECT_EQ(mtemp->ncam, 3); + EXPECT_EQ(mtemp->cam_output[0], mjCAMOUT_RGB); + EXPECT_EQ(mtemp->cam_output[1], mjCAMOUT_DEPTH | mjCAMOUT_DIST); + EXPECT_EQ(mtemp->cam_output[2], mjCAMOUT_SEG); + mj_deleteModel(mtemp); + mj_deleteModel(model); +} + } // namespace } // namespace mujoco diff --git a/unity/Runtime/Bindings/MjBindings.cs b/unity/Runtime/Bindings/MjBindings.cs index 30b42ecd..d59ea93d 100644 --- a/unity/Runtime/Bindings/MjBindings.cs +++ b/unity/Runtime/Bindings/MjBindings.cs @@ -440,6 +440,14 @@ public enum mjtRayDataField : int{ mjRAYDATA_DEPTH = 5, mjNRAYDATA = 6, } +public enum mjtCamOutBit : int{ + mjCAMOUT_RGB = 1, + mjCAMOUT_DEPTH = 2, + mjCAMOUT_DIST = 4, + mjCAMOUT_NORMAL = 8, + mjCAMOUT_SEG = 16, + mjNCAMOUT = 5, +} public enum mjtSameFrame : int{ mjSAMEFRAME_NONE = 0, mjSAMEFRAME_BODY = 1, @@ -5491,6 +5499,7 @@ public unsafe struct mjModel_ { public double* cam_fovy; public double* cam_ipd; public int* cam_resolution; + public int* cam_output; public float* cam_sensorsize; public float* cam_intrinsic; public double* cam_user; diff --git a/wasm/codegen/generated/bindings.cc b/wasm/codegen/generated/bindings.cc index e56faa41..5e00d5f2 100644 --- a/wasm/codegen/generated/bindings.cc +++ b/wasm/codegen/generated/bindings.cc @@ -3138,6 +3138,12 @@ struct MjsCamera { emscripten::val resolution() const { return emscripten::val(emscripten::typed_memory_view(2, ptr_->resolution)); } + int output() const { + return ptr_->output; + } + void set_output(int value) { + ptr_->output = value; + } double fovy() const { return ptr_->fovy; } @@ -4174,6 +4180,9 @@ struct MjModel { emscripten::val cam_resolution() const { return emscripten::val(emscripten::typed_memory_view(ptr_->ncam * 2, ptr_->cam_resolution)); } + emscripten::val cam_output() const { + return emscripten::val(emscripten::typed_memory_view(ptr_->ncam, ptr_->cam_output)); + } emscripten::val cam_sensorsize() const { return emscripten::val(emscripten::typed_memory_view(ptr_->ncam * 2, ptr_->cam_sensorsize)); } @@ -10191,6 +10200,13 @@ EMSCRIPTEN_BINDINGS(mujoco_bindings) { .value("mjCAMLIGHT_TRACKCOM", mjCAMLIGHT_TRACKCOM) .value("mjCAMLIGHT_TARGETBODY", mjCAMLIGHT_TARGETBODY) .value("mjCAMLIGHT_TARGETBODYCOM", mjCAMLIGHT_TARGETBODYCOM); + enum_("mjtCamOutBit") + .value("mjCAMOUT_RGB", mjCAMOUT_RGB) + .value("mjCAMOUT_DEPTH", mjCAMOUT_DEPTH) + .value("mjCAMOUT_DIST", mjCAMOUT_DIST) + .value("mjCAMOUT_NORMAL", mjCAMOUT_NORMAL) + .value("mjCAMOUT_SEG", mjCAMOUT_SEG) + .value("mjNCAMOUT", mjNCAMOUT); enum_("mjtCamera") .value("mjCAMERA_FREE", mjCAMERA_FREE) .value("mjCAMERA_TRACKING", mjCAMERA_TRACKING) @@ -11043,6 +11059,7 @@ EMSCRIPTEN_BINDINGS(mujoco_bindings) { .property("cam_ipd", &MjModel::cam_ipd) .property("cam_mat0", &MjModel::cam_mat0) .property("cam_mode", &MjModel::cam_mode) + .property("cam_output", &MjModel::cam_output) .property("cam_pos", &MjModel::cam_pos) .property("cam_pos0", &MjModel::cam_pos0) .property("cam_poscom0", &MjModel::cam_poscom0) @@ -11744,6 +11761,7 @@ EMSCRIPTEN_BINDINGS(mujoco_bindings) { .property("intrinsic", &MjsCamera::intrinsic) .property("ipd", &MjsCamera::ipd, &MjsCamera::set_ipd, reference()) .property("mode", &MjsCamera::mode, &MjsCamera::set_mode, reference()) + .property("output", &MjsCamera::output, &MjsCamera::set_output, reference()) .property("pos", &MjsCamera::pos) .property("principal_length", &MjsCamera::principal_length) .property("principal_pixel", &MjsCamera::principal_pixel)