#include #include #include #include #include #include using namespace std; #include "Heartbeat.h" #include "txs_globals.h" #include "txs_algo.h" // global variable - nhood size. usually should be 17 int SR_NHOOD_PIXELS; static int accumAllFinestPixLocs(vector &out, TxsMesh &mesh) { Heartbeat hb; list faces = mesh.getFaces(); int num = 0; int faceI = 0; list::iterator fit; for(fit = faces.begin(); fit != faces.end(); ++fit) { TxsFace* f = *fit; num += f->accumFinestPixelLocns(out); if(hb.OK_to_beat()) { cout << "accum'ing pixel locns " << (double)faceI/(double)faces.size()*100 << "% done" << endl; } faceI++; } return num; } static void synthPixelValue(pixelLocn &p, TiffImage &img) { //__DBa("begin SPC for PL " << &p); // all the faces that our nhood patch could possibly need // ie. the incident face, and its immediate nbors TxsFace* face = p.face; // note that this is a reference list &faces = face->getImmediateNbors(); int finestLevel = face->getPyramid()->finestLevel(); // set up the neighborhood patch NhoodPatch_s nhood; nhood.setTo(p, UNITS_PER_PIXEL, SR_NHOOD_PIXELS); bool someNoHits = false; TiffImage nhoodImg(SR_NHOOD_PIXELS, SR_NHOOD_PIXELS); // go along the nborhood grid.. for(int gx = 0; gx < SR_NHOOD_PIXELS; ++gx) { for(int gy = 0; gy < SR_NHOOD_PIXELS; ++gy) { Point gridPt = nhood.getSquareCenter(gx, gy); // shoot perp ray into faces // try em all NormRGB hitRgb; bool hit = getHitRgb(faces, gridPt, nhood.normal, finestLevel, hitRgb); if(!hit) { /* __LOG__("not hit for grid pt:"); __LOG__(" " << gridPt); __LOG__(" " << " pointed towards "); __LOG__(" " << (gridPt+gridNorm)); __LOG__(" number of faces in set: " << faces.size()); */ someNoHits = true; g_numNhoodRaysMissed++; } nhoodImg.setRGB(gx, gy, hitRgb); } } // TEMP DEBUG /* if(someNoHits) { char filename[64]; sprintf(filename, "nhood_debug/%d.tif", rand()); nhoodImg.writeToTiff(filename); } */ // now we have nhood // find best match in sample img // tell it to ignore the middle pixel const int midOfs = (SR_NHOOD_PIXELS - 1) / 2; int mx = -1; int my = -1; img.getBestMatchingRegion(nhoodImg, mx, my, midOfs); // set p's color using the middle pixel //__LOG__("midOfs is " << midOfs << " BMR is " << mx << " " << my); NormRGB bestMatch = img.getRGB(mx + midOfs, my + midOfs); p.setRGB(bestMatch); // TEMP DEBUG // using the phong-shaded normal to determine color.. // do simple lighting /* Vector sunDir(0, 0, -1); double light = max(0.0, -1.0 * sunDir.Dot(gridNorm)); p.setRGB(NormRGB(light, light, light)); */ } // unused right now static void performSynthPass(vector &pixLocs, TiffImage &img) { double startTime = clock(); __STAT__("starting pass 2"); int numPixLocs = pixLocs.size(); knuth_shuffle(pixLocs); Heartbeat hb(3); int counter = 0; vector::iterator pit; for(pit = pixLocs.begin(); pit != pixLocs.end(); ++pit) { pixelLocn loc = *pit; synthPixelValue(loc, img); if(hb.OK_to_beat()) { cout << "synthesized " << counter << " of " << numPixLocs << " pixels. " << (double)counter/(double)numPixLocs*100 << "% done." << endl; cout << " elapsed seconds: " << (clock() - startTime)/1000 << endl; } counter++; } cout << "DONE synthesis.." << endl; double endTime = clock(); __LOG__("total run time: " << (endTime - startTime)/1000.0 << " seconds for " << numPixLocs << " pixel locations."); __LOG__("number of nhood rays that didn't hit anything: " << g_numNhoodRaysMissed); } /* * the algo without pyramids * we randomly visit and relax in multiple passes (3's usually good) */ void synthTexturesSingleRes(TxsMesh &mesh, TiffImage &img) { // front matter.. unsigned int seed = (unsigned int)time(NULL); srand(seed); __LOG__("Rand seed: " << seed); // get all pixel locations and shuffle them vector pixLocs; int numPixLocs = accumAllFinestPixLocs(pixLocs, mesh); __LOG__("Accum'd " << numPixLocs << " pixels. Shuffling.."); knuth_shuffle(pixLocs); __LOG__("shuffled."); // go thru each pixel loc and set it to a // random color vector::iterator pit; for(pit = pixLocs.begin(); pit != pixLocs.end(); ++pit) { pixelLocn loc = *pit; loc.setRGB(randomRgb()); } cout << "Begin synthesis pass 1.." << endl; double startTime = clock(); // now do the synth process for each pixel Heartbeat hb(3); int counter = 0; for(pit = pixLocs.begin(); pit != pixLocs.end(); ++pit) { pixelLocn loc = *pit; synthPixelValue(loc, img); if(hb.OK_to_beat()) { cout << "synthesized " << counter << " of " << numPixLocs << " pixels. " << (double)counter/(double)numPixLocs*100 << "% done." << endl; cout << " elapsed seconds: " << (clock() - startTime)/1000 << endl; } counter++; } __STAT__("starting pass 2"); knuth_shuffle(pixLocs); counter = 0; for(pit = pixLocs.begin(); pit != pixLocs.end(); ++pit) { pixelLocn loc = *pit; synthPixelValue(loc, img); if(hb.OK_to_beat()) { cout << "synthesized " << counter << " of " << numPixLocs << " pixels. " << (double)counter/(double)numPixLocs*100 << "% done." << endl; cout << " elapsed seconds: " << (clock() - startTime)/1000 << endl; } counter++; } __STAT__("starting pass 3"); knuth_shuffle(pixLocs); counter = 0; for(pit = pixLocs.begin(); pit != pixLocs.end(); ++pit) { pixelLocn loc = *pit; synthPixelValue(loc, img); if(hb.OK_to_beat()) { cout << "synthesized " << counter << " of " << numPixLocs << " pixels. " << (double)counter/(double)numPixLocs*100 << "% done." << endl; cout << " elapsed seconds: " << (clock() - startTime)/1000 << endl; } counter++; } /* __STAT__("starting pass 4"); knuth_shuffle(pixLocs); counter = 0; for(pit = pixLocs.begin(); pit != pixLocs.end(); ++pit) { pixelLocn loc = *pit; synthPixelValue(loc, img); if(hb.OK_to_beat()) { cout << "synthesized " << counter << " of " << numPixLocs << " pixels. " << (double)counter/(double)numPixLocs*100 << "% done." << endl; cout << " elapsed seconds: " << (clock() - startTime)/1000 << endl; } counter++; } */ cout << "DONE synthesis.." << endl; double endTime = clock(); __LOG__("total run time: " << (endTime - startTime)/1000.0 << " seconds for " << numPixLocs << " pixel locations."); __LOG__("number of nhood rays that didn't hit anything: " << g_numNhoodRaysMissed); }