tavli

view 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
line source
1 #include "opengl.h"
2 #include "board.h"
3 #include "meshgen.h"
6 Board::Board()
7 {
8 puck_obj = 0;
9 clear();
10 }
12 Board::~Board()
13 {
14 destroy();
15 }
17 bool Board::init()
18 {
19 if(!generate_textures()) {
20 return false;
21 }
22 if(!generate()) {
23 return false;
24 }
26 return true;
27 }
29 void Board::destroy()
30 {
31 for(size_t i=0; i<obj.size(); i++) {
32 delete obj[i];
33 }
34 obj.clear();
36 delete puck_obj;
37 puck_obj = 0;
38 }
40 void Board::clear()
41 {
42 memset(slots, 0, sizeof slots);
43 }
45 void Board::draw() const
46 {
47 for(size_t i=0; i<obj.size(); i++) {
48 obj[i]->draw();
49 }
50 }
52 #define HSIZE 1.0
53 #define VSIZE (2.0 * HSIZE)
54 #define BOT_THICKNESS (HSIZE * 0.01)
55 #define WALL_THICKNESS (HSIZE * 0.05)
56 #define WALL_HEIGHT (HSIZE * 0.1)
57 #define GAP (HSIZE * 0.025)
58 #define HINGE_RAD (GAP * 0.5)
59 #define HINGE_HEIGHT (VSIZE * 0.075)
61 bool Board::generate()
62 {
63 Mesh tmp;
64 Matrix4x4 xform;
66 obj.clear();
68 for(int i=0; i<2; i++) {
69 int sign = i * 2 - 1;
71 // generate bottom
72 Mesh *bottom = new Mesh;
73 gen_box(bottom, HSIZE, BOT_THICKNESS, HSIZE * 2.0);
74 xform.set_translation(Vector3(0, -BOT_THICKNESS / 2.0, 0));
75 bottom->apply_xform(xform);
77 Object *obottom = new Object;
78 obottom->set_mesh(bottom);
79 obottom->xform().set_translation(Vector3(sign * (HSIZE / 2.0 + WALL_THICKNESS + HINGE_RAD * 0.25), 0, 0));
80 obottom->set_texture(img_field.texture());
81 obj.push_back(obottom);
84 // generate the 4 sides
85 Mesh *sides = new Mesh;
86 gen_box(sides, WALL_THICKNESS, WALL_HEIGHT, VSIZE + WALL_THICKNESS * 2);
87 xform.set_translation(Vector3(-(HSIZE + WALL_THICKNESS) / 2.0,
88 WALL_HEIGHT / 2.0 - BOT_THICKNESS, 0));
89 sides->apply_xform(xform);
91 gen_box(&tmp, WALL_THICKNESS, WALL_HEIGHT, VSIZE + WALL_THICKNESS * 2);
92 xform.set_translation(Vector3((HSIZE + WALL_THICKNESS) / 2.0,
93 WALL_HEIGHT / 2.0 - BOT_THICKNESS, 0));
94 tmp.apply_xform(xform);
95 sides->append(tmp);
96 tmp.clear();
98 gen_box(&tmp, HSIZE, WALL_HEIGHT, WALL_THICKNESS);
99 xform.set_translation(Vector3(0, WALL_HEIGHT / 2.0 - BOT_THICKNESS,
100 (VSIZE + WALL_THICKNESS) / 2.0));
101 tmp.apply_xform(xform);
102 sides->append(tmp);
103 tmp.clear();
105 gen_box(&tmp, HSIZE, WALL_HEIGHT, WALL_THICKNESS);
106 xform.set_translation(Vector3(0, WALL_HEIGHT / 2.0 - BOT_THICKNESS,
107 -(VSIZE + WALL_THICKNESS) / 2.0));
108 tmp.apply_xform(xform);
109 sides->append(tmp);
110 tmp.clear();
112 Object *osides = new Object;
113 osides->set_mesh(sides);
114 osides->xform() = obottom->xform();
115 obj.push_back(osides);
117 }
120 // generate the hinges
121 Mesh *hinges = new Mesh;
122 gen_cylinder(hinges, HINGE_RAD, HINGE_HEIGHT, 10, 1, 1);
123 xform.reset_identity();
124 xform.translate(Vector3(0, WALL_HEIGHT - HINGE_RAD * 0.5, VSIZE / 4.0));
125 xform.rotate(Vector3(M_PI / 2.0, 0, 0));
126 hinges->apply_xform(xform);
128 gen_cylinder(&tmp, HINGE_RAD, HINGE_HEIGHT, 10, 1, 1);
129 xform.reset_identity();
130 xform.translate(Vector3(0, WALL_HEIGHT - HINGE_RAD * 0.5, -VSIZE / 4.0));
131 xform.rotate(Vector3(M_PI / 2.0, 0, 0));
132 tmp.apply_xform(xform);
134 hinges->append(tmp);
136 Object *ohinges = new Object;
137 ohinges->set_mesh(hinges);
138 obj.push_back(ohinges);
141 return true;
142 }
144 static bool spike(float x, float y)
145 {
146 x = fmod(x * 5.0, 1.0);
147 return y < (x < 0.5 ? 2.0 * x : 2.0 - 2.0 * x);
148 }
150 static bool circle(float x, float y, float rad)
151 {
152 x = fmod(x * 5.0, 1.0) - 0.5;
153 y = (y - 0.65) * 5.0;
154 float len = sqrt(x * x + y * y);
155 return len < rad;
156 }
158 static bool diamond(float x, float y)
159 {
160 return y >= (1.0 - (x < 0.5 ? 2.0 * x : 2.0 - 2.0 * x)) * 0.3333333 + 0.88;
161 }
163 static bool center_circle(float x, float y, float rad)
164 {
165 x = x - 0.5;
166 y = 1.0 - y;
167 return sqrt(x * x + y * y) < rad;
168 }
170 bool Board::generate_textures()
171 {
172 const int xsz = 512;
173 const int ysz = 1024;
175 img_field.create(xsz, ysz);
176 clear_image(&img_field, 0, 0, 0);
178 unsigned char *pptr = img_field.pixels;
180 for(int i=0; i<ysz; i++) {
181 float v = (float)i / (float)ysz;
183 for(int j=0; j<xsz; j++) {
184 float u = (float)j / (float)xsz;
186 int r = 0, g = 0, b = 0;
188 float x = u;
189 float y = v < 0.5 ? v * 2.0 : 2.0 - v * 2.0;
190 bool inside = false;
192 inside |= (spike(x, y + 0.33333) && !spike(x, y + 0.4)) ||
193 (spike(x, y + 0.5) && !spike(x, y + 0.68));
194 inside |= (circle(x, y, 0.12) && !circle(x, y, 0.1)) || circle(x, y, 0.06);
195 inside |= (diamond(x, y) && !diamond(x, y - 0.015)) ||
196 (diamond(x, y - 0.023) && !diamond(x, y - 0.028));
197 inside |= center_circle(x, y, 0.03);
199 if(inside) {
200 r = g = b = 255;
201 }
203 pptr[0] = r;
204 pptr[1] = g;
205 pptr[2] = b;
206 pptr += 3;
207 }
208 }
210 img_field.texture();
211 return true;
212 }