Ykkrosh
8fee3d8ef8
Add textured line overlay rendering. Change terrain height calculations to be triangulation-dependent for improved accuracy. Add triangulation-dependent terrain normal function. Support separate S/T wrap modes for textures. Rename CVector2D_Maths since it no longer conflicts with simulation CVector2D. Coalesce freed chunks in vertex buffers, to avoid excessive fragmentation. Add some things to help debug vertex buffer allocation a little. This was SVN commit r9929.
185 lines
4.1 KiB
C++
185 lines
4.1 KiB
C++
/* Copyright (C) 2009 Wildfire Games.
|
|
* This file is part of 0 A.D.
|
|
*
|
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* 0 A.D. is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/*
|
|
* 2D and 3D seamless Perlin noise
|
|
*/
|
|
|
|
// Based on http://www.cs.cmu.edu/~mzucker/code/perlin-noise-math-faq.html
|
|
// and http://mrl.nyu.edu/~perlin/paper445.pdf.
|
|
// Not optimized for speed yet.
|
|
|
|
#include "precompiled.h"
|
|
#include "Noise.h"
|
|
#include <cmath>
|
|
#include <boost/random/mersenne_twister.hpp>
|
|
|
|
namespace
|
|
{
|
|
/// Random number generator (Boost Mersenne Twister)
|
|
boost::mt19937 rng;
|
|
|
|
/// Utility function for random numbers
|
|
float randFloat() {
|
|
return ((float)rng()) / 4294967296.0f;
|
|
}
|
|
|
|
/// Utility function used in both noises as an ease curve
|
|
float easeCurve(float t)
|
|
{
|
|
return t*t*t*(t*(t*6-15)+10);
|
|
}
|
|
}
|
|
|
|
Noise2D::Noise2D(int f)
|
|
{
|
|
freq = f;
|
|
grads = new CVector2D*[freq];
|
|
for(int i=0; i<freq; i++)
|
|
{
|
|
grads[i] = new CVector2D[freq];
|
|
for(int j=0; j<freq; j++)
|
|
{
|
|
float a = randFloat() * 2 * (float)M_PI;
|
|
grads[i][j] = CVector2D(cos(a), sin(a));
|
|
}
|
|
}
|
|
}
|
|
|
|
Noise2D::~ Noise2D()
|
|
{
|
|
for(int i=0; i<freq; i++)
|
|
{
|
|
delete[] grads[i];
|
|
}
|
|
delete[] grads;
|
|
}
|
|
|
|
float Noise2D::operator()(float x, float y)
|
|
{
|
|
x *= freq;
|
|
y *= freq;
|
|
|
|
int ix = (int)floor(x);
|
|
int iy = (int)floor(y);
|
|
|
|
float fx = x - ix;
|
|
float fy = y - iy;
|
|
|
|
ix %= freq; if(ix<0) ix += freq;
|
|
iy %= freq; if(iy<0) iy += freq;
|
|
|
|
int ix1 = (ix+1) % freq;
|
|
int iy1 = (iy+1) % freq;
|
|
|
|
float s = grads[ix][iy].Dot(CVector2D(fx, fy));
|
|
float t = grads[ix1][iy].Dot(CVector2D(fx-1, fy));
|
|
float u = grads[ix][iy1].Dot(CVector2D(fx, fy-1));
|
|
float v = grads[ix1][iy1].Dot(CVector2D(fx-1, fy-1));
|
|
|
|
float ex = easeCurve(fx);
|
|
float ey = easeCurve(fy);
|
|
float a = s + ex*(t-s);
|
|
float b = u + ex*(v-u);
|
|
return (a + ey*(b-a)) * .5 + .5;
|
|
}
|
|
|
|
Noise3D::Noise3D(int f, int v) : freq(f), vfreq(v)
|
|
{
|
|
grads = new CVector3D**[freq];
|
|
for(int i=0; i<freq; i++)
|
|
{
|
|
grads[i] = new CVector3D*[freq];
|
|
for(int j=0; j<freq; j++)
|
|
{
|
|
grads[i][j] = new CVector3D[vfreq];
|
|
for(int k=0; k<vfreq; k++)
|
|
{
|
|
CVector3D vec;
|
|
do {
|
|
vec = CVector3D(2*randFloat()-1, 2*randFloat()-1, 2*randFloat()-1);
|
|
}
|
|
while(vec.LengthSquared() > 1 || vec.LengthSquared() < 0.1);
|
|
vec.Normalize();
|
|
grads[i][j][k] = CVector3D(vec.X, vec.Y, vec.Z);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Noise3D::~ Noise3D()
|
|
{
|
|
for(int i=0; i<freq; i++)
|
|
{
|
|
for(int j=0; j<freq; j++)
|
|
{
|
|
delete[] grads[i][j];
|
|
}
|
|
delete[] grads[i];
|
|
}
|
|
delete[] grads;
|
|
}
|
|
|
|
float Noise3D::operator()(float x, float y, float z)
|
|
{
|
|
x *= freq;
|
|
y *= freq;
|
|
z *= vfreq;
|
|
|
|
int ix = (int)floor(x);
|
|
int iy = (int)floor(y);
|
|
int iz = (int)floor(z);
|
|
|
|
float fx = x - ix;
|
|
float fy = y - iy;
|
|
float fz = z - iz;
|
|
|
|
ix %= freq; if(ix<0) ix += freq;
|
|
iy %= freq; if(iy<0) iy += freq;
|
|
iz %= vfreq; if(iz<0) iz += vfreq;
|
|
|
|
int ix1 = (ix+1) % freq;
|
|
int iy1 = (iy+1) % freq;
|
|
int iz1 = (iz+1) % vfreq;
|
|
|
|
float s0 = grads[ix][iy][iz].Dot(CVector3D(fx, fy, fz));
|
|
float t0 = grads[ix1][iy][iz].Dot(CVector3D(fx-1, fy, fz));
|
|
float u0 = grads[ix][iy1][iz].Dot(CVector3D(fx, fy-1, fz));
|
|
float v0 = grads[ix1][iy1][iz].Dot(CVector3D(fx-1, fy-1, fz));
|
|
|
|
float s1 = grads[ix][iy][iz1].Dot(CVector3D(fx, fy, fz-1));
|
|
float t1 = grads[ix1][iy][iz1].Dot(CVector3D(fx-1, fy, fz-1));
|
|
float u1 = grads[ix][iy1][iz1].Dot(CVector3D(fx, fy-1, fz-1));
|
|
float v1 = grads[ix1][iy1][iz1].Dot(CVector3D(fx-1, fy-1, fz-1));
|
|
|
|
float ex = easeCurve(fx);
|
|
float ey = easeCurve(fy);
|
|
float ez = easeCurve(fz);
|
|
|
|
float a0 = s0 + ex*(t0-s0);
|
|
float b0 = u0 + ex*(v0-u0);
|
|
float c0 = a0 + ey*(b0-a0);
|
|
|
|
float a1 = s1 + ex*(t1-s1);
|
|
float b1 = u1 + ex*(v1-u1);
|
|
float c1 = a1 + ey*(b1-a1);
|
|
|
|
return (c0 + ez*(c1-c0)) * .5 + .5;
|
|
}
|
|
|
|
|