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 :
|