Refactored osg::TransferFunction1D to use an std::map internally which is kept in sync with the actual osg::Image that is passed to the GPU.

Added .osg support for osg::TransferFunction1D.

Updated wrappers
This commit is contained in:
Robert Osfield
2009-02-02 14:43:27 +00:00
parent 6130f292a7
commit 2d55740b3e
12 changed files with 381 additions and 354 deletions

View File

@@ -831,15 +831,17 @@ int main(int argc, char** argv)
osg::ref_ptr<osg::TransferFunction1D> tf = new osg::TransferFunction1D;
tf->setInputRange(minValue, maxValue);
unsigned int numCells = 6;
float delta = (maxValue-minValue)/float(numCells-1);
float v = minValue;
tf->allocate(6);
tf->setValue(0, osg::Vec4(1.0,1.0,1.0,1.0));
tf->setValue(1, osg::Vec4(1.0,0.0,1.0,1.0));
tf->setValue(2, osg::Vec4(1.0,0.0,0.0,1.0));
tf->setValue(3, osg::Vec4(1.0,1.0,0.0,1.0));
tf->setValue(4, osg::Vec4(0.0,1.0,1.0,1.0));
tf->setValue(5, osg::Vec4(0.0,1.0,0.0,1.0));
tf->setColor(v, osg::Vec4(1.0,1.0,1.0,1.0)); v += delta;
tf->setColor(v, osg::Vec4(1.0,0.0,1.0,1.0)); v += delta;
tf->setColor(v, osg::Vec4(1.0,0.0,0.0,1.0)); v += delta;
tf->setColor(v, osg::Vec4(1.0,1.0,0.0,1.0)); v += delta;
tf->setColor(v, osg::Vec4(0.0,1.0,1.0,1.0)); v += delta;
tf->setColor(v, osg::Vec4(0.0,1.0,0.0,1.0));
osg::notify(osg::NOTICE)<<"--tf "<<minValue<<" "<<maxValue<<std::endl;

View File

@@ -716,7 +716,7 @@ osg::TransferFunction1D* readTransferFunctionFile(const std::string& filename)
std::cout<<"Reading transfer function "<<filename<<std::endl;
osg::TransferFunction1D::ValueMap valueMap;
osg::TransferFunction1D::ColorMap colorMap;
osgDB::ifstream fin(foundFile.c_str());
while(fin)
{
@@ -725,18 +725,18 @@ osg::TransferFunction1D* readTransferFunctionFile(const std::string& filename)
if (fin)
{
std::cout<<"value = "<<value<<" ("<<red<<", "<<green<<", "<<blue<<", "<<alpha<<")"<<std::endl;
valueMap[value] = osg::Vec4(red,green,blue,alpha);
colorMap[value] = osg::Vec4(red,green,blue,alpha);
}
}
if (valueMap.empty())
if (colorMap.empty())
{
std::cout<<"Error: No values read from transfer function file: "<<filename<<std::endl;
return 0;
}
osg::TransferFunction1D* tf = new osg::TransferFunction1D;
tf->assign(valueMap, true);
tf->assign(colorMap);
return tf;
}
@@ -851,6 +851,23 @@ int main( int argc, char **argv )
{
transferFunction = readTransferFunctionFile(tranferFunctionFile);
}
while(arguments.read("--test"))
{
transferFunction = new osg::TransferFunction1D;
transferFunction->setColor(0.0, osg::Vec4(1.0,0.0,0.0,0.0));
transferFunction->setColor(0.5, osg::Vec4(1.0,1.0,0.0,0.5));
transferFunction->setColor(1.0, osg::Vec4(0.0,0.0,1.0,1.0));
}
while(arguments.read("--test2"))
{
transferFunction = new osg::TransferFunction1D;
transferFunction->setColor(0.0, osg::Vec4(1.0,0.0,0.0,0.0));
transferFunction->setColor(0.5, osg::Vec4(1.0,1.0,0.0,0.5));
transferFunction->setColor(1.0, osg::Vec4(0.0,0.0,1.0,1.0));
transferFunction->assign(transferFunction->getColorMap());
}
unsigned int numSlices=500;
while (arguments.read("-s",numSlices)) {}
@@ -975,7 +992,7 @@ int main( int argc, char **argv )
osgDB::ifstream fin(transfer_filename.c_str());
if (fin)
{
osg::TransferFunction1D::ValueMap valueMap;
osg::TransferFunction1D::ColorMap colorMap;
float value = 0.0;
while(fin && value<=1.0)
{
@@ -983,21 +1000,21 @@ int main( int argc, char **argv )
fin >> red >> green >> blue >> alpha;
if (fin)
{
valueMap[value] = osg::Vec4(red/255.0f,green/255.0f,blue/255.0f,alpha/255.0f);
colorMap[value] = osg::Vec4(red/255.0f,green/255.0f,blue/255.0f,alpha/255.0f);
std::cout<<"value = "<<value<<" ("<<red<<", "<<green<<", "<<blue<<", "<<alpha<<")";
std::cout<<" ("<<valueMap[value]<<")"<<std::endl;
std::cout<<" ("<<colorMap[value]<<")"<<std::endl;
}
value += 1/255.0;
}
if (valueMap.empty())
if (colorMap.empty())
{
std::cout<<"Error: No values read from transfer function file: "<<transfer_filename<<std::endl;
return 0;
}
transferFunction = new osg::TransferFunction1D;
transferFunction->assign(valueMap, true);
transferFunction->assign(colorMap);
}
}

