Manta Interactive Ray Tracer Development Mailing List

Text archives Help


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


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

Author: abhinav
Date: Wed Feb  8 18:12:00 2006
New Revision: 909

Added:
   trunk/fox/afr_demo/Engine/ImageTraversers/STAFRImageTraverser.cc
   trunk/fox/afr_demo/Engine/ImageTraversers/STAFRImageTraverser.h
Modified:
   trunk/fox/afr_demo/CMakeLists.txt
   trunk/fox/afr_demo/StandAlone/afr.cc
Log:
added stafr imagetraverser, that shares updates and uses 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 18:12:00 2006
@@ -28,6 +28,8 @@
     Engine/ImageTraversers/GSTAFRImageTraverserNew.h
     Engine/ImageTraversers/GSTAFRImageTraverser.h
     Engine/ImageTraversers/AFRImageTraverser.h
+    Engine/ImageTraversers/STAFRImageTraverser.cc
+    Engine/ImageTraversers/STAFRImageTraverser.h
     Engine/ImageTraversers/AFImageTraverser.cc
     Engine/ImageTraversers/AFImageTraverser.h
     # Model

Added: trunk/fox/afr_demo/Engine/ImageTraversers/STAFRImageTraverser.cc
==============================================================================
--- (empty file)
+++ trunk/fox/afr_demo/Engine/ImageTraversers/STAFRImageTraverser.cc    Wed 
Feb  8 18:12:00 2006
@@ -0,0 +1,890 @@
+
+#include <Engine/ImageTraversers/STAFRImageTraverser.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 XhairPacketSize RayPacket::MaxSize/3
+#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* STAFRImageTraverser::create(const vector<string>& args)
+{
+  return new STAFRImageTraverser(args);
+}
+
+STAFRImageTraverser::STAFRImageTraverser(const vector<string>& args) :
+
+  AFRImageTraverser( args ),
+  
+  myRandomNumber( 0 ),
+  inner_loop_time( 0.016666667 ),
+  chunk_size( 256 ),
+  samplingrate( 400000 ),
+  outputStreams( false ),
+  spatialCoherence( false ),
+  num_masters( 1 ),
+  master_thread( 0 ),
+  sourcetgrads( false ),
+  afterupdateonly( false ),
+  masters_exempt( 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] == "-groups") {
+      if (!getArg( i, args, num_masters )) {
+        throw IllegalArgument("-groups <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] == "-sourcetgrads") {
+      sourcetgrads = true;
+    }
+    else if (args[i] == "-afterupdateonly") {
+      afterupdateonly = true;
+    }
+    // Specify the offset into a group for the master threads
+    else if (args[i] == "-thread") {
+      if (!getArg( i, args, master_thread )) {
+        throw IllegalArgument("-thread <Int>", i, args);
+      }
+    }
+
+    // Set the master threads to be exempt from doing rendering.
+    else if (args[i] == "-exempt") {
+      masters_exempt = true;
+    }
+    else if (args[i] == "-stats") {
+      outputstats = true;
+    }
+  }
+}
+
+STAFRImageTraverser::~STAFRImageTraverser()
+{
+  if(myRandomNumber!=NULL) delete [] myRandomNumber;
+  // free the kdtree and queues. I suppose this will be done automatically
+  // confirm! Am I dreaming?
+}
+
+// This factory method returns a context specific to this AFRImageTraverser 
implementation.
+AFRImageTraverser::AFRContext *STAFRImageTraverser::contextFactory( int 
proc, int numProc ) {
+
+  return new AFRContext;
+};
+
+
+#define DESIRED_FRAME_RATE 15
+void STAFRImageTraverser::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 STAFRImageTraverser::write_Tile_and_Camera(RenderContext& context, 
double currenttime)
+{
+  //streamlock.lock();
+  
+  if(!outputStreams) return;
+  int myID = context.proc;
+  fprintf(textstreamfile[myID],"\n\nbegin_tiles\n");
+  
+  // call thread's tree, print to file function
+  if(!isMaster(myID))
+  {
+    fprintf(textstreamfile[myID],"num_tiles %d\n",1);
+    fprintf(textstreamfile[myID],"timestamp %f\n",(float)currenttime);
+    TilePrintFormat tpf;
+    tpf.index = 1;
+    tpf.xGrad = tpf.yGrad = tpf.tGrad = 0.0f;
+    // find the current sampling rate for this call
+    tpf.oldest_sample_timestamp = 0.0f;
+//     // <TODO> may be we want to compoute this on a per tile basis too
+    fwrite(&tpf, sizeof(tpf), 1, tilestreamfile[myID]);
+  }
+  else
+  {
+    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 STAFRImageTraverser::setupBegin(SetupContext& context, int numChannels) 
{
+
+  if (context.proc == 0)
+    context.loadBalancer->setupBegin(context, numChannels);
+
+  //if (getDebugWindow()) {
+  //  context.setMultipleGLWindows();
+  //  getDebugWindow()->createStatsWin( context );
+  //}
+}
+
+
+void STAFRImageTraverser::setupDisplayChannel(SetupContext& context) {
+
+  if (context.proc != 0)
+    return;
+  
+  // Specify that the rendering pipeline should use only one image buffer.
+  //if (getDebugWindow())
+  //  context.setMultipleGLWindows();
+  numFrontXhairSamples = 3;
+  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;
+  //chunk_size = (chunk_size/num_clients)>10? chunk_size/num_clients : 10;
+  cout << "number of masters = " << num_masters << endl;
+  groupSize = new int[num_masters];
+  avgGroupSize = num_clients/num_masters;
+  for(i=0; i<num_masters-1; i++)
+    {
+      groupSize[i] = avgGroupSize;
+      cout << " number of clients for master " << i+1 << " = " << 
avgGroupSize << endl;
+    }
+  groupSize[num_masters-1] = num_clients-avgGroupSize*(num_masters-1);
+  cout << " number of clients for master " << num_masters << " = " << 
groupSize[num_masters-1] << endl;
+  
+  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 );
+
+  // Per master performance timer.
+  tile_refresh = new double[num_masters];
+  last_time    = new double[num_masters];
+
+  for (int i=0;i<num_masters;++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 master.
+  
+  //---------------------------------------------------------
+  // make our kdtree, given the resolution of image/channel
+  //---------------------------------------------------------
+  kdtree = new KDTree[num_masters];
+  updatecount = new int[num_masters];
+  initpass    = new bool[num_masters];
+  for(i=0; i<num_masters; 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<PartialSampleSet>[num_clients];
+#else
+  temporalQ        = new CQ<PartialSampleSet>[num_clients];
+#endif
+  newPartialSampleSet     = new PartialSampleSet* [num_clients];
+  newTempPartialSampleSet = new PartialSampleSet* [num_clients];
+  lastxhairindex   = new int[num_clients];
+  if(outputstats)
+  {
+    outputfile = new FILE* [num_clients];
+    timestatslastwritten = new float[num_clients];
+  }
+  // Initialize
+  for(i = 0; i<num_clients; i++)
+    {
+      lastxhairindex[i] = 0;
+      temporalQ[i].init(qSize+1, &myRandomNumber[i]);
+      newPartialSampleSet[i] = new PartialSampleSet[chunk_size];
+      newTempPartialSampleSet[i] = new PartialSampleSet[chunk_size];
+      if(outputstats)
+      {
+        char outname[32];
+        sprintf(outname, "stnew_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*numFrontXhairSamples];
+      }
+      streamfile = (FILE**)malloc(num_clients*sizeof(FILE*));
+      tilestreamfile = (FILE**)malloc(num_clients*sizeof(FILE*));
+      textstreamfile = (FILE**)malloc(num_clients*sizeof(FILE*));
+      initStreams(xres, yres);
+    }
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// RENDER CROSS HAIR  RENDER CROSS HAIR  RENDER CROSS HAIR  RENDER CROSS 
HAIR  
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+int STAFRImageTraverser::renderCrossHair(const RenderContext& context,
+                                          AFRContext *afr_context,
+                                          int myID, 
+                                          Image *image, const int xres, 
const int yres,
+                                          PartialSampleSet *sampleset, int 
sscount, double currenttime, bool endChunk)
+{
+  int start = lastxhairindex[myID];
+  bool validinfo[RayPacket::MaxSize];
+  //cout << "now rendering xhair " << myID << ", " << xres << ", " << yres 
<< ", " << sscount << ", " << endChunk << ", " << XhairPacketSize << endl;
+  if((sscount-start+1)<RayPacket::MaxSize && !endChunk)
+    {
+      newPartialSampleSet[myID][sscount].reset();
+      newPartialSampleSet[myID][sscount] = *sampleset;
+      //newPartialSampleSet[myID][sscount].tileindex = 
kdtree[context.proc].getTileforXY(s->viewCoord[0], s->viewCoord[1]);
+      //cout << "checking ...sscount = " << sscount << ", blockstart = " << 
xhairBlockStart[myID] << endl;
+      return 0;
+    }
+  if(start>=sscount) return 0;
+  
+  Real afr_begin = afr_context->beginTraceRays();
+  
+  int myMasterID = getMasterID( myID );
+  float t = (float)currenttime;
+  int flags = RayPacket::HaveImageCoordinates | RayPacket::ConstantEye;
+  int depth = 0;
+  RayPacketData raydata;
+  Fragment frag;
+  RayPacket rays(raydata, 0, (sscount-start+1), depth, flags);
+  int i, j;
+  j = 0;
+  //cout << "size = " << (sscount-start+1) << endl;
+  for(i=start; i<=sscount; i++) {
+    double px, py;
+    if(xres > yres) // let the smaller dimension be mapped to [-1,1]
+      {
+        px = (double)(-1.0 + 
2.0*(newPartialSampleSet[myID][i].sample[0].viewCoord[0])/(double)yres); 
+        py = (double)(-1.0 + 
2.0*(newPartialSampleSet[myID][i].sample[0].viewCoord[1])/(double)yres);
+      }
+    else
+      {
+        px = (double)(-1.0 + 
2.0*(newPartialSampleSet[myID][i].sample[0].viewCoord[0])/(double)xres); 
+        py = (double)(-1.0 + 
2.0*(newPartialSampleSet[myID][i].sample[0].viewCoord[1])/(double)xres);
+      }  
+      
+    // Specify the pixel.
+    rays.setPixel(j, 0, px, py);
+    
frag.addElement((int)(newPartialSampleSet[myID][i].sample[0].viewCoord[0]), 
(int)(newPartialSampleSet[myID][i].sample[0].viewCoord[1]), 0);
+    j++;
+  }
+  
+  
/////////////////////////////////////////////////////////////////////////////
+  // Trace the rays.  The results will automatically go into the fragment  
+  traceRays(context, afr_context, rays, xres, yres, validinfo);
+  afr_context->endTraceRays( afr_begin , (sscount-start+1));
+  
/////////////////////////////////////////////////////////////////////////////
+  // okay now copy from fragment to temporalQ
+  j = 0;
+  for(i=start; i<=sscount; i++) {
+    Color clr = rays.getColor(j);
+    Point p = rays.getHitPosition(j); 
+    RGBColor tempcol = clr.convertRGB();
+    //cout << "processing sampleset " << i << endl;
+    newPartialSampleSet[myID][i].set( numFrontXhairSamples,
+                               
newPartialSampleSet[myID][i].sample[0].viewCoord[0],
+                               
newPartialSampleSet[myID][i].sample[0].viewCoord[1], t, 
+                               p.x(), p.y(), p.z(),
+                               tempcol.r(), tempcol.g(), tempcol.b(), 
validinfo[j] );
+    newPartialSampleSet[myID][i].computeGradients(t);
+    //cout << "grad info <complete>: " << newPartialSampleSet[myID][i].xgrad 
<< ", "
+    //     << newPartialSampleSet[myID][i].ygrad << ", " 
+    //     << newPartialSampleSet[myID][i].tgrad << endl;
+    //samples_done[myID].addOne();
+    frag.setColor(j, clr);
+    j++;
+  }
+  image->set(frag);
+  lastxhairindex[myID] = sscount+1;
+  //cout << "done one xhairBlock" << endl;
+  return (sscount-start+1);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Render all of samples in a fragment of the chunk.
+///////////////////////////////////////////////////////////////////////////////
+void STAFRImageTraverser::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 = 0, j, f;
+  int myID = context.proc;
+  int myMasterID = getMasterID( context.proc );
+  int fsize = chunk_size;
+  float t = (float)currenttime;
+  bool validinfo[RayPacket::MaxSize];
+  if(initpass[myMasterID])
+  {
+    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.
+  int raypacketsize = 
numFrontXhairSamples*(RayPacket::MaxSize/numFrontXhairSamples);
+  //cout << "raypacketsize = " << raypacketsize << endl;
+  int numXhairPerRayPack = raypacketsize/numFrontXhairSamples;
+
+  // Make sure that we don't overflow newTempPartialSampleSet
+  Real afr_begin;
+  int ncsize = numXhairPerRayPack*(chunk_size/numXhairPerRayPack);
+  fsize = numXhairPerRayPack*(fsize/numXhairPerRayPack);
+  for(int g=0; g<fsize; g+=ncsize)
+  {
+    int csize = ncsize;
+    if(csize>(fsize-g))
+      csize = fsize-g;
+    for(f=0;f<csize;f+=numXhairPerRayPack) 
+    {
+      int size = numXhairPerRayPack;
+      if(size>(csize-f))
+        size = csize-f;
+      // Create a ray packet
+      int depth = 0;
+      RayPacketData raydata;
+      Fragment frag;
+      RayPacket rays(raydata, 0, numXhairPerRayPack*numFrontXhairSamples, 
depth, flags);
+      int cx, cy, ox, oy;
+      int tindex = kdtree[myMasterID].getRandomTile(myRandomNumber[myID]);
+      //int tindex = kdtree[myID].getPseudoRandomTile();
+      //cout << "got tile " << tindex << endl;
+      
+      //if(spatialCoherence)
+      //{
+        // do the 10x4 thing here
+      //}
+      //else
+  
+  
+      // Make sure that we don't overflow newTempPartialSampleSet
+      for(i=0; i<size; i++)
+      {
+        kdtree[myMasterID].getRandomSamplefromTile(tindex, cx, cy, 
myRandomNumber[myID]);
+        //cout << "got random loc: " << cx << ", " << cy << endl;
+        double jitterx, jittery;
+        jitterx = myRandomNumber[myID].genfrand()-0.5;
+        jittery = myRandomNumber[myID].genfrand()-0.5;
+        int pssindex = (f+i);
+       
+        newTempPartialSampleSet[myID][pssindex].setTempXhair((cx+jitterx), 
(cy+jittery), xres, yres, tindex, t, myRandomNumber[myID]);
+        for(j=0; j<numFrontXhairSamples; j++)
+        {
+          // normalized
+          double px, py;
+        
+          if(xres>yres) // let the smaller dimension be mapped to [-1,1]
+          {
+            px = (double)(-1.0 + 
2.0*((double)newTempPartialSampleSet[myID][pssindex].sample[j].viewCoord[0])/(double)yres);
 
+            py = (double)(-1.0 + 
2.0*((double)newTempPartialSampleSet[myID][pssindex].sample[j].viewCoord[1])/(double)yres);
+          }
+          else
+          {
+            px = (double)(-1.0 + 
2.0*((double)newTempPartialSampleSet[myID][pssindex].sample[j].viewCoord[0])/(double)xres);
 
+            py = (double)(-1.0 + 
2.0*((double)newTempPartialSampleSet[myID][pssindex].sample[j].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*numFrontXhairSamples+j, 0, px, py);
+          
frag.addElement((int)(newTempPartialSampleSet[myID][pssindex].sample[j].viewCoord[0]),
+                          
(int)(newTempPartialSampleSet[myID][pssindex].sample[j].viewCoord[1]),
+                          0);
+          if(!spatialCoherence) tindex = 
kdtree[myMasterID].getRandomTile(myRandomNumber[myID]);
+          //tindex = kdtree[myMasterID].getPseudoRandomTile();
+          //cout << "got tile " << tindex << endl;
+        }
+      }
+      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 , 
numXhairPerRayPack*numFrontXhairSamples);
+      
///////////////////////////////////////////////////////////////////////////
+      // okay now copy from fragment to temporalQ
+      for(i=0;i<size;i++)
+      {
+        int pssindex = (f+i);
+        for(j=0; j<numFrontXhairSamples; j++)
+        {
+          int rayindex = i*numFrontXhairSamples+j;
+          Color clr = rays.getColor(rayindex);
+          RGBColor tempcol = clr.convertRGB();
+          Point p = rays.getHitPosition(rayindex);
+          newTempPartialSampleSet[myID][pssindex].set(j,
+              newTempPartialSampleSet[myID][pssindex].sample[j].viewCoord[0],
+              newTempPartialSampleSet[myID][pssindex].sample[j].viewCoord[1],
+              t,
+              p.x(), p.y(), p.z(),
+              tempcol.r(), tempcol.g(), tempcol.b(), validinfo[rayindex] );
+          frag.setColor(rayindex, clr);
+        }
+        
/////////////////////////////////////////////////////////////////////////////
+        newTempPartialSampleSet[myID][pssindex].computeGradients(t);
+        samples_done[myID].addThree();
+        temporalQ[myID].qInsert(&newTempPartialSampleSet[myID][pssindex], 
&myRandomNumber[myID]);
+      }
+      image->set(frag);
+    }
+    if(!afterupdateonly)
+    {
+      int ucount=0;
+      afr_begin = afr_context->beginUpdateStats();
+      for(i=0; i<csize; i++)
+      {
+        ucount += 
kdtree[myMasterID].updateStatsAddPartialSampleSet_global_tree(&newTempPartialSampleSet[myID][i],
 t, samplingrate, sourcetgrads);
+      }
+      afr_context->endUpdateStats( afr_begin , ucount*3 );
+    }
+    
+    if(outputStreams)
+    {
+      for(i=0;i<csize;i++)
+      {
+        
newTempPartialSampleSet[myID][i].sample[C_SAMPLE].copySPF(&spf[myID][i*numFrontXhairSamples+0]);
+        
newTempPartialSampleSet[myID][i].sample[X_SAMPLE].copySPF(&spf[myID][i*numFrontXhairSamples+1]);
+        
newTempPartialSampleSet[myID][i].sample[Y_SAMPLE].copySPF(&spf[myID][i*numFrontXhairSamples+2]);
+      }
+      fwrite(spf[myID], sizeof(SamplePrintFormat), 
csize*numFrontXhairSamples, streamfile[myID]);
+    }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// This method implements the master thread functionality.
+///////////////////////////////////////////////////////////////////////////////
+void STAFRImageTraverser::masterTask(const RenderContext& context, 
AFRContext *afr_context, Image* image, double currenttime) {
+
+  // Check to see if the master thread called this function.
+ // cout << "thread " << context.proc << " master status is " << isMaster( 
context.proc ) << endl;
+  if (isMaster( context.proc ))
+  {
+    
///////////////////////////////////////////////////////////////////////////
+    // update kdtree based on previous results from the client threads
+    // Get the current image resolution.
+    bool stereo;
+    int i;
+    int xres, yres;
+    Real afr_begin = afr_context->beginUpdateStats();
+    image->getResolution(stereo, xres, yres);
+    // get the masterID
+    int masterID = context.proc/avgGroupSize;
+    
///////////////////////////////////////////////////////////////////////////
+    // Determine the refresh rate.
+    double current_time = SCIRun::Time::currentSeconds();
+    kdtree[masterID].setAB(samplingrate);
+    tile_refresh[masterID] = (current_time - last_time[masterID]);
+    last_time[masterID] = current_time;
+    // for clients context.proc+1 to context.proc+groupSize[masterID]
+    // read output queue of all clients and update the kdtree[masterID]
+    kdtree[masterID].update_parents_and_minmax(currenttime, samplingrate);
+    afr_context->endUpdateStats( afr_begin , 0 );
+    // adjust tiles based on current status
+    if(initpass[masterID]) {
+      // adjust tiles based on current status
+      Real afr_begin = afr_context->beginAdjustTiles();
+      adjustTiles(afr_context, masterID, currenttime);
+      afr_context->endAdjustTiles( afr_begin );
+      //cout << "updateCount says: " << updatecount[masterID] << endl;
+    }
+    else if (getSamplesDone()>xres*yres) {
+      initpass[masterID] = true;
+      std::cerr << "Master Thread: " << masterID << " initialized" << 
std::endl;
+    }
+    image->setValid( true );
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// This method implements the master thread functionality.
+///////////////////////////////////////////////////////////////////////////////
+void STAFRImageTraverser::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;
+  int myMasterID = getMasterID( myID );
+  //cout << "client " << myID << " belongs to master " << myMasterID << endl;
+  Sample s;
+  
+  // render the chunk
+  renderChunk(context, afr_context, image, xres, yres, currenttime);
+  
+  int xhairRendered = 0;
+  if(initpass[myMasterID])
+    {
+      // initialization is done so we can reproject one chunk worth
+      int i, j;
+      int sscount=0;
+      lastxhairindex[myID] = 0;
+      PartialSampleSet *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;
+      fsize = (chunk_size<temporalQ[myID].getN())? chunk_size : 
temporalQ[myID].getN();
+      for(i=0; i<fsize; i++) {
+    
+        sp = temporalQ[myID].qDelete(&myRandomNumber[myID]);
+        if(sp!=NULL) {
+          Manta::Real px, py, pz;
+          for(j=0; j<numFrontXhairSamples; 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);
+                    sp->sample[j].viewCoord[0] = rp.x()*xres;
+                    sp->sample[j].viewCoord[1] = rp.y()*yres;
+                    sp->sample[j].viewCoord[2] = rp.z();
+                  }
+            }
+          sp->viewX = sp->sample[C_SAMPLE].viewCoord[0];
+          sp->viewY = sp->sample[C_SAMPLE].viewCoord[1];
+          sp->viewZ = sp->sample[C_SAMPLE].viewCoord[2];
+          if(sp->sample[0].viewCoord[0]<xres && 
sp->sample[0].viewCoord[0]>=0 
+             && sp->sample[0].viewCoord[1]<yres && 
sp->sample[0].viewCoord[1]>=0
+             && sp->sample[0].viewCoord[2]<=1.0)
+            {
+              xhairRendered += renderCrossHair(context, afr_context, myID, 
image, xres, yres, sp, sscount, currenttime);
+              sscount++;
+            }
+        }
+        else break;
+      }
+      xhairRendered += renderCrossHair(context, afr_context, myID, image, 
xres, yres, sp, sscount-1, currenttime, true);
+      // write to outputQ
+      Real afr_begin = afr_context->beginUpdateStats();
+      int ucount=0;
+      for(i=0; i<xhairRendered; i++)
+      {
+          samples_done[myID].addOne();
+          ucount += 
kdtree[myMasterID].updateStatsAddPartialSampleSet_global_tree(&newPartialSampleSet[myID][i],
 newPartialSampleSet[myID][i].sample[T_SAMPLE].t, samplingrate, sourcetgrads);
+      }
+      afr_context->endUpdateStats( afr_begin , ucount );
+      // write to file 
+      if(outputStreams)
+      {
+        for(i=0; i<xhairRendered; i++)
+        {
+          
newPartialSampleSet[myID][i].sample[T_SAMPLE].copySPF(&spf[myID][i]);
+        }
+        
fwrite(spf[myID],sizeof(SamplePrintFormat),xhairRendered,streamfile[myID]);
+      }
+    }
+}
+/*
+///////////////////////////////////////////////////////////////////////////////
+// This method adjusts the kdtree-cut by either merging nodes along the cut
+// or splitting nodes and adding their children to the cut.
+///////////////////////////////////////////////////////////////////////////////
+void STAFRImageTraverser::adjustTiles(AFRContext *afr_context, int id, 
Timestamp currenttime)
+{
+  float minError, maxError;
+  int minIndex, maxIndex;
+  int count;
+  int required_tiles = kdtree[id].getMaxTiles();
+  count = 0;
+  //kdtree[id].doingMasterTask = true;
+  if(kdtree[id].number_of_tiles()!=required_tiles)
+    {
+      do
+        {
+          while(kdtree[id].number_of_tiles()>required_tiles )
+            {
+              count++;
+              minIndex = kdtree[id].getminErrorParentTile();
+              kdtree[id].getLock(minIndex, PARENT_TILE);
+              kdtree[id].merge(minIndex, currenttime, samplingrate);
+              kdtree[id].unlock(minIndex, PARENT_TILE);
+            }
+          while(kdtree[id].number_of_tiles()<required_tiles)
+            {
+              count++;
+              maxIndex = kdtree[id].getmaxErrorTile();
+              kdtree[id].getLock(maxIndex, VALID_TILE);
+              kdtree[id].split(maxIndex, currenttime, samplingrate);
+              kdtree[id].unlock(maxIndex, VALID_TILE);
+            }
+        }
+      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)
+    {
+      int i;
+      count = 0;
+      do
+        {
+          count++;
+          minIndex = kdtree[id].getminErrorParentTile();
+          kdtree[id].getLock(minIndex, PARENT_TILE);
+          kdtree[id].merge(minIndex, currenttime, samplingrate);
+          kdtree[id].unlock(minIndex, PARENT_TILE);
+          count++;
+          maxIndex = kdtree[id].getmaxErrorTile();
+          kdtree[id].getLock(maxIndex, VALID_TILE);
+          kdtree[id].split(maxIndex, currenttime, samplingrate);
+          kdtree[id].unlock(maxIndex, VALID_TILE);
+          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);
+    }
+  //kdtree[id].doingMasterTask = false;
+}*/
+//#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 STAFRImageTraverser::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].doingMasterTask = true;
+  //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].mergeSafely(minIndex, currenttime, samplingrate);
+#else
+        kdtree[id].mergeSafely(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].splitSafely(maxIndex, currenttime, samplingrate);
+#else
+        kdtree[id].splitSafely(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].mergeSafely(minIndex, currenttime, samplingrate);
+        kdtree[id].bruteforceminmax(minIndex, maxIndex, minError,maxError);
+#else
+        kdtree[id].mergeSafely(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].splitSafely(maxIndex, currenttime, samplingrate);
+        kdtree[id].bruteforceminmax(minIndex, maxIndex, minError,maxError);
+#else
+        kdtree[id].splitSafely(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].consistencycheck();
+  //kdtree[id].showErrors();
+  //kdtree[id].doingMasterTask = false;
+}
+
+
+void STAFRImageTraverser::outputStats(int myID, AFRContext *afr_context)
+{
+  if(outputstats)
+  {
+    int myMasterID = getMasterID( myID );
+    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/STAFRImageTraverser.h
==============================================================================
--- (empty file)
+++ trunk/fox/afr_demo/Engine/ImageTraversers/STAFRImageTraverser.h     Wed 
Feb  8 18:12:00 2006
@@ -0,0 +1,220 @@
+
+#ifndef Manta_Engine_STAFRImageTraverser_h
+#define Manta_Engine_STAFRImageTraverser_h
+
+#include <SCIRun/Core/Thread/Time.h>
+#include <SCIRun/Core/Thread/Thread.h>
+
+#include <Interface/ImageTraverser.h>
+#include <Interface/Fragment.h>
+#include <sgi_stl_warnings_off.h>
+#include <string>
+#include <vector>
+#include <sgi_stl_warnings_on.h>
+#include <Engine/ImageTraversers/AFRImageTraverser.h>
+#include <Engine/ImageTraversers/AFR/kdtree.h>
+#include <Engine/ImageTraversers/AFR/CQ.h>
+#include <Engine/ImageTraversers/AFR/sample.h>
+#include <Interface/XWindow.h>
+//#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <GL/glx.h>
+
+#ifdef __ia64__
+#include <malloc.h>
+#include <ia64intrin.h>
+#endif
+
+//#define RANDOM_ACCESS_TEMPORALQ
+namespace Manta {
+
+  using namespace std;
+  
+  namespace Afr {
+
+    class STAFRImageTraverser : public AFRImageTraverser {
+    
+      friend class AFRPipeline;
+    
+    public:
+    
+      STAFRImageTraverser(const vector<string>& args);
+    
+      virtual ~STAFRImageTraverser();
+
+      virtual AFRContext *contextFactory( int proc, int numProc );      
+      
+      virtual void setupBegin(SetupContext&, int numChannels);
+      virtual void setupDisplayChannel(SetupContext&);
+      virtual void setupFrame(const RenderContext& context) { /*Undefined 
for AFRPipeline.*/ };
+      virtual void renderImage(const RenderContext& context, Image* image) { 
/*Undefined for AFRPipeline. */ };
+      
+      void renderChunk(const RenderContext& context,
+                       AFRContext *afr_context,
+                       Image* image,
+                       int xres, int yres, double currenttime);
+
+      int renderCrossHair(const RenderContext& context,
+                          AFRContext *afr_context,
+                          int myID,
+                          Image *image, const int xres, const int yres,
+                          PartialSampleSet *sampleset, const int sscount, 
double currenttime,
+                          bool endChunk=false);
+      
+      // 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);
+      
+      inline bool isMaster          (int id) { return 
((id%avgGroupSize)==master_thread); }
+      inline int  getMasterThreadNum(int id) { return 
(id/avgGroupSize)+master_thread; }
+      inline int  getMasterID       (int id) { return (id/avgGroupSize); }
+
+      // Accessors used by pipeline.
+      virtual bool isExempt( int client ) { return masters_exempt && 
isMaster( client ); };
+      virtual int  totalExempt() { return (masters_exempt) ? num_masters : 
0; }
+      inline bool isWithExempt() { return masters_exempt; };
+      // 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);
+      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;
+          }  
+      }
+      static ImageTraverser* create(const vector<string>& args);
+
+      // Accessors, used by AFRDebugWindow
+      inline int    getSamplingRate()               { return samplingrate; };
+     
+      inline KDTree *getKdtree( int client )        { return 
&kdtree[client]; };
+      
+    private:
+      STAFRImageTraverser(const STAFRImageTraverser&);
+      STAFRImageTraverser& operator=(const STAFRImageTraverser&);
+      int numFrontXhairSamples;
+      // 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;
+    
+      //SCIRun::Mutex streamlock;
+      SamplePrintFormat **spf;
+    
+      // the reprojection queue per thread
+#ifdef RANDOM_ACCESS_TEMPORALQ
+      CSTACK<PartialSampleSet> *temporalQ;
+#else
+      CQ<PartialSampleSet> *temporalQ;
+#endif
+      PartialSampleSet **newPartialSampleSet, **newTempPartialSampleSet;
+      // Random number generator array??
+      MT_RNG *myRandomNumber;
+
+      // Master/sampler client
+      bool masters_exempt;  // Are the masters exempt from doing sampling.
+      int num_clients;
+      int num_masters, avgGroupSize;
+      int master_thread;
+      int *groupSize;
+      int chunk_size;
+      int samplingrate;
+      int *lastxhairindex, *updatecount;
+
+      // Per master performance timers.
+      double *tile_refresh;
+      double *last_time;
+      
+      // 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 void addThree() { __fetchadd4_acq( &value, -1 ); 
__fetchadd4_acq( &value, 4 ); };
+        inline unsigned int load()    { return __ld4_acq( &value ); };
+#else
+        inline void addOne()  { value++; };
+        inline void addFive() { value+=5; };
+        inline void addThree() { value+=3; };
+        inline unsigned int load()    { return value; };
+#endif
+      };
+      SamplesDone *samples_done;
+
+      // Arguments.
+      Real inner_loop_time;
+
+      bool   *initpass;
+
+    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;
+      };
+
+      // This method is called by the benchmark helper to determine when to 
start
+      // measuring performance.
+      inline bool allThreadsInitialized() {
+        bool all = true;
+        for (int i=0;(i<num_masters)&&all;++i) {
+          
+          // Don't wait for the master to initialize--this takes forever 
since the master
+          // is doing a lot more work then the distributed tree case.
+          all = (initpass[i]) && all;
+        }
+        return all;
+      }
+      inline int getNumThreads()
+      {
+        return num_masters;
+      }
+      // Accessors.
+      virtual double getInnerLoopTime()              { return 
inner_loop_time; };
+      virtual double getTileRefresh( int master_id ) { return 
tile_refresh[master_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:12:00 2006
@@ -43,6 +43,7 @@
 #include <Core/Thread/Time.h>
 
 #include <Engine/ImageTraversers/GSTAFRImageTraverser.h>
+#include <Engine/ImageTraversers/STAFRImageTraverser.h>
 #include <Engine/ImageTraversers/GSTAFRImageTraverserNew.h>
 #include <Engine/ImageTraversers/AFImageTraverser.h>
 #include <Engine/Control/AFRPipeline.h>
@@ -461,6 +462,9 @@
       }
       else if (name == "afr") {
          rtrt->setImageTraverser( AFImageTraverser::create( args ) );
+      }
+      else if (name == "stafr") {
+         rtrt->setImageTraverser( STAFRImageTraverser::create( args ) );
       }
       // Otherwise attempt to load a default image traverser from manta.
       else {




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

Archive powered by MHonArc 2.6.16.

Top of page