From b176c3a2233361a877130df967c81e5333b33644 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 16 Jan 2009 17:59:38 +0000 Subject: [PATCH] Removed old volume rendering scene graph code from osgvolume example. Moved createNormalMapTexture and applyTransferFunction functions from osgvolume example into include/osgVolume/Layer. --- examples/osgvolume/osgvolume.cpp | 969 +-------------------- include/osgVolume/Layer | 7 + src/osgPlugins/dicom/ReaderWriterDICOM.cpp | 12 +- src/osgVolume/Layer.cpp | 259 ++++++ src/osgVolume/ShaderTechnique.cpp | 7 +- 5 files changed, 275 insertions(+), 979 deletions(-) diff --git a/examples/osgvolume/osgvolume.cpp b/examples/osgvolume/osgvolume.cpp index e1b568287..08046042b 100644 --- a/examples/osgvolume/osgvolume.cpp +++ b/examples/osgvolume/osgvolume.cpp @@ -76,18 +76,6 @@ enum ShadingModel MaximumIntensityProjection }; -// example ReadOperator -// struct ReadOperator -// { -// inline void luminance(float l) const { rgba(l,l,l,1.0f); } -// inline void alpha(float a) const { rgba(1.0f,1.0f,1.0f,a); } -// inline void luminance_alpha(float l,float a) const { rgba(l,l,l,a); } -// inline void rgb(float r,float g,float b) const { rgba(r,g,b,1.0f); } -// inline void rgba(float r,float g,float b,float a) const { std::cout<<"pixel("<getDataType(); - - unsigned int sourcePixelIncrement = 1; - unsigned int alphaOffset = 0; - switch(image_3d->getPixelFormat()) - { - case(GL_ALPHA): - case(GL_LUMINANCE): - sourcePixelIncrement = 1; - alphaOffset = 0; - break; - case(GL_LUMINANCE_ALPHA): - sourcePixelIncrement = 2; - alphaOffset = 1; - break; - case(GL_RGB): - sourcePixelIncrement = 3; - alphaOffset = 0; - break; - case(GL_RGBA): - sourcePixelIncrement = 4; - alphaOffset = 3; - break; - default: - osg::notify(osg::NOTICE)<<"Source pixel format not support for normal map generation."< normalmap_3d = new osg::Image; - normalmap_3d->allocateImage(image_3d->s(),image_3d->t(),image_3d->r(), - GL_RGBA,GL_UNSIGNED_BYTE); - - if (osg::getCpuByteOrder()==osg::LittleEndian) alphaOffset = sourcePixelIncrement-alphaOffset-1; - - for(int r=1;rr()-1;++r) - { - for(int t=1;tt()-1;++t) - { - - if (dataType==GL_UNSIGNED_BYTE) - { - unsigned char* ptr = image_3d->data(1,t,r)+alphaOffset; - unsigned char* left = image_3d->data(0,t,r)+alphaOffset; - unsigned char* right = image_3d->data(2,t,r)+alphaOffset; - unsigned char* above = image_3d->data(1,t+1,r)+alphaOffset; - unsigned char* below = image_3d->data(1,t-1,r)+alphaOffset; - unsigned char* in = image_3d->data(1,t,r+1)+alphaOffset; - unsigned char* out = image_3d->data(1,t,r-1)+alphaOffset; - - unsigned char* destination = (unsigned char*) normalmap_3d->data(1,t,r); - - for(int s=1;ss()-1;++s) - { - - osg::Vec3 grad((float)(*left)-(float)(*right), - (float)(*below)-(float)(*above), - (float)(*out) -(float)(*in)); - - grad.normalize(); - - if (grad.x()==0.0f && grad.y()==0.0f && grad.z()==0.0f) - { - grad.set(128.0f,128.0f,128.0f); - } - else - { - grad.x() = osg::clampBetween((grad.x()+1.0f)*128.0f,0.0f,255.0f); - grad.y() = osg::clampBetween((grad.y()+1.0f)*128.0f,0.0f,255.0f); - grad.z() = osg::clampBetween((grad.z()+1.0f)*128.0f,0.0f,255.0f); - } - - *(destination++) = (unsigned char)(grad.x()); // scale and bias X. - *(destination++) = (unsigned char)(grad.y()); // scale and bias Y. - *(destination++) = (unsigned char)(grad.z()); // scale and bias Z. - - *destination++ = *ptr; - - ptr += sourcePixelIncrement; - left += sourcePixelIncrement; - right += sourcePixelIncrement; - above += sourcePixelIncrement; - below += sourcePixelIncrement; - in += sourcePixelIncrement; - out += sourcePixelIncrement; - } - } - else if (dataType==GL_SHORT) - { - short* ptr = (short*)(image_3d->data(1,t,r)+alphaOffset); - short* left = (short*)(image_3d->data(0,t,r)+alphaOffset); - short* right = (short*)(image_3d->data(2,t,r)+alphaOffset); - short* above = (short*)(image_3d->data(1,t+1,r)+alphaOffset); - short* below = (short*)(image_3d->data(1,t-1,r)+alphaOffset); - short* in = (short*)(image_3d->data(1,t,r+1)+alphaOffset); - short* out = (short*)(image_3d->data(1,t,r-1)+alphaOffset); - - unsigned char* destination = (unsigned char*) normalmap_3d->data(1,t,r); - - for(int s=1;ss()-1;++s) - { - - osg::Vec3 grad((float)(*left)-(float)(*right), - (float)(*below)-(float)(*above), - (float)(*out) -(float)(*in)); - - grad.normalize(); - - //osg::notify(osg::NOTICE)<<"normal "<data(1,t,r)+alphaOffset); - unsigned short* left = (unsigned short*)(image_3d->data(0,t,r)+alphaOffset); - unsigned short* right = (unsigned short*)(image_3d->data(2,t,r)+alphaOffset); - unsigned short* above = (unsigned short*)(image_3d->data(1,t+1,r)+alphaOffset); - unsigned short* below = (unsigned short*)(image_3d->data(1,t-1,r)+alphaOffset); - unsigned short* in = (unsigned short*)(image_3d->data(1,t,r+1)+alphaOffset); - unsigned short* out = (unsigned short*)(image_3d->data(1,t,r-1)+alphaOffset); - - unsigned char* destination = (unsigned char*) normalmap_3d->data(1,t,r); - - for(int s=1;ss()-1;++s) - { - - osg::Vec3 grad((float)(*left)-(float)(*right), - (float)(*below)-(float)(*above), - (float)(*out) -(float)(*in)); - - grad.normalize(); - - if (grad.x()==0.0f && grad.y()==0.0f && grad.z()==0.0f) - { - grad.set(128.0f,128.0f,128.0f); - } - else - { - grad.x() = osg::clampBetween((grad.x()+1.0f)*128.0f,0.0f,255.0f); - grad.y() = osg::clampBetween((grad.y()+1.0f)*128.0f,0.0f,255.0f); - grad.z() = osg::clampBetween((grad.z()+1.0f)*128.0f,0.0f,255.0f); - } - - *(destination++) = (unsigned char)(grad.x()); // scale and bias X. - *(destination++) = (unsigned char)(grad.y()); // scale and bias Y. - *(destination++) = (unsigned char)(grad.z()); // scale and bias Z. - - *destination++ = *ptr/256; - - ptr += sourcePixelIncrement; - left += sourcePixelIncrement; - right += sourcePixelIncrement; - above += sourcePixelIncrement; - below += sourcePixelIncrement; - in += sourcePixelIncrement; - out += sourcePixelIncrement; - } - } - } - } - - - osg::notify(osg::NOTICE)<<"Created NormalMapTexture"<setVertexArray(coords); - for(unsigned int i=0;isetNormalArray(normals); - geom->setNormalBinding(osg::Geometry::BIND_OVERALL); - - osg::Vec4Array* colors = new osg::Vec4Array(1); - (*colors)[0].set(1.0f,1.0f,1.0f,alpha); - geom->setColorArray(colors); - geom->setColorBinding(osg::Geometry::BIND_OVERALL); - - geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,coords->size())); - - osg::Billboard* billboard = new osg::Billboard; - billboard->setMode(osg::Billboard::POINT_ROT_WORLD); - billboard->addDrawable(geom); - billboard->setPosition(0,osg::Vec3(0.0f,0.0f,0.0f)); - - return billboard; -} - class FollowMouseCallback : public osgGA::GUIEventHandler, public osg::StateSet::Callback { public: @@ -819,590 +565,6 @@ class FollowMouseCallback : public osgGA::GUIEventHandler, public osg::StateSet: }; -osg::Node* createShaderModel(ShadingModel shadingModel, - osg::ref_ptr& image_3d, - osg::Image* normalmap_3d, - osg::TransferFunction1D* tf, - osg::Texture::InternalFormatMode internalFormatMode, - float xSize, float ySize, float zSize, - float /*xMultiplier*/, float /*yMultiplier*/, float /*zMultiplier*/, - unsigned int /*numSlices*/=500, float /*sliceEnd*/=1.0f, float alphaFuncValue=0.02f) -{ - osg::Texture::FilterMode minFilter = osg::Texture::LINEAR; - osg::Texture::FilterMode magFilter = osg::Texture::LINEAR; - - osg::Group* root = new osg::Group; - - osg::Geode* geode = new osg::Geode; - root->addChild(geode); - - osg::StateSet* stateset = geode->getOrCreateStateSet(); - - stateset->setEventCallback(new FollowMouseCallback(true)); - - stateset->setMode(GL_ALPHA_TEST,osg::StateAttribute::ON); - - - osg::Program* program = new osg::Program; - stateset->setAttribute(program); - - // get shaders from source - - osg::Shader* vertexShader = osgDB::readShaderFile(osg::Shader::VERTEX, "volume.vert"); - if (vertexShader) - { - program->addShader(vertexShader); - } - else - { - #include "volume_vert.cpp" - program->addShader(new osg::Shader(osg::Shader::VERTEX, volume_vert)); - } - - if (!(normalmap_3d && tf)) - { - // set up the 3d texture itself, - // note, well set the filtering up so that mip mapping is disabled, - // gluBuild3DMipsmaps doesn't do a very good job of handled the - // imbalanced dimensions of the 256x256x4 texture. - osg::Texture3D* texture3D = new osg::Texture3D; - texture3D->setResizeNonPowerOfTwoHint(false); - texture3D->setFilter(osg::Texture3D::MIN_FILTER,minFilter); - texture3D->setFilter(osg::Texture3D::MAG_FILTER, magFilter); - texture3D->setWrap(osg::Texture3D::WRAP_R,osg::Texture3D::CLAMP_TO_EDGE); - texture3D->setWrap(osg::Texture3D::WRAP_S,osg::Texture3D::CLAMP_TO_EDGE); - texture3D->setWrap(osg::Texture3D::WRAP_T,osg::Texture3D::CLAMP_TO_EDGE); - if (image_3d->getPixelFormat()==GL_ALPHA || - image_3d->getPixelFormat()==GL_LUMINANCE) - { - texture3D->setInternalFormatMode(osg::Texture3D::USE_USER_DEFINED_FORMAT); - texture3D->setInternalFormat(GL_INTENSITY); - } - else - { - texture3D->setInternalFormatMode(internalFormatMode); - } - texture3D->setImage(image_3d.get()); - - stateset->setTextureAttributeAndModes(0,texture3D,osg::StateAttribute::ON); - - osg::Uniform* baseTextureSampler = new osg::Uniform("baseTexture",0); - stateset->addUniform(baseTextureSampler); - } - - - if (shadingModel==MaximumIntensityProjection) - { - if (tf) - { - osg::Texture1D* texture1D = new osg::Texture1D; - texture1D->setImage(tf->getImage()); - stateset->setTextureAttributeAndModes(1,texture1D,osg::StateAttribute::ON); - - osg::Shader* fragmentShader = osgDB::readShaderFile(osg::Shader::FRAGMENT, "volume_tf_mip.frag"); - if (fragmentShader) - { - program->addShader(fragmentShader); - } - else - { - #include "volume_tf_mip_frag.cpp" - program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_tf_mip_frag)); - } - - osg::Uniform* tfTextureSampler = new osg::Uniform("tfTexture",1); - stateset->addUniform(tfTextureSampler); - - } - else - { - osg::Shader* fragmentShader = osgDB::readShaderFile(osg::Shader::FRAGMENT, "volume_mip.frag"); - if (fragmentShader) - { - program->addShader(fragmentShader); - } - else - { - #include "volume_mip_frag.cpp" - program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_mip_frag)); - } - } - } - else if (shadingModel==Isosurface) - { - - if (tf) - { - osg::Texture1D* texture1D = new osg::Texture1D; - texture1D->setImage(tf->getImage()); - texture1D->setResizeNonPowerOfTwoHint(false); - texture1D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); - texture1D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); - texture1D->setWrap(osg::Texture::WRAP_R,osg::Texture::CLAMP_TO_EDGE); - stateset->setTextureAttributeAndModes(1,texture1D,osg::StateAttribute::ON); - - osg::Uniform* tfTextureSampler = new osg::Uniform("tfTexture",1); - stateset->addUniform(tfTextureSampler); - - osg::Shader* fragmentShader = osgDB::readShaderFile(osg::Shader::FRAGMENT, "volume_tf_iso.frag"); - if (fragmentShader) - { - program->addShader(fragmentShader); - } - else - { - #include "volume_tf_iso_frag.cpp" - program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_tf_iso_frag)); - } - } - else - { - osg::Shader* fragmentShader = osgDB::readShaderFile(osg::Shader::FRAGMENT, "volume_iso.frag"); - if (fragmentShader) - { - program->addShader(fragmentShader); - } - else - { - #include "volume_iso_frag.cpp" - program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_iso_frag)); - } - } - } - else if (normalmap_3d) - { - osg::notify(osg::NOTICE)<<"Setting up normalmapping shader"<addUniform(normalMapSampler); - - osg::Texture3D* normalMap = new osg::Texture3D; - normalMap->setImage(normalmap_3d); - normalMap->setResizeNonPowerOfTwoHint(false); - normalMap->setInternalFormatMode(internalFormatMode); - normalMap->setFilter(osg::Texture3D::MIN_FILTER, osg::Texture::LINEAR); - normalMap->setFilter(osg::Texture3D::MAG_FILTER, osg::Texture::LINEAR); - normalMap->setWrap(osg::Texture3D::WRAP_R,osg::Texture3D::CLAMP_TO_EDGE); - normalMap->setWrap(osg::Texture3D::WRAP_S,osg::Texture3D::CLAMP_TO_EDGE); - normalMap->setWrap(osg::Texture3D::WRAP_T,osg::Texture3D::CLAMP_TO_EDGE); - - stateset->setTextureAttributeAndModes(1,normalMap,osg::StateAttribute::ON); - - if (tf) - { - osg::Texture1D* texture1D = new osg::Texture1D; - texture1D->setImage(tf->getImage()); - texture1D->setResizeNonPowerOfTwoHint(false); - texture1D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); - texture1D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); - texture1D->setWrap(osg::Texture::WRAP_R,osg::Texture::CLAMP_TO_EDGE); - stateset->setTextureAttributeAndModes(0,texture1D,osg::StateAttribute::ON); - - osg::Shader* fragmentShader = osgDB::readShaderFile(osg::Shader::FRAGMENT, "volume-tf-n.frag"); - if (fragmentShader) - { - program->addShader(fragmentShader); - } - else - { - #include "volume_tf_n_frag.cpp" - program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_tf_n_frag)); - } - - osg::Uniform* tfTextureSampler = new osg::Uniform("tfTexture",0); - stateset->addUniform(tfTextureSampler); - } - else - { - osg::Shader* fragmentShader = osgDB::readShaderFile(osg::Shader::FRAGMENT, "volume-n.frag"); - if (fragmentShader) - { - program->addShader(fragmentShader); - } - else - { - #include "volume_n_frag.cpp" - program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_n_frag)); - } - } - } - else if (tf) - { - osg::Texture1D* texture1D = new osg::Texture1D; - texture1D->setImage(tf->getImage()); - texture1D->setResizeNonPowerOfTwoHint(false); - texture1D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); - texture1D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); - texture1D->setWrap(osg::Texture::WRAP_R,osg::Texture::CLAMP_TO_EDGE); - stateset->setTextureAttributeAndModes(1,texture1D,osg::StateAttribute::ON); - - osg::Uniform* tfTextureSampler = new osg::Uniform("tfTexture",1); - stateset->addUniform(tfTextureSampler); - - osg::Shader* fragmentShader = osgDB::readShaderFile(osg::Shader::FRAGMENT, "volume-tf.frag"); - if (fragmentShader) - { - program->addShader(fragmentShader); - } - else - { - #include "volume_tf_frag.cpp" - program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_tf_frag)); - } - - } - else - { - - osg::Shader* fragmentShader = osgDB::readShaderFile(osg::Shader::FRAGMENT, "volume.frag"); - if (fragmentShader) - { - program->addShader(fragmentShader); - } - else - { - #include "volume_frag.cpp" - program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_frag)); - } - } - - osg::Uniform* sampleDensity = new osg::Uniform("sampleDensity", 0.005f); - stateset->addUniform(sampleDensity); - - osg::Uniform* transpancy = new osg::Uniform("transparency",0.5f); - stateset->addUniform(transpancy); - - osg::Uniform* alphaCutOff = new osg::Uniform("alphaCutOff",alphaFuncValue); - stateset->addUniform(alphaCutOff); - - stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON); - - osg::TexGen* texgen = new osg::TexGen; - texgen->setMode(osg::TexGen::OBJECT_LINEAR); - texgen->setPlane(osg::TexGen::S, osg::Plane(1.0f/xSize,0.0f,0.0f,0.0f)); - texgen->setPlane(osg::TexGen::T, osg::Plane(0.0f,1.0f/ySize,0.0f,0.0f)); - texgen->setPlane(osg::TexGen::R, osg::Plane(0.0f,0.0f,1.0f/zSize,0.0f)); - texgen->setPlane(osg::TexGen::Q, osg::Plane(0.0f,0.0f,0.0f,1.0f)); - - stateset->setTextureAttributeAndModes(0, texgen, osg::StateAttribute::ON); - - { - osg::Geometry* geom = new osg::Geometry; - - osg::Vec3Array* coords = new osg::Vec3Array(8); - (*coords)[0].set(0,0,0); - (*coords)[1].set(xSize,0,0); - (*coords)[2].set(xSize,ySize,0); - (*coords)[3].set(0,ySize,0); - (*coords)[4].set(0,0,zSize); - (*coords)[5].set(xSize,0,zSize); - (*coords)[6].set(ySize,ySize,zSize); - (*coords)[7].set(0,ySize,zSize); - geom->setVertexArray(coords); - - osg::Vec4Array* colours = new osg::Vec4Array(1); - (*colours)[0].set(1.0f,1.0f,1.0,1.0f); - geom->setColorArray(colours); - geom->setColorBinding(osg::Geometry::BIND_OVERALL); - - osg::DrawElementsUShort* drawElements = new osg::DrawElementsUShort(GL_QUADS); - // bottom - drawElements->push_back(0); - drawElements->push_back(1); - drawElements->push_back(2); - drawElements->push_back(3); - - // bottom - drawElements->push_back(3); - drawElements->push_back(2); - drawElements->push_back(6); - drawElements->push_back(7); - - // left - drawElements->push_back(0); - drawElements->push_back(3); - drawElements->push_back(7); - drawElements->push_back(4); - - // right - drawElements->push_back(5); - drawElements->push_back(6); - drawElements->push_back(2); - drawElements->push_back(1); - - // front - drawElements->push_back(1); - drawElements->push_back(0); - drawElements->push_back(4); - drawElements->push_back(5); - - // top - drawElements->push_back(7); - drawElements->push_back(6); - drawElements->push_back(5); - drawElements->push_back(4); - - geom->addPrimitiveSet(drawElements); - - geode->addDrawable(geom); - - } - return root; -} - -osg::Node* createModel(ShadingModel shadeModel, - osg::ref_ptr& image_3d, - osg::ref_ptr& normalmap_3d, - osg::Texture::InternalFormatMode internalFormatMode, - float xSize, float ySize, float zSize, - float xMultiplier, float yMultiplier, float zMultiplier, - unsigned int numSlices=500, float sliceEnd=1.0f, float alphaFuncValue=0.02f, bool maximumIntensityProjection = false) -{ - bool two_pass = normalmap_3d.valid() && (image_3d->getPixelFormat()==GL_RGB || image_3d->getPixelFormat()==GL_RGBA); - - osg::BoundingBox bb(-xSize*0.5f,-ySize*0.5f,-zSize*0.5f,xSize*0.5f,ySize*0.5f,zSize*0.5f); - - - osg::Texture::FilterMode minFilter = osg::Texture::NEAREST; - osg::Texture::FilterMode magFilter = osg::Texture::NEAREST; - - float maxAxis = xSize; - if (ySize > maxAxis) maxAxis = ySize; - if (zSize > maxAxis) maxAxis = zSize; - - osg::Group* group = new osg::Group; - - osg::TexGenNode* texgenNode_0 = new osg::TexGenNode; - texgenNode_0->setTextureUnit(0); - texgenNode_0->getTexGen()->setMode(osg::TexGen::EYE_LINEAR); - texgenNode_0->getTexGen()->setPlane(osg::TexGen::S, osg::Plane(xMultiplier/xSize,0.0f,0.0f,0.5f)); - texgenNode_0->getTexGen()->setPlane(osg::TexGen::T, osg::Plane(0.0f,yMultiplier/ySize,0.0f,0.5f)); - texgenNode_0->getTexGen()->setPlane(osg::TexGen::R, osg::Plane(0.0f,0.0f,zMultiplier/zSize,0.5f)); - - if (two_pass) - { - osg::TexGenNode* texgenNode_1 = new osg::TexGenNode; - texgenNode_1->setTextureUnit(1); - texgenNode_1->getTexGen()->setMode(osg::TexGen::EYE_LINEAR); - texgenNode_1->getTexGen()->setPlane(osg::TexGen::S, texgenNode_0->getTexGen()->getPlane(osg::TexGen::S)); - texgenNode_1->getTexGen()->setPlane(osg::TexGen::T, texgenNode_0->getTexGen()->getPlane(osg::TexGen::T)); - texgenNode_1->getTexGen()->setPlane(osg::TexGen::R, texgenNode_0->getTexGen()->getPlane(osg::TexGen::R)); - - texgenNode_1->addChild(texgenNode_0); - - group->addChild(texgenNode_1); - } - else - { - group->addChild(texgenNode_0); - } - - float cubeSize = sqrtf(xSize*xSize+ySize*ySize+zSize*zSize); - - osg::ClipNode* clipnode = new osg::ClipNode; - clipnode->addChild(createCube(cubeSize,1.0f, numSlices,sliceEnd)); - clipnode->createClipBox(bb); - - { - // set up the Geometry to enclose the clip volume to prevent near/far clipping from affecting billboard - osg::Geometry* geom = new osg::Geometry; - - osg::Vec3Array* coords = new osg::Vec3Array(); - coords->push_back(bb.corner(0)); - coords->push_back(bb.corner(1)); - coords->push_back(bb.corner(2)); - coords->push_back(bb.corner(3)); - coords->push_back(bb.corner(4)); - coords->push_back(bb.corner(5)); - coords->push_back(bb.corner(6)); - coords->push_back(bb.corner(7)); - - geom->setVertexArray(coords); - - osg::Vec4Array* colors = new osg::Vec4Array(1); - (*colors)[0].set(1.0f,1.0f,1.0f,1.0f); - geom->setColorArray(colors); - geom->setColorBinding(osg::Geometry::BIND_OVERALL); - - geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS,0,coords->size())); - - osg::Geode* geode = new osg::Geode; - geode->addDrawable(geom); - - clipnode->addChild(geode); - - } - - texgenNode_0->addChild(clipnode); - - osg::StateSet* stateset = texgenNode_0->getOrCreateStateSet(); - - stateset->setEventCallback(new FollowMouseCallback(false)); - - stateset->setMode(GL_LIGHTING,osg::StateAttribute::ON); - stateset->setMode(GL_BLEND,osg::StateAttribute::ON); - stateset->setAttributeAndModes(new osg::AlphaFunc(osg::AlphaFunc::GREATER,alphaFuncValue), osg::StateAttribute::ON); - - osg::Material* material = new osg::Material; - material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); - stateset->setAttributeAndModes(material); - - if (shadeModel==MaximumIntensityProjection) - { - stateset->setAttribute(new osg::BlendFunc(osg::BlendFunc::ONE, osg::BlendFunc::ONE)); - stateset->setAttribute(new osg::BlendEquation(osg::BlendEquation::RGBA_MAX)); - } - - osg::Vec3 lightDirection(1.0f,-1.0f,1.0f); - lightDirection.normalize(); - - if (normalmap_3d.valid()) - { - if (two_pass) - { - - // set up normal texture - osg::Texture3D* bump_texture3D = new osg::Texture3D; - bump_texture3D->setFilter(osg::Texture3D::MIN_FILTER,minFilter); - bump_texture3D->setFilter(osg::Texture3D::MAG_FILTER, magFilter); - bump_texture3D->setWrap(osg::Texture3D::WRAP_R,osg::Texture3D::CLAMP_TO_EDGE); - bump_texture3D->setWrap(osg::Texture3D::WRAP_S,osg::Texture3D::CLAMP_TO_EDGE); - bump_texture3D->setWrap(osg::Texture3D::WRAP_T,osg::Texture3D::CLAMP_TO_EDGE); - bump_texture3D->setImage(normalmap_3d.get()); - - bump_texture3D->setInternalFormatMode(internalFormatMode); - - stateset->setTextureAttributeAndModes(0,bump_texture3D,osg::StateAttribute::ON); - - osg::TexEnvCombine* tec = new osg::TexEnvCombine; - tec->setConstantColorAsLightDirection(lightDirection); - - tec->setCombine_RGB(osg::TexEnvCombine::DOT3_RGB); - tec->setSource0_RGB(osg::TexEnvCombine::CONSTANT); - tec->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR); - tec->setSource1_RGB(osg::TexEnvCombine::TEXTURE); - - tec->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR); - - tec->setCombine_Alpha(osg::TexEnvCombine::REPLACE); - tec->setSource0_Alpha(osg::TexEnvCombine::PRIMARY_COLOR); - tec->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA); - tec->setSource1_Alpha(osg::TexEnvCombine::TEXTURE); - tec->setOperand1_Alpha(osg::TexEnvCombine::SRC_ALPHA); - - stateset->setTextureAttributeAndModes(0, tec, osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON); - - stateset->setTextureMode(0,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); - stateset->setTextureMode(0,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); - stateset->setTextureMode(0,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); - - - // set up color texture - osg::Texture3D* texture3D = new osg::Texture3D; - texture3D->setResizeNonPowerOfTwoHint(false); - texture3D->setFilter(osg::Texture3D::MIN_FILTER,minFilter); - texture3D->setFilter(osg::Texture3D::MAG_FILTER, magFilter); - texture3D->setWrap(osg::Texture3D::WRAP_R,osg::Texture3D::CLAMP_TO_EDGE); - texture3D->setWrap(osg::Texture3D::WRAP_S,osg::Texture3D::CLAMP_TO_EDGE); - texture3D->setWrap(osg::Texture3D::WRAP_T,osg::Texture3D::CLAMP_TO_EDGE); - if (image_3d->getPixelFormat()==GL_ALPHA || - image_3d->getPixelFormat()==GL_LUMINANCE) - { - texture3D->setInternalFormatMode(osg::Texture3D::USE_USER_DEFINED_FORMAT); - texture3D->setInternalFormat(GL_INTENSITY); - } - else - { - texture3D->setInternalFormatMode(internalFormatMode); - } - texture3D->setImage(image_3d.get()); - - stateset->setTextureAttributeAndModes(1,texture3D,osg::StateAttribute::ON); - - stateset->setTextureMode(1,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); - stateset->setTextureMode(1,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); - stateset->setTextureMode(1,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); - - stateset->setTextureAttributeAndModes(1,new osg::TexEnv(),osg::StateAttribute::ON); - - } - else - { - osg::Texture3D* bump_texture3D = new osg::Texture3D; - bump_texture3D->setResizeNonPowerOfTwoHint(false); - bump_texture3D->setFilter(osg::Texture3D::MIN_FILTER,minFilter); - bump_texture3D->setFilter(osg::Texture3D::MAG_FILTER, magFilter); - bump_texture3D->setWrap(osg::Texture3D::WRAP_R,osg::Texture3D::CLAMP_TO_EDGE); - bump_texture3D->setWrap(osg::Texture3D::WRAP_S,osg::Texture3D::CLAMP_TO_EDGE); - bump_texture3D->setWrap(osg::Texture3D::WRAP_T,osg::Texture3D::CLAMP_TO_EDGE); - bump_texture3D->setImage(normalmap_3d.get()); - - bump_texture3D->setInternalFormatMode(internalFormatMode); - - stateset->setTextureAttributeAndModes(0,bump_texture3D,osg::StateAttribute::ON); - - osg::TexEnvCombine* tec = new osg::TexEnvCombine; - tec->setConstantColorAsLightDirection(lightDirection); - - tec->setCombine_RGB(osg::TexEnvCombine::DOT3_RGB); - tec->setSource0_RGB(osg::TexEnvCombine::CONSTANT); - tec->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR); - tec->setSource1_RGB(osg::TexEnvCombine::TEXTURE); - tec->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR); - - tec->setCombine_Alpha(osg::TexEnvCombine::MODULATE); - tec->setSource0_Alpha(osg::TexEnvCombine::PRIMARY_COLOR); - tec->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA); - tec->setSource1_Alpha(osg::TexEnvCombine::TEXTURE); - tec->setOperand1_Alpha(osg::TexEnvCombine::SRC_ALPHA); - - stateset->setTextureAttributeAndModes(0, tec, osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON); - - stateset->setTextureMode(0,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); - stateset->setTextureMode(0,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); - stateset->setTextureMode(0,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); - - image_3d = normalmap_3d; - } - } - else - { - // set up the 3d texture itself, - // note, well set the filtering up so that mip mapping is disabled, - // gluBuild3DMipsmaps doesn't do a very good job of handled the - // imbalanced dimensions of the 256x256x4 texture. - osg::Texture3D* texture3D = new osg::Texture3D; - texture3D->setResizeNonPowerOfTwoHint(false); - texture3D->setFilter(osg::Texture3D::MIN_FILTER,minFilter); - texture3D->setFilter(osg::Texture3D::MAG_FILTER, magFilter); - texture3D->setWrap(osg::Texture3D::WRAP_R,osg::Texture3D::CLAMP_TO_EDGE); - texture3D->setWrap(osg::Texture3D::WRAP_S,osg::Texture3D::CLAMP_TO_EDGE); - texture3D->setWrap(osg::Texture3D::WRAP_T,osg::Texture3D::CLAMP_TO_EDGE); - if (image_3d->getPixelFormat()==GL_ALPHA || - image_3d->getPixelFormat()==GL_LUMINANCE) - { - texture3D->setInternalFormatMode(osg::Texture3D::USE_USER_DEFINED_FORMAT); - texture3D->setInternalFormat(GL_INTENSITY); - } - else - { - texture3D->setInternalFormatMode(internalFormatMode); - } - - texture3D->setImage(image_3d.get()); - - stateset->setTextureAttributeAndModes(0,texture3D,osg::StateAttribute::ON); - - stateset->setTextureMode(0,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); - stateset->setTextureMode(0,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); - stateset->setTextureMode(0,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); - - stateset->setTextureAttributeAndModes(0,new osg::TexEnv(),osg::StateAttribute::ON); - } - - return group; -} - struct ScaleOperator { ScaleOperator():_scale(1.0f) {} @@ -1651,58 +813,6 @@ osg::Image* doColourSpaceConversion(ColourSpaceOperation op, osg::Image* image, } -struct ApplyTransferFunctionOperator -{ - ApplyTransferFunctionOperator(osg::TransferFunction1D* tf, unsigned char* data): - _tf(tf), - _data(data) {} - - inline void luminance(float l) const - { - osg::Vec4 c = _tf->getInterpolatedValue(l); - //std::cout<<"l = "<allocateImage(image->s(),image->t(), image->r(), GL_RGBA, GL_UNSIGNED_BYTE); - - ApplyTransferFunctionOperator op(transferFunction, output_image->data()); - osg::readImage(image,op); - - return output_image; -} - osg::TransferFunction1D* readTransferFunctionFile(const std::string& filename) { std::string foundFile = osgDB::findDataFile(filename); @@ -1776,7 +886,6 @@ int main( int argc, char **argv ) arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use of 3D textures."); arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ..."); arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information"); - arguments.getApplicationUsage()->addCommandLineOption("-n","Create normal map for per voxel lighting."); arguments.getApplicationUsage()->addCommandLineOption("-s ","Number of slices to create."); arguments.getApplicationUsage()->addCommandLineOption("--images [filenames]","Specify a stack of 2d images to build the 3d volume from."); arguments.getApplicationUsage()->addCommandLineOption("--shader","Use OpenGL Shading Language. (default)"); @@ -1866,13 +975,6 @@ int main( int argc, char **argv ) ShadingModel shadingModel = Standard; while(arguments.read("--mip")) shadingModel = MaximumIntensityProjection; - bool createNormalMap = false; - while (arguments.read("-n")) - { - shadingModel = Light; - createNormalMap=true; - } - while (arguments.read("--isosurface")) { shadingModel = Isosurface; @@ -2129,15 +1231,6 @@ int main( int argc, char **argv ) osg::RefMatrix* matrix = dynamic_cast(images.front()->getUserData()); -#if 0 - if (matrix) - { - osg::notify(osg::NOTICE)<<"Image has Matrix = "<<*matrix<get(), transferFunction.get()); + *itr = osgVolume::applyTransferFunction(itr->get(), transferFunction.get()); } } @@ -2263,31 +1356,9 @@ int main( int argc, char **argv ) imageSequence->play(); } - osg::ref_ptr normalmap_3d = 0; - if (createNormalMap) - { - if (images.size()==1) - { - normalmap_3d = createNormalMapTexture(images.front().get()); - } - else - { - osg::ref_ptr normalmapSequence = new osg::ImageSequence; - normalmap_3d = normalmapSequence.get(); - for(Images::iterator itr = images.begin(); - itr != images.end(); - ++itr) - { - normalmapSequence->addImage(createNormalMapTexture(itr->get())); - } - normalmapSequence->play(); - } - } - // create a model from the images. osg::ref_ptr rootNode = 0; - if (useOsgVolume) { osg::ref_ptr volume = new osgVolume::Volume; @@ -2334,38 +1405,6 @@ int main( int argc, char **argv ) rootNode = volume.get(); - - } - else - { - if (useShader) - { - rootNode = createShaderModel(shadingModel, - image_3d, normalmap_3d.get(), - (gpuTransferFunction ? transferFunction.get() : 0), - internalFormatMode, - xSize, ySize, zSize, - xMultiplier, yMultiplier, zMultiplier, - numSlices, sliceEnd, alphaFunc); - } - else - { - rootNode = createModel(shadingModel, - image_3d, normalmap_3d, - internalFormatMode, - xSize, ySize, zSize, - xMultiplier, yMultiplier, zMultiplier, - numSlices, sliceEnd, alphaFunc); - } - - if (matrix && rootNode) - { - osg::MatrixTransform* mt = new osg::MatrixTransform; - mt->setMatrix(*matrix); - mt->addChild(rootNode); - - rootNode = mt; - } } if (!outputFile.empty()) @@ -2379,12 +1418,6 @@ int main( int argc, char **argv ) image_3d->setFileName(name_no_ext + ".dds"); osgDB::writeImageFile(*image_3d, image_3d->getFileName()); } - if (normalmap_3d.valid()) - { - normalmap_3d->setFileName(name_no_ext + "_normalmap.dds"); - osgDB::writeImageFile(*normalmap_3d, normalmap_3d->getFileName()); - } - osgDB::writeNodeFile(*rootNode, outputFile); } else if (ext=="ive") diff --git a/include/osgVolume/Layer b/include/osgVolume/Layer index 2b5a8018c..8fee4f84d 100644 --- a/include/osgVolume/Layer +++ b/include/osgVolume/Layer @@ -15,6 +15,7 @@ #define OSGVOLUME_LAYER 1 #include +#include #include #include @@ -208,6 +209,12 @@ class OSGVOLUME_EXPORT CompositeLayer : public Layer Layers _layers; }; +/** Compute a 3d image that represent the normal map of the specified 3d image.*/ +extern OSGVOLUME_EXPORT osg::Image* createNormalMapTexture(osg::Image* image_3d); + +/** Create an image that has a transfer function applied specified Image.*/ +extern OSGVOLUME_EXPORT osg::Image* applyTransferFunction(osg::Image* image, osg::TransferFunction1D* transferFunction); + } #endif diff --git a/src/osgPlugins/dicom/ReaderWriterDICOM.cpp b/src/osgPlugins/dicom/ReaderWriterDICOM.cpp index 74d603529..b089a4ab8 100644 --- a/src/osgPlugins/dicom/ReaderWriterDICOM.cpp +++ b/src/osgPlugins/dicom/ReaderWriterDICOM.cpp @@ -134,12 +134,6 @@ class ReaderWriterDICOM : public osgDB::ReaderWriter if (matrix) { - - - // scale up to provide scale of complete tile - osg::Vec3d scale(osg::Vec3(result.getImage()->s(),result.getImage()->t(), result.getImage()->r())); - matrix->postMultScale(scale); - osgVolume::Locator* locator = new osgVolume::Locator(*matrix); tile->setLocator(locator); @@ -240,6 +234,8 @@ class ReaderWriterDICOM : public osgDB::ReaderWriter } image->setUserData(matrix); + + matrix.preMult(osg::Matrix::scale(double(image->s()), double(image->t()), double(image->r()))); return image; } @@ -622,6 +618,8 @@ class ReaderWriterDICOM : public osgDB::ReaderWriter (*matrix)(1,2) = fileInfo.matrix(1,2) * averageThickness; (*matrix)(2,2) = fileInfo.matrix(2,2) * averageThickness; + + image = new osg::Image; image->setUserData(matrix.get()); image->setFileName(fileName.c_str()); @@ -629,6 +627,8 @@ class ReaderWriterDICOM : public osgDB::ReaderWriter pixelFormat, dataType); + matrix->preMult(osg::Matrix::scale(double(image->s()), double(image->t()), double(image->r()))); + notice()<<"Image dimensions = "<s()<<", "<t()<<", "<r()<<" pixelFormat=0x"<getPlanes()>numPlanes || diff --git a/src/osgVolume/Layer.cpp b/src/osgVolume/Layer.cpp index 2cdec5e17..35825771f 100644 --- a/src/osgVolume/Layer.cpp +++ b/src/osgVolume/Layer.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -182,3 +183,261 @@ void CompositeLayer::clear() { _layers.clear(); } + +///////////////////////////////////////////////////////////////////////////// +// +// createNormalMapTexture +// +osg::Image* osgVolume::createNormalMapTexture(osg::Image* image_3d) +{ + osg::notify(osg::INFO)<<"Computing NormalMapTexture"<getDataType(); + + unsigned int sourcePixelIncrement = 1; + unsigned int alphaOffset = 0; + switch(image_3d->getPixelFormat()) + { + case(GL_ALPHA): + case(GL_LUMINANCE): + sourcePixelIncrement = 1; + alphaOffset = 0; + break; + case(GL_LUMINANCE_ALPHA): + sourcePixelIncrement = 2; + alphaOffset = 1; + break; + case(GL_RGB): + sourcePixelIncrement = 3; + alphaOffset = 0; + break; + case(GL_RGBA): + sourcePixelIncrement = 4; + alphaOffset = 3; + break; + default: + osg::notify(osg::NOTICE)<<"Source pixel format not support for normal map generation."< normalmap_3d = new osg::Image; + normalmap_3d->allocateImage(image_3d->s(),image_3d->t(),image_3d->r(), + GL_RGBA,GL_UNSIGNED_BYTE); + + if (osg::getCpuByteOrder()==osg::LittleEndian) alphaOffset = sourcePixelIncrement-alphaOffset-1; + + for(int r=1;rr()-1;++r) + { + for(int t=1;tt()-1;++t) + { + + if (dataType==GL_UNSIGNED_BYTE) + { + unsigned char* ptr = image_3d->data(1,t,r)+alphaOffset; + unsigned char* left = image_3d->data(0,t,r)+alphaOffset; + unsigned char* right = image_3d->data(2,t,r)+alphaOffset; + unsigned char* above = image_3d->data(1,t+1,r)+alphaOffset; + unsigned char* below = image_3d->data(1,t-1,r)+alphaOffset; + unsigned char* in = image_3d->data(1,t,r+1)+alphaOffset; + unsigned char* out = image_3d->data(1,t,r-1)+alphaOffset; + + unsigned char* destination = (unsigned char*) normalmap_3d->data(1,t,r); + + for(int s=1;ss()-1;++s) + { + + osg::Vec3 grad((float)(*left)-(float)(*right), + (float)(*below)-(float)(*above), + (float)(*out) -(float)(*in)); + + grad.normalize(); + + if (grad.x()==0.0f && grad.y()==0.0f && grad.z()==0.0f) + { + grad.set(128.0f,128.0f,128.0f); + } + else + { + grad.x() = osg::clampBetween((grad.x()+1.0f)*128.0f,0.0f,255.0f); + grad.y() = osg::clampBetween((grad.y()+1.0f)*128.0f,0.0f,255.0f); + grad.z() = osg::clampBetween((grad.z()+1.0f)*128.0f,0.0f,255.0f); + } + + *(destination++) = (unsigned char)(grad.x()); // scale and bias X. + *(destination++) = (unsigned char)(grad.y()); // scale and bias Y. + *(destination++) = (unsigned char)(grad.z()); // scale and bias Z. + + *destination++ = *ptr; + + ptr += sourcePixelIncrement; + left += sourcePixelIncrement; + right += sourcePixelIncrement; + above += sourcePixelIncrement; + below += sourcePixelIncrement; + in += sourcePixelIncrement; + out += sourcePixelIncrement; + } + } + else if (dataType==GL_SHORT) + { + short* ptr = (short*)(image_3d->data(1,t,r)+alphaOffset); + short* left = (short*)(image_3d->data(0,t,r)+alphaOffset); + short* right = (short*)(image_3d->data(2,t,r)+alphaOffset); + short* above = (short*)(image_3d->data(1,t+1,r)+alphaOffset); + short* below = (short*)(image_3d->data(1,t-1,r)+alphaOffset); + short* in = (short*)(image_3d->data(1,t,r+1)+alphaOffset); + short* out = (short*)(image_3d->data(1,t,r-1)+alphaOffset); + + unsigned char* destination = (unsigned char*) normalmap_3d->data(1,t,r); + + for(int s=1;ss()-1;++s) + { + + osg::Vec3 grad((float)(*left)-(float)(*right), + (float)(*below)-(float)(*above), + (float)(*out) -(float)(*in)); + + grad.normalize(); + + //osg::notify(osg::NOTICE)<<"normal "<data(1,t,r)+alphaOffset); + unsigned short* left = (unsigned short*)(image_3d->data(0,t,r)+alphaOffset); + unsigned short* right = (unsigned short*)(image_3d->data(2,t,r)+alphaOffset); + unsigned short* above = (unsigned short*)(image_3d->data(1,t+1,r)+alphaOffset); + unsigned short* below = (unsigned short*)(image_3d->data(1,t-1,r)+alphaOffset); + unsigned short* in = (unsigned short*)(image_3d->data(1,t,r+1)+alphaOffset); + unsigned short* out = (unsigned short*)(image_3d->data(1,t,r-1)+alphaOffset); + + unsigned char* destination = (unsigned char*) normalmap_3d->data(1,t,r); + + for(int s=1;ss()-1;++s) + { + + osg::Vec3 grad((float)(*left)-(float)(*right), + (float)(*below)-(float)(*above), + (float)(*out) -(float)(*in)); + + grad.normalize(); + + if (grad.x()==0.0f && grad.y()==0.0f && grad.z()==0.0f) + { + grad.set(128.0f,128.0f,128.0f); + } + else + { + grad.x() = osg::clampBetween((grad.x()+1.0f)*128.0f,0.0f,255.0f); + grad.y() = osg::clampBetween((grad.y()+1.0f)*128.0f,0.0f,255.0f); + grad.z() = osg::clampBetween((grad.z()+1.0f)*128.0f,0.0f,255.0f); + } + + *(destination++) = (unsigned char)(grad.x()); // scale and bias X. + *(destination++) = (unsigned char)(grad.y()); // scale and bias Y. + *(destination++) = (unsigned char)(grad.z()); // scale and bias Z. + + *destination++ = *ptr/256; + + ptr += sourcePixelIncrement; + left += sourcePixelIncrement; + right += sourcePixelIncrement; + above += sourcePixelIncrement; + below += sourcePixelIncrement; + in += sourcePixelIncrement; + out += sourcePixelIncrement; + } + } + } + } + + + osg::notify(osg::INFO)<<"Created NormalMapTexture"<getInterpolatedValue(l); + //std::cout<<"l = "<allocateImage(image->s(),image->t(), image->r(), GL_RGBA, GL_UNSIGNED_BYTE); + + ApplyTransferFunctionOperator op(transferFunction, output_image->data()); + osg::readImage(image,op); + + return output_image; +} diff --git a/src/osgVolume/ShaderTechnique.cpp b/src/osgVolume/ShaderTechnique.cpp index fc3ebc99d..a2d1564a2 100644 --- a/src/osgVolume/ShaderTechnique.cpp +++ b/src/osgVolume/ShaderTechnique.cpp @@ -112,15 +112,12 @@ void ShaderTechnique::init() { matrix = masterLocator->getTransform(); } - + + osg::notify(osg::NOTICE)<<"Matrix = "<