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