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)及叶子节点的混合

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

而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 s[3];

osg::Vec3 extentSet[3] =

{

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 = elements[i];

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

}

相关推荐
directx3d_beginner1 天前
8,将0级简模文件和精模文件同时放入pagedlod
osg
directx3d_beginner1 天前
9,0级建模文件和0级精模文件写成根节点
osg
directx3d_beginner2 天前
5,保存4个一级节点
osg
directx3d_beginner2 天前
1, pagedlod和lod
osg
CHPCWWHSU1 个月前
pointCloudExtractor:一个基于 osgPotree 的 Potree 点云数据提取工具
目标识别·osg·potree·点云提取
CHPCWWHSU2 个月前
CesiumforUnreal环境准备
c++·cesium·unreal·osg
妙为2 个月前
osgEarth中文显示乱码
中文乱码·osgearth·osg
CHPCWWHSU3 个月前
osg中文字的使用
osg·osgtext·text3d
CHPCWWHSU5 个月前
osg中相机矩阵到vsg相机矩阵的转换
opengl·osg·投影矩阵·vulkan·vsg