tavli

annotate src/board.cc @ 4:b41ceead1708

procedural playing field texture mask
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 25 Jun 2015 05:58:35 +0300
parents 893192aea099
children e48b40a3c82a
rev   line source
nuclear@0 1 #include "opengl.h"
nuclear@0 2 #include "board.h"
nuclear@1 3 #include "meshgen.h"
nuclear@0 4
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@4 112 Object *osides = new Object;
nuclear@4 113 osides->set_mesh(sides);
nuclear@4 114 osides->xform() = obottom->xform();
nuclear@4 115 obj.push_back(osides);
nuclear@4 116
nuclear@4 117 }
nuclear@2 118
nuclear@2 119
nuclear@1 120 // generate the hinges
nuclear@1 121 Mesh *hinges = new Mesh;
nuclear@1 122 gen_cylinder(hinges, HINGE_RAD, HINGE_HEIGHT, 10, 1, 1);
nuclear@4 123 xform.reset_identity();
nuclear@4 124 xform.translate(Vector3(0, WALL_HEIGHT - HINGE_RAD * 0.5, VSIZE / 4.0));
nuclear@4 125 xform.rotate(Vector3(M_PI / 2.0, 0, 0));
nuclear@1 126 hinges->apply_xform(xform);
nuclear@1 127
nuclear@1 128 gen_cylinder(&tmp, 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 tmp.apply_xform(xform);
nuclear@1 133
nuclear@1 134 hinges->append(tmp);
nuclear@1 135
nuclear@2 136 Object *ohinges = new Object;
nuclear@2 137 ohinges->set_mesh(hinges);
nuclear@2 138 obj.push_back(ohinges);
nuclear@1 139
nuclear@2 140
nuclear@1 141 return true;
nuclear@0 142 }
nuclear@4 143
nuclear@4 144 static bool spike(float x, float y)
nuclear@4 145 {
nuclear@4 146 x = fmod(x * 5.0, 1.0);
nuclear@4 147 return y < (x < 0.5 ? 2.0 * x : 2.0 - 2.0 * x);
nuclear@4 148 }
nuclear@4 149
nuclear@4 150 static bool circle(float x, float y, float rad)
nuclear@4 151 {
nuclear@4 152 x = fmod(x * 5.0, 1.0) - 0.5;
nuclear@4 153 y = (y - 0.65) * 5.0;
nuclear@4 154 float len = sqrt(x * x + y * y);
nuclear@4 155 return len < rad;
nuclear@4 156 }
nuclear@4 157
nuclear@4 158 static bool diamond(float x, float y)
nuclear@4 159 {
nuclear@4 160 return y >= (1.0 - (x < 0.5 ? 2.0 * x : 2.0 - 2.0 * x)) * 0.3333333 + 0.88;
nuclear@4 161 }
nuclear@4 162
nuclear@4 163 static bool center_circle(float x, float y, float rad)
nuclear@4 164 {
nuclear@4 165 x = x - 0.5;
nuclear@4 166 y = 1.0 - y;
nuclear@4 167 return sqrt(x * x + y * y) < rad;
nuclear@4 168 }
nuclear@4 169
nuclear@4 170 bool Board::generate_textures()
nuclear@4 171 {
nuclear@4 172 const int xsz = 512;
nuclear@4 173 const int ysz = 1024;
nuclear@4 174
nuclear@4 175 img_field.create(xsz, ysz);
nuclear@4 176 clear_image(&img_field, 0, 0, 0);
nuclear@4 177
nuclear@4 178 unsigned char *pptr = img_field.pixels;
nuclear@4 179
nuclear@4 180 for(int i=0; i<ysz; i++) {
nuclear@4 181 float v = (float)i / (float)ysz;
nuclear@4 182
nuclear@4 183 for(int j=0; j<xsz; j++) {
nuclear@4 184 float u = (float)j / (float)xsz;
nuclear@4 185
nuclear@4 186 int r = 0, g = 0, b = 0;
nuclear@4 187
nuclear@4 188 float x = u;
nuclear@4 189 float y = v < 0.5 ? v * 2.0 : 2.0 - v * 2.0;
nuclear@4 190 bool inside = false;
nuclear@4 191
nuclear@4 192 inside |= (spike(x, y + 0.33333) && !spike(x, y + 0.4)) ||
nuclear@4 193 (spike(x, y + 0.5) && !spike(x, y + 0.68));
nuclear@4 194 inside |= (circle(x, y, 0.12) && !circle(x, y, 0.1)) || circle(x, y, 0.06);
nuclear@4 195 inside |= (diamond(x, y) && !diamond(x, y - 0.015)) ||
nuclear@4 196 (diamond(x, y - 0.023) && !diamond(x, y - 0.028));
nuclear@4 197 inside |= center_circle(x, y, 0.03);
nuclear@4 198
nuclear@4 199 if(inside) {
nuclear@4 200 r = g = b = 255;
nuclear@4 201 }
nuclear@4 202
nuclear@4 203 pptr[0] = r;
nuclear@4 204 pptr[1] = g;
nuclear@4 205 pptr[2] = b;
nuclear@4 206 pptr += 3;
nuclear@4 207 }
nuclear@4 208 }
nuclear@4 209
nuclear@4 210 img_field.texture();
nuclear@4 211 return true;
nuclear@4 212 }