Add frustum visualization for orthographic cameras.
PiperOrigin-RevId: 847698917 Change-Id: I13633e8ba2d4718b127a5838c404ab74c6180e3d
This commit is contained in:
committed by
Copybara-Service
parent
158525269b
commit
c7f5766345
@@ -2976,12 +2976,19 @@ and the +Y axis points up. Thus the frame position and orientation are the key a
|
|||||||
for most scenes and should likely be reduced. In either case, the horizontal field of view is computed automatically
|
for most scenes and should likely be reduced. In either case, the horizontal field of view is computed automatically
|
||||||
given the window size and the vertical field of view.
|
given the window size and the vertical field of view.
|
||||||
|
|
||||||
|
.. _body-camera-resolution:
|
||||||
|
|
||||||
|
:at:`resolution`: :at-val:`int(2), "1 1"`
|
||||||
|
Resolution of the camera in pixels [width height]. Note that these values are not used for rendering since those
|
||||||
|
dimensions are determined by the size of the rendering context. This attribute serves as a convenient
|
||||||
|
location to save the required resolution. Setting either value larger than 1
|
||||||
|
enables frustum visualization when the :ref:`mjVIS_CAMERA<mjtVisFlag>` visualization flag is active.
|
||||||
|
|
||||||
.. _body-camera-sensorsize:
|
.. _body-camera-sensorsize:
|
||||||
|
|
||||||
:at:`sensorsize`: :at-val:`real(2), "0 0"`
|
:at:`sensorsize`: :at-val:`real(2), "0 0"`
|
||||||
Size of the camera sensor in length units. When specified, all intrinsic attributes become active and :at:`fovy`
|
Size of the camera sensor in length units. When specified, all intrinsic attributes become active and :at:`fovy`
|
||||||
is ignored. The field-of-view is then computed automatically from the focal length and sensor size. This
|
is ignored. The field-of-view is then computed automatically from the focal length and sensor size.
|
||||||
also enables frustum visualization when the :ref:`mjVIS_CAMERA<mjtVisFlag>` visualization flag is active.
|
|
||||||
|
|
||||||
.. _body-camera-focal:
|
.. _body-camera-focal:
|
||||||
.. _body-camera-focalpixel:
|
.. _body-camera-focalpixel:
|
||||||
@@ -2998,13 +3005,6 @@ and the +Y axis points up. Thus the frame position and orientation are the key a
|
|||||||
specified, the pixel value is used. At zero offset, the rendered image is centered on the camera's negative Z axis,
|
specified, the pixel value is used. At zero offset, the rendered image is centered on the camera's negative Z axis,
|
||||||
as in a standard pinhole camera model.
|
as in a standard pinhole camera model.
|
||||||
|
|
||||||
.. _body-camera-resolution:
|
|
||||||
|
|
||||||
:at:`resolution`: :at-val:`int(2), "1 1"`
|
|
||||||
Resolution of the camera in pixels [width height]. Note that these values are not used for rendering since those
|
|
||||||
dimensions are determined by the size of the rendering context. This attribute serves as a convenient
|
|
||||||
location to save the required resolution when creating a context.
|
|
||||||
|
|
||||||
.. _body-camera-ipd:
|
.. _body-camera-ipd:
|
||||||
|
|
||||||
:at:`ipd`: :at-val:`real, "0.068"`
|
:at:`ipd`: :at-val:`real, "0.068"`
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ Upcoming version (not yet released)
|
|||||||
|
|
||||||
General
|
General
|
||||||
^^^^^^^
|
^^^^^^^
|
||||||
|
- Camera frustum visualization is now triggered by setting :ref:`resolution<body-camera-resolution>` to values larger
|
||||||
|
than 1. Relatedly, frustum visualization also works for :ref:`orthographic<body-camera-projection>` cameras.
|
||||||
- Non-breaking ABI changes:
|
- Non-breaking ABI changes:
|
||||||
|
|
||||||
- The type of the ``sig`` (signature) argument of :ref:`mj_stateSize` and related functions has been changed from
|
- The type of the ``sig`` (signature) argument of :ref:`mj_stateSize` and related functions has been changed from
|
||||||
|
|||||||
@@ -539,21 +539,13 @@ void mjv_cameraFrustum(float zver[2], float zhor[2], float zclip[2], const mjMod
|
|||||||
const float znear = m->vis.map.znear * m->stat.extent;
|
const float znear = m->vis.map.znear * m->stat.extent;
|
||||||
|
|
||||||
if (orthographic) {
|
if (orthographic) {
|
||||||
if (zver) {
|
if (zver) zver[0] = zver[1] = fovy / 2;
|
||||||
zver[0] = zver[1] = fovy / 2;
|
if (zhor) zhor[0] = zhor[1] = 0.0f;
|
||||||
}
|
|
||||||
if (zhor) {
|
|
||||||
zhor[0] = zhor[1] = 0.0f;
|
|
||||||
}
|
|
||||||
} else if (intrinsic) {
|
} else if (intrinsic) {
|
||||||
getFrustum(zver, zhor, znear, intrinsic, sensorsize);
|
getFrustum(zver, zhor, znear, intrinsic, sensorsize);
|
||||||
} else {
|
} else {
|
||||||
if (zver) {
|
if (zver) zver[0] = zver[1] = znear * mju_tan(fovy * mjPI/360.0);
|
||||||
zver[0] = zver[1] = znear * mju_tan(fovy * mjPI/360.0);
|
if (zhor) zhor[0] = zhor[1] = 0.0f;
|
||||||
}
|
|
||||||
if (zhor) {
|
|
||||||
zhor[0] = zhor[1] = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zclip) {
|
if (zclip) {
|
||||||
@@ -2232,8 +2224,8 @@ static void addCameraGeoms(const mjModel* m, mjData* d, const mjvOption* vopt, m
|
|||||||
float cam_rgba[4];
|
float cam_rgba[4];
|
||||||
f2f(cam_rgba, m->vis.rgba.camera, 4);
|
f2f(cam_rgba, m->vis.rgba.camera, 4);
|
||||||
|
|
||||||
// draw frustum if sensorsize is defined
|
// draw frustum if resolution larger than (1, 1)
|
||||||
if (m->cam_sensorsize[2*i+1] > 0) {
|
if (m->cam_resolution[2*i] > 1 || m->cam_resolution[2*i+1] > 1) {
|
||||||
// when drawing frustum, make camera translucent
|
// when drawing frustum, make camera translucent
|
||||||
cam_rgba[3] = 0.3;
|
cam_rgba[3] = 0.3;
|
||||||
|
|
||||||
@@ -2244,9 +2236,22 @@ static void addCameraGeoms(const mjModel* m, mjData* d, const mjvOption* vopt, m
|
|||||||
mjtNum znear = m->vis.map.znear * m->stat.extent;
|
mjtNum znear = m->vis.map.znear * m->stat.extent;
|
||||||
mjtNum zfar = m->vis.scale.frustum * scl;
|
mjtNum zfar = m->vis.scale.frustum * scl;
|
||||||
float zver[2], zhor[2];
|
float zver[2], zhor[2];
|
||||||
|
int orthographic = m->cam_projection[i] == mjPROJ_ORTHOGRAPHIC;
|
||||||
|
|
||||||
// get frustum
|
// get frustum
|
||||||
getFrustum(zver, zhor, znear, m->cam_intrinsic + 4*i, m->cam_sensorsize + 2*i);
|
if (orthographic) {
|
||||||
|
float aspect = (float)m->cam_resolution[2*i] / m->cam_resolution[2*i+1];
|
||||||
|
zver[0] = zver[1] = m->cam_fovy[i] / 2;
|
||||||
|
zhor[0] = zhor[1] = m->cam_fovy[i] * aspect / 2;
|
||||||
|
} else if (m->cam_sensorsize[2*i] && m->cam_sensorsize[2*i+1]) {
|
||||||
|
// intrinsic-based perspective camera
|
||||||
|
getFrustum(zver, zhor, znear, m->cam_intrinsic+4*i, m->cam_sensorsize+2*i);
|
||||||
|
} else {
|
||||||
|
// fovy-based perspective camera
|
||||||
|
float aspect = (float)m->cam_resolution[2*i] / m->cam_resolution[2*i+1];
|
||||||
|
zver[0] = zver[1] = znear * mju_tan(m->cam_fovy[i] * mjPI / 360.0);
|
||||||
|
zhor[0] = zhor[1] = zver[0] * aspect;
|
||||||
|
}
|
||||||
|
|
||||||
// frustum frame to convert from planes to vertex representation
|
// frustum frame to convert from planes to vertex representation
|
||||||
mjtNum* cam_xpos = d->cam_xpos+3*i;
|
mjtNum* cam_xpos = d->cam_xpos+3*i;
|
||||||
@@ -2266,11 +2271,15 @@ static void addCameraGeoms(const mjModel* m, mjData* d, const mjvOption* vopt, m
|
|||||||
mju_addToScl3(vnear[2], y, zver[1]);
|
mju_addToScl3(vnear[2], y, zver[1]);
|
||||||
mju_addToScl3(vnear[3], y, zver[1]);
|
mju_addToScl3(vnear[3], y, zver[1]);
|
||||||
|
|
||||||
// vertices of the far plane
|
// vertices of the far plane: scale for perspective, average(width, height) for orthographic
|
||||||
zhor[0] *= zfar / znear;
|
if (!orthographic) {
|
||||||
zhor[1] *= zfar / znear;
|
zhor[0] *= zfar / znear;
|
||||||
zver[0] *= zfar / znear;
|
zhor[1] *= zfar / znear;
|
||||||
zver[1] *= zfar / znear;
|
zver[0] *= zfar / znear;
|
||||||
|
zver[1] *= zfar / znear;
|
||||||
|
} else {
|
||||||
|
zfar = (zhor[0] + zver[0]) / 2;
|
||||||
|
}
|
||||||
mju_addScl3(center, cam_xpos, z, -zfar);
|
mju_addScl3(center, cam_xpos, z, -zfar);
|
||||||
mju_addScl3(vfar[0], center, x, -zhor[0]);
|
mju_addScl3(vfar[0], center, x, -zhor[0]);
|
||||||
mju_addScl3(vfar[1], center, x, zhor[1]);
|
mju_addScl3(vfar[1], center, x, zhor[1]);
|
||||||
|
|||||||
+3
-3
@@ -4,7 +4,7 @@
|
|||||||
<visual>
|
<visual>
|
||||||
<!-- free camera is orthorgaphic with a 5m vertical field-of-view -->
|
<!-- free camera is orthorgaphic with a 5m vertical field-of-view -->
|
||||||
<global orthographic="true" fovy="5"/>
|
<global orthographic="true" fovy="5"/>
|
||||||
<scale camera="1"/>
|
<scale camera="0.5"/>
|
||||||
</visual>
|
</visual>
|
||||||
|
|
||||||
<asset>
|
<asset>
|
||||||
@@ -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" projection="orthographic" fovy="1"/>
|
<camera name="fovy = 1" pos=".5 .5 2" projection="orthographic" fovy="1" resolution="640 480"/>
|
||||||
|
|
||||||
<!-- 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 projection="orthographic" from defaults -->
|
<camera name="fovy = 2" pos="0 0 3" fovy="2"/> <!-- inherits projection="orthographic" from defaults -->
|
||||||
</worldbody>
|
</worldbody>
|
||||||
</mujoco>
|
</mujoco>
|
||||||
|
|||||||
Reference in New Issue
Block a user