【Overload游戏引擎】源码分析之五:OvRendering函数库(三)

2021SC@SDUSC

目录

IMesh.h与Mesh.h

1.CreateBuffers

2.ComputeBoundingSphere

3.其他函数


回顾一下前几篇文章,我们讲到了有关图形学三维空间的变换与各种数据存储对象的信息,接下来就是关于三维空间中物体的网格表示。

IMesh.h与Mesh.h

与网格相关的类有两个其中IMesh是一个基类,定义了4个纯虚函数用于子类继承。

namespace OvRendering::Resources
{
	/**
	* Interface for any mesh
	*/
	class IMesh
	{
	public:
		virtual void Bind() = 0;
		virtual void Unbind() = 0;
		virtual uint32_t GetVertexCount() = 0;
		virtual uint32_t GetIndexCount() = 0;
	};
}

而重点则是以下这个Mesh类,它对IMesh进行公有继承,用于实现网格的相关操作。

class Mesh : public IMesh
	{
	public:
		Mesh(const std::vector<Geometry::Vertex>& p_vertices, const std::vector<uint32_t>& p_indices, uint32_t p_materialIndex);
		virtual void Bind() override;
		virtual void Unbind() override;
		virtual uint32_t GetVertexCount() override;
		virtual uint32_t GetIndexCount() override;
		uint32_t GetMaterialIndex() const;
		const OvRendering::Geometry::BoundingSphere& GetBoundingSphere() const;

	private:
		void CreateBuffers(const std::vector<Geometry::Vertex>& p_vertices, const std::vector<uint32_t>& p_indices);
		void ComputeBoundingSphere(const std::vector<Geometry::Vertex>& p_vertices);

	private:
		const uint32_t m_vertexCount;
		const uint32_t m_indicesCount;
		const uint32_t m_materialIndex;

		Buffers::VertexArray							m_vertexArray;
		std::unique_ptr<Buffers::VertexBuffer<float>>	m_vertexBuffer;
		std::unique_ptr<Buffers::IndexBuffer>			m_indexBuffer;

		Geometry::BoundingSphere m_boundingSphere;
	};

Mesh类中包含了以下几个成员变量:

m_vertexCount:网格中的顶点个数;

m_indicesCount:顶点索引个数;

m_materialIndex:材质索引个数; 

m_vertexArray:顶点数组对象;

m_vertexBuffer:顶点缓冲对象;

m_indexBuffer:索引缓冲对象;

m_boundingSphere:当前网格的碰撞球对象。

这里我们看到一个新的数据类型unique_ptr,它是 C++ 11 提供的用于防止内存泄漏的智能指针中的一种实现,独享被管理对象指针所有权的智能指针。unique_ptr对象包装一个原始指针,并负责其生命周期。当该对象被销毁时,会在其析构函数中删除关联的原始指针。
unique_ptr具有->和*运算符重载符,因此它可以像普通指针一样使用。

总的来说就是比起从前的new指针,unique_ptr对象更为安全,这里作了解就好。

这些数据类型在前文都有提及,此处就不再赘述,紧接着我们来看Mesh类的两个重要的私有函数:

1.CreateBuffers

首先我们来看CreateBuffers函数,它的作用在于为传入的网格顶点数据创建一个缓冲。我们看一看到,CreateBuffers函数的两个参数分别是一个顶点向量(相当于一个2维矩阵),以及一个索引向量。

在函数开头,创建了一个浮点向量用于存储顶点数据,然后是一个无符号整型向量用于存储索引数据。

void OvRendering::Resources::Mesh::CreateBuffers(const std::vector<Geometry::Vertex>& p_vertices, const std::vector<uint32_t>& p_indices)
{
	std::vector<float> vertexData;

	std::vector<unsigned int> rawIndices;

然后函数开始了一个遍历过程,在这个地方有一个语句for(auto &a:b),这个语句可以利用a容器来遍历b中的内容,同时可以利用a对b的值做出改变。

for (const auto& vertex : p_vertices)
	{
		vertexData.push_back(vertex.position[0]);
		vertexData.push_back(vertex.position[1]);
		vertexData.push_back(vertex.position[2]);

		vertexData.push_back(vertex.texCoords[0]);
		vertexData.push_back(vertex.texCoords[1]);

		vertexData.push_back(vertex.normals[0]);
		vertexData.push_back(vertex.normals[1]);
		vertexData.push_back(vertex.normals[2]);

		vertexData.push_back(vertex.tangent[0]);
		vertexData.push_back(vertex.tangent[1]);
		vertexData.push_back(vertex.tangent[2]);

		vertexData.push_back(vertex.bitangent[0]);
		vertexData.push_back(vertex.bitangent[1]);
		vertexData.push_back(vertex.bitangent[2]);
	}

在以下for循环中,函数利用变量vertex来存储p_vertices的数据,然后将vertex中的位置信息(position)、纹理坐标(texCoords)、法向量(normals)、切向量(tangent)、侧切向量(bitangent)等信息依次压入vertexData中。利用这个过程将多个变量转为一个变量,方便后期读取。

之后,为vertexData创建一个VBO顶点缓冲对下,并利用make_unique函数(一个创建unique_ptr智能指针的函数)创建一个指向该VBO的指针。

同样的也为索引向量创建上述的索引缓冲指针。

    m_vertexBuffer	= std::make_unique<Buffers::VertexBuffer<float>>(vertexData);
	m_indexBuffer	= std::make_unique<Buffers::IndexBuffer>(const_cast<uint32_t*>(p_indices.data()), p_indices.size());

最后,将VBO中的顶点数据与VAO(即变量m_vertexArray)绑定,并配置顶点信息读取格式。

在这里我们简单来看看,VBO的第一组信息是位置坐标position,所以读取信息的指针为0号,顶点数据来源为VBO _mvertexBuffer,OpenGL特定数据类型为GL_Float,每组数据的长度为3个单位数据,步长为一个vertex结构体所占的字节数。

    uint64_t vertexSize = sizeof(Geometry::Vertex);

	m_vertexArray.BindAttribute(0, *m_vertexBuffer, Buffers::EType::FLOAT, 3, vertexSize, 0);
	m_vertexArray.BindAttribute(1, *m_vertexBuffer,	Buffers::EType::FLOAT, 2, vertexSize, sizeof(float) * 3);
	m_vertexArray.BindAttribute(2, *m_vertexBuffer,	Buffers::EType::FLOAT, 3, vertexSize, sizeof(float) * 5);
	m_vertexArray.BindAttribute(3, *m_vertexBuffer,	Buffers::EType::FLOAT, 3, vertexSize, sizeof(float) * 8);
	m_vertexArray.BindAttribute(4, *m_vertexBuffer,	Buffers::EType::FLOAT, 3, vertexSize, sizeof(float) * 11);

后面的以此类推。

2.ComputeBoundingSphere

接下来是ComputeBoundingSphere函数,该函数的作用是对于一组网格顶点数据计算其碰撞球的中心点与半径。

具体的思路很简单,首先,为碰撞球赋一个初值,坐标为原点,半径为0。

void OvRendering::Resources::Mesh::ComputeBoundingSphere(const std::vector<Geometry::Vertex>& p_vertices)
{
	m_boundingSphere.position = OvMaths::FVector3::Zero;
	m_boundingSphere.radius = 0.0f;

然后,将C++标准模板库的float型数据最大值分别赋值给初始最小坐标minX、minY、minZ;同样将最小值赋值给初始最大坐标maxX、maxY、maxZ。

接着利用上文提到的for语句对p_vertices的数据进行遍历,在访问每一个顶点数据时,将最小坐标的3的分量与当前顶点坐标的3个分量进行比较,选择更小的一方更新最小坐标值;同样最大坐标值进行类似处理,只不过是利用更大的值更新变量。

	if (!p_vertices.empty())
	{
		float minX = std::numeric_limits<float>::max();
		float minY = std::numeric_limits<float>::max();
		float minZ = std::numeric_limits<float>::max();

		float maxX = std::numeric_limits<float>::min();
		float maxY = std::numeric_limits<float>::min();
		float maxZ = std::numeric_limits<float>::min();

		for (const auto& vertex : p_vertices)
		{
			minX = std::min(minX, vertex.position[0]);
			minY = std::min(minY, vertex.position[1]);
			minZ = std::min(minZ, vertex.position[2]);

			maxX = std::max(maxX, vertex.position[0]);
			maxY = std::max(maxY, vertex.position[1]);
			maxZ = std::max(maxZ, vertex.position[2]);
		}

完成上述过程后,就会得到一个网格所能接触的最大与最小的坐标值分量。 

最后,将最大值与最小值求平均,得到的3个坐标分量就是当前网格的碰撞球的中心点;同时再度遍历所有顶点,将该顶点到碰撞球中心的距离,与当前碰撞球半径作比较,去最大值更新碰撞球半径。

		m_boundingSphere.position = OvMaths::FVector3{ minX + maxX, minY + maxY, minZ + maxZ } / 2.0f;

		for (const auto& vertex : p_vertices)
		{
			const auto& position = reinterpret_cast<const OvMaths::FVector3&>(vertex.position);
			m_boundingSphere.radius = std::max(m_boundingSphere.radius, OvMaths::FVector3::Distance(m_boundingSphere.position, position));
		}
	}
}

如此,便完成了网格碰撞球的计算。

3.其他函数

剩下的函数与前文提到的一些函数大同小异,都是对一些具体函数进行二次封装,在这里,就不做太多介绍。有一点需要注意的是,其中的一些函数是对IMesh基类中的纯虚函数的重定义,如果Mesh类中没有完成该操作,就会产生错误。

OvRendering::Resources::Mesh::Mesh(const std::vector<Geometry::Vertex>& p_vertices, const std::vector<uint32_t>& p_indices, uint32_t p_materialIndex) :
	m_vertexCount(static_cast<uint32_t>(p_vertices.size())),
	m_indicesCount(static_cast<uint32_t>(p_indices.size())),
	m_materialIndex(p_materialIndex)
{
	CreateBuffers(p_vertices, p_indices);
	ComputeBoundingSphere(p_vertices);
}

void OvRendering::Resources::Mesh::Bind()
{
	m_vertexArray.Bind();
}

void OvRendering::Resources::Mesh::Unbind()
{
	m_vertexArray.Unbind();
}

uint32_t OvRendering::Resources::Mesh::GetVertexCount()
{
	return m_vertexCount;
}

uint32_t OvRendering::Resources::Mesh::GetIndexCount()
{
	return m_indicesCount;
}

uint32_t OvRendering::Resources::Mesh::GetMaterialIndex() const
{
	return m_materialIndex;
}

const OvRendering::Geometry::BoundingSphere& OvRendering::Resources::Mesh::GetBoundingSphere() const
{
	return m_boundingSphere;
}

内容概要:本文介绍了一个基于冠豪猪优化算法(CPO)的无人机维路径规划项目,利用Python实现了在复杂维环境中为无人机规划安全、高效、低能耗飞行路径的完整解决方案。项目涵盖空间环境建模、无人机动力学约束、路径编码、多目标代价函数设计以及CPO算法的核心实现。通过体素网格建模、动态障碍物处理、路径平滑技术和多约束融合机制,系统能够在高维、密集障碍环境下快速搜索出满足飞行可行性、安全性与能效最优的路径,并支持在线重规划以适应动态环境变化。文中还提供了关键模块的代码示例,包括环境建模、路径评估和CPO优化流程。; 适合人群:具备一定Python编程基础和优化算法基础知识,从事无人机、智能机器人、路径规划或智能优化算法研究的相关科研人员与工程技术人员,尤其适合研究生及有一定工作经验的研发工程师。; 使用场景及目标:①应用于复杂维环境下的无人机自主导航与避障;②研究智能优化算法(如CPO)在路径规划中的实际部署与性能优化;③实现多目标(路径最短、能耗最低、安全性最高)耦合条件下的工程化路径求解;④构建可扩展的智能无人系统决策框架。; 阅读建议:建议结合文中模型架构与代码示例进行实践运行,重点关注目标函数设计、CPO算法改进策略与约束处理机制,宜在仿真环境中测试不同场景以深入理解算法行为与系统鲁棒性。
在科技快速演进的时代背景下,移动终端性能持续提升,用户对移动应用的功能需求日益增长。增强现实、虚拟现实、机器人导航、自动驾驶辅助、手势识别、物体检测与距离测量等前沿技术正成为研究与应用的热点。作为支撑这些技术的核心,双目视觉系统通过模仿人类双眼的成像机制,同步获取两路图像数据,并借助图像处理与立体匹配算法提取场景深度信息,进而生成点云并实现维重建。这一技术体系对提高移动终端的智能化程度及优化人机交互体验具有关键作用。 双目视觉系统需对同步采集的两路视频流进行严格的时间同步与空间校正,确保图像在时空维度上精确对齐,这是后续深度计算与立体匹配的基础。立体匹配旨在建立两幅图像中对应特征点的关联,通常依赖复杂且高效的计算算法以满足实时处理的要求。点云生成则是将匹配后的特征点转换为维空间坐标集合,以表征物体的立体结构;其质量直接取决于图像处理效率与匹配算法的精度。维重建基于点云数据,运用计算机图形学方法构建物体或场景的维模型,该技术在增强现实与虚拟现实等领域尤为重要,能够为用户创造高度沉浸的交互环境。 双目视觉技术已广泛应用于多个领域:在增强现实与虚拟现实中,它可提升场景的真实感与沉浸感;在机器人导航与自动驾驶辅助系统中,能实时感知环境并完成距离测量,为路径规划与决策提供依据;在手势识别与物体检测方面,可精准捕捉用户动作与物体位置,推动人机交互设计与智能识别系统的发展。此外,结合深度计算与点云技术,双目系统在精确距离测量方面展现出显著潜力,能为多样化的应用场景提供可靠数据支持。 综上所述,双目视觉技术在图像处理、深度计算、立体匹配、点云生成及维重建等环节均扮演着不可或缺的角色。其应用跨越多个科技前沿领域,不仅推动了移动设备智能化的发展,也为丰富交互体验提供了坚实的技术基础。随着相关算法的持续优化与硬件性能的不断提升,未来双目视觉技术有望在各类智能系统中实现更广泛、更深层次的应用。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值