📄 visual_surface.c
字号:
VS3D_SetViewport(eff->surface, eff->camera->vp); /*setup projection*/ VS_SetupProjection(eff); /*turn off depth buffer in 2D*/ VS3D_SetDepthBuffer(eff->surface, eff->camera->is_3D); /*set headlight if any*/ VS3D_SetHeadlight(eff->surface, (eff->camera->navigation_flags & NAV_HEADLIGHT) ? 1 : 0, eff->camera); /*setup background*/ mode = eff->traversing_mode; eff->traversing_mode = TRAVERSE_RENDER_BINDABLE; bindable = (GF_Node*) gf_list_get(eff->backgrounds, 0); /*if in layer clear z buffer (even if background)*/ if (in_layer) VS3D_ClearDepth(eff->surface); if (Bindable_GetIsBound(bindable)) { gf_node_render(bindable, eff); } /*clear if not in layer*/ else if (!in_layer) { SFColor col; col.red = INT2FIX((eff->surface->render->compositor->back_color>>16)&0xFF) / 255; col.green = INT2FIX((eff->surface->render->compositor->back_color>>8)&0xFF) / 255; col.blue = INT2FIX((eff->surface->render->compositor->back_color)&0xFF) / 255; /*if composite surface, clear with alpha = 0*/ VS3D_ClearSurface(eff->surface, col, (eff->surface==eff->surface->render->surface) ? FIX_ONE : 0); } eff->traversing_mode = mode;}void VS_SetupEffects(VisualSurface *surface, RenderEffect3D *eff){ eff->surface = surface; eff->camera = &surface->camera; eff->backgrounds = surface->back_stack; eff->viewpoints = surface->view_stack; eff->fogs = surface->fog_stack; eff->navigations = surface->navigation_stack; eff->color_mat.identity = 1; eff->camera->vp.x = eff->camera->vp.y = 0; eff->min_hsize = INT2FIX(MIN(surface->width, surface->height) / 2); if (!eff->min_hsize) eff->min_hsize = FIX_ONE; /*main surface, set AR*/ if (surface->render->surface==surface) { if (eff->surface->render->compositor->has_size_info) { eff->camera->vp.x = INT2FIX(eff->surface->render->out_x); eff->camera->vp.y = INT2FIX(eff->surface->render->out_y); eff->camera->vp.width = INT2FIX(eff->surface->render->out_width); eff->camera->vp.height = INT2FIX(eff->surface->render->out_height); eff->camera->width = INT2FIX(eff->surface->width); eff->camera->height = INT2FIX(eff->surface->height); } else { Fixed sw, sh; sw = INT2FIX(eff->surface->render->out_width); sh = INT2FIX(eff->surface->render->out_height); /*AR changed, rebuild camera*/ if ((sw!=eff->camera->vp.width) || (sh!=eff->camera->vp.height)) { eff->camera->width = eff->camera->vp.width = INT2FIX(eff->surface->render->out_width); eff->camera->height = eff->camera->vp.height = INT2FIX(eff->surface->render->out_height); eff->camera->flags |= CAM_IS_DIRTY; } } } /*composite surface, no AR*/ else { eff->camera->vp.width = eff->camera->width = INT2FIX(surface->width); eff->camera->vp.height = eff->camera->height = INT2FIX(surface->height); } if (!eff->is_pixel_metrics) { if (eff->camera->height > eff->camera->width) { eff->camera->height = 2*gf_divfix(eff->camera->height , eff->camera->width); eff->camera->width = 2*FIX_ONE; } else { eff->camera->width = 2 * gf_divfix(eff->camera->width, eff->camera->height); eff->camera->height = 2 * FIX_ONE; } } /*setup surface bounds*/ eff->bbox.max_edge.x = eff->camera->width / 2; eff->bbox.min_edge.x = -eff->bbox.max_edge.x; eff->bbox.max_edge.y = eff->camera->height / 2; eff->bbox.min_edge.y = -eff->bbox.max_edge.y; eff->bbox.max_edge.z = eff->bbox.min_edge.z = 0; eff->bbox.is_set = 1;}void VS_NodeRender(RenderEffect3D *eff, GF_Node *root_node){ GF_Node *fog; if (!eff->camera || !eff->surface) return; VS_InitRender(eff); /*main surface, handle collisions*/ if ((eff->surface==eff->surface->render->surface) && eff->camera->is_3D) VS_DoCollisions(eff, NULL); /*setup fog*/ fog = (GF_Node*) gf_list_get(eff->surface->fog_stack, 0); eff->traversing_mode = TRAVERSE_RENDER_BINDABLE; if (Bindable_GetIsBound(fog)) gf_node_render(fog, eff); /*turn global lights on*/ eff->traversing_mode = TRAVERSE_LIGHTING; gf_node_render(root_node, eff); /*sort graph*/ eff->traversing_mode = TRAVERSE_SORT; gf_node_render(root_node, eff); /*and draw*/ VS_FlushContexts(eff->surface, eff); /*and turn off lights*/ VS3D_ClearAllLights(eff->surface);}void VS_RootRenderChildren(RenderEffect3D *eff, GF_ChildNodeItem *children){ GF_ChildNodeItem *l; GF_Matrix mx; GF_Node *child; if (!eff->camera || !eff->surface) return; /*don't reset given matrix (used by compositeTexture2D when rescaling to POW2 sizes)*/ gf_mx_copy(mx, eff->model_matrix); VS_InitRender(eff); /**/ gf_mx_copy(eff->model_matrix, mx); VS3D_MultMatrix(eff->surface, mx.m); l = children; eff->traversing_mode = TRAVERSE_LIGHTING; while (l) { gf_node_render(l->node, eff); l = l->next; } l = children; eff->traversing_mode = TRAVERSE_SORT; while (l) { gf_node_render(l->node, eff); l = l->next; } /*setup fog*/ child = (GF_Node*) gf_list_get(eff->fogs, 0); eff->traversing_mode = TRAVERSE_RENDER_BINDABLE; if (Bindable_GetIsBound(child)) gf_node_render(child, eff); /*and draw*/ VS_FlushContexts(eff->surface, eff); /*and turn off lights*/ VS3D_ClearAllLights(eff->surface);}static GFINLINE Bool appear_has_alpha(RenderEffect3D *eff, GF_Node *node_to_draw){ u32 tag; Bool is_mat3D; DrawableStack *stack; GF_Node *mat = eff->appear ? ((M_Appearance *)eff->appear)->material : NULL; is_mat3D = 0; if (mat) { tag = gf_node_get_tag(mat); switch (tag) { /*for M2D: if filled & transparent we're transparent - otherwise we must check texture*/ case TAG_MPEG4_Material2D: if (((M_Material2D *)mat)->filled && ((M_Material2D *)mat)->transparency) return 1; break; case TAG_MPEG4_Material: case TAG_X3D_Material: is_mat3D = 1; if ( ((M_Material *)mat)->transparency) return 1; break; case TAG_MPEG4_MaterialKey: return 1; break; } } else if (eff->camera->is_3D && eff->appear) { GF_TextureHandler *txh = R3D_GetTextureHandler(((M_Appearance *)eff->appear)->texture); if (txh && txh->transparent) return 1; } /*check alpha texture in3D or with bitmap*/ if (is_mat3D || (gf_node_get_tag(((M_Shape *)node_to_draw)->geometry)==TAG_MPEG4_Bitmap)) { GF_TextureHandler *txh = R3D_GetTextureHandler(((M_Appearance *)eff->appear)->texture); if (txh && txh->transparent) return 1; } /*TODO - FIXME check alpha only...*/ if (!eff->color_mat.identity) return 1; stack = (DrawableStack*)gf_node_get_private(((M_Shape *)node_to_draw)->geometry); if (stack && (stack->mesh->flags & MESH_HAS_ALPHA)) return 1; return 0;}void VS_RegisterContext(RenderEffect3D *eff, GF_Node *node_to_draw, GF_BBox *bounds, Bool is_shape){ u32 i, count; GF_BBox b; DLightContext *nl, *ol; Draw3DContext *ctx; assert(eff->traversing_mode == TRAVERSE_SORT); /*if 2D draw in declared order. Otherwise, if no alpha or node is a layer, draw directly*/ if (!eff->camera->is_3D || !is_shape || !appear_has_alpha(eff, node_to_draw)) { eff->traversing_mode = TRAVERSE_RENDER; /*layout/form clipper, set it in world coords only*/ if (eff->has_clip) { VS3D_PushMatrix(eff->surface); VS3D_ResetMatrix(eff->surface); VS3D_SetClipper2D(eff->surface, eff->clipper); VS3D_PopMatrix(eff->surface); } gf_node_render(node_to_draw, eff); /*back to SORT*/ eff->traversing_mode = TRAVERSE_SORT; if (eff->has_clip) VS3D_ResetClipper2D(eff->surface); return; } GF_SAFEALLOC(ctx, Draw3DContext); ctx->directional_lights = gf_list_new(); ctx->node_to_draw = node_to_draw; memcpy(&ctx->model_matrix, &eff->model_matrix, sizeof(GF_Matrix)); ctx->color_mat.identity = eff->color_mat.identity; if (!eff->color_mat.identity) memcpy(&ctx->color_mat, &eff->color_mat, sizeof(GF_ColorMatrix)); ctx->is_pixel_metrics = eff->is_pixel_metrics; ctx->split_text_idx = eff->split_text_idx; i=0; while ((ol = (DLightContext*)gf_list_enum(eff->local_lights, &i))) { nl = (DLightContext*)malloc(sizeof(DLightContext)); memcpy(nl, ol, sizeof(DLightContext)); gf_list_add(ctx->directional_lights, nl); } ctx->clipper = eff->clipper; ctx->has_clipper = eff->has_clip; ctx->cull_flag = eff->cull_flag; if ((ctx->num_clip_planes = eff->num_clip_planes)) memcpy(ctx->clip_planes, eff->clip_planes, sizeof(GF_Plane)*MAX_USER_CLIP_PLANES); /*and insert from further to closest*/ b = *bounds; gf_mx_apply_bbox(&ctx->model_matrix, &b); gf_mx_apply_bbox(&eff->camera->modelview, &b); ctx->zmax = b.max_edge.z; /*we don't need an exact sorting, as long as we keep transparent nodes above -note that for speed purposes we store in reverse-z transparent nodes*/ count = gf_list_count(eff->surface->alpha_nodes_to_draw); for (i=0; i<count; i++) { Draw3DContext *next = (Draw3DContext *)gf_list_get(eff->surface->alpha_nodes_to_draw, i); if (next->zmax>ctx->zmax) { gf_list_insert(eff->surface->alpha_nodes_to_draw, ctx, i); return; } } gf_list_add(eff->surface->alpha_nodes_to_draw, ctx);}void VS_FlushContexts(VisualSurface *surf, RenderEffect3D *eff){ u32 i, idx, count; eff->traversing_mode = TRAVERSE_RENDER; count = gf_list_count(surf->alpha_nodes_to_draw); for (idx=0; idx<count; idx++) { DLightContext *dl; Draw3DContext *ctx = (Draw3DContext *)gf_list_get(surf->alpha_nodes_to_draw, idx); VS3D_PushMatrix(surf); /*apply directional lights*/ eff->local_light_on = 1; i=0; while ((dl = (DLightContext*)gf_list_enum(ctx->directional_lights, &i))) { VS3D_PushMatrix(surf); VS3D_MultMatrix(surf, dl->light_matrix.m); gf_node_render(dl->dlight, eff); VS3D_PopMatrix(surf); } /*clipper, set it in world coords only*/ if (ctx->has_clipper) { VS3D_PushMatrix(surf); VS3D_ResetMatrix(surf); VS3D_SetClipper2D(surf, ctx->clipper); VS3D_PopMatrix(surf); } /*clip planes, set it in world coords only*/ for (i=0; i<ctx->num_clip_planes; i++) VS3D_SetClipPlane(surf, ctx->clip_planes[i]); /*restore effect*/ VS3D_MultMatrix(surf, ctx->model_matrix.m); memcpy(&eff->model_matrix, &ctx->model_matrix, sizeof(GF_Matrix)); eff->color_mat.identity = ctx->color_mat.identity; if (!eff->color_mat.identity) memcpy(&eff->color_mat, &ctx->color_mat, sizeof(GF_ColorMatrix)); eff->split_text_idx = ctx->split_text_idx; eff->is_pixel_metrics = ctx->is_pixel_metrics; /*restore cull flag in case we're completely inside (avoids final frustum/AABB tree culling)*/ eff->cull_flag = ctx->cull_flag; gf_node_render(ctx->node_to_draw, eff); /*reset directional lights*/ eff->local_light_on = 0; for (i=gf_list_count(ctx->directional_lights); i>0; i--) { DLightContext *dl = (DLightContext*)gf_list_get(ctx->directional_lights, i-1); gf_node_render(dl->dlight, eff); free(dl); } if (ctx->has_clipper) VS3D_ResetClipper2D(surf); for (i=0; i<ctx->num_clip_planes; i++) VS3D_ResetClipPlane(surf); VS3D_PopMatrix(surf); /*and destroy*/ gf_list_del(ctx->directional_lights); free(ctx); } gf_list_reset(eff->surface->alpha_nodes_to_draw);}static void reset_collide_cursor(Render3D *sr){ if (sr->last_cursor == GF_CURSOR_COLLIDE) { GF_Event evt; sr->last_cursor = evt.cursor.cursor_type = GF_CURSOR_NORMAL; evt.type = GF_EVENT_SET_CURSOR; sr->compositor->video_out->ProcessEvent(sr->compositor->video_out, &evt); }}Bool VS_ExecuteEvent(VisualSurface *surf, RenderEffect3D *eff, GF_Event *ev, GF_ChildNodeItem *node_list){ Fixed x, y; SFVec3f start, end; SensorHandler *hs, *hs_grabbed; SFVec4f res; Fixed in_x, in_y; GF_List *tmp; u32 i, count, stype; Render3D *sr = surf->render; count = 0; if ((ev->type > GF_EVENT_MOUSEMOVE) || sr->nav_is_grabbed) return 0; eff->camera = &surf->camera; eff->surface = surf; eff->backgrounds = surf->back_stack; eff->viewpoints = surf->view_stack; eff->fogs = surf->fog_stack; eff->navigations = surf->navigation_stack; eff->min_hsize = INT2FIX(MIN(surf->width, surf->height)) / 2; /*setup projection*/ VS_SetupProjection(eff); eff->traversing_mode = TRAVERSE_PICK; eff->collect_layer = NULL; sr->hit_info.appear = NULL; x = INT2FIX(ev->mouse.x); y = INT2FIX(ev->mouse.y); /*main surface with AR*/ if ((sr->surface == surf) && sr->compositor->has_size_info) { Fixed scale = gf_divfix(INT2FIX(surf->width), INT2FIX(sr->out_width)); x = gf_mulfix(x, scale); scale = gf_divfix(INT2FIX(surf->height), INT2FIX(sr->out_height)); y = gf_mulfix(y, scale); } start.z = surf->camera.z_near; end.z = surf->camera.z_far; if (!eff->camera->is_3D && !eff->is_pixel_metrics) { start.x = end.x = gf_divfix(x, eff->min_hsize); start.y = end.y = gf_divfix(y, eff->min_hsize); } else { start.x = end.x = x; start.y = end.y = y; } /*unproject to world coords*/ in_x = 2*x/ (s32) surf->width; in_y = 2*y/ (s32) surf->height; res.x = in_x; res.y = in_y; res.z = -FIX_ONE; res.q = FIX_ONE; gf_mx_apply_vec_4x4(&surf->camera.unprojection, &res); if (!res.q) return 0; start.x = gf_divfix(res.x, res.q); start.y = gf_divfix(res.y, res.q); start.z = gf_divfix(res.z, res.q); res.x = in_x; res.y = in_y; res.z = FIX_ONE; res.q = FIX_ONE; gf_mx_apply_vec_4x4(&surf->camera.unprojection, &res); if (!res.q) return 0; end.x = gf_divfix(res.x, res.q); end.y = gf_divfix(res.y, res.q); end.z = gf_divfix(res.z, res.q); eff->ray = gf_ray(start, end); /*also update hit info world ray in case we have a grabbed sensor with mouse off*/ sr->hit_info.world_ray = eff->ray;#ifndef GPAC_DISABLE_LOG GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] cast ray\n\tOrigin %.4f %.4f %.4f - End %.4f %.4f %.4f\n\tDir %.4f %.4f %.4f\n", FIX2FLT(eff->ray.orig.x), FIX2FLT(eff->ray.orig.y), FIX2FLT(eff->ray.orig.z), FIX2FLT(end.x), FIX2FLT(end.y), FIX2FLT(end.z),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -