LCOV - code coverage report
Current view: top level - compositor - camera.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 271 326 83.1 %
Date: 2021-04-29 23:48:07 Functions: 15 15 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2012
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / Scene Compositor sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/internal/camera.h>
      27             : 
      28             : #include <gpac/options.h>
      29             : #include "visual_manager.h"
      30             : 
      31             : #define FORCE_CAMERA_3D
      32             : 
      33         684 : void camera_invalidate(GF_Camera *cam)
      34             : {
      35             :         /*forces recompute of default viewpoint*/
      36         684 :         cam->had_viewpoint = 2;
      37         684 :         cam->had_nav_info = GF_TRUE;
      38         684 :         cam->flags = CAM_IS_DIRTY;
      39             : //      cam->navigate_mode = GF_NAVIGATE_NONE;
      40         684 : }
      41             : 
      42        2477 : static void camera_frustum_from_matrix(GF_Camera *cam, GF_Matrix *mx)
      43             : {
      44             :         u32 i;
      45             : 
      46        2477 :         cam->planes[FRUS_LEFT_PLANE].normal.x = mx->m[3] + mx->m[0];
      47        2477 :         cam->planes[FRUS_LEFT_PLANE].normal.y = mx->m[7] + mx->m[4];
      48        2477 :         cam->planes[FRUS_LEFT_PLANE].normal.z = mx->m[11] + mx->m[8];
      49        2477 :         cam->planes[FRUS_LEFT_PLANE].d = mx->m[15] + mx->m[12];
      50             : 
      51        2477 :         cam->planes[FRUS_RIGHT_PLANE].normal.x = mx->m[3] - mx->m[0];
      52        2477 :         cam->planes[FRUS_RIGHT_PLANE].normal.y = mx->m[7] - mx->m[4];
      53        2477 :         cam->planes[FRUS_RIGHT_PLANE].normal.z = mx->m[11] - mx->m[8];
      54        2477 :         cam->planes[FRUS_RIGHT_PLANE].d = mx->m[15] - mx->m[12];
      55             : 
      56        2477 :         cam->planes[FRUS_BOTTOM_PLANE].normal.x = mx->m[3] + mx->m[1];
      57        2477 :         cam->planes[FRUS_BOTTOM_PLANE].normal.y = mx->m[7] + mx->m[5];
      58        2477 :         cam->planes[FRUS_BOTTOM_PLANE].normal.z = mx->m[11] + mx->m[9];
      59        2477 :         cam->planes[FRUS_BOTTOM_PLANE].d = mx->m[15] + mx->m[13];
      60             : 
      61        2477 :         cam->planes[FRUS_TOP_PLANE].normal.x = mx->m[3] - mx->m[1];
      62        2477 :         cam->planes[FRUS_TOP_PLANE].normal.y = mx->m[7] - mx->m[5];
      63        2477 :         cam->planes[FRUS_TOP_PLANE].normal.z = mx->m[11] - mx->m[9];
      64        2477 :         cam->planes[FRUS_TOP_PLANE].d = mx->m[15] - mx->m[13];
      65             : 
      66        2477 :         cam->planes[FRUS_FAR_PLANE].normal.x = mx->m[3] - mx->m[2];
      67        2477 :         cam->planes[FRUS_FAR_PLANE].normal.y = mx->m[7] - mx->m[6];
      68        2477 :         cam->planes[FRUS_FAR_PLANE].normal.z = mx->m[11] - mx->m[10];
      69        2477 :         cam->planes[FRUS_FAR_PLANE].d = mx->m[15] - mx->m[14];
      70             : 
      71        2477 :         cam->planes[FRUS_NEAR_PLANE].normal.x = mx->m[3] + mx->m[2];
      72        2477 :         cam->planes[FRUS_NEAR_PLANE].normal.y = mx->m[7] + mx->m[6];
      73        2477 :         cam->planes[FRUS_NEAR_PLANE].normal.z = mx->m[11] + mx->m[10];
      74        2477 :         cam->planes[FRUS_NEAR_PLANE].d = mx->m[15] + mx->m[14];
      75             : 
      76       17339 :         for (i=0; i<6; ++i) {
      77             : #ifdef GPAC_FIXED_POINT
      78             :                 /*after some testing, it's just safer to move back to float here, the smallest drift will
      79             :                 result in completely wrong culling...*/
      80             :                 Float vx, vy, vz, nor;
      81             :                 vx = FIX2FLT(cam->planes[i].normal.x);
      82             :                 vy = FIX2FLT(cam->planes[i].normal.y);
      83             :                 vz = FIX2FLT(cam->planes[i].normal.z);
      84             :                 nor = (Float) sqrt(vx*vx + vy*vy + vz*vz);
      85             :                 vx /= nor;
      86             :                 vy /= nor;
      87             :                 vz /= nor;
      88             :                 cam->planes[i].d = FLT2FIX (FIX2FLT(cam->planes[i].d) / nor);
      89             :                 cam->planes[i].normal.x = FLT2FIX(vx);
      90             :                 cam->planes[i].normal.y = FLT2FIX(vy);
      91             :                 cam->planes[i].normal.z = FLT2FIX(vz);
      92             : #else
      93       14862 :                 Float len = (Float)(1.0f / gf_vec_len(cam->planes[i].normal));
      94       14862 :                 cam->planes[i].normal = gf_vec_scale(cam->planes[i].normal, len);
      95       14862 :                 cam->planes[i].d *= len;
      96             : #endif
      97             : 
      98             :                 /*compute p-vertex idx*/
      99       14862 :                 cam->p_idx[i] = gf_plane_get_p_vertex_idx(&cam->planes[i]);
     100             :         }
     101        2477 : }
     102             : 
     103             : /*based on  Copyright (C) 1995  Stephen Chenney (schenney@cs.berkeley.edu)*/
     104         158 : SFRotation camera_get_orientation(SFVec3f pos, SFVec3f target, SFVec3f up)
     105             : {
     106             :         SFVec3f dir, tmp, v, axis, new_y;
     107             :         SFVec4f norm, inv_norm, y_quat, ny_quat, rot_y, rot;
     108             : 
     109         158 :         gf_vec_diff(dir, target, pos);
     110         158 :         gf_vec_norm(&dir);
     111         158 :         tmp = gf_vec_scale(dir, gf_vec_dot(up, dir));
     112         158 :         gf_vec_diff(v, up, tmp);
     113         158 :         gf_vec_norm(&v);
     114         158 :         axis.x = dir.y;
     115         158 :         axis.y = -dir.x;
     116         158 :         axis.z = 0;
     117             : 
     118         158 :         if (gf_vec_dot(axis, axis) < FIX_EPSILON) {
     119         107 :                 if (dir.z> 0) {
     120           1 :                         norm.x = 0;
     121           1 :                         norm.y = FIX_ONE;
     122           1 :                         norm.z = 0;
     123           1 :                         norm.q = 0;
     124             :                 } else {
     125         106 :                         norm.x = 0;
     126         106 :                         norm.y = 0;
     127         106 :                         norm.z = 0;
     128         106 :                         norm.q = FIX_ONE;
     129             :                 }
     130             :         } else {
     131          51 :                 gf_vec_norm(&axis);
     132          51 :                 norm = gf_quat_from_axis_cos(axis, -dir.z);
     133             :         }
     134             :         /* Find the inverse rotation. */
     135         158 :         inv_norm.x = -norm.x;
     136         158 :         inv_norm.y = -norm.y;
     137         158 :         inv_norm.z = -norm.z;
     138         158 :         inv_norm.q = norm.q;
     139             :         /* Rotate the y. */
     140         158 :         y_quat.x = y_quat.z = y_quat.q = 0;
     141         158 :         y_quat.y = FIX_ONE;
     142         158 :         ny_quat = gf_quat_multiply(&norm, &y_quat);
     143         158 :         ny_quat = gf_quat_multiply(&ny_quat, &inv_norm);
     144             : 
     145         158 :         new_y.x = ny_quat.x;
     146         158 :         new_y.y = ny_quat.y;
     147         158 :         new_y.z = ny_quat.z;
     148             : 
     149         158 :         tmp = gf_vec_cross(new_y, v);
     150             : 
     151         158 :         if (gf_vec_dot(tmp, tmp) < FIX_EPSILON) {
     152             :                 /* The old and new may be pointing in the same or opposite. Need
     153             :                 ** to generate a vector perpendicular to the old or new y.
     154             :                 */
     155         142 :                 tmp.x = 0;
     156         142 :                 tmp.y = -v.z;
     157         142 :                 tmp.z = v.y;
     158         142 :                 if (gf_vec_dot(tmp, tmp) < FIX_EPSILON) {
     159           0 :                         tmp.x = v.z;
     160           0 :                         tmp.y = 0;
     161           0 :                         tmp.z = -v.x;
     162             :                 }
     163             :         }
     164         158 :         gf_vec_norm(&tmp);
     165             : 
     166         158 :         rot_y = gf_quat_from_axis_cos(tmp, gf_vec_dot(new_y, v));
     167             : 
     168             :         /* rot_y holds the rotation about the initial camera direction needed
     169             :         ** to align the up vectors in the final position.
     170             :         */
     171             : 
     172             :         /* Put the 2 rotations together. */
     173         158 :         rot = gf_quat_multiply(&rot_y, &norm);
     174         158 :         return gf_quat_to_rotation(&rot);
     175             : }
     176             : 
     177             : #define FAR_PLANE_2D    -10000
     178             : #define NEAR_PLANE_2D   1000
     179             : 
     180         587 : void camera_set_2d(GF_Camera *cam)
     181             : {
     182         587 :         cam->is_3D = GF_FALSE;
     183             : #ifdef FORCE_CAMERA_3D
     184         587 :         cam->position.x = cam->position.y = 0;
     185         587 :         cam->position.z = INT2FIX(NEAR_PLANE_2D);
     186         587 :         cam->up.x = cam->up.z = 0;
     187         587 :         cam->up.y = FIX_ONE;
     188         587 :         cam->target.x = cam->target.y = cam->target.z = 0;
     189         587 :         cam->vp_position = cam->position;
     190         587 :         cam->vp_orientation.x = cam->vp_orientation.y = 0;
     191         587 :         cam->vp_orientation.q = 0;
     192         587 :         cam->vp_orientation.y = FIX_ONE;
     193         587 :         cam->vp_fov = cam->fieldOfView = FLT2FIX(0.785398);
     194         587 :         cam->vp_dist = INT2FIX(NEAR_PLANE_2D);
     195         587 :         cam->end_zoom = FIX_ONE;
     196             : #endif
     197         587 : }
     198             : 
     199       10367 : void camera_update_stereo(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coords, Fixed horizontal_shift, Fixed nominal_view_distance, Fixed view_distance_offset, u32 camlay)
     200             : {
     201             :         Fixed vlen, h, w, ar;
     202             :         SFVec3f corner, center;
     203             :         GF_Matrix post_model_view;
     204             : 
     205       18257 :         if (! (cam->flags & CAM_IS_DIRTY)) return;
     206             : 
     207        2477 :         ar = gf_divfix(cam->width, cam->height);
     208        2477 :         gf_mx_init(post_model_view);
     209             : 
     210        2477 :         if (cam->is_3D) {
     211        1277 :                 if (!cam->z_far) {
     212           0 :                         cam->z_near = FIX_ONE / 100;
     213           0 :                         cam->z_far = FIX_ONE * 100;
     214             :                 }
     215             :                 /*setup perspective*/
     216        1277 :                 if (camlay==GF_3D_CAMERA_OFFAXIS) {
     217             :                         Fixed left, right, top, bottom, shift, wd2, ndfl, viewing_distance;
     218             :                         SFVec3f eye, pos, tar, disp;
     219             : 
     220             :                         viewing_distance = nominal_view_distance;
     221             : 
     222         830 :                         wd2 = gf_mulfix(cam->z_near, gf_tan(cam->fieldOfView/2));
     223         830 :                         ndfl = gf_divfix(cam->z_near, viewing_distance);
     224             :                         /*compute h displacement*/
     225         830 :                         shift = gf_mulfix(horizontal_shift, ndfl);
     226             : 
     227             :                         top = wd2;
     228             :                         bottom = -top;
     229         830 :                         left = -gf_mulfix(ar, wd2) - shift;
     230         830 :                         right = gf_mulfix(ar, wd2) - shift;
     231             : 
     232         830 :                         gf_mx_init(cam->projection);
     233         830 :                         cam->projection.m[0] = gf_divfix(2*cam->z_near, (right-left));
     234         830 :                         cam->projection.m[5] = gf_divfix(2*cam->z_near, (top-bottom));
     235         830 :                         cam->projection.m[8] = gf_divfix(right+left, right-left);
     236         830 :                         cam->projection.m[9] = gf_divfix(top+bottom, top-bottom);
     237         830 :                         cam->projection.m[10] = gf_divfix(cam->z_far+cam->z_near, cam->z_near-cam->z_far);
     238         830 :                         cam->projection.m[11] = -FIX_ONE;
     239         830 :                         cam->projection.m[14] = 2*gf_muldiv(cam->z_near, cam->z_far, cam->z_near-cam->z_far);
     240         830 :                         cam->projection.m[15] = 0;
     241             : 
     242         830 :                         gf_vec_diff(eye, cam->target, cam->position);
     243         830 :                         gf_vec_norm(&eye);
     244         830 :                         disp = gf_vec_cross(eye, cam->up);
     245         830 :                         gf_vec_norm(&disp);
     246             : 
     247         830 :                         gf_vec_diff(center, cam->world_bbox.center, cam->position);
     248         830 :                         vlen = gf_vec_len(center);
     249         830 :                         shift = gf_mulfix(horizontal_shift, gf_divfix(vlen, viewing_distance));
     250             : 
     251         830 :                         pos = gf_vec_scale(disp, shift);
     252         830 :                         gf_vec_add(pos, pos, cam->position);
     253         830 :                         gf_vec_add(tar, pos, eye);
     254             : 
     255             :                         /*setup modelview*/
     256         830 :                         gf_mx_lookat(&cam->modelview, pos, tar, cam->up);
     257             :                 } else {
     258         447 :                         gf_mx_perspective(&cam->projection, cam->fieldOfView, ar, cam->z_near, cam->z_far);
     259             : 
     260             :                         /*setup modelview*/
     261         447 :                         gf_mx_lookat(&cam->modelview, cam->position, cam->target, cam->up);
     262             :                 }
     263             : 
     264        1277 :                 if (!center_coords) {
     265           0 :                         gf_mx_add_scale(&post_model_view, FIX_ONE, -FIX_ONE, FIX_ONE);
     266           0 :                         gf_mx_add_translation(&post_model_view, -cam->width / 2, -cam->height / 2, 0);
     267             :                 }
     268             : 
     269             :                 /*compute center and radius - CHECK ME!*/
     270        1277 :                 vlen = cam->z_far - cam->z_near;
     271        1277 :                 h = gf_mulfix(vlen , gf_tan(cam->fieldOfView / 2));
     272        1277 :                 w = gf_mulfix(h, ar);
     273             :                 center.x = 0;
     274             :                 center.y = 0;
     275        1277 :                 center.z = cam->z_near + vlen / 2;
     276             :                 corner.x = w;
     277             :                 corner.y = h;
     278             :                 corner.z = vlen;
     279        1277 :                 gf_vec_diff(corner, corner, center);
     280        1277 :                 cam->radius = gf_vec_len(corner);
     281        1277 :                 gf_vec_diff(cam->center, cam->target, cam->position);
     282        1277 :                 gf_vec_norm(&cam->center);
     283        1277 :                 cam->center = gf_vec_scale(cam->center, cam->z_near + vlen/2);
     284        1277 :                 gf_vec_add(cam->center, cam->center, cam->position);
     285             :         } else {
     286             :                 GF_BBox b;
     287             :                 Fixed hw, hh;
     288        1200 :                 hw = cam->width / 2;
     289        1200 :                 hh = cam->height / 2;
     290        1200 :                 cam->z_near = INT2FIX(NEAR_PLANE_2D);
     291        1200 :                 cam->z_far = INT2FIX(FAR_PLANE_2D);
     292             : 
     293             :                 /*setup ortho*/
     294        1200 :                 gf_mx_ortho(&cam->projection, -hw, hw, -hh, hh, cam->z_near, cam->z_far);
     295             : 
     296             :                 /*setup modelview*/
     297        2400 :                 gf_mx_init(cam->modelview);
     298             : #ifdef FORCE_CAMERA_3D
     299        1200 :                 if (! (cam->flags & CAM_NO_LOOKAT))
     300        1200 :                         gf_mx_lookat(&cam->modelview, cam->position, cam->target, cam->up);
     301             : #endif
     302             : 
     303        1200 :                 if (!center_coords) {
     304           1 :                         gf_mx_add_scale(&post_model_view, FIX_ONE, -FIX_ONE, FIX_ONE);
     305           1 :                         gf_mx_add_translation(&post_model_view, -hw, -hh, 0);
     306             :                 }
     307        1200 :                 if (user_transform) {
     308             : #ifdef FORCE_CAMERA_3D
     309         138 :                         if (! (cam->flags & CAM_NO_LOOKAT)) {
     310             :                                 GF_Matrix mx;
     311         138 :                                 gf_mx_from_mx2d(&mx, user_transform);
     312         138 :                                 mx.m[10] = mx.m[0];
     313         138 :                                 gf_mx_add_matrix(&post_model_view, &mx);
     314             :                         } else
     315             : #endif
     316           0 :                                 gf_mx_add_matrix_2d(&post_model_view, user_transform);
     317             :                 }
     318        1200 :                 if (cam->end_zoom != FIX_ONE) gf_mx_add_scale(&post_model_view, cam->end_zoom, cam->end_zoom, cam->end_zoom);
     319        1200 :                 if (cam->flags & CAM_HAS_VIEWPORT) gf_mx_add_matrix(&post_model_view, &cam->viewport);
     320             : 
     321             :                 /*compute center & radius*/
     322        1200 :                 b.max_edge.x = hw;
     323        1200 :                 b.max_edge.y = hh;
     324        1200 :                 b.min_edge.x = -hw;
     325        1200 :                 b.min_edge.y = -hh;
     326        1200 :                 b.min_edge.z = b.max_edge.z = (cam->z_near+cam->z_far) / 2;
     327        1200 :                 gf_bbox_refresh(&b);
     328        1200 :                 cam->center = b.center;
     329        1200 :                 cam->radius = b.radius;
     330             : 
     331        1200 :                 if (camlay==GF_3D_CAMERA_OFFAXIS)
     332             :                         camlay=GF_3D_CAMERA_LINEAR;
     333             :         }
     334             : 
     335        2477 :         if (camlay == GF_3D_CAMERA_CIRCULAR) {
     336             :                 GF_Matrix mx;
     337             :                 Fixed viewing_distance = nominal_view_distance;
     338             :                 SFVec3f pos, target;
     339             :                 Fixed angle;
     340             : 
     341           0 :                 gf_vec_diff(center, cam->world_bbox.center, cam->position);
     342           0 :                 vlen = gf_vec_len(center);
     343           0 :                 vlen += gf_mulfix(view_distance_offset, gf_divfix(vlen, nominal_view_distance));
     344             : 
     345           0 :                 gf_vec_diff(pos, cam->target, cam->position);
     346           0 :                 gf_vec_norm(&pos);
     347           0 :                 pos = gf_vec_scale(pos, vlen);
     348           0 :                 gf_vec_add(target, pos, cam->position);
     349             : 
     350           0 :                 gf_mx_init(mx);
     351           0 :                 gf_mx_add_translation(&mx, target.x, target.y, target.z);
     352           0 :                 angle = gf_atan2(horizontal_shift, viewing_distance);
     353           0 :                 gf_mx_add_rotation(&mx, angle, cam->up.x, cam->up.y, cam->up.z);
     354           0 :                 gf_mx_add_translation(&mx, -target.x, -target.y, -target.z);
     355             : 
     356           0 :                 pos = cam->position;
     357           0 :                 gf_mx_apply_vec(&mx, &pos);
     358             : 
     359           0 :                 gf_mx_lookat(&cam->modelview, pos, target, cam->up);
     360        2477 :         } else if (camlay == GF_3D_CAMERA_LINEAR) {
     361           0 :                 Fixed viewing_distance = nominal_view_distance + view_distance_offset;
     362             :                 GF_Vec eye, disp, pos, tar;
     363             : 
     364           0 :                 gf_vec_diff(center, cam->world_bbox.center, cam->position);
     365           0 :                 vlen = gf_vec_len(center);
     366           0 :                 vlen += gf_mulfix(view_distance_offset, gf_divfix(vlen, nominal_view_distance));
     367             : 
     368           0 :                 gf_vec_diff(eye, cam->target, cam->position);
     369           0 :                 gf_vec_norm(&eye);
     370           0 :                 tar = gf_vec_scale(eye, vlen);
     371           0 :                 gf_vec_add(tar, tar, cam->position);
     372             : 
     373           0 :                 disp = gf_vec_cross(eye, cam->up);
     374           0 :                 gf_vec_norm(&disp);
     375             : 
     376           0 :                 disp= gf_vec_scale(disp, gf_divfix(gf_mulfix(vlen, horizontal_shift), viewing_distance));
     377           0 :                 gf_vec_add(pos, cam->position, disp);
     378             : 
     379           0 :                 gf_mx_lookat(&cam->modelview, pos, tar, cam->up);
     380             :         }
     381        2477 :         gf_mx_add_matrix(&cam->modelview, &post_model_view);
     382             : 
     383             :         /*compute frustum planes*/
     384        2477 :         gf_mx_copy(cam->unprojection, cam->projection);
     385        2477 :         gf_mx_add_matrix_4x4(&cam->unprojection, &cam->modelview);
     386        2477 :         camera_frustum_from_matrix(cam, &cam->unprojection);
     387             :         /*also compute reverse PM for unprojections*/
     388        2477 :         gf_mx_inverse_4x4(&cam->unprojection);
     389        2477 :         cam->flags &= ~CAM_IS_DIRTY;
     390             : }
     391             : 
     392        9537 : void camera_update(GF_Camera *cam, GF_Matrix2D *user_transform, Bool center_coords)
     393             : {
     394        9537 :         camera_update_stereo(cam, user_transform, center_coords, 0, 0, 0, GF_3D_CAMERA_STRAIGHT);
     395        9537 : }
     396         878 : void camera_set_vectors(GF_Camera *cam, SFVec3f pos, SFRotation ori, Fixed fov)
     397             : {
     398             :         Fixed sin_a, cos_a, icos_a, tmp;
     399             : 
     400         878 :         cam->fieldOfView = fov;
     401         878 :         cam->last_pos = cam->position;
     402         878 :         cam->position = pos;
     403             :         /*compute up & target vectors in local system*/
     404         878 :         sin_a = gf_sin(ori.q);
     405         878 :         cos_a = gf_cos(ori.q);
     406         878 :         icos_a = FIX_ONE - cos_a;
     407         878 :         tmp = gf_mulfix(icos_a, ori.z);
     408         878 :         cam->target.x = gf_mulfix(ori.x, tmp) + gf_mulfix(sin_a, ori.y);
     409         878 :         cam->target.y = gf_mulfix(ori.y, tmp) - gf_mulfix(sin_a, ori.x);
     410         878 :         cam->target.z = gf_mulfix(ori.z, tmp) + cos_a;
     411         878 :         gf_vec_norm(&cam->target);
     412         878 :         cam->target = gf_vec_scale(cam->target, -cam->vp_dist);
     413         878 :         gf_vec_add(cam->target, cam->target, pos);
     414         878 :         tmp = gf_mulfix(icos_a, ori.y);
     415         878 :         cam->up.x = gf_mulfix(ori.x, tmp) - gf_mulfix(sin_a, ori.z);
     416         878 :         cam->up.y = gf_mulfix(ori.y, tmp) + cos_a;
     417         878 :         cam->up.z = gf_mulfix(ori.z, tmp) + gf_mulfix(sin_a, ori.x);
     418         878 :         gf_vec_norm(&cam->up);
     419         878 :         cam->flags |= CAM_IS_DIRTY;
     420         878 : }
     421             : 
     422         627 : void camera_reset_viewpoint(GF_Camera *cam, Bool animate)
     423             : {
     424         627 :         if (!animate || (cam->had_viewpoint==2) ) {
     425         623 :                 camera_set_vectors(cam, cam->vp_position, cam->vp_orientation, cam->vp_fov);
     426         623 :                 cam->last_pos = cam->vp_position;
     427         623 :                 cam->anim_len = 0;
     428         623 :                 return;
     429             :         }
     430             : #ifndef FORCE_CAMERA_3D
     431             :         if (cam->is_3D)
     432             : #endif
     433             :         {
     434           4 :                 cam->start_pos = cam->position;
     435           4 :                 cam->start_ori = camera_get_orientation(cam->position, cam->target, cam->up);
     436           4 :                 cam->start_fov = cam->fieldOfView;
     437           4 :                 cam->end_pos = cam->vp_position;
     438           4 :                 cam->end_ori = cam->vp_orientation;
     439           4 :                 cam->end_fov = cam->vp_fov;
     440             : 
     441           4 :                 cam->flags |= CAM_IS_DIRTY;
     442           4 :                 cam->anim_start = 0;
     443           4 :                 cam->anim_len = 1000;
     444             :         }
     445             : #ifndef FORCE_CAMERA_3D
     446             :         else {
     447             :                 cam->start_zoom = FIX_ONE;
     448             :                 cam->start_trans.x = cam->start_trans.y = 0;
     449             :                 cam->start_rot.x = cam->start_rot.y = 0;
     450             :                 cam->flags |= CAM_IS_DIRTY;
     451             :                 /*no animation on 3D viewports*/
     452             :                 cam->anim_start = cam->anim_len = 0;
     453             :         }
     454             : #endif
     455             : }
     456             : 
     457          76 : void camera_move_to(GF_Camera *cam, SFVec3f pos, SFVec3f target, SFVec3f up)
     458             : {
     459          76 :         if (!cam->anim_len) {
     460          76 :                 cam->start_pos = cam->position;
     461          76 :                 cam->start_ori = camera_get_orientation(cam->position, cam->target, cam->up);
     462          76 :                 cam->start_fov = cam->fieldOfView;
     463             :         }
     464          76 :         cam->end_pos = pos;
     465          76 :         cam->end_ori = camera_get_orientation(pos, target, up);
     466          76 :         cam->end_fov = cam->fieldOfView;
     467             : 
     468          76 :         cam->flags |= CAM_IS_DIRTY;
     469          76 :         cam->anim_start = 0;
     470          76 :         cam->anim_len = 100;
     471          76 : }
     472             : 
     473         285 : void camera_stop_anim(GF_Camera *cam)
     474             : {
     475         285 :         cam->anim_len = 0;
     476         285 : }
     477             : 
     478           1 : void camera_jump(GF_Camera *cam)
     479             : {
     480             :         /*no "double-jump" :)*/
     481           1 :         if (cam->jumping) return;
     482           1 :         cam->anim_start = 0;
     483           1 :         cam->anim_len = 1000;
     484           1 :         cam->jumping = GF_TRUE;
     485           1 :         cam->flags |= CAM_IS_DIRTY;
     486             : }
     487             : 
     488             : 
     489        8742 : Bool camera_animate(GF_Camera *cam, void *_compositor)
     490             : {
     491             :         u32 now;
     492             :         Fixed frac;
     493             :         GF_Compositor *compositor = (GF_Compositor *) _compositor;
     494        8742 :         if (!cam->anim_len) return GF_FALSE;
     495             : 
     496         106 :         now = gf_sc_get_clock(compositor);
     497             : 
     498         106 :         if (cam->jumping) {
     499           0 :                 if (!cam->anim_start) {
     500           0 :                         cam->anim_start = now;
     501           0 :                         cam->dheight = 0;
     502           0 :                         return GF_TRUE;
     503             :                 }
     504           0 :                 cam->position.y -= cam->dheight;
     505           0 :                 cam->target.y -= cam->dheight;
     506             : 
     507           0 :                 now -= cam->anim_start;
     508           0 :                 if (now > cam->anim_len) {
     509           0 :                         cam->anim_len = 0;
     510           0 :                         cam->jumping = GF_FALSE;
     511           0 :                         cam->flags |= CAM_IS_DIRTY;
     512           0 :                         return GF_TRUE;
     513             :                 }
     514           0 :                 frac = FLT2FIX ( ((Float) now) / cam->anim_len);
     515           0 :                 if (frac>FIX_ONE / 2) frac = FIX_ONE - frac;
     516           0 :                 cam->dheight = gf_mulfix(cam->avatar_size.y, frac);
     517           0 :                 cam->position.y += cam->dheight;
     518           0 :                 cam->target.y += cam->dheight;
     519           0 :                 cam->flags |= CAM_IS_DIRTY;
     520           0 :                 return GF_TRUE;
     521             :         }
     522             : 
     523         106 :         if (!cam->anim_start) {
     524           7 :                 cam->anim_start = now;
     525             :                 frac = 0;
     526             :         } else {
     527          99 :                 now -= cam->anim_start;
     528          99 :                 if (now > cam->anim_len) {
     529           4 :                         cam->anim_len = 0;
     530             : #ifndef FORCE_CAMERA_3D
     531             :                         if (cam->is_3D)
     532             : #endif
     533             :                         {
     534           4 :                                 camera_set_vectors(cam, cam->end_pos, cam->end_ori, cam->end_fov);
     535           4 :                                 cam->end_zoom = FIX_ONE;
     536             :                         }
     537             : #ifndef FORCE_CAMERA_3D
     538             :                         else {
     539             :                                 cam->flags |= CAM_IS_DIRTY;
     540             :                         }
     541             : #endif
     542             : 
     543           4 :                         if (cam->flags & CF_STORE_VP) {
     544           2 :                                 cam->flags &= ~CF_STORE_VP;
     545           2 :                                 cam->vp_position = cam->position;
     546           2 :                                 cam->vp_fov = cam->fieldOfView;
     547           2 :                                 cam->vp_orientation = camera_get_orientation(cam->position, cam->target, cam->up);
     548             :                         }
     549             :                         return GF_TRUE;
     550             :                 } else {
     551          95 :                         frac = FLT2FIX( ((Float) now) / cam->anim_len);
     552             :                 }
     553             :         }
     554             : 
     555             : #ifndef FORCE_CAMERA_3D
     556             :         if (cam->is_3D)
     557             : #endif
     558             :         {
     559             :                 SFVec3f pos, dif;
     560             :                 SFRotation rot;
     561             :                 Fixed fov;
     562         102 :                 rot = gf_sg_sfrotation_interpolate(cam->start_ori, cam->end_ori, frac);
     563         102 :                 gf_vec_diff(dif, cam->end_pos, cam->start_pos);
     564         102 :                 dif = gf_vec_scale(dif, frac);
     565         102 :                 gf_vec_add(pos, cam->start_pos, dif);
     566         102 :                 fov = gf_mulfix(cam->end_fov - cam->start_fov, frac) + cam->start_fov;
     567         102 :                 cam->end_zoom = frac + gf_mulfix((FIX_ONE-frac), cam->start_zoom);
     568         102 :                 camera_set_vectors(cam, pos, rot, fov);
     569             :         }
     570         102 :         return GF_TRUE;
     571             : }
     572             : 
     573             : 
     574        4045 : SFVec3f camera_get_pos_dir(GF_Camera *cam)
     575             : {
     576             :         SFVec3f v;
     577        4045 :         gf_vec_diff(v, cam->position, cam->target);
     578        4045 :         gf_vec_norm(&v);
     579        4045 :         return v;
     580             : }
     581        4035 : SFVec3f camera_get_target_dir(GF_Camera *cam)
     582             : {
     583             :         SFVec3f v;
     584        4035 :         gf_vec_diff(v, cam->target, cam->position);
     585        4035 :         gf_vec_norm(&v);
     586        4035 :         return v;
     587             : }
     588        3953 : SFVec3f camera_get_right_dir(GF_Camera *cam)
     589             : {
     590             :         SFVec3f v, pos;
     591        3953 :         pos = camera_get_pos_dir(cam);
     592        3953 :         v = gf_vec_cross(cam->up, pos );
     593        3953 :         gf_vec_norm(&v);
     594        3953 :         return v;
     595             : }
     596             : 
     597             : 

Generated by: LCOV version 1.13