osg::Node* createBase(const osg::Vec3& center,float radius)
{ int numTilesX = ;
int numTilesY = ; float width = *radius;
float height = *radius; osg::Vec3 v000(center - osg::Vec3(width*0.5f,height*0.5f,0.0f));
osg::Vec3 dx(osg::Vec3(width/((float)numTilesX),0.0,0.0f));
osg::Vec3 dy(osg::Vec3(0.0f,height/((float)numTilesY),0.0f)); // fill in vertices for grid, note numTilesX+1 * numTilesY+1...
osg::Vec3Array* coords = new osg::Vec3Array;
int iy;
for(iy=;iy<=numTilesY;++iy)
{
for(int ix=;ix<=numTilesX;++ix)
{
coords->push_back(v000+dx*(float)ix+dy*(float)iy);
}
} //Just two colours - black and white.
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); // white
colors->push_back(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); // black osg::ref_ptr<osg::DrawElementsUShort> whitePrimitives = new osg::DrawElementsUShort(GL_QUADS);
osg::ref_ptr<osg::DrawElementsUShort> blackPrimitives = new osg::DrawElementsUShort(GL_QUADS); int numIndicesPerRow=numTilesX+;
for(iy=;iy<numTilesY;++iy)
{
for(int ix=;ix<numTilesX;++ix)
{
osg::DrawElementsUShort* primitives = ((iy+ix)%==) ? whitePrimitives.get() : blackPrimitives.get();
primitives->push_back(ix +(iy+)*numIndicesPerRow);
primitives->push_back(ix +iy*numIndicesPerRow);
primitives->push_back((ix+)+iy*numIndicesPerRow);
primitives->push_back((ix+)+(iy+)*numIndicesPerRow);
}
} // set up a single normal
osg::Vec3Array* normals = new osg::Vec3Array;
normals->push_back(osg::Vec3(0.0f,0.0f,1.0f)); osg::Geometry* geom = new osg::Geometry;
geom->setVertexArray(coords); geom->setColorArray(colors, osg::Array::BIND_PER_PRIMITIVE_SET); geom->setNormalArray(normals, osg::Array::BIND_OVERALL); geom->addPrimitiveSet(whitePrimitives.get());
geom->addPrimitiveSet(blackPrimitives.get()); osg::Geode* geode = new osg::Geode;
geode->addDrawable(geom); return geode;
}
createBase函数用于建立模型模拟时的地板,作为飞机飞行的参照。
23行中,循环向变量coords中添加坐标点,作为地板的控制点。
36-46行中,交替取出白色面元和黑色面元,并向其中每次添加四个顶点(索引值),指示面元的角点坐标(按照索引值从coords数组中取出)。
随后设置所有面元的法向量,并将黑白面元分别添加进绘制几何节点中,并将绘制几何节点添加到集合节点中,由函数返回。
接下来分析第三个函数:
osg::Node* createMovingModel(const osg::Vec3& center, float radius)
{
float animationLength = 10.0f; osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength); osg::ref_ptr<osg::Group> model = new osg::Group; osg::ref_ptr<osg::Node> glider = osgDB::readRefNodeFile("glider.osgt");
if (glider)
{
const osg::BoundingSphere& bs = glider->getBound(); float size = radius/bs.radius()*0.3f;
osg::MatrixTransform* positioned = new osg::MatrixTransform;
positioned->setDataVariance(osg::Object::STATIC);
positioned ->setMatrix(osg::Matrix::translate(-bs.center())*
osg::Matrix::scale(size,size,size)*
osg::Matrix::rotate(osg::inDegrees(-90.0f),0.0f,0.0f,1.0f)); positioned->addChild(glider); osg::PositionAttitudeTransform* xform = new osg::PositionAttitudeTransform;
xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0,1.0));
xform->addChild(positioned); model->addChild(xform);
} osg::ref_ptr<osg::Node> cessna = osgDB::readRefNodeFile("cessna.osgt");
if (cessna)
{
const osg::BoundingSphere& bs = cessna->getBound(); float size = radius/bs.radius()*0.3f;
osg::MatrixTransform* positioned = new osg::MatrixTransform;
positioned->setDataVariance(osg::Object::STATIC);
positioned->setMatrix(osg::Matrix::translate(-bs.center())*
osg::Matrix::scale(size,size,size)*
osg::Matrix::rotate(osg::inDegrees(180.0f),0.0f,0.0f,1.0f)); positioned->addChild(cessna); osg::ref_ptr<osg::MatrixTransform> xform = new osg::MatrixTransform;
xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0f,2.0));
xform->addChild(positioned); model->addChild(xform);
} #ifndef OSG_GLES2_AVAILABLE
model->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
#endif return model.release();
}
这个函数的作用是创建运动模型。
首先利用上一节介绍的createAnimationPath 函数创建模拟路径,并以此为基础加载模型,并控制模型的运动。
动态更新的核心就是设置数据变度属性DataVariance,它决定了OSG在多线程渲染的过程中的执行策略:只有所有DYNAMIC属性的对象被渲染 完毕之后,OSG才会开始执行下一帧的用户更新操作;这样有效地可以避免数据的过快更新造成当前的渲染动作出错,以致系统崩溃。
将模型进行平移,缩放,并绕z轴旋转180度。创建转换函数,并设置其更新回调函数。AnimationPathCallback的构造函数为:
osg::AnimationPathCallback::AnimationPathCallback ( AnimationPath * ap,
double timeOffset = 0.0,
double timeMultiplier = 1.0
)
该函数的第三个参数决定了节点旋转的速度。因此cessna模型的旋转速度是glider的二倍。这两个模型的加载和回调更新函数的设定过程相同,只是参数有所不同。