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 :
27 :
28 : #include "nodes_stacks.h"
29 :
30 : #ifndef GPAC_DISABLE_VRML
31 :
32 : #ifndef GPAC_DISABLE_3D
33 :
34 : #include "texturing.h"
35 : #include "visual_manager.h"
36 :
37 : /*for background textures - the offset is to prevent lines on cube map edges*/
38 : #define PLANE_HSIZE FLT2FIX(0.5025f)
39 : #define PLANE_HSIZE_LOW FLT2FIX(0.5f)
40 :
41 :
42 : static Bool back_use_texture(MFURL *url)
43 : {
44 588 : if (!url->count) return 0;
45 137 : if (url->vals[0].OD_ID > 0) return 1;
46 77 : if (url->vals[0].url && strlen(url->vals[0].url)) return 1;
47 : return 0;
48 : }
49 :
50 6366 : static void UpdateBackgroundTexture(GF_TextureHandler *txh)
51 : {
52 6366 : gf_sc_texture_update_frame(txh, 0);
53 : /*restart texture if needed (movie background controled by MediaControl)*/
54 6366 : if (txh->stream_finished && gf_mo_get_loop(txh->stream, 0)) gf_sc_texture_restart(txh);
55 6366 : }
56 :
57 :
58 528 : static Bool back_gf_sc_texture_enabled(MFURL *url, GF_TextureHandler *txh)
59 : {
60 528 : Bool use_texture = back_use_texture(url);
61 : if (use_texture) {
62 : /*texture not ready*/
63 129 : if (!txh->tx_io) {
64 : use_texture = 0;
65 70 : gf_sc_invalidate(txh->compositor, NULL);
66 : }
67 129 : gf_sc_texture_set_blend_mode(txh, gf_sc_texture_is_transparent(txh) ? TX_REPLACE : TX_DECAL);
68 : }
69 528 : return use_texture;
70 : }
71 :
72 30 : static void back_check_gf_sc_texture_change(GF_TextureHandler *txh, MFURL *url)
73 : {
74 : /*if open and changed, stop and play*/
75 30 : if (txh->is_open) {
76 4 : if (! gf_sc_texture_check_url_change(txh, url)) return;
77 0 : gf_sc_texture_stop(txh);
78 0 : gf_sc_texture_play(txh, url);
79 0 : return;
80 : }
81 : /*if not open and changed play*/
82 26 : if (url->count) gf_sc_texture_play(txh, url);
83 : }
84 :
85 11 : static void DestroyBackground(GF_Node *node)
86 : {
87 11 : BackgroundStack *ptr = (BackgroundStack *) gf_node_get_private(node);
88 11 : PreDestroyBindable(node, ptr->reg_stacks);
89 11 : gf_list_del(ptr->reg_stacks);
90 :
91 11 : if (ptr->sky_mesh) mesh_free(ptr->sky_mesh);
92 11 : if (ptr->ground_mesh) mesh_free(ptr->ground_mesh);
93 :
94 11 : gf_sg_vrml_mf_reset(&ptr->ground_ang, GF_SG_VRML_MFFLOAT);
95 11 : gf_sg_vrml_mf_reset(&ptr->sky_ang, GF_SG_VRML_MFFLOAT);
96 11 : gf_sg_vrml_mf_reset(&ptr->ground_col, GF_SG_VRML_MFCOLOR);
97 11 : gf_sg_vrml_mf_reset(&ptr->sky_col, GF_SG_VRML_MFCOLOR);
98 :
99 11 : mesh_free(ptr->front_mesh);
100 11 : mesh_free(ptr->back_mesh);
101 11 : mesh_free(ptr->top_mesh);
102 11 : mesh_free(ptr->bottom_mesh);
103 11 : mesh_free(ptr->left_mesh);
104 11 : mesh_free(ptr->right_mesh);
105 :
106 :
107 11 : gf_sc_texture_destroy(&ptr->txh_front);
108 11 : gf_sc_texture_destroy(&ptr->txh_back);
109 11 : gf_sc_texture_destroy(&ptr->txh_top);
110 11 : gf_sc_texture_destroy(&ptr->txh_bottom);
111 11 : gf_sc_texture_destroy(&ptr->txh_left);
112 11 : gf_sc_texture_destroy(&ptr->txh_right);
113 :
114 11 : gf_free(ptr);
115 11 : }
116 :
117 : #define COL_TO_RGBA(res, col) { res.red = col.red; res.green = col.green; res.blue = col.blue; res.alpha = FIX_ONE; }
118 :
119 : #define DOME_STEP_V 32
120 : #define DOME_STEP_H 16
121 :
122 4 : static void back_build_dome(GF_Mesh *mesh, MFFloat *angles, MFColor *color, Bool ground_dome)
123 : {
124 : u32 i, j, last_idx, ang_idx, new_idx;
125 : Bool pad;
126 : u32 step_div_h;
127 : GF_Vertex vx;
128 : SFColorRGBA start_col, end_col, fcol;
129 : Fixed start_angle, next_angle, angle, r, frac, first_angle;
130 :
131 : start_angle = 0;
132 4 : mesh_reset(mesh);
133 :
134 : start_col.red = start_col.green = start_col.blue = 0;
135 : start_col.alpha = FIX_ONE;
136 : end_col = start_col;
137 :
138 4 : if (color->count) {
139 4 : COL_TO_RGBA(start_col, color->vals[0]);
140 : end_col = start_col;
141 4 : if (color->count>1) COL_TO_RGBA(end_col, color->vals[1]);
142 : }
143 :
144 4 : vx.texcoords.x = vx.texcoords.y = 0;
145 4 : vx.color = MESH_MAKE_COL(start_col);
146 4 : vx.pos.x = vx.pos.z = 0;
147 4 : vx.pos.y = FIX_ONE;
148 4 : vx.normal.x = vx.normal.z = 0;
149 4 : vx.normal.y = -MESH_NORMAL_UNIT;
150 :
151 4 : mesh_set_vertex_vx(mesh, &vx);
152 : last_idx = 0;
153 : ang_idx = 0;
154 :
155 : pad = 1;
156 : next_angle = first_angle = 0;
157 4 : if (angles->count) {
158 4 : next_angle = angles->vals[0];
159 4 : first_angle = 7*next_angle/8;
160 : pad = 0;
161 : }
162 :
163 : step_div_h = DOME_STEP_H;
164 : i=0;
165 4 : if (ground_dome) {
166 : step_div_h *= 2;
167 : i=1;
168 : }
169 :
170 106 : for (; i<DOME_STEP_V; i++) {
171 108 : if (ground_dome) {
172 44 : angle = first_angle + (i * (GF_PI2-first_angle) / DOME_STEP_V);
173 : } else {
174 64 : angle = (i * GF_PI / DOME_STEP_V);
175 : }
176 :
177 : /*switch cols*/
178 108 : if (angle >= next_angle) {
179 34 : if (ang_idx+1 < angles->count) {
180 : start_angle = next_angle;
181 6 : next_angle = angles->vals[ang_idx+1];
182 6 : if (next_angle>GF_PI) next_angle=GF_PI;
183 : start_col = end_col;
184 : ang_idx++;
185 6 : if (ang_idx+1<color->count) {
186 6 : COL_TO_RGBA(end_col, color->vals[ang_idx+1]);
187 : } else {
188 : pad = 1;
189 : }
190 : } else {
191 28 : if (ground_dome) break;
192 : pad = 1;
193 : }
194 : }
195 :
196 106 : if (pad) {
197 : fcol = end_col;
198 : } else {
199 80 : frac = gf_divfix(angle - start_angle, next_angle - start_angle) ;
200 80 : fcol.red = gf_mulfix(end_col.red - start_col.red, frac) + start_col.red;
201 80 : fcol.green = gf_mulfix(end_col.green - start_col.green, frac) + start_col.green;
202 80 : fcol.blue = gf_mulfix(end_col.blue - start_col.blue, frac) + start_col.blue;
203 : fcol.alpha = FIX_ONE;
204 : }
205 106 : vx.color = MESH_MAKE_COL(fcol);
206 :
207 106 : vx.pos.y = gf_sin(GF_PI2 - angle);
208 106 : r = gf_sqrt(FIX_ONE - gf_mulfix(vx.pos.y, vx.pos.y));
209 :
210 106 : new_idx = mesh->v_count;
211 2474 : for (j = 0; j < step_div_h; j++) {
212 : SFVec3f n;
213 2368 : Fixed lon = 2 * GF_PI * j / step_div_h;
214 2368 : vx.pos.x = gf_mulfix(gf_sin(lon), r);
215 2368 : vx.pos.z = gf_mulfix(gf_cos(lon), r);
216 2368 : n = gf_vec_scale(vx.pos, FIX_ONE /*-FIX_ONE*/);
217 2368 : gf_vec_norm(&n);
218 2368 : MESH_SET_NORMAL(vx, n);
219 2368 : mesh_set_vertex_vx(mesh, &vx);
220 :
221 2368 : if (j) {
222 2262 : if (i>1) {
223 2140 : mesh_set_triangle(mesh, last_idx+j, new_idx+j, new_idx+j-1);
224 2140 : mesh_set_triangle(mesh, last_idx+j, new_idx+j-1, last_idx+j-1);
225 : } else {
226 122 : mesh_set_triangle(mesh, 0, new_idx+j, new_idx+j-1);
227 : }
228 : }
229 : }
230 106 : if (i>1) {
231 100 : mesh_set_triangle(mesh, last_idx, new_idx, new_idx+step_div_h-1);
232 100 : mesh_set_triangle(mesh, last_idx, new_idx+step_div_h-1, last_idx+step_div_h-1);
233 : } else {
234 6 : mesh_set_triangle(mesh, 0, new_idx, new_idx+step_div_h-1);
235 : }
236 : last_idx = new_idx;
237 : }
238 :
239 4 : if (!ground_dome) {
240 2 : new_idx = mesh->v_count;
241 2 : vx.pos.x = vx.pos.z = 0;
242 2 : vx.pos.y = -FIX_ONE;
243 2 : vx.normal.x = vx.normal.z = 0;
244 2 : vx.normal.y = MESH_NORMAL_UNIT;
245 2 : mesh_set_vertex_vx(mesh, &vx);
246 :
247 32 : for (j=1; j < step_div_h; j++) {
248 30 : mesh_set_triangle(mesh, last_idx+j-1, last_idx+j, new_idx);
249 : }
250 2 : mesh_set_triangle(mesh, last_idx+step_div_h-1, last_idx, new_idx);
251 : }
252 :
253 4 : mesh->flags |= MESH_HAS_COLOR | MESH_NO_TEXTURE;
254 4 : mesh_update_bounds(mesh);
255 4 : }
256 :
257 59 : static void back_draw_texture(GF_TraverseState *tr_state, GF_TextureHandler *txh, GF_Mesh *mesh)
258 : {
259 59 : if (gf_sc_texture_enable(txh, NULL)) {
260 59 : tr_state->mesh_num_textures = 1;
261 59 : visual_3d_mesh_paint(tr_state, mesh);
262 59 : gf_sc_texture_disable(txh);
263 59 : tr_state->mesh_num_textures = 0;
264 : }
265 59 : }
266 :
267 530 : static void TraverseBackground(GF_Node *node, void *rs, Bool is_destroy)
268 : {
269 : M_Background *bck;
270 : BackgroundStack *st;
271 : SFVec4f res;
272 : Fixed scale;
273 : Bool has_sky, has_ground, front_tx, back_tx, top_tx, bottom_tx, right_tx, left_tx;
274 : GF_Matrix mx;
275 : GF_Compositor *compositor;
276 : GF_TraverseState *tr_state = (GF_TraverseState *)rs;
277 :
278 530 : if (is_destroy) {
279 11 : DestroyBackground(node);
280 11 : return;
281 : }
282 519 : if (tr_state->visual->compositor->noback)
283 : return;
284 :
285 519 : gf_node_dirty_clear(node, 0);
286 : bck = (M_Background *)node;
287 519 : st = (BackgroundStack *) gf_node_get_private(node);
288 519 : compositor = (GF_Compositor*)st->compositor;
289 :
290 :
291 : /*may happen in get_bounds*/
292 519 : if (!tr_state->backgrounds) return;
293 :
294 : /*first traverse, bound if needed*/
295 517 : if (gf_list_find(tr_state->backgrounds, node) < 0) {
296 10 : gf_list_add(tr_state->backgrounds, node);
297 : assert(gf_list_find(st->reg_stacks, tr_state->backgrounds)==-1);
298 10 : gf_list_add(st->reg_stacks, tr_state->backgrounds);
299 : /*only bound if we're on top*/
300 10 : if (gf_list_get(tr_state->backgrounds, 0) == bck) {
301 10 : if (!bck->isBound) Bindable_SetIsBound(node, 1);
302 : }
303 :
304 : /*check streams*/
305 13 : if (back_use_texture(&bck->frontUrl) && !st->txh_front.is_open) gf_sc_texture_play(&st->txh_front, &bck->frontUrl);
306 11 : if (back_use_texture(&bck->bottomUrl) && !st->txh_bottom.is_open) gf_sc_texture_play(&st->txh_bottom, &bck->bottomUrl);
307 11 : if (back_use_texture(&bck->backUrl) && !st->txh_back.is_open) gf_sc_texture_play(&st->txh_back, &bck->backUrl);
308 11 : if (back_use_texture(&bck->topUrl) && !st->txh_top.is_open) gf_sc_texture_play(&st->txh_top, &bck->topUrl);
309 11 : if (back_use_texture(&bck->rightUrl) && !st->txh_right.is_open) gf_sc_texture_play(&st->txh_right, &bck->rightUrl);
310 11 : if (back_use_texture(&bck->leftUrl) && !st->txh_left.is_open) gf_sc_texture_play(&st->txh_left, &bck->leftUrl);
311 :
312 : /*in any case don't draw the first time (since the background could have been declared last)*/
313 10 : gf_sc_invalidate(st->compositor, NULL);
314 10 : return;
315 : }
316 507 : if (!bck->isBound) return;
317 :
318 204 : if (tr_state->traversing_mode != TRAVERSE_BINDABLE) {
319 116 : if (tr_state->traversing_mode == TRAVERSE_SORT) {
320 50 : gf_mx_copy(st->current_mx, tr_state->model_matrix);
321 50 : if (!tr_state->pixel_metrics && tr_state->visual->compositor->inherit_type_3d) {
322 0 : Fixed pix_scale = gf_divfix(FIX_ONE, tr_state->min_hsize);
323 0 : gf_mx_add_scale(&st->current_mx, pix_scale, pix_scale, pix_scale);
324 :
325 : }
326 : }
327 : return;
328 : }
329 :
330 88 : front_tx = back_gf_sc_texture_enabled(&bck->frontUrl, &st->txh_front);
331 88 : back_tx = back_gf_sc_texture_enabled(&bck->backUrl, &st->txh_back);
332 88 : top_tx = back_gf_sc_texture_enabled(&bck->topUrl, &st->txh_top);
333 88 : bottom_tx = back_gf_sc_texture_enabled(&bck->bottomUrl, &st->txh_bottom);
334 88 : right_tx = back_gf_sc_texture_enabled(&bck->rightUrl, &st->txh_right);
335 88 : left_tx = back_gf_sc_texture_enabled(&bck->leftUrl, &st->txh_left);
336 :
337 88 : has_sky = ((bck->skyColor.count>1) && bck->skyAngle.count) ? 1 : 0;
338 88 : has_ground = ((bck->groundColor.count>1) && bck->groundAngle.count) ? 1 : 0;
339 :
340 : /*if we clear the main visual clear it entirely - ONLY IF NOT IN LAYER*/
341 88 : if ((tr_state->visual == compositor->visual) && (tr_state->visual->back_stack == tr_state->backgrounds)) {
342 : SFColor bcol;
343 13 : bcol.red = INT2FIX( GF_COL_R(tr_state->visual->compositor->back_color)) / 255;
344 13 : bcol.green = INT2FIX( GF_COL_G(tr_state->visual->compositor->back_color)) / 255;
345 13 : bcol.blue = INT2FIX( GF_COL_B(tr_state->visual->compositor->back_color)) / 255;
346 :
347 13 : visual_3d_clear(tr_state->visual, bcol, FIX_ONE);
348 13 : if (!has_sky && !has_ground && !front_tx && !back_tx && !top_tx && !bottom_tx && !left_tx && !right_tx) {
349 0 : return;
350 : }
351 : }
352 :
353 : /*undo translation*/
354 88 : res.x = res.y = res.z = 0;
355 88 : res.q = FIX_ONE;
356 88 : gf_mx_apply_vec_4x4(&tr_state->camera->unprojection, &res);
357 : assert(res.q);
358 88 : res.x = gf_divfix(res.x, res.q);
359 88 : res.y = gf_divfix(res.y, res.q);
360 88 : res.z = gf_divfix(res.z, res.q);
361 : /*NB: we don't support local rotation of the background ...*/
362 :
363 : /*enable background state (turn off all quality options)*/
364 88 : visual_3d_set_background_state(tr_state->visual, 1);
365 :
366 88 : if (has_sky) {
367 : GF_Matrix bck_mx;
368 13 : gf_mx_copy(bck_mx, tr_state->model_matrix);
369 13 : gf_mx_copy(tr_state->model_matrix, st->current_mx);
370 :
371 13 : if (!st->sky_mesh) {
372 2 : st->sky_mesh = new_mesh();
373 2 : back_build_dome(st->sky_mesh, &bck->skyAngle, &bck->skyColor, 0);
374 : }
375 :
376 13 : gf_mx_init(mx);
377 13 : gf_mx_add_translation(&mx, res.x, res.y, res.z);
378 :
379 : /*CHECKME - not sure why, we need to scale less in fixed point otherwise z-far clipping occur - probably some
380 : rounding issues...*/
381 : #ifdef GPAC_FIXED_POINT
382 : scale = (tr_state->camera->z_far/10)*8;
383 : #else
384 13 : scale = 8*tr_state->camera->z_far/10;
385 : #endif
386 13 : gf_mx_add_scale(&mx, scale, scale, scale);
387 :
388 13 : gf_mx_add_matrix(&tr_state->model_matrix, &mx);
389 :
390 13 : visual_3d_mesh_paint(tr_state, st->sky_mesh);
391 :
392 : gf_mx_copy(tr_state->model_matrix, bck_mx);
393 : }
394 :
395 88 : if (has_ground) {
396 : GF_Matrix bck_mx;
397 13 : gf_mx_copy(bck_mx, tr_state->model_matrix);
398 13 : gf_mx_copy(tr_state->model_matrix, st->current_mx);
399 :
400 13 : if (!st->ground_mesh) {
401 2 : st->ground_mesh = new_mesh();
402 2 : back_build_dome(st->ground_mesh, &bck->groundAngle, &bck->groundColor, 1);
403 : }
404 :
405 13 : gf_mx_init(mx);
406 13 : gf_mx_add_translation(&mx, res.x, res.y, res.z);
407 : /*cf above*/
408 : #ifdef GPAC_FIXED_POINT
409 : scale = (tr_state->camera->z_far/100)*70;
410 : #else
411 13 : scale = 70*tr_state->camera->z_far/100;
412 : #endif
413 13 : gf_mx_add_scale(&mx, scale, -scale, scale);
414 :
415 13 : gf_mx_add_matrix(&tr_state->model_matrix, &mx);
416 13 : visual_3d_mesh_paint(tr_state, st->ground_mesh);
417 : gf_mx_copy(tr_state->model_matrix, bck_mx);
418 : }
419 :
420 88 : if (front_tx || back_tx || left_tx || right_tx || top_tx || bottom_tx) {
421 : GF_Matrix bck_mx;
422 54 : gf_mx_copy(bck_mx, tr_state->model_matrix);
423 54 : gf_mx_copy(tr_state->model_matrix, st->current_mx);
424 :
425 54 : gf_mx_init(mx);
426 54 : gf_mx_add_translation(&mx, res.x, res.y, res.z);
427 : #ifdef GPAC_FIXED_POINT
428 : scale = (tr_state->camera->z_far/100)*90;
429 : #else
430 54 : scale = (tr_state->camera->z_far/100)*90;
431 : #endif
432 54 : gf_mx_add_scale(&mx, scale, scale, scale);
433 :
434 54 : visual_3d_enable_antialias(tr_state->visual, 1);
435 :
436 54 : gf_mx_add_matrix(&tr_state->model_matrix, &mx);
437 :
438 54 : if (front_tx) back_draw_texture(tr_state, &st->txh_front, st->front_mesh);
439 54 : if (back_tx) back_draw_texture(tr_state, &st->txh_back, st->back_mesh);
440 54 : if (top_tx) back_draw_texture(tr_state, &st->txh_top, st->top_mesh);
441 54 : if (bottom_tx) back_draw_texture(tr_state, &st->txh_bottom, st->bottom_mesh);
442 54 : if (left_tx) back_draw_texture(tr_state, &st->txh_left, st->left_mesh);
443 54 : if (right_tx) back_draw_texture(tr_state, &st->txh_right, st->right_mesh);
444 :
445 : gf_mx_copy(tr_state->model_matrix, bck_mx);
446 : }
447 :
448 : /*enable background state (turn off all quality options)*/
449 88 : visual_3d_set_background_state(tr_state->visual, 0);
450 : }
451 :
452 :
453 5 : static void back_set_bind(GF_Node *node, GF_Route *route)
454 : {
455 5 : BackgroundStack *st = (BackgroundStack *)gf_node_get_private(node);
456 5 : Bindable_OnSetBind(node, st->reg_stacks, NULL);
457 : /*and redraw scene*/
458 5 : gf_sc_invalidate(st->compositor, NULL);
459 5 : }
460 :
461 11 : void compositor_init_background(GF_Compositor *compositor, GF_Node *node)
462 : {
463 : BackgroundStack *ptr;
464 11 : GF_SAFEALLOC(ptr, BackgroundStack);
465 11 : if (!ptr) {
466 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate background stack\n"));
467 : return;
468 : }
469 :
470 11 : ptr->compositor = compositor;
471 11 : ptr->reg_stacks = gf_list_new();
472 11 : ((M_Background *)node)->on_set_bind = back_set_bind;
473 :
474 22 : gf_mx_init(ptr->current_mx);
475 :
476 : /*build texture cube*/
477 11 : ptr->front_mesh = new_mesh();
478 11 : mesh_set_vertex(ptr->front_mesh, -PLANE_HSIZE, -PLANE_HSIZE, -PLANE_HSIZE_LOW, 0, 0, FIX_ONE, 0, 0);
479 11 : mesh_set_vertex(ptr->front_mesh, PLANE_HSIZE, -PLANE_HSIZE, -PLANE_HSIZE_LOW, 0, 0, FIX_ONE, FIX_ONE, 0);
480 11 : mesh_set_vertex(ptr->front_mesh, PLANE_HSIZE, PLANE_HSIZE, -PLANE_HSIZE_LOW, 0, 0, FIX_ONE, FIX_ONE, FIX_ONE);
481 11 : mesh_set_vertex(ptr->front_mesh, -PLANE_HSIZE, PLANE_HSIZE, -PLANE_HSIZE_LOW, 0, 0, FIX_ONE, 0, FIX_ONE);
482 11 : mesh_set_triangle(ptr->front_mesh, 0, 1, 2);
483 11 : mesh_set_triangle(ptr->front_mesh, 0, 2, 3);
484 11 : mesh_update_bounds(ptr->front_mesh);
485 :
486 11 : ptr->back_mesh = new_mesh();
487 11 : mesh_set_vertex(ptr->back_mesh, -PLANE_HSIZE, -PLANE_HSIZE, PLANE_HSIZE_LOW, 0, 0, -FIX_ONE, FIX_ONE, 0);
488 11 : mesh_set_vertex(ptr->back_mesh, PLANE_HSIZE, -PLANE_HSIZE, PLANE_HSIZE_LOW, 0, 0, -FIX_ONE, 0, 0);
489 11 : mesh_set_vertex(ptr->back_mesh, PLANE_HSIZE, PLANE_HSIZE, PLANE_HSIZE_LOW, 0, 0, -FIX_ONE, 0, FIX_ONE);
490 11 : mesh_set_vertex(ptr->back_mesh, -PLANE_HSIZE, PLANE_HSIZE, PLANE_HSIZE_LOW, 0, 0, -FIX_ONE, FIX_ONE, FIX_ONE);
491 11 : mesh_set_triangle(ptr->back_mesh, 0, 1, 2);
492 11 : mesh_set_triangle(ptr->back_mesh, 0, 2, 3);
493 11 : mesh_update_bounds(ptr->back_mesh);
494 :
495 11 : ptr->top_mesh = new_mesh();
496 11 : mesh_set_vertex(ptr->top_mesh, -PLANE_HSIZE, PLANE_HSIZE_LOW, PLANE_HSIZE, 0, -FIX_ONE, 0, 0, 0);
497 11 : mesh_set_vertex(ptr->top_mesh, PLANE_HSIZE, PLANE_HSIZE_LOW, PLANE_HSIZE, 0, -FIX_ONE, 0, 0, FIX_ONE);
498 11 : mesh_set_vertex(ptr->top_mesh, PLANE_HSIZE, PLANE_HSIZE_LOW, -PLANE_HSIZE, 0, -FIX_ONE, 0, FIX_ONE, FIX_ONE);
499 11 : mesh_set_vertex(ptr->top_mesh, -PLANE_HSIZE, PLANE_HSIZE_LOW, -PLANE_HSIZE, 0, -FIX_ONE, 0, FIX_ONE, 0);
500 11 : mesh_set_triangle(ptr->top_mesh, 0, 1, 2);
501 11 : mesh_set_triangle(ptr->top_mesh, 0, 2, 3);
502 11 : mesh_update_bounds(ptr->top_mesh);
503 :
504 11 : ptr->bottom_mesh = new_mesh();
505 11 : mesh_set_vertex(ptr->bottom_mesh, -PLANE_HSIZE, -PLANE_HSIZE_LOW, -PLANE_HSIZE, 0, FIX_ONE, 0, FIX_ONE, FIX_ONE);
506 11 : mesh_set_vertex(ptr->bottom_mesh, PLANE_HSIZE, -PLANE_HSIZE_LOW, -PLANE_HSIZE, 0, FIX_ONE, 0, FIX_ONE, 0);
507 11 : mesh_set_vertex(ptr->bottom_mesh, PLANE_HSIZE, -PLANE_HSIZE_LOW, PLANE_HSIZE, 0, FIX_ONE, 0, 0, 0);
508 11 : mesh_set_vertex(ptr->bottom_mesh, -PLANE_HSIZE, -PLANE_HSIZE_LOW, PLANE_HSIZE, 0, FIX_ONE, 0, 0, FIX_ONE);
509 11 : mesh_set_triangle(ptr->bottom_mesh, 0, 1, 2);
510 11 : mesh_set_triangle(ptr->bottom_mesh, 0, 2, 3);
511 11 : mesh_update_bounds(ptr->bottom_mesh);
512 :
513 11 : ptr->left_mesh = new_mesh();
514 11 : mesh_set_vertex(ptr->left_mesh, -PLANE_HSIZE_LOW, -PLANE_HSIZE, -PLANE_HSIZE, FIX_ONE, 0, 0, FIX_ONE, 0);
515 11 : mesh_set_vertex(ptr->left_mesh, -PLANE_HSIZE_LOW, -PLANE_HSIZE, PLANE_HSIZE, FIX_ONE, 0, 0, 0, 0);
516 11 : mesh_set_vertex(ptr->left_mesh, -PLANE_HSIZE_LOW, PLANE_HSIZE, PLANE_HSIZE, FIX_ONE, 0, 0, 0, FIX_ONE);
517 11 : mesh_set_vertex(ptr->left_mesh, -PLANE_HSIZE_LOW, PLANE_HSIZE, -PLANE_HSIZE, FIX_ONE, 0, 0, FIX_ONE, FIX_ONE);
518 11 : mesh_set_triangle(ptr->left_mesh, 0, 1, 2);
519 11 : mesh_set_triangle(ptr->left_mesh, 0, 2, 3);
520 11 : mesh_update_bounds(ptr->left_mesh);
521 :
522 11 : ptr->right_mesh = new_mesh();
523 11 : mesh_set_vertex(ptr->right_mesh, PLANE_HSIZE_LOW, -PLANE_HSIZE, PLANE_HSIZE, -FIX_ONE, 0, 0, FIX_ONE, 0);
524 11 : mesh_set_vertex(ptr->right_mesh, PLANE_HSIZE_LOW, -PLANE_HSIZE, -PLANE_HSIZE, -FIX_ONE, 0, 0, 0, 0);
525 11 : mesh_set_vertex(ptr->right_mesh, PLANE_HSIZE_LOW, PLANE_HSIZE, -PLANE_HSIZE, -FIX_ONE, 0, 0, 0, FIX_ONE);
526 11 : mesh_set_vertex(ptr->right_mesh, PLANE_HSIZE_LOW, PLANE_HSIZE, PLANE_HSIZE, -FIX_ONE, 0, 0, FIX_ONE, FIX_ONE);
527 11 : mesh_set_triangle(ptr->right_mesh, 0, 1, 2);
528 11 : mesh_set_triangle(ptr->right_mesh, 0, 2, 3);
529 11 : mesh_update_bounds(ptr->right_mesh);
530 :
531 :
532 11 : gf_sc_texture_setup(&ptr->txh_back, compositor, node);
533 11 : ptr->txh_back.update_texture_fcnt = UpdateBackgroundTexture;
534 11 : gf_sc_texture_setup(&ptr->txh_front, compositor, node);
535 11 : ptr->txh_front.update_texture_fcnt = UpdateBackgroundTexture;
536 11 : gf_sc_texture_setup(&ptr->txh_top, compositor, node);
537 11 : ptr->txh_top.update_texture_fcnt = UpdateBackgroundTexture;
538 11 : gf_sc_texture_setup(&ptr->txh_bottom, compositor, node);
539 11 : ptr->txh_bottom.update_texture_fcnt = UpdateBackgroundTexture;
540 11 : gf_sc_texture_setup(&ptr->txh_left, compositor, node);
541 11 : ptr->txh_left.update_texture_fcnt = UpdateBackgroundTexture;
542 11 : gf_sc_texture_setup(&ptr->txh_right, compositor, node);
543 11 : ptr->txh_right.update_texture_fcnt = UpdateBackgroundTexture;
544 :
545 11 : gf_node_set_private(node, ptr);
546 11 : gf_node_set_callback_function(node, TraverseBackground);
547 :
548 : }
549 :
550 5 : void compositor_background_modified(GF_Node *node)
551 : {
552 : M_Background *bck = (M_Background *)node;
553 5 : BackgroundStack *st = (BackgroundStack *) gf_node_get_private(node);
554 5 : if (!st) return;
555 :
556 5 : if (!gf_sg_vrml_field_equal(&bck->skyColor, &st->sky_col, GF_SG_VRML_MFCOLOR)
557 2 : || !gf_sg_vrml_field_equal(&bck->skyAngle, &st->sky_ang, GF_SG_VRML_MFFLOAT)
558 : ) {
559 :
560 3 : if (st->sky_mesh) mesh_free(st->sky_mesh);
561 3 : st->sky_mesh = NULL;
562 3 : gf_sg_vrml_field_copy(&st->sky_col, &bck->skyColor, GF_SG_VRML_MFCOLOR);
563 3 : gf_sg_vrml_field_copy(&st->sky_ang, &bck->skyAngle, GF_SG_VRML_MFFLOAT);
564 : }
565 5 : if (!gf_sg_vrml_field_equal(&bck->groundColor, &st->ground_col, GF_SG_VRML_MFCOLOR)
566 5 : || !gf_sg_vrml_field_equal(&bck->groundAngle, &st->ground_ang, GF_SG_VRML_MFFLOAT)
567 : ) {
568 :
569 0 : if (st->ground_mesh) mesh_free(st->ground_mesh);
570 0 : st->ground_mesh = NULL;
571 0 : gf_sg_vrml_field_copy(&st->ground_col, &bck->groundColor, GF_SG_VRML_MFCOLOR);
572 0 : gf_sg_vrml_field_copy(&st->ground_ang, &bck->groundAngle, GF_SG_VRML_MFFLOAT);
573 : }
574 :
575 5 : back_check_gf_sc_texture_change(&st->txh_front, &bck->frontUrl);
576 5 : back_check_gf_sc_texture_change(&st->txh_back, &bck->backUrl);
577 5 : back_check_gf_sc_texture_change(&st->txh_top, &bck->topUrl);
578 5 : back_check_gf_sc_texture_change(&st->txh_bottom, &bck->bottomUrl);
579 5 : back_check_gf_sc_texture_change(&st->txh_left, &bck->leftUrl);
580 5 : back_check_gf_sc_texture_change(&st->txh_right, &bck->rightUrl);
581 :
582 :
583 5 : gf_sc_invalidate(st->compositor, NULL);
584 : }
585 :
586 : #endif /*GPAC_DISABLE_3D*/
587 :
588 : #endif /*GPAC_DISABLE_VRML*/
|