Refactor camera orthographic attribute to projection enum.

PiperOrigin-RevId: 847069028
Change-Id: I7f686fe654e9b56519cab8bd2f37c9cc40091d3f
This commit is contained in:
Yuval Tassa
2025-12-20 03:27:42 -08:00
committed by Copybara-Service
parent 44c8ef890d
commit b8a4ac5d48
20 changed files with 102 additions and 44 deletions
+10
View File
@@ -166,6 +166,16 @@ elements. These values are used in ``m->geom_type`` and ``m->site_type``.
.. mujoco-include:: mjtGeom .. mujoco-include:: mjtGeom
.. _mjtProjection:
mjtProjection
~~~~~~~~~~~~~
Type of camera projection. Used in ``m->cam_projection``.
.. mujoco-include:: mjtProjection
.. _mjtCamLight: .. _mjtCamLight:
mjtCamLight mjtCamLight
+5 -5
View File
@@ -2961,11 +2961,11 @@ and the +Y axis points up. Thus the frame position and orientation are the key a
When the camera mode is "targetbody" or "targetbodycom", this attribute becomes required. It specifies which body When the camera mode is "targetbody" or "targetbodycom", this attribute becomes required. It specifies which body
should be targeted by the camera. In all other modes this attribute is ignored. should be targeted by the camera. In all other modes this attribute is ignored.
.. _body-camera-orthographic: .. _body-camera-projection:
:at:`orthographic`: :at-val:`[false, true], "false"` :at:`projection`: :at-val:`[perspective, orthographic], "perspective"`
Whether the camera uses a perspective projection (the default) or an orthographic projection. Setting this attribute Whether the camera uses a perspective (the default) or orthographic projection. Setting this
changes the semantic of the :ref:`fovy<body-camera-fovy>` attribute, see below. attribute to "orthographic" changes the semantic of the :ref:`fovy<body-camera-fovy>` attribute, see below.
.. _body-camera-fovy: .. _body-camera-fovy:
@@ -8666,7 +8666,7 @@ if omitted.
| This element sets the attributes of the dummy :ref:`site <body-site>` element of the defaults class. | This element sets the attributes of the dummy :ref:`site <body-site>` element of the defaults class.
| All site attributes are available here except: name, class. | All site attributes are available here except: name, class.
.. _default-camera-orthographic: .. _default-camera-projection:
.. _default-camera-fovy: .. _default-camera-fovy:
+2 -2
View File
@@ -302,7 +302,7 @@
| :ref:`camera | \* | :class: mjcf-attributes | | :ref:`camera | \* | :class: mjcf-attributes |
| <body-camera>` | | | | <body-camera>` | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`name<body-camera-name>` | :ref:`class<body-camera-class>` | :ref:`orthographic<body-camera-orthographic>` | :ref:`fovy<body-camera-fovy>` | | | | | | :ref:`name<body-camera-name>` | :ref:`class<body-camera-class>` | :ref:`projection<body-camera-projection>` | :ref:`fovy<body-camera-fovy>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`ipd<body-camera-ipd>` | :ref:`resolution<body-camera-resolution>` | :ref:`pos<body-camera-pos>` | :ref:`quat<body-camera-quat>` | | | | | | :ref:`ipd<body-camera-ipd>` | :ref:`resolution<body-camera-resolution>` | :ref:`pos<body-camera-pos>` | :ref:`quat<body-camera-quat>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
@@ -1490,7 +1490,7 @@
| :ref:`camera | ? | :class: mjcf-attributes | | :ref:`camera | ? | :class: mjcf-attributes |
| <default-camera>` | | | | <default-camera>` | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`orthographic<default-camera-orthographic>` | :ref:`fovy<default-camera-fovy>` | :ref:`ipd<default-camera-ipd>` | :ref:`resolution<default-camera-resolution>` | | | | | | :ref:`projection<default-camera-projection>` | :ref:`fovy<default-camera-fovy>` | :ref:`ipd<default-camera-ipd>` | :ref:`resolution<default-camera-resolution>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`pos<default-camera-pos>` | :ref:`quat<default-camera-quat>` | :ref:`axisangle<default-camera-axisangle>` | :ref:`xyaxes<default-camera-xyaxes>` | | | | | | :ref:`pos<default-camera-pos>` | :ref:`quat<default-camera-quat>` | :ref:`axisangle<default-camera-axisangle>` | :ref:`xyaxes<default-camera-xyaxes>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+12 -1
View File
@@ -5,6 +5,17 @@ Changelog
Upcoming version (not yet released) Upcoming version (not yet released)
----------------------------------- -----------------------------------
.. admonition:: Breaking API changes
:class: attention
- The ``mjModel.cam_orthographic`` field has been renamed to ``cam_projection``, with the semantic of a new enum type
:ref:`mjtProjection`. This will allow for more projection types in the future like fisheye cameras.
Relatedly, the ``camera/orthographic`` MJCF attribute for cameras has been renamed to
:ref:`camera/projection<body-camera-projection>` and now accepts the values ``orthographic`` and ``perspective``.
**Migration:** Replace ``orthographic = "false/true"`` with ``projection="perspective/orthographic"``,
respectively.
General General
^^^^^^^ ^^^^^^^
- Non-breaking ABI changes: - Non-breaking ABI changes:
@@ -793,7 +804,7 @@ General
:width: 240px :width: 240px
8. Added support for orthographic cameras. This is available for both fixed cameras and the free camera, using the 8. Added support for orthographic cameras. This is available for both fixed cameras and the free camera, using the
:ref:`camera/orthographic<body-camera-orthographic>` and :ref:`global/orthographic<visual-global-orthographic>` ``camera/orthographic`` and :ref:`global/orthographic<visual-global-orthographic>`
attributes, respectively. attributes, respectively.
9. Added :ref:`maxhullvert<asset-mesh-maxhullvert>`, the maximum number of vertices in a mesh's convex hull. 9. Added :ref:`maxhullvert<asset-mesh-maxhullvert>`, the maximum number of vertices in a mesh's convex hull.
10. Added :ref:`mj_setKeyframe` for saving the current state into a model keyframe. 10. Added :ref:`mj_setKeyframe` for saving the current state into a model keyframe.
+6 -2
View File
@@ -538,6 +538,10 @@ typedef enum mjtGeom_ { // type of geometric shape
mjGEOM_NONE = 1001 // missing geom type mjGEOM_NONE = 1001 // missing geom type
} mjtGeom; } mjtGeom;
typedef enum mjtProjection_ { // type of camera projection
mjPROJ_PERSPECTIVE = 0, // perspective
mjPROJ_ORTHOGRAPHIC // orthographic
} mjtProjection;
typedef enum mjtCamLight_ { // tracking mode for camera and light typedef enum mjtCamLight_ { // tracking mode for camera and light
mjCAMLIGHT_FIXED = 0, // pos and rot fixed in body mjCAMLIGHT_FIXED = 0, // pos and rot fixed in body
mjCAMLIGHT_TRACK, // pos tracks body, rot fixed in global mjCAMLIGHT_TRACK, // pos tracks body, rot fixed in global
@@ -1223,7 +1227,7 @@ struct mjModel_ {
mjtNum* cam_poscom0; // global position rel. to sub-com in qpos0 (ncam x 3) mjtNum* cam_poscom0; // global position rel. to sub-com in qpos0 (ncam x 3)
mjtNum* cam_pos0; // global position rel. to body in qpos0 (ncam x 3) mjtNum* cam_pos0; // global position rel. to body in qpos0 (ncam x 3)
mjtNum* cam_mat0; // global orientation in qpos0 (ncam x 9) mjtNum* cam_mat0; // global orientation in qpos0 (ncam x 9)
int* cam_orthographic; // orthographic camera; 0: no, 1: yes (ncam x 1) int* cam_projection; // projection type (mjtProjection) (ncam x 1)
mjtNum* cam_fovy; // y field-of-view (ortho ? len : deg) (ncam x 1) mjtNum* cam_fovy; // y field-of-view (ortho ? len : deg) (ncam x 1)
mjtNum* cam_ipd; // inter-pupilary distance (ncam x 1) mjtNum* cam_ipd; // inter-pupilary distance (ncam x 1)
int* cam_resolution; // resolution: pixels [width, height] (ncam x 2) int* cam_resolution; // resolution: pixels [width, height] (ncam x 2)
@@ -2102,7 +2106,7 @@ typedef struct mjsCamera_ { // camera specification
mjString* targetbody; // target body for tracking/targeting mjString* targetbody; // target body for tracking/targeting
// intrinsics // intrinsics
int orthographic; // is camera orthographic mjtProjection proj; // camera projection type
double fovy; // y-field of view double fovy; // y-field of view
double ipd; // inter-pupilary distance double ipd; // inter-pupilary distance
float intrinsic[4]; // camera intrinsics (length) float intrinsic[4]; // camera intrinsics (length)
+7 -1
View File
@@ -124,6 +124,12 @@ typedef enum mjtGeom_ { // type of geometric shape
} mjtGeom; } mjtGeom;
typedef enum mjtProjection_ { // type of camera projection
mjPROJ_PERSPECTIVE = 0, // perspective
mjPROJ_ORTHOGRAPHIC // orthographic
} mjtProjection;
typedef enum mjtCamLight_ { // tracking mode for camera and light typedef enum mjtCamLight_ { // tracking mode for camera and light
mjCAMLIGHT_FIXED = 0, // pos and rot fixed in body mjCAMLIGHT_FIXED = 0, // pos and rot fixed in body
mjCAMLIGHT_TRACK, // pos tracks body, rot fixed in global mjCAMLIGHT_TRACK, // pos tracks body, rot fixed in global
@@ -882,7 +888,7 @@ struct mjModel_ {
mjtNum* cam_poscom0; // global position rel. to sub-com in qpos0 (ncam x 3) mjtNum* cam_poscom0; // global position rel. to sub-com in qpos0 (ncam x 3)
mjtNum* cam_pos0; // global position rel. to body in qpos0 (ncam x 3) mjtNum* cam_pos0; // global position rel. to body in qpos0 (ncam x 3)
mjtNum* cam_mat0; // global orientation in qpos0 (ncam x 9) mjtNum* cam_mat0; // global orientation in qpos0 (ncam x 9)
int* cam_orthographic; // orthographic camera; 0: no, 1: yes (ncam x 1) int* cam_projection; // projection type (mjtProjection) (ncam x 1)
mjtNum* cam_fovy; // y field-of-view (ortho ? len : deg) (ncam x 1) mjtNum* cam_fovy; // y field-of-view (ortho ? len : deg) (ncam x 1)
mjtNum* cam_ipd; // inter-pupilary distance (ncam x 1) mjtNum* cam_ipd; // inter-pupilary distance (ncam x 1)
int* cam_resolution; // resolution: pixels [width, height] (ncam x 2) int* cam_resolution; // resolution: pixels [width, height] (ncam x 2)
+1 -1
View File
@@ -373,7 +373,7 @@ typedef struct mjsCamera_ { // camera specification
mjString* targetbody; // target body for tracking/targeting mjString* targetbody; // target body for tracking/targeting
// intrinsics // intrinsics
int orthographic; // is camera orthographic mjtProjection proj; // camera projection type
double fovy; // y-field of view double fovy; // y-field of view
double ipd; // inter-pupilary distance double ipd; // inter-pupilary distance
float intrinsic[4]; // camera intrinsics (length) float intrinsic[4]; // camera intrinsics (length)
+1 -1
View File
@@ -302,7 +302,7 @@
X ( mjtNum, cam_poscom0, ncam, 3 ) \ X ( mjtNum, cam_poscom0, ncam, 3 ) \
X ( mjtNum, cam_pos0, ncam, 3 ) \ X ( mjtNum, cam_pos0, ncam, 3 ) \
X ( mjtNum, cam_mat0, ncam, 9 ) \ X ( mjtNum, cam_mat0, ncam, 9 ) \
X ( int, cam_orthographic, ncam, 1 ) \ X ( int, cam_projection, ncam, 1 ) \
X ( mjtNum, cam_fovy, ncam, 1 ) \ X ( mjtNum, cam_fovy, ncam, 1 ) \
X ( mjtNum, cam_ipd, ncam, 1 ) \ X ( mjtNum, cam_ipd, ncam, 1 ) \
X ( int, cam_resolution, ncam, 2 ) \ X ( int, cam_resolution, ncam, 2 ) \
+9
View File
@@ -101,6 +101,15 @@ ENUMS: Mapping[str, EnumDecl] = dict([
('mjGEOM_NONE', 1001), ('mjGEOM_NONE', 1001),
]), ]),
)), )),
('mjtProjection',
EnumDecl(
name='mjtProjection',
declname='enum mjtProjection_',
values=dict([
('mjPROJ_PERSPECTIVE', 0),
('mjPROJ_ORTHOGRAPHIC', 1),
]),
)),
('mjtCamLight', ('mjtCamLight',
EnumDecl( EnumDecl(
name='mjtCamLight', name='mjtCamLight',
+5 -5
View File
@@ -2244,11 +2244,11 @@ STRUCTS: Mapping[str, StructDecl] = dict([
array_extent=('ncam', 9), array_extent=('ncam', 9),
), ),
StructFieldDecl( StructFieldDecl(
name='cam_orthographic', name='cam_projection',
type=PointerType( type=PointerType(
inner_type=ValueType(name='int'), inner_type=ValueType(name='int'),
), ),
doc='orthographic camera; 0: no, 1: yes', doc='projection type (mjtProjection)',
array_extent=('ncam',), array_extent=('ncam',),
), ),
StructFieldDecl( StructFieldDecl(
@@ -7566,9 +7566,9 @@ STRUCTS: Mapping[str, StructDecl] = dict([
doc='target body for tracking/targeting', doc='target body for tracking/targeting',
), ),
StructFieldDecl( StructFieldDecl(
name='orthographic', name='proj',
type=ValueType(name='int'), type=ValueType(name='mjtProjection'),
doc='is camera orthographic', doc='camera projection type',
), ),
StructFieldDecl( StructFieldDecl(
name='fovy', name='fovy',
+4 -2
View File
@@ -295,8 +295,10 @@ class SpecsTest(absltest.TestCase):
self.assertEqual(site.info, 'info') self.assertEqual(site.info, 'info')
# Add camera. # Add camera.
cam = body.add_camera(orthographic=1, resolution=[10, 20]) cam = body.add_camera(
self.assertEqual(cam.orthographic, 1) proj=mujoco.mjtProjection.mjPROJ_ORTHOGRAPHIC, resolution=[10, 20]
)
self.assertEqual(cam.proj, 1)
np.testing.assert_array_equal(cam.resolution, [10, 20]) np.testing.assert_array_equal(cam.resolution, [10, 20])
# Add frame. # Add frame.
+2 -2
View File
@@ -522,7 +522,7 @@ void mjv_cameraFrustum(float zver[2], float zhor[2], float zclip[2], const mjMod
if (cid < 0 || cid >= m->ncam) { if (cid < 0 || cid >= m->ncam) {
mjERROR("fixed camera id is outside valid range"); mjERROR("fixed camera id is outside valid range");
} }
orthographic = m->cam_orthographic[cid]; orthographic = m->cam_projection[cid] == mjPROJ_ORTHOGRAPHIC;
fovy = m->cam_fovy[cid]; fovy = m->cam_fovy[cid];
// if positive sensorsize, get sensorsize and intrinsic // if positive sensorsize, get sensorsize and intrinsic
@@ -2763,7 +2763,7 @@ void mjv_updateCamera(const mjModel* m, const mjData* d, mjvCamera* cam, mjvScen
mjERROR("fixed camera id is outside valid range"); mjERROR("fixed camera id is outside valid range");
} }
ipd = m->cam_ipd[cid]; ipd = m->cam_ipd[cid];
orthographic = m->cam_orthographic[cid]; orthographic = m->cam_projection[cid] == mjPROJ_ORTHOGRAPHIC;
break; break;
default: default:
+1 -1
View File
@@ -2864,7 +2864,7 @@ void mjCModel::CopyTree(mjModel* m) {
m->cam_targetbodyid[cid] = pc->targetbodyid; m->cam_targetbodyid[cid] = pc->targetbodyid;
mjuu_copyvec(m->cam_pos+3*cid, pc->pos, 3); mjuu_copyvec(m->cam_pos+3*cid, pc->pos, 3);
mjuu_copyvec(m->cam_quat+4*cid, pc->quat, 4); mjuu_copyvec(m->cam_quat+4*cid, pc->quat, 4);
m->cam_orthographic[cid] = pc->orthographic; m->cam_projection[cid] = pc->proj;
m->cam_fovy[cid] = (mjtNum)pc->fovy; m->cam_fovy[cid] = (mjtNum)pc->fovy;
m->cam_ipd[cid] = (mjtNum)pc->ipd; m->cam_ipd[cid] = (mjtNum)pc->ipd;
mjuu_copyvec(m->cam_resolution+2*cid, pc->resolution, 2); mjuu_copyvec(m->cam_resolution+2*cid, pc->resolution, 2);
+2
View File
@@ -27,6 +27,7 @@
// keyword maps (defined in implementation files) // keyword maps (defined in implementation files)
extern const int joint_sz; extern const int joint_sz;
extern const int bodysleep_sz; extern const int bodysleep_sz;
extern const int projection_sz;
extern const int camlight_sz; extern const int camlight_sz;
extern const int lighttype_sz; extern const int lighttype_sz;
extern const int integrator_sz; extern const int integrator_sz;
@@ -53,6 +54,7 @@ extern const mjMap TFAuto_map[];
extern const mjMap joint_map[]; extern const mjMap joint_map[];
extern const mjMap bodysleep_map[]; extern const mjMap bodysleep_map[];
extern const mjMap geom_map[]; extern const mjMap geom_map[];
extern const mjMap projection_map[];
extern const mjMap camlight_map[]; extern const mjMap camlight_map[];
extern const mjMap lighttype_map[]; extern const mjMap lighttype_map[];
extern const mjMap integrator_map[]; extern const mjMap integrator_map[];
+11 -4
View File
@@ -171,7 +171,7 @@ std::vector<const char*> MJCF[nMJCF] = {
"hfield", "mesh", "fitscale", "rgba", "fluidshape", "fluidcoef", "user"}, "hfield", "mesh", "fitscale", "rgba", "fluidshape", "fluidcoef", "user"},
{"site", "?", "type", "group", "pos", "quat", "material", {"site", "?", "type", "group", "pos", "quat", "material",
"size", "fromto", "axisangle", "xyaxes", "zaxis", "euler", "rgba", "user"}, "size", "fromto", "axisangle", "xyaxes", "zaxis", "euler", "rgba", "user"},
{"camera", "?", "orthographic", "fovy", "ipd", "resolution", "pos", "quat", {"camera", "?", "projection", "fovy", "ipd", "resolution", "pos", "quat",
"axisangle", "xyaxes", "zaxis", "euler", "mode", "focal", "focalpixel", "axisangle", "xyaxes", "zaxis", "euler", "mode", "focal", "focalpixel",
"principal", "principalpixel", "sensorsize", "user"}, "principal", "principalpixel", "sensorsize", "user"},
{"light", "?", "pos", "dir", "bulbradius", "intensity", "range", {"light", "?", "pos", "dir", "bulbradius", "intensity", "range",
@@ -285,7 +285,7 @@ std::vector<const char*> MJCF[nMJCF] = {
{"attach", "*", "model", "body", "prefix"}, {"attach", "*", "model", "body", "prefix"},
{"site", "*", "name", "class", "type", "group", "pos", "quat", {"site", "*", "name", "class", "type", "group", "pos", "quat",
"material", "size", "fromto", "axisangle", "xyaxes", "zaxis", "euler", "rgba", "user"}, "material", "size", "fromto", "axisangle", "xyaxes", "zaxis", "euler", "rgba", "user"},
{"camera", "*", "name", "class", "orthographic", "fovy", "ipd", "resolution", "pos", {"camera", "*", "name", "class", "projection", "fovy", "ipd", "resolution", "pos",
"quat", "axisangle", "xyaxes", "zaxis", "euler", "mode", "target", "quat", "axisangle", "xyaxes", "zaxis", "euler", "mode", "target",
"focal", "focalpixel", "principal", "principalpixel", "sensorsize", "user"}, "focal", "focalpixel", "principal", "principalpixel", "sensorsize", "user"},
{"light", "*", "name", "class", "directional", "type", "castshadow", "active", {"light", "*", "name", "class", "directional", "type", "castshadow", "active",
@@ -590,6 +590,13 @@ const mjMap geom_map[mjNGEOMTYPES] = {
}; };
// projection type
const int projection_sz = 2;
const mjMap projection_map[projection_sz] = {
{"perspective", mjPROJ_PERSPECTIVE},
{"orthographic", mjPROJ_ORTHOGRAPHIC}
};
// camlight type // camlight type
const int camlight_sz = 5; const int camlight_sz = 5;
const mjMap camlight_map[camlight_sz] = { const mjMap camlight_map[camlight_sz] = {
@@ -1926,8 +1933,8 @@ void mjXReader::OneCamera(XMLElement* elem, mjsCamera* camera) {
ReadAlternative(elem, camera->alt); ReadAlternative(elem, camera->alt);
ReadAttr(elem, "ipd", 1, &camera->ipd, text); ReadAttr(elem, "ipd", 1, &camera->ipd, text);
if (MapValue(elem, "orthographic", &n, bool_map, 2)) { if (MapValue(elem, "projection", &n, projection_map, 2)) {
camera->orthographic = (n == 1); camera->proj = (mjtProjection)n;
} }
bool has_principal = ReadAttr(elem, "principalpixel", 2, camera->principal_pixel, text) || bool has_principal = ReadAttr(elem, "principalpixel", 2, camera->principal_pixel, text) ||
+1 -1
View File
@@ -573,7 +573,7 @@ void mjXWriter::OneCamera(XMLElement* elem, const mjCCamera* camera, mjCDef* def
WriteAttr(elem, "ipd", 1, &camera->ipd, &def->Camera().ipd); WriteAttr(elem, "ipd", 1, &camera->ipd, &def->Camera().ipd);
WriteAttrKey(elem, "mode", camlight_map, camlight_sz, camera->mode, def->Camera().mode); WriteAttrKey(elem, "mode", camlight_map, camlight_sz, camera->mode, def->Camera().mode);
WriteAttr(elem, "resolution", 2, camera->resolution, def->Camera().resolution); WriteAttr(elem, "resolution", 2, camera->resolution, def->Camera().resolution);
WriteAttrKey(elem, "orthographic", bool_map, 2, camera->orthographic, def->Camera().orthographic); WriteAttrKey(elem, "projection", projection_map, projection_sz, camera->proj, def->Camera().proj);
// camera intrinsics if specified // camera intrinsics if specified
if (camera->sensor_size[0] > 0 && camera->sensor_size[1] > 0) { if (camera->sensor_size[0] > 0 && camera->sensor_size[1] > 0) {
+3 -3
View File
@@ -13,7 +13,7 @@
</asset> </asset>
<default> <default>
<camera orthographic="true"/> <camera projection="orthographic"/>
</default> </default>
<worldbody> <worldbody>
@@ -26,9 +26,9 @@
</body> </body>
<!-- box should pefectly fit within field-of-view --> <!-- box should pefectly fit within field-of-view -->
<camera name="fovy = 1" pos=".5 .5 2" orthographic="true" fovy="1"/> <camera name="fovy = 1" pos=".5 .5 2" projection="orthographic" fovy="1"/>
<!-- 2 floor squares should pefectly fit within field-of-view --> <!-- 2 floor squares should pefectly fit within field-of-view -->
<camera name="fovy = 2" pos="0 0 2" fovy="2"/> <!-- inherits orthographic="true" from defaults --> <camera name="fovy = 2" pos="0 0 2" fovy="2"/> <!-- inherits projection="orthographic" from defaults -->
</worldbody> </worldbody>
</mujoco> </mujoco>
+4 -4
View File
@@ -2274,11 +2274,11 @@ TEST_F(XMLReaderTest, Orthographic) {
</visual> </visual>
<default> <default>
<camera orthographic="true"/> <camera projection="orthographic"/>
</default> </default>
<worldbody> <worldbody>
<camera name="fovy=1" pos=".5 .5 2" orthographic="true" fovy="1"/> <camera name="fovy=1" pos=".5 .5 2" projection="orthographic" fovy="1"/>
<camera name="fovy=2" pos="0 0 2" fovy="2"/> <camera name="fovy=2" pos="0 0 2" fovy="2"/>
</worldbody> </worldbody>
</mujoco> </mujoco>
@@ -2288,8 +2288,8 @@ TEST_F(XMLReaderTest, Orthographic) {
EXPECT_THAT(model, NotNull()) << error.data(); EXPECT_THAT(model, NotNull()) << error.data();
EXPECT_EQ(model->vis.global.orthographic, 1); EXPECT_EQ(model->vis.global.orthographic, 1);
EXPECT_EQ(model->cam_orthographic[0], 1); EXPECT_EQ(model->cam_projection[0], mjPROJ_ORTHOGRAPHIC);
EXPECT_EQ(model->cam_orthographic[1], 1); EXPECT_EQ(model->cam_projection[1], mjPROJ_ORTHOGRAPHIC);
EXPECT_EQ(model->cam_fovy[0], 1); EXPECT_EQ(model->cam_fovy[0], 1);
EXPECT_EQ(model->cam_fovy[1], 2); EXPECT_EQ(model->cam_fovy[1], 2);
+5 -1
View File
@@ -221,6 +221,10 @@ public enum mjtGeom : int{
mjGEOM_TRIANGLE = 108, mjGEOM_TRIANGLE = 108,
mjGEOM_NONE = 1001, mjGEOM_NONE = 1001,
} }
public enum mjtProjection : int{
mjPROJ_PERSPECTIVE = 0,
mjPROJ_ORTHOGRAPHIC = 1,
}
public enum mjtCamLight : int{ public enum mjtCamLight : int{
mjCAMLIGHT_FIXED = 0, mjCAMLIGHT_FIXED = 0,
mjCAMLIGHT_TRACK = 1, mjCAMLIGHT_TRACK = 1,
@@ -5474,7 +5478,7 @@ public unsafe struct mjModel_ {
public double* cam_poscom0; public double* cam_poscom0;
public double* cam_pos0; public double* cam_pos0;
public double* cam_mat0; public double* cam_mat0;
public int* cam_orthographic; public int* cam_projection;
public double* cam_fovy; public double* cam_fovy;
public double* cam_ipd; public double* cam_ipd;
public int* cam_resolution; public int* cam_resolution;
+11 -8
View File
@@ -3129,11 +3129,11 @@ struct MjsCamera {
*(ptr_->targetbody) = value; *(ptr_->targetbody) = value;
} }
} }
int orthographic() const { mjtProjection proj() const {
return ptr_->orthographic; return ptr_->proj;
} }
void set_orthographic(int value) { void set_proj(mjtProjection value) {
ptr_->orthographic = value; ptr_->proj = value;
} }
double fovy() const { double fovy() const {
return ptr_->fovy; return ptr_->fovy;
@@ -4162,8 +4162,8 @@ struct MjModel {
emscripten::val cam_mat0() const { emscripten::val cam_mat0() const {
return emscripten::val(emscripten::typed_memory_view(ptr_->ncam * 9, ptr_->cam_mat0)); return emscripten::val(emscripten::typed_memory_view(ptr_->ncam * 9, ptr_->cam_mat0));
} }
emscripten::val cam_orthographic() const { emscripten::val cam_projection() const {
return emscripten::val(emscripten::typed_memory_view(ptr_->ncam, ptr_->cam_orthographic)); return emscripten::val(emscripten::typed_memory_view(ptr_->ncam, ptr_->cam_projection));
} }
emscripten::val cam_fovy() const { emscripten::val cam_fovy() const {
return emscripten::val(emscripten::typed_memory_view(ptr_->ncam, ptr_->cam_fovy)); return emscripten::val(emscripten::typed_memory_view(ptr_->ncam, ptr_->cam_fovy));
@@ -10503,6 +10503,9 @@ EMSCRIPTEN_BINDINGS(mujoco_bindings) {
.value("mjPLUGIN_SENSOR", mjPLUGIN_SENSOR) .value("mjPLUGIN_SENSOR", mjPLUGIN_SENSOR)
.value("mjPLUGIN_PASSIVE", mjPLUGIN_PASSIVE) .value("mjPLUGIN_PASSIVE", mjPLUGIN_PASSIVE)
.value("mjPLUGIN_SDF", mjPLUGIN_SDF); .value("mjPLUGIN_SDF", mjPLUGIN_SDF);
enum_<mjtProjection>("mjtProjection")
.value("mjPROJ_PERSPECTIVE", mjPROJ_PERSPECTIVE)
.value("mjPROJ_ORTHOGRAPHIC", mjPROJ_ORTHOGRAPHIC);
enum_<mjtRndFlag>("mjtRndFlag") enum_<mjtRndFlag>("mjtRndFlag")
.value("mjRND_SHADOW", mjRND_SHADOW) .value("mjRND_SHADOW", mjRND_SHADOW)
.value("mjRND_WIREFRAME", mjRND_WIREFRAME) .value("mjRND_WIREFRAME", mjRND_WIREFRAME)
@@ -11032,10 +11035,10 @@ EMSCRIPTEN_BINDINGS(mujoco_bindings) {
.property("cam_ipd", &MjModel::cam_ipd) .property("cam_ipd", &MjModel::cam_ipd)
.property("cam_mat0", &MjModel::cam_mat0) .property("cam_mat0", &MjModel::cam_mat0)
.property("cam_mode", &MjModel::cam_mode) .property("cam_mode", &MjModel::cam_mode)
.property("cam_orthographic", &MjModel::cam_orthographic)
.property("cam_pos", &MjModel::cam_pos) .property("cam_pos", &MjModel::cam_pos)
.property("cam_pos0", &MjModel::cam_pos0) .property("cam_pos0", &MjModel::cam_pos0)
.property("cam_poscom0", &MjModel::cam_poscom0) .property("cam_poscom0", &MjModel::cam_poscom0)
.property("cam_projection", &MjModel::cam_projection)
.property("cam_quat", &MjModel::cam_quat) .property("cam_quat", &MjModel::cam_quat)
.property("cam_resolution", &MjModel::cam_resolution) .property("cam_resolution", &MjModel::cam_resolution)
.property("cam_sensorsize", &MjModel::cam_sensorsize) .property("cam_sensorsize", &MjModel::cam_sensorsize)
@@ -11733,10 +11736,10 @@ EMSCRIPTEN_BINDINGS(mujoco_bindings) {
.property("intrinsic", &MjsCamera::intrinsic) .property("intrinsic", &MjsCamera::intrinsic)
.property("ipd", &MjsCamera::ipd, &MjsCamera::set_ipd, reference()) .property("ipd", &MjsCamera::ipd, &MjsCamera::set_ipd, reference())
.property("mode", &MjsCamera::mode, &MjsCamera::set_mode, reference()) .property("mode", &MjsCamera::mode, &MjsCamera::set_mode, reference())
.property("orthographic", &MjsCamera::orthographic, &MjsCamera::set_orthographic, reference())
.property("pos", &MjsCamera::pos) .property("pos", &MjsCamera::pos)
.property("principal_length", &MjsCamera::principal_length) .property("principal_length", &MjsCamera::principal_length)
.property("principal_pixel", &MjsCamera::principal_pixel) .property("principal_pixel", &MjsCamera::principal_pixel)
.property("proj", &MjsCamera::proj, &MjsCamera::set_proj, reference())
.property("quat", &MjsCamera::quat) .property("quat", &MjsCamera::quat)
.property("resolution", &MjsCamera::resolution) .property("resolution", &MjsCamera::resolution)
.property("sensor_size", &MjsCamera::sensor_size) .property("sensor_size", &MjsCamera::sensor_size)