📄 mesh.c
字号:
if (faces[i]->v_count) TesselateFaceMesh(mesh, faces[i]); mesh_free(faces[i]); } free(faces); mesh_update_bounds(mesh); if (!coord2D) gf_mesh_build_aabbtree(mesh); if (colorRGBA) mesh->flags |= MESH_HAS_ALPHA; if (gen_tex_coords) mesh_generate_tex_coords(mesh, __texCoords);}void mesh_new_ifs2d(GF_Mesh *mesh, GF_Node *node){ M_IndexedFaceSet2D *ifs2D = (M_IndexedFaceSet2D *)node; mesh_new_ifs_intern(mesh, ifs2D->coord, &ifs2D->coordIndex, ifs2D->color, &ifs2D->colorIndex, ifs2D->colorPerVertex, NULL, NULL, 0, ifs2D->texCoord, &ifs2D->texCoordIndex, 0); mesh->flags |= MESH_IS_2D;}void mesh_new_ifs(GF_Mesh *mesh, GF_Node *node){ M_IndexedFaceSet *ifs = (M_IndexedFaceSet *)node; mesh_new_ifs_intern(mesh, ifs->coord, &ifs->coordIndex, ifs->color, &ifs->colorIndex, ifs->colorPerVertex, ifs->normal, &ifs->normalIndex, ifs->normalPerVertex, ifs->texCoord, &ifs->texCoordIndex, ifs->creaseAngle); if (ifs->solid) mesh->flags |= MESH_IS_SOLID; if (!ifs->ccw) mesh->flags |= MESH_IS_CW;}void mesh_new_elevation_grid(GF_Mesh *mesh, GF_Node *node){ u32 i, j, face_count, pt_count, zDimension, xDimension, cur_face, idx, pt_idx; Bool has_normal, has_txcoord, has_color, smooth_normals; GF_Mesh **faces; GF_Vertex vx; SFVec3f v1, v2, n; struct face_info *faces_info; struct pt_info *pts_info; M_ElevationGrid *eg = (M_ElevationGrid *) node; M_Normal *norm = (M_Normal *)eg->normal; M_Color *colorRGB = (M_Color *)eg->color; X_ColorRGBA *colorRGBA = (X_ColorRGBA *)eg->color; M_TextureCoordinate *txc = (M_TextureCoordinate *)eg->texCoord; mesh_reset(mesh); if (!eg->height.count || (eg->xDimension<2) || (eg->zDimension<2)) return; has_txcoord = txc ? txc->point.count : 0; has_normal = norm ? norm->vector.count : 0; has_color = 0; if (eg->color) { if (gf_node_get_tag(eg->color)==TAG_X3D_ColorRGBA) { colorRGB = NULL; has_color = colorRGBA->color.count ? 1 : 0; } else { colorRGBA = NULL; has_color = colorRGB->color.count ? 1 : 0; } } face_count = (eg->xDimension-1) * (eg->zDimension-1); pt_count = eg->xDimension * eg->zDimension; if (pt_count>eg->height.count) return; smooth_normals = (!has_normal && (eg->creaseAngle > FIX_EPSILON)) ? 1 : 0; faces = NULL; faces_info = NULL; pts_info = NULL; /*alloc face & normals tables*/ if (smooth_normals) { faces = (GF_Mesh **)malloc(sizeof(GF_Mesh *)*face_count); faces_info = (struct face_info*)malloc(sizeof(struct face_info)*face_count); memset(faces_info, 0, sizeof(struct face_info)*face_count); pts_info = (struct pt_info*)malloc(sizeof(struct pt_info)*pt_count); memset(pts_info, 0, sizeof(struct pt_info)*pt_count); } zDimension = (u32) eg->zDimension; xDimension = (u32) eg->xDimension; cur_face = 0; pt_idx = 0; if (smooth_normals) faces[cur_face] = new_mesh(); for (j=0; j<zDimension-1; j++) { for (i = 0; i < xDimension-1; i++) { u32 k, l; /*get face color*/ if (has_color && !eg->colorPerVertex) { idx = i + j * (xDimension-1); MESH_GET_COL(vx.color, idx); } /*get face normal*/ if (has_normal && !eg->normalPerVertex) { idx = i + j * (xDimension-1); if (idx<norm->vector.count) { vx.normal = norm->vector.vals[idx]; gf_vec_norm(&vx.normal); } } for (k=0; k<2; k++) { vx.pos.z = eg->zSpacing * (j+k); for (l=0; l<2; l++) { vx.pos.y = eg->height.vals[(i+l) +(j+k)*xDimension]; vx.pos.x = eg->xSpacing * (i+l); /*get color per vertex*/ if (has_color && eg->colorPerVertex) { idx = i+l + (j+k) * xDimension; MESH_GET_COL(vx.color, idx); } /*get tex coord*/ if (!has_txcoord) { vx.texcoords.x = INT2FIX(i+l) / (xDimension - 1); vx.texcoords.y = INT2FIX(j+k) / (zDimension - 1); } else { idx = (i+l) +(j+k)*xDimension; if (idx<txc->point.count) vx.texcoords = txc->point.vals[idx]; } /*get normal per vertex*/ if (has_normal && eg->normalPerVertex) { idx = (i+l) + (j+k) * xDimension; if (idx<norm->vector.count) { vx.normal = norm->vector.vals[idx]; gf_vec_norm(&vx.normal); } } /*update face to point and point to face structures*/ if (smooth_normals) { mesh_set_vertex_vx(faces[cur_face], &vx); register_point_in_face(&faces_info[cur_face], (i+l) + (j+k)*xDimension); register_face_in_point(&pts_info[(i+l) + (j+k)*xDimension], cur_face); } else { mesh_set_vertex_vx(mesh, &vx); } } } /*compute face normal*/ if (smooth_normals) { mesh_set_triangle(faces[cur_face], 0, 2, 3); mesh_set_triangle(faces[cur_face], 0, 3, 1); gf_vec_diff(v1, faces[cur_face]->vertices[0].pos, faces[cur_face]->vertices[1].pos); gf_vec_diff(v2, faces[cur_face]->vertices[3].pos, faces[cur_face]->vertices[1].pos); faces_info[cur_face].nor = gf_vec_cross(v1, v2); gf_vec_norm(&faces_info[cur_face].nor); /*done with face*/ cur_face++; if (cur_face<face_count) faces[cur_face] = new_mesh(); } else { mesh_set_triangle(mesh, pt_idx+0, pt_idx+2, pt_idx+3); mesh_set_triangle(mesh, pt_idx+0, pt_idx+3, pt_idx+1); if (!has_normal) { gf_vec_diff(v1, mesh->vertices[pt_idx+0].pos, mesh->vertices[pt_idx+1].pos); gf_vec_diff(v2, mesh->vertices[pt_idx+3].pos, mesh->vertices[pt_idx+1].pos); n = gf_vec_cross(v1, v2); gf_vec_norm(&n); mesh->vertices[pt_idx+0].normal = n; mesh->vertices[pt_idx+1].normal = n; mesh->vertices[pt_idx+2].normal = n; mesh->vertices[pt_idx+3].normal = n; } pt_idx+=4; } } } /*generate normals*/ if (smooth_normals) { Fixed cosCrease; /*we only support 0->PI, whatever exceeds is smoothest*/ if (eg->creaseAngle>GF_PI) cosCrease = -FIX_ONE; else cosCrease = gf_cos(eg->creaseAngle); for (i=0; i<face_count; i++) { for (j=0; j<faces[i]->v_count; j++) { faces[i]->vertices[j].normal = smooth_face_normals(pts_info, pt_count, faces_info, face_count, j, i, cosCrease); } } if (faces_info) { for (i=0; i<face_count; i++) if (faces_info[i].idx) free(faces_info[i].idx); free(faces_info); } if (pts_info) { for (i=0; i<pt_count; i++) if (pts_info[i].faces) free(pts_info[i].faces); free(pts_info); } mesh->flags |= MESH_IS_SMOOTHED; for (i=0; i<face_count; i++) { if (faces[i]->v_count) { u32 init_idx; GF_Mesh *face = faces[i]; init_idx = mesh->v_count; /*quads only*/ mesh_set_vertex_vx(mesh, &face->vertices[0]); mesh_set_vertex_vx(mesh, &face->vertices[1]); mesh_set_vertex_vx(mesh, &face->vertices[2]); mesh_set_vertex_vx(mesh, &face->vertices[3]); mesh_set_triangle(mesh, init_idx, init_idx + 2, init_idx + 3); mesh_set_triangle(mesh, init_idx, init_idx + 3, init_idx + 1); } mesh_free(faces[i]); } /*destroy faces*/ free(faces); } mesh->mesh_type = MESH_TRIANGLES; if (has_color) mesh->flags |= MESH_HAS_COLOR; mesh_update_bounds(mesh); if (!eg->ccw) mesh->flags |= MESH_IS_CW; if (eg->solid) mesh->flags |= MESH_IS_SOLID; if (colorRGBA) mesh->flags |= MESH_HAS_ALPHA; gf_mesh_build_aabbtree(mesh);}typedef struct{ SFVec3f yaxis, zaxis, xaxis;} SCP;typedef struct{ SFVec3f pt, yaxis, zaxis, xaxis; u32 max_idx;} SCPInfo;#define REGISTER_POINT_FACE(FACE_IDX) \ { u32 fidx; \ fidx = FACE_IDX; \ mesh_set_vertex_vx(faces[fidx], &vx); \ if (smooth_normals) { \ register_point_in_face(&faces_info[fidx], pidx); \ register_face_in_point(&pts_info[pidx], fidx); \ } \ } \#define NEAR_ZERO(__x) (ABS(__x)<=FIX_EPSILON) static void mesh_extrude_path_intern(GF_Mesh *mesh, GF_Path *path, MFVec3f *thespine, Fixed creaseAngle, Fixed min_cx, Fixed min_cy, Fixed width_cx, Fixed width_cy, Bool begin_cap, Bool end_cap, MFRotation *spine_ori, MFVec2f *spine_scale, Bool tx_along_spine){ GF_Mesh **faces; GF_Vertex vx; struct face_info *faces_info; struct pt_info *pts_info; GF_Matrix mx; SCP *SCPs, SCPbegin, SCPend; SCPInfo *SCPi; Bool smooth_normals, spine_closed, check_first_spine_vec, do_close; u32 i, j, k, nb_scp, nb_spine, face_count, pt_count, faces_per_cross, begin_face, end_face, face_spines, pts_per_cross, cur_pts_in_cross,cur, nb_pts, convexity; SFVec3f *spine, v1, v2, n, spine_vec; Fixed cross_len, spine_len, cur_cross, cur_spine; SFRotation r; SFVec2f scale; if (!path->n_contours) return; if (path->n_points<2) return; if (thespine->count<2) return; spine_closed = 0; if (gf_vec_equal(thespine->vals[0], thespine->vals[thespine->count-1])) spine_closed = 1; if (spine_closed && (thespine->count==2)) return; gf_path_flatten(path); pts_per_cross = 0; cross_len = 0; cur = 0; for (i=0; i<path->n_contours; i++) { nb_pts = 1 + path->contours[i] - cur; pts_per_cross += nb_pts; for (j=0; j<nb_pts; j++) { if (j) { v1.z = 0; v1.x = path->points[j+cur].x - path->points[j-1+cur].x; v1.y = path->points[j+cur].y - path->points[j-1+cur].y; cross_len += gf_vec_len(v1); } } } faces_per_cross = pts_per_cross - path->n_contours; begin_face = end_face = 0; face_spines = face_count = (thespine->count-1)*faces_per_cross; if (begin_cap) { begin_face = face_count; face_count ++; } if (end_cap) { end_face = face_count; face_count ++; } pt_count = pts_per_cross * thespine->count; smooth_normals = NEAR_ZERO(creaseAngle) ? 0 : 1; faces = (GF_Mesh**)malloc(sizeof(GF_Mesh *)*face_count); for (i=0; i<face_count; i++) faces[i] = new_mesh(); faces_info = NULL; pts_info = NULL; /*alloc face & normals tables*/ if (smooth_normals) { faces_info = (struct face_info*)malloc(sizeof(struct face_info)*face_count); memset(faces_info, 0, sizeof(struct face_info)*face_count); pts_info = (struct pt_info*)malloc(sizeof(struct pt_info)*pt_count); memset(pts_info, 0, sizeof(struct pt_info)*pt_count); } spine = thespine->vals; nb_spine = thespine->count; SCPs = (SCP *)malloc(sizeof(SCP) * nb_spine); memset(SCPs, 0, sizeof(SCP) * nb_spine); SCPi = (SCPInfo *) malloc(sizeof(SCPInfo) * nb_spine); memset(SCPi, 0, sizeof(SCPInfo) * nb_spine); /*collect all # SCPs: 1- if a spine has identical consecutive points with # orientation, these points use the same SCPs 2- if 2 segs of the spine are colinear, they also use the same SCP */ SCPi[0].pt = spine[0]; SCPi[0].max_idx = 0; nb_scp=1; spine_len = 0; check_first_spine_vec = 1; for (i=1; i<nb_spine; i++) { Fixed len; /*also get spine length for txcoord*/ gf_vec_diff(v2, spine[i], spine[i-1]); len = gf_vec_len(v2); spine_len += len; if (check_first_spine_vec && len) { check_first_spine_vec = 0; spine_vec = v2; } /*case 1: same point, same SCP*/ if (gf_vec_equal(SCPi[nb_scp-1].pt, spine[i])) { SCPi[nb_scp-1].max_idx = i; continue; } /*last point in spine*/ if (i+1 == nb_spine) { nb_scp++; SCPi[nb_scp-1].pt = spine[i]; SCPi[nb_scp-1].max_idx = i; break; } gf_vec_diff(v1, spine[i+1], spine[i]); gf_vec_diff(v2, SCPi[nb_scp-1].pt, spine[i]); n = gf_vec_cross(v1, v2); /*case 2: spine segs are colinear*/ if (!n.x && !n.y && !n.z) { SCPi[nb_scp-1].max_idx = i; } /*OK new SCP*/ else { nb_scp++; SCPi[nb_scp-1].pt = spine[i]; SCPi[nb_scp-1].max_idx = i; } } /*all colinear!!*/ if (nb_scp<=2) { SCPi[0].xaxis.x = FIX_ONE; SCPi[0].xaxis.y = 0; SCPi[0].xaxis.z = 0; SCPi[0].yaxis.x = 0; SCPi[0].yaxis.y = FIX_ONE; SCPi[0].yaxis.z = 0; SCPi[0].zaxis.x = 0; SCPi[0].zaxis.y = 0; SCPi[0].zaxis.z = FIX_ONE; /*compute rotation from (0, 1, 0) to spine_vec*/ if (!check_first_spine_vec) { Fixed alpha, gamma; Fixed cos_a, sin_a, sin_g, cos_g; gf_vec_norm(&spine_vec); if (! NEAR_ZERO(spine_vec.x) ) { if (spine_vec.x >= FIX_ONE-FIX_EPSILON) alpha = GF_PI2; else if (spine_vec.x <= -FIX_ONE+FIX_EPSILON) alpha = -GF_PI2; else alpha = gf_asin(spine_vec.x); cos_a = gf_cos(alpha); sin_a = spine_vec.x; sin_g = 0; if (NEAR_ZERO(cos_a)) gamma = 0; else { Fixed __abs; gamma = gf_acos(gf_divfix(spine_vec.y, cos_a)); sin_g = gf_sin(gamma); __abs = gf_divfix(spine_vec.z, cos_a) + sin_g; if (ABS(__abs) > ABS(sin_g) ) gamma *= -1; } cos_g = gf_cos(gamma); if (NEAR_ZERO(cos_g)) { cos_g = 0; sin_g = 1; } else { sin_g = gf_sin(gamma); } SCPi[0].yaxis.y = gf_mulfix(cos_a, sin_g); SCPi[0].yaxis.z = gf_mulfix(cos_a, cos_g); SCPi[0].yaxis.x = sin_a; SCPi[0].zaxis.y = -gf_mulfix(sin_a, sin_g); SCPi[0].zaxis.z = -gf_mulfix(sin_a, cos_g); SCPi[0].zaxis.x = cos_a; } if (! NEAR_ZERO(spine_vec.z) ) { if (spine_vec.z >= FIX_ONE-FIX_EPSILON) alpha = GF_PI2; else if (spine_vec.z <= -FIX_ONE+FIX_EPSILON) alpha = -GF_PI2; else alpha = gf_asin(spine_vec.z);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -