Text archives Help
- From: abhinav@sci.utah.edu
- To: manta@sci.utah.edu
- Subject: [MANTA] r910 - in trunk/fox/afr_demo: . Engine/ImageTraversers StandAlone
- Date: Wed, 8 Feb 2006 18:24:45 -0700 (MST)
Author: abhinav
Date: Wed Feb 8 18:24:45 2006
New Revision: 910
Added:
trunk/fox/afr_demo/Engine/ImageTraversers/EGSRImageTraverser.cc
trunk/fox/afr_demo/Engine/ImageTraversers/EGSRImageTraverser.h
Modified:
trunk/fox/afr_demo/CMakeLists.txt
trunk/fox/afr_demo/StandAlone/afr.cc
Log:
Added EGSR imagetraverser. This is the one that was used for EGSR 2005
publication.
Modified: trunk/fox/afr_demo/CMakeLists.txt
==============================================================================
--- trunk/fox/afr_demo/CMakeLists.txt (original)
+++ trunk/fox/afr_demo/CMakeLists.txt Wed Feb 8 18:24:45 2006
@@ -32,6 +32,8 @@
Engine/ImageTraversers/STAFRImageTraverser.h
Engine/ImageTraversers/AFImageTraverser.cc
Engine/ImageTraversers/AFImageTraverser.h
+ Engine/ImageTraversers/EGSRImageTraverser.cc
+ Engine/ImageTraversers/EGSRImageTraverser.h
# Model
Model/Cameras/AfrPinholeCamera.cc
Model/Cameras/AfrPinholeCamera.h
Added: trunk/fox/afr_demo/Engine/ImageTraversers/EGSRImageTraverser.cc
==============================================================================
--- (empty file)
+++ trunk/fox/afr_demo/Engine/ImageTraversers/EGSRImageTraverser.cc Wed
Feb 8 18:24:45 2006
@@ -0,0 +1,759 @@
+//
+// C++ Implementation: EGSRImageTraverser
+//
+// Description:
+//
+//
+// Author: Abhinav Dayal <abhinav@cs.northwestern.edu>, (C) 2005
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include <Engine/ImageTraversers/EGSRImageTraverser.h>
+#include <Interface/RayPacket.h>
+#include <Interface/Renderer.h>
+#include <Interface/Context.h>
+#include <Interface/Fragment.h>
+#include <Model/Cameras/AfrPinholeCamera.h>
+#include <Interface/Image.h>
+#include <Interface/LoadBalancer.h>
+#include <Interface/PixelSampler.h>
+#include <Core/Exceptions/IllegalArgument.h>
+#include <Core/Exceptions/IllegalValue.h>
+#include <Core/Exceptions/InternalError.h>
+#include <Core/Util/Args.h>
+#include <Core/Util/NotFinished.h>
+#include <Core/Thread/Mutex.h>
+#include <Core/XUtils/XHelper.h>
+#include <Interface/Fragment.h>
+
+#include <SCIRun/Core/Thread/Time.h>
+#include <cmath>
+
+#ifdef __sgi
+#include <ieeefp.h>
+#endif
+
+#include <GL/glu.h>
+
+#define MAX_MIN_RATIO 0.5
+#define MAX_MERGE_SPLIT_LIMIT 50
+
+using namespace std;
+using namespace Manta;
+using namespace Manta::Afr;
+
+using SCIRun::IllegalValue;
+using SCIRun::InternalError;
+
+using namespace std;
+
+// args are the command line options, if the user wants to pas to th
+// eimage traverser look in TiledimageTraverser.cc for usage
+ImageTraverser* EGSRImageTraverser::create(const vector<string>& args)
+{
+ return new EGSRImageTraverser(args);
+}
+
+EGSRImageTraverser::EGSRImageTraverser(const vector<string>& args) :
+
+ AFRImageTraverser( args ),
+
+ myRandomNumber( 0 ),
+ inner_loop_time( 0.066666667 ),
+ chunk_size( 256 ),
+ samplingrate( 400000 ),
+ outputStreams( false ),
+ spatialCoherence( false ),
+ outputstats( false ),
+ dbDepth ( 4 ),
+ numReproj ( 5 )
+ //streamlock( "streamlock" ),
+{
+
+ for (int i=0;i<args.size();++i) {
+ if (args[i] == "-inner") {
+ if (!getArg( i, args, inner_loop_time )) {
+ throw IllegalArgument("-inner <Real>", i, args);
+ }
+ }
+ if (args[i] == "-chunk") {
+ if (!getArg( i, args, chunk_size )) {
+ throw IllegalArgument("-chunk <Int>", i, args);
+ }
+ }
+ if (args[i] == "-samplingrate") {
+ if (!getArg( i, args, samplingrate )) {
+ throw IllegalArgument("-samplingrate <Int>", i, args);
+ }
+ }
+ if (args[i] == "-depth") {
+ if (!getArg( i, args, dbDepth )) {
+ throw IllegalArgument("-depth <Int>", i, args);
+ }
+ }
+ if (args[i] == "-reproj") {
+ if (!getArg( i, args, numReproj)) {
+ throw IllegalArgument("-reproj <Int>", i, args);
+ }
+ }
+ if (args[i] == "-stream") {
+ if (!getArg( i, args, streamfilename )) {
+ throw IllegalArgument("-streamfilename <string>", i, args);
+ }
+ outputStreams = true;
+ }
+ if (args[i] == "-spatial") {
+ spatialCoherence = true;
+ }
+ if (args[i] == "-stats") {
+ outputstats = true;
+ }
+ }
+}
+
+EGSRImageTraverser::~EGSRImageTraverser()
+{
+ if(myRandomNumber!=NULL) delete [] myRandomNumber;
+ // free the kdtree and queues. I suppose this will be done automatically
+ // confirm!
+}
+
+// This factory method returns a context specific to this AFRImageTraverser
implementation.
+AFRImageTraverser::AFRContext *EGSRImageTraverser::contextFactory( int proc,
int numProc ) {
+
+ return new AFRContext;
+};
+
+void EGSRImageTraverser::setupBegin(SetupContext& context, int numChannels) {
+
+ if (context.proc == 0)
+ context.loadBalancer->setupBegin(context, numChannels);
+
+ //if (getDebugWindow()) {
+ // context.setMultipleGLWindows();
+ // getDebugWindow()->createStatsWin( context );
+ //}
+}
+
+#define DESIRED_FRAME_RATE 15
+void EGSRImageTraverser::initStreams(int xres, int yres)
+{ // print the version info
+ char fname[80];
+ time_t t;
+ time(&t);
+ //streamlock.lock();
+ for(int i=0; i<num_clients; i++)
+ {
+ sprintf(fname,"%s%03d",streamfilename.c_str(),i);
+ streamfile[i] = fopen(fname,"wb");
+ sprintf(fname,"%s_text%03d",streamfilename.c_str(),i);
+ textstreamfile[i] = fopen(fname,"w");
+ sprintf(fname,"%s_tiles%03d",streamfilename.c_str(),i);
+ tilestreamfile[i] = fopen(fname,"wb");
+ fprintf(textstreamfile[i], "Version 1.5\n");
+ fprintf(textstreamfile[i],"Created on: %s", ctime(&t));
+ // print the width and height
+ fprintf(textstreamfile[i],"width %d\n", xres);
+ fprintf(textstreamfile[i],"height %d\n", yres);
+ // print the simulated frame rate
+ fprintf(textstreamfile[i],"frame_rate %d\n",DESIRED_FRAME_RATE);
+ fprintf(textstreamfile[i],"END\n");
+ //streamlock.unlock();
+ cout << "initialized stream for client " << i << endl;
+ }
+}
+
+void EGSRImageTraverser::write_Tile_and_Camera(RenderContext& context,
double currenttime)
+{
+ //streamlock.lock();
+
+ if(!outputStreams) return;
+ int myID = context.proc;
+ fprintf(textstreamfile[myID],"\n\nbegin_tiles\n");
+
+ fprintf(textstreamfile[myID],"num_tiles
%d\n",kdtree[myID].number_of_tiles());
+ fprintf(textstreamfile[myID],"timestamp %f\n",(float)currenttime);
+ kdtree[myID].writeToFile(tilestreamfile[myID], (float)currenttime,
samplingrate);
+ // have flag for camera and dump the camera
+ fprintf(textstreamfile[myID],"\n\nbegin_camera\n");
+ // print camera to file
+ ((AFRPinholeCamera*)context.camera)->writeToFile(textstreamfile[myID]);
+}
+
+void EGSRImageTraverser::setupDisplayChannel(SetupContext& context) {
+
+ if (context.proc != 0)
+ return;
+ // Specify that the rendering pipeline should use only one image buffer.
+ //if (getDebugWindow()) {
+ // context.setMultipleGLWindows();
+ //}
+
+ context.constrainPipelineDepth(1,1); // single buffer mode is set here
+ bool stereo; // get whether it is stereo, (shoot two rays for left
+ // and right eye)
+ int i;
+ int xres,yres;
+ num_clients = context.numProcs;
+ cout << "samplingrate = " << samplingrate << endl;
+ // Samples done.
+#ifdef __ia64__
+ samples_done = (SamplesDone *)memalign( 128,
sizeof(SamplesDone)*num_clients );
+#else
+ samples_done = (SamplesDone *)malloc( sizeof(SamplesDone)*num_clients );
+#endif
+ memset( samples_done, 0x0, sizeof(SamplesDone)*num_clients );
+ initpass = new bool[num_clients];
+
+ // Per master performance timer.
+ tile_refresh = new double[num_clients];
+ last_time = new double[num_clients];
+
+ for (int i=0;i<num_clients;++i) {
+ tile_refresh[i] = 0.0;
+ last_time[i] = 0.0;
+ }
+
+ // this will change when we can actually simulate
+ context.getResolution(stereo, xres, yres);
+
+ cout << "context resolution is: " << xres << ", " << yres << endl;
+ //---------------------------------------------------------
+ // initialize random number generators for each thread.
+ //---------------------------------------------------------
+ myRandomNumber = new MT_RNG[context.numProcs];
+ for(i=0; i<context.numProcs; i++) {
+ myRandomNumber[i].seed_rng(1234*(i+1)); // just to begin give a simple
seed
+ }
+
+
/////////////////////////////////////////////////////////////////////////////
+ // Create a kdtree for each client.
+
+ //---------------------------------------------------------
+ // make our kdtree, given the resolution of image/channel
+ //---------------------------------------------------------
+ kdtree = new KDTree[num_clients];
+ db = new DeepBuffer[num_clients];
+ for(i=0; i<num_clients; i++)
+ {
+ // samples_done[i] = 0;
+ db[i].init(xres, yres,dbDepth);
+ initpass[i] = false;
+ kdtree[i].setAB(samplingrate);
+ kdtree[i].init(xres, yres, samplingrate, i, dbDepth); // initialize
the tree
+ }
+
+ // chunk_size = 256; // this is a fixed number as of now
+ occlusionSample = new Sample* [num_clients];
+ newSampleSet = new SampleSet* [num_clients];
+ reprojSampleSet = new SampleSet* [num_clients];
+ buffer = new Sample* [num_clients];
+ // find raypacket size and divide it by 5 to get xhairBlockSize
+ xhairBlockSize = RayPacket::MaxSize/5;
+ cout << "xhairBlockSize = " << xhairBlockSize << endl;
+ xhairBlockStart = new int [num_clients];
+ if(outputstats)
+ {
+ outputfile = new FILE* [num_clients];
+ timestatslastwritten = new float[num_clients];
+ }
+ // Initialize
+ for(i = 0; i<num_clients; i++)
+ {
+ // these are really overdimensioned I believe.
+ buffer[i] = new Sample [xres*yres];
+ occlusionSample[i] = new Sample [chunk_size*numReproj];
+ reprojSampleSet[i] = new SampleSet [chunk_size*numReproj];
+ newSampleSet[i] = new SampleSet [chunk_size];
+ xhairBlockStart[i] = -1;
+
+ for(int bx=0; bx<xres; bx++)
+ for(int by=0; by<yres; by++)
+ {
+ buffer[i][by*xres+bx].init((float)(bx+0.5),(float)(by+0.5), 0.0f);
+ }
+ if(outputstats)
+ {
+ char outname[32];
+ sprintf(outname, "dt_stats%03d.txt",i);
+ if((outputfile[i] = fopen(outname, "w"))==NULL)
+ {
+ cout << "cannot open " << outname << " for stats. Exiting ..." <<
endl;
+ exit(1);
+ }
+ timestatslastwritten[i] = 0.0f;
+ fprintf(outputfile[i]," Trace Rays Adjust
Tiles Update Stats Rates\n");
+ fprintf(outputfile[i],"currenttime time number time
number time number trace update adjust\n");
+ }
+ }
+ if(outputStreams)
+ {
+ spf = new SamplePrintFormat* [num_clients];
+ for(i=0; i<num_clients; i++)
+ {
+ spf[i] = new SamplePrintFormat[chunk_size*numReproj*5];
+ }
+ streamfile = (FILE**)malloc(num_clients*sizeof(FILE*));
+ tilestreamfile = (FILE**)malloc(num_clients*sizeof(FILE*));
+ textstreamfile = (FILE**)malloc(num_clients*sizeof(FILE*));
+ initStreams(xres, yres);
+ }
+}
+
+int EGSRImageTraverser::renderCrossHair(const RenderContext& context,
+ AFRContext *afr_context,
+ int myID,
+ Image *image, const int xres, const
int yres,
+ const int sscount, double currenttime,
bool endChunk)
+{
+ //cout << "now rendering xhair" << endl;
+ if(!endChunk)
+ {
+ int tindex = kdtree[myID].getRandomTile(myRandomNumber[myID]);
+ int cx, cy;
+ kdtree[myID].getRandomSamplefromTile(tindex, cx, cy,
myRandomNumber[myID]);
+ if(cx<0) cx = 0;
+ if(cx>=xres) cx = xres-1;
+ if(cy<0) cy = 0;
+ if(cy>=yres) cy = yres-1;
+ newSampleSet[myID][sscount].sample[TEMPORAL_SAMPLE] =
buffer[myID][cy*xres+cx];
+ }
+ if(!endChunk && (sscount - xhairBlockStart[myID])<xhairBlockSize) return 0;
+ int size = (sscount - xhairBlockStart[myID])*5;
+ if(size==0) return 0;
+ bool validinfo[RayPacket::MaxSize];
+ Real afr_begin = afr_context->beginTraceRays();
+ float t = (float)currenttime;
+ int flags = RayPacket::HaveImageCoordinates | RayPacket::ConstantEye;
+ int depth = 0;
+ RayPacketData raydata;
+ Fragment frag;
+ RayPacket rays(raydata, 0, size, depth, flags);
+ int i, j;
+ int start = xhairBlockStart[myID]+1;
+ const static double offset[5][2] = {
+ { 0.0, 0.0},
+ {-1.0, 0.0},
+ { 1.0, 0.0},
+ { 0.0,-1.0},
+ { 0.0, 1.0}
+ };
+ for(j=start; j<=sscount; j++) {
+ for(i=0; i<5; i++) {
+ double px, py;
+ if(xres > yres) // let the smaller dimension be mapped to [-1,1]
+ {
+ px = (double)(-1.0 +
2.0*(newSampleSet[myID][j].sample[TEMPORAL_SAMPLE].viewCoord[0]
+ + offset[i][0])/(double)yres);
+ py = (double)(-1.0 +
2.0*(newSampleSet[myID][j].sample[TEMPORAL_SAMPLE].viewCoord[1]
+ + offset[i][1])/(double)yres);
+ }
+ else
+ {
+ px = (double)(-1.0 +
2.0*(newSampleSet[myID][j].sample[TEMPORAL_SAMPLE].viewCoord[0]
+ + offset[i][0])/(double)xres);
+ py = (double)(-1.0 +
2.0*(newSampleSet[myID][j].sample[TEMPORAL_SAMPLE].viewCoord[1]
+ + offset[i][1])/(double)xres);
+ }
+
+ // Specify the pixel.
+ rays.setPixel((j-start)*5+i, 0, px, py);
+
frag.addElement((int)(newSampleSet[myID][j].sample[TEMPORAL_SAMPLE].viewCoord[0]
+ offset[i][0]),
+
(int)(newSampleSet[myID][j].sample[TEMPORAL_SAMPLE].viewCoord[1] +
offset[i][1]),
+ 0);
+ }
+ }
+
/////////////////////////////////////////////////////////////////////////////
+ // Trace the rays. The results will automatically go into the fragment
+ traceRays( context, afr_context, rays, xres, yres, validinfo );
+
+ afr_context->endTraceRays( afr_begin , size );
+
/////////////////////////////////////////////////////////////////////////////
+ // okay now copy from fragment to temporalQ
+ for(j=start; j<=sscount; j++) {
+ for(i=0; i<5; i++) {
+ int rayindex = (j-start)*5+i;
+ Color clr = rays.getColor(rayindex);
+ RGBColor tempcol = clr.convertRGB();
+ Point p = rays.getHitPosition(rayindex);
+ float nsx, nsy;
+ nsx = newSampleSet[myID][j].sample[TEMPORAL_SAMPLE].viewCoord[0] +
offset[i][0];
+ nsy = newSampleSet[myID][j].sample[TEMPORAL_SAMPLE].viewCoord[1] +
offset[i][1];
+ newSampleSet[myID][j].complete = true;
+ newSampleSet[myID][j].enableocclusion = false;
+ newSampleSet[myID][j].set( i, nsx, nsy, t, p.x(), p.y(),
p.z(),tempcol.r(), tempcol.g(), tempcol.b(), validinfo[(j-start)*5+i] );
+ frag.setColor(rayindex, clr);
+ }
+ newSampleSet[myID][j].computeGradients(t);
+ samples_done[myID].addFive();
+ }
+ image->set( frag );
+ //cout << "done one xhairBlock" << endl;
+ size = sscount-start+1;
+ xhairBlockStart[myID] = sscount;
+ return size;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Render all of samples in a fragment of the chunk.
+///////////////////////////////////////////////////////////////////////////////
+bool EGSRImageTraverser::reprojectsampleset(const RenderContext& context,
SampleSet *sp,
+ int xres, int yres, double
currenttime)
+{
+ int j;
+ Manta::Real px, py, pz;
+ bool sameloc=true;
+ for(j=0; j<5; j++)
+ {
+ px = sp->sample[j].worldCoord[0];
+ py = sp->sample[j].worldCoord[1];
+ pz = sp->sample[j].worldCoord[2];
+ //if the point is INF, no need to reproject as it will remain
the same
+#ifdef __sgi
+ if(finite(px) && finite(py) && finite(pz))
+#else
+ if(!isinf(px) && !isinf(py) && !isinf(pz))
+#endif
+ {
+ const Point p(px, py, pz);
+ Point rp;
+ rp = ((AFRPinholeCamera*)context.camera)->project(p);
+ if(fabsf(rp.x()*xres- sp->sample[j].viewCoord[0])>0.001)
sameloc=false;
+ if(fabsf(rp.y()*yres- sp->sample[j].viewCoord[1])>0.001)
sameloc=false;
+
+ sp->sample[j].viewCoord[0] = rp.x()*xres;
+ sp->sample[j].viewCoord[1] = rp.y()*yres;
+ sp->sample[j].viewCoord[2] = rp.z();
+ }
+ }
+ if(sameloc) return false;
+ sp->viewX = sp->sample[CENTER_SAMPLE].viewCoord[0];
+ sp->viewY = sp->sample[CENTER_SAMPLE].viewCoord[1];
+ sp->viewZ = sp->sample[CENTER_SAMPLE].viewCoord[2];
+ if(sp->viewX<xres && sp->viewX>=0 && sp->viewY<yres && sp->viewY>=0 &&
sp->viewZ<=1.0)
+ return true;
+ return false;
+}
+
+void EGSRImageTraverser::reprojectchunk(const RenderContext& context,
+ AFRContext *afr_context,
+ Image* image,
+ int xres, int yres, double currenttime)
+{
+ int flags = RayPacket::HaveImageCoordinates | RayPacket::ConstantEye;
+ int i,f,j;
+ int myID = context.proc;
+ float t = (float)currenttime;
+ Real afr_begin;
+ bool validinfo[RayPacket::MaxSize];
+ j = 0;
+ for(f=0;f<chunk_size; f++)
+ {
+ int tindex = kdtree[myID].getRandomTile(myRandomNumber[myID]);
+ int cx, cy, ox, oy;
+ SampleSet *s, ns;
+ for(i=0; i<numReproj; i++)
+ {
+ kdtree[myID].getRandomSamplefromTile(tindex, cx, cy,
myRandomNumber[myID]);
+ // get a sampleset from deepbuffer
+ if(cx<0) cx = 0;
+ if(cx>=xres) cx = xres-1;
+ if(cy<0) cy = 0;
+ if(cy>=yres) cy = yres-1;
+ s = db[myID].qDelete(cx, cy);
+
+ if(s!=NULL)
+ ns = *s;
+ //kdtree[myID].updateStatsDelSampleSet( s, t, samplingrate);
+
+ if(s==NULL || !reprojectsampleset(context, s, xres, yres,
currenttime)) continue;
+ // find the new reprojected location
+ // add it to reprojSampleSet
+ kdtree[myID].updateStatsDelEGSR( &ns, t, samplingrate, true);
+ reprojSampleSet[myID][j] = *s;
+ j++;
+ }
+ }
+ // now we will form occlusion rays, shoot rays,
+ // compute tgrads for thesereprojected xhairs
+ // and update the tree
+ for(f=0; f<j; f+=RayPacket::MaxSize)
+ {
+ int size = RayPacket::MaxSize;
+ if(size >= j-f)
+ size = j-f;
+ // Create a ray packet
+ int depth = 0;
+ RayPacketData raydata;
+ Fragment frag;
+ RayPacket rays(raydata, 0, size, depth, flags);
+ for(i=0; i<size; i++)
+ {
+ int fi = f+i;
+ occlusionSample[myID][fi].viewCoord[0] =
reprojSampleSet[myID][fi].sample[CENTER_SAMPLE].viewCoord[0];
+ occlusionSample[myID][fi].viewCoord[1] =
reprojSampleSet[myID][fi].sample[CENTER_SAMPLE].viewCoord[1];
+ // cout << "raytracing: " << cx << ", " << cy << endl;
+ occlusionSample[myID][fi].tileindex =
kdtree[myID].getTileforXY(occlusionSample[myID][fi].viewCoord[0],
+ occlusionSample[myID][fi].viewCoord[1]);
+ occlusionSample[myID][fi].t = t;
+ // normalized
+ double px, py;
+ if(xres>yres) // let the smaller dimension be mapped to [-1,1]
+ {
+ px = (double)(-1.0 +
2.0*((double)occlusionSample[myID][fi].viewCoord[0])/(double)yres);
+ py = (double)(-1.0 +
2.0*((double)occlusionSample[myID][fi].viewCoord[1])/(double)yres);
+ }
+ else
+ {
+ px = (double)(-1.0 +
2.0*((double)occlusionSample[myID][fi].viewCoord[0])/(double)xres);
+ py = (double)(-1.0 +
2.0*((double)occlusionSample[myID][fi].viewCoord[1])/(double)xres);
+ }
+ // samples_done[context.proc] ++;
+ samples_done[myID].addOne();
+ // Specify the position and color pointer for the packet element.
+ rays.setPixel(i, 0, px, py);
+ frag.addElement((int)(occlusionSample[myID][fi].viewCoord[0]),
(int)(occlusionSample[myID][fi].viewCoord[1]), 0);
+ }
+ afr_begin = afr_context->beginTraceRays();
+
//////////////////////////////////////////////////////////////////////////
+ // Trace the rays. The results will automatically go into the fragment
+ traceRays(context, afr_context, rays, xres, yres, validinfo);
+
+ afr_context->endTraceRays( afr_begin, size );
+
///////////////////////////////////////////////////////////////////////////
+ // okay now copy from fragment to temporalQ
+
+ for(i=0;i<size;i++) {
+
+ int fi = (f+i);
+ Color clr = rays.getColor(i);
+ RGBColor tempcol = clr.convertRGB();
+ occlusionSample[myID][fi].c[0] = tempcol.r();
+ occlusionSample[myID][fi].c[1] = tempcol.g();
+ occlusionSample[myID][fi].c[2] = tempcol.b();
+ Point p = rays.getHitPosition(i);
+ occlusionSample[myID][fi].worldCoord[0] = p.x();
+ occlusionSample[myID][fi].worldCoord[1] = p.y();
+ occlusionSample[myID][fi].worldCoord[2] = p.z();
+ occlusionSample[myID][fi].valid = validinfo[i];
+ // set the temporal sample of xhair to this sample
+ // and recompute the grads
+
buffer[myID][(int)occlusionSample[myID][fi].viewCoord[1]*xres+(int)occlusionSample[myID][fi].viewCoord[0]]
+ = occlusionSample[myID][fi];
+ reprojSampleSet[myID][fi].sample[TEMPORAL_SAMPLE] =
reprojSampleSet[myID][fi].sample[CENTER_SAMPLE];
+ reprojSampleSet[myID][fi].sample[CENTER_SAMPLE] =
occlusionSample[myID][fi];
+ reprojSampleSet[myID][fi].enableocclusion = true;
+ reprojSampleSet[myID][fi].complete = true;
+ reprojSampleSet[myID][fi].computeGradients(t);
+
reprojSampleSet[myID][fi].copymygrads_to_sample(occlusionSample[myID][fi]);
+ frag.setColor(i, clr);
+ }
+ image->set(frag);
+ }
+ if(outputStreams)
+ {
+ for(i=0;i<j;i++)
+ {
+
/////////////////////////////////////////////////////////////////////////////
+ // add sample to the corresponding file
+ //occlusionSample[myID][i].writeToFile(streamfile[myID]);
+ occlusionSample[myID][i].copySPF(&spf[myID][i]);
+ }
+ fwrite(spf[myID],sizeof(SamplePrintFormat), j, streamfile[myID]);
+ }
+ afr_begin = afr_context->beginUpdateStats();
+ for(i=0;i<j;i++)
+ {
+
/////////////////////////////////////////////////////////////////////////////
+ // add sampleset to the corresponding kdtree
+ kdtree[myID].updateStatsAddEGSR( &reprojSampleSet[myID][i], t,
samplingrate, true);
+ // add it to the new db location
+ if(db[myID].queueDepth((int)(reprojSampleSet[myID][i].viewX),
(int)(reprojSampleSet[myID][i].viewY))==dbDepth)
+ {
+ SampleSet *ds =
db[myID].qDelete((int)(reprojSampleSet[myID][i].viewX),
(int)(reprojSampleSet[myID][i].viewY));
+ kdtree[myID].updateStatsDelEGSR( ds, (float)currenttime,
samplingrate,false);
+ }
+ db[myID].qInsert((int)(reprojSampleSet[myID][i].viewX),
(int)(reprojSampleSet[myID][i].viewY),
+ &reprojSampleSet[myID][i]);
+ }
+ afr_context->endUpdateStats( afr_begin , j);
+}
+///////////////////////////////////////////////////////////////////////////////
+// This method implements the master thread functionality.
+///////////////////////////////////////////////////////////////////////////////
+void EGSRImageTraverser::masterTask(const RenderContext& context, AFRContext
*afr_context, Image* image, double currenttime) {
+
+ /* This should remain the same */
+ // update kdtree based on previous results from the client threads
+
+ // Every thread does both the master task and the client task,
+ // so there is no need to check.
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Determine the refresh rate.
+ double current_time = SCIRun::Time::currentSeconds();
+ tile_refresh[context.proc] = (current_time - last_time[context.proc]);
+ last_time[context.proc] = current_time;
+
+ bool stereo;
+ int xres, yres;
+ image->getResolution(stereo, xres, yres);
+ kdtree[context.proc].setAB(samplingrate);
+
+ //cout << "time (thread = " << context.proc << " ) is now " <<
chunkTimeStamp[context.proc] << endl;
+ // return during intialization here
+
+ if(initpass[context.proc]) {
+ Real afr_begin = afr_context->beginAdjustTiles();
+ // adjust tiles based on current status
+ adjustTiles(afr_context, context.proc, (float)currenttime);
+ afr_context->endAdjustTiles( afr_begin );
+ }
+ else if (samples_done[context.proc].load() >= (xres*yres*6)) {
+ initpass[context.proc] = true;
+ std::cerr << "Thread: " << context.proc << " initialized" << std::endl;
+ }
+
+ image->setValid( true );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// This method implements the master thread functionality.
+///////////////////////////////////////////////////////////////////////////////
+void EGSRImageTraverser::clientTask(const RenderContext& context, AFRContext
*afr_context, Image* image, double currenttime) {
+
+ /*
+ choose a random tile.
+ reproject numReproj samples at random locations
+ for this add a function that reprojects. This will require to shoot
occlusion rays.
+ for not omit deleting stats for samples that leave the tile, sonce we can
assume that weighting will take care of that reasonably well.
+ rather than using reprojected location queue sample, use the occlusion
test sample to compte tgrads and to add to tree
+
+ get another random location and schedule to make a crosshair there,
+ for tgrads use temporal sample as the sample in the end of queue at that
position in db
+ whenever needed update kdtree
+
+ so basically we have two arrays to fill
+ for chunk_size*numReproj xhairs, reproject and make a new sample at reproj
loc
+ store the xhairs in another array
+ in a separate array of chunk_size make that many xhairs
+ */
+ //cout << "inside clientThread for frametype " << frametype[context.proc]
<< endl;
+ bool stereo;
+ int xres, yres;
+ image->getResolution(stereo, xres, yres);
+ int myID = context.proc;
+ Sample s;
+ Real afr_begin;
+ // reproject the chunk
+ if(initpass[myID])
+ reprojectchunk(context, afr_context, image, xres, yres, currenttime);
+ int xhairRendered = 0;
+ // initialization is done so we can reproject one chunk worth
+ int i;
+ int sscount=0;
+ xhairBlockStart[myID] = -1;
+ Sample *sp;
+ //cout << "now making xhairs" << endl;
+ //int fsize = temporalQ[myID].getN()-qSize;
+ //for(i=0; i<fsize; i++)
+ //temporalQ[myID].qDelete(&myRandomNumber[myID]);
+ //cout << "fsize = " << fsize << endl;
+ //if(fsize <= 0)
+ for(i=0; i<chunk_size; i++)
+ {
+ xhairRendered += renderCrossHair(context, afr_context, myID, image,
xres, yres, sscount, currenttime);
+ sscount++;
+ }
+ xhairRendered += renderCrossHair(context, afr_context, myID, image, xres,
yres, sscount-1, currenttime, true);
+ // write to file
+ if(outputStreams)
+ for(i=0; i<xhairRendered; i++)
+ {
+ // write each sample one by one
+ newSampleSet[myID][i].writeToFile(streamfile[myID]);
+ }
+ afr_begin = afr_context->beginUpdateStats();
+ // add the sample to the corresponding kdtree
+ for(i=0; i<xhairRendered; i++)
+ {
+ kdtree[myID].updateStatsAddEGSR( &newSampleSet[myID][i],
(float)currenttime, samplingrate, false);
+
+ if(db[myID].queueDepth((int)newSampleSet[myID][i].viewX,
(int)newSampleSet[myID][i].viewY)==dbDepth)
+ {
+ SampleSet *s = db[myID].qDelete((int)newSampleSet[myID][i].viewX,
(int)newSampleSet[myID][i].viewY);
+ kdtree[myID].updateStatsDelEGSR( s, (float)currenttime,
samplingrate,false);
+ }
+ db[myID].qInsert((int)newSampleSet[myID][i].viewX,
(int)newSampleSet[myID][i].viewY, &newSampleSet[myID][i]);
+
buffer[myID][(int)newSampleSet[myID][i].viewY*xres+(int)newSampleSet[myID][i].viewX]
+ = newSampleSet[myID][i].sample[CENTER_SAMPLE];
+ }
+ afr_context->endUpdateStats( afr_begin , xhairRendered*5);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// This method adjusts the kdtree-cut by either merging nodes along the cut
+// or splitting nodes and adding their children to the cut.
+///////////////////////////////////////////////////////////////////////////////
+void EGSRImageTraverser::adjustTiles( AFRContext *afr_context, int id,
Timestamp currenttime)
+{
+ float minError, maxError;
+ int count;
+ int required_tiles = kdtree[id].getMaxTiles();
+ //cout << "minError = " << minError << ", maxError = " << maxError << endl;
+ if(kdtree[id].number_of_tiles()!=required_tiles)
+ {
+ do
+ {
+ while(kdtree[id].number_of_tiles()>required_tiles)
+ {
+ kdtree[id].merge(kdtree[id].getminErrorParentTile(), currenttime,
samplingrate);
+ //kdtree[id].consistencycheck();
+ }
+ while(kdtree[id].number_of_tiles()<required_tiles)
+ {
+ kdtree[id].split(kdtree[id].getmaxErrorTile(), currenttime,
samplingrate, &db[id]);
+ //kdtree[id].consistencycheck();
+ }
+ }
+ while(kdtree[id].number_of_tiles()!=required_tiles);
+ }
+ minError = kdtree[id].getminError();
+ maxError = kdtree[id].getmaxError();
+ //cout << "minError = " << minError << ", maxError = " << maxError << endl;
+ if(minError/maxError<MAX_MIN_RATIO)
+ {
+ count = 0;
+ do
+ {
+ count++;
+ kdtree[id].merge(kdtree[id].getminErrorParentTile(), currenttime,
samplingrate);
+ //kdtree[id].consistencycheck();
+ count++;
+ kdtree[id].split(kdtree[id].getmaxErrorTile(), currenttime,
samplingrate, &db[id]);
+ //kdtree[id].consistencycheck();
+ minError = kdtree[id].getminError();
+ maxError = kdtree[id].getmaxError();
+ //cout << "minError = " << minError << ", maxError = " << maxError <<
endl;
+ }
+ while(minError/maxError<MAX_MIN_RATIO && count<MAX_MERGE_SPLIT_LIMIT);
+ }
+}
+
+
+void EGSRImageTraverser::outputStats(int myID, AFRContext *afr_context)
+{
+ if(outputstats)
+ {
+ float t = SCIRun::Time::currentSeconds();
+ if((t-timestatslastwritten[myID])>=5.0f)
+ {
+ timestatslastwritten[myID] = t;
+ afr_context->writetofile(outputfile[myID], t);
+ fflush(outputfile[myID]);
+ }
+ }
+}
Added: trunk/fox/afr_demo/Engine/ImageTraversers/EGSRImageTraverser.h
==============================================================================
--- (empty file)
+++ trunk/fox/afr_demo/Engine/ImageTraversers/EGSRImageTraverser.h Wed
Feb 8 18:24:45 2006
@@ -0,0 +1,203 @@
+//
+// C++ Interface: EGSRImageTraverser
+//
+// Description:
+//
+//
+// Author: Abhinav Dayal <abhinav@cs.northwestern.edu>, (C) 2005
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef Manta_Engine_EGSRImageTraverser_h
+#define Manta_Engine_EGSRImageTraverser_h
+
+#include <SCIRun/Core/Thread/Time.h>
+#include <SCIRun/Core/Thread/Thread.h>
+
+#include <Engine/ImageTraversers/AFRImageTraverser.h>
+#include <Engine/ImageTraversers/AFRDebugWindow.h>
+
+
+#include <Interface/Fragment.h>
+#include <sgi_stl_warnings_off.h>
+#include <string>
+#include <vector>
+#include <sgi_stl_warnings_on.h>
+#include <Engine/ImageTraversers/AFR/kdtree.h>
+#include <Engine/ImageTraversers/AFR/CQ.h>
+#include <Engine/ImageTraversers/AFR/sample.h>
+#include <Engine/ImageTraversers/AFR/deepbuffer.h>
+
+
+
+#ifdef __ia64__
+#include <malloc.h>
+#include <ia64intrin.h>
+#endif
+
+namespace Manta {
+
+ using namespace std;
+
+ namespace Afr {
+ class EGSRImageTraverser : public AFRImageTraverser {
+
+ friend class AFRPipeline;
+
+ public:
+
+ EGSRImageTraverser(const vector<string>& args);
+ virtual ~EGSRImageTraverser();
+
+ // Context factory method.
+ virtual AFRContext *contextFactory( int proc, int numProc );
+
+ virtual void setupBegin(SetupContext&, int numChannels);
+ virtual void setupDisplayChannel(SetupContext&);
+
+ // Render a cross hair after initialization is complete.
+ int renderCrossHair(const RenderContext& context,
+ AFRContext *afr_context,
+ int myID,
+ Image *image, const int xres, const int yres,
+ const int sscount, double currenttime, bool
endChunk = false);
+
///////////////////////////////////////////////////////////////////////////////
+ bool reprojectsampleset(const RenderContext& context, SampleSet *sp,
+ int xres, int yres, double currenttime);
+ void reprojectchunk(const RenderContext& context,
+ AFRContext *afr_context,
+ Image* image,
+ int xres, int yres, double currenttime);
+
+ // All EGSRImageTraversers are both master and client.
+ virtual bool isMaster( int id ) { return true; };
+
+ // Master thread task.
+ void masterTask(const RenderContext& context, AFRContext
*afr_context, Image* image, double currenttime);
+
+ // Sampler/Renderer task.
+ void clientTask(const RenderContext& context, AFRContext
*afr_context, Image* image, double currenttime);
+
+ // Update kdtree-cut.
+ void adjustTiles(AFRContext *afr_context, int id, Timestamp
currenttime);
+
+ void createStatsWin();
+ void display_stats();
+ void toggleTileDisplayMode();
+ void initStreams(int xres, int yres);
+ void write_Tile_and_Camera(RenderContext& context, double
currenttime);
+ void outputStats(int myID, AFRContext *afr_context);
+ inline int setSamplingRate(unsigned int srate) {
+
+ static unsigned int numUpdates=0;
+ //cout << "srate = " << srate << endl;
+ float rate = (float)srate/(float)num_clients;
+ if(numUpdates==0)
+ samplingrate = (int)rate;
+ else
+ samplingrate = (int)(((float)samplingrate*numUpdates +
rate)/(float)(numUpdates+1));
+ numUpdates++;
+ }
+
+ // Accessors, used by AFRDebugWindow
+ inline int getSamplingRate() { return samplingrate;
};
+
+ inline KDTree *getKdtree( int client ) { return
&kdtree[client]; };
+
+ static ImageTraverser* create(const vector<string>& args);
+
+ private:
+ EGSRImageTraverser(const EGSRImageTraverser&);
+ EGSRImageTraverser& operator=(const EGSRImageTraverser&);
+ // Image kd-tree. per thread
+ KDTree *kdtree;
+ DeepBuffer *db; // deepbuffer, well lets us see how much memory this
will take
+ int dbDepth; // what is depth of deepbuffer
+ int numReproj; // how many samples to reproject per tile visit
+ // number of fragments a chunk is divided into. It is divided equally
amongst all clients
+ int numFragments;
+ bool outputStreams;
+ bool spatialCoherence;
+ string streamfilename;
+ FILE **streamfile, **tilestreamfile, **textstreamfile;
+ Sample **buffer;
+ Sample **occlusionSample;
+ SamplePrintFormat **spf;
+ SampleSet **reprojSampleSet, **newSampleSet;
+ int *xhairBlockStart;
+ int xhairBlockSize;
+ // Random number generator array??
+ MT_RNG *myRandomNumber;
+
+ // ??????????????
+ int num_clients;
+ int chunk_size;
+ int samplingrate;
+
+ // stats
+ bool outputstats;
+ FILE **outputfile;
+ float *timestatslastwritten;
+
/////////////////////////////////////////////////////////////////////////
+ // Samples done.
+ struct SamplesDone {
+ SamplesDone() : value (0) {};
+ unsigned int value;
+ unsigned int padding[31];
+#ifdef __ia64__
+ inline void addOne() { __fetchadd4_acq( &value, 1 ); };
+ inline void addFive() { addOne(); __fetchadd4_acq( &value, 4 ); };
+ inline unsigned int load() { return __ld4_acq( &value ); };
+#else
+ inline void addOne() { value++; };
+ inline void addFive() { value+=5; };
+ inline unsigned int load() { return value; };
+#endif
+ };
+ SamplesDone *samples_done;
+
+ bool *initpass;
+
+
/////////////////////////////////////////////////////////////////////////
+ // Arguments.
+ Real inner_loop_time;
+
+ // Per master performance timers.
+ double *tile_refresh;
+ double *last_time;
+
+ public:
+
+ // Sum up all of the samples done by all of the threads.
+ inline unsigned int getSamplesDone() {
+ unsigned int total = 0;
+ for (int i=0;i<num_clients;++i) {
+ total += samples_done[i].load();
+ }
+ return total;
+ };
+ inline int getNumThreads()
+ {
+ return num_clients;
+ }
+ inline bool allThreadsInitialized() {
+ bool all = true;
+ for (int i=0;(i<num_clients)&&all;++i) {
+ all = initpass[i] && all;
+ }
+
+ return all;
+ }
+
+ virtual double getInnerLoopTime() { return inner_loop_time; };
+ virtual double getTileRefresh( int client_id ) { return
tile_refresh[client_id]; };
+
+ };
+
+ };
+
+};
+
+#endif
Modified: trunk/fox/afr_demo/StandAlone/afr.cc
==============================================================================
--- trunk/fox/afr_demo/StandAlone/afr.cc (original)
+++ trunk/fox/afr_demo/StandAlone/afr.cc Wed Feb 8 18:24:45 2006
@@ -43,6 +43,7 @@
#include <Core/Thread/Time.h>
#include <Engine/ImageTraversers/GSTAFRImageTraverser.h>
+#include <Engine/ImageTraversers/EGSRImageTraverser.h>
#include <Engine/ImageTraversers/STAFRImageTraverser.h>
#include <Engine/ImageTraversers/GSTAFRImageTraverserNew.h>
#include <Engine/ImageTraversers/AFImageTraverser.h>
@@ -465,6 +466,9 @@
}
else if (name == "stafr") {
rtrt->setImageTraverser( STAFRImageTraverser::create( args ) );
+ }
+ else if (name == "egsr") {
+ rtrt->setImageTraverser( EGSRImageTraverser::create( args ) );
}
// Otherwise attempt to load a default image traverser from manta.
else {
- [MANTA] r910 - in trunk/fox/afr_demo: . Engine/ImageTraversers StandAlone, abhinav, 02/08/2006
Archive powered by MHonArc 2.6.16.