tavli

diff 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 diff
     1.1 --- a/src/board.cc	Mon Jun 22 21:46:57 2015 +0300
     1.2 +++ b/src/board.cc	Thu Jun 25 05:58:35 2015 +0300
     1.3 @@ -16,6 +16,9 @@
     1.4  
     1.5  bool Board::init()
     1.6  {
     1.7 +	if(!generate_textures()) {
     1.8 +		return false;
     1.9 +	}
    1.10  	if(!generate()) {
    1.11  		return false;
    1.12  	}
    1.13 @@ -57,65 +60,75 @@
    1.14  
    1.15  bool Board::generate()
    1.16  {
    1.17 +	Mesh tmp;
    1.18  	Matrix4x4 xform;
    1.19  
    1.20  	obj.clear();
    1.21  
    1.22 -	// generate bottom
    1.23 -	Mesh *bottom = new Mesh;
    1.24 -	gen_box(bottom, HSIZE, BOT_THICKNESS, HSIZE * 2.0);
    1.25 -	xform.set_translation(Vector3(0, -BOT_THICKNESS / 2.0, 0));
    1.26 -	bottom->apply_xform(xform);
    1.27 +	for(int i=0; i<2; i++) {
    1.28 +		int sign = i * 2 - 1;
    1.29  
    1.30 -	Object *obottom = new Object;
    1.31 -	obottom->set_mesh(bottom);
    1.32 -	obj.push_back(obottom);
    1.33 +		// generate bottom
    1.34 +		Mesh *bottom = new Mesh;
    1.35 +		gen_box(bottom, HSIZE, BOT_THICKNESS, HSIZE * 2.0);
    1.36 +		xform.set_translation(Vector3(0, -BOT_THICKNESS / 2.0, 0));
    1.37 +		bottom->apply_xform(xform);
    1.38  
    1.39 +		Object *obottom = new Object;
    1.40 +		obottom->set_mesh(bottom);
    1.41 +		obottom->xform().set_translation(Vector3(sign * (HSIZE / 2.0 + WALL_THICKNESS + HINGE_RAD * 0.25), 0, 0));
    1.42 +		obottom->set_texture(img_field.texture());
    1.43 +		obj.push_back(obottom);
    1.44  
    1.45 -	// generate the 4 sides
    1.46 -	Mesh *sides = new Mesh;
    1.47 -	gen_box(sides, WALL_THICKNESS, WALL_HEIGHT, VSIZE + WALL_THICKNESS * 2);
    1.48 -	xform.set_translation(Vector3(-(HSIZE + WALL_THICKNESS) / 2.0,
    1.49 -				WALL_HEIGHT / 2.0 - BOT_THICKNESS, 0));
    1.50 -	sides->apply_xform(xform);
    1.51  
    1.52 -	Mesh tmp;
    1.53 -	gen_box(&tmp, WALL_THICKNESS, WALL_HEIGHT, VSIZE + WALL_THICKNESS * 2);
    1.54 -	xform.set_translation(Vector3((HSIZE + WALL_THICKNESS) / 2.0,
    1.55 -				WALL_HEIGHT / 2.0 - BOT_THICKNESS, 0));
    1.56 -	tmp.apply_xform(xform);
    1.57 -	sides->append(tmp);
    1.58 -	tmp.clear();
    1.59 +		// generate the 4 sides
    1.60 +		Mesh *sides = new Mesh;
    1.61 +		gen_box(sides, WALL_THICKNESS, WALL_HEIGHT, VSIZE + WALL_THICKNESS * 2);
    1.62 +		xform.set_translation(Vector3(-(HSIZE + WALL_THICKNESS) / 2.0,
    1.63 +					WALL_HEIGHT / 2.0 - BOT_THICKNESS, 0));
    1.64 +		sides->apply_xform(xform);
    1.65  
    1.66 -	gen_box(&tmp, HSIZE, WALL_HEIGHT, WALL_THICKNESS);
    1.67 -	xform.set_translation(Vector3(0, WALL_HEIGHT / 2.0 - BOT_THICKNESS,
    1.68 -				(VSIZE + WALL_THICKNESS) / 2.0));
    1.69 -	tmp.apply_xform(xform);
    1.70 -	sides->append(tmp);
    1.71 -	tmp.clear();
    1.72 +		gen_box(&tmp, WALL_THICKNESS, WALL_HEIGHT, VSIZE + WALL_THICKNESS * 2);
    1.73 +		xform.set_translation(Vector3((HSIZE + WALL_THICKNESS) / 2.0,
    1.74 +					WALL_HEIGHT / 2.0 - BOT_THICKNESS, 0));
    1.75 +		tmp.apply_xform(xform);
    1.76 +		sides->append(tmp);
    1.77 +		tmp.clear();
    1.78  
    1.79 -	gen_box(&tmp, HSIZE, WALL_HEIGHT, WALL_THICKNESS);
    1.80 -	xform.set_translation(Vector3(0, WALL_HEIGHT / 2.0 - BOT_THICKNESS,
    1.81 -				-(VSIZE + WALL_THICKNESS) / 2.0));
    1.82 -	tmp.apply_xform(xform);
    1.83 -	sides->append(tmp);
    1.84 -	tmp.clear();
    1.85 +		gen_box(&tmp, HSIZE, WALL_HEIGHT, WALL_THICKNESS);
    1.86 +		xform.set_translation(Vector3(0, WALL_HEIGHT / 2.0 - BOT_THICKNESS,
    1.87 +					(VSIZE + WALL_THICKNESS) / 2.0));
    1.88 +		tmp.apply_xform(xform);
    1.89 +		sides->append(tmp);
    1.90 +		tmp.clear();
    1.91  
    1.92 -	Object *osides = new Object;
    1.93 -	osides->set_mesh(sides);
    1.94 -	obj.push_back(osides);
    1.95 +		gen_box(&tmp, HSIZE, WALL_HEIGHT, WALL_THICKNESS);
    1.96 +		xform.set_translation(Vector3(0, WALL_HEIGHT / 2.0 - BOT_THICKNESS,
    1.97 +					-(VSIZE + WALL_THICKNESS) / 2.0));
    1.98 +		tmp.apply_xform(xform);
    1.99 +		sides->append(tmp);
   1.100 +		tmp.clear();
   1.101 +
   1.102 +		Object *osides = new Object;
   1.103 +		osides->set_mesh(sides);
   1.104 +		osides->xform() = obottom->xform();
   1.105 +		obj.push_back(osides);
   1.106 +
   1.107 +	}
   1.108  
   1.109  
   1.110  	// generate the hinges
   1.111  	Mesh *hinges = new Mesh;
   1.112  	gen_cylinder(hinges, HINGE_RAD, HINGE_HEIGHT, 10, 1, 1);
   1.113 -	xform.set_rotation(Vector3(M_PI / 2.0, 0, 0));
   1.114 -	xform.translate(Vector3(0, VSIZE / 4.0, 0));
   1.115 +	xform.reset_identity();
   1.116 +	xform.translate(Vector3(0, WALL_HEIGHT - HINGE_RAD * 0.5, VSIZE / 4.0));
   1.117 +	xform.rotate(Vector3(M_PI / 2.0, 0, 0));
   1.118  	hinges->apply_xform(xform);
   1.119  
   1.120  	gen_cylinder(&tmp, HINGE_RAD, HINGE_HEIGHT, 10, 1, 1);
   1.121 -	xform.set_rotation(Vector3(M_PI / 2.0, 0, 0));
   1.122 -	xform.translate(Vector3(0, -VSIZE / 4.0, 0));
   1.123 +	xform.reset_identity();
   1.124 +	xform.translate(Vector3(0, WALL_HEIGHT - HINGE_RAD * 0.5, -VSIZE / 4.0));
   1.125 +	xform.rotate(Vector3(M_PI / 2.0, 0, 0));
   1.126  	tmp.apply_xform(xform);
   1.127  
   1.128  	hinges->append(tmp);
   1.129 @@ -127,3 +140,73 @@
   1.130  
   1.131  	return true;
   1.132  }
   1.133 +
   1.134 +static bool spike(float x, float y)
   1.135 +{
   1.136 +	x = fmod(x * 5.0, 1.0);
   1.137 +	return y < (x < 0.5 ? 2.0 * x : 2.0 - 2.0 * x);
   1.138 +}
   1.139 +
   1.140 +static bool circle(float x, float y, float rad)
   1.141 +{
   1.142 +	x = fmod(x * 5.0, 1.0) - 0.5;
   1.143 +	y = (y - 0.65) * 5.0;
   1.144 +	float len = sqrt(x * x + y * y);
   1.145 +	return len < rad;
   1.146 +}
   1.147 +
   1.148 +static bool diamond(float x, float y)
   1.149 +{
   1.150 +	return y >= (1.0 - (x < 0.5 ? 2.0 * x : 2.0 - 2.0 * x)) * 0.3333333 + 0.88;
   1.151 +}
   1.152 +
   1.153 +static bool center_circle(float x, float y, float rad)
   1.154 +{
   1.155 +	x = x - 0.5;
   1.156 +	y = 1.0 - y;
   1.157 +	return sqrt(x * x + y * y) < rad;
   1.158 +}
   1.159 +
   1.160 +bool Board::generate_textures()
   1.161 +{
   1.162 +	const int xsz = 512;
   1.163 +	const int ysz = 1024;
   1.164 +
   1.165 +	img_field.create(xsz, ysz);
   1.166 +	clear_image(&img_field, 0, 0, 0);
   1.167 +
   1.168 +	unsigned char *pptr = img_field.pixels;
   1.169 +
   1.170 +	for(int i=0; i<ysz; i++) {
   1.171 +		float v = (float)i / (float)ysz;
   1.172 +
   1.173 +		for(int j=0; j<xsz; j++) {
   1.174 +			float u = (float)j / (float)xsz;
   1.175 +
   1.176 +			int r = 0, g = 0, b = 0;
   1.177 +
   1.178 +			float x = u;
   1.179 +			float y = v < 0.5 ? v * 2.0 : 2.0 - v * 2.0;
   1.180 +			bool inside = false;
   1.181 +
   1.182 +			inside |= (spike(x, y + 0.33333) && !spike(x, y + 0.4)) ||
   1.183 +				(spike(x, y + 0.5) && !spike(x, y + 0.68));
   1.184 +			inside |= (circle(x, y, 0.12) && !circle(x, y, 0.1)) || circle(x, y, 0.06);
   1.185 +			inside |= (diamond(x, y) && !diamond(x, y - 0.015)) ||
   1.186 +				(diamond(x, y - 0.023) && !diamond(x, y - 0.028));
   1.187 +			inside |= center_circle(x, y, 0.03);
   1.188 +
   1.189 +			if(inside) {
   1.190 +				r = g = b = 255;
   1.191 +			}
   1.192 +
   1.193 +			pptr[0] = r;
   1.194 +			pptr[1] = g;
   1.195 +			pptr[2] = b;
   1.196 +			pptr += 3;
   1.197 +		}
   1.198 +	}
   1.199 +
   1.200 +	img_field.texture();
   1.201 +	return true;
   1.202 +}