Show
Ignore:
Timestamp:
01/17/09 18:23:47 (5 years ago)
Author:
robert
Message:

Updated event callback to be able to update iso surface value.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/examples/osgvolume/osgvolume.cpp

    r9505 r9509  
    458458 
    459459 
     460struct ScaleOperator 
     461{ 
     462    ScaleOperator():_scale(1.0f) {} 
     463    ScaleOperator(float scale):_scale(scale) {} 
     464    ScaleOperator(const ScaleOperator& so):_scale(so._scale) {} 
     465     
     466    ScaleOperator& operator = (const ScaleOperator& so) { _scale = so._scale; return *this; } 
     467 
     468    float _scale; 
     469 
     470    inline void luminance(float& l) const { l*= _scale; }  
     471    inline void alpha(float& a) const { a*= _scale; }  
     472    inline void luminance_alpha(float& l,float& a) const { l*= _scale; a*= _scale;  }  
     473    inline void rgb(float& r,float& g,float& b) const { r*= _scale; g*=_scale; b*=_scale; } 
     474    inline void rgba(float& r,float& g,float& b,float& a) const { r*= _scale; g*=_scale; b*=_scale; a*=_scale; } 
     475}; 
     476 
     477struct RecordRowOperator 
     478{ 
     479    RecordRowOperator(unsigned int num):_colours(num),_pos(0) {} 
     480 
     481    mutable std::vector<osg::Vec4>  _colours; 
     482    mutable unsigned int            _pos; 
     483     
     484    inline void luminance(float l) const { rgba(l,l,l,1.0f); }  
     485    inline void alpha(float a) const { rgba(1.0f,1.0f,1.0f,a); }  
     486    inline void luminance_alpha(float l,float a) const { rgba(l,l,l,a);  }  
     487    inline void rgb(float r,float g,float b) const { rgba(r,g,b,1.0f); } 
     488    inline void rgba(float r,float g,float b,float a) const { _colours[_pos++].set(r,g,b,a); } 
     489}; 
     490 
     491struct WriteRowOperator 
     492{ 
     493    WriteRowOperator():_pos(0) {} 
     494    WriteRowOperator(unsigned int num):_colours(num),_pos(0) {} 
     495 
     496    std::vector<osg::Vec4>  _colours; 
     497    mutable unsigned int    _pos; 
     498     
     499    inline void luminance(float& l) const { l = _colours[_pos++].r(); }  
     500    inline void alpha(float& a) const { a = _colours[_pos++].a(); }  
     501    inline void luminance_alpha(float& l,float& a) const { l = _colours[_pos].r(); a = _colours[_pos++].a(); }  
     502    inline void rgb(float& r,float& g,float& b) const { r = _colours[_pos].r(); g = _colours[_pos].g(); b = _colours[_pos].b(); } 
     503    inline void rgba(float& r,float& g,float& b,float& a) const {  r = _colours[_pos].r(); g = _colours[_pos].g(); b = _colours[_pos].b(); a = _colours[_pos++].a(); } 
     504}; 
     505 
     506osg::Image* readRaw(int sizeX, int sizeY, int sizeZ, int numberBytesPerComponent, int numberOfComponents, const std::string& endian, const std::string& raw_filename) 
     507{ 
     508    osgDB::ifstream fin(raw_filename.c_str(), std::ifstream::binary); 
     509    if (!fin) return 0; 
     510 
     511    GLenum pixelFormat; 
     512    switch(numberOfComponents) 
     513    { 
     514        case 1 : pixelFormat = GL_LUMINANCE; break; 
     515        case 2 : pixelFormat = GL_LUMINANCE_ALPHA; break; 
     516        case 3 : pixelFormat = GL_RGB; break; 
     517        case 4 : pixelFormat = GL_RGBA; break; 
     518        default : 
     519            osg::notify(osg::NOTICE)<<"Error: numberOfComponents="<<numberOfComponents<<" not supported, only 1,2,3 or 4 are supported."<<std::endl; 
     520            return 0; 
     521    } 
     522 
     523     
     524    GLenum dataType; 
     525    switch(numberBytesPerComponent) 
     526    { 
     527        case 1 : dataType = GL_UNSIGNED_BYTE; break; 
     528        case 2 : dataType = GL_UNSIGNED_SHORT; break; 
     529        case 4 : dataType = GL_UNSIGNED_INT; break; 
     530        default :  
     531            osg::notify(osg::NOTICE)<<"Error: numberBytesPerComponent="<<numberBytesPerComponent<<" not supported, only 1,2 or 4 are supported."<<std::endl; 
     532            return 0; 
     533    } 
     534     
     535    int s_maximumTextureSize=256, t_maximumTextureSize=256, r_maximumTextureSize=256; 
     536     
     537    int sizeS = sizeX; 
     538    int sizeT = sizeY; 
     539    int sizeR = sizeZ; 
     540    clampToNearestValidPowerOfTwo(sizeS, sizeT, sizeR, s_maximumTextureSize, t_maximumTextureSize, r_maximumTextureSize); 
     541 
     542    osg::ref_ptr<osg::Image> image = new osg::Image; 
     543    image->allocateImage(sizeS, sizeT, sizeR, pixelFormat, dataType); 
     544     
     545     
     546    bool endianSwap = (osg::getCpuByteOrder()==osg::BigEndian) ? (endian!="big") : (endian=="big"); 
     547     
     548    unsigned int r_offset = (sizeZ<sizeR) ? sizeR/2 - sizeZ/2 : 0; 
     549     
     550    int offset = endianSwap ? numberBytesPerComponent : 0; 
     551    int delta = endianSwap ? -1 : 1; 
     552    for(int r=0;r<sizeZ;++r) 
     553    { 
     554        for(int t=0;t<sizeY;++t) 
     555        { 
     556            char* data = (char*) image->data(0,t,r+r_offset); 
     557            for(int s=0;s<sizeX;++s) 
     558            { 
     559                if (!fin) return 0; 
     560                 
     561                for(int c=0;c<numberOfComponents;++c) 
     562                { 
     563                    char* ptr = data+offset; 
     564                    for(int b=0;b<numberBytesPerComponent;++b) 
     565                    { 
     566                        fin.read((char*)ptr, 1); 
     567                        ptr += delta; 
     568                    } 
     569                    data += numberBytesPerComponent; 
     570                } 
     571            } 
     572        } 
     573    } 
     574 
     575 
     576    // normalise texture 
     577    { 
     578        // compute range of values 
     579        osg::Vec4 minValue, maxValue; 
     580        osg::computeMinMax(image.get(), minValue, maxValue); 
     581        osg::modifyImage(image.get(),ScaleOperator(1.0f/maxValue.r()));  
     582    } 
     583     
     584     
     585    fin.close(); 
     586 
     587    if (dataType!=GL_UNSIGNED_BYTE) 
     588    { 
     589        // need to convert to ubyte 
     590         
     591        osg::ref_ptr<osg::Image> new_image = new osg::Image; 
     592        new_image->allocateImage(sizeS, sizeT, sizeR, pixelFormat, GL_UNSIGNED_BYTE); 
     593         
     594        RecordRowOperator readOp(sizeS); 
     595        WriteRowOperator writeOp; 
     596 
     597        for(int r=0;r<sizeR;++r) 
     598        { 
     599            for(int t=0;t<sizeT;++t) 
     600            { 
     601                // reset the indices to beginning 
     602                readOp._pos = 0; 
     603                writeOp._pos = 0; 
     604             
     605                // read the pixels into readOp's _colour array 
     606                osg::readRow(sizeS, pixelFormat, dataType, image->data(0,t,r), readOp); 
     607                                 
     608                // pass readOp's _colour array contents over to writeOp (note this is just a pointer swap). 
     609                writeOp._colours.swap(readOp._colours); 
     610                 
     611                osg::modifyRow(sizeS, pixelFormat, GL_UNSIGNED_BYTE, new_image->data(0,t,r), writeOp); 
     612 
     613                // return readOp's _colour array contents back to its rightful owner. 
     614                writeOp._colours.swap(readOp._colours); 
     615            } 
     616        } 
     617         
     618        image = new_image; 
     619    } 
     620     
     621    return image.release(); 
     622     
     623     
     624} 
     625 
     626enum ColourSpaceOperation 
     627{ 
     628    NO_COLOUR_SPACE_OPERATION, 
     629    MODULATE_ALPHA_BY_LUMINANCE, 
     630    MODULATE_ALPHA_BY_COLOUR, 
     631    REPLACE_ALPHA_WITH_LUMINANACE, 
     632    REPLACE_RGB_WITH_LUMINANCE 
     633}; 
     634 
     635struct ModulateAlphaByLuminanceOperator 
     636{ 
     637    ModulateAlphaByLuminanceOperator() {} 
     638 
     639    inline void luminance(float&) const {}  
     640    inline void alpha(float&) const {}  
     641    inline void luminance_alpha(float& l,float& a) const { a*= l; }  
     642    inline void rgb(float&,float&,float&) const {} 
     643    inline void rgba(float& r,float& g,float& b,float& a) const { float l = (r+g+b)*0.3333333; a *= l;} 
     644}; 
     645 
     646struct ModulateAlphaByColourOperator 
     647{ 
     648    ModulateAlphaByColourOperator(const osg::Vec4& colour):_colour(colour) { _lum = _colour.length(); } 
     649     
     650    osg::Vec4 _colour; 
     651    float _lum; 
     652 
     653    inline void luminance(float&) const {}  
     654    inline void alpha(float&) const {}  
     655    inline void luminance_alpha(float& l,float& a) const { a*= l*_lum; }  
     656    inline void rgb(float&,float&,float&) const {} 
     657    inline void rgba(float& r,float& g,float& b,float& a) const { a = (r*_colour.r()+g*_colour.g()+b*_colour.b()+a*_colour.a()); } 
     658}; 
     659 
     660struct ReplaceAlphaWithLuminanceOperator 
     661{ 
     662    ReplaceAlphaWithLuminanceOperator() {} 
     663 
     664    inline void luminance(float&) const {}  
     665    inline void alpha(float&) const {}  
     666    inline void luminance_alpha(float& l,float& a) const { a= l; }  
     667    inline void rgb(float&,float&,float&) const { } 
     668    inline void rgba(float& r,float& g,float& b,float& a) const { float l = (r+g+b)*0.3333333; a = l; } 
     669}; 
     670 
     671osg::Image* doColourSpaceConversion(ColourSpaceOperation op, osg::Image* image, osg::Vec4& colour) 
     672{ 
     673    switch(op) 
     674    { 
     675        case (MODULATE_ALPHA_BY_LUMINANCE): 
     676        { 
     677            std::cout<<"doing conversion MODULATE_ALPHA_BY_LUMINANCE"<<std::endl; 
     678            osg::modifyImage(image,ModulateAlphaByLuminanceOperator());  
     679            return image; 
     680        } 
     681        case (MODULATE_ALPHA_BY_COLOUR): 
     682        { 
     683            std::cout<<"doing conversion MODULATE_ALPHA_BY_COLOUR"<<std::endl; 
     684            osg::modifyImage(image,ModulateAlphaByColourOperator(colour));  
     685            return image; 
     686        } 
     687        case (REPLACE_ALPHA_WITH_LUMINANACE): 
     688        { 
     689            std::cout<<"doing conversion REPLACE_ALPHA_WITH_LUMINANACE"<<std::endl; 
     690            osg::modifyImage(image,ReplaceAlphaWithLuminanceOperator());  
     691            return image; 
     692        } 
     693        case (REPLACE_RGB_WITH_LUMINANCE): 
     694        { 
     695            std::cout<<"doing conversion REPLACE_ALPHA_WITH_LUMINANACE"<<std::endl; 
     696            osg::Image* newImage = new osg::Image; 
     697            newImage->allocateImage(image->s(), image->t(), image->r(), GL_LUMINANCE, image->getDataType()); 
     698            osg::copyImage(image, 0, 0, 0, image->s(), image->t(), image->r(), 
     699                           newImage, 0, 0, 0, false); 
     700            return newImage; 
     701        } 
     702        default: 
     703            return image; 
     704    } 
     705} 
     706 
     707 
     708osg::TransferFunction1D* readTransferFunctionFile(const std::string& filename) 
     709{ 
     710    std::string foundFile = osgDB::findDataFile(filename); 
     711    if (foundFile.empty())  
     712    { 
     713        std::cout<<"Error: could not find transfer function file : "<<filename<<std::endl; 
     714        return 0; 
     715    } 
     716     
     717    std::cout<<"Reading transfer function "<<filename<<std::endl; 
     718 
     719    osg::TransferFunction1D::ValueMap valueMap; 
     720    osgDB::ifstream fin(foundFile.c_str()); 
     721    while(fin) 
     722    { 
     723        float value, red, green, blue, alpha; 
     724        fin >> value >> red >> green >> blue >> alpha; 
     725        if (fin)  
     726        { 
     727            std::cout<<"value = "<<value<<" ("<<red<<", "<<green<<", "<<blue<<", "<<alpha<<")"<<std::endl; 
     728            valueMap[value] = osg::Vec4(red,green,blue,alpha); 
     729        } 
     730    } 
     731     
     732    if (valueMap.empty()) 
     733    { 
     734        std::cout<<"Error: No values read from transfer function file: "<<filename<<std::endl; 
     735        return 0; 
     736    } 
     737     
     738    osg::TransferFunction1D* tf = new osg::TransferFunction1D; 
     739    tf->assign(valueMap, true); 
     740     
     741    return tf; 
     742} 
     743 
     744 
    460745class FollowMouseCallback : public osgGA::GUIEventHandler, public osg::StateSet::Callback 
    461746{ 
    462747    public: 
    463748     
    464         FollowMouseCallback(bool shader = false): 
    465             _shader(shader) 
     749        FollowMouseCallback() 
    466750        { 
    467751            _updateTransparency = false; 
     
    474758        META_Object(osg,FollowMouseCallback); 
    475759 
    476         virtual void operator() (osg::StateSet* stateset, osg::NodeVisitor* nv) 
    477         { 
    478             if (nv->getVisitorType()==osg::NodeVisitor::EVENT_VISITOR) 
    479             { 
    480                 osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(nv); 
    481                 if (ev) 
    482                 { 
    483                     osgGA::GUIActionAdapter* aa = ev->getActionAdapter(); 
    484                     osgGA::EventQueue::Events& events = ev->getEvents(); 
    485                     for(osgGA::EventQueue::Events::iterator itr=events.begin(); 
    486                         itr!=events.end(); 
    487                         ++itr) 
    488                     { 
    489                         handle(*(*itr), *aa, stateset, ev); 
    490                     } 
    491                 } 
    492             } 
    493         } 
    494          
    495760        virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&, osg::Object* object, osg::NodeVisitor*) 
    496761        { 
    497             osg::StateSet* stateset = dynamic_cast<osg::StateSet*>(object); 
    498             if (!stateset) return false; 
     762            osgVolume::VolumeTile* tile = dynamic_cast<osgVolume::VolumeTile*>(object); 
     763            osgVolume::Layer* layer = tile ? tile->getLayer() : 0; 
     764            osgVolume::Property* property = layer ? layer->getProperty() : 0; 
     765            if (!property) return false; 
     766                         
     767            osgVolume::CollectPropertiesVisitor cpv; 
     768            property->accept(cpv); 
    499769             
    500770            switch(ea.getEventType()) 
     
    504774                { 
    505775                    float v = (ea.getY()-ea.getYmin())/(ea.getYmax()-ea.getYmin()); 
    506                     if (_shader) 
     776 
     777                    if (_updateAlphaCutOff && cpv._isoProperty.valid()) 
    507778                    { 
    508                         osg::Uniform* uniform = 0; 
    509                         if (_updateTransparency && (uniform = stateset->getUniform("transparency"))) uniform->set(v); 
    510                         if (_updateAlphaCutOff && (uniform = stateset->getUniform("alphaCutOff"))) uniform->set(v); 
    511                         if (_updateSampleDensity && (uniform = stateset->getUniform("sampleDensity")))  
    512                         { 
    513                             float value = powf(v,5); 
    514                             osg::notify(osg::INFO)<<"sampleDensity = "<<value<<std::endl; 
    515                             uniform->set(value); 
    516                         } 
     779                        osg::notify(osg::NOTICE)<<"Setting isoProperty to "<<v<<std::endl; 
     780                        cpv._isoProperty->setValue(v); 
    517781                    } 
    518                     else 
    519                     {                     
    520                         if (_updateAlphaCutOff) 
    521                         { 
    522                             osg::AlphaFunc* alphaFunc = dynamic_cast<osg::AlphaFunc*>(stateset->getAttribute(osg::StateAttribute::ALPHAFUNC)); 
    523                             if (alphaFunc)  
    524                             { 
    525                                 alphaFunc->setReferenceValue(v); 
    526                             } 
    527                         } 
    528                          
    529                         if (_updateTransparency) 
    530                         { 
    531                             osg::Material* material = dynamic_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL)); 
    532                             if (material) 
    533                             { 
    534                                 material->setAlpha(osg::Material::FRONT_AND_BACK,v); 
    535                             } 
    536                         } 
     782 
     783                    if (_updateAlphaCutOff && cpv._afProperty.valid()) 
     784                    { 
     785                        cpv._afProperty->setValue(v); 
    537786                    } 
    538  
    539                     break; 
    540787                } 
    541788                case(osgGA::GUIEventAdapter::KEYDOWN): 
     
    559806        } 
    560807         
    561         bool _shader; 
    562808        bool _updateTransparency; 
    563809        bool _updateAlphaCutOff; 
    564810        bool _updateSampleDensity; 
    565  
    566811}; 
    567  
    568 struct ScaleOperator 
    569 { 
    570     ScaleOperator():_scale(1.0f) {} 
    571     ScaleOperator(float scale):_scale(scale) {} 
    572     ScaleOperator(const ScaleOperator& so):_scale(so._scale) {} 
    573      
    574     ScaleOperator& operator = (const ScaleOperator& so) { _scale = so._scale; return *this; } 
    575  
    576     float _scale; 
    577  
    578     inline void luminance(float& l) const { l*= _scale; }  
    579     inline void alpha(float& a) const { a*= _scale; }  
    580     inline void luminance_alpha(float& l,float& a) const { l*= _scale; a*= _scale;  }  
    581     inline void rgb(float& r,float& g,float& b) const { r*= _scale; g*=_scale; b*=_scale; } 
    582     inline void rgba(float& r,float& g,float& b,float& a) const { r*= _scale; g*=_scale; b*=_scale; a*=_scale; } 
    583 }; 
    584  
    585 struct RecordRowOperator 
    586 { 
    587     RecordRowOperator(unsigned int num):_colours(num),_pos(0) {} 
    588  
    589     mutable std::vector<osg::Vec4>  _colours; 
    590     mutable unsigned int            _pos; 
    591      
    592     inline void luminance(float l) const { rgba(l,l,l,1.0f); }  
    593     inline void alpha(float a) const { rgba(1.0f,1.0f,1.0f,a); }  
    594     inline void luminance_alpha(float l,float a) const { rgba(l,l,l,a);  }  
    595     inline void rgb(float r,float g,float b) const { rgba(r,g,b,1.0f); } 
    596     inline void rgba(float r,float g,float b,float a) const { _colours[_pos++].set(r,g,b,a); } 
    597 }; 
    598  
    599 struct WriteRowOperator 
    600 { 
    601     WriteRowOperator():_pos(0) {} 
    602     WriteRowOperator(unsigned int num):_colours(num),_pos(0) {} 
    603  
    604     std::vector<osg::Vec4>  _colours; 
    605     mutable unsigned int    _pos; 
    606      
    607     inline void luminance(float& l) const { l = _colours[_pos++].r(); }  
    608     inline void alpha(float& a) const { a = _colours[_pos++].a(); }  
    609     inline void luminance_alpha(float& l,float& a) const { l = _colours[_pos].r(); a = _colours[_pos++].a(); }  
    610     inline void rgb(float& r,float& g,float& b) const { r = _colours[_pos].r(); g = _colours[_pos].g(); b = _colours[_pos].b(); } 
    611     inline void rgba(float& r,float& g,float& b,float& a) const {  r = _colours[_pos].r(); g = _colours[_pos].g(); b = _colours[_pos].b(); a = _colours[_pos++].a(); } 
    612 }; 
    613  
    614 osg::Image* readRaw(int sizeX, int sizeY, int sizeZ, int numberBytesPerComponent, int numberOfComponents, const std::string& endian, const std::string& raw_filename) 
    615 { 
    616     osgDB::ifstream fin(raw_filename.c_str(), std::ifstream::binary); 
    617     if (!fin) return 0; 
    618  
    619     GLenum pixelFormat; 
    620     switch(numberOfComponents) 
    621     { 
    622         case 1 : pixelFormat = GL_LUMINANCE; break; 
    623         case 2 : pixelFormat = GL_LUMINANCE_ALPHA; break; 
    624         case 3 : pixelFormat = GL_RGB; break; 
    625         case 4 : pixelFormat = GL_RGBA; break; 
    626         default : 
    627             osg::notify(osg::NOTICE)<<"Error: numberOfComponents="<<numberOfComponents<<" not supported, only 1,2,3 or 4 are supported."<<std::endl; 
    628             return 0; 
    629     } 
    630  
    631      
    632     GLenum dataType; 
    633     switch(numberBytesPerComponent) 
    634     { 
    635         case 1 : dataType = GL_UNSIGNED_BYTE; break; 
    636         case 2 : dataType = GL_UNSIGNED_SHORT; break; 
    637         case 4 : dataType = GL_UNSIGNED_INT; break; 
    638         default :  
    639             osg::notify(osg::NOTICE)<<"Error: numberBytesPerComponent="<<numberBytesPerComponent<<" not supported, only 1,2 or 4 are supported."<<std::endl; 
    640             return 0; 
    641     } 
    642      
    643     int s_maximumTextureSize=256, t_maximumTextureSize=256, r_maximumTextureSize=256; 
    644      
    645     int sizeS = sizeX; 
    646     int sizeT = sizeY; 
    647     int sizeR = sizeZ; 
    648     clampToNearestValidPowerOfTwo(sizeS, sizeT, sizeR, s_maximumTextureSize, t_maximumTextureSize, r_maximumTextureSize); 
    649  
    650     osg::ref_ptr<osg::Image> image = new osg::Image; 
    651     image->allocateImage(sizeS, sizeT, sizeR, pixelFormat, dataType); 
    652      
    653      
    654     bool endianSwap = (osg::getCpuByteOrder()==osg::BigEndian) ? (endian!="big") : (endian=="big"); 
    655      
    656     unsigned int r_offset = (sizeZ<sizeR) ? sizeR/2 - sizeZ/2 : 0; 
    657      
    658     int offset = endianSwap ? numberBytesPerComponent : 0; 
    659     int delta = endianSwap ? -1 : 1; 
    660     for(int r=0;r<sizeZ;++r) 
    661     { 
    662         for(int t=0;t<sizeY;++t) 
    663         { 
    664             char* data = (char*) image->data(0,t,r+r_offset); 
    665             for(int s=0;s<sizeX;++s) 
    666             { 
    667                 if (!fin) return 0; 
    668                  
    669                 for(int c=0;c<numberOfComponents;++c) 
    670                 { 
    671                     char* ptr = data+offset; 
    672                     for(int b=0;b<numberBytesPerComponent;++b) 
    673                     { 
    674                         fin.read((char*)ptr, 1); 
    675                         ptr += delta; 
    676                     } 
    677                     data += numberBytesPerComponent; 
    678                 } 
    679             } 
    680         } 
    681     } 
    682  
    683  
    684     // normalise texture 
    685     { 
    686         // compute range of values 
    687         osg::Vec4 minValue, maxValue; 
    688         osg::computeMinMax(image.get(), minValue, maxValue); 
    689         osg::modifyImage(image.get(),ScaleOperator(1.0f/maxValue.r()));  
    690     } 
    691      
    692      
    693     fin.close(); 
    694  
    695     if (dataType!=GL_UNSIGNED_BYTE) 
    696     { 
    697         // need to convert to ubyte 
    698          
    699         osg::ref_ptr<osg::Image> new_image = new osg::Image; 
    700         new_image->allocateImage(sizeS, sizeT, sizeR, pixelFormat, GL_UNSIGNED_BYTE); 
    701          
    702         RecordRowOperator readOp(sizeS); 
    703         WriteRowOperator writeOp; 
    704  
    705         for(int r=0;r<sizeR;++r) 
    706         { 
    707             for(int t=0;t<sizeT;++t) 
    708             { 
    709                 // reset the indices to beginning 
    710                 readOp._pos = 0; 
    711                 writeOp._pos = 0; 
    712              
    713                 // read the pixels into readOp's _colour array 
    714                 osg::readRow(sizeS, pixelFormat, dataType, image->data(0,t,r), readOp); 
    715                                  
    716                 // pass readOp's _colour array contents over to writeOp (note this is just a pointer swap). 
    717                 writeOp._colours.swap(readOp._colours); 
    718                  
    719                 osg::modifyRow(sizeS, pixelFormat, GL_UNSIGNED_BYTE, new_image->data(0,t,r), writeOp); 
    720  
    721                 // return readOp's _colour array contents back to its rightful owner. 
    722                 writeOp._colours.swap(readOp._colours); 
    723             } 
    724         } 
    725          
    726         image = new_image; 
    727     } 
    728      
    729     return image.release(); 
    730      
    731      
    732 } 
    733  
    734 enum ColourSpaceOperation 
    735 { 
    736     NO_COLOUR_SPACE_OPERATION, 
    737     MODULATE_ALPHA_BY_LUMINANCE, 
    738     MODULATE_ALPHA_BY_COLOUR, 
    739     REPLACE_ALPHA_WITH_LUMINANACE, 
    740     REPLACE_RGB_WITH_LUMINANCE 
    741 }; 
    742  
    743 struct ModulateAlphaByLuminanceOperator 
    744 { 
    745     ModulateAlphaByLuminanceOperator() {} 
    746  
    747     inline void luminance(float&) const {}  
    748     inline void alpha(float&) const {}  
    749     inline void luminance_alpha(float& l,float& a) const { a*= l; }  
    750     inline void rgb(float&,float&,float&) const {} 
    751     inline void rgba(float& r,float& g,float& b,float& a) const { float l = (r+g+b)*0.3333333; a *= l;} 
    752 }; 
    753  
    754 struct ModulateAlphaByColourOperator 
    755 { 
    756     ModulateAlphaByColourOperator(const osg::Vec4& colour):_colour(colour) { _lum = _colour.length(); } 
    757      
    758     osg::Vec4 _colour; 
    759     float _lum; 
    760  
    761     inline void luminance(float&) const {}  
    762     inline void alpha(float&) const {}  
    763     inline void luminance_alpha(float& l,float& a) const { a*= l*_lum; }  
    764     inline void rgb(float&,float&,float&) const {} 
    765     inline void rgba(float& r,float& g,float& b,float& a) const { a = (r*_colour.r()+g*_colour.g()+b*_colour.b()+a*_colour.a()); } 
    766 }; 
    767  
    768 struct ReplaceAlphaWithLuminanceOperator 
    769 { 
    770     ReplaceAlphaWithLuminanceOperator() {} 
    771  
    772     inline void luminance(float&) const {}  
    773     inline void alpha(float&) const {}  
    774     inline void luminance_alpha(float& l,float& a) const { a= l; }  
    775     inline void rgb(float&,float&,float&) const { } 
    776     inline void rgba(float& r,float& g,float& b,float& a) const { float l = (r+g+b)*0.3333333; a = l; } 
    777 }; 
    778  
    779 osg::Image* doColourSpaceConversion(ColourSpaceOperation op, osg::Image* image, osg::Vec4& colour) 
    780 { 
    781     switch(op) 
    782     { 
    783         case (MODULATE_ALPHA_BY_LUMINANCE): 
    784         { 
    785             std::cout<<"doing conversion MODULATE_ALPHA_BY_LUMINANCE"<<std::endl; 
    786             osg::modifyImage(image,ModulateAlphaByLuminanceOperator());  
    787             return image; 
    788         } 
    789         case (MODULATE_ALPHA_BY_COLOUR): 
    790         { 
    791             std::cout<<"doing conversion MODULATE_ALPHA_BY_COLOUR"<<std::endl; 
    792             osg::modifyImage(image,ModulateAlphaByColourOperator(colour));  
    793             return image; 
    794         } 
    795         case (REPLACE_ALPHA_WITH_LUMINANACE): 
    796         { 
    797             std::cout<<"doing conversion REPLACE_ALPHA_WITH_LUMINANACE"<<std::endl; 
    798             osg::modifyImage(image,ReplaceAlphaWithLuminanceOperator());  
    799             return image; 
    800         } 
    801         case (REPLACE_RGB_WITH_LUMINANCE): 
    802         { 
    803             std::cout<<"doing conversion REPLACE_ALPHA_WITH_LUMINANACE"<<std::endl; 
    804             osg::Image* newImage = new osg::Image; 
    805             newImage->allocateImage(image->s(), image->t(), image->r(), GL_LUMINANCE, image->getDataType()); 
    806             osg::copyImage(image, 0, 0, 0, image->s(), image->t(), image->r(), 
    807                            newImage, 0, 0, 0, false); 
    808             return newImage; 
    809         } 
    810         default: 
    811             return image; 
    812     } 
    813 } 
    814  
    815  
    816 osg::TransferFunction1D* readTransferFunctionFile(const std::string& filename) 
    817 { 
    818     std::string foundFile = osgDB::findDataFile(filename); 
    819     if (foundFile.empty())  
    820     { 
    821         std::cout<<"Error: could not find transfer function file : "<<filename<<std::endl; 
    822         return 0; 
    823     } 
    824      
    825     std::cout<<"Reading transfer function "<<filename<<std::endl; 
    826  
    827     osg::TransferFunction1D::ValueMap valueMap; 
    828     osgDB::ifstream fin(foundFile.c_str()); 
    829     while(fin) 
    830     { 
    831         float value, red, green, blue, alpha; 
    832         fin >> value >> red >> green >> blue >> alpha; 
    833         if (fin)  
    834         { 
    835             std::cout<<"value = "<<value<<" ("<<red<<", "<<green<<", "<<blue<<", "<<alpha<<")"<<std::endl; 
    836             valueMap[value] = osg::Vec4(red,green,blue,alpha); 
    837         } 
    838     } 
    839      
    840     if (valueMap.empty()) 
    841     { 
    842         std::cout<<"Error: No values read from transfer function file: "<<filename<<std::endl; 
    843         return 0; 
    844     } 
    845      
    846     osg::TransferFunction1D* tf = new osg::TransferFunction1D; 
    847     tf->assign(valueMap, true); 
    848      
    849     return tf; 
    850 } 
    851812 
    852813 
     
    13781339        tile->setLayer(layer.get()); 
    13791340         
     1341        tile->setEventCallback(new FollowMouseCallback()); 
     1342         
    13801343        if (useShader) 
    13811344        {