10,cookbook的lod示例

现在看下cookbook中的lod示例。

那么

一,lod和pagedlod有什么异同呢?

1,只考虑按视点远近进行判断。

Pagedlod是根据视点远近按需加载或者卸载场景的文件。

lod把场景中的精模简模都加载进来,按视点远近显隐。

复制代码
lod->setCenter(center);
lod->setRange(0, radius * 5.0f, FLT_MAX);
lod->setRange(1, 0.0f, radius * 5.0f);

level->insertChild(0, createBoxForDebug(total._max, total._min));
level->insertChild(1, group.get());
根据远处是简模,近处是精模,可以知道,盒子是简模,一系列group是精模

2,每级的group节点组成相同

(1)叶子节点

复制代码
	for (unsigned int i = 0; i < childData.size(); i++)
	{
		const ElementInfo& obj = childData[i];
		osg::Vec3 center = (obj.second._max + obj.second._min) * 0.5;
		float radius = (obj.second._max - obj.second._min).length() * 0.5f;
		group->addChild(createElement(obj.first, center, radius));
	}

(2)lod节点(或者PagedLod)

(3)lod节点(或者PagedLod)及叶子节点的混合

childNodesid = build(depth + 1, osg::BoundingBox(min, max), childData);

复制代码
	for (unsigned int i = 0; i < 8; i++)
	{
		if (childNodes[i] && childNodes[i]->getNumChildren())
		{
			group->addChild(childNodes[i]);
		}
	}

而build函数返回的是lod节点

复制代码
osg::LOD* level = createNewLevel(depth, center, radius);
level->insertChild(0, createBoxForDebug(total._max, total._min));
level->insertChild(1, group.get());

return level;

二,八叉树是什么呢?

我个人理解是将整个包围盒所在的元素,按照空间划分下去,直到叶子节点。xyz的维度是2X2X2(八叉树)

当然,也可以是其他任何一种维度相乘的空间划分,不一定是八叉树。比如四叉树。

那么什么时候才能到叶子节点呢?也就是递归结束呢?

答案是,该空间元素足够少,或者层级足够深

复制代码
if ((int) childData.size()<= _maxChildNumber|| depth > _maxTreeDepth)
{
	isLeafNode = true;
}

运行结果如下:



代码如下:

common.h

#pragma once

#include

#include <osg/Vec3>

#include <osg/PolygonMode>

#include <osg/ShapeDrawable>

#include <osg/Geometry>

#include <osg/Geode>

#include <osgDB/ReadFile>

#include <osgUtil/PrintVisitor>

#include <osgViewer/ViewerEventHandlers>

#include <osgViewer/Viewer>

#include

#include

#include

float randomValue(float minValue, float maxValue);

osg::Vec3 randomVector(float minValue, float maxValue);

common.cpp

#include "common.h"

float randomValue(float minValue, float maxValue)

{

return minValue + (float)rand() / (RAND_MAX + 1.0f) * (maxValue - minValue);

}

osg::Vec3 randomVector(float minValue, float maxValue)

{

return osg::Vec3(

randomValue(minValue, maxValue),

randomValue(minValue, maxValue),

randomValue(minValue, maxValue));

}

OctreeBuilder.h

#pragma once

#include "common.h"

class OctreeBuilder

{

protected:

osg::LOD* createNewLevel(int level, const osg::Vec3& center, float radius);

osg::Node* createElement(const std::string& od, const osg::Vec3& center, float radius);

osg::Geode* createBoxForDebug(const osg::Vec3& maxValue, const osg::Vec3& minValue);

复制代码
int _maxChildNumber;
int _maxTreeDepth;
int _maxLevel;

public:

OctreeBuilder()

{

_maxChildNumber = 16;

_maxTreeDepth = 32;

_maxLevel = 0;

}

int getMaxLevel() const

{

return _maxLevel;

}

void setMaxChildNumber(int maxValue)

{

_maxChildNumber = maxValue;

}

int getMaxChildNumber()

{

return _maxChildNumber;

}

void setMaxTreeDepth(int maxValue)

{

_maxTreeDepth = maxValue;

}

int getMaxTreeDepth() const

{

return _maxTreeDepth;

}

typedef std::pair<std::string, osg::BoundingBox> ElementInfo;

osg::Group* build(int depth, const osg::BoundingBox& total, std::vector& elements);

};

OctreeBuilder.cpp

#include "OctreeBuilder.h"

osg::LOD* OctreeBuilder::createNewLevel(int level, const osg::Vec3& center, float radius)

{

osg::ref_ptrosg::LOD lod = new osg::LOD;

lod->setCenterMode(osg::LOD::USER_DEFINED_CENTER);

lod->setCenter(center);

lod->setRadius(radius);

lod->setRange(0, radius * 5.0f, FLT_MAX);

lod->setRange(1, 0.0f, radius * 5.0f);

if (_maxLevel < level)

{

_maxLevel = level;

}

return lod.release();

}

osg::Node* OctreeBuilder::createElement(const std::string& id, const osg::Vec3& center, float radius)

{

osg::ref_ptrosg::Geode geode = new osg::Geode;

geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(center, radius)));

