// EvalStats.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include #include #include #include #include #include #include using namespace std; /** This is a small function which takes two log files and computes the difference in percent of the weighted render cost. */ struct RenderStats { float mRenderCost; float mAvgRenderCost; }; typedef vector StatsContainer; enum {NO_TAG, RENDER_COST, AVG_RENDER_COST}; bool extractRenderStats(ifstream &file, StatsContainer &renderStats) { if (!file.is_open()) return false; string buf; int currentTag = NO_TAG; while (!(getline(file, buf)).eof()) { //cout << "buf: " << buf << endl; if (buf[0] == '#') { char entry[50]; sscanf(buf.c_str(), "#%s", entry); // new entry if (strcmp(entry, "Pass") == 0) { //cout << "\nnew render stat " << endl; renderStats.push_back(RenderStats()); } else if (strcmp(entry, "TotalRenderCost") == 0) { currentTag = RENDER_COST; } else if (strcmp(entry, "AvgRenderCost") == 0) { currentTag = AVG_RENDER_COST; } } else { float val; sscanf(buf.c_str(), "%f", &val); switch (currentTag) { case RENDER_COST: //cout << "render cost: " << val << endl; renderStats.back().mRenderCost = val; break; case AVG_RENDER_COST: //cout << "avg render cost: " << val << endl; renderStats.back().mAvgRenderCost = val; break; default: break; } currentTag = NO_TAG; } } return true; } void ComputeStats(ofstream &statsOut, const RenderStats &firstStats, const RenderStats ¤tStats, const int index) { float denom = firstStats.mRenderCost ? firstStats.mRenderCost : 0.000001f; float costRatio = currentStats.mRenderCost / denom; denom = firstStats.mAvgRenderCost ? firstStats.mAvgRenderCost : 0.000001f; float avgCostRatio = currentStats.mAvgRenderCost / denom; statsOut << "#ViewCells\n" << index + 1 << endl << "#TotalRenderCostRatio\n" << costRatio << endl << "#AvgRenderCostRatio\n" << avgCostRatio << endl << endl; } inline bool vlt(const RenderStats &c1, const RenderStats &c2) { return c1.mRenderCost > c2.mRenderCost; } // evaluate number of view cells needed for same rendercost void EvalNumViewCells(ofstream &outstream, const StatsContainer &firstStats, const StatsContainer ¤tStats) { const int n = min((int)firstStats.size(), (int)currentStats.size()); //const int n = (int)firstStats.size(); StatsContainer::const_iterator it, it_end = currentStats.end(); int i = 0; // currentStats would be the other (necessarily worse?) method, firstStats would be our method // loop through view cells of currentStats // Compare render cost with render cost of other view cell // compute ratio of view cells for (it = currentStats.begin(); it != it_end; ++ it, ++ i) { const float renderCost = (*it).mRenderCost; // find equivalent render cost in the other stats container. // don't stop until cursor is placed one element behind // or end of vector is reached StatsContainer::const_iterator equalCostIt = std::upper_bound(firstStats.begin(), firstStats.end(), *it, vlt); int j = (int)(equalCostIt - firstStats.begin()); float val; // special cases if (j == 0) { val = (float)j; } else if (j >= n) { val = (float)(j - 1); } else // interpolate linearly. NOTE: probably big error because of steep curve // => intepolate logarithmically { #if 1 const float rcu = log(firstStats[j - 1].mRenderCost); const float rcl = log(firstStats[j].mRenderCost); const float rc = log(renderCost); #else const float rcu = firstStats[j - 1].mRenderCost; const float rcl = firstStats[j].mRenderCost; const float rc = renderCost; #endif const float factor = (rcu - rcl != 0) ? (rcu - rc) / (rcu - rcl) : 1; // view cells needed for same render cost val = (float)j - 1 + factor; } float ratio = (i && val) ? (float)i / val : 1; outstream << "#Pass\n" << i << endl; outstream << "#RenderCost\n" << renderCost << endl; outstream << "#ViewCellsRatio\n" << ratio << endl << endl; } } // evaluate number of view cells needed for same rendercost int EvalSingleNumViewCells(const StatsContainer ¤tStats, const float cost) { StatsContainer::const_iterator it, it_end = currentStats.end(); RenderStats dummy; dummy.mRenderCost = cost; // find equivalent render cost in the other stats container. // don't stop until cursor is placed one element behind // or end of vector is reached StatsContainer::const_iterator equalCostIt = std::upper_bound(currentStats.begin(),currentStats.end(), dummy, vlt); int j = (int)(equalCostIt - currentStats.begin()); return j; } int _tmain(int argc, _TCHAR* argv[]) { vector renderStats; if (argc < 3) { cerr << "arguments missing. Usage: input1 input2 ... intputn" << endl; exit(1); } vector outFilenames; vector outFilenames2; vector methodnames; // read input files from command line for (int i = 1; i < argc; ++ i) { StatsContainer currentStats; ifstream file; file.open(argv[i]); // extract the render cost cout << "extracting render cost of file " << argv[i] << endl; if (extractRenderStats(file, currentStats)) { renderStats.push_back(currentStats); // create output file name string fn = argv[i]; string::size_type pos = fn.find(".log", 0); fn.erase(pos, 4); //sscanf(argv[i], "%s.log", fn); string outFilename = string(fn) + string("-ratio.log"); string outFilename2 = string(fn) + string("-reverse.log"); outFilenames.push_back(outFilename); outFilenames2.push_back(outFilename2); methodnames.push_back(fn); cout << "new filen: " << outFilename2 << endl; } else { cout << "could not open file!" << endl; } } //statsOut << "rc1 size: " << (int)renderCosts1.size() << " " << (int)renderCosts2.size() << endl << endl; vector::const_iterator it = renderStats.begin(), it_end = renderStats.end(); vector::const_iterator sit, sit_end = outFilenames.end(); vector::const_iterator sit2, sit2_end = outFilenames2.end(); vector::const_iterator sit3, sit3_end = methodnames.end(); sit = outFilenames.begin(); sit2 = outFilenames2.begin(); sit3 = methodnames.begin(); // compare all values with this vector StatsContainer &firstStats = renderStats[0]; // don't compare with itself //++ it; //++ sit; ofstream statsOut3; statsOut3.open("numviewcells.log"); for (it; it != it_end; ++ it, ++ sit, ++ sit2, ++sit3) { cout << "now writing output to file " << *sit << endl; ofstream statsOut; statsOut.open((*sit).c_str()); ofstream statsOut2; statsOut2.open((*sit2).c_str()); cout << "opening new file: " << (*sit2).c_str() << endl; // compute size of output vector const int n = min((int)firstStats.size(), (int)(*it).size()); for (int i = 0; i < n; ++ i) { //cout << "rc: " << (*it)[i].mRenderCost << endl; ComputeStats(statsOut, firstStats[i], (*it)[i], i); } // evaluate number of view cells needed for same rendercost EvalNumViewCells(statsOut2, firstStats, (*it)); const float rendercost = 100; const int j = EvalSingleNumViewCells(*it, rendercost); statsOut3 << (*sit3).c_str() << " " << j << endl; statsOut.close(); statsOut2.close(); } statsOut3.close(); return 0; }