some working perlin noise rubbish and subdivision of sphere with some edge fixup...

git-svn-id: https://pioneer.svn.sourceforge.net/svnroot/pioneer/trunk@222 e632f14b-6550-0410-b89e-a82653faca30
master
tompox 2009-03-15 12:14:26 +00:00
parent 06c1d43c4e
commit b904be91c1
6 changed files with 280 additions and 1050 deletions

1026
aclocal.m4 vendored

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@ include_HEADERS = Body.h Frame.h GenericSystemView.h glfreetype.h GuiButton.h Gu
SystemView.h vector3.h View.h WorldView.h utils.h SpaceStation.h SpaceStationView.h ModelBody.h GuiISelectable.h \
ShipType.h Object.h InfoView.h ModelCollMeshData.h ObjectViewerView.h custom_starsystems.h Aabb.h Serializer.h \
Sfx.h GuiVScrollPortal.h GuiVScrollBar.h GuiAdjustment.h MarketAgent.h GuiTabbed.h EquipType.h CargoBody.h \
NameGenerator.h
NameGenerator.h perlin.h
libgui_a_SOURCES = GuiButton.cpp Gui.cpp GuiFixed.cpp GuiScreen.cpp GuiLabel.cpp GuiToolTip.cpp GuiToggleButton.cpp GuiRadioButton.cpp \
GuiRadioGroup.cpp GuiImageButton.cpp GuiImage.cpp GuiImageRadioButton.cpp GuiMultiStateImageButton.cpp GuiWidget.cpp \
@ -21,7 +21,7 @@ pioneer_SOURCES = main.cpp glfreetype.cpp Body.cpp Space.cpp Ship.cpp Player.cpp
StarSystem.cpp Sector.cpp SystemInfoView.cpp GenericSystemView.cpp utils.cpp SpaceStation.cpp \
SpaceStationView.cpp ModelBody.cpp ShipType.cpp InfoView.cpp ModelCollMeshData.cpp \
ObjectViewerView.cpp custom_starsystems.cpp Serializer.cpp Sfx.cpp Ship-AI.cpp MarketAgent.cpp \
EquipType.cpp CargoBody.cpp NameGenerator.cpp
EquipType.cpp CargoBody.cpp NameGenerator.cpp perlin.cpp
pioneer_LDADD = sbre/libsbre.a collider/libcollider.a mods/libmods.a libgui.a
sbreviewer_SOURCES = SbreViewer.cpp glfreetype.cpp

View File

@ -5,6 +5,7 @@
#include "WorldView.h"
#include "Serializer.h"
#include "StarSystem.h"
#include "perlin.h"
Planet::Planet(SBody *sbody): Body()
{
@ -884,21 +885,55 @@ static float nus_vdata[12][3] = {
};
static int nus_tindices[20][3] = {
{0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
{8,10,1}, {8,3,10},{5,3,8}, {5,2,3}, {2,7,3},
{7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
{6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11}
{0,4,1}, // 0
{0,9,4}, // 1
{9,5,4}, // 2
{4,5,8}, // 3
{4,8,1}, // 4
{8,10,1}, //5
{8,3,10}, //6
{5,3,8}, // 7
{5,2,3}, // 8
{2,7,3}, // 9
{7,10,3}, // 10
{7,6,10}, // 11
{7,11,6}, // 12
{11,0,6}, // 13
{0,1,6}, // 14
{6,1,10}, // 15
{9,0,11}, // 16
{9,11,2}, // 17
{9,2,5}, // 18
{7,2,11} // 19
};
// which face (of the 20) is on our edge for edge {v01, v12, v20}
static int nus_edgecomrade[20][3] = {
{1,4,14}, {16,2,0}, {18,3,1}, {2,7,4}, {3,5,0},
{6,15,4}, {7,10,5}, {8,6,3}, {18,9,7}, {19,10,8},
{11,6,9}, {12,15,10}, {19,13,11}, {16,14,12}, {0,15,13},
{14,5,11}, {1,13,17}, {16,19,18}, {17,8,2}, {9,17,12}
};
// tri edge lengths
#define GEOPATCH_SUBDIVIDE_AT_CAMDIST 0.5
#define GEOPATCH_MAX_DEPTH 4
#define GEOPATCH_MAX_DEPTH 6
// should be power of two + 1
#define GEOPATCH_EDGELEN 33
static unsigned short *geovtxidx;
#define PRINT_VECTOR(_v) printf("%.2f,%.2f,%.2f\n", (_v).x, (_v).y, (_v).z);
class GeoPatch {
public:
vector3d v[3];
GLdouble *vertices;
GLdouble *normals;
GLuint *indices;
GeoPatch *kids[4];
GeoPatch *parent;
GeoPatch *edgeFriend[3]; // [0]=v01, [1]=v12, [2]=v20
int m_numVertices;
int m_depth;
GeoPatch() {
memset(this, 0, sizeof(GeoPatch));
@ -912,13 +947,88 @@ public:
if (vertices) delete vertices;
if (indices) delete indices;
}
void Render(vector3d &campos) {
// should be power of two + 1
#define GEOPATCH_EDGELEN 33
void GetEdgeVertices(int edge, GLdouble ev[3*GEOPATCH_EDGELEN]) {
int pos, elen;
if (edge == 1) {
pos = m_numVertices - GEOPATCH_EDGELEN;
for (; pos<m_numVertices; pos++) {
ev[0] = vertices[3*pos];
ev[1] = vertices[3*pos+1];
ev[2] = vertices[3*pos+2];
ev += 3;
}
} else {
pos = 0;
elen = ((edge == 0) ? 1 : 2);
for (; pos<m_numVertices; pos+=elen, elen++) {
ev[0] = vertices[3*pos];
ev[1] = vertices[3*pos+1];
ev[2] = vertices[3*pos+2];
ev += 3;
}
}
}
void SetEdgeVertices(int edge, GLdouble ev[3*GEOPATCH_EDGELEN]) {
int pos, elen;
//memset(ev, 0, sizeof(double)*3*GEOPATCH_EDGELEN);
if (edge == 1) {
pos = m_numVertices - GEOPATCH_EDGELEN;
for (; pos<m_numVertices; pos++) {
vertices[3*pos] = ev[0];
vertices[3*pos+1] = ev[1];
vertices[3*pos+2] = ev[2];
ev += 3;
}
} else {
pos = 0;
elen = ((edge == 0) ? 1 : 2);
for (; pos<m_numVertices; pos+=elen, elen++) {
vertices[3*pos] = ev[0];
vertices[3*pos+1] = ev[1];
vertices[3*pos+2] = ev[2];
ev += 3;
}
}
}
void SetEdgeVerticesFlipped(int edge, GLdouble ev[3*GEOPATCH_EDGELEN]) {
int pos, elen;
ev += 3*GEOPATCH_EDGELEN;
//memset(ev, 0, sizeof(double)*3*GEOPATCH_EDGELEN);
if (edge == 1) {
pos = m_numVertices - GEOPATCH_EDGELEN;
for (; pos<m_numVertices; pos++) {
ev -= 3;
vertices[3*pos] = ev[0];
vertices[3*pos+1] = ev[1];
vertices[3*pos+2] = ev[2];
}
} else {
pos = 0;
elen = ((edge == 0) ? 1 : 2);
for (; pos<m_numVertices; pos+=elen, elen++) {
ev -= 3;
vertices[3*pos] = ev[0];
vertices[3*pos+1] = ev[1];
vertices[3*pos+2] = ev[2];
}
}
}
int GetEdgeIdxOf(GeoPatch *e) {
for (int i=0; i<3; i++) {
if (edgeFriend[i] == e) return i;
}
return -1;
}
void Generate() {
if (!vertices) {
int num_verts = 0;
for (int i=1; i<=GEOPATCH_EDGELEN; i++) num_verts += i;
vertices = new GLdouble[3*num_verts];
m_numVertices = 0;
for (int i=1; i<=GEOPATCH_EDGELEN; i++) m_numVertices += i;
vertices = new GLdouble[3*m_numVertices];
normals = new GLdouble[3*m_numVertices];
GLdouble *vts = vertices;
for (int elen = 1; elen<=GEOPATCH_EDGELEN; elen++) {
for (int pos=0; pos<elen; pos++) {
@ -931,12 +1041,16 @@ public:
ucoord = jizz*pos/(double)(elen-1);
vcoord = jizz*((elen-1)-pos)/(double)(elen-1);
}
vector3d p = (v[0] + ucoord*(v[1]-v[0]) + vcoord*(v[2]-v[0])).Normalized();
vector3d p = (v[0] + vcoord*(v[1]-v[0]) + ucoord*(v[2]-v[0])).Normalized();
double n = noise(100*p.x, 100*p.y, 100*p.z);
n = n*n*noise(10*p.x, 10*p.y, 10*p.z);
p = p + p*0.01*n;
vts[0] = p.x; vts[1] = p.y; vts[2] = p.z;
vts+=3;
}
}
assert(vts == &vertices[3*num_verts]);
assert(vts == &vertices[3*m_numVertices]);
indices = new GLuint[(GEOPATCH_EDGELEN-1)*(GEOPATCH_EDGELEN-1)*3];
GLuint *idx = indices;
int abspos = 0;
@ -944,14 +1058,14 @@ public:
for (int elen = 1; elen<GEOPATCH_EDGELEN; elen++) {
for (int pos=0; pos<elen; pos++) {
idx[0] = abspos;
idx[1] = abspos+elen;
idx[2] = abspos+elen+1;
idx[1] = abspos+elen+1;
idx[2] = abspos+elen;
idx+=3;
wank++;
if (pos < elen-1) {
idx[0] = abspos;
idx[1] = abspos+elen+1;
idx[2] = abspos+1;
idx[1] = abspos+1;
idx[2] = abspos+elen+1;
idx+=3;
wank++;
}
@ -959,25 +1073,82 @@ public:
}
}
assert(wank == (GEOPATCH_EDGELEN-1)*(GEOPATCH_EDGELEN-1));
/* take edge vertices from adjacent tiles if they
* exist, so there are no breaks in the terrain */
GLdouble ev[3*GEOPATCH_EDGELEN];
for (int j=0; j<3; j++) {
GeoPatch *edge = edgeFriend[j];
if (!edge->vertices) continue;
int we_are = edge->GetEdgeIdxOf(this);
if (we_are == -1) {
continue;
/// not joined to edge properly. TODO
//TODO TODO for kids on edge!!
}
edge->GetEdgeVertices(we_are, ev);
if (we_are == 2) {
assert(j==0);
// dunno what to do when j=1,2.
// should it be flipped or what??
}
if (we_are == 2) {
SetEdgeVertices(j, ev);
} else if (j==2) {
SetEdgeVertices(j, ev);
} else {
SetEdgeVerticesFlipped(j, ev);
}
}
#if 0
/* XXX some tests to ensure vertices match */
for (int i=0; i<3; i++) {
GeoPatch *edge = edgeFriend[i];
if (edge) {
int we_are = edge->GetEdgeIdxOf(this);
assert(v[i] == edge->v[(1+we_are)%3]);
assert(v[(i+1)%3] == edge->v[(we_are)%3]);
}
}
#endif
}
}
void Render(vector3d &campos) {
Generate();
vector3d centroid = (v[0]+v[1]+v[2])*0.33333333333333333333333333333333333333333333;
if ((m_depth < GEOPATCH_MAX_DEPTH) &&
((campos - centroid).Length() < (v[0]-v[1]).Length()*GEOPATCH_SUBDIVIDE_AT_CAMDIST)) {
if (!kids[0]) {
vector3d v01, v12, v20;
v01 = (v[0]+v[1]).Normalized();
v12 = (v[1]+v[2]).Normalized();
v20 = (v[2]+v[0]).Normalized();
kids[0] = new GeoPatch(v[0], v01, v20);
kids[1] = new GeoPatch(v[1], v12, v01);
kids[2] = new GeoPatch(v[2], v20, v12);
kids[1] = new GeoPatch(v01, v[1], v12);
kids[2] = new GeoPatch(v20, v12, v[2]);
kids[3] = new GeoPatch(v01, v12, v20);
kids[0]->m_depth = m_depth+1;
kids[1]->m_depth = m_depth+1;
kids[2]->m_depth = m_depth+1;
kids[3]->m_depth = m_depth+1;
// hm.. edges.
kids[0]->edgeFriend[0] = edgeFriend[0]; // XXX giving parent's neighbour...
kids[0]->edgeFriend[1] = kids[3];
kids[0]->edgeFriend[2] = edgeFriend[2]; // XXX
kids[1]->edgeFriend[0] = edgeFriend[0]; // XXX
kids[1]->edgeFriend[1] = edgeFriend[1]; // XXX
kids[1]->edgeFriend[2] = kids[3];
kids[2]->edgeFriend[0] = kids[3];
kids[2]->edgeFriend[1] = edgeFriend[1]; // XXX
kids[2]->edgeFriend[2] = edgeFriend[2]; // XXX
kids[3]->edgeFriend[0] = kids[1];
kids[3]->edgeFriend[1] = kids[2];
kids[3]->edgeFriend[2] = kids[0];
kids[0]->parent = kids[1]->parent = kids[2]->parent = kids[3]->parent = this;
}
for (int i=0; i<4; i++) kids[i]->Render(campos);
} else {
@ -1001,9 +1172,15 @@ public:
GeoSphere() {
for (int i=0; i<20; i++) {
GeoPatch *p = &m_patches[i];
p->v[0] = vector3d(nus_vdata[nus_tindices[i][0]]);
p->v[1] = vector3d(nus_vdata[nus_tindices[i][1]]);
p->v[2] = vector3d(nus_vdata[nus_tindices[i][2]]);
*p = GeoPatch(vector3d(nus_vdata[nus_tindices[i][0]]),
vector3d(nus_vdata[nus_tindices[i][1]]),
vector3d(nus_vdata[nus_tindices[i][2]]));
for (int j=0; j<3; j++) {
p->edgeFriend[j] = &m_patches[nus_edgecomrade[i][j]];
}
}
for (int i=0; i<20; i++) {
m_patches[i].Generate();
}
}
void Render(vector3d campos) {
@ -1016,6 +1193,26 @@ public:
void Planet::Render(const Frame *a_camFrame)
{
if (!geovtxidx) {
/* build this funny array to make indexing the vertices less
* of a total fucking nightmare */
/* looks like: {
* 0, -1, -1, -1, ..
* 1, 2, -1, -1, ..
* 3, 4, 5, -1, .. */
geovtxidx = new unsigned short[GEOPATCH_EDGELEN*GEOPATCH_EDGELEN];
unsigned short *p = geovtxidx;
int abspos = 0;
for (int elen=1; elen<=GEOPATCH_EDGELEN; elen++) {
int i=0;
for (; i<elen; i++) {
*(p++) = abspos++;
}
for (; i<GEOPATCH_EDGELEN; i++) {
*(p++) = -1;
}
}
}
glPushMatrix();
if (!m_geosphere) m_geosphere = new GeoSphere();

View File

@ -22,6 +22,7 @@
#include "Serializer.h"
#include "NameGenerator.h"
#include "mods/Mods.h"
#include "perlin.h"
float Pi::timeAccel = 1.0f;
int Pi::scrWidth;
@ -671,6 +672,7 @@ int main(int argc, char**)
{
printf("Pioneer ultra high tech tech demo dude!\n");
signal(SIGSEGV, sigsegv_handler);
perlin_init();
IniConfig cfg("config.ini");
Pi::Init(cfg);
Pi::Start();

50
src/perlin.cpp Normal file
View File

@ -0,0 +1,50 @@
#include <math.h>
static double fade(double t) { return t * t * t * (t * (t * 6 - 15) + 10); }
static double lerp(double t, double a, double b) { return a + t * (b - a); }
static double grad(int hash, double x, double y, double z) {
int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE
double u = h<8 ? x : y, // INTO 12 GRADIENT DIRECTIONS.
v = h<4 ? y : h==12||h==14 ? x : z;
return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
}
static int p[512];
static const int permutation[] = { 151,160,137,91,90,15,
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
};
double noise(double x, double y, double z) {
int X = (int)floor(x) & 255, // FIND UNIT CUBE THAT
Y = (int)floor(y) & 255, // CONTAINS POINT.
Z = (int)floor(z) & 255;
x -= floor(x); // FIND RELATIVE X,Y,Z
y -= floor(y); // OF POINT IN CUBE.
z -= floor(z);
double u = fade(x), // COMPUTE FADE CURVES
v = fade(y), // FOR EACH OF X,Y,Z.
w = fade(z);
int A = p[X ]+Y, AA = p[A]+Z, AB = p[A+1]+Z, // HASH COORDINATES OF
B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z; // THE 8 CUBE CORNERS,
return lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ), // AND ADD
grad(p[BA ], x-1, y , z )), // BLENDED
lerp(u, grad(p[AB ], x , y-1, z ), // RESULTS
grad(p[BB ], x-1, y-1, z ))),// FROM 8
lerp(v, lerp(u, grad(p[AA+1], x , y , z-1 ), // CORNERS
grad(p[BA+1], x-1, y , z-1 )), // OF CUBE
lerp(u, grad(p[AB+1], x , y-1, z-1 ),
grad(p[BB+1], x-1, y-1, z-1 ))));
}
void perlin_init() { for (int i=0; i < 256 ; i++) p[256+i] = p[i] = permutation[i]; }

7
src/perlin.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef _PERLIN_H
#define _PERLIN_H
double noise(double x, double y, double z);
void perlin_init();
#endif /* _PERLIN_H */