📄 geometry_x3d.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / 3D rendering module * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include "visual_surface.h"Bool Stack2DIntersectWithRay(GF_Node *owner, GF_Ray *r, SFVec3f *outPoint, SFVec3f *outNormal, SFVec2f *outTexCoords);static Bool R3D_NoIntersectionWithRay(GF_Node *owner, GF_Ray *ray, SFVec3f *vec, SFVec3f *outNormal, SFVec2f *outTexCoords){ return 0;}static Bool Disk2DIntersectWithRay(GF_Node *owner, GF_Ray *ray, SFVec3f *outPoint, SFVec3f *outNormal, SFVec2f *outTexCoords){ Fixed r, sqr, sqdist; Bool inside; if (!R3D_Get2DPlaneIntersection(ray, outPoint)) return 0; sqdist = gf_mulfix(outPoint->x, outPoint->x) + gf_mulfix(outPoint->y, outPoint->y); r = ((X_Disk2D *)owner)->outerRadius; sqr = gf_mulfix(r, r); inside = (sqr >= sqdist) ? 1 : 0; if (!inside) return 0; r = ((X_Disk2D *)owner)->innerRadius; sqr = r*r; inside = (sqr <= sqdist) ? 1 : 0; if (!inside) return 0; if (outNormal) { outNormal->x = outNormal->y = 0; outNormal->z = FIX_ONE; } if (outTexCoords) { outTexCoords->x = gf_divfix(outPoint->x, r) + FIX_ONE/2; outTexCoords->y = gf_divfix(outPoint->y, r) + FIX_ONE/2; } return 1;}static void RenderDisk2D(GF_Node *node, void *rs, Bool is_destroy){ stack2D *st = (stack2D *)gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { stack2D_node_predestroy(node); return; } if (gf_node_dirty_get(node)) { Fixed a = ((X_Disk2D *) node)->outerRadius * 2; stack2D_reset(st); /*FIXME - move to 3D stack and skip path stuff to enable it with OpenGL-ES*/ gf_path_add_ellipse(st->path, 0, 0, a, a); a = ((X_Disk2D *) node)->innerRadius * 2; if (a) gf_path_add_ellipse(st->path, 0, 0, a, a); mesh_from_path(st->mesh, st->path); gf_node_dirty_clear(node, 0); } if (!eff->traversing_mode) { stack2D_draw(st, eff); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) eff->bbox = st->mesh->bounds;}void R3D_InitDisk2D(Render3D *sr, GF_Node *node){ stack2D *st = BaseStack2D(sr->compositor, node); gf_node_set_callback_function(node, RenderDisk2D); st->IntersectWithRay = Disk2DIntersectWithRay;}static void RenderArc2D(GF_Node *node, void *rs, Bool is_destroy){ stack2D *st = (stack2D *)gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { stack2D_node_predestroy(node); return; } if (gf_node_dirty_get(node)) { stack2D_reset(st); if (gf_node_get_tag(node)==TAG_X3D_Arc2D) { X_Arc2D *a = (X_Arc2D *) node; gf_path_add_arc(st->path, a->radius, a->startAngle, a->endAngle, 0); mesh_get_outline(st->mesh, st->path); } else { X_ArcClose2D *a = (X_ArcClose2D *) node; gf_path_add_arc(st->path, a->radius, a->startAngle, a->endAngle, !stricmp(a->closureType.buffer, "PIE") ? 2 : 1); mesh_from_path(st->mesh, st->path); } gf_node_dirty_clear(node, 0); } if (!eff->traversing_mode) { stack2D_draw(st, eff); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) eff->bbox = st->mesh->bounds;}void R3D_InitArc2D(Render3D *sr, GF_Node *node){ stack2D *st = BaseStack2D(sr->compositor, node); gf_node_set_callback_function(node, RenderArc2D); if (gf_node_get_tag(node)==TAG_X3D_Arc2D) { st->IntersectWithRay = R3D_NoIntersectionWithRay; } else { st->IntersectWithRay = Stack2DIntersectWithRay; }}static void RenderPolyline2D(GF_Node *node, void *rs, Bool is_destroy){ stack2D *st = (stack2D *)gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { stack2D_node_predestroy(node); return; } if (gf_node_dirty_get(node)) { u32 i; X_Polyline2D *a = (X_Polyline2D *) node; stack2D_reset(st); for (i=0; i<a->lineSegments.count; i++) { if (i) { gf_path_add_line_to(st->path, a->lineSegments.vals[i].x, a->lineSegments.vals[i].y); } else { gf_path_add_move_to(st->path, a->lineSegments.vals[i].x, a->lineSegments.vals[i].y); } } mesh_get_outline(st->mesh, st->path); gf_node_dirty_clear(node, 0); } if (!eff->traversing_mode) { stack2D_draw(st, eff); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) eff->bbox = st->mesh->bounds;}void R3D_InitPolyline2D(Render3D *sr, GF_Node *node){ stack2D *st = BaseStack2D(sr->compositor, node); gf_node_set_callback_function(node, RenderPolyline2D); st->IntersectWithRay = R3D_NoIntersectionWithRay;}static void RenderPolypoint2D(GF_Node *node, void *rs, Bool is_destroy){ SFColorRGBA col; DrawableStack *st = (DrawableStack *)gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { drawable_node_destroy(node); return; } if (gf_node_dirty_get(node)) { u32 i; X_Polypoint2D *p = (X_Polypoint2D *)node; mesh_reset(st->mesh); st->mesh->mesh_type = MESH_POINTSET; col.red = col.green = col.blue = 0; col.alpha = FIX_ONE; for (i=0; i<p->point.count; i++) { mesh_set_point(st->mesh, p->point.vals[i].x, p->point.vals[i].y, 0, col); mesh_set_index(st->mesh, st->mesh->v_count-1); } gf_node_dirty_clear(node, 0); } if (!eff->traversing_mode) { VS_DrawMesh(eff, st->mesh); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) eff->bbox = st->mesh->bounds;}void R3D_InitPolypoint2D(Render3D *sr, GF_Node *node){ DrawableStack *st = BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderPolypoint2D); st->IntersectWithRay = R3D_NoIntersectionWithRay;}static void RenderLineSet(GF_Node *node, void *rs, Bool is_destroy){ DrawableStack *st = (DrawableStack *)gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { drawable_node_destroy(node); return; } if (gf_node_dirty_get(node)) { u32 i, j, c_idx; GenMFField *cols; GF_Vertex vx; Bool rgba_col; X_LineSet *p = (X_LineSet *)node; X_Coordinate *c = (X_Coordinate *) p->coord; gf_node_dirty_clear(node, 0); mesh_reset(st->mesh); st->mesh->mesh_type = MESH_LINESET; cols = NULL; rgba_col = 0; if (p->color) { if (gf_node_get_tag(p->color)==TAG_X3D_ColorRGBA) { rgba_col = 1; cols = (GenMFField *) & ((X_ColorRGBA *) p->color)->color; } else { cols = (GenMFField *) & ((M_Color *) p->color)->color; } } c_idx = 0; memset(&vx, 0, sizeof(GF_Vertex)); for (i=0; i<p->vertexCount.count; i++) { if (p->vertexCount.vals[i]<2) continue; for (j=0; j<(u32) p->vertexCount.vals[i]; j++) { vx.pos = c->point.vals[c_idx]; if (cols && (cols->count>c_idx)) { if (rgba_col) { vx.color = ((MFColorRGBA *)cols)->vals[c_idx]; } else { vx.color = gf_sg_sfcolor_to_rgba( ((MFColor *)cols)->vals[c_idx]); } } mesh_set_vertex_vx(st->mesh, &vx); if (j) { mesh_set_index(st->mesh, st->mesh->v_count-2); mesh_set_index(st->mesh, st->mesh->v_count-1); } c_idx++; if (c_idx==c->point.count) break; } } if (cols) st->mesh->flags |= MESH_HAS_COLOR; mesh_update_bounds(st->mesh); } if (!eff->traversing_mode) { VS_DrawMesh(eff, st->mesh); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) eff->bbox = st->mesh->bounds;}void R3D_InitLineSet(Render3D *sr, GF_Node *node){ DrawableStack *st = BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderLineSet); st->IntersectWithRay = R3D_NoIntersectionWithRay;}static void RenderTriangleSet2D(GF_Node *node, void *rs, Bool is_destroy){ DrawableStack *st = (DrawableStack *)gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { drawable_node_destroy(node); return; } if (gf_node_dirty_get(node)) { u32 i, count, idx; GF_Vertex v1, v2, v3; X_TriangleSet2D *p = (X_TriangleSet2D *)node; mesh_reset(st->mesh); st->mesh->mesh_type = MESH_TRIANGLES; v1.color.red = v1.color.green = v1.color.blue = 0; v1.normal.x = v1.normal.y = 0; v1.normal.z = FIX_ONE; v1.pos.z = 0; v3 = v2 = v1; count = p->vertices.count; while (count%3) count--; for (i=0; i<count; i+=3) { idx = st->mesh->v_count; v1.pos.x = p->vertices.vals[i].x; v1.pos.y = p->vertices.vals[i].y; v2.pos.x = p->vertices.vals[i+1].x; v2.pos.y = p->vertices.vals[i+1].y; v3.pos.x = p->vertices.vals[i+2].x; v3.pos.y = p->vertices.vals[i+2].y; mesh_set_vertex_vx(st->mesh, &v1); mesh_set_vertex_vx(st->mesh, &v2); mesh_set_vertex_vx(st->mesh, &v3); gf_vec_diff(v2.pos, v2.pos, v1.pos); gf_vec_diff(v3.pos, v3.pos, v1.pos); v1.pos = gf_vec_cross(v2.pos, v3.pos); if (v1.pos.z<0) { mesh_set_triangle(st->mesh, idx, idx+2, idx+1); } else { mesh_set_triangle(st->mesh, idx, idx+1, idx+2); } } st->mesh->flags |= MESH_IS_2D; mesh_update_bounds(st->mesh); gf_node_dirty_clear(node, 0); } if (!eff->traversing_mode) { VS_DrawMesh(eff, st->mesh); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) eff->bbox = st->mesh->bounds;}void R3D_InitTriangleSet2D(Render3D *sr, GF_Node *node){ BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderTriangleSet2D);}static void BuildTriangleSet(GF_Mesh *mesh, GF_Node *_coords, GF_Node *_color, GF_Node *_txcoords, GF_Node *_normal, MFInt32 *indices, Bool normalPerVertex, Bool ccw, Bool solid){ u32 i, count, generate_tx; GF_Vertex vx; GenMFField *cols; MFVec3f *norms; MFVec2f *txcoords; Bool rgba_col; X_Coordinate *c = (X_Coordinate *) _coords; mesh_reset(mesh); cols = NULL; rgba_col = 0; if (_color) { if (gf_node_get_tag(_color)==TAG_X3D_ColorRGBA) { rgba_col = 1; cols = (GenMFField *) & ((X_ColorRGBA *) _color)->color; } else { cols = (GenMFField *) & ((M_Color *) _color)->color; } } norms = NULL; if (_normal) norms = & ((M_Normal *)_normal)->vector; txcoords = NULL; generate_tx = 0; /*FIXME - this can't work with multitexturing*/ if (_txcoords) { switch (gf_node_get_tag(_txcoords)) { case TAG_X3D_TextureCoordinate: case TAG_MPEG4_TextureCoordinate: txcoords = & ((M_TextureCoordinate *)_txcoords)->point; break; case TAG_X3D_TextureCoordinateGenerator: generate_tx = 1; break; } } if (indices) { count = indices->count; } else { count = c->point.count; } while (count%3) count--; memset(&vx, 0, sizeof(GF_Vertex)); for (i=0; i<count; i++) { u32 idx; if (indices) { if (indices->count<=i) return; idx = indices->vals[i]; } else { idx = i; } vx.pos = c->point.vals[idx]; if (cols && (cols->count>idx)) { if (rgba_col) { vx.color = ((MFColorRGBA *)cols)->vals[idx]; } else { vx.color = gf_sg_sfcolor_to_rgba( ((MFColor *)cols)->vals[idx]); } } if (norms && (norms->count>idx)) { vx.normal = norms->vals[idx]; gf_vec_norm(&vx.normal); } if (txcoords) { if (txcoords->count>idx) vx.texcoords = txcoords->vals[idx]; } /*X3D says nothing about default texture mapping here...*/ else if (!generate_tx) { switch (i%3) { case 2: vx.texcoords.x = FIX_ONE; vx.texcoords.y = 0; break; case 1: vx.texcoords.x = FIX_ONE/2; vx.texcoords.y = FIX_ONE; break; case 0: vx.texcoords.x = 0; vx.texcoords.y = 0; break; } } mesh_set_vertex_vx(mesh, &vx); } for (i=0; i<mesh->v_count; i+=3) { mesh_set_triangle(mesh, i, i+1, i+2); } if (generate_tx) mesh_generate_tex_coords(mesh, _txcoords); if (!ccw) mesh->flags |= MESH_IS_CW; if (cols) mesh->flags |= MESH_HAS_COLOR; if (rgba_col) mesh->flags |= MESH_HAS_ALPHA; if (!_normal) mesh_recompute_normals(mesh); if (solid) mesh->flags |= MESH_IS_SOLID; mesh_update_bounds(mesh); gf_mesh_build_aabbtree(mesh);}static void RenderTriangleSet(GF_Node *node, void *rs, Bool is_destroy){ DrawableStack *st = (DrawableStack *)gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { drawable_node_destroy(node); return; } if (gf_node_dirty_get(node)) { X_TriangleSet *ts = (X_TriangleSet *)node; gf_node_dirty_clear(node, 0); if (!ts->coord) return; BuildTriangleSet(st->mesh, ts->coord, ts->color, ts->texCoord, ts->normal, NULL, ts->normalPerVertex, ts->ccw, ts->solid); } if (!eff->traversing_mode) { VS_DrawMesh(eff, st->mesh); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) { eff->bbox = st->mesh->bounds; }}void R3D_InitTriangleSet(Render3D *sr, GF_Node *node){ BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderTriangleSet);}static void RenderIndexedTriangleSet(GF_Node *node, void *rs, Bool is_destroy){ DrawableStack *st = (DrawableStack *)gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { drawable_node_destroy(node); return; } if (gf_node_dirty_get(node)) { X_IndexedTriangleSet *its = (X_IndexedTriangleSet *)node; gf_node_dirty_clear(node, 0); if (!its->coord) return; BuildTriangleSet(st->mesh, its->coord, its->color, its->texCoord, its->normal, &its->index, its->normalPerVertex, its->ccw, its->solid); } if (!eff->traversing_mode) { VS_DrawMesh(eff, st->mesh); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) { eff->bbox = st->mesh->bounds; }}static void ITS_SetIndex(GF_Node *node){ X_IndexedTriangleSet *its = (X_IndexedTriangleSet*)node; gf_sg_vrml_field_copy(&its->index, &its->set_index, GF_SG_VRML_MFINT32); gf_sg_vrml_mf_reset(&its->set_index, GF_SG_VRML_MFINT32);}void R3D_InitIndexedTriangleSet(Render3D *sr, GF_Node *node){ X_IndexedTriangleSet *its = (X_IndexedTriangleSet*)node; BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderIndexedTriangleSet); its->on_set_index = ITS_SetIndex;}static void BuildTriangleStripSet(GF_Mesh *mesh, GF_Node *_coords, GF_Node *_color, GF_Node *_txcoords, GF_Node *_normal, MFInt32 *stripList, MFInt32 *indices, Bool normalPerVertex, Bool ccw, Bool solid)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -