球面细分(下)

本文继续探讨球面细分技术,介绍如何将点数据转换为三角形图元,并展示分配随机颜色后的渲染效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上篇之后本文给出将点数据导出为三角形图元的方法,分配随机颜色并渲染后如图一:

《图一》

因为上篇给出了源代码下载地址,所以这里就只贴出本篇需要修改的两处源文件:

首先是CSphere类的头文件:

////////////////////////////////////////////////////////////
// GLsphere.h
//
////////////////////////////////////////////////////////////
#pragma once
#include "stdafx.h"
#include <vector>

using std::vector;


// 浮点向量
struct VECTOR_F{
	VECTOR_F(const float &xparam, const float &yparam, const float &zparam)
	:x(xparam), y(yparam), z(zparam)
	{}
	
	float x, y, z;
};
// 3维点
struct POINT3D_F{
	float x, y, z;
	POINT3D_F *a, *b, *c, *d, *e, *f;
};
// 3维三角形
struct TRIANGLE_F{
	// 三个顶点
	POINT3D_F *a, *b, *c;	
	// 三角形相对于圆心法线,单位向量
	float normal[3];
};


class CSphere{
public:
	CSphere(const int &detialLevel, const float &sphereSize);
	~CSphere();
	void release();
	bool isSuccess() { return issuccess; }
private:
	int private_power(const int &m, const int &n);			// 求冪
	// 计算指定复杂度存储所有顶点需要的行数
	int private_calNumofRows(const int &detailLevel);
	// 计算指定复杂度下某行顶点数量
	int private_calPointsoftheRow(const int &detailLevel, const int &rowNumber);
	// 计算指定复杂度下某行三角形数量
	int private_calTriangleoftheRow(const int &dl, const int &rowNumber);
	int private_calRowX(const int &detailLevel);
	// 取得vector<POINT3D_F*>指定索引元素的迭代器(非安全)
	vector<POINT3D_F*>::iterator private_getVectorofPoints_iterator(vector<POINT3D_F*> &pointsArray,int &index);
	// 取得vector<vector<POINT3D_F*>>指定索引数组的迭代器(非安全)
	vector<vector<POINT3D_F*>>::iterator private_getVectorofVectorofPoints_iterator(
		vector<vector<POINT3D_F*>> &vectorArray, int &index
		);
	// 取得指定点的编号A邻居
	POINT3D_F* private_getNeighborA(int curDL, int rowindex, int elementindex);
	// 取得指定点的编号B邻居
	POINT3D_F* private_getNeighborB(int curDL, int rowindex, int elementindex);
	// 取得指定点的编号C邻居
	POINT3D_F* private_getNeighborC(int curDL, int rowindex, int elementindex);
	// 取得指定点的编号D邻居
	POINT3D_F* private_getNeighborD(int curDL, int rowindex, int elementindex);
	// 取得指定点的编号E邻居
	POINT3D_F* private_getNeighborE(int curDL, int rowindex, int elementindex);
	// 取得指定点的编号F邻居
	POINT3D_F* private_getNeighborF(int curDL, int rowindex, int elementindex);
	// 计算两向量的中间向量
	VECTOR_F private_calMidVector(const VECTOR_F &v1, const VECTOR_F &v2);
	// 根据三角形三个顶点计算三角形法线
	void private_initTriangleNormal(TRIANGLE_F *triangle);
public:
	bool issuccess;			// 是否初始化成功
	int dl;
	float size;

	int pointsCount;		// 顶点数量:6+(n-1)*3
	vector<vector<POINT3D_F *>> points;
	int trianglesCount;		// 三角形数量:4^detailLevel
	vector<vector<TRIANGLE_F*>> triangles;
};

CSphere类的源文件:

////////////////////////////////////////////////////////////
// GLsphere.cpp
//
////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GLsphere.h"


/*
* 构造
* @detailLevel:细分等级,大于等于2
* @size:球半径
*/
CSphere::CSphere(const int &detailLevel, const float &sphereSize)
:dl(0), size(0.0f), pointsCount(0), trianglesCount(0)
{ 
	if ( (detailLevel < 2)||(sphereSize <= 0.0f) )
	{
		issuccess = false;
	}else{
		dl = detailLevel;
		size = sphereSize;
		
		// 手动插入当复杂度为1时的点
		vector<POINT3D_F *> temp;
		points.push_back(temp);
		points.push_back(temp);
		points.push_back(temp);
		POINT3D_F *newpoint = nullptr;
		// 上
		newpoint = (POINT3D_F*)malloc(sizeof(POINT3D_F));
		newpoint->x = newpoint->z = 0.0f;
		newpoint->y = size;
		points[0].push_back(newpoint);
		// 前
		newpoint = (POINT3D_F*)malloc(sizeof(POINT3D_F));
		newpoint->x = newpoint->y = 0.0f;
		newpoint->z = size;
		points[1].push_back(newpoint);
		// 右
		newpoint = (POINT3D_F*)malloc(sizeof(POINT3D_F));
		newpoint->y = newpoint->z = 0.0f;
		newpoint->x = size;
		points[1].push_back(newpoint);
		// 后
		newpoint = (POINT3D_F*)malloc(sizeof(POINT3D_F));
		newpoint->x = newpoint->y = 0.0f;
		newpoint->z = -size;
		points[1].push_back(newpoint);
		// 左
		newpoint = (POINT3D_F *)malloc(sizeof(POINT3D_F));
		newpoint->y = newpoint->z = 0.0f;
		newpoint->x = -size;
		points[1].push_back(newpoint);
		// 下
		newpoint = (POINT3D_F*)malloc(sizeof(POINT3D_F));
		newpoint->x = newpoint->z = 0.0f;
		newpoint->y = -size;
		points[2].push_back(newpoint);
		// 开始插值,递增复杂度
		for (int curDL = 2; curDL <= dl;++curDL)
		{
			// 第一步:对已存在的行进行插值
			int rowMax = private_calNumofRows(curDL-1) - 2;
			// 开始逐行插值
			for (int rowindex = 1; rowindex <= rowMax;++rowindex)
			{
				// 逐行间隔插入新点
				for (int elementindex = 0; (unsigned)elementindex < points[rowindex].size(); ++++elementindex)
				{
					// 初始化一个新点
					newpoint = (POINT3D_F *)malloc(sizeof(POINT3D_F));
					int lindex = elementindex;
					int rindex = (elementindex + 1) % points[rowindex].size();
					VECTOR_F newv = private_calMidVector(
						VECTOR_F( points[rowindex][lindex]->x, points[rowindex][lindex]->y, points[rowindex][lindex]->z ),
						VECTOR_F( points[rowindex][rindex]->x, points[rowindex][rindex]->y, points[rowindex][rindex]->z )
						);
					// 根据圆心到点有向线段的单位向量计算点的坐标
					newpoint->x = newv.x * size;
					newpoint->y = newv.y * size;
					newpoint->z = newv.z * size;
					// 插入点
					points[rowindex].insert(private_getVectorofPoints_iterator(points[rowindex], elementindex) + 1, newpoint);
				}
			}
			// 第二步:插入整行的点
			rowMax = private_calNumofRows(curDL) - 1;
			for (int rowindex = 0; rowindex < rowMax;)
			{
				// 在当前行索引之后插入一个空行,并递增索引指向新插入的行
				++rowindex;		// rowindex指向新插入的行
				points.insert(private_getVectorofVectorofPoints_iterator(points, rowindex), temp);
				// 初始化当前行
				int elementMax = private_calPointsoftheRow(curDL, rowindex);
				int preElementMax = private_calPointsoftheRow(curDL, rowindex-1 );
				int nextElementMax = private_calPointsoftheRow(curDL, rowindex+1 );
				for (int elementindex = 0; elementindex < elementMax; ++elementindex)
				{
					POINT3D_F *prePoint = nullptr;
					POINT3D_F *nextP
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值