OpenCV实现随机地形图并附加光照

随机地形图参考链接:https://blog.csdn.net/ZJU_fish1996/article/details/71248890

法向计算参考链接:https://blog.csdn.net/fisherwan/article/details/40897939

 

函数AreaDotProduct用于计算每个面的法向,函数PointDotProduct用于计算每个顶点的法向(需要调用AreaDotProduct函数),得到的法向值存储在顶点结构体中。

用glNormal3f函数将存储的法向赋给顶点,设置光照的时候就会自动产生效果了。

 

fractal.h

#pragma once 
#include <gl/glut.h>
#include <gl/gl.h>

struct TriangleVertexs
{
	GLfloat xyz[3];
	GLfloat Pnormal[3];
};

class fractal
{
private:	
	enum { MAX = 10000 };
	float roughness;
	int times;
	int height;
	float minHeight;
	float maxHeight;
	int n;
	int D;
	int indiceNum; 
	float** data; //根据随机数计算生成的顶点高度值
	float* vertex; //数据三个一组,存放的是顶点的三个坐标值
	int* indice; //存放下标的数组,高度6,三个一组,分别存放左下三角形和右上三角形的三个顶点坐标
	TriangleVertexs normal;//存储面的法向
	float A[3], B[3];//两个矢量
	TriangleVertexs* result; //result[in+j]
	float step;
	void genIndice();
	void chooseColor(float height);
public:	
	void draw();
	void calculate();
	TriangleVertexs AreaDotProduct(TriangleVertexs V1, TriangleVertexs V2, TriangleVertexs V3);
	void PointDotProduct(int ij);
	fractal(int _height, int _times, float _step, int D,int seed);
};

  

fractal.cpp

#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <iostream>
#include "fractal.h"
#include <gl/glut.h>
#include <gl/gl.h>
using namespace std; 
// height : 值越大,地形起伏越大 
// times  : 迭代次数,次数越多,tire越多
// step   : 绘制时一个网格的程度
// D      : 随机数衰减因子,越大随机数随迭代的取值越小
// seed   : 随机数种子
fractal::fractal(int _height, int _times, float _step, int _D,int seed)
{	
	srand(seed);	
	step = _step;	//绘制时一个网格的程度
	times = _times;	 //迭代次数
	height = _height;	
	D = _D; //随机数衰减因子,越大随机数衰减越快
	n = pow(2, times) + 1;	
	//n = 1000;
	indiceNum = 6 * (n - 1)*(n - 1);	
	vertex = new float[3 * n*n];	//vertex是一个三维数组,长方体,底面=边长( n )正方形,高= 3
	indice = new int[indiceNum];	//indice是一个三维数组,长方体,底面=边长(n-1)正方形,高= 6
	data = new float*[n];	//data是 n*n 二维数组
	result = new TriangleVertexs[n*n];
	//normal = new float[2 * (n - 1)*(n - 1)];

	for (int i = 0; i < n; i++)
	{		
		data[i] = new float[n];	
		for (int j = 0; j < n; j++)
		{			
			data[i][j] = 0;
		}	
	}//把data[][]清零了
} 

// 生成顶点索引数据
void fractal::genIndice()
{	
	for (int i = 0; i < n - 1; i++) 
	{		
		for (int j = 0; j < n - 1; j++)
		{			
			indice[3 * ((n - 1) * i + j)] = (n * i + j); // A在indice底面上 B在data表格上(草稿纸)A*3=B的下标
			indice[3 * ((n - 1) * i + j) + 1] = (n * i + j + 1);	// (草稿纸)A*3+1 = B的下标+1 B的下边的下标
			indice[3 * ((n - 1) * i + j) + 2] = (n * (i + 1) + j + 1); 	// (草稿纸)A*3+2 = B的右下的下标
		}	
	}	//将indice长方体分成了上下两部分,高都是3,这是下半部分
	cout << endl;	
	int off = 3 * (n - 1)*(n - 1);//indice底面*3
	for (int i = 0; i < n - 1; i++)
	{		
		for (int j = 0; j < n - 1; j++)
		{			
			indice[off + 3 * ((n - 1) * i + j)] = (n * i + j);	// A*3=B的下标 保持不变
			indice[off + 3 * ((n - 1) * i + j) + 1] = (n * (i + 1) + j); //A*3+1 = B的右边的下标
			indice[off + 3 * ((n - 1)* i + j) + 2] = (n * (i + 1) + j + 1);  //A*3+2 = B的右下的下标 保持不变
		}	
	}  //将indice长方体分成了上下两部分,高都是3,这是下半部分
} //这两部分分别存储了一个左下三角形和一个右上三角形的顶点下标,这两个三角形有两个共享顶点

