Add optional azimuth and elevation to initial free camera.

- Add `azimuth` and `elevation` to `visual.global`.
- Add `mjv_defaultFreeCamera`.
- Use `mjv_defaultFreeCamera` in `simulate`.

PiperOrigin-RevId: 465505244
Change-Id: I61e60f14a990d4e2d220958adb75c325001978ee
This commit is contained in:
Yuval Tassa
2022-08-05 01:03:08 -07:00
committed by Copybara-Service
parent 5ee184ddaa
commit b966a37855
15 changed files with 92 additions and 19 deletions
+12 -1
View File
@@ -1230,7 +1230,7 @@ mjVisual
{
struct // global parameters
{
float fovy; // y-field of view (deg) for free camera
float fovy; // y-field of view for free camera (degrees)
float ipd; // inter-pupilary distance for free camera
float linewidth; // line width for wireframe and ray rendering
float glow; // glow coefficient for selected body
@@ -4722,6 +4722,17 @@ mjv_defaultCamera
Set default camera.
.. _mjv_defaultFreeCamera:
mjv_defaultFreeCamera
~~~~~~~~~~~~~~~~~~~~~
.. code-block:: C
void mjv_defaultFreeCamera(const mjModel* m, mjvCamera* cam);
Set default free camera.
.. _mjv_defaultPerturb:
mjv_defaultPerturb
+14 -3
View File
@@ -120,9 +120,11 @@ in the second column of the table have the following meaning:
| | | :class: mjcf-attributes |
| | | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`fovy` | :at:`ipd` | :at:`linewidth` | |
| | | | :at:`fovy` | :at:`ipd` | :at:`azimuth` | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`glow` | :at:`offwidth` | :at:`offheight` | |
| | | | :at:`elevation` | :at:`linewidth` | :at:`glow` | |
| | | +-------------------------+-------------------------+-------------------------+ |
| | | | :at:`offwidth` | :at:`offheight` | | |
| | | +-------------------------+-------------------------+-------------------------+ |
+--------------------------+----+------------------------------------------------------------------------------------+
| |_2|:el:`quality` | ? | .. table:: |
@@ -1960,6 +1962,14 @@ is effectively a miscellaneous subsection.
:at:`ipd`: :at-val:`real, "0.068"`
This attribute specifies the inter-pupilary distance of the free camera. It only affects the rendering in
stereoscopic mode. The left and right viewpoints are offset by half of this value in the corresponding direction.
:at:`azimuth`: :at-val:`real, "90"`
This attribute specifies the initial azimuth of the free camera around the vertical z-axis, in degrees. A value of 0
corresponds to looking in the positive x direction, while the default value of 90 corresponds to looking in the
positive y direction.
:at:`elevation`: :at-val:`real, "-45"`
This attribute specifies the initial elevation of the free camera with respect to the lookat point. Note that since
this is a rotation around a vector parallel to the camera's X-axis (right in pixel space), *negative* numbers
correspond to moving the camera *up* from the horizontal plane, and vice-versa.
:at:`linewidth`: :at-val:`real, "1"`
This attribute specifies the line-width in the sense of OpenGL. It affects the rendering in wire-frame mode.
:at:`glow`: :at-val:`real, "0.3"`
@@ -2216,7 +2226,8 @@ parameters.
:at:`extent`: :at-val:`real, optional`
If this attribute is specified, it replaces the value of mjModel.stat.extent computed by the compiler. The computed
value is half the side of the bounding box of the model in the initial configuration. At runtime this value is
multiplied by some of the attributes of the :ref:`map <map>` element above.
multiplied by some of the attributes of the :ref:`map <map>` element above. When the model is first loaded, the free
camera's initial distance from the :at:`center` (see below) is 1.5 times the :at:`extent`.
:at:`center`: :at-val:`real(3), optional`
If this attribute is specified, it replaces the value of mjModel.stat.center computed by the compiler. The computed
value is the center of the bounding box of the entire model in the initial configuration. This 3D vector is used to
+3
View File
@@ -16,6 +16,9 @@ General
computations. This is currently supported only for meshes.
- Raise error if the orientation of mesh faces is not consistent, which causes the inertia computations to be
inaccurate. If this occurs, open the mesh in MeshLab or Blender and recalculate the faces.
- Added ``azimuth`` and ``elevation`` attributes to :ref:`visual/global<global>`, defining the initial orientation of
the free camera at model load time.
- Added ``mjv_defaultFreeCamera`` which sets the default free camera, respecting the above attributes.
Bug fixes
^^^^^^^^^
+3 -1
View File
@@ -418,8 +418,10 @@ typedef struct mjOption_ mjOption;
struct mjVisual_ { // visualization options
struct { // global parameters
float fovy; // y-field of view (deg) for free camera
float fovy; // y-field of view for free camera (degrees)
float ipd; // inter-pupilary distance for free camera
float azimuth; // initial azimuth of free camera (degrees)
float elevation; // initial elevation of free camera (degrees)
float linewidth; // line width for wireframe and ray rendering
float glow; // glow coefficient for selected body
int offwidth; // width of offscreen buffer
+3
View File
@@ -492,6 +492,9 @@ MJAPI mjtNum mju_raySkin(int nface, int nvert, const int* face, const float* ver
// Set default camera.
MJAPI void mjv_defaultCamera(mjvCamera* cam);
// Set default free camera.
MJAPI void mjv_defaultFreeCamera(const mjModel* m, mjvCamera* cam);
// Set default perturbation.
MJAPI void mjv_defaultPerturb(mjvPerturb* pert);
+20
View File
@@ -2929,6 +2929,26 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
),
doc='Set default camera.',
)),
('mjv_defaultFreeCamera',
FunctionDecl(
name='mjv_defaultFreeCamera',
return_type=ValueType(name='void'),
parameters=(
FunctionParameterDecl(
name='m',
type=PointerType(
inner_type=ValueType(name='mjModel', is_const=True),
),
),
FunctionParameterDecl(
name='cam',
type=PointerType(
inner_type=ValueType(name='mjvCamera'),
),
),
),
doc='Set default free camera.',
)),
('mjv_defaultPerturb',
FunctionDecl(
name='mjv_defaultPerturb',
+1
View File
@@ -546,6 +546,7 @@ PYBIND11_MODULE(_functions, pymodule) {
// Interaction
Def<traits::mjv_defaultCamera>(pymodule);
Def<traits::mjv_defaultFreeCamera>(pymodule);
Def<traits::mjv_defaultPerturb>(pymodule);
Def<traits::mjv_room2model>(pymodule);
Def<traits::mjv_model2room>(pymodule);
+2 -5
View File
@@ -74,11 +74,8 @@ void initMuJoCo(const char* filename) {
mjv_makeScene(m, &scn, 2000);
mjr_makeContext(m, &con, 200);
// center and scale view
cam.lookat[0] = m->stat.center[0];
cam.lookat[1] = m->stat.center[1];
cam.lookat[2] = m->stat.center[2];
cam.distance = 1.5 * m->stat.extent;
// default free camera
mjv_defaultFreeCamera(m, &cam);
}
+3 -8
View File
@@ -904,16 +904,11 @@ void makesections(mj::Simulate* sim) {
// align and scale view
void alignscale(mj::Simulate* sim) {
// autoscale
sim->cam.lookat[0] = sim->m->stat.center[0];
sim->cam.lookat[1] = sim->m->stat.center[1];
sim->cam.lookat[2] = sim->m->stat.center[2];
sim->cam.distance = 1.5 * sim->m->stat.extent;
// set to free camera
sim->cam.type = mjCAMERA_FREE;
// use default free camera parameters
mjv_defaultFreeCamera(sim->m, &sim->cam);
}
// copy qpos to clipboard as key
void copykey(mj::Simulate* sim) {
char clipboard[5000] = "<key qpos='";
+2
View File
@@ -152,6 +152,8 @@ void mj_defaultVisual(mjVisual* vis) {
// global
vis->global.fovy = 45;
vis->global.ipd = 0.068;
vis->global.azimuth = 90;
vis->global.elevation = -45;
vis->global.linewidth = 1.0;
vis->global.glow = 0.3;
vis->global.offwidth = 640;
+17
View File
@@ -241,6 +241,23 @@ void mjv_defaultCamera(mjvCamera* cam) {
// set default free camera
void mjv_defaultFreeCamera(const mjModel* m, mjvCamera* cam) {
memset(cam, 0, sizeof(mjvCamera));
cam->type = mjCAMERA_FREE;
cam->fixedcamid = -1;
cam->trackbodyid = -1;
cam->lookat[0] = m->stat.center[0];
cam->lookat[1] = m->stat.center[1];
cam->lookat[2] = m->stat.center[2];
cam->distance = 1.5 * m->stat.extent;
cam->azimuth = m->vis.global.azimuth;
cam->elevation = m->vis.global.elevation;
}
// set default perturbation
void mjv_defaultPerturb(mjvPerturb* pert) {
memset(pert, 0, sizeof(mjvPerturb));
+3
View File
@@ -43,6 +43,9 @@ MJAPI void mjv_freeScene(mjvScene* scn);
// set default visualization options
MJAPI void mjv_defaultOption(mjvOption* vopt);
// set default free camera
MJAPI void mjv_defaultFreeCamera(const mjModel* m, mjvCamera* cam);
// set default camera
MJAPI void mjv_defaultCamera(mjvCamera* cam);
+4 -1
View File
@@ -75,7 +75,8 @@ static const char* MJCF[nMJCF][mjXATTRNUM] = {
{"visual", "*", "0"},
{"<"},
{"global", "?", "6", "fovy", "ipd", "linewidth", "glow", "offwidth", "offheight"},
{"global", "?", "8", "fovy", "ipd", "azimuth", "elevation", "linewidth", "glow", "offwidth",
"offheight"},
{"quality", "?", "5", "shadowsize", "offsamples", "numslices", "numstacks",
"numquads"},
{"headlight", "?", "4", "ambient", "diffuse", "specular", "active"},
@@ -2034,6 +2035,8 @@ void mjXReader::Visual(XMLElement* section) {
if (name=="global") {
ReadAttr(elem, "fovy", 1, &vis->global.fovy, text);
ReadAttr(elem, "ipd", 1, &vis->global.ipd, text);
ReadAttr(elem, "azimuth", 1, &vis->global.azimuth, text);
ReadAttr(elem, "elevation", 1, &vis->global.elevation, text);
ReadAttr(elem, "linewidth", 1, &vis->global.linewidth, text);
ReadAttr(elem, "glow", 1, &vis->global.glow, text);
ReadAttrInt(elem, "offwidth", &vis->global.offwidth);
+2
View File
@@ -796,6 +796,8 @@ void mjXWriter::Visual(XMLElement* root) {
elem = InsertEnd(section, "global");
WriteAttr(elem, "fovy", 1, &vis->global.fovy, &visdef.global.fovy);
WriteAttr(elem, "ipd", 1, &vis->global.ipd, &visdef.global.ipd);
WriteAttr(elem, "azimuth", 1, &vis->global.azimuth, &visdef.global.azimuth);
WriteAttr(elem, "elevation", 1, &vis->global.elevation, &visdef.global.elevation);
WriteAttr(elem, "linewidth", 1, &vis->global.linewidth, &visdef.global.linewidth);
WriteAttr(elem, "glow", 1, &vis->global.glow, &visdef.global.glow);
WriteAttrInt(elem, "offwidth", vis->global.offwidth, visdef.global.offwidth);
+3
View File
@@ -3009,6 +3009,9 @@ public static unsafe extern double mju_raySkin(int nface, int nvert, int* face,
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern void mjv_defaultCamera(mjvCamera_* cam);
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern void mjv_defaultFreeCamera(mjModel_* m, mjvCamera_* cam);
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern void mjv_defaultPerturb(mjvPerturb_* pert);