From 7c3c42a31d7c4d7d5188621578703232bbdc18ee Mon Sep 17 00:00:00 2001 From: Carlos Sanchez Date: Tue, 13 Aug 2024 02:08:21 -0400 Subject: [PATCH] Nearly working freecam --- camera.h | 48 ++++++++ haloo3d | 2 +- keys.h | 14 +++ scene_freecam.c | 286 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 349 insertions(+), 1 deletion(-) create mode 100644 keys.h create mode 100644 scene_freecam.c diff --git a/camera.h b/camera.h index 9d225d2..40fcd15 100644 --- a/camera.h +++ b/camera.h @@ -1,6 +1,9 @@ #ifndef __3DTOYS_CAMERA #define __3DTOYS_CAMERA #include "haloo3d/haloo3d.h" +// #include "unigi/unigi.headers/src/main.h" + +#define LOOKLOCK MPI / 32 typedef struct { mfloat_t xofs; @@ -28,4 +31,49 @@ static inline int readcam(camset *set, int max, char *filename) { printf("Read %d camlines from %s\n", num, filename); return num; } + +/* +void camera_from_unigi(unigi_type_event * ev, haloo3d_camera * cam, float speed) +{ + + Fps := float32(*fps) + mouse := rl.GetMouseDelta() + pitch += Rotation * mouse.Y / Fps + yaw += Rotation * mouse.X / Fps + pitch = hrend.Clamp(pitch, LookLock, math.Pi-LookLock) + + newcamtrans := hrend.Vec3f{X: 0, Y: 0, Z: 0} + move := float32(Movement) + if rl.IsMouseButtonDown(rl.MouseButtonLeft) { + move *= 6 + } + if rl.IsKeyDown(rl.KeyD) { + newcamtrans.X += move / Fps + } + if rl.IsKeyDown(rl.KeyA) { + newcamtrans.X -= move / Fps + } + // Moving forward moves in the negative z direction, since we FACE + // the -z axis (the camera does anyway) + if rl.IsKeyDown(rl.KeyW) { + newcamtrans.Z -= move / Fps + } + if rl.IsKeyDown(rl.KeyS) { + newcamtrans.Z += move / Fps + } + if rl.IsKeyDown(rl.KeySpace) { + newcamtrans.Y += move / Fps + } + if rl.IsKeyDown(rl.KeyLeftShift) { + newcamtrans.Y -= move / Fps + } + + // translate the new camera movement based on the yaw + var moverot hrend.Mat44f + moverot.SetRotationY(-yaw) + hnewcamtrans := moverot.MultiplyPoint3(newcamtrans) + + return yaw, pitch, hnewcamtrans.MakeConventional() +}*/ + #endif diff --git a/haloo3d b/haloo3d index f3eae62..c7104a0 160000 --- a/haloo3d +++ b/haloo3d @@ -1 +1 @@ -Subproject commit f3eae6298d41599490f811a14b95996686bcde80 +Subproject commit c7104a09b0698ca7c81b1c7dd55f5b5095a66a4e diff --git a/keys.h b/keys.h new file mode 100644 index 0000000..d87d1d4 --- /dev/null +++ b/keys.h @@ -0,0 +1,14 @@ +#ifndef __3DTOYS_KEYS +#define __3DTOYS_KEYS +#define KEY_ESC 9 +#define KEY_W 25 +#define KEY_A 38 +#define KEY_S 39 +#define KEY_D 40 +#define KEY_LSHIFT 50 +#define KEY_SPACE 65 + +#define MOUSE_LCLICK 1 +#define MOUSE_MCLICK 2 +#define MOUSE_RCLICK 3 +#endif diff --git a/scene_freecam.c b/scene_freecam.c new file mode 100644 index 0000000..c8ed4dd --- /dev/null +++ b/scene_freecam.c @@ -0,0 +1,286 @@ +#include "haloo3d/haloo3d.h" +#include "haloo3d/haloo3dex_gen.h" +#include "haloo3d/haloo3dex_img.h" +#include "haloo3d/haloo3dex_obj.h" +#include "haloo3d/haloo3dex_print.h" + +#include "unigi/unigi.headers/src/main.h" +#include "unigi/unigi.platform.sdl1/src/main.c" +// #include "unigi/unigi.ext/src/main.c" + +#include "camera.h" +#include "keys.h" +#include "resources/flower.h" + +#include +#include + +#define DOLIGHTING +#define FASTTRIS + +// IDK you probably have to change this based on your display. +// Maybe there's a way to fix this? +#define UNIGIBITDEPTH 32 +#define MOVESPEED 3 +#define ROTSPEED 0.02 +#define TARGETFPS 60 + +#define WIDTH 640 +#define HEIGHT 480 +#define ASPECT ((float)WIDTH / HEIGHT) +#define FOV 90.0 +#define NEARCLIP 0.01 +#define FARCLIP 100.0 +#define LIGHTANG -MPI / 4.0 +#define MINLIGHT 0.25 +#define SKYSCALE 30 +#define AVGWEIGHT 0.85 + +// this is the number of DYNAMIC objects.. +#define NUMOBJECTS 4 +#define NUMFLOWERS 300 +#define PLANESIZE 61 +#define FLOWERIND (NUMOBJECTS - 1) +#define NUMINSTANCES (NUMOBJECTS - 1 + NUMFLOWERS) +#define MAXCAM 1200 + +#ifdef FASTTRIS +#define WBUFCLEAR FARCLIP +#define TRIFUNC haloo3d_texturedtriangle_fast +#else +#define WBUFCLEAR 0 +#define TRIFUNC haloo3d_texturedtriangle +#endif + +#define CALCTIME(thistime, start, end, sum) \ + thistime = 1000.0 * (float)(end - start) / CLOCKS_PER_SEC; \ + if (sum == 0) \ + sum = thistime; \ + sum = AVGWEIGHT * sum + (1 - AVGWEIGHT) * thistime; + +uint16_t redflower[64] = H3D_FLOWER(0xFE55, 0xF6C4, 0xFFE0, 0xFD44, 0xF492); + +int main(int argc, char **argv) { + + if (argc != 3) { + dieerr("You must pass in the obj and ppm file!\n"); + } + + // Load the junk + generate stuff + haloo3d_obj models[NUMOBJECTS]; + haloo3d_fb textures[NUMOBJECTS]; + haloo3d_obj_loadfile(models, argv[1]); + haloo3d_img_loadppmfile(textures, argv[2]); + haloo3d_gen_1pxgradient(textures + 1, 0xF44F, 0xF001, 32); + haloo3d_gen_skybox(models + 1); + uint16_t checkcols[2] = {0xF0A0, 0xF270}; + haloo3d_gen_checkerboard(textures + 2, checkcols, 2, 32); + haloo3d_gen_sloped(models + 2, PLANESIZE, 1.0, 1.25); + haloo3d_fb_init_tex(textures + 3, 8, 8); + memcpy(textures[3].buffer, redflower, sizeof(uint16_t) * 64); + haloo3d_gen_crossquad(models + 3, textures + 3); + + // Create the camera matrix, which DOES change. In this one, + // we move the camera instead of the model + haloo3d_camera camera; + haloo3d_camera_init(&camera); + struct vec4 movement; + vec4(movement.v, 0, 0, 0, 1); + char buttonsheld[256]; + char mouseheld[256]; + memset(buttonsheld, 0, 256); + memset(mouseheld, 0, 256); + + // Create the perspective matrix, which doesn't change + mfloat_t perspective[MAT4_SIZE]; + haloo3d_perspective(perspective, FOV, ASPECT, NEARCLIP, FARCLIP); + + // Lighting. Note that for performance, the lighting is always calculated + // against the base model, and is thus not realistic if the object rotates in + // the world. This can be fixed easily, since each object gets its own + // lighting vector, which can easily be rotated in the opposite direction of + // the model + struct vec3 light; + vec3(light.v, 0, -MCOS(LIGHTANG), MSIN(LIGHTANG)); + + int totalfaces = 0; + int totalverts = 0; + haloo3d_obj_instance objects[NUMINSTANCES]; + for (int i = 0; i < NUMINSTANCES; i++) { + if (i < FLOWERIND) { + haloo3d_objin_init(objects + i, models + i, textures + i); + } else { // Setup the flowers + haloo3d_objin_init(objects + i, models + FLOWERIND, textures + FLOWERIND); + objects[i].cullbackface = 0; + objects[i].scale = 0.5; + int rvi = rand() % models[2].numvertices; + vec3_assign(objects[i].pos.v, models[2].vertices[rvi].v); + objects[i].pos.y += 0.5; + } + totalfaces += objects[i].model->numfaces; + totalverts += objects[i].model->numvertices; + } +#ifdef DOLIGHTING + objects[0].lighting = &light; + objects[2].lighting = &light; +#endif + objects[0].pos.y = 1; + objects[1].scale = SKYSCALE; + + // Now we create a framebuffer to draw the triangle into + haloo3d_fb fb; + haloo3d_fb_init(&fb, WIDTH, HEIGHT); + + unigi_type_event event; + unigi_type_resolution res; + res.width = WIDTH; + res.height = HEIGHT; + res.depth = UNIGIBITDEPTH; + + // Printing to screen needs tracking + haloo3d_print_tracker t; + char printbuf[8192]; + haloo3d_print_initdefault(&t, printbuf, sizeof(printbuf)); + t.fb = &fb; + // t.logprints = 1; + + // Storage stuff + mfloat_t matrix3d[MAT4_SIZE], matrixcam[MAT4_SIZE], matrixscreen[MAT4_SIZE], + matrixmodel[MAT4_SIZE]; + haloo3d_facef outfaces[H3D_FACEF_MAXCLIP]; + struct vec3 tmp1; + haloo3d_facef face, baseface; + struct vec4 *vert_precalc; + mallocordie(vert_precalc, sizeof(struct vec4) * H3D_OBJ_MAXVERTICES); + clock_t begin, end; + // Measured in milliseconds + float sumframe = 0, lastframe = 0, speed; + float msperframe = 1000.0 / TARGETFPS; + int totaldrawn = 0; + + eprintf("Scene has %d tris, %d verts\n", totalfaces, totalverts); + + // Init unigi system + sprintf(printbuf, "scene.exe - %s %s %s", argv[1], argv[2], argv[3]); + unigi_graphics_init(); + unigi_window_create(res, printbuf); + + // ----------------------------------- + // Actual rendering + // ----------------------------------- + + while (1) { + begin = clock(); + + while (1) { + unigi_event_get(&event); + switch (event.type) { + case unigi_enum_event_none: + goto LBL_END_INPUT; + case unigi_enum_event_input_keyboard: + buttonsheld[event.data.input_keyboard.button] = + event.data.input_keyboard.down; + switch ((int)event.data.input_keyboard.button) { + case KEY_ESC: + eprintf("Exiting\n"); + exit(0); + default: + eprintf("KEY: %d - %d\n", event.data.input_keyboard.button, + event.data.input_keyboard.down); + } + break; + case unigi_enum_event_input_mouse_move: + camera.yaw += ROTSPEED * event.data.input_mouse_move.rel_x; + camera.pitch += ROTSPEED * event.data.input_mouse_move.rel_y; + CLAMP(camera.pitch, LOOKLOCK, MPI - LOOKLOCK); + break; + case unigi_enum_event_input_mouse_button: + mouseheld[event.data.input_mouse_button.button] = + event.data.input_mouse_button.down; + eprintf("MOUSE: %d - %d\n", event.data.input_mouse_button.button, + event.data.input_mouse_button.down); + break; + } + } + LBL_END_INPUT:; + + speed = (float)MOVESPEED / TARGETFPS; + if (mouseheld[MOUSE_LCLICK]) { + speed *= 5; + } + movement.z = speed * (buttonsheld[KEY_S] - buttonsheld[KEY_W]); + movement.x = speed * (buttonsheld[KEY_D] - buttonsheld[KEY_A]); + haloo3d_camera_calcmove_yaw(&camera, &movement); + movement.y = speed * (buttonsheld[KEY_SPACE] - buttonsheld[KEY_LSHIFT]); + vec4_add(camera.pos.v, camera.pos.v, movement.v); + + totaldrawn = 0; + + haloo3d_print_refresh(&t); + // camera.yaw = cams[cami].yaw; + // camera.pitch = cams[cami].pitch + MPI_2; + + // REMEMBER TO CLEAR DEPTH BUFFER + haloo3d_fb_cleardepth(&fb, WBUFCLEAR); + + // Screen matrix calc. We multiply the modelview matrix with this later + haloo3d_camera_calclook(&camera, matrixcam); + mat4_inverse(matrixcam, matrixcam); + mat4_multiply(matrixscreen, perspective, matrixcam); + + // Iterate over objects + for (int i = 0; i < NUMINSTANCES; i++) { + // Setup final model matrix and the precalced vertices + vec3_add(tmp1.v, objects[i].pos.v, objects[i].lookvec.v); + haloo3d_my_lookat(matrixmodel, objects[i].pos.v, tmp1.v, camera.up.v); + haloo3d_mat4_scale(matrixmodel, objects[i].scale); + mat4_multiply(matrix3d, matrixscreen, matrixmodel); + haloo3d_precalc_verts(objects[i].model, matrix3d, vert_precalc); + // Iterate over object faces + for (int fi = 0; fi < objects[i].model->numfaces; fi++) { + // Copy face values out of precalc array and clip them + haloo3d_make_facef(objects[i].model->faces[fi], vert_precalc, + objects[i].model->vtexture, face); + int tris = haloo3d_facef_clip(face, outfaces); + for (int ti = 0; ti < tris; ti++) { + int backface = !haloo3d_facef_finalize(outfaces[ti]); + if (objects[i].cullbackface && backface) { + continue; + } + totaldrawn++; + mfloat_t intensity = 1.0; + if (objects[i].lighting) { + haloo3d_obj_facef(objects[i].model, objects[i].model->faces[fi], + baseface); + intensity = + haloo3d_calc_light(objects[i].lighting->v, MINLIGHT, baseface); + } + // We still have to convert the points into the view + haloo3d_facef_viewport_into(outfaces[ti], WIDTH, HEIGHT); + TRIFUNC(&fb, objects[i].texture, intensity, outfaces[ti]); + } + } + } + + haloo3d_print(&t, "Last frame: %05.2f (%05.2f)\nTris: %d / %d\nVerts: %d\n", + lastframe, sumframe, totaldrawn, totalfaces, totalverts); + + unigi_graphics_blit(0, (unigi_type_color *)fb.buffer, + res.width * res.height); + unigi_graphics_flush(); + + end = clock(); + CALCTIME(lastframe, begin, end, sumframe); + + float waittime = msperframe - lastframe; + if (waittime > 0) { + unigi_time_sleep(waittime * unigi_time_clocks_per_s / 1000); + } + } + + // Free after loop + for (int i = 0; i < NUMOBJECTS; i++) { + haloo3d_obj_free(models + i); + haloo3d_fb_free(textures + i); + } +}