TEST(ReplaceBulkData, read_replace_write) { stk::ParallelMachine pm = MPI_COMM_WORLD; const int p_size = stk::parallel_machine_size(pm); if (p_size > 1) { return; } // const unsigned spatialDim = 3; stk::mesh::MetaData* meta = new stk::mesh::MetaData; stk::mesh::BulkData* bulk = new stk::mesh::BulkData(*meta, pm); std::string filename("generated:1x1x1"); read_mesh(filename, *bulk); //replace BulkData: delete bulk; bulk = new stk::mesh::BulkData(*meta, pm); create_1_hex_element(*bulk); //write out to exodus file std::string out_filename("replace_out.exo"); write_mesh(out_filename, *bulk); delete bulk; delete meta; unlink(out_filename.c_str()); }
void write_nodes(FILE *o, Lib3dsFile *f, Lib3dsNode *first_node) { Lib3dsNode *p; for (p = first_node; p; p = p->next) { if (p->type == LIB3DS_NODE_MESH_INSTANCE) { write_mesh(o, f, (Lib3dsMeshInstanceNode*)p); write_nodes(o, f, p->childs); } } }
int main(int argc, char *argv[]) { if (argc != 1) { err_msg("Usage: %s < mesh.sm > mesh.iv", argv[0]); return 1; } BMESHptr mesh = BMESH::read_jot_stream(cin); if (!mesh || mesh->empty()) return 1; // didn't work // Write it out write_mesh(*mesh, cout); return 0; }
void CDomain::signal_write_mesh(SignalArgs& node) { SignalOptions options( node ); URI fileuri = options.value<URI>("file"); write_mesh(fileuri); }
/* Main */ int main(int argc, char* argv[]) { int nnF = 200000, nnV = 200000, nnT = 1100000; int nF = 0, nV = 0, nT = 0; int *face = 0, *facematerial = 0, *facedup = 0, *facematdup = 0; int *tetra = 0, *tetramaterial = 0; double *vertex = 0; int i, nFdup, r, j, medge, msurf, m, k, p; int nVVert, nLine, nSurface; int *LineD, *LineP; double *LineT; int *SurfL, *SurfI; double *SurfT; double *VVert; int *expCrv; int nE = 0, nnE = 100000, *edge, *edgematerial; int va, vb, vc, vd, ve, vf, vg, vh; int vc1a, vc1b, vc2a, vc2b, vc3a, vc3b; int arc1a, arc1b, arc2a, arc2b, arc3a, arc3b; int eab, ebc, ecd, eda, eef, efg, egh, ehe, eae, ebf, ecg, edh; int ntfix = 0, nvfix = 0; int izero = 0; // allocate memory for mesh ctructures vertex = (double*)malloc(sizeof(double) * 3 * nnV); face = (int*) malloc(sizeof(int) * 3 * nnF); facedup = (int*) malloc(sizeof(int) * 3 * nnF); facematerial = (int*) malloc(sizeof(int) * nnF); facematdup = (int*) malloc(sizeof(int) * nnF); tetra = (int*) malloc(sizeof(int) * 4 * nnT); tetramaterial = (int*) malloc(sizeof(int) * nnT); edge = (int*) malloc(sizeof(int) * 2 * nnE); edgematerial = (int*) malloc(sizeof(int) * nnE); // allocate memory for boundary representation structure VVert = (double*)malloc(sizeof(double) * 3*100); nVVert = 0; LineD = (int*) malloc(sizeof(int) * 3*100); LineP = (int*) malloc(sizeof(int) * 2*2*100); LineT = (double*)malloc(sizeof(double) * 2*2*100); nLine = 0; SurfL = (int*) malloc(sizeof(int) * 5*100); SurfI = (int*) malloc(sizeof(int) * 2*2*100); SurfT = (double*)malloc(sizeof(double) * 4*100); nSurface = 0; expCrv = (int*) malloc(sizeof(int) * 100); memset(expCrv, 0, sizeof(int) * 100); /***/ #define ADD_VERTEX(X, Y, Z) (VVert[3*nVVert+0] = X, VVert[3*nVVert+1] = Y, VVert[3*nVVert+2] = Z, ++nVVert) #define EDGE(V1, V2, N, ...) add_edge(LineD, LineP, LineT, &nLine, &medge, V1, V2, N, __VA_ARGS__) #define SURF(P, C1, C2, D, U1, U2, V1, V2, N, ...) add_surf(SurfL, SurfT, SurfI, &nSurface, &msurf, P, C1, C2, D, U1, U2, V1, V2, N, __VA_ARGS__) /***/ vc1a = ADD_VERTEX( R1, 0, 0); vc1b = ADD_VERTEX(-R1, 0, 0); vc2a = ADD_VERTEX( R2, 0, 0); vc2b = ADD_VERTEX(-R2, 0, 0); vc3a = ADD_VERTEX( R3, 0, 0); vc3b = ADD_VERTEX(-R3, 0, 0); va = ADD_VERTEX(-Db, -Db, 0); vb = ADD_VERTEX(-Db, Db, 0); vc = ADD_VERTEX( Db, Db, 0); vd = ADD_VERTEX( Db, -Db, 0); ve = ADD_VERTEX(-Db, -Db, -Db); vf = ADD_VERTEX(-Db, Db, -Db); vg = ADD_VERTEX( Db, Db, -Db); vh = ADD_VERTEX( Db, -Db, -Db); medge = 0; /* EDGE(v1, v2, nSurf, [iSurf, iLine, t_0, t1,] ...); */ arc1a = EDGE(vc1a, vc1b, 1, 1, 1, 0.0, M_PI); arc1b = EDGE(vc1b, vc1a, 1, 1, 1, M_PI, 2.0*M_PI); arc2a = EDGE(vc2a, vc2b, 1, 1, 2, M_PI, 0.0); arc2b = EDGE(vc2b, vc2a, 1, 1, 2, 2.0*M_PI, M_PI); arc3a = EDGE(vc3a, vc3b, 1, 1, 3, 0.0, M_PI); arc3b = EDGE(vc3b, vc3a, 1, 1, 3, M_PI, 2.0*M_PI); expCrv[arc1a-1] = 1, expCrv[arc1b-1] = 1; expCrv[arc2a-1] = 1, expCrv[arc2b-1] = 1; expCrv[arc3a-1] = 1, expCrv[arc3b-1] = 1; eab = EDGE(va, vb, 1, 0, 0, 0.0, 0.0); ebc = EDGE(vb, vc, 1, 0, 0, 0.0, 0.0); ecd = EDGE(vc, vd, 1, 0, 0, 0.0, 0.0); eda = EDGE(vd, va, 1, 0, 0, 0.0, 0.0); eef = EDGE(ve, vf, 1, 0, 0, 0.0, 0.0); efg = EDGE(vf, vg, 1, 0, 0, 0.0, 0.0); egh = EDGE(vg, vh, 1, 0, 0, 0.0, 0.0); ehe = EDGE(vh, ve, 1, 0, 0, 0.0, 0.0); eae = EDGE(va, ve, 1, 0, 0, 0.0, 0.0); ebf = EDGE(vb, vf, 1, 0, 0, 0.0, 0.0); ecg = EDGE(vc, vg, 1, 0, 0, 0.0, 0.0); edh = EDGE(vd, vh, 1, 0, 0, 0.0, 0.0); msurf = 0; /* SURF(iSurf, color1, color2, direction, u0, u1, v0, v1, n, [edge, edge_dir,] ...); */ SURF(1, 2, 11, 0, -Db, Db, -Db, Db, 2, arc1a, 0, arc1b, 0); SURF(1, 1, 0, 0, -Db, Db, -Db, Db, 4, arc2a, 1, arc2b, 1, arc1a, 1, arc1b, 1); SURF(1, 2, 12, 0, -Db, Db, -Db, Db, 4, arc3a, 0, arc3b, 0, arc2a, 0, arc2b, 0); SURF(0, 1, 0, 0, 0.0, 0.0, 0.0, 0.0, 6, arc3a, 1, arc3b, 1, eab, 1, ebc, 1, ecd, 1, eda, 1); SURF(0, 1, 0, 0, 0.0, 0.0, 0.0, 0.0, 4, eef, 0, efg, 0, egh, 0, ehe, 0); SURF(0, 1, 0, 0, 0.0, 0.0, 0.0, 0.0, 4, eab, 0, ebf, 0, eef, 1, eae, 1); SURF(0, 1, 0, 0, 0.0, 0.0, 0.0, 0.0, 4, ebc, 0, ecg, 0, efg, 1, ebf, 1); SURF(0, 1, 0, 0, 0.0, 0.0, 0.0, 0.0, 4, ecd, 0, edh, 0, egh, 1, ecg, 1); SURF(0, 1, 0, 0, 0.0, 0.0, 0.0, 0.0, 4, eda, 0, eae, 0, ehe, 1, edh, 1); tria_dump_front = 0; tria_debug_front = 0; region_dump_face = 0; printf("\n * Generating surface mesh\n"); i = ani3d_surface_edges_boundary_(&nVVert, VVert, &nLine, LineD, LineP, LineT, &nSurface, SurfL, SurfI, SurfT, NULL, surface_param, line_param, NULL/*periodic*/, fsize, expCrv, &nV, vertex, &nF, face, facematerial, &nE, edge, edgematerial, &nnV, &nnF, &nnE ); free(VVert), free(LineD), free(LineP), free(LineT), free(SurfL), free(SurfI), free(SurfT); printf("INFO: nV = %d, nE = %d, nF = %d, nT = %d\n", nV, nE, nF, nT); /* Generate skin mesh */ printf("\n * Generating skin mesh\n"); nFdup = 0; addlayer(electrodesize, &nV, vertex-3, nE, edge, edgematerial, &nF, face, facematerial, &nT, tetra, tetramaterial, &nFdup, facedup, facematdup, nnV, nnF, nnT); fix_vertices(&nV, vertex-3, nF, face, nT, tetra, nFdup, facedup, nE, edge); printf("INFO: nV = %d, nF = %d, nT = %d\n", nV, nF, nT); // It could be usefull to dump the triangulation of the surface in case we want to check // that boundary representation is correct and represents the desired region if (0) { write_mesh_gmv("surf.gmv", nV, vertex, nF, face, facematerial, nT, tetra, tetramaterial); // for GMV write_front ("surf.smv", nV, vertex, nF, face, facematerial); // for smv // return 0; // do not mesh the volume, just exit write_mesh_gmv("dups.gmv", nV, vertex, nFdup, facedup, facematdup, nT, tetra, tetramaterial); // for GMV write_front ("dups.smv", nV, vertex, nFdup, facedup, facematdup); // for smv } // We will copy the front, so that it could be used in output in future. ntfix = nT; nvfix = nV; for (i=0; i<nF; i++) { facedup[3*nFdup+0] = face[3*i+0]; facedup[3*nFdup+1] = face[3*i+1]; facedup[3*nFdup+2] = face[3*i+2]; facematdup[nFdup] = facematerial[i]; nFdup++; } // Generate 3D mesh using our own size function fsize() printf("\n * Generating volume mesh\n"); r = mesh_3d_aft_func_(&nV, vertex, &nF, face, facematerial, &nT, tetra, tetramaterial, &nnV, &nnF, &nnT, fsize); printf("\nINFO: nV = %d, nF = %d, nT = %d\n", nV, nF, nT); if (r) { write_mesh_gmv("fail.gmv", nV, vertex, nF, face, facematerial, nT, tetra, tetramaterial); } else { /* Check that 3D mesh corresponds with surface mesh */ /*printf("Checking topology: "), fflush(stdout);*/ if (0 && check_mesh_topology_(&nV, vertex, &nFdup, facedup, &nT, tetra)) printf("FAILED!\n"); else { /*printf("ok.\n");*/ if (0) { write_mesh ("bfix.out", nV, vertex, nFdup, facedup, facematdup, nT, tetra, tetramaterial); write_mesh_gmv_qual("bfix.gmv", nV, vertex, nFdup, facedup, facematdup, nT, tetra, tetramaterial); } for (i=0; i<nT; i++) tetramaterial[i] = (tetramaterial[i]==1) ? 2 : tetramaterial[i]; keepskin(&nFdup, facedup, facematdup); /* Improve mesh quality */ printf("\n * Smoothing volume mesh\n"); fixshape(&nV, vertex, &nT, tetra, tetramaterial, &nFdup, facedup, facematdup, 0, ntfix, nFdup, nnV, nnT, nnF); keepskin(&nFdup, facedup, facematdup); // Write output files write_mesh_gmv_qual("mesh.gmv", nV, vertex, nFdup, facedup, facematdup, nT, tetra, tetramaterial); /*write_mesh ("mesh.out", nV, vertex, nFdup, facedup, facematdup, nT, tetra, tetramaterial);*/ saveMani(&nV, &nFdup, &nT, vertex, facedup, tetra, facematdup, tetramaterial, &izero, &izero, &izero, NULL, NULL, NULL, &izero, NULL, NULL, "mesh.ani"); } } free(vertex); free(face); free(facedup); free(facematerial); free(facematdup); free(tetra); free(tetramaterial); return 0; }
bool Surface_mesh:: write(const std::string& filename) const { return write_mesh(*this, filename); }
int main(int argc, char* argv[]) { int nnF = 1000000, nnV = 1000000, nnT = 1000000; int nF = 0, nV = 0, nT = 0; int nnS = 1000, nnE = 1000; int *face = 0, *facematerial = 0, *facedup = 0, *facematdup = 0; int *tetra = 0, *tetramaterial = 0; double *vertex = 0; int i, nFdup, r, m; int nVVert, nLine, nSurface; int *LineD, *LineP; double *LineT; int *SurfL, *SurfI; double *SurfT; double *VVert; (void) argc, (void) argv; // allocate memory for mesh ctructures vertex = (double*)malloc(sizeof(double) * 3 * nnV); face = (int*) malloc(sizeof(int) * 3 * nnF); facedup = (int*) malloc(sizeof(int) * 3 * nnF); facematerial = (int*) malloc(sizeof(int) * nnF); facematdup = (int*) malloc(sizeof(int) * nnF); tetra = (int*) malloc(sizeof(int) * 4 * nnT); tetramaterial = (int*) malloc(sizeof(int) * nnT); // allocate memory for boundary representation structure VVert = (double*)malloc(sizeof(double) * 3*nnV); nVVert = 0; LineD = (int*) malloc(sizeof(int) * 3*nnE); LineP = (int*) malloc(sizeof(int) * 2*2*nnE); LineT = (double*)malloc(sizeof(double) * 2*2*nnE); nLine = 0; SurfL = (int*) malloc(sizeof(int) * 5*nnS); SurfI = (int*) malloc(sizeof(int) * 2*2*nnE); SurfT = (double*)malloc(sizeof(double) * 4*nnS); nSurface = 0; // First we will define coords of the main points. // Main points are the end points of each curve. // They are also known as V-points or V-vertices // We will define 8 vertices of the box // and two points on equator of the sphere // Here is an example how we can add point with coords(x,y,z): /* VVert[3*nVVert+0] = x; VVert[3*nVVert+1] = y; VVert[3*nVVert+2] = z; nVVert++; */ // To simplify our program we can use the following macros: #define ADD_VERTEX(X, Y, Z); {\ VVert[3*nVVert+0] = X;\ VVert[3*nVVert+1] = Y;\ VVert[3*nVVert+2] = Z;\ nVVert++;\ } // 8 vertices of the box ADD_VERTEX(CX - L, CY - L, CZ - L); // 1 ADD_VERTEX(CX + L, CY - L, CZ - L); // 2 ADD_VERTEX(CX + L, CY + L, CZ - L); // 3 ADD_VERTEX(CX - L, CY + L, CZ - L); // 4 ADD_VERTEX(CX - L, CY - L, CZ + L); // 5 ADD_VERTEX(CX + L, CY - L, CZ + L); // 6 ADD_VERTEX(CX + L, CY + L, CZ + L); // 7 ADD_VERTEX(CX - L, CY + L, CZ + L); // 8 // If the vertex is the end of parametrized curve it coords will be forcly recalculated // So for such points we can just say nVVert++; // But in this example we will still fill the coords for clarity/ ADD_VERTEX(CX - R, CY, CZ); // 9 | In fact coords of these points will be recalculated ADD_VERTEX(CX + R, CY, CZ); // 10 | using parametrization of the curves m = 0; // Now we will define our curves // For each curve we should define indices of start point and end point // We also should define number of parametrized surfaces this curve belongs to. // For each such surface we define the F_i and V_j, so curve is parametrized as // u -> (u,v) = (u,V_j(u)) -> (x,y,z) = F_i(u,v) // Pairs (i,j) are stored in separate array in successive order // If curve is a segment, it still needs one pair of (i,j)=(0,0) // For each pair (i,j) we also define the value of parameter u for start and end points, // they are stored in third array // Here is an example how we can add curve: /* LineD[3*nLine+0] = v1; LineD[3*nLine+1] = v2; // indices of start and end points LineD[3*nLine+2] = 2; // this curve belongs to two surfaces // first one have parametrization function number 1 (F_1) // and in this surface curve could be parametrized by V_5(u), where u are from -1.0 to 1.0 LineP[2*m+0] = 1; LineP[2*m+1] = 5; LineT[2*m+0] = -1.0; LineT[2*m+1] = 1.0; m++; // first surface have parametrization function number 2 (F_2) // and in this surface curve could be parametrized by V_9(u), where u are from 0.0 to 2.0 LineP[2*m+0] = 2; LineP[2*m+1] = 9; LineT[2*m+0] = 0.0; LineT[2*m+1] = 2.0; m++; nLine++; */ // To simplify our program we can use the following macros for segments: #define ADD_SEGMENT(V1, V2); {\ LineD[3*nLine+0] = V1; LineD[3*nLine+1] = V2;\ LineD[3*nLine+2] = 1;\ LineP[2*m+0] = 0; LineP[2*m+1] = 0; LineT[2*m+0] = 0.0; LineT[2*m+1] = 0.0; m++;\ nLine++;\ } // 12 edges of the box ADD_SEGMENT(1, 2); // 1 ADD_SEGMENT(2, 3); // 2 ADD_SEGMENT(3, 4); // 3 ADD_SEGMENT(4, 1); // 4 ADD_SEGMENT(5, 6); // 5 ADD_SEGMENT(6, 7); // 6 ADD_SEGMENT(7, 8); // 7 ADD_SEGMENT(8, 5); // 8 ADD_SEGMENT(1, 5); // 9 ADD_SEGMENT(2, 6); // 10 ADD_SEGMENT(3, 7); // 11 ADD_SEGMENT(4, 8); // 12 // First arc on equator from point 9 to point 10 LineD[3*nLine+0] = 9; LineD[3*nLine+1] = 10; // This arc belongs to two surfaces (halfs of the sphere) LineD[3*nLine+2] = 2; // On both halfs of the sphere this arc is parametrized by the same (u,v) // We will use V_1 for both surfaces, u in [-1.0, 1.0] LineP[2*m+0] = 1; LineP[2*m+1] = 1; LineT[2*m+0] = -1.0; LineT[2*m+1] = 1.0; m++; LineP[2*m+0] = 2; LineP[2*m+1] = 1; LineT[2*m+0] = -1.0; LineT[2*m+1] = 1.0; m++; nLine++; // 13 // Second arc on equator from point 10 to point 9 LineD[3*nLine+0] = 10; LineD[3*nLine+1] = 9; // This arc also belongs to two surfaces (halfs of the sphere) LineD[3*nLine+2] = 2; // On both halfs of the sphere this arc is parametrized by the same (u,v) // We will use V_2 for both surfaces, u in [1.0, -1.0] LineP[2*m+0] = 1; LineP[2*m+1] = 2; LineT[2*m+0] = 1.0; LineT[2*m+1] = -1.0; m++; LineP[2*m+0] = 2; LineP[2*m+1] = 2; LineT[2*m+0] = 1.0; LineT[2*m+1] = -1.0; m++; nLine++; // 14 m = 0; // Now we will define surfaces // For each surface we define 5 integer numbers (SurfL): // 1st: number of boundary curves // 2nd: number of parametrization function // 3rd: color of the face // 4th: 0 if the face is boundary face, or the second color of the face if it is used to split volume // 5th: 0 if orientation of the face corresponds with parametrization, 1 if it should be inverted, 0 for flat faces // For each surface we alse define minimax values of (u,v) parametrization (SurfT) // u_min, u_max, v_min, v_max // For each boundary curve we define a pair of integers (SurfI): // 1st: index of curve // 2nd: orientation, 0 for normal, 1 for reversed // Here is an example how we can add surface: /* SurfL[5*nSurface+0] = 2; // surface is bounded by two curves SurfL[5*nSurface+1] = 1; // surface is parametrized by F_1 SurfL[5*nSurface+2] = 1; // the color of face is 1 SurfL[5*nSurface+3] = 0; // the face is boundary SurfL[5*nSurface+4] = 0; // orientation of the face corresponds with parametrization // minimax values of parametrs SurfT[4*nSurface+0] = -1.0; SurfT[4*nSurface+1] = -1.0; SurfT[4*nSurface+2] = 1.0; SurfT[4*nSurface+3] = 1.0; // first curve is curve number c1, orientation is normal SurfI[2*m+0] = c1; SurfI[2*m+1] = 0; m++; // second curve is curve number c2, orientation is reversed SurfI[2*m+0] = c2; SurfI[2*m+1] = 1; m++; nSurface++; */ // In common case to invert orientation of the face one should invert the 5th parameter in SurfL // and invert orientation of all boundary curves // To simplify our program we can use the following macros for flat quadrilaterals: // Here for each curve (V,I) is for index of the curve V and orientation I #define ADD_QUADRILATERAL(V1,I1, V2,I2, V3,I3, V4,I4); {\ SurfL[5*nSurface+0] = 4;\ SurfL[5*nSurface+1] = 0;\ SurfL[5*nSurface+2] = 1;\ SurfL[5*nSurface+3] = 0;\ SurfL[5*nSurface+4] = 0;\ SurfT[4*nSurface+0] = 0.0; SurfT[4*nSurface+1] = 0.0; SurfT[4*nSurface+2] = 0.0; SurfT[4*nSurface+3] = 0.0;\ SurfI[2*m+0] = V1; SurfI[2*m+1] = I1; m++;\ SurfI[2*m+0] = V2; SurfI[2*m+1] = I2; m++;\ SurfI[2*m+0] = V3; SurfI[2*m+1] = I3; m++;\ SurfI[2*m+0] = V4; SurfI[2*m+1] = I4; m++;\ nSurface++;\ } // 6 faces of the box ADD_QUADRILATERAL( 4,1, 3,1, 2,1, 1,1); // 1 ADD_QUADRILATERAL( 5,0, 6,0, 7,0, 8,0); // 2 ADD_QUADRILATERAL( 1,0, 10,0, 5,1, 9,1); // 3 ADD_QUADRILATERAL( 2,0, 11,0, 6,1, 10,1); // 4 ADD_QUADRILATERAL( 3,0, 12,0, 7,1, 11,1); // 5 ADD_QUADRILATERAL( 4,0, 9,0, 8,1, 12,1); // 6 // top half of the sphere, parametrized by F_1 SurfL[5*nSurface+0] = 2; SurfL[5*nSurface+1] = 1; SurfL[5*nSurface+2] = 1; SurfL[5*nSurface+3] = 0; SurfL[5*nSurface+4] = 1; SurfT[4*nSurface+0] = -1.0; SurfT[4*nSurface+1] = 1.0; SurfT[4*nSurface+2] = -1.0; SurfT[4*nSurface+3] = 1.0; SurfI[2*m+0] = 13; SurfI[2*m+1] = 0; m++; SurfI[2*m+0] = 14; SurfI[2*m+1] = 0; m++; nSurface++; // 7 // bottom half of the sphere, parametrized by F_2 SurfL[5*nSurface+0] = 2; SurfL[5*nSurface+1] = 2; SurfL[5*nSurface+2] = 1; SurfL[5*nSurface+3] = 0; SurfL[5*nSurface+4] = 0; SurfT[4*nSurface+0] = -1.0; SurfT[4*nSurface+1] = 1.0; SurfT[4*nSurface+2] = -1.0; SurfT[4*nSurface+3] = 1.0; SurfI[2*m+0] = 13; SurfI[2*m+1] = 1; m++; SurfI[2*m+0] = 14; SurfI[2*m+1] = 1; m++; nSurface++; // 8 // Note the difference of orientations of last two surfaces // When creating new boundary representations it could be usefull to check // the boundary of each surface // tria_dump_front = 1; // enable dumping of initial front for each surface // If triangulation of surface fails, it could be usefull to check the process // of the triangulation // tria_debug_front = 1; // enable dumping front on each step. Will generate a lot of files // fronts will be droped in files frt_gmv.{num} for gmv // and frt_smv.{num} for smv or manual reference // {num} is 000, 001, 002, ... // region_dump_face = 1; // Setting up our boundary parametrization functions // First one is for (x,y,z)=F_i(u,v) and second one is for v=V_j(u) set_param_functions(surface_param, v_u_param); // Now we are ready to create the surface mesh // Setting up our own size function. set_surface_size_function(fsize); // Making surface mesh i = surface_boundary_(&nVVert, VVert, &nLine, LineD, LineP, LineT, &nSurface, SurfL, SurfI, SurfT, &nV, vertex, &nF, face, facematerial, &nnV, &nnF); free(VVert), free(LineD), free(LineP), free(LineT), free(SurfL), free(SurfI), free(SurfT); printf("\nINFO: nV = %d, nF = %d, nT = %d\n", nV, nF, nT); // It could be usefull to dump the triangulation of the surface in case we want to check // that boundary representation is correct and represents the desired region if (0) { write_mesh_gmv("surf.gmv", nV, vertex, nF, face, facematerial, 0, 0, 0); // for GMV write_front ("surf.smv", nV, vertex, nF, face, facematerial); // for smv // return 0; // do not mesh the volume, just exit } // We will copy the front, so that it could be used in output in future. nFdup = nF; memcpy(facedup, face, sizeof(int)*3*nF); memcpy(facematdup, facematerial, sizeof(int)*nF); // Generate 3D mesh using our own size function fsize() r = mesh_3d_aft_func_(&nV, vertex, &nF, face, facematerial, &nT, tetra, tetramaterial, &nnV, &nnF, &nnT, fsize); printf("\nINFO: nV = %d, nF = %d, nT = %d\n", nV, nF, nT); if (r) { write_mesh_gmv("fail.gmv", nV, vertex, nF, face, facematerial, nT, tetra, tetramaterial); } else { // Checking that 3D mesh corresponds with surface mesh printf("Cheking topology: "); fflush(stdout); if (check_mesh_topology_(&nV, vertex, &nFdup, facedup, &nT, tetra)) printf("FAILED!\n"); else printf("ok.\n"); // Write output files write_mesh_gmv("mesh.gmv", nV, vertex, nFdup, facedup, facematdup, nT, tetra, tetramaterial); write_mesh ("mesh.out", nV, vertex, nFdup, facedup, facematdup, nT, tetra, tetramaterial); } return 0; }
bool write_face(HOBJXIO hobjxio, const string& name, const faces& fcs, const obj_mesh_data& dat, const material& mtl) { static vec4_coll vertices; static vec4_coll normals; static vec4_coll tangents; static vec2_coll texcoords; mesh_info mesh; mesh.num_indices = 0; mesh.indices = NULL; for(int i = 0; i < faces::MAX; i++) { const face& fc = fcs.face_data[i]; // stat vertices mesh.num_vertices = 0; for(int i = 0; i < (int)fc.size(); i++) // 3 indices for 1 triangle, 4 for 2, 5 for 3, ... n indices for n-2 triangles make (n-2)*3 vertices mesh.num_vertices += (fc[i].vertIndices.size() - 2) * 3; if(0 == mesh.num_vertices) continue; // prepare container vertices.clear(); normals.clear(); tangents.clear(); texcoords.clear(); // for each facet for(int i = 0; i < (int)fc.size(); i++) { const facet& f = fc[i]; // facet -> triangles for(int j = 1; j < (int)f.vertIndices.size() - 1; j++) { vertices.push_back(dat.vertices[f.vertIndices[ 0]]); vertices.push_back(dat.vertices[f.vertIndices[ j]]); vertices.push_back(dat.vertices[f.vertIndices[j + 1]]); } } ATLASSERT(vertices.size() > 0); mesh.vertices = &vertices[0]; // for each facet for(int i = 0; i < (int)fc.size(); i++) { const facet& f = fc[i]; // facet -> triangles for(int j = 1; j < (int)f.normIndices.size() - 1; j++) { normals.push_back(dat.normals[f.normIndices[ 0]]); normals.push_back(dat.normals[f.normIndices[ j]]); normals.push_back(dat.normals[f.normIndices[j + 1]]); } } // unlike vertices, normal data can be absent if(0 == normals.size()) // if normal not exists, we generate { for(int i = 0; i < (int)vertices.size(); i += 3) { const vec4& a = vertices[ i]; const vec4& b = vertices[i + 1]; const vec4& c = vertices[i + 2]; vec4 edge1, edge2, n; mcemaths_sub_3_4(edge1, c, b); mcemaths_sub_3_4(edge2, a, b); mcemaths_cross_3(n, edge1, edge2); mcemaths_norm_3_4(n); normals.push_back(n); normals.push_back(n); normals.push_back(n); } } mesh.normals = &normals[0]; mesh.has_normals = true; // for each facet for(int i = 0; i < (int)fc.size(); i++) { const facet& f = fc[i]; // facet -> triangles for(int j = 1; j < (int)f.texIndices.size() - 1; j++) { texcoords.push_back(dat.texcoords[f.texIndices[ 0]]); texcoords.push_back(dat.texcoords[f.texIndices[ j]]); texcoords.push_back(dat.texcoords[f.texIndices[j + 1]]); } } mesh.texcoords = NULL; mesh.tangents = NULL; mesh.has_texcoords = mesh.has_tangents = false; if(texcoords.size() > 0) // unlike vertices, texture coordinate can also be absent { mesh.texcoords = &texcoords[0]; mesh.has_texcoords = true; // if texcoords exist, generate tangents (save time for game initialization as much as possible) for(int i = 0; i < (int)vertices.size(); i += 3) { const vec4& a = vertices [ i]; const vec4& b = vertices [i + 1]; const vec4& c = vertices [i + 2]; const vec2& ta2 = texcoords[ i]; const vec2& tb2 = texcoords[i + 1]; const vec2& tc2 = texcoords[i + 2]; vec4 ta(ta2.x, ta2.y, 0, 0); vec4 tb(tb2.x, tb2.y, 0, 0); vec4 tc(tc2.x, tc2.y, 0, 0); vec4 modvec1(0.0f), modvec4(0.0f), texvec1(0.0f), texvec4(0.0f); mcemaths_sub_3_4(modvec1, c , a); mcemaths_sub_3_4(modvec4, b , a); mcemaths_sub_3_4(texvec1, tc, ta); mcemaths_sub_3_4(texvec4, tb, ta); mcemaths_mul_3_4(modvec1, texvec4.y); mcemaths_mul_3_4(modvec4, texvec1.y); mcemaths_sub_3_4_ip(modvec1, modvec4); mcemaths_div_3_4(modvec1, texvec1.x * texvec4.y - texvec4.x * texvec1.y); mcemaths_norm_3_4(modvec1); tangents.push_back(modvec1); tangents.push_back(modvec1); tangents.push_back(modvec1); } mesh.tangents = &tangents[0]; mesh.has_tangents = true; } mesh.mesh_name = name; mesh.ambient_colour = vec4(mtl.ambientColour.x, mtl.ambientColour.y, mtl.ambientColour.z, 1.0f); mesh.diffuse_colour = vec4(mtl.diffuseColour.x, mtl.diffuseColour.y, mtl.diffuseColour.z, 1.0f); mesh.specular_colour = vec4(mtl.specularColour.x, mtl.specularColour.y, mtl.specularColour.z, 1.0f); mesh.specular_exponent = mtl.specularExponent; mesh.diffuse_file = mtl.diffuseFile; mesh.bump_file = mtl.bumpFile; mesh.spc_file = mtl.spcFile; mesh.spe_file = mtl.speFile; mesh.programme = mtl.programmeName; if(!write_mesh(hobjxio, mesh)) return false; } return true; }
int main(int argc, char* argv[]) { int zeroindex = 0, invert = 0; int nnF = 1000000, nnV = 2000000, nnT = 4000000; int nF = 0, nV = 0, nT = 0; int *face = 0, *facematerial = 0; int *tetra = 0, *tetramaterial = 0; double *vertex = 0; int nFdup, *facedup, *facematdup; int r; // default values double cf=1.2, cfs=1.2; double pc[5] = {0.0, 0.05, 0.01, 0.3, 100.0}; // reading surfacemesh from file if (argc<2) { printf("Usage: ParamToTet_aft.exe file.frt cf cfs abs rel c1 c2 dist\n"); printf(" cf - coarsening factor (default: %lg)\n", cf); printf(" cfs - coarsening factor on surface (default: %lg)\n", cfs); printf(" abs - absolute minimal mesh size (default: %lg)\n", pc[0]); printf(" rel - relative minimal mesh size (default: %lg)\n", pc[1]); printf(" c1, c2 - maximal angle deviation (default: %lg, %lg)\n", pc[2], pc[3]); printf(" dist - maximal distance deviation (default: %lg)\n", pc[4]); return 0; } if (argc>2) sscanf(argv[2], "%lf", &cf); if (argc>3) sscanf(argv[3], "%lf", &cfs); if (argc>4) sscanf(argv[4], "%lf", pc+0); if (argc>5) sscanf(argv[5], "%lf", pc+1); if (argc>6) sscanf(argv[6], "%lf", pc+2); if (argc>7) sscanf(argv[7], "%lf", pc+3); if (argc>8) sscanf(argv[8], "%lf", pc+4); // Allocating memory for mesh structures vertex = (double*)malloc(sizeof(double) * 3 * nnV); face = (int*) malloc(sizeof(int) * 3 * nnF); facematerial = (int*) malloc(sizeof(int) * nnF); facedup = (int*) malloc(sizeof(int) * 3 * nnF); // this is for saving facematdup = (int*) malloc(sizeof(int) * nnF); // new surface mesh tetra = (int*) malloc(sizeof(int) * 4 * nnT); tetramaterial = (int*) malloc(sizeof(int) * nnT); printf("[cfs = %lg, cf = %lg]\n", cfs, cf); if (read_front(argv[1], &nV, vertex, &nF, face, facematerial, nnV, nnF, zeroindex, invert, 1)) { printf("Error in file %s\n", argv[1]); } // checking topology and merging duplicate vertices check_surface_topology_fix_(&nV, vertex, &nF, face); printf("\nINFO: nV = %d, nF = %d, nT = %d\n", nV, nF, nT); // We can write initial mesh in GMV format here if (0) write_mesh_gmv("initial.gmv", nV, vertex, nF, face, facematerial, nT, tetra, tetramaterial); // for debugging // setting parameters for surface_refine // Each edge could be splitted into multiple segments // first param bounds the mininal absolute length of these segments // if first param is set to zero (default value) then absolute length is not bounded below // second param bounds relative length of segments // (value of 0.1 mean that each segment should be at least 0.1*edge_length) // Surface is splitted into almost flat regions, next two params control the degree of this flatness // 3rd and 4th params control maximum angle between normals of triangle faces // 3rd is for regular triangles // 4th is for low-quality triangles // if both params are nearly zero, then all regions are really flat // these values are something like (1 - cos \alpha) // Fifth parameter is the maximal distance from original plane for that regions // if any param is set to zero or less, then the default value is used // you can try playing with this params // default values: 0, 0.05, 0.01, 0.3, 100 surface_refine_setup_poly_extra(pc[0], pc[1], pc[2], pc[3], pc[4]); surface_refine_setup_cf(cfs); // refine the surface mesh // this function does not require the front to be in cube [0,1]^3 surface_refine_(&nV, vertex, &nF, face, facematerial, &nnV, &nnF); printf("\nINFO: nV = %d, nF = %d, nT = %d\n", nV, nF, nT); write_mesh_gmv("refined.gmv", nV, vertex, nF, face, facematerial, nT, tetra, tetramaterial); // for debugging write_front ("refined.smv", nV, vertex, nF, face, facematerial); // for debugging // if we want to mesh external part of the space // we should add an additional inverted copy of our front // each triangle will be used twice in our front with different orientation and color // tetra colors are defined by the colors of the boundary front // we will shift colors of second inverted front by 1 //double_front(&nF, face, facematerial, 1, nnF); // we should bound our second front, otherwise it will grow far-far-away // here we construct bounding cube with color 2, which is somewhat bigger than the model //add_bound_box(&nV, vertex, &nF, face, facematerial, 2, 1, 1.5, nnV, nnF); // saving surface mesh before 3D meshing // this mesh could be used in future for checking topolgy or writing to the file memcpy(facedup, face, sizeof(int)*3*nnF); memcpy(facematdup, facematerial, sizeof(int)*nnF); nFdup = nF; printf("cf = %lf\n", cf); // cf is the rate at which mesh coarseness changes from the boundary to the center // value of 1.0 should produce semi-uniform mesh // value of 1.2 is the default value (you can call mesh_3d_aft_ if you want to use default value) // value of 1.5 could be used to produce coarse mesh // if meshing fails try to play with this value // cf = 1.3; // make 3D mesh from the front // this function could leave something unmeshed if advancing front fails // this function does not require the front to be in cube [0,1]^3 r = mesh_3d_aft_cf_(&nV, vertex, &nF, face, facematerial, &nT, tetra, tetramaterial, &nnV, &nnF, &nnT, &cf); // r==0 - ok, complete meshing // r!=0 - something is left, (nF, face, facematerial) is the surface mesh (aka front) of the rest printf("\nINFO: nV = %d, nF = %d, nT = %d\n", nV, nF, nT); fprintf(stderr, "\nAFT returned: %s\n", (r)?"FAIL":"ok"); if (r==0) { // Checking that 3D mesh corresponds with surface mesh printf("Checking topology: "); fflush(stdout); if ((r = check_mesh_topology_(&nV, vertex, &nFdup, facedup, &nT, tetra))) printf("FAILED!\n"), fprintf(stderr, "\nMESH: failed\n"); else printf("ok.\n"), fprintf(stderr, "\nMESH: ok\n"); // Write output files write_mesh_gmv("mesh.gmv", nV, vertex, nFdup, facedup, facematdup, nT, tetra, tetramaterial); write_mesh ("mesh.out", nV, vertex, nFdup, facedup, facematdup, nT, tetra, tetramaterial); printf("\nINFO: nV = %d, nF = %d, nT = %d\n", nV, nFdup, nT); } else { // Meshing failed. We save current meshed part and current front in gmv format printf("FAILED!\n"); write_mesh_gmv("fail.gmv", nV, vertex, nF, face, facematerial, nT, tetra, tetramaterial); fprintf(stderr, "\nMESH: failed\n"); } free(vertex), free(face), free(facematerial), free(facedup), free(facematdup), free(tetra), free(tetramaterial); return r; }