geode->setName(id);

return geode.release();

}

osg::Geode* OctreeBuilder::createBoxForDebug(const osg::Vec3& maxValue, const osg::Vec3& minValue)

{

osg::ref_ptrosg::Geode geode = new osg::Geode;

osg::Vec3 center = (maxValue + minValue) / 2.0;

float width = (maxValue - minValue).length() * 0.5;

//float width = 100;

geode->addDrawable(new osg::ShapeDrawable(new osg::Box(center, width)));

return geode.release();

}

osg::Group* OctreeBuilder::build(int depth, const osg::BoundingBox& total, std::vector& elements)

{

int s3;

osg::Vec3 extentSet3 =

{

total._min,

(total._max + total._min) * 0.5f,

total._max

};

std::vector childData;

for (unsigned int i = 0; i < elements.size(); i++)

{

const ElementInfo& obj = elementsi;

if (total.contains(obj.second._min) && total.contains(obj.second._max))

{

childData.push_back(obj);

}

else if (total.intersects(obj.second))

{

osg::Vec3 center = (obj.second._max + obj.second._min) * 0.5f;

if (total.contains(center))

{

childData.push_back(obj);

}

}

}

复制代码
bool isLeafNode = false;
if ((int) childData.size()<= _maxChildNumber|| depth > _maxTreeDepth)
{
	isLeafNode = true;
}
osg::ref_ptr<osg::Group> group = new osg::Group;
if (!isLeafNode)
{
	osg::ref_ptr<osg::Group> childNodes[8];
	for (s[0] = 0; s[0] < 2; s[0]++ )
		{
			for (s[1] = 0; s[1] < 2; s[1]++)
			{
				for (s[2] = 0; s[2] < 2; s[2]++)
				{
					osg::Vec3 min, max;
					for (int a = 0; a < 3; a++)
					{
						min[a] = (extentSet[s[a] + 0])[a];
						max[a] = (extentSet[s[a] + 1])[a];
					}
					int id = s[0] + (2 * s[1]) + 4 * s[2];
					childNodes[id] = build(depth + 1, osg::BoundingBox(min, max), childData);
				}
			}
		}

	for (unsigned int i = 0; i < 8; i++)
	{
		if (childNodes[i] && childNodes[i]->getNumChildren())
		{
			group->addChild(childNodes[i]);
		}
	}
}
else
{
	for (unsigned int i = 0; i < childData.size(); i++)
	{
		const ElementInfo& obj = childData[i];
		osg::Vec3 center = (obj.second._max + obj.second._min) * 0.5;
		float radius = (obj.second._max - obj.second._min).length() * 0.5f;
		group->addChild(createElement(obj.first, center, radius));
	}
}
osg::Vec3 center = (total._max + total._min) * 0.5;
float radius = (total._max - total._min).length() * 0.5f;
osg::LOD* level = createNewLevel(depth, center, radius);
level->insertChild(0, createBoxForDebug(total._max, total._min));
level->insertChild(1, group.get());

return level;

}

main.cpp

#include "OctreeBuilder.h"

int main()

{

osg::BoundingBox globalBound;

std::vectorOctreeBuilder::ElementInfo globalElements;

for (unsigned int i = 0; i < 5000; i++)

{

osg::Vec3 pos = randomVector(-500.0f, 500.0f);

float radius = randomValue(0.2f, 0.5f);

osg::Vec3 minValue = pos - osg::Vec3(radius, radius, radius);

osg::Vec3 maxValue = pos + osg::Vec3(radius, radius, radius);

osg::BoundingBox region(minValue, maxValue);

globalBound.expandBy(region);

std::string str = "Ball-" + std::to_string(i);

globalElements.push_back(OctreeBuilder::ElementInfo(str, region));

}

OctreeBuilder octree;

osg::ref_ptrosg::Group root = octree.build(0, globalBound, globalElements);

复制代码
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
viewer->setSceneData(root);
return viewer->run();

}

相关推荐
扶尔魔ocy3 天前
【qt openGL入门笔记】windows编译MinGW版本的osgearth(2.10.1)
qt·opengl·osg
扶尔魔ocy4 天前
【QT OpenGL】知识点编目及传送门
qt·opengl·osg
扶尔魔ocy17 天前
【qt openGL入门笔记】OSG实现飞机模型在网格图上飞行并进行态势标绘(四)
qt·opengl·osg
扶尔魔ocy19 天前
【qt openGL入门笔记】OSG实现显示飞机模型飞行的点迹(二)
qt·opengl·osg
扶尔魔ocy19 天前
【qt openGL入门笔记】OSG实现飞机模型在网格图上飞行(三)
opengl·osg
扶尔魔ocy20 天前
【qt openGL入门笔记】OSG实现飞机模型在网格图上飞行
qt·opengl·osg
directx3d_beginner8 个月前
8,将0级简模文件和精模文件同时放入pagedlod
osg
directx3d_beginner8 个月前
9,0级建模文件和0级精模文件写成根节点
osg
directx3d_beginner8 个月前
5,保存4个一级节点
osg