我要发帖 回复

高级会员

109

主题

1589

积分

0

专家分

OSG-VR-GIS

忠于职守杰出贡献

:

私信
发表时间 : 2007-12-21 14:18:49 | 浏览 : 1983    评论 : 2
Navy16 - 交集测试 (1)
目的:
5.jpg
向场景中添加一系列随机放置着的灌木。使用osgUtil库的交集函数来获取正确的地形高度值,以便正确安置灌木告示牌节点。
-----------------------------

概述:


如果我们希望扩展前一个教程的内容,向场景中的地形添加一些随意放置的告示牌节点,那么我们最好能够获取任意经纬(x,y)位置的地形高度值。我们可以使用osgUtil库提供的交集运算模块函数来实现这一功能。我们可能会用到的基本类描述如下:

线段(osg::LineSegment)- 交集测试的基础是场景中的射线。线段类提供了一种定义射线的方法。它包括两个osg::Vec3实例:一个用于定义线段的起点,另一个用于定义终点。当交集测试被触发时,它将检测射线的相交情况并执行相应的操作。

交点(osgUtil::Hit)- 这个类向程序员提供了获取交集检测的基本数据的方法。交点类包括一条射线与场景中几何体相交的状态信息。尤为重要的是,它以Vec3的形式提供了局部和世界坐标的位置以及法线数据。它的成员方法getLocalIntersectPoint,getLocalIntersectNormal,getWorldIntersectPoint和getworldIntersectNormal分别以osg::Vec3作为返回值,返回局部/世界坐标的相交点/法线数值。

交点列表(osgUtil::IntersectVisitor::HitList)- 一条单一的线段可能与场景中的多个几何体实例(或者多次与同一个几何体)产生交集。对于每一条参与交集测试的线段,系统均会产生一个列表。这个列表包含了所有交集测试产生的Hit实例。如果没有监测到任何交集,该列表保持为空。

交集访问器(osgUtil::IntersectVisitor)- 射线与场景中几何体的交集测试由交集访问器来创建并实现初始化。IntersectionVisitor类继承自NodeVisitor类,因此其创建和触发机制与NodeVisitor实例大致相似。访问器需要维护一个进行交集测试的线段列表。而对于其中的每一条线段,访问器都会创建一个交点列表(osgUtil::IntersectVisitor::HitList实例)。

代码:
为了正确获取放置灌木模型所需的地形高度值,我们需要遵循下面的基本步骤:

创建一个LineSegment实例,它使用两个Vec3实例来定义交集测试所用射线的起点和终点。
创建一个IntersectVisitor实例。
将LineSegment实例添加到IntersectVisitor实例。
初始化IntersectVisitor实例,使其从场景图形中适当的节点开始遍历。
获取交集测试结果的世界坐标。
下面的代码演示了上述步骤的两种实现方式。第一部分是将单个LineSegment添加到IntersectVisitor,以判断坦克模型的放置高度是否正确。第二部分是将与告示牌节点相关的多个线段添加到IntersectVisitor,每一个线段实例均对应一个灌木告示牌对象。针对每个LineSegment执行与其关联的交集测试之后,我们既可正确地放置告示牌的位置了。

#include <ctime>
#include <cstdlib>
#include <iostream>
#include <osg/Geometry>
#include <osg/Texture2D>
#include <osg/Billboard>
#include <osg/BlendFunc>
#include <osg/AlphaFunc>
#include <osg/PositionAttitudeTransform>
#include <osgUtil/IntersectVisitor>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osgGA/TrackballManipulator>
#include <osgDB/FileUtils>

#define NUMBER_O_SHRUBS 1000

osg::Drawable* createShrub(const float & scale, osg::StateSet* bbState)
{
   float width = 1.5f;
   float height = 3.0f;

   width *= scale;
   height *= scale;

   osg::Geometry* shrubQuad = new osg::Geometry;

   osg::Vec3Array* shrubVerts = new osg::Vec3Array(4);
   (*shrubVerts)[0] = osg::Vec3(-width/2.0f, 0, 0);
   (*shrubVerts)[1] = osg::Vec3( width/2.0f, 0, 0);
   (*shrubVerts)[2] = osg::Vec3( width/2.0f, 0, height);
   (*shrubVerts)[3] = osg::Vec3(-width/2.0f, 0, height);

   shrubQuad->setVertexArray(shrubVerts);

   osg::Vec2Array* shrubTexCoords = new osg::Vec2Array(4);
   (*shrubTexCoords)[0].set(0.0f,0.0f);
   (*shrubTexCoords)[1].set(1.0f,0.0f);
   (*shrubTexCoords)[2].set(1.0f,1.0f);
   (*shrubTexCoords)[3].set(0.0f,1.0f);
   shrubQuad->setTexCoordArray(0,shrubTexCoords);

   shrubQuad->addPrimitiveSet(new osg::DrawArrays osg::PrimitiveSet::QUADS,0,4));

   shrubQuad->setStateSet(bbState);

   return shrubQuad;
}

int main( int argc, char **argv )
{
   osgViewer::Viewer viewer;

   osg::Group* rootNode = new osg::Group();
   osg::Node* tankNode = NULL;
   osg::Node* terrainNode = NULL;
   osg::PositionAttitudeTransform* tankXform =
      new osg::PositionAttitudeTransform();

   tankNode = osgDB::readNodeFile("\\Models\\T72-Tank\\T72-tank_des.flt");
   terrainNode = osgDB::readNodeFile("\\Models\\JoeDirt\\JoeDirt.flt");
   if (! (tankNode && terrainNode))
   {
      std::cout << "Couldn't load models, quitting." << std::endl;
      return -1;
   }
   rootNode->addChild(terrainNode);
   rootNode->addChild(tankXform);
   tankXform->addChild(tankNode);

最近VR访客


OSG中国官方网站:http://www.osgChina.org
OSG中国官方讨论区:http://bbs.osgChina.org

OSG专业群-OSG地形研究者 49668412
      OSG地形专业研究 45763709
obuil 评论于2007-12-21 14:37:41
好久没学了 支持flysky
liangyou2008 评论于2007-12-26 15:23:19
好帖,

手机版|VR开发网 统计 津ICP备18009691号
网安备12019202000257

GMT+8, 2021-4-22 10:49 PM

返回顶部