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 : #include "visual_manager.h"
30 :
31 : #ifndef GPAC_DISABLE_VRML
32 :
33 7558 : static void ifs2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
34 : {
35 : u32 i;
36 : SFVec2f *pts;
37 : u32 ci_count, c_count;
38 : Bool started;
39 : M_IndexedFaceSet2D *ifs2D;
40 : M_Coordinate2D *coord;
41 :
42 7558 : if (! gf_node_dirty_get(node)) return;
43 :
44 : ifs2D = (M_IndexedFaceSet2D *)node;
45 243 : coord = (M_Coordinate2D *)ifs2D->coord;
46 243 : drawable_reset_path(stack);
47 243 : gf_node_dirty_clear(node, 0);
48 243 : drawable_mark_modified(stack, tr_state);
49 :
50 :
51 243 : c_count = coord->point.count;
52 243 : ci_count = ifs2D->coordIndex.count;
53 243 : pts = coord->point.vals;
54 :
55 243 : if (ci_count > 0) {
56 : started = 0;
57 201 : for (i=0; i < ci_count; i++) {
58 201 : if (ifs2D->coordIndex.vals[i] == -1) {
59 25 : gf_path_close(stack->path);
60 : started = 0;
61 176 : } else if (!started) {
62 : started = 1;
63 36 : gf_path_add_move_to_vec(stack->path, &pts[ifs2D->coordIndex.vals[i]]);
64 : } else {
65 140 : gf_path_add_line_to_vec(stack->path, &pts[ifs2D->coordIndex.vals[i]]);
66 : }
67 : }
68 26 : if (started) gf_path_close(stack->path);
69 217 : } else if (c_count) {
70 217 : gf_path_add_move_to_vec(stack->path, &pts[0]);
71 1227 : for (i=1; i < c_count; i++) {
72 1010 : gf_path_add_line_to_vec(stack->path, &pts[i]);
73 : }
74 217 : gf_path_close(stack->path);
75 : }
76 : }
77 :
78 :
79 2419 : static void IFS2D_Draw(GF_Node *node, GF_TraverseState *tr_state)
80 : {
81 : u32 i, count, ci_count;
82 : #if 0 //unused
83 : u32 j, ind_col, num_col;
84 : SFVec2f center, end;
85 : SFColor col_cen;
86 : GF_EVGStencil *grad;
87 : u32 *colors;
88 : #endif
89 : SFVec2f start;
90 : SFVec2f *pts;
91 : SFColor col;
92 : Fixed alpha;
93 2419 : DrawableContext *ctx = tr_state->ctx;
94 : M_IndexedFaceSet2D *ifs2D = (M_IndexedFaceSet2D *)node;
95 2419 : M_Coordinate2D *coord = (M_Coordinate2D*) ifs2D->coord;
96 2419 : M_Color *color = (M_Color *) ifs2D->color;
97 :
98 : col.red = col.green = col.blue = 0;
99 : /*simple case, no color specified*/
100 2419 : if (!ifs2D->color) {
101 2409 : visual_2d_texture_path(tr_state->visual, ctx->drawable->path, ctx, tr_state);
102 2409 : visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, NULL, NULL, tr_state);
103 2409 : return;
104 : }
105 :
106 : /*if default face use first color*/
107 10 : ci_count = ifs2D->coordIndex.count;
108 10 : pts = coord->point.vals;
109 :
110 10 : if (ci_count == 0) {
111 0 : col = (ifs2D->colorIndex.count > 0) ? color->color.vals[ifs2D->colorIndex.vals[0]] : color->color.vals[0];
112 :
113 0 : alpha = INT2FIX(GF_COL_A(ctx->aspect.fill_color)) / 255;
114 0 : if (!alpha || !ctx->aspect.pen_props.width) {
115 0 : alpha = INT2FIX(GF_COL_A(ctx->aspect.line_color)) / 255;
116 0 : ctx->aspect.line_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
117 : } else {
118 0 : ctx->aspect.fill_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
119 : }
120 0 : visual_2d_texture_path(tr_state->visual, ctx->drawable->path, ctx, tr_state);
121 0 : visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, NULL, NULL, tr_state);
122 0 : return;
123 : }
124 :
125 : /*we have color per faces so we need N path :(*/
126 10 : if (! ifs2D->colorPerVertex) {
127 0 : GF_Path *path = gf_path_new();
128 :
129 : count = 0;
130 : i = 0;
131 : while (1) {
132 0 : gf_path_reset(path);
133 0 : start = pts[ifs2D->coordIndex.vals[i]];
134 0 : gf_path_add_move_to(path, start.x, start.y);
135 0 : i++;
136 :
137 0 : while (ifs2D->coordIndex.vals[i] != -1) {
138 0 : start = pts[ifs2D->coordIndex.vals[i]];
139 0 : gf_path_add_line_to(path, start.x, start.y);
140 0 : i++;
141 0 : if (i >= ci_count) break;
142 : }
143 : /*close in ALL cases because even if the start/end points are the same the line join needs to be present*/
144 0 : gf_path_close(path);
145 :
146 0 : col = (ifs2D->colorIndex.count > 0) ? color->color.vals[ifs2D->colorIndex.vals[count]] : color->color.vals[count];
147 :
148 0 : alpha = INT2FIX(GF_COL_A(ctx->aspect.fill_color)) / 255;
149 0 : if (!alpha) {
150 0 : alpha = INT2FIX(GF_COL_A(ctx->aspect.line_color)) / 255;
151 0 : ctx->aspect.line_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
152 : } else {
153 0 : ctx->aspect.fill_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
154 : }
155 :
156 0 : visual_2d_texture_path(tr_state->visual, path, ctx, tr_state);
157 0 : visual_2d_draw_path(tr_state->visual, path, ctx, NULL, NULL, tr_state);
158 0 : count++;
159 0 : i++;
160 0 : if (i >= ci_count) break;
161 0 : ctx->flags &= ~CTX_PATH_FILLED;
162 0 : ctx->flags &= ~CTX_PATH_STROKE;
163 : }
164 0 : gf_path_del(path);
165 0 : return;
166 : }
167 :
168 : /*final case, color per vertex means gradient fill/strike*/
169 : /*not supported, fill default*/
170 10 : visual_2d_texture_path(tr_state->visual, ctx->drawable->path, ctx, tr_state);
171 10 : visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, NULL, NULL, tr_state);
172 10 : return;
173 :
174 :
175 : #if 0 //deprecated
176 : path = gf_path_new();
177 :
178 : ind_col = 0;
179 : i = 0;
180 : while (1) {
181 : gf_path_reset(path);
182 : start = pts[ifs2D->coordIndex.vals[i]];
183 : center = start;
184 : gf_path_add_move_to(path, start.x, start.y);
185 : num_col = 1;
186 : i+=1;
187 : while (ifs2D->coordIndex.vals[i] != -1) {
188 : end = pts[ifs2D->coordIndex.vals[i]];
189 : gf_path_add_line_to(path, end.x, end.y);
190 : i++;
191 : center.x += end.x;
192 : center.y += end.y;
193 : num_col ++;
194 : if (i >= ci_count) break;
195 : }
196 : gf_path_close(path);
197 : num_col++;
198 :
199 : alpha = INT2FIX(GF_COL_A(ctx->aspect.fill_color) ) / 255;
200 :
201 : colors = (u32*)gf_malloc(sizeof(u32) * num_col);
202 : col_cen.blue = col_cen.red = col_cen.green = 0;
203 : for (j=0; j<num_col-1; j++) {
204 : if (ifs2D->colorIndex.count > ind_col + j) {
205 : col = color->color.vals[ifs2D->colorIndex.vals[ind_col + j]];
206 : } else if (ci_count > ind_col + j) {
207 : col = color->color.vals[ifs2D->coordIndex.vals[ind_col + j]];
208 : }
209 : colors[j] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
210 : col_cen.blue += col.blue;
211 : col_cen.green += col.green;
212 : col_cen.red += col.red;
213 : }
214 : colors[num_col-1] = colors[0];
215 :
216 : if (ifs2D->colorIndex.count > ind_col) {
217 : col = color->color.vals[ifs2D->colorIndex.vals[ind_col]];
218 : } else if (ci_count > ind_col) {
219 : col = color->color.vals[ifs2D->coordIndex.vals[ind_col]];
220 : }
221 : col_cen.blue += col.blue;
222 : col_cen.green += col.green;
223 : col_cen.red += col.red;
224 :
225 : gf_evg_stencil_set_vertex_path(grad, path);
226 : gf_evg_stencil_set_vertex_colors(grad, colors, num_col);
227 :
228 : gf_free(colors);
229 :
230 : col_cen.blue /= num_col;
231 : col_cen.green /= num_col;
232 : col_cen.red /= num_col;
233 : center.x /= num_col;
234 : center.y /= num_col;
235 : gf_evg_stencil_set_vertex_center(grad, center.x, center.y, GF_COL_ARGB_FIXED(alpha, col_cen.red, col_cen.green, col_cen.blue) );
236 :
237 : gf_evg_stencil_set_matrix(grad, &ctx->transform);
238 :
239 : /*draw*/
240 : visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, grad, grad, tr_state);
241 :
242 : gf_evg_stencil_delete(grad);
243 :
244 : //goto next point
245 : i++;
246 : ind_col += num_col + 1;
247 : if (i >= ci_count) break;
248 : grad = gf_evg_stencil_new(GF_STENCIL_VERTEX_GRADIENT);
249 : ctx->flags &= ~CTX_PATH_FILLED;
250 : ctx->flags &= ~CTX_PATH_STROKE;
251 : }
252 : gf_path_del(path);
253 : #endif
254 :
255 :
256 : }
257 :
258 7651 : static void TraverseIFS2D(GF_Node *node, void *rs, Bool is_destroy)
259 : {
260 : DrawableContext *ctx;
261 : M_IndexedFaceSet2D *ifs2D = (M_IndexedFaceSet2D *)node;
262 7651 : Drawable *stack = (Drawable *)gf_node_get_private(node);
263 : GF_TraverseState *tr_state = (GF_TraverseState *)rs;
264 :
265 7651 : if (is_destroy) {
266 93 : drawable_node_del(node);
267 93 : return;
268 : }
269 7558 : if (!ifs2D->coord) return;
270 :
271 7558 : ifs2d_check_changes(node, stack, tr_state);
272 :
273 7558 : switch (tr_state->traversing_mode) {
274 2419 : case TRAVERSE_DRAW_2D:
275 2419 : IFS2D_Draw(node, tr_state);
276 2419 : return;
277 : #ifndef GPAC_DISABLE_3D
278 211 : case TRAVERSE_DRAW_3D:
279 : {
280 : DrawAspect2D asp;
281 :
282 211 : if (!stack->mesh) {
283 32 : stack->mesh = new_mesh();
284 32 : mesh_new_ifs2d(stack->mesh, node);
285 : }
286 :
287 : memset(&asp, 0, sizeof(DrawAspect2D));
288 211 : drawable_get_aspect_2d_mpeg4(node, &asp, tr_state);
289 211 : if (ifs2D->color && !GF_COL_A(asp.fill_color) ) {
290 : /*use special func to disable outline recompute and handle recompute ourselves*/
291 0 : StrikeInfo2D *si = drawable_get_strikeinfo(tr_state->visual->compositor, stack, &asp, tr_state->appear, NULL, 0, tr_state);
292 0 : if (!si->mesh_outline) {
293 0 : si->mesh_outline = new_mesh();
294 0 : mesh_new_ils(si->mesh_outline, ifs2D->coord, &ifs2D->coordIndex, ifs2D->color, &ifs2D->colorIndex, ifs2D->colorPerVertex, 1);
295 : }
296 0 : visual_3d_mesh_strike(tr_state, si->mesh_outline, asp.pen_props.width, asp.line_scale, asp.pen_props.dash);
297 : } else {
298 211 : visual_3d_draw_2d_with_aspect(stack, tr_state, &asp);
299 : }
300 : return;
301 : }
302 : #endif
303 674 : case TRAVERSE_PICK:
304 674 : vrml_drawable_pick(stack, tr_state);
305 674 : return;
306 6 : case TRAVERSE_GET_BOUNDS:
307 6 : gf_path_get_bounds(stack->path, &tr_state->bounds);
308 6 : return;
309 4248 : case TRAVERSE_SORT:
310 : #ifndef GPAC_DISABLE_3D
311 4248 : if (tr_state->visual->type_3d) return;
312 : #endif
313 :
314 4248 : ctx = drawable_init_context_mpeg4(stack, tr_state);
315 4248 : if (!ctx) return;
316 4243 : drawable_finalize_sort(ctx, tr_state, NULL);
317 4243 : return;
318 : }
319 : }
320 :
321 0 : static void IFS2D_SetColorIndex(GF_Node *node, GF_Route *route)
322 : {
323 : M_IndexedFaceSet2D *ifs2D = (M_IndexedFaceSet2D *)node;
324 0 : if (node) {
325 0 : gf_sg_vrml_field_copy(&ifs2D->colorIndex, &ifs2D->set_colorIndex, GF_SG_VRML_MFINT32);
326 0 : gf_sg_vrml_mf_reset(&ifs2D->set_colorIndex, GF_SG_VRML_MFINT32);
327 : }
328 0 : }
329 :
330 0 : static void IFS2D_SetCoordIndex(GF_Node *node, GF_Route *route)
331 : {
332 : M_IndexedFaceSet2D *ifs2D = (M_IndexedFaceSet2D *)node;
333 0 : if (node) {
334 0 : gf_sg_vrml_field_copy(&ifs2D->coordIndex, &ifs2D->set_coordIndex, GF_SG_VRML_MFINT32);
335 0 : gf_sg_vrml_mf_reset(&ifs2D->set_coordIndex, GF_SG_VRML_MFINT32);
336 : }
337 0 : }
338 :
339 93 : void compositor_init_indexed_face_set2d(GF_Compositor *compositor, GF_Node *node)
340 : {
341 : M_IndexedFaceSet2D *ifs2D = (M_IndexedFaceSet2D *)node;
342 93 : Drawable *stack = drawable_stack_new(compositor, node);
343 93 : stack->flags = DRAWABLE_USE_TRAVERSE_DRAW;
344 93 : gf_node_set_callback_function(node, TraverseIFS2D);
345 93 : ifs2D->on_set_colorIndex = IFS2D_SetColorIndex;
346 93 : ifs2D->on_set_coordIndex = IFS2D_SetCoordIndex;
347 :
348 : #ifdef GPAC_ENABLE_COVERAGE
349 93 : if (gf_sys_is_cov_mode()) {
350 : IFS2D_SetCoordIndex(NULL, NULL);
351 : IFS2D_SetColorIndex(NULL, NULL);
352 : }
353 : #endif
354 :
355 93 : }
356 :
357 : #endif /*GPAC_DISABLE_VRML*/
|