📄 grouping_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 "render3d_nodes.h"#include "grouping.h"struct og_pos{ Fixed priority; u32 position;};typedef struct{ GF_Node *owner; GF_Renderer *compositor; GROUPINGNODESTACK u32 *positions;} OrderedGroupStack;static s32 compare_priority(const void* elem1, const void* elem2){ struct og_pos *p1, *p2; p1 = (struct og_pos *)elem1; p2 = (struct og_pos *)elem2; if (p1->priority < p2->priority) return -1; if (p1->priority > p2->priority) return 1; return 0;}static void RenderOrderedGroup(GF_Node *node, void *rs, Bool is_destroy){ u32 i, count; struct og_pos *priorities; OrderedGroupStack *ogs = (OrderedGroupStack *) gf_node_get_private(node); M_OrderedGroup *og = (M_OrderedGroup *)node; RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { DeleteGroupingNode((GroupingNode *)ogs); if (ogs->positions) free(ogs->positions); free(ogs); return; } if (!og->order.count) { grouping_traverse((GroupingNode*)ogs, eff, NULL); return; } /*check whether the OrderedGroup node has changed*/ if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) { if (ogs->positions) free(ogs->positions); count = gf_node_list_get_count(og->children); priorities = (struct og_pos*)malloc(sizeof(struct og_pos)*count); for (i=0; i<count; i++) { priorities[i].position = i; priorities[i].priority = (i<og->order.count) ? og->order.vals[i] : 0; } qsort(priorities, count, sizeof(struct og_pos), compare_priority); ogs->positions = (u32*)malloc(sizeof(u32) * count); for (i=0; i<count; i++) ogs->positions[i] = priorities[i].position; free(priorities); } grouping_traverse((GroupingNode*)ogs, eff, ogs->positions);}void R3D_InitOrderedGroup(Render3D *sr, GF_Node *node){ OrderedGroupStack *ptr; GF_SAFEALLOC(ptr, OrderedGroupStack); SetupGroupingNode((GroupingNode*)ptr, sr->compositor, node, & ((M_OrderedGroup *)node)->children); gf_node_set_private(node, ptr); gf_node_set_callback_function(node, RenderOrderedGroup);}static void RenderSwitch(GF_Node *node, void *rs, Bool is_destroy){ u32 i; GF_ChildNodeItem *children; s32 whichChoice; Bool prev_switch; s32 *last_switch = (s32 *)gf_node_get_private(node); RenderEffect3D *eff; if (is_destroy) { free(last_switch); return; } eff = (RenderEffect3D *)rs; gf_node_dirty_clear(node, 0); prev_switch = eff->trav_flags; /*WARNING: X3D/MPEG4 NOT COMPATIBLE*/ if (gf_node_get_tag(node)==TAG_MPEG4_Switch) { children = ((M_Switch *)node)->choice; whichChoice = ((M_Switch *)node)->whichChoice; } else { children = ((X_Switch *)node)->children; whichChoice = ((X_Switch *)node)->whichChoice; } /*check changes in choice field*/ if (*last_switch != whichChoice) { GF_ChildNodeItem *l = children; eff->trav_flags |= GF_SR_TRAV_SWITCHED_OFF; /*deactivation must be signaled because switch may contain audio nodes (I hate this spec!!!)*/ i = 0; while (l) { if ((s32) i!=whichChoice) gf_node_render(l->node, eff); i++; l = l->next; } eff->trav_flags &= ~GF_SR_TRAV_SWITCHED_OFF; *last_switch = whichChoice; } eff->trav_flags = prev_switch; if (whichChoice>=0) { gf_node_render( gf_node_list_get_child(children, whichChoice), eff); }}void R3D_InitSwitch(Render3D *sr, GF_Node *node){ s32 *last_switch = (s32*)malloc(sizeof(s32)); *last_switch = -1; gf_node_set_private(node, last_switch); gf_node_set_callback_function(node, RenderSwitch);}typedef struct{ GF_Node *owner; GF_Renderer *compositor; GROUPINGNODESTACK GF_ColorMatrix cmat;} ColorTransformStack;/*ColorTransform*/static void RenderColorTransform(GF_Node *node, void *rs, Bool is_destroy){ M_ColorTransform *tr = (M_ColorTransform *)node; ColorTransformStack *ptr = (ColorTransformStack *)gf_node_get_private(node); RenderEffect3D *eff; if (is_destroy) { DeleteGroupingNode((GroupingNode *)ptr); free(ptr); return; } eff = (RenderEffect3D *) rs; if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) { gf_cmx_set(&ptr->cmat, tr->mrr , tr->mrg, tr->mrb, tr->mra, tr->tr, tr->mgr , tr->mgg, tr->mgb, tr->mga, tr->tg, tr->mbr, tr->mbg, tr->mbb, tr->mba, tr->tb, tr->mar, tr->mag, tr->mab, tr->maa, tr->ta); } /*note we don't clear dirty flag, this is done in traversing*/ if (ptr->cmat.identity) { grouping_traverse((GroupingNode *) ptr, eff, NULL); } else { GF_ColorMatrix gf_cmx_bck; Bool prev_cmat = !eff->color_mat.identity; if (prev_cmat) { gf_cmx_copy(&gf_cmx_bck, &eff->color_mat); gf_cmx_multiply(&eff->color_mat, &ptr->cmat); } else { gf_cmx_copy(&eff->color_mat, &ptr->cmat); } grouping_traverse((GroupingNode *) ptr, eff, NULL); /*restore effects*/ if (prev_cmat) gf_cmx_copy(&eff->color_mat, &gf_cmx_bck); else eff->color_mat.identity = 1; }}void R3D_InitColorTransform(Render3D *sr, GF_Node *node){ ColorTransformStack *stack = (ColorTransformStack *)malloc(sizeof(ColorTransformStack)); SetupGroupingNode((GroupingNode *)stack, sr->compositor, node, & ((M_ColorTransform *)node)->children); gf_cmx_init(&stack->cmat); gf_node_set_private(node, stack); gf_node_set_callback_function(node, RenderColorTransform);}static void RenderGroup(GF_Node *node, void *rs, Bool is_destroy){ GroupingNode *group = (GroupingNode *) gf_node_get_private(node); if (is_destroy) { DestroyBaseGrouping(node); } else { grouping_traverse(group, (RenderEffect3D*)rs, NULL); }}void R3D_InitGroup(Render3D *sr, GF_Node *node){ GroupingNode *stack = (GroupingNode *)malloc(sizeof(GroupingNode)); SetupGroupingNode(stack, sr->compositor, node, & ((M_Group *)node)->children); gf_node_set_private(node, stack); gf_node_set_callback_function(node, RenderGroup);}void RenderCollision(GF_Node *node, void *rs, Bool is_destroy){ u32 collide_flags; SFVec3f last_point; Fixed last_dist; M_Collision *col = (M_Collision *)node; RenderEffect3D *eff = (RenderEffect3D *)rs; GroupingNode *group = (GroupingNode *) gf_node_get_private(node); if (is_destroy) { DestroyBaseGrouping(node); return; } if (eff->traversing_mode != TRAVERSE_COLLIDE) { grouping_traverse(group, eff, NULL); } else if (col->collide) { collide_flags = eff->camera->collide_flags; last_dist = eff->camera->collide_dist; eff->camera->collide_flags &= 0; eff->camera->collide_dist = FIX_MAX; last_point = eff->camera->collide_point; if (col->proxy) { /*always check bounds to update any dirty node*/ eff->traversing_mode = TRAVERSE_GET_BOUNDS; gf_node_render(col->proxy, rs); eff->traversing_mode = TRAVERSE_COLLIDE; gf_node_render(col->proxy, rs); } else { grouping_traverse(group, (RenderEffect3D*)rs, NULL); } if (eff->camera->collide_flags & CF_COLLISION) { col->collideTime = gf_node_get_scene_time(node); gf_node_event_out_str(node, "collideTime"); /*if not closer restore*/ if (collide_flags && (last_dist<eff->camera->collide_dist)) { eff->camera->collide_flags = collide_flags; eff->camera->collide_dist = last_dist; eff->camera->collide_point = last_point; } } else { eff->camera->collide_flags = collide_flags; eff->camera->collide_dist = last_dist; } }}void R3D_InitCollision(Render3D *sr, GF_Node *node){ GroupingNode *stack = (GroupingNode *)malloc(sizeof(GroupingNode)); SetupGroupingNode(stack, sr->compositor, node, & ((M_Group *)node)->children); gf_node_set_private(node, stack); gf_node_set_callback_function(node, RenderCollision);}/*for transform, transform2D & transformMatrix2D*/typedef struct{ GF_Node *owner; GF_Renderer *compositor; GROUPINGNODESTACK GF_Matrix mx; Bool has_scale;} TransformStack;static void DestroyTransform(GF_Node *n){ TransformStack *ptr = (TransformStack *)gf_node_get_private(n); DeleteGroupingNode((GroupingNode *)ptr); free(ptr);}static void NewTransformStack(Render3D *sr, GF_Node *node, GF_ChildNodeItem **children){ TransformStack *st; GF_SAFEALLOC(st, TransformStack); gf_mx_init(st->mx); SetupGroupingNode((GroupingNode *)st, sr->compositor, node, children); gf_node_set_private(node, st);}#define TRANS_PUSH_MX \ if (eff->traversing_mode == TRAVERSE_SORT) { \ VS3D_PushMatrix(eff->surface); \ VS3D_MultMatrix(eff->surface, st->mx.m); \ } \#define TRANS_POP_MX if (eff->traversing_mode==TRAVERSE_SORT) VS3D_PopMatrix(eff->surface);static void RenderTransform(GF_Node *n, void *rs, Bool is_destroy){ GF_Matrix gf_mx_bckup; TransformStack *st = (TransformStack *)gf_node_get_private(n); M_Transform *tr = (M_Transform *)n; RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { DestroyTransform(n); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -