一个入门四叉树例子

H.266 JEM编码块结构:四叉树+二叉树QTBT 四叉树+二叉树QTBT编码结构,已经被JVET采纳加入到了新一代编码标准和JEM中。 阅读详情

概述: 

      一个四叉树读书笔记

     源代码: http://www.pudn.com/downloads343/sourcecode/windows/opengl/detail1500968.html

 

正文:

      首先四叉树结构

typedef struct _QNode_{

	unsigned int	*m_tri_indexes;				//地形的索引序列
	
	unsigned int	m_num_triangles;			//该节点含有的三角面片数,可能为0

	Vector3	        m_min, m_max;		                 //X Z 平面的包围盒

	struct _QNode_	*m_children[4];				//所包含的子节点


}QNode;

基础地形数据的建立:

    创建一个Row*Col的网格,毋庸置疑,他包含了(Row-1)* (Col-1)个有效的三维顶点,包含(Row-1) * (Col-1)  * 2个三角形一个网格由两个三角形来表示,要表示这些三角形,则需要 (Row-1) * (Col-1)  * 2 * 3 个索引来表示。

   值得一提的是本例子采用的三角形索引顶点存储顺序如图所示:

             三角形索引序列为: 以一个网格为例 右上角三角形(i,j),(i+1,j+1) , (i+1,j+0),
左下角三角形 (i,j+1),(i+1,j+1),(i,j) 索引序列存储的是连续的三角形(以第一个顶点为标记),

依次类推…..


创建节点树

 

1 四叉树由上到下建立,从根节点开始,通过遍历顶点的X,Z,将整张地形的大小赋值给根节点。

 

2,根节点包围盒宽高,根据包围盒的起始位置,将其分割为四个子节点。一次判断对应子节点中包围盒中对应的位置包含的三角面片数来确定是否继续分割,本例的分割三角面片数为500个

 

主:应为每次为子节点添加实际的三角面片时,都需遍历整个网格,为了提高效率,了一个标记为存储已经归档的是三角顶点,在顶点遍历的过程中提前进行筛选已经遍历过的顶点

顶点索引很好判断:原始的顶点索引是以第一个顶点确定三角面片,索引只要知道某一个顶点在包围盒内,后边连续两个索引即为组成三角面片的三个索引。

 

这样顶点编译进四叉树中了


进入渲染

首先进入根节点:

1,判断当前视点是否在节点范围内,不在,则推出,不渲染

2,判断当前视角到节点的距离是否超过最小视距,如果是,退出渲染

这里提一下如何判断视点到节点(平面包围盒的距离)

:计算平面包围盒的四条线,依次判视点到线的距离,取其最短一点,

最短距离不是视点到包围盒中心平面的投影?

3  如果包围四个顶点到到视点的方向与视点方向的夹角超过82度,则退出渲染


渲染技术点:

点到线的最短距离判断

void QuadTree::ClosestPointOnLine(Vector3 *start, Vector3 *end, Vector3 *point, Vector3 *result)
{
    Vector3  c,                          // vector from a->p
            ev,                         // vector from a->b
            pv;                         // projection of a->p onto a->b

    float   d,                          // length of vector from a->b (distance from start to end of line)
            t;                          // amount of c that projects onto ev

    // Get vector from point to start of line
	c.x = point->x - start->x;
	//c.y = point->y - start->y;			//quick speedup. Quadtrees ignore Y!
	c.z = point->z - start->z;

	
    // Get edge vector
	ev.x = end->x - start->x;
	//ev.y = end->y - start->y;				//quick speedup. Quadtrees ignore Y!
	ev.z = end->z - start->z;

    

    // find length of ev
	d = sqrtf(ev.x*ev.x + ev.z*ev.z);		//quick speedup. Quadtrees ignore Y!
    
    // Normalise ev
    ev.x /= d;
    //ev.y /= d;							//quick speedup. Quadtrees ignore Y!
    ev.z /= d;

    // Calculate projection of vector from start to point (c) onto line (ev)
	t = (ev.x*c.x) + (ev.z*c.z);			//quick speedup. Quadtrees ignore Y!
    

    // Check that projection amount (t) is within range 0 < t < d
    // n.b. 0 = start of line, d = length of line
    if (t < 0)
    {
        // closest point is start of line
        *result = *start;
        return;
    }

    if (t > d)
    {
        // closest point is end of line
        *result = *end;
        return;
    }

    // Closest point is somewhere on the line
    // Calculate projected vector using amount & normalised edge vector
	pv.x = ev.x * t;
	//pv.y = ev.y * t;						//quick speedup. Quadtrees ignore Y!
	pv.z = ev.z * t;

	

    // Closest point on line is start + projected vector
	result->x = start->x + pv.x;
	//result->y = start->y + pv.y;			//quick speedup. Quadtrees ignore Y!
	result->y = 0.0f;
	result->z = start->z + pv.z;
}

节点视距的角度判断

bool QuadTree::NodeIsBehind(QNode *node, Vector3 *pos, Vector3 *at)
{
	//Calculate the angle from at, to node corners.

	Vector3 points[4], v;


	points[0].x = node->m_min.x;
	points[0].z = node->m_min.z;

	points[1].x = node->m_max.x;
	points[1].z = node->m_min.z;

	points[2].x = node->m_min.x;
	points[2].z = node->m_max.z;

	points[3].x = node->m_max.x;
	points[3].z = node->m_max.z;



	for(int i=0; i<4; i++)
	{
		v.x = points[i].x - pos->x;
		v.z = points[i].z - pos->z;

		//normalize.
		float mag = (v.x * v.x) + (v.z * v.z);
		mag = 1.0f / sqrtf(mag);

		v.x *= mag;
		v.z *= mag;

		//do dot product.
		float dot = (v.x * at->x) + (v.z * at->z);

		float angle = (float) acos(dot);

		angle *= 180.0f / 3.14592f;

		if(angle < 82.0f)
		{
			return false;
		}
	}

	return true;

}

视点到节点包围盒的距离

float QuadTree::DistFromPoint(QNode *node, Vector3 *pos)
{//This function calcs the distance between pos, and the node, at the closest point, checks all 4 lines aroun
 //bounding box of node.

	Vector3 v, points[4], p;
	float distance[4], ret_dist;
	int i;


	//Get the 4 points of the bounding box.
	points[0].x = node->m_min.x;			points[0].z = node->m_min.z;
	points[1].x = node->m_max.x;			points[1].z = node->m_max.z;

	points[2].x = node->m_min.x;			points[2].z = node->m_max.z;
	points[3].x = node->m_max.x;			points[3].z = node->m_min.z;


	// speedup hacks here, by ignoring Y.
	ClosestPointOnLine(&points[0], &points[3], pos, &p);
	v.x = p.x - pos->x;
	v.z = p.z - pos->z;
	distance[0] = (v.x * v.x) + (v.z * v.z);

	ClosestPointOnLine(&points[0], &points[2], pos, &p);
	v.x = p.x - pos->x;
	v.z = p.z - pos->z;
	distance[1] = (v.x * v.x) + (v.z * v.z);

	ClosestPointOnLine(&points[1], &points[3], pos, &p);
	v.x = p.x - pos->x;
	v.z = p.z - pos->z;
	distance[2] = (v.x * v.x) + (v.z * v.z);

	ClosestPointOnLine(&points[2], &points[1], pos, &p);
	v.x = p.x - pos->x;
	v.z = p.z - pos->z;
	distance[3] = (v.x * v.x) + (v.z * v.z);


	ret_dist = distance[0];

	for(i=1; i<4; i++)
	{
		if(distance[i] < ret_dist)
		{
			ret_dist = distance[i];
		}
		
	}

	ret_dist = sqrtf(ret_dist);			//Square root it.
	/*printf("\n distance to camera = %f ", ret_dist);*/
	return ret_dist;
}

主要做了什么:

1 以四叉树结构来组织顶点数据,三角数据

2 通过视点与四叉树的包围盒进行数据筛选,优化加载

 

缺点:

1,没有LOD

2,筛选判断过于简单主要体现在节点包围盒与视距的距离判断,尤其是节点是否在视距范围内的判断

3,数据是一次性载入内存的,对于大数据不吭能叫所有顶点都放入内存中



四叉树编码实现 关于四叉树的原理我想应该不需要多说啦,大家都懂得,实在不晓得的话,百度吧~ 由于四叉树索引效率还可以并且非常简单,因此在Gis中广泛的应用也是毋庸置疑的。   本次就自己实现一个地图四叉树索引,但是还有一些问题也希望各位路过的大神能指点一下。   首先,结合一下应用场景(我们需要用四叉树来索引地图数据),考虑一下使用四叉树索引地图数据存在的一些问题。 1.什么时候建立四叉树索引,四叉树 阅读详情

相关推荐

四叉树索引

 四叉树索引(Quadtree),类似于前面介绍的网格索引,也是对地理空间进行网格划分,对地理空间递归进行四分来构建四叉树,本文将在普通四叉树的基础上,介绍一种改进的四叉树索引结构。       首先,先介绍一个GIS(Geographic Information System)或者计算机图形学上非常重要的概念——最小外包矩形(MBR-Minimum Bounding Rectangle)

sjzwl的专栏 5681

iOS LeetCode ☞ 建立四叉树

给你一个 n * n 矩阵 grid ,矩阵由若干 0 和 1 组成。请你用四叉树表示该矩阵 grid 。 你需要返回能表示矩阵的 四叉树 的根结点。 注意,当 isLeaf 为 False 时,你可以把 True 或者 False 赋值给节点,两种值都会被判题机制 接受 。 四叉树数据结构中,每个内部节点只有四个子节点。此外,每个节点都有两个属性: val:储存叶子结点所代表的区域的值。1 对应 True,0 对应 False; isLeaf: 当这个节点是一个叶子结点时为 True,如果它有 4 个子

HumorousGhost 2320

Unity四叉树地图

当使用Unity构建大规模的游戏地图或场景时,使用四叉树数据结构可以提高性能和效率。四叉树是一种基于分割的数据结构,将空间划分为四个相等的子区域,并以递归方式构建树结构。在游戏开发中,四叉树常用于空间分区、碰撞检测和可视化剔除等方面。

Asklyw的博客 3576

【leetcode刷题】[简单]427. 建立四叉树(construct quad tree)-java

建立四叉树 construct quad tree题目分析解答 题目 我们想要使用一棵四叉树来储存一个 N x N 的布尔值网络。网络中每一格的值只会是真或假。树的根结点代表整个网络。对于每个结点, 它将被分等成四个孩子结点直到这个区域内的值都是相同的. 每个结点还有另外两个布尔变量: isLeaf 和 val。isLeaf 当这个节点是一个叶子结点时为真。val 变量储存叶子结点所代表的区域的值...

mikuluna的博客 3482

四叉树编码的原理

文档主要描述四叉树的思想的原理,能清除的给读者知道四叉树的来龙去脉,因此,不懂此原理的朋友可下载。

图像数据结构图遍历算法四叉树

vc++实现图像数据结构图遍历算法四叉树等

一个线性四叉树编码的试题

这个应该是压缩后的图像。计算过程。1 一维数组 十进制M码 M 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1...

GIS骆驼的GIS博客 3万+

四叉树编码

基于十进制实现四叉树的编码,以moton码存储属性数据的行列号

地理信息系统原理-空间数据结构(7)

指针不仅增加了数据的存储量,还增加了操作的复杂性:如层次数(分割次数)由从父结点移到根结点的次数来确定,结点所代表的图像块的位置需要从根节点开始逐步推算下来。④如何计算莫顿码:如图所示,通常是将栅格数据十进制的行列号,转成二进制的行列号,再将二进制的行号和列号进行错位交叉排列,得到二进制的莫顿码,再将二进制的莫顿码转成十进制的莫顿码。(1) 常规四叉树(记录这棵树的叶结点外,中间结点,结点之间的联系用指针联系,每个结点需要6个变量:父结点指针、四个子结点的指针和本结点的属性值。

lntu_ling 8919

打造你自己的小程序容器 —— 一套能装得下整个未来的跨端技术!

摘要: 本文介绍了一种基于Capacitor框架开发的轻量级“小程序容器”解决方案——LapDrop。通过模拟微信小程序的运行逻辑(动态加载、原生能力调用、沙盒环境),LapDrop允许开发者自主构建跨平台(iOS/Android/Web)的小程序生态。其核心利用Capacitor的插件桥接机制,实现JS与原生功能的无缝调用,并支持浏览器调试与原生环境一致化。优势包括插件化架构、状态隔离、热更新及开放权限控制,适用于企业级模块化应用或开发者工具。未来计划扩展生命周期管理、远程加载等功能,目标成为开源的小程序

CangYuChenAi的博客 975

嵌入式环境下XML配置文件解析实践

在资源受限的嵌入式环境中,如何轻量级地解析XML配置文件成为关键。通过简化语法结构与优化内存使用,实现快速读取和解析配置文件,提升系统启动效率与稳定性。

weixin_31869917的博客 400

四叉树算法

title: 四叉树算法 date: 2016-1-11 15:10 categories: IOS tags: 算法 小小程序猿 我的博客:http://daycoding.com 转载:http://blog.youkuaiyun.com/zhanxinhang/article/details/6706217 高德iOS聚合实例 高德Android聚合实例 四叉树或四元树也被称为Q树(Q-T

小小程序猿 2万+

实战指南 | 快速修复Adobe Acrobat 2020安装过程中的常见注册表错误

本文提供了Adobe Acrobat 2020安装过程中遇到“无法打开键”注册表错误的详细修复指南。通过安全编辑注册表,精准定位并删除残留键值,可快速解决此常见安装报错,确保软件顺利安装。同时,文章也介绍了其他安装问题的应对策略与预防措施。

weixin_29200485的博客 562

四叉树C#实现

四叉树是用于二维空间对象查找的一个数据结构,本实现包括了三个类:QuadTree,QuadTreeNode, QuadNodeItem。见名思意用于对外提供构建和查找功能的接口都定义在泛型的QuadTree中,QuadTreeNode类和QuadNodeItem类都做为QuadTree类的内部类型实现,对外不可见。

草莽的专栏 9881

Android AVB 分析(十六)5 个例子彻底理解 FEC(Reed-Solomon) 的工作原理

关于 FEC 是如何工作的,一直是我 Android OTA 讨论群中的未解话题,大家基本上都不清楚 Android 上面的 FEC 是如何工作的,为什么在 OTA 升级的最后阶段,FEC 的编码计算会消耗大量的 IO 资源,并持续很长时间。接下来的几篇,我会从一个程序员的角度,演示基于里德所罗门编码的 FEC 到底是如何工作的。

洛奇看世界 668

C# 上位机程序中的数据采集与存储技术:从采集到持久化的完整解决方案

本文系统讲解C#上位机程序如何实现设备数据采集与持久化。主要内容包括:1)多种数据采集方式(串口通信、Modbus、OPC等)及代码示例;2)详细对比不同存储技术(CSV、SQLite、关系型数据库等)的优缺点;3)提供SQLite等存储实现代码;4)推荐分层系统架构(采集-缓存-存储-可视化);5)性能优化建议(多线程采集、异步存储、批量写入等)。文章强调应根据项目需求选择合适的技术方案,构建高效稳定的数据采集存储闭环系统。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1025

四叉树 相关内容

///////////////////////////////////////////////////////////////////////////// 四叉树索引的基本思想是将地理空间递归划分为不同层次的树结构。它将已知范围的空间等分成四个相等的子空间,如此递归下去,直至树的层次达到一定深度或者满足某种要求后停止分割。四叉树的结构比较简单,并且当空间数据对象分布比较均匀时,具有比较高的空间数据插入和查询效率,因此四叉树是GIS中常用的空间索引之一。常规四叉树的结构如图所示,地理空间对象都存储在叶子..

蛰伏--当你不够强大时,就不要放弃努力 6165

基于sklearn实现LDA主题模型(附实战案例)

目录LDA主题模型1.LDA主题模型原理2.LDA主题模型推演过程3.sklearn实现LDA主题模型(实战)3.1数据集介绍3.2导入数据3.3分词处理 3.4文本向量化3.5构建LDA模型3.6LDA模型可视化 3.7困惑度 其实说到LDA能想到的有两个含义,一种是线性判别分析(Linear Discriminant Analysis),一种说的是概率主题模型:隐含狄利克雷分布(Latent Dirichlet Allocation,简称LDA)。 现在讨论的是主题模型

m0_64336780的博客 2万+

空间索引 - 四叉树

前言 作为程序员,应该都对二叉树都不陌生,我们都知道二叉树的变体二叉查找树,非常适合用来进行对一维数列的存储和查找,可以达到 O(logn) 的效率;我们在用二叉查找树进行插入数据时,根据一个数据的值和树结点值的对比,选择二叉树的两个叉之一向下,直到叶子结点,查找时使用二分法也可以迅速找到需要的数据。 但二叉树只支持一维数据,如一个标量数值,对地图上的位置点这种有xy两个方向上的信息却无能为力,那么是否有一种树能够支持二维数据的快速查询呢? 四叉树 介绍 四元树又称四叉树是一种树状数据结构,在每

woaitingting1985的博客 2735

SAP S/4 FICO科目辅助余额表开发说明书(包括测试样例、程序代码仅作参考,不保证一定可以运行)

SAP S/4 FICO科目辅助余额表开发说明书(包括测试样例、程序代码仅作参考,不保证一定可以运行)

我好像病了的博客 329

树莓派 Raspberry Pi 使用 YOLOv8 YOLOv10 YOLOv11进行目标检测及推理加速,Run YOLOv8 YOLOv10 YOLOv11 on Raspberry Pi

libcamera 是 linux 新增加用于访问 camera 的 API。树莓派参与了 libcamera 的开发,并且在新的摄像头软件中开始从依赖于固件的摄像头图像处理管道(Image processing pipeline, ISP)迁移到更加开放的 libcamera。当然这块用USB 摄像头应该也是可以的。

shiter编写程序的艺术 5568

一个四叉树Demo学习(C#)

程序代码: http://www.codeproject.com/Articles/30535/A-Simple-QuadTree-Implementation-in-C 四叉树: using System; using System.Drawing; using System.Collections.Generic; using System.Diagnostics; names...

小胖七少爷的博客 2247

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

在Unity中使用四叉树算法绘制地形

四叉树算法在游戏中获得了广泛的应用,前几年3D引擎实现的地形绘制大部分都是用四叉树生成的,因为移动端在硬件方面的限制,我们的地形使用的是美术自己制作的地形,对于程序来说省去了不少工作量,但是作为程序开发者尤其是想从事引擎开发的程序员,我们还是要自己实现一遍四叉树算法的,其实网上很多资料都有C++ OpenGL或者C++ DX实现的四叉树地形。很多引擎的地形它也是在四叉树的基础上改进而成,如果我们想...

海洋个人博客 8518

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

四叉树

前序 四叉树或四元树也被称为Q树(Q-Tree)。四叉树广泛应用于图像处理、空间数据索引、2D中的快速碰撞检测、存储稀疏数据等,而八叉树(Octree)主要应用于3D图形处理。对游戏编程,这会很有用。本文着重于对四叉树与八叉树的原理与结构的介绍,帮助您在脑海中建立四叉树与八叉树的基本思想。本文并不对这两种数据结构同时进行详解,而只对四叉树进行详解,因为八叉树的建立可由四叉树的建立推得。...

weixin_30487201的博客 2884

558. 四叉树交集

四叉树是一种树数据,其中每个结点恰好有四个子结点:topLeft、topRight、bottomLeft和bottomRight。四叉树通常被用来划分一个二维空间,递归地将其细分为四个象限或区域。 我们希望在四叉树中存储 True/False 信息。四叉树用来表示 N * N 的布尔网格。对于每个结点, 它将被等分成四个孩子结点直到这个区域内的值都是相同的。每个节点都有另外两个布尔属性:is...

Umbrella Corporation 7225

松散四叉树实战

本文介绍了四叉树,松散四叉树概念,并进一步给出相关的参考资料和代码。通过阅读这篇文章可以让你了解并实现自己四叉树~~~

Ron的专栏 2950
上一篇: LOD四叉树一些笔记
下一篇: osg_beginer_guider_Chapter 5: Managing Scene Graph
CCCStudyer
博客等级 码龄16年 14粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值