📄 grouping_stacks.c
字号:
if (gf_node_dirty_get(n) & GF_SG_NODE_DIRTY) { Bool scale_rot, recenter; gf_mx_init(st->mx); if (tr->translation.x || tr->translation.y || tr->translation.z) gf_mx_add_translation(&st->mx, tr->translation.x, tr->translation.y, tr->translation.z); recenter = (tr->center.x || tr->center.y || tr->center.z) ? 1 : 0; if (recenter) gf_mx_add_translation(&st->mx, tr->center.x, tr->center.y, tr->center.z); if (tr->rotation.q) gf_mx_add_rotation(&st->mx, tr->rotation.q, tr->rotation.x, tr->rotation.y, tr->rotation.z); scale_rot = (tr->scaleOrientation.q) ? 1 : 0; if (scale_rot) gf_mx_add_rotation(&st->mx, tr->scaleOrientation.q, tr->scaleOrientation.x, tr->scaleOrientation.y, tr->scaleOrientation.z); if ((tr->scale.x != FIX_ONE) || (tr->scale.y != FIX_ONE) || (tr->scale.z != FIX_ONE)) gf_mx_add_scale(&st->mx, tr->scale.x, tr->scale.y, tr->scale.z); if (scale_rot) gf_mx_add_rotation(&st->mx, -tr->scaleOrientation.q, tr->scaleOrientation.x, tr->scaleOrientation.y, tr->scaleOrientation.z); if (recenter) gf_mx_add_translation(&st->mx, -tr->center.x, -tr->center.y, -tr->center.z); st->has_scale = ((tr->scale.x != FIX_ONE) || (tr->scale.y != FIX_ONE) || (tr->scale.z != FIX_ONE)) ? 1 : 0; } gf_mx_copy(gf_mx_bckup, eff->model_matrix); gf_mx_add_matrix(&eff->model_matrix, &st->mx); TRANS_PUSH_MX /*note we don't clear dirty flag, this is done in traversing*/ grouping_traverse((GroupingNode *) st, eff, NULL); TRANS_POP_MX gf_mx_copy(eff->model_matrix, gf_mx_bckup); if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) gf_mx_apply_bbox(&st->mx, &eff->bbox);}void R3D_InitTransform(Render3D *sr, GF_Node *node){ NewTransformStack(sr, node, & ((M_Transform *)node)->children); gf_node_set_callback_function(node, RenderTransform);}static void RenderTransform2D(GF_Node *node, void *rs, Bool is_destroy){ GF_Matrix gf_mx_bckup; M_Transform2D *tr = (M_Transform2D *)node; TransformStack *st = (TransformStack*)gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *) rs; if (is_destroy) { DestroyTransform(node); return; } if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) { GF_Matrix2D mx; gf_mx2d_init(mx); if ((tr->scale.x != FIX_ONE) || (tr->scale.y != FIX_ONE)) gf_mx2d_add_scale_at(&mx, tr->scale.x, tr->scale.y, 0, 0, tr->scaleOrientation); if (tr->rotationAngle) gf_mx2d_add_rotation(&mx, tr->center.x, tr->center.y, tr->rotationAngle); if (tr->translation.x || tr->translation.y) gf_mx2d_add_translation(&mx, tr->translation.x, tr->translation.y); st->has_scale = ((tr->scale.x != FIX_ONE) || (tr->scale.y != FIX_ONE)) ? 1 : 0; gf_mx_from_mx2d(&st->mx, &mx); } gf_mx_copy(gf_mx_bckup, eff->model_matrix); gf_mx_add_matrix(&eff->model_matrix, &st->mx); TRANS_PUSH_MX /*note we don't clear dirty flag, this is done in traversing*/ grouping_traverse((GroupingNode *) st, eff, NULL); TRANS_POP_MX gf_mx_copy(eff->model_matrix, gf_mx_bckup); if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) gf_mx_apply_bbox(&st->mx, &eff->bbox);}void R3D_InitTransform2D(Render3D *sr, GF_Node *node){ NewTransformStack(sr, node, & ((M_Transform2D *)node)->children); gf_node_set_callback_function(node, RenderTransform2D);}void TM2D_GetMatrix(GF_Node *n, GF_Matrix *mx){ GF_Matrix2D mat; M_TransformMatrix2D *tm = (M_TransformMatrix2D*)n; gf_mx2d_init(mat); mat.m[0] = tm->mxx; mat.m[1] = tm->mxy; mat.m[2] = tm->tx; mat.m[3] = tm->myx; mat.m[4] = tm->myy; mat.m[5] = tm->ty; gf_mx_from_mx2d(mx, &mat);}/*TransformMatrix2D*/static void RenderTransformMatrix2D(GF_Node *node, void *rs, Bool is_destroy){ GF_Matrix gf_mx_bckup; M_TransformMatrix2D *tm = (M_TransformMatrix2D*)node; TransformStack *st = (TransformStack *) gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { DestroyTransform(node); return; } if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) { TM2D_GetMatrix(node, &st->mx); st->has_scale = ((tm->mxx != FIX_ONE) || (tm->myy != FIX_ONE) || tm->mxy || tm->myx) ? 1 : 0; } gf_mx_copy(gf_mx_bckup, eff->model_matrix); gf_mx_add_matrix(&eff->model_matrix, &st->mx); TRANS_PUSH_MX /*note we don't clear dirty flag, this is done in traversing*/ grouping_traverse((GroupingNode *)st, eff, NULL); TRANS_POP_MX gf_mx_copy(eff->model_matrix, gf_mx_bckup); if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) gf_mx_apply_bbox(&st->mx, &eff->bbox);}void R3D_InitTransformMatrix2D(Render3D *sr, GF_Node *node){ NewTransformStack(sr, node, & ((M_TransformMatrix2D *)node)->children); gf_node_set_callback_function(node, RenderTransformMatrix2D);}static void RenderBillboard(GF_Node *n, void *rs, Bool is_destroy){ GF_Matrix gf_mx_bckup; TransformStack *st = (TransformStack *)gf_node_get_private(n); M_Billboard *bb = (M_Billboard *)n; RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { DestroyTransform(n); return; } /*can't cache the matrix here*/ gf_mx_init(st->mx); if (eff->camera->is_3D) { SFVec3f z, axis; Fixed axis_len; SFVec3f user_pos = eff->camera->position; gf_mx_apply_vec(&eff->model_matrix, &user_pos); gf_vec_norm(&user_pos); axis = bb->axisOfRotation; axis_len = gf_vec_len(axis); if (axis_len<FIX_EPSILON) { SFVec3f x, y, t; /*get user's right in local coord*/ gf_vec_diff(t, eff->camera->position, eff->camera->target); gf_vec_norm(&t); x = gf_vec_cross(eff->camera->up, t); gf_vec_norm(&x); gf_mx_rotate_vector(&eff->model_matrix, &x); gf_vec_norm(&x); /*get user's up in local coord*/ y = eff->camera->up; gf_mx_rotate_vector(&eff->model_matrix, &y); gf_vec_norm(&y); z = gf_vec_cross(x, y); gf_vec_norm(&z); gf_mx_rotation_matrix_from_vectors(&st->mx, x, y, z); gf_mx_inverse(&st->mx); } else { SFVec3f tmp; Fixed d, cosw, sinw, angle; gf_vec_norm(&axis); /*map eye & z into plane with normal axis through 0.0*/ d = -gf_vec_dot(axis, user_pos); tmp = gf_vec_scale(axis, d); gf_vec_add(user_pos, user_pos, tmp); gf_vec_norm(&user_pos); z.x = z.y = 0; z.z = FIX_ONE; d = -gf_vec_dot(axis, z); tmp = gf_vec_scale(axis, d); gf_vec_add(z, z, tmp); gf_vec_norm(&z); cosw = gf_vec_dot(user_pos, z); tmp = gf_vec_cross(user_pos, z); sinw = gf_vec_len(tmp); angle = gf_acos(cosw); gf_vec_norm(&tmp); if ((sinw>0) && (gf_vec_dot(axis, tmp) > 0)) gf_vec_rev(axis); gf_mx_add_rotation(&st->mx, angle, axis.x, axis.y, axis.z); } } gf_mx_copy(gf_mx_bckup, eff->model_matrix); gf_mx_add_matrix(&eff->model_matrix, &st->mx); TRANS_PUSH_MX /*note we don't clear dirty flag, this is done in traversing*/ grouping_traverse((GroupingNode *) st, eff, NULL); TRANS_POP_MX gf_mx_copy(eff->model_matrix, gf_mx_bckup); if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) gf_mx_apply_bbox(&st->mx, &eff->bbox);}void R3D_InitBillboard(Render3D *sr, GF_Node *node){ NewTransformStack(sr, node, & ((M_Billboard *)node)->children); gf_node_set_callback_function(node, RenderBillboard);}static void RenderLOD(GF_Node *node, void *rs, Bool is_destroy){ GF_ChildNodeItem *children; MFFloat *ranges; SFVec3f pos, usr; u32 which_child, nb_children; Fixed dist; Bool do_all; GF_Matrix mx; SFVec3f center; RenderEffect3D *eff = (RenderEffect3D *)rs; s32 *prev_child = (s32 *)gf_node_get_private(node); if (is_destroy) { free(prev_child); return; } /*WARNING: X3D/MPEG4 NOT COMPATIBLE*/ if (gf_node_get_tag(node) == TAG_MPEG4_LOD) { children = ((M_LOD *) node)->level; ranges = &((M_LOD *) node)->range; center = ((M_LOD *) node)->center; } else { children = ((X_LOD *) node)->children; ranges = &((X_LOD *) node)->range; center = ((X_LOD *) node)->center; } if (!children) return; nb_children = gf_node_list_get_count(children); /*can't cache the matric here*/ usr = eff->camera->position; pos = center; gf_mx_copy(mx, eff->model_matrix); gf_mx_inverse(&mx); gf_mx_apply_vec(&mx, &usr); gf_vec_diff(pos, pos, usr); dist = gf_vec_len(pos); for (which_child=0; which_child<ranges->count; which_child++) { if (dist<ranges->vals[which_child]) break; } if (which_child>=nb_children) which_child = nb_children-1; /*check if we're traversing the same child or not for audio rendering*/ do_all = 0; if (gf_node_dirty_get(node)) { gf_node_dirty_clear(node, 0); do_all = 1; } else if ((s32) which_child != *prev_child) { *prev_child = which_child; do_all = 1; } if (do_all) { u32 i; Bool prev_flags = eff->trav_flags; GF_ChildNodeItem *l = children; eff->trav_flags |= GF_SR_TRAV_SWITCHED_OFF; i=0; while (l) { if (i!=which_child) gf_node_render(l->node, rs); l = l->next; } eff->trav_flags = prev_flags; } gf_node_render(gf_node_list_get_child(children, which_child), rs);}void R3D_InitLOD(Render3D *sr, GF_Node *node){ s32 *stack = (s32*)malloc(sizeof(s32)); *stack = -1; gf_node_set_callback_function(node, RenderLOD); gf_node_set_private(node, stack);}/*currently static group use the same render as all grouping nodes, without any opts.since we already do a lot of caching (lights, sensors) at the grouping node level, I'm not surewe could get anything better trying to optimize the rest, since what is not cached in the base groupingnode always involves frustum culling, and caching that would require caching partial model matrix (fromthe static group to each leaf)*/#if 0static void RenderStaticGroup(GF_Node *node, void *rs){ GroupingNode *group = (GroupingNode *) gf_node_get_private(node); grouping_traverse(group, (RenderEffect3D*)rs, NULL);}#endifvoid R3D_InitStaticGroup(Render3D *sr, GF_Node *node){ GroupingNode *stack = (GroupingNode *)malloc(sizeof(GroupingNode)); SetupGroupingNode(stack, sr->compositor, node, & ((X_StaticGroup *)node)->children); gf_node_set_private(node, stack); gf_node_set_callback_function(node, RenderGroup);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -