这节课NeHe教我们怎样把图片作为资源嵌入到exe可执行文件中,这样当我们发布程序的时候就可以不需要附带上图片文件了。由于这部分的内容和OSG并没有关系,主要是使用Windows编程中资源的概念,我对这部分并不是很熟悉,因此本课只实现最后的效果。图片并未处理成NeHe中的这种方式。
首先创建我们需要的50只蝴蝶的模型,并且加载需要的纹理
void initialize() { for (int loop=0; loop<50; loop++) { setObject(loop); } g_Tex1 = new osg::Texture2D; g_Tex1->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); g_Tex1->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); g_Tex1->setImage(osgDB::readImageFile("Data/Butterfly1.bmp")); g_Tex2 = new osg::Texture2D; g_Tex2->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); g_Tex2->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); g_Tex2->setImage(osgDB::readImageFile("Data/Butterfly2.bmp")); g_Tex3 = new osg::Texture2D; g_Tex3->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); g_Tex3->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); g_Tex3->setImage(osgDB::readImageFile("Data/Butterfly3.bmp")); }接下来把蝴蝶添加到组节点中,并设置每只蝴蝶的位置回调函数,更新它们的位置
osg::Group* createButterflyGroup()在回调中写下蝴蝶的位置变化以及旋转变化等:
class ButterFlyGroupCallback : public osg::NodeCallback
class TranslateUpdateCallback : public osg::NodeCallback这些内容前面的课程中已经重复很多次了,相信不难理解,具体代码参见后面的附录部分:
将所有这些部分添加到场景根节点下,编译运行程序:
附:本课源码(源码中可能存在错误和不足,仅供参考)
#include "../osgNeHe.h" #include <QtCore/QTimer> #include <QtGui/QApplication> #include <QtGui/QVBoxLayout> #include <osgViewer/Viewer> #include <osgDB/ReadFile> #include <osgQt/GraphicsWindowQt> #include <osg/MatrixTransform> #include <osg/PolygonMode> #include <osg/Texture2D> #include <osg/BlendFunc> osg::Texture2D *g_Tex1, *g_Tex2, *g_Tex3; struct object { int tex; float x; float y; float z; float yi; float spinz; float spinzi; float flap; float fi; }; object obj[50]; void setObject(int loop) { obj[loop].tex=rand()%3; obj[loop].x=rand()%34-17.0f; obj[loop].y=18.0f; obj[loop].z=-((rand()%30000/1000.0f)+10.0f); obj[loop].spinzi=(rand()%10000)/5000.0f-1.0f; obj[loop].flap=0.0f; obj[loop].fi=0.05f+(rand()%100)/1000.0f; obj[loop].yi=0.001f+(rand()%1000)/10000.0f; } void initialize() { for (int loop=0; loop<50; loop++) { setObject(loop); } g_Tex1 = new osg::Texture2D; g_Tex1->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); g_Tex1->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); g_Tex1->setImage(osgDB::readImageFile("Data/Butterfly1.bmp")); g_Tex2 = new osg::Texture2D; g_Tex2->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); g_Tex2->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); g_Tex2->setImage(osgDB::readImageFile("Data/Butterfly2.bmp")); g_Tex3 = new osg::Texture2D; g_Tex3->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); g_Tex3->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); g_Tex3->setImage(osgDB::readImageFile("Data/Butterfly3.bmp")); } class ButterflyUpdateCallback : public osg::Drawable::UpdateCallback { public: ButterflyUpdateCallback(int index, int texIndex) : _index(index), _texIndex(texIndex) { //NOP } virtual void update(osg::NodeVisitor*, osg::Drawable* drawable) { osg::Geometry *geometry = dynamic_cast<osg::Geometry*>(drawable); if(!geometry) return; osg::Vec3Array *vertexArray = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()); if (!vertexArray) return; vertexArray->clear(); vertexArray->push_back(osg::Vec3(1.0f, 1.0f, 0.0f)); vertexArray->push_back(osg::Vec3(-1.0f, 1.0f, obj[_index].flap)); vertexArray->push_back(osg::Vec3(-1.0f,-1.0f, 0.0f)); vertexArray->push_back(osg::Vec3(1.0f, 1.0f, 0.0f)); vertexArray->push_back(osg::Vec3(-1.0f,-1.0f, 0.0f)); vertexArray->push_back(osg::Vec3(1.0f,-1.0f, obj[_index].flap)); vertexArray->dirty(); geometry->setVertexArray(vertexArray); if (!geometry->getOrCreateStateSet()->getTextureAttribute(0, osg::StateAttribute::TEXTURE)) { if (_texIndex == 0 ) { geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, g_Tex1); } if (_texIndex == 1) { geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, g_Tex2); } if (_texIndex == 2) { geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, g_Tex3); } } } int _index; int _texIndex; }; class RotateUpdateCallback : public osg::NodeCallback { public: RotateUpdateCallback(int index) : _index(index){ } virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) { osg::MatrixTransform *mt = dynamic_cast<osg::MatrixTransform*>(node); if (!mt) return; mt->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(obj[_index].spinz), osg::Z_AXIS)); traverse(node, nv); } int _index; }; class TranslateUpdateCallback : public osg::NodeCallback { public: TranslateUpdateCallback(int index) : _index(index){} virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) { osg::MatrixTransform *mt = dynamic_cast<osg::MatrixTransform*>(node); if (!mt) return; mt->setMatrix(osg::Matrix::translate(obj[_index].x,obj[_index].y,obj[_index].z)); traverse(node, nv); } int _index; }; class ButterFlyGroupCallback : public osg::NodeCallback { public: ButterFlyGroupCallback(){} virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) { for (int loop = 0; loop < 50; ++loop) { obj[loop].y-=obj[loop].yi; obj[loop].spinz+=obj[loop].spinzi; obj[loop].flap+=obj[loop].fi; if (obj[loop].y<-18.0f) { setObject(loop); } if ((obj[loop].flap>1.0f) || (obj[loop].flap<-1.0f)) { obj[loop].fi=-obj[loop].fi; } } traverse(node, nv); } }; osg::Group* createButterflyGroup() { osg::Group *butterflyGroup = new osg::Group; butterflyGroup->addUpdateCallback(new ButterFlyGroupCallback); for (int loop = 0; loop < 50; ++loop) { osg::MatrixTransform *zoomMT = new osg::MatrixTransform; zoomMT->setMatrix(osg::Matrix::translate(obj[loop].x,obj[loop].y,obj[loop].z)); zoomMT->addUpdateCallback(new TranslateUpdateCallback(loop)); osg::MatrixTransform *rotateX = new osg::MatrixTransform; rotateX->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(45.0), osg::X_AXIS)); osg::MatrixTransform *rotateZ = new osg::MatrixTransform; rotateZ->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(obj[loop].spinz), osg::Z_AXIS)); rotateZ->addUpdateCallback(new RotateUpdateCallback(loop)); osg::Geode *butterflyGeode = new osg::Geode; osg::Geometry *butterGeometry = new osg::Geometry; butterGeometry->setUpdateCallback(new ButterflyUpdateCallback(loop, obj[loop].tex)); osg::Vec3Array *vertexArray = new osg::Vec3Array; osg::Vec2Array *texArray = new osg::Vec2Array; vertexArray->push_back(osg::Vec3(1.0f, 1.0f, 0.0f)); vertexArray->push_back(osg::Vec3(-1.0f, 1.0f, obj[loop].flap)); vertexArray->push_back(osg::Vec3(-1.0f,-1.0f, 0.0f)); vertexArray->push_back(osg::Vec3(1.0f, 1.0f, 0.0f)); vertexArray->push_back(osg::Vec3(-1.0f,-1.0f, 0.0f)); vertexArray->push_back(osg::Vec3(1.0f,-1.0f, obj[loop].flap)); texArray->push_back(osg::Vec2(1.0f,1.0f)); texArray->push_back(osg::Vec2(0.0f,1.0f)); texArray->push_back(osg::Vec2(0.0f,0.0f)); texArray->push_back(osg::Vec2(1.0f,1.0f)); texArray->push_back(osg::Vec2(0.0f, 0.0f)); texArray->push_back(osg::Vec2(1.0f,0.0f)); butterGeometry->setVertexArray(vertexArray); butterGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, vertexArray->size())); butterGeometry->setTexCoordArray(0, texArray, osg::Array::BIND_PER_VERTEX); butterGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, false); osg::BlendFunc *blendFunc = new osg::BlendFunc(osg::BlendFunc::ONE, osg::BlendFunc::SRC_ALPHA); butterGeometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc); butterGeometry->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, false); butterflyGeode->addDrawable(butterGeometry); butterflyGroup->addChild(zoomMT); zoomMT->addChild(rotateX); rotateX->addChild(rotateZ); rotateZ->addChild(butterflyGeode); } return butterflyGroup; } class ViewerWidget : public QWidget, public osgViewer::Viewer { public: ViewerWidget(osg::Node *scene = NULL) { QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,640,480), scene); QVBoxLayout* layout = new QVBoxLayout; layout->addWidget(renderWidget); layout->setContentsMargins(0, 0, 0, 1); setLayout( layout ); connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) ); _timer.start( 10 ); } QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene ) { osg::Camera* camera = this->getCamera(); camera->setGraphicsContext( gw ); const osg::GraphicsContext::Traits* traits = gw->getTraits(); camera->setClearColor( osg::Vec4(0.0, 0.0, 0.0, 0.5) ); camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) ); camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f ); camera->setViewMatrixAsLookAt(osg::Vec3d(0.0f, 25.0f, -45.0f), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 1, 0)); this->setSceneData( scene ); return gw->getGLWidget(); } osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name="", bool windowDecoration=false ) { osg::DisplaySettings* ds = osg::DisplaySettings::instance().get(); osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; traits->windowName = name; traits->windowDecoration = windowDecoration; traits->x = x; traits->y = y; traits->width = w; traits->height = h; traits->doubleBuffer = true; traits->alpha = ds->getMinimumNumAlphaBits(); traits->stencil = ds->getMinimumNumStencilBits(); traits->sampleBuffers = ds->getMultiSamples(); traits->samples = ds->getNumMultiSamples(); return new osgQt::GraphicsWindowQt(traits.get()); } virtual void paintEvent( QPaintEvent* event ) { frame(); } protected: QTimer _timer; }; osg::Node* buildScene() { initialize(); osg::Group *root = new osg::Group; root->addChild(createButterflyGroup()); return root; } int main( int argc, char** argv ) { QApplication app(argc, argv); ViewerWidget* viewWidget = new ViewerWidget(buildScene()); viewWidget->setGeometry( 100, 100, 640, 480 ); viewWidget->show(); return app.exec(); }