bloboland

annotate src/level.cc @ 5:2f4406cc341e

meh
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 19 Dec 2012 02:37:20 +0200
parents 9021a906c5d3
children
rev   line source
nuclear@1 1 #include "level.h"
nuclear@1 2
nuclear@1 3 #include "opt.h"
nuclear@1 4
nuclear@1 5 Level::Level()
nuclear@1 6 {
nuclear@1 7 terrain = 0;
nuclear@4 8 world_size = Vector3(1, 1, 1);
nuclear@1 9 }
nuclear@1 10
nuclear@1 11 Level::~Level()
nuclear@1 12 {
nuclear@1 13 delete terrain;
nuclear@1 14 }
nuclear@1 15
nuclear@3 16 static float terrain_func(float x, float y, float z)
nuclear@3 17 {
nuclear@3 18 float nx = (x * 2.0 - 1.0) * 0.9;
nuclear@3 19 float ny = (y * 2.0 - 1.0) * 0.9;
nuclear@3 20 float valley = nx * nx + ny * ny;
nuclear@3 21
nuclear@3 22 float s = opt.gen_noise_scale;
nuclear@4 23 float noise = 0.2 * fbm2(x * s, y * s, 4) * (valley + 0.25);
nuclear@3 24 float grad = 0.75 - z + noise + valley * 0.4;
nuclear@3 25
nuclear@3 26 return grad;
nuclear@3 27 }
nuclear@3 28
nuclear@1 29 void Level::generate()
nuclear@1 30 {
nuclear@1 31 delete terrain;
nuclear@1 32
nuclear@1 33 int xsz = opt.world_size[0];
nuclear@1 34 int ysz = opt.world_size[1];
nuclear@1 35 int zsz = opt.world_size[2];
nuclear@1 36
nuclear@1 37 terrain = new Volume(xsz, ysz, zsz);
nuclear@1 38
nuclear@1 39 for(int i=0; i<xsz; i++) {
nuclear@1 40 for(int j=0; j<ysz; j++) {
nuclear@3 41 float x = (float)i / (float)xsz;
nuclear@3 42 float y = (float)j / (float)ysz;
nuclear@3 43 //float peak = 0.4 * noise2(x, y) * 0.5 + 0.5;
nuclear@1 44
nuclear@1 45 for(int k=0; k<zsz; k++) {
nuclear@1 46 Vector4 voxel(1, 1, 1, 1);
nuclear@1 47 float z = (float)k / (float)zsz;
nuclear@1 48
nuclear@3 49 float alpha = terrain_func(x, y, z);
nuclear@3 50
nuclear@1 51 if(z < 0.1) {
nuclear@1 52 // lava
nuclear@1 53 static const Vector4 col1(0.96, 0.3, 0.1, 1);
nuclear@1 54 static const Vector4 col2(0.96, 0.75, 0.1, 1);
nuclear@3 55 float t = noise3(x, y, z) * 0.5 + 0.5;
nuclear@1 56 voxel = lerp(col1, col2, t);
nuclear@3 57 } else if(z < 0.8) {
nuclear@3 58 if(alpha < 0.56) {
nuclear@3 59 // grass
nuclear@4 60 voxel = Vector4(0.49, 0.72, 0.48);
nuclear@3 61 } else {
nuclear@3 62 // mud
nuclear@3 63 voxel = Vector4(0.57, 0.43, 0.29, 1);
nuclear@3 64 }
nuclear@1 65 } // else snow (default)
nuclear@1 66
nuclear@3 67 voxel.w = alpha;
nuclear@1 68 terrain->set_voxel(i, j, k, voxel);
nuclear@1 69 }
nuclear@1 70 }
nuclear@1 71 }
nuclear@4 72
nuclear@4 73 // generate some blobs
nuclear@4 74 for(int i=0; i<opt.gen_num_blobs; i++) {
nuclear@4 75 Blob b;
nuclear@5 76 b.pos = Vector3(frand(1.0) - 0.5, 2.0, frand(1.0) - 0.5) * 2.0;
nuclear@5 77 printf("blob[%d]: %f %f %f\n", i, b.pos.x, b.pos.y, b.pos.z);
nuclear@4 78 b.velocity = Vector3(0, 0, 0);
nuclear@4 79 blobs.push_back(b);
nuclear@4 80 }
nuclear@1 81 }
nuclear@1 82
nuclear@1 83 bool Level::load(const char *fname)
nuclear@1 84 {
nuclear@1 85 return false;
nuclear@1 86 }
nuclear@1 87
nuclear@1 88 bool Level::save(const char *fname) const
nuclear@1 89 {
nuclear@1 90 return false;
nuclear@1 91 }
nuclear@4 92
nuclear@4 93 #define CLAMP(x, a, b) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x)))
nuclear@4 94
nuclear@4 95 const Vector4 &Level::get_voxel(const Vector3 &pos) const
nuclear@4 96 {
nuclear@4 97 Vector3 p = pos / world_size + Vector3(0.5, 0.5, 0.5);
nuclear@4 98
nuclear@4 99 int xsz = terrain->get_size(0);
nuclear@4 100 int ysz = terrain->get_size(1);
nuclear@4 101 int zsz = terrain->get_size(2);
nuclear@4 102
nuclear@4 103 int i = (int)(p.x * xsz);
nuclear@4 104 int j = (int)(p.y * ysz);
nuclear@4 105 int k = (int)(p.z * zsz);
nuclear@4 106
nuclear@4 107 return terrain->get_voxel(CLAMP(i, 0, xsz - 1), CLAMP(j, 0, ysz - 1), CLAMP(k, 0, zsz - 1));
nuclear@4 108 }
nuclear@4 109
nuclear@4 110 Vector3 Level::calc_normal(const Vector3 &pos) const
nuclear@4 111 {
nuclear@4 112 int xsz = terrain->get_size(0);
nuclear@4 113 int ysz = terrain->get_size(1);
nuclear@4 114 int zsz = terrain->get_size(2);
nuclear@4 115
nuclear@4 116 float dx = world_size.x / (float)xsz;
nuclear@4 117 float dy = world_size.y / (float)ysz;
nuclear@4 118 float dz = world_size.z / (float)zsz;
nuclear@4 119
nuclear@4 120 float dfdx = get_voxel(pos + Vector3(dx, 0, 0)).w - get_voxel(pos - Vector3(dx, 0, 0)).w;
nuclear@4 121 float dfdy = get_voxel(pos + Vector3(0, dy, 0)).w - get_voxel(pos - Vector3(0, dy, 0)).w;
nuclear@4 122 float dfdz = get_voxel(pos + Vector3(0, 0, dz)).w - get_voxel(pos - Vector3(0, 0, dz)).w;
nuclear@4 123
nuclear@4 124 return Vector3(dfdx, dfdy, dfdz);
nuclear@4 125 }
nuclear@4 126
nuclear@4 127 bool Level::collision(const Vector3 &pos0, const Vector3 &pos1, Vector3 *outpos, Vector3 *outnorm) const
nuclear@4 128 {
nuclear@4 129 Vector4 vox0 = get_voxel(pos0);
nuclear@4 130 Vector4 vox1 = get_voxel(pos1);
nuclear@4 131
nuclear@4 132 if(vox0.w < 0.5 && vox1.w >= 0.5) {
nuclear@4 133 *outpos = lerp(pos0, pos1, 0.5); // TODO
nuclear@4 134 *outnorm = calc_normal(*outpos);
nuclear@4 135 return true;
nuclear@4 136 }
nuclear@4 137 return false;
nuclear@4 138 }