|
楼主 |
发表于 2012-5-23 10:57:27
|
显示全部楼层
*/
#include "stdafx.h"
#include <osg/Node>
#include <osg/Geometry>
#include <osg/Notify>
#include <osg/Texture1D>
#include <osg/Texture2D>
#include <osg/Texture3D>
#include <osg/TextureRectangle>
#include <osg/ImageSequence>
#include <osg/Geode>
#include <osg/MatrixTransform>
#include <osg/Material>
#include <osg/ShapeDrawable>
#include <osg/Shape>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgUtil/SmoothingVisitor>
#include <osg/CullFace>
#include <osg/StateSet>
#include <osg/LightModel>
#include <osg/AlphaFunc>
#include <iostream>
using namespace std;
osg::ref_ptr<osg::Geode> createFlagGeometry(float radius,float flagzAxis,osg::Vec3 originCoodinate);
osg::ref_ptr<osg::Node> createCylinder(osg::Vec3 originCoodinate)
{
osg::ref_ptr<osg::Geometry> cylinderGeom = new osg::Geometry;
//计算圆柱体的顶点
osg::ref_ptr<osg::Vec3Array> cylinderVertices = new osg::Vec3Array;
cylinderGeom->setVertexArray( cylinderVertices.get() );
float cylinderRadiusdown=0.02;
float cylinderRadiusup=0.02;
float cylinderHeight=2.5;
//下底面顶点计算,以y轴坐标为自变量,x轴对应为因变量,最后加上世界坐标起始点
for (float a=0.f;a<=2.0*cylinderRadiusdown;a+=2*cylinderRadiusdown/100.0)
{
cylinderVertices->push_back(originCoodinate+osg::Vec3(sqrt(fabs(pow(cylinderRadiusdown,2)-pow(fabs(a-cylinderRadiusdown),2))),a,0.0f));
cylinderVertices->push_back(originCoodinate+osg::Vec3(sqrt(fabs(pow(cylinderRadiusup,2)-pow(fabs(a*(cylinderRadiusup/cylinderRadiusdown)-cylinderRadiusup),2))),a*(cylinderRadiusup/cylinderRadiusdown),0.0f)+osg::Vec3(0.0,0.0,cylinderHeight));
}
//上底面顶点计算
for (float a=2.0*cylinderRadiusdown;a>=0;a-=2*cylinderRadiusdown/100.0)
{
cylinderVertices->push_back(originCoodinate+osg::Vec3(-1.0f*sqrt(fabs(pow(cylinderRadiusdown,2)-pow(fabs(a-cylinderRadiusdown),2))),a,0.0f));
cylinderVertices->push_back(originCoodinate+osg::Vec3(-1.0f*sqrt(fabs(pow(cylinderRadiusup,2)-pow(fabs(a*(cylinderRadiusup/cylinderRadiusdown)-cylinderRadiusup),2))),a*(cylinderRadiusup/cylinderRadiusdown),0.0f)+osg::Vec3(0.0,0.0,cylinderHeight));
}
//计算圆柱体各个顶点的法线
float verticesNum=404;
osg::ref_ptr<osg::Vec3Array> cylinderNormal = new osg::Vec3Array;
cylinderGeom->setNormalArray( cylinderNormal.get() );
cylinderGeom->setNormalBinding( osg::Geometry::BIND_PER_VERTEX);
float x2=cylinderRadiusdown*cylinderHeight/sqrt(cylinderHeight*cylinderHeight+pow((cylinderRadiusdown-cylinderRadiusup),2));//x2为半径cylinderRadiusdown*pow(cosΘ,2),Θ角是圆柱的侧面与中轴线的夹角
float x3=x2*(cylinderRadiusdown-cylinderRadiusup)/cylinderHeight;//x3为半径cylinderRadiusdown在圆柱侧表面的投影
osg::Vec3 Vec3temp;
//计算下底面的顶点法线坐标
for (float a=-1.0*cylinderRadiusdown;a<=1.0*cylinderRadiusdown;a+=2*cylinderRadiusdown/100.0)
{
Vec3temp=osg::Vec3(0.0,0.0,0.0)+osg::Vec3(sqrt(fabs(pow(x2,2)-pow(a*(x2/cylinderRadiusdown),2))),a*(x2/cylinderRadiusdown),0.0f)+osg::Vec3(0.0,0.0,x3);
Vec3temp=Vec3temp*(1.0/sqrt(pow(Vec3temp.x(),2)+pow(Vec3temp.y(),2)+pow(Vec3temp.z(),2)));//法线归一化
cylinderNormal->push_back(Vec3temp);
cylinderNormal->push_back(Vec3temp);
}
//计算上地面的顶点法线坐标
for (float a=1.0*cylinderRadiusdown;a>=-1.0*cylinderRadiusdown;a-=2*cylinderRadiusdown/100.0)
{
Vec3temp=osg::Vec3(0.0,0.0,0.0)+(osg::Vec3(-1*sqrt(fabs(pow(x2,2)-pow(a*(x2/cylinderRadiusdown),2))),a*(x2/cylinderRadiusdown),0.0f)+osg::Vec3(0.0,0.0,x3));
Vec3temp=Vec3temp*(1.0/sqrt(pow(Vec3temp.x(),2)+pow(Vec3temp.y(),2)+pow(Vec3temp.z(),2)));
cylinderNormal->push_back(Vec3temp);
cylinderNormal->push_back(Vec3temp);
}
//各顶点颜色数组及参数设置
osg::ref_ptr<osg::Vec4Array> cylinderColorArray = new osg::Vec4Array;
cylinderColorArray->push_back( osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
cylinderGeom->setColorArray( cylinderColorArray.get() );
cylinderGeom->setColorBinding( osg::Geometry::BIND_OVERALL );
cylinderGeom->addPrimitiveSet(new osg:rawArrays( osg:rimitiveSet::TRIANGLE_STRIP, 0,verticesNum) );
osg::ref_ptr<osg::Geode> cylinderGeode = new osg::Geode;
cylinderGeode->addDrawable(cylinderGeom.get());
osg::ref_ptr<osg::MatrixTransform> flagMT = new osg::MatrixTransform;
flagMT->addChild(createFlagGeometry(cylinderRadiusdown,cylinderHeight,originCoodinate));
osg::ref_ptr<osg::MatrixTransform> cylinderMT = new osg::MatrixTransform();
cylinderMT->addChild(cylinderGeode.get());
cylinderMT->addChild(flagMT.get());
osg::StateSet* cylinderStateset = cylinderGeode->getOrCreateStateSet();
osg::ref_ptr<osg::Material> cylinderMaterial = new osg::Material();
//漫反射光
cylinderMaterial->setDiffuse( osg::Material::FRONT_AND_BACK,osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
//镜面反射光
cylinderMaterial->setSpecular( osg::Material::FRONT_AND_BACK,osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
//环境反射光
cylinderMaterial->setShininess( osg::Material::FRONT_AND_BACK, 128.f );
cylinderStateset->setAttribute( cylinderMaterial.get() );
cylinderStateset->setRenderingHint( osg::StateSet::OPAQUE_BIN );
return cylinderMT.get();
}
class MyGeometryCallback : public osg::Drawable::UpdateCallback, public osg::Drawable::AttributeFunctor
{
public:
MyGeometryCallback(const osg::Vec3& o,const osg::Vec3& x,const osg::Vec3& y,const osg::Vec3& z,double period,double xphase,double amplitude):
_firstCall(true),
_startTime(0.0),
_time(0.0),
_period(period),
_xphase(xphase),
_amplitude(amplitude),
_origin(o),
_xAxis(x),
_yAxis(y),
_zAxis(z)
{
}
virtual void update(osg::NodeVisitor* nv,osg::Drawable* drawable)
{
const osg::FrameStamp* fs = nv->getFrameStamp();
double simulationTime = fs->getSimulationTime();
if (_firstCall)
{
_firstCall = false;
_startTime = simulationTime;
}
_time = simulationTime-_startTime;
drawable->accept(*this);
drawable->dirtyBound();
osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(drawable);
if (geometry)
{
osgUtil::SmoothingVisitor::smooth(*geometry);
}
}
virtual void apply(osg::Drawable::AttributeType type,unsigned int count,osg::Vec3* begin)
{
if (type == osg::Drawable::VERTICES)
{
const float TwoPI=2.0f*osg::PI;
const float phase = -_time/_period;
osg::Vec3* end = begin+count;
for (osg::Vec3* itr=begin;itr<end;++itr)
{
osg::Vec3 dv(*itr-_origin);
osg::Vec3 local(dv*_xAxis,dv*_yAxis,dv*_zAxis);
local.z() = local.x()*_amplitude*
sinf(TwoPI*(phase+local.x()*_xphase));
(*itr) = _origin +
_xAxis*local.x()+
_yAxis*local.y()+
_zAxis*local.z();
}
}
}
bool _firstCall;
double _startTime;
double _time;
double _period;
double _xphase;
float _amplitude;
osg::Vec3 _origin;
osg::Vec3 _xAxis;
osg::Vec3 _yAxis;
osg::Vec3 _zAxis;
};
osg::ref_ptr<osg::Geode> createFlagGeometry(float radius,float flagzAxis,osg::Vec3 originCoodinate)
{
//纹理尺寸
unsigned int tex_width =128;
unsigned int tex_height = 64;
bool useTextureRectangle = false;
osg::Geometry* polyGeom = new osg::Geometry();//绘制几何体
polyGeom->setName( "flagsurface" );//几何体的名字
polyGeom->setDataVariance( osg::Object::DYNAMIC );
polyGeom->setSupportsDisplayList(false);
osg::Vec3f origin = osg::Vec3f(0.0f,radius,flagzAxis-0.3f) + originCoodinate;
osg::Vec3 xAxis(1.0f,0.0f,0.0f);
osg::Vec3 yAxis(0.0f,0.0f,1.0f);
osg::Vec3 zAxis(0.0f,-1.0f,0.0f);
float height = 0.3;
float width = 0.5;
int noSteps = 20;
osg::Vec3Array* vertices = new osg::Vec3Array;
osg::Vec3 bottom = origin;
osg::Vec3 top = origin;
top.z()+= height;
osg::Vec3 dv = xAxis*(width/((float)(noSteps-1)));//以xAxis为单位向量,顶点坐标的最小单位
osg::Vec2Array* texcoords = new osg::Vec2Array;
// note, when we use TextureRectangle we have to scale the tex coords up to compensate.
osg::Vec2 bottom_texcoord(0.0f,0.0f);
osg::Vec2 top_texcoord(0.0f, useTextureRectangle ? tex_height : 1.0f);
osg::Vec2 dv_texcoord((useTextureRectangle ? tex_width : 1.0f)/(float)(noSteps-1),0.0f);//纹理坐标的最小单位
for(int i=0;i<noSteps;i++)
{
vertices->push_back(top);
vertices->push_back(bottom);
top+=dv;//顶部顶点以dv步进增大
bottom+=dv;
texcoords->push_back(top_texcoord);
texcoords->push_back(bottom_texcoord);
top_texcoord+=dv_texcoord;
bottom_texcoord+=dv_texcoord;
}
// pass the created vertex array to the points geometry object.
polyGeom->setVertexArray(vertices);//压入顶点坐标
polyGeom->setTexCoordArray(0,texcoords);//压入纹理坐标
osg::Vec4Array* colors = new osg::Vec4Array();//pushback颜色数组
colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
polyGeom->setColorArray(colors);
polyGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet:UAD_STRIP,0,vertices->size()));
// 添加纹理
osg::Texture2D* flagTexture = new osg::Texture2D();
flagTexture->setDataVariance(osg::Object::DYNAMIC);
osg::Image* flagImage = osgDB::readImageFile("qizi.jpg");
if (!flagImage)
{
cout << " couldn't find texture, quitting." << endl;
return 0;
}
flagTexture->setImage(flagImage);
osg::StateSet* stateset = new osg::StateSet;//创建状态集
stateset = polyGeom->getOrCreateStateSet();
//设置双面渲染
osg::ref_ptr<osg:ightModel> lightModel = new osg::LightModel;
lightModel->setTwoSided(true);//双面渲染
stateset->setAttributeAndModes( lightModel.get() );
stateset->setRenderingHint( osg::StateSet::DEFAULT_BIN );
stateset->setTextureAttributeAndModes(0, flagTexture,osg::StateAttribute::ON);//将状态集关联到纹理
polyGeom->setUpdateCallback(new MyGeometryCallback(origin,xAxis,yAxis,zAxis,1.0,1.0/width,0.2f));//绘制体回调函数
osg::Geode* geode = new osg::Geode();
geode->addDrawable(polyGeom);
return geode;
}
int main(int argc, char **argv)
{
// construct the viewer.
osgViewer::Viewer viewer;
osg::Vec3 originCoodinate = osg::Vec3(3.02756f, 368.043f, 12.3346f);//-21.373f , 242.777f , 8.535f;3.02756f, 368.043f, 12.3346f
osg::ref_ptr<osg::Group> root = new osg::Group;
osg::ref_ptr<osg::Node> flag = osgDB::readNodeFile( "hole1a.ive" );
root->addChild(flag);
root->addChild(createCylinder(originCoodinate));
代码附上,各位老师给个建议,谢谢谢谢。。。。
viewer.setSceneData(root);
return viewer.run();
}
|
|