PDA

View Full Version : How to create a 3D hexagonal tile?



z_Zelman
06-06-2013, 10:53 AM
I want to create a 3D hexagonal tile. It is two hexagons (top and bottom) connected with rectangles between the two on their respective edge. Right now I have a function that draws a 2D hexagon on a 3D coordinate system in the positive x-z plane with the y being the height it is drawn at. You give the center coordinates you want it drawn at:

glBegin(GL_POLYGON);
for (GLfloat i = 0; i < 6; i++)
{

GLfloat angle = 2 * PI / 6 * (i + 0.5);

GLfloat vertex_x = center_x + size * cos(angle);

GLfloat vertex_z = center_z + size * sin(angle);

glVertex3f(vertex_x, center_y, vertex_z);
}
glEnd();

I would like to have an actual tile drawn instead of a 2D hexagon, but I do not know how to do that. Thoughts?

z_Zelman
06-06-2013, 03:17 PM
I found a solution, although it may not be the best one. Here is the entire function:

// draws a pointy-topped hexagon at (x,y,z) with <size> and <height>
// <size> is from the center to the corners, <height> is from the botom hex to the top hex (rectangles form the walls)
// drawn in the x-z plane with y as the height
void drawHexagon(GLfloat center_x, GLfloat center_y, GLfloat center_z, GLfloat size, GLfloat height, GLfloat* color)
{
glPushMatrix();
{
glColor3f(color[0], color[1], color[2]);
GLfloat firstHex[6][3];
GLfloat secondHex[6][3];
glBegin(GL_POLYGON);
{
for (GLint i = 0; i < 6; i++)
{
GLfloat angle = 2 * PI / 6 * (i + 0.5);
GLfloat x_tempVertex = center_x + size * cos(angle);
GLfloat z_tempVertex = center_z + size * sin(angle);
firstHex[i][0] = x_tempVertex;
firstHex[i][1] = center_y;
firstHex[i][2] = z_tempVertex;
glVertex3f(x_tempVertex, center_y, z_tempVertex);
}
}
glEnd();

glBegin(GL_POLYGON);
{
for (GLint i = 0; i < 6; i++)
{
GLfloat angle = 2 * PI / 6 * (i + 0.5);
GLfloat x_tempVertex = center_x + size * cos(angle);
GLfloat z_tempVertex = center_z + size * sin(angle);
secondHex[i][0] = x_tempVertex;
secondHex[i][1] = center_y + height;
secondHex[i][2] = z_tempVertex;
glVertex3f(x_tempVertex, center_y+height, z_tempVertex);
}
}
glEnd();

// Begin filling the rectangles between the two hexagons
// drawing begins at ( 0, 0, 0 ) and moves clockwise
// ( 0, 0, 1 ) [the mid single coord in each set represents the middle point up/down respectivly]
glColor3f(1,1,1);
glBegin(GL_QUADS);
{
for (GLint i = 0; i < 5; i++)
{
glVertex3f(firstHex[i][0], firstHex[i][1], firstHex[i][2]); // top left
glVertex3f(secondHex[i][0], secondHex[i][1], secondHex[i][2]); // bottom left
glVertex3f(secondHex[i+1][0], secondHex[i+1][1], secondHex[i+1][2]); // top right
glVertex3f(firstHex[i+1][0], firstHex[i+1][1], firstHex[i+1][2]); // bottom right
}

// corner case (connecting the end to the beginning)
glVertex3f(firstHex[5][0], firstHex[5][1], firstHex[5][2]); // top left
glVertex3f(secondHex[5][0], secondHex[5][1], secondHex[5][2]); // bottom left
glVertex3f(secondHex[0][0], secondHex[0][1], secondHex[0][2]); // top right
glVertex3f(firstHex[0][0], firstHex[0][1], firstHex[0][2]); // bottom right
}
glEnd();
}
glPopMatrix();
}

(I know that the {} for glBegin/glEnd and glPushMatrix/glPopMatrix are not necessary, but they do help readability in an IDE immensely)

Carmine
06-07-2013, 10:22 AM
What you have done is invaluable in learning how to program OpenGL.
You worked out the problem yourself (I assume?).
Too many people on this forum simply ask for source code to solve a problem.
They won't learn much going that route.
The next time you program up a similar problem it will be more elegant,
but this is only because you took the time to work out this solution.
Note - you will get more enthusiastic response if you put your code inside
[ code] and [ /code] tags with proper indentation. Without deviating too
much from your code, here are a few ways to make it simpler and faster.
This code has not been tested, but should be close to correct.



void drawHexagon (GLfloat center_x, GLfloat center_y, GLfloat center_z,
GLfloat size, GLfloat height, GLfloat* color)
{
int i, v;
float angle;

static int first = TRUE;
static float hexbot[6][3], hextop[6][3];

// Compute hex coordinates. Put in static array.
// Only necessary to compute hex coords first time routine is called.

if (first) {
for (i = 0; i < 6; i++) {
hexbot[i][0] = center_x + size * cos(angle);
hexbot[i][1] = center_y;
hexbot[i][2] = center_z + size * sin(angle);
hextop[i][0] = hexbot[i][0];
hextop[i][1] = hexbot[i][1] + height;
hextop[i][2] = hexbot[i][2];
}
first = FALSE;
}

// Draw 3D hexagon.

glBegin (GL_POLYGON);
for (i = 0; i < 6; i++) glVertex3f (hexbot[i]); // Bottom hexagon
glEnd();

glBegin (GL_POLYGON);
for (i = 0; i < 6; i++) glVertex3f (hextop[i]); // Top hexagon
glEnd();

glBegin (GL_QUADS); // Only one loop necessary to draw all 6 quads.
for (i = 0; i < 6; i++) {
v = (i + 1) % 6;
glVertex3f (hexbot[i][0], hexbot[i][1], hexbot[i][2]);
glVertex3f (hextop[i][0], hextop[i][1], hextop[i][2]);
glVertex3f (hextop[v][0], hextop[v][1], hextop[v][2]);
glVertex3f (hexbot[v][0], hexbot[v][1], hexbot[v][2]);
}
glEnd();
}