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 }