#include "mesh.hpp"
unsigned Mesh::iso2tile_x(GLfloat a) const {
assert(a >= -1.0f && a <= 1.0f);
a /= len_x;
return (float)(w/2) + round(a);
}
unsigned Mesh::iso2tile_y(GLfloat a) const {
assert(a >= -1.0f && a <= 1.0f);
a /= len_y;
return (float)(h/2) + round(a);
}
GLfloat Mesh::tile2iso_x(unsigned a, bool mid) const {
assert(a < w);
return -1.0 + off_x + ((float)a*len_x);
}
GLfloat Mesh::tile2iso_y(unsigned a, bool mid) const {
assert(a < h);
return -1.0 + off_y + ((float)a*len_y);
}
static unsigned greatest_odd(unsigned a) { return (a%2)? a: a-1; }
Mesh::Mesh(const Window* win, unsigned hh): h(greatest_odd(hh)), w(greatest_odd(floor(float(h)*(float)win->w)/(float)win->h)) {
assert(w && h);
assert(h % 2 == 1); // odd, s.t. the player can be at 0.0/0.0
assert(w % 2 == 1);
vertices_num = w * h * 4 * 2 * 2;
vertices_len = vertices_num * sizeof(GLfloat);
vertices = (GLfloat*)malloc(vertices_len); // can't we overlap and thus re-use vertices?
// make sure 0.0 is at the center and the aspect is preserved (square)
float dim_x = (float)win->w/(float)w;
float dim_y = (float)win->h/(float)h;
if (dim_x < dim_y) { // y tiles would be too wide and need os
off_x = 0.0f;
off_y = ((2.0f*dim_y/dim_x)-2.0f) / 2.0f;
} else {
off_x = ((2.0f*dim_x/dim_y)-2.0f) / 2.0f;
off_y = 0.0f;
}
len_x = (2.0f - (2.0f*off_x)) / (float)w;
len_y = (2.0f - (2.0f*off_y)) / (float)h;
// we dont use stripes so we can hardcode texture positions
GLfloat* p = vertices;
for (unsigned y=0; y<h; ++y) {
GLfloat y_start = tile2iso_y(y);
GLfloat y_end = (y==h-1)? 1.0f-off_y: tile2iso_y(y+1);
for (unsigned x=0; x<w; ++x) {
GLfloat x_start = tile2iso_x(x);
GLfloat x_end = (x==w-1)? 1.0f-off_x: tile2iso_x(x+1);
// top left
*(p++) = x_start;
*(p++) = y_end;
*(p++) = 0.0f;
*(p++) = 0.0f;
// bottom left
*(p++) = x_start;
*(p++) = y_start;
*(p++) = 0.0f;
*(p++) = 1.0f;
// top right
*(p++) = x_end;
*(p++) = y_end;
*(p++) = 1.0f;
*(p++) = 0.0f;
// bottom right
*(p++) = x_end;
*(p++) = y_start;
*(p++) = 1.0f;
*(p++) = 1.0f;
}
}
// 0,1,2, 1,2,3, 4,5,6, 5,6,7
size_t elements_num = w * h * 6;
elements_len = elements_num * sizeof(GLuint);
elements = (GLuint*)malloc(elements_len);
GLuint* q = elements;
for (GLuint i=0; i<w*h; ++i) {
GLuint ii = i*4;
*(q++) = ii+0;
*(q++) = ii+1;
*(q++) = ii+2;
*(q++) = ii+1;
*(q++) = ii+2;
*(q++) = ii+3;
}
}
void Mesh::draw(unsigned line, unsigned pos, unsigned len) const {
assert(line < h);
assert(pos+len-1 < w);
glDrawElements(GL_TRIANGLES, 6*len, GL_UNSIGNED_INT, (void*)((intptr_t)((line*w)+pos)*6*sizeof(GLuint)));
}
Mesh::~Mesh() {
free(vertices);
free(elements);
}