OSG 矢量贴地显示示例

#include <osg/Notify>
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include <osg/Geometry>
#include <osg/Geode>
#include <osg/ComputeBoundsVisitor>

#include <osgUtil/Optimizer>

#include <osgDB/Registry>
#include <osgDB/ReadFile>

#include <osgGA/TrackballManipulator>
#include <osgSim/OverlayNode>
#include <osgViewer/Viewer>

osg::AnimationPath* createAnimationPath(const osg::Vec3& center, float radius, double looptime)
{
	// set up the animation path
	osg::AnimationPath* animationPath = new osg::AnimationPath;
	animationPath->setLoopMode(osg::AnimationPath::LOOP);

	int numSamples = 40;
	float yaw = 0.0f;
	float yaw_delta = 2.0f*osg::PI / ((float)numSamples - 1.0f);
	float roll = osg::inDegrees(30.0f);

	double time = 0.0f;
	double time_delta = looptime / (double)numSamples;
	for (int i = 0; i < numSamples; ++i)
	{
		osg::Vec3 position(center + osg::Vec3(sinf(yaw)*radius, cosf(yaw)*radius, 0.0f));
		osg::Quat rotation(osg::Quat(roll, osg::Vec3(0.0, 1.0, 0.0))*osg::Quat(-(yaw + osg::inDegrees(90.0f)), osg::Vec3(0.0, 0.0, 1.0)));

		animationPath->insert(time, osg::AnimationPath::ControlPoint(position, rotation));

		yaw += yaw_delta;
		time += time_delta;

	}
	return animationPath;
}

osg::Node* createBase(const osg::Vec3& center, float radius)
{
	int numTilesX = 10;
	int numTilesY = 10;

	float width = 2 * radius;
	float height = 2 * 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 = 0; iy <= numTilesY; ++iy)
	{
		for (int ix = 0; 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 + 1;
	for (iy = 0; iy < numTilesY; ++iy)
	{
		for (int ix = 0; ix < numTilesX; ++ix)
		{
			osg::DrawElementsUShort* primitives = ((iy + ix) % 2 == 0) ? whitePrimitives.get() : blackPrimitives.get();
			primitives->push_back(ix + (iy + 1)*numIndicesPerRow);
			primitives->push_back(ix + iy * numIndicesPerRow);
			primitives->push_back((ix + 1) + iy * numIndicesPerRow);
			primitives->push_back((ix + 1) + (iy + 1)*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;
}

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("D:\\Project\\Data\\osg_data\\cessna.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("D:\\Project\\Data\\osg_data\\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->setMatrix(osg::Matrix::translate(-center * 0.6));

		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);
	}

	return model.release();
}


osg::ref_ptr<osg::Group> createModel(bool overlay, osgSim::OverlayNode::OverlayTechnique technique)
{
	osg::ref_ptr<osg::Node> cessna = osgDB::readRefNodeFile("D:\\Project\\Data\\osg_data\\lz.osg");
	osg::ComputeBoundsVisitor cbv;
	cessna->accept(cbv);
	osg::BoundingBox boundingBox = cbv.getBoundingBox();

	osg::Vec3 center(0.0f, 0.0f, 0.0f);
	float radius = 100.0f;

	osg::ref_ptr<osg::Group> root = new osg::Group;

	float baseHeight = center.z() - radius * 0.5;
	osg::ref_ptr<osg::Node> baseModel = createBase(osg::Vec3(center.x(), center.y(), baseHeight), radius);
	osg::ref_ptr<osg::Node> movingModel = createMovingModel(osg::Vec3(boundingBox.xMin(), boundingBox.yMin(),0.0), radius*0.8f);
	//osg::ref_ptr<osg::Node> movingModel = createMovingModel(center, radius*0.8f);

	if (overlay)
	{
		osgSim::OverlayNode* overlayNode = new osgSim::OverlayNode(technique);
		overlayNode->setContinuousUpdate(true);
		overlayNode->setOverlaySubgraph(new osg::Group);
		overlayNode->setOverlayBaseHeight(boundingBox.zMin());
		overlayNode->addChild(osg::ref_ptr<osg::Node>());
		//overlayNode->setOverlayBaseHeight(baseHeight - 0.01);
		//overlayNode->addChild(baseModel);
		root->addChild(overlayNode);

		osg::Group* group = dynamic_cast<osg::Group*>(overlayNode->getOverlaySubgraph());
		group->addChild(movingModel);

	}
	else
	{
		root->addChild(baseModel);
	}

	//root->addChild(movingModel);
	return root;
}


int main(int argc, char **argv)
{
	bool overlay = true;
	osg::ArgumentParser arguments(&argc, argv);
	while (arguments.read("--overlay")) overlay = true;

	osgSim::OverlayNode::OverlayTechnique technique = osgSim::OverlayNode::OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY;
	while (arguments.read("--object")) { technique = osgSim::OverlayNode::OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY; overlay = true; }
	while (arguments.read("--ortho") || arguments.read("--orthographic")) { technique = osgSim::OverlayNode::VIEW_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY; overlay = true; }
	while (arguments.read("--persp") || arguments.read("--perspective")) { technique = osgSim::OverlayNode::VIEW_DEPENDENT_WITH_PERSPECTIVE_OVERLAY; overlay = true; }

	// initialize the viewer.
	osgViewer::Viewer viewer;

	// load the nodes from the commandline arguments.
	osg::ref_ptr<osg::Group> model = createModel(overlay, technique);
	if (!model)
	{
		return 1;
	}

	// tilt the scene so the default eye position is looking down on the model.
	osg::ref_ptr<osg::MatrixTransform> rootnode = new osg::MatrixTransform;
	rootnode->setMatrix(osg::Matrix::rotate(osg::inDegrees(30.0f), 1.0f, 0.0f, 0.0f));
	rootnode->addChild(model);

	// run optimization over the scene graph
	osgUtil::Optimizer optimzer;
	optimzer.optimize(rootnode);

	// set the scene to render
	viewer.setSceneData(rootnode);
	viewer.setCameraManipulator(new osgGA::TrackballManipulator());

#if 0

	// use of custom simulation time.

	viewer.realize();

	double simulationTime = 0.0;

	while (!viewer.done())
	{
		viewer.frame(simulationTime);
		simulationTime += 0.001;
	}

	return 0;
#else

	// normal viewer usage.
	return viewer.run();

#endif
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
osgEarth是一个开源的地理空间引擎,它基于OpenSceneGraph(OSG)库,提供了一套用于创建地理可视化应用程序的工具和功能。osgEarth可以用于创建各种地理信息系统(GIS)应用程序,包括地图浏览、地形渲染、卫星图像显示等。 在osgEarth中,视口跟随模型是一种常见的功能,它可以使相机(视口)跟随指定的模型进行移动和旋转。下面是一个osgEarth视口跟随模型的示例代码: ```cpp #include <osgEarth/MapNode> #include <osgEarthUtil/EarthManipulator> #include <osgViewer/Viewer> int main(int argc, char** argv) { // 创建osgViewer::Viewer对象 osgViewer::Viewer viewer; // 创建osgEarth的地图节点 osg::ref_ptr<osgEarth::MapNode> mapNode = osgEarth::MapNode::create(); // 设置地图节点为场景根节点 viewer.setSceneData(mapNode.get()); // 创建osgEarth的地球操作器 osg::ref_ptr<osgEarth::Util::EarthManipulator> earthManipulator = new osgEarth::Util::EarthManipulator(); // 设置地球操作器为相机操作器 viewer.setCameraManipulator(earthManipulator.get()); // 创建一个模型节点 osg::ref_ptr<osg::Node> modelNode = osgDB::readNodeFile("path/to/your/model.osg"); // 将模型节点添加到地图节点中 mapNode->addChild(modelNode.get()); // 设置相机跟随模型 earthManipulator->setViewpointNode(modelNode.get()); // 运行osgViewer return viewer.run(); } ``` 上述示例代码中,首先创建了一个osgViewer::Viewer对象,并创建了osgEarth的地图节点。然后,将地图节点设置为场景根节点,并创建了osgEarth的地球操作器。接下来,创建了一个模型节点,并将其添加到地图节点中。最后,通过设置相机跟随模型,实现了视口跟随模型的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值