PageRenderTime 57ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/src/compositor/mpeg4_geometry_ifs2d.c

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