📄 geometry_stacks.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"#include <gpac/options.h>/* Shape */static void RenderShape(GF_Node *node, void *rs, Bool is_destroy){ DrawableStack *st; u32 cull_bckup; RenderEffect3D *eff; M_Shape *shape; if (is_destroy) return; eff = (RenderEffect3D *) rs; if (eff->traversing_mode==TRAVERSE_LIGHTING) return; shape = (M_Shape *) node; if (!shape->geometry) return; eff->appear = (GF_Node *) shape->appearance; /*reset this node dirty flag (because bitmap may trigger bounds invalidation on the fly)*/ gf_node_dirty_clear(node, 0); /*check traverse mode, and take care of switch-off flag*/ if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) { /*this is done regardless of switch flag*/ gf_node_render((GF_Node *) shape->geometry, eff); /*reset appearance dirty flag to get sure size changes in textures invalidates the parent graph(s)*/ gf_node_dirty_clear(eff->appear, 0); eff->appear = NULL; } else { if (eff->trav_flags & GF_SR_TRAV_SWITCHED_OFF) return; /*if we're here we passed culler already*/ if (eff->traversing_mode==TRAVERSE_RENDER) gf_node_render((GF_Node *) shape->geometry, eff); else if (eff->traversing_mode==TRAVERSE_SORT) { st = (DrawableStack*)gf_node_get_private(shape->geometry); cull_bckup = eff->cull_flag; if (st && node_cull(eff, &st->mesh->bounds, 0)) { gf_node_allow_cyclic_render(node); VS_RegisterContext(eff, node, &st->mesh->bounds, 1); } eff->cull_flag = cull_bckup; } else if (eff->traversing_mode==TRAVERSE_PICK) drawable_do_pick(shape->geometry, eff); else if (eff->traversing_mode==TRAVERSE_COLLIDE) drawable_do_collide(shape->geometry, eff); }}Bool R3D_Get2DPlaneIntersection(GF_Ray *ray, SFVec3f *res){ GF_Plane p; Fixed t, t2; p.normal.x = p.normal.y = 0; p.normal.z = FIX_ONE; p.d = 0; t2 = gf_vec_dot(p.normal, ray->dir); if (t2 == 0) return 0; t = - gf_divfix(gf_vec_dot(p.normal, ray->orig) + p.d, t2); if (t<0) return 0; *res = gf_vec_scale(ray->dir, t); gf_vec_add(*res, ray->orig, *res); return 1;}Bool R3D_PickInClipper(RenderEffect3D *eff, GF_Rect *clip){ SFVec3f pos; GF_Matrix mx; GF_Ray r; gf_mx_copy(mx, eff->model_matrix); gf_mx_inverse(&mx); r = eff->ray; gf_mx_apply_ray(&mx, &r); if (!R3D_Get2DPlaneIntersection(&r, &pos)) return 0; if ( (pos.x < clip->x) || (pos.y > clip->y) || (pos.x > clip->x + clip->width) || (pos.y < clip->y - clip->height) ) return 0; return 1;}void R3D_InitShape(Render3D *sr, GF_Node *node){ gf_node_set_callback_function(node, RenderShape);}static Bool R3D_NoIntersectionWithRay(GF_Node *owner, GF_Ray *ray, SFVec3f *vec, SFVec3f *outNormal, SFVec2f *outTexCoords){ return 0;}static void RenderBox(GF_Node *n, void *rs, Bool is_destroy){ RenderEffect3D *eff = (RenderEffect3D *)rs; DrawableStack *st = (DrawableStack*)gf_node_get_private(n); M_Box *box = (M_Box *)n; if (is_destroy) { drawable_node_destroy(n); return; } if (gf_node_dirty_get(n)) { mesh_new_box(st->mesh, box->size); gf_node_dirty_clear(n, 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_InitBox(Render3D *sr, GF_Node *node){ BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderBox);}static void RenderCone(GF_Node *n, void *rs, Bool is_destroy){ RenderEffect3D *eff = (RenderEffect3D *)rs; DrawableStack *st = (DrawableStack*)gf_node_get_private(n); M_Cone *co = (M_Cone *)n; if (is_destroy) { drawable_node_destroy(n); return; } if (gf_node_dirty_get(n)) { mesh_new_cone(st->mesh, co->height, co->bottomRadius, co->bottom, co->side, eff->surface->render->compositor->high_speed); gf_node_dirty_clear(n, 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_InitCone(Render3D *sr, GF_Node *node){ BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderCone);}static void RenderCylinder(GF_Node *n, void *rs, Bool is_destroy){ RenderEffect3D *eff = (RenderEffect3D *)rs; DrawableStack *st = (DrawableStack*)gf_node_get_private(n); M_Cylinder *cy = (M_Cylinder *)n; if (is_destroy) { drawable_node_destroy(n); return; } if (gf_node_dirty_get(n) ) { mesh_new_cylinder(st->mesh, cy->height, cy->radius, cy->bottom, cy->side, cy->top, eff->surface->render->compositor->high_speed); gf_node_dirty_clear(n, 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_InitCylinder(Render3D *sr, GF_Node *node){ BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderCylinder);}static void RenderSphere(GF_Node *n, void *rs, Bool is_destroy){ RenderEffect3D *eff = (RenderEffect3D *)rs; DrawableStack *st = (DrawableStack*)gf_node_get_private(n); M_Sphere *sp = (M_Sphere *)n; if (is_destroy) { drawable_node_destroy(n); return; } if (gf_node_dirty_get(n)) { mesh_new_sphere(st->mesh, sp->radius, eff->surface->render->compositor->high_speed); gf_node_dirty_clear(n, 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_InitSphere(Render3D *sr, GF_Node *node){ BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderSphere);}static Bool CircleIntersectWithRay(GF_Node *owner, GF_Ray *ray, SFVec3f *outPoint, SFVec3f *outNormal, SFVec2f *outTexCoords){ Fixed r, sqr; Bool inside; if (!R3D_Get2DPlaneIntersection(ray, outPoint)) return 0; r = ((M_Circle *)owner)->radius; sqr = gf_mulfix(r, r); inside = (sqr >= gf_mulfix(outPoint->x, outPoint->x) + gf_mulfix(outPoint->y, outPoint->y)) ? 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 RenderCircle(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 = ((M_Circle *) node)->radius * 2; stack2D_reset(st); gf_path_add_ellipse(st->path, 0, 0, a, a); mesh_new_ellipse(st->mesh, a, a, eff->surface->render->compositor->high_speed); 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_InitCircle(Render3D *sr, GF_Node *node){ stack2D *st = BaseStack2D(sr->compositor, node); gf_node_set_callback_function(node, RenderCircle); st->IntersectWithRay = CircleIntersectWithRay;}static Bool EllipseIntersectWithRay(GF_Node *owner, GF_Ray *ray, SFVec3f *outPoint, SFVec3f *outNormal, SFVec2f *outTexCoords){ Fixed a, b; Bool inside; if (!R3D_Get2DPlaneIntersection(ray, outPoint)) return 0; a = ((M_Ellipse *)owner)->radius.x; a = gf_mulfix(a, a); b = ((M_Ellipse *)owner)->radius.y; b = gf_mulfix(b, b); inside = (gf_muldiv(outPoint->x, outPoint->x, a) + gf_muldiv(outPoint->y, outPoint->y, b) <= 1) ? 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, a) + FIX_ONE/2; outTexCoords->y = gf_divfix(outPoint->y, b) + FIX_ONE/2; } return 1;}static void RenderEllipse(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 = ((M_Ellipse *) node)->radius.x; Fixed b = ((M_Ellipse *) node)->radius.y; stack2D_reset(st); gf_path_add_ellipse(st->path, 0, 0, a, b); mesh_new_ellipse(st->mesh, a, b, eff->surface->render->compositor->high_speed); 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_InitEllipse(Render3D *sr, GF_Node *node){ stack2D *st = BaseStack2D(sr->compositor, node); gf_node_set_callback_function(node, RenderEllipse); st->IntersectWithRay = EllipseIntersectWithRay;}static Bool RectangleIntersectWithRay(GF_Node *owner, GF_Ray *ray, SFVec3f *outPoint, SFVec3f *outNormal, SFVec2f *outTexCoords){ stack2D *st; Bool inside; if (!R3D_Get2DPlaneIntersection(ray, outPoint)) return 0; st = (stack2D *) gf_node_get_private(owner); inside = ( (outPoint->x >= st->mesh->bounds.min_edge.x) && (outPoint->y >= st->mesh->bounds.min_edge.y) && (outPoint->x <= st->mesh->bounds.max_edge.x) && (outPoint->y <= st->mesh->bounds.max_edge.y) ) ? 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, ((M_Rectangle*)owner)->size.x) + FIX_ONE/2; outTexCoords->y = gf_divfix(outPoint->y, ((M_Rectangle*)owner)->size.y) + FIX_ONE/2; } return 1;}static void RenderRectangle(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; } /*build vec path*/ if (gf_node_dirty_get(node)) { SFVec2f s = ((M_Rectangle *) node)->size; stack2D_reset(st); gf_path_add_rect_center(st->path, 0, 0, s.x, s.y); mesh_new_rectangle(st->mesh, s); 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_InitRectangle(Render3D *sr, GF_Node *node){ stack2D *st = BaseStack2D(sr->compositor, node); gf_node_set_callback_function(node, RenderRectangle); st->IntersectWithRay = RectangleIntersectWithRay;}Bool Stack2DIntersectWithRay(GF_Node *owner, GF_Ray *r, SFVec3f *outPoint, SFVec3f *outNormal, SFVec2f *outTexCoords){ Bool inside; stack2D *st; if (!R3D_Get2DPlaneIntersection(r, outPoint)) return 0; st = (stack2D *) gf_node_get_private(owner); if ( (outPoint->x < st->mesh->bounds.min_edge.x) || (outPoint->y < st->mesh->bounds.min_edge.y) || (outPoint->x > st->mesh->bounds.max_edge.x) || (outPoint->y > st->mesh->bounds.max_edge.y) ) return 0; inside = gf_path_point_over(st->path, outPoint->x, outPoint->y); if (!inside) return 0; if (outNormal) { outNormal->x = outNormal->y = 0; outNormal->z = FIX_ONE; } if (outTexCoords) { outTexCoords->x = gf_divfix(outPoint->x, (st->mesh->bounds.max_edge.x - st->mesh->bounds.min_edge.x)) + FIX_ONE/2; outTexCoords->y = gf_divfix(outPoint->y, (st->mesh->bounds.max_edge.y - st->mesh->bounds.min_edge.y)) + FIX_ONE/2; } return 1;}//#define CHECK_VALID_C2D(nbPts) if (cur_index+nbPts>=pt_count) { gf_path_reset(st->path); return; }#define CHECK_VALID_C2D(nbPts)static void build_curve2D(stack2D *st, M_Curve2D *c2D){ SFVec2f orig, ct_orig, ct_end, end; u32 cur_index, i, remain, type_count, pt_count; SFVec2f *pts; M_Coordinate2D *coord = (M_Coordinate2D *)c2D->point;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -