函数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