1 #include <stdlib.h>
2 #include <math.h>
3 #include "OgreMath.h"
4 #include "PerlinNoiseTerrainGenerator.h"
5
6 using namespace Ogre;
7
8 #define BM 0xff
9 #define N 0x1000
10 #define NP 12 /* 2^N */
11 #define NM 0xfff
12
PerlinNoiseTerrainGenerator(const Real & alpha,const Real & beta,int iterationNum,const Real & cycle,const Real & heightScale)13 PerlinNoiseTerrainGenerator::PerlinNoiseTerrainGenerator(const Real& alpha, const Real& beta, int iterationNum, const Real& cycle, const Real& heightScale)
14 : mAlpha(alpha)
15 , mBeta(beta)
16 , mIterationNum(iterationNum)
17 , mCycle(cycle)
18 , mHeightScale(heightScale)
19 , mOriginPoint(0.f)
20 {
21 for (int i = 0 ; i < B ; i++) {
22 p[i] = i;
23 g1[i] = Math::SymmetricRandom();
24
25 g2[i] = Vector2(Math::SymmetricRandom(), Math::SymmetricRandom());
26 g2[i].normalise();
27
28 g3[i] = Vector3(Math::SymmetricRandom(), Math::SymmetricRandom(), Math::SymmetricRandom());
29 g3[i].normalise();
30 }
31
32 for (int i = 0 ; i < B ; i++) {
33 int j = (int) Math::RangeRandom (0,B);
34
35 int k = p[i];
36 p[i] = p[j];
37 p[j] = k;
38 }
39
40 for (int i = 0 ; i < B + 2 ; i++) {
41 p[B + i] = p[i];
42 g1[B + i] = g1[i];
43 g2[B + i] = g2[i];
44 g3[B + i] = g3[i];
45 }
46 }
47
define(TerrainGroup * terrainGroup,long x,long y)48 void PerlinNoiseTerrainGenerator::define( TerrainGroup* terrainGroup, long x, long y )
49 {
50 uint16 terrainSize = terrainGroup->getTerrainSize();
51 float* heightMap = OGRE_ALLOC_T(float, terrainSize*terrainSize, MEMCATEGORY_GEOMETRY);
52
53 Vector2 worldOffset( Real(x*(terrainSize-1)), Real(y*(terrainSize-1)) );
54 worldOffset += mOriginPoint;
55
56 Vector2 revisedValuePoint;
57 for( uint16 i=0; i<terrainSize; i++ )
58 for( uint16 j=0; j<terrainSize; j++ )
59 {
60 revisedValuePoint = (worldOffset + Vector2(j,i)) / mCycle;
61 heightMap[i*terrainSize + j] = produceSingleHeight( revisedValuePoint ) * mHeightScale;
62 }
63 terrainGroup->defineTerrain(x,y,heightMap);
64 OGRE_FREE(heightMap, MEMCATEGORY_GEOMETRY);
65 }
66
produceSingleHeight(const Vector2 & vec2)67 Real PerlinNoiseTerrainGenerator::produceSingleHeight(const Vector2& vec2)
68 {
69 Vector2 tempVec(vec2);
70 Real sum = 0;
71 Real scale = 1;
72
73 for (int i=0;i<mIterationNum;i++)
74 {
75 sum += noise(tempVec) / scale;
76 scale *= mAlpha;
77 tempVec *= mBeta;
78 }
79 return sum;
80 }
81
noise(const Vector2 & vec2)82 Real PerlinNoiseTerrainGenerator::noise(const Vector2& vec2)
83 {
84 int bx0, bx1, by0, by1, b00, b10, b01, b11;
85 Real rx0, rx1, ry0, ry1, sx, sy, a, b, u, v;
86
87 setup(vec2.x, bx0,bx1, rx0,rx1);
88 setup(vec2.y, by0,by1, ry0,ry1);
89
90 int i = p[ bx0 ];
91 int j = p[ bx1 ];
92
93 b00 = p[ i + by0 ];
94 b10 = p[ j + by0 ];
95 b01 = p[ i + by1 ];
96 b11 = p[ j + by1 ];
97
98 sx = sCurve(rx0);
99 sy = sCurve(ry0);
100
101 u = g2[b00].dotProduct( Vector2(rx0,ry0) );
102 v = g2[b10].dotProduct( Vector2(rx1,ry0) );
103 a = lerp(sx, u, v);
104
105 u = g2[b01].dotProduct( Vector2(rx0,ry1) );
106 v = g2[b11].dotProduct( Vector2(rx1,ry1) );
107 b = lerp(sx, u, v);
108
109 return lerp(sy, a, b);
110 }
111
setup(const Real & target,int & b0,int & b1,Real & r0,Real & r1)112 void PerlinNoiseTerrainGenerator::setup( const Real& target, int& b0, int& b1, Real& r0, Real& r1)
113 {
114 Real t = target + N;
115 b0 = ((int)t) & BM;
116 b1 = (b0+1) & BM;
117 r0 = t - (int)t;
118 r1 = r0 - 1;
119 }
120
randomize()121 void PerlinNoiseTerrainGenerator:: randomize()
122 {
123 mOriginPoint.x = Math::RangeRandom( -1000, 1000 );
124 mOriginPoint.y = Math::RangeRandom( -1000, 1000 );
125 }