LCOV - code coverage report
Current view: top level - compositor - mpeg4_viewport.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 248 300 82.7 %
Date: 2021-04-29 23:48:07 Functions: 14 15 93.3 %

          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 "nodes_stacks.h"
      27             : #include "visual_manager.h"
      28             : 
      29             : #include <gpac/options.h>
      30             : 
      31             : 
      32             : GF_EXPORT
      33           2 : GF_Err gf_sc_get_viewpoint(GF_Compositor *compositor, u32 viewpoint_idx, const char **outName, Bool *is_bound)
      34             : {
      35             : #ifndef GPAC_DISABLE_VRML
      36             :         u32 count;
      37             :         GF_Node *n;
      38           2 :         if (!compositor->visual) return GF_BAD_PARAM;
      39           2 :         count = gf_list_count(compositor->visual->view_stack);
      40           2 :         if (!viewpoint_idx) return GF_BAD_PARAM;
      41           2 :         if (viewpoint_idx>count) return GF_EOS;
      42             : 
      43           0 :         n = (GF_Node*)gf_list_get(compositor->visual->view_stack, viewpoint_idx-1);
      44           0 :         switch (gf_node_get_tag(n)) {
      45           0 :         case TAG_MPEG4_Viewport:
      46           0 :                 if (outName)
      47           0 :                         *outName = ((M_Viewport*)n)->description.buffer;
      48           0 :                 if (is_bound)
      49           0 :                         *is_bound = ((M_Viewport*)n)->isBound;
      50             :                 return GF_OK;
      51           0 :         case TAG_MPEG4_Viewpoint:
      52             : #ifndef GPAC_DISABLE_X3D
      53             :         case TAG_X3D_Viewpoint:
      54             : #endif
      55           0 :                 if (outName)
      56           0 :                         *outName = ((M_Viewpoint*)n)->description.buffer;
      57           0 :                 if (is_bound)
      58           0 :                         *is_bound = ((M_Viewpoint*)n)->isBound;
      59             :                 return GF_OK;
      60           0 :         default:
      61           0 :                 if (outName)
      62           0 :                         *outName = NULL;
      63           0 :                 if (is_bound)
      64           0 :                         *is_bound = GF_FALSE;
      65             :                 return GF_OK;
      66             :         }
      67             : #else
      68             :         return GF_NOT_SUPPORTED;
      69             : #endif
      70             : }
      71             : 
      72             : GF_EXPORT
      73           2 : GF_Err gf_sc_set_viewpoint(GF_Compositor *compositor, u32 viewpoint_idx, const char *viewpoint_name)
      74             : {
      75             : #ifndef GPAC_DISABLE_VRML
      76             :         u32 count, i;
      77             :         GF_Node *n;
      78           2 :         if (!compositor->visual) return GF_BAD_PARAM;
      79           2 :         count = gf_list_count(compositor->visual->view_stack);
      80           2 :         if (viewpoint_idx>count) return GF_BAD_PARAM;
      81           0 :         if (!viewpoint_idx && !viewpoint_name) return GF_BAD_PARAM;
      82             : 
      83           0 :         if (viewpoint_idx) {
      84             :                 Bool bind;
      85           0 :                 n = (GF_Node*)gf_list_get(compositor->visual->view_stack, viewpoint_idx-1);
      86           0 :                 bind = Bindable_GetIsBound(n);
      87           0 :                 Bindable_SetSetBind(n, !bind);
      88           0 :                 return GF_OK;
      89             :         }
      90           0 :         for (i=0; i<count; i++) {
      91             :                 char *name = NULL;
      92           0 :                 n = (GF_Node*)gf_list_get(compositor->visual->view_stack, viewpoint_idx-1);
      93           0 :                 switch (gf_node_get_tag(n)) {
      94           0 :                 case TAG_MPEG4_Viewport:
      95           0 :                         name = ((M_Viewport*)n)->description.buffer;
      96           0 :                         break;
      97           0 :                 case TAG_MPEG4_Viewpoint:
      98           0 :                         name = ((M_Viewpoint*)n)->description.buffer;
      99           0 :                         break;
     100             : #ifndef GPAC_DISABLE_X3D
     101           0 :                 case TAG_X3D_Viewpoint:
     102           0 :                         name = ((M_Viewpoint*)n)->description.buffer;
     103           0 :                         break;
     104             : #endif
     105             :                 default:
     106             :                         break;
     107             :                 }
     108           0 :                 if (name && !stricmp(name, viewpoint_name)) {
     109           0 :                         Bool bind = Bindable_GetIsBound(n);
     110           0 :                         Bindable_SetSetBind(n, !bind);
     111           0 :                         return GF_OK;
     112             :                 }
     113             :         }
     114             :         return GF_BAD_PARAM;
     115             : #else
     116             :         return GF_NOT_SUPPORTED;
     117             : #endif
     118             : }
     119             : 
     120             : #ifndef GPAC_DISABLE_VRML
     121             : 
     122             : 
     123             : #define VPCHANGED(__comp) { GF_Event evt; evt.type = GF_EVENT_VIEWPOINTS; gf_sc_send_event(__comp, &evt); }
     124             : 
     125             : 
     126         144 : static void DestroyViewStack(GF_Node *node)
     127             : {
     128         144 :         ViewStack *st = (ViewStack *) gf_node_get_private(node);
     129         144 :         PreDestroyBindable(node, st->reg_stacks);
     130         144 :         gf_list_del(st->reg_stacks);
     131         144 :         VPCHANGED(gf_sc_get_compositor(node));
     132         144 :         gf_free(st);
     133         144 : }
     134             : 
     135           7 : static void viewport_set_bind(GF_Node *node, GF_Route *route)
     136             : {
     137           7 :         GF_Compositor *rend = gf_sc_get_compositor(node);
     138           7 :         ViewStack *st = (ViewStack *) gf_node_get_private(node);
     139           7 :         Bindable_OnSetBind(node, st->reg_stacks, NULL);
     140             : 
     141           7 :         gf_sc_invalidate(rend, NULL);
     142             :         /*notify change of vp stack*/
     143           7 :         VPCHANGED(rend);
     144             :         /*and dirty ourselves to force frustrum update*/
     145           7 :         gf_node_dirty_set(node, 0, 0);
     146           7 : }
     147             : 
     148             : 
     149        1075 : static void TraverseViewport(GF_Node *node, void *rs, Bool is_destroy)
     150             : {
     151             :         Fixed sx, sy, w, h, tx, ty;
     152             : #ifndef GPAC_DISABLE_3D
     153             :         GF_Matrix mx;
     154             : #endif
     155             :         GF_Matrix2D mat;
     156             :         GF_Rect rc, rc_bckup;
     157        1075 :         ViewStack *st = (ViewStack *) gf_node_get_private(node);
     158             :         M_Viewport *vp = (M_Viewport *) node;
     159             :         GF_TraverseState *tr_state = (GF_TraverseState *)rs;
     160             : 
     161        1075 :         if (is_destroy) {
     162          51 :                 DestroyViewStack(node);
     163          51 :                 return;
     164             :         }
     165             : 
     166             : #ifndef GPAC_DISABLE_3D
     167        1024 :         if (tr_state->visual->type_3d>1) return;
     168             : #endif
     169             : 
     170             :         /*first traverse, bound if needed*/
     171        1024 :         if (gf_list_find(tr_state->viewpoints, node) < 0) {
     172          51 :                 gf_list_add(tr_state->viewpoints, node);
     173             :                 assert(gf_list_find(st->reg_stacks, tr_state->viewpoints)==-1);
     174          51 :                 gf_list_add(st->reg_stacks, tr_state->viewpoints);
     175             : 
     176          51 :                 if (gf_list_get(tr_state->viewpoints, 0) == vp) {
     177          51 :                         if (!vp->isBound) Bindable_SetIsBound(node, 1);
     178             :                 } else {
     179           0 :                         if (gf_inline_is_default_viewpoint(node)) Bindable_SetSetBindEx(node, 1, tr_state->viewpoints);
     180             :                 }
     181          51 :                 VPCHANGED(tr_state->visual->compositor);
     182             :                 /*in any case don't draw the first time (since the viewport could have been declared last)*/
     183          51 :                 gf_sc_invalidate(tr_state->visual->compositor, NULL);
     184          51 :                 return;
     185             :         }
     186             : 
     187         973 :         if (tr_state->traversing_mode != TRAVERSE_BINDABLE) return;
     188         580 :         if (!vp->isBound) return;
     189             : 
     190         557 :         if (gf_list_get(tr_state->viewpoints, 0) != vp)
     191             :                 return;
     192             : 
     193             : #ifndef GPAC_DISABLE_3D
     194         557 :         if (tr_state->visual->type_3d) {
     195         234 :                 w = tr_state->bbox.max_edge.x - tr_state->bbox.min_edge.x;
     196         234 :                 h = tr_state->bbox.max_edge.y - tr_state->bbox.min_edge.y;
     197             :         } else
     198             : #endif
     199             :         {
     200         323 :                 w = tr_state->bounds.width;
     201         323 :                 h = tr_state->bounds.height;
     202             :         }
     203         557 :         if (!w || !h) return;
     204             : 
     205             : 
     206             :         /*if no parent this is the main viewport, don't update if not changed*/
     207             : //      if (!tr_state->is_layer && !gf_node_dirty_get(node)) return;
     208             : 
     209         557 :         gf_node_dirty_clear(node, 0);
     210             : 
     211         557 :         gf_mx2d_init(mat);
     212         557 :         gf_mx2d_add_translation(&mat, vp->position.x, vp->position.y);
     213         557 :         gf_mx2d_add_rotation(&mat, 0, 0, vp->orientation);
     214             : 
     215             :         //compute scaling ratio
     216         557 :         sx = (vp->size.x>=0) ? vp->size.x : w;
     217         557 :         sy = (vp->size.y>=0) ? vp->size.y : h;
     218         557 :         rc = gf_rect_center(sx, sy);
     219             :         rc_bckup = rc;
     220             : 
     221         557 :         switch (vp->fit) {
     222             :         /*covers all area and respect aspect ratio*/
     223         262 :         case 2:
     224         262 :                 if (gf_divfix(rc.width, w) > gf_divfix(rc.height, h)) {
     225          12 :                         rc.width = gf_muldiv(rc.width, h, rc.height);
     226             :                         rc.height = h;
     227             :                 } else {
     228         250 :                         rc.height = gf_muldiv(rc.height , w, rc.width);
     229             :                         rc.width = w;
     230             :                 }
     231             :                 break;
     232             :         /*fits inside the area and respect AR*/
     233          95 :         case 1:
     234          95 :                 if (gf_divfix(rc.width, w)> gf_divfix(rc.height, h)) {
     235          71 :                         rc.height = gf_muldiv(rc.height, w, rc.width);
     236             :                         rc.width = w;
     237             :                 } else {
     238          24 :                         rc.width = gf_muldiv(rc.width, h, rc.height);
     239             :                         rc.height = h;
     240             :                 }
     241             :                 break;
     242             :         /*fit entirely: nothing to change*/
     243             :         case 0:
     244             :                 rc.width = w;
     245             :                 rc.height = h;
     246             :                 break;
     247             :         default:
     248             :                 return;
     249             :         }
     250         557 :         sx = gf_divfix(rc.width, rc_bckup.width);
     251         557 :         sy = gf_divfix(rc.height, rc_bckup.height);
     252             : 
     253             :         /*viewport on root visual, remove compositor scale*/
     254         557 :         if (!tr_state->is_layer && (tr_state->visual->compositor->visual==tr_state->visual) ) {
     255         473 :                 sx = gf_divfix(sx, tr_state->visual->compositor->scale_x);
     256         473 :                 sy = gf_divfix(sy, tr_state->visual->compositor->scale_y);
     257             :         }
     258             : 
     259         557 :         rc.x = - rc.width/2;
     260         557 :         rc.y = rc.height/2;
     261             : 
     262             :         tx = ty = 0;
     263         557 :         if (vp->fit && vp->alignment.count) {
     264             :                 /*left alignment*/
     265         357 :                 if (vp->alignment.vals[0] == -1) tx = rc.width/2 - w/2;
     266         345 :                 else if (vp->alignment.vals[0] == 1) tx = w/2 - rc.width/2;
     267             : 
     268         357 :                 if (vp->alignment.count>1) {
     269             :                         /*top-alignment*/
     270         298 :                         if (vp->alignment.vals[1]==-1) ty = rc.height/2 - h/2;
     271         286 :                         else if (vp->alignment.vals[1]==1) ty = h/2 - rc.height/2;
     272             :                 }
     273             :         }
     274             : 
     275         557 :         gf_mx2d_init(mat);
     276         557 :         if (tr_state->pixel_metrics) {
     277         557 :                 gf_mx2d_add_scale(&mat, sx, sy);
     278             :         } else {
     279             :                 /*if we are not in pixelMetrics, undo the meterMetrics->pixelMetrics transformation*/
     280           0 :                 gf_mx2d_add_scale(&mat, gf_divfix(sx, tr_state->min_hsize), gf_divfix(sy, tr_state->min_hsize) );
     281             :         }
     282         557 :         gf_mx2d_add_translation(&mat, tx, ty);
     283             : 
     284         557 :         gf_mx2d_add_translation(&mat, -gf_mulfix(vp->position.x,sx), -gf_mulfix(vp->position.y,sy) );
     285         557 :         gf_mx2d_add_rotation(&mat, 0, 0, vp->orientation);
     286             : 
     287         557 :         tr_state->bounds = rc;
     288         557 :         tr_state->bounds.x += tx;
     289         557 :         tr_state->bounds.y += ty;
     290             : 
     291             : #ifndef GPAC_DISABLE_3D
     292         557 :         if (tr_state->visual->type_3d) {
     293             :                 /*in layers directly modify the model matrix*/
     294         234 :                 if (tr_state->is_layer) {
     295          28 :                         gf_mx_from_mx2d(&mx, &mat);
     296          28 :                         gf_mx_add_matrix(&tr_state->model_matrix, &mx);
     297             :                 }
     298             :                 /*otherwise add to camera viewport matrix*/
     299             :                 else {
     300         206 :                         gf_mx_from_mx2d(&tr_state->camera->viewport, &mat);
     301         206 :                         tr_state->camera->flags = (CAM_HAS_VIEWPORT | CAM_IS_DIRTY);
     302             :                 }
     303             :         } else
     304             : #endif
     305         323 :                 gf_mx2d_pre_multiply(&tr_state->transform, &mat);
     306             : }
     307             : 
     308          51 : void compositor_init_viewport(GF_Compositor *compositor, GF_Node *node)
     309             : {
     310             :         ViewStack *ptr;
     311          51 :         GF_SAFEALLOC(ptr, ViewStack);
     312          51 :         if (!ptr) {
     313           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate viewport stack\n"));
     314             :                 return;
     315             :         }
     316             : 
     317          51 :         ptr->reg_stacks = gf_list_new();
     318             : 
     319          51 :         gf_node_set_private(node, ptr);
     320          51 :         gf_node_set_callback_function(node, TraverseViewport);
     321          51 :         ((M_Viewport*)node)->on_set_bind = viewport_set_bind;
     322             : }
     323             : 
     324             : 
     325             : #ifndef GPAC_DISABLE_3D
     326             : 
     327          11 : static void viewpoint_set_bind(GF_Node *node, GF_Route *route)
     328             : {
     329          11 :         GF_Compositor *rend = gf_sc_get_compositor(node);
     330          11 :         ViewStack *st = (ViewStack *) gf_node_get_private(node);
     331             : 
     332          11 :         if (!((M_Viewpoint*)node)->isBound )
     333          11 :                 st->prev_was_bound = 0;
     334          11 :         Bindable_OnSetBind(node, st->reg_stacks, NULL);
     335          11 :         gf_sc_invalidate(rend, NULL);
     336             :         /*notify change of vp stack*/
     337          11 :         VPCHANGED(rend);
     338             :         /*and dirty ourselves to force frustrum update*/
     339          11 :         gf_node_dirty_set(node, 0, 0);
     340          11 : }
     341             : 
     342       19790 : static void TraverseViewpoint(GF_Node *node, void *rs, Bool is_destroy)
     343             : {
     344             :         SFVec3f pos, v1, v2;
     345             :         SFRotation ori;
     346             :         GF_Matrix mx;
     347             :         GF_TraverseState *tr_state = (GF_TraverseState *)rs;
     348             :         M_Viewpoint *vp = (M_Viewpoint*) node;
     349       19790 :         ViewStack *st = (ViewStack *) gf_node_get_private(node);
     350             : 
     351       19790 :         if (is_destroy) {
     352          61 :                 DestroyViewStack(node);
     353          61 :                 return;
     354             :         }
     355             :         /*may happen in get_bounds*/
     356       19729 :         if (!tr_state->viewpoints) return;
     357             : //      if (!tr_state->camera->is_3D) return;
     358             : 
     359             :         /*first traverse, bound if needed*/
     360       19686 :         if (gf_list_find(tr_state->viewpoints, node) < 0) {
     361          63 :                 gf_list_add(tr_state->viewpoints, node);
     362             :                 assert(gf_list_find(st->reg_stacks, tr_state->viewpoints)==-1);
     363          63 :                 gf_list_add(st->reg_stacks, tr_state->viewpoints);
     364             : 
     365          63 :                 if (gf_list_get(tr_state->viewpoints, 0) == vp) {
     366          55 :                         if (!vp->isBound) Bindable_SetIsBound(node, 1);
     367             :                 } else {
     368           8 :                         if (gf_inline_is_default_viewpoint(node)) Bindable_SetSetBind(node, 1);
     369             :                 }
     370          63 :                 VPCHANGED(tr_state->visual->compositor);
     371             :                 /*in any case don't draw the first time (since the viewport could have been declared last)*/
     372          63 :                 if (tr_state->layer3d) gf_node_dirty_set(tr_state->layer3d, GF_SG_VRML_BINDABLE_DIRTY, 0);
     373          63 :                 gf_sc_invalidate(tr_state->visual->compositor, NULL);
     374             :         }
     375             :         /*not evaluating vp, return*/
     376       19686 :         if (tr_state->traversing_mode != TRAVERSE_BINDABLE) {
     377             :                 /*store model matrix if changed - NOTE: we always have a 1-frame delay between VP used and real world...
     378             :                 we could remove this by pre-traversing the scene before applying vp, but that would mean 2 scene
     379             :                 traversals*/
     380       12195 :                 if ((tr_state->traversing_mode==TRAVERSE_SORT) || (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) ) {
     381        6450 :                         if (!gf_mx_equal(&st->world_view_mx, &tr_state->model_matrix)) {
     382             :                                 gf_mx_copy(st->world_view_mx, tr_state->model_matrix);
     383         254 :                                 gf_node_dirty_set(node, 0, 0);
     384             :                         }
     385             :                 }
     386             :                 return;
     387             :         }
     388             : 
     389             :         /*not bound or in 2D visual*/
     390        7491 :         if (!vp->isBound || !tr_state->navigations) return;
     391             : 
     392        7417 :         if (!gf_node_dirty_get(node)) {
     393        7215 :                 if ((tr_state->vp_size.x == st->last_vp_size.x) &&  (tr_state->vp_size.y == st->last_vp_size.y)) return;
     394             :         }
     395         202 :         gf_node_dirty_clear(node, 0);
     396             : 
     397         202 :         st->last_vp_size.x = tr_state->vp_size.x;
     398         202 :         st->last_vp_size.y = tr_state->vp_size.y;
     399             : 
     400             :         /*move to local system*/
     401         202 :         gf_mx_copy(mx, st->world_view_mx);
     402         202 :         gf_mx_add_translation(&mx, vp->position.x, vp->position.y, vp->position.z);
     403         202 :         gf_mx_add_rotation(&mx, vp->orientation.q, vp->orientation.x, vp->orientation.y, vp->orientation.z);
     404         202 :         gf_mx_decompose(&mx, &pos, &v1, &ori, &v2);
     405             :         /*get center*/
     406         202 :         v1.x = v1.y = v1.z = 0;
     407             : #ifndef GPAC_DISABLE_X3D
     408             :         /*X3D specifies examine center*/
     409         202 :         if (gf_node_get_tag(node)==TAG_X3D_Viewpoint) v1 = ((X_Viewpoint *)node)->centerOfRotation;
     410             : #endif
     411         202 :         gf_mx_apply_vec(&st->world_view_mx, &v1);
     412             :         /*set frustrum param - animate only if not bound last frame and jump false*/
     413         202 :         visual_3d_viewpoint_change(tr_state, node, (!st->prev_was_bound && !vp->jump) ? 1 : 0, vp->fieldOfView, pos, ori, v1);
     414         202 :         st->prev_was_bound = 1;
     415             : }
     416             : 
     417          61 : void compositor_init_viewpoint(GF_Compositor *compositor, GF_Node *node)
     418             : {
     419             :         ViewStack *st;
     420          61 :         GF_SAFEALLOC(st, ViewStack);
     421          61 :         if (!st) {
     422           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate viewpoint stack\n"));
     423             :                 return;
     424             :         }
     425             : 
     426          61 :         st->reg_stacks = gf_list_new();
     427         122 :         gf_mx_init(st->world_view_mx);
     428          61 :         gf_node_set_private(node, st);
     429          61 :         gf_node_set_callback_function(node, TraverseViewpoint);
     430          61 :         ((M_Viewpoint*)node)->on_set_bind = viewpoint_set_bind;
     431             : }
     432             : 
     433             : #endif
     434             : 
     435           0 : static void navinfo_set_bind(GF_Node *node, GF_Route *route)
     436             : {
     437           0 :         if (node) {
     438           0 :                 ViewStack *st = (ViewStack *) gf_node_get_private(node);
     439           0 :                 Bindable_OnSetBind(node, st->reg_stacks, NULL);
     440           0 :                 gf_sc_invalidate( gf_sc_get_compositor(node), NULL);
     441             :         }
     442           0 : }
     443             : 
     444        5187 : static void TraverseNavigationInfo(GF_Node *node, void *rs, Bool is_destroy)
     445             : {
     446             :         u32 i;
     447             : #ifndef GPAC_DISABLE_3D
     448             :         u32 nb_select_mode;
     449             :         SFVec3f start, end;
     450             :         Fixed scale;
     451        5187 :         ViewStack *st = (ViewStack *) gf_node_get_private(node);
     452             : #endif
     453             :         GF_TraverseState *tr_state = (GF_TraverseState *)rs;
     454             :         M_NavigationInfo *ni = (M_NavigationInfo *) node;
     455             : 
     456        5187 :         if (is_destroy) {
     457          28 :                 DestroyViewStack(node);
     458          28 :                 return;
     459             :         }
     460             : #ifdef GPAC_DISABLE_3D
     461             : 
     462             :         /*FIXME, we only deal with one node, no bind stack for the current time*/
     463             :         for (i=0; i<ni->type.count; i++) {
     464             :                 if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "NONE")) {
     465             :                         tr_state->visual->compositor->navigation_disabled = 1;
     466             :                 }
     467             :         }
     468             : #else
     469             : 
     470        5159 :         if (!tr_state->navigations) return;
     471             : 
     472             :         /*first traverse, bound if needed*/
     473        5146 :         if (gf_list_find(tr_state->navigations, node) < 0) {
     474          28 :                 gf_list_add(tr_state->navigations, node);
     475          28 :                 if (gf_list_get(tr_state->navigations, 0) == ni) {
     476          28 :                         if (!ni->isBound) Bindable_SetIsBound(node, 1);
     477             :                 }
     478             :                 assert(gf_list_find(st->reg_stacks, tr_state->navigations)==-1);
     479          28 :                 gf_list_add(st->reg_stacks, tr_state->navigations);
     480          28 :                 gf_mx_copy(st->world_view_mx, tr_state->model_matrix);
     481             :                 /*in any case don't draw the first time*/
     482          28 :                 gf_sc_invalidate(tr_state->visual->compositor, NULL);
     483          28 :                 return;
     484             :         }
     485             :         /*not bound*/
     486        5118 :         if (!ni->isBound) return;
     487             :         /*not evaluating, return*/
     488        5118 :         if (tr_state->traversing_mode != TRAVERSE_BINDABLE) {
     489        3060 :                 if ((tr_state->traversing_mode==TRAVERSE_SORT) || (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) ) {
     490        1300 :                         if (!gf_mx_equal(&st->world_view_mx, &tr_state->model_matrix)) {
     491             :                                 gf_mx_copy(st->world_view_mx, tr_state->model_matrix);
     492           0 :                                 gf_node_dirty_set(node, 0, 0);
     493             :                         }
     494             :                 }
     495             :                 return;
     496             :         }
     497             : 
     498        2058 :         if (!gf_node_dirty_get(node)) return;
     499          20 :         gf_node_dirty_clear(node, 0);
     500             : 
     501             :         nb_select_mode = 0;
     502          20 :         tr_state->camera->navigation_flags = 0;
     503          20 :         tr_state->camera->navigate_mode = 0;
     504          55 :         for (i=0; i<ni->type.count; i++) {
     505          35 :                 if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "ANY")) tr_state->camera->navigation_flags |= NAV_ANY;
     506             :                 else {
     507          22 :                         nb_select_mode++;
     508             :                 }
     509             : 
     510          35 :                 if (!tr_state->camera->navigate_mode) {
     511          27 :                         if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "NONE")) tr_state->camera->navigate_mode = GF_NAVIGATE_NONE;
     512          26 :                         else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "WALK")) tr_state->camera->navigate_mode = GF_NAVIGATE_WALK;
     513          22 :                         else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "EXAMINE")) tr_state->camera->navigate_mode = GF_NAVIGATE_EXAMINE;
     514           9 :                         else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "FLY")) tr_state->camera->navigate_mode = GF_NAVIGATE_FLY;
     515           9 :                         else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "VR")) tr_state->camera->navigate_mode = GF_NAVIGATE_VR;
     516             :                 }
     517             :         }
     518          20 :         if (nb_select_mode>1) tr_state->camera->navigation_flags |= NAV_SELECTABLE;
     519             : 
     520          20 :         if (ni->headlight) tr_state->camera->navigation_flags |= NAV_HEADLIGHT;
     521             : 
     522          20 :         start.x = start.y = start.z = 0;
     523          20 :         end.x = end.y = 0;
     524          20 :         end.z = FIX_ONE;
     525          20 :         gf_mx_apply_vec(&st->world_view_mx, &start);
     526          20 :         gf_mx_apply_vec(&st->world_view_mx, &end);
     527          20 :         gf_vec_diff(end, end, start);
     528          20 :         scale = gf_vec_len(end);
     529             : 
     530          20 :         tr_state->camera->speed = gf_mulfix(scale, ni->speed);
     531          20 :         tr_state->camera->visibility = gf_mulfix(scale, ni->visibilityLimit);
     532          20 :         if (ni->avatarSize.count) tr_state->camera->avatar_size.x = gf_mulfix(scale, ni->avatarSize.vals[0]);
     533          20 :         if (ni->avatarSize.count>1) tr_state->camera->avatar_size.y = gf_mulfix(scale, ni->avatarSize.vals[1]);
     534          20 :         if (ni->avatarSize.count>2) tr_state->camera->avatar_size.z = gf_mulfix(scale, ni->avatarSize.vals[2]);
     535             : 
     536             : #if 0
     537             :         if (tr_state->pixel_metrics) {
     538             :                 u32 s = MAX(tr_state->visual->width, tr_state->visual->height);
     539             :                 s /= 2;
     540             : //              tr_state->camera->speed = ni->speed;
     541             :                 tr_state->camera->visibility *= s;
     542             :                 tr_state->camera->avatar_size.x *= s;
     543             :                 tr_state->camera->avatar_size.y *= s;
     544             :                 tr_state->camera->avatar_size.z *= s;
     545             :         }
     546             : #endif
     547             : 
     548             : #endif
     549             : 
     550             : }
     551             : 
     552          28 : void compositor_init_navigation_info(GF_Compositor *compositor, GF_Node *node)
     553             : {
     554             :         ViewStack *st;
     555          28 :         GF_SAFEALLOC(st, ViewStack);
     556          28 :         if (!st) {
     557           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate navigation stack\n"));
     558             :                 return;
     559             :         }
     560             : 
     561          28 :         st->reg_stacks = gf_list_new();
     562          28 :         gf_node_set_private(node, st);
     563          28 :         gf_node_set_callback_function(node, TraverseNavigationInfo);
     564          28 :         ((M_NavigationInfo*)node)->on_set_bind = navinfo_set_bind;
     565             : 
     566             : #ifdef GPAC_ENABLE_COVERAGE
     567          28 :         if (gf_sys_is_cov_mode()) {
     568             :                 navinfo_set_bind(NULL, NULL);
     569             :         }
     570             : #endif
     571             : }
     572             : 
     573             : 
     574             : #ifndef GPAC_DISABLE_3D
     575             : 
     576           2 : static void fog_set_bind(GF_Node *node, GF_Route *route)
     577             : {
     578           2 :         ViewStack *st = (ViewStack *) gf_node_get_private(node);
     579           2 :         Bindable_OnSetBind(node, st->reg_stacks, NULL);
     580           2 :         gf_sc_invalidate(gf_sc_get_compositor(node), NULL);
     581           2 : }
     582             : 
     583        5035 : static void TraverseFog(GF_Node *node, void *rs, Bool is_destroy)
     584             : {
     585             :         Fixed density, vrange;
     586             :         SFVec3f start, end;
     587             :         ViewStack *vp_st;
     588             :         M_Viewpoint *vp;
     589             :         GF_TraverseState *tr_state = (GF_TraverseState *)rs;
     590             :         M_Fog *fog = (M_Fog *) node;
     591        5035 :         ViewStack *st = (ViewStack *) gf_node_get_private(node);
     592             : 
     593        5035 :         if (is_destroy) {
     594           4 :                 DestroyViewStack(node);
     595           4 :                 return;
     596             :         }
     597             : 
     598        5031 :         if (!tr_state->fogs) return;
     599             : 
     600             :         /*first traverse, bound if needed*/
     601        4907 :         if (gf_list_find(tr_state->fogs, node) < 0) {
     602           4 :                 gf_list_add(tr_state->fogs, node);
     603           4 :                 if (gf_list_get(tr_state->fogs, 0) == fog) {
     604           4 :                         if (!fog->isBound) Bindable_SetIsBound(node, 1);
     605             :                 }
     606             :                 assert(gf_list_find(st->reg_stacks, tr_state->fogs)==-1);
     607           4 :                 gf_list_add(st->reg_stacks, tr_state->fogs);
     608             : 
     609           4 :                 gf_mx_copy(st->world_view_mx, tr_state->model_matrix);
     610             :                 /*in any case don't draw the first time*/
     611           4 :                 gf_sc_invalidate(tr_state->visual->compositor, NULL);
     612           4 :                 return;
     613             :         }
     614             :         /*not evaluating, return*/
     615        4903 :         if (tr_state->traversing_mode != TRAVERSE_BINDABLE) {
     616        3607 :                 if ((tr_state->traversing_mode==TRAVERSE_SORT) || (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) )
     617        2168 :                         gf_mx_copy(st->world_view_mx, tr_state->model_matrix);
     618             :                 return;
     619             :         }
     620             :         /*not bound*/
     621        1296 :         if (!fog->isBound || !fog->visibilityRange) return;
     622             : 
     623             :         /*fog visibility is expressed in current bound VP so get its matrix*/
     624        1288 :         vp = (M_Viewpoint*)gf_list_get(tr_state->viewpoints, 0);
     625             :         vp_st = NULL;
     626        1288 :         if (vp && vp->isBound) vp_st = (ViewStack *) gf_node_get_private((GF_Node *)vp);
     627             : 
     628        1288 :         start.x = start.y = start.z = 0;
     629        1288 :         end.x = end.y = 0;
     630        1288 :         end.z = fog->visibilityRange;
     631        1288 :         if (vp_st) {
     632        1172 :                 gf_mx_apply_vec(&vp_st->world_view_mx, &start);
     633        1172 :                 gf_mx_apply_vec(&vp_st->world_view_mx, &end);
     634             :         }
     635        1288 :         gf_mx_apply_vec(&st->world_view_mx, &start);
     636        1288 :         gf_mx_apply_vec(&st->world_view_mx, &end);
     637        1288 :         gf_vec_diff(end, end, start);
     638        1288 :         vrange = gf_vec_len(end);
     639             : 
     640        1288 :         density = gf_invfix(vrange);
     641        1288 :         visual_3d_set_fog(tr_state->visual, fog->fogType.buffer, fog->color, density, vrange);
     642             : }
     643             : 
     644           4 : void compositor_init_fog(GF_Compositor *compositor, GF_Node *node)
     645             : {
     646             :         ViewStack *st;
     647           4 :         GF_SAFEALLOC(st, ViewStack);
     648           4 :         if (!st) {
     649           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate fog stack\n"));
     650             :                 return;
     651             :         }
     652             : 
     653           4 :         st->reg_stacks = gf_list_new();
     654           4 :         gf_node_set_private(node, st);
     655           4 :         gf_node_set_callback_function(node, TraverseFog);
     656           4 :         ((M_Fog*)node)->on_set_bind = fog_set_bind;
     657             : }
     658             : 
     659             : #endif  /*GPAC_DISABLE_3D*/
     660             : 
     661             : #endif /*GPAC_DISABLE_VRML*/

Generated by: LCOV version 1.13