From 6c8ef3b7df25d5ea9f9282f45fdabb2dcae72742 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 20 Nov 2002 07:46:25 +0000 Subject: [PATCH] Fixed the texture apply method which was broken yesterday, the new code wasn't checking for the validity of _image before doing checks on it. This breaks when render to texture is used as there is no image to check against... Added osgshadowtexture demo source. Demos still in development, so don't expect any shadows yet... --- Make/debugtests.bat | 4 + Make/makedefs | 2 +- Make/makedirdefs | 1 + Make/osgtests.bat | 3 + src/Demos/osganimate/osganimate.cpp | 26 +- src/Demos/osgshadowtexture/Makefile | 15 + src/Demos/osgshadowtexture/Makefile.inst | 11 + .../osgshadowtexture/osgshadowtexture.cpp | 428 ++++++++++++++++++ src/osg/Texture1D.cpp | 2 +- src/osg/Texture2D.cpp | 2 +- src/osg/Texture3D.cpp | 2 +- 11 files changed, 483 insertions(+), 13 deletions(-) create mode 100644 src/Demos/osgshadowtexture/Makefile create mode 100644 src/Demos/osgshadowtexture/Makefile.inst create mode 100644 src/Demos/osgshadowtexture/osgshadowtexture.cpp diff --git a/Make/debugtests.bat b/Make/debugtests.bat index 68997063c..089a22523 100755 --- a/Make/debugtests.bat +++ b/Make/debugtests.bat @@ -54,6 +54,10 @@ echo osgprerender dumptruck.osg osgprerender dumptruck.osg more memleaks.log +echo osgshadowtexture cessna.osg +osgshadowtexture cessna.osg +more memleaks.log + echo osgparticle osgparticle more memleaks.log diff --git a/Make/makedefs b/Make/makedefs index 4fdd69522..db385ab11 100644 --- a/Make/makedefs +++ b/Make/makedefs @@ -308,7 +308,7 @@ ifeq ($(OS),Darwin) DEMOS_DIRS = osgbillboard osgcallback osgclip \ osgcluster osgconv osgcopy osgcube osggeometry \ osghangglide osgimpostor osgmultitexture osgoccluder \ - osgparticle osglightpoint osgprerender osgreflect osgscribe osgstereoimage \ + osgparticle osglightpoint osgprerender osgshadowtexture osgreflect osgscribe osgstereoimage \ osgtexture1D osgtexture2D osgtexture3D osgversion osgviews sgv \ osgshape osganimate osgteapot endif diff --git a/Make/makedirdefs b/Make/makedirdefs index c0c507252..0474c6053 100644 --- a/Make/makedirdefs +++ b/Make/makedirdefs @@ -92,6 +92,7 @@ DEMOS_DIRS = \ osgoccluder\ osgparticle\ osgprerender\ + osgshadowtexture\ osgreflect\ osgscribe\ osgsequence\ diff --git a/Make/osgtests.bat b/Make/osgtests.bat index 815fc5643..7f083b115 100755 --- a/Make/osgtests.bat +++ b/Make/osgtests.bat @@ -37,6 +37,9 @@ osggeometry echo osgprerender dumptruck.osg osgprerender dumptruck.osg +echo osgshadowtexture cessna.osg +osgshadowtexture cessna.osg + echo osgparticle osgparticle diff --git a/src/Demos/osganimate/osganimate.cpp b/src/Demos/osganimate/osganimate.cpp index b3ab2f20c..73b23891e 100644 --- a/src/Demos/osganimate/osganimate.cpp +++ b/src/Demos/osganimate/osganimate.cpp @@ -120,16 +120,14 @@ osg::Node* createBase(const osg::Vec3& center,float radius) return geode; } -osg::Node* createModel() +osg::Node* createMovingModel(const osg::Vec3& center, float radius) { - osg::Vec3 center(0.0f,0.0f,0.0f); - float radius = 100.0f; - - osg::Group* root = osgNew osg::Group; - float animationLength = 10.0f; + osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength); + osg::Group* model = new osg::Group; + osg::Node* glider = osgDB::readNodeFile("glider.osg"); if (glider) { @@ -148,7 +146,7 @@ osg::Node* createModel() xform->setAppCallback(new osg::PositionAttitudeTransform::AnimationPathCallback(animationPath,0.0,1.0)); xform->addChild(positioned); - root->addChild(xform); + model->addChild(xform); } osg::Node* cessna = osgDB::readNodeFile("cessna.osg"); @@ -169,10 +167,20 @@ osg::Node* createModel() xform->setAppCallback(new osg::MatrixTransform::AnimationPathCallback(animationPath,0.0f,2.0)); xform->addChild(positioned); - root->addChild(xform); + model->addChild(xform); } + + return model; +} -// osg::Node* truck = osgDB::readNodeFile("dumptruck.osg"); +osg::Node* createModel() +{ + osg::Vec3 center(0.0f,0.0f,0.0f); + float radius = 100.0f; + + osg::Group* root = osgNew osg::Group; + + root->addChild(createMovingModel(center,radius*0.8f)); root->addChild(createBase(center-osg::Vec3(0.0f,0.0f,radius*0.5),radius)); diff --git a/src/Demos/osgshadowtexture/Makefile b/src/Demos/osgshadowtexture/Makefile new file mode 100644 index 000000000..28d711c63 --- /dev/null +++ b/src/Demos/osgshadowtexture/Makefile @@ -0,0 +1,15 @@ +TOPDIR = ../../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgshadowtexture.cpp\ + +LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +INSTFILES = \ + $(CXXFILES)\ + Makefile.inst=Makefile + +EXEC = osgshadowtexture + +include $(TOPDIR)/Make/makerules diff --git a/src/Demos/osgshadowtexture/Makefile.inst b/src/Demos/osgshadowtexture/Makefile.inst new file mode 100644 index 000000000..c781199fd --- /dev/null +++ b/src/Demos/osgshadowtexture/Makefile.inst @@ -0,0 +1,11 @@ +TOPDIR = ../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgshadowtexture.cpp\ + +LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +EXEC = osgshadowtexture + +include $(TOPDIR)/Make/makerules diff --git a/src/Demos/osgshadowtexture/osgshadowtexture.cpp b/src/Demos/osgshadowtexture/osgshadowtexture.cpp new file mode 100644 index 000000000..03c9eea48 --- /dev/null +++ b/src/Demos/osgshadowtexture/osgshadowtexture.cpp @@ -0,0 +1,428 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + + +#include +#include + + +class MyCullCallback : public osg::NodeCallback +{ + public: + + MyCullCallback(osg::Node* subgraph,osg::Texture2D* texture): + _subgraph(subgraph), + _texture(texture) {} + + MyCullCallback(osg::Node* subgraph,osg::Image* image): + _subgraph(subgraph), + _image(image) {} + + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + { + + osgUtil::CullVisitor* cullVisitor = dynamic_cast(nv); + if (cullVisitor && (_texture.valid()|| _image.valid()) && _subgraph.valid()) + { + doPreRender(*node,*cullVisitor); + + // must traverse the subgraph + traverse(node,nv); + + } + else + { + // must traverse the subgraph + traverse(node,nv); + } + } + + void doPreRender(osg::Node& node, osgUtil::CullVisitor& cv); + + osg::ref_ptr _subgraph; + osg::ref_ptr _texture; + osg::ref_ptr _image; + + +}; + +void MyCullCallback::doPreRender(osg::Node&, osgUtil::CullVisitor& cv) +{ + + const osg::BoundingSphere& bs = _subgraph->getBound(); + if (!bs.valid()) + { + osg::notify(osg::WARN) << "bb invalid"<<_subgraph.get()< rtts = osgNew osgUtil::RenderToTextureStage; + + // set up lighting. + // currently ignore lights in the scene graph itself.. + // will do later. + osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->_stage; + + // set up the background color and clear mask. + rtts->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,0.0f)); + rtts->setClearMask(previous_stage->getClearMask()); + + // set up to charge the same RenderStageLighting is the parent previous stage. + rtts->setRenderStageLighting(previous_stage->getRenderStageLighting()); + + + // record the render bin, to be restored after creation + // of the render to text + osgUtil::RenderBin* previousRenderBin = cv.getCurrentRenderBin(); + + // set the current renderbin to be the newly created stage. + cv.setCurrentRenderBin(rtts.get()); + + + float znear = 1.0f*bs.radius(); + float zfar = 3.0f*bs.radius(); + + // 2:1 aspect ratio as per flag geomtry below. + float top = 0.25f*znear; + float right = 0.5f*znear; + + znear *= 0.9f; + zfar *= 1.1f; + + // set up projection. + osg::Matrix* projection = osgNew osg::Matrix; + projection->makeFrustum(-right,right,-top,top,znear,zfar); + + cv.pushProjectionMatrix(projection); + + osg::Matrix* matrix = new osg::Matrix; + matrix->makeLookAt(bs.center()+osg::Vec3(0.0f,2.0f,0.0f)*bs.radius(),bs.center(),osg::Vec3(0.0f,0.0f,1.0f)); + + cv.pushModelViewMatrix(matrix); + + osg::ref_ptr dummyState = osgNew osg::StateSet; + + cv.pushStateSet(dummyState.get()); + + { + + // traverse the subgraph + _subgraph->accept(cv); + + } + + cv.popStateSet(); + + // restore the previous model view matrix. + cv.popModelViewMatrix(); + + // restore the previous model view matrix. + cv.popProjectionMatrix(); + + // restore the previous renderbin. + cv.setCurrentRenderBin(previousRenderBin); + + if (rtts->_renderGraphList.size()==0 && rtts->_bins.size()==0) + { + // getting to this point means that all the subgraph has been + // culled by small feature culling or is beyond LOD ranges. + return; + } + + + + int height = 256; + int width = 512; + + + const osg::Viewport& viewport = *cv.getViewport(); + + // offset the impostor viewport from the center of the main window + // viewport as often the edges of the viewport might be obscured by + // other windows, which can cause image/reading writing problems. + int center_x = viewport.x()+viewport.width()/2; + int center_y = viewport.y()+viewport.height()/2; + + osg::Viewport* new_viewport = new osg::Viewport; + new_viewport->setViewport(center_x-width/2,center_y-height/2,width,height); + rtts->setViewport(new_viewport); + + dummyState->setAttribute(new_viewport); + + // and the render to texture stage to the current stages + // dependancy list. + cv.getCurrentRenderBin()->_stage->addToDependencyList(rtts.get()); + + // if one exist attach texture to the RenderToTextureStage. + if (_texture.valid()) rtts->setTexture(_texture.get()); + + // if one exist attach image to the RenderToTextureStage. + if (_image.valid()) rtts->setImage(_image.get()); + +} + + + + + + +osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime) +{ + // set up the animation path + osg::AnimationPath* animationPath = new osg::AnimationPath; + animationPath->setLoopMode(osg::AnimationPath::LOOP); + + int numSamples = 40; + float yaw = 0.0f; + float yaw_delta = 2.0f*osg::PI/((float)numSamples-1.0f); + float roll = osg::inDegrees(30.0f); + + double time=0.0f; + double time_delta = looptime/(double)numSamples; + for(int i=0;iinsert(time,osg::AnimationPath::ControlPoint(position,rotation)); + + yaw += yaw_delta; + time += time_delta; + + } + return animationPath; +} + +osg::Node* createBase(const osg::Vec3& center,float radius) +{ + + + + int numTilesX = 10; + int numTilesY = 10; + + float width = 2*radius; + float height = 2*radius; + + osg::Vec3 v000(center - osg::Vec3(width*0.5f,height*0.5f,0.0f)); + osg::Vec3 dx(osg::Vec3(width/((float)numTilesX),0.0,0.0f)); + osg::Vec3 dy(osg::Vec3(0.0f,height/((float)numTilesY),0.0f)); + + // fill in vertices for grid, note numTilesX+1 * numTilesY+1... + osg::Vec3Array* coords = osgNew osg::Vec3Array; + int iy; + for(iy=0;iy<=numTilesY;++iy) + { + for(int ix=0;ix<=numTilesX;++ix) + { + coords->push_back(v000+dx*(float)ix+dy*(float)iy); + } + } + + //Just two colours - black and white. + osg::Vec4Array* colors = osgNew osg::Vec4Array; + colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); // white + colors->push_back(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); // black + int numColors=colors->size(); + + + int numIndicesPerRow=numTilesX+1; + osg::UByteArray* coordIndices = osgNew osg::UByteArray; // assumes we are using less than 256 points... + osg::UByteArray* colorIndices = osgNew osg::UByteArray; + for(iy=0;iypush_back(ix +(iy+1)*numIndicesPerRow); + coordIndices->push_back(ix +iy*numIndicesPerRow); + coordIndices->push_back((ix+1)+iy*numIndicesPerRow); + coordIndices->push_back((ix+1)+(iy+1)*numIndicesPerRow); + + // one color per quad + colorIndices->push_back((ix+iy)%numColors); + } + } + + + // set up a single normal + osg::Vec3Array* normals = osgNew osg::Vec3Array; + normals->push_back(osg::Vec3(0.0f,0.0f,1.0f)); + + + osg::Geometry* geom = osgNew osg::Geometry; + geom->setVertexArray(coords); + geom->setVertexIndices(coordIndices); + + geom->setColorArray(colors); + geom->setColorIndices(colorIndices); + geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE); + + geom->setNormalArray(normals); + geom->setNormalBinding(osg::Geometry::BIND_OVERALL); + + geom->addPrimitiveSet(osgNew osg::DrawArrays(osg::PrimitiveSet::QUADS,0,coordIndices->size())); + + osg::Geode* geode = osgNew osg::Geode; + geode->addDrawable(geom); + + osg::Group* group = osgNew osg::Group; + group->addChild(geode); + + return group; +} + +osg::Node* createMovingModel(const osg::Vec3& center, float radius) +{ + float animationLength = 10.0f; + + osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength); + + osg::Group* model = new osg::Group; + + osg::Node* glider = osgDB::readNodeFile("glider.osg"); + if (glider) + { + const osg::BoundingSphere& bs = glider->getBound(); + + float size = radius/bs.radius()*0.3f; + osg::MatrixTransform* positioned = osgNew osg::MatrixTransform; + positioned->setDataVariance(osg::Object::STATIC); + positioned->setMatrix(osg::Matrix::translate(-bs.center())* + osg::Matrix::scale(size,size,size)* + osg::Matrix::rotate(osg::inDegrees(-90.0f),0.0f,0.0f,1.0f)); + + positioned->addChild(glider); + + osg::PositionAttitudeTransform* xform = osgNew osg::PositionAttitudeTransform; + xform->setAppCallback(new osg::PositionAttitudeTransform::AnimationPathCallback(animationPath,0.0,1.0)); + xform->addChild(positioned); + + model->addChild(xform); + } + + osg::Node* cessna = osgDB::readNodeFile("cessna.osg"); + if (cessna) + { + const osg::BoundingSphere& bs = cessna->getBound(); + + float size = radius/bs.radius()*0.3f; + osg::MatrixTransform* positioned = osgNew osg::MatrixTransform; + positioned->setDataVariance(osg::Object::STATIC); + positioned->setMatrix(osg::Matrix::translate(-bs.center())* + osg::Matrix::scale(size,size,size)* + osg::Matrix::rotate(osg::inDegrees(180.0f),0.0f,0.0f,1.0f)); + + positioned->addChild(cessna); + + osg::MatrixTransform* xform = osgNew osg::MatrixTransform; + xform->setAppCallback(new osg::MatrixTransform::AnimationPathCallback(animationPath,0.0f,2.0)); + xform->addChild(positioned); + + model->addChild(xform); + } + + return model; +} + +osg::Node* createModel() +{ + osg::Vec3 center(0.0f,0.0f,0.0f); + float radius = 100.0f; + + osg::Group* root = osgNew osg::Group; + + // the occluder subgraph + osg::Node* occluder = createMovingModel(center,radius*0.8f); + + // the occludee subgraph + osg::Node* occludee = createBase(center-osg::Vec3(0.0f,0.0f,radius*0.5),radius); + + // now add a state with a texture for the shadow + osg::Texture2D* texture = new osg::Texture2D; + texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); + texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); + + osg::StateSet* stateset = occludee->getOrCreateStateSet(); +// stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); + occludee->setCullCallback(new MyCullCallback(occluder,texture)); + + root->addChild(occluder); + root->addChild(occludee); + + + return root; +} + + +int main( int argc, char **argv ) +{ + + // initialize the GLUT + glutInit( &argc, argv ); + + // create the commandline args. + std::vector commandLine; + for(int i=1;isetMatrix(osg::Matrix::rotate(osg::inDegrees(30.0f),1.0f,0.0f,0.0f)); + rootnode->addChild(model); + + // run optimization over the scene graph + osgUtil::Optimizer optimzer; + optimzer.optimize(rootnode); + + // add a viewport to the viewer and attach the scene graph. + viewer.addViewport( rootnode ); + + // register trackball, flight and drive. + viewer.registerCameraManipulator(new osgGA::TrackballManipulator); + viewer.registerCameraManipulator(new osgGA::FlightManipulator); + viewer.registerCameraManipulator(new osgGA::DriveManipulator); + + + // open the viewer window. + viewer.open(); + + // fire up the event loop. + viewer.run(); + + return 0; +} diff --git a/src/osg/Texture1D.cpp b/src/osg/Texture1D.cpp index 4ea39d3f0..f385bca3b 100644 --- a/src/osg/Texture1D.cpp +++ b/src/osg/Texture1D.cpp @@ -91,7 +91,7 @@ void Texture1D::apply(State& state) const { _subloadCallback->subload(*this,state); } - else if(getModifiedTag(contextID) != _image->getModifiedTag()) + else if (_image.valid() && getModifiedTag(contextID) != _image->getModifiedTag()) { applyTexImage1D(GL_TEXTURE_1D,_image.get(),state, _textureWidth, _numMimpmapLevels); } diff --git a/src/osg/Texture2D.cpp b/src/osg/Texture2D.cpp index 2809a2259..840b78423 100644 --- a/src/osg/Texture2D.cpp +++ b/src/osg/Texture2D.cpp @@ -94,7 +94,7 @@ void Texture2D::apply(State& state) const { _subloadCallback->subload(*this,state); } - else if(getModifiedTag(contextID) != _image->getModifiedTag()) + else if (_image.valid() && getModifiedTag(contextID) != _image->getModifiedTag()) { applyTexImage2D(GL_TEXTURE_2D,_image.get(),state, _textureWidth, _textureHeight, _numMimpmapLevels); diff --git a/src/osg/Texture3D.cpp b/src/osg/Texture3D.cpp index 764b0eb48..eb302fcea 100644 --- a/src/osg/Texture3D.cpp +++ b/src/osg/Texture3D.cpp @@ -108,7 +108,7 @@ void Texture3D::apply(State& state) const { _subloadCallback->subload(*this,state); } - else if(getModifiedTag(contextID) != _image->getModifiedTag()) + else if (_image.get() && getModifiedTag(contextID) != _image->getModifiedTag()) { applyTexImage3D(GL_TEXTURE_3D,_image.get(),state, _textureWidth, _textureHeight, _textureDepth,_numMimpmapLevels); }