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); }