#include #include #include #include #include #include using namespace std; #include "Heartbeat.h" #include "txs_globals.h" #include "txs_algo.h" void getProgressStats(int done, int total, double startClk, double &remainingSecs, double &elapsedSecs, double &percentageDone) { percentageDone = (double)done/(double)total * 100; elapsedSecs = (clock() - startClk) / 1000.0; double secsPerPercent = elapsedSecs / percentageDone; remainingSecs = (100 - percentageDone) * secsPerPercent; } void statProgress(int done, int total, double startClk) { double remSecs, elapsedSecs, percDone; getProgressStats(done, total, startClk, remSecs, elapsedSecs, percDone); __STAT__("-- completed " << done << "/" << total << " pixels (" << percDone << "%) "); __STAT__("---- elapsed secs: " << elapsedSecs << " remaining secs: " << remSecs); } void fillPixelsWithRandomColors(vector &pixLocs) { vector::iterator pit; for(pit = pixLocs.begin(); pit != pixLocs.end(); ++pit) { pixelLocn loc = *pit; loc.setRGB(randomRgb()); } } void perform2LevPyraRandomRelaxPass(vector &pixLocs, TxsPyramid &inPy) { // first, shuffle them knuth_shuffle(pixLocs); // go! int counter = 0; int numPixLocs = pixLocs.size(); double startClk = clock(); Heartbeat hb(3); vector::iterator pit; for(pit = pixLocs.begin(); pit != pixLocs.end(); ++pit) { pixelLocn loc = *pit; // do the big search.. setToClosestUsing2LevPyramid(loc, inPy); if(hb.OK_to_beat()) { double remSecs, elapsedSecs, percDone; getProgressStats(counter, numPixLocs, startClk, remSecs, elapsedSecs, percDone); __STAT__("-- relaxed " << counter << "/" << numPixLocs << " pixels (" << percDone << "%) "); __STAT__("---- elapsed secs: " << elapsedSecs << " remaining secs: " << remSecs); } counter++; } } /* * This algorithm uses multiple res's, but performs random relaxation * multiple times for each level. * Basically, it replaces pass 1 with random noise assignment, * and performs pass 2 multiple times. */ void performMultiResRelaxTextureSynth(TxsMesh &mesh, TxsPyramid &inPy) { __STAT__("BEGIN multi res relaxation synth algo"); // seed unsigned int seed = (unsigned int)time(NULL); srand(seed); __LOG__("Rand seed: " << seed); // accumulate pixel locs for each level vector*> pixLocLevels; int numPixLocs = accumPixelLocsForAllLevels(pixLocLevels, mesh); // fill the lowest with random pixels from the full-res image // maybe don't do this? maybe use the same rand-relax procedure for lowest level? fillPixelsWithRandomImageRGBs(*pixLocLevels[0], *inPy.getFinestLevel()); // now, go through each non-0 level and run rand/relax synthesis __STAT__("Begin synthesis for " << numPixLocs << " pixels.."); double startClk = clock(); int counter = 0; int finestLev = getFinestLevel(mesh); int lev = 0; for(lev = 1; lev <= finestLev; ++lev) { vector *pixLocs = pixLocLevels[lev]; __STAT__("BEGIN synth'ing level " << lev); fillPixelsWithRandomColors(*pixLocs); __STAT__(" BEGIN relax pass 1"); perform2LevPyraRandomRelaxPass(*pixLocs, inPy); __STAT__(" END relax pass 1"); __STAT__(" BEGIN relax pass 2"); perform2LevPyraRandomRelaxPass(*pixLocs, inPy); __STAT__(" END relax pass 2"); __STAT__("END synth'ing level " << lev); } // done! __STAT__("DONE synthesis.."); double endClk = clock(); __STAT__("total synthesis time: " << (endClk - startClk)/1000.0 << " seconds for " << numPixLocs << " pixel locations."); __STAT__("number of nhood rays that didn't hit anything: " << g_numNhoodRaysMissed); // All done. Delete the pixel location lists vector*>::iterator itr; for(itr = pixLocLevels.begin(); itr != pixLocLevels.end(); ++itr) { vector* pixLocs = *itr; delete pixLocs; } }