zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    js公共时间戳方法es6
    vue权限路由
    vue中websocket心跳写法
    vue引入全局组件和局部组件的区别以及全局注册公共函数
    [干货]关于vue作用域插槽的新的深入理解
    vue系统指令v-text(前端网备份)
    浏览器兼容html头部<meta>标签主要内容详情
    如何设置td中溢出内容的隐藏显示
    7-4列表/元组/字典/集合的内置方法
    7-3 整型/浮点型/字符串/列表常用方法
  • 原文地址:https://www.cnblogs.com/yigeqiu/p/11755927.html
Copyright © 2011-2022 走看看