// 生成[-num,num]之间的随机数
static float randnum(float num)
{	
	float max = num;	
	float min = -num;	
	int r;	
	float	x; 
	r = rand();
	x = (float)(r & 0x7fff) /		(float)0x7fff;	
	return (x * (max - min) + min);
} 

// 计算顶点高度
void fractal::calculate()
{	
	int size = n - 1;	
	int number = 1;	
	int ratio = pow(2, D); // 2^D
	roughness = height; 	
	//times为迭代次数,times值越大,则区域越大,同时也越趋于平坦(?)	
	for (int t = 0; t < times; t++)
	{		
		//此处算法核心思想:
		//diamond算中心值,square算上下左右四个值
		//先算出data中心的值,再for循环算其他的值
		//再把data分成四块,分别算四个中心的值,再for循环算每一块的其他的值
		//再把每一块分成四块...以此类推

		// diamand阶段	
		//第一次:只能执行i=0和j=0的情况
		//i = 0 j = 0  cx = 1/2(n-1)  cy = 1/2(n-1)
		for (int i = 0; i < number; i++) 
		{			
			for (int j = 0; j < number; j++) 
			{				
				float r = randnum(.5) * roughness;	//随机高度,用来增加
				int center_x = (size >> 1) + size * i;	// (i + 1/2) * size
				int center_y = (size >> 1) + size * j;	// (j + 1/2) * size
				data[center_x][center_y] =	(data[size * i][size * j]
											+ data[size*i + size][size * j]
											+ data[size * i][size * j + size]
											+ data[size * i + size][size * j + size]) / 4 + r;		
			}   //四个角的平均值加随机高度
		} 	
		
		// square阶段	
		//不停地迭代,更新四周的高度值
		int pointNum = ((t + 1) << 1) + 1;	//2t+3
		int pointStep = (n - 1) / (pointNum - 1);	//(n-1)/(2t+2) = (2^time)/(2t+2)
		for (int i = 0; i < pointNum; i++)
		{			
			for (int j = 0; j < pointNum; j++) 
			{				
				if ((i + j) % 2 == 1) //间错交替,可理解为黑白格中的黑格
				{					  //作用是筛出了一半格子,这一半格子每个格子的上下左右都是空的
					float r = randnum(.5) * roughness;	//又生成一个随机高度
					if (i == 0) //data的第一列
					{			
						//data[i*pointStep][j*pointStep] = //randnum(.5) * roughness;
						data[i*pointStep][j*pointStep] =		//data[0][j*ps]=
							(data[n - pointStep][j*pointStep] +		//( data[n-ps][j*ps] +
							data[(i + 1)*pointStep][j*pointStep] +	//data[ps][j*ps] +
							data[i*pointStep][(j + 1)*pointStep] +	//data[0][(j+1)*ps]	+
							data[i*pointStep][(j-1)*pointStep]) / 4 + r;	//data[0][(j-1)*ps] )/4 + r;
					}			//相当于是把第一列左边用最右边补齐了,就是中间格子的特殊化而已,计算的规则是一样的
								//就是把ps当成单位1(把单位1放大ps倍),然后每个格子都是自己上下左右的平均值+随机高度
								//那么下面应该都是同理了
					else if (j == 0)
					{		
						data[i*pointStep][j*pointStep] = //randnum(.5) * roughness;
						(data[(i-1)*pointStep][j*pointStep] +	
						data[(i + 1)*pointStep][j*pointStep] +	
						data[i*pointStep][(j + 1)*pointStep] +		
						data[i*pointStep][n - pointStep]) / 4 + r;		
					}					
					else if (i == pointNum - 1)
					{						
						data[i*pointStep][j*pointStep] = //randnum(.5) * roughness;
							(data[pointStep][j*pointStep] +	
							data[(i - 1)*pointStep][j*pointStep] +
							data[i*pointStep][(j + 1)*pointStep] +	
							data[i*pointStep][(j - 1)*pointStep]) / 4 + r;	
					}				
					else if (j == pointNum - 1)
					{					
						data[i*pointStep][j*pointStep] =// randnum(.5) * roughness;
							(data[(i-1)*pointStep][j*pointStep] +	
							data[(i + 1)*pointStep][j*pointStep] +		
							data[i*pointStep][pointStep] +				
							data[i*pointStep][(j - 1)*pointStep]) / 4 + r;	
					}				
					else 
					{		
						data[i*pointStep][j*pointStep] = //randnum(.5) * roughness;
							(data[(i - 1)*pointStep][j*pointStep] +	
							data[(i + 1)*pointStep][j*pointStep] +		
							data[i*pointStep][(j + 1)*pointStep] +			
							data[i*pointStep][(j - 1)*pointStep]) / 4 + r;	
					}				
				}			
			}		
		}		
		size >>= 1;	// size/2 ,就是一圈一圈地算
		number <<= 1; // number*2 
	} 
	
	// 把data映射到vertex数据上,并删除data,同时计算出最大高度和最小高度
	minHeight = 10000;	
	maxHeight = -10000;
	for (int i = 0; i < n; i++)
	{		
		for (int j = 0; j < n; j++) 
		{	//in+j是B的下标,这三个一组对应的是B
			//vertex[3 * (i*n + j)] = i*step - n*step / 2;        //第一个 x=( i - n/2 )*step
			//vertex[3 * (i*n + j) + 1] = data[i][j];		        //第二个 y= 高度值(随机随出来的)
			//vertex[3 * (i*n + j) + 2] = j*step - n*step / 2;	//第三个 z=( j - n/2 )*step

			vertex[3 * (i*n + j)] = i*step ;        //第一个 x=( i - n/2 )*step
			vertex[3 * (i*n + j) + 1] = data[i][j];		        //第二个 y= 高度值(随机随出来的)
			vertex[3 * (i*n + j) + 2] = j*step ;	//第三个 z=( j - n/2 )*step

			if (maxHeight < data[i][j])
			{				
				maxHeight = data[i][j];		
			}			
			if (minHeight > data[i][j])
			{			
				minHeight = data[i][j];	
			}	
		}		
		delete[] data[i];
	}	
	delete[] data; 
	// 生成索引	
	genIndice();
} 

// 根据高度选择颜色
void fractal::chooseColor(float height)
{	
	const GLfloat blue[] = { 1.0 * 65 / 255, 1.0 * 127 / 255, 1.0 * 219 / 255 };	
	const GLfloat green[] = { 1.0 * 73 / 255, 1.0 * 161 / 255, 1.0 * 101 / 255 };	
	const GLfloat yellow[] = { 1.0 * 172 / 255, 1.0 * 189 / 255, 1.0 * 117 / 255 };	
	const GLfloat brown[] = { 1.0 * 153 / 255, 1.0 * 123 / 255, 1.0 * 46 / 255 }; 	
	float interval = maxHeight - minHeight;
	if (height < minHeight + interval / 4)
	{		
		glColor3fv(blue);
	}	
	else if (height < minHeight + interval / 2)
	{		
		glColor3fv(green);
	}	
	else if (height < minHeight + 3 * interval / 4)
	{		
		glColor3fv(yellow);
	}	
	else if (height < maxHeight)
	{		
		glColor3fv(brown);	
	}
} 
 
TriangleVertexs fractal::AreaDotProduct(TriangleVertexs V1, TriangleVertexs V2, TriangleVertexs V3)
{
	//A 2->3   3-2    B 2->1 1-2
	A[0] = V3.xyz[0] - V2.xyz[0];
	A[1] = V3.xyz[1] - V2.xyz[1];
	A[2] = V3.xyz[2] - V2.xyz[2];
	B[0] = V1.xyz[0] - V2.xyz[0];
	B[1] = V1.xyz[1] - V2.xyz[1]; 
	B[2] = V1.xyz[2] - V2.xyz[2]; 
	normal.xyz[0] = A[1] * B[2] - B[1] * A[2];
	normal.xyz[1] = A[2] * B[0] - A[0] * B[2];
	normal.xyz[2] = A[0] * B[1] - A[1] * B[0];
	return normal;
}

void fractal::PointDotProduct(int ij)
{
	int i = ij / n;
	int j = ij % n;
	if (i == 0 && j == 0)//左上角
	{
		result[ij].Pnormal[0] = 0.5 *
			( AreaDotProduct(result[0], result[1], result[n + 1]).xyz[0] 
			+ AreaDotProduct(result[n], result[0], result[n + 1]).xyz[0] );
		result[ij].Pnormal[1] = 0.5 *
			(AreaDotProduct(result[0], result[1], result[n + 1]).xyz[1]
			+ AreaDotProduct(result[n], result[0], result[n + 1]).xyz[1]);
		result[ij].Pnormal[2] = 0.5 *
			(AreaDotProduct(result[0], result[1], result[n + 1]).xyz[2]
			+ AreaDotProduct(result[n], result[0], result[n + 1]).xyz[2]);
	}
	else if (i == (n - 1) && j == 0) //右上角
	{
		result[ij].Pnormal[0] = AreaDotProduct(result[i * n], result[(i - 1) * n], result[i * n + 1]).xyz[0];
		result[ij].Pnormal[1] = AreaDotProduct(result[i * n], result[(i - 1) * n], result[i * n + 1]).xyz[1];
		result[ij].Pnormal[2] = AreaDotProduct(result[i * n], result[(i - 1) * n], result[i * n + 1]).xyz[2];
	}
	else if (i == 0 && j == (n - 1)) //左下角
	{
		result[ij].Pnormal[0] = AreaDotProduct(result[i - 1], result[i], result[i + n]).xyz[0];
		result[ij].Pnormal[1] = AreaDotProduct(result[i - 1], result[i], result[i + n]).xyz[1];
		result[ij].Pnormal[2] = AreaDotProduct(result[i - 1], result[i], result[i + n]).xyz[2];
	}
	else if (i == (n - 1) && j == (n - 1))//右下角
	{
		result[ij].Pnormal[0] = 0.5 *
			(AreaDotProduct(result[(i - 1) * n + j - 1], result[(i - 1) * n + j], result[i * n + j]).xyz[0]
			+ AreaDotProduct(result[i * n+j], result[i * n + j - 1], result[(i - 1) * n + j - 1]).xyz[0]);
		result[ij].Pnormal[1] = 0.5 *
			(AreaDotProduct(result[(i - 1) * n + j - 1], result[(i - 1) * n + j], result[i * n + j]).xyz[1]
			+ AreaDotProduct(result[i * n + j], result[i * n + j - 1], result[(i - 1) * n + j - 1]).xyz[1]);
		result[ij].Pnormal[2] = 0.5 *
			(AreaDotProduct(result[(i - 1) * n + j - 1], result[(i - 1) * n + j], result[i * n + j]).xyz[2]
			+ AreaDotProduct(result[i * n + j], result[i * n + j - 1], result[(i - 1) * n + j - 1]).xyz[2]);
	}
	else if (i == 0) //最左一列
	{
		result[ij].Pnormal[0] = 0.3333 *
			(AreaDotProduct(result[i * n + j], result[i * n + j + 1], result[(i + 1) * n + j + 1]).xyz[0]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j + 1], result[(i + 1) * n + j]).xyz[0]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j], result[i * n + j - 1]).xyz[0]);
		result[ij].Pnormal[1] = 0.3333 *
			(AreaDotProduct(result[i * n + j], result[i * n + j + 1], result[(i + 1) * n + j + 1]).xyz[1]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j + 1], result[(i + 1) * n + j]).xyz[1]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j], result[i * n + j - 1]).xyz[1]);
		result[ij].Pnormal[2] = 0.3333 *
			(AreaDotProduct(result[i * n + j], result[i * n + j + 1], result[(i + 1) * n + j + 1]).xyz[2]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j + 1], result[(i + 1) * n + j]).xyz[2]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j], result[i * n + j - 1]).xyz[2]);
	}
	else if (j == 0) //最上一行
	{
		result[ij].Pnormal[0] = 0.3333 *
			(AreaDotProduct(result[i * n + j], result[(i - 1) * n + j], result[i * n + j + 1]).xyz[0]
			+ AreaDotProduct(result[i * n + j], result[i * n + j + 1], result[(i + 1) * n + j + 1]).xyz[0]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j + 1], result[(i + 1) * n + j]).xyz[0]);
		result[ij].Pnormal[1] = 0.3333 *
			(AreaDotProduct(result[i * n + j], result[(i - 1) * n + j], result[i * n + j + 1]).xyz[1]
			+ AreaDotProduct(result[i * n + j], result[i * n + j + 1], result[(i + 1) * n + j + 1]).xyz[1]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j + 1], result[(i + 1) * n + j]).xyz[1]);
		result[ij].Pnormal[2] = 0.3333 *
			(AreaDotProduct(result[i * n + j], result[(i - 1) * n + j], result[i * n + j + 1]).xyz[2]
			+ AreaDotProduct(result[i * n + j], result[i * n + j + 1], result[(i + 1) * n + j + 1]).xyz[2]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j + 1], result[(i + 1) * n + j]).xyz[2]);
	}
	else if (i == n - 1)//最右一列
	{
		result[ij].Pnormal[0] = 0.3333 *
			(AreaDotProduct(result[i * n + j], result[i * n + j - 1], result[(i - 1) * n + j - 1]).xyz[0]
			+ AreaDotProduct(result[i * n + j], result[(i - 1) * n + j - 1], result[(i - 1) * n + j]).xyz[0]
			+ AreaDotProduct(result[i * n + j], result[(i - 1) * n + j], result[i * n + j + 1]).xyz[0]);
		result[ij].Pnormal[1] = 0.3333 *
			(AreaDotProduct(result[i * n + j], result[i * n + j - 1], result[(i - 1) * n + j - 1]).xyz[1]
			+ AreaDotProduct(result[i * n + j], result[(i - 1) * n + j - 1], result[(i - 1) * n + j]).xyz[1]
			+ AreaDotProduct(result[i * n + j], result[(i - 1) * n + j], result[i * n + j + 1]).xyz[1]);
		result[ij].Pnormal[2] = 0.3333 *
			(AreaDotProduct(result[i * n + j], result[i * n + j - 1], result[(i - 1) * n + j - 1]).xyz[2]
			+ AreaDotProduct(result[i * n + j], result[(i - 1) * n + j - 1], result[(i - 1) * n + j]).xyz[2]
			+ AreaDotProduct(result[i * n + j], result[(i - 1) * n + j], result[i * n + j + 1]).xyz[2]);
	}
	else if (j == n - 1)//最下一行
	{
		result[ij].Pnormal[0] = 0.3333 *
			(AreaDotProduct(result[i * n + j], result[i * n + j - 1], result[(i - 1) * n + j - 1]).xyz[0]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j], result[i * n + j - 1]).xyz[0]
			+ AreaDotProduct(result[i * n + j], result[(i - 1) * n + j - 1], result[(i - 1) * n + j]).xyz[0]);
		result[ij].Pnormal[1] = 0.3333 *
			(AreaDotProduct(result[i * n + j], result[i * n + j - 1], result[(i - 1) * n + j - 1]).xyz[1]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j], result[i * n + j - 1]).xyz[1]
			+ AreaDotProduct(result[i * n + j], result[(i - 1) * n + j - 1], result[(i - 1) * n + j]).xyz[1]);
		result[ij].Pnormal[2] = 0.3333 *
			(AreaDotProduct(result[i * n + j], result[i * n + j - 1], result[(i - 1) * n + j - 1]).xyz[2]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j], result[i * n + j - 1]).xyz[2]
			+ AreaDotProduct(result[i * n + j], result[(i - 1) * n + j - 1], result[(i - 1) * n + j]).xyz[2]);
	}
	else //左加右
	{
		result[ij].Pnormal[0] = 0.1667 *
			( AreaDotProduct(result[i * n + j], result[i * n + j + 1], result[(i + 1) * n + j + 1]).xyz[0]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j + 1], result[(i + 1) * n + j]).xyz[0]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j], result[i * n + j - 1]).xyz[0]
			+ AreaDotProduct(result[i * n + j], result[i * n + j - 1], result[(i - 1) * n + j - 1]).xyz[0]
			+ AreaDotProduct(result[i * n + j], result[(i - 1) * n + j - 1], result[(i - 1) * n + j]).xyz[0]
			+ AreaDotProduct(result[i * n + j], result[(i - 1) * n + j], result[i * n + j + 1]).xyz[0] );
		result[ij].Pnormal[1] = 0.1667 *
			( AreaDotProduct(result[i * n + j], result[i * n + j + 1], result[(i + 1) * n + j + 1]).xyz[1]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j + 1], result[(i + 1) * n + j]).xyz[1]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j], result[i * n + j - 1]).xyz[1]
			+ AreaDotProduct(result[i * n + j], result[i * n + j - 1], result[(i - 1) * n + j - 1]).xyz[1]
			+ AreaDotProduct(result[i * n + j], result[(i - 1) * n + j - 1], result[(i - 1) * n + j]).xyz[1]
			+ AreaDotProduct(result[i * n + j], result[(i - 1) * n + j], result[i * n + j + 1]).xyz[1] );
		result[ij].Pnormal[2] = 0.1667 *
			( AreaDotProduct(result[i * n + j], result[i * n + j + 1], result[(i + 1) * n + j + 1]).xyz[2]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j + 1], result[(i + 1) * n + j]).xyz[2]
			+ AreaDotProduct(result[i * n + j], result[(i + 1) * n + j], result[i * n + j - 1]).xyz[2]
			+ AreaDotProduct(result[i * n + j], result[i * n + j - 1], result[(i - 1) * n + j - 1]).xyz[2]
			+ AreaDotProduct(result[i * n + j], result[(i - 1) * n + j - 1], result[(i - 1) * n + j]).xyz[2]
			+ AreaDotProduct(result[i * n + j], result[(i - 1) * n + j], result[i * n + j + 1]).xyz[2] );
	}
}


void fractal::draw()
{	
	glPushMatrix();
	const GLfloat green[] = { 1.0 * 73 / 255, 1.0 * 161 / 255, 1.0 * 101 / 255 };
	glColor3fv(green);
	//glEnable()
	for (int i = 0; i < indiceNum / 3; i++)
	{
		glBegin(GL_TRIANGLE_STRIP);
		//i = indice[3 * i]/n  j = indice[3 * i]%n
		// indice[3 * i] = in+j
		result[indice[3 * i]].xyz[0] = vertex[3 * indice[3 * i]];
		result[indice[3 * i]].xyz[1] = vertex[3 * indice[3 * i] + 1];
		result[indice[3 * i]].xyz[2] = vertex[3 * indice[3 * i] + 2];
		PointDotProduct(indice[3 * i]);
		glNormal3f(result[indice[3 * i]].Pnormal[0], result[indice[3 * i]].Pnormal[1], result[indice[3 * i]].Pnormal[2]);
		glVertex3fv(result[indice[3 * i]].xyz);//一个点

		result[indice[3 * i + 1]].xyz[0] = vertex[3 * indice[3 * i + 1]];
		result[indice[3 * i + 1]].xyz[1] = vertex[3 * indice[3 * i + 1] + 1];
		result[indice[3 * i + 1]].xyz[2] = vertex[3 * indice[3 * i + 1] + 2];
		PointDotProduct(indice[3 * i + 1]);
		glNormal3f(result[indice[3 * i + 1]].Pnormal[0], result[indice[3 * i + 1]].Pnormal[1], result[indice[3 * i + 1]].Pnormal[2]);
		glVertex3fv(result[indice[3 * i + 1]].xyz);//两个点

		result[indice[3 * i + 2]].xyz[0] = vertex[3 * indice[3 * i + 2]];
		result[indice[3 * i + 2]].xyz[1] = vertex[3 * indice[3 * i + 2] + 1];
		result[indice[3 * i + 2]].xyz[2] = vertex[3 * indice[3 * i + 2] + 2];
		PointDotProduct(indice[3 * i + 2]);
		glNormal3f(result[indice[3 * i + 2]].Pnormal[0], result[indice[3 * i + 2]].Pnormal[1], result[indice[3 * i + 2]].Pnormal[2]);
		glVertex3fv(result[indice[3 * i + 2]].xyz);//三个点

		glEnd();

		//AreaDotProduct(result[indice[3 * i]], result[indice[3 * i + 1]], result[indice[3 * i + 2]]);
		//cout << "三角形" << i << "法向:(" << normal[0] << "," << ends << normal[1] << "," << ends << normal[2] << ")" << endl;
	}

	glColor3f(1,1,1);	
	glPopMatrix();
}

  

stdafx.h

// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//

#pragma once

#include "targetver.h"
#include <stdio.h>
#include <tchar.h>

// TODO: 在此处引用程序需要的其他头文件

  

stdafx.cpp

// stdafx.cpp : 只包括标准包含文件的源文件
// OpenGL_exe1.pch 将作为预编译头
// stdafx.obj 将包含预编译类型信息

#include "stdafx.h"

// TODO: 在 STDAFX.H 中
// 引用任何所需的附加头文件,而不是在此文件中引用

  

targetver.h

#pragma once

// 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。

// 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并将
// WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。

#include <SDKDDKVer.h>

  

main.cpp

#define _CRT_SECURE_NO_WARNINGS  
#include <stdlib.h>    
#include <time.h>  
#include <gl/glut.h>
#include <gl/gl.h>
#include"fractal.h"   

fractal* f;
float center[] = { 0, 0, 0 };
//float eye[] = { 0, 100, 400};
float eye[] = { 0, 0, 200};
//float tx=0,ty = 200, ax, ay=0, mx, my, zoom = 0;
float tx , ty =10, ax, ay = 10, mx, my=0 ,zoom = -60;
bool isLine = false;
bool isDown = false;
GLfloat roomSizeY = 15;


void reshape(int width, int height)
{	
	if (height == 0)
	{    		
		height = 1; 
	}	
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);	
	glLoadIdentity();	
	float whRatio = (GLfloat)width / (GLfloat)height;	
	gluPerspective(45, whRatio, 1, 500);
	glMatrixMode(GL_MODELVIEW);
}
void idle()
{	
	glutPostRedisplay();//标记当前窗体来重新显示,会促使主循环尽快的调用完显示函数
} 


void init(void)
{	
	glClearColor(1.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_DEPTH_TEST);	

	  //光照
	GLfloat position[4] = { 10.0, 1.0, 10.0, 1.0 };//最后一个参数为0,说明是方向性光源,不考虑衰减;非0则为位置性光源,考虑衰减
	glLightfv(GL_LIGHT0, GL_POSITION, position);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);

	GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };//环境光
	GLfloat diffuse[] = { 0.25, 0.95, 0.5, 1.0 };//漫反射
	GLfloat specular[] = { 0.0, 0.0, 0.0, 1.0 };//镜面反射
	glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
	glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
	glMaterialfv(GL_FRONT, GL_SPECULAR, specular);

	glBlendFunc(GL_SRC_ALPHA, GL_ONE);
	glEnable(GL_COLOR_MATERIAL);
	glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

	// height : 值越大,地形起伏越大 	
	// times  : 迭代次数,次数越多,tire越多
	// step   : 绘制时一个网格的程度	
	// D      : 随机数衰减因子,越大随机数随迭代的取值越小(大于1)
	// seed   : 随机数种子	
	f = new fractal(5, 8, 2, 2, 23);
	f->calculate();
} 
void redraw()
{	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
	glClearColor(0, 0, 0, 1);
	glMatrixMode(GL_MODELVIEW);	
	glLoadIdentity();      
	//gluLookAt(eye[0], eye[1], eye[2], center[0], center[1], center[2], 0, 1, 0); 
	gluLookAt(0,0,200, 0,0,0, 0,1,0);
	if(isLine)glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);	
	else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);	
	glTranslatef(tx,ty,zoom);	
	glRotatef(ax, 1.0f, 0.0f, 0.0f);
	glRotatef(ay, 0.0f, 1.0f, 0.0f); 	
	glPushMatrix();
	glTranslatef(0, -roomSizeY / 2,0);
	f->draw();	

	glPopMatrix(); 
	glutSwapBuffers();
} 
void myMouse(int button, int state, int x, int y)
{	
	if (button == GLUT_LEFT_BUTTON) 
	{		
		if (state == GLUT_DOWN)
		{			
			isDown = true;	
			mx = x;		
			my = y;		
		}		
		else if (state == GLUT_UP)
		{			
			isDown = false;	
		}	
	}	
	glutPostRedisplay();
} 
void mouseMotion(int x, int y)
{	
	if (isDown)
	{		
		ax += 1.0f*(y - my) / 10.0f;
		ay += 1.0f*(x - mx) / 10.0f;	
		mx = x;	
		my = y;
	}	
	glutPostRedisplay();
} 
void myKeyboard(unsigned char key, int x, int y)
{	
	switch (key)
	{	
	case 'a': 
		//左移  
		tx -= 10;	
		break;		
	case 'd':
		//右移  
		tx += 10;	
		break;
	case 'w': 
		//上移  
		ty += 10;		
		break;
	case 's': 
		//下移  		
		ty -= 10;
		break;
	case 'z':
		//后移
		zoom += 10;	
		break;
	case 'c': 
		//前移  
		zoom -= 10;	
		break;
	case 'p':
		// 切换绘制模式	
		if (isLine) 
		{		
			isLine = false;	
		}		
		else isLine = true;
	}	
	glutPostRedisplay();
} 

int main(int argc, char *argv[])
{	
	glutInit(&argc, argv);  
	glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);   
	glutInitWindowSize(800, 600);	
	int windowHandle = glutCreateWindow("地形图");    
	glutDisplayFunc(redraw);             
	glutReshapeFunc(reshape);      
	glutMouseFunc(myMouse);	
	glutMotionFunc(mouseMotion);
	glutKeyboardFunc(myKeyboard);	
	glutIdleFunc(idle);          
	init();	
	glutMainLoop();  
	system("pause");
	return 0;
}

  

配置环境:VS2013 + glut-3.7.6

posted @ 2019-10-28 22:11  一个圆球  阅读(580)  评论(0编辑  收藏  举报