球面細分(下)

上篇之後本文給出將點數據導出爲三角形圖元的方法,分配隨機顏色並渲染後如圖一:

《圖一》

因爲上篇給出了源代碼下載地址,所以這裏就只貼出本篇需要修改的兩處源文件:

首先是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 *nextPoint = nullptr;
					if (0 == elementindex)
					{
						prePoint = points[rowindex - 1][0];
						nextPoint = points[rowindex + 1][0];
					}else{
						if (rowindex < private_calNumofRows(curDL)/2)
						{
							prePoint = private_getNeighborA(curDL, rowindex, elementindex);
							nextPoint = private_getNeighborD(curDL, rowindex, elementindex);
						}else{
							prePoint = private_getNeighborF(curDL, rowindex, elementindex);
							nextPoint = private_getNeighborC(curDL, rowindex, elementindex);
						}
						
					}
					// 計算圓心到新插值點有向線段的單位向量
					VECTOR_F newv = private_calMidVector( VECTOR_F(prePoint->x, prePoint->y, prePoint->z), VECTOR_F(nextPoint->x, nextPoint->y, nextPoint->z) );
					// 新點
					newpoint = (POINT3D_F *)malloc(sizeof(POINT3D_F));
					newpoint->x = newv.x * size;
					newpoint->y = newv.y * size;
					newpoint->z = newv.z * size;

					points[rowindex].push_back(newpoint);
				}
				// 再次遞增索引
				++rowindex;
			}
		}

		// 手動初始化北極點指針成員
		points[0][0]->a = private_getNeighborA(dl, 0, 0);
		points[0][0]->b = private_getNeighborB(dl, 0, 0);
		points[0][0]->c = private_getNeighborC(dl, 0, 0);
		points[0][0]->d = private_getNeighborD(dl, 0, 0);
		points[0][0]->e = points[0][0]->f = nullptr;
		// 手動初始化南極點成員
		int maxRowIndex = private_calNumofRows(dl) - 1;
		points[maxRowIndex][0]->a = private_getNeighborA(dl, maxRowIndex, 0);
		points[maxRowIndex][0]->b = private_getNeighborB(dl, maxRowIndex, 0);
		points[maxRowIndex][0]->c = private_getNeighborC(dl, maxRowIndex, 0);
		points[maxRowIndex][0]->d = private_getNeighborD(dl, maxRowIndex, 0);
		points[maxRowIndex][0]->e = points[maxRowIndex][0]->f = nullptr;
		// 初始化頂點指針成員
		for (int rowindex = 0; (unsigned)rowindex < points.size();++rowindex)
		{
			for (int elementindex = 0; (unsigned)elementindex < points[rowindex].size(); ++elementindex)
			{
				points[rowindex][elementindex]->a = private_getNeighborA(dl, rowindex, elementindex);
				points[rowindex][elementindex]->b = private_getNeighborB(dl, rowindex, elementindex);
				points[rowindex][elementindex]->c = private_getNeighborC(dl, rowindex, elementindex);
				points[rowindex][elementindex]->d = private_getNeighborD(dl, rowindex, elementindex);
				points[rowindex][elementindex]->e = private_getNeighborE(dl, rowindex, elementindex);
				points[rowindex][elementindex]->f = private_getNeighborF(dl, rowindex, elementindex);
			}
		}

		vector<TRIANGLE_F*> trians;
		TRIANGLE_F *newtrian = nullptr;
		// 手動插入第一行三角形數據(全部爲正三角形)
		triangles.push_back(trians);
		newtrian = (TRIANGLE_F*)malloc(sizeof(TRIANGLE_F));
		newtrian->a = points[0][0];
		newtrian->b = points[1][0];
		newtrian->c = points[1][1];
		private_initTriangleNormal(newtrian);
		triangles[0].push_back(newtrian);
		newtrian = (TRIANGLE_F*)malloc(sizeof(TRIANGLE_F));
		newtrian->a = points[0][0];
		newtrian->b = points[1][1];
		newtrian->c = points[1][2];
		private_initTriangleNormal(newtrian);
		triangles[0].push_back(newtrian);
		newtrian = (TRIANGLE_F*)malloc(sizeof(TRIANGLE_F));
		newtrian->a = points[0][0];
		newtrian->b = points[1][2];
		newtrian->c = points[1][3];
		private_initTriangleNormal(newtrian);
		triangles[0].push_back(newtrian);
		newtrian = (TRIANGLE_F*)malloc(sizeof(TRIANGLE_F));
		newtrian->a = points[0][0];
		newtrian->b = points[1][3];
		newtrian->c = points[1][0];
		private_initTriangleNormal(newtrian);
		triangles[0].push_back(newtrian);
		// 生成第一行和最後一行外其他的行的三角形數據
		maxRowIndex = private_calNumofRows(dl) - 3;
		for (int rowindex = 1; rowindex <= maxRowIndex;++rowindex)
		{
			triangles.push_back(trians);
			int maxElementIndex = private_calTriangleoftheRow(dl, rowindex) - 1;
			int midflag = (private_calNumofRows(dl) - 1) / 2;
			for (int elementindex = 0; elementindex <= maxElementIndex;++elementindex)
			{
				newtrian = (TRIANGLE_F*)malloc(sizeof(TRIANGLE_F));
				if (rowindex < midflag)// 如果位於上半球
				{
					if (0 == elementindex)// 如果索引爲0(上半球索引爲0的三角形都是正三角)
					{
						newtrian->a = points[rowindex][0];
						newtrian->b = points[rowindex + 1][0];
						newtrian->c = points[rowindex + 1][1];
					}else{
						int groupid = elementindex / (rowindex * 2 + 1);
						if ((groupid % 2 == 0 && elementindex % 2 == 0)||(groupid % 2 != 0 && elementindex % 2 != 0))
						{// 如果是正三角
							int ax = (elementindex - groupid) / 2 % private_calPointsoftheRow(dl, rowindex);
							int ay = rowindex;
							newtrian->a = points[ay][ax];
							int bx = (elementindex - groupid) / 2 + groupid;
							int by = ay + 1;
							newtrian->b = points[by][bx];
							int cx = (bx + 1) % private_calPointsoftheRow(dl, rowindex+1);
							int cy = by;
							newtrian->c = points[cy][cx];
						}else{// 如果是倒三角
							int cx = (elementindex + 1 - groupid)/2 % private_calPointsoftheRow(dl, rowindex);
							int cy = rowindex;
							newtrian->c = points[cy][cx];
							int ax = ((elementindex + 1 - groupid) / 2 - 1 + private_calPointsoftheRow(dl, rowindex)) % private_calPointsoftheRow(dl, rowindex);
							int ay = cy;
							newtrian->a = points[ay][ax];
							int bx = (elementindex + 1 - groupid) / 2 + groupid;
							int by = cy + 1;
							newtrian->b = points[by][bx];
						}
					}
				}else{// 如果位於下半球
					if (0 == elementindex)// 如果索引爲0(下半球索引爲0的三角形是倒三角形)
					{
						newtrian->a = points[rowindex][0];
						newtrian->b = points[rowindex + 1][0];
						newtrian->c = points[rowindex][1];
					}else{
						int resverRowindex = private_calNumofRows(dl) - 1 - rowindex - 1;
						int groupid = elementindex / (resverRowindex * 2 + 1);
						if ((groupid % 2 == 0 && elementindex % 2 != 0) || (groupid % 2 != 0 && elementindex % 2 == 0))
						{// 如果是正三角形
							int cx = (elementindex + 1 - groupid) / 2 % private_calPointsoftheRow(dl, rowindex + 1);
							int cy = rowindex + 1 ;
							newtrian->c = points[cy][cx];
							int ax = (elementindex + 1 - groupid) / 2 + groupid;
							int ay = rowindex;
							newtrian->a = points[ay][ax];
							int bx = (elementindex + 1 - groupid) / 2 - 1;
							int by = cy;
							newtrian->b = points[by][bx];
						}else{ // 如果是倒三角形
							int cx = (elementindex - groupid) / 2 % private_calPointsoftheRow(dl, rowindex + 1);
							int cy = rowindex + 1;
							newtrian->c = points[cy][cx];
							int ax = (elementindex - groupid) / 2 + groupid;
							int ay = rowindex;
							newtrian->a = points[ay][ax];
							int bx = (ax + 1) % private_calPointsoftheRow(dl, rowindex);
							int by = rowindex;
							newtrian->b = points[by][bx];
						}
					}
				}
				private_initTriangleNormal(newtrian);
				triangles[rowindex].push_back(newtrian);
			}
		}
		// 手動插入最後一行三角形數據(倒三角)
		triangles.push_back(trians);
		maxRowIndex = private_calNumofRows(dl) - 1;
		newtrian = (TRIANGLE_F*)malloc(sizeof(TRIANGLE_F));
		newtrian->a = points[maxRowIndex - 1][0];
		newtrian->b = points[maxRowIndex][0];
		newtrian->c = points[maxRowIndex - 1][1];
		triangles[maxRowIndex - 1].push_back(newtrian);
		newtrian = (TRIANGLE_F*)malloc(sizeof(TRIANGLE_F));
		newtrian->a = points[maxRowIndex - 1][1];
		newtrian->b = points[maxRowIndex][0];
		newtrian->c = points[maxRowIndex - 1][2];
		triangles[maxRowIndex - 1].push_back(newtrian);
		newtrian = (TRIANGLE_F*)malloc(sizeof(TRIANGLE_F));
		newtrian->a = points[maxRowIndex - 1][2];
		newtrian->b = points[maxRowIndex][0];
		newtrian->c = points[maxRowIndex - 1][3];
		triangles[maxRowIndex - 1].push_back(newtrian);
		newtrian = (TRIANGLE_F*)malloc(sizeof(TRIANGLE_F));
		newtrian->a = points[maxRowIndex - 1][3];
		newtrian->b = points[maxRowIndex][0];
		newtrian->c = points[maxRowIndex - 1][0];
		triangles[maxRowIndex - 1].push_back(newtrian);
		// 初始化三角形的指針成員

	}
}

/*
* 析構
*/
CSphere::~CSphere()
{
	this->release();
}

/*
* 釋放資源
*/
void CSphere::release()
{
	// 刪除頂點數據
	for (int i = 0; (unsigned int)i < points.size(); ++i)
	{
		for (int j = 0; (unsigned int)j < points[i].size();++j)
		{
			free(points[i][j]);
			points[i][j] = nullptr;
		}
		points[i].clear();
	}
	points.clear();

	// 刪除三角形數據
	for (int i = 0; (unsigned)i < triangles.size(); ++i)
	{
		for (int j = 0; (unsigned)j < triangles[i].size(); ++j)
		{
			free(points[i][j]);
			points[i][j] = nullptr;
		}
		points[i].clear();
	}
	triangles.clear();
}

/*
* 求冪(非法參數返回-1)
*/
int CSphere::private_power(const int &m, const int &n)
{
	if (n < 0)
		return -1;

	if (n == 0)
		return 1;

	if (n == 1)
		return m;

	return m*private_power(m, (n-1));
}

/*
* 計算當前複雜等級需要的行數
* 注意:南極點和北極點各算一行,赤道算一行,其他行數=private_calRowX(detailLevel)*2
*/
int CSphere::private_calNumofRows(const int &detailLevel)
{
	return (this->private_calRowX(detailLevel)*2 +3);
}

/*
* 使用迭代計算指定行的rowx
*/
int CSphere::private_calRowX(const int &detailLevel)
{
	if (detailLevel == 1)
		return 0;
	else
		return (this->private_calRowX(detailLevel - 1) * 2 + 1);
}

/*
* 計算指定複雜度下某行頂點數量
* @detailLevel:當前指定的複雜度
* @rowNumber:指定的行編號(從0開始)
*/
int CSphere::private_calPointsoftheRow(const int &detailLevel, const int &rowNumber)
{
	int result = (4 * private_power(2, (detailLevel - 1)) - (abs((private_calNumofRows(detailLevel) / 2) - rowNumber)) * 4);
	if (0 == result)
		return 1;
	else
		return result;
}

/*
* 計算指定複雜度下某行三角形數量
*/ 
int CSphere::private_calTriangleoftheRow(const int &dl, const int &rowNumber)
{
	if (rowNumber < (private_calNumofRows(dl) - 1)/2)	// 如果位於上半球
	{
		return (rowNumber * 2 + 1)*4;
	}else{												// 如果位於下半球
		int resverRowNumber = private_calNumofRows(dl) - 1 - rowNumber - 1;
		return (resverRowNumber * 2 + 1)*4;
	}
}

/*
* 取得vector<int>指定索引元素的迭代器(非安全)
*/
vector<POINT3D_F*>::iterator CSphere::private_getVectorofPoints_iterator(vector<POINT3D_F*> &pointsArray, int &index)
{
	return (pointsArray.begin() + index);
}

/*
* 取得vector<vector<POINT3D_F*>>指定索引數組的迭代器(非安全)
*/
vector<vector<POINT3D_F*>>::iterator CSphere::private_getVectorofVectorofPoints_iterator(
	vector<vector<POINT3D_F*>> &vectorArray, int &index
	)
{
	return (vectorArray.begin() + index);
}

/*
* 取得指定點的編號A鄰居
* 注意:此爲樣板函數,其他函數可參考此函數
*/ 
POINT3D_F* CSphere::private_getNeighborA(int curDL, int rowindex, int elementindex)
{
	POINT3D_F *a = nullptr;
	//POINT3D_F *b = nullptr;
	//POINT3D_F *c = nullptr;
	//POINT3D_F *d = nullptr;
	//POINT3D_F *e = nullptr;
	//POINT3D_F *f = nullptr;
	if ( 0 == rowindex )
	{
		// 如果點屬於第一行(北極點),只有四個鄰居a,b,c,d
		a = points[1][2];
		// b = points[1][3];
		// c = points[1][0];
		// d = points[1][1];
		// e = nullptr;
		// f = nullptr;
	}else if ( (private_calNumofRows(curDL)-1) == rowindex ){
		// 如果點屬於最後一行(南極點),只有四個鄰居a,b,c,d
		a = points[private_calNumofRows(curDL) - 2][0];
		// b = points[preRowIndex][3];
		// c = points[preRowIndex][2];
		// d = points[preRowIndex][1];
		// e = nullptr;
		// f = nullptr;
	}else if (rowindex < private_calNumofRows(curDL)/2){
		// 如果點屬於上半球(北極點和赤道之間),那麼有六個鄰居abcdef
		if ( 0 == elementindex )
		{
			// 如果恰好是第一個元素
			a = points[rowindex - 1][private_calPointsoftheRow(curDL, rowindex - 1) - 1];
			// b = points[rowindex][private_calPointsoftheRow(curDL, rowindex) - 1];
			// c = points[rowindex + 1][0];
			// d = points[rowindex + 1][1];
			// e = points[rowindex][1];
			// f = points[rowindex - 1][0];
		}else{
			int groupid = 0;
			int y = 0;
			int x = 0;
			
			// a鄰居索引
			if (elementindex % rowindex)
				groupid = (elementindex - elementindex % rowindex + rowindex) / rowindex;
			else
				groupid = elementindex / rowindex;
			y = rowindex - 1;
			x = elementindex - groupid;
			a = points[y][x];
			//// b鄰居索引
			//y = rowindex;
			//x = elementindex - 1;
			//b = points[y][x];
			//// c鄰居索引
			//if (elementindex % rowindex)
			//	groupid = (elementindex - elementindex % rowindex + rowindex) / rowindex;
			//else
			//	groupid = elementindex / rowindex;
			//y = rowindex + 1;
			//x = elementindex + groupid - 1;
			//c = points[y][x];
			// d鄰居索引
			//if (elementindex % rowindex)
			//	groupid = (elementindex - elementindex % rowindex + rowindex) / rowindex;
			//else
			//	groupid = elementindex / rowindex;
			//y = rowindex + 1;
			//x = elementindex + groupid;
			//d = points[y][x];
			//// e鄰居索引
			//y = rowindex;
			//x = (elementindex + 1) % private_calPointsoftheRow(curDL, rowindex);
			//e = points[y][x];
			//// f鄰居索引
			//if (elementindex % rowindex)
			//	groupid = (elementindex - elementindex % rowindex + rowindex) / rowindex;
			//else
			//	groupid = elementindex / rowindex;
			//y = (rowindex - 1;
			//x = (elementindex - groupid + 1) % private_calPointsofthe(curDL, rowindex - 1);
			//f = points[y][x];
		}
	}else if (rowindex > private_calNumofRows(curDL)/2){
		// 如果是屬於下半球(赤道和南極點之間),那麼有六個鄰居abcdef
		if (0 == elementindex)
		{
			// 如果恰好是第一個元素
			a = points[rowindex - 1][0];
			// b = points[rowindex][private_calPointsoftheRow(curDL, rowindex) - 1];
			// c = points[rowindex + 1][private_calPointsoftheRow(curDL, rowindex+1) - 1];
			// d = points[rowindex + 1][0];
			// e = points[rowindex][1];
			// f = points[rowindex - 1][1];
		}else{
			int groupid = 0;
			int rowResverIndex = private_calNumofRows(curDL) - rowindex - 1;	// 當前行的反序索引
			int y = 0;
			int x = 0;
			// a鄰居的索引
			if (elementindex % rowResverIndex)
				groupid = (elementindex - elementindex % rowResverIndex + rowResverIndex) / rowResverIndex;
			else
				groupid = elementindex / rowResverIndex;
			y = rowindex - 1;
			x = elementindex + groupid - 1;
			a = points[y][x];
			//// b鄰居的索引
			//y = rowindex;
			//x = elementindex - 1;
			//b = points[y][x];
			//// c鄰居的索引
			//if (elementindex % rowResverIndex)
			//	groupid = (elementindex - elementindex % rowResverIndex + rowResverIndex) / rowResverIndex - 1;
			//else
			//	groupid = elementindex / rowResverIndex ;
			//y = rowindex + 1;
			//x = elementindex - groupid;
			//c = points[y][x];
			//// d鄰居的索引
			//if (elementindex % rowResverIndex)
			//	groupid = (elementindex - elementindex % rowResverIndex + rowResverIndex) / rowResverIndex;
			//else
			//	groupid = elementindex / rowResverIndex;
			//y = rowindex + 1;
			//x = (elementindex - groupid + 1) % private_calPointsoftheRow(curDL, y);
			//d = points[y][x];
			//// e鄰居的索引
			//y = rowindex;
			//x = (elementindex + 1) % private_calPointsoftheRow(curDL, rowindex);
			//e = points[y][x];
			//// f鄰居的索引
			//if (elementindex % rowResverIndex)
			//	groupid = (elementindex - elementindex % rowResverIndex + rowResverIndex) / rowResverIndex;
			//else
			//	groupid = elementindex / rowResverIndex;
			//y = rowindex - 1;
			//x = (elementindex + groupid) % private_calPointsoftheRow(curDL, rowindex - 1);
			//f = points[y][x];
		}
	}else if (private_calNumofRows(curDL)/2 == rowindex){
		if (0 == elementindex)
		{
			// 如果恰好是第一個元素
			a = points[rowindex - 1][private_calPointsoftheRow(curDL, rowindex - 1) - 1];
			// b = points[rowindex][private_calPointsoftheRow(curDL, rowindex) - 1] - 1;
			// c = points[rowindex + 1][0];
			// d = points[rowindex + 1][1];
			// e = points[rowindex][1];
			// f = points[rowindex - 1][0];
		}else{
			// 如果點屬於赤道,那麼有六個鄰居abcdef
			int groupid = 0;
			int rowResverIndex = private_calNumofRows(curDL) - rowindex - 1;	// 當前行的反序索引
			int y = 0;
			int x = 0;
			// a鄰居索引
			if (elementindex % rowindex)
				groupid = (elementindex - elementindex % rowindex + rowindex) / rowindex;
			else
				groupid = elementindex / rowindex;
			y = rowindex - 1;
			x = elementindex - groupid;
			a = points[y][x];
			//// b鄰居索引
			//y = rowindex;
			//x = elementindex - 1;
			//b = points[y][x];
			//// c鄰居索引
			//if (elementindex % rowResverIndex)
			//	groupid = (elementindex - elementindex % rowResverIndex + rowResverIndex) / rowResverIndex;
			//else
			//	groupid = elementindex / rowResverIndex;
			//y = rowindex + 1;
			//x = elementindex - groupid;
			//c = points[y][x];
			//// d鄰居索引
			//if (elementindex % rowResverIndex)
			//	groupid = (elementindex - elementindex % rowResverIndex + rowResverIndex) / rowResverIndex;
			//else
			//	groupid = elementindex / rowResverIndex;
			//y = rowindex + 1;
			//x = (elementindex - groupid + 1) % private_calPointsoftheRow(curDL, y);
			//d = points[y][x];
			//// e鄰居索引
			//y = rowindex;
			//x = (elementindex + 1) % private_calPointsoftheRow(curDL, rowindex);
			//e = points[y][x];
			//// f鄰居索引
			//if (elementindex % rowindex)
			//	elementindex = (elementindex - elementindex % rowindex + rowindex) / rowindex;
			//else
			//	groupid = elementindex / rowindex;
			//y = rowindex - 1;
			//x = (elementindex - groupid + 1) % private_calPointsoftheRow(curDL, rowindex - 1);
			//f = points[y][x];
		}
	}

	return a;
	//return b;
	//return c;
	//return d;
	//return e;
	//return f;
}

/*
* 取得指定點的編號B鄰居
*/ 
POINT3D_F* CSphere::private_getNeighborB(int curDL, int rowindex, int elementindex)
{
	POINT3D_F *b = nullptr;
	if (0 == rowindex)
	{
		// 如果點屬於第一行(北極點),只有四個鄰居a,b,c,d
		b = points[1][3];
	}else if ((private_calNumofRows(curDL) - 1) == rowindex){
		// 如果點屬於最後一行(南極點),只有四個鄰居a,b,c,d
		b = points[private_calNumofRows(curDL) - 2][3];
	}else if (rowindex < private_calNumofRows(curDL) / 2){
		// 如果點屬於上半球(北極點和赤道之間),那麼有六個鄰居abcdef
		if (0 == elementindex)
		{
			// 如果恰好是第一個元素
			b = points[rowindex][private_calPointsoftheRow(curDL, rowindex) - 1];
		}else{
			int groupid = 0;
			int y = 0;
			int x = 0;

			// b鄰居索引
			y = rowindex;
			x = elementindex - 1;
			b = points[y][x];
		}
	}else if (rowindex > private_calNumofRows(curDL) / 2){
		// 如果是屬於下半球(赤道和南極點之間),那麼有六個鄰居abcdef
		if (0 == elementindex)
			// 如果恰好是第一個元素
			b = points[rowindex][private_calPointsoftheRow(curDL, rowindex) - 1];
		else
			b = points[rowindex][elementindex - 1];
	}else if (private_calNumofRows(curDL) / 2 == rowindex){
		if (0 == elementindex)
			// 如果恰好是第一個元素
			b = points[rowindex][private_calPointsoftheRow(curDL, rowindex) - 1] - 1;
		else
			b = points[rowindex][elementindex - 1];
	}

	return b;
}

/*
* 取得指定點的編號C鄰居
*/ 
POINT3D_F* CSphere::private_getNeighborC(int curDL, int rowindex, int elementindex)
{
	POINT3D_F *c = nullptr;
	if (0 == rowindex)
	{
		// 如果點屬於第一行(北極點),只有四個鄰居a,b,c,d
		c = points[1][0];
	}else if ((private_calNumofRows(curDL) - 1) == rowindex){
		// 如果點屬於最後一行(南極點),只有四個鄰居a,b,c,d
		c = points[private_calNumofRows(curDL) - 2][2];
	}else if (rowindex < private_calNumofRows(curDL) / 2){
		// 如果點屬於上半球(北極點和赤道之間),那麼有六個鄰居abcdef
		if (0 == elementindex)
		{
			c = points[rowindex + 1][0];
		}else{
			int groupid = 0;
			// c鄰居索引
			if (elementindex % rowindex)
				groupid = (elementindex - elementindex % rowindex + rowindex) / rowindex;
			else
				groupid = elementindex / rowindex;
			c = points[rowindex + 1][elementindex + groupid - 1];
		}
	}else if (rowindex > private_calNumofRows(curDL) / 2){
		// 如果是屬於下半球(赤道和南極點之間),那麼有六個鄰居abcdef
		if (0 == elementindex)
		{
			// 如果恰好是第一個元素
			c = points[rowindex + 1][private_calPointsoftheRow(curDL, rowindex+1) - 1];
		}else{
			int groupid = 0;
			int rowResverIndex = private_calNumofRows(curDL) - rowindex - 1;	// 當前行的反序索引
			// c鄰居的索引
			if (elementindex % rowResverIndex)
				groupid = (elementindex - elementindex % rowResverIndex + rowResverIndex) / rowResverIndex;
			else
				groupid = elementindex / rowResverIndex ;
			c = points[rowindex + 1][elementindex - groupid];
		}
	}else if (private_calNumofRows(curDL) / 2 == rowindex){
		if (0 == elementindex)
		{
			// 如果恰好是第一個元素
			c = points[rowindex + 1][0];
		}else{
			// 如果點屬於赤道,那麼有六個鄰居abcdef
			int groupid = 0;
			int rowResverIndex = private_calNumofRows(curDL) - rowindex - 1;	// 當前行的反序索引	
			// c鄰居索引
			if (elementindex % rowResverIndex)
				groupid = (elementindex - elementindex % rowResverIndex + rowResverIndex) / rowResverIndex;
			else
				groupid = elementindex / rowResverIndex;
			c = points[rowindex + 1][elementindex - groupid];
		}
	}

	return c;
}

/*
* 取得指定點的編號D鄰居
*/ 
POINT3D_F* CSphere::private_getNeighborD(int curDL, int rowindex, int elementindex)
{
	POINT3D_F *d = nullptr;
	if (0 == rowindex)
	{
		// 如果點屬於第一行(北極點),只有四個鄰居a,b,c,d
		d = points[1][1];
	}else if ((private_calNumofRows(curDL) - 1) == rowindex){
		// 如果點屬於最後一行(南極點),只有四個鄰居a,b,c,d
		d = points[private_calNumofRows(curDL) - 2][1];
	}else if (rowindex < private_calNumofRows(curDL) / 2){
		// 如果點屬於上半球(北極點和赤道之間),那麼有六個鄰居abcdef
		if (0 == elementindex)
		{
			d = points[rowindex + 1][1];
		}else{
			int groupid = 0;
			// d鄰居索引
			if (elementindex % rowindex)
				groupid = (elementindex - elementindex % rowindex + rowindex) / rowindex;
			else
				groupid = elementindex / rowindex;
			d = points[rowindex + 1][elementindex + groupid];
		}
	}else if (rowindex > private_calNumofRows(curDL) / 2){
		// 如果是屬於下半球(赤道和南極點之間),那麼有六個鄰居abcdef
		if (0 == elementindex)
		{
			// 如果恰好是第一個元素
			d = points[rowindex + 1][0];
		}else{
			int groupid = 0;
			int rowResverIndex = private_calNumofRows(curDL) - rowindex - 1;	// 當前行的反序索引
			int y = 0;
			int x = 0;
			
			// d鄰居的索引
			if (elementindex % rowResverIndex)
				groupid = (elementindex - elementindex % rowResverIndex + rowResverIndex) / rowResverIndex;
			else
				groupid = elementindex / rowResverIndex;
			y = rowindex + 1;
			x = (elementindex - groupid + 1) % private_calPointsoftheRow(curDL, y);
			d = points[y][x];
		}
	}else if (private_calNumofRows(curDL) / 2 == rowindex){
		if (0 == elementindex)
		{
			// 如果恰好是第一個元素
			d = points[rowindex + 1][1];
		}else{
			// 如果點屬於赤道,那麼有六個鄰居abcdef
			int groupid = 0;
			int rowResverIndex = private_calNumofRows(curDL) - rowindex - 1;	// 當前行的反序索引
			int y = 0;
			int x = 0;
		
			// d鄰居索引
			if (elementindex % rowResverIndex)
				groupid = (elementindex - elementindex % rowResverIndex + rowResverIndex) / rowResverIndex;
			else
				groupid = elementindex / rowResverIndex;
			y = rowindex + 1;
			x = (elementindex - groupid + 1) % private_calPointsoftheRow(curDL, y);
			d = points[y][x];
		}
	}

	return d;
}

/*
* 取得指定點的編號E鄰居
*/ 
POINT3D_F* CSphere::private_getNeighborE(int curDL, int rowindex, int elementindex)
{
	POINT3D_F *e = nullptr;
	if (0 == rowindex)
	{
		// 如果點屬於第一行(北極點),只有四個鄰居a,b,c,d
		e = nullptr;
	}else if ((private_calNumofRows(curDL) - 1) == rowindex){
		// 如果點屬於最後一行(南極點),只有四個鄰居a,b,c,d
		e = nullptr;
	}else if (rowindex < private_calNumofRows(curDL) / 2){
		// 如果點屬於上半球(北極點和赤道之間),那麼有六個鄰居abcdef
		if (0 == elementindex)
		{
			e = points[rowindex][1];
		}else{
			int groupid = 0;
			int y = 0;
			int x = 0;

			// e鄰居索引
			y = rowindex;
			x = (elementindex + 1) % private_calPointsoftheRow(curDL, rowindex);
			e = points[y][x];
		}
	}else if (rowindex > private_calNumofRows(curDL) / 2){
		// 如果是屬於下半球(赤道和南極點之間),那麼有六個鄰居abcdef
		if (0 == elementindex)
		{
			// 如果恰好是第一個元素
			e = points[rowindex][1];
		}else{
			int groupid = 0;
			int rowResverIndex = private_calNumofRows(curDL) - rowindex - 1;	// 當前行的反序索引
			int y = 0;
			int x = 0;
			
			// e鄰居的索引
			y = rowindex;
			x = (elementindex + 1) % private_calPointsoftheRow(curDL, rowindex);
			e = points[y][x];
		}
	}else if (private_calNumofRows(curDL) / 2 == rowindex){
		if (0 == elementindex)
		{
			// 如果恰好是第一個元素
			e = points[rowindex][1];
		}else{
			// 如果點屬於赤道,那麼有六個鄰居abcdef
			int groupid = 0;
			int rowResverIndex = private_calNumofRows(curDL) - rowindex - 1;	// 當前行的反序索引
			int y = 0;
			int x = 0;
			
			// e鄰居索引
			y = rowindex;
			x = (elementindex + 1) % private_calPointsoftheRow(curDL, rowindex);
			e = points[y][x];
		}
	}

	return e;
}

/*
* 取得指定點的編號F鄰居
*/ 
POINT3D_F* CSphere::private_getNeighborF(int curDL, int rowindex, int elementindex)
{
	POINT3D_F *f = nullptr;
	if (0 == rowindex)
	{
		// 如果點屬於第一行(北極點),只有四個鄰居a,b,c,d
		f = nullptr;
	}else if ((private_calNumofRows(curDL) - 1) == rowindex){
		// 如果點屬於最後一行(南極點),只有四個鄰居a,b,c,d 
		f = nullptr;
	}else if (rowindex < private_calNumofRows(curDL) / 2){
		// 如果點屬於上半球(北極點和赤道之間),那麼有六個鄰居abcdef
		if (0 == elementindex)
		{
			f = points[rowindex - 1][0];
		}else{
			int groupid = 0;
			int y = 0;
			int x = 0;

			// f鄰居索引
			if (elementindex % rowindex)
				groupid = (elementindex - elementindex % rowindex + rowindex) / rowindex;
			else
				groupid = elementindex / rowindex;
			y = rowindex - 1;
			x = (elementindex - groupid + 1) % private_calPointsoftheRow(curDL, rowindex - 1);
			f = points[y][x];
		}
	}else if (rowindex > private_calNumofRows(curDL) / 2){
		// 如果是屬於下半球(赤道和南極點之間),那麼有六個鄰居abcdef
		if (0 == elementindex)
		{
			// 如果恰好是第一個元素
			f = points[rowindex - 1][1];
		}else{
			int groupid = 0;
			int rowResverIndex = private_calNumofRows(curDL) - rowindex - 1;	// 當前行的反序索引
			int y = 0;
			int x = 0;
			
			// f鄰居的索引
			if (elementindex % rowResverIndex)
				groupid = (elementindex - elementindex % rowResverIndex + rowResverIndex) / rowResverIndex;
			else
				groupid = elementindex / rowResverIndex;
			y = rowindex - 1;
			x = (elementindex + groupid) % private_calPointsoftheRow(curDL, rowindex - 1);
			f = points[y][x];
		}
	}else if (private_calNumofRows(curDL) / 2 == rowindex){
		if (0 == elementindex)
		{
			// 如果恰好是第一個元素
			f = points[rowindex - 1][0];
		}else{
			// 如果點屬於赤道,那麼有六個鄰居abcdef
			int groupid = 0;
			int rowResverIndex = private_calNumofRows(curDL) - rowindex - 1;	// 當前行的反序索引
			int y = 0;
			int x = 0;
			
			// f鄰居索引
			if (elementindex % rowindex)
				elementindex = (elementindex - elementindex % rowindex + rowindex) / rowindex;
			else
				groupid = elementindex / rowindex;
			y = rowindex - 1;
			x = (elementindex - groupid + 1) % private_calPointsoftheRow(curDL, rowindex - 1);
			f = points[y][x];
		}
	}

	return f;
}

/*
* 計算兩個向量的中間向量,並返回中間向量的單位向量
*/
VECTOR_F CSphere::private_calMidVector(const VECTOR_F &v1, const VECTOR_F &v2)
{
	VECTOR_F result(0.0f, 0.0f, 0.0f);
	float delta[3] = { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };
	result.x = v2.x + delta[0] / 2.0f;
	result.y = v2.y + delta[1] / 2.0f;
	result.z = v2.z + delta[2] / 2.0f;
	// 單位化
	float len = sqrtf(result.x*result.x + result.y*result.y + result.z*result.z);
	result.x /= len;
	result.y /= len;
	result.z /= len;

	return result;
}

/*
* 根據三角形三個頂點計算三角形法線
*/ 
void CSphere::private_initTriangleNormal(TRIANGLE_F *triangle)
{
	// 首先計算出圓心到三角形中心的向量
	triangle->normal[0] = (triangle->a->x + triangle->b->x + triangle->c->x) / 3.0f;
	triangle->normal[1] = (triangle->a->y + triangle->b->y + triangle->c->y) / 3.0f;
	triangle->normal[2] = (triangle->a->z + triangle->b->z + triangle->c->z) / 3.0f;
	// 單位化
	float len = sqrtf( triangle->normal[0] * triangle->normal[0] + triangle->normal[1] * triangle->normal[1] + triangle->normal[2] * triangle->normal[2] );
	triangle->normal[0] /= len;
	triangle->normal[1] /= len;
	triangle->normal[2] /= len;
}

代碼寫的太爛,請見諒委屈


發佈了31 篇原創文章 · 獲贊 18 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章