#include #include #include using namespace std; #include "TxsMesh.h" #include "SlideWriter.h" #include "txs_algo.h" #include "txs_multires_algo.h" #include "Heartbeat.h" #include "SimpleHeightFunc.h" using namespace TXS; #include "../parsestl.h" #include "txs_globals.h" #include "unit_tests.h" #include "../ccs/Mesh.h" #include "../ccs/SlideWriter.h" #include "../ccs/BinaryWriter.h" #include "relax/unit_tests.h" namespace TXS { template typename _T::iterator nextIterWrapped(_T &l, typename _T::iterator iter) { typename _T::iterator out = iter; ++out; if(out == l.end()) { out = l.begin(); } return out; } template typename _T::iterator nextNextIterWrapped(_T &l, typename _T::iterator iter) { return nextIterWrapped<_T>(l, nextIterWrapped<_T>(l, iter)); } } int feedTxsMeshToCcsMesh(TxsMesh &in, CCS::Mesh &out) { list::iterator f_iter; for(f_iter = in.getFaces().begin(); f_iter != in.getFaces().end(); ++f_iter) { TxsFace* f = *f_iter; // collect all vert-points and UVs list pts; list uvs; for(int iv = 0; iv < f->getNumVerts(); ++iv) { TxsVertex* v = f->getVertexMod(iv); pts.push_back(v->getPoint()); UVs uv = f->calcUV(v->getPoint()); //UVs uv(0,0); //__STAT__("UV: " << uv ); uvs.push_back(uv); } // add it out.addFace(pts, f->getFinestPyLevel(), uvs); } __STAT__("ccsMesh now has " << out.faces.size() << " faces."); return out.faces.size(); } int feedCcsMeshToTxsMesh(CCS::Mesh &in, TxsMesh &out) { int num_faces_added = 0; list faces = in.faces; list::iterator f_iter; for(f_iter = faces.begin(); f_iter != faces.end(); ++f_iter) { CCS::Face* f = *f_iter; // accum a list of points to give to the mesh list verts; CCS::Face::VertexIterator v_iter; for(v_iter.start(f); !v_iter.done(); v_iter.advance()) { verts.push_back(v_iter.get_point()); } // give it to the txs mesh out.addFace(verts); num_faces_added++; } __STAT__("fed " << num_faces_added << " faces into TxsMesh"); return num_faces_added; } int addStlToTxsMesh(TxsMesh &mesh, char *stlFile) { char* parseStlArgs[2]; CLEDSGeometry *STL = NULL; // Let the parser do its thing parseStlArgs[0] = "dummy stl arg 0"; parseStlArgs[1] = stlFile; STL = ParseSTL(2, parseStlArgs); // Now loop through all the triangles in the STL // using Greg's code list verts; // List of verts, for passing verts to TxsMesh int numTrisAdded = 0; CListIter CListIterIntFace; CLEDSliteFace *pFace; CLEDSliteFaceIter FaceIter; CLEDSliteVertex *p1stVtx, *pVtx; Point P,Q,R,S; int index=0; //Initialize face list iterator CListIterIntFace.Init(STL->GetCListFaces()); //Pull out the first face pFace = CListIterIntFace.PeekFirst(); Heartbeat hb; while (pFace) { // Initialize face iterator FaceIter.Init(pFace); // Get first vertex in face pVtx = p1stVtx = (CLEDSVertex *)FaceIter.PeekFirstCVertex(); // (Steve) Iterate through all tris and find the closest // of all distances do { index++; if (index == 1) { Q = pVtx->GetPoint(); } else if (index == 2) { R = pVtx->GetPoint(); } else { S = pVtx->GetPoint(); index = 0; // QRS is now a triangle // We're good. add it to the txs mesh verts.clear(); verts.push_back(Q); verts.push_back(R); verts.push_back(S); mesh.addFace(verts); numTrisAdded++; } // Get next vertex in face pVtx = (CLEDSVertex *)FaceIter.PeekNextCVertex(); } while (pVtx != p1stVtx); // Until you're back to the start //Get next face pFace = CListIterIntFace.PeekNext(); if(hb.OK_to_beat()) { cout << "Added " << numTrisAdded << " tris so far" << endl; } } return numTrisAdded; } int runSingleRes(int argc, char **argv, int argBegin) { __STAT__("Running single res algorithm"); char *stlFile = argv[argBegin]; __STAT__("Using STL file: \"" << stlFile << "\""); //---------------------------------------- // create the mesh and give it the STL file //---------------------------------------- TxsMesh mesh; int numTris = addStlToTxsMesh(mesh, stlFile); mesh.doneFeedingTris(); cout << "STL file had " << numTris << " triangles" << endl; cout << "mesh dimensions: " << mesh.getMaxs() - mesh.getMins() << endl; // get nhood size SR_NHOOD_PIXELS = atoi(argv[argBegin+1]); __STAT__("Using " << SR_NHOOD_PIXELS << "x" << SR_NHOOD_PIXELS << " neighborhoods"); // get the input image TiffImage finest(argv[argBegin+2]); // GO!!! synthTexturesSingleRes(mesh, finest); //--------------------------------- // Output! //--------------------------------- SlideWriter slfer; slfer.write("out_sr", &mesh); return 0; } int runMultiRes(int argc, char **argv, int argBegin) { __STAT__("Running MultiRes synth algo.."); /* * Parse and check the args */ if(argc < argBegin+ 1 + NUM_PYLEVS) { cout << "Too few arguments given!" << endl; cout << "Example usage: txs mesh.stl tex-64.tif tex-32.tif tex-16.tif tex-08.tif" << endl; return 1; } char *stlFile = argv[argBegin]; cout << "Using STL file: \"" << stlFile << "\"" << endl; //---------------------------------------- // create the mesh and give it the STL file //---------------------------------------- TxsMesh *mesh = new TxsMesh; int numTris = addStlToTxsMesh(*mesh, stlFile); mesh->doneFeedingTris(); __STAT__("STL file had " << numTris << " triangles"); __STAT__("mesh dimensions: " << mesh->getMaxs() - mesh->getMins()); //mesh.printVertStats(); // MAJOR HACK // TEMP TODO if(true) { if(strcmp(stlFile, "tetrus-0.stl") == 0) { __WARN__("converting tris to quads!!"); mesh->collapse_tris_into_quads_around_valence_4_verts(); if(true) { // TEMP // This code basically subdivides the tetrus once // sure is a lotta over head.. __STAT__("subdividing the tetrus once.."); CCS::Mesh toBeSubdivd; feedTxsMeshToCcsMesh(*mesh, toBeSubdivd); CCS::Mesh subdivd; toBeSubdivd.subdivide(subdivd, 1); // and feed back into a normal mesh object. __STAT__("putting subdiv'd teturs back into TxsMesh"); delete mesh; mesh = new TxsMesh; feedCcsMeshToTxsMesh(subdivd, *mesh); mesh->doneFeedingTris(); __STAT__("subdiv'd mesh dimensions: " << mesh->getMaxs() - mesh->getMins()); // write it out, for inspection __STAT__("writing subdiv'd teturs for inspection"); mesh->phongShadeAllFaces(); SlideWriter slfer; slfer.write("tetrus_after_1_subdiv", mesh); } } } //---------------------------------------- // read in the input pyramid //---------------------------------------- // first read in the biggest level to determine size int firstTiffArg = argBegin + 1; TiffImage finest(argv[firstTiffArg + NUM_PYLEVS - 1]); int finestSize = finest.getWidth(); __STAT__("highest input res: " << finestSize); // now create the pyramid TxsPyramid inPy(finestSize); // load each level // they're inputted in increasing order for(int lev = 0; lev < NUM_PYLEVS; ++lev) { char *filename = argv[firstTiffArg + lev]; inPy.getLevel(lev)->readFromTiff(filename); } //--------------------------------- // Go! //--------------------------------- // the multi-res algo synthTexturesMultiRes(*mesh, inPy); //--------------------------------- // Output! // First, just normal out //--------------------------------- SlideWriter slfer; slfer.write("out_mr", mesh); // write out other pyramid levels // This is now done in synthTexturesMultiRes // slfer.write("out_mr0", mesh, 0); // slfer.write("out_mr1", mesh, 1); // slfer.write("out_mr2", mesh, 2); //---------------------------------------- // now subdivide and output CCS::Mesh subA; __STAT__("adding tetrus to ccs mesh"); feedTxsMeshToCcsMesh(*mesh, subA); __STAT__("DONE adding tetrus to ccs mesh"); __STAT__("subdividing"); CCS::Mesh subB; subA.subdivide(subB, 2); __STAT__("DONE subdividing"); __STAT__("writing to SLF"); CCS::SlideWriter writer; writer.write("out_mr_subdiv3", &subB); // subdiv some more and displace CCS::Mesh subC; subB.subdivide(subC, 4); __STAT__("displacing.."); SimpleHeightFunc *hf = new SimpleHeightFunc(0.0030); subC.displaceVertsByTextures(hf); delete hf; __STAT__("DONE displacing"); // write finer displaced to CCS binary __STAT__("writing displaced subdiv'd to binary"); CCS::BinaryWriter binner; binner.write(&subC, "out_mr/very-fine-disp.ccs"); return 0; } int txsMain(int argc, char **argv) { char *algo = argv[1]; if(strcmp(algo, "mr") == 0) { return runMultiRes(argc, argv, 2); } else if(strcmp(algo, "sr") == 0) { return runSingleRes(argc, argv, 2); } else if(strcmp(algo, "unit_tests") == 0) { run_all_unit_tests(); return 0; } else if(strcmp(algo, "test_relax") == 0) { return test_relax_proc(argc, argv); } // test cases else if(strcmp(algo, "test_quads") == 0) { cout << "running quad test" << endl; test_quadSynthesis(); return 0; } else if(strcmp(algo, "test_tris2quads") == 0) { cout << "running tri->quad test" << endl; //test_tris2quads_weird(); test_tris2quads(); return 0; } else if(strcmp(algo, "test_tris2quads_tetrus") == 0) { cout << "running tri->quad test" << endl; test_tris2quads_tetrus(); return 0; } else if(strcmp(algo, "test_CCS_input") == 0) { test_CCS_input(); return 0; } else if(strcmp(algo, "test_tetrus_subdiv") == 0) { test_tetrus_subdiv(); return 0; } else if(strcmp(algo, "test_quadCube_synth_subdiv") == 0) { test_quadCube_synth_subdiv(); return 0; } else { __ERROR__("Invalid algorithm specified as first arg: " << algo); return 1; } } int main(int argc, char **argv) { cout << "Compile time: " << get_time_tag() << endl; init_logging(); // run test cases here //test_multires_pyramid_search(); //return 0; // TEMP //__LOG__("Testing tiff's"); //TiffImage img("by-pat-64.tif"); //img.writeToTiff("test.tif"); return txsMain(argc, argv); }