tavli

view src/board.cc @ 15:b1a195c3ee16

added shaders
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 28 Jun 2015 08:34:24 +0300
parents 283eb6e9f0a3
children 16a420432aa3
line source
1 #include <float.h>
2 #include "opengl.h"
3 #include "board.h"
4 #include "game.h"
5 #include "meshgen.h"
6 #include "pnoise.h"
7 #include "revol.h"
9 Board::Board()
10 {
11 puck_obj = 0;
12 clear();
13 }
15 Board::~Board()
16 {
17 destroy();
18 }
20 bool Board::init()
21 {
22 if(!generate_textures()) {
23 return false;
24 }
25 if(!generate()) {
26 return false;
27 }
29 return true;
30 }
32 void Board::destroy()
33 {
34 for(size_t i=0; i<obj.size(); i++) {
35 delete obj[i];
36 }
37 obj.clear();
39 delete puck_obj;
40 puck_obj = 0;
41 }
43 void Board::clear()
44 {
45 memset(slots, 0, sizeof slots);
46 }
48 void Board::draw() const
49 {
50 for(size_t i=0; i<obj.size(); i++) {
51 if(wireframe) {
52 obj[i]->draw_wire();
53 obj[i]->draw_normals(0.075);
54 } else {
55 obj[i]->draw();
56 }
57 }
58 }
60 #define HSIZE 1.0
61 #define VSIZE (2.0 * HSIZE)
62 #define BOT_THICKNESS (HSIZE * 0.01)
63 #define WALL_THICKNESS (HSIZE * 0.05)
64 #define WALL_HEIGHT (HSIZE * 0.1)
65 #define GAP (HSIZE * 0.025)
66 #define HINGE_RAD (GAP * 0.5)
67 #define HINGE_HEIGHT (VSIZE * 0.075)
68 #define PIECE_RAD (0.45 * HSIZE / 5.0)
71 static const vec2_t piece_cp[] = {
72 {0, 0.25},
73 {1, 0.25}, // mid0
74 {2, 0.5},
75 {2.5, 0.5}, // mid1
76 {3, 0.5},
77 {4, 0.5}, // mid2
78 {4, 0},
79 {4, -0.5}, // mid3
80 {3, -0.5},
81 {2.5, -0.5}, // mid4
82 {0, -0.5}
83 };
84 static const BezCurve piece_curve = {
85 sizeof piece_cp / sizeof *piece_cp,
86 (vec2_t*)piece_cp,
87 0.25 * PIECE_RAD
88 };
91 bool Board::generate()
92 {
93 Mesh tmp;
94 Matrix4x4 xform;
96 obj.clear();
98 for(int i=0; i<2; i++) {
99 int sign = i * 2 - 1;
101 // generate bottom
102 Mesh *bottom = new Mesh;
103 gen_box(bottom, HSIZE, BOT_THICKNESS, HSIZE * 2.0);
104 xform.set_translation(Vector3(0, -BOT_THICKNESS / 2.0, 0));
105 bottom->apply_xform(xform);
107 Object *obottom = new Object;
108 obottom->set_mesh(bottom);
109 obottom->xform().set_translation(Vector3(sign * (HSIZE / 2.0 + WALL_THICKNESS + HINGE_RAD * 0.25), 0, 0));
110 obottom->set_texture(img_field.texture());
111 obj.push_back(obottom);
114 // generate the 4 sides
115 Mesh *sides = new Mesh;
116 gen_box(sides, WALL_THICKNESS, WALL_HEIGHT, VSIZE + WALL_THICKNESS * 2);
117 xform.set_translation(Vector3(-(HSIZE + WALL_THICKNESS) / 2.0,
118 WALL_HEIGHT / 2.0 - BOT_THICKNESS, 0));
119 sides->apply_xform(xform);
121 gen_box(&tmp, WALL_THICKNESS, WALL_HEIGHT, VSIZE + WALL_THICKNESS * 2);
122 xform.set_translation(Vector3((HSIZE + WALL_THICKNESS) / 2.0,
123 WALL_HEIGHT / 2.0 - BOT_THICKNESS, 0));
124 tmp.apply_xform(xform);
125 sides->append(tmp);
126 tmp.clear();
128 gen_box(&tmp, HSIZE, WALL_HEIGHT, WALL_THICKNESS);
129 xform.set_translation(Vector3(0, WALL_HEIGHT / 2.0 - BOT_THICKNESS,
130 (VSIZE + WALL_THICKNESS) / 2.0));
131 tmp.apply_xform(xform);
132 sides->append(tmp);
133 tmp.clear();
135 gen_box(&tmp, HSIZE, WALL_HEIGHT, WALL_THICKNESS);
136 xform.set_translation(Vector3(0, WALL_HEIGHT / 2.0 - BOT_THICKNESS,
137 -(VSIZE + WALL_THICKNESS) / 2.0));
138 tmp.apply_xform(xform);
139 sides->append(tmp);
140 tmp.clear();
142 // generate texture coordinates
143 sides->texcoord_gen_box();
145 Object *osides = new Object;
146 osides->set_mesh(sides);
147 osides->xform() = obottom->xform();
148 osides->set_texture(img_wood.texture());
149 osides->tex_xform().set_scaling(Vector3(2, 2, 2));
150 osides->tex_xform().rotate(-Vector3(1, 0, 0.5), M_PI / 4.0);
151 obj.push_back(osides);
153 }
156 // generate the hinges
157 Mesh *hinges = new Mesh;
158 for(int i=0; i<2; i++) {
159 float sign = i * 2 - 1;
161 // barrel
162 gen_cylinder(&tmp, HINGE_RAD, HINGE_HEIGHT, 8, 1, 1);
163 xform.reset_identity();
164 xform.translate(Vector3(0, WALL_HEIGHT - HINGE_RAD * 0.5, sign * VSIZE / 4.0));
165 xform.rotate(Vector3(-M_PI / 2.0, 0, 0));
166 tmp.apply_xform(xform);
167 hinges->append(tmp);
169 // flange
170 gen_plane(&tmp, HINGE_HEIGHT * 0.6, HINGE_HEIGHT * 0.8);
171 tmp.apply_xform(xform);
173 Matrix4x4 tex_xform;
174 tex_xform.set_rotation(Vector3(0, 0, M_PI / 2.0));
175 tmp.texcoord_apply_xform(tex_xform);
176 hinges->append(tmp);
178 // studs
179 for(int j=0; j<4; j++) {
180 Vector3 pos;
182 pos.x = (float)((j & 1) * 2 - 1) * HINGE_HEIGHT * 0.2;
183 pos.y = (float)((j & 2) - 1) * HINGE_HEIGHT * 0.3;
185 Matrix4x4 stud_xform = xform;
186 stud_xform.translate(pos);
188 Matrix4x4 squash;
189 squash.set_scaling(Vector3(1, 1, 0.5));
191 gen_sphere(&tmp, HINGE_RAD * 0.5, 8, 4);
192 tmp.apply_xform(stud_xform * squash);
193 hinges->append(tmp);
194 }
195 }
197 Object *ohinges = new Object;
198 ohinges->set_mesh(hinges);
199 ohinges->set_texture(img_hinge.texture());
200 obj.push_back(ohinges);
202 // debug object
203 /*
204 Mesh *dbgmesh = new Mesh;
205 gen_box(dbgmesh, 0.5, 0.5, 0.5);
206 xform.set_translation(Vector3(0, 0.4, 0));
207 xform.set_scaling(Vector3(1, 1, 1));
208 dbgmesh->apply_xform(xform);
209 Object *dbgobj = new Object;
210 dbgobj->set_mesh(dbgmesh);
211 dbgobj->set_texture(img_hinge.texture());
212 //dbgobj->tex_xform().set_scaling(Vector3(3, 3, 3));
213 obj.push_back(dbgobj);
214 */
216 Mesh *piece = new Mesh;
217 gen_revol(piece, 18, 17, bezier_revol, bezier_revol_normal, (void*)&piece_curve);
219 Object *opiece = new Object;
220 opiece->set_mesh(piece);
221 opiece->mtl.diffuse = Vector3(0.6, 0.6, 0.6);
222 opiece->mtl.specular = Vector3(0.8, 0.8, 0.8);
223 opiece->xform().set_translation(Vector3(0, 0.2, 0));
224 opiece->set_shader(sdr_phong_notex);
225 obj.push_back(opiece);
227 // meshgen stats
228 printf("Generated board:\n %u meshes\n", (unsigned int)obj.size());
229 unsigned int polycount = 0;
230 for(size_t i=0; i<obj.size(); i++) {
231 const Mesh *m = obj[i]->get_mesh();
232 polycount += m->get_poly_count();
233 }
234 printf(" %u polygons\n", polycount);
236 return true;
237 }
239 static float wood(float x, float y)
240 {
241 float u = x;
242 float v = y;
243 x += 1.0;
244 x *= 10.0;
245 y *= 20.0;
247 float len = sqrt(x * x + y * y) + turbulence2(u * 6.0, v * 12.0, 2) * 1.2 +
248 turbulence2(u * 0.5, v, 2) * 15.0;
249 float val = fmod(len, 1.0);
251 //val = val * 0.5 + 0.5;
252 return val < 0.0 ? 0.0 : (val > 1.0 ? 1.0 : val);
253 }
255 static float wood_tile(float x, float y)
256 {
257 float u = x;
258 float v = y;
259 x *= 10.0;
260 y *= 10.0;
262 float val = x + pnoise2(u * 6.0, v, 6, 1) * 3.0 +
263 pturbulence2(u * 4, v * 2, 4, 2, 2) * 1.5 + pturbulence2(u * 8, v * 8, 8, 8, 2) * 0.5;
265 val = fmod(val, 1.0);
266 return val < 0.0 ? 0.0 : (val > 1.0 ? 1.0 : val);
267 }
269 static bool spike(float x, float y)
270 {
271 x = fmod(x * 5.0, 1.0);
272 return y < (x < 0.5 ? 2.0 * x : 2.0 - 2.0 * x);
273 }
275 static bool circle(float x, float y, float rad)
276 {
277 x = fmod(x * 5.0, 1.0) - 0.5;
278 y = (y - 0.65) * 5.0;
279 float len = sqrt(x * x + y * y);
280 return len < rad;
281 }
283 static bool diamond(float x, float y)
284 {
285 return y >= (1.0 - (x < 0.5 ? 2.0 * x : 2.0 - 2.0 * x)) * 0.3333333 + 0.88;
286 }
288 static bool center_circle(float x, float y, float rad)
289 {
290 x = x - 0.5;
291 y = 1.0 - y;
292 return sqrt(x * x + y * y) < rad;
293 }
295 bool Board::generate_textures()
296 {
297 // ---- board field texture ----
298 static const Vector3 wcol1 = Vector3(0.6, 0.4, 0.2);
299 static const Vector3 wcol2 = Vector3(0.53, 0.32, 0.1);
300 static const Vector3 wcol3 = Vector3(0.38, 0.25, 0.08);
302 img_field.create(1024, 1024);
303 unsigned char *pptr = img_field.pixels;
304 for(int i=0; i<img_field.height; i++) {
305 float v = (float)i / (float)img_field.height;
307 for(int j=0; j<img_field.width; j++) {
308 float u = (float)j / (float)img_field.width;
310 int r = 0, g = 0, b = 0;
312 float wood_val = wood(u, v);
314 // pattern mask
315 float x = u;
316 float y = v < 0.5 ? v * 2.0 : 2.0 - v * 2.0;
317 bool inside = false;
319 inside |= (spike(x, y + 0.33333) && !spike(x, y + 0.4)) ||
320 (spike(x, y + 0.5) && !spike(x, y + 0.68));
321 inside |= (circle(x, y, 0.12) && !circle(x, y, 0.1)) || circle(x, y, 0.06);
322 inside |= (diamond(x, y) && !diamond(x, y - 0.015)) ||
323 (diamond(x, y - 0.023) && !diamond(x, y - 0.028));
324 inside |= center_circle(x, y, 0.03);
326 Vector3 wood_color = lerp(wcol1, wcol2, wood_val) * 0.9;
327 if(inside) {
328 wood_color = lerp(wcol1, wcol2, 1.0 - wood_val) * 2.0;
329 }
331 r = (int)(wood_color.x * 255.0);
332 g = (int)(wood_color.y * 255.0);
333 b = (int)(wood_color.z * 255.0);
335 pptr[0] = r > 255 ? 255 : r;
336 pptr[1] = g > 255 ? 255 : g;
337 pptr[2] = b > 255 ? 255 : b;
338 pptr += 3;
339 }
340 }
341 img_field.texture();
343 // ---- generic wood texture ----
344 img_wood.create(256, 256);
345 pptr = img_wood.pixels;
346 for(int i=0; i<img_wood.height; i++) {
347 float v = (float)i / (float)img_wood.height;
348 for(int j=0; j<img_wood.width; j++) {
349 float u = (float)j / (float)img_wood.width;
351 float wood_val = wood_tile(u, v);
352 Vector3 wood_color = lerp(wcol2, wcol3, wood_val) * 0.7;
354 int r = (int)(wood_color.x * 255.0);
355 int g = (int)(wood_color.y * 255.0);
356 int b = (int)(wood_color.z * 255.0);
358 pptr[0] = r > 255 ? 255 : r;
359 pptr[1] = g > 255 ? 255 : g;
360 pptr[2] = b > 255 ? 255 : b;
361 pptr += 3;
362 }
363 }
364 img_wood.texture();
366 // ---- metal hinge diffuse texture ----
367 Vector3 rusty_col1 = Vector3(0.43, 0.46, 0.52);
368 Vector3 rusty_col2 = Vector3(0.52, 0.47, 0.43);
370 img_hinge.create(128, 128);
371 pptr = img_hinge.pixels;
372 for(int i=0; i<img_hinge.height; i++) {
373 float v = (float)i / (float)img_hinge.height;
374 for(int j=0; j<img_hinge.width; j++) {
375 float u = (float)j / (float)img_hinge.width;
377 // rust pattern
378 float w1 = fbm2(u * 4.0, v * 4.0, 3) * 0.5 + 0.5;
379 //float w2 = fbm2(u * 8.0, v * 8.0, 1) * 0.5 + 0.5;
380 Vector3 col = lerp(rusty_col1, rusty_col2 * 0.5, w1);
382 // center hinge split
383 if(fabs(v - 0.5) < 0.01) {
384 col *= 0.5;
385 }
387 int r = (int)(col.x * 255.0);
388 int g = (int)(col.y * 255.0);
389 int b = (int)(col.z * 255.0);
391 pptr[0] = r > 255 ? 255 : (r < 0 ? 0 : r);
392 pptr[1] = g > 255 ? 255 : (g < 0 ? 0 : g);
393 pptr[2] = b > 255 ? 255 : (b < 0 ? 0 : b);
395 pptr += 3;
396 }
397 }
398 img_hinge.texture();
400 return true;
401 }