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 2338 : static void ils2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
34 : {
35 : u32 i;
36 : Bool started;
37 : SFVec2f *pts;
38 : M_IndexedLineSet2D *ils2D;
39 : M_Coordinate2D *coord;
40 :
41 2338 : if (! gf_node_dirty_get(node)) return;
42 :
43 49 : drawable_reset_path(stack);
44 49 : gf_node_dirty_clear(node, 0);
45 49 : drawable_mark_modified(stack, tr_state);
46 :
47 : ils2D = (M_IndexedLineSet2D *)node;
48 49 : coord = (M_Coordinate2D *)ils2D->coord;
49 :
50 49 : pts = coord->point.vals;
51 49 : if (ils2D->coordIndex.count > 0) {
52 : started = 0;
53 99 : for (i=0; i < ils2D->coordIndex.count; i++) {
54 : /*NO close on ILS2D*/
55 99 : if (ils2D->coordIndex.vals[i] == -1) {
56 : started = 0;
57 72 : } else if (!started) {
58 : started = 1;
59 30 : gf_path_add_move_to(stack->path, pts[ils2D->coordIndex.vals[i]].x, pts[ils2D->coordIndex.vals[i]].y);
60 : } else {
61 42 : gf_path_add_line_to(stack->path, pts[ils2D->coordIndex.vals[i]].x, pts[ils2D->coordIndex.vals[i]].y);
62 : }
63 : }
64 36 : } else if (coord->point.count) {
65 36 : gf_path_add_move_to(stack->path, pts[0].x, pts[0].y);
66 95 : for (i=1; i < coord->point.count; i++) {
67 59 : gf_path_add_line_to(stack->path, pts[i].x, pts[i].y);
68 : }
69 : }
70 49 : stack->path->flags |= GF_PATH_FILL_ZERO_NONZERO;
71 : }
72 :
73 898 : static void ILS2D_Draw(GF_Node *node, GF_TraverseState *tr_state)
74 : {
75 : GF_Path *path;
76 : SFVec2f *pts;
77 : SFColor col;
78 : Fixed alpha;
79 : u32 i, count, col_ind, ind, end_at;
80 : u32 linear[2];
81 : #if 0 //unused
82 : u32 *colors, j;
83 : #endif
84 : SFVec2f start, end;
85 : u32 num_col;
86 : GF_EVGStencil *grad;
87 898 : DrawableContext *ctx = tr_state->ctx;
88 : M_IndexedLineSet2D *ils2D = (M_IndexedLineSet2D *)node;
89 898 : M_Coordinate2D *coord = (M_Coordinate2D*) ils2D->coord;
90 898 : M_Color *color = (M_Color *) ils2D->color;
91 :
92 : end.x = end.y = 0;
93 1794 : if (!coord->point.count) return;
94 :
95 898 : if (! ils2D->color) {
96 : /*no texturing*/
97 894 : visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, NULL, NULL, tr_state);
98 894 : return;
99 : }
100 :
101 4 : alpha = INT2FIX(GF_COL_A(ctx->aspect.line_color)) / 255;
102 4 : pts = coord->point.vals;
103 :
104 4 : if (!ils2D->colorPerVertex || (color->color.count<2) ) {
105 : count = 0;
106 2 : end_at = ils2D->coordIndex.count;
107 2 : if (!end_at) end_at = coord->point.count;
108 2 : ind = ils2D->coordIndex.count ? ils2D->coordIndex.vals[0] : 0;
109 : i=1;
110 2 : path = gf_path_new();
111 2 : gf_path_add_move_to(path, pts[ind].x, pts[ind].y);
112 :
113 16 : for (; i<=end_at; i++) {
114 16 : if ((i==end_at) || (ils2D->coordIndex.count && ils2D->coordIndex.vals[i] == -1)) {
115 :
116 : /*draw current*/
117 4 : col_ind = (ils2D->colorIndex.count && (ils2D->colorIndex.vals[count]>=0) ) ? (u32) ils2D->colorIndex.vals[count] : count;
118 4 : if (col_ind>=color->color.count) col_ind=color->color.count-1;
119 4 : col = color->color.vals[col_ind];
120 4 : ctx->aspect.line_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
121 :
122 4 : visual_2d_draw_path(tr_state->visual, path, ctx, NULL, NULL, tr_state);
123 :
124 4 : i++;
125 4 : if (i>=end_at) break;
126 2 : gf_path_reset(path);
127 :
128 2 : ind = (ils2D->coordIndex.count && (ils2D->coordIndex.vals[i]>=0)) ? (u32) ils2D->coordIndex.vals[i] : i;
129 2 : gf_path_add_move_to(path, pts[ind].x, pts[ind].y);
130 :
131 2 : if (ils2D->coordIndex.count) count++;
132 2 : continue;
133 : } else {
134 12 : ind = (ils2D->coordIndex.count && (ils2D->coordIndex.vals[i]>=0) ) ? (u32) ils2D->coordIndex.vals[i] : i;
135 12 : gf_path_add_line_to(path, pts[ind].x, pts[ind].y);
136 : }
137 : }
138 2 : gf_path_del(path);
139 2 : return;
140 : }
141 :
142 2 : end_at = ils2D->coordIndex.count;
143 2 : if (!end_at) end_at = coord->point.count;
144 :
145 : col_ind = 0;
146 : i=0;
147 2 : path = gf_path_new();
148 : while (1) {
149 6 : gf_path_reset(path);
150 4 : ind = (ils2D->coordIndex.count && (ils2D->coordIndex.vals[i]>=0)) ? (u32) ils2D->coordIndex.vals[i] : i;
151 4 : start = pts[ind];
152 : num_col = 1;
153 4 : i++;
154 4 : gf_path_add_move_to(path, start.x, start.y);
155 :
156 4 : if (ils2D->coordIndex.count) {
157 14 : while (ils2D->coordIndex.vals[i] != -1) {
158 12 : end = pts[ils2D->coordIndex.vals[i]];
159 12 : gf_path_add_line_to(path, end.x, end.y);
160 12 : i++;
161 12 : num_col++;
162 12 : if (i >= ils2D->coordIndex.count) break;
163 : }
164 : } else {
165 0 : while (i<end_at) {
166 0 : end = pts[i];
167 0 : gf_path_add_line_to(path, end.x, end.y);
168 0 : i++;
169 0 : num_col++;
170 : }
171 : }
172 :
173 : /*use linear gradient*/
174 4 : if (num_col==2) {
175 : Fixed pos[2];
176 0 : grad = gf_evg_stencil_new(GF_STENCIL_LINEAR_GRADIENT);
177 0 : if (ils2D->colorIndex.count) {
178 0 : col = color->color.vals[ils2D->colorIndex.vals[col_ind]];
179 0 : linear[0] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
180 0 : col = color->color.vals[ils2D->colorIndex.vals[col_ind+1]];
181 0 : linear[1] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
182 0 : } else if (ils2D->coordIndex.count) {
183 0 : col = color->color.vals[ils2D->coordIndex.vals[col_ind]];
184 0 : linear[0] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
185 0 : col = color->color.vals[ils2D->coordIndex.vals[col_ind+1]];
186 0 : linear[1] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
187 : } else {
188 0 : col = color->color.vals[col_ind];
189 0 : linear[0] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
190 0 : col = color->color.vals[col_ind+1];
191 0 : linear[1] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
192 : }
193 0 : pos[0] = 0;
194 0 : pos[1] = FIX_ONE;
195 0 : gf_evg_stencil_set_linear_gradient(grad, start.x, start.y, end.x, end.y);
196 0 : gf_evg_stencil_set_gradient_interpolation(grad, pos, linear, 2);
197 : } else {
198 : grad = NULL;
199 : #if 0 //unused
200 : grad = gf_evg_stencil_new(GF_STENCIL_VERTEX_GRADIENT);
201 : if (grad) {
202 : gf_evg_stencil_set_vertex_path(grad, path);
203 :
204 : colors = (u32*)gf_malloc(sizeof(u32) * num_col);
205 : for (j=0; j<num_col; j++) {
206 : if (ils2D->colorIndex.count>0) {
207 : col = color->color.vals[ils2D->colorIndex.vals[col_ind+j]];
208 : } else if (ils2D->coordIndex.count) {
209 : col = color->color.vals[ils2D->coordIndex.vals[col_ind+j]];
210 : } else {
211 : col = color->color.vals[col_ind+j];
212 : }
213 : colors[j] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
214 : }
215 : gf_evg_stencil_set_vertex_colors(grad, colors, num_col);
216 : gf_free(colors);
217 : }
218 : #endif
219 :
220 : }
221 4 : gf_evg_stencil_set_matrix(grad, &ctx->transform);
222 4 : visual_2d_draw_path(tr_state->visual, path, ctx, NULL, grad, tr_state);
223 4 : if (grad) gf_evg_stencil_delete(grad);
224 :
225 4 : i ++;
226 4 : col_ind += num_col + 1;
227 4 : if (i >= ils2D->coordIndex.count) break;
228 2 : ctx->flags &= ~CTX_PATH_STROKE;
229 : }
230 2 : gf_path_del(path);
231 : }
232 :
233 :
234 2387 : static void TraverseILS2D(GF_Node *node, void *rs, Bool is_destroy)
235 : {
236 : DrawableContext *ctx;
237 : M_IndexedLineSet2D *ils2D = (M_IndexedLineSet2D *)node;
238 2387 : Drawable *stack = (Drawable *)gf_node_get_private(node);
239 : GF_TraverseState *tr_state = (GF_TraverseState *)rs;
240 :
241 2387 : if (is_destroy) {
242 49 : drawable_node_del(node);
243 49 : return;
244 : }
245 :
246 2338 : if (!ils2D->coord) return;
247 :
248 2338 : ils2d_check_changes(node, stack, tr_state);
249 :
250 2338 : switch (tr_state->traversing_mode) {
251 898 : case TRAVERSE_DRAW_2D:
252 898 : ILS2D_Draw(node, tr_state);
253 898 : return;
254 : #ifndef GPAC_DISABLE_3D
255 164 : case TRAVERSE_DRAW_3D:
256 164 : if (!stack->mesh) {
257 13 : stack->mesh = new_mesh();
258 13 : mesh_new_ils(stack->mesh, ils2D->coord, &ils2D->coordIndex, ils2D->color, &ils2D->colorIndex, ils2D->colorPerVertex, 0);
259 : }
260 164 : if (ils2D->color) {
261 : DrawAspect2D asp;
262 : memset(&asp, 0, sizeof(DrawAspect2D));
263 0 : drawable_get_aspect_2d_mpeg4(node, &asp, tr_state);
264 :
265 0 : visual_3d_mesh_strike(tr_state, stack->mesh, asp.pen_props.width, asp.line_scale, asp.pen_props.dash);
266 : } else {
267 164 : visual_3d_draw_2d(stack, tr_state);
268 : }
269 : return;
270 : #endif
271 372 : case TRAVERSE_PICK:
272 372 : vrml_drawable_pick(stack, tr_state);
273 372 : return;
274 0 : case TRAVERSE_GET_BOUNDS:
275 0 : gf_path_get_bounds(stack->path, &tr_state->bounds);
276 0 : return;
277 904 : case TRAVERSE_SORT:
278 : #ifndef GPAC_DISABLE_3D
279 904 : if (tr_state->visual->type_3d) return;
280 : #endif
281 :
282 904 : ctx = drawable_init_context_mpeg4(stack, tr_state);
283 904 : if (!ctx) return;
284 : /*ILS2D are NEVER filled*/
285 904 : ctx->aspect.fill_color &= 0x00FFFFFF;
286 904 : drawable_finalize_sort(ctx, tr_state, NULL);
287 904 : return;
288 : default:
289 : return;
290 : }
291 : }
292 :
293 0 : static void ILS2D_SetColorIndex(GF_Node *node, GF_Route *route)
294 : {
295 : M_IndexedLineSet2D *ils2D = (M_IndexedLineSet2D *)node;
296 0 : if (node) {
297 0 : gf_sg_vrml_field_copy(&ils2D->colorIndex, &ils2D->set_colorIndex, GF_SG_VRML_MFINT32);
298 0 : gf_sg_vrml_mf_reset(&ils2D->set_colorIndex, GF_SG_VRML_MFINT32);
299 : }
300 0 : }
301 :
302 0 : static void ILS2D_SetCoordIndex(GF_Node *node, GF_Route *route)
303 : {
304 : M_IndexedLineSet2D *ils2D = (M_IndexedLineSet2D *)node;
305 0 : if (node) {
306 0 : gf_sg_vrml_field_copy(&ils2D->coordIndex, &ils2D->set_coordIndex, GF_SG_VRML_MFINT32);
307 0 : gf_sg_vrml_mf_reset(&ils2D->set_coordIndex, GF_SG_VRML_MFINT32);
308 : }
309 0 : }
310 :
311 49 : void compositor_init_indexed_line_set2d(GF_Compositor *compositor, GF_Node *node)
312 : {
313 : M_IndexedLineSet2D *ils2D = (M_IndexedLineSet2D *)node;
314 49 : Drawable *stack = drawable_stack_new(compositor, node);
315 49 : stack->flags = DRAWABLE_USE_TRAVERSE_DRAW;
316 49 : gf_node_set_callback_function(node, TraverseILS2D);
317 49 : ils2D->on_set_colorIndex = ILS2D_SetColorIndex;
318 49 : ils2D->on_set_coordIndex = ILS2D_SetCoordIndex;
319 :
320 : #ifdef GPAC_ENABLE_COVERAGE
321 49 : if (gf_sys_is_cov_mode()) {
322 : ILS2D_SetCoordIndex(NULL, NULL);
323 : ILS2D_SetColorIndex(NULL, NULL);
324 : }
325 : #endif
326 :
327 49 : }
328 :
329 : #endif /*GPAC_DISABLE_VRML*/
|