Manta Interactive Ray Tracer Development Mailing List

Text archives Help


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


Chronological Thread 
  • From: abhinav@sci.utah.edu
  • To: manta@sci.utah.edu
  • Subject: [MANTA] r908 - in trunk/fox/afr_demo: . Engine/ImageTraversers StandAlone
  • Date: Wed, 8 Feb 2006 17:59:11 -0700 (MST)

Author: abhinav
Date: Wed Feb  8 17:59:11 2006
New Revision: 908

Added:
   trunk/fox/afr_demo/Engine/ImageTraversers/AFImageTraverser.cc
   trunk/fox/afr_demo/Engine/ImageTraversers/AFImageTraverser.h
Modified:
   trunk/fox/afr_demo/CMakeLists.txt
   trunk/fox/afr_demo/StandAlone/afr.cc
Log:
added the first imagetraverser afr, that makes separate kdtree for each 
thread using old crosshair pattern.



Modified: trunk/fox/afr_demo/CMakeLists.txt
==============================================================================
--- trunk/fox/afr_demo/CMakeLists.txt   (original)
+++ trunk/fox/afr_demo/CMakeLists.txt   Wed Feb  8 17:59:11 2006
@@ -28,7 +28,8 @@
     Engine/ImageTraversers/GSTAFRImageTraverserNew.h
     Engine/ImageTraversers/GSTAFRImageTraverser.h
     Engine/ImageTraversers/AFRImageTraverser.h
-
+    Engine/ImageTraversers/AFImageTraverser.cc
+    Engine/ImageTraversers/AFImageTraverser.h
     # Model
     Model/Cameras/AfrPinholeCamera.cc
     Model/Cameras/AfrPinholeCamera.h

Added: trunk/fox/afr_demo/Engine/ImageTraversers/AFImageTraverser.cc
==============================================================================
--- (empty file)
+++ trunk/fox/afr_demo/Engine/ImageTraversers/AFImageTraverser.cc       Wed 
Feb  8 17:59:11 2006
@@ -0,0 +1,789 @@
+
+#include <Engine/ImageTraversers/AFImageTraverser.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 256
+
+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* AFImageTraverser::create(const vector<string>& args)
+{
+  return new AFImageTraverser(args);
+}
+
+AFImageTraverser::AFImageTraverser(const vector<string>& args) :
+
+  AFRImageTraverser( args ),
+  
+  myRandomNumber( 0 ),
+  //inner_loop_time( 0.016666667 ),
+  inner_loop_time( 0.016666667 ),
+  chunk_size( 256 ),
+  samplingrate( 400000 ),
+  outputStreams( false ),
+  spatialCoherence( false ),
+  sourcetgrads( false ),
+  afterupdateonly( false ),
+  outputstats( false )
+  //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);
+      }
+    }
+    else if (args[i] == "-chunk") {
+      if (!getArg( i, args, chunk_size )) {
+        throw IllegalArgument("-chunk <Int>", i, args);
+      }
+    }
+    else if (args[i] == "-samplingrate") {
+      if (!getArg( i, args, samplingrate )) {
+        throw IllegalArgument("-samplingrate <Int>", i, args);
+      }
+    }
+    else if (args[i] == "-stream") {
+      if (!getArg( i, args, streamfilename )) {
+        throw IllegalArgument("-streamfilename <string>", i, args);
+      }
+      outputStreams = true;
+    }
+    else if (args[i] == "-spatial") {
+      spatialCoherence = true;
+    }
+    else if (args[i] == "-stats") {
+      outputstats = true;
+    }
+    else if (args[i] == "-sourcetgrads") {
+      sourcetgrads = true;
+    }
+    else if (args[i] == "-afterupdateonly") {
+      afterupdateonly = true;
+    }
+  }
+}
+
+AFImageTraverser::~AFImageTraverser()
+{
+  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 *AFImageTraverser::contextFactory( int proc, 
int numProc ) {
+
+  return new AFRContext;
+};
+
+void AFImageTraverser::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 AFImageTraverser::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 %3.1f\n",STREAM_VERSION);
+    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 AFImageTraverser::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 AFImageTraverser::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];
+  for(i=0; i<num_clients; i++)
+  {
+    // samples_done[i] = 0;
+    
+    initpass[i] = false;
+    kdtree[i].setAB(samplingrate);
+    kdtree[i].init(xres, yres, samplingrate, i);       // initialize the tree
+  }
+  
+  // chunk_size = 256; // this is a fixed number as of now
+  maxQSize = qSize = (int)(samplingrate*0.1); // temporal queue size
+#ifdef RANDOM_ACCESS_TEMPORALQ
+  temporalQ        = new CSTACK<Sample>[num_clients];
+#else
+  temporalQ        = new CQ<Sample>[num_clients];
+#endif
+  newSample = new Sample* [num_clients];
+  newSampleSet = new SampleSet* [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++)
+  {
+    temporalQ[i].init(qSize+1, &myRandomNumber[i]);
+    // these are really overdimensioned I believe.
+    newSample[i] = new Sample [chunk_size];
+    newSampleSet[i] = new SampleSet [chunk_size];
+    xhairBlockStart[i] = -1;
+    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];
+    }
+    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 AFImageTraverser::renderCrossHair(const RenderContext& context,
+                                      AFRContext *afr_context,
+                                      int myID,
+                                      Image *image, const int xres, const 
int yres, Sample *s,
+                                      const int sscount, double currenttime, 
bool endChunk)
+{
+ //cout << "now rendering xhair" << endl;
+  if(!endChunk)
+  {
+    newSampleSet[myID][sscount].set(TEMPORAL_SAMPLE, s->viewCoord[0], 
s->viewCoord[1], s->t,
+           s->worldCoord[0], s->worldCoord[1], s->worldCoord[2],
+           s->c[0], s->c[1], s->c[2], s->valid);
+  }
+  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);
+      }  
+      int rayindex = (j-start)*5+i;
+      // Specify the pixel.
+      rays.setPixel(rayindex, 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);
+      Point p = rays.getHitPosition(rayindex);
+      RGBColor tempcol = clr.convertRGB();
+      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].set( i, nsx, nsy, t, p.x(), p.y(), 
p.z(),tempcol.r(), tempcol.g(), tempcol.b(), validinfo[rayindex] );
+      
+      frag.setColor(rayindex, clr );
+    }
+    newSampleSet[myID][j].computeGradients(t);
+    samples_done[myID].addFive();
+  }
+  image->set(frag);
+  //cout << "done one xhairBlock" << endl;
+  xhairBlockStart[myID] = sscount;
+  return size/5;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Render all of samples in a fragment of the chunk.
+///////////////////////////////////////////////////////////////////////////////
+void AFImageTraverser::renderChunk(const RenderContext& context,
+                                   AFRContext *afr_context,
+                                   Image* image,
+                                   int xres, int yres, double currenttime)
+{
+  //cout << "inside renderChunk " << endl;     
+  // renders the fragment by jittering it and stores result in temporalQ
+  int flags = RayPacket::HaveImageCoordinates | RayPacket::ConstantEye;
+  int i,f;
+  int myID = context.proc;
+  int fsize = chunk_size;
+  float t = (float)currenttime;
+  Real afr_begin;
+  bool validinfo[RayPacket::MaxSize];
+  if(initpass[myID])
+  {
+    fsize = (chunk_size>(qSize-temporalQ[myID].getN()))? chunk_size : 
qSize-temporalQ[myID].getN();
+    //if((fsize + temporalQ[myID].getN()) > temporalQ[myID].getMaxSize())
+      //fsize = temporalQ[myID].getMaxSize() - temporalQ[myID].getN() -1;
+    //cout << "fsize = " << fsize << endl;
+  }
+  fsize = chunk_size*(fsize/chunk_size);
+  Color color[RayPacket::MaxSize];
+  //Sample newSample[RayPacket::MaxSize];
+  //cout << "fsize = " << fsize << ", myID = " << myID << endl;
+  
/////////////////////////////////////////////////////////////////////////////
+  // Create ray packets.
+  
+  const static int offset[5][2] = {
+    { 0, 0},
+    {-3, 0},
+    { 3, 0},
+    { 0,-3},
+    { 0, 3}
+  };
+  
+  for(int g=0; g<fsize; g+=chunk_size)
+  {
+    int csize = chunk_size;
+    if(csize >= fsize-g)
+      csize = fsize-g;
+    for(f=0;f<csize;f+=RayPacket::MaxSize) {
+      int size = RayPacket::MaxSize;
+      if(size >= csize-f)
+        size = csize-f;
+      // Create a ray packet
+      int depth = 0;
+      RayPacketData raydata;
+      Fragment frag;
+      RayPacket rays(raydata, 0, size, depth, flags);
+      
+      int cx, cy, ox, oy;
+      int tindex = kdtree[myID].getRandomTile(myRandomNumber[myID]);
+      float xgrad, ygrad, tgrad;
+      xgrad = UNDEFINED_GRAD;
+      ygrad = UNDEFINED_GRAD;
+      tgrad = UNDEFINED_GRAD;
+      int coherenceCount=0;
+      // Copy samples from the sampleQ into the fragment.
+      
+      for(i=0;i<size;i++) 
+      {
+        if(spatialCoherence) 
+        {
+          if(coherenceCount==0)
+          {
+            kdtree[myID].getRandomSamplefromTile(tindex, cx, cy, 
myRandomNumber[myID]);
+            ox = cx; oy = cy;
+          }
+          else
+          {
+            cx += offset[coherenceCount-1][0];
+            cy += offset[coherenceCount-1][1];
+            if(cx<0 || cx>=xres || cy<0 || cy>=yres)
+              kdtree[myID].getRandomSamplefromTile(tindex, cx, cy, 
myRandomNumber[myID]);
+          }
+        }
+        else
+          kdtree[myID].getRandomSamplefromTile(tindex, cx, cy, 
myRandomNumber[myID]);
+  
+        int fi = (f+i);
+        //if(cx<0) cx=0; if(cx>=xres) cx = xres-1;
+        //if(cy<0) cy=0; if(cy>=yres) cy = yres-1;
+        // cout << "f+i = " << f+i << endl;
+        double jitterx, jittery;
+        jitterx = myRandomNumber[myID].genfrand()-0.5;
+        jittery = myRandomNumber[myID].genfrand()-0.5;
+  
+        newSample[myID][fi].viewCoord[0] = (float)cx+jitterx;
+        newSample[myID][fi].viewCoord[1] = (float)cy+jittery;
+        
+        if(newSample[myID][fi].viewCoord[0]<0) 
+          newSample[myID][fi].viewCoord[0]=0; 
+        if(newSample[myID][fi].viewCoord[0]>=xres) 
+          newSample[myID][fi].viewCoord[0]= xres-1;
+        if(newSample[myID][fi].viewCoord[1]<0) 
+          newSample[myID][fi].viewCoord[1]=0; 
+        if(newSample[myID][fi].viewCoord[1]>=yres) 
+          newSample[myID][fi].viewCoord[1]= yres-1;
+        // cout << "raytracing: " << cx << ", " << cy << endl;
+        newSample[myID][fi].tileindex = tindex;
+        newSample[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)newSample[myID][fi].viewCoord[0])/(double)yres); 
+            py = (double)(-1.0 + 
2.0*((double)newSample[myID][fi].viewCoord[1])/(double)yres);
+          }
+        else
+          {
+            px = (double)(-1.0 + 
2.0*((double)newSample[myID][fi].viewCoord[0])/(double)xres); 
+            py = (double)(-1.0 + 
2.0*((double)newSample[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)(newSample[myID][fi].viewCoord[0]), 
(int)(newSample[myID][fi].viewCoord[1]), 0);
+        coherenceCount++;
+        if(!spatialCoherence || 
coherenceCount>=6)//kdtree[myID].getTileSize(tindex)/10)
+        {
+          tindex = kdtree[myID].getRandomTile(myRandomNumber[myID]);
+          coherenceCount=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();
+        Point p = rays.getHitPosition(i);
+        newSample[myID][fi].c[0] = tempcol.r();
+        newSample[myID][fi].c[1] = tempcol.g();
+        newSample[myID][fi].c[2] = tempcol.b();
+        newSample[myID][fi].worldCoord[0] = p.x();
+        newSample[myID][fi].worldCoord[1] = p.y();
+        newSample[myID][fi].worldCoord[2] = p.z();
+        newSample[myID][fi].valid = validinfo[i];
+        // get tilegrads
+        newSample[myID][fi].setgrads(xgrad, ygrad, tgrad);
+        // newSample[i].print();
+        // Skip reconstruction and set the image pixel.
+        frag.setColor(i, clr);
+        // add this sample into the temporalQ
+        temporalQ[myID].qInsert(&newSample[myID][fi], &myRandomNumber[myID]);
+      }
+      image->set(frag);
+    }
+    if(outputStreams)
+    {
+      for(i=0;i<csize;i++) 
+      {
+        
/////////////////////////////////////////////////////////////////////////////
+        // add sample to the corresponding file
+        //newSample[myID][i].writeToFile(streamfile[myID]);
+        newSample[myID][i].copySPF(&spf[myID][i]);
+      }
+      fwrite(spf[myID],sizeof(SamplePrintFormat), csize, streamfile[myID]);  
    
+    }
+    if(!afterupdateonly)
+    {
+      afr_begin = afr_context->beginUpdateStats();
+      for(i=0;i<csize;i++) 
+      {
+        
/////////////////////////////////////////////////////////////////////////////
+        // add sample to the corresponding kdtree
+        kdtree[myID].updateStatsAddSample( &newSample[myID][i], t, 
samplingrate);
+      }
+      afr_context->endUpdateStats( afr_begin , csize);
+    }
+  }
+}
+  
+///////////////////////////////////////////////////////////////////////////////
+// This method implements the master thread functionality.
+///////////////////////////////////////////////////////////////////////////////
+void AFImageTraverser::masterTask(const RenderContext& context, AFRContext 
*afr_context, Image* image, double currenttime) {
+
+  // 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);
+  
+  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)) {
+    initpass[context.proc] = true;
+    std::cerr << "Thread: " << context.proc << " initialized" << std::endl;  
  
+  }
+
+  image->setValid( true );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// This method implements the master thread functionality.
+///////////////////////////////////////////////////////////////////////////////
+void AFImageTraverser::clientTask(const RenderContext& context, AFRContext 
*afr_context, Image* image, double currenttime) {
+
+  //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;
+  // render the chunk
+  renderChunk(context, afr_context, image, xres, yres, currenttime);
+  int xhairRendered = 0;
+
+  if(initpass[myID]) 
+  {
+
+    // 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)
+    fsize = (qSize<chunk_size)? qSize : chunk_size;
+    for(i=0; i<fsize; i++)
+    {
+      sp = temporalQ[myID].qDelete(&myRandomNumber[myID]);
+      if(sp!=NULL) {
+        Manta::Real px, py, pz;
+        px = sp->worldCoord[0];
+        py = sp->worldCoord[1];
+        pz = sp->worldCoord[2];
+        newSampleSet[myID][sscount].oldviewX = sp->viewCoord[0];
+        newSampleSet[myID][sscount].oldviewY = sp->viewCoord[1];
+        //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);
+          sp->viewCoord[0] = rp.x()*xres;
+          sp->viewCoord[1] = rp.y()*yres;
+          sp->viewCoord[2] = rp.z();
+          if(sp->viewCoord[0]<xres && sp->viewCoord[0]>=0 
+               && sp->viewCoord[1]<yres && sp->viewCoord[1]>=0
+               && sp->viewCoord[2]<=1.0)
+          {
+            xhairRendered += renderCrossHair(context, afr_context, myID, 
image, xres, yres, sp, sscount, currenttime);
+            sscount++;
+          }
+        }
+        else
+        {
+          xhairRendered += renderCrossHair(context, afr_context, myID, 
image, xres, yres, sp, sscount, currenttime);
+          sscount++;
+        }
+      }
+      else break;
+    }
+    xhairRendered += renderCrossHair(context, afr_context, myID, image, 
xres, yres, NULL, 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++)
+    {
+      // update tree for each sample one by one
+      kdtree[myID].updateStatsAddSampleSet( &newSampleSet[myID][i], 
(float)currenttime, samplingrate, sourcetgrads);
+    }
+    afr_context->endUpdateStats( afr_begin , xhairRendered*5);
+  }
+}
+
+//#define USE_BRUTE_FORCE
+///////////////////////////////////////////////////////////////////////////////
+// This method adjusts the kdtree-cut by either merging nodes along the cut
+// or splitting nodes and adding their children to the cut.
+///////////////////////////////////////////////////////////////////////////////
+void AFImageTraverser::adjustTiles( AFRContext *afr_context, int id, 
Timestamp currenttime)
+{
+  float minError, maxError;
+  int count, minIndex, maxIndex;
+  int required_tiles = kdtree[id].getMaxTiles();
+  //cout << "minError = " << minError << ", maxError = " << maxError << endl;
+  //kdtree[id].ageAllStats(samplingrate, currenttime);
+  if(kdtree[id].number_of_tiles()!=required_tiles)
+  {
+    do
+    {
+      while(kdtree[id].number_of_tiles()>required_tiles)
+      {
+#ifdef USE_BRUTE_FORCE
+        kdtree[id].bruteforceminmax(minIndex, maxIndex, minError,maxError);
+        kdtree[id].merge(minIndex, currenttime, samplingrate);
+#else
+        kdtree[id].merge(kdtree[id].getminErrorParentTile(), currenttime, 
samplingrate);
+#endif
+        //cout << " merge " << endl;
+        //kdtree[id].consistencycheck();
+      }
+      while(kdtree[id].number_of_tiles()<required_tiles)
+      {
+#ifdef USE_BRUTE_FORCE
+        kdtree[id].bruteforceminmax(minIndex, maxIndex, minError,maxError);
+        kdtree[id].split(maxIndex, currenttime, samplingrate);
+#else
+        kdtree[id].split(kdtree[id].getmaxErrorTile(), currenttime, 
samplingrate);
+#endif
+        //cout << " split " << endl;
+        //kdtree[id].consistencycheck();
+      }
+    }
+    while(kdtree[id].number_of_tiles()!=required_tiles);
+  }
+#ifdef USE_BRUTE_FORCE
+  kdtree[id].bruteforceminmax(minIndex, maxIndex, minError,maxError);
+#else
+  minError = kdtree[id].getminError();
+  maxError = kdtree[id].getmaxError();
+#endif
+  //cout << "minError = " << minError << ", maxError = " << maxError << endl;
+  if(maxError>0.001 && minError/maxError<MAX_MIN_RATIO)
+  {
+    //cout << "minError = " << minError << ", maxError = " << maxError << 
endl;
+    count = 0;
+    do
+    {
+      //for(int i=0; i<128; i++)
+      {
+#ifdef USE_BRUTE_FORCE
+        kdtree[id].merge(minIndex, currenttime, samplingrate);
+        kdtree[id].bruteforceminmax(minIndex, maxIndex, minError,maxError);
+#else
+        kdtree[id].merge(kdtree[id].getminErrorParentTile(), currenttime, 
samplingrate);
+#endif
+        //cout << " merge " << endl;
+        //kdtree[id].consistencycheck();
+      }
+      count++;
+      //for(int i=0; i<128; i++)
+      {
+#ifdef USE_BRUTE_FORCE
+        kdtree[id].split(maxIndex, currenttime, samplingrate);
+        kdtree[id].bruteforceminmax(minIndex, maxIndex, minError,maxError);
+#else
+        kdtree[id].split(kdtree[id].getmaxErrorTile(), currenttime, 
samplingrate);
+#endif
+        //cout << " split " << endl;
+        //kdtree[id].consistencycheck();
+      }
+      count++;
+#ifndef USE_BRUTE_FORCE
+      minError = kdtree[id].getminError();
+      maxError = kdtree[id].getmaxError();
+#endif
+      //cout << "minError = " << minError << ", maxError = " << maxError << 
endl;
+    }
+    while(minError/maxError<MAX_MIN_RATIO && count<MAX_MERGE_SPLIT_LIMIT);
+  }
+  //kdtree[id].showErrors();
+}
+
+
+void AFImageTraverser::outputStats(int myID, AFRContext *afr_context)
+{
+  if(outputstats)
+  {
+    float t = (float)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/AFImageTraverser.h
==============================================================================
--- (empty file)
+++ trunk/fox/afr_demo/Engine/ImageTraversers/AFImageTraverser.h        Wed 
Feb  8 17:59:11 2006
@@ -0,0 +1,196 @@
+
+#ifndef Manta_Engine_AFImageTraverser_h
+#define Manta_Engine_AFImageTraverser_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>
+
+
+
+
+#ifdef __ia64__
+#include <malloc.h>
+#include <ia64intrin.h>
+#endif
+//#define RANDOM_ACCESS_TEMPORALQ
+namespace Manta {
+
+  using namespace std;
+  
+  namespace Afr {
+    class AFImageTraverser : public AFRImageTraverser {
+    
+    friend class AFRPipeline;
+    
+    public:
+    
+      AFImageTraverser(const vector<string>& args);
+      virtual ~AFImageTraverser();
+
+      // Context factory method.
+      virtual AFRContext *contextFactory( int proc, int numProc );
+      
+      virtual void setupBegin(SetupContext&, int numChannels);
+      virtual void setupDisplayChannel(SetupContext&);
+
+      // Render single sample per pixel during initialization.
+      void renderChunk(const RenderContext& context, AFRContext 
*afr_context, Image* image, 
+                       int xres, int yres, double currenttime);
+
+      // 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, 
+                          Sample *s, const int sscount, double currenttime, 
bool endChunk=false);
+
+      // All AFImageTraversers 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++;
+        
+        if(numUpdates%1000==0) {
+          qSize = (int)(samplingrate*0.1);
+          if(qSize>maxQSize) qSize = maxQSize;
+        }  
+      }
+
+      // 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:
+      AFImageTraverser(const AFImageTraverser&);
+      AFImageTraverser& operator=(const AFImageTraverser&);
+      // Image kd-tree. per thread
+      KDTree *kdtree;
+      int qSize, maxQSize;
+      bool sourcetgrads, afterupdateonly;
+      // 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;
+      // the reprojection queue per thread
+#ifdef RANDOM_ACCESS_TEMPORALQ
+      CSTACK<Sample> *temporalQ;
+#else
+      CQ<Sample> *temporalQ;
+#endif
+      Sample **newSample;
+      SamplePrintFormat **spf;
+      SampleSet **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() {
+        if(num_clients==0) return false;
+        bool all = true;
+        for (int i=0;(i<num_clients)&&all;++i) {
+          all = (initpass[i] || isExempt(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 17:59:11 2006
@@ -44,6 +44,7 @@
 
 #include <Engine/ImageTraversers/GSTAFRImageTraverser.h>
 #include <Engine/ImageTraversers/GSTAFRImageTraverserNew.h>
+#include <Engine/ImageTraversers/AFImageTraverser.h>
 #include <Engine/Control/AFRPipeline.h>
 #include <Model/Cameras/AfrPinholeCamera.h>
 
@@ -457,6 +458,9 @@
       }
       else if (name == "gstafrnew") {
          rtrt->setImageTraverser( GSTAFRImageTraverserNew::create( args ) );
+      }
+      else if (name == "afr") {
+         rtrt->setImageTraverser( AFImageTraverser::create( args ) );
       }
       // Otherwise attempt to load a default image traverser from manta.
       else {




  • [MANTA] r908 - in trunk/fox/afr_demo: . Engine/ImageTraversers StandAlone, abhinav, 02/08/2006

Archive powered by MHonArc 2.6.16.

Top of page