#include "mesh.h"
#include "3dgfx.h"
+void free_mesh(struct g3d_mesh *mesh)
+{
+ destroy_mesh(mesh);
+ free(mesh);
+}
+
+void destroy_mesh(struct g3d_mesh *mesh)
+{
+ free(mesh->varr);
+ free(mesh->iarr);
+}
+
+int copy_mesh(struct g3d_mesh *dest, struct g3d_mesh *src)
+{
+ dest->prim = src->prim;
+ if(src->varr) {
+ if(!(dest->varr = malloc(src->vcount * sizeof *src->varr))) {
+ return -1;
+ }
+ memcpy(dest->varr, src->varr, src->vcount * sizeof *src->varr);
+ }
+ dest->vcount = src->vcount;
+ if(src->iarr) {
+ if(!(dest->iarr = malloc(src->icount * sizeof *src->iarr))) {
+ free(dest->varr);
+ dest->varr = 0;
+ return -1;
+ }
+ memcpy(dest->iarr, src->iarr, src->icount * sizeof *src->iarr);
+ }
+ dest->icount = src->icount;
+ return 0;
+}
+
static struct {
+ int prim;
struct g3d_vertex *varr;
const float *xform;
} zsort_cls;
static int zsort_cmp(const void *aptr, const void *bptr)
{
+ int i;
+ float za = 0.0f;
+ float zb = 0.0f;
const float *m = zsort_cls.xform;
-
const struct g3d_vertex *va = (const struct g3d_vertex*)aptr;
const struct g3d_vertex *vb = (const struct g3d_vertex*)bptr;
- float za = m[2] * va->x + m[6] * va->y + m[10] * va->z + m[14];
- float zb = m[2] * vb->x + m[6] * vb->y + m[10] * vb->z + m[14];
-
- ++va;
- ++vb;
-
- za += m[2] * va->x + m[6] * va->y + m[10] * va->z + m[14];
- zb += m[2] * vb->x + m[6] * vb->y + m[10] * vb->z + m[14];
-
+ for(i=0; i<zsort_cls.prim; i++) {
+ za += m[2] * va->x + m[6] * va->y + m[10] * va->z + m[14];
+ zb += m[2] * vb->x + m[6] * vb->y + m[10] * vb->z + m[14];
+ ++va;
+ ++vb;
+ }
return za - zb;
}
static int zsort_indexed_cmp(const void *aptr, const void *bptr)
{
- const int16_t *a = (const int16_t*)aptr;
- const int16_t *b = (const int16_t*)bptr;
+ int i;
+ float za = 0.0f;
+ float zb = 0.0f;
+ const uint16_t *a = (const uint16_t*)aptr;
+ const uint16_t *b = (const uint16_t*)bptr;
const float *m = zsort_cls.xform;
- const struct g3d_vertex *va = zsort_cls.varr + a[0];
- const struct g3d_vertex *vb = zsort_cls.varr + b[0];
-
- float za = m[2] * va->x + m[6] * va->y + m[10] * va->z + m[14];
- float zb = m[2] * vb->x + m[6] * vb->y + m[10] * vb->z + m[14];
-
- va = zsort_cls.varr + a[2];
- vb = zsort_cls.varr + b[2];
-
- za += m[2] * va->x + m[6] * va->y + m[10] * va->z + m[14];
- zb += m[2] * vb->x + m[6] * vb->y + m[10] * vb->z + m[14];
+ for(i=0; i<zsort_cls.prim; i++) {
+ const struct g3d_vertex *va = zsort_cls.varr + a[i];
+ const struct g3d_vertex *vb = zsort_cls.varr + b[i];
+ za += m[2] * va->x + m[6] * va->y + m[10] * va->z + m[14];
+ zb += m[2] * vb->x + m[6] * vb->y + m[10] * vb->z + m[14];
+ }
return za - zb;
}
{
zsort_cls.varr = m->varr;
zsort_cls.xform = g3d_get_matrix(G3D_MODELVIEW, 0);
+ zsort_cls.prim = m->prim;
if(m->iarr) {
int nfaces = m->icount / m->prim;
{
int i, new_vcount, new_icount;
void *tmp;
- int16_t *iptr;
+ uint16_t *iptr;
if(ma->prim != mb->prim) {
fprintf(stderr, "append_mesh failed, primitive mismatch\n");
int i, j, nfaces, max_icount, idx;
int out_vcount = 0;
struct g3d_vertex *vin, *vout;
- int16_t *iout;
+ uint16_t *iout;
if(mesh->iarr) {
fprintf(stderr, "indexify_mesh failed: already indexed\n");
return 0;
}
+void normalize_mesh_normals(struct g3d_mesh *mesh)
+{
+ int i;
+ struct g3d_vertex *v = mesh->varr;
+
+ for(i=0; i<mesh->vcount; i++) {
+ float mag = sqrt(v->nx * v->nx + v->ny * v->ny + v->nz * v->nz);
+ float s = (mag == 0.0f) ? 1.0f : 1.0f / mag;
+ v->nx *= s;
+ v->ny *= s;
+ v->nz *= s;
+ ++v;
+ }
+}
+
+
+static void sphvec(float *res, float theta, float phi, float rad)
+{
+ theta = -theta;
+ res[0] = sin(theta) * sin(phi);
+ res[1] = cos(phi);
+ res[2] = cos(theta) * sin(phi);
+}
+
+int gen_sphere_mesh(struct g3d_mesh *mesh, float rad, int usub, int vsub)
+{
+ int i, j;
+ int nfaces, uverts, vverts;
+ struct g3d_vertex *vptr;
+ uint16_t *iptr;
+
+ mesh->prim = G3D_QUADS;
+
+ if(usub < 4) usub = 4;
+ if(vsub < 2) vsub = 2;
+
+ uverts = usub + 1;
+ vverts = vsub + 1;
+
+ mesh->vcount = uverts * vverts;
+ nfaces = usub * vsub;
+ mesh->icount = nfaces * 4;
+
+ if(!(mesh->varr = malloc(mesh->vcount * sizeof *mesh->varr))) {
+ fprintf(stderr, "gen_sphere_mesh: failed to allocate vertex buffer (%d vertices)\n", mesh->vcount);
+ return -1;
+ }
+ if(!(mesh->iarr = malloc(mesh->icount * sizeof *mesh->iarr))) {
+ fprintf(stderr, "gen_sphere_mesh: failed to allocate index buffer (%d indices)\n", mesh->icount);
+ return -1;
+ }
+ vptr = mesh->varr;
+ iptr = mesh->iarr;
+
+ for(i=0; i<uverts; i++) {
+ float u = (float)i / (float)(uverts - 1);
+ float theta = u * 2.0 * M_PI;
+
+ for(j=0; j<vverts; j++) {
+ float v = (float)j / (float)(vverts - 1);
+ float phi = v * M_PI;
+ int chess = (i & 1) == (j & 1);
+
+ sphvec(&vptr->x, theta, phi, rad);
+ vptr->w = 1.0f;
+
+ vptr->nx = vptr->x / rad;
+ vptr->ny = vptr->y / rad;
+ vptr->nz = vptr->z / rad;
+ vptr->u = u;
+ vptr->v = v;
+ vptr->r = chess ? 255 : 64;
+ vptr->g = 128;
+ vptr->b = chess ? 64 : 255;
+ ++vptr;
+
+ if(i < usub && j < vsub) {
+ int idx = i * vverts + j;
+ *iptr++ = idx;
+ *iptr++ = idx + 1;
+ *iptr++ = idx + vverts + 1;
+ *iptr++ = idx + vverts;
+ }
+ }
+ }
+ return 0;
+}
+
int gen_plane_mesh(struct g3d_mesh *m, float width, float height, int usub, int vsub)
{
int i, j;
int nfaces, nverts, nidx, uverts, vverts;
float x, y, u, v, du, dv;
struct g3d_vertex *vptr;
- int16_t *iptr;
+ uint16_t *iptr;
if(usub < 1) usub = 1;
if(vsub < 1) vsub = 1;
int i;
struct g3d_mesh *m;
struct g3d_mesh tmpmesh;
- float xform[16];
static float rotface[][4] = {
{0, 0, 1, 0},
{90, 0, 1, 0},
g3d_load_identity();
g3d_rotate(rotface[i][0], rotface[i][1], rotface[i][2], rotface[i][3]);
g3d_translate(0, 0, sz / 2.0f);
- g3d_get_matrix(G3D_MODELVIEW, xform);
- apply_mesh_xform(m, xform);
+ apply_mesh_xform(m, g3d_get_matrix(G3D_MODELVIEW, 0));
if(i > 0) {
if(append_mesh(mesh, m) == -1) {
return -1;
int i, j;
int nfaces, uverts, vverts;
struct g3d_vertex *vptr;
- int16_t *iptr;
+ uint16_t *iptr;
mesh->prim = G3D_QUADS;
int chess = (i & 1) == (j & 1);
torusvec(&vptr->x, theta, phi, rad, ringrad);
+ vptr->w = 1.0f;
vptr->nx = (vptr->x - rcent[0]) / ringrad;
vptr->ny = (vptr->y - rcent[1]) / ringrad;