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