tavli

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