LCOV - code coverage report
Current view: top level - compositor - mpeg4_layer_3d.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 233 280 83.2 %
Date: 2021-04-29 23:48:07 Functions: 5 8 62.5 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2020
       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             : 
      27             : 
      28             : #include "nodes_stacks.h"
      29             : #include "mpeg4_grouping.h"
      30             : #include "texturing.h"
      31             : #include "visual_manager.h"
      32             : 
      33             : #ifndef GPAC_DISABLE_VRML
      34             : 
      35             : #ifndef GPAC_DISABLE_3D
      36             : 
      37             : #ifdef GPAC_USE_TINYGL
      38             : #include <GL/oscontext.h>
      39             : #endif
      40             : 
      41             : typedef struct
      42             : {
      43             :         GROUPING_NODE_STACK_3D
      44             :         Bool first;
      45             :         GF_Rect clip, vp;
      46             :         GF_VisualManager *visual;
      47             : 
      48             :         Bool unsupported;
      49             :         GF_TextureHandler txh;
      50             :         Drawable *drawable;
      51             : #ifdef GPAC_USE_TINYGL
      52             :         ostgl_context *tgl_ctx;
      53             : #endif
      54             :         Fixed scale_x, scale_y;
      55             : } Layer3DStack;
      56             : 
      57             : 
      58          15 : static void DestroyLayer3D(GF_Node *node)
      59             : {
      60          15 :         Layer3DStack *st = (Layer3DStack *) gf_node_get_private(node);
      61          15 :         GF_Compositor *compositor = st->visual->compositor;
      62             : 
      63          15 :         drawable_del(st->drawable);
      64             : 
      65             : #ifdef GPAC_USE_TINYGL
      66             :         if (st->tgl_ctx) ostgl_delete_context(st->tgl_ctx);
      67             : #endif
      68             : 
      69          15 :         if (st->txh.data) gf_free(st->txh.data);
      70             :         /*destroy texture*/
      71          15 :         gf_sc_texture_destroy(&st->txh);
      72             : 
      73          15 :         BindableStackDelete(st->visual->back_stack);
      74          15 :         st->visual->back_stack = NULL;
      75          15 :         BindableStackDelete(st->visual->view_stack);
      76          15 :         st->visual->view_stack = NULL;
      77          15 :         BindableStackDelete(st->visual->navigation_stack);
      78          15 :         st->visual->navigation_stack = NULL;
      79          15 :         BindableStackDelete(st->visual->fog_stack);
      80          15 :         st->visual->fog_stack = NULL;
      81          15 :         visual_del(st->visual);
      82             : 
      83             : 
      84          15 :         if (compositor && compositor->active_layer == node) compositor->active_layer = NULL;
      85          15 :         gf_free(st);
      86          15 : }
      87             : 
      88        1196 : static void l3d_CheckBindables(GF_Node *n, GF_TraverseState *tr_state, Bool force_traverse)
      89             : {
      90             :         GF_Node *btop;
      91             :         u32 mode;
      92             :         M_Layer3D *l3d;
      93             :         l3d = (M_Layer3D *)n;
      94             : 
      95        1196 :         mode = tr_state->traversing_mode;
      96        1196 :         tr_state->traversing_mode = TRAVERSE_GET_BOUNDS;
      97             : 
      98        1196 :         if (force_traverse) gf_node_traverse(l3d->background, tr_state);
      99        1196 :         btop = (GF_Node*)gf_list_get(tr_state->backgrounds, 0);
     100        1196 :         if (btop != l3d->background) {
     101           6 :                 gf_node_unregister(l3d->background, n);
     102           6 :                 gf_node_register(btop, n);
     103           6 :                 l3d->background = btop;
     104           6 :                 gf_node_event_out(n, 4/*"background"*/);
     105             :         }
     106        1196 :         if (force_traverse) gf_node_traverse(l3d->viewpoint, tr_state);
     107        1196 :         btop = (GF_Node*)gf_list_get(tr_state->viewpoints, 0);
     108        1196 :         if (btop != l3d->viewpoint) {
     109           2 :                 gf_node_unregister(l3d->viewpoint, n);
     110           2 :                 gf_node_register(btop, n);
     111           2 :                 l3d->viewpoint = btop;
     112           2 :                 gf_node_event_out(n, 7/*"viewpoint"*/);
     113             :         }
     114        1196 :         if (force_traverse) gf_node_traverse(l3d->navigationInfo, tr_state);
     115        1196 :         btop = (GF_Node*)gf_list_get(tr_state->navigations, 0);
     116        1196 :         if (btop != l3d->navigationInfo) {
     117           0 :                 gf_node_unregister(l3d->navigationInfo, n);
     118           0 :                 gf_node_register(btop, n);
     119           0 :                 l3d->navigationInfo = btop;
     120           0 :                 gf_node_event_out(n, 6/*"navigationInfo"*/);
     121             :         }
     122        1196 :         if (force_traverse) gf_node_traverse(l3d->fog, tr_state);
     123        1196 :         btop = (GF_Node*)gf_list_get(tr_state->fogs, 0);
     124        1196 :         if (btop != l3d->fog) {
     125           0 :                 gf_node_unregister(l3d->fog, n);
     126           0 :                 gf_node_register(btop, n);
     127           0 :                 l3d->fog = btop;
     128           0 :                 gf_node_event_out(n, 5/*"fog"*/);
     129             :         }
     130        1196 :         tr_state->traversing_mode = mode;
     131        1196 : }
     132             : 
     133             : 
     134           0 : static void layer3d_draw_2d(GF_Node *node, GF_TraverseState *tr_state)
     135             : {
     136           0 :         DrawableContext *ctx = tr_state->ctx;
     137           0 :         if (tr_state->visual->DrawBitmap(tr_state->visual, tr_state, ctx))
     138             :                 return;
     139             : 
     140           0 :         visual_2d_texture_path(tr_state->visual, ctx->drawable->path, ctx, tr_state);
     141             : }
     142             : 
     143        1194 : static void layer3d_setup_clip(Layer3DStack *st, GF_TraverseState *tr_state, Bool prev_cam, GF_Rect rc)
     144             : {
     145             :         Fixed sw, sh;
     146             : 
     147        1194 :         if (tr_state->visual->compositor->visual==tr_state->visual) {
     148        1194 :                 sw = INT2FIX(tr_state->visual->compositor->display_width);
     149        1194 :                 sh = INT2FIX(tr_state->visual->compositor->display_height);
     150             :         } else {
     151           0 :                 sw = INT2FIX(tr_state->visual->width);
     152           0 :                 sh = INT2FIX(tr_state->visual->height);
     153             :         }
     154             : 
     155        1194 :         if ((tr_state->traversing_mode==TRAVERSE_SORT) && !prev_cam) {
     156             :                 rc.x = rc.y = 0;
     157           0 :                 st->visual->camera.vp = rc;
     158             :         } else {
     159        1194 :                 st->visual->camera.vp = rc;
     160        1194 :                 st->visual->camera.vp.x += sw/2;
     161        1194 :                 st->visual->camera.vp.y -= st->visual->camera.vp.height;
     162        1194 :                 st->visual->camera.vp.y += sh/2;
     163             :         }
     164             : 
     165        1194 :         tr_state->camera->width = tr_state->camera->vp.width;
     166        1194 :         tr_state->camera->height = tr_state->camera->vp.height;
     167             : 
     168        1194 :         if (!tr_state->pixel_metrics) {
     169           0 :                 if (tr_state->camera->height > tr_state->camera->width) {
     170           0 :                         tr_state->camera->height = 2 * gf_divfix(tr_state->camera->height, tr_state->camera->width);
     171           0 :                         tr_state->camera->width = 2*FIX_ONE;
     172             :                 } else {
     173           0 :                         tr_state->camera->width = 2 * gf_divfix(tr_state->camera->width, tr_state->camera->height);
     174           0 :                         tr_state->camera->height = 2*FIX_ONE;
     175             :                 }
     176             :         }
     177             : 
     178             :         /*setup bounds*/
     179        1194 :         tr_state->bbox.max_edge.x = tr_state->camera->width/2;
     180        1194 :         tr_state->bbox.min_edge.x = -tr_state->bbox.max_edge.x;
     181        1194 :         tr_state->bbox.max_edge.y = tr_state->camera->height/2;
     182        1194 :         tr_state->bbox.min_edge.y = -tr_state->bbox.max_edge.y;
     183        1194 :         tr_state->bbox.max_edge.z = tr_state->bbox.min_edge.z = 0;
     184        1194 :         tr_state->bbox.is_set = 1;
     185             : 
     186        1194 : }
     187             : 
     188        2432 : static void TraverseLayer3D(GF_Node *node, void *rs, Bool is_destroy)
     189             : {
     190             :         Bool prev_layer;//, changed;
     191             :         GF_List *oldb, *oldv, *oldf, *oldn;
     192             :         GF_Rect rc;
     193             :         u32 cur_lights;
     194             :         GF_List *node_list_backup;
     195             :         GF_BBox bbox_backup;
     196             :         GF_Matrix model_backup;
     197             :         GF_Matrix2D mx2d_backup;
     198             :         GF_Camera *prev_cam;
     199             :         GF_VisualManager *old_visual;
     200             :         GF_Matrix2D *transform;
     201             :         M_Layer3D *l = (M_Layer3D *)node;
     202        2432 :         Layer3DStack *st = (Layer3DStack *) gf_node_get_private(node);
     203             :         GF_TraverseState *tr_state = (GF_TraverseState *) rs;
     204             :         GF_TraverseState a_tr;
     205             :         u32 old_type_3d;
     206             : 
     207        2432 :         if (is_destroy) {
     208          15 :                 DestroyLayer3D(node);
     209          15 :                 return;
     210             :         }
     211        2417 :         if (st->unsupported) return;
     212             : 
     213             :         memcpy(&a_tr, tr_state, sizeof(GF_TraverseState));
     214             : 
     215        2107 :         if (gf_node_dirty_get(node)) {
     216             : 
     217             :                 /*main visual in pixel metrics, use output width*/
     218        1289 :                 if (tr_state->pixel_metrics && (tr_state->visual->compositor->visual==tr_state->visual)) {
     219        1289 :                         st->clip.width = INT2FIX(tr_state->visual->compositor->vp_width);
     220        1289 :                         st->clip.height = INT2FIX(tr_state->visual->compositor->vp_height);
     221             :                 } else {
     222           0 :                         visual_get_size_info(tr_state, &st->clip.width, &st->clip.height);
     223             :                 }
     224             :                 /*setup bounds in local coord system*/
     225        1289 :                 if (l->size.x>=0) st->clip.width = l->size.x;
     226        1289 :                 if (l->size.y>=0) st->clip.height = l->size.y;
     227        1289 :                 st->clip = gf_rect_center(st->clip.width, st->clip.height);
     228             : 
     229             : //              changed = 1;
     230             :         }
     231             : 
     232        2107 :         transform = &tr_state->transform;
     233             : 
     234             :         /*layer3D maintains its own stacks*/
     235        2107 :         oldb = tr_state->backgrounds;
     236        2107 :         oldv = tr_state->viewpoints;
     237        2107 :         oldf = tr_state->fogs;
     238        2107 :         oldn = tr_state->navigations;
     239        2107 :         old_visual = tr_state->visual;
     240        2107 :         prev_layer = tr_state->is_layer;
     241        2107 :         prev_cam = tr_state->camera;
     242        2107 :         bbox_backup = tr_state->bbox;
     243             : 
     244             : 
     245        2107 :         switch (tr_state->traversing_mode) {
     246           0 :         case TRAVERSE_GET_BOUNDS:
     247           0 :                 if (!tr_state->for_node) {
     248           0 :                         tr_state->bounds = st->clip;
     249           0 :                         gf_bbox_from_rect(&tr_state->bbox, &st->clip);
     250           0 :                         return;
     251             :                 }
     252             :         case TRAVERSE_PICK:
     253             :                 /*layers can only be used in a 2D context*/
     254          79 :                 if (tr_state->camera && tr_state->camera->is_3D)
     255             :                         return;
     256             :                 break;
     257             : 
     258        1253 :         case TRAVERSE_SORT:
     259             :                 /*layers can only be used in a 2D context*/
     260        1253 :                 if (tr_state->camera && tr_state->camera->is_3D)
     261             :                         return;
     262             : 
     263        1253 :                 if (tr_state->visual->compositor->hybrid_opengl) {
     264         911 :                         DrawableContext *ctx = drawable_init_context_mpeg4(st->drawable, tr_state);
     265         911 :                         if (!ctx) goto l3d_exit;
     266         911 :                         ctx->aspect.fill_texture = &st->txh;
     267         911 :                         ctx->flags |= CTX_APP_DIRTY | CTX_IS_TRANSPARENT;
     268         911 :                         drawable_finalize_sort(ctx, tr_state, &st->clip);
     269         911 :                         return;
     270             :                 }
     271             :                 break;
     272         775 :         case TRAVERSE_DRAW_2D:
     273         775 :                 if (tr_state->visual->compositor->hybrid_opengl) {
     274         775 :                         transform = &tr_state->ctx->transform;
     275         775 :                         break;
     276             :                 }
     277           0 :                 layer3d_draw_2d(node, tr_state);
     278           0 :                 return;
     279             :         case TRAVERSE_DRAW_3D:
     280             :         default:
     281             :                 return;
     282             :         }
     283             : 
     284             :         /*layer3D maintains its own stacks*/
     285        1196 :         tr_state->backgrounds = st->visual->back_stack;
     286        1196 :         tr_state->viewpoints = st->visual->view_stack;
     287        1196 :         tr_state->navigations = st->visual->navigation_stack;
     288        1196 :         tr_state->fogs = st->visual->fog_stack;
     289        1196 :         tr_state->is_layer = 1;
     290        1196 :         tr_state->camera = &st->visual->camera;
     291             : 
     292        1196 :         gf_mx_copy(model_backup, tr_state->model_matrix);
     293        1196 :         gf_mx2d_copy(mx2d_backup, tr_state->transform);
     294             : 
     295             :         /*compute viewport in visual coordinate*/
     296        1196 :         rc = st->clip;
     297        1196 :         if (prev_cam) {
     298             : 
     299        1194 :                 gf_mx_apply_rect(&tr_state->model_matrix, &rc);
     300             : 
     301        1194 :                 if (tr_state->visual->compositor->hybrid_opengl) {
     302         854 :                         gf_mx2d_apply_rect(transform, &rc);
     303             :                 } else {
     304         340 :                         gf_mx_apply_rect(&prev_cam->modelview, &rc);
     305             :                 }
     306             : 
     307        1194 :                 if (tr_state->camera->flags & CAM_HAS_VIEWPORT)
     308           0 :                         gf_mx_apply_rect(&prev_cam->viewport, &rc);
     309             : 
     310             :         } else {
     311           2 :                 gf_mx2d_apply_rect(&tr_state->transform, &rc);
     312             : 
     313             :                 /*switch visual*/
     314           2 :                 tr_state->visual = st->visual;
     315             :         }
     316             : 
     317             : 
     318             :         /*check bindables*/
     319        2392 :         gf_mx_init(tr_state->model_matrix);
     320        1196 :         l3d_CheckBindables(node, tr_state, st->first);
     321             : 
     322        1196 :         if (prev_cam) gf_mx_copy(tr_state->model_matrix, model_backup);
     323             : 
     324             :         /*drawing a layer means drawing all subelements as a whole (no depth sorting with parents)*/
     325        1196 :         if ((tr_state->traversing_mode==TRAVERSE_SORT) || (tr_state->traversing_mode==TRAVERSE_DRAW_2D)) {
     326             :                 u32 trav_mode = tr_state->traversing_mode;
     327             : 
     328             : //              if (gf_node_dirty_get(node)) changed = 1;
     329        1117 :                 gf_node_dirty_clear(node, GF_SG_NODE_DIRTY|GF_SG_VRML_BINDABLE_DIRTY);
     330             : 
     331             :                 /*!! we were in a 2D mode without hybridGL, not supported !*/
     332        1117 :                 if (!prev_cam) {
     333           2 :                         st->unsupported = GF_TRUE;
     334           2 :                         goto l3d_exit;
     335             :                 }
     336             :                 /*note that we don't backup the state as a layer3D cannot be declared in a layer3D*/
     337        1115 :                 tr_state->layer3d = node;
     338             : 
     339             : 
     340        1115 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Layer3D] Redrawing\n"));
     341             : 
     342        1115 :                 layer3d_setup_clip(st, tr_state, 1, rc);
     343             : 
     344             :                 //this only happens in hybridGL mode
     345        1115 :                 if (trav_mode==TRAVERSE_DRAW_2D) {
     346         775 :                         visual_2d_flush_hybgl_canvas(tr_state->visual, NULL, tr_state->ctx, tr_state);
     347             :                 }
     348             : 
     349        1115 :                 old_type_3d = tr_state->visual->type_3d;
     350        1115 :                 tr_state->visual->type_3d = 2;
     351             : 
     352        1115 :                 visual_3d_clear_all_lights(tr_state->visual);
     353             : 
     354        1115 :                 cur_lights = tr_state->visual->num_lights;
     355             :                 /*this will init projection. Note that we're binding the viewpoint in the current pixelMetrics context
     356             :                 even if the viewpoint was declared in an inline below
     357             :                 if no previous camera, we're using offscreen rendering, force clear */
     358        1115 :                 visual_3d_init_draw(tr_state, 1);
     359             : 
     360        1115 :                 visual_3d_check_collisions(tr_state, NULL, l->children);
     361        1115 :                 tr_state->traversing_mode = TRAVERSE_SORT;
     362             : 
     363             :                 /*shortcut node list*/
     364        1115 :                 node_list_backup = tr_state->visual->alpha_nodes_to_draw;
     365        1115 :                 tr_state->visual->alpha_nodes_to_draw = gf_list_new();
     366             : 
     367             :                 /*reset cull flag*/
     368        1115 :                 tr_state->cull_flag = 0;
     369        1115 :                 group_3d_traverse(node, (GroupingNode *)st, tr_state);
     370             : 
     371        1115 :                 visual_3d_flush_contexts(tr_state->visual, tr_state);
     372             : 
     373        1115 :                 gf_list_del(tr_state->visual->alpha_nodes_to_draw);
     374        1115 :                 tr_state->visual->alpha_nodes_to_draw = node_list_backup;
     375             : 
     376        3345 :                 while (cur_lights < tr_state->visual->num_lights) {
     377        1115 :                         visual_3d_remove_last_light(tr_state->visual);
     378             :                 }
     379             : 
     380        1115 :                 tr_state->traversing_mode = trav_mode ;
     381        1115 :                 tr_state->visual->type_3d = old_type_3d;
     382        1115 :                 tr_state->layer3d = NULL;
     383             : 
     384             : #if 0
     385             :                 /*!! we were in a 2D mode, create drawable context!!*/
     386             :                 if (!prev_cam ) {
     387             :                         DrawableContext *ctx;
     388             :                         /*with TinyGL we draw directly to the offscreen buffer*/
     389             : #ifndef GPAC_USE_TINYGL
     390             :                         gf_sc_copy_to_stencil(&st->txh);
     391             : #else
     392             :                         if (st->txh.pixelformat==GF_PIXEL_RGBDS)
     393             :                                 gf_get_tinygl_depth(&st->txh);
     394             : #endif
     395             : 
     396             :                         gf_sc_texture_set_stencil(&st->txh, gf_sc_texture_get_stencil(&st->txh) );
     397             :                         changed = 1;
     398             : 
     399             :                         /*restore visual*/
     400             :                         tr_state->visual = old_visual;
     401             :                         tr_state->appear = NULL;
     402             :                         //      tr_state->camera = prev_cam;
     403             : 
     404             :                         ctx = drawable_init_context_mpeg4(st->drawable, tr_state);
     405             :                         if (!ctx) goto l3d_exit;
     406             :                         ctx->aspect.fill_texture = &st->txh;
     407             :                         ctx->flags |= CTX_NO_ANTIALIAS;
     408             :                         if (changed) ctx->flags |= CTX_APP_DIRTY;
     409             :                         if (st->txh.transparent) ctx->flags |= CTX_IS_TRANSPARENT;
     410             :                         drawable_finalize_sort(ctx, tr_state, NULL);
     411             :                 }
     412             : #endif
     413             : 
     414             :         }
     415             :         /*check picking - we must fall in our 2D clipper except when mvt is grabbed on layer*/
     416         158 :         else if (!gf_node_dirty_get(node)  && (tr_state->traversing_mode==TRAVERSE_PICK)) {
     417             :                 GF_Ray prev_r;
     418             :                 SFVec3f start, end;
     419             :                 SFVec4f res;
     420             :                 Fixed in_x, in_y;
     421             :                 Bool do_pick = 0;
     422             : 
     423          79 :                 if (!prev_cam) rc = st->vp;
     424             : 
     425          79 :                 layer3d_setup_clip(st, tr_state, prev_cam ? 1 : 0, rc);
     426             : 
     427          79 :                 old_type_3d = tr_state->visual->type_3d;
     428          79 :                 tr_state->visual->type_3d = 2;
     429             : 
     430          79 :                 if (tr_state->visual->compositor->active_layer==node) {
     431           3 :                         do_pick = (tr_state->visual->compositor->grabbed_sensor || tr_state->visual->compositor->navigation_state) ? 1 : 0;
     432             :                 }
     433             : 
     434          79 :                 if (!prev_cam || tr_state->visual->compositor->hybrid_opengl) gf_mx_from_mx2d(&tr_state->model_matrix, &tr_state->transform);
     435             : 
     436          79 :                 if (!do_pick && !gf_list_count(tr_state->visual->compositor->sensors))
     437          79 :                         do_pick = gf_sc_pick_in_clipper(tr_state, &st->clip);
     438             : 
     439          79 :                 if (!do_pick) {
     440          27 :                         tr_state->visual->type_3d = old_type_3d;
     441          54 :                         goto l3d_exit;
     442             :                 }
     443             : 
     444          52 :                 prev_r = tr_state->ray;
     445             : 
     446          52 :                 compositor_get_2d_plane_intersection(&tr_state->ray, &start);
     447             : 
     448          52 :                 gf_mx_inverse(&tr_state->model_matrix);
     449          52 :                 gf_mx_apply_vec(&tr_state->model_matrix, &start);
     450             : 
     451             : 
     452          52 :                 if (tr_state->visual->compositor->visual==tr_state->visual) {
     453          52 :                         start.x = gf_mulfix(start.x, tr_state->visual->compositor->scale_x);
     454          52 :                         start.y = gf_mulfix(start.y, tr_state->visual->compositor->scale_y);
     455           0 :                 } else if (!prev_cam) {
     456           0 :                         start.x = gf_muldiv(start.x, st->visual->camera.width, st->clip.width);
     457           0 :                         start.y = gf_muldiv(start.y, st->visual->camera.height, st->clip.height);
     458             :                 }
     459             : 
     460          52 :                 visual_3d_setup_projection(tr_state, 1);
     461             : 
     462          52 :                 in_x = 2 * gf_divfix(start.x, st->visual->camera.width);
     463          52 :                 in_y = 2 * gf_divfix(start.y, st->visual->camera.height);
     464             : 
     465          52 :                 res.x = in_x;
     466          52 :                 res.y = in_y;
     467          52 :                 res.z = -FIX_ONE;
     468          52 :                 res.q = FIX_ONE;
     469          52 :                 gf_mx_apply_vec_4x4(&st->visual->camera.unprojection, &res);
     470          52 :                 if (!res.q) {
     471           0 :                         tr_state->visual->type_3d = old_type_3d;
     472           0 :                         goto l3d_exit;
     473             :                 }
     474          52 :                 start.x = gf_divfix(res.x, res.q);
     475          52 :                 start.y = gf_divfix(res.y, res.q);
     476          52 :                 start.z = gf_divfix(res.z, res.q);
     477             : 
     478          52 :                 res.x = in_x;
     479          52 :                 res.y = in_y;
     480          52 :                 res.z = FIX_ONE;
     481          52 :                 res.q = FIX_ONE;
     482          52 :                 gf_mx_apply_vec_4x4(&st->visual->camera.unprojection, &res);
     483          52 :                 if (!res.q) {
     484           0 :                         tr_state->visual->type_3d = old_type_3d;
     485           0 :                         goto l3d_exit;
     486             :                 }
     487          52 :                 end.x = gf_divfix(res.x, res.q);
     488          52 :                 end.y = gf_divfix(res.y, res.q);
     489          52 :                 end.z = gf_divfix(res.z, res.q);
     490          52 :                 tr_state->ray = gf_ray(start, end);
     491             : 
     492          52 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Layer3D] Picking: cast ray\n\tOrigin %.4f %.4f %.4f - End %.4f %.4f %.4f\n\tDir %.4f %.4f %.4f\n",
     493             :                                                       FIX2FLT(tr_state->ray.orig.x), FIX2FLT(tr_state->ray.orig.y), FIX2FLT(tr_state->ray.orig.z),
     494             :                                                       FIX2FLT(end.x), FIX2FLT(end.y), FIX2FLT(end.z),
     495             :                                                       FIX2FLT(tr_state->ray.dir.x), FIX2FLT(tr_state->ray.dir.y), FIX2FLT(tr_state->ray.dir.z)));
     496             : 
     497          52 :                 group_3d_traverse(node, (GroupingNode *)st, tr_state);
     498          52 :                 tr_state->ray = prev_r;
     499             : 
     500          52 :                 tr_state->visual->type_3d = old_type_3d;
     501             : 
     502             :                 /*store info if navigation allowed - we just override any layer3D picked first since we are picking 2D
     503             :                 objects*/
     504          52 :                 if (tr_state->camera->navigate_mode || (tr_state->camera->navigation_flags & NAV_ANY))
     505          52 :                         tr_state->layer3d = node;
     506             : 
     507          52 :                 tr_state->traversing_mode = TRAVERSE_PICK;
     508             :         }
     509             : 
     510        1196 : l3d_exit:
     511             : 
     512             :         /*restore camera*/
     513        1196 :         tr_state->camera = prev_cam;
     514        1196 :         if (prev_cam) {
     515             :                 //remember to reload previous projection matrix
     516        1194 :                 visual_3d_projection_matrix_modified(tr_state->visual);
     517        1194 :                 if (tr_state->visual == old_visual) {
     518        1194 :                         visual_3d_set_viewport(tr_state->visual, tr_state->camera->vp);
     519             :                 }
     520             :         }
     521        1196 :         tr_state->visual = old_visual;
     522             : 
     523             :         /*restore traversing state*/
     524        1196 :         tr_state->backgrounds = oldb;
     525        1196 :         tr_state->viewpoints = oldv;
     526        1196 :         tr_state->fogs = oldf;
     527        1196 :         tr_state->navigations = oldn;
     528        1196 :         tr_state->bbox = bbox_backup;
     529        1196 :         tr_state->is_layer = prev_layer;
     530        1196 :         gf_mx_copy(tr_state->model_matrix, model_backup);
     531        1196 :         gf_mx2d_copy(tr_state->transform, mx2d_backup);
     532             : 
     533             :         /*in case we missed bindables*/
     534        1196 :         if (st->first) {
     535          15 :                 st->first = 0;
     536          15 :                 gf_node_dirty_set(node, 0, 0);
     537          15 :                 gf_sc_invalidate(tr_state->visual->compositor, NULL);
     538             :         }
     539             : }
     540             : 
     541          15 : void compositor_init_layer3d(GF_Compositor *compositor, GF_Node *node)
     542             : {
     543             :         Layer3DStack *stack;
     544             : 
     545          15 :         if (!gf_sc_check_gl_support(compositor)) {
     546           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_COMPOSE, ("[Compositor] Driver disabled, cannot render Layer 3D\n"));
     547             :                 return;
     548             :         }
     549             : 
     550          15 :         GF_SAFEALLOC(stack, Layer3DStack);
     551          15 :         if (!stack) {
     552           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate layer 3d stack\n"));
     553             :                 return;
     554             :         }
     555          15 :         stack->visual = visual_new(compositor);
     556          15 :         stack->visual->type_3d = 2;
     557          15 :         stack->visual->camera.is_3D = 1;
     558          15 :         stack->visual->camera.visibility = 0;
     559          15 :         stack->visual->camera.speed = FIX_ONE;
     560          15 :         camera_invalidate(&stack->visual->camera);
     561          15 :         stack->first = 1;
     562             : 
     563          15 :         stack->txh.compositor = compositor;
     564          15 :         stack->drawable = drawable_new();
     565          15 :         stack->drawable->node = node;
     566          15 :         stack->drawable->flags = DRAWABLE_USE_TRAVERSE_DRAW;
     567             : 
     568          15 :         gf_node_set_private(node, stack);
     569          15 :         gf_node_set_callback_function(node, TraverseLayer3D);
     570             : }
     571             : 
     572           0 : GF_Camera *compositor_layer3d_get_camera(GF_Node *node)
     573             : {
     574           0 :         Layer3DStack *st = (Layer3DStack *) gf_node_get_private(node);
     575           0 :         return &st->visual->camera;
     576             : }
     577             : 
     578           0 : void compositor_layer3d_bind_camera(GF_Node *node, Bool do_bind, u32 nav_value)
     579             : {
     580           0 :         Layer3DStack *st = (Layer3DStack *) gf_node_get_private(node);
     581           0 :         GF_Node *n = (GF_Node*)gf_list_get(st->visual->navigation_stack, 0);
     582           0 :         if (n) Bindable_SetSetBind(n, do_bind);
     583           0 :         else st->visual->camera.navigate_mode = nav_value;
     584           0 : }
     585             : 
     586             : #endif /*GPAC_DISABLE_3D*/
     587             : 
     588             : #endif /*GPAC_DISABLE_VRML*/
     589             : 

Generated by: LCOV version 1.13