rev |
line source |
nuclear@0
|
1 #include "opengl.h"
|
nuclear@0
|
2 #include "board.h"
|
nuclear@1
|
3 #include "meshgen.h"
|
nuclear@6
|
4 #include "pnoise.h"
|
nuclear@0
|
5
|
nuclear@0
|
6 Board::Board()
|
nuclear@0
|
7 {
|
nuclear@2
|
8 puck_obj = 0;
|
nuclear@0
|
9 clear();
|
nuclear@0
|
10 }
|
nuclear@0
|
11
|
nuclear@0
|
12 Board::~Board()
|
nuclear@0
|
13 {
|
nuclear@0
|
14 destroy();
|
nuclear@0
|
15 }
|
nuclear@0
|
16
|
nuclear@0
|
17 bool Board::init()
|
nuclear@0
|
18 {
|
nuclear@4
|
19 if(!generate_textures()) {
|
nuclear@4
|
20 return false;
|
nuclear@4
|
21 }
|
nuclear@1
|
22 if(!generate()) {
|
nuclear@0
|
23 return false;
|
nuclear@0
|
24 }
|
nuclear@1
|
25
|
nuclear@0
|
26 return true;
|
nuclear@0
|
27 }
|
nuclear@0
|
28
|
nuclear@0
|
29 void Board::destroy()
|
nuclear@0
|
30 {
|
nuclear@2
|
31 for(size_t i=0; i<obj.size(); i++) {
|
nuclear@2
|
32 delete obj[i];
|
nuclear@1
|
33 }
|
nuclear@2
|
34 obj.clear();
|
nuclear@1
|
35
|
nuclear@2
|
36 delete puck_obj;
|
nuclear@2
|
37 puck_obj = 0;
|
nuclear@0
|
38 }
|
nuclear@0
|
39
|
nuclear@0
|
40 void Board::clear()
|
nuclear@0
|
41 {
|
nuclear@0
|
42 memset(slots, 0, sizeof slots);
|
nuclear@0
|
43 }
|
nuclear@0
|
44
|
nuclear@0
|
45 void Board::draw() const
|
nuclear@0
|
46 {
|
nuclear@2
|
47 for(size_t i=0; i<obj.size(); i++) {
|
nuclear@2
|
48 obj[i]->draw();
|
nuclear@1
|
49 }
|
nuclear@0
|
50 }
|
nuclear@0
|
51
|
nuclear@1
|
52 #define HSIZE 1.0
|
nuclear@1
|
53 #define VSIZE (2.0 * HSIZE)
|
nuclear@1
|
54 #define BOT_THICKNESS (HSIZE * 0.01)
|
nuclear@1
|
55 #define WALL_THICKNESS (HSIZE * 0.05)
|
nuclear@1
|
56 #define WALL_HEIGHT (HSIZE * 0.1)
|
nuclear@1
|
57 #define GAP (HSIZE * 0.025)
|
nuclear@1
|
58 #define HINGE_RAD (GAP * 0.5)
|
nuclear@1
|
59 #define HINGE_HEIGHT (VSIZE * 0.075)
|
nuclear@1
|
60
|
nuclear@1
|
61 bool Board::generate()
|
nuclear@0
|
62 {
|
nuclear@4
|
63 Mesh tmp;
|
nuclear@1
|
64 Matrix4x4 xform;
|
nuclear@1
|
65
|
nuclear@2
|
66 obj.clear();
|
nuclear@2
|
67
|
nuclear@4
|
68 for(int i=0; i<2; i++) {
|
nuclear@4
|
69 int sign = i * 2 - 1;
|
nuclear@1
|
70
|
nuclear@4
|
71 // generate bottom
|
nuclear@4
|
72 Mesh *bottom = new Mesh;
|
nuclear@4
|
73 gen_box(bottom, HSIZE, BOT_THICKNESS, HSIZE * 2.0);
|
nuclear@4
|
74 xform.set_translation(Vector3(0, -BOT_THICKNESS / 2.0, 0));
|
nuclear@4
|
75 bottom->apply_xform(xform);
|
nuclear@2
|
76
|
nuclear@4
|
77 Object *obottom = new Object;
|
nuclear@4
|
78 obottom->set_mesh(bottom);
|
nuclear@4
|
79 obottom->xform().set_translation(Vector3(sign * (HSIZE / 2.0 + WALL_THICKNESS + HINGE_RAD * 0.25), 0, 0));
|
nuclear@4
|
80 obottom->set_texture(img_field.texture());
|
nuclear@4
|
81 obj.push_back(obottom);
|
nuclear@2
|
82
|
nuclear@1
|
83
|
nuclear@4
|
84 // generate the 4 sides
|
nuclear@4
|
85 Mesh *sides = new Mesh;
|
nuclear@4
|
86 gen_box(sides, WALL_THICKNESS, WALL_HEIGHT, VSIZE + WALL_THICKNESS * 2);
|
nuclear@4
|
87 xform.set_translation(Vector3(-(HSIZE + WALL_THICKNESS) / 2.0,
|
nuclear@4
|
88 WALL_HEIGHT / 2.0 - BOT_THICKNESS, 0));
|
nuclear@4
|
89 sides->apply_xform(xform);
|
nuclear@1
|
90
|
nuclear@4
|
91 gen_box(&tmp, WALL_THICKNESS, WALL_HEIGHT, VSIZE + WALL_THICKNESS * 2);
|
nuclear@4
|
92 xform.set_translation(Vector3((HSIZE + WALL_THICKNESS) / 2.0,
|
nuclear@4
|
93 WALL_HEIGHT / 2.0 - BOT_THICKNESS, 0));
|
nuclear@4
|
94 tmp.apply_xform(xform);
|
nuclear@4
|
95 sides->append(tmp);
|
nuclear@4
|
96 tmp.clear();
|
nuclear@1
|
97
|
nuclear@4
|
98 gen_box(&tmp, HSIZE, WALL_HEIGHT, WALL_THICKNESS);
|
nuclear@4
|
99 xform.set_translation(Vector3(0, WALL_HEIGHT / 2.0 - BOT_THICKNESS,
|
nuclear@4
|
100 (VSIZE + WALL_THICKNESS) / 2.0));
|
nuclear@4
|
101 tmp.apply_xform(xform);
|
nuclear@4
|
102 sides->append(tmp);
|
nuclear@4
|
103 tmp.clear();
|
nuclear@1
|
104
|
nuclear@4
|
105 gen_box(&tmp, HSIZE, WALL_HEIGHT, WALL_THICKNESS);
|
nuclear@4
|
106 xform.set_translation(Vector3(0, WALL_HEIGHT / 2.0 - BOT_THICKNESS,
|
nuclear@4
|
107 -(VSIZE + WALL_THICKNESS) / 2.0));
|
nuclear@4
|
108 tmp.apply_xform(xform);
|
nuclear@4
|
109 sides->append(tmp);
|
nuclear@4
|
110 tmp.clear();
|
nuclear@4
|
111
|
nuclear@6
|
112 // generate texture coordinates
|
nuclear@6
|
113 sides->texcoord_gen_box();
|
nuclear@6
|
114
|
nuclear@4
|
115 Object *osides = new Object;
|
nuclear@4
|
116 osides->set_mesh(sides);
|
nuclear@4
|
117 osides->xform() = obottom->xform();
|
nuclear@6
|
118 osides->set_texture(img_wood.texture());
|
nuclear@6
|
119 osides->tex_xform().set_scaling(Vector3(2, 2, 2));
|
nuclear@6
|
120 osides->tex_xform().rotate(-Vector3(1, 0, 0.5), M_PI / 4.0);
|
nuclear@4
|
121 obj.push_back(osides);
|
nuclear@4
|
122
|
nuclear@4
|
123 }
|
nuclear@2
|
124
|
nuclear@2
|
125
|
nuclear@1
|
126 // generate the hinges
|
nuclear@1
|
127 Mesh *hinges = new Mesh;
|
nuclear@1
|
128 gen_cylinder(hinges, HINGE_RAD, HINGE_HEIGHT, 10, 1, 1);
|
nuclear@4
|
129 xform.reset_identity();
|
nuclear@4
|
130 xform.translate(Vector3(0, WALL_HEIGHT - HINGE_RAD * 0.5, VSIZE / 4.0));
|
nuclear@4
|
131 xform.rotate(Vector3(M_PI / 2.0, 0, 0));
|
nuclear@1
|
132 hinges->apply_xform(xform);
|
nuclear@1
|
133
|
nuclear@1
|
134 gen_cylinder(&tmp, HINGE_RAD, HINGE_HEIGHT, 10, 1, 1);
|
nuclear@4
|
135 xform.reset_identity();
|
nuclear@4
|
136 xform.translate(Vector3(0, WALL_HEIGHT - HINGE_RAD * 0.5, -VSIZE / 4.0));
|
nuclear@4
|
137 xform.rotate(Vector3(M_PI / 2.0, 0, 0));
|
nuclear@1
|
138 tmp.apply_xform(xform);
|
nuclear@1
|
139
|
nuclear@1
|
140 hinges->append(tmp);
|
nuclear@1
|
141
|
nuclear@2
|
142 Object *ohinges = new Object;
|
nuclear@2
|
143 ohinges->set_mesh(hinges);
|
nuclear@2
|
144 obj.push_back(ohinges);
|
nuclear@1
|
145
|
nuclear@6
|
146 // debug object
|
nuclear@6
|
147 /*Mesh *dbgmesh = new Mesh;
|
nuclear@6
|
148 gen_box(dbgmesh, 0.5, 0.5, 0.5);
|
nuclear@6
|
149 xform.set_translation(Vector3(0, 0.4, 0));
|
nuclear@6
|
150 xform.set_scaling(Vector3(4, 1, 4));
|
nuclear@6
|
151 dbgmesh->apply_xform(xform);
|
nuclear@6
|
152 Object *dbgobj = new Object;
|
nuclear@6
|
153 dbgobj->set_mesh(dbgmesh);
|
nuclear@6
|
154 dbgobj->set_texture(img_wood.texture());
|
nuclear@6
|
155 dbgobj->tex_xform().set_scaling(Vector3(3, 3, 3));
|
nuclear@6
|
156 obj.push_back(dbgobj);*/
|
nuclear@2
|
157
|
nuclear@1
|
158 return true;
|
nuclear@0
|
159 }
|
nuclear@4
|
160
|
nuclear@5
|
161 static float wood(float x, float y)
|
nuclear@5
|
162 {
|
nuclear@5
|
163 float u = x;
|
nuclear@5
|
164 float v = y;
|
nuclear@5
|
165 x += 1.0;
|
nuclear@5
|
166 x *= 10.0;
|
nuclear@5
|
167 y *= 20.0;
|
nuclear@5
|
168
|
nuclear@5
|
169 float len = sqrt(x * x + y * y) + turbulence2(u * 6.0, v * 12.0, 2) * 1.2 +
|
nuclear@5
|
170 turbulence2(u * 0.5, v, 2) * 15.0;
|
nuclear@5
|
171 float val = fmod(len, 1.0);
|
nuclear@5
|
172
|
nuclear@5
|
173 //val = val * 0.5 + 0.5;
|
nuclear@5
|
174 return val < 0.0 ? 0.0 : (val > 1.0 ? 1.0 : val);
|
nuclear@5
|
175 }
|
nuclear@5
|
176
|
nuclear@6
|
177 static float wood_tile(float x, float y)
|
nuclear@6
|
178 {
|
nuclear@6
|
179 float u = x;
|
nuclear@6
|
180 float v = y;
|
nuclear@6
|
181 x *= 10.0;
|
nuclear@6
|
182 y *= 10.0;
|
nuclear@6
|
183
|
nuclear@6
|
184 float val = x + pnoise2(u * 6.0, v, 6, 1) * 3.0 +
|
nuclear@6
|
185 pturbulence2(u * 4, v * 2, 4, 2, 2) * 1.5 + pturbulence2(u * 8, v * 8, 8, 8, 2) * 0.5;
|
nuclear@6
|
186
|
nuclear@6
|
187 val = fmod(val, 1.0);
|
nuclear@6
|
188 return val < 0.0 ? 0.0 : (val > 1.0 ? 1.0 : val);
|
nuclear@6
|
189 }
|
nuclear@6
|
190
|
nuclear@4
|
191 static bool spike(float x, float y)
|
nuclear@4
|
192 {
|
nuclear@4
|
193 x = fmod(x * 5.0, 1.0);
|
nuclear@4
|
194 return y < (x < 0.5 ? 2.0 * x : 2.0 - 2.0 * x);
|
nuclear@4
|
195 }
|
nuclear@4
|
196
|
nuclear@4
|
197 static bool circle(float x, float y, float rad)
|
nuclear@4
|
198 {
|
nuclear@4
|
199 x = fmod(x * 5.0, 1.0) - 0.5;
|
nuclear@4
|
200 y = (y - 0.65) * 5.0;
|
nuclear@4
|
201 float len = sqrt(x * x + y * y);
|
nuclear@4
|
202 return len < rad;
|
nuclear@4
|
203 }
|
nuclear@4
|
204
|
nuclear@4
|
205 static bool diamond(float x, float y)
|
nuclear@4
|
206 {
|
nuclear@4
|
207 return y >= (1.0 - (x < 0.5 ? 2.0 * x : 2.0 - 2.0 * x)) * 0.3333333 + 0.88;
|
nuclear@4
|
208 }
|
nuclear@4
|
209
|
nuclear@4
|
210 static bool center_circle(float x, float y, float rad)
|
nuclear@4
|
211 {
|
nuclear@4
|
212 x = x - 0.5;
|
nuclear@4
|
213 y = 1.0 - y;
|
nuclear@4
|
214 return sqrt(x * x + y * y) < rad;
|
nuclear@4
|
215 }
|
nuclear@4
|
216
|
nuclear@4
|
217 bool Board::generate_textures()
|
nuclear@4
|
218 {
|
nuclear@6
|
219 // ---- board field texture ----
|
nuclear@5
|
220 static const Vector3 wcol1 = Vector3(0.6, 0.4, 0.2);
|
nuclear@6
|
221 static const Vector3 wcol2 = Vector3(0.53, 0.32, 0.1);
|
nuclear@6
|
222 static const Vector3 wcol3 = Vector3(0.38, 0.25, 0.08);
|
nuclear@5
|
223
|
nuclear@6
|
224 img_field.create(512, 1024);
|
nuclear@6
|
225 unsigned char *pptr = img_field.pixels;
|
nuclear@6
|
226 for(int i=0; i<img_field.height; i++) {
|
nuclear@6
|
227 float v = (float)i / (float)img_field.height;
|
nuclear@4
|
228
|
nuclear@6
|
229 for(int j=0; j<img_field.width; j++) {
|
nuclear@6
|
230 float u = (float)j / (float)img_field.width;
|
nuclear@4
|
231
|
nuclear@4
|
232 int r = 0, g = 0, b = 0;
|
nuclear@4
|
233
|
nuclear@5
|
234 float wood_val = wood(u, v);
|
nuclear@5
|
235
|
nuclear@5
|
236 // pattern mask
|
nuclear@4
|
237 float x = u;
|
nuclear@4
|
238 float y = v < 0.5 ? v * 2.0 : 2.0 - v * 2.0;
|
nuclear@4
|
239 bool inside = false;
|
nuclear@4
|
240
|
nuclear@4
|
241 inside |= (spike(x, y + 0.33333) && !spike(x, y + 0.4)) ||
|
nuclear@4
|
242 (spike(x, y + 0.5) && !spike(x, y + 0.68));
|
nuclear@4
|
243 inside |= (circle(x, y, 0.12) && !circle(x, y, 0.1)) || circle(x, y, 0.06);
|
nuclear@4
|
244 inside |= (diamond(x, y) && !diamond(x, y - 0.015)) ||
|
nuclear@4
|
245 (diamond(x, y - 0.023) && !diamond(x, y - 0.028));
|
nuclear@4
|
246 inside |= center_circle(x, y, 0.03);
|
nuclear@4
|
247
|
nuclear@5
|
248 Vector3 wood_color = lerp(wcol1, wcol2, wood_val) * 0.9;
|
nuclear@4
|
249 if(inside) {
|
nuclear@5
|
250 wood_color = lerp(wcol1, wcol2, 1.0 - wood_val) * 2.0;
|
nuclear@4
|
251 }
|
nuclear@4
|
252
|
nuclear@5
|
253 r = (int)(wood_color.x * 255.0);
|
nuclear@5
|
254 g = (int)(wood_color.y * 255.0);
|
nuclear@5
|
255 b = (int)(wood_color.z * 255.0);
|
nuclear@5
|
256
|
nuclear@5
|
257 pptr[0] = r > 255 ? 255 : r;
|
nuclear@5
|
258 pptr[1] = g > 255 ? 255 : g;
|
nuclear@5
|
259 pptr[2] = b > 255 ? 255 : b;
|
nuclear@4
|
260 pptr += 3;
|
nuclear@4
|
261 }
|
nuclear@4
|
262 }
|
nuclear@6
|
263 img_field.texture();
|
nuclear@4
|
264
|
nuclear@6
|
265 // ---- generic wood texture ----
|
nuclear@6
|
266 img_wood.create(256, 256);
|
nuclear@6
|
267 pptr = img_wood.pixels;
|
nuclear@6
|
268 for(int i=0; i<img_wood.height; i++) {
|
nuclear@6
|
269 float v = (float)i / (float)img_wood.height;
|
nuclear@6
|
270 for(int j=0; j<img_wood.width; j++) {
|
nuclear@6
|
271 float u = (float)j / (float)img_wood.width;
|
nuclear@6
|
272
|
nuclear@6
|
273 float wood_val = wood_tile(u, v);
|
nuclear@6
|
274 Vector3 wood_color = lerp(wcol2, wcol3, wood_val) * 0.7;
|
nuclear@6
|
275
|
nuclear@6
|
276 int r = (int)(wood_color.x * 255.0);
|
nuclear@6
|
277 int g = (int)(wood_color.y * 255.0);
|
nuclear@6
|
278 int b = (int)(wood_color.z * 255.0);
|
nuclear@6
|
279
|
nuclear@6
|
280 pptr[0] = r > 255 ? 255 : r;
|
nuclear@6
|
281 pptr[1] = g > 255 ? 255 : g;
|
nuclear@6
|
282 pptr[2] = b > 255 ? 255 : b;
|
nuclear@6
|
283 pptr += 3;
|
nuclear@6
|
284 }
|
nuclear@6
|
285 }
|
nuclear@6
|
286 img_wood.texture();
|
nuclear@4
|
287 return true;
|
nuclear@4
|
288 }
|