From: John Tsiombikas Date: Sat, 17 Feb 2018 08:08:42 +0000 (+0200) Subject: envmap, fake phong texture generation, and more X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=commitdiff_plain;h=1883deae4194ed84395bfb1102555b803a4f28e2 envmap, fake phong texture generation, and more --- diff --git a/src/3dgfx.c b/src/3dgfx.c index 673122d..3999747 100644 --- a/src/3dgfx.c +++ b/src/3dgfx.c @@ -396,7 +396,7 @@ void g3d_draw(int prim, const struct g3d_vertex *varr, int varr_size) } void g3d_draw_indexed(int prim, const struct g3d_vertex *varr, int varr_size, - const int16_t *iarr, int iarr_size) + const uint16_t *iarr, int iarr_size) { int i, j, nfaces; struct pvertex pv[16]; @@ -423,6 +423,10 @@ void g3d_draw_indexed(int prim, const struct g3d_vertex *varr, int varr_size, if(st->opt & G3D_LIGHTING) { shade(v + i); } + if(st->opt & G3D_TEXTURE_GEN) { + v[i].u = v[i].nx * 0.5 + 0.5; + v[i].v = v[i].ny * 0.5 + 0.5; + } xform4_vec3(st->mat[G3D_PROJECTION][ptop], &v[i].x); } diff --git a/src/3dgfx.h b/src/3dgfx.h index 94884ca..fd7f625 100644 --- a/src/3dgfx.h +++ b/src/3dgfx.h @@ -28,6 +28,7 @@ enum { G3D_LIGHT3 = 0x0040, G3D_TEXTURE = 0x0080, G3D_BLEND = 0x0100, + G3D_TEXTURE_GEN = 0x0200, G3D_ALL = 0x7fffffff }; @@ -96,7 +97,7 @@ void g3d_set_texture(int xsz, int ysz, void *pixels); void g3d_draw(int prim, const struct g3d_vertex *varr, int varr_size); void g3d_draw_indexed(int prim, const struct g3d_vertex *varr, int varr_size, - const int16_t *iarr, int iarr_size); + const uint16_t *iarr, int iarr_size); void g3d_begin(int prim); void g3d_end(void); diff --git a/src/infcubes.c b/src/infcubes.c index 36225f9..6ce74af 100644 --- a/src/infcubes.c +++ b/src/infcubes.c @@ -1,4 +1,5 @@ #include +#include #include #include #include "demo.h" @@ -14,7 +15,8 @@ static int init(void); static void destroy(void); static void start(long trans_time); static void draw(void); -static void draw_cube(float sz); +static int gen_phong_tex(struct pimage *img, int xsz, int ysz, float sexp, + int dr, int dg, int db, int sr, int sg, int sb); static struct screen scr = { "infcubes", @@ -25,31 +27,37 @@ static struct screen scr = { }; static float cam_theta = -29, cam_phi = 35; -static float cam_dist = 5; +static float cam_dist = 6; static struct pimage tex_inner, tex_outer; -static struct g3d_mesh mesh_cube; +static struct g3d_mesh mesh_cube, mesh_cube2; struct screen *infcubes_screen(void) { return &scr; } +#define PHONG_TEX_SZ 128 static int init(void) { + static const float scalemat[16] = {-6, 0, 0, 0, 0, -6, 0, 0, 0, 0, -6, 0, 0, 0, 0, 1}; + /* if(!(tex_inner.pixels = img_load_pixels("data/crate.jpg", &tex_inner.width, &tex_inner.height, IMG_FMT_RGB24))) { fprintf(stderr, "infcubes: failed to load crate texture\n"); return -1; } convimg_rgb24_rgb16(tex_inner.pixels, (unsigned char*)tex_inner.pixels, tex_inner.width, tex_inner.height); + */ + gen_phong_tex(&tex_inner, PHONG_TEX_SZ, PHONG_TEX_SZ, 5.0f, 10, 50, 92, 192, 192, 192); - if(!(tex_outer.pixels = img_load_pixels("data/steelfrm.jpg", &tex_outer.width, + if(!(tex_outer.pixels = img_load_pixels("data/refmap1.jpg", &tex_outer.width, &tex_outer.height, IMG_FMT_RGB24))) { - fprintf(stderr, "infcubes: failed to load ornamental texture\n"); + fprintf(stderr, "infcubes: failed to load outer texture\n"); return -1; } convimg_rgb24_rgb16(tex_outer.pixels, (unsigned char*)tex_outer.pixels, tex_outer.width, tex_outer.height); + /*gen_phong_tex(&tex_outer, PHONG_TEX_SZ, PHONG_TEX_SZ, 5.0f, 50, 50, 50, 255, 255, 255);*/ /* if(gen_cube_mesh(&mesh_cube, 1.0f, 3) == -1) { @@ -59,6 +67,11 @@ static int init(void) if(load_mesh(&mesh_cube, "data/bevelbox.obj") == -1) { return -1; } + if(load_mesh(&mesh_cube2, "data/bevelbox.obj") == -1) { + return -1; + } + apply_mesh_xform(&mesh_cube2, scalemat); + normalize_mesh_normals(&mesh_cube2); return 0; } @@ -71,7 +84,7 @@ static void start(long trans_time) { g3d_matrix_mode(G3D_PROJECTION); g3d_load_identity(); - g3d_perspective(50.0, 1.3333333, 0.5, 100.0); + g3d_perspective(70.0, 1.3333333, 0.5, 100.0); g3d_enable(G3D_CULL_FACE); g3d_disable(G3D_LIGHTING); @@ -85,6 +98,7 @@ static void update(void) static void draw(void) { + float t = (float)time_msec / 16.0f; update(); g3d_matrix_mode(G3D_MODELVIEW); @@ -99,15 +113,61 @@ static void draw(void) memset(fb_pixels, 0, fb_width * fb_height * 2); g3d_polygon_mode(G3D_TEX); + g3d_enable(G3D_TEXTURE_GEN); g3d_push_matrix(); - g3d_scale(-6, -6, -6); + g3d_rotate(t, 1, 0, 0); + g3d_rotate(t, 0, 1, 0); g3d_set_texture(tex_outer.width, tex_outer.height, tex_outer.pixels); - draw_mesh(&mesh_cube); + draw_mesh(&mesh_cube2); g3d_pop_matrix(); g3d_set_texture(tex_inner.width, tex_inner.height, tex_inner.pixels); draw_mesh(&mesh_cube); + g3d_disable(G3D_TEXTURE_GEN); swap_buffers(fb_pixels); } + +static int gen_phong_tex(struct pimage *img, int xsz, int ysz, float sexp, + int dr, int dg, int db, int sr, int sg, int sb) +{ + int i, j; + float u, v, du, dv; + uint16_t *pix; + + if(!(img->pixels = malloc(xsz * ysz * sizeof *pix))) { + return -1; + } + pix = img->pixels; + + du = 2.0f / (float)(xsz - 1); + dv = 2.0f / (float)(ysz - 1); + + v = -1.0f; + for(i=0; i 255) r = 255; + if(g > 255) g = 255; + if(b > 255) b = 255; + + *pix++ = PACK_RGB16(r, g, b); + + u += du; + } + v += dv; + } + + img->width = xsz; + img->height = ysz; + return 0; +} diff --git a/src/mesh.c b/src/mesh.c index c4c8a87..bde8266 100644 --- a/src/mesh.c +++ b/src/mesh.c @@ -31,8 +31,8 @@ static int zsort_cmp(const void *aptr, const void *bptr) 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; + const uint16_t *a = (const uint16_t*)aptr; + const uint16_t *b = (const uint16_t*)bptr; const float *m = zsort_cls.xform; @@ -100,7 +100,7 @@ int append_mesh(struct g3d_mesh *ma, struct g3d_mesh *mb) { 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"); @@ -173,7 +173,7 @@ int indexify_mesh(struct g3d_mesh *mesh) 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"); @@ -209,13 +209,28 @@ int indexify_mesh(struct g3d_mesh *mesh) return 0; } +void normalize_mesh_normals(struct g3d_mesh *mesh) +{ + int i; + struct g3d_vertex *v = mesh->varr; + + for(i=0; ivcount; 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; + } +} + 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; @@ -341,7 +356,7 @@ int gen_torus_mesh(struct g3d_mesh *mesh, float rad, float ringrad, int usub, in int i, j; int nfaces, uverts, vverts; struct g3d_vertex *vptr; - int16_t *iptr; + uint16_t *iptr; mesh->prim = G3D_QUADS; diff --git a/src/mesh.h b/src/mesh.h index 704c492..eb0256d 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -6,11 +6,12 @@ struct g3d_mesh { int prim; struct g3d_vertex *varr; - int16_t *iarr; + uint16_t *iarr; int vcount, icount; }; int load_mesh(struct g3d_mesh *mesh, const char *fname); +int save_mesh(struct g3d_mesh *mesh, const char *fname); void zsort_mesh(struct g3d_mesh *mesh); void draw_mesh(struct g3d_mesh *mesh); @@ -19,6 +20,8 @@ void apply_mesh_xform(struct g3d_mesh *mesh, const float *xform); int append_mesh(struct g3d_mesh *ma, struct g3d_mesh *mb); int indexify_mesh(struct g3d_mesh *mesh); +void normalize_mesh_normals(struct g3d_mesh *mesh); + int gen_plane_mesh(struct g3d_mesh *mesh, float width, float height, int usub, int vsub); int gen_cube_mesh(struct g3d_mesh *mesh, float sz, int sub); int gen_torus_mesh(struct g3d_mesh *mesh, float rad, float ringrad, int usub, int vsub); diff --git a/src/meshload.c b/src/meshload.c index 61cf128..7e3bd29 100644 --- a/src/meshload.c +++ b/src/meshload.c @@ -1,16 +1,21 @@ #include #include #include +#include #include "mesh.h" #include "dynarr.h" #include "rbtree.h" #include "vmath.h" #include "3dgfx.h" +#include "util.h" +struct vertex_pos_color { + float x, y, z; + float r, g, b, a; +}; struct facevertex { int vidx, tidx, nidx; - int myidx; }; static char *clean_line(char *s); @@ -18,20 +23,31 @@ static char *parse_face_vert(char *ptr, struct facevertex *fv, int numv, int num static int cmp_facevert(const void *ap, const void *bp); static void free_rbnode_key(struct rbnode *n, void *cls); - +/* merge of different indices per attribute happens during face processing. + * + * A triplet of (vertex index/texcoord index/normal index) is used as the key + * to search in a balanced binary search tree for vertex buffer index assigned + * to the same triplet if it has been encountered before. That index is + * appended to the index buffer. + * + * If a particular triplet has not been encountered before, a new g3d_vertex is + * appended to the vertex buffer. The index of this new vertex is appended to + * the index buffer, and also inserted into the tree for future searches. + */ int load_mesh(struct g3d_mesh *mesh, const char *fname) { int i, line_num = 0, result = -1; int found_quad = 0; - FILE *fp; + FILE *fp = 0; char buf[256]; - vec3_t *varr = 0, *narr = 0; + struct vertex_pos_color *varr = 0; + vec3_t *narr = 0; vec2_t *tarr = 0; - struct rbtree *rbtree; + struct rbtree *rbtree = 0; if(!(fp = fopen(fname, "rb"))) { fprintf(stderr, "load_mesh: failed to open file: %s\n", fname); - return -1; + goto err; } if(!(rbtree = rb_create(cmp_facevert))) { @@ -62,11 +78,24 @@ int load_mesh(struct g3d_mesh *mesh, const char *fname) case 'v': if(isspace(line[1])) { /* vertex */ - vec3_t v; - if(sscanf(line + 2, "%f %f %f", &v.x, &v.y, &v.z) != 3) { + struct vertex_pos_color v; + int num; + + num = sscanf(line + 2, "%f %f %f %f %f %f %f", &v.x, &v.y, &v.z, &v.x, &v.y, &v.z, &v.a); + if(num < 3) { fprintf(stderr, "%s:%d: invalid vertex definition: \"%s\"\n", fname, line_num, line); goto err; } + switch(num) { + case 3: + v.r = 1.0f; + case 4: + v.g = 1.0f; + case 5: + v.b = 1.0f; + case 6: + v.a = 1.0f; + } if(!(varr = dynarr_push(varr, &v))) { fprintf(stderr, "load_mesh: failed to resize vertex buffer\n"); goto err; @@ -125,7 +154,7 @@ int load_mesh(struct g3d_mesh *mesh, const char *fname) goto err; } } else { - uint16_t idx = dynarr_size(mesh->varr); + uint16_t newidx = dynarr_size(mesh->varr); struct g3d_vertex v; struct facevertex *newfv; @@ -133,6 +162,10 @@ int load_mesh(struct g3d_mesh *mesh, const char *fname) v.y = varr[fv.vidx].y; v.z = varr[fv.vidx].z; v.w = 1.0f; + v.r = cround64(varr[fv.vidx].r * 255.0); + v.g = cround64(varr[fv.vidx].g * 255.0); + v.b = cround64(varr[fv.vidx].b * 255.0); + v.a = cround64(varr[fv.vidx].a * 255.0); if(fv.tidx >= 0) { v.u = tarr[fv.tidx].x; v.v = tarr[fv.tidx].y; @@ -148,13 +181,12 @@ int load_mesh(struct g3d_mesh *mesh, const char *fname) v.nx = v.ny = 0.0f; v.nz = 1.0f; } - v.r = v.g = v.b = v.a = 255; if(!(mesh->varr = dynarr_push(mesh->varr, &v))) { fprintf(stderr, "load_mesh: failed to resize combined vertex array\n"); goto err; } - if(!(mesh->iarr = dynarr_push(mesh->iarr, &idx))) { + if(!(mesh->iarr = dynarr_push(mesh->iarr, &newidx))) { fprintf(stderr, "load_mesh: failed to resize index array\n"); goto err; } @@ -162,7 +194,7 @@ int load_mesh(struct g3d_mesh *mesh, const char *fname) if((newfv = malloc(sizeof *newfv))) { *newfv = fv; } - if(!newfv || rb_insert(rbtree, newfv, &idx) == -1) { + if(!newfv || rb_insert(rbtree, newfv, (void*)(intptr_t)newidx) == -1) { fprintf(stderr, "load_mesh: failed to insert facevertex to the binary search tree\n"); goto err; } @@ -200,6 +232,46 @@ err: return result; } +int save_mesh(struct g3d_mesh *mesh, const char *fname) +{ + int i, fvcount; + FILE *fp; + + if(!(fp = fopen(fname, "wb"))) { + fprintf(stderr, "save_mesh: failed to open %s for writing\n", fname); + return -1; + } + fprintf(fp, "# Wavefront OBJ file shoved in your FACE by Mindlapse. Deal with it\n"); + + for(i=0; ivcount; i++) { + struct g3d_vertex *v = mesh->varr + i; + fprintf(fp, "v %f %f %f %f %f %f %f\n", v->x, v->y, v->z, v->r / 255.0f, v->g / 255.0f, + v->b / 255.0f, v->a / 255.0f); + } + for(i=0; ivcount; i++) { + fprintf(fp, "vn %f %f %f\n", mesh->varr[i].nx, mesh->varr[i].ny, mesh->varr[i].nz); + } + for(i=0; ivcount; i++) { + fprintf(fp, "vt %f %f\n", mesh->varr[i].u, mesh->varr[i].v); + } + + fvcount = mesh->prim; + for(i=0; iicount; i++) { + int idx = mesh->iarr[i] + 1; + + if(fvcount == mesh->prim) { + fprintf(fp, "\nf"); + fvcount = 0; + } + fprintf(fp, " %d/%d/%d", idx, idx, idx); + ++fvcount; + } + fprintf(fp, "\n"); + + fclose(fp); + return 0; +} + static char *clean_line(char *s) { char *end;