View File

@@ -38,16 +38,16 @@ class OSG_EXPORT TransferFunction : public osg::Object
META_Object(osg, TransferFunction)
/** Get the image that is used for passing the transfer function data to the GPU.*/
osg::Image* getImage() { return _image.get(); }
/** Get the const image that is used for passing the transfer function data to the GPU.*/
const osg::Image* getImage() const { return _image.get(); }
protected:
virtual ~TransferFunction();
typedef std::vector<osg::Vec4> Colors;
Colors _colors;
osg::ref_ptr<osg::Image> _image;
};
@@ -62,48 +62,65 @@ class OSG_EXPORT TransferFunction1D : public osg::TransferFunction
TransferFunction1D(const TransferFunction1D& tf, const CopyOp& copyop=CopyOp::SHALLOW_COPY);
META_Object(osg, TransferFunction1D)
void setInputRange(float minimum, float maximum);
void setMinimum(float value) { _minimum = value; }
float getMinimum() const { return _minimum; }
/** Get the mnimum transfer function value.*/
float getMinimum() const { return _colorMap.empty() ? 0.0f : _colorMap.begin()->first; }
void setMaximum(float value) { _maximum = value; }
float getMaximum() const { return _maximum; }
/** Get the maximum transfer function value.*/
float getMaximum() const { return _colorMap.empty() ? 0.0f : _colorMap.rbegin()->first; }
void allocate(unsigned int numX);
/** allocate the osg::Image with specified dimension. The Image tracks the color map, and is used to represent the
* transfer function when download to GPU.*/
void allocate(unsigned int numImageCells);
/** Clear the whole range to just represet a single color.*/
void clear(const osg::Vec4& color = osg::Vec4(1.0f,1.0f,1.0f,1.0f));
unsigned int getNumberCellsX() const { return _colors.size(); }
void setValue(unsigned int i, const osg::Vec4& color) { _colors[i] = color; if (_image.valid()) _image->dirty(); }
const osg::Vec4& getValue(unsigned int i) const { return _colors[i]; }
osg::Vec4 getInterpolatedValue(float v) const
/** Get pixel value from the image. */
osg::Vec4 getPixelValue(unsigned int i) const
{
float iPos = (v-_minimum)*float(_colors.size()-1)/(_maximum-_minimum);
if (iPos<0.0) return _colors[0];
if (iPos>float(_colors.size()-1)) return _colors[_colors.size()-1];
unsigned int iLower = (unsigned int)(iPos);
unsigned int iUpper = iLower+1;
if (iUpper>=_colors.size()) return _colors[iLower];
float r = iPos-floorf(iLower);
const osg::Vec4& cLower = _colors[iLower];
const osg::Vec4& cUpper = _colors[iUpper];
return cLower + (cUpper-cLower)*r;
if (_image.valid() && i<static_cast<unsigned int>(_image->s()))
{
return *reinterpret_cast<osg::Vec4*>(_image->data(i));
}
else
{
return osg::Vec4(1.0f,1.0f,1.0f,1.0f);
}
}
/** Get the number of image cells that are assigned to the represent the transfer function when download to the GPU.*/
unsigned int getNumberImageCells() const { return _image.valid() ? _image->s() : 0; }
/** Set the color for a specified transfer function value.
* updateImage defaults to true, and tells the setColor function to update the associate osg::Image that
* tracks the color map. Pass in false as the updateImage parameter if you are setting up many values
* at once to avoid recomputating og the image data, then once all setColor calls are made explictly call
* updateImage() to bring the osg::Image back into sync with the color map. */
void setColor(float v, const osg::Vec4& color, bool updateImage=true);
typedef std::map<float, osg::Vec4> ValueMap;
void assign(const ValueMap& vcm, bool updateMinMaxRange);
/** Get the color for a specified transfer function value, interpolating the value if no exact match is found.*/
osg::Vec4 getColor(float v) const;
typedef std::map<float, osg::Vec4> ColorMap;
/** Get the color map that stores the mapping between the the tranfser function value and the colour it maps to.*/
ColorMap& getColorMap() { return _colorMap; }
/** Get the const color map that stores the mapping between the the tranfser function value and the colour it maps to.*/
const ColorMap& getColorMap() const { return _colorMap; }
/** Assign a color map and automatically update the image to make sure they are in sync.*/
void assign(const ColorMap& vcm);
/** Manually update the associate osg::Image to represent the colors assigned in the color map.*/
void updateImage();
protected:
float _minimum;
float _maximum;
ColorMap _colorMap;
void assignToImage(float lower_v, const osg::Vec4& lower_c, float upper_v, const osg::Vec4& upper_c);
};
}

View File

@@ -285,7 +285,7 @@ class OSGTERRAIN_EXPORT ContourLayer : public Layer
virtual const osg::Image* getImage() const { return _tf.valid() ? _tf->getImage() : 0; }
virtual unsigned int getNumColumns() const { return _tf.valid() ? _tf->getNumberCellsX() : 0; }
virtual unsigned int getNumColumns() const { return _tf.valid() ? _tf->getNumberImageCells() : 0; }
virtual unsigned int getNumRows() const { return _tf.valid() ? 1 : 0; }
virtual bool getValue(unsigned int i, unsigned int j, float& value) const;

View File

@@ -42,118 +42,175 @@ TransferFunction::~TransferFunction()
//
TransferFunction1D::TransferFunction1D()
{
_minimum = 0.0;
_maximum = 1.0;
}
TransferFunction1D::TransferFunction1D(const TransferFunction1D& tf, const CopyOp& copyop):
TransferFunction(tf,copyop),
_minimum(tf._minimum),
_maximum(tf._maximum)
TransferFunction(tf,copyop)
{
allocate(tf._colors.size());
for(unsigned int i=0; i<_colors.size(); ++i)
{
_colors[i] = tf._colors[i];
}
}
void TransferFunction1D::setInputRange(float minimum, float maximum)
{
_minimum = minimum;
_maximum = maximum;
allocate(tf.getNumberImageCells());
assign(_colorMap);
}
void TransferFunction1D::allocate(unsigned int numX)
{
_colors.resize(numX);
_image = new osg::Image;
_image->setImage(numX,1,1,GL_RGBA, GL_RGBA, GL_FLOAT, (unsigned char*)&_colors[0], osg::Image::NO_DELETE);
_image->allocateImage(numX,1,1,GL_RGBA, GL_FLOAT);
if (!_colorMap.empty()) assign(_colorMap);
}
void TransferFunction1D::clear(const osg::Vec4& color)
{
for(Colors::iterator itr = _colors.begin();
itr != _colors.end();
++itr)
ColorMap newColours;
newColours[getMinimum()] = color;
newColours[getMaximum()] = color;
assign(newColours);
}
void TransferFunction1D::assignToImage(float lower_v, const osg::Vec4& lower_c, float upper_v, const osg::Vec4& upper_c)
{
float minimum = _colorMap.begin()->first;
float maximum = _colorMap.rbegin()->first;
float endPos = float(getNumberImageCells()-1);
float multiplier = endPos/(maximum - minimum);
osg::Vec4* imageData = reinterpret_cast<osg::Vec4*>(_image->data());
float lower_iPos = (lower_v - minimum)*multiplier;
float upper_iPos = (upper_v - minimum)*multiplier;
float start_iPos = ceilf(lower_iPos);
if (start_iPos<0.0f) start_iPos=0.0f;
if (start_iPos>endPos) return;
float end_iPos = floorf(upper_iPos);
if (end_iPos<0.0f) return;
if (end_iPos>endPos) end_iPos=endPos;
Vec4 delta_c = (upper_c-lower_c)/(upper_iPos-lower_iPos);
unsigned int i=static_cast<unsigned int>(start_iPos);
for(float iPos=start_iPos;
iPos<=end_iPos;
++iPos, ++i)
{
*itr = color;
imageData[i] = lower_c + delta_c*(iPos-lower_v);
}
_image->dirty();
}
void TransferFunction1D::assign(const ValueMap& vcm, bool updateMinMaxRange)
void TransferFunction1D::setColor(float v, const osg::Vec4& color, bool updateImage)
{
if (vcm.empty()) return;
if (updateMinMaxRange)
if (!updateImage)
{
_minimum = vcm.begin()->first;
_maximum = vcm.rbegin()->first;
_colorMap[v] = color;
return;
}
if (!_image) allocate(1024);
if (_colors.empty()) allocate(1024);
float multiplier = float(_colors.size()-1)/(_maximum - _minimum);
if (vcm.size()==1)
if (_colorMap.empty() || v<getMinimum() || v>getMaximum())
{
osg::Vec4 color = vcm.begin()->second;
if (_minimum == _maximum)
_colorMap[v] = color;
assign(_colorMap);
return;
}
_colorMap[v] = color;
ColorMap::iterator itr = _colorMap.find(v);
if (itr != _colorMap.begin())
{
ColorMap::iterator previous_itr = itr;
--previous_itr;
assignToImage(previous_itr->first, previous_itr->second, v, color);
}
ColorMap::iterator next_itr = itr;
++next_itr;
if (next_itr != _colorMap.end())
{
assignToImage(v, color, next_itr->first, next_itr->second);
}
}
osg::Vec4 TransferFunction1D::getColor(float v) const
{
if (_colorMap.empty()) return osg::Vec4(1.0f,1.0f,1.0f,1.0f);
if (_colorMap.size()==1) return _colorMap.begin()->second;
if (v <= _colorMap.begin()->first) return _colorMap.begin()->second;
if (v >= _colorMap.rbegin()->first) return _colorMap.rbegin()->second;
// need to implement
std::pair<ColorMap::const_iterator, ColorMap::const_iterator> range = _colorMap.equal_range(v);
// we have an identical match
if (v == range.first->first) return range.first->second;
// range.first will be at the next element after v, so move it before.
--range.first;
float vBefore = range.first->first;
const osg::Vec4& cBefore = range.first->second;
float vAfter = range.second->first;
const osg::Vec4& cAfter = range.second->second;
float r = (v-vBefore)/(vAfter-vBefore);
return cBefore*(1.0f-r) + cAfter*r;
}
void TransferFunction1D::assign(const ColorMap& newColours)
{
_colorMap = newColours;
updateImage();
}
void TransferFunction1D::updateImage()
{
if (_colorMap.empty()) return;
if (!_image || _image->data()==0) allocate(1024);
osg::Vec4* imageData = reinterpret_cast<osg::Vec4*>(_image->data());
if (_colorMap.size()==1)
{
osg::Vec4 color = _colorMap.begin()->second;
for(int i=0; i<_image->s(); ++i)
{
clear(color);
}
else
{
float iPos = (vcm.begin()->first - _minimum)*multiplier;
if (iPos>=0.0f || iPos<float(_colors.size()))
{
float iFloor = floorf(iPos);
unsigned int i = (unsigned int)(iFloor);
_colors[i] = color;
}
imageData[i] = color;
}
_image->dirty();
return;
}
ValueMap::const_iterator lower_itr = vcm.begin();
ValueMap::const_iterator upper_itr = lower_itr;
ColorMap::const_iterator lower_itr = _colorMap.begin();
ColorMap::const_iterator upper_itr = lower_itr;
++upper_itr;
for(;
upper_itr != vcm.end();
upper_itr != _colorMap.end();
++upper_itr)
{
float lower_v = lower_itr->first;
const osg::Vec4& lower_c = lower_itr->second;
float upper_v = upper_itr->first;
const osg::Vec4& upper_c = upper_itr->second;
float lower_iPos = (lower_v - _minimum)*multiplier;
float upper_iPos = (upper_v - _minimum)*multiplier;
float start_iPos = ceilf(lower_iPos);
if (start_iPos<0.0f) start_iPos=0.0f;
if (start_iPos>float(_colors.size()-1)) break;
float end_iPos = floorf(upper_iPos);
if (end_iPos<0.0f) continue;
if (end_iPos>float(_colors.size()-1)) end_iPos=_colors.size()-1;
Vec4 delta_c = (upper_c-lower_c)/(upper_iPos-lower_iPos);
unsigned int i=static_cast<unsigned int>(start_iPos);
for(float iPos=start_iPos;
iPos<=end_iPos;
++iPos, ++i)
{
_colors[i] = lower_c + delta_c*(iPos-lower_v);
}
assignToImage(lower_v, lower_c, upper_v, upper_c);
lower_itr = upper_itr;
}
_image->dirty();
}

