📄 geometry_stacks.c
字号:
} if (gf_node_dirty_get(node)) { mesh_new_ifs(st->mesh, node); gf_node_dirty_clear(node, 0); } if (!eff->traversing_mode) { VS_DrawMesh(eff, st->mesh); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) { eff->bbox = st->mesh->bounds; }}static void IFS_SetColorIndex(GF_Node *node){ M_IndexedFaceSet *ifs = (M_IndexedFaceSet *)node; gf_sg_vrml_field_copy(&ifs->colorIndex, &ifs->set_colorIndex, GF_SG_VRML_MFINT32); gf_sg_vrml_mf_reset(&ifs->set_colorIndex, GF_SG_VRML_MFINT32);}static void IFS_SetCoordIndex(GF_Node *node){ M_IndexedFaceSet *ifs = (M_IndexedFaceSet *)node; gf_sg_vrml_field_copy(&ifs->coordIndex, &ifs->set_coordIndex, GF_SG_VRML_MFINT32); gf_sg_vrml_mf_reset(&ifs->set_coordIndex, GF_SG_VRML_MFINT32);}static void IFS_SetNormalIndex(GF_Node *node){ M_IndexedFaceSet *ifs = (M_IndexedFaceSet *)node; gf_sg_vrml_field_copy(&ifs->normalIndex, &ifs->set_normalIndex, GF_SG_VRML_MFINT32); gf_sg_vrml_mf_reset(&ifs->set_normalIndex, GF_SG_VRML_MFINT32);}static void IFS_SetTexCoordIndex(GF_Node *node){ M_IndexedFaceSet *ifs = (M_IndexedFaceSet *)node; gf_sg_vrml_field_copy(&ifs->texCoordIndex, &ifs->set_texCoordIndex, GF_SG_VRML_MFINT32); gf_sg_vrml_mf_reset(&ifs->set_texCoordIndex, GF_SG_VRML_MFINT32);}void R3D_InitIFS(Render3D *sr, GF_Node *node){ M_IndexedFaceSet *ifs = (M_IndexedFaceSet *)node; BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderIFS); ifs->on_set_colorIndex = IFS_SetColorIndex; ifs->on_set_coordIndex = IFS_SetCoordIndex; ifs->on_set_normalIndex = IFS_SetNormalIndex; ifs->on_set_texCoordIndex = IFS_SetTexCoordIndex;}static void RenderILS(GF_Node *node, void *rs, Bool is_destroy){ M_IndexedLineSet *ils = (M_IndexedLineSet *)node; DrawableStack *st = (DrawableStack *)gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { drawable_node_destroy(node); return; } if (!ils->coord) return; if (gf_node_dirty_get(node)) { mesh_new_ils(st->mesh, ils->coord, &ils->coordIndex, ils->color, &ils->colorIndex, ils->colorPerVertex, 0); gf_node_dirty_clear(node, 0); } if (!eff->traversing_mode) { VS3D_SetAntiAlias(eff->surface, (eff->surface->render->compositor->antiAlias==GF_ANTIALIAS_FULL) ? 1 : 0); VS_DrawMesh(eff, st->mesh); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) { eff->bbox = st->mesh->bounds; }}static void ILS_SetColorIndex(GF_Node *node){ M_IndexedLineSet *ils = (M_IndexedLineSet *)node; gf_sg_vrml_field_copy(&ils->colorIndex, &ils->set_colorIndex, GF_SG_VRML_MFINT32); gf_sg_vrml_mf_reset(&ils->set_colorIndex, GF_SG_VRML_MFINT32);}static void ILS_SetCoordIndex(GF_Node *node){ M_IndexedLineSet *ils = (M_IndexedLineSet *)node; gf_sg_vrml_field_copy(&ils->coordIndex, &ils->set_coordIndex, GF_SG_VRML_MFINT32); gf_sg_vrml_mf_reset(&ils->set_coordIndex, GF_SG_VRML_MFINT32);}void R3D_InitILS(Render3D *sr, GF_Node *node){ M_IndexedLineSet *ils = (M_IndexedLineSet *)node; DrawableStack *st = BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderILS); ils->on_set_colorIndex = ILS_SetColorIndex; ils->on_set_coordIndex = ILS_SetCoordIndex; st->IntersectWithRay = R3D_NoIntersectionWithRay;}static void RenderElevationGrid(GF_Node *node, void *rs, Bool is_destroy){ DrawableStack *st = (DrawableStack *)gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { drawable_node_destroy(node); return; } if (gf_node_dirty_get(node)) { mesh_new_elevation_grid(st->mesh, node); gf_node_dirty_clear(node, 0); } if (!eff->traversing_mode) { VS_DrawMesh(eff, st->mesh); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) { eff->bbox = st->mesh->bounds; }}static void ElevationGrid_SetHeight(GF_Node *node){ M_ElevationGrid *eg = (M_ElevationGrid *)node; gf_sg_vrml_field_copy(&eg->height, &eg->set_height, GF_SG_VRML_MFFLOAT); gf_sg_vrml_mf_reset(&eg->set_height, GF_SG_VRML_MFFLOAT);}void R3D_InitElevationGrid(Render3D *sr, GF_Node *node){ M_ElevationGrid *eg = (M_ElevationGrid *)node; BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderElevationGrid); eg->on_set_height = ElevationGrid_SetHeight;}static void RenderExtrusion(GF_Node *node, void *rs, Bool is_destroy){ DrawableStack *st = (DrawableStack *)gf_node_get_private(node); RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { drawable_node_destroy(node); return; } if (gf_node_dirty_get(node)) { mesh_new_extrusion(st->mesh, node); gf_node_dirty_clear(node, 0); } if (!eff->traversing_mode) { VS_DrawMesh(eff, st->mesh); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) { eff->bbox = st->mesh->bounds; }}static void Extrusion_SetCrossSection(GF_Node *node){ M_Extrusion *eg = (M_Extrusion *)node; gf_sg_vrml_field_copy(&eg->crossSection, &eg->set_crossSection, GF_SG_VRML_MFVEC2F); gf_sg_vrml_mf_reset(&eg->set_crossSection, GF_SG_VRML_MFVEC2F);}static void Extrusion_SetOrientation(GF_Node *node){ M_Extrusion *eg = (M_Extrusion *)node; gf_sg_vrml_field_copy(&eg->orientation, &eg->set_orientation, GF_SG_VRML_MFROTATION); gf_sg_vrml_mf_reset(&eg->set_orientation, GF_SG_VRML_MFROTATION);}static void Extrusion_SetScale(GF_Node *node){ M_Extrusion *eg = (M_Extrusion *)node; gf_sg_vrml_field_copy(&eg->scale, &eg->set_scale, GF_SG_VRML_MFVEC2F); gf_sg_vrml_mf_reset(&eg->set_scale, GF_SG_VRML_MFVEC2F);}static void Extrusion_SetSpine(GF_Node *node){ M_Extrusion *eg = (M_Extrusion *)node; gf_sg_vrml_field_copy(&eg->spine, &eg->set_spine, GF_SG_VRML_MFVEC3F); gf_sg_vrml_mf_reset(&eg->set_spine, GF_SG_VRML_MFVEC3F);}void R3D_InitExtrusion(Render3D *sr, GF_Node *node){ M_Extrusion *ext = (M_Extrusion *)node; BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderExtrusion); ext->on_set_crossSection = Extrusion_SetCrossSection; ext->on_set_orientation = Extrusion_SetOrientation; ext->on_set_scale = Extrusion_SetScale; ext->on_set_spine = Extrusion_SetSpine;}/* NonLinearDeformer NOTE: AFX spec is just hmm, well, hmm. NonLinearDeformer.extend interpretation differ from type to type within the spec, and between the spec and the ref soft. This is GPAC interpretation * all params are specified with default transform axis (Z axis) * NLD.type = 0 (taper): * taping radius = NLD.param * extend = N * [diff, perc] with - diff : relative position along taper axis (for default, diff=0: z min, diff=1: z max) - perc: mult ratio for base taper radius extend works like key/keyValue for a scalar interpolator final radius: r(z) = LinearInterp(extend[min key], extend[min key + 1]) * param * NLD.type = 1 (twister): * twisting angle = NLD.param * extend = N * [diff, perc] with - diff : relative position along twister axis (for default, diff=0: z min, diff=1: z max) - perc: mult ratio for base twister angle extend works like key/keyValue for a scalar interpolator final angle: a(z) = LinearInterp(extend[min key], extend[min key + 1]) * param * NLD.type = 2 (bender): * bending curvature = NLD.param * extend = N * [diff, perc] with - diff : relative position along bender axis (for default, diff=0: z min, diff=1: z max) - perc: mult ratio for base bender curvature extend works like key/keyValue for a scalar interpolator final curvature: c(z) = LinearInterp(extend[min key], extend[min key + 1]) * param Another pb of NLD is that the spec says nothing about object/axis alignment: should we center the object at 0,0,0 (local coords) or not? the results are quite different. Here we don't recenter the object before transform*/static Bool NLD_GetMatrix(M_NonLinearDeformer *nld, GF_Matrix *mx){ SFVec3f v1, v2; SFRotation r; Fixed l1, l2, dot; /*compute rotation matrix from NLD axis to 0 0 1*/ v1 = nld->axis; gf_vec_norm(&v1); v2.x = v2.y = 0; v2.z = FIX_ONE; if (gf_vec_equal(v1, v2)) return 0; l1 = gf_vec_len(v1); l2 = gf_vec_len(v2); dot = gf_divfix(gf_vec_dot(v1, v2), gf_mulfix(l1, l2)); r.x = gf_mulfix(v1.y, v2.z) - gf_mulfix(v2.y, v1.z); r.y = gf_mulfix(v1.z, v2.x) - gf_mulfix(v2.z, v1.x); r.z = gf_mulfix(v1.x, v2.y) - gf_mulfix(v2.x, v1.y); r.q = gf_atan2(gf_sqrt(FIX_ONE - gf_mulfix(dot, dot)), dot); gf_mx_init(*mx); gf_mx_add_rotation(mx, r.q, r.x, r.y, r.z); return 1;}static GFINLINE void NLD_GetKey(M_NonLinearDeformer *nld, Fixed frac, Fixed *f_min, Fixed *min, Fixed *f_max, Fixed *max){ u32 i, count; count = nld->extend.count; if (count%2) count--; *f_min = 0; *min = 0; for (i=0; i<count; i+=2) { if (frac>=nld->extend.vals[i]) { *f_min = nld->extend.vals[i]; *min = nld->extend.vals[i+1]; } if ((i+2<count) && (frac<=nld->extend.vals[i+2])) { *f_max = nld->extend.vals[i+2]; *max = nld->extend.vals[i+3]; return; } } if (count) { *f_max = nld->extend.vals[count-2]; *max = nld->extend.vals[count-1]; } else { *f_max = FIX_ONE; *max = GF_PI; }}static void NLD_Apply(M_NonLinearDeformer *nld, GF_Mesh *mesh){ u32 i; GF_Matrix mx; Fixed param, z_min, z_max, v_min, v_max, f_min, f_max, frac, val, a_cos, a_sin; Bool needs_transform = NLD_GetMatrix(nld, &mx); param = nld->param; if (!param) param = 1; if (mesh->bounds.min_edge.z == mesh->bounds.max_edge.z) return; z_min = FIX_MAX; z_max = -FIX_MAX; if (needs_transform) { for (i=0; i<mesh->v_count; i++) { gf_mx_apply_vec(&mx, &mesh->vertices[i].pos); gf_mx_rotate_vector(&mx, &mesh->vertices[i].normal); if (mesh->vertices[i].pos.z<z_min) z_min = mesh->vertices[i].pos.z; if (mesh->vertices[i].pos.z>z_max) z_max = mesh->vertices[i].pos.z; } } else { z_min = mesh->bounds.min_edge.z; z_max = mesh->bounds.max_edge.z; } for (i=0; i<mesh->v_count; i++) { SFVec3f old = mesh->vertices[i].pos; frac = gf_divfix(old.z - z_min, z_max - z_min); NLD_GetKey(nld, frac, &f_min, &v_min, &f_max, &v_max); if (f_max == f_min) { val = v_min; } else { frac = gf_divfix(frac-f_min, f_max - f_min); val = gf_mulfix(v_max - v_min, frac) + v_min; } val = gf_mulfix(val, param); switch (nld->type) { /*taper*/ case 0: mesh->vertices[i].pos.x = gf_mulfix(mesh->vertices[i].pos.x, val); mesh->vertices[i].pos.y = gf_mulfix(mesh->vertices[i].pos.y, val); old = mesh->vertices[i].normal; mesh->vertices[i].normal.x = gf_mulfix(mesh->vertices[i].normal.x, val); mesh->vertices[i].normal.y = gf_mulfix(mesh->vertices[i].normal.y, val); gf_vec_norm(&mesh->vertices[i].normal); break; /*twist*/ case 1: a_cos = gf_cos(val); a_sin = gf_sin(val); mesh->vertices[i].pos.x = gf_mulfix(a_cos, old.x) - gf_mulfix(a_sin, old.y); mesh->vertices[i].pos.y = gf_mulfix(a_sin, old.x) + gf_mulfix(a_cos, old.y); old = mesh->vertices[i].normal; mesh->vertices[i].normal.x = gf_mulfix(a_cos, old.x) - gf_mulfix(a_sin, old.y); mesh->vertices[i].normal.y = gf_mulfix(a_sin, old.x) + gf_mulfix(a_cos, old.y); gf_vec_norm(&mesh->vertices[i].normal); break; /*bend*/ case 2: a_cos = gf_cos(val); a_sin = gf_sin(val); mesh->vertices[i].pos.x = gf_mulfix(a_sin, old.z) + gf_mulfix(a_cos, old.x); mesh->vertices[i].pos.z = gf_mulfix(a_cos, old.z) - gf_mulfix(a_sin, old.x); old = mesh->vertices[i].normal; mesh->vertices[i].normal.x = gf_mulfix(a_sin, old.z) + gf_mulfix(a_cos, old.x); mesh->vertices[i].normal.z = gf_mulfix(a_cos, old.z) - gf_mulfix(a_sin, old.x); gf_vec_norm(&mesh->vertices[i].normal); break; /*pinch, not standard (taper on X dim only)*/ case 3: mesh->vertices[i].pos.x = gf_mulfix(mesh->vertices[i].pos.x, val); old = mesh->vertices[i].normal; mesh->vertices[i].normal.x = gf_mulfix(mesh->vertices[i].normal.x, val); gf_vec_norm(&mesh->vertices[i].normal); break; } } if (needs_transform) { gf_mx_inverse(&mx); for (i=0; i<mesh->v_count; i++) { gf_mx_apply_vec(&mx, &mesh->vertices[i].pos); gf_mx_rotate_vector(&mx, &mesh->vertices[i].normal); } } mesh_update_bounds(mesh); gf_mesh_build_aabbtree(mesh);}static void RenderNonLinearDeformer(GF_Node *n, void *rs, Bool is_destroy){ DrawableStack *st = (DrawableStack *) gf_node_get_private(n); M_NonLinearDeformer *nld = (M_NonLinearDeformer*)n; RenderEffect3D *eff = (RenderEffect3D *)rs; if (is_destroy) { drawable_node_destroy(n); return; } if (!nld->geometry) return; /*call render for get_bounds to make sure geometry is up to date*/ if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) { gf_node_render(nld->geometry, eff); } /*invalidated*/ if (gf_node_dirty_get(n)) { DrawableStack *geo_st = (DrawableStack *)gf_node_get_private(nld->geometry); if (!geo_st) return; gf_node_dirty_clear(n, 0); mesh_clone(st->mesh, geo_st->mesh); /*apply deforms*/ NLD_Apply(nld, st->mesh); } if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) { eff->bbox = st->mesh->bounds; } /*in case there's a cascading of NLDs*/ else if (!eff->traversing_mode && eff->appear) { VS_DrawMesh(eff, st->mesh); }}void R3D_InitNonLinearDeformer(Render3D *sr, GF_Node *node){ BaseDrawableStack(sr->compositor, node); gf_node_set_callback_function(node, RenderNonLinearDeformer);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -