|
发表于 2014-6-20 10:11:32
|
显示全部楼层
不修改osg代码的话,需要重载osg:ShapeDrawable,仅供参考
- // Test.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <osgViewer/Viewer>
- #include <osgViewer/ViewerEventHandlers>
- #include <osgViewer/api/win32/GraphicsWindowWin32>
- #include <osgGA/TrackballManipulator>
- #include <osgGA/KeySwitchMatrixManipulator>
- #include <osgGA/StateSetManipulator>
- #include <osgDB/DatabasePager>
- #include <osgDB/Registry>
- #include <osgDB/ReadFile>
- #include <osgDB/WriteFile>
- #include <osgUtil/Optimizer>
- #include <osgUtil/SmoothingVisitor>
- #include <osg/ShapeDrawable>
- #include <osg/Shape>
- #include <osg/MatrixTransform>
- #include <osg/Transform>
- #include <osg/PositionAttitudeTransform>
- #include <osg/StateSet>
- #include <osg/NodeVisitor>
- #include <osg/ImageSequence>
- #include <osg/ImageStream>
- #include <osg/ClipPlane>
- #include <osg/ClipNode>
- #include <iostream>
- #include<iomanip>
- #include<fstream>
- #include <vector>
- #include <cstring>
- #include <string>
- const unsigned int MIN_NUM_ROWS = 3;
- const unsigned int MIN_NUM_SEGMENTS = 5;
- class DrawShapeVisitor : public osg::ConstShapeVisitor
- {
- public:
- DrawShapeVisitor(osg::State& state,const osg::TessellationHints* hints, float minu = 0.0f, float maxu = 1.0f, float minv = 0.0f, float maxv = 1.0f):
- _state(state),
- _hints(hints),
- _minu(minu),
- _maxu(maxu),
- _minv(minv),
- _maxv(maxv)
- {
- #if 0
- if (hints)
- {
- OSG_NOTICE<<"Warning: TessellationHints ignored in present osg::ShapeDrawable implementation."<<std::endl;
- }
- #endif
- }
- virtual void apply(const osg::Cylinder&);
- osg::State& _state;
- const osg::TessellationHints* _hints;
- float _minu;
- float _maxu;
- float _minv;
- float _maxv;
- protected:
- DrawShapeVisitor& operator = (const DrawShapeVisitor&) { return *this; }
- enum SphereHalf { SphereTopHalf, SphereBottomHalf };
- // helpers for apply( Cylinder | Sphere | Capsule )
- void drawCylinderBody(unsigned int numSegments, float radius, float height);
- };
- void DrawShapeVisitor::drawCylinderBody(unsigned int numSegments, float radius, float height)
- {
- const float angleDelta = 2.0f*osg::PI/(float)numSegments;
- const float texCoordDelta = (_maxu - _minu)/(float)numSegments;
- const float r = radius;
- const float h = height;
- float basez = -h*0.5f;
- float topz = h*0.5f;
- float angle = 0.0f;
- float texCoord = _minu;
- bool drawFrontFace = _hints ? _hints->getCreateFrontFace() : true;
- bool drawBackFace = _hints ? _hints->getCreateBackFace() : false;
- // The only difference between the font & back face loops is that the
- // normals are inverted and the order of the vertex pairs is reversed.
- // The code is mostly duplicated in order to hoist the back/front face
- // test out of the loop for efficiency
- osg::GLBeginEndAdapter& gl = _state.getGLBeginEndAdapter();
- gl.Begin(GL_QUAD_STRIP);
- if (drawFrontFace) {
- for(unsigned int bodyi=0;
- bodyi<numSegments;
- ++bodyi,angle+=angleDelta,texCoord+=texCoordDelta)
- {
- float c = cosf(angle);
- float s = sinf(angle);
- gl.Normal3f(c,s,0.0f);
- gl.TexCoord2f(texCoord,_maxv);
- gl.Vertex3f(c*r,s*r,topz);
- gl.TexCoord2f(texCoord,_minv);
- gl.Vertex3f(c*r,s*r,basez);
- }
- // do last point by hand to ensure no round off errors.
- gl.Normal3f(1.0f,0.0f,0.0f);
- gl.TexCoord2f(_maxu,_maxv);
- gl.Vertex3f(r,0.0f,topz);
- gl.TexCoord2f(_maxu,_minv);
- gl.Vertex3f(r,0.0f,basez);
- }
- if (drawBackFace) {
- for(unsigned int bodyi=0;
- bodyi<numSegments;
- ++bodyi,angle+=angleDelta,texCoord+=texCoordDelta)
- {
- float c = cosf(angle);
- float s = sinf(angle);
- gl.Normal3f(-c,-s,0.0f);
- gl.TexCoord2f(texCoord,_minv);
- gl.Vertex3f(c*r,s*r,basez);
- gl.TexCoord2f(texCoord,_maxv);
- gl.Vertex3f(c*r,s*r,topz);
- }
- // do last point by hand to ensure no round off errors.
- gl.Normal3f(-1.0f,0.0f,0.0f);
- gl.TexCoord2f(_maxu,_minv);
- gl.Vertex3f(r,0.0f,basez);
- gl.TexCoord2f(_maxu,_maxv);
- gl.Vertex3f(r,0.0f,topz);
- }
- gl.End();
- }
- void DrawShapeVisitor::apply(const osg::Cylinder& cylinder)
- {
- osg::GLBeginEndAdapter& gl = _state.getGLBeginEndAdapter();
- gl.PushMatrix();
- gl.Translated(cylinder.getCenter().x(),cylinder.getCenter().y(),cylinder.getCenter().z());
- if (!cylinder.zeroRotation())
- {
- osg::Matrixd rotation(cylinder.computeRotationMatrix());
- gl.MultMatrixd(rotation.ptr());
- }
- // evaluate hints
- bool createBody = (_hints ? _hints->getCreateBody() : true);
- bool createTop = (_hints ? _hints->getCreateTop() : true);
- bool createBottom = (_hints ? _hints->getCreateBottom() : true);
- unsigned int numSegments = 40;
- float ratio = (_hints ? _hints->getDetailRatio() : 1.0f);
- if (ratio > 0.0f && ratio != 1.0f) {
- numSegments = (unsigned int) (numSegments * ratio);
- if (numSegments < MIN_NUM_SEGMENTS)
- numSegments = MIN_NUM_SEGMENTS;
- }
- // cylinder body
- if (createBody)
- drawCylinderBody(numSegments, cylinder.getRadius(), cylinder.getHeight());
- float angleDelta = 2.0f*osg::PI/(float)numSegments;
- float texCoordDelta = (_maxu-_minu)/(float)numSegments;
- float halfU = (_maxu-_minu)/2.0f;
- float halfV = (_maxv-_minv)/2.0f;
- float r = cylinder.getRadius();
- float h = cylinder.getHeight();
- float basez = -h*0.5f;
- float topz = h*0.5f;
- float angle = 0.0f;
- float texCoord = _minu;
- // cylinder top
- if (createTop) {
- gl.Begin(GL_TRIANGLE_FAN);
- gl.Normal3f(0.0f,0.0f,1.0f);
- gl.TexCoord2f(0.5f,0.5f);
- gl.Vertex3f(0.0f,0.0f,topz);
- angle = 0.0f;
- texCoord = 0.0f;
- for(unsigned int topi=0;
- topi<numSegments;
- ++topi,angle+=angleDelta,texCoord+=texCoordDelta)
- {
- float c = cosf(angle);
- float s = sinf(angle);
- gl.TexCoord2f(c*halfU+halfU,s*halfV+halfV);
- gl.Vertex3f(c*r,s*r,topz);
- }
- gl.TexCoord2f(_maxu,halfV);
- gl.Vertex3f(r,0.0f,topz);
- gl.End();
- }
- // cylinder bottom
- if (createBottom)
- {
- gl.Begin(GL_TRIANGLE_FAN);
- gl.Normal3f(0.0f,0.0f,-1.0f);
- gl.TexCoord2f(halfU,halfV);
- gl.Vertex3f(0.0f,0.0f,basez);
- angle = osg::PI*2.0f;
- texCoord = _maxu;
- for(unsigned int bottomi=0;
- bottomi<numSegments;
- ++bottomi,angle-=angleDelta,texCoord-=texCoordDelta)
- {
- float c = cosf(angle);
- float s = sinf(angle);
- gl.TexCoord2f(c*halfU+halfU,s*halfV+halfV);
- gl.Vertex3f(c*r,s*r,basez);
- }
- gl.TexCoord2f(_maxu,halfV);
- gl.Vertex3f(r,0.0f,basez);
- gl.End();
- }
- gl.PopMatrix();
- }
- class ShapeDrawableEx : public osg::ShapeDrawable
- {
- public:
- ShapeDrawableEx() : _minu(0.0f), _maxu(1.0f), _minv(0.0f), _maxv(1.0f) {}
- ShapeDrawableEx(osg::Shape* shape, osg::TessellationHints* hints=0)
- : osg::ShapeDrawable(shape, hints), _minu(0.0f), _maxu(1.0f), _minv(0.0f), _maxv(1.0f)
- {}
- ShapeDrawableEx(const ShapeDrawableEx& pg,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY)
- : osg::ShapeDrawable(pg, copyop), _minu(pg._minu), _maxu(pg._maxu), _minv(pg._minv), _maxv(pg._maxv)
- {}
- public:
- inline void setMinU(float v) { _minu=v; }
- inline float getMinU() const { return _minu; }
- inline void setMaxU(float v) { _maxu=v; }
- inline float getMaxU() const { return _maxu; }
- inline void setMinV(float v) { _minv=v; }
- inline float getMinV() const { return _minv; }
- inline void setMaxV(float v) { _maxv=v; }
- inline float getMaxV() const { return _maxv; }
- public:
- virtual void drawImplementation(osg::RenderInfo& renderInfo) const
- {
- osg::State& state = *renderInfo.getState();
- osg::GLBeginEndAdapter& gl = state.getGLBeginEndAdapter();
- if (_shape.valid())
- {
- gl.Color4fv(_color.ptr());
- DrawShapeVisitor dsv(state,_tessellationHints.get(), _minu, _maxu, _minv, _maxv);
- _shape->accept(dsv);
- }
- }
- protected:
- float _minu;
- float _maxu;
- float _minv;
- float _maxv;
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- osg::TessellationHints* hints = new osg::TessellationHints;
- hints->setDetailRatio(0.5f);
- hints->setCreateBody(true);
- //hints->setCreateBackFace(true); //必须去除这句话,否则贴图闪烁。
- hints->setCreateBottom(false);
- hints->setCreateTop(false);
- hints->setCreateTextureCoords(true);
- float radius = 5.f;
- float height = 8.f;
- osg::ref_ptr<osg::PositionAttitudeTransform> group = new osg::PositionAttitudeTransform;
- osg::ref_ptr<osg::Geode> genode = new osg::Geode;
- osg::ref_ptr<osg::Geode> genode2 = new osg::Geode;
- osg::ref_ptr<ShapeDrawableEx> drawable = new ShapeDrawableEx(new osg::Cylinder(osg::Vec3(0.0f,0.0f,0.0f),radius,height),hints);
- drawable->setMinV(0.5f); // 设置纹理坐标
- osg::ref_ptr<ShapeDrawableEx> drawable2 = new ShapeDrawableEx(new osg::Cylinder(osg::Vec3(0.0f,0.0f,0.0f),radius,height),hints);
- drawable2->setMaxV(0.5f); // 设置纹理坐标
- genode->addDrawable(drawable.get()); // geom.get() or gemo. both are ok.
- genode2->addDrawable(drawable2.get()); // geom.get() or gemo. both are ok.
- osg::ref_ptr<osg::MatrixTransform> tans = new osg::MatrixTransform;
- tans->setMatrix(osg::Matrix::translate(0,0,height/2.0));
- tans->addChild(genode.get());
- osg::ref_ptr<osg::MatrixTransform> tans2 = new osg::MatrixTransform;
- tans2->setMatrix(osg::Matrix::translate(0,0,-height/2.0));
- tans2->addChild(genode2.get());
- group->addChild(tans2);
- group->addChild(tans);
- osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
- osg::ref_ptr<osg::Image> image = osgDB::readImageFile("land_shallow_topo_2048.png");
- texture->setImage(image);
- texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
- texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
- texture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
- texture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
- osg::StateSet* state = group->getOrCreateStateSet();
- state->setMode( GL_LIGHTING, osg::StateAttribute::OFF |
- osg::StateAttribute::PROTECTED );
- state->setTextureAttributeAndModes(0,texture.get());
- osgViewer::Viewer viewer;
- viewer.setSceneData(group.get());
- viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
- viewer.addEventHandler(new osgViewer::WindowSizeHandler);
- return viewer.run();
- }
复制代码 |
|