#include <GLFW/glfw3.h>
#ifdef __APPLE__
#include <OpenGL/glu.h>
#include <OpenGL/gl.h>
// Tell Xcode IDE to not gripe about OpenGL deprecation
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#else
#include <GL/glu.h>
#include <GL/gl.h>
#endif
#include <math.h>
#include <stdio.h>
#include "draw_steve.h"
#include "main.h"
void
draw_leg(float hipX, float hipY, float hipZ, float angle)
{
glPushMatrix();
/* ensure the leg renders "behind" the chest to prevent z fighting */
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0f, 1.0f);
glTranslatef(hipX, hipY, hipZ);
glRotatef(angle, 1.0f, 0.0f, 0.0f);
for (int row = 0; row < S_LEG_ROWS; row++)
{
Color color;
if (row < 2)
{
color = COLOR_SHOES;
}
else
{
color = COLOR_PANTS;
}
for (int col = 0; col < S_LEG_WIDTH; col++)
{
for (int d = 0; d < S_LEG_DEPTH; d++)
{
/* center the depth on the hip so the leg pivots around its middle */
float z = (d - (S_LEG_DEPTH - 1) / 2.0f) * OFFSET_UNIT;
drawCube(col * OFFSET_UNIT,
(row - (S_LEG_ROWS - 1)) * OFFSET_UNIT,
z,
SIZE_UNIT, SIZE_UNIT, SIZE_UNIT,
90.0f, color);
}
}
}
glDisable(GL_POLYGON_OFFSET_FILL);
glPopMatrix();
}
void
draw_chest(float x, float y, float z)
{
glPushMatrix();
glTranslatef(x, y, z);
for (int row = 0; row < S_CHEST_ROWS; row++)
{
int row_from_top = S_CHEST_ROWS - row;
for (int col = 0; col < S_TOROSO_WIDTH; col++)
{
int right = S_TOROSO_WIDTH - 1;
int corner = (row == 0 && col == right) ||
(row == 1 && col == right - 1) ||
(row == 1 && col == right);
int c = col + 1;
int skin = (row_from_top == 1 && c >= 3 && c <= 6) ||
(row_from_top == 2 && c >= 4 && c <= 5);
for (int d = 0; d < S_CHEST_DEPTH; d++)
{
Color color;
if (skin)
{
color = COLOR_SKIN;
}
else if (row < 2 && !(corner && d == S_LEG_DEPTH - 1))
{
color = COLOR_PANTS; /* pants */
}
else
{
color = COLOR_SHIRT; /* shirt */
}
float dz = (d - (S_CHEST_DEPTH - 1) / 2.0f) * OFFSET_UNIT;
drawCube(col * OFFSET_UNIT,
row * OFFSET_UNIT,
dz,
SIZE_UNIT, SIZE_UNIT, SIZE_UNIT,
90.0f, color);
}
}
}
glPopMatrix();
}
void
draw_arm(float x, float y, float z, float angle)
{
glPushMatrix();
glTranslatef(x, y, z);
glRotatef(angle, 1.0f, 0.0f, 0.0f);
for (int row = 0; row < S_ARM_ROWS; row++)
{
Color color;
if (row < S_ARM_SLEEVE_ROWS)
{
color = COLOR_SHIRT; /* shirt sleeve */
}
else
{
color = COLOR_SKIN; /* arm */
}
for (int col = 0; col < S_ARM_WIDTH; col++)
{
for (int d = 0; d < S_ARM_DEPTH; d++)
{
float dz = (d - (S_ARM_DEPTH - 1) / 2.0f) * OFFSET_UNIT;
drawCube(col * OFFSET_UNIT,
-row * OFFSET_UNIT, /* row 0 is the top, arm hangs down */
dz,
SIZE_UNIT, SIZE_UNIT, SIZE_UNIT,
90.0f, color);
}
}
}
glPopMatrix();
}
void
draw_head(float x, float y, float z)
{
/* no call to alloca(3) necessary if it's in .data! */
static const Color face_rows[4][S_HEAD_SIZE] = {
/* row 5: eyes */
{COLOR_SKIN, {255, 255, 255}, {82, 61, 136}, COLOR_SKIN, COLOR_SKIN, {82, 61, 136}, {255, 255, 255}, COLOR_SKIN},
/* 6: nose */
{COLOR_SKIN, COLOR_SKIN, COLOR_SKIN, {175, 98, 55}, {175, 98, 55}, COLOR_SKIN, COLOR_SKIN, COLOR_SKIN},
/* 7: mouth */
{COLOR_SKIN, COLOR_SKIN, {83, 33, 5}, COLOR_SKIN, COLOR_SKIN, {83, 33, 5}, COLOR_SKIN, COLOR_SKIN},
/* 8: mouth */
{COLOR_SKIN, COLOR_SKIN, {83, 33, 5}, {83, 33, 5}, {83, 33, 5}, {83, 33, 5}, COLOR_SKIN, COLOR_SKIN}};
glPushMatrix();
glTranslatef(x, y, z);
for (int row = 0; row < S_HEAD_SIZE; row++)
{
/* 1-based row from the top */
int r = S_HEAD_SIZE - row;
for (int col = 0; col < S_HEAD_SIZE; col++)
{
/* 1-based column from the left */
int c = col + 1;
for (int d = 0; d < S_HEAD_DEPTH; d++)
{
Color color = COLOR_SKIN;
float eps = 0.0f; /* extra offset toward the viewer for face details */
if (r <= 2 || (r == 3 && (c == 1 || c == S_HEAD_SIZE)))
{
color = COLOR_HAIR;
}
else if (d == S_HEAD_DEPTH - 1) /* front face */
{
if (r >= 5)
{
color = face_rows[r - 5][col];
eps = FACE_EPSILON;
}
}
/* d == 0 is the lowest z, so "toward the viewer" should be -z */
float dz = (d - (S_HEAD_DEPTH - 1) / 2.0f) * OFFSET_UNIT - eps;
drawCube(col * OFFSET_UNIT,
row * OFFSET_UNIT,
dz,
SIZE_UNIT, SIZE_UNIT, SIZE_UNIT,
90.0f, color);
}
}
}
glPopMatrix();
}