Text archives Help
- From: cgribble@sci.utah.edu
- To: manta@sci.utah.edu
- Subject: [MANTA] r1151 - in trunk: . Core Core/Util DynLT Engine/Control Model Model/Groups Model/Primitives scenes
- Date: Thu, 20 Jul 2006 21:25:05 -0600 (MDT)
Author: cgribble
Date: Thu Jul 20 21:24:57 2006
New Revision: 1151
Added:
trunk/Core/Util/Stat.h
trunk/DynLT/
trunk/DynLT/CMakeLists.txt
trunk/DynLT/DynLTContext.cc
trunk/DynLT/DynLTContext.h
trunk/DynLT/DynLTGridSpheres.cc
trunk/DynLT/DynLTGridSpheres.h
trunk/DynLT/DynLTQueue.cc
trunk/DynLT/DynLTQueue.h
trunk/DynLT/DynLTStatsCollector.cc
trunk/DynLT/DynLTStatsCollector.h
trunk/DynLT/DynLTWorker.cc
trunk/DynLT/DynLTWorker.h
trunk/scenes/dynlt.cc
Removed:
trunk/Engine/Control/DynPLTQueue.cc
trunk/Engine/Control/DynPLTQueue.h
trunk/Engine/Control/DynPLTWorker.cc
trunk/Engine/Control/DynPLTWorker.h
trunk/Model/Primitives/DynPLTGridSpheres.cc
trunk/Model/Primitives/DynPLTGridSpheres.h
trunk/scenes/dynplt.cc
Modified:
trunk/CMakeLists.txt
trunk/Core/CMakeLists.txt
trunk/Engine/Control/CMakeLists.txt
trunk/Model/CMakeLists.txt
trunk/Model/Groups/TimeSteppedParticles.cc
trunk/Model/Groups/TimeSteppedParticles.h
trunk/Model/Primitives/CMakeLists.txt
trunk/Model/Primitives/GridSpheres.cc
trunk/scenes/CMakeLists.txt
Log:
*** Major rework of Dynamic Luminance Texture stuff
DLT files are now in DynLT/ (with the exception of scenes/dynlt.cc)
Changed DynPLT --> DynLT (not technically precomputed, so drop the "P")
Now builds DynLT library: Manta_DynLT
Removed DynPLT-related files from other directories
Removed or changed DynPLT-related references to CMakeLists.txt of other
directories
*** Leave BUILD_DYNLT off because it's currently broken (circular dependency
during link stage: Manta_DynLT <--> Manta_Model)
Other changes
-------------
Core/Util/Stat.h
Core/CMakeLists.txt
Added thread-safe, DynRT-style Stats class: tracks min, max, avg, total,
variance and deviation values
Use with a StatsCollector class (see DynLT example below) to track
interesting
values per-frame, per-session, etc.
If USE_STATS_COLLECTOR is not defined, all operations are no-ops, so you
don't
have to worry about wrapping all of your StatsCollector calls in
#ifdef/#endif blocks or adversely affecting performance
Model/CMakeLists.txt
Added conditional link of Manta_DynLT library --> causes circular dependency
Interface/Callback.h
Interface/CallbackHelpers.h
Added CallbackBase_1Data create(...) function for static 1 Data, 0 Arg
callbacks
Added Callback_Static_1Data_0Arg class for static 1 Data, 0 Arg callbacks
Model/Groups/TimeSteppedParticles.cc
Model/Groups/TimeSteppedParticles.h
Use DynLTGridSpheres (if supported by build); otherwise, print warning and
use
standard GridSpheres
CMakeLists.txt
Added cmake flag to enable statistics collection; if *not* enabled, Stat
member functions become no-ops so you don't have to worry about wrapping
all
of your StatsCollector calls in #ifdef/#endif blocks or adversely
affecting
performance
BUILD_DYNLT flag now adds -DBUILD_DYNLT on the compile command lines and
adds
the DynLT subdirectory to the build process
scenes/dynlt.cc
Reduced default number of samples for texture generation (32 --> 25)
Added "-stats" cmdln parameter to dump summary statistics (if supported by
build)
Register some callbacks for stats collection (if supported by build)
DynLT/DynLTGridSpheres.cc
DynLT/DynLTGridSpheres.h
Added data members and functions to track texture generation latency and
texture generation time for each particle
Added code to increment counters for: requests/frame, textures
generated/frame, etc.
Changed UPDATE_TIME from 5 seconds to 2.5 seconds (the lag was a little too
long)
DynLT/DynLTStatsCollector.cc
DynLT/DynLTStatsCollector.h
Added StatsCollector for interesting things related to dynamic luminance
textures
Use this as an example for doing interesting things with Core/Util/Stat.h
DynLT/DynLTWorker.cc
DynLT/DynLTWorker.h
Track texture generation times for each particle (if supported by build)
Removed DynLTContext (now in its own file, see below)
DynLT/DynLTContext.cc
DynLT/DynLTContext.h
Moved DynLTContext from DynLTWorker to stand-alone source files
DynLT/CMakeLists.txt
Added file for building the Manta_DynLT library from the DynLT sources
Modified: trunk/CMakeLists.txt
==============================================================================
--- trunk/CMakeLists.txt (original)
+++ trunk/CMakeLists.txt Thu Jul 20 21:24:57 2006
@@ -301,7 +301,17 @@
ENDIF(BUILD_FOX)
SET(BUILD_NRRDPARTICLES 0 CACHE BOOL "Build NRRD particle data reader/scene")
-SET(BUILD_DYNPLT 0 CACHE BOOL "Lazily evaluated PLTs for NRRD particle
datasets")
+
+SET(BUILD_DYNLT 0 CACHE BOOL "Lazily evaluated LTs for NRRD particle
datasets")
+IF(BUILD_DYNLT)
+ ADD_DEFINITIONS(-DBUILD_DYNLT)
+ SUBDIRS(DynLT)
+ENDIF(BUILD_DYNLT)
+
+SET(USE_STATS_COLLECTOR 0 CACHE BOOL "Enable stats collection")
+IF(USE_STATS_COLLECTOR)
+ ADD_DEFINITIONS(-DUSE_STATS_COLLECTOR)
+ENDIF(USE_STATS_COLLECTOR)
##################################################################
# Look for Teem
http://teem.sourceforge.net/
Modified: trunk/Core/CMakeLists.txt
==============================================================================
--- trunk/Core/CMakeLists.txt (original)
+++ trunk/Core/CMakeLists.txt Thu Jul 20 21:24:57 2006
@@ -56,6 +56,7 @@
Util/Endian.h
Util/LargeFile.h
Util/LargeFile.cc
+ Util/Stat.h
Util/ThreadStorage.h
Util/ThreadStorage.cc)
Added: trunk/Core/Util/Stat.h
==============================================================================
--- (empty file)
+++ trunk/Core/Util/Stat.h Thu Jul 20 21:24:57 2006
@@ -0,0 +1,108 @@
+#ifndef Manta_Core_Stat_h
+#define Manta_Core_Stat_h
+
+#include <SCIRun/Core/Thread/Mutex.h>
+
+#include <float.h>
+#include <math.h>
+
+using namespace SCIRun;
+
+namespace Manta
+{
+ class Stat
+ {
+#ifndef USE_STATS_COLLECTOR
+ public:
+ Stat(void) { /* no-op */ }
+
+ inline void reset(void) { /* no-op */ }
+ inline void increment(float /* inc_value */ = 1.0f) { /* no-op */ }
+ inline void increment(int /* inc_value */) { /* no-op */ }
+ inline float getTotal(void) { return -1.0f; }
+ inline float getAverage(void) { return -1.0f; }
+ inline float getVariance(void) { return -1.0f; }
+ inline float getDeviation(void) { return -1.0f; }
+ inline float getMinimum(void) { return -1.0f; }
+ inline float getMaximum(void) { return -1.0f; }
+#else
+ public:
+ Stat(void) : mutex("Stat mutex") { reset(); }
+
+ inline void reset(void)
+ {
+ mutex.lock();
+
+ sum_values=sum_squares=num_values=0.0f;
+ min_value=FLT_MAX;
+ max_value =-FLT_MAX;
+
+ mutex.unlock();
+ }
+
+ inline void increment(float inc_value=1.0f)
+ {
+ mutex.lock();
+
+ sum_values += inc_value;
+ sum_squares += (inc_value*inc_value);
+ num_values += 1.0f;
+ if (inc_value<min_value)
+ min_value=inc_value;
+ if (inc_value>max_value)
+ max_value=inc_value;
+
+ mutex.unlock();
+ }
+
+ inline void increment(int inc_value)
+ {
+ increment(static_cast<float>(inc_value));
+ }
+
+ inline float getTotal(void)
+ {
+ return sum_values;
+ }
+
+ inline float getAverage(void)
+ {
+ return sum_values/num_values;
+ }
+
+ inline float getVariance(void)
+ {
+ float inv_n=1.f/num_values;
+ float first=sum_squares*inv_n;
+ float second=sum_values*inv_n;
+ return first - second*second;
+ }
+
+ inline float getDeviation(void)
+ {
+ return sqrt(getVariance());
+ }
+
+ inline float getMinimum(void)
+ {
+ return min_value;
+ }
+
+ inline float getMaximum(void)
+ {
+ return max_value;
+ }
+
+ float sum_values;
+ float sum_squares;
+ float min_value;
+ float max_value;
+ float num_values;
+
+ private:
+ Mutex mutex;
+#endif
+ };
+}
+
+#endif // Manta_Core_Stat_h
Added: trunk/DynLT/CMakeLists.txt
==============================================================================
--- (empty file)
+++ trunk/DynLT/CMakeLists.txt Thu Jul 20 21:24:57 2006
@@ -0,0 +1,17 @@
+
+SET(Manta_DynLT_SRCS
+ DynLTContext.h
+ DynLTContext.cc
+ DynLTGridSpheres.h
+ DynLTGridSpheres.cc
+ DynLTQueue.h
+ DynLTQueue.cc
+ DynLTStatsCollector.h
+ DynLTStatsCollector.cc
+ DynLTWorker.h
+ DynLTWorker.cc
+ )
+
+ADD_LIBRARY(Manta_DynLT ${Manta_DynLT_SRCS})
+
+TARGET_LINK_LIBRARIES(Manta_DynLT Manta_Model SCIRun_Core)
Added: trunk/DynLT/DynLTContext.cc
==============================================================================
--- (empty file)
+++ trunk/DynLT/DynLTContext.cc Thu Jul 20 21:24:57 2006
@@ -0,0 +1,26 @@
+
+#include <DynLT/DynLTContext.h>
+#include <SCIRun/Core/Math/Expon.h>
+#include <SCIRun/Core/Math/MiscMath.h>
+
+using namespace Manta;
+using namespace SCIRun;
+
+DynLTContext::DynLTContext(MantaInterface* manta_interface,
+ DynLTQueue* queue,
+ Scene* scene, unsigned int ngroups,
+ unsigned int nsamples, unsigned int max_depth,
+ bool dilate, Background* background, double
runtime,
+ unsigned int minproc, unsigned int maxproc,
+ Real Kd, Real Ka) :
+ manta_interface(manta_interface),
+ queue(queue), scene(scene), ngroups(ngroups), nsamples(nsamples),
+ max_depth(max_depth), dilate(dilate), background(background),
runtime(runtime),
+ minproc(minproc), maxproc(maxproc), Kd(Kd), Ka(Ka)
+{
+ // Ensure that the number of samples is a perfect square
+ nsamples_root=static_cast<int>(Ceil(Sqrt(static_cast<Real>(nsamples))));
+ unsigned int squared=nsamples_root*nsamples_root;
+ if (squared != nsamples)
+ nsamples=squared;
+}
Added: trunk/DynLT/DynLTContext.h
==============================================================================
--- (empty file)
+++ trunk/DynLT/DynLTContext.h Thu Jul 20 21:24:57 2006
@@ -0,0 +1,60 @@
+
+#ifndef Manta_DynLT_DynLTContext_h
+#define Manta_DynLT_DynLTContext_h
+
+#include <MantaTypes.h>
+
+#include <float.h>
+#include <limits.h>
+
+namespace Manta
+{
+ class Background;
+ class DynLTContext;
+ class DynLTMessage;
+ class DynLTQueue;
+ class MantaInterface;
+ class Scene;
+
+ class DynLTContext
+ {
+ public:
+ DynLTContext(MantaInterface* manta_interface,
+ DynLTQueue* queue, Scene* scene,
+ unsigned int ngroups, unsigned int nsamples,
+ unsigned int max_depth, bool dilate,
+ Background* background, double runtime=DBL_MAX,
+ unsigned int minproc=0, unsigned int maxproc=INT_MAX,
+ Real Kd=0.6, Real Ka=0.4);
+ ~DynLTContext(void) { }
+
+ // Manta interface
+ MantaInterface* manta_interface;
+
+ // DynLT work queue
+ DynLTQueue* queue;
+
+ // Manta scene
+ Scene* scene;
+ Background* background;
+
+ // Texture generation parameters
+ unsigned int ngroups;
+ unsigned int nsamples;
+ unsigned int nsamples_root;
+ unsigned int max_depth;
+ double runtime;
+ unsigned int minproc;
+ unsigned int maxproc;
+ Real Ka;
+ Real Kd;
+
+ // Texture dilation parameters
+ bool dilate;
+ unsigned int support;
+ unsigned int use_weighted_avg;
+ Real threshold;
+ };
+}
+
+#endif // Manta_DynLT_DynLTContext_h
Added: trunk/DynLT/DynLTGridSpheres.cc
==============================================================================
--- (empty file)
+++ trunk/DynLT/DynLTGridSpheres.cc Thu Jul 20 21:24:57 2006
@@ -0,0 +1,315 @@
+
+#include <Core/Color/RegularColorMap.h>
+#include <DynLT/DynLTContext.h>
+#include <DynLT/DynLTGridSpheres.h>
+#include <DynLT/DynLTQueue.h>
+#include <DynLT/DynLTWorker.h>
+#include <Interface/AmbientLight.h>
+#include <Interface/LightSet.h>
+#include <Interface/RayPacket.h>
+
+#include <iostream>
+using std::cerr;
+
+using namespace Manta;
+using namespace SCIRun;
+
+#define UPDATE_TIME 2.5
+
+DynLTGridSpheres::DynLTGridSpheres(DynLTQueue* queue,
+ float* spheres, int nspheres, int nvars,
+ int ncells, int depth, Real radius,
+ int ridx, RegularColorMap* cmap, int
cidx) :
+ queue(queue), GridSpheres(spheres, nspheres, nvars, ncells, depth, radius,
+ ridx, cmap, cidx)
+{
+ cerr<<"Initializing DynLTGridSpheres\n";
+ plts.resize(nspheres);
+ valid.resize(nspheres);
+ allocated.resize(nspheres);
+ requested.resize(nspheres);
+#ifdef USE_STATS_COLLECTOR
+ latency.resize(nspheres);
+ texgen.resize(nspheres);
+#endif
+ for (unsigned int i=0; i<nspheres; ++i) {
+ plts[i]=0;
+ requested[i]=0;
+ allocated[i]=false;
+ valid[i]=false;
+#ifdef USE_STATS_COLLECTOR
+ latency[i]=0;
+ texgen[i]=0;
+#endif
+ }
+
+ // XXX: hard coded for now
+ // textureMode=AmbientOcclusion;
+ textureMode=GlobalIllumination;
+}
+
+DynLTGridSpheres::~DynLTGridSpheres(void)
+{
+ // Do nothing
+}
+
+void DynLTGridSpheres::shade(const RenderContext& context,
+ RayPacket& rays) const
+{
+ switch (textureMode) {
+ case AmbientOcclusion:
+ shadeAmbient(context, rays);
+ break;
+ case GlobalIllumination:
+ default:
+ shadeGlobal(context, rays);
+ break;
+ }
+}
+
+void DynLTGridSpheres::shadeAmbient(const RenderContext& context,
+ RayPacket& rays) const
+{
+ ColorArray ambient;
+
+ for (unsigned int i=rays.begin(); i<rays.end(); ) {
+ // Find a run of rays that hit the same particle
+ int offset=rays.scratchpad<int>(i);
+ unsigned int end=i + 1;
+ while (end < rays.end() && rays.scratchpad<int>(end)==offset)
+ ++end;
+
+ int particle=offset/nvars;
+
+ // Compute ambient light for the rays
+ RayPacket sub(rays, i, end);
+ if (valid[particle]) {
+ // Compute diffuse colors
+ Packet<Color> diffuse;
+ mapDiffuseColors(diffuse, sub);
+
+ // Compute textured ambient luminance
+ sub.computeTextureCoordinates2(context);
+
+ for (unsigned int i=sub.begin(); i<sub.end(); ++i) {
+ Real luminance=computeLuminance(i, sub, particle);
+ for (int j=0; j < Color::NumComponents; ++j)
+ ambient[j][i]=luminance;
+ }
+ } else {
+ // Request texture generation, if necessary
+ if (requested[particle]==0.) {
+#ifdef USE_STATS_COLLECTOR
+ // Store request time
+ latency[particle]=Time::currentSeconds();
+
+ // Increment number of requests
+ DynLTStatsCollector::TexturesRequestedPerFrame.increment();
+#endif
+
+ // Create and post message
+ double priority=computePriority(rays.getMinT(i));
+ DynLTMessage msg(particle, priority, this);
+ if (queue->trySend(msg))
+ requested[particle]=priority;
+ } else {
+#ifdef UPDATE_TIME
+ // Update priority only after UPDATE_TIME seconds
+ if (Time::currentSeconds() - requested[particle] > UPDATE_TIME) {
+ requested[particle]=computePriority(rays.getMinT(i));
+ queue->updatePriority(particle, requested[particle]);
+ }
+#else
+ requested[particle]=computePriority(rays.getMinT(i));
+ queue->updatePriority(particle, requested[particle]);
+#endif
+ }
+
+ // Use default ambient light while texture is invalid
+ activeLights->getAmbientLight()->computeAmbient(context, sub, ambient);
+ }
+
+ i=end;
+ }
+
+ // Shade the rays
+ GridSpheres::lambertianShade(context, rays, ambient);
+}
+
+void DynLTGridSpheres::shadeGlobal(const RenderContext& context,
+ RayPacket& rays) const
+{
+ for (unsigned int i=rays.begin(); i<rays.end(); ) {
+ // Find a run of rays that hit the same particle
+ int offset=rays.scratchpad<int>(i);
+ unsigned int end=i + 1;
+ while (end < rays.end() && rays.scratchpad<int>(end)==offset)
+ ++end;
+
+ int particle=offset/nvars;
+
+ // Shade the rays
+ RayPacket sub(rays, i, end);
+ if (valid[particle]) {
+ // Compute diffuse colors
+ Packet<Color> diffuse;
+ mapDiffuseColors(diffuse, rays);
+
+ // Compute textured luminance
+ sub.computeTextureCoordinates2(context);
+
+ for (unsigned int i=sub.begin(); i<sub.end(); ++i) {
+ Real luminance=computeLuminance(i, rays, particle);
+ sub.setColor(i, diffuse.get(i)*luminance);
+ }
+ } else {
+ // Request texture generation, if necessary
+ if (requested[particle]==0.) {
+#ifdef USE_STATS_COLLECTOR
+ // Store request time
+ latency[particle]=Time::currentSeconds();
+
+ // Increment number of requests
+ DynLTStatsCollector::TexturesRequestedPerFrame.increment();
+#endif
+
+ // Create and post message
+ double priority=computePriority(rays.getMinT(i));
+ DynLTMessage msg(particle, priority, this);
+ if (queue->trySend(msg))
+ requested[particle]=priority;
+ } else {
+#ifdef UPDATE_TIME
+ // Update priority only after UPDATE_TIME seconds
+ if (Time::currentSeconds() - requested[particle] > UPDATE_TIME) {
+ requested[particle]=computePriority(rays.getMinT(i));
+ queue->updatePriority(particle, requested[particle]);
+ }
+#else
+ requested[particle]=computePriority(rays.getMinT(i));
+ queue->updatePriority(particle, requested[particle]);
+#endif
+ }
+
+ // Use Lambertian shading while texture is invalid
+ GridSpheres::shade(context, sub);
+ }
+
+ i=end;
+ }
+}
+
+Real DynLTGridSpheres::computeLuminance(unsigned int ray_idx, RayPacket&
rays,
+ unsigned int particle) const
+{
+ // Wrap in x (assumes xres is a power of two)
+ Real x=rays.getTexCoords2(ray_idx, 0)*XRES;
+ int lx=static_cast<int>(x) & (XRES - 1);
+ int hx=(lx + 1) & (XRES - 1);
+ Real wx=x - lx;
+
+ // Clamp in y
+ Real y=rays.getTexCoords2(ray_idx, 1);
+ int ly;
+ Real wy;
+ if (y < 0) {
+ ly=0;
+ wy=0;
+ } else {
+ y *= YRES - 1;
+ ly=static_cast<int>(y);
+ if (ly > YRES - 1) {
+ ly=YRES - 1;
+ wy=0;
+ } else {
+ wy=y - ly;
+ }
+ }
+
+ int hy=ly + 1;
+
+ // Bi-linearly interpolate
+ Real a=(plts[particle]->texture[lx][ly]*(1 - wx) +
+ plts[particle]->texture[hx][ly]*wx);
+ Real b=(plts[particle]->texture[lx][hy]*(1 - wx) +
+ plts[particle]->texture[hx][hy]*wx);
+
+ return a*(1 - wy) + b*wy;
+}
+
+void DynLT::dilate(const DynLTContext* context)
+{
+ // Compute the min and max of inside texture
+ unsigned int width=XRES;
+ unsigned int height=YRES;
+ Real min=inside[0][0];
+ Real max=inside[0][0];
+ for (unsigned int y=1; y<height; ++y) {
+ for (unsigned int x=1; x<width; ++x) {
+ Real tmp=inside[x][y];
+ if (tmp < min)
+ min=tmp;
+ if (tmp > max)
+ max=tmp;
+ }
+ }
+
+ // Normalize the inside texture
+ Real inv_maxmin=1/(max-min);
+ for (unsigned int y=0; y<height; ++y)
+ for (unsigned int x=0; x<width; ++x)
+ inside[x][y]=(inside[x][y] - min)*inv_maxmin;
+
+ // Initialize the dilated texture
+ Real dilated[XRES][YRES];
+ for (unsigned int y=0; y<height; ++y)
+ for (unsigned int x=0; x<width; ++x)
+ dilated[x][y]=texture[x][y];
+
+ // Dilate any necessary pixels
+ unsigned int support=context->support;
+ unsigned int use_weighted_avg=context->use_weighted_avg;
+ Real threshold=context->threshold;
+
+ for (unsigned int y=0; y < height; ++y) {
+ for (unsigned int x=0; x < width; ++x) {
+ // Determine if the pixel should be dilated
+ Real value=inside[x][y];
+ if (value<=0)
+ continue;
+
+ // Loop over each neighbor
+ Real avg=0;
+ Real contribution_total=0;
+ for (unsigned int j=y-support; j <= y+support; j++) {
+ for (unsigned int i=x-support; i <= x+support; i++) {
+ // Check boundary conditions
+ unsigned int newi=i;
+ if (newi >= width)
+ newi=newi - width;
+
+ unsigned int newj=j;
+ if (newj >= height)
+ newj=height - 1;
+
+ // Determine neighbor's contribution
+ Real contributer=inside[newi][newj];
+ if (contributer < threshold) {
+ contributer *= use_weighted_avg;
+ avg += texture[newi][newj]*(1 - contributer);
+ contribution_total += (1 - contributer);
+ }
+ }
+ }
+
+ // Dilate the pixel
+ if (contribution_total > 0)
+ dilated[x][y]=avg/contribution_total;
+ }
+ }
+
+ // Update texture with dilated results
+ for (unsigned int y=0; y<height; ++y)
+ for (unsigned int x=0; x<width; ++x)
+ texture[x][y]=dilated[x][y];
+}
Added: trunk/DynLT/DynLTGridSpheres.h
==============================================================================
--- (empty file)
+++ trunk/DynLT/DynLTGridSpheres.h Thu Jul 20 21:24:57 2006
@@ -0,0 +1,171 @@
+
+#ifndef Manta_DynLT_DynLTGridSpheres_h
+#define Manta_DynLT_DynLTGridSpheres_h
+
+#include <DynLT/DynLTStatsCollector.h>
+#include <Model/Primitives/GridSpheres.h>
+#include <SCIRun/Core/Thread/Mailbox.h>
+#include <SCIRun/Core/Thread/Time.h>
+
+#include <vector>
+using std::vector;
+
+#include <float.h>
+
+using namespace SCIRun;
+
+#define XRES 16
+#define YRES 16
+
+namespace Manta {
+ class DynLTContext;
+ class DynLTQueue;
+ class RegularColorMap;
+
+ class DynLT {
+ public:
+ DynLT(void) { }
+ ~DynLT(void) { }
+
+ unsigned int getXRes(void) const { return XRES; }
+ unsigned int getYRes(void) const { return YRES; }
+
+ void dilate(const DynLTContext* context);
+
+ // Luminance texture data
+ Real texture[XRES][YRES];
+ Real inside[XRES][YRES];
+ };
+
+ class DynLTGridSpheres : public GridSpheres
+ {
+ public:
+ enum {
+ AmbientOcclusion,
+ GlobalIllumination
+ } TextureMode;
+
+ DynLTGridSpheres(DynLTQueue* queue, float* spheres,
+ int nspheres, int nvars, int ncells, int depth,
+ Real radius, int ridx, RegularColorMap* cmap, int cidx);
+ ~DynLTGridSpheres(void);
+
+ void shade(const RenderContext& context, RayPacket& rays) const;
+
+ const LightSet* getActiveLights(void) const { return activeLights; }
+
+ unsigned int getTextureMode(void) const { return textureMode; }
+
+ void setTextureMode(unsigned int mode)
+ {
+ if (textureMode != mode) {
+ invalidateTextures();
+ textureMode=mode;
+ }
+ }
+
+ Vector getCenter(int particle) const
+ {
+ float* data=spheres + particle*nvars;
+ return Vector(data[0], data[1], data[2]);
+ }
+
+ Real getRadius(int particle) const
+ {
+ float* data=spheres + particle*nvars;
+ if (ridx>0) {
+ if (data[ridx] <= 0)
+ return radius;
+ else
+ return data[ridx];
+ }
+
+ return radius;
+ }
+
+ bool isValid(int idx) {
+ return valid[idx];
+ }
+
+ bool isAllocated(int idx) {
+ return allocated[idx];
+ }
+
+ void setValid(int idx) {
+ valid[idx]=true;
+
+#ifdef USE_STATS_COLLECTOR
+ // Compute latency and increment counter
+ latency[idx]=Time::currentSeconds() - latency[idx];
+
DynLTStatsCollector::TexGenLatency.increment(static_cast<float>(latency[idx]));
+#endif
+ }
+
+ void allocate(int idx) {
+ plts[idx]=new DynLT();
+ allocated[idx]=true;
+ }
+
+ void dilate(const DynLTContext* context, int idx) {
+ plts[idx]->dilate(context);
+ }
+
+ DynLT* getTexture(int idx) {
+ return plts[idx];
+ }
+
+ double computePriority(Real t) const {
+ // Time-stamp only
+ return Time::currentSeconds();
+
+ // Distance only (closest first)
+ // return DBL_MAX - t;
+
+ // Time-stamp and distance
+ // return Time::currentSeconds() + (DBL_MAX - t);
+ }
+
+ void resetRequested(int idx) {
+ requested[idx]=0.;
+ }
+
+#ifdef USE_STATS_COLLECTOR
+ void setTexGenTime(int idx, double time)
+ {
+ // Set texture generation time and increment counters
+ texgen[idx]=time;
+
DynLTStatsCollector::TexGenTime.increment(static_cast<float>(texgen[idx]));
+ DynLTStatsCollector::TexturesGeneratedPerFrame.increment();
+ }
+#endif
+
+ private:
+ void shadeAmbient(const RenderContext& context, RayPacket& rays) const;
+ void shadeGlobal(const RenderContext& context, RayPacket& rays) const;
+ Real computeLuminance(unsigned int ray_idx, RayPacket& rays,
+ unsigned int particle) const;
+
+ void invalidateTextures(void)
+ {
+ for (unsigned int i=0; i<nspheres; ++i) {
+ requested[i]=0;
+ valid[i]=false;
+ }
+ }
+
+ DynLTQueue* queue;
+ mutable vector<double> requested;
+ vector<bool> allocated;
+ vector<bool> valid;
+ vector<DynLT*> plts;
+
+ unsigned int textureMode;
+
+#ifdef USE_STATS_COLLECTOR
+ mutable vector<double> latency;
+ mutable vector<double> texgen;
+#endif
+ };
+}
+
+#endif // Manta_DynLT_DynLTGridSpheres_h
Added: trunk/DynLT/DynLTQueue.cc
==============================================================================
--- (empty file)
+++ trunk/DynLT/DynLTQueue.cc Thu Jul 20 21:24:57 2006
@@ -0,0 +1,355 @@
+
+#include <DynLT/DynLTGridSpheres.h>
+#include <DynLT/DynLTQueue.h>
+
+#include <iostream>
+using std::cerr;
+
+using namespace Manta;
+
+DynLTLifoQ::DynLTLifoQ(int size) :
+ mutex("LifoQ lock"), empty("LifoQ empty condition"),
+ full("LifoQ full condition"), top(-1), max_size(size)
+{
+ // Allocate dataspace
+ dataspace=new char[max_size*sizeof(DynLTMessage)];
+ queue=reinterpret_cast<DynLTMessage*>(dataspace);
+}
+
+DynLTLifoQ::~DynLTLifoQ(void)
+{
+ // Release all waiting threads
+ empty.conditionBroadcast();
+ full.conditionBroadcast();
+
+ // Free dataspace
+ delete [] dataspace;
+}
+
+bool DynLTLifoQ::tryReceive(DynLTMessage& msg)
+{
+ mutex.lock();
+
+ // Return false if queue is empty
+ if (top==-1) {
+ mutex.unlock();
+ return false;
+ }
+
+ // Pop top item from the queue
+ msg=pop();
+
+ mutex.unlock();
+
+ return true;
+}
+
+DynLTMessage DynLTLifoQ::receive(void)
+{
+ mutex.lock();
+
+ // Block calling thread while queue is empty
+ while (top==-1)
+ empty.wait(mutex);
+
+ // Pop top item from the queue
+ DynLTMessage msg=pop();
+
+ mutex.unlock();
+
+ return msg;
+}
+
+bool DynLTLifoQ::trySend(const DynLTMessage& msg)
+{
+ mutex.lock();
+
+ // Return false if queue is full
+ if (top==max_size - 1) {
+ mutex.unlock();
+ return false;
+ }
+
+ push(msg);
+ mutex.unlock();
+
+ return true;
+}
+
+void DynLTLifoQ::send(const DynLTMessage& msg)
+{
+ mutex.lock();
+
+ // Block calling thread while queue is full
+ while (top==max_size - 1)
+ full.wait(mutex);
+
+ push(msg);
+ mutex.unlock();
+}
+
+DynLTPriorityQ::DynLTPriorityQ(int size) :
+ mutex("PriorityQ lock"), empty("PriorityQ empty condition"),
+ full("PriorityQ full condition"), nheap(0), max_size(size)
+{
+ // Allocate dataspace
+ dataspace=new char[max_size*sizeof(DynLTMessage)];
+ heap=reinterpret_cast<DynLTMessage*>(dataspace);
+}
+
+DynLTPriorityQ::~DynLTPriorityQ(void)
+{
+ // Release all waiting threads
+ empty.conditionBroadcast();
+ full.conditionBroadcast();
+
+ // Free dataspace
+ delete [] dataspace;
+
+#ifndef FIXED_SIZE_QUEUE
+ delete [] heap_idx;
+#endif
+}
+
+bool DynLTPriorityQ::tryReceive(DynLTMessage& msg)
+{
+ mutex.lock();
+
+ // Return false if heap is empty
+ if (nheap==0) {
+ mutex.unlock();
+ return false;
+ }
+
+ // Pop top item from the heap
+ msg=pop();
+
+ mutex.unlock();
+
+ return true;
+}
+
+DynLTMessage DynLTPriorityQ::receive(void)
+{
+ mutex.lock();
+
+ // Block calling thread while heap is empty
+ while (nheap==0)
+ empty.wait(mutex);
+
+ // Pop top item from the heap
+ DynLTMessage msg=pop();
+
+ mutex.unlock();
+
+ return msg;
+}
+
+bool DynLTPriorityQ::trySend(const DynLTMessage& msg)
+{
+ mutex.lock();
+
+ // Return false if heap is full
+ if (nheap==max_size) {
+ mutex.unlock();
+ return false;
+ }
+
+ push(msg);
+ mutex.unlock();
+
+ return true;
+}
+
+void DynLTPriorityQ::send(const DynLTMessage& msg)
+{
+ mutex.lock();
+
+ // Block calling thread while heap is full
+ while (nheap==max_size)
+ full.wait(mutex);
+
+ push(msg);
+ mutex.unlock();
+}
+
+void DynLTPriorityQ::updatePriority(int particle, double priority)
+{
+#ifdef FIXED_SIZE_QUEUE
+ mutex.lock();
+
+ for (unsigned int i=0; i<nheap; ++i) {
+ if (heap[i].particle == particle) {
+ // Found particle, create new node with updated priority
+ DynLTMessage msg(particle, priority, heap[i].grid);
+
+ // Staring at old node's position in the heap, walk new node up the
heap
+ // until its priority is less than its parent's
+ int parent=(i + 1)/2 - 1;
+ while (i && heap[parent].priority < priority) {
+ heap[i]=heap[parent];
+ i=parent;
+ parent=(i + 1)/2 - 1;
+ }
+
+ // Insert message
+ heap[i]=msg;
+
+ break;
+ }
+ }
+
+ mutex.unlock();
+#else
+ mutex.lock();
+
+ int idx=heap_idx[particle];
+ if (idx>-1) {
+ // Found particle, create new message with updated priority
+ DynLTMessage msg(particle, priority, heap[idx].grid);
+
+ // Staring at old node's position in the heap, walk new node up the heap
+ // until its priority is less than its parent's
+ int parent=(idx + 1)/2 - 1;
+ while (idx && heap[parent].priority < priority) {
+ // Swap parent
+ heap[idx]=heap[parent];
+ heap_idx[heap[idx].particle]=idx;
+
+ idx=parent;
+ parent=(idx + 1)/2 - 1;
+ }
+
+ // Insert message and update heap_idx
+ heap[idx]=msg;
+ heap_idx[particle]=idx;
+ }
+
+ mutex.unlock();
+#endif
+}
+
+void DynLTPriorityQ::push(DynLTMessage const& msg)
+{
+#ifdef FIXED_SIZE_QUEUE
+ // NOTE: This code is supposed to implement a fixed size queue in which
old
+ // requests (i.e., low priority) are dropped and new ones added; it
+ // sort of works, but I'm not sure it's bullet proof yet...
+ if (nheap<max_size) {
+ // Increment number of nodes in the heap
+ ++nheap;
+
+ // Walk node up the heap until its priority is less than its parent's
+ int i=nheap - 1;
+ int parent=(i + 1)/2 - 1;
+ while (i && heap[parent].priority < msg.priority) {
+ heap[i]=heap[parent];
+ i=parent;
+ parent=(i + 1)/2 - 1;
+ }
+
+ // Insert message and update heap_idx
+ heap[i]=msg;
+ } else {
+ // Drop last node
+ DynLTMessage last=heap[nheap-1];
+ DynLTGridSpheres* grid=const_cast<DynLTGridSpheres*>(last.grid);
+ grid->resetRequested(last.particle);
+
+ // Move old root to end, insert new node at root, and rebuild
+ heap[nheap-1]=heap[0];
+ heap[0]=msg;
+ heapify(0, nheap);
+ }
+#else
+ // NOTE: In theory, the following code allows the queue to grow without
bound.
+ // However, in practice, the heap reaches some semi-stable size as
+ // texture generation requests are produced/consumed by the threads
+ ++nheap;
+ if (nheap>=max_size) {
+ // Save old dataspace, allocate new dataspace
+ char* oldspace=dataspace;
+ dataspace=new char[2*max_size*sizeof(DynLTMessage)];
+
+ // Copy current elements
+ memcpy(reinterpret_cast<void*>(dataspace),
+ reinterpret_cast<void*>(oldspace),
+ (nheap - 1)*sizeof(DynLTMessage));
+
+ // Release old dataspace
+ delete [] oldspace;
+
+ // Update heap pointer and max_size
+ heap=reinterpret_cast<DynLTMessage*>(dataspace);
+ max_size *= 2;
+
+ /*
+ cerr<<"Heap is now "<<max_size*sizeof(DynLTMessage)<<" bytes
("<<max_size
+ <<" messages)\n";
+ */
+ }
+
+ // Walk node up the heap until its priority is less than its parent's
+ int i=nheap - 1;
+ int parent=(i + 1)/2 - 1;
+ while (i && heap[parent].priority < msg.priority) {
+ heap[i]=heap[parent];
+ heap_idx[heap[i].particle]=i;
+
+ i=parent;
+ parent=(i + 1)/2 - 1;
+ }
+
+ // Insert message and update heap_idx
+ heap[i]=msg;
+ heap_idx[msg.particle]=i;
+#endif
+}
+
+DynLTMessage DynLTPriorityQ::pop(void)
+{
+ // Grab first message
+ DynLTMessage msg=heap[0];
+#ifndef FIXED_SIZE_QUEUE
+ heap_idx[msg.particle]=-1;
+#endif
+
+ // Rebuild the heap
+ --nheap;
+ heap[0]=heap[nheap];
+#ifndef FIXED_SIZE_QUEUE
+ heap_idx[heap[0].particle]=0;
+#endif
+ heapify(0, nheap);
+
+ return msg;
+}
+
+void DynLTPriorityQ::heapify(int i, int nnodes)
+{
+ // Initialize indices of left/right children
+ int highest=i;
+ int l=2*i + 1;
+ int r=l + 1;
+
+ // Find index of node with highest priority
+ if (l<nnodes && heap[l].priority > heap[highest].priority)
+ highest=l;
+
+ if (r<nnodes && heap[r].priority > heap[highest].priority)
+ highest=r;
+
+ // Swap heap[i] and heap[highest]
+ if (highest != i) {
+ DynLTMessage tmp=heap[i];
+ heap[i]=heap[highest];
+ heap[highest]=tmp;
+#ifndef FIXED_SIZE_QUEUE
+ heap_idx[heap[i].particle]=i;
+ heap_idx[heap[highest].particle]=highest;
+#endif
+
+ // Recursively build the heap
+ heapify(highest, nnodes);
+ }
+}
Added: trunk/DynLT/DynLTQueue.h
==============================================================================
--- (empty file)
+++ trunk/DynLT/DynLTQueue.h Thu Jul 20 21:24:57 2006
@@ -0,0 +1,160 @@
+
+#ifndef Manta_DynLT_DynLTQueue_h
+#define Manta_DynLT_DynLTQueue_h
+
+#include <MantaTypes.h>
+#include <SCIRun/Core/Thread/Mailbox.h>
+#include <SCIRun/Core/Thread/ConditionVariable.h>
+#include <SCIRun/Core/Thread/Mutex.h>
+
+using namespace SCIRun;
+
+// #define FIXED_SIZE_QUEUE
+
+namespace Manta
+{
+ class DynLTGridSpheres;
+
+ struct DynLTMessage {
+ DynLTMessage(int particle, double priority, const DynLTGridSpheres*
grid) :
+ particle(particle), priority(priority), grid(grid)
+ {
+ // Do nothing
+ }
+
+ DynLTMessage(void) :
+ particle(-1), priority(0), grid(0)
+ {
+ // Do nothing
+ }
+
+ int particle;
+ double priority;
+ const DynLTGridSpheres* grid;
+ };
+
+ class DynLTQueue
+ {
+ public:
+ DynLTQueue(void) { /* no-op */ }
+ ~DynLTQueue(void) { /* no-op */ }
+
+ virtual bool tryReceive(DynLTMessage& msg) = 0;
+ virtual DynLTMessage receive(void) = 0;
+
+ virtual bool trySend(const DynLTMessage& msg) = 0;
+ virtual void send(const DynLTMessage& msg) = 0;
+
+ virtual void updatePriority(int particle, double priority) { /* no-op */
}
+ virtual void resizeHeapIdx(unsigned int nparticles_) { /* no-op */ }
+ };
+
+ class DynLTFifoQ : public DynLTQueue
+ {
+ public:
+ DynLTFifoQ(int size)
+ {
+ mailbox=new SCIRun::Mailbox<DynLTMessage>("DynLT Work Queue", size);
+ }
+
+ ~DynLTFifoQ(void)
+ {
+ delete mailbox;
+ }
+
+ bool tryReceive(DynLTMessage& msg)
+ {
+ return mailbox->tryReceive(msg);
+ }
+
+ DynLTMessage receive(void)
+ {
+ return mailbox->receive();
+ }
+
+ bool trySend(const DynLTMessage& msg)
+ {
+ mailbox->trySend(msg);
+ }
+
+ void send(const DynLTMessage& msg)
+ {
+ mailbox->send(msg);
+ }
+
+ private:
+ SCIRun::Mailbox<DynLTMessage>* mailbox;
+ };
+
+ class DynLTLifoQ : public DynLTQueue
+ {
+ public:
+ DynLTLifoQ(int size);
+ ~DynLTLifoQ(void);
+
+ bool tryReceive(DynLTMessage& msg);
+ DynLTMessage receive(void);
+ bool trySend(const DynLTMessage& msg);
+ void send(const DynLTMessage& msg);
+
+ private:
+ void push(DynLTMessage const& msg) { queue[++top]=msg; }
+ DynLTMessage pop(void) { return queue[top--]; }
+
+ // Thread control
+ Mutex mutex;
+ ConditionVariable empty;
+ ConditionVariable full;
+
+ // Data variables
+ DynLTMessage* queue;
+ char* dataspace;
+ int max_size;
+ int top;
+ };
+
+ class DynLTPriorityQ : public DynLTQueue
+ {
+ public:
+ DynLTPriorityQ(int size);
+ ~DynLTPriorityQ(void);
+
+ bool tryReceive(DynLTMessage& msg);
+ DynLTMessage receive(void);
+ bool trySend(const DynLTMessage& msg);
+ void send(const DynLTMessage& msg);
+
+ void updatePriority(int particle, double priority);
+#ifndef FIXED_SIZE_QUEUE
+ void resizeHeapIdx(unsigned int nparticles_)
+ {
+ nparticles=nparticles_;
+ heap_idx=new int[nparticles];
+ for (unsigned int i=0; i<nparticles; ++i)
+ heap_idx[i]=-1;
+ }
+#endif
+
+ private:
+ void push(DynLTMessage const& msg);
+ DynLTMessage pop(void);
+ void heapify(int i, int nnodes);
+
+ // Thread control
+ Mutex mutex;
+ ConditionVariable empty;
+ ConditionVariable full;
+
+ // Data variables
+ DynLTMessage* heap;
+ char* dataspace;
+ int max_size;
+ int nheap;
+#ifndef FIXED_SIZE_QUEUE
+ int* heap_idx;
+ unsigned int nparticles;
+#endif
+ };
+}
+
+#endif // Manta_DynLT_DynLTQueue_h
Added: trunk/DynLT/DynLTStatsCollector.cc
==============================================================================
--- (empty file)
+++ trunk/DynLT/DynLTStatsCollector.cc Thu Jul 20 21:24:57 2006
@@ -0,0 +1,61 @@
+#include <DynLT/DynLTStatsCollector.h>
+
+#include <iostream>
+using std::cerr;
+
+using namespace Manta;
+
+void DynLTStatsCollector::resetPerFrameStats(int /* unused */, int /* unused
*/)
+{
+#if 0
+ cerr<<"Per-frame stats\n";
+ cerr<<" Requests:\t"<<TexturesRequestedPerFrame.getTotal()<<'\n';
+ cerr<<" Generated:\t"<<TexturesGeneratedPerFrame.getTotal()<<'\n';
+#endif
+
+ // Increment total counters
+ TexturesRequested.increment(TexturesRequestedPerFrame.getTotal());
+ TexturesGenerated.increment(TexturesGeneratedPerFrame.getTotal());
+
+ // Reset per-frame counters
+ TexturesRequestedPerFrame.reset();
+ TexturesGeneratedPerFrame.reset();
+}
+
+void DynLTStatsCollector::dump(MantaInterface* /* unused */)
+{
+ cerr<<'\n';
+ cerr<<"Texture generation latency\n";
+ cerr<<" Average:\t"<<TexGenLatency.getAverage()<<" seconds\n";
+ cerr<<" Minimum:\t"<<TexGenLatency.getMinimum()<<" seconds\n";
+ cerr<<" Maximum:\t"<<TexGenLatency.getMaximum()<<" seconds\n";
+ cerr<<'\n';
+ cerr<<"Texture generation time\n";
+ cerr<<" Average:\t"<<TexGenTime.getAverage()<<" seconds\n";
+ cerr<<" Minimum:\t"<<TexGenTime.getMinimum()<<" seconds\n";
+ cerr<<" Maximum:\t"<<TexGenTime.getMaximum()<<" seconds\n";
+ cerr<<" ------------------------------\n";
+ cerr<<" Total:\t"<<TexGenTime.getTotal()<<" seconds\n";
+ cerr<<'\n';
+ cerr<<"Textures requested\n";
+ cerr<<" Average:\t"<<TexturesRequested.getAverage()<<'\n';
+ cerr<<" Minimum:\t"<<TexturesRequested.getMinimum()<<'\n';
+ cerr<<" Maximum:\t"<<TexturesRequested.getMaximum()<<'\n';
+ cerr<<" ------------------------------\n";
+ cerr<<" Total:\t"<<TexturesRequested.getTotal()<<'\n';
+ cerr<<'\n';
+ cerr<<"Textures generated\n";
+ cerr<<" Average:\t"<<TexturesGenerated.getAverage()<<'\n';
+ cerr<<" Minimum:\t"<<TexturesGenerated.getMinimum()<<'\n';
+ cerr<<" Maximum:\t"<<TexturesGenerated.getMaximum()<<'\n';
+ cerr<<" ------------------------------\n";
+ cerr<<" Total:\t"<<TexturesGenerated.getTotal()<<'\n';
+ cerr<<'\n';
+}
+
+Stat DynLTStatsCollector::TexGenLatency;
+Stat DynLTStatsCollector::TexGenTime;
+Stat DynLTStatsCollector::TexturesRequested;
+Stat DynLTStatsCollector::TexturesRequestedPerFrame;
+Stat DynLTStatsCollector::TexturesGenerated;
+Stat DynLTStatsCollector::TexturesGeneratedPerFrame;
Added: trunk/DynLT/DynLTStatsCollector.h
==============================================================================
--- (empty file)
+++ trunk/DynLT/DynLTStatsCollector.h Thu Jul 20 21:24:57 2006
@@ -0,0 +1,31 @@
+
+#ifndef Manta_DynLT_DynLTStatsCollector_h
+#define Manta_DynLT_DynLTStatsCollector_h
+
+#include <Core/Util/Stat.h>
+
+namespace Manta
+{
+ class MantaInterface;
+
+ class DynLTStatsCollector
+ {
+ public:
+ static void resetPerFrameStats(int, int);
+ static void dump(MantaInterface*);
+
+ // Per-particle stats
+ static Stat TexGenLatency;
+ static Stat TexGenTime;
+
+ // Per-frame stats
+ static Stat TexturesRequestedPerFrame;
+ static Stat TexturesGeneratedPerFrame;
+
+ // Per-session stats
+ static Stat TexturesRequested;
+ static Stat TexturesGenerated;
+ };
+}
+
+#endif // Manta_DynLT_DynLTStatsCollector_h
Added: trunk/DynLT/DynLTWorker.cc
==============================================================================
--- (empty file)
+++ trunk/DynLT/DynLTWorker.cc Thu Jul 20 21:24:57 2006
@@ -0,0 +1,585 @@
+
+#include <DynLT/DynLTContext.h>
+#include <DynLT/DynLTGridSpheres.h>
+#include <DynLT/DynLTQueue.h>
+#include <DynLT/DynLTWorker.h>
+#include <Interface/Background.h>
+#include <Interface/Context.h>
+#include <Interface/Packet.h>
+#include <Interface/Scene.h>
+#include <Engine/Shadows/HardShadows.h>
+#include <Model/Primitives/Sphere.h>
+#include <SCIRun/Core/Thread/Time.h>
+
+#include <string>
+
+using namespace Manta;
+using namespace SCIRun;
+using namespace std;
+
+// XXX: the exit strategy for static thread scheduling only works
occasionally
+// (no segfault) when the queue isn't empty, and never when it is empty
+
+DynLTWorker::DynLTWorker(const DynLTContext* context, unsigned int id) :
+ context(context), id(id), exitSem(0)
+{
+ // Seed the random number generator
+ rng.seed_rng(100 + id);
+
+ // Generate groups of random 2D sample points
+ sample_groups.resize(context->ngroups);
+ for (unsigned int i=0; i<context->ngroups; ++i) {
+ sample_groups[i].resize(context->nsamples);
+
+ // Generate random (u, v) samples in the texel --> [-0.5, 0.5]
+ unsigned int idx=0;
+ unsigned int nsamples_root=context->nsamples_root;
+ Real delta=1/static_cast<Real>(nsamples_root);
+ Real u=0;
+ for (unsigned int j=0; j<nsamples_root; ++j) {
+ Real v=0;
+ for (unsigned int k=0; k<nsamples_root; ++k) {
+ sample_groups[i][idx++]=Vector2D(u - 0.5 + delta*rng.gendrand(),
+ v - 0.5 + delta*rng.gendrand());
+
+ v += delta;
+ }
+
+ u += delta;
+ }
+
+ // Shuffle the sample points
+ unsigned int nsamples=context->nsamples;
+ unsigned int max_idx=nsamples - 1;
+ for (unsigned int j=0; j<nsamples; ++j) {
+ unsigned int target=static_cast<unsigned int>(max_idx*rng.gendrand());
+ Vector2D tmp=sample_groups[i][j];
+ sample_groups[i][j]=sample_groups[i][target];
+ sample_groups[i][target]=tmp;
+ }
+ }
+
+ // Allocate sample group indices for picking a group of sample points on
the
+ // hemisphere at each depth
+ hidx=new int[context->max_depth];
+}
+
+DynLTWorker::~DynLTWorker(void)
+{
+ delete [] hidx;
+}
+
+void DynLTWorker::run(void)
+{
+ // Create a render context for computing ray intersections
+ vector<string> args;
+ HardShadows shadows(args);
+ // RenderContext(MantaInterface*, int, int, int, const FrameState*,
+ // LoadBalancer*, PixelSampler*, Renderer*, ShadowAlgorithm*,
+ // const Camera*, const Scene*, ThreadStorage*);
+ RenderContext rctx(0, 0, 0, 0, 0, 0, 0, 0, &shadows, 0, context->scene, 0);
+
+ DynLTMessage msg=context->queue->receive();
+ while (msg.particle>=0) {
+ // Generate texture
+ innerLoop(rctx, msg);
+
+ // Receive next message
+ msg=context->queue->receive();
+ }
+
+ if (exitSem)
+ exitSem->up();
+}
+
+void DynLTWorker::timedRun(int proc, int numProcs)
+{
+ // Only specified range of threads should be generating textures
+ if (proc < context->minproc || proc > context->maxproc)
+ return;
+
+ // Create a render context for computing ray intersections
+ vector<string> args;
+ HardShadows shadows(args);
+ // RenderContext(MantaInterface*, int, int, int, const FrameState*,
+ // LoadBalancer*, PixelSampler*, Renderer*, ShadowAlgorithm*,
+ // const Camera*, const Scene*, ThreadStorage*);
+ RenderContext rctx(0, 0, 0, 0, 0, 0, 0, 0, &shadows, 0, context->scene, 0);
+
+ double start=Time::currentSeconds();
+ DynLTMessage msg;
+ while (Time::currentSeconds() - start < context->runtime) {
+ if (context->queue->tryReceive(msg)) {
+ // Generate texture
+ innerLoop(rctx, msg);
+ } else {
+ // No texture requests available, continue with rendering immediately
+ break;
+ }
+ }
+}
+
+void DynLTWorker::innerLoop(const RenderContext& rctx, const DynLTMessage&
msg)
+{
+#ifdef USE_STATS_COLLECTOR
+ // Store start time
+ double start=Time::currentSeconds();
+#endif
+
+ // Grab message data
+ int particle=msg.particle;
+ DynLTGridSpheres* grid=const_cast<DynLTGridSpheres*>(msg.grid);
+
+ // Skip valid textures
+ if (grid->isValid(particle))
+ return;
+
+ // Allocate new texture, if necessary
+ if (!grid->isAllocated(particle))
+ grid->allocate(particle);
+
+ bool dilateTexture=false;
+
+ // Render the texture
+ switch (grid->getTextureMode()) {
+ case DynLTGridSpheres::AmbientOcclusion:
+ dilateTexture=renderAmbient(context, rctx, grid, particle);
+ break;
+ case DynLTGridSpheres::GlobalIllumination:
+ default:
+ dilateTexture=renderGlobal(context, rctx, grid, particle);
+ break;
+ }
+
+ // Dilate texture, if necessary
+ if (context->dilate && dilateTexture)
+ grid->dilate(context, particle);
+
+ // Mark the texture as valid
+ context->manta_interface->addTransaction("Texture valid",
+ Callback::create(grid,
&DynLTGridSpheres::setValid, particle));
+
+#ifdef USE_STATS_COLLECTOR
+ // Compute texture generation time and increment counter
+ double elapsed=Time::currentSeconds() - start;
+ grid->setTexGenTime(particle, elapsed);
+#endif
+}
+
+bool DynLTWorker::renderAmbient(const DynLTContext* context,
+ const RenderContext& rctx,
+ DynLTGridSpheres* grid,
+ unsigned int particle)
+{
+ // Grab useful information from the DynLT context
+ unsigned int ngroups=context->ngroups;
+ unsigned int nsamples=context->nsamples;
+ unsigned int max_depth=context->max_depth;
+ Real inv_nsamples=1/static_cast<Real>(nsamples);
+
+ // Determine texture resolution
+ DynLT* dynplt=grid->getTexture(particle);
+ unsigned int xres=dynplt->getXRes();
+ unsigned int yres=dynplt->getYRes();
+ // Real inv_width=1/static_cast<Real>(xres - 1);
+ // Real inv_height=1/static_cast<Real>(yres - 1);
+ Real inv_width=1/static_cast<Real>(xres);
+ Real inv_height=1/static_cast<Real>(yres);
+
+ // Intialize the textures
+ bzero(dynplt->texture, xres*yres*sizeof(float));
+ bzero(dynplt->inside, xres*yres*sizeof(float));
+
+ // Generate texture
+ const Vector center=grid->getCenter(particle);
+ Real radius=grid->getRadius(particle);
+ bool dilateTexture=false;
+
+ for (unsigned int v=0; v<yres; ++v) {
+ for (unsigned int u=0; u<xres; ++u) {
+ // Pick a random sample group for surface points
+ unsigned int sidx=static_cast<unsigned int>(ngroups*rng.gendrand());
+
+ // Pick random sample group for points on the hemisphere at each depth
+ for (int d=0; d<=max_depth; ++d)
+ hidx[d]=static_cast<unsigned int>(ngroups*rng.gendrand());
+
+ Real ambient=0;
+ for (unsigned int s=0; s<nsamples; s += RayPacket::MaxSize) {
+ // Initialize a ray packet
+ int size=RayPacket::MaxSize;
+ if (size >= nsamples - s) {
+ // Remaining number of samples isn't large enough to fill a ray
+ // packet, so set the size of the ray packet to the number of
samples
+ // that remain
+ size=nsamples - s;
+ }
+
+ RayPacketData raydata;
+ RayPacket rays(raydata, RayPacket::UnknownShape, 0, size, 0, 0);
+
+ // Fill in the ray origins and directions at sample points
+ for (int i=rays.begin(); i<rays.end(); ++i) {
+ // Project surface sample point onto particle's surface
+ Vector2D sample=sample_groups[sidx][s + i];
+
+ // Range of 2*M_PI*(u + sample.x)/(xres - 1) --> [0, 2*Pi]
+ // Range of M_PI*(v + sample.y)/(yres - 1) --> [0, Pi]
+ Real phi=2*M_PI*(u + sample.x())*inv_width;
+ Real theta=M_PI*(v + sample.y())*inv_height;
+
+ Real x=cos(phi)*sin(theta);
+ Real y=sin(phi)*sin(theta);
+ Real z=cos(theta);
+
+ Vector normal(x, y, z);
+ Vector origin=center + radius*normal;
+
+ // Compute an ONB at the surface point
+ Vector v0(Cross(normal, Vector(1,0,0)));
+ if (v0.length2()==0)
+ v0=Cross(normal, Vector(0,1,0));
+ Vector v1=Cross(normal, v0);
+ v0.normalize();
+ v1.normalize();
+
+ // Generate a random direction in the hemisphere
+ Vector2D hemi=sample_groups[hidx[0]][i];
+ Real hphi=2.0*M_PI*hemi.x();
+ Real hr=Sqrt(hemi.y());
+ Real hx=hr*cos(hphi);
+ Real hy=hr*sin(hphi);
+ Real hz=1 - hx*hx - hy*hy;
+ hz=(hz>0?Sqrt(hz):0);
+
+ Vector out=Vector(hx, hy, hz).normal();
+ Vector dir=v0*out.x() + v1*out.y() + normal*out.z();
+ dir.normalize();
+
+ // Set ray origin and direction
+ rays.setOrigin(i, origin);
+ rays.setDirection(i, dir);
+ }
+
+ // Reset ray packet
+ rays.setAllFlags(0);
+ rays.setFlag(RayPacket::NormalizedDirections);
+ rays.resetHits();
+
+ // Intersect rays with the geometry
+ context->scene->getObject()->intersect(rctx, rays);
+
+ for (unsigned int i=rays.begin(); i<rays.end();) {
+ if (rays.wasHit(i)) {
+ // Find a run of rays that hit an object
+ unsigned int end=i + 1;
+ while (end < rays.end() && rays.wasHit(end))
+ ++end;
+
+ // Rays that intersect other objects do not contribute, but
check for
+ // invalid hits (if necessary)
+ if (context->dilate) {
+ // Compute hit positions and normals
+ RayPacket sub(rays, i, end);
+ sub.computeHitPositions();
+ sub.computeNormals(rctx);
+
+ for (unsigned int j=sub.begin(); j<sub.end(); ++j) {
+ Real dotprod=Dot(sub.getNormal(j), -sub.getDirection(j));
+ if (dotprod<=0) {
+ // An invalid hit, resulting from:
+ //
+ // 1. Intersecting spheres---Ray origin is inside of one
+ // sphere and it hits the inside surface of the other
+ //
+ // 2. Ray origin is coincident with the surface of a
+ // neighboring sphere---May result in some crazy
+ // math, and thus a negative dot product
+ //
+ // Either way, ignore the hit and mark the texel for
+ // dilation
+ dynplt->inside[u][v] += 1;
+ dilateTexture=true;
+ }
+ }
+ }
+
+ i=end;
+ } else {
+ // Find a run of rays that didn't hit anything
+ unsigned int end=i + 1;
+ while (end < rays.end() && !rays.wasHit(end))
+ ++end;
+
+ // Only rays that don't intersect other objects contribute to the
+ // ambient illumination at this texel
+ ambient += end - i;
+
+ i=end;
+ }
+ }
+ }
+
+ // Store the normalized result
+ dynplt->texture[u][v]=context->Ka*ambient*inv_nsamples;
+ }
+ }
+
+ return dilateTexture;
+}
+
+bool DynLTWorker::renderGlobal(const DynLTContext* context,
+ const RenderContext& rctx,
+ DynLTGridSpheres* grid,
+ unsigned int particle)
+{
+ // Grab useful information from the DynLT context
+ unsigned int ngroups=context->ngroups;
+ unsigned int nsamples=context->nsamples;
+ unsigned int max_depth=context->max_depth;
+ Real inv_nsamples=1/static_cast<Real>(nsamples);
+
+ // Determine texture resolution
+ DynLT* dynplt=grid->getTexture(particle);
+ unsigned int xres=dynplt->getXRes();
+ unsigned int yres=dynplt->getYRes();
+ // Real inv_width=1/static_cast<Real>(xres - 1);
+ // Real inv_height=1/static_cast<Real>(yres - 1);
+ Real inv_width=1/static_cast<Real>(xres);
+ Real inv_height=1/static_cast<Real>(yres);
+
+ // Intialize the textures
+ bzero(dynplt->texture, xres*yres*sizeof(float));
+ bzero(dynplt->inside, xres*yres*sizeof(float));
+
+ // Generate texture
+ const Vector center=grid->getCenter(particle);
+ Real radius=grid->getRadius(particle);
+ bool dilateTexture=false;
+
+ for (unsigned int v=0; v<yres; ++v) {
+ for (unsigned int u=0; u<xres; ++u) {
+ // Pick a random sample group for surface points
+ unsigned int sidx=static_cast<unsigned int>(ngroups*rng.gendrand());
+
+ // Pick random sample group for points on the hemisphere at each depth
+ for (int d=0; d<=max_depth; ++d)
+ hidx[d]=static_cast<unsigned int>(ngroups*rng.gendrand());
+
+ for (unsigned int s=0; s<nsamples; s += RayPacket::MaxSize) {
+ Real diffuse=0;
+ Real ambient=0;
+ Packet<Real> atten;
+
+ // Initialize a ray packet
+ int size=RayPacket::MaxSize;
+ if (size >= nsamples - s) {
+ // Remaining number of samples isn't large enough to fill a ray
+ // packet, so set the size of the ray packet to the number of
samples
+ // that remain
+ size=nsamples - s;
+ }
+
+ RayPacketData raydata;
+ RayPacket rays(raydata, RayPacket::UnknownShape, 0, size, 0, 0);
+
+ // Fill in the hit positions and surface normals at sample points
+ for (int i=rays.begin(); i<rays.end(); ++i) {
+ // Project surface sample point onto particle's surface
+ Vector2D sample=sample_groups[sidx][s + i];
+
+ // Range of 2*M_PI*(u + sample.x)/(xres - 1) --> [0, 2*Pi]
+ // Range of M_PI*(v + sample.y)/(yres - 1) --> [0, Pi]
+ Real phi=2*M_PI*(u + sample.x())*inv_width;
+ Real theta=M_PI*(v + sample.y())*inv_height;
+
+ Real x=cos(phi)*sin(theta);
+ Real y=sin(phi)*sin(theta);
+ Real z=cos(theta);
+
+ Vector normal(x, y, z);
+ Vector surface=center + radius*normal;
+
+ rays.setHitPosition(i, surface);
+ rays.setNormal(i, normal);
+ atten.set(i, 1);
+ }
+
+ // Iteratively trace the ray packet
+ for (unsigned int d=0; d<max_depth; ++d) {
+ // Reset ray packet flags
+ rays.setAllFlags(0);
+ rays.setFlag(RayPacket::HaveHitPositions | RayPacket::HaveNormals |
+ RayPacket::HaveUnitNormals);
+
+ // Compute direct lighting at current hit positions
+ const LightSet* activeLights=grid->getActiveLights();
+ ShadowAlgorithm::StateBuffer stateBuffer;
+ bool firstTime=true;
+ bool done;
+ do {
+ RayPacketData shadowData;
+ RayPacket shadowRays(shadowData, RayPacket::UnknownShape, 0, 0,
+ rays.getDepth(), 0);
+
+ // Call the shadow algorithm (SA) to generate shadow rays. We
+ // may not be able to compute all of them, so we pass along a
+ // buffer for the SA object to store it's state. The firstTime
+ // flag tells the SA to fill in the state rather than using
+ // anything in the state buffer. Most SAs will only need to
+ // store an int or two in the statebuffer.
+ done=rctx.shadowAlgorithm->computeShadows(rctx, activeLights,
+ rays, shadowRays,
+ firstTime,
+ stateBuffer);
+
+ // Normalize directions for proper dot product computation
+ shadowRays.normalizeDirections();
+
+ for (int i=shadowRays.begin(); i<shadowRays.end(); ++i) {
+ if (!shadowRays.wasHit(i)) {
+ // Not in shadow, so compute the direct contribution
+ Vector normal=rays.getNormal(i);
+ Vector shadowdir=shadowRays.getDirection(i);
+ Real cos_theta=Dot(shadowdir, normal);
+ Color light=shadowRays.getColor(i);
+ diffuse += atten.get(i)*light.luminance()*cos_theta;
+ }
+ }
+
+ firstTime=false;
+ } while(!done);
+
+ // Don't fill/trace ray packet if it's not going to contribute
+ if (d >= max_depth - 1)
+ break;
+
+ for (int i=rays.begin(); i<rays.end(); ++i) {
+ // Compute an ONB at the surface point
+ Vector normal=rays.getNormal(i);
+ Vector v0(Cross(normal, Vector(1,0,0)));
+ if (v0.length2()==0)
+ v0=Cross(normal, Vector(0,1,0));
+ Vector v1=Cross(normal, v0);
+ v0.normalize();
+ v1.normalize();
+
+ // Generate a random direction in the hemisphere
+ Vector2D hemi=sample_groups[hidx[d]][i] + VectorT<Real, 2>(0.5,
0.5);
+ Real hphi=2.0*M_PI*hemi.x();
+ Real hr=Sqrt(hemi.y());
+ Real hx=hr*cos(hphi);
+ Real hy=hr*sin(hphi);
+ Real hz=1 - hx*hx - hy*hy;
+ hz=(hz>0?Sqrt(hz):0);
+
+ Vector out=Vector(hx, hy, hz).normal();
+ Vector dir=v0*out.x() + v1*out.y() + normal*out.z();
+ dir.normalize();
+
+ // Set ray origin and direction
+ rays.setOrigin(i, rays.getHitPosition(i));
+ rays.setDirection(i, dir);
+
+ // Update attenutation
+ atten.set(i, atten.get(i)*Dot(normal, dir));
+ }
+
+ // Reset ray packet
+ rays.setAllFlags(0);
+ rays.setFlag(RayPacket::NormalizedDirections);
+ rays.resetHits();
+
+ // Intersect rays with the geometry
+ context->scene->getObject()->intersect(rctx, rays);
+
+ // Prepare ray packet for next iteration
+ unsigned int validRays=0;
+ for (unsigned int i=rays.begin(); i<rays.end();) {
+ if (rays.wasHit(i)) {
+ // Find a run of rays that hit an object
+ unsigned int end=i + 1;
+ while (end < rays.end() && rays.wasHit(end))
+ ++end;
+
+ // Compute hit positions and normals
+ RayPacket sub(rays, i, end);
+ sub.computeHitPositions();
+ sub.computeNormals(rctx);
+
+ // Store hit positions, normals for valid hits
+ for (unsigned int j=sub.begin(); j<sub.end(); ++j) {
+ Real dotprod=Dot(sub.getNormal(j), -sub.getDirection(j));
+ if (dotprod>0) {
+ rays.setHitPosition(validRays, sub.getHitPosition(j));
+ rays.setNormal(validRays, sub.getNormal(j));
+ atten.set(validRays, atten.get(j));
+ ++validRays;
+ } else {
+ // An invalid hit, resulting from:
+ //
+ // 1. Intersecting spheres---Ray origin is inside of one
+ // sphere and it hits the inside surface of the other
+ //
+ // 2. Ray origin is coincident with the surface of a
+ // neighboring sphere---May result in some crazy
+ // math, and thus a negative dot product
+ //
+ // Either way, ignore the hit and mark the texel for
+ // dilation
+ dynplt->inside[u][v] += 1;
+ dilateTexture=true;
+ }
+ }
+
+ i=end;
+ } else {
+ // Find a run of rays that didn't hit anything
+ unsigned int end=i + 1;
+ while (end < rays.end() && !rays.wasHit(end))
+ ++end;
+
+ // Shade the rays, and accumulate background color
+ RayPacket sub(rays, i, end);
+ context->background->shade(rctx, sub);
+
+ for (unsigned int j=sub.begin(); j<sub.end(); ++j)
+ ambient += sub.getColor(j).luminance();
+
+ i=end;
+ }
+ }
+
+ // Terminate at current depth, if necessary
+ if (validRays==0)
+ break;
+
+ // Update the ray packet configuration, loop to next depth
+ rays.setDepth(rays.getDepth() + 1);
+ rays.resize(validRays);
+ }
+
+ // Store the result
+ dynplt->texture[u][v] += context->Ka*ambient + context->Kd*diffuse;
+ }
+
+ // Normalize the texel
+ dynplt->texture[u][v] *= inv_nsamples;
+ }
+ }
+
+ return dilateTexture;
+}
+
+void DynLTWorker::terminate(MantaInterface*)
+{
+ Semaphore semaphore("DynLTWorker Exit Semaphore", 0);
+
+ // Notify worker to exit
+ exitSem=&semaphore;
+ DynLTMessage fake(-1, 0., 0);
+ context->queue->send(fake);
+
+ // Block the calling thread until the worker's done
+ semaphore.down();
+}
Added: trunk/DynLT/DynLTWorker.h
==============================================================================
--- (empty file)
+++ trunk/DynLT/DynLTWorker.h Thu Jul 20 21:24:57 2006
@@ -0,0 +1,63 @@
+
+#ifndef Manta_DynLT_DynLTWorker_h
+#define Manta_DynLT_DynLTWorker_h
+
+#include <Core/Math/MT_RNG.h>
+#include <Core/Math/vector2d.h>
+#include <Core/Util/Stat.h>
+#include <Interface/MantaInterface.h>
+#include <SCIRun/Core/Containers/Array1.h>
+#include <SCIRun/Core/Containers/Array2.h>
+#include <SCIRun/Core/Thread/Mailbox.h>
+#include <SCIRun/Core/Thread/Runnable.h>
+#include <SCIRun/Core/Thread/Semaphore.h>
+
+#include <float.h>
+
+using namespace SCIRun;
+
+namespace Manta
+{
+ class Background;
+ class DynLTContext;
+ class DynLTGridSpheres;
+ class DynLTMessage;
+ class MantaInterface;
+ class RayPacket;
+ class RenderContext;
+ class Scene;
+ class Sphere;
+
+ class DynLTWorker : public Runnable
+ {
+ public:
+ DynLTWorker(const DynLTContext* context, unsigned int id);
+ virtual ~DynLTWorker(void);
+
+ // Thread run function for static thread scheduling
+ virtual void run(void);
+
+ // Termination call back for static thread scheduling
+ void terminate(MantaInterface*);
+
+ // Parallel pre-render callback for dynamic thread scheduling
+ void timedRun(int proc, int numProcs);
+
+ private:
+ bool renderAmbient(const DynLTContext* context, const RenderContext&
rctx,
+ DynLTGridSpheres* grid, unsigned int particle);
+ bool renderGlobal(const DynLTContext* context, const RenderContext& rctx,
+ DynLTGridSpheres* grid, unsigned int particle);
+ void innerLoop(const RenderContext& rctx, const DynLTMessage& msg);
+
+ const DynLTContext* context;
+ unsigned int id;
+ MT_RNG rng;
+ Array1<Array1<Vector2D> > sample_groups;
+ int* hidx;
+ Background* background;
+ Semaphore* exitSem;
+ };
+}
+
+#endif // Manta_DynLT_DynLTWorker_h
Modified: trunk/Engine/Control/CMakeLists.txt
==============================================================================
--- trunk/Engine/Control/CMakeLists.txt (original)
+++ trunk/Engine/Control/CMakeLists.txt Thu Jul 20 21:24:57 2006
@@ -3,14 +3,3 @@
Control/RTRT.h
Control/RTRT.cc
)
-
-# Conditionally compile DynPLTWorker code
-IF(BUILD_DYNPLT)
- SET(Manta_Control_SRCS
- ${Manta_Control_SRCS}
- Control/DynPLTQueue.h
- Control/DynPLTQueue.cc
- Control/DynPLTWorker.h
- Control/DynPLTWorker.cc
- )
-ENDIF(BUILD_DYNPLT)
Modified: trunk/Model/CMakeLists.txt
==============================================================================
--- trunk/Model/CMakeLists.txt (original)
+++ trunk/Model/CMakeLists.txt Thu Jul 20 21:24:57 2006
@@ -37,9 +37,6 @@
TARGET_LINK_LIBRARIES(Manta_Model Manta_Interface Manta_Core Manta_Image)
-IF(BUILD_DYNPLT)
- TARGET_LINK_LIBRARIES(Manta_Model
- ${FOUND_TEEM_LIB})
-ENDIF(BUILD_DYNPLT)
-
-
+IF(BUILD_DYNLT)
+ TARGET_LINK_LIBRARIES(Manta_Model Manta_DynLT)
+ENDIF(BUILD_DYNLT)
Modified: trunk/Model/Groups/TimeSteppedParticles.cc
==============================================================================
--- trunk/Model/Groups/TimeSteppedParticles.cc (original)
+++ trunk/Model/Groups/TimeSteppedParticles.cc Thu Jul 20 21:24:57 2006
@@ -1,7 +1,9 @@
#include <Core/Exceptions/InputError.h>
#include <Core/Exceptions/OutputError.h>
-#include <Engine/Control/DynPLTQueue.h>
+#ifdef BUILD_DYNLT
+#include <DynLT/DynLTGridSpheres.h>
+#endif
#include <Model/Groups/TimeSteppedParticles.h>
#include <Model/Primitives/GridSpheres.h>
#include <Model/Readers/ParticleNRRD.h>
@@ -9,15 +11,15 @@
#include <fstream>
using std::ifstream;
-using namespace Manta;
-
#include <iostream>
using std::cerr;
+using namespace Manta;
+
TimeSteppedParticles::TimeSteppedParticles(const string& filename, int
ncells,
int depth, Real radius, int ridx,
RegularColorMap* cmap, int cidx,
- DynPLTQueue* queue,
+ DynLTQueue* queue,
int min, int max) :
tstep(0)
{
@@ -25,16 +27,21 @@
string::size_type pos=filename.find(".nrrd", 0);
if (pos != string::npos) {
ParticleNRRD pnrrd(filename);
+#ifdef BUILD_DYNLT
if (queue) {
- queue->resizeHeapIdx(pnrrd.getNParticles());
- add(new DynPLTGridSpheres(queue, pnrrd.getParticleData(),
+ add(new DynLTGridSpheres(queue, pnrrd.getParticleData(),
pnrrd.getNParticles(), pnrrd.getNVars(),
ncells,
depth, radius, ridx, cmap, cidx));
} else {
+#else
+ cerr<<"TimeSteppedParticles - DynLTGridSpheres is not supported\n";
+#endif
add(new GridSpheres(pnrrd.getParticleData(), pnrrd.getNParticles(),
pnrrd.getNVars(), ncells, depth, radius, ridx,
cmap,
cidx));
+#ifdef BUILD_DYNLT
}
+#endif
return;
}
@@ -59,15 +66,21 @@
// Load the particle data
ParticleNRRD pnrrd(fname);
+#ifdef BUILD_DYNLT
if (queue) {
- add(new DynPLTGridSpheres(queue, pnrrd.getParticleData(),
+ add(new DynLTGridSpheres(queue, pnrrd.getParticleData(),
pnrrd.getNParticles(), pnrrd.getNVars(),
ncells,
depth, radius, ridx, cmap, cidx));
} else {
+#else
+ cerr<<"TimeSteppedParticles - DynLTGridSpheres is not supported\n";
+#endif
add(new GridSpheres(pnrrd.getParticleData(), pnrrd.getNParticles(),
pnrrd.getNVars(), ncells, depth, radius, ridx,
cmap,
cidx));
+#ifdef BUILD_DYNLT
}
+#endif
++nloaded;
}
Modified: trunk/Model/Groups/TimeSteppedParticles.h
==============================================================================
--- trunk/Model/Groups/TimeSteppedParticles.h (original)
+++ trunk/Model/Groups/TimeSteppedParticles.h Thu Jul 20 21:24:57 2006
@@ -4,7 +4,6 @@
#include <MantaTypes.h>
#include <Model/Groups/Group.h>
-#include <Model/Primitives/DynPLTGridSpheres.h>
#include <SCIRun/Core/Thread/Mailbox.h>
#include <string>
@@ -14,7 +13,7 @@
namespace Manta
{
- class DynPLTQueue;
+ class DynLTQueue;
class RegularColorMap;
class TimeSteppedParticles : public Group
@@ -22,7 +21,7 @@
public:
TimeSteppedParticles(const string& filename, int ncells, int depth,
Real radius, int ridx, RegularColorMap* cmap, int
cidx,
- DynPLTQueue* queue=0, int min=0,
+ DynLTQueue* queue=0, int min=0,
int max=INT_MAX);
~TimeSteppedParticles(void);
Modified: trunk/Model/Primitives/CMakeLists.txt
==============================================================================
--- trunk/Model/Primitives/CMakeLists.txt (original)
+++ trunk/Model/Primitives/CMakeLists.txt Thu Jul 20 21:24:57 2006
@@ -10,8 +10,6 @@
Primitives/Cylinder.h
Primitives/Disk.cc
Primitives/Disk.h
- Primitives/DynPLTGridSpheres.cc
- Primitives/DynPLTGridSpheres.h
Primitives/GridSpheres.cc
Primitives/GridSpheres.h
Primitives/HeavyTriangle.cc
Modified: trunk/Model/Primitives/GridSpheres.cc
==============================================================================
--- trunk/Model/Primitives/GridSpheres.cc (original)
+++ trunk/Model/Primitives/GridSpheres.cc Thu Jul 20 21:24:57 2006
@@ -31,6 +31,8 @@
spheres(spheres), nspheres(nspheres), nvars(nvars), ncells(ncells),
depth(depth), radius(radius), ridx(ridx), cmap(cmap), cidx(cidx)
{
+ cerr<<"Initializing GridSpheres\n";
+
if (radius <= 0) {
if (ridx <= 0)
cerr<<"Resetting default radius to 1\n";
Modified: trunk/scenes/CMakeLists.txt
==============================================================================
--- trunk/scenes/CMakeLists.txt (original)
+++ trunk/scenes/CMakeLists.txt Thu Jul 20 21:24:57 2006
@@ -104,8 +104,8 @@
TARGET_LINK_LIBRARIES(scene_pnrrd ${MANTA_SCENE_LINK})
ENDIF(BUILD_NRRDPARTICLES)
-# Lazily evaluated PLTs for NRRD particle datasets
-IF(BUILD_DYNPLT)
- ADD_LIBRARY(scene_dynplt dynplt.cc)
- TARGET_LINK_LIBRARIES(scene_dynplt ${MANTA_SCENE_LINK})
-ENDIF(BUILD_DYNPLT)
+# Lazily evaluated LTs for NRRD particle datasets
+IF(BUILD_DYNLT)
+ ADD_LIBRARY(scene_dynlt dynlt.cc)
+ TARGET_LINK_LIBRARIES(scene_dynlt ${MANTA_SCENE_LINK})
+ENDIF(BUILD_DYNLT)
Added: trunk/scenes/dynlt.cc
==============================================================================
--- (empty file)
+++ trunk/scenes/dynlt.cc Thu Jul 20 21:24:57 2006
@@ -0,0 +1,276 @@
+
+#include <Core/Color/RegularColorMap.h>
+#include <Core/Exceptions/IllegalArgument.h>
+#include <Core/Geometry/Vector.h>
+#include <Core/Util/Args.h>
+#include <DynLT/DynLTGridSpheres.h>
+#include <DynLT/DynLTQueue.h>
+#include <DynLT/DynLTStatsCollector.h>
+#include <DynLT/DynLTWorker.h>
+#include <Interface/Context.h>
+#include <Interface/LightSet.h>
+#include <Interface/MantaInterface.h>
+#include <Interface/Scene.h>
+#include <Model/AmbientLights/ConstantAmbient.h>
+#include <Model/Backgrounds/ConstantBackground.h>
+#include <Model/Backgrounds/EnvMapBackground.h>
+#include <Model/Groups/TimeSteppedParticles.h>
+#include <Model/Lights/PointLight.h>
+#include <Model/Primitives/Sphere.h>
+#include <Model/Readers/ParticleNRRD.h>
+#include <SCIRun/Core/Thread/Thread.h>
+
+#include <sgi_stl_warnings_off.h>
+#include <iostream>
+#include <sgi_stl_warnings_on.h>
+
+#include <float.h>
+
+#define WORKER_THREAD_STACKSIZE 8*1024*1024
+
+using namespace Manta;
+using namespace SCIRun;
+using namespace std;
+
+extern "C"
+Scene* make_scene(ReadContext const& context, vector<string> const& args)
+{
+ Group* world=0;
+ int cidx=0;
+ string env_fname="";
+ bool use_envmap=false;
+ string fname="";
+ int depth=1;
+ bool dilate=false;
+ bool fifo=false;
+ bool lifo=false;
+ int max_depth=3;
+ int ncells=2;
+ int ngroups=100;
+ int nsamples=25;
+ int nthreads=1;
+ int qsize=16;
+ double radius=1.;
+ int ridx=-1;
+ bool static_threads=false;
+ bool stats=false;
+ double runtime=1./25.;
+ int minproc=0;
+ int maxproc=INT_MAX;
+
+ int argc=static_cast<int>(args.size());
+ for(int i=0; i<argc; ++i) {
+ string arg=args[i];
+#if 0
+ if (arg=="-bv") {
+ string s;
+ if (!getStringArg(i, args, s))
+ throw IllegalArgument("scene dynplt -bv", i, args);
+ world=context.manta_interface->makeGroup(s);
+#endif
+ if (arg=="-cidx") {
+ if (!getIntArg(i, args, cidx))
+ throw IllegalArgument("scene pnrrd -cidx", i, args);
+ } else if (arg=="-depth") {
+ if (!getIntArg(i, args, depth))
+ throw IllegalArgument("scene dynplt -depth", i, args);
+ } else if (arg=="-dilate") {
+ dilate=true;
+ } else if (arg=="-fifo") {
+ fifo=true;
+ lifo=false;
+ } else if (arg=="-envmap") {
+ string s;
+ if (!getStringArg(i, args, s))
+ throw IllegalArgument("scene dynplt -envmap", i, args);
+
+ if (s[0] != '-') {
+ if (s=="bg") {
+ use_envmap=true;
+ if (!getStringArg(i, args, env_fname))
+ throw IllegalArgument("scene dynplt -envmap", i, args);
+ } else {
+ env_fname=s;
+ }
+ } else {
+ throw IllegalArgument("scene dynplt -envmap", i, args);
+ }
+ } else if (arg=="-i") {
+ if (!getStringArg(i, args, fname))
+ throw IllegalArgument("scene dynplt -i", i, args);
+ } else if (arg=="-lifo") {
+ fifo=false;
+ lifo=true;
+ } else if (arg=="-nbounces") {
+ if (!getIntArg(i, args, max_depth))
+ throw IllegalArgument("scene dynplt -nbounces", i, args);
+ ++max_depth;
+ } else if (arg=="-ncells") {
+ if (!getIntArg(i, args, ncells))
+ throw IllegalArgument("scene dynplt -ncells", i, args);
+ } else if (arg=="-ngroups") {
+ if (!getIntArg(i, args, ngroups))
+ throw IllegalArgument("scene dynplt -ngroups", i, args);
+ } else if (arg=="-nsamples") {
+ if (!getIntArg(i, args, nsamples))
+ throw IllegalArgument("scene dynplt -nsamples", i, args);
+ } else if (arg=="-nthreads") {
+ static_threads=true;
+ if (!getIntArg(i, args, nthreads))
+ throw IllegalArgument("scene dynplt -nthreads", i, args);
+ } else if (arg=="-radius") {
+ if (!getDoubleArg(i, args, radius))
+ throw IllegalArgument("scene dynplt -radius", i, args);
+ } else if (arg=="-ridx") {
+ if (!getIntArg(i, args, ridx))
+ throw IllegalArgument("scene dynplt -ridx", i, args);
+ } else if (arg=="-qsize") {
+ if (!getIntArg(i, args, qsize))
+ throw IllegalArgument("scene dynplt -qsize", i, args);
+ } else if (arg=="-stats") {
+ stats=true;
+ } else if (arg=="-timed") {
+ string s;
+ if (getStringArg(i, args, s)) {
+ if (s[0] != '-') {
+ runtime=atof(s.c_str());
+ if (getStringArg(i, args, s)) {
+ minproc=atoi(s.c_str());
+ if (!getIntArg(i, args, maxproc))
+ throw IllegalArgument("scene dynplt -nthreads", i, args);
+ }
+ }
+ }
+ } else {
+ cerr<<"Valid options for scene dynplt:\n";
+ // cerr<<" -bv <string> bounding volume
{bvh|grid|group}\n";
+ cerr<<" -cidx <int> data value index for
color mapping\n";
+ cerr<<" -depth <int> grid depth\n";
+ cerr<<" -dilate dilate textures during
generation\n";
+ cerr<<" -fifo use fifo queue for
texture requests\n";
+ cerr<<" -envmap [bg] <string> environment map
filename\n";
+ cerr<<" -i <string> particle data filename\n";
+ cerr<<" -lifo use lifo queue for
texture requests\n";
+ cerr<<" -nbounces <int> number of indirect
nbounces\n";
+ cerr<<" -ncells <int> grid resolution\n";
+ cerr<<" -ngroups <int> number of sample
groups\n";
+ cerr<<" -nsamples <int> number of
samples/texel\n";
+ cerr<<" -nthreads <int> number of static dynplt
workers\n";
+ cerr<<" -qsize <int> maximum queue qsize\n";
+ cerr<<" -radius <float> particle radius\n";
+ cerr<<" -ridx <int> radius index\n";
+ cerr<<" -stats dump summary stats on
exit (if stats collection supported by build)\n";
+ cerr<<" -timed [<double> [<int> <int>]] texgen thread range and
runtime (in seconds)\n";
+ throw IllegalArgument("scene dynplt", i, args);
+ }
+ }
+
+ if (!world)
+ world=new Group();
+
+ // Create a scene
+ Scene* scene=new Scene();
+
+ // Create DynLT work queue
+ DynLTQueue* queue;
+ if (fifo) {
+ queue=new DynLTFifoQ(nthreads*qsize);
+ cerr<<"Using FIFO Queue\n";
+ } else if (lifo) {
+ queue=new DynLTLifoQ(nthreads*qsize);
+ cerr<<"Using LIFO Queue\n";
+ } else {
+ queue=new DynLTPriorityQ(nthreads*qsize);
+ cerr<<"Using Priority Queue\n";
+ }
+
+ Background* bg=0;
+ if (env_fname != "")
+ bg=new EnvMapBackground(env_fname);
+ else
+ bg=new ConstantBackground(Color(RGB(0, 0, 0)));
+
+ if (static_threads) {
+ // Static thread scheduling --> create DynLTWorker threads
+ DynLTContext* dpltctx=new DynLTContext(context.manta_interface,
+ queue, scene, ngroups, nsamples,
+ max_depth, dilate, bg /*,
runtime,
+
minproc, maxproc, kd, ka */);
+
+ for (unsigned int i=0; i<nthreads; ++i) {
+ ostringstream name;
+ name<<"DynLT Worker "<<i;
+ DynLTWorker* worker=new DynLTWorker(dpltctx, i);
+ Thread* thread=new Thread(worker, name.str().c_str(), 0,
+ Thread::NotActivated);
+ thread->setStackSize(WORKER_THREAD_STACKSIZE);
+ thread->activate(false);
+
+ // Register termination callback
+
context.manta_interface->registerTerminationCallback(Callback::create(worker,
&DynLTWorker::terminate));
+ }
+ } else {
+ // Dynamic thread scheduling --> register timed texgen function
+ DynLTContext* dpltctx=new DynLTContext(context.manta_interface,
+ queue, scene, ngroups, nsamples,
+ max_depth, dilate, bg, runtime,
+ minproc, maxproc /*, kd, ka */);
+
+ DynLTWorker* worker=new DynLTWorker(dpltctx, 0);
+
context.manta_interface->registerParallelPreRenderCallback(Callback::create(worker,
&DynLTWorker::timedRun));
+ }
+
+#ifdef USE_STATS_COLLECTOR
+ // Register DynLTStatsCollector::resetPerFrameStats to reset per-frame
stats
+
context.manta_interface->registerSerialPreRenderCallback(Callback::create(DynLTStatsCollector::resetPerFrameStats));
+
+ if (stats) {
+ // Register DynLTStatsCollector::dump to output statistics on exit
+
context.manta_interface->registerTerminationCallback(Callback::create(DynLTStatsCollector::dump));
+ }
+#else
+ if (stats)
+ cerr<<"Warning: USE_STATS_COLLECTOR not defined\n";
+#endif
+
+ // Create color map
+ unsigned int type=RegularColorMap::parseType("InvRainbowIso");
+ RegularColorMap* cmap=new RegularColorMap(type);
+
+ // Load particle data, add particles to group
+ TimeSteppedParticles* tsteps=new TimeSteppedParticles(fname, ncells,
depth,
+ radius, ridx,
cmap, cidx,
+ queue);
+
+ // Initialize the scene
+ if (env_fname != "" && use_envmap)
+ scene->setBackground(bg);
+ else
+ scene->setBackground(new ConstantBackground(Color(RGB(0, 0, 0))));
+ scene->setObject(tsteps);
+
+ // Add lights
+ LightSet* lights=new LightSet();
+ lights->add(new PointLight(Vector(10, 10, 10), Color(RGB(1, 1, 1))));
+ lights->setAmbientLight(new ConstantAmbient(Color(RGB(0.4, 0.4, 0.4))));
+ scene->setLights(lights);
+
+ /*
+ scene->addBookmark("debug 0", Vector(0.06, 26.9721, 0.06),
+ Vector(0.06, 0.06, 0.06), Vector(0, 0, 1), 0.59);
+ scene->addBookmark("view 0", Vector(0.02, 1.02, 0.20),
+ Vector(0.02, 0.02, 0.20), Vector(0, 0, 1),
+ 0.59);
+ scene->addBookmark("view 1", Vector(0.83, 0.85, 4.71),
+ Vector(0.02, 0.01, 0.29), Vector(-0.54, -0.58, 0.59),
+ 0.59);
+ scene->addBookmark("view 2", Vector(-0.83, 0.85, 4.71),
+ Vector(0.02, 0.01, 0.29), Vector(-0.59, -0.59, 0.59),
+ 0.59);
+ scene->addBookmark("view 3", Vector(1.01349, 0.0783629, 0.297803),
+ Vector(0.02, 0.02, 0.2),
+ Vector(-0.0890283, -0.13761, 0.986477), 0.204219);
+ */
+
+ return scene;
+ }
- [MANTA] r1151 - in trunk: . Core Core/Util DynLT Engine/Control Model Model/Groups Model/Primitives scenes, cgribble, 07/20/2006
Archive powered by MHonArc 2.6.16.