//returns -1 on fail, number of vertices on success int load_off_mesh(FILE* fp, jmesh *jm){ fseek(fp, 0, SEEK_SET); //ensure we are at the start of the file if(is_off_file(fp) != 0){ fprintf(stderr, "not an off file\n"); return -1; } int i; i=get_verts_faces(fp, jm); if(i != 3){ fprintf(stderr,"off file corrupt on line 2\n"); return -1; } i=get_tuples(fp, jm); if(i != jm->nvert){ fprintf(stderr,"off file corrupt on tuple line %d\n", i); return -1; } i=get_faces(fp, jm); if(i != jm->ntri){ fprintf(stderr,"off file corrupt on polygon line %d\n", i); return -1; } get_normals(jm); get_centroid(jm, jm->center); return i; }
void in_sphere(float xyz[4][3], float xyz_in[3], float &radius_in) { float matrix_1[4][4], matrix_2[4][4], rhs[4], det_matrix_1, sub_det[4]; float norm[4][3]; int i, j, l; // get outward facing normals for each face of this tet get_normals(xyz,norm); // pack the matrix equations for ( j = 0 ; j <= 2 ; j++ ) { matrix_1[0][j] = norm[0][j]; matrix_1[1][j] = norm[1][j]; matrix_1[2][j] = norm[2][j]; matrix_1[3][j] = norm[3][j]; } for ( i = 0 ; i <= 3 ; i++ ) { matrix_1[i][3] = 1.; } // pack the right-handside rhs[0] = norm[0][0]*xyz[0][0] + norm[0][1]*xyz[0][1] + norm[0][2]*xyz[0][2]; rhs[1] = norm[1][0]*xyz[3][0] + norm[1][1]*xyz[3][1] + norm[1][2]*xyz[3][2]; rhs[2] = norm[2][0]*xyz[3][0] + norm[2][1]*xyz[3][1] + norm[2][2]*xyz[3][2]; rhs[3] = norm[3][0]*xyz[3][0] + norm[3][1]*xyz[3][1] + norm[3][2]*xyz[3][2]; // get determinant of original 4x4 matrix determinant(matrix_1,&det_matrix_1); // solve system of equations using Kramer's rule if ( det_matrix_1 != 0. ) { for ( l = 0 ; l <= 3 ; l++ ) { // grab a copy of the original matrix for ( i = 0 ; i <= 3 ; i++ ) { for ( j = 0 ; j <= 3 ; j++ ) { matrix_2[i][j] = matrix_1[i][j]; } } // fill the l'th column with right-hand-side vector for ( i = 0 ; i <= 3 ; i++ ) { matrix_2[i][l] = rhs[i]; } // solve for determinant of this system determinant(matrix_2,&sub_det[l]); } // solve for the unknowns xyz_in and radius_in for ( j = 0 ; j <= 2 ; j++ ) { xyz_in[j] = sub_det[j]/det_matrix_1; } // solve for radius radius_in = sub_det[3]/det_matrix_1; } else { radius_in = -1.; } }
void Mesher::check_feature() { auto contour = get_contour(); const auto normals = get_normals(contour); // Find the largest cone and the normals that enclose // the largest angle as n0, n1. float theta = 1; Vec3f n0, n1; for (auto ni : normals) { for (auto nj : normals) { float dot = ni.dot(nj); if (dot < theta) { theta = dot; n0 = ni; n1 = nj; } } } // If there isn't a feature in this fan, then return immediately. if (theta > 0.9) return; // Decide whether this is a corner or edge feature. const Vec3f nstar = n0.cross(n1); float phi = 0; for (auto n : normals) phi = fmax(phi, fabs(nstar.dot(n))); bool edge = phi < 0.7; // Find the center of the contour. Vec3f center(0, 0, 0); for (auto c : contour) center += c; center /= contour.size(); // Construct the matrices for use in our least-square fit. Eigen::MatrixX3d A(normals.size(), 3); { int i=0; for (auto n : normals) A.row(i++) << n.transpose(); } // When building the second matrix, shift position values to be centered // about the origin (because that's what the least-squares fit will // minimize). Eigen::VectorXd B(normals.size(), 1); { auto n = normals.begin(); auto c = contour.begin(); int i=0; while (n != normals.end()) B.row(i++) << (n++)->dot(*(c++) - center); } // Use singular value decomposition to solve the least-squares fit. Eigen::JacobiSVD<Eigen::MatrixX3d> svd(A, Eigen::ComputeFullU | Eigen::ComputeFullV); // Set the smallest singular value to zero to make fitting happier. if (edge) { auto singular = svd.singularValues(); svd.setThreshold(singular.minCoeff() / singular.maxCoeff() * 1.01); } // Solve for the new point's position. const Vec3f new_pt = svd.solve(B) + center; // Erase this triangle fan, as we'll be inserting a vertex in the center. triangles.erase(fan_start, voxel_start); // Construct a new triangle fan. contour.push_back(contour.front()); { auto p0 = contour.begin(); auto p1 = contour.begin(); p1++; while (p1 != contour.end()) push_swappable_triangle(Triangle(*(p0++), *(p1++), new_pt)); } }
void write_mesh_data() { size_t ret; /* Data format: Size of Mesh Name String (2 bytes - short) Mesh Name String (n chars) Number of vertices (4 bytes - int) Number of faces (4 bytes - int) Vertex triples (m*3*4 bytes - float[]) Normal triples (m*3*4 bytes - float[]) Face index format (1 byte) {0=1 byte; 1=2 bytes - short; 2=4 bytes - int} Face triples (m*3*4 bytes - int[]) */ curr = head; while (NULL != curr) { size_t len; uint32_t nvert, nface; size_t i; float vec[3]; char format; /* face triples */ unsigned char ind8[3] = {0, 0, 0}; uint16_t ind16[3] = {0, 0, 0}; uint32_t ind32[3] = {0, 0, 0}; if (verbose) { fprintf(stderr, ">> writing out mesh '%s' (%lu, %lu)\n", curr->name, (long unsigned int)curr->bot->num_vertices, (long unsigned int)curr->bot->num_faces); } len = strlen(curr->name); /* mesh name string length */ ret = fwrite(&len, sizeof(uint16_t), 1, fp_out); if (ret != 1) perror("fwrite"); /* mesh name string */ ret = fwrite(curr->name, 1, len, fp_out); if (ret != len) perror("fwrite"); nvert = (uint32_t)curr->bot->num_vertices; nface = (uint32_t)curr->bot->num_faces; /* number of vertices */ ret = fwrite(&nvert, sizeof(uint32_t), 1, fp_out); if (ret != 1) perror("fwrite"); /* number of faces */ ret = fwrite(&nface, sizeof(uint32_t), 1, fp_out); if (ret != 1) perror("fwrite"); /* vertex triples */ for (i = 0; i < curr->bot->num_vertices; i++) { get_vertex(curr->bot, i, vec); ret = fwrite(vec, sizeof(float), 3, fp_out); if (ret != 3) perror("fwrite"); } /* normal triples */ if (curr->bot->num_normals == curr->bot->num_vertices) { if (verbose) fprintf(stderr, ">> .. normals found!\n"); /* normals are provided */ ret = fwrite(curr->bot->normals, sizeof(float), curr->bot->num_normals * 3, fp_out); if (ret != curr->bot->num_normals * 3) perror("fwrite"); } else { float *normals; if (verbose) { fprintf(stderr, ">> .. normals will be computed\n"); } /* normals need to be computed */ normals = (float *)bu_calloc(sizeof(float), curr->bot->num_vertices * 3, "normals"); get_normals(curr->bot, normals); ret = fwrite(normals, sizeof(float), curr->bot->num_vertices * 3, fp_out); if (ret != curr->bot->num_vertices * 3) perror("fwrite"); bu_free(normals, "normals"); } if (nface < 1<<8) { format = 0; } else if (nface < 1<<16) { format = 1; } else { format = 2; } /* face index format */ ret = fwrite(&format, 1, 1, fp_out); if (ret != 1) perror("fwrite"); switch (format) { default: case 0: for (i = 0; i < nface; i++) { ind8[0] = curr->bot->faces[3*i]; if (flip_normals) { ind8[1] = curr->bot->faces[3*i+2]; ind8[2] = curr->bot->faces[3*i+1]; } else { ind8[1] = curr->bot->faces[3*i+1]; ind8[2] = curr->bot->faces[3*i+2]; } ret = fwrite(&ind8, 1, 3, fp_out); if (ret != 3) perror("fwrite"); } break; case 1: for (i = 0; i < nface; i++) { ind16[0] = curr->bot->faces[3*i]; if (flip_normals) { ind16[1] = curr->bot->faces[3*i+2]; ind16[2] = curr->bot->faces[3*i+1]; } else { ind16[1] = curr->bot->faces[3*i+1]; ind16[2] = curr->bot->faces[3*i+2]; } ret = fwrite(&ind16, 2, 3, fp_out); if (ret != 3) perror("fwrite"); } break; case 2: for (i = 0; i < nface; i++) { ind32[0] = curr->bot->faces[3*i]; if (flip_normals) { ind32[1] = curr->bot->faces[3*i+2]; ind32[2] = curr->bot->faces[3*i+1]; } else { ind32[1] = curr->bot->faces[3*i+1]; ind32[2] = curr->bot->faces[3*i+2]; } ret = fwrite(&ind32, 4, 3, fp_out); if (ret != 3) perror("fwrite"); } break; } curr = curr->next; } }