Author: brownlee
Date: Fri Sep 12 17:34:52 2008
New Revision: 2324
Modified:
trunk/Model/Materials/Volume.h
trunk/Model/Primitives/Cube.cc
trunk/Model/Primitives/Cube.h
trunk/SwigInterface/wxManta.py
trunk/scenes/csafe/python/SceneInfo.py
trunk/scenes/csafe/python/SceneMenus.py
trunk/scenes/csafe/python/csafe_demo.py
trunk/scenes/csafe/src/CDGridSpheres.cc
trunk/scenes/csafe/src/CDTest.h
Log:
added option to change background in wxManta, currently only supports constant background and has a memory leak though it's minor (can I delete old background?). added ability to modify cube dimensions. added ability to modify volume size and position in csafe demo.
Modified: trunk/Model/Materials/Volume.h
= = = = = = = = ======================================================================
--- trunk/Model/Materials/Volume.h (original)
+++ trunk/Model/Materials/Volume.h Fri Sep 12 17:34:52 2008
@@ -91,181 +91,182 @@
struct VMCell
{
- // Need to make sure we have a 64 bit thing
- unsigned long long course_hash;
- // The max of unsigned long long is ULLONG_MAX
- VMCell(): course_hash(0) {}
-
- void turn_on_bits(float min, float max, float data_min, float data_max) {
- // We know that we have 64 bits, so figure out where min and max map
- // into [0..63].
- int min_index = (int)((min-data_min)/(data_max- data_min)*63);
- /* T max_index_prep = ((max-data_min)/(data_max- data_min)*63); */
- /* int max_index = max_index_prep- (int)max_index_prep>0? */
- /* (int)max_index_prep+1:(int)max_index_prep; */
- int max_index = (int)ceil(double((max-data_min)/(data_max- data_min)*63));
- // Do some checks
-
- // This will handle clamping, I hope.
- if (min_index > 63)
- min_index = 63;
- if (max_index < 0)
- max_index = 0;
- if (min_index < 0)
- min_index = 0;
- if (max_index > 63)
- max_index = 63;
- for (int i = min_index; i <= max_index; i++)
- course_hash |= 1ULL << i;
- }
- inline VMCell& operator |= (const VMCell& v) {
- course_hash |= v.course_hash;
- return *this;
- }
- inline bool operator & (const VMCell& v) {
- return (course_hash & v.course_hash) != 0;
- }
- friend ostream& operator<<(ostream& out,const VMCell& cell) {
- for( int i = 0; i < 64; i++) {
- unsigned long long bit= cell.course_hash & (1ULL << i);
- if (bit)
- out << "1";
- else
- out << "0";
- }
- return out;
- }
+ // Need to make sure we have a 64 bit thing
+ unsigned long long course_hash;
+ // The max of unsigned long long is ULLONG_MAX
+ VMCell(): course_hash(0) {}
+
+ void turn_on_bits(float min, float max, float data_min, float data_max) {
+ // We know that we have 64 bits, so figure out where min and max map
+ // into [0..63].
+ int min_index = (int)((min-data_min)/(data_max-data_min)*63);
+ /* T max_index_prep = ((max-data_min)/(data_max- data_min)*63); */
+ /* int max_index = max_index_prep- (int)max_index_prep>0? */
+ /* (int)max_index_prep+1:(int)max_index_prep; */
+ int max_index = (int)ceil(double((max-data_min)/(data_max- data_min)*63));
+ // Do some checks
+
+ // This will handle clamping, I hope.
+ if (min_index > 63)
+ min_index = 63;
+ if (max_index < 0)
+ max_index = 0;
+ if (min_index < 0)
+ min_index = 0;
+ if (max_index > 63)
+ max_index = 63;
+ for (int i = min_index; i <= max_index; i++)
+ course_hash |= 1ULL << i;
+ }
+ inline VMCell& operator |= (const VMCell& v) {
+ course_hash |= v.course_hash;
+ return *this;
+ }
+ inline bool operator & (const VMCell& v) {
+ return (course_hash & v.course_hash) != 0;
+ }
+ friend ostream& operator<<(ostream& out,const VMCell& cell) {
+ for( int i = 0; i < 64; i++) {
+ unsigned long long bit= cell.course_hash & (1ULL << i);
+ if (bit)
+ out << "1";
+ else
+ out << "0";
+ }
+ return out;
+ }
};
struct CellData {
- VMCell cell;
+ VMCell cell;
};
template<class T>
- class Volume : public Material
- {
- protected:
- class HVIsectContext {
- public:
- // These parameters could be modified and hold accumulating state
- Color total;
- float alpha;
- // These parameters should not change
- int dix_dx, diy_dy, diz_dz;
- VMCell transfunct;
- double t_inc;
- double t_min;
- double t_max;
- double t_inc_inv;
- Ray ray;
- };
- public:
- static void newFrame();
- typedef unsigned long long mcT;
- vector<mcT> cellVector_mc; // color hashes
-
- Volume(GridArray3<T>* data, RGBAColorMap* colorMap, const BBox& bounds,
- double cellStepSize, int depth,
- double forceDataMin = -FLT_MAX, double forceDataMax = -FLT_MAX);
- virtual ~Volume();
- void setColorMap(RGBAColorMap* map) { _colorMap = map; }
- void getMinMax(double* min, double* max){ *min = _dataMin; *max = _dataMax; }
- void computeHistogram(int numBuckets, int* histValues);
- virtual void preprocess(const PreprocessContext& context);
- virtual void shade(const RenderContext & context, RayPacket& rays) const;
- virtual void attenuateShadows(const RenderContext& context, RayPacket& shadowRays) const;
- GridArray3<T>* _data;
- float getValue(int x, int y, int z);
- GridArray3<VMCell>* macrocells;
- void calc_mcell(int depth, int ix, int iy, int iz, VMCell& mcell);
- void parallel_calc_mcell(int cell);
- void isect(const int depth, double t_sample,
- const double dtdx, const double dtdy, const double dtdz,
- double next_x, double next_y, double next_z,
- int ix, int iy, int iz,
- const int startx, const int starty, const int startz,
- const Vector& cellcorner, const Vector& celldir,
- HVIsectContext &isctx) const;
- Vector diag;
- Vector inv_diag;
- protected:
- int _nx,_ny,_nz;
- RGBAColorMap* _colorMap;
- BBox _bounds;
- Vector _datadiag;
- Vector _sdiag;
- Vector _hierdiag;
- Vector _ihierdiag;
- int _depth;
- int* _xsize,*_ysize,*_zsize;
- double* _ixsize, *_iysize, *_izsize;
- Vector _cellSize;
- float _stepSize;
- float _dataMin;
- float _dataMax;
- float _colorScalar;
- float _maxDistance;
- };
+ class Volume : public Material
+ {
+ protected:
+ class HVIsectContext {
+ public:
+ // These parameters could be modified and hold accumulating state
+ Color total;
+ float alpha;
+ // These parameters should not change
+ int dix_dx, diy_dy, diz_dz;
+ VMCell transfunct;
+ double t_inc;
+ double t_min;
+ double t_max;
+ double t_inc_inv;
+ Ray ray;
+ };
+ public:
+ static void newFrame();
+ typedef unsigned long long mcT;
+ vector<mcT> cellVector_mc; // color hashes
+
+ Volume(GridArray3<T>* data, RGBAColorMap* colorMap, const BBox& bounds,
+ double cellStepSize, int depth,
+ double forceDataMin = -FLT_MAX, double forceDataMax = - FLT_MAX);
+ virtual ~Volume();
+ void setBounds(BBox bounds);
+ void setColorMap(RGBAColorMap* map) { _colorMap = map; }
+ void getMinMax(double* min, double* max){ *min = _dataMin; *max = _dataMax; }
+ void computeHistogram(int numBuckets, int* histValues);
+ virtual void preprocess(const PreprocessContext& context);
+ virtual void shade(const RenderContext & context, RayPacket& rays) const;
+ virtual void attenuateShadows(const RenderContext& context, RayPacket& shadowRays) const;
+ GridArray3<T>* _data;
+ float getValue(int x, int y, int z);
+ GridArray3<VMCell>* macrocells;
+ void calc_mcell(int depth, int ix, int iy, int iz, VMCell& mcell);
+ void parallel_calc_mcell(int cell);
+ void isect(const int depth, double t_sample,
+ const double dtdx, const double dtdy, const double dtdz,
+ double next_x, double next_y, double next_z,
+ int ix, int iy, int iz,
+ const int startx, const int starty, const int startz,
+ const Vector& cellcorner, const Vector& celldir,
+ HVIsectContext &isctx) const;
+ Vector diag;
+ Vector inv_diag;
+ protected:
+ int _nx,_ny,_nz;
+ RGBAColorMap* _colorMap;
+ BBox _bounds;
+ Vector _datadiag;
+ Vector _sdiag;
+ Vector _hierdiag;
+ Vector _ihierdiag;
+ int _depth;
+ int* _xsize,*_ysize,*_zsize;
+ double* _ixsize, *_iysize, *_izsize;
+ Vector _cellSize;
+ float _stepSize;
+ float _dataMin;
+ float _dataMax;
+ float _colorScalar;
+ float _maxDistance;
+ };
template<class T>
- Volume<T>::Volume(GridArray3<T>* data, RGBAColorMap* colorMap,
- const BBox& bounds, double cellStepSize,
- int depth,
- double forceDataMin, double forceDataMax)
- : _data(data), _colorMap(colorMap)
- {
- //slightly expand the bounds.
- _bounds[0] = bounds[0] - bounds.diagonal().length()*T_EPSILON;
- _bounds[1] = bounds[1] + bounds.diagonal().length()*T_EPSILON;
-
- Vector diag = _bounds.diagonal();
-
- _cellSize = diag*Vector( 1.0 / (double)(_data->getNx()-1),
- 1.0 / (double)(_data->getNy()-1),
- 1.0 / (double)(_data->getNz()-1));
-
- //_stepSize = cellStepSize*_cellSize.length()/sqrt(3.0);
- _stepSize = cellStepSize;
- _maxDistance = diag.length();
-
- float min = 0,max = 0;
- //_data->getMinMax(&min, &max);
- min = FLT_MAX;
- max = -FLT_MAX;
- //computeMinMax(min, max, *_data);
- unsigned int size = _data->getNx()*_data->getNy()*_data- >getNz();
- for (int i = 0; i < (int)size; i++)
- {
- if ((*_data)[i] < min) min = (*_data)[i];
- if ((*_data)[i] > max) max = (*_data)[i];
- }
- if (forceDataMin != -FLT_MAX || forceDataMax != -FLT_MAX)
- {
- min = forceDataMin;
- max = forceDataMax;
- }
- _dataMin = min;
- _dataMax = max;
- _colorScalar = 1.0f/(_dataMax - _dataMin);
- cout << "datamin/max: " << min << " " << max << endl;
+ Volume<T>::Volume(GridArray3<T>* data, RGBAColorMap* colorMap,
+ const BBox& bounds, double cellStepSize,
+ int depth,
+ double forceDataMin, double forceDataMax)
+ : _data(data), _colorMap(colorMap)
+ {
+ //slightly expand the bounds.
+ _bounds[0] = bounds[0] - bounds.diagonal().length()*T_EPSILON;
+ _bounds[1] = bounds[1] + bounds.diagonal().length()*T_EPSILON;
+
+ Vector diag = _bounds.diagonal();
+
+ _cellSize = diag*Vector( 1.0 / (double)(_data->getNx()-1),
+ 1.0 / (double)(_data->getNy()-1),
+ 1.0 / (double)(_data->getNz()-1));
+
+ //_stepSize = cellStepSize*_cellSize.length()/sqrt(3.0);
+ _stepSize = cellStepSize;
+ _maxDistance = diag.length();
+
+ float min = 0,max = 0;
+ //_data->getMinMax(&min, &max);
+ min = FLT_MAX;
+ max = -FLT_MAX;
+ //computeMinMax(min, max, *_data);
+ unsigned int size = _data->getNx()*_data->getNy()*_data- >getNz();
+ for (int i = 0; i < (int)size; i++)
+ {
+ if ((*_data)[i] < min) min = (*_data)[i];
+ if ((*_data)[i] > max) max = (*_data)[i];
+ }
+ if (forceDataMin != -FLT_MAX || forceDataMax != -FLT_MAX)
+ {
+ min = forceDataMin;
+ max = forceDataMax;
+ }
+ _dataMin = min;
+ _dataMax = max;
+ _colorScalar = 1.0f/(_dataMax - _dataMin);
+ cout << "datamin/max: " << min << " " << max << endl;
- _depth = depth;
- if (_depth <= 0)
+ _depth = depth;
+ if (_depth <= 0)
_depth=1;
- _datadiag = diag;
- _nx = _data->getNx();
- _ny = _data->getNy();
- _nz = _data->getNz();
- _sdiag = _datadiag/Vector(_nx-1,_ny-1,_nz-1);
- inv_diag = diag.inverse();
-
- // Compute all the grid stuff
- _xsize=new int[depth];
- _ysize=new int[depth];
- _zsize=new int[depth];
- int tx=_nx-1;
- int ty=_ny-1;
- int tz=_nz-1;
- for(int i=depth-1;i>=0;i--){
+ _datadiag = diag;
+ _nx = _data->getNx();
+ _ny = _data->getNy();
+ _nz = _data->getNz();
+ _sdiag = _datadiag/Vector(_nx-1,_ny-1,_nz-1);
+ inv_diag = diag.inverse();
+
+ // Compute all the grid stuff
+ _xsize=new int[depth];
+ _ysize=new int[depth];
+ _zsize=new int[depth];
+ int tx=_nx-1;
+ int ty=_ny-1;
+ int tz=_nz-1;
+ for(int i=depth-1;i>=0;i--){
int nx=(int)(pow(tx, 1./(i+1))+.9);
tx=(tx+nx-1)/nx;
_xsize[depth-i-1]=nx;
@@ -275,88 +276,114 @@
int nz=(int)(pow(tz, 1./(i+1))+.9);
tz=(tz+nz-1)/nz;
_zsize[depth-i-1]=nz;
- }
- _ixsize=new double[depth];
- _iysize=new double[depth];
- _izsize=new double[depth];
- cerr << "Calculating depths...\n";
- for(int i=0;i<depth;i++){
+ }
+ _ixsize=new double[depth];
+ _iysize=new double[depth];
+ _izsize=new double[depth];
+ cerr << "Calculating depths...\n";
+ for(int i=0;i<depth;i++){
cerr << "xsize=" << _xsize[i] << ", ysize=" << _ysize[i] << ", zsize=" << _zsize[i] << '\n';
_ixsize[i]=1./_xsize[i];
_iysize[i]=1./_ysize[i];
_izsize[i]=1./_zsize[i];
- }
- cerr << "X: ";
- tx=1;
- for(int i=depth-1;i>=0;i--){
+ }
+ cerr << "X: ";
+ tx=1;
+ for(int i=depth-1;i>=0;i--){
cerr << _xsize[i] << ' ';
tx*=_xsize[i];
- }
- cerr << "(" << tx << ")\n";
- if(tx<_nx-1){
+ }
+ cerr << "(" << tx << ")\n";
+ if(tx<_nx-1){
cerr << "TX TOO SMALL!\n";
exit(1);
- }
- cerr << "Y: ";
- ty=1;
- for(int i=depth-1;i>=0;i--){
+ }
+ cerr << "Y: ";
+ ty=1;
+ for(int i=depth-1;i>=0;i--){
cerr << _ysize[i] << ' ';
ty*=_ysize[i];
- }
- cerr << "(" << ty << ")\n";
- if(ty<_ny-1){
+ }
+ cerr << "(" << ty << ")\n";
+ if(ty<_ny-1){
cerr << "TY TOO SMALL!\n";
exit(1);
- }
- cerr << "Z: ";
- tz=1;
- for(int i=depth-1;i>=0;i--){
+ }
+ cerr << "Z: ";
+ tz=1;
+ for(int i=depth-1;i>=0;i--){
cerr << _zsize[i] << ' ';
tz*=_zsize[i];
- }
- cerr << "(" << tz << ")\n";
- if(tz<_nz-1){
+ }
+ cerr << "(" << tz << ")\n";
+ if(tz<_nz-1){
cerr << "TZ TOO SMALL!\n";
exit(1);
- }
- _hierdiag=_datadiag*Vector(tx,ty,tz)/Vector(_nx-1,_ny-1,_nz-1);
- _ihierdiag=_hierdiag.inverse();
+ }
+ _hierdiag=_datadiag*Vector(tx,ty,tz)/ Vector(_nx-1,_ny-1,_nz-1);
+ _ihierdiag=_hierdiag.inverse();
- if(depth==1){
+ if(depth==1){
macrocells=0;
- } else {
+ } else {
macrocells=new GridArray3<VMCell>[depth+1];
int xs=1;
int ys=1;
int zs=1;
for(int d=depth-1;d>=1;d--){
- xs*=_xsize[d];
- ys*=_ysize[d];
- zs*=_zsize[d];
- macrocells[d].resize(xs, ys, zs);
- cerr << "Depth " << d << ": " << xs << "x" << ys << "x" << zs << '\n';
+ xs*=_xsize[d];
+ ys*=_ysize[d];
+ zs*=_zsize[d];
+ macrocells[d].resize(xs, ys, zs);
+ cerr << "Depth " << d << ": " << xs << "x" << ys << "x" << zs << '\n';
}
cerr << "Building hierarchy\n";
VMCell top;
calc_mcell(depth-1,0,0,0,top);
cerr << "done\n";
- }
- //cerr << "************************************************** \n";
- //print(cerr);
- //cerr << "************************************************** \n";
- }
+ }
+ //cerr << "************************************************** \n";
+ //print(cerr);
+ //cerr << "************************************************** \n";
+ }
template<class T>
- Volume<T>::~Volume()
- {
- delete[] macrocells;
- delete[] _xsize;
- delete[] _ysize;
- delete[] _zsize;
- delete[] _ixsize;
- delete[] _iysize;
- delete[] _izsize;
- }
+ Volume<T>::~Volume()
+ {
+ delete[] macrocells;
+ delete[] _xsize;
+ delete[] _ysize;
+ delete[] _zsize;
+ delete[] _ixsize;
+ delete[] _iysize;
+ delete[] _izsize;
+ }
+
+ template<class T>
+ void Volume<T>::setBounds(BBox bounds)
+ {
+ //slightly expand the bounds.
+ _bounds[0] = bounds[0] - bounds.diagonal().length()*T_EPSILON;
+ _bounds[1] = bounds[1] + bounds.diagonal().length()*T_EPSILON;
+ Vector diag = _bounds.diagonal();
+
+ _cellSize = diag*Vector( 1.0 / (double)(_data->getNx()-1),
+ 1.0 / (double)(_data->getNy()-1),
+ 1.0 / (double)(_data->getNz()-1));
+
+ //_stepSize = cellStepSize*_cellSize.length()/sqrt(3.0);
+ _maxDistance = diag.length();
+
+ if (_depth <= 0)
+ _depth=1;
+ Vector old_datadiag = _datadiag;
+ _datadiag = diag;
+ _sdiag = _datadiag/Vector(_nx-1,_ny-1,_nz-1);
+ inv_diag = diag.inverse();
+
+ _hierdiag=_hierdiag*_datadiag/old_datadiag;
+ _ihierdiag=_hierdiag.inverse();
+ }
template<class T>
void computeMinMax(float& min, float& max, GridArray3<T>& grid)
@@ -909,7 +936,7 @@
if (alphas[i] < RAY_TERMINATION) {
if (start < 0)
start = i;
-
+
const Ray ray = rays.getRay(i);
if (lRays1.getHitMaterial(i) == this) //did we hit the outside of the volume?
lRays1.setRay(i, ray.origin() + ray.direction()*tMaxs[i],
Modified: trunk/Model/Primitives/Cube.cc
= = = = = = = = ======================================================================
--- trunk/Model/Primitives/Cube.cc (original)
+++ trunk/Model/Primitives/Cube.cc Fri Sep 12 17:34:52 2008
@@ -20,6 +20,12 @@
{
}
+void Cube::setMinMax(const Vector& p0, const Vector& p1)
+{
+ bbox[0] = Min(p0, p1);
+ bbox[1] = Max(p0, p1);
+}
+
void Cube::computeBounds(const PreprocessContext&, BBox& bbox_) const
{
// bbox.extendByPoint(Point(xmin, ymin, zmin));
Modified: trunk/Model/Primitives/Cube.h
= = = = = = = = ======================================================================
--- trunk/Model/Primitives/Cube.h (original)
+++ trunk/Model/Primitives/Cube.h Fri Sep 12 17:34:52 2008
@@ -13,11 +13,7 @@
public:
Cube(Material* mat, const Vector& min_, const Vector& max_ );
~Cube();
- void setMinMax(const Vector& p0, const Vector& p1)
- {
- bbox[0] = Min(p0, p1);
- bbox[1] = Max(p0, p1);
-}
+ void setMinMax(const Vector& p0, const Vector& p1);
virtual void computeBounds(const PreprocessContext& context,
BBox& bbox) const;
virtual void intersect(const RenderContext& context, RayPacket& rays) const ;
Modified: trunk/SwigInterface/wxManta.py
= = = = = = = = ======================================================================
--- trunk/SwigInterface/wxManta.py (original)
+++ trunk/SwigInterface/wxManta.py Fri Sep 12 17:34:52 2008
@@ -21,6 +21,7 @@
from MantaCameraPath import *
from CameraFrame import *
+from BackgroundFrame import *
from LightFrame import *
from MiscFrames import *
from ThreadsFrame import *
@@ -313,6 +314,12 @@
self.dialog_map[dialog_id] = CameraFrame
self.Bind(wx.EVT_MENU, self.OnShowDialog,
self.view_menu.Append(dialog_id, "Edit Camera"))
+
+ #Edit Background dialog.
+ dialog_id = wx.NewId()
+ self.dialog_map[dialog_id] = BackgroundFrame
+ self.Bind(wx.EVT_MENU, self.OnShowDialog,
+ self.view_menu.Append(dialog_id, "Edit Background"))
# Camera Path dialog.
dialog_id = wx.NewId()
Modified: trunk/scenes/csafe/python/SceneInfo.py
= = = = = = = = ======================================================================
--- trunk/scenes/csafe/python/SceneInfo.py (original)
+++ trunk/scenes/csafe/python/SceneInfo.py Fri Sep 12 17:34:52 2008
@@ -32,4 +32,6 @@
self.maxX = self.maxY = self.maxZ = 0.1
self.maxY = 0.2
self.histogramBuckets = 300
+ self.volumeMinBound = [-0.001, -0.101, -0.001]
+ self.volumeMaxBound = [0.101, 0.201, 0.101]
Modified: trunk/scenes/csafe/python/SceneMenus.py
= = = = = = = = ======================================================================
--- trunk/scenes/csafe/python/SceneMenus.py (original)
+++ trunk/scenes/csafe/python/SceneMenus.py Fri Sep 12 17:34:52 2008
@@ -196,11 +196,68 @@
self.scene.maxX = self.maxXSP.GetValue()
self.scene.maxY = self.maxYSP.GetValue()
self.scene.maxZ = self.maxZSP.GetValue()
- min = manta_new(Vector(float(self.scene.minX), float(self.scene.minY), float(self.scene.minZ)))
- max = manta_new(Vector(float(self.scene.maxX), float(self.scene.maxY), float(self.scene.maxZ)))
+ min = Vector(float(self.scene.minX), float(self.scene.minY), float(self.scene.minZ))
+ max = Vector(float(self.scene.maxX), float(self.scene.maxY), float(self.scene.maxZ))
self.scene.test.setClippingBBox(min, max)
self.scene.test.useClippingBBox(True)
+
+class VolPositionSizeFrame(wx.Frame):
+ def __init__(self, parent, id, title, scene):
+ wx.Frame.__init__(self, parent, id, title, None, (700, 600))
+ self.scene = scene
+ panel = wx.Panel(self,-1)
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ hSizer = wx.BoxSizer(wx.HORIZONTAL)
+ hSizer.Add(wx.StaticText(self,-1,"volume Position: "))
+ size = [ scene.volumeMaxBound[0]-scene.volumeMinBound[0],
+ scene.volumeMaxBound[1]-scene.volumeMinBound[1],
+ scene.volumeMaxBound[2]-scene.volumeMinBound[2] ]
+ position = [scene.volumeMinBound[0] + size[0]/2.0,
+ scene.volumeMinBound[1] + size[1]/2.0,
+ scene.volumeMinBound[2] + size[2]/2.0 ]
+
+ self.minXSP = self.addSpinner(self,position[0])
+ self.minYSP = self.addSpinner(self,position[1])
+ self.minZSP = self.addSpinner(self,position[2])
+ hSizer.Add(self.minXSP,0,wx.ALL,3)
+ hSizer.Add(self.minYSP,0,wx.ALL,3)
+ hSizer.Add(self.minZSP,0,wx.ALL,3)
+ sizer.Add(hSizer, 0, wx.ALL|wx.ALIGN_LEFT, 10)
+
+ hSizer2 = wx.BoxSizer(wx.HORIZONTAL)
+ hSizer2.Add(wx.StaticText(self,-1,"volume Size: "))
+ self.maxXSP = self.addSpinner(self,size[0])
+ self.maxYSP = self.addSpinner(self,size[1])
+ self.maxZSP = self.addSpinner(self,size[2])
+ hSizer2.Add(self.maxXSP,0,wx.ALL,3)
+ hSizer2.Add(self.maxYSP,0,wx.ALL,3)
+ hSizer2.Add(self.maxZSP,0,wx.ALL,3)
+ sizer.Add(hSizer2,0, wx.ALL|wx.ALIGN_LEFT, 10)
+
+ panel.SetSizer(sizer)
+
+
+
+ def addSpinner(self, where, value, id=wx.ID_ANY):
+ floatspin = FS.FloatSpin(where, id,
+ increment=0.001, value=value,
+ extrastyle=FS.FS_LEFT)
+ floatspin.SetFormat("%g")
+ floatspin.SetDigits(6)
+ floatspin.Bind(FS.EVT_FLOATSPIN, self.OnFloatSpin)
+ return floatspin
+
+ def OnFloatSpin(self, event):
+ self.scene.minX = self.minXSP.GetValue()
+ self.scene.minY = self.minYSP.GetValue()
+ self.scene.minZ = self.minZSP.GetValue()
+ self.scene.maxX = self.maxXSP.GetValue()
+ self.scene.maxY = self.maxYSP.GetValue()
+ self.scene.maxZ = self.maxZSP.GetValue()
+ min = Vector(float(self.scene.minX), float(self.scene.minY), float(self.scene.minZ))
+ max = Vector(float(self.scene.maxX), float(self.scene.maxY), float(self.scene.maxZ))
+ self.scene.test.setVolumePositionSize(min,max)
Modified: trunk/scenes/csafe/python/csafe_demo.py
= = = = = = = = ======================================================================
--- trunk/scenes/csafe/python/csafe_demo.py (original)
+++ trunk/scenes/csafe/python/csafe_demo.py Fri Sep 12 17:34:52 2008
@@ -86,6 +86,7 @@
menuScene.Append(204, "Add &Histogram", "Add a histogram to the panel")
menuScene.Append(202, "Scene Preferences")
menuScene.Append(205, "Cutting Bounding Box")
+ menuScene.Append(206, "Volume Position/Size")
menuScene.Append(203, "&Generate")
menuBar.Append(menuScene, "Scene")
@@ -108,12 +109,17 @@
self.Bind(wx.EVT_MENU, self.Menu204, id=204)
self.Bind(wx.EVT_MENU, self.Menu110, id=110)
self.Bind(wx.EVT_MENU, self.Menu205, id=205)
+ self.Bind(wx.EVT_MENU, self.MenuVolPositionSize, id = 206)
self.SetBackgroundColour(self.scene.bgColor)
def Menu205(self, evt):
frame = SceneMenus.BBoxFrame(self, -1, "Bounding Box", self.scene)
frame.Show(True)
+ def MenuVolPositionSize(self, evt):
+ frame = SceneMenus.VolPositionSizeFrame(self, -1, "Volume Position and Size", self.scene)
+ frame.Show(True)
+
def Menu110(self, evt):
self.SetFocus()
dlg = wx.DirDialog(self, message="Open UDA folder", style=wx.OPEN| wx.CHANGE_DIR)
@@ -400,7 +406,9 @@
self.volCMap = manta_new(RGBAColorMap(slices, 64));
- self.test = manta_new(CDTest(scene, engine));
+ minBound = Vector(self.scene.volumeMinBound[0], self.scene.volumeMinBound[1], self.scene.volumeMinBound[2])
+ maxBound = Vector(self.scene.volumeMaxBound[0], self.scene.volumeMaxBound[1], self.scene.volumeMaxBound[2])
+ self.test = manta_new(CDTest(scene, engine, minBound, maxBound));
self.test.initScene();
self.test.setVolCMap(self.volCMap);
self.scene.test = self.test
Modified: trunk/scenes/csafe/src/CDGridSpheres.cc
= = = = = = = = ======================================================================
--- trunk/scenes/csafe/src/CDGridSpheres.cc (original)
+++ trunk/scenes/csafe/src/CDGridSpheres.cc Fri Sep 12 17:34:52 2008
@@ -553,15 +553,14 @@
float* data=spheres + rays.scratchpad<int>(i);
Vector n=rays.getHitPosition(i) - Vector(data[0], data[1], data[2]);
- if (ridx>0) {
- if (data[ridx] <= 0)
- n *= inv_radius;
- else
- n /= data[ridx];
+ if (ridx>0) {
+ if (data[ridx] <= 0)
+ n *= inv_radius;
+ else
+ n.normalize();
} else {
- n *= inv_radius;
- }
-
+ n *= inv_radius;
+ }
rays.setNormal(i, n);
}
@@ -576,7 +575,7 @@
// Shade a bunch of rays that have intersected the same particle
// lambertianShade(context, rays, ambient);
-
+
_matl->shade(context, rays);
}
@@ -589,6 +588,7 @@
// Compute colors
Packet<Color> diffuse;
mapDiffuseColors(diffuse, rays);
+
/*
// Normalize directions for proper dot product computation
rays.normalizeDirections();
@@ -1085,12 +1085,12 @@
}
void CDGridSpheres::mapValues(Packet<Color>& results, const RenderContext&, RayPacket& rays) const {
- // cout << "mapping values based on color index: " << cidx << endl;
+ float minimum = cmin[cidx];
+ float inv_range = 1.0/(cmax[cidx]-minimum);
for(int i = rays.begin(); i < rays.end(); i++) {
int particle=rays.scratchpad<int>(i);
float value=*(spheres + particle + cidx);
- float minimum=cmin[cidx];
- float normalized=(value-minimum)/(cmax[cidx] - minimum);
+ float normalized=(value-minimum)*inv_range;
results.set(i, cmap->GetColor(normalized).color);
}
}
Modified: trunk/scenes/csafe/src/CDTest.h
= = = = = = = = ======================================================================
--- trunk/scenes/csafe/src/CDTest.h (original)
+++ trunk/scenes/csafe/src/CDTest.h Fri Sep 12 17:34:52 2008
@@ -66,960 +66,964 @@
/*!
- \class CDTest
- \brief c++ Bridge for running csafe code
- \author Carson Brownlee
- Description: used for running c++ heavy code for csafe demo
- */
+ \class CDTest
+ \brief c++ Bridge for running csafe code
+ \author Carson Brownlee
+ Description: used for running c++ heavy code for csafe demo
+*/
class CDTest
+{
+ public:
+ //! CDTest constructor
+ /*!
+ \param pass in the scene, or NULL and set it later
+ \param pass in MantaInterface used for rendering
+ */
+ CDTest(Scene* scene, MantaInterface* interface, Vector volumeMinBound, Vector volumeMaxBound)
{
- public:
- //! CDTest constructor
- /*!
- \param pass in the scene, or NULL and set it later
- \param pass in MantaInterface used for rendering
- */
- CDTest(Scene* scene, MantaInterface* interface)
- {
- _sphereAnimation=NULL;
- _volCMap=NULL;
- _volAnimation = NULL;
- _scene = scene;
- _ridx = 6;
- _cidx = 4;
- _radius = 0.0003;
- numFrames = numFrames1 = numFrames2 = 0;
- //_readContext = context;
- _manta_interface = interface;
- _forceDataMin = -FLT_MAX;
- _forceDataMax = -FLT_MAX;
- _useAO = false;
- _spheresVisible = true;
- _volVisible = true;
- _sphereCMap = NULL;
- _sphereDMins = new float[16];
- _sphereDMaxs = new float[16];
- }
-
- ~CDTest()
- {
- delete[] _sphereDMins;
- delete[] _sphereDMaxs;
- }
+ _sphereAnimation=NULL;
+ _volCMap=NULL;
+ _volAnimation = NULL;
+ _scene = scene;
+ _ridx = 6;
+ _cidx = 4;
+ _radius = 0.0003;
+ numFrames = numFrames1 = numFrames2 = 0;
+ //_readContext = context;
+ _manta_interface = interface;
+ _forceDataMin = -FLT_MAX;
+ _forceDataMax = -FLT_MAX;
+ _useAO = false;
+ _spheresVisible = true;
+ _volVisible = true;
+ _sphereCMap = NULL;
+ _sphereDMins = new float[16];
+ _sphereDMaxs = new float[16];
+ _minBound = volumeMinBound;
+ _maxBound = volumeMaxBound;
+ }
+
+ ~CDTest()
+ {
+ delete[] _sphereDMins;
+ delete[] _sphereDMaxs;
+ }
- //! sets the scene object, necessary for initializing scene and loading spheres/volume
- /*!
- \param scene to set
- */
- void setScene(Scene* scene)
- {
- _scene = scene;
- }
-
- //! initializes the scene, must do before rendering
- /*!
- */
- void initScene()
- {
- if (!_sphereCMap)
- _sphereCMap = LinearColormap<float>::createColormap(Rainbow, 400,600);
- ValueColormap<float>* vcmap = new ValueColormap<float>(_sphereCMap);
- _sphereMatl = new Phong(vcmap,vcmap, 10, NULL);
- _world = new Group();
- _scene->setBackground(new ConstantBackground(Color(RGB(. 5, .5, .5))));
- _scene->setObject(_world);
-
- LightSet* lights = new LightSet();
- lights->add(new PointLight(Vector(-500, 300, -300), Color(RGB(.8,.8,.8))));
-
- lights->setAmbientLight(new ConstantAmbient(Color(RGB(. 4,.4,.4))));
- _scene->setLights(lights);
- Group* group = new Group();
- Primitive* prim = new Cube( new Lambertian(Color(RGBColor(1,0,0))), Vector(-0.1, -0.1, 0.4)*0, Vector(0.1, 0.1, 0.7)*0);
- if (_sphereAnimation)
- delete _sphereAnimation;
- _sphereAnimation= new KeyFrameAnimation();
+ //! sets the scene object, necessary for initializing scene and loading spheres/volume
+ /*!
+ \param scene to set
+ */
+ void setScene(Scene* scene)
+ {
+ _scene = scene;
+ }
+
+ //! initializes the scene, must do before rendering
+ /*!
+ */
+ void initScene()
+ {
+ if (!_sphereCMap)
+ _sphereCMap = LinearColormap<float>::createColormap(Rainbow, 400,600);
+ ValueColormap<float>* vcmap = new ValueColormap<float>(_sphereCMap);
+ _sphereMatl = new Phong(vcmap,vcmap, 10, NULL);
+ _world = new Group();
+ _scene->setBackground(new ConstantBackground(Color(RGB(.5, . 5, .5))));
+ _scene->setObject(_world);
+
+ LightSet* lights = new LightSet();
+ lights->add(new PointLight(Vector(-500, 300, -300), Color(RGB(.8,.8,.8))));
+
+ lights->setAmbientLight(new ConstantAmbient(Color(RGB(. 4,.4,.4))));
+ _scene->setLights(lights);
+ Group* group = new Group();
+ Primitive* prim = new Cube( new Lambertian(Color(RGBColor(1,0,0))), Vector(-0.1, -0.1, 0.4)*0, Vector(0.1, 0.1, 0.7)*0);
+ if (_sphereAnimation)
+ delete _sphereAnimation;
+ _sphereAnimation= new KeyFrameAnimation();
#if !PRECOMPUTE_GRIDS
- _sphereAnimation->useAccelerationStructure(new RecursiveGrid(3));
+ _sphereAnimation->useAccelerationStructure(new RecursiveGrid(3));
#endif
- if (_volAnimation)
- delete _volAnimation;
- _volAnimation = new KeyFrameAnimation();
- Primitive* prim2 = new Cube( new Lambertian(Color(RGBColor(0,0,1))), Vector(-0.1, -0.1, 0.4), Vector(0.1, 0.1, .7));
- group->add(prim);
- Group* group2 = new Group();
- group2->add(prim2);
- _world->add(_sphereAnimation);
- _world->add(_volAnimation);
- _sphereAnimation->setDuration(15);
- _volAnimation->setDuration(15);
- duration = 10;
- numFrames1 = numFrames2 = numFrames = 1;
-
- _minBound = Vector(-0.001, -0.101, -0.001);
- _maxBound = Vector( 0.101, 0.201, 0.101);
-
- if (!_volCMap)
- {
- vector<ColorSlice> slices;
- float div = 1.0/255.0;
- float a = 0.1;
- slices.push_back(ColorSlice(0.0f, RGBAColor(Color(RGB(0, 0, 0)) * div, 0*a)));
- slices.push_back(ColorSlice(0.109804f, RGBAColor(Color(RGB(52, 0, 0)) * div, 0*a)));
- slices.push_back(ColorSlice(0.01f, RGBAColor(Color(RGB(102, 2, 0)) * div, 0.1*a)));
- slices.push_back(ColorSlice(0.328571f, RGBAColor(Color(RGB(153, 18, 0)) * div, 0.216667*a)));
- slices.push_back(ColorSlice(0.4f, RGBAColor(Color(RGB(200, 41, 0)) * div, 0.23*a)));
- slices.push_back(ColorSlice(0.5f, RGBAColor(Color(RGB(230, 71, 0)) * div, 0.27*a)));
- slices.push_back(ColorSlice(0.618367f, RGBAColor(Color(RGB(255, 120, 0)) * div, 0.3375*a)));
- slices.push_back(ColorSlice(0.68f, RGBAColor(Color(RGB(255, 163, 20)) * div, 0.35*a)));
- slices.push_back(ColorSlice(0.72f, RGBAColor(Color(RGB(255, 204, 55)) * div, 0.37*a)));
- slices.push_back(ColorSlice(0.79f, RGBAColor(Color(RGB(255, 228, 80)) * div, 0.39*a)));
- slices.push_back(ColorSlice(0.85f, RGBAColor(Color(RGB(255, 247, 120)) * div, 0.43*a)));
- slices.push_back(ColorSlice(0.92f, RGBAColor(Color(RGB(255, 255, 180)) * div, 0.47*a)));
- slices.push_back(ColorSlice(1.0f, RGBAColor(Color(RGB(255, 255, 255)) * div, 0.5*a)));
+ if (_volAnimation)
+ delete _volAnimation;
+ _volAnimation = new KeyFrameAnimation();
+ Primitive* prim2 = new Cube( new Lambertian(Color(RGBColor(0,0,1))), Vector(-0.1, -0.1, 0.4), Vector(0.1, 0.1, .7));
+ group->add(prim);
+ Group* group2 = new Group();
+ group2->add(prim2);
+ _world->add(_sphereAnimation);
+ _world->add(_volAnimation);
+ _sphereAnimation->setDuration(15);
+ _volAnimation->setDuration(15);
+ duration = 10;
+ numFrames1 = numFrames2 = numFrames = 1;
+
+
+ if (!_volCMap)
+ {
+ vector<ColorSlice> slices;
+ float div = 1.0/255.0;
+ float a = 0.1;
+ slices.push_back(ColorSlice(0.0f, RGBAColor(Color(RGB(0, 0, 0)) * div, 0*a)));
+ slices.push_back(ColorSlice(0.109804f, RGBAColor(Color(RGB(52, 0, 0)) * div, 0*a)));
+ slices.push_back(ColorSlice(0.01f, RGBAColor(Color(RGB(102, 2, 0)) * div, 0.1*a)));
+ slices.push_back(ColorSlice(0.328571f, RGBAColor(Color(RGB(153, 18, 0)) * div, 0.216667*a)));
+ slices.push_back(ColorSlice(0.4f, RGBAColor(Color(RGB(200, 41, 0)) * div, 0.23*a)));
+ slices.push_back(ColorSlice(0.5f, RGBAColor(Color(RGB(230, 71, 0)) * div, 0.27*a)));
+ slices.push_back(ColorSlice(0.618367f, RGBAColor(Color(RGB(255, 120, 0)) * div, 0.3375*a)));
+ slices.push_back(ColorSlice(0.68f, RGBAColor(Color(RGB(255, 163, 20)) * div, 0.35*a)));
+ slices.push_back(ColorSlice(0.72f, RGBAColor(Color(RGB(255, 204, 55)) * div, 0.37*a)));
+ slices.push_back(ColorSlice(0.79f, RGBAColor(Color(RGB(255, 228, 80)) * div, 0.39*a)));
+ slices.push_back(ColorSlice(0.85f, RGBAColor(Color(RGB(255, 247, 120)) * div, 0.43*a)));
+ slices.push_back(ColorSlice(0.92f, RGBAColor(Color(RGB(255, 255, 180)) * div, 0.47*a)));
+ slices.push_back(ColorSlice(1.0f, RGBAColor(Color(RGB(255, 255, 255)) * div, 0.5*a)));
- _volCMap = new RGBAColorMap(slices, 64);
- }
- //Group* cutWorld = new Group();
- //cutWorld->add(new CuttingPlane(Vector(0,0,0), Vector(0,1,0), _world));
- //_scene->setObject(cutWorld);
- _sphereAnimationCut = new Group();
- _cuts[0] = new CuttingPlane(Vector(0,1,0), Vector(0,1,0), _sphereAnimation);
- _cuts[1] = new CuttingPlane(Vector(0,0,0), Vector(0,-1,0), _cuts[0]);
- _cuts[2] = new CuttingPlane(Vector(0,0,0), Vector(-1,0,0), _cuts[1]);
- _cuts[3] = new CuttingPlane(Vector(0,0,0), Vector(1,0,0), _cuts[2]);
- _cuts[4] = new CuttingPlane(Vector(0,0,0), Vector(0,0,1), _cuts[3]);
- _cuts[5] = new CuttingPlane(Vector(0,0,0), Vector(0,0,-1), _cuts[4]);
- _sphereAnimationCut->add(_cuts[0]);
- }
- Group* _sphereAnimationCut;
- CuttingPlane* _cuts[6]; //up down left right forward back
- bool _useClippingBBox, _spheresVisible, _volVisible;
- void setClippingBBox(Vector min, Vector max)
- {
- cout << "clipping min max: " << min[0] << " " << min[1] << " " << min[2]
- << "\n" << max[0] << " " << max[1] << " " << max[2] << endl;
- /*_cuts[0]->setPlanePoint(max);
- _cuts[1]->setPlanePoint(min);
- _cuts[2]->setPlanePoint(min);
- _cuts[3]->setPlanePoint(max);
- _cuts[4]->setPlanePoint(max);
- _cuts[5]->setPlanePoint(min);
- LightSet* lights = _scene->getLights();
- PreprocessContext context(_manta_interface, 0, 1, lights);
- for(int i = 0; i < 6; i++)
- {
- _sphereAnimation->computeBounds(context, _cuts[i]- >bounds);
- }*/
- for(int i =0; i < 3; i++)
- setClipMinMax(i, min[i], max[i]);
- Vector minB(_minBound);
- Vector maxB(_maxBound);
- for(int i=0;i<3;i++)
- {
- minB[i] = std::max(min[i], minB[i]);
- maxB[i] = std::min(max[i], maxB[i]);
- }
- for(int i = 0; i < int(_volPrims.size()); i++)
- {
- _volPrims[i]->setMinMax(minB, maxB);
- }
- }
- void useClippingBBox(bool st)
- {
- /* _useClippingBBox = st;
- if (st == true)
- {
- _world = new Group();
- if (_volVisible)
- _world->add(_volAnimation);
- if (_spheresVisible)
- _world->add(_sphereAnimationCut);
- _scene->setObject(_world);
- }
- else
- {
- _world = new Group();
- if (_volVisible)
- _world->add(_volAnimation);
- if (_spheresVisible)
- _world->add(_sphereAnimation);
- }*/
- }
- void setVisibility(bool spheres, bool volume)
- {
- _spheresVisible = spheres;
- _volVisible = volume;
- _world = new Group();
- if (spheres)
- {
- _world->add(_sphereAnimation);
- /*if(_useClippingBBox)
- _world->add(_sphereAnimationCut);
+ _volCMap = new RGBAColorMap(slices, 64);
+ }
+ //Group* cutWorld = new Group();
+ //cutWorld->add(new CuttingPlane(Vector(0,0,0), Vector(0,1,0), _world));
+ //_scene->setObject(cutWorld);
+ _sphereAnimationCut = new Group();
+ _cuts[0] = new CuttingPlane(Vector(0,1,0), Vector(0,1,0), _sphereAnimation);
+ _cuts[1] = new CuttingPlane(Vector(0,0,0), Vector(0,-1,0), _cuts[0]);
+ _cuts[2] = new CuttingPlane(Vector(0,0,0), Vector(-1,0,0), _cuts[1]);
+ _cuts[3] = new CuttingPlane(Vector(0,0,0), Vector(1,0,0), _cuts[2]);
+ _cuts[4] = new CuttingPlane(Vector(0,0,0), Vector(0,0,1), _cuts[3]);
+ _cuts[5] = new CuttingPlane(Vector(0,0,0), Vector(0,0,-1), _cuts[4]);
+ _sphereAnimationCut->add(_cuts[0]);
+ }
+ Group* _sphereAnimationCut;
+ CuttingPlane* _cuts[6]; //up down left right forward back
+ bool _useClippingBBox, _spheresVisible, _volVisible;
+ void setVolumePositionSize(Vector position, Vector size)
+ {
+ _volPosition = position;
+ _volSize = size;
+ _manta_interface- >addOneShotCallback(MantaInterface::Relative, 2, Callback::create(this, &CDTest::setVolumePositionSizeHelper));
+ }
+ void setClippingBBox(Vector min, Vector max)
+ {
+ for(int i =0; i < 3; i++)
+ setClipMinMax(i, min[i], max[i]);
+ Vector minB(_minBound);
+ Vector maxB(_maxBound);
+ for(int i=0;i<3;i++)
+ {
+ minB[i] = std::max(min[i], minB[i]);
+ maxB[i] = std::min(max[i], maxB[i]);
+ }
+ for(int i = 0; i < int(_volPrims.size()); i++)
+ {
+ _volPrims[i]->setMinMax(minB, maxB);
+ }
+ }
+ void useClippingBBox(bool st)
+ {
+ /* _useClippingBBox = st;
+ if (st == true)
+ {
+ _world = new Group();
+ if (_volVisible)
+ _world->add(_volAnimation);
+ if (_spheresVisible)
+ _world->add(_sphereAnimationCut);
+ _scene->setObject(_world);
+ }
+ else
+ {
+ _world = new Group();
+ if (_volVisible)
+ _world->add(_volAnimation);
+ if (_spheresVisible)
+ _world->add(_sphereAnimation);
+ }*/
+ }
+ void setVisibility(bool spheres, bool volume)
+ {
+ _spheresVisible = spheres;
+ _volVisible = volume;
+ _world = new Group();
+ if (spheres)
+ {
+ _world->add(_sphereAnimation);
+ /*if(_useClippingBBox)
+ _world->add(_sphereAnimationCut);
else
_world->add(_sphereAnimation);*/
- }
- if (volume)
- _world->add(_volAnimation);
- _scene->setObject(_world);
- }
-
- //! add a sphere file to be loaded
- /*!
- \param file to be loaded later
- */
- void addSphereNrrd(string file)
- {
- _nrrdFilenames.push_back(file);
- }
-
- //! clear list of sphere files
- /*!
- */
- void clearSphereNrrds()
- {
- _nrrdFilenames.clear();
- numFrames1 = 0;
- numFrames = numFrames2;
- }
-
- //! add volume nrrd file to be loaded
- /*!
- \param file to add to be loaded later
- */
- void addVolNrrd(string file)
- {
- _nrrdFilenames2.push_back(file);
- }
-
- //! clear list of volume files
- /*!
- */
- void clearVolNrrds()
- {
- _nrrdFilenames2.clear();
- numFrames2 = 0;
- numFrames = numFrames1;
- }
-
- //! load list of sphere nrrd files
- /*!
- */
- void loadSphereNrrds()
- {
- LightSet* lights = _scene->getLights();
- PreprocessContext context(_manta_interface, 0, 1, lights);
- _nrrds.clear();
- for(int i = 0; i < 16; i++) {
- _sphereDMins[i] = -FLT_MAX;
- _sphereDMaxs[i] = FLT_MAX;
- }
+ }
+ if (volume)
+ _world->add(_volAnimation);
+ _scene->setObject(_world);
+ }
- for(vector<string>::iterator itr = _nrrdFilenames.begin(); itr != _nrrdFilenames.end(); itr++)
- {
- cout << "Loading Nrrd file: " << *itr << "...\n";
- ParticleNRRD* pnrrd = new ParticleNRRD();
- pnrrd->readFile(*itr);
- if (_cidx >= int(pnrrd->getNVars())) {
- cerr << "error: color index not in data, settting to index
0\n";
- _cidx = 0;
- }
- if (_ridx >= int(pnrrd->getNVars())) {
- cerr << "error: radius index not in data, setting to constant radius\n";
- _ridx = -1;
- }
- if (pnrrd->getNVars() < 3) {
- cerr << "fatal IO error: expected a sphere file with at least 3 data indices\n";
- exit(2);
- }
- _spherePNrrds.push_back(pnrrd);
- Group* group = new Group();
+ //! add a sphere file to be loaded
+ /*!
+ \param file to be loaded later
+ */
+ void addSphereNrrd(string file)
+ {
+ _nrrdFilenames.push_back(file);
+ }
+
+ //! clear list of sphere files
+ /*!
+ */
+ void clearSphereNrrds()
+ {
+ _nrrdFilenames.clear();
+ numFrames1 = 0;
+ numFrames = numFrames2;
+ }
+
+ //! add volume nrrd file to be loaded
+ /*!
+ \param file to add to be loaded later
+ */
+ void addVolNrrd(string file)
+ {
+ _nrrdFilenames2.push_back(file);
+ }
+
+ //! clear list of volume files
+ /*!
+ */
+ void clearVolNrrds()
+ {
+ _nrrdFilenames2.clear();
+ numFrames2 = 0;
+ numFrames = numFrames1;
+ }
+
+ //! load list of sphere nrrd files
+ /*!
+ */
+ void loadSphereNrrds()
+ {
+ LightSet* lights = _scene->getLights();
+ PreprocessContext context(_manta_interface, 0, 1, lights);
+ _nrrds.clear();
+ for(int i = 0; i < 16; i++) {
+ _sphereDMins[i] = -FLT_MAX;
+ _sphereDMaxs[i] = FLT_MAX;
+ }
+
+ for(vector<string>::iterator itr = _nrrdFilenames.begin(); itr != _nrrdFilenames.end(); itr++)
+ {
+ cout << "Loading Nrrd file: " << *itr << "...\n";
+ ParticleNRRD* pnrrd = new ParticleNRRD();
+ pnrrd->readFile(*itr);
+ if (_cidx >= int(pnrrd->getNVars())) {
+ cerr << "error: color index not in data, settting to index 0\n";
+ _cidx = 0;
+ }
+ if (_ridx >= int(pnrrd->getNVars())) {
+ cerr << "error: radius index not in data, setting to constant radius\n";
+ _ridx = -1;
+ }
+ if (pnrrd->getNVars() < 3) {
+ cerr << "fatal IO error: expected a sphere file with at least 3 data indices\n";
+ exit(2);
+ }
+ _spherePNrrds.push_back(pnrrd);
+ Group* group = new Group();
#if USE_GRIDSPHERES
- RGBAColorMap* cmap = new RGBAColorMap(1);
- CDGridSpheres* grid = new CDGridSpheres(pnrrd- >getParticleData(), pnrrd->getNParticles(), pnrrd->getNVars(), 6, 2,_radius, _ridx, cmap , _cidx);
- //grid->setCMinMax(4, 299.50411987304688, 500.59423828125);
- //Material* matl = new Phong(Color(RGB(1,0,0)), Color(RGB(1,0,0)), 10);
- //Material* matl = new AmbientOcclusion(colormap, 0.01, 10);
- //grid->preprocess(context);
+ RGBAColorMap* cmap = new RGBAColorMap(1);
+ CDGridSpheres* grid = new CDGridSpheres(pnrrd- >getParticleData(), pnrrd->getNParticles(), pnrrd->getNVars(), 6, 2,_radius, _ridx, cmap , _cidx);
+ //grid->setCMinMax(4, 299.50411987304688, 500.59423828125);
+ //Material* matl = new Phong(Color(RGB(1,0,0)), Color(RGB(1,0,0)), 10);
+ //Material* matl = new AmbientOcclusion(colormap, 0.01, 10);
+ //grid->preprocess(context);
#else
- Group* g = new Group();
- _sphereGroups.push_back(g);
- CSAFEPrim::init(pnrrd->getNVars(), _sphereDMins, _sphereDMaxs, _cidx);
- float radius = _radius;
- for(size_t i = 0; i < pnrrd->getNParticles(); i++) {
- float* data = pnrrd->getParticleData() +
i*pnrrd->getNVars();
- if (_ridx > -1)
- radius = data[_ridx];
- g->add(new CSAFEPrim(new Sphere(_sphereMatl, Vector(data[0],data[1],data[2]),radius), data));
- // g->add( new ValuePrimitive<float>(new Sphere(matl, Vector(data[0],data[1],data[2]),data[_ridx]), data[_cidx]));
- // g->add(new Sphere(matl, Vector(data[0], data[1], data[2]), data[_ridx]));
- }
+ Group* g = new Group();
+ _sphereGroups.push_back(g);
+ CSAFEPrim::init(pnrrd->getNVars(), _sphereDMins, _sphereDMaxs, _cidx);
+ float radius = _radius;
+ for(size_t i = 0; i < pnrrd->getNParticles(); i++) {
+ float* data = pnrrd->getParticleData() + i*pnrrd->getNVars();
+ if (_ridx > -1)
+ radius = data[_ridx];
+ g->add(new CSAFEPrim(new Sphere(_sphereMatl, Vector(data[0],data[1],data[2]),radius), data));
+ // g->add( new ValuePrimitive<float>(new Sphere(matl, Vector(data[0],data[1],data[2]),data[_ridx]), data[_cidx]));
+ // g->add(new Sphere(matl, Vector(data[0], data[1], data[2]), data[_ridx]));
+ }
#if PRECOMPUTE_GRIDS
- RecursiveGrid* grid = new RecursiveGrid();
- //g->preprocess(context);
- //ParticleGrid* grid = new ParticleGrid(pnrrd, _radius, _ridx, _cidx);
- grid->setGroup(g);
- //grid->preprocess(context);
- cout << "building grid\n";
- grid->rebuild();
- cout << "done building grid\n";
+ RecursiveGrid* grid = new RecursiveGrid();
+ //g->preprocess(context);
+ //ParticleGrid* grid = new ParticleGrid(pnrrd, _radius, _ridx, _cidx);
+ grid->setGroup(g);
+ //grid->preprocess(context);
+ cout << "building grid\n";
+ grid->rebuild();
+ cout << "done building grid\n";
#endif
#endif //USE_GRIDSPHERES
- group->add(grid);
- _sphereGrids.push_back(grid);
+ group->add(grid);
+ _sphereGrids.push_back(grid);
#if PRECOMPUTE_GRIDS
- _sphereAnimation->push_back(group);
+ _sphereAnimation->push_back(group);
#else
- _sphereAnimation->push_back(g);
+ _sphereAnimation->push_back(g);
#endif //PRECOMPUTE_GRIDS
- if (pnrrd->getNVars() > _sphereMins.size())
- {
- for(size_t j = _sphereMins.size(); j < pnrrd- >getNVars(); j++)
- {
- _sphereMins.push_back(FLT_MAX);
- _sphereMaxs.push_back(-FLT_MAX);
- }
- }
- for(int j = 0; j < int(_sphereMins.size()); j++)
- {
- float min = _sphereMins[j];
- float max = _sphereMaxs[j];
- float* pdata = pnrrd->getParticleData();
- for(size_t i = 0; i < pnrrd->getNParticles(); i++) {
- if (pdata[j] < min)
- min = pdata[j];
- if (pdata[j] > max)
- max = pdata[j];
- pdata += pnrrd->getNVars();
- }
- _sphereMins[j] = min;
- _sphereMaxs[j] = max;
- }
- //_sphereAnimation->useAccelerationStructure(grid);
- numFrames1++;
- //Nrrd *new_nrrd = nrrdNew();
-
////////////////////////////////////////////////////////////////////////////
- // Attempt to open the nrrd
- //if (nrrdLoad( new_nrrd, i->c_str(), 0 )) {
- // char *reason = biffGetDone( NRRD );
- // std::cout << "WARNING Loading Nrrd Failed: " << reason << std::endl;
- // exit(__LINE__);
- // }
-
- // Check to make sure the nrrd is the proper dimensions.
- // if (new_nrrd->dim != 3) {
- // std::cout << "WARNING Nrrd must three dimension RGB" << std::endl;
- // exit(__LINE__);
- // }
-
- //_nrrds.push_back(new_nrrd);
- cout << "Loading " << *itr << " done.\n";
- }
- // _sphereAnimation->preprocess(context);
- updateFrames();
- if (_clipFrames && _endFrame < int(_sphereGrids.size()))
- _sphereAnimation->clipFrames(_startFrame, _endFrame);
- }
- vector<Cube*> _volPrims;
- //! clear list of volume files
- /*!
- */
- void loadVolNrrds()
- {
- for(vector<string>::iterator i = _nrrdFilenames2.begin(); i != _nrrdFilenames2.end(); i++)
- {
- cout << "Loading Nrrd file: " << *i << "..." << endl;
- Group* group = new Group();
- Volume<float>* mat = new Volume<float>(loadNRRDToGrid<float>(*i), _volCMap, BBox(_minBound, _maxBound), 0.00125, 3, _forceDataMin, _forceDataMax);
- Cube* vol = new Cube(mat, _minBound, _maxBound);
- group->add(vol);
- _volAnimation->push_back(group);
- _vols.push_back(mat);
- _volPrims.push_back(vol);
- numFrames2++;
- cout << "Loading " << *i << " done.\n";
- }
- updateFrames();
- if (_clipFrames && _endFrame < int(_vols.size()))
- _volAnimation->clipFrames(_startFrame, _endFrame);
- }
- void readUDAHeader(string directory)
- {
- uda.readUDAHeader(directory);
- }
- int getUDANumVars() { return uda.getNumVariables(); }
- string getUDAVarName(int i) { return uda.getVarHeader(i).name; }
- void loadUDA(string file, string volName)
- {
- //TODO: clear out existing data
- LightSet* lights = _scene->getLights();
- PreprocessContext context(_manta_interface, 0, 1, lights);
- uda.readUDA(file, volName);
- for (std::vector<UDAReader::Timestep>::iterator itr = uda.timesteps.begin(); itr != uda.timesteps.end(); itr++)
- {
- float* sdata = itr->sphereData;
+ if (pnrrd->getNVars() > _sphereMins.size())
+ {
+ for(size_t j = _sphereMins.size(); j < pnrrd->getNVars(); j++)
+ {
+ _sphereMins.push_back(FLT_MAX);
+ _sphereMaxs.push_back(-FLT_MAX);
+ }
+ }
+ for(int j = 0; j < int(_sphereMins.size()); j++)
+ {
+ float min = _sphereMins[j];
+ float max = _sphereMaxs[j];
+ float* pdata = pnrrd->getParticleData();
+ for(size_t i = 0; i < pnrrd->getNParticles(); i++) {
+ if (pdata[j] < min)
+ min = pdata[j];
+ if (pdata[j] > max)
+ max = pdata[j];
+ pdata += pnrrd->getNVars();
+ }
+ _sphereMins[j] = min;
+ _sphereMaxs[j] = max;
+ }
+ //_sphereAnimation->useAccelerationStructure(grid);
+ numFrames1++;
+ //Nrrd *new_nrrd = nrrdNew();
+ ////////////////////////////////////////////////////////////////////////////
+ // Attempt to open the nrrd
+ //if (nrrdLoad( new_nrrd, i->c_str(), 0 )) {
+ // char *reason = biffGetDone( NRRD );
+ // std::cout << "WARNING Loading Nrrd Failed: " << reason << std::endl;
+ // exit(__LINE__);
+ // }
+
+ // Check to make sure the nrrd is the proper dimensions.
+ // if (new_nrrd->dim != 3) {
+ // std::cout << "WARNING Nrrd must three dimension RGB" << std::endl;
+ // exit(__LINE__);
+ // }
+
+ //_nrrds.push_back(new_nrrd);
+ cout << "Loading " << *itr << " done.\n";
+ }
+ // _sphereAnimation->preprocess(context);
+ updateFrames();
+ if (_clipFrames && _endFrame < int(_sphereGrids.size()))
+ _sphereAnimation->clipFrames(_startFrame, _endFrame);
+ }
+ //! clear list of volume files
+ /*!
+ */
+ void loadVolNrrds()
+ {
+ for(vector<string>::iterator i = _nrrdFilenames2.begin(); i ! = _nrrdFilenames2.end(); i++)
+ {
+ cout << "Loading Nrrd file: " << *i << "..." << endl;
+ Group* group = new Group();
+ Volume<float>* mat = new Volume<float>(loadNRRDToGrid<float>(*i), _volCMap, BBox(_minBound, _maxBound), 0.00125, 3, _forceDataMin, _forceDataMax);
+ Cube* vol = new Cube(mat, _minBound, _maxBound);
+ group->add(vol);
+ _volAnimation->push_back(group);
+ _vols.push_back(mat);
+ _volPrims.push_back(vol);
+ numFrames2++;
+ cout << "Loading " << *i << " done.\n";
+ }
+ updateFrames();
+ if (_clipFrames && _endFrame < int(_vols.size()))
+ _volAnimation->clipFrames(_startFrame, _endFrame);
+ }
+ void readUDAHeader(string directory)
+ {
+ uda.readUDAHeader(directory);
+ }
+ int getUDANumVars() { return uda.getNumVariables(); }
+ string getUDAVarName(int i) { return uda.getVarHeader(i).name; }
+ void loadUDA(string file, string volName)
+ {
+ //TODO: clear out existing data
+ LightSet* lights = _scene->getLights();
+ PreprocessContext context(_manta_interface, 0, 1, lights);
+ uda.readUDA(file, volName);
+ for (std::vector<UDAReader::Timestep>::iterator itr = uda.timesteps.begin(); itr != uda.timesteps.end(); itr++)
+ {
+ float* sdata = itr->sphereData;
- for (int i = 0; i < 100; i++)
- {
+ for (int i = 0; i < 100; i++)
+ {
cout << "sphere data: " << sdata[i] << endl;
- }
- Group* group = new Group();
- RGBAColorMap* cmap = new RGBAColorMap(1);
- int ridx = _ridx;
- if (ridx >= itr->numSphereVars)
- ridx = -1;
- int cidx = _cidx;
- if (cidx >= itr->numSphereVars)
- cidx = 0;
- CDGridSpheres* grid = new CDGridSpheres(itr- >sphereData, itr->numSpheres, itr->numSphereVars, 6, 2,_radius, ridx, cmap , cidx);
-#if USE_GRIDSPHERES
- group->add(grid);
- _sphereGrids.push_back(grid);
-#endif
- if (itr->numSphereVars > int(_sphereMins.size()))
- {
- for(int j = int(_sphereMins.size()); j < itr- >numSphereVars; j++)
- {
- _sphereMins.push_back(FLT_MAX);
- _sphereMaxs.push_back(-FLT_MAX);
- }
- }
- for(int j = 0; j < int(_sphereMins.size()); j++)
- {
- float min,max;
- grid->getMinMax(j, min, max);
- if (_sphereMins[j] > min)
- _sphereMins[j] = min;
- if (_sphereMaxs[j] < max)
- _sphereMaxs[j] = max;
- }
- _sphereAnimation->push_back(group);
- numFrames1++;
-
- Group* group2 = new Group();
- Volume<float>* mat = new Volume<float>(itr->volume, _volCMap, BBox(_minBound, _maxBound), 0.00125, 3, _forceDataMin, _forceDataMax);
- Primitive* vol = new Cube(mat, _minBound - Vector(0.001, 0.001, 0.001), _maxBound + Vector(0.001, 0.001, 0.001));
- group2->add(vol);
- _volAnimation->push_back(group2);
- _vols.push_back(mat);
- numFrames2++;
- }
- updateFrames();
- if (_clipFrames && _endFrame < int(_vols.size()))
- _volAnimation->clipFrames(_startFrame, _endFrame);
- if (_clipFrames && _endFrame < int(_sphereGrids.size()))
- _sphereAnimation->clipFrames(_startFrame, _endFrame);
- }
+ }
+ Group* group = new Group();
+ RGBAColorMap* cmap = new RGBAColorMap(1);
+ int ridx = _ridx;
+ if (ridx >= itr->numSphereVars)
+ ridx = -1;
+ int cidx = _cidx;
+ if (cidx >= itr->numSphereVars)
+ cidx = 0;
+ CDGridSpheres* grid = new CDGridSpheres(itr->sphereData, itr- >numSpheres, itr->numSphereVars, 6, 2,_radius, ridx, cmap , cidx);
+#if USE_GRIDSPHERES
+ group->add(grid);
+ _sphereGrids.push_back(grid);
+#endif
+ if (itr->numSphereVars > int(_sphereMins.size()))
+ {
+ for(int j = int(_sphereMins.size()); j < itr->numSphereVars; j++)
+ {
+ _sphereMins.push_back(FLT_MAX);
+ _sphereMaxs.push_back(-FLT_MAX);
+ }
+ }
+ for(int j = 0; j < int(_sphereMins.size()); j++)
+ {
+ float min,max;
+ grid->getMinMax(j, min, max);
+ if (_sphereMins[j] > min)
+ _sphereMins[j] = min;
+ if (_sphereMaxs[j] < max)
+ _sphereMaxs[j] = max;
+ }
+ _sphereAnimation->push_back(group);
+ numFrames1++;
+
+ Group* group2 = new Group();
+ Volume<float>* mat = new Volume<float>(itr->volume, _volCMap, BBox(_minBound, _maxBound), 0.00125, 3, _forceDataMin, _forceDataMax);
+ Cube* vol = new Cube(mat, _minBound - Vector(0.001, 0.001, 0.001), _maxBound + Vector(0.001, 0.001, 0.001));
+ group2->add(vol);
+ _volAnimation->push_back(group2);
+ _vols.push_back(mat);
+ _volPrims.push_back(vol);
+ numFrames2++;
+ }
+ updateFrames();
+ if (_clipFrames && _endFrame < int(_vols.size()))
+ _volAnimation->clipFrames(_startFrame, _endFrame);
+ if (_clipFrames && _endFrame < int(_sphereGrids.size()))
+ _sphereAnimation->clipFrames(_startFrame, _endFrame);
+ }
- //! calls destructors on all loaded data, then reloads sphere and volume files
- /*!
- */
- void reloadData()
- {
- //_scene = new Scene();
- //TODO: i don't delete the old scene object... I don't want to to do a recursive delete
- //_manta_interface->setScene(_scene);
- //initScene();
- //_volsOld = _vols;
- //_sphereGridsOld = _sphereGrids;
- //_spherePNrrdsOld = _spherePNrrds;
- //_vols.clear();
- //_spherePNrrds.clear();
- //_sphereGrids.clear();
- loadSphereNrrds();
- loadVolNrrds();
- //_manta_interface- >addOneShotCallback(MantaInterface::Relative, 2, Callback::create(this, &CDTest::reloadDataHelper));
- }
+ //! calls destructors on all loaded data, then reloads sphere and volume files
+ /*!
+ */
+ void reloadData()
+ {
+ //_scene = new Scene();
+ //TODO: i don't delete the old scene object... I don't want to to do a recursive delete
+ //_manta_interface->setScene(_scene);
+ //initScene();
+ //_volsOld = _vols;
+ //_sphereGridsOld = _sphereGrids;
+ //_spherePNrrdsOld = _spherePNrrds;
+ //_vols.clear();
+ //_spherePNrrds.clear();
+ //_sphereGrids.clear();
+ loadSphereNrrds();
+ loadVolNrrds();
+ //_manta_interface- >addOneShotCallback(MantaInterface::Relative, 2, Callback::create(this, &CDTest::reloadDataHelper));
+ }
- //! update the frame cieling
- /*!
- */
- void updateFrames()
- {
- numFrames = std::max(numFrames1, numFrames2);
- }
-
- //! pause animation
- /*!
- */
- void pauseAnimation() { _sphereAnimation->pauseAnimation(); _volAnimation->pauseAnimation(); }
-
- //! resume animation
- /*!
- */
- void resumeAnimation() { _sphereAnimation- >resumeAnimation(); _volAnimation->resumeAnimation();}
-
- //! go to a time in animation
- /*!
- \param time to go to
- */
- void gotoTime(float time) { _sphereAnimation- >setTime(time); _volAnimation->setTime(time); }
-
- // 0-based
- void gotoFrame(int frame) {
- if (frame < 0 || frame >= numFrames)
- {
- cerr << "ERROR: frame: " << frame << " out of bounds \n";
- return;
- }
- float step;
- if (numFrames == 0)
- step = 0;
- else
- step = duration/float(numFrames);
- _sphereAnimation->setTime( step*float(frame) + 0.0001f);
- _volAnimation->setTime(step*float(frame) + 0.0001f);
- }
-
- void lockFrames(bool st) { _sphereAnimation- >lockFrames(st); _volAnimation->lockFrames(st); }
- void loopAnimations(bool st) {_sphereAnimation- >loopAnimation(st); _volAnimation->loopAnimation(st); }
- void clipFrames(int start, int end) { _startFrame = start; _endFrame = end; _clipFrames = true;
- if (end < numFrames1) _sphereAnimation- >clipFrames(start,end); if (end < numFrames2) _volAnimation- >clipFrames(start,end); }
- void repeatLastFrame(float time) { _sphereAnimation- >repeatLastFrameForSeconds(time); _volAnimation- >repeatLastFrameForSeconds(time); }
-
- //! skip ahead one frame
- /*!
- */
- void forwardAnimation()
- {
- float step;
- if (numFrames == 0)
- step = 0;
- else
- step = duration/float(numFrames);
- float st = _sphereAnimation->getTime();
- st = std::max(st, 0.0f);
- float vt = _volAnimation->getTime();
- vt = std::max(vt, 0.0f);
-
- _sphereAnimation->setTime( _sphereAnimation->getTime() + step);
- _volAnimation->setTime(_volAnimation->getTime()+step);
- }
-
- //! skip back one frame
- /*!
- */
- void backAnimation()
- {
- float step;
- if (numFrames == 0)
- step = 0;
- else
- step = duration/float(numFrames);
- _sphereAnimation->setTime( _sphereAnimation->getTime() - step);
- _volAnimation->setTime(_volAnimation->getTime()-step);
- }
-
- //! get the duration of the animation in seconds
- /*!
- \return duration in seconds of animation
- */
- float getDuration()
- {
- return duration;
- }
-
- //! set the duration of animation in seconds
- /*!
- \param number of seconds animation takes
- */
- void setDuration(float time)
- {
- duration = time;
- _sphereAnimation->setDuration(time);
- _volAnimation->setDuration(time);
- }
-
- //! computes histogram of spherefiles
- /*!
- \param index of data to compute histogram of
- \param number of buckets to compute, ie 100 bars
- \param an allocated list of ints to store the values, must be size numBuckets
- \param will return min
- \param will return max
- */
- void getHistogram(int index, int numBuckets, int* histValues, float* min, float* max)
- {
- for(int i = 0; i < numBuckets; i++)
- histValues[i] = 0;
- for(size_t i = 0; i < _spherePNrrds.size(); i++)
- {
- ParticleNRRD* pnrrd = _spherePNrrds[i];
- float dataMin = _sphereMins[index];
- float dataMax = _sphereMaxs[index];
- cout << "histo dataMin/Max: " << dataMin << " " << dataMax << endl;
- float scale;
- if (dataMin != dataMax)
- scale = (numBuckets-1)/(dataMax - dataMin);
- else
- continue;
- for(int j = 0; j < int(pnrrd->getNParticles()); j++)
- {
- float val = *(pnrrd->getParticleData() + j*pnrrd->getNVars() + index);
- int bucket = int((val-dataMin)*scale);
- static int count = 0; if (val > 0.06 && count++ < 20) cout << "val: " << val << " " << bucket << endl;
- histValues[bucket]++;
- }
- }
- if (int(_sphereMins.size()) > index)
- {
- *min = _sphereMins[index];
- *max = _sphereMaxs[index];
- }
- else
- {
- *min = -FLT_MAX;
- *max = FLT_MAX;
- }
- }
-
- //! compute histogram for volume data
- /*!
- \param number of buckets to compute, ie 100 bars
- \param an allocated list of ints to store the values, must be size numBuckets
- \param will return min
- \param will return max
- */
- void getVolHistogram(int numBuckets, int* histValues, float* min, float* max)
- {
- cout << "computing volume histogram for " << _vols.size() << " volumes\n";
- *min = FLT_MAX;
- *max = -FLT_MAX;
- for(int i = 0; i < numBuckets; i++)
- histValues[i] = 0;
- for (int i = 0; i < int(_vols.size()); i++)
- {
- if (_vols[i] == NULL)
- continue;
- int* histValues2 = new int[numBuckets];
- _vols[i]->computeHistogram(numBuckets, histValues2);
- for(int j = 0; j < numBuckets; j++)
- histValues[j] += histValues2[j];
- double nmin, nmax;
- _vols[i]->getMinMax(&nmin, &nmax);
- *min= std::min(float(nmin), *min);
- *max = std::max(float(nmax), *max);
- cout << "compared min/max: " << nmin << " " << nmax << endl;
- }
- cout << "histogram computed: min/max: " << *min << " " << *max << endl;
- }
-
- //! get the colormap used for the volume
- /*!
- \return colormap used for volume
- */
- RGBAColorMap* getVolCMap() { return _volCMap; }
-
- //! set the colormap for volume
- /*!
- \param colormap
- */
- void setVolCMap(RGBAColorMap* map) { _volCMap = map;
- for(vector<Volume<float>*>::iterator i = _vols.begin(); i != _vols.end(); i++)
- {
- (*i)->setColorMap(map);
-
- }
- }
-
- //! set the colormap for spheres
- /*!
- \param colormap
- */
- void setSphereCMap(RGBAColorMap* map) {
- #if USE_GRIDSPHERES
- for(int i =0; i < int(_sphereGrids.size()); i++)
- _sphereGrids[i]->setCMap(map);
- #else
- _setCMapHelper = map;
- _manta_interface->addOneShotCallback(MantaInterface::Relative, 1, Callback::create(this, &CDTest::setSphereCMapHelper));
- #endif
- }
+ //! update the frame cieling
+ /*!
+ */
+ void updateFrames()
+ {
+ numFrames = std::max(numFrames1, numFrames2);
+ }
+
+ //! pause animation
+ /*!
+ */
+ void pauseAnimation() { _sphereAnimation->pauseAnimation(); _volAnimation->pauseAnimation(); }
+
+ //! resume animation
+ /*!
+ */
+ void resumeAnimation() { _sphereAnimation->resumeAnimation(); _volAnimation->resumeAnimation();}
+
+ //! go to a time in animation
+ /*!
+ \param time to go to
+ */
+ void gotoTime(float time) { _sphereAnimation->setTime(time); _volAnimation->setTime(time); }
+
+ // 0-based
+ void gotoFrame(int frame) {
+ if (frame < 0 || frame >= numFrames)
+ {
+ cerr << "ERROR: frame: " << frame << " out of bounds\n";
+ return;
+ }
+ float step;
+ if (numFrames == 0)
+ step = 0;
+ else
+ step = duration/float(numFrames);
+ _sphereAnimation->setTime( step*float(frame) + 0.0001f);
+ _volAnimation->setTime(step*float(frame) + 0.0001f);
+ }
+
+ void lockFrames(bool st) { _sphereAnimation->lockFrames(st); _volAnimation->lockFrames(st); }
+ void loopAnimations(bool st) {_sphereAnimation- >loopAnimation(st); _volAnimation->loopAnimation(st); }
+ void clipFrames(int start, int end) { _startFrame = start; _endFrame = end; _clipFrames = true;
+ if (end < numFrames1) _sphereAnimation->clipFrames(start,end); if (end < numFrames2) _volAnimation->clipFrames(start,end); }
+ void repeatLastFrame(float time) { _sphereAnimation- >repeatLastFrameForSeconds(time); _volAnimation- >repeatLastFrameForSeconds(time); }
+
+ //! skip ahead one frame
+ /*!
+ */
+ void forwardAnimation()
+ {
+ float step;
+ if (numFrames == 0)
+ step = 0;
+ else
+ step = duration/float(numFrames);
+ float st = _sphereAnimation->getTime();
+ st = std::max(st, 0.0f);
+ float vt = _volAnimation->getTime();
+ vt = std::max(vt, 0.0f);
+
+ _sphereAnimation->setTime( _sphereAnimation->getTime() + step);
+ _volAnimation->setTime(_volAnimation->getTime()+step);
+ }
+
+ //! skip back one frame
+ /*!
+ */
+ void backAnimation()
+ {
+ float step;
+ if (numFrames == 0)
+ step = 0;
+ else
+ step = duration/float(numFrames);
+ _sphereAnimation->setTime( _sphereAnimation->getTime() - step);
+ _volAnimation->setTime(_volAnimation->getTime()-step);
+ }
+
+ //! get the duration of the animation in seconds
+ /*!
+ \return duration in seconds of animation
+ */
+ float getDuration()
+ {
+ return duration;
+ }
+
+ //! set the duration of animation in seconds
+ /*!
+ \param number of seconds animation takes
+ */
+ void setDuration(float time)
+ {
+ duration = time;
+ _sphereAnimation->setDuration(time);
+ _volAnimation->setDuration(time);
+ }
+
+ //! computes histogram of spherefiles
+ /*!
+ \param index of data to compute histogram of
+ \param number of buckets to compute, ie 100 bars
+ \param an allocated list of ints to store the values, must be size numBuckets
+ \param will return min
+ \param will return max
+ */
+ void getHistogram(int index, int numBuckets, int* histValues, float* min, float* max)
+ {
+ for(int i = 0; i < numBuckets; i++)
+ histValues[i] = 0;
+ for(size_t i = 0; i < _spherePNrrds.size(); i++)
+ {
+ ParticleNRRD* pnrrd = _spherePNrrds[i];
+ float dataMin = _sphereMins[index];
+ float dataMax = _sphereMaxs[index];
+ cout << "histo dataMin/Max: " << dataMin << " " << dataMax << endl;
+ float scale;
+ if (dataMin != dataMax)
+ scale = (numBuckets-1)/(dataMax - dataMin);
+ else
+ continue;
+ for(int j = 0; j < int(pnrrd->getNParticles()); j++)
+ {
+ float val = *(pnrrd->getParticleData() + j*pnrrd->getNVars() + index);
+ int bucket = int((val-dataMin)*scale);
+ static int count = 0; if (val > 0.06 && count++ < 20) cout << "val: " << val << " " << bucket << endl;
+ histValues[bucket]++;
+ }
+ }
+ if (int(_sphereMins.size()) > index)
+ {
+ *min = _sphereMins[index];
+ *max = _sphereMaxs[index];
+ }
+ else
+ {
+ *min = -FLT_MAX;
+ *max = FLT_MAX;
+ }
+ }
+
+ //! compute histogram for volume data
+ /*!
+ \param number of buckets to compute, ie 100 bars
+ \param an allocated list of ints to store the values, must be size numBuckets
+ \param will return min
+ \param will return max
+ */
+ void getVolHistogram(int numBuckets, int* histValues, float* min, float* max)
+ {
+ cout << "computing volume histogram for " << _vols.size() << " volumes\n";
+ *min = FLT_MAX;
+ *max = -FLT_MAX;
+ for(int i = 0; i < numBuckets; i++)
+ histValues[i] = 0;
+ for (int i = 0; i < int(_vols.size()); i++)
+ {
+ if (_vols[i] == NULL)
+ continue;
+ int* histValues2 = new int[numBuckets];
+ _vols[i]->computeHistogram(numBuckets, histValues2);
+ for(int j = 0; j < numBuckets; j++)
+ histValues[j] += histValues2[j];
+ double nmin, nmax;
+ _vols[i]->getMinMax(&nmin, &nmax);
+ *min= std::min(float(nmin), *min);
+ *max = std::max(float(nmax), *max);
+ cout << "compared min/max: " << nmin << " " << nmax << endl;
+ }
+ cout << "histogram computed: min/max: " << *min << " " << *max << endl;
+ }
+
+ //! get the colormap used for the volume
+ /*!
+ \return colormap used for volume
+ */
+ RGBAColorMap* getVolCMap() { return _volCMap; }
+
+ //! set the colormap for volume
+ /*!
+ \param colormap
+ */
+ void setVolCMap(RGBAColorMap* map) { _volCMap = map;
+ for(vector<Volume<float>*>::iterator i = _vols.begin(); i != _vols.end(); i++)
+ {
+ (*i)->setColorMap(map);
+
+ }
+ }
+
+ //! set the colormap for spheres
+ /*!
+ \param colormap
+ */
+ void setSphereCMap(RGBAColorMap* map) {
+#if USE_GRIDSPHERES
+ for(int i =0; i < int(_sphereGrids.size()); i++)
+ _sphereGrids[i]->setCMap(map);
+#else
+ _setCMapHelper = map;
+ _manta_interface->addOneShotCallback(MantaInterface::Relative, 1, Callback::create(this, &CDTest::setSphereCMapHelper));
+#endif
+ }
- void updateSphereCMap() {
+ void updateSphereCMap() {
#if !USE_GRIDSPHERES
- _manta_interface->addOneShotCallback(MantaInterface::Relative, 1, Callback::create(this, &CDTest::setSphereCMapHelper));
+ _manta_interface->addOneShotCallback(MantaInterface::Relative, 1, Callback::create(this, &CDTest::setSphereCMapHelper));
#endif
- }
+ }
- //! called by setSphereCMap
- /*!
- */
- void setSphereCMapHelper(int, int)
- {
- std::vector<Color> colors;
- RGBAColorMap* map = _setCMapHelper;
- if (!map)
- return;
- for(int i = 0; i < map->GetNumSlices(); i++) {
- colors.push_back(map->GetSlice(i).color.color);
- }
- cout << "setting sphere colors\n";
- _sphereCMap->setColors(colors);
- }
+ //! called by setSphereCMap
+ /*!
+ */
+ void setSphereCMapHelper(int, int)
+ {
+ std::vector<Color> colors;
+ RGBAColorMap* map = _setCMapHelper;
+ if (!map)
+ return;
+ for(int i = 0; i < map->GetNumSlices(); i++) {
+ colors.push_back(map->GetSlice(i).color.color);
+ }
+ cout << "setting sphere colors\n";
+ _sphereCMap->setColors(colors);
+ }
- //! set minimum and maximum clipping region for a specific index into spheres
- /*!
- \param index into data
- \param min
- \param max
- */
- void setClipMinMax(int index, float min, float max)
- {
- cout << "setclip called index: " << index << " sphereminssize: " << _sphereMins.size() << "\n";
- if (index >= int(_sphereMins.size()))
- return;
- cout << "2\n";
-#if USE_GRIDSPHERES
- cout << "setting clips\n";
- for(int i = 0; i < int(_sphereGrids.size()); i++)
- if (_sphereGrids[i]) _sphereGrids[i]- >setClipMinMax(index, min, max);
+ //! set minimum and maximum clipping region for a specific index into spheres
+ /*!
+ \param index into data
+ \param min
+ \param max
+ */
+ void setClipMinMax(int index, float min, float max)
+ {
+ cout << "setclip called index: " << index << " sphereminssize: " << _sphereMins.size() << "\n";
+ if (index >= int(_sphereMins.size()))
+ return;
+ cout << "2\n";
+#if USE_GRIDSPHERES
+ cout << "setting clips\n";
+ for(int i = 0; i < int(_sphereGrids.size()); i++)
+ if (_sphereGrids[i]) _sphereGrids[i]->setClipMinMax(index, min, max);
#else
- _sphereDMins[index] = min;
- _sphereDMaxs[index] = max;
- for(size_t i = 0; i < _sphereGroups.size(); i++) {
- for(size_t s = 0; s < _sphereGroups[i]->size(); s++) {
- CSAFEPrim* prim = dynamic_cast<CSAFEPrim*>(_sphereGroups[i]- >get(s));
- if (prim)
- prim->updateOcclusion();
- }
- }
+ _sphereDMins[index] = min;
+ _sphereDMaxs[index] = max;
+ for(size_t i = 0; i < _sphereGroups.size(); i++) {
+ for(size_t s = 0; s < _sphereGroups[i]->size(); s++) {
+ CSAFEPrim* prim = dynamic_cast<CSAFEPrim*>(_sphereGroups[i]- >get(s));
+ if (prim)
+ prim->updateOcclusion();
+ }
+ }
#endif
- }
+ }
- //! set the minimum and maximum data values used for normalizing color data
- /*!
- \param index into data
- \param min
- \param max
- */
- void setSphereColorMinMax(int index, float min, float max) //set the min max for normalizing color data
- {
+ //! set the minimum and maximum data values used for normalizing color data
+ /*!
+ \param index into data
+ \param min
+ \param max
+ */
+ void setSphereColorMinMax(int index, float min, float max) // set the min max for normalizing color data
+ {
#if USE_GRIDSPHERES
- for(int i =0; i < int(_sphereGrids.size()); i++)
- _sphereGrids[i]->setCMinMax(index, min, max);
+ for(int i =0; i < int(_sphereGrids.size()); i++)
+ _sphereGrids[i]->setCMinMax(index, min, max);
#else
- if (!_sphereCMap)
- return;
- cout << "setting color min/max to: " << min << " " << max << endl;
- _sphereCMap->setRange(min, max);
-#endif
- }
-
- //! get the min and max being used for normalizing color values
- /*!
- \param index into data
- \param returns min
- \param returns max
- */
- void getSphereColorMinMax(int index, float& min, float& max)
- {
+ if (!_sphereCMap)
+ return;
+ cout << "setting color min/max to: " << min << " " << max << endl;
+ _sphereCMap->setRange(min, max);
+#endif
+ }
+
+ //! get the min and max being used for normalizing color values
+ /*!
+ \param index into data
+ \param returns min
+ \param returns max
+ */
+ void getSphereColorMinMax(int index, float& min, float& max)
+ {
#if USE_GRIDSPHERES
- for(int i =0;i<int(_sphereGrids.size());i++)
- _sphereGrids[i]->getCMinMax(index, min, max);
+ for(int i =0;i<int(_sphereGrids.size());i++)
+ _sphereGrids[i]->getCMinMax(index, min, max);
#else
- min = _sphereCMap->getMin();
- max = _sphereCMap->getMax();
+ min = _sphereCMap->getMin();
+ max = _sphereCMap->getMax();
#endif
- }
+ }
- //! get the min and max of spheres
- /*!
- \param index into data
- \param returns min
- \param returns max
- */
- void getSphereDataMinMax(int index, float& min, float& max)
- {
+ //! get the min and max of spheres
+ /*!
+ \param index into data
+ \param returns min
+ \param returns max
+ */
+ void getSphereDataMinMax(int index, float& min, float& max)
+ {
#if USE_GRIDSPHERES
- for(int i =0;i<int(_sphereGrids.size());i++)
- _sphereGrids[i]->getCMinMax(index, min, max);
+ for(int i =0;i<int(_sphereGrids.size());i++)
+ _sphereGrids[i]->getCMinMax(index, min, max);
#else
- if(index >= int(_sphereMins.size()))
- {
- min = -FLT_MAX;
- max = FLT_MIN;
- return;
- }
- min = _sphereMins[index];
- max = _sphereMaxs[index];
-#endif
- }
-
- //! set minimum and maximum data values for volume data, should be called before loading
- /*!
- \param min
- \param max
- */
- void setVolColorMinMax(float min, float max)
- {
- _forceDataMin = min;
- _forceDataMax = max;
- }
-
- //! get the min and max data values used for normalizing color values
- /*!
- \param returns min
- \param returns max
- */
- void getVolColorMinMax(float& min, float& max)
- {
- min = _forceDataMin;
- max = _forceDataMax;
- }
-
- //! get the min and max data values of the volume
- /*!
- \param returns min
- \param returns max
- */
- void getVolDataMinMax(float& min, float& max)
- {
- min = FLT_MAX;
- max = -FLT_MAX;
- for(int i =0;i<int(_vols.size());i++)
- {
- if (_vols[i] == NULL)
- continue;
- double min1, max1;
- _vols[i]->getMinMax(&min1, &max1);
- min = std::min(min, float(min1));
- max = std::max(max, float(max1));
- }
- }
-
- //! sets radius index used for spheredata
- /*!
- \param radius index
- */
- void setRidx(int ridx) { _ridx = ridx; }
-
- //! get radius index
- /*!
- \return radius index
- */
- int getRidx() { return _ridx; }
-
- //! set default radius of spheres
- /*!
- \param radius
- */
- void setRadius(float radius) { _radius = radius; }
-
- //! get the default radius of spheres
- /*!
- \return default radius
- */
- float getRadius() { return _radius; }
-
- //! set color index, what index colormap uses
- /*!
- \param color index to use
- */
- void setCidx(int cidx) {
-#if USE_GRIDSPHERES
- cout << "2\n";
- for(int i =0; i < int(_sphereGrids.size()); i++)
- _sphereGrids[i]->setCidx(cidx);
+ if(index >= int(_sphereMins.size()))
+ {
+ min = -FLT_MAX;
+ max = FLT_MIN;
+ return;
+ }
+ min = _sphereMins[index];
+ max = _sphereMaxs[index];
+#endif
+ }
+
+ //! set minimum and maximum data values for volume data, should be called before loading
+ /*!
+ \param min
+ \param max
+ */
+ void setVolColorMinMax(float min, float max)
+ {
+ _forceDataMin = min;
+ _forceDataMax = max;
+ }
+
+ //! get the min and max data values used for normalizing color values
+ /*!
+ \param returns min
+ \param returns max
+ */
+ void getVolColorMinMax(float& min, float& max)
+ {
+ min = _forceDataMin;
+ max = _forceDataMax;
+ }
+
+ //! get the min and max data values of the volume
+ /*!
+ \param returns min
+ \param returns max
+ */
+ void getVolDataMinMax(float& min, float& max)
+ {
+ min = FLT_MAX;
+ max = -FLT_MAX;
+ for(int i =0;i<int(_vols.size());i++)
+ {
+ if (_vols[i] == NULL)
+ continue;
+ double min1, max1;
+ _vols[i]->getMinMax(&min1, &max1);
+ min = std::min(min, float(min1));
+ max = std::max(max, float(max1));
+ }
+ }
+
+ //! sets radius index used for spheredata
+ /*!
+ \param radius index
+ */
+ void setRidx(int ridx) { _ridx = ridx; }
+
+ //! get radius index
+ /*!
+ \return radius index
+ */
+ int getRidx() { return _ridx; }
+
+ //! set default radius of spheres
+ /*!
+ \param radius
+ */
+ void setRadius(float radius) { _radius = radius; }
+
+ //! get the default radius of spheres
+ /*!
+ \return default radius
+ */
+ float getRadius() { return _radius; }
+
+ //! set color index, what index colormap uses
+ /*!
+ \param color index to use
+ */
+ void setCidx(int cidx) {
+#if USE_GRIDSPHERES
+ cout << "2\n";
+ for(int i =0; i < int(_sphereGrids.size()); i++)
+ _sphereGrids[i]->setCidx(cidx);
#else
- CSAFEPrim::setCIndex(cidx);
+ CSAFEPrim::setCIndex(cidx);
#endif
- _cidx = cidx;
- }
+ _cidx = cidx;
+ }
- //! get color index
- /*!
- \return color index
- */
- int getCidx() { return _cidx; }
+ //! get color index
+ /*!
+ \return color index
+ */
+ int getCidx() { return _cidx; }
- //! set to use ambient occlusion on spheres
- void useAO(bool st)
- {
+ //! set to use ambient occlusion on spheres
+ void useAO(bool st)
+ {
#if USE_GRIDSPHERES
- for(int i = 0; i < int(_sphereGrids.size()); i++)
- _sphereGrids[i]->useAmbientOcclusion(st);
-#endif
- if (st == _useAO)
- return;
- _useAO = st;
- }
+ for(int i = 0; i < int(_sphereGrids.size()); i++)
+ _sphereGrids[i]->useAmbientOcclusion(st);
+#endif
+ if (st == _useAO)
+ return;
+ _useAO = st;
+ }
- //! set the cutoff distance and number of generated rays
- /*!
- \param cutoff distance, distance to check if rays hit objects
- \param number of generated rays
- */
- void setAOVars(float cutoff, int numDirs)
- {
- #if USE_GRIDSPHERES
- for(int i = 0; i < int(_sphereGrids.size()); i++)
- _sphereGrids[i]- >setAmbientOcclusionVariables(cutoff, numDirs);
- #endif
- }
+ //! set the cutoff distance and number of generated rays
+ /*!
+ \param cutoff distance, distance to check if rays hit objects
+ \param number of generated rays
+ */
+ void setAOVars(float cutoff, int numDirs)
+ {
+#if USE_GRIDSPHERES
+ for(int i = 0; i < int(_sphereGrids.size()); i++)
+ _sphereGrids[i]->setAmbientOcclusionVariables(cutoff, numDirs);
+#endif
+ }
-protected:
- //! called by reloadData
- /*!
- */
- void reloadDataHelper(int, int)
- {
- for (vector<Volume<float>*>::iterator itr = _volsOld.begin(); itr != _volsOld.end(); itr++)
- delete *itr;
- _volsOld.clear();
-#if USE_GRIDSPHERES
- for (vector<CDGridSpheres*>::iterator itr = _sphereGridsOld.begin(); itr != _sphereGridsOld.end(); itr++)
- delete *itr;
-#endif
- _sphereGridsOld.clear();
- for (vector<ParticleNRRD*>::iterator itr = _spherePNrrdsOld.begin(); itr != _spherePNrrdsOld.end(); itr++)
- delete *itr;
- _spherePNrrdsOld.clear();
- }
-
- MantaInterface* _manta_interface;
- RGBAColorMap* _volCMap;
- LinearColormap<float>* _sphereCMap;
- Material* _sphereMatl;
- Vector _minBound;
- Vector _maxBound;
- float _forceDataMin;
- float _forceDataMax;
- int _cidx;
- int _ridx;
- float _radius;
- float duration; //number of seconds for animation
- int numFrames; //number of keyframes
- int numFrames1, numFrames2;
- ReadContext* _readContext;
- vector<string> _nrrdFilenames;
- vector<string> _nrrdFilenames2;
- vector<Nrrd*> _nrrds;
- vector<ParticleNRRD*> _spherePNrrds;
- vector<GridType*> _sphereGrids;
- vector<Volume<float>*> _vols;
- vector<ParticleNRRD*> _spherePNrrdsOld;
- vector<GridType*> _sphereGridsOld;
- vector<Volume<float>*> _volsOld;
- vector<Group*> _sphereGroups;
- vector<float> _sphereMins;
- vector<float> _sphereMaxs;
- Group* _world;
- Scene* _scene;
- KeyFrameAnimation* _sphereAnimation;
- KeyFrameAnimation* _volAnimation;
- int _startFrame, _endFrame, _clipFrames;
- bool _useAO;
- RGBAColorMap* _setCMapHelper;
- UDAReader uda;
- float* _sphereDMins, *_sphereDMaxs;
- };
+ protected:
+ //! called by reloadData
+ /*!
+ */
+ void reloadDataHelper(int, int)
+ {
+ for (vector<Volume<float>*>::iterator itr = _volsOld.begin(); itr != _volsOld.end(); itr++)
+ delete *itr;
+ _volsOld.clear();
+#if USE_GRIDSPHERES
+ for (vector<CDGridSpheres*>::iterator itr = _sphereGridsOld.begin(); itr != _sphereGridsOld.end(); itr++)
+ delete *itr;
+#endif
+ _sphereGridsOld.clear();
+ for (vector<ParticleNRRD*>::iterator itr = _spherePNrrdsOld.begin(); itr != _spherePNrrdsOld.end(); itr++)
+ delete *itr;
+ _spherePNrrdsOld.clear();
+ }
+ void setVolumePositionSizeHelper(int, int)
+ {
+ BBox bounds(_volPosition - _volSize/2.0, _volPosition + _volSize/2.0);
+ for(vector<Volume<float>*>::iterator itr = _vols.begin(); itr != _vols.end(); itr++) {
+ (*itr)->setBounds(bounds);
+ }
+ for(vector<Cube*>::iterator itr = _volPrims.begin(); itr != _volPrims.end(); itr++) {
+ (*itr)->setMinMax(bounds.getMin(), bounds.getMax());
+ }
+ }
+
+ MantaInterface* _manta_interface;
+ RGBAColorMap* _volCMap;
+ LinearColormap<float>* _sphereCMap;
+ Material* _sphereMatl;
+ Vector _minBound;
+ Vector _maxBound;
+ float _forceDataMin;
+ float _forceDataMax;
+ int _cidx;
+ int _ridx;
+ float _radius;
+ float duration; //number of seconds for animation
+ int numFrames; //number of keyframes
+ int numFrames1, numFrames2;
+ ReadContext* _readContext;
+ vector<string> _nrrdFilenames;
+ vector<string> _nrrdFilenames2;
+ vector<Nrrd*> _nrrds;
+ vector<ParticleNRRD*> _spherePNrrds;
+ vector<GridType*> _sphereGrids;
+ vector<Volume<float>*> _vols;
+ vector<Cube*> _volPrims;
+ vector<ParticleNRRD*> _spherePNrrdsOld;
+ vector<GridType*> _sphereGridsOld;
+ vector<Volume<float>*> _volsOld;
+ vector<Group*> _sphereGroups;
+ vector<float> _sphereMins;
+ vector<float> _sphereMaxs;
+ Group* _world;
+ Scene* _scene;
+ KeyFrameAnimation* _sphereAnimation;
+ KeyFrameAnimation* _volAnimation;
+ int _startFrame, _endFrame, _clipFrames;
+ bool _useAO;
+ RGBAColorMap* _setCMapHelper;
+ UDAReader uda;
+ float* _sphereDMins, *_sphereDMaxs;
+ Vector _volPosition, _volSize;
+};
#endif
Archive powered by MHonArc 2.6.16.