View File

@@ -31,22 +31,60 @@ bool TransferFunction1D_readLocalData(osg::Object& obj, osgDB::Input &fr)
osg::TransferFunction1D& tf = static_cast<osg::TransferFunction1D&>(obj);
bool itrAdvanced = false;
unsigned int numCells;
if (fr.read("NumberImageCells ",numCells))
{
tf.allocate(numCells);
itrAdvanced = true;
}
if (fr.matchSequence("Colours {"))
{
int entry = fr[0].getNoNestedBrackets();
fr += 2;
float v;
osg::Vec4 color;
osg::TransferFunction1D::ColorMap colorMap;
while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
{
if (fr.read(v, color.r(), color.g(), color.b(), color.a()))
{
colorMap[v] = color;
}
else
{
++fr;
}
}
tf.assign(colorMap);
itrAdvanced = true;
}
return itrAdvanced;
}
bool TransferFunction1D_writeLocalData(const osg::Object& obj, osgDB::Output& fw)
{
const osg::TransferFunction1D& tf = static_cast<const osg::TransferFunction1D&>(obj);
fw.indent()<<"Minimum "<<tf.getMinimum()<<std::endl;
fw.indent()<<"Maximum "<<tf.getMaximum()<<std::endl;
fw.indent()<<"Colours "<<tf.getNumberCellsX()<<" {"<<std::endl;
const osg::TransferFunction1D::ColorMap& colorMap = tf.getColorMap();
fw.indent()<<"NumberImageCells "<<tf.getNumberImageCells()<<std::endl;
fw.indent()<<"Colours {"<<std::endl;
fw.moveIn();
for(unsigned int i = 0; i<tf.getNumberCellsX(); ++i)
for(osg::TransferFunction1D::ColorMap::const_iterator itr = colorMap.begin();
itr != colorMap.end();
++itr)
{
const osg::Vec4& c = tf.getValue(i);
fw.indent()<<c.r()<<" "<<c.g()<<" "<<c.b()<<" "<<c.a()<<std::endl;
const osg::Vec4& c = itr->second;
fw.indent()<<itr->first<<" "<<c.r()<<" "<<c.g()<<" "<<c.b()<<" "<<c.a()<<std::endl;
}
fw.moveOut();
fw.indent()<<"}"<<std::endl;

View File

@@ -25,93 +25,6 @@ osgDB::RegisterDotOsgWrapperProxy TerrainTile_Proxy
TerrainTile_writeLocalData
);
osg::TransferFunction* readTransferFunction(osgDB::Input& fr)
{
osg::ref_ptr<osg::TransferFunction1D> tf = new osg::TransferFunction1D;
int entry = fr[0].getNoNestedBrackets();
fr += 2;
std::vector<osg::Vec4> colours;
while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
{
bool itrAdvanced = false;
if (fr.matchSequence("range %f %f"))
{
float minValue,maxValue;
fr[1].getFloat(minValue);
fr[2].getFloat(maxValue);
tf->setInputRange(minValue,maxValue);
fr += 3;
itrAdvanced = true;
}
if (fr.matchSequence("color %f %f %f %f"))
{
float r,g,b,a;
fr[1].getFloat(r);
fr[2].getFloat(g);
fr[3].getFloat(b);
fr[4].getFloat(a);
colours.push_back(osg::Vec4(r,g,b,a));
fr += 5;
itrAdvanced = true;
}
if (fr.matchSequence("color %f %f %f"))
{
float r,g,b;
fr[1].getFloat(r);
fr[2].getFloat(g);
fr[3].getFloat(b);
colours.push_back(osg::Vec4(r,g,b,1.0f));
fr += 5;
itrAdvanced = true;
}
if (!itrAdvanced)
{
if (fr[0].getStr()) osg::notify(osg::NOTICE)<<"TransferFunction - unreconised token : "<<fr[0].getStr() << std::endl;
++fr;
}
}
// step over trailing }
++fr;
if (!colours.empty())
{
tf->allocate(colours.size());
for(unsigned int i=0; i<colours.size(); ++i)
{
tf->setValue(i, colours[i]);
}
}
if (tf->getNumberCellsX()==0)
{
tf->allocate(6);
tf->setValue(0, osg::Vec4(1.0,1.0,1.0,1.0));
tf->setValue(1, osg::Vec4(1.0,0.0,1.0,1.0));
tf->setValue(2, osg::Vec4(1.0,0.0,0.0,1.0));
tf->setValue(3, osg::Vec4(1.0,1.0,0.0,1.0));
tf->setValue(4, osg::Vec4(0.0,1.0,1.0,1.0));
tf->setValue(5, osg::Vec4(0.0,1.0,0.0,1.0));
}
return tf.release();
}
bool TerrainTile_readLocalData(osg::Object& obj, osgDB::Input &fr)
{
osgTerrain::TerrainTile& terrainTile = static_cast<osgTerrain::TerrainTile&>(obj);

View File

@@ -25,93 +25,6 @@ osgDB::RegisterDotOsgWrapperProxy VolumeTile_Proxy
VolumeTile_writeLocalData
);
osg::TransferFunction* readTransferFunction(osgDB::Input& fr)
{
osg::ref_ptr<osg::TransferFunction1D> tf = new osg::TransferFunction1D;
int entry = fr[0].getNoNestedBrackets();
fr += 2;
std::vector<osg::Vec4> colours;
while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
{
bool itrAdvanced = false;
if (fr.matchSequence("range %f %f"))
{
float minValue,maxValue;
fr[1].getFloat(minValue);
fr[2].getFloat(maxValue);
tf->setInputRange(minValue,maxValue);
fr += 3;
itrAdvanced = true;
}
if (fr.matchSequence("color %f %f %f %f"))
{
float r,g,b,a;
fr[1].getFloat(r);
fr[2].getFloat(g);
fr[3].getFloat(b);
fr[4].getFloat(a);
colours.push_back(osg::Vec4(r,g,b,a));
fr += 5;
itrAdvanced = true;
}
if (fr.matchSequence("color %f %f %f"))
{
float r,g,b;
fr[1].getFloat(r);
fr[2].getFloat(g);
fr[3].getFloat(b);
colours.push_back(osg::Vec4(r,g,b,1.0f));
fr += 5;
itrAdvanced = true;
}
if (!itrAdvanced)
{
if (fr[0].getStr()) osg::notify(osg::NOTICE)<<"TransferFunction - unreconised token : "<<fr[0].getStr() << std::endl;
++fr;
}
}
// step over trailing }
++fr;
if (!colours.empty())
{
tf->allocate(colours.size());
for(unsigned int i=0; i<colours.size(); ++i)
{
tf->setValue(i, colours[i]);
}
}
if (tf->getNumberCellsX()==0)
{
tf->allocate(6);
tf->setValue(0, osg::Vec4(1.0,1.0,1.0,1.0));
tf->setValue(1, osg::Vec4(1.0,0.0,1.0,1.0));
tf->setValue(2, osg::Vec4(1.0,0.0,0.0,1.0));
tf->setValue(3, osg::Vec4(1.0,1.0,0.0,1.0));
tf->setValue(4, osg::Vec4(0.0,1.0,1.0,1.0));
tf->setValue(5, osg::Vec4(0.0,1.0,0.0,1.0));
}
return tf.release();
}
bool VolumeTile_readLocalData(osg::Object& obj, osgDB::Input &fr)
{
osgVolume::VolumeTile& volumeTile = static_cast<osgVolume::VolumeTile&>(obj);

View File

@@ -328,16 +328,20 @@ bool ContourLayer::transform(float offset, float scale)
osg::notify(osg::NOTICE)<<"ContourLayer::transform("<<offset<<","<<scale<<")"<<std::endl;;
for(unsigned int i=0; i<_tf->getNumberCellsX(); ++i)
osg::TransferFunction1D::ColorMap newColorMap = _tf->getColorMap();
for(osg::TransferFunction1D::ColorMap::iterator itr = newColorMap.begin();
itr != newColorMap.end();
++itr)
{
osg::Vec4 value = _tf->getValue(i);
osg::Vec4& value = itr->second;
value.r() = offset + value.r()* scale;
value.g() = offset + value.g()* scale;
value.b() = offset + value.b()* scale;
value.a() = offset + value.a()* scale;
_tf->setValue(i, value);
}
_tf->assign(newColorMap);
dirty();
return true;
@@ -347,7 +351,7 @@ bool ContourLayer::getValue(unsigned int i, unsigned int j, float& value) const
{
if (!_tf) return false;
const osg::Vec4& v = _tf->getValue(i);
const osg::Vec4& v = _tf->getPixelValue(i);
value = v[0];
return true;
@@ -357,7 +361,7 @@ bool ContourLayer::getValue(unsigned int i, unsigned int j, osg::Vec2& value) co
{
if (!_tf) return false;
const osg::Vec4& v = _tf->getValue(i);
const osg::Vec4& v = _tf->getPixelValue(i);
value.x() = v.x();
value.y() = v.y();
@@ -368,7 +372,7 @@ bool ContourLayer::getValue(unsigned int i, unsigned int j, osg::Vec3& value) co
{
if (!_tf) return false;
const osg::Vec4& v = _tf->getValue(i);
const osg::Vec4& v = _tf->getPixelValue(i);
value.x() = v.x();
value.y() = v.y();
value.z() = v.z();
@@ -380,7 +384,7 @@ bool ContourLayer::getValue(unsigned int i, unsigned int j, osg::Vec4& value) co
{
if (!_tf) return false;
value = _tf->getValue(i);
value = _tf->getPixelValue(i);
return true;
}

View File

@@ -117,7 +117,8 @@ ELSE(WIN32)
IF(OSGVIEWER_USE_XRANDR)
ADD_DEFINITIONS(-DOSGVIEWER_USE_XRANDR)
SET(LIB_PRIVATE_HEADERS ${LIB_PRIVATE_HEADERS} ${XRANDR_INCLUDE_DIRS} )
SET(LIB_EXTRA_LIBS ${X11_Xrandr_LIB} ${LIB_EXTRA_LIBS})
# SET(LIB_EXTRA_LIBS ${X11_Xrandr_LIB} ${LIB_EXTRA_LIBS})
SET(LIB_EXTRA_LIBS ${XRANDR_LIBRARIES} ${LIB_EXTRA_LIBS})
ENDIF(OSGVIEWER_USE_XRANDR)
# X11 on Apple requires X11 library plus OpenGL linking hack on Leopard

View File

@@ -398,7 +398,7 @@ struct ApplyTransferFunctionOperator
inline void luminance(float l) const
{
osg::Vec4 c = _tf->getInterpolatedValue(l);
osg::Vec4 c = _tf->getColor(l);
//std::cout<<"l = "<<l<<" c="<<c<<std::endl;
*(_data++) = (unsigned char)(c[0]*255.0f + 0.5f);
*(_data++) = (unsigned char)(c[1]*255.0f + 0.5f);

View File

@@ -10,7 +10,9 @@
#include <osgIntrospection/StaticMethodInfo>
#include <osgIntrospection/Attributes>
#include <osg/CopyOp>
#include <osg/Image>
#include <osg/Object>
#include <osg/TransferFunction>
#include <osg/Vec4>
@@ -24,10 +26,39 @@
BEGIN_OBJECT_REFLECTOR(osg::TransferFunction)
I_DeclaringFile("osg/TransferFunction");
I_BaseType(osg::Referenced);
I_BaseType(osg::Object);
I_Constructor0(____TransferFunction,
"",
"");
I_ConstructorWithDefaults2(IN, const osg::TransferFunction &, tf, , IN, const osg::CopyOp &, copyop, osg::CopyOp::SHALLOW_COPY,
____TransferFunction__C5_TransferFunction_R1__C5_CopyOp_R1,
"Copy constructor using CopyOp to manage deep vs shallow copy. ",
"");
I_Method0(osg::Object *, cloneType,
Properties::VIRTUAL,
__osg_Object_P1__cloneType,
"Clone the type of an object, with Object* return type. ",
"Must be defined by derived classes. ");
I_Method1(osg::Object *, clone, IN, const osg::CopyOp &, copyop,
Properties::VIRTUAL,
__osg_Object_P1__clone__C5_osg_CopyOp_R1,
"Clone an object, with Object* return type. ",
"Must be defined by derived classes. ");
I_Method1(bool, isSameKindAs, IN, const osg::Object *, obj,
Properties::VIRTUAL,
__bool__isSameKindAs__C5_osg_Object_P1,
"",
"");
I_Method0(const char *, libraryName,
Properties::VIRTUAL,
__C5_char_P1__libraryName,
"return the name of the object's library. ",
"Must be defined by derived classes. The OpenSceneGraph convention is that the namespace of a library is the same as the library name. ");
I_Method0(const char *, className,
Properties::VIRTUAL,
__C5_char_P1__className,
"return the name of the object's class type. ",
"Must be defined by derived classes. ");
I_Method0(osg::Image *, getImage,
Properties::NON_VIRTUAL,
__osg_Image_P1__getImage,
@@ -43,7 +74,7 @@ BEGIN_OBJECT_REFLECTOR(osg::TransferFunction)
0);
END_REFLECTOR
TYPE_NAME_ALIAS(std::map< float COMMA osg::Vec4 >, osg::TransferFunction1D::ValueMap)
TYPE_NAME_ALIAS(std::map< float COMMA osg::Vec4 >, osg::TransferFunction1D::ColorMap)
BEGIN_OBJECT_REFLECTOR(osg::TransferFunction1D)
I_DeclaringFile("osg/TransferFunction");
@@ -51,79 +82,113 @@ BEGIN_OBJECT_REFLECTOR(osg::TransferFunction1D)
I_Constructor0(____TransferFunction1D,
"",
"");
I_Method2(void, setInputRange, IN, float, minimum, IN, float, maximum,
Properties::NON_VIRTUAL,
__void__setInputRange__float__float,
"",
"");
I_Method1(void, setMinimum, IN, float, value,
Properties::NON_VIRTUAL,
__void__setMinimum__float,
I_ConstructorWithDefaults2(IN, const osg::TransferFunction1D &, tf, , IN, const osg::CopyOp &, copyop, osg::CopyOp::SHALLOW_COPY,
____TransferFunction1D__C5_TransferFunction1D_R1__C5_CopyOp_R1,
"Copy constructor using CopyOp to manage deep vs shallow copy. ",
"");
I_Method0(osg::Object *, cloneType,
Properties::VIRTUAL,
__osg_Object_P1__cloneType,
"Clone the type of an object, with Object* return type. ",
"Must be defined by derived classes. ");
I_Method1(osg::Object *, clone, IN, const osg::CopyOp &, copyop,
Properties::VIRTUAL,
__osg_Object_P1__clone__C5_osg_CopyOp_R1,
"Clone an object, with Object* return type. ",
"Must be defined by derived classes. ");
I_Method1(bool, isSameKindAs, IN, const osg::Object *, obj,
Properties::VIRTUAL,
__bool__isSameKindAs__C5_osg_Object_P1,
"",
"");
I_Method0(const char *, libraryName,
Properties::VIRTUAL,
__C5_char_P1__libraryName,
"return the name of the object's library. ",
"Must be defined by derived classes. The OpenSceneGraph convention is that the namespace of a library is the same as the library name. ");
I_Method0(const char *, className,
Properties::VIRTUAL,
__C5_char_P1__className,
"return the name of the object's class type. ",
"Must be defined by derived classes. ");
I_Method0(float, getMinimum,
Properties::NON_VIRTUAL,
__float__getMinimum,
"",
"");
I_Method1(void, setMaximum, IN, float, value,
Properties::NON_VIRTUAL,
__void__setMaximum__float,
"",
"Get the mnimum transfer function value. ",
"");
I_Method0(float, getMaximum,
Properties::NON_VIRTUAL,
__float__getMaximum,
"",
"Get the maximum transfer function value. ",
"");
I_Method1(void, allocate, IN, unsigned int, numX,
I_Method1(void, allocate, IN, unsigned int, numImageCells,
Properties::NON_VIRTUAL,
__void__allocate__unsigned_int,
"",
"");
"allocate the osg::Image with specified dimension. ",
"The Image tracks the color map, and is used to represent the transfer function when download to the graphics card. ");
I_MethodWithDefaults1(void, clear, IN, const osg::Vec4 &, color, osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f),
Properties::NON_VIRTUAL,
__void__clear__C5_osg_Vec4_R1,
"",
"Clear the whole range to just represet a single color. ",
"");
I_Method0(unsigned int, getNumberCellsX,
I_Method1(osg::Vec4, getPixelValue, IN, unsigned int, i,
Properties::NON_VIRTUAL,
__unsigned_int__getNumberCellsX,
"",
__osg_Vec4__getPixelValue__unsigned_int,
"Get pixel value from the image. ",
"");
I_Method2(void, setValue, IN, unsigned int, i, IN, const osg::Vec4 &, color,
I_Method0(unsigned int, getNumberImageCells,
Properties::NON_VIRTUAL,
__void__setValue__unsigned_int__C5_osg_Vec4_R1,
"",
__unsigned_int__getNumberImageCells,
"Get the number of image cells that are assigned to the represent the transfer function when download to the graphics card. ",
"");
I_Method1(const osg::Vec4 &, getValue, IN, unsigned int, i,
I_MethodWithDefaults3(void, setColor, IN, float, v, , IN, const osg::Vec4 &, color, , IN, bool, updateImage, true,
Properties::NON_VIRTUAL,
__void__setColor__float__C5_osg_Vec4_R1__bool,
"Set the color for a specified transfer function value. ",
"updateImage defaults to true, and tells the setColor function to update the associate osg::Image that tracks the color map. Pass in false as the updateImage parameter if you are setting up many values at once to avoid recomputating og the image data, then once all setColor calls are made explictly call updateImage() to bring the osg::Image back into sync with the color map. ");
I_Method1(osg::Vec4, getColor, IN, float, v,
Properties::NON_VIRTUAL,
__C5_osg_Vec4_R1__getValue__unsigned_int,
"",
__osg_Vec4__getColor__float,
"Get the color for a specified transfer function value, interpolating the value if no exact match is found. ",
"");
I_Method1(osg::Vec4, getInterpolatedValue, IN, float, v,
I_Method0(osg::TransferFunction1D::ColorMap &, getColorMap,
Properties::NON_VIRTUAL,
__osg_Vec4__getInterpolatedValue__float,
"",
__ColorMap_R1__getColorMap,
"Get the color map that stores the mapping between the the tranfser function value and the colour it maps to. ",
"");
I_Method2(void, assign, IN, const osg::TransferFunction1D::ValueMap &, vcm, IN, bool, updateMinMaxRange,
I_Method0(const osg::TransferFunction1D::ColorMap &, getColorMap,
Properties::NON_VIRTUAL,
__void__assign__C5_ValueMap_R1__bool,
"",
__C5_ColorMap_R1__getColorMap,
"Get the const color map that stores the mapping between the the tranfser function value and the colour it maps to. ",
"");
I_Method1(void, assign, IN, const osg::TransferFunction1D::ColorMap &, vcm,
Properties::NON_VIRTUAL,
__void__assign__C5_ColorMap_R1,
"Assign a color map and automatically update the image to make sure they are in sync. ",
"");
I_Method0(void, updateImage,
Properties::NON_VIRTUAL,
__void__updateImage,
"Manually update the associate osg::Image to represent the colors assigned in the color map. ",
"");
I_ProtectedMethod4(void, assignToImage, IN, float, lower_v, IN, const osg::Vec4 &, lower_c, IN, float, upper_v, IN, const osg::Vec4 &, upper_c,
Properties::NON_VIRTUAL,
Properties::NON_CONST,
__void__assignToImage__float__C5_osg_Vec4_R1__float__C5_osg_Vec4_R1,
"",
"");
I_SimpleProperty(osg::TransferFunction1D::ColorMap &, ColorMap,
__ColorMap_R1__getColorMap,
0);
I_SimpleProperty(float, Maximum,
__float__getMaximum,
__void__setMaximum__float);
0);
I_SimpleProperty(float, Minimum,
__float__getMinimum,
__void__setMinimum__float);
I_SimpleProperty(unsigned int, NumberCellsX,
__unsigned_int__getNumberCellsX,
0);
I_IndexedProperty(const osg::Vec4 &, Value,
__C5_osg_Vec4_R1__getValue__unsigned_int,
__void__setValue__unsigned_int__C5_osg_Vec4_R1,
0);
I_SimpleProperty(unsigned int, NumberImageCells,
__unsigned_int__getNumberImageCells,
0);
END_REFLECTOR
STD_MAP_REFLECTOR(std::map< float COMMA osg::Vec4 >)