Manta Interactive Ray Tracer Development Mailing List

Text archives Help


[MANTA] r910 - in trunk/fox/afr_demo: . Engine/ImageTraversers StandAlone


Chronological Thread 
  • 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.

Top of page