📄 visual_surface.c
字号:
if (asp.filled) VS3D_SetMaterial2D(eff->surface, asp.fill_color, asp.alpha); VS3D_DrawMesh(eff, st->mesh); /*reset texturing in case of line texture*/ if (eff->mesh_has_texture) { tx_disable(fill_txh); eff->mesh_has_texture = 0; } } /*strike path*/ if (!asp.line_alpha) return; si = VS_GetStrikeInfo(st, &asp, eff); if (si) { VS_Set2DStrikeAspect(eff, &asp);// if (asp.txh) eff->mesh_has_texture = 1; if (!si->is_vectorial) { VS3D_StrikeMesh(eff, si->outline, Aspect_GetLineWidth(&asp), asp.pen_props.dash); } else { VS3D_DrawMesh(eff, si->outline); } if (asp.txh) { tx_disable(asp.txh); eff->mesh_has_texture = 0; } }}static GFINLINE Bool VS_setup_material(RenderEffect3D *eff, u32 mesh_type){ SFColor def; GF_Node *__mat; def.red = def.green = def.blue = FIX_ONE; /*temp storage of diffuse alpha*/ eff->ray.orig.x = FIX_ONE; if (!eff->appear) { /*use material2D to disable lighting*/ VS3D_SetMaterial2D(eff->surface, def, FIX_ONE); return 1; } if (gf_node_get_tag(eff->appear)==TAG_X3D_Appearance) { X_FillProperties *fp = (X_FillProperties *) ((X_Appearance*)eff->appear)->fillProperties; if (fp && !fp->filled) return 0; } __mat = ((M_Appearance *)eff->appear)->material; if (!__mat) { /*use material2D to disable lighting (cf VRML specs)*/ VS3D_SetMaterial2D(eff->surface, def, FIX_ONE); return 1; } switch (gf_node_get_tag((GF_Node *)__mat)) { case TAG_MPEG4_Material: case TAG_X3D_Material: { SFColor diff, spec, emi; Fixed diff_a, spec_a, emi_a; Fixed vec[4]; Bool has_alpha; u32 flag = F3D_LIGHT /*| F3D_COLOR*/; M_Material *mat = (M_Material *)__mat; diff = mat->diffuseColor; diff_a = FIX_ONE - mat->transparency; /*if drawing in 2D context or special meshes (lines, points) disable lighting*/ if (mesh_type || !eff->camera->is_3D) { if (eff->camera->is_3D) diff = mat->emissiveColor; if (!eff->color_mat.identity) gf_cmx_apply_fixed(&eff->color_mat, &diff_a, &diff.red, &diff.green, &diff.blue); VS3D_SetMaterial2D(eff->surface, diff, diff_a); return 1; } spec = mat->specularColor; emi = mat->emissiveColor; spec_a = emi_a = FIX_ONE - mat->transparency; if (!eff->color_mat.identity) { gf_cmx_apply_fixed(&eff->color_mat, &diff_a, &diff.red, &diff.green, &diff.blue); gf_cmx_apply_fixed(&eff->color_mat, &spec_a, &spec.red, &spec.green, &spec.blue); gf_cmx_apply_fixed(&eff->color_mat, &emi_a, &emi.red, &emi.green, &emi.blue); if ((diff_a+FIX_EPSILON<FIX_ONE) || (spec_a+FIX_EPSILON<FIX_ONE) || (emi_a+FIX_EPSILON<FIX_ONE )) { has_alpha = 1; } else { has_alpha = 0; } } else { has_alpha = (mat->transparency>FIX_EPSILON) ? 1 : 0; /*100% transparent DON'T DRAW*/ if (mat->transparency+FIX_EPSILON>=FIX_ONE) return 0; } /*using antialiasing with alpha usually gives bad results (non-edge face segments are visible)*/ VS3D_SetAntiAlias(eff->surface, !has_alpha); if (has_alpha) { flag |= F3D_BLEND; eff->mesh_is_transparent = 1; } VS3D_SetState(eff->surface, flag, 1); vec[0] = gf_mulfix(diff.red, mat->ambientIntensity); vec[1] = gf_mulfix(diff.green, mat->ambientIntensity); vec[2] = gf_mulfix(diff.blue, mat->ambientIntensity); vec[3] = diff_a; VS3D_SetMaterial(eff->surface, MATERIAL_AMBIENT, vec); vec[0] = diff.red; vec[1] = diff.green; vec[2] = diff.blue; vec[3] = diff_a; VS3D_SetMaterial(eff->surface, MATERIAL_DIFFUSE, vec); vec[0] = spec.red; vec[1] = spec.green; vec[2] = spec.blue; vec[3] = spec_a; VS3D_SetMaterial(eff->surface, MATERIAL_SPECULAR, vec); vec[0] = emi.red; vec[1] = emi.green; vec[2] = emi.blue; vec[3] = emi_a; VS3D_SetMaterial(eff->surface, MATERIAL_EMISSIVE, vec); VS3D_SetShininess(eff->surface, mat->shininess); eff->ray.orig.x = diff_a; } break; case TAG_MPEG4_Material2D: { SFColor emi; Fixed emi_a; M_Material2D *mat = (M_Material2D *)__mat; emi = mat->emissiveColor; emi_a = FIX_ONE - mat->transparency; if (!eff->color_mat.identity) gf_cmx_apply_fixed(&eff->color_mat, &emi_a, &emi.red, &emi.green, &emi.blue); /*100% transparent DON'T DRAW*/ if (emi_a<FIX_EPSILON) return 0; else if (emi_a+FIX_EPSILON<FIX_ONE) VS3D_SetState(eff->surface, F3D_BLEND, 1); /*this is an extra feature: if material2D.filled is FALSE on 3D objects, switch to TX_REPLACE mode and enable lighting*/ if (!mat->filled) { GF_TextureHandler *txh = R3D_GetTextureHandler(((M_Appearance *)eff->appear)->texture); if (txh) { tx_set_blend_mode(txh, TX_REPLACE); VS3D_SetState(eff->surface, F3D_COLOR, 0); VS3D_SetState(eff->surface, F3D_LIGHT, 1); return 1; } } /*regular mat 2D*/ VS3D_SetState(eff->surface, F3D_LIGHT | F3D_COLOR, 0); VS3D_SetMaterial2D(eff->surface, emi, emi_a); } break; default: break; } return 1;}Bool VS_setup_texture(RenderEffect3D *eff){ GF_TextureHandler *txh; eff->mesh_has_texture = 0; if (!eff->appear) return 0; txh = R3D_GetTextureHandler(((M_Appearance *)eff->appear)->texture); if (txh) { tx_set_blend_mode(txh, tx_is_transparent(txh) ? TX_MODULATE : TX_REPLACE); eff->mesh_has_texture = tx_enable(txh, ((M_Appearance *)eff->appear)->textureTransform); if (eff->mesh_has_texture) { Fixed v[4]; switch (txh->pixelformat) { /*override diffuse color with full intensity, but keep material alpha (cf VRML lighting)*/ case GF_PIXEL_RGB_24: v[0] = v[1] = v[2] = 1; v[3] = eff->ray.orig.x; VS3D_SetMaterial(eff->surface, MATERIAL_DIFFUSE, v); break; /*override diffuse color AND material alpha (cf VRML lighting)*/ case GF_PIXEL_RGBA: v[0] = v[1] = v[2] = v[3] = 1; VS3D_SetMaterial(eff->surface, MATERIAL_DIFFUSE, v); break; case GF_PIXEL_GREYSCALE: eff->mesh_has_texture = 2; break; } } return eff->mesh_has_texture; } return 0;}void VS_disable_texture(RenderEffect3D *eff){ if (eff->mesh_has_texture) { tx_disable(R3D_GetTextureHandler(((M_Appearance *)eff->appear)->texture) ); eff->mesh_has_texture = 0; }}Bool VS_SetupAppearance(RenderEffect3D *eff){ /*setup material and check if 100% transparent - in which case don't draw*/ if (!VS_setup_material(eff, 0)) return 0; /*setup texture*/ VS_setup_texture(eff); return 1;}void VS_DrawMesh(RenderEffect3D *eff, GF_Mesh *mesh){ if (mesh->mesh_type) { if (VS_setup_material(eff, mesh->mesh_type)) { VS3D_DrawMesh(eff, mesh); } } else if (VS_SetupAppearance(eff)) { VS3D_DrawMesh(eff, mesh); VS_disable_texture(eff); #ifndef GPAC_USE_OGL_ES if (eff->appear && gf_node_get_tag(eff->appear)==TAG_X3D_Appearance) { X_Appearance *ap = (X_Appearance *)eff->appear; X_FillProperties *fp = ap->fillProperties ? (X_FillProperties *) ap->fillProperties : NULL; if (fp && fp->hatched) VS3D_HatchMesh(eff, mesh, fp->hatchStyle, fp->hatchColor); }#endif }}/*uncomment to disable frustum cull*///#define DISABLE_VIEW_CULL#ifndef GPAC_DISABLE_LOGstatic const char *szPlaneNames [] = { "Near", "Far", "Left", "Right", "Bottom", "Top"};#endifBool node_cull(RenderEffect3D *eff, GF_BBox *bbox, Bool skip_near) { GF_BBox b; Fixed irad, rad; GF_Camera *cam; Bool do_sphere; u32 i, p_idx; SFVec3f cdiff, vertices[8]; if (eff->cull_flag == CULL_INSIDE) return 1; assert(eff->cull_flag != CULL_OUTSIDE);#ifdef DISABLE_VIEW_CULL eff->cull_flag = CULL_INSIDE; return 1;#endif /*empty bounds*/ if (!bbox->is_set) { eff->cull_flag = CULL_OUTSIDE; GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Culling: Node out (bbox not set)\n")); return 0; } /*get bbox in world space*/ b = *bbox; gf_mx_apply_bbox(&eff->model_matrix, &b); cam = eff->camera; /*if camera is inside bbox consider we intersect*/ if (gf_bbox_point_inside(&b, &cam->position)) { eff->cull_flag = CULL_INTERSECTS; GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Culling: Node intersect (camera in box test)\n")); return 1; } /*first check: sphere vs frustum sphere intersection, this will discard far objects quite fast*/ gf_vec_diff(cdiff, cam->center, b.center); rad = b.radius + cam->radius; if (gf_vec_len(cdiff) > rad) { eff->cull_flag = CULL_OUTSIDE; GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Culling: Node out (sphere-sphere test)\n")); return 0; } /*second check: sphere vs frustum planes intersection, if any intersection is detected switch to n/p vertex check.*/ rad = b.radius; irad = -b.radius; do_sphere = 1; /*skip near/far tests in ortho mode, and near in 3D*/ i = (eff->camera->is_3D) ? (skip_near ? 1 : 0) : 2; for (; i<6; i++) { if (do_sphere) { Fixed d = gf_plane_get_distance(&cam->planes[i], &b.center); if (d<irad) { eff->cull_flag = CULL_OUTSIDE; GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Culling: Node out (sphere-planes test) plane %s\n", szPlaneNames[i])); return 0; } /*intersect, move to n-p vertex test*/ if (d<rad) { /*get box vertices*/ gf_bbox_get_vertices(b.min_edge, b.max_edge, vertices); do_sphere = 0; } else { continue; } } p_idx = cam->p_idx[i]; /*check p-vertex: if not in plane, we're out (since p-vertex is the closest point to the plane)*/ if (gf_plane_get_distance(&cam->planes[i], &vertices[p_idx])<0) { eff->cull_flag = CULL_OUTSIDE; GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Culling: Node out (p-vertex test) plane %s\n", szPlaneNames[i])); return 0; } /*check n-vertex: if not in plane, we're intersecting*/ if (gf_plane_get_distance(&cam->planes[i], &vertices[7-p_idx])<0) { eff->cull_flag = CULL_INTERSECTS; GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Culling: Node intersect (n-vertex test) plane %s\n", szPlaneNames[i])); return 1; } } eff->cull_flag = CULL_INSIDE; GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 3D] Culling: Node inside (%s test)\n", do_sphere ? "sphere-planes" : "n-p vertex")); return 1;}void VS_SetupProjection(RenderEffect3D *eff){ GF_Node *bindable; u32 mode = eff->traversing_mode; eff->traversing_mode = TRAVERSE_RENDER_BINDABLE; /*setup viewpoint (this directly modifies the frustum)*/ bindable = (GF_Node*)gf_list_get(eff->viewpoints, 0); if (Bindable_GetIsBound(bindable)) { gf_node_render(bindable, eff); eff->camera->had_viewpoint = 1; } else if (eff->camera->had_viewpoint) { if (eff->camera->is_3D) { SFVec3f pos, center; SFRotation r; Fixed fov = GF_PI/4; /*default viewpoint*/ pos.x = pos.y = 0; pos.z = 10 * FIX_ONE; center.x = center.y = center.z = 0; r.q = r.x = r.z = 0; r.y = FIX_ONE; /*this takes care of pixelMetrics*/ VS_ViewpointChange(eff, NULL, 0, fov, pos, r, center); /*initial vp compute, don't animate*/ if (eff->camera->had_viewpoint == 2) { camera_stop_anim(eff->camera); camera_reset_viewpoint(eff->camera, 0); } } else { eff->camera->zoom = FIX_ONE; eff->camera->trans.x = eff->camera->trans.y = eff->camera->rot.x = eff->camera->rot.y = 0; eff->camera->flags &= ~CAM_HAS_VIEWPORT; eff->camera->flags |= CAM_IS_DIRTY; } eff->camera->had_viewpoint = 0; } camera_update(eff->camera); /*setup projection/modelview*/ VS3D_SetMatrixMode(eff->surface, MAT_PROJECTION); VS3D_LoadMatrix(eff->surface, eff->camera->projection.m); VS3D_SetMatrixMode(eff->surface, MAT_MODELVIEW); VS3D_LoadMatrix(eff->surface, eff->camera->modelview.m); gf_mx_init(eff->model_matrix); eff->traversing_mode = mode;}void VS_InitRender(RenderEffect3D *eff){ Bool in_layer; u32 mode; GF_Node *bindable; in_layer = (eff->backgrounds != eff->surface->back_stack) ? 1 : 0; /*if not in layer, render navigation FIXME: we should update the nav info according to the world transform at the current viewpoint (vrml)*/ eff->traversing_mode = TRAVERSE_RENDER_BINDABLE; bindable = eff->navigations ? (GF_Node*) gf_list_get(eff->navigations, 0) : NULL; if (Bindable_GetIsBound(bindable)) { gf_node_render(bindable, eff); eff->camera->had_nav_info = 1; } else if (eff->camera->had_nav_info) { /*if no navigation specified, use default VRML one*/ eff->camera->avatar_size.x = FLT2FIX(0.25f); eff->camera->avatar_size.y = FLT2FIX(1.6f); eff->camera->avatar_size.z = FLT2FIX(0.75f); eff->camera->visibility = 0; eff->camera->speed = FIX_ONE; /*not specified in the spec, but by default we forbid navigation in layer*/ if (in_layer) { eff->camera->navigation_flags = NAV_HEADLIGHT; eff->camera->navigate_mode = GF_NAVIGATE_NONE; } else { eff->camera->navigation_flags = NAV_ANY | NAV_HEADLIGHT; if (eff->camera->is_3D) { /*X3D is by default examine, VRML/MPEG4 is WALK*/ eff->camera->navigate_mode = (eff->surface->render->root_is_3D==2) ? GF_NAVIGATE_EXAMINE : GF_NAVIGATE_WALK; } else { eff->camera->navigate_mode = GF_NAVIGATE_NONE; } } eff->camera->had_nav_info = 0; if (eff->is_pixel_metrics) { eff->camera->visibility = gf_mulfix(eff->camera->visibility, eff->min_hsize); eff->camera->avatar_size.x = gf_mulfix(eff->camera->avatar_size.x, eff->min_hsize); eff->camera->avatar_size.y = gf_mulfix(eff->camera->avatar_size.y, eff->min_hsize); eff->camera->avatar_size.z = gf_mulfix(eff->camera->avatar_size.z, eff->min_hsize); } } /*animate current camera - if returns TRUE draw next frame*/ if (camera_animate(eff->camera)) gf_sr_invalidate(eff->surface->render->compositor, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -