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 }
|