Show
Ignore:
Timestamp:
04/11/06 21:56:53 (9 years ago)
Author:
robert
Message:

Added support for LOD's with transistion between quads and point rendering.

Files:
1 modified

Legend:

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

    r5083 r5084  
    3131{ 
    3232public: 
     33 
     34        PrecipitationGeometry() 
     35        { 
     36            setSupportsDisplayList(false); 
     37        } 
     38 
    3339        virtual bool supports(const osg::PrimitiveFunctor&) const { return false; } 
    3440        virtual void accept(osg::PrimitiveFunctor&) const {} 
    3541        virtual bool supports(const osg::PrimitiveIndexFunctor&) const { return false; } 
    3642        virtual void accept(osg::PrimitiveIndexFunctor&) const {} 
    37          
     43 
     44        void setInternalGeometry(osg::Geometry* geometry) { _internalGeometry = geometry; } 
     45         
     46        osg::Geometry* getInternalGeometry() { return _internalGeometry.get(); } 
     47 
     48         
     49        virtual void compileGLObjects(osg::State& state) const 
     50        { 
     51            if (!_internalGeometry) return; 
     52 
     53            static bool s_interalGeometryCompiled = false; 
     54            if (!s_interalGeometryCompiled) 
     55            { 
     56                _internalGeometry->compileGLObjects(state); 
     57                s_interalGeometryCompiled = true; 
     58            } 
     59        } 
     60 
     61        virtual void drawImplementation(osg::State& state) const 
     62        { 
     63            if (!_internalGeometry) return; 
     64             
     65            _internalGeometry->draw(state); 
     66        } 
     67 
    3868        virtual osg::BoundingBox computeBound() const 
    3969        { 
    4070            return osg::BoundingBox(); 
    4171        } 
     72         
     73protected:         
     74 
     75        osg::ref_ptr<osg::Geometry> _internalGeometry; 
    4276 
    4377}; 
     
    132166        if (i>0) mipmapData.push_back(totalSize); 
    133167        totalSize += s*s*4; 
    134         std::cout<<" i= "<<i<<" s="<<s<<" p="<<totalSize<<std::endl; 
    135     } 
    136  
    137     std::cout<<"Total size ="<<totalSize<<std::endl; 
     168    } 
    138169 
    139170    unsigned char* ptr = new unsigned char[totalSize]; 
     
    247278 
    248279 
    249 osg::Node* createRainEffect(const osg::BoundingBox& bb, const osg::Vec3& velocity, unsigned int numParticles, bool useShaders) 
    250 { 
    251     osg::Geode* geode = new osg::Geode; 
    252  
    253     osg::Geometry* quad_geometry = 0; 
    254     osg::Geometry* line_geometry = 0; 
    255     osg::Geometry* point_geometry = 0; 
    256      
    257 #if 0 
    258     quad_geometry = new PrecipitationGeometry; 
    259     quad_geometry->setUseVertexBufferObjects(true); 
    260     quad_geometry->setInitialBound(bb); 
    261     geode->addDrawable(quad_geometry); 
    262  
    263     osg::StateSet* quad_stateset = quad_geometry->getOrCreateStateSet(); 
    264     { 
     280static osg::ref_ptr<osg::Geometry> quad_geometry = 0; 
     281static osg::ref_ptr<osg::StateSet> quad_stateset = 0; 
     282 
     283static osg::ref_ptr<osg::Geometry> line_geometry = 0; 
     284static osg::ref_ptr<osg::StateSet> line_stateset = 0; 
     285 
     286static osg::ref_ptr<osg::Geometry> point_geometry = 0; 
     287static osg::ref_ptr<osg::StateSet> point_stateset = 0; 
     288 
     289void setUpGeometries(unsigned int numParticles) 
     290{ 
     291    { 
     292        quad_geometry = new osg::Geometry; 
     293        quad_geometry->setUseVertexBufferObjects(true); 
     294 
     295        quad_stateset = new osg::StateSet; 
    265296        osg::Program* program = new osg::Program; 
    266297        quad_stateset->setAttribute(program); 
     
    270301        program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile("rain.frag"))); 
    271302    } 
    272 #endif 
    273  
    274 #if 0    
    275     line_geometry = new PrecipitationGeometry; 
    276     line_geometry->setUseVertexBufferObjects(true); 
    277     line_geometry->setInitialBound(bb); 
    278     geode->addDrawable(line_geometry); 
    279  
    280     osg::StateSet* line_stateset = line_geometry->getOrCreateStateSet(); 
    281     { 
     303 
     304 
     305    { 
     306        line_geometry = new osg::Geometry; 
     307        line_geometry->setUseVertexBufferObjects(true); 
     308 
     309        line_stateset = new osg::StateSet; 
     310 
    282311        osg::Program* program = new osg::Program; 
    283312        line_stateset->setAttribute(program); 
     
    287316        program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile("rain.frag"))); 
    288317    } 
    289 #endif 
    290  
    291  
    292 #if 1     
    293     point_geometry = new PrecipitationGeometry; 
    294     point_geometry->setUseVertexBufferObjects(true); 
    295     point_geometry->setInitialBound(bb); 
    296     geode->addDrawable(point_geometry); 
    297  
    298     osg::StateSet* point_stateset = point_geometry->getOrCreateStateSet(); 
    299     { 
     318 
     319 
     320    { 
     321        point_geometry = new osg::Geometry; 
     322        point_geometry->setUseVertexBufferObjects(true); 
     323 
     324        point_stateset = new osg::StateSet; 
     325 
    300326        osg::Program* program = new osg::Program; 
    301327        point_stateset->setAttribute(program); 
     
    312338 
    313339    } 
    314 #endif 
    315  
    316  
    317     createGeometry(numParticles, quad_geometry, line_geometry, point_geometry); 
     340 
     341    createGeometry(numParticles, quad_geometry.get(), line_geometry.get(), point_geometry.get()); 
     342 
     343} 
     344 
     345 
     346osg::Node* createRainEffect(const osg::BoundingBox& bb, const osg::Vec3& velocity) 
     347{ 
     348    osg::LOD* lod = new osg::LOD; 
     349     
     350    float nearDistance = 100.0; 
     351    float farDistance = 200.0; 
     352     
     353    // high res LOD. 
     354    { 
     355        osg::Geode* highres_geode = new osg::Geode; 
     356 
     357        PrecipitationGeometry* geometry = new PrecipitationGeometry; 
     358 
     359        highres_geode->addDrawable(geometry); 
     360 
     361        geometry->setInitialBound(bb); 
     362        geometry->setInternalGeometry(quad_geometry.get()); 
     363        geometry->setStateSet(quad_stateset.get()); 
     364         
     365        lod->addChild( highres_geode, 0.0f, nearDistance ); 
     366    } 
     367     
     368    // low res LOD 
     369    { 
     370        osg::Geode* lowres_geode = new osg::Geode; 
     371 
     372        PrecipitationGeometry* geometry = new PrecipitationGeometry; 
     373 
     374        lowres_geode->addDrawable(geometry); 
     375 
     376        geometry->setInitialBound(bb); 
     377        geometry->setInternalGeometry(point_geometry.get()); 
     378        geometry->setStateSet(point_stateset.get()); 
     379         
     380        lod->addChild( lowres_geode, nearDistance, farDistance ); 
     381    } 
    318382 
    319383 
    320384    // set up state. 
    321     osg::StateSet* stateset = geode->getOrCreateStateSet(); 
     385    osg::StateSet* stateset = lod->getOrCreateStateSet(); 
    322386    { 
    323387        // time taken to get from start to the end of cycle 
     
    332396        // set up uniforms 
    333397        osg::Uniform* position_Uniform = new osg::Uniform("position",position); 
    334         osg::Uniform* dv_i_Uniform = new osg::Uniform("dv_i",dv_i); 
    335         osg::Uniform* dv_j_Uniform = new osg::Uniform("dv_j",dv_j); 
    336         osg::Uniform* dv_k_Uniform = new osg::Uniform("dv_k",dv_k); 
    337          
    338         osg::Uniform* inversePeriodUniform = new osg::Uniform("inversePeriod",1.0f/period); 
    339         osg::Uniform* startTime = new osg::Uniform("startTime",0.0f); 
     398        static osg::Uniform* dv_i_Uniform = new osg::Uniform("dv_i",dv_i); 
     399        static osg::Uniform* dv_j_Uniform = new osg::Uniform("dv_j",dv_j); 
     400        static osg::Uniform* dv_k_Uniform = new osg::Uniform("dv_k",dv_k); 
     401         
     402        static osg::Uniform* inversePeriodUniform = new osg::Uniform("inversePeriod",1.0f/period); 
     403        static osg::Uniform* startTime = new osg::Uniform("startTime",0.0f); 
    340404 
    341405 
     
    351415        stateset->addUniform(new osg::Uniform("particleColour", osg::Vec4(0.6,0.6,0.6,1.0))); 
    352416         
    353         osg::Uniform* baseTextureSampler = new osg::Uniform("baseTexture",0); 
     417        static osg::Uniform* baseTextureSampler = new osg::Uniform("baseTexture",0); 
    354418        stateset->addUniform(baseTextureSampler); 
    355419         
    356 //        osg::Texture2D* texture = new osg::Texture2D(osgDB::readImageFile("Images/particle.rgb")); 
    357         osg::Texture2D* texture = new osg::Texture2D(createSpotLightImage(osg::Vec4(1.0f,1.0f,1.0f,1.0f),osg::Vec4(1.0f,1.0f,1.0f,0.0f),32,1.0)); 
    358 //        texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); 
     420        static osg::Texture2D* texture = new osg::Texture2D(createSpotLightImage(osg::Vec4(1.0f,1.0f,1.0f,1.0f),osg::Vec4(1.0f,1.0f,1.0f,0.0f),32,1.0)); 
    359421        stateset->setTextureAttribute(0, texture); 
    360422 
     
    364426        osg::Uniform* previousModelViewUniform = new osg::Uniform("previousModelViewMatrix",osg::Matrix()); 
    365427        stateset->addUniform(previousModelViewUniform); 
    366         geode->setCullCallback(new CullCallback(previousModelViewUniform)); 
    367  
    368     } 
    369      
    370  
    371  
    372  
    373  
    374     return geode; 
    375 } 
    376 /* 
    377 osg::Node* createSnowEffect(const osg::BoundingBox& bb, const osg::Vec3& velocity, unsigned int numParticles, bool useShaders) 
    378 { 
    379     osg::Geometry* geometry = new osg::Geometry; 
    380  
    381     osg::StateSet* stateset = geometry->getOrCreateStateSet(); 
    382  
    383     // set up geometry. 
    384     { 
    385      
    386         // per vertex properties 
    387         osg::Vec3Array* vertices = new osg::Vec3Array(numParticles); 
    388         osg::FloatArray* offsets = new osg::FloatArray(numParticles); 
    389          
    390         for(unsigned int i=0; i< numParticles; ++i) 
    391         { 
    392             (*vertices)[i].set(random(bb.xMin(), bb.xMax()), random(bb.yMin(),bb.yMax()), bb.zMax()); 
    393             (*offsets)[i] = random(0.0, 1.0); 
    394         } 
    395  
    396         geometry->setVertexArray(vertices); 
    397         geometry->setTexCoordArray(0, offsets); 
    398  
    399         // overall attributes 
    400         osg::Vec4Array* colours = new osg::Vec4Array(1); 
    401         (*colours)[0].set(1.0f,1.0f,1.0f,1.0f); 
    402         geometry->setColorArray(colours); 
    403         geometry->setColorBinding(osg::Geometry::BIND_OVERALL); 
    404          
    405         geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, numParticles)); 
    406     } 
    407  
    408     // set up state. 
    409     { 
    410         // time taken to get from start to the end of cycle 
    411         float period = fabs((bb.zMax()-bb.zMin()) / velocity.z()); 
    412  
    413         // distance between start point and end of cyclce 
    414         osg::Vec3 delta = velocity * period; 
    415  
    416         // set up uniforms 
    417         osg::Uniform* deltaUniform = new osg::Uniform("delta",delta); 
    418         osg::Uniform* inversePeriodUniform = new osg::Uniform("inversePeriod",1.0f/period); 
    419         osg::Uniform* startTime = new osg::Uniform("startTime",0.0f); 
    420  
    421         osg::Program* program = new osg::Program; 
    422         stateset->setAttribute(program); 
    423  
    424         // get shaders from source 
    425         program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, osgDB::findDataFile("snow.vert"))); 
    426         program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile("snow.frag"))); 
    427  
    428         stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); 
    429          
    430         stateset->addUniform(deltaUniform); 
    431         stateset->addUniform(inversePeriodUniform); 
    432         stateset->addUniform(startTime); 
    433     } 
    434      
    435     geometry->setInitialBound(bb); 
    436  
    437  
    438     osg::Geode* geode = new osg::Geode; 
    439     geode->addDrawable(geometry); 
    440  
    441     return geode; 
    442 } 
    443 */ 
    444 osg::Node* createModel(osg::Node* loadedModel, bool useShaders) 
     428        lod->setCullCallback(new CullCallback(previousModelViewUniform)); 
     429 
     430    } 
     431 
     432 
     433    return lod; 
     434} 
     435 
     436osg::Node* createCellRainEffect(const osg::BoundingBox& bb, const osg::Vec3& velocity, unsigned int numParticles) 
     437{ 
     438     
     439    unsigned int numX = 50; 
     440    unsigned int numY = 50; 
     441    unsigned int numCells = numX*numY; 
     442    unsigned int numParticlesPerCell = numParticles/numCells; 
     443 
     444    setUpGeometries(numParticlesPerCell); 
     445     
     446    std::cout<<"Effect total number of particles = "<<numParticles<<std::endl; 
     447    std::cout<<"Number of cells = "<<numCells<<std::endl; 
     448    std::cout<<"Number of particles per cell = "<<numParticlesPerCell<<std::endl; 
     449    std::cout<<"Cell width = "<<(bb.xMax()-bb.xMin())/(float)(numX)<<std::endl; 
     450    std::cout<<"Cell length = "<<(bb.yMax()-bb.yMin())/(float)(numY)<<std::endl; 
     451    std::cout<<"Cell height = "<<(bb.zMax()-bb.zMin())<<std::endl; 
     452 
     453    osg::Group* group = new osg::Group; 
     454    for(unsigned int i=0; i<numX; ++i) 
     455    { 
     456        for(unsigned int j=0; j<numX; ++j) 
     457        { 
     458            osg::BoundingBox bbLocal(bb.xMin() + ((bb.xMax()-bb.xMin())*(float)i)/(float)(numX), 
     459                                     bb.yMin() + ((bb.yMax()-bb.yMin())*(float)j)/(float)(numY), 
     460                                     bb.zMin(), 
     461                                     bb.xMin() + ((bb.xMax()-bb.xMin())*(float)(i+1))/(float)(numX), 
     462                                     bb.yMin() + ((bb.yMax()-bb.yMin())*(float)(j+1))/(float)(numY), 
     463                                     bb.zMax()); 
     464 
     465            group->addChild(createRainEffect(bbLocal, velocity)); 
     466        }         
     467    } 
     468    return group; 
     469} 
     470 
     471osg::Node* createModel(osg::Node* loadedModel, bool /*useShaders*/) 
    445472{ 
    446473    osg::Group* group = new osg::Group; 
     
    448475    osg::BoundingBox bb(0.0, 0.0, 0.0, 100.0, 100.0, 100.0); 
    449476    osg::Vec3 velocity(0.0,2.0,-5.0); 
    450     unsigned int numParticles = 150000; 
     477    unsigned int numParticles = 10000000; 
    451478     
    452479    if (loadedModel) 
     
    456483        osg::BoundingSphere bs = loadedModel->getBound(); 
    457484 
    458         bb.set( -100, -100, 0, +100, +100, 10); 
     485        bb.set( -500, -500, 0, +500, +500, 10); 
    459486         
    460487        osg::StateSet* stateset = loadedModel->getOrCreateStateSet(); 
     
    480507                 
    481508    } 
    482  
    483     group->addChild(createRainEffect(bb, velocity, numParticles, useShaders)); 
    484  
     509     
     510#if 0 
     511    setUpGeometries(numParticles); 
     512    group->addChild(createRainEffect(bb, velocity)); 
     513#else 
     514    group->addChild(createCellRainEffect(bb, velocity, numParticles)); 
     515#endif 
    485516    return group;     
    486517} 
     
    552583    // optimize the scene graph, remove rendundent nodes and state etc. 
    553584    osgUtil::Optimizer optimizer; 
    554     optimizer.optimize(loadedModel.get()); 
     585    // optimizer.optimize(loadedModel.get()); 
    555586 
    556587    // set the scene to render