tavli

changeset 1:3fcd7b4d631f

board mesh generation
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 22 Jun 2015 05:05:37 +0300
parents 52e0dd47753b
children 893192aea099
files Makefile src/board.cc src/board.h src/game.cc src/mesh.cc src/meshgen.cc src/meshgen.h src/object.cc src/object.h
diffstat 9 files changed, 676 insertions(+), 33 deletions(-) [+]
line diff
     1.1 --- a/Makefile	Sun Jun 21 06:30:39 2015 +0300
     1.2 +++ b/Makefile	Mon Jun 22 05:05:37 2015 +0300
     1.3 @@ -6,7 +6,7 @@
     1.4  bin = tavli
     1.5  
     1.6  CXXFLAGS = -pedantic -Wall -g
     1.7 -LDFLAGS = $(libgl)
     1.8 +LDFLAGS = $(libgl) -lvmath -limago -lm -lpthread
     1.9  
    1.10  ifeq ($(shell uname -s), Darwin)
    1.11  	libgl = -framework OpenGL -framework GLUT -lGLEW
     2.1 --- a/src/board.cc	Sun Jun 21 06:30:39 2015 +0300
     2.2 +++ b/src/board.cc	Mon Jun 22 05:05:37 2015 +0300
     2.3 @@ -1,11 +1,11 @@
     2.4  #include "opengl.h"
     2.5  #include "board.h"
     2.6 +#include "meshgen.h"
     2.7  
     2.8 -static Mesh *gen_board_mesh();
     2.9 -static Mesh *gen_puck_mesh();
    2.10  
    2.11  Board::Board()
    2.12  {
    2.13 +	puck_mesh = 0;
    2.14  	clear();
    2.15  }
    2.16  
    2.17 @@ -16,20 +16,22 @@
    2.18  
    2.19  bool Board::init()
    2.20  {
    2.21 -	if(!(board_mesh = gen_board_mesh())) {
    2.22 +	if(!generate()) {
    2.23  		return false;
    2.24  	}
    2.25 -	if(!(puck_mesh = gen_puck_mesh())) {
    2.26 -		return false;
    2.27 -	}
    2.28 +
    2.29  	return true;
    2.30  }
    2.31  
    2.32  void Board::destroy()
    2.33  {
    2.34 -	delete board_mesh;
    2.35 +	for(size_t i=0; i<board_meshes.size(); i++) {
    2.36 +		delete board_meshes[i];
    2.37 +	}
    2.38 +	board_meshes.clear();
    2.39 +
    2.40  	delete puck_mesh;
    2.41 -	board_mesh = puck_mesh = 0;
    2.42 +	puck_mesh = 0;
    2.43  }
    2.44  
    2.45  void Board::clear()
    2.46 @@ -39,16 +41,77 @@
    2.47  
    2.48  void Board::draw() const
    2.49  {
    2.50 -	if(board_mesh)
    2.51 -		board_mesh->draw();
    2.52 +	for(size_t i=0; i<board_meshes.size(); i++) {
    2.53 +		board_meshes[i]->draw();
    2.54 +	}
    2.55  }
    2.56  
    2.57 -static Mesh *gen_board_mesh()
    2.58 +#define HSIZE	1.0
    2.59 +#define VSIZE	(2.0 * HSIZE)
    2.60 +#define BOT_THICKNESS	(HSIZE * 0.01)
    2.61 +#define WALL_THICKNESS	(HSIZE * 0.05)
    2.62 +#define WALL_HEIGHT		(HSIZE * 0.1)
    2.63 +#define GAP				(HSIZE * 0.025)
    2.64 +#define HINGE_RAD		(GAP * 0.5)
    2.65 +#define HINGE_HEIGHT	(VSIZE * 0.075)
    2.66 +
    2.67 +bool Board::generate()
    2.68  {
    2.69 -	return 0;
    2.70 +	Matrix4x4 xform;
    2.71 +
    2.72 +	// generate bottom
    2.73 +	Mesh *bottom = new Mesh;
    2.74 +	gen_box(bottom, HSIZE, BOT_THICKNESS, HSIZE * 2.0);
    2.75 +	xform.set_translation(Vector3(0, -BOT_THICKNESS / 2.0, 0));
    2.76 +	bottom->apply_xform(xform);
    2.77 +
    2.78 +	// generate the 4 sides
    2.79 +	Mesh *sides = new Mesh;
    2.80 +	gen_box(sides, WALL_THICKNESS, WALL_HEIGHT, VSIZE + WALL_THICKNESS * 2);
    2.81 +	xform.set_translation(Vector3(-(HSIZE + WALL_THICKNESS) / 2.0,
    2.82 +				WALL_HEIGHT / 2.0 - BOT_THICKNESS, 0));
    2.83 +	sides->apply_xform(xform);
    2.84 +
    2.85 +	Mesh tmp;
    2.86 +	gen_box(&tmp, WALL_THICKNESS, WALL_HEIGHT, VSIZE + WALL_THICKNESS * 2);
    2.87 +	xform.set_translation(Vector3((HSIZE + WALL_THICKNESS) / 2.0,
    2.88 +				WALL_HEIGHT / 2.0 - BOT_THICKNESS, 0));
    2.89 +	tmp.apply_xform(xform);
    2.90 +	sides->append(tmp);
    2.91 +	tmp.clear();
    2.92 +
    2.93 +	gen_box(&tmp, HSIZE, WALL_HEIGHT, WALL_THICKNESS);
    2.94 +	xform.set_translation(Vector3(0, WALL_HEIGHT / 2.0 - BOT_THICKNESS,
    2.95 +				(VSIZE + WALL_THICKNESS) / 2.0));
    2.96 +	tmp.apply_xform(xform);
    2.97 +	sides->append(tmp);
    2.98 +	tmp.clear();
    2.99 +
   2.100 +	gen_box(&tmp, HSIZE, WALL_HEIGHT, WALL_THICKNESS);
   2.101 +	xform.set_translation(Vector3(0, WALL_HEIGHT / 2.0 - BOT_THICKNESS,
   2.102 +				-(VSIZE + WALL_THICKNESS) / 2.0));
   2.103 +	tmp.apply_xform(xform);
   2.104 +	sides->append(tmp);
   2.105 +	tmp.clear();
   2.106 +
   2.107 +	// generate the hinges
   2.108 +	Mesh *hinges = new Mesh;
   2.109 +	gen_cylinder(hinges, HINGE_RAD, HINGE_HEIGHT, 10, 1, 1);
   2.110 +	xform.set_rotation(Vector3(M_PI / 2.0, 0, 0));
   2.111 +	xform.translate(Vector3(0, VSIZE / 4.0, 0));
   2.112 +	hinges->apply_xform(xform);
   2.113 +
   2.114 +	gen_cylinder(&tmp, HINGE_RAD, HINGE_HEIGHT, 10, 1, 1);
   2.115 +	xform.set_rotation(Vector3(M_PI / 2.0, 0, 0));
   2.116 +	xform.translate(Vector3(0, -VSIZE / 4.0, 0));
   2.117 +	tmp.apply_xform(xform);
   2.118 +
   2.119 +	hinges->append(tmp);
   2.120 +
   2.121 +
   2.122 +	board_meshes.clear();
   2.123 +	board_meshes.push_back(bottom);
   2.124 +	board_meshes.push_back(sides);
   2.125 +	board_meshes.push_back(hinges);
   2.126 +	return true;
   2.127  }
   2.128 -
   2.129 -static Mesh *gen_puck_mesh()
   2.130 -{
   2.131 -	return 0;
   2.132 -}
     3.1 --- a/src/board.h	Sun Jun 21 06:30:39 2015 +0300
     3.2 +++ b/src/board.h	Mon Jun 22 05:05:37 2015 +0300
     3.3 @@ -1,6 +1,7 @@
     3.4  #ifndef BOARD_H_
     3.5  #define BOARD_H_
     3.6  
     3.7 +#include <vector>
     3.8  #include "mesh.h"
     3.9  
    3.10  #define NUM_SLOTS	24
    3.11 @@ -11,7 +12,10 @@
    3.12  class Board {
    3.13  private:
    3.14  	int slots[NUM_SLOTS][MAX_PUCKS];
    3.15 -	Mesh *board_mesh, *puck_mesh;
    3.16 +	std::vector<Mesh*> board_meshes;
    3.17 +	Mesh *puck_mesh;
    3.18 +
    3.19 +	bool generate();
    3.20  
    3.21  public:
    3.22  	Board();
     4.1 --- a/src/game.cc	Sun Jun 21 06:30:39 2015 +0300
     4.2 +++ b/src/game.cc	Mon Jun 22 05:05:37 2015 +0300
     4.3 @@ -1,11 +1,14 @@
     4.4  #include <stdio.h>
     4.5  #include <GL/glew.h>
     4.6  #include "game.h"
     4.7 +#include "board.h"
     4.8  
     4.9  static void draw_backdrop();
    4.10  
    4.11  int win_width, win_height;
    4.12  
    4.13 +static Board board;
    4.14 +
    4.15  static float cam_theta, cam_phi = 25, cam_dist = 6;
    4.16  static bool bnstate[8];
    4.17  static int prev_x, prev_y;
    4.18 @@ -19,11 +22,16 @@
    4.19  	glEnable(GL_LIGHTING);
    4.20  	glEnable(GL_LIGHT0);
    4.21  
    4.22 +	if(!board.init()) {
    4.23 +		return false;
    4.24 +	}
    4.25 +
    4.26  	return true;
    4.27  }
    4.28  
    4.29  void game_cleanup()
    4.30  {
    4.31 +	board.destroy();
    4.32  }
    4.33  
    4.34  void game_update(unsigned long time_msec)
    4.35 @@ -42,13 +50,16 @@
    4.36  
    4.37  	draw_backdrop();
    4.38  
    4.39 +	board.draw();
    4.40 +
    4.41 +	/*
    4.42  	glBegin(GL_QUADS);
    4.43  	glNormal3f(0, 1, 0);
    4.44  	glVertex3f(-1, 0, 1);
    4.45  	glVertex3f(1, 0, 1);
    4.46  	glVertex3f(1, 0, -1);
    4.47  	glVertex3f(-1, 0, -1);
    4.48 -	glEnd();
    4.49 +	glEnd();*/
    4.50  }
    4.51  
    4.52  static void draw_backdrop()
    4.53 @@ -85,7 +96,7 @@
    4.54  {
    4.55  	glMatrixMode(GL_PROJECTION);
    4.56  	glLoadIdentity();
    4.57 -	gluPerspective(50, (float)x / (float)y, 0.5, 500.0);
    4.58 +	gluPerspective(50, (float)x / (float)y, 0.2, 200.0);
    4.59  
    4.60  	glViewport(0, 0, x, y);
    4.61  }
     5.1 --- a/src/mesh.cc	Sun Jun 21 06:30:39 2015 +0300
     5.2 +++ b/src/mesh.cc	Mon Jun 22 05:05:37 2015 +0300
     5.3 @@ -5,15 +5,16 @@
     5.4  #include "opengl.h"
     5.5  #include "mesh.h"
     5.6  //#include "xform_node.h"
     5.7 -#include "shader.h"
     5.8  
     5.9 -int Mesh::global_sdr_loc[NUM_MESH_ATTR] = {
    5.10 +int Mesh::global_sdr_loc[NUM_MESH_ATTR] = { 0, 1, 2, 3, 4, 5, 6 };
    5.11 +/*
    5.12  	(int)SDR_ATTR_VERTEX,
    5.13  	(int)SDR_ATTR_NORMAL,
    5.14  	(int)SDR_ATTR_TANGENT,
    5.15  	(int)SDR_ATTR_TEXCOORD,
    5.16  	(int)SDR_ATTR_COLOR,
    5.17  	-1, -1};
    5.18 +*/
    5.19  unsigned int Mesh::intersect_mode = ISECT_DEFAULT;
    5.20  float Mesh::vertex_sel_dist = 0.01;
    5.21  float Mesh::vis_vecsize = 1.0;
    5.22 @@ -555,12 +556,9 @@
    5.23  
    5.24  void Mesh::draw() const
    5.25  {
    5.26 -#ifdef GL_ES_VERSION_2_0
    5.27 -	if(!SdrProg::active) {
    5.28 -		fprintf(stderr, "%s: CrippledGL ES can't draw without a shader\n", __FUNCTION__);
    5.29 -		return;
    5.30 -	}
    5.31 -#endif
    5.32 +	int cur_sdr;
    5.33 +	glGetIntegerv(GL_CURRENT_PROGRAM, &cur_sdr);
    5.34 +
    5.35  
    5.36  	((Mesh*)this)->update_buffers();
    5.37  
    5.38 @@ -569,7 +567,7 @@
    5.39  		return;
    5.40  	}
    5.41  
    5.42 -	if(SdrProg::active) {
    5.43 +	if(cur_sdr) {
    5.44  		// rendering with shaders
    5.45  		if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) {
    5.46  			fprintf(stderr, "%s: shader attribute location for vertices unset\n", __FUNCTION__);
    5.47 @@ -618,7 +616,7 @@
    5.48  		glDrawArrays(GL_TRIANGLES, 0, nverts);
    5.49  	}
    5.50  
    5.51 -	if(SdrProg::active) {
    5.52 +	if(cur_sdr) {
    5.53  		// rendered with shaders
    5.54  		for(int i=0; i<NUM_MESH_ATTR; i++) {
    5.55  			int loc = global_sdr_loc[i];
    5.56 @@ -1128,7 +1126,6 @@
    5.57  
    5.58  	glDisableVertexAttribArray(vloc);
    5.59  	glDisableVertexAttribArray(nloc);
    5.60 -	CHECK_GLERROR;
    5.61  }
    5.62  
    5.63  void Triangle::draw_wire() const
    5.64 @@ -1142,7 +1139,6 @@
    5.65  	glDrawElements(GL_LINES, 6, GL_UNSIGNED_INT, idxarr);
    5.66  
    5.67  	glDisableVertexAttribArray(vloc);
    5.68 -	CHECK_GLERROR;
    5.69  }
    5.70  
    5.71  Vector3 Triangle::calc_barycentric(const Vector3 &pos) const
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/meshgen.cc	Mon Jun 22 05:05:37 2015 +0300
     6.3 @@ -0,0 +1,487 @@
     6.4 +#include <stdio.h>
     6.5 +#include "meshgen.h"
     6.6 +#include "mesh.h"
     6.7 +
     6.8 +// -------- sphere --------
     6.9 +
    6.10 +#define SURAD(u)	((u) * 2.0 * M_PI)
    6.11 +#define SVRAD(v)	((v) * M_PI)
    6.12 +
    6.13 +static Vector3 sphvec(float theta, float phi)
    6.14 +{
    6.15 +	return Vector3(sin(theta) * sin(phi),
    6.16 +			cos(phi),
    6.17 +			cos(theta) * sin(phi));
    6.18 +}
    6.19 +
    6.20 +void gen_sphere(Mesh *mesh, float rad, int usub, int vsub, float urange, float vrange)
    6.21 +{
    6.22 +	if(usub < 4) usub = 4;
    6.23 +	if(vsub < 2) vsub = 2;
    6.24 +
    6.25 +	int uverts = usub + 1;
    6.26 +	int vverts = vsub + 1;
    6.27 +
    6.28 +	int num_verts = uverts * vverts;
    6.29 +	int num_quads = usub * vsub;
    6.30 +	int num_tri = num_quads * 2;
    6.31 +
    6.32 +	mesh->clear();
    6.33 +	Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
    6.34 +	Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
    6.35 +	Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
    6.36 +	Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
    6.37 +	unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
    6.38 +
    6.39 +	float du = urange / (float)(uverts - 1);
    6.40 +	float dv = vrange / (float)(vverts - 1);
    6.41 +
    6.42 +	float u = 0.0;
    6.43 +	for(int i=0; i<uverts; i++) {
    6.44 +		float theta = SURAD(u * urange);
    6.45 +
    6.46 +		float v = 0.0;
    6.47 +		for(int j=0; j<vverts; j++) {
    6.48 +			float phi = SVRAD(v * vrange);
    6.49 +
    6.50 +			Vector3 pos = sphvec(theta, phi);
    6.51 +
    6.52 +			*varr++ = pos * rad;
    6.53 +			*narr++ = pos;
    6.54 +			*tarr++ = (sphvec(theta + 0.1f, (float)M_PI / 2.0f) - sphvec(theta - 0.1f, (float)M_PI / 2.0f)).normalized();
    6.55 +			*uvarr++ = Vector2(u * urange, v * vrange);
    6.56 +
    6.57 +			if(i < usub && j < vsub) {
    6.58 +				int idx = i * vverts + j;
    6.59 +				*idxarr++ = idx;
    6.60 +				*idxarr++ = idx + 1;
    6.61 +				*idxarr++ = idx + vverts + 1;
    6.62 +
    6.63 +				*idxarr++ = idx;
    6.64 +				*idxarr++ = idx + vverts + 1;
    6.65 +				*idxarr++ = idx + vverts;
    6.66 +			}
    6.67 +
    6.68 +			v += dv;
    6.69 +		}
    6.70 +		u += du;
    6.71 +	}
    6.72 +}
    6.73 +
    6.74 +
    6.75 +// -------- cylinder --------
    6.76 +
    6.77 +static Vector3 cylvec(float theta, float height)
    6.78 +{
    6.79 +	return Vector3(sin(theta), height, cos(theta));
    6.80 +}
    6.81 +
    6.82 +void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
    6.83 +{
    6.84 +	if(usub < 4) usub = 4;
    6.85 +	if(vsub < 1) vsub = 1;
    6.86 +
    6.87 +	int uverts = usub + 1;
    6.88 +	int vverts = vsub + 1;
    6.89 +
    6.90 +	int num_body_verts = uverts * vverts;
    6.91 +	int num_body_quads = usub * vsub;
    6.92 +	int num_body_tri = num_body_quads * 2;
    6.93 +
    6.94 +	int capvverts = capsub ? capsub + 1 : 0;
    6.95 +	int num_cap_verts = uverts * capvverts;
    6.96 +	int num_cap_quads = usub * capsub;
    6.97 +	int num_cap_tri = num_cap_quads * 2;
    6.98 +
    6.99 +	int num_verts = num_body_verts + num_cap_verts * 2;
   6.100 +	int num_tri = num_body_tri + num_cap_tri * 2;
   6.101 +
   6.102 +	mesh->clear();
   6.103 +	Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
   6.104 +	Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
   6.105 +	Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
   6.106 +	Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
   6.107 +	unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
   6.108 +
   6.109 +	float du = urange / (float)(uverts - 1);
   6.110 +	float dv = vrange / (float)(vverts - 1);
   6.111 +
   6.112 +	float u = 0.0;
   6.113 +	for(int i=0; i<uverts; i++) {
   6.114 +		float theta = SURAD(u);
   6.115 +
   6.116 +		float v = 0.0;
   6.117 +		for(int j=0; j<vverts; j++) {
   6.118 +			float y = (v - 0.5) * height;
   6.119 +			Vector3 pos = cylvec(theta, y);
   6.120 +
   6.121 +			*varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad);
   6.122 +			*narr++ = Vector3(pos.x, 0.0, pos.z);
   6.123 +			*tarr++ = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
   6.124 +			*uvarr++ = Vector2(u * urange, v * vrange);
   6.125 +
   6.126 +			if(i < usub && j < vsub) {
   6.127 +				int idx = i * vverts + j;
   6.128 +
   6.129 +				*idxarr++ = idx;
   6.130 +				*idxarr++ = idx + vverts + 1;
   6.131 +				*idxarr++ = idx + 1;
   6.132 +
   6.133 +				*idxarr++ = idx;
   6.134 +				*idxarr++ = idx + vverts;
   6.135 +				*idxarr++ = idx + vverts + 1;
   6.136 +			}
   6.137 +
   6.138 +			v += dv;
   6.139 +		}
   6.140 +		u += du;
   6.141 +	}
   6.142 +
   6.143 +
   6.144 +	// now the cap!
   6.145 +	if(!capsub) {
   6.146 +		return;
   6.147 +	}
   6.148 +
   6.149 +	dv = 1.0 / (float)(capvverts - 1);
   6.150 +
   6.151 +	u = 0.0;
   6.152 +	for(int i=0; i<uverts; i++) {
   6.153 +		float theta = SURAD(u);
   6.154 +
   6.155 +		float v = 0.0;
   6.156 +		for(int j=0; j<capvverts; j++) {
   6.157 +			float r = v * rad;
   6.158 +
   6.159 +			Vector3 pos = cylvec(theta, height / 2.0) * r;
   6.160 +			pos.y = height / 2.0;
   6.161 +			Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
   6.162 +
   6.163 +			*varr++ = pos;
   6.164 +			*narr++ = Vector3(0, 1, 0);
   6.165 +			*tarr++ = tang;
   6.166 +			*uvarr++ = Vector2(u * urange, v);
   6.167 +
   6.168 +			pos.y = -height / 2.0;
   6.169 +			*varr++ = pos;
   6.170 +			*narr++ = Vector3(0, -1, 0);
   6.171 +			*tarr++ = -tang;
   6.172 +			*uvarr++ = Vector2(u * urange, v);
   6.173 +
   6.174 +			if(i < usub && j < capsub) {
   6.175 +				unsigned int idx = num_body_verts + (i * capvverts + j) * 2;
   6.176 +
   6.177 +				unsigned int vidx[4] = {
   6.178 +					idx,
   6.179 +					idx + capvverts * 2,
   6.180 +					idx + (capvverts + 1) * 2,
   6.181 +					idx + 2
   6.182 +				};
   6.183 +
   6.184 +				*idxarr++ = vidx[0];
   6.185 +				*idxarr++ = vidx[2];
   6.186 +				*idxarr++ = vidx[1];
   6.187 +				*idxarr++ = vidx[0];
   6.188 +				*idxarr++ = vidx[3];
   6.189 +				*idxarr++ = vidx[2];
   6.190 +
   6.191 +				*idxarr++ = vidx[0] + 1;
   6.192 +				*idxarr++ = vidx[1] + 1;
   6.193 +				*idxarr++ = vidx[2] + 1;
   6.194 +				*idxarr++ = vidx[0] + 1;
   6.195 +				*idxarr++ = vidx[2] + 1;
   6.196 +				*idxarr++ = vidx[3] + 1;
   6.197 +			}
   6.198 +
   6.199 +			v += dv;
   6.200 +		}
   6.201 +		u += du;
   6.202 +	}
   6.203 +}
   6.204 +
   6.205 +// -------- cone --------
   6.206 +
   6.207 +static Vector3 conevec(float theta, float y, float height)
   6.208 +{
   6.209 +	float scale = 1.0 - y / height;
   6.210 +	return Vector3(sin(theta) * scale, y, cos(theta) * scale);
   6.211 +}
   6.212 +
   6.213 +void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
   6.214 +{
   6.215 +	if(usub < 4) usub = 4;
   6.216 +	if(vsub < 1) vsub = 1;
   6.217 +
   6.218 +	int uverts = usub + 1;
   6.219 +	int vverts = vsub + 1;
   6.220 +
   6.221 +	int num_body_verts = uverts * vverts;
   6.222 +	int num_body_quads = usub * vsub;
   6.223 +	int num_body_tri = num_body_quads * 2;
   6.224 +
   6.225 +	int capvverts = capsub ? capsub + 1 : 0;
   6.226 +	int num_cap_verts = uverts * capvverts;
   6.227 +	int num_cap_quads = usub * capsub;
   6.228 +	int num_cap_tri = num_cap_quads * 2;
   6.229 +
   6.230 +	int num_verts = num_body_verts + num_cap_verts;
   6.231 +	int num_tri = num_body_tri + num_cap_tri;
   6.232 +
   6.233 +	mesh->clear();
   6.234 +	Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
   6.235 +	Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
   6.236 +	Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
   6.237 +	Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
   6.238 +	unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
   6.239 +
   6.240 +	float du = urange / (float)(uverts - 1);
   6.241 +	float dv = vrange / (float)(vverts - 1);
   6.242 +
   6.243 +	float u = 0.0;
   6.244 +	for(int i=0; i<uverts; i++) {
   6.245 +		float theta = SURAD(u);
   6.246 +
   6.247 +		float v = 0.0;
   6.248 +		for(int j=0; j<vverts; j++) {
   6.249 +			float y = v * height;
   6.250 +			Vector3 pos = conevec(theta, y, height);
   6.251 +
   6.252 +			Vector3 tang = (conevec(theta + 0.1, 0.0, height) - conevec(theta - 0.1, 0.0, height)).normalized();
   6.253 +			Vector3 bitang = (conevec(theta, y + 0.1, height) - pos).normalized();
   6.254 +
   6.255 +			*varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad);
   6.256 +			*narr++ = cross_product(tang, bitang);
   6.257 +			*tarr++ = tang;
   6.258 +			*uvarr++ = Vector2(u * urange, v * vrange);
   6.259 +
   6.260 +			if(i < usub && j < vsub) {
   6.261 +				int idx = i * vverts + j;
   6.262 +
   6.263 +				*idxarr++ = idx;
   6.264 +				*idxarr++ = idx + vverts + 1;
   6.265 +				*idxarr++ = idx + 1;
   6.266 +
   6.267 +				*idxarr++ = idx;
   6.268 +				*idxarr++ = idx + vverts;
   6.269 +				*idxarr++ = idx + vverts + 1;
   6.270 +			}
   6.271 +
   6.272 +			v += dv;
   6.273 +		}
   6.274 +		u += du;
   6.275 +	}
   6.276 +
   6.277 +
   6.278 +	// now the bottom cap!
   6.279 +	if(!capsub) {
   6.280 +		return;
   6.281 +	}
   6.282 +
   6.283 +	dv = 1.0 / (float)(capvverts - 1);
   6.284 +
   6.285 +	u = 0.0;
   6.286 +	for(int i=0; i<uverts; i++) {
   6.287 +		float theta = SURAD(u);
   6.288 +
   6.289 +		float v = 0.0;
   6.290 +		for(int j=0; j<capvverts; j++) {
   6.291 +			float r = v * rad;
   6.292 +
   6.293 +			Vector3 pos = conevec(theta, 0.0, height) * r;
   6.294 +			Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
   6.295 +
   6.296 +			*varr++ = pos;
   6.297 +			*narr++ = Vector3(0, -1, 0);
   6.298 +			*tarr++ = tang;
   6.299 +			*uvarr++ = Vector2(u * urange, v);
   6.300 +
   6.301 +			if(i < usub && j < capsub) {
   6.302 +				unsigned int idx = num_body_verts + i * capvverts + j;
   6.303 +
   6.304 +				unsigned int vidx[4] = {
   6.305 +					idx,
   6.306 +					idx + capvverts,
   6.307 +					idx + (capvverts + 1),
   6.308 +					idx + 1
   6.309 +				};
   6.310 +
   6.311 +				*idxarr++ = vidx[0];
   6.312 +				*idxarr++ = vidx[1];
   6.313 +				*idxarr++ = vidx[2];
   6.314 +				*idxarr++ = vidx[0];
   6.315 +				*idxarr++ = vidx[2];
   6.316 +				*idxarr++ = vidx[3];
   6.317 +			}
   6.318 +
   6.319 +			v += dv;
   6.320 +		}
   6.321 +		u += du;
   6.322 +	}
   6.323 +}
   6.324 +
   6.325 +
   6.326 +// -------- plane --------
   6.327 +
   6.328 +void gen_plane(Mesh *mesh, float width, float height, int usub, int vsub)
   6.329 +{
   6.330 +	gen_heightmap(mesh, width, height, usub, vsub, 0);
   6.331 +}
   6.332 +
   6.333 +
   6.334 +// ----- heightmap ------
   6.335 +
   6.336 +void gen_heightmap(Mesh *mesh, float width, float height, int usub, int vsub, float (*hf)(float, float, void*), void *hfdata)
   6.337 +{
   6.338 +	if(usub < 1) usub = 1;
   6.339 +	if(vsub < 1) vsub = 1;
   6.340 +
   6.341 +	mesh->clear();
   6.342 +
   6.343 +	int uverts = usub + 1;
   6.344 +	int vverts = vsub + 1;
   6.345 +	int num_verts = uverts * vverts;
   6.346 +
   6.347 +	int num_quads = usub * vsub;
   6.348 +	int num_tri = num_quads * 2;
   6.349 +
   6.350 +	Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
   6.351 +	Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
   6.352 +	Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
   6.353 +	Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
   6.354 +	unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
   6.355 +
   6.356 +	float du = 1.0 / (float)usub;
   6.357 +	float dv = 1.0 / (float)vsub;
   6.358 +
   6.359 +	float u = 0.0;
   6.360 +	for(int i=0; i<uverts; i++) {
   6.361 +		float v = 0.0;
   6.362 +		for(int j=0; j<vverts; j++) {
   6.363 +			float x = (u - 0.5) * width;
   6.364 +			float y = (v - 0.5) * height;
   6.365 +			float z = hf ? hf(u, v, hfdata) : 0.0;
   6.366 +
   6.367 +			Vector3 normal = Vector3(0, 0, 1);
   6.368 +			if(hf) {
   6.369 +				float u1z = hf(u + du, v, hfdata);
   6.370 +				float v1z = hf(u, v + dv, hfdata);
   6.371 +
   6.372 +				Vector3 tang = Vector3(du * width, 0, u1z - z);
   6.373 +				Vector3 bitan = Vector3(0, dv * height, v1z - z);
   6.374 +				normal = cross_product(tang, bitan).normalized();
   6.375 +			}
   6.376 +
   6.377 +			*varr++ = Vector3(x, y, z);
   6.378 +			*narr++ = normal;
   6.379 +			*tarr++ = Vector3(1, 0, 0);
   6.380 +			*uvarr++ = Vector2(u, v);
   6.381 +
   6.382 +			if(i < usub && j < vsub) {
   6.383 +				int idx = i * vverts + j;
   6.384 +
   6.385 +				*idxarr++ = idx;
   6.386 +				*idxarr++ = idx + vverts + 1;
   6.387 +				*idxarr++ = idx + 1;
   6.388 +
   6.389 +				*idxarr++ = idx;
   6.390 +				*idxarr++ = idx + vverts;
   6.391 +				*idxarr++ = idx + vverts + 1;
   6.392 +			}
   6.393 +
   6.394 +			v += dv;
   6.395 +		}
   6.396 +		u += du;
   6.397 +	}
   6.398 +}
   6.399 +
   6.400 +// ----- heightmap ------
   6.401 +
   6.402 +void gen_box(Mesh *mesh, float xsz, float ysz, float zsz)
   6.403 +{
   6.404 +	mesh->clear();
   6.405 +
   6.406 +	const int num_faces = 6;
   6.407 +	int num_verts = num_faces * 4;
   6.408 +	int num_tri = num_faces * 2;
   6.409 +
   6.410 +	float x = xsz / 2.0;
   6.411 +	float y = ysz / 2.0;
   6.412 +	float z = zsz / 2.0;
   6.413 +
   6.414 +	Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
   6.415 +	Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
   6.416 +	Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
   6.417 +	Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
   6.418 +	unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
   6.419 +
   6.420 +	static const Vector2 uv[] = { Vector2(0, 0), Vector2(1, 0), Vector2(1, 1), Vector2(0, 1) };
   6.421 +
   6.422 +	// front
   6.423 +	for(int i=0; i<4; i++) {
   6.424 +		*narr++ = Vector3(0, 0, 1);
   6.425 +		*tarr++ = Vector3(1, 0, 0);
   6.426 +		*uvarr++ = uv[i];
   6.427 +	}
   6.428 +	*varr++ = Vector3(-x, -y, z);
   6.429 +	*varr++ = Vector3(x, -y, z);
   6.430 +	*varr++ = Vector3(x, y, z);
   6.431 +	*varr++ = Vector3(-x, y, z);
   6.432 +	// right
   6.433 +	for(int i=0; i<4; i++) {
   6.434 +		*narr++ = Vector3(1, 0, 0);
   6.435 +		*tarr++ = Vector3(0, 0, -1);
   6.436 +		*uvarr++ = uv[i];
   6.437 +	}
   6.438 +	*varr++ = Vector3(x, -y, z);
   6.439 +	*varr++ = Vector3(x, -y, -z);
   6.440 +	*varr++ = Vector3(x, y, -z);
   6.441 +	*varr++ = Vector3(x, y, z);
   6.442 +	// back
   6.443 +	for(int i=0; i<4; i++) {
   6.444 +		*narr++ = Vector3(0, 0, -1);
   6.445 +		*tarr++ = Vector3(-1, 0, 0);
   6.446 +		*uvarr++ = uv[i];
   6.447 +	}
   6.448 +	*varr++ = Vector3(x, -y, -z);
   6.449 +	*varr++ = Vector3(-x, -y, -z);
   6.450 +	*varr++ = Vector3(-x, y, -z);
   6.451 +	*varr++ = Vector3(x, y, -z);
   6.452 +	// left
   6.453 +	for(int i=0; i<4; i++) {
   6.454 +		*narr++ = Vector3(-1, 0, 0);
   6.455 +		*tarr++ = Vector3(0, 0, 1);
   6.456 +		*uvarr++ = uv[i];
   6.457 +	}
   6.458 +	*varr++ = Vector3(-x, -y, -z);
   6.459 +	*varr++ = Vector3(-x, -y, z);
   6.460 +	*varr++ = Vector3(-x, y, z);
   6.461 +	*varr++ = Vector3(-x, y, -z);
   6.462 +	// top
   6.463 +	for(int i=0; i<4; i++) {
   6.464 +		*narr++ = Vector3(0, 1, 0);
   6.465 +		*tarr++ = Vector3(1, 0, 0);
   6.466 +		*uvarr++ = uv[i];
   6.467 +	}
   6.468 +	*varr++ = Vector3(-x, y, z);
   6.469 +	*varr++ = Vector3(x, y, z);
   6.470 +	*varr++ = Vector3(x, y, -z);
   6.471 +	*varr++ = Vector3(-x, y, -z);
   6.472 +	// bottom
   6.473 +	for(int i=0; i<4; i++) {
   6.474 +		*narr++ = Vector3(0, -1, 0);
   6.475 +		*tarr++ = Vector3(1, 0, 0);
   6.476 +		*uvarr++ = uv[i];
   6.477 +	}
   6.478 +	*varr++ = Vector3(-x, -y, -z);
   6.479 +	*varr++ = Vector3(x, -y, -z);
   6.480 +	*varr++ = Vector3(x, -y, z);
   6.481 +	*varr++ = Vector3(-x, -y, z);
   6.482 +
   6.483 +	// index array
   6.484 +	static const int faceidx[] = {0, 1, 2, 0, 2, 3};
   6.485 +	for(int i=0; i<num_faces; i++) {
   6.486 +		for(int j=0; j<6; j++) {
   6.487 +			*idxarr++ = faceidx[j] + i * 4;
   6.488 +		}
   6.489 +	}
   6.490 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/meshgen.h	Mon Jun 22 05:05:37 2015 +0300
     7.3 @@ -0,0 +1,13 @@
     7.4 +#ifndef MESHGEN_H_
     7.5 +#define MESHGEN_H_
     7.6 +
     7.7 +class Mesh;
     7.8 +
     7.9 +void gen_sphere(Mesh *mesh, float rad, int usub, int vsub, float urange = 1.0, float vrange = 1.0);
    7.10 +void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub = 0, float urange = 1.0, float vrange = 1.0);
    7.11 +void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub = 0, float urange = 1.0, float vrange = 1.0);
    7.12 +void gen_plane(Mesh *mesh, float width, float height, int usub = 1, int vsub = 1);
    7.13 +void gen_heightmap(Mesh *mesh, float width, float height, int usub, int vsub, float (*hf)(float, float, void*), void *hfdata = 0);
    7.14 +void gen_box(Mesh *mesh, float xsz, float ysz, float zsz);
    7.15 +
    7.16 +#endif	// MESHGEN_H_
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/object.cc	Mon Jun 22 05:05:37 2015 +0300
     8.3 @@ -0,0 +1,45 @@
     8.4 +#include "object.h"
     8.5 +#include "opengl.h"
     8.6 +
     8.7 +Object::Object()
     8.8 +{
     8.9 +	mesh = 0;
    8.10 +}
    8.11 +
    8.12 +Object::~Object()
    8.13 +{
    8.14 +	delete mesh;
    8.15 +}
    8.16 +
    8.17 +Matrix4x4 &Object::xform()
    8.18 +{
    8.19 +	return matrix;
    8.20 +}
    8.21 +
    8.22 +const Matrix4x4 &Object::xform() const
    8.23 +{
    8.24 +	return matrix;
    8.25 +}
    8.26 +
    8.27 +void Object::set_mesh(Mesh *m)
    8.28 +{
    8.29 +	this->mesh = m;
    8.30 +}
    8.31 +
    8.32 +Mesh *Object::get_mesh() const
    8.33 +{
    8.34 +	return mesh;
    8.35 +}
    8.36 +
    8.37 +void Object::draw() const
    8.38 +{
    8.39 +	if(!mesh) return;
    8.40 +
    8.41 +	glMatrixMode(GL_MODELVIEW);
    8.42 +	glPushMatrix();
    8.43 +	glLoadTransposeMatrixf(matrix[0]);
    8.44 +
    8.45 +	mesh->draw();
    8.46 +
    8.47 +	glPopMatrix();
    8.48 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/object.h	Mon Jun 22 05:05:37 2015 +0300
     9.3 @@ -0,0 +1,24 @@
     9.4 +#ifndef OBJECT_H_
     9.5 +#define OBJECT_H_
     9.6 +
     9.7 +#include "mesh.h"
     9.8 +
     9.9 +class Object {
    9.10 +private:
    9.11 +	Mesh *mesh;
    9.12 +	Matrix4x4 matrix;
    9.13 +
    9.14 +public:
    9.15 +	Object();
    9.16 +	~Object();
    9.17 +
    9.18 +	Matrix4x4 &xform();
    9.19 +	const Matrix4x4 &xform() const;
    9.20 +
    9.21 +	void set_mesh(Mesh *m);
    9.22 +	Mesh *get_mesh() const;
    9.23 +
    9.24 +	void draw() const;
    9.25 +};
    9.26 +
    9.27 +#endif	// OBJECT_H_