@@ -539,21 +539,13 @@ void mjv_cameraFrustum(float zver[2], float zhor[2], float zclip[2], const mjMod
539539 const float znear = m -> vis .map .znear * m -> stat .extent ;
540540
541541 if (orthographic ) {
542- if (zver ) {
543- zver [0 ] = zver [1 ] = fovy / 2 ;
544- }
545- if (zhor ) {
546- zhor [0 ] = zhor [1 ] = 0.0f ;
547- }
542+ if (zver ) zver [0 ] = zver [1 ] = fovy / 2 ;
543+ if (zhor ) zhor [0 ] = zhor [1 ] = 0.0f ;
548544 } else if (intrinsic ) {
549545 getFrustum (zver , zhor , znear , intrinsic , sensorsize );
550546 } else {
551- if (zver ) {
552- zver [0 ] = zver [1 ] = znear * mju_tan (fovy * mjPI /360.0 );
553- }
554- if (zhor ) {
555- zhor [0 ] = zhor [1 ] = 0.0f ;
556- }
547+ if (zver ) zver [0 ] = zver [1 ] = znear * mju_tan (fovy * mjPI /360.0 );
548+ if (zhor ) zhor [0 ] = zhor [1 ] = 0.0f ;
557549 }
558550
559551 if (zclip ) {
@@ -2232,8 +2224,8 @@ static void addCameraGeoms(const mjModel* m, mjData* d, const mjvOption* vopt, m
22322224 float cam_rgba [4 ];
22332225 f2f (cam_rgba , m -> vis .rgba .camera , 4 );
22342226
2235- // draw frustum if sensorsize is defined
2236- if (m -> cam_sensorsize [2 * i + 1 ] > 0 ) {
2227+ // draw frustum if resolution larger than (1, 1)
2228+ if (m -> cam_resolution [2 * i ] > 1 || m -> cam_resolution [ 2 * i + 1 ] > 1 ) {
22372229 // when drawing frustum, make camera translucent
22382230 cam_rgba [3 ] = 0.3 ;
22392231
@@ -2244,9 +2236,22 @@ static void addCameraGeoms(const mjModel* m, mjData* d, const mjvOption* vopt, m
22442236 mjtNum znear = m -> vis .map .znear * m -> stat .extent ;
22452237 mjtNum zfar = m -> vis .scale .frustum * scl ;
22462238 float zver [2 ], zhor [2 ];
2239+ int orthographic = m -> cam_projection [i ] == mjPROJ_ORTHOGRAPHIC ;
22472240
22482241 // get frustum
2249- getFrustum (zver , zhor , znear , m -> cam_intrinsic + 4 * i , m -> cam_sensorsize + 2 * i );
2242+ if (orthographic ) {
2243+ float aspect = (float )m -> cam_resolution [2 * i ] / m -> cam_resolution [2 * i + 1 ];
2244+ zver [0 ] = zver [1 ] = m -> cam_fovy [i ] / 2 ;
2245+ zhor [0 ] = zhor [1 ] = m -> cam_fovy [i ] * aspect / 2 ;
2246+ } else if (m -> cam_sensorsize [2 * i ] && m -> cam_sensorsize [2 * i + 1 ]) {
2247+ // intrinsic-based perspective camera
2248+ getFrustum (zver , zhor , znear , m -> cam_intrinsic + 4 * i , m -> cam_sensorsize + 2 * i );
2249+ } else {
2250+ // fovy-based perspective camera
2251+ float aspect = (float )m -> cam_resolution [2 * i ] / m -> cam_resolution [2 * i + 1 ];
2252+ zver [0 ] = zver [1 ] = znear * mju_tan (m -> cam_fovy [i ] * mjPI / 360.0 );
2253+ zhor [0 ] = zhor [1 ] = zver [0 ] * aspect ;
2254+ }
22502255
22512256 // frustum frame to convert from planes to vertex representation
22522257 mjtNum * cam_xpos = d -> cam_xpos + 3 * i ;
@@ -2266,11 +2271,15 @@ static void addCameraGeoms(const mjModel* m, mjData* d, const mjvOption* vopt, m
22662271 mju_addToScl3 (vnear [2 ], y , zver [1 ]);
22672272 mju_addToScl3 (vnear [3 ], y , zver [1 ]);
22682273
2269- // vertices of the far plane
2270- zhor [0 ] *= zfar / znear ;
2271- zhor [1 ] *= zfar / znear ;
2272- zver [0 ] *= zfar / znear ;
2273- zver [1 ] *= zfar / znear ;
2274+ // vertices of the far plane: scale for perspective, average(width, height) for orthographic
2275+ if (!orthographic ) {
2276+ zhor [0 ] *= zfar / znear ;
2277+ zhor [1 ] *= zfar / znear ;
2278+ zver [0 ] *= zfar / znear ;
2279+ zver [1 ] *= zfar / znear ;
2280+ } else {
2281+ zfar = (zhor [0 ] + zver [0 ]) / 2 ;
2282+ }
22742283 mju_addScl3 (center , cam_xpos , z , - zfar );
22752284 mju_addScl3 (vfar [0 ], center , x , - zhor [0 ]);
22762285 mju_addScl3 (vfar [1 ], center , x , zhor [1 ]);
0 commit comments