bloboland

annotate src/level.cc @ 4:9021a906c5d3

lots of stuff
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 18 Dec 2012 06:13:09 +0200
parents a39c301cdcce
children 2f4406cc341e
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@4 76 b.pos = Vector3(frand(1.0) - 0.5, 10.0, frand(1.0) - 0.5);
nuclear@4 77 b.velocity = Vector3(0, 0, 0);
nuclear@4 78 blobs.push_back(b);
nuclear@4 79 }
nuclear@1 80 }
nuclear@1 81
nuclear@1 82 bool Level::load(const char *fname)
nuclear@1 83 {
nuclear@1 84 return false;
nuclear@1 85 }
nuclear@1 86
nuclear@1 87 bool Level::save(const char *fname) const
nuclear@1 88 {
nuclear@1 89 return false;
nuclear@1 90 }
nuclear@4 91
nuclear@4 92 #define CLAMP(x, a, b) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x)))
nuclear@4 93
nuclear@4 94 const Vector4 &Level::get_voxel(const Vector3 &pos) const
nuclear@4 95 {
nuclear@4 96 Vector3 p = pos / world_size + Vector3(0.5, 0.5, 0.5);
nuclear@4 97
nuclear@4 98 int xsz = terrain->get_size(0);
nuclear@4 99 int ysz = terrain->get_size(1);
nuclear@4 100 int zsz = terrain->get_size(2);
nuclear@4 101
nuclear@4 102 int i = (int)(p.x * xsz);
nuclear@4 103 int j = (int)(p.y * ysz);
nuclear@4 104 int k = (int)(p.z * zsz);
nuclear@4 105
nuclear@4 106 return terrain->get_voxel(CLAMP(i, 0, xsz - 1), CLAMP(j, 0, ysz - 1), CLAMP(k, 0, zsz - 1));
nuclear@4 107 }
nuclear@4 108
nuclear@4 109 Vector3 Level::calc_normal(const Vector3 &pos) const
nuclear@4 110 {
nuclear@4 111 int xsz = terrain->get_size(0);
nuclear@4 112 int ysz = terrain->get_size(1);
nuclear@4 113 int zsz = terrain->get_size(2);
nuclear@4 114
nuclear@4 115 float dx = world_size.x / (float)xsz;
nuclear@4 116 float dy = world_size.y / (float)ysz;
nuclear@4 117 float dz = world_size.z / (float)zsz;
nuclear@4 118
nuclear@4 119 float dfdx = get_voxel(pos + Vector3(dx, 0, 0)).w - get_voxel(pos - Vector3(dx, 0, 0)).w;
nuclear@4 120 float dfdy = get_voxel(pos + Vector3(0, dy, 0)).w - get_voxel(pos - Vector3(0, dy, 0)).w;
nuclear@4 121 float dfdz = get_voxel(pos + Vector3(0, 0, dz)).w - get_voxel(pos - Vector3(0, 0, dz)).w;
nuclear@4 122
nuclear@4 123 return Vector3(dfdx, dfdy, dfdz);
nuclear@4 124 }
nuclear@4 125
nuclear@4 126 bool Level::collision(const Vector3 &pos0, const Vector3 &pos1, Vector3 *outpos, Vector3 *outnorm) const
nuclear@4 127 {
nuclear@4 128 Vector4 vox0 = get_voxel(pos0);
nuclear@4 129 Vector4 vox1 = get_voxel(pos1);
nuclear@4 130
nuclear@4 131 if(vox0.w < 0.5 && vox1.w >= 0.5) {
nuclear@4 132 *outpos = lerp(pos0, pos1, 0.5); // TODO
nuclear@4 133 *outnorm = calc_normal(*outpos);
nuclear@4 134 return true;
nuclear@4 135 }
nuclear@4 136 return false;
nuclear@4 137 }