#include <osgViewer/Viewer>#include <osgViewer/ViewerEventHandlers>#include <osg/Node>#include <osg/Group>#include <osg/Geode>#include <osg/Camera>#include <osg/ShapeDrawable>#include <osg/ComputeBoundsVisitor>#include <osg/BoundingBox>#include <osg/BoundingSphere>#include <osg/AnimationPath>#include <osgDB/ReadFile>#include <osgDB/WriteFile>#include <osgShadow/ShadowedScene>#include <osgShadow/ShadowVolume>#include <osgShadow/ShadowTexture>#include <osgShadow/ShadowMap>#include <osgShadow/SoftShadowMap>#include <osgShadow/ParallelSplitShadowMap>#include <osgShadow/MinimalShadowMap>#include <osgShadow/StandardShadowMap>#include <osgShadow/SoftShadowMap>#include <osgShadow/ViewDependentShadowTechnique>#include <osgUtil/Optimizer>#include <osgUtil/SmoothingVisitor>#include <osg/AnimationPath>#include <iostream>
//标识阴影接收对象 const int ReceivesShadowTraversalMask=0x1; //标识阴影投影对象 const int CastsShadowTraversalMask=0x2;
//地面
osg::ref_ptr<osg::Node> DrawGround(float a1,float b1,float c11,float a2,float b2,float c2,float a3,float b3,float c3,float a4,float b4,float c4){osg::ref_ptr<osg::Node> node;osg::ref_ptr<osg::Image> image1=osgDB::readImageFile("C:\\Texture\\texture\\ground_stole.bmp");if(!image1){std::cout <<" No image data loaded,DrawGround" << std::endl;system("pause");}node=createQuad(a1,b1,c11,a2,b2, c2, a3, b3, c3, a4, b4, c4);//直接调用静态函数node->setStateSet(createTexture2DState(image1.get(),0));//使用二维纹理,禁用混合和光照node->setNodeMask(ReceivesShadowTraversalMask);return node;}
//创建一个光照 osg::ref_ptr<osg::Node>createLight(osg::ref_ptr<osg::Node>model,osg::Vec3 m_pos) { osg::ComputeBoundsVisitor cbbv; model->accept(cbbv); osg::BoundingBox bb=cbbv.getBoundingBox(); osg::ref_ptr<osg::Light>lt=new osg::Light; lt->setLightNum(0); osg::Vec4 a(m_pos.x(),m_pos.y(),m_pos.z(),1);lt->setPosition(a);//设置环境光的颜色 lt->setAmbient(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); osg::ref_ptr<osg::LightSource>ls=new osg::LightSource(); ls->setLight(lt.get()); return ls.get(); } //光源球osg::ref_ptr<osg::Geode> CreateLiSphere(osg::Vec3 m_center,float m_radius){//光源物体osg::ref_ptr<osg::Geode>geode=new osg::Geode; geode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); osg::ref_ptr<osg::ShapeDrawable>sd=new osg::ShapeDrawable(new osg::Sphere(m_center,m_radius)); sd->setColor(osg::Vec4(1,0,0,1)); geode->addDrawable(sd); return geode.get();}osg::ref_ptr<osgShadow::ShadowedScene> CreateShadowScene(osg::ref_ptr<osg::Group> &m_scenemodel,osg::Vec3 m_pos){//创建一个阴影节点,并标识接收对象和投影对象 osg::ref_ptr<osgShadow::ShadowedScene> shadowedScene = new osgShadow::ShadowedScene(); shadowedScene->setReceivesShadowTraversalMask(ReceivesShadowTraversalMask); shadowedScene->setCastsShadowTraversalMask(CastsShadowTraversalMask); //创建阴影纹理,使用的是shadowTexture技法 osg::ref_ptr<osgShadow::ShadowTexture> st = new osgShadow::ShadowTexture; osg::ref_ptr<osgShadow::ParallelSplitShadowMap> pss = new osgShadow::ParallelSplitShadowMap; //osg::ref_ptr<osgShadow::ShadowVolume> sv = new osgShadow::ShadowVolume; osg::ref_ptr<osgShadow::MinimalShadowMap> ms = new osgShadow::MinimalShadowMap; osg::ref_ptr<osgShadow::StandardShadowMap> ss = new osgShadow::StandardShadowMap; osg::ref_ptr<osgShadow::SoftShadowMap> softS = new osgShadow::SoftShadowMap; osg::ref_ptr<osgShadow::ViewDependentShadowTechnique> vds = new osgShadow::ViewDependentShadowTechnique; //关联阴影纹理 shadowedScene->setShadowTechnique(softS); //添加场景数据并添加光源 shadowedScene->addChild(createLight(m_scenemodel.get(),m_pos)); shadowedScene->addChild(m_scenemodel.get()); return shadowedScene;}osg::ref_ptr<osg::AnimationPath> createAnimationPath( float radius, float time ){osg::ref_ptr<osg::AnimationPath> path = new osg::AnimationPath;path->setLoopMode( osg::AnimationPath::LOOP );unsigned int numSamples = 32;float delta_yaw = 2.0f * osg::PI/((float)numSamples - 1.0f);float delta_time = time / (float)numSamples;for ( unsigned int i=0; i<numSamples; ++i ){float yaw = delta_yaw * (float)i;osg::Vec3 pos( sinf(yaw)*radius, cosf(yaw)*radius, 20.0f );osg::Quat rot( -yaw, osg::Z_AXIS );path->insert( delta_time * (float)i, osg::AnimationPath::ControlPoint(pos, rot) );}return path.release(); }//创建场景数据、模型....可以直接设,也可以对整个结点进行设置osg::ref_ptr<osg::Node>createModel(){//创建投影对象,读取房子模型osg::ref_ptr<osg::Node> node1=new osg::Node;node1=osgDB::readNodeFile("XX"); //node1->setNodeMask(CastsShadowTraversalMask); //可以直接设,也可以对整个结点进行设置//设置阴影投射对象和接受对象,使房子恰好在地形模型之上osg::ref_ptr <osg::MatrixTransform> mat=new osg::MatrixTransform();osg::Matrix m = osg::Matrix::scale(1.0f,1.0f,1.0f)*osg ::Matrix::translate(osg::Vec3(0,0,10.0f));mat->setMatrix(m);mat->addChild(node1.get());osg::ref_ptr<osg::AnimationPathCallback> apcb = new osg::AnimationPathCallback;apcb->setAnimationPath( createAnimationPath(50.0f, 6.0f) );mat->setUpdateCallback( apcb.get() );osg::ref_ptr<osg::Node> node2=osgDB::readNodeFile("XX"); //node2->setNodeMask(CastsShadowTraversalMask);//设置另外一个建筑物的位置和大小,同上osg::ref_ptr <osg::MatrixTransform> mat2=new osg::MatrixTransform();osg::Matrix m2=osg::Matrix::scale(1.0f,1.0f,1.0f)*osg ::Matrix::translate(osg::Vec3(20,0,10.0f));mat2->setMatrix(m2);mat2->addChild(node2.get());//创建一个组节点,将各个子节点添加进来osg::ref_ptr<osg::Group>group=new osg::Group;group->addChild(mat.get());group->addChild(mat2.get());group->setNodeMask(CastsShadowTraversalMask);//整体设置,该结点下的物体全部都可以投射阴影return group.get();}int main(){osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();viewer->addEventHandler(new osgViewer::WindowSizeHandler);//创建一个组节点osg::ref_ptr<osg::Group> root = new osg::Group();osg::Vec3 ltpos(0,0,200);root->addChild(CreateShadowScene(CreateSceneModel(createModel();),ltpos));root->addChild(CreateLiSphere(ltpos,10));//添加光源球,不要放到阴影场景里
root->addChild(DrawGround(-1300,-1300,-24,1300,-1300,-24,130,1300,-24,-1300,1300,-24));//优化场景数据osgUtil::Optimizer optimizer ;optimizer.optimize(root.get()) ;viewer->setSceneData(root.get());viewer->realize();viewer->run();return 0 ;}
0 0