473 lines
15 KiB
C
473 lines
15 KiB
C
#include <math.h>
|
|
#include "cube.h"
|
|
#include "item.h"
|
|
#include "matrix.h"
|
|
#include "util.h"
|
|
|
|
void make_cube_faces(
|
|
float *data, float ao[6][4], float light[6][4],
|
|
int left, int right, int top, int bottom, int front, int back,
|
|
int wleft, int wright, int wtop, int wbottom, int wfront, int wback,
|
|
float x, float y, float z, float scale, NonCubeType noncube)
|
|
{
|
|
/*static const float positions[6][4][3] = {
|
|
{{-1, -1, -1}, {-1, -1, +1}, {-1, +1, -1}, {-1, +1, +1}},
|
|
{{+1, -1, -1}, {+1, -1, +1}, {+1, +1, -1}, {+1, +1, +1}},
|
|
{{-1, +1, -1}, {-1, +1, +1}, {+1, +1, -1}, {+1, +1, +1}},
|
|
{{-1, -1, -1}, {-1, -1, +1}, {+1, -1, -1}, {+1, -1, +1}},
|
|
{{-1, -1, -1}, {-1, +1, -1}, {+1, -1, -1}, {+1, +1, -1}},
|
|
{{-1, -1, +1}, {-1, +1, +1}, {+1, -1, +1}, {+1, +1, +1}}
|
|
};*/
|
|
static const float positions[6][4][3] = {
|
|
{{-1, -1, -1}, {-1, -1, +1}, {-1, +1, -1}, {-1, +1, +1}},
|
|
{{+1, -1, -1}, {+1, -1, +1}, {+1, +1, -1}, {+1, +1, +1}},
|
|
{{-1, +1, -1}, {-1, +1, +1}, {+1, +1, -1}, {+1, +1, +1}},
|
|
{{-1, -1, -1}, {-1, -1, +1}, {+1, -1, -1}, {+1, -1, +1}},
|
|
{{-1, -1, -1}, {-1, +1, -1}, {+1, -1, -1}, {+1, +1, -1}},
|
|
{{-1, -1, +1}, {-1, +1, +1}, {+1, -1, +1}, {+1, +1, +1}}
|
|
};
|
|
|
|
static const float normals[6][3] = {
|
|
{-1, 0, 0},
|
|
{+1, 0, 0},
|
|
{0, +1, 0},
|
|
{0, -1, 0},
|
|
{0, 0, -1},
|
|
{0, 0, +1}
|
|
};
|
|
static const float uvs[6][4][2] = {
|
|
{{0, 0}, {1, 0}, {0, 1}, {1, 1}},
|
|
{{1, 0}, {0, 0}, {1, 1}, {0, 1}},
|
|
{{0, 1}, {0, 0}, {1, 1}, {1, 0}},
|
|
{{0, 0}, {0, 1}, {1, 0}, {1, 1}},
|
|
{{0, 0}, {0, 1}, {1, 0}, {1, 1}},
|
|
{{1, 0}, {1, 1}, {0, 0}, {0, 1}}
|
|
};
|
|
static const float indices[6][6] = {
|
|
{0, 3, 2, 0, 1, 3},
|
|
{0, 3, 1, 0, 2, 3},
|
|
{0, 3, 2, 0, 1, 3},
|
|
{0, 3, 1, 0, 2, 3},
|
|
{0, 3, 2, 0, 1, 3},
|
|
{0, 3, 1, 0, 2, 3}
|
|
};
|
|
static const float flipped[6][6] = {
|
|
{0, 1, 2, 1, 3, 2},
|
|
{0, 2, 1, 2, 3, 1},
|
|
{0, 1, 2, 1, 3, 2},
|
|
{0, 2, 1, 2, 3, 1},
|
|
{0, 1, 2, 1, 3, 2},
|
|
{0, 2, 1, 2, 3, 1}
|
|
};
|
|
float *d = data;
|
|
float s = 0.0625;
|
|
float a = 0 + 1 / 2048.0;
|
|
float b = s - 1 / 2048.0;
|
|
int faces[6] = {left, right, top, bottom, front, back};
|
|
int tiles[6] = {wleft, wright, wtop, wbottom, wfront, wback};
|
|
for (int i = 0; i < 6; i++) {
|
|
if (faces[i] == 0) {
|
|
continue;
|
|
}
|
|
|
|
float du = (tiles[i] % 16) * s;
|
|
float dv = (tiles[i] / 16) * s;
|
|
int flip = ao[i][0] + ao[i][3] > ao[i][1] + ao[i][2];
|
|
float y_multiplier = (noncube == NonCubeType_SLAB_LOWER) ? 0.0f : 1.0f;
|
|
for (int v = 0; v < 6; v++) {
|
|
int j = flip ? flipped[i][v] : indices[i][v];
|
|
*(d++) = x + scale * positions[i][j][0];
|
|
//The origin of the cube is its center.
|
|
//If we are rendering a slab, the top vertices of the cube are not multiplied by the offsets,
|
|
// so that the top of the slab is the origin, at the center. This makes slabs half-height.
|
|
|
|
//Only the vertices on the top should be 0, or the slab would be a paperlike
|
|
// horizontal billboard. If the y position is positive, we are above the XZ plane of the
|
|
// cube and are about to determine the top vertices.
|
|
if (noncube == NonCubeType_SLAB_LOWER && positions[i][j][1] > 0) {
|
|
*(d++) = y;
|
|
}
|
|
else {
|
|
*(d++) = y + scale * positions[i][j][1];
|
|
}
|
|
|
|
*(d++) = z + scale * positions[i][j][2];
|
|
*(d++) = normals[i][0];
|
|
*(d++) = normals[i][1];
|
|
*(d++) = normals[i][2];
|
|
*(d++) = du + (uvs[i][j][0] ? b : a);
|
|
|
|
//If we have have a slab, are rendering the top vertices, and are on the side --
|
|
// (i == 2) and (i == 3) are for the top and bottom, see faces and tiles arrays above --
|
|
// we must subtract half a texture tile to only use the lower half of the texture.
|
|
// Otherwise, the texture of a full block will be sqeezed onto the slab.
|
|
if (positions[i][j][1] > 0 && i != 2 && i != 3 && noncube == NonCubeType_SLAB_LOWER) {
|
|
*(d++) = (dv - (1.0f / 32.0f)) + (uvs[i][j][1] ? b : a);
|
|
}
|
|
else {
|
|
*(d++) = dv + (uvs[i][j][1] ? b : a);
|
|
}
|
|
|
|
*(d++) = ao[i][j];
|
|
*(d++) = light[i][j];
|
|
}
|
|
}
|
|
}
|
|
|
|
void make_cube(
|
|
float *data, float ao[6][4], float light[6][4],
|
|
int left, int right, int top, int bottom, int front, int back,
|
|
float x, float y, float z, float n, int w)
|
|
{
|
|
int wleft = blocks[w][0];
|
|
int wright = blocks[w][1];
|
|
int wtop = blocks[w][2];
|
|
int wbottom = blocks[w][3];
|
|
int wfront = blocks[w][4];
|
|
int wback = blocks[w][5];
|
|
|
|
make_cube_faces(
|
|
data, ao, light,
|
|
left, right, top, bottom, front, back,
|
|
wleft, wright, wtop, wbottom, wfront, wback,
|
|
//left, right, top, bottom, front, back,
|
|
x, y, z, n, noncube_type(w));
|
|
}
|
|
|
|
void make_plant(
|
|
float *data, float ao, float light,
|
|
float px, float py, float pz, float n, int w, float rotation)
|
|
{
|
|
static const float positions[4][4][3] = {
|
|
{{ 0, -1, -1}, { 0, -1, +1}, { 0, +1, -1}, { 0, +1, +1}},
|
|
{{ 0, -1, -1}, { 0, -1, +1}, { 0, +1, -1}, { 0, +1, +1}},
|
|
{{-1, -1, 0}, {-1, +1, 0}, {+1, -1, 0}, {+1, +1, 0}},
|
|
{{-1, -1, 0}, {-1, +1, 0}, {+1, -1, 0}, {+1, +1, 0}}
|
|
};
|
|
static const float normals[4][3] = {
|
|
{-1, 0, 0},
|
|
{+1, 0, 0},
|
|
{0, 0, -1},
|
|
{0, 0, +1}
|
|
};
|
|
static const float uvs[4][4][2] = {
|
|
{{0, 0}, {1, 0}, {0, 1}, {1, 1}},
|
|
{{1, 0}, {0, 0}, {1, 1}, {0, 1}},
|
|
{{0, 0}, {0, 1}, {1, 0}, {1, 1}},
|
|
{{1, 0}, {1, 1}, {0, 0}, {0, 1}}
|
|
};
|
|
static const float indices[4][6] = {
|
|
{0, 3, 2, 0, 1, 3},
|
|
{0, 3, 1, 0, 2, 3},
|
|
{0, 3, 2, 0, 1, 3},
|
|
{0, 3, 1, 0, 2, 3}
|
|
};
|
|
float *d = data;
|
|
float s = 0.0625;
|
|
float a = 0;
|
|
float b = s;
|
|
float du = (plants[w] % 16) * s;
|
|
float dv = (plants[w] / 16) * s;
|
|
for (int i = 0; i < 4; i++) {
|
|
for (int v = 0; v < 6; v++) {
|
|
int j = indices[i][v];
|
|
*(d++) = n * positions[i][j][0];
|
|
*(d++) = n * positions[i][j][1];
|
|
*(d++) = n * positions[i][j][2];
|
|
*(d++) = normals[i][0];
|
|
*(d++) = normals[i][1];
|
|
*(d++) = normals[i][2];
|
|
*(d++) = du + (uvs[i][j][0] ? b : a);
|
|
*(d++) = dv + (uvs[i][j][1] ? b : a);
|
|
*(d++) = ao;
|
|
*(d++) = light;
|
|
}
|
|
}
|
|
float ma[16];
|
|
float mb[16];
|
|
mat_identity(ma);
|
|
mat_rotate(mb, 0, 1, 0, RADIANS(rotation));
|
|
mat_multiply(ma, mb, ma);
|
|
mat_apply(data, ma, 24, 3, 10);
|
|
mat_translate(mb, px, py, pz);
|
|
mat_multiply(ma, mb, ma);
|
|
mat_apply(data, ma, 24, 0, 10);
|
|
}
|
|
|
|
// Player model
|
|
void make_player(
|
|
float *data,
|
|
float x, float y, float z, float rx, float ry)
|
|
{
|
|
float ao[6][4] = {0};
|
|
float light[6][4] = {
|
|
{0.8, 0.8, 0.8, 0.8},
|
|
{0.8, 0.8, 0.8, 0.8},
|
|
{0.8, 0.8, 0.8, 0.8},
|
|
{0.8, 0.8, 0.8, 0.8},
|
|
{0.8, 0.8, 0.8, 0.8},
|
|
{0.8, 0.8, 0.8, 0.8}
|
|
};
|
|
make_cube_faces(
|
|
data, ao, light,
|
|
1, 1, 1, 1, 1, 1,
|
|
226, 224, 241, 209, 225, 227,
|
|
0, 0, 0, 0.4, NonCubeType_NOT_NONCUBE);
|
|
float ma[16];
|
|
float mb[16];
|
|
mat_identity(ma);
|
|
mat_rotate(mb, 0, 1, 0, rx);
|
|
mat_multiply(ma, mb, ma);
|
|
mat_rotate(mb, cosf(rx), 0, sinf(rx), -ry);
|
|
mat_multiply(ma, mb, ma);
|
|
mat_apply(data, ma, 36, 3, 10);
|
|
mat_translate(mb, x, y, z);
|
|
mat_multiply(ma, mb, ma);
|
|
mat_apply(data, ma, 36, 0, 10);
|
|
}
|
|
|
|
void make_cube_wireframe(float *data, float x, float y, float z, float n) {
|
|
static const float positions[8][3] = {
|
|
{-1, -1, -1},
|
|
{-1, -1, +1},
|
|
{-1, +1, -1},
|
|
{-1, +1, +1},
|
|
{+1, -1, -1},
|
|
{+1, -1, +1},
|
|
{+1, +1, -1},
|
|
{+1, +1, +1}
|
|
};
|
|
static const int indices[24] = {
|
|
0, 1, 0, 2, 0, 4, 1, 3,
|
|
1, 5, 2, 3, 2, 6, 3, 7,
|
|
4, 5, 4, 6, 5, 7, 6, 7
|
|
};
|
|
float *d = data;
|
|
for (int i = 0; i < 24; i++) {
|
|
int j = indices[i];
|
|
*(d++) = x + n * positions[j][0];
|
|
*(d++) = y + n * positions[j][1];
|
|
*(d++) = z + n * positions[j][2];
|
|
}
|
|
}
|
|
|
|
void make_character(
|
|
float *data,
|
|
float x, float y, float n, float m, char c)
|
|
{
|
|
float *d = data;
|
|
float s = 0.0625;
|
|
float a = s;
|
|
float b = s * 2;
|
|
int w = c - 32;
|
|
float du = (w % 16) * a;
|
|
float dv = 1 - (w / 16) * b - b;
|
|
*(d++) = x - n; *(d++) = y - m;
|
|
*(d++) = du + 0; *(d++) = dv;
|
|
*(d++) = x + n; *(d++) = y - m;
|
|
*(d++) = du + a; *(d++) = dv;
|
|
*(d++) = x + n; *(d++) = y + m;
|
|
*(d++) = du + a; *(d++) = dv + b;
|
|
*(d++) = x - n; *(d++) = y - m;
|
|
*(d++) = du + 0; *(d++) = dv;
|
|
*(d++) = x + n; *(d++) = y + m;
|
|
*(d++) = du + a; *(d++) = dv + b;
|
|
*(d++) = x - n; *(d++) = y + m;
|
|
*(d++) = du + 0; *(d++) = dv + b;
|
|
}
|
|
|
|
void make_ui_quad(
|
|
float *data,
|
|
float x, float y, float n, float m, char spritesheet_index)
|
|
{
|
|
float *d = data;
|
|
float s = 0.0625;
|
|
float a = s;
|
|
float b = s;
|
|
int w = spritesheet_index - 32;
|
|
float du = (w % 16) * a;
|
|
float dv = 1 - (w / 16) * b - b;
|
|
*(d++) = x - n; *(d++) = y - m;
|
|
*(d++) = du + 0; *(d++) = dv;
|
|
*(d++) = x + n; *(d++) = y - m;
|
|
*(d++) = du + a; *(d++) = dv;
|
|
*(d++) = x + n; *(d++) = y + m;
|
|
*(d++) = du + a; *(d++) = dv + b;
|
|
*(d++) = x - n; *(d++) = y - m;
|
|
*(d++) = du + 0; *(d++) = dv;
|
|
*(d++) = x + n; *(d++) = y + m;
|
|
*(d++) = du + a; *(d++) = dv + b;
|
|
*(d++) = x - n; *(d++) = y + m;
|
|
*(d++) = du + 0; *(d++) = dv + b;
|
|
}
|
|
|
|
void make_logo_quad(
|
|
float *data,
|
|
float x, float y, float n, float m, char spritesheet_index)
|
|
{
|
|
float *d = data;
|
|
float s = 0.0625*16; // changes the size of pixel array
|
|
float a = s;
|
|
float b = s;
|
|
int w = spritesheet_index - 32;
|
|
float du = (w % 16) * a;
|
|
float dv = 1 - (w / 16) * b - b;
|
|
*(d++) = x - n; *(d++) = y - m;
|
|
*(d++) = du + 0; *(d++) = dv;
|
|
*(d++) = x + n; *(d++) = y - m;
|
|
*(d++) = du + a; *(d++) = dv;
|
|
*(d++) = x + n; *(d++) = y + m;
|
|
*(d++) = du + a; *(d++) = dv + b;
|
|
*(d++) = x - n; *(d++) = y - m;
|
|
*(d++) = du + 0; *(d++) = dv;
|
|
*(d++) = x + n; *(d++) = y + m;
|
|
*(d++) = du + a; *(d++) = dv + b;
|
|
*(d++) = x - n; *(d++) = y + m;
|
|
*(d++) = du + 0; *(d++) = dv + b;
|
|
}
|
|
|
|
void make_character_3d(
|
|
float *data, float x, float y, float z, float n, int face, char c)
|
|
{
|
|
static const float positions[8][6][3] = {
|
|
{{0, -2, -1}, {0, +2, +1}, {0, +2, -1},
|
|
{0, -2, -1}, {0, -2, +1}, {0, +2, +1}},
|
|
{{0, -2, -1}, {0, +2, +1}, {0, -2, +1},
|
|
{0, -2, -1}, {0, +2, -1}, {0, +2, +1}},
|
|
{{-1, -2, 0}, {+1, +2, 0}, {+1, -2, 0},
|
|
{-1, -2, 0}, {-1, +2, 0}, {+1, +2, 0}},
|
|
{{-1, -2, 0}, {+1, -2, 0}, {+1, +2, 0},
|
|
{-1, -2, 0}, {+1, +2, 0}, {-1, +2, 0}},
|
|
{{-1, 0, +2}, {+1, 0, +2}, {+1, 0, -2},
|
|
{-1, 0, +2}, {+1, 0, -2}, {-1, 0, -2}},
|
|
{{-2, 0, +1}, {+2, 0, -1}, {-2, 0, -1},
|
|
{-2, 0, +1}, {+2, 0, +1}, {+2, 0, -1}},
|
|
{{+1, 0, +2}, {-1, 0, -2}, {-1, 0, +2},
|
|
{+1, 0, +2}, {+1, 0, -2}, {-1, 0, -2}},
|
|
{{+2, 0, -1}, {-2, 0, +1}, {+2, 0, +1},
|
|
{+2, 0, -1}, {-2, 0, -1}, {-2, 0, +1}}
|
|
};
|
|
static const float uvs[8][6][2] = {
|
|
{{0, 0}, {1, 1}, {0, 1}, {0, 0}, {1, 0}, {1, 1}},
|
|
{{1, 0}, {0, 1}, {0, 0}, {1, 0}, {1, 1}, {0, 1}},
|
|
{{1, 0}, {0, 1}, {0, 0}, {1, 0}, {1, 1}, {0, 1}},
|
|
{{0, 0}, {1, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 1}},
|
|
{{0, 0}, {1, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 1}},
|
|
{{0, 1}, {1, 0}, {1, 1}, {0, 1}, {0, 0}, {1, 0}},
|
|
{{0, 1}, {1, 0}, {1, 1}, {0, 1}, {0, 0}, {1, 0}},
|
|
{{0, 1}, {1, 0}, {1, 1}, {0, 1}, {0, 0}, {1, 0}}
|
|
};
|
|
static const float offsets[8][3] = {
|
|
{-1, 0, 0}, {+1, 0, 0}, {0, 0, -1}, {0, 0, +1},
|
|
{0, +1, 0}, {0, +1, 0}, {0, +1, 0}, {0, +1, 0},
|
|
};
|
|
float *d = data;
|
|
float s = 0.0625;
|
|
float pu = s / 5;
|
|
float pv = s / 2.5;
|
|
float u1 = pu;
|
|
float v1 = pv;
|
|
float u2 = s - pu;
|
|
float v2 = s * 2 - pv;
|
|
float p = 0.5;
|
|
int w = c - 32;
|
|
float du = (w % 16) * s;
|
|
float dv = 1 - (w / 16 + 1) * s * 2;
|
|
x += p * offsets[face][0];
|
|
y += p * offsets[face][1];
|
|
z += p * offsets[face][2];
|
|
for (int i = 0; i < 6; i++) {
|
|
*(d++) = x + n * positions[face][i][0];
|
|
*(d++) = y + n * positions[face][i][1];
|
|
*(d++) = z + n * positions[face][i][2];
|
|
*(d++) = du + (uvs[face][i][0] ? u2 : u1);
|
|
*(d++) = dv + (uvs[face][i][1] ? v2 : v1);
|
|
}
|
|
}
|
|
|
|
int _make_sphere(
|
|
float *data, float r, int detail,
|
|
float *a, float *b, float *c,
|
|
float *ta, float *tb, float *tc)
|
|
{
|
|
if (detail == 0) {
|
|
float *d = data;
|
|
*(d++) = a[0] * r; *(d++) = a[1] * r; *(d++) = a[2] * r;
|
|
*(d++) = a[0]; *(d++) = a[1]; *(d++) = a[2];
|
|
*(d++) = ta[0]; *(d++) = ta[1];
|
|
*(d++) = b[0] * r; *(d++) = b[1] * r; *(d++) = b[2] * r;
|
|
*(d++) = b[0]; *(d++) = b[1]; *(d++) = b[2];
|
|
*(d++) = tb[0]; *(d++) = tb[1];
|
|
*(d++) = c[0] * r; *(d++) = c[1] * r; *(d++) = c[2] * r;
|
|
*(d++) = c[0]; *(d++) = c[1]; *(d++) = c[2];
|
|
*(d++) = tc[0]; *(d++) = tc[1];
|
|
return 1;
|
|
}
|
|
else {
|
|
float ab[3], ac[3], bc[3];
|
|
for (int i = 0; i < 3; i++) {
|
|
ab[i] = (a[i] + b[i]) / 2;
|
|
ac[i] = (a[i] + c[i]) / 2;
|
|
bc[i] = (b[i] + c[i]) / 2;
|
|
}
|
|
normalize(ab + 0, ab + 1, ab + 2);
|
|
normalize(ac + 0, ac + 1, ac + 2);
|
|
normalize(bc + 0, bc + 1, bc + 2);
|
|
float tab[2], tac[2], tbc[2];
|
|
tab[0] = 0; tab[1] = 1 - acosf(ab[1]) / PI;
|
|
tac[0] = 0; tac[1] = 1 - acosf(ac[1]) / PI;
|
|
tbc[0] = 0; tbc[1] = 1 - acosf(bc[1]) / PI;
|
|
int total = 0;
|
|
int n;
|
|
n = _make_sphere(data, r, detail - 1, a, ab, ac, ta, tab, tac);
|
|
total += n; data += n * 24;
|
|
n = _make_sphere(data, r, detail - 1, b, bc, ab, tb, tbc, tab);
|
|
total += n; data += n * 24;
|
|
n = _make_sphere(data, r, detail - 1, c, ac, bc, tc, tac, tbc);
|
|
total += n; data += n * 24;
|
|
n = _make_sphere(data, r, detail - 1, ab, bc, ac, tab, tbc, tac);
|
|
total += n; data += n * 24;
|
|
return total;
|
|
}
|
|
}
|
|
|
|
void make_sphere(float *data, float r, int detail) {
|
|
// detail, triangles, floats
|
|
// 0, 8, 192
|
|
// 1, 32, 768
|
|
// 2, 128, 3072
|
|
// 3, 512, 12288
|
|
// 4, 2048, 49152
|
|
// 5, 8192, 196608
|
|
// 6, 32768, 786432
|
|
// 7, 131072, 3145728
|
|
static int indices[8][3] = {
|
|
{4, 3, 0}, {1, 4, 0},
|
|
{3, 4, 5}, {4, 1, 5},
|
|
{0, 3, 2}, {0, 2, 1},
|
|
{5, 2, 3}, {5, 1, 2}
|
|
};
|
|
static float positions[6][3] = {
|
|
{ 0, 0,-1}, { 1, 0, 0},
|
|
{ 0,-1, 0}, {-1, 0, 0},
|
|
{ 0, 1, 0}, { 0, 0, 1}
|
|
};
|
|
static float uvs[6][3] = {
|
|
{0, 0.5}, {0, 0.5},
|
|
{0, 0}, {0, 0.5},
|
|
{0, 1}, {0, 0.5}
|
|
};
|
|
int total = 0;
|
|
for (int i = 0; i < 8; i++) {
|
|
int n = _make_sphere(
|
|
data, r, detail,
|
|
positions[indices[i][0]],
|
|
positions[indices[i][1]],
|
|
positions[indices[i][2]],
|
|
uvs[indices[i][0]],
|
|
uvs[indices[i][1]],
|
|
uvs[indices[i][2]]);
|
|
total += n; data += n * 24;
|
|
}
|
|
}
|