📄 viewport.c
字号:
RenderEffect3D *eff = (RenderEffect3D *)rs; M_Viewpoint *vp = (M_Viewpoint*) node; ViewStack *st = (ViewStack *) gf_node_get_private(node); if (is_destroy) { DestroyViewStack(node); return; } assert(eff->viewpoints);// if (!eff->camera->is_3D) return; /*first traverse, bound if needed*/ if (gf_list_find(eff->viewpoints, node) < 0) { gf_list_add(eff->viewpoints, node); assert(gf_list_find(st->reg_stacks, eff->viewpoints)==-1); gf_list_add(st->reg_stacks, eff->viewpoints); if (gf_list_get(eff->viewpoints, 0) == vp) { if (!vp->isBound) Bindable_SetIsBound(node, 1); } else { if (gf_is_default_scene_viewpoint(node)) Bindable_SetSetBind(node, 1); } VPCHANGED(st->compositor); /*in any case don't draw the first time (since the viewport could have been declared last)*/ gf_sr_invalidate(st->compositor, NULL); } /*not rendering vp, return*/ if (eff->traversing_mode != TRAVERSE_RENDER_BINDABLE) { /*store model matrix if changed - NOTE: we always have a 1-frame delay between VP used and real world... we could remove this by pre-rendering the scene before applying vp, but that would mean 2 scene traversals*/ if ((eff->traversing_mode==TRAVERSE_SORT) || (eff->traversing_mode==TRAVERSE_GET_BOUNDS) ) { if (!gf_mx_equal(&st->world_view_mx, &eff->model_matrix)) { gf_mx_copy(st->world_view_mx, eff->model_matrix); gf_node_dirty_set(node, 0, 0); } } eff->trav_flags |= TF_DONT_CULL; return; } /*not bound or in 2D surface*/ if (!vp->isBound || !eff->navigations) return; if (!gf_node_dirty_get(node)) return; gf_node_dirty_clear(node, 0); /*move to local system*/ gf_mx_copy(mx, st->world_view_mx); gf_mx_add_translation(&mx, vp->position.x, vp->position.y, vp->position.z); gf_mx_add_rotation(&mx, vp->orientation.q, vp->orientation.x, vp->orientation.y, vp->orientation.z); gf_mx_decompose(&mx, &pos, &v1, &ori, &v2); /*get center*/ v1.x = v1.y = v1.z = 0; /*X3D specifies examine center*/ if (gf_node_get_tag(node)==TAG_X3D_Viewpoint) v1 = ((X_Viewpoint *)node)->centerOfRotation; gf_mx_apply_vec(&st->world_view_mx, &v1); /*set frustrum param - animate only if not bound last frame and jump false*/ VS_ViewpointChange(eff, node, (!st->prev_was_bound && !vp->jump) ? 1 : 0, vp->fieldOfView, pos, ori, v1); st->prev_was_bound = 1;}void R3D_InitViewpoint(Render3D *sr, GF_Node *node){ ViewStack *st; GF_SAFEALLOC(st, ViewStack); st->reg_stacks = gf_list_new(); gf_mx_init(st->world_view_mx); gf_sr_traversable_setup(st, node, sr->compositor); gf_node_set_private(node, st); gf_node_set_callback_function(node, RenderViewpoint); ((M_Viewpoint*)node)->on_set_bind = viewpoint_set_bind;}static void navinfo_set_bind(GF_Node *node){ ViewStack *st = (ViewStack *) gf_node_get_private(node); Bindable_OnSetBind(node, st->reg_stacks); gf_sr_invalidate(st->compositor, NULL);}static void RenderNavigationInfo(GF_Node *node, void *rs, Bool is_destroy){ u32 i; SFVec3f start, end; Fixed scale; RenderEffect3D *eff = (RenderEffect3D *)rs; M_NavigationInfo *ni = (M_NavigationInfo *) node; ViewStack *st = (ViewStack *) gf_node_get_private(node); if (is_destroy) { DestroyViewStack(node); return; } if (!eff->navigations) return; /*first traverse, bound if needed*/ if (gf_list_find(eff->navigations, node) < 0) { gf_list_add(eff->navigations, node); if (gf_list_get(eff->navigations, 0) == ni) { if (!ni->isBound) Bindable_SetIsBound(node, 1); } assert(gf_list_find(st->reg_stacks, eff->navigations)==-1); gf_list_add(st->reg_stacks, eff->navigations); /*in any case don't draw the first time*/ gf_sr_invalidate(st->compositor, NULL); return; } /*not bound*/ if (!ni->isBound) return; /*not rendering, return*/ if (eff->traversing_mode != TRAVERSE_RENDER_BINDABLE) { if ((eff->traversing_mode==TRAVERSE_SORT) || (eff->traversing_mode==TRAVERSE_GET_BOUNDS) ) { if (!gf_mx_equal(&st->world_view_mx, &eff->model_matrix)) { gf_mx_copy(st->world_view_mx, eff->model_matrix); gf_node_dirty_set(node, 0, 0); } } return; } if (!gf_node_dirty_get(node)) return; gf_node_dirty_clear(node, 0); eff->camera->navigation_flags = 0; eff->camera->navigate_mode = 0; for (i=0; i<ni->type.count; i++) { if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "ANY")) eff->camera->navigation_flags |= NAV_ANY; if (!eff->camera->navigate_mode) { if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "NONE")) eff->camera->navigate_mode = GF_NAVIGATE_NONE; else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "WALK")) eff->camera->navigate_mode = GF_NAVIGATE_WALK; else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "EXAMINE")) eff->camera->navigate_mode = GF_NAVIGATE_EXAMINE; else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "FLY")) eff->camera->navigate_mode = GF_NAVIGATE_FLY; else if (ni->type.vals[i] && !stricmp(ni->type.vals[i], "QTVR")) eff->camera->navigate_mode = GF_NAVIGATE_VR; } } if (ni->headlight) eff->camera->navigation_flags |= NAV_HEADLIGHT; start.x = start.y = start.z = 0; end.x = end.y = 0; end.z = FIX_ONE; gf_mx_apply_vec(&st->world_view_mx, &start); gf_mx_apply_vec(&st->world_view_mx, &end); gf_vec_diff(end, end, start); scale = gf_vec_len(end); eff->camera->speed = gf_mulfix(scale, ni->speed); eff->camera->visibility = gf_mulfix(scale, ni->visibilityLimit); if (ni->avatarSize.count) eff->camera->avatar_size.x = gf_mulfix(scale, ni->avatarSize.vals[0]); if (ni->avatarSize.count>1) eff->camera->avatar_size.y = gf_mulfix(scale, ni->avatarSize.vals[1]); if (ni->avatarSize.count>2) eff->camera->avatar_size.z = gf_mulfix(scale, ni->avatarSize.vals[2]); if (eff->is_pixel_metrics) { u32 s = MAX(eff->surface->width, eff->surface->height); s /= 2;// eff->camera->speed = ni->speed; eff->camera->visibility *= s; eff->camera->avatar_size.x *= s; eff->camera->avatar_size.y *= s; eff->camera->avatar_size.z *= s; }}void R3D_InitNavigationInfo(Render3D *sr, GF_Node *node){ ViewStack *st; GF_SAFEALLOC(st, ViewStack); st->reg_stacks = gf_list_new(); gf_sr_traversable_setup(st, node, sr->compositor); gf_node_set_private(node, st); gf_node_set_callback_function(node, RenderNavigationInfo); ((M_NavigationInfo*)node)->on_set_bind = navinfo_set_bind;}static void fog_set_bind(GF_Node *node){ ViewStack *st = (ViewStack *) gf_node_get_private(node); Bindable_OnSetBind(node, st->reg_stacks); gf_sr_invalidate(st->compositor, NULL);}static void RenderFog(GF_Node *node, void *rs, Bool is_destroy){ Fixed density, vrange; SFVec3f start, end; ViewStack *vp_st; M_Viewpoint *vp; RenderEffect3D *eff = (RenderEffect3D *)rs; M_Fog *fog = (M_Fog *) node; ViewStack *st = (ViewStack *) gf_node_get_private(node); if (is_destroy) { DestroyViewStack(node); return; } if (!eff->fogs) return; /*first traverse, bound if needed*/ if (gf_list_find(eff->fogs, node) < 0) { gf_list_add(eff->fogs, node); if (gf_list_get(eff->fogs, 0) == fog) { if (!fog->isBound) Bindable_SetIsBound(node, 1); } assert(gf_list_find(st->reg_stacks, eff->fogs)==-1); gf_list_add(st->reg_stacks, eff->fogs); gf_mx_copy(st->world_view_mx, eff->model_matrix); /*in any case don't draw the first time*/ gf_sr_invalidate(st->compositor, NULL); return; } /*not rendering, return*/ if (eff->traversing_mode != TRAVERSE_RENDER_BINDABLE) { if ((eff->traversing_mode==TRAVERSE_SORT) || (eff->traversing_mode==TRAVERSE_GET_BOUNDS) ) gf_mx_copy(st->world_view_mx, eff->model_matrix); return; } /*not bound*/ if (!fog->isBound || !fog->visibilityRange) return; /*fog visibility is expressed in current bound VP so get its matrix*/ vp = (M_Viewpoint*)gf_list_get(eff->viewpoints, 0); vp_st = NULL; if (vp && vp->isBound) vp_st = (ViewStack *) gf_node_get_private((GF_Node *)vp); start.x = start.y = start.z = 0; end.x = end.y = 0; end.z = fog->visibilityRange; if (vp_st) { gf_mx_apply_vec(&vp_st->world_view_mx, &start); gf_mx_apply_vec(&vp_st->world_view_mx, &end); } gf_mx_apply_vec(&st->world_view_mx, &start); gf_mx_apply_vec(&st->world_view_mx, &end); gf_vec_diff(end, end, start); vrange = gf_vec_len(end); density = gf_invfix(vrange); VS3D_SetFog(eff->surface, fog->fogType.buffer, fog->color, density, vrange);}void R3D_InitFog(Render3D *sr, GF_Node *node){ ViewStack *st; GF_SAFEALLOC(st, ViewStack); st->reg_stacks = gf_list_new(); gf_sr_traversable_setup(st, node, sr->compositor); gf_node_set_private(node, st); gf_node_set_callback_function(node, RenderFog); ((M_Fog*)node)->on_set_bind = fog_set_bind;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -