#include "haloo3d/haloo3d.h" #include "haloo3d/haloo3dex_easy.h" #include "haloo3d/haloo3dex_gen.h" #include "haloo3d/haloo3dex_obj.h" #include "haloo3d/lib/mathc.h" #include "unigi/unigi.headers/src/main.h" #include "unigi/unigi.platform.sdl1/src/main.c" #include "ecs2.h" // #include "keys.h" #include "terrain_ecstypes.h" #include #define WIDTH 480 #define HEIGHT 300 #define SCREENSCALE 2 #define SWIDTH (WIDTH * SCREENSCALE) #define SHEIGHT (HEIGHT * SCREENSCALE) #define AVGWEIGHT 0.85 // These are initial values but there may be ways to change it #define CAM_INITPITCH MPI_2 #define INIT_NEARCLIP 0.01 #define INIT_FARCLIP 100.0 #define INIT_DITHERSTART 10000 #define INIT_DITHEREND 10000 // Some globals you can mess around with potentially int fps = 30; // The terrain ecs systems // All initialization for a specific render context void sys_rendercontext(ecs_rendercontext *erc, ecs_placement *p) { render_context *rc = *erc; rc->precalc_halfwidth = rc->window.width * H3DVF(0.5); rc->precalc_halfheight = rc->window.height * H3DVF(0.5); haloo3d_perspective(rc->precalc_perspective, rc->fov, (mfloat_t)rc->window.width / rc->window.height, rc->nearclip, rc->farclip); haloo3d_fb_cleardepth(&rc->window); if (rc->windowclear & 0xF000) { haloo3d_fb_clear(&rc->window, rc->windowclear); } } // Apply rotation to lookvec of placement void sys_rotation(ecs_placement *p, ecs_rotation *r) { YAWP2VEC(r->yaw, r->pitch, p->lookvec.v); } void sys_movement(ecs_placement *p, ecs_movement *m) { vec3_add(p->lookvec.v, p->lookvec.v, m->lookvec.v); vec3_add(p->up.v, p->up.v, m->up.v); vec3_add(p->pos.v, p->pos.v, m->pos.v); } // Perform the entire rendering of an object void sys_renderobject(ecs_placement *p, ecs_object *o) { struct vec3 lighting; struct vec4 precalc_verts[H3D_OBJ_MAXVERTICES]; // First, precalc all the vertices in the object // ------------------------------------------------------------------ mfloat_t tmp[VEC4_SIZE]; mfloat_t modelm[MAT4_SIZE]; mfloat_t finalmatrix[MAT4_SIZE]; vec3_add(tmp, p->pos.v, p->lookvec.v); haloo3d_my_lookat(modelm, p->pos.v, tmp, p->up.v); // Apply scale such that it looks like it was applied first (this prevents // scaling applying skew to a rotated object) haloo3d_mat4_prescalev(modelm, o->scale.v); mat4_multiply(finalmatrix, o->context->precalc_screen, modelm); haloo3d_precalc_verts(o->model, finalmatrix, precalc_verts); // Next, setup some rendering invariants // ------------------------------------------------------------------ o->context->rendersettings.texture = o->texture; if (o->lighting) { if (o->lighting->autolightfix) { // Lighting doesn't rotate with the model unless you do it yourself. // In the easy system, you can request the renderer to do it for you struct vec4 ltmp, lout; // Lighting is centered at 0 vec4(ltmp.v, 0, 0, 0, 1); // Calc the same lookat just without translation. THis should be the same // rotation matrix used on the model haloo3d_my_lookat(modelm, ltmp.v, p->lookvec.v, p->up.v); // We actually want the inverse. Apparently to speed things up, the // transpose works for rotation matrices(?) but I don't trust that this // lookat does that // mat4_inverse(modelm, modelm); mat4_transpose(modelm, modelm); // We HAVE to have a vec4 (oof) vec4(ltmp.v, o->lighting->dir.x, o->lighting->dir.y, o->lighting->dir.z, 1); haloo3d_vec4_multmat_into(<mp, modelm, &lout); // No need to fix W, should all be good (no perspective divide). But we DO // need to pull out that result vec3(lighting.v, lout.x, lout.y, lout.z); vec3_normalize(lighting.v, lighting.v); } else { vec3_assign(lighting.v, o->lighting->dir.v); } } // Finally, actually render faces // ------------------------------------------------------------------ int totaldrawn = 0; haloo3d_facef face, baseface; haloo3d_facef outfaces[H3D_FACEF_MAXCLIP]; for (int facei = 0; facei < o->model->numfaces; facei++) { // Copy face values out of precalc array and clip them haloo3d_make_facef(o->model->faces[facei], precalc_verts, o->model->vtexture, face); int tris = haloo3d_facef_clip(face, outfaces); if (tris > 0) { uint8_t oflags = o->context->rendersettings.flags; if (o->lighting) { haloo3d_obj_facef(o->model, o->model->faces[facei], baseface); o->context->rendersettings.intensity = haloo3d_calc_light(lighting.v, o->lighting->minlight, baseface); } else { o->context->rendersettings.intensity = H3DVF(1.0); } // if ((r->_objstate[object - r->objects] & H3D_EASYOBJSTATE_NOTRANS)) { // r->rendersettings.flags &= ~H3DR_TRANSPARENCY; // } for (int ti = 0; ti < tris; ti++) { int backface = !haloo3d_facef_finalize(outfaces[ti]); if (o->cullbackface && backface) { continue; } totaldrawn++; // We still have to convert the points into the view haloo3d_facef_viewport_into_fast(outfaces[ti], o->context->precalc_halfwidth, o->context->precalc_halfheight); haloo3d_triangle(&o->context->window, &o->context->rendersettings, outfaces[ti]); } o->context->rendersettings.flags = oflags; } } // return totaldrawn; } int main() { // int argc, char **argv) { srand(clock()); // Init unigi system. Can use anything here that can render to screen unigi_type_event event; unigi_type_resolution res; res.width = SWIDTH; res.height = SHEIGHT; res.depth = 0; unigi_graphics_init(); unigi_window_create(res, "terrain.exe"); // render.printbuf); eprintf("Initialized unigi system\n"); haloo3d_easystore storage; haloo3d_easystore_init(&storage); haloo3d_fb *palettetex = haloo3d_easystore_addtex(&storage, "palette"); haloo3d_gen_palettetex(palettetex); eprintf("Initialized storage and default textures/etc\n"); haloo3d_fb screen3d; haloo3d_fb_init(&screen3d, WIDTH, HEIGHT); haloo3d_fb screen; haloo3d_fb_init(&screen, SWIDTH, SHEIGHT); haloo3d_easytimer frametimer, drawtimer, sdltimer, filltimer, logictimer; haloo3d_easytimer_init(&frametimer, AVGWEIGHT); haloo3d_easytimer_init(&drawtimer, AVGWEIGHT); haloo3d_easytimer_init(&sdltimer, AVGWEIGHT); haloo3d_easytimer_init(&filltimer, AVGWEIGHT); haloo3d_easytimer_init(&logictimer, AVGWEIGHT); eprintf("Initialized screen buffers and timers\n"); tecs ecs; tecs_init(&ecs); // MAIN LOOP while (1) { haloo3d_easytimer_start(&frametimer); do { unigi_event_get(&event); switch (event.type) { case unigi_enum_event_input_keyboard: if (event.data.input_keyboard.down) { switch (event.data.input_keyboard.button) { // case KEY_SPACE: // haloo3d_debugconsole_beginprompt(&dc); // break; default: exit(0); } } break; } } while (event.type != unigi_enum_event_none); // ECS logic (which includes rendering) ECS_RUNSYSTEM2(&ecs, sys_rotation, ecs_placement, ecs_rotation); ECS_RUNSYSTEM2(&ecs, sys_movement, ecs_placement, ecs_movement); ECS_RUNSYSTEM2(&ecs, sys_rendercontext, ecs_rendercontext, ecs_placement); ECS_RUNSYSTEM2(&ecs, sys_renderobject, ecs_placement, ecs_object); // Scale 3D into final buffer haloo3d_easytimer_start(&filltimer); haloo3d_fb_fill(&screen, &screen3d); haloo3d_easytimer_end(&filltimer); /* haloo3d_print(&render.tprint, "Pframe: %05.2f (%05.2f)\nPSDLFl: %05.2f " "(%05.2f)\nFill: %05.2f " "(%05.2f)\nLogic: %05.2f (%05.2f)\nTris: %d / %d\nVerts: " "%d\nWState: %d", frametimer.last * 1000, frametimer.sum * 1000, sdltimer.last * 1000, sdltimer.sum * 1000, filltimer.last * 1000, filltimer.sum * 1000, logictimer.last * 1000, logictimer.sum * 1000, totaldrawn, render.totalfaces, render.totalverts, wstate.state); */ // Finally, actually put buffer onto screen haloo3d_easytimer_start(&sdltimer); unigi_graphics_blit(0, (unigi_type_color *)screen.buffer, res.width * res.height); unigi_graphics_flush(); haloo3d_easytimer_end(&sdltimer); haloo3d_easytimer_end(&frametimer); // Wait for next frame based on fps float waittime = (1.0 / fps) - frametimer.last; if (waittime > 0) { unigi_time_sleep(waittime * unigi_time_clocks_per_s); } } haloo3d_fb_free(&screen); haloo3d_fb_free(&screen3d); haloo3d_easystore_deleteallobj(&storage, haloo3d_obj_free); haloo3d_easystore_deletealltex(&storage, haloo3d_fb_free); }