commit 6291496d8715522922309ca13746ff212a4452c3
parent 5081718387b3df8914a9624fc109adc5cc9e9aad
Author: William Casarin <jb55@jb55.com>
Date: Thu, 5 Aug 2021 06:58:55 -0700
terrain loading for wasm
Diffstat:
15 files changed, 173 insertions(+), 94 deletions(-)
diff --git a/Makefile b/Makefile
@@ -17,13 +17,13 @@ BASE_CFLAGS = $(DEFS) -O2 -g -I src -Wall -Werror -Wextra -std=c99 \
$(shell pkg-config --cflags sdl2 gl)
CFLAGS = $(BASE_CFLAGS)
-EM_CFLAGS = $(BASE_CFLAGS)
-
+EM_CFLAGS = $(BASE_CFLAGS) -s STANDALONE_WASM
LDFLAGS = $(shell pkg-config --libs sdl2 gl) -lm
SRC=src
SRCS=$(wildcard $(SRC)/*.c)
+HEADERS=$(wildcard $(SRC)/*.h)
PLYS=$(wildcard data/models/*.ply)
MODELS=$(PLYS:.ply=.mdl)
@@ -81,6 +81,6 @@ install: $(BIN)
install $(BIN) $(PREFIX)/bin
tags:
- ctags $(SRCS)
+ ctags $(SRCS) $(HEADERS)
-.PHONY: TAGS
+.PHONY: TAGS tags
diff --git a/default.nix b/default.nix
@@ -13,7 +13,7 @@ stdenv.mkDerivation rec {
makeFlags = "PREFIX=$(out)";
- nativeBuildInputs = with pkgs; [ tinycc pkg-config gdb emscripten ];
+ nativeBuildInputs = with pkgs; [ tinycc pkg-config gdb emscripten binaryen ];
buildInputs = with pkgs; [ SDL2 mesa libglvnd ] ++
(with xorg; [ libX11 libxcb libXau libXdmcp libXext libXcursor
diff --git a/main.c b/main.c
@@ -72,6 +72,7 @@ int main(void)
while (!game.quit) {
+ game.input.keystates = SDL_GetKeyboardState(NULL);
game.frame++;
process_events(&game.input, game.frame);
if (game.input.resized_height) {
@@ -83,6 +84,8 @@ int main(void)
double new_time = hires_time_in_seconds();
double frame_time = new_time - last;
game.dt = frame_time;
+ if (game.frame % 24 == 0)
+ printf("frame time %f\n", frame_time * 1000);
update(&game);
diff --git a/src/dae.c b/src/dae.c
@@ -351,7 +351,7 @@ void dae_attr(struct xmlparser *x, const char *t, size_t tl,
}
else if (data->state == PARSING_NODE
&& streq(a, "name")) {
- strncpy(data->current_name, v, sizeof(data->current_name));
+ strncpy(data->current_name, v, sizeof(data->current_name)-1);
}
else if (data->state == PARSING_NODE
&& streq(a, "type")
diff --git a/src/delaunay.c b/src/delaunay.c
@@ -513,11 +513,11 @@ static halfedge_t* del_valid_left( halfedge_t* b )
v = b->next->pair->vertex; /* pair(next(next(halfedge)) point */
- if( classify_point_seg(g, d, u) == ON_LEFT )
+ if( v!=u && classify_point_seg(g, d, u) == ON_LEFT )
{
/* 3 points aren't colinear */
/* as long as the 4 points belong to the same circle, do the cleaning */
- assert( v != u && "1: floating point precision error");
+ //assert( v != u && "1: floating point precision error");
while( v != d && v != g && in_circle(g, d, u, v) == INSIDE )
{
c = b->next;
@@ -528,7 +528,7 @@ static halfedge_t* del_valid_left( halfedge_t* b )
v = b->next->pair->vertex;
}
- assert( v != u && "2: floating point precision error");
+ //assert( v != u && "2: floating point precision error");
if( v != d && v != g && in_circle(g, d, u, v) == ON_CIRCLE )
{
du = du->prev;
@@ -559,9 +559,9 @@ static halfedge_t* del_valid_right( halfedge_t *b )
v = b->prev->pair->vertex;
- if( classify_point_seg(lv, rv, u) == ON_LEFT )
+ if( v!=u && classify_point_seg(lv, rv, u) == ON_LEFT )
{
- assert( v != u && "1: floating point precision error");
+ //assert( v != u && "1: floating point precision error");
while( v != lv && v != rv && in_circle(lv, rv, u, v) == INSIDE )
{
c = b->prev;
@@ -572,7 +572,7 @@ static halfedge_t* del_valid_right( halfedge_t *b )
v = b->prev->pair->vertex;
}
- assert( v != u && "1: floating point precision error");
+ //assert( v != u && "1: floating point precision error");
if( v != lv && v != rv && in_circle(lv, rv, u, v) == ON_CIRCLE )
{
du = du->next;
diff --git a/src/game.c b/src/game.c
@@ -56,7 +56,7 @@ static void init_user_settings(struct user_settings *settings) {
static void init_sdl(SDL_Window **window, int width, int height)
{
- SDL_Init( SDL_INIT_JOYSTICK );
+ SDL_Init( 0);
/* SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); */
@@ -95,7 +95,8 @@ void init_misc(struct game *game, int width, int height) {
game->quit = 0;
game->frame = 0;
- const double size = 1000.0;
+ const double size = 4000.0;
+ //double scale = 0.03;
double scale = 0.03;
terrain->settings = (struct perlin_settings){
@@ -110,16 +111,19 @@ void init_misc(struct game *game, int width, int height) {
.scale = scale
};
+ debug("creating ui...\n");
create_ui(&game->ui, width, height, &res->programs[UI_PROGRAM]);
check_gl();
init_terrain(terrain, size);
/* terrain->samples = load_samples(&seed, &terrain->n_samples); */
terrain->n_samples = 0;
- create_terrain(terrain, size, game->seed);
+ //create_terrain(terrain, size, game->seed);
+ load_terrain(terrain);
/* update_terrain(terrain, terrain->cell_size); */
/* get_entity(&terrain->entity_id)->flags |= ENT_INVISIBLE; */
+ debug("creating skybox...\n");
create_skybox(&res->skybox, &res->programs[SKYBOX_PROGRAM]); /* node_translate(&res->skybox.node, V3(-100.0, -100.0, 0.0)); */
/* node_scale(&res->skybox.node, size/4.0); */
diff --git a/src/geometry.c b/src/geometry.c
@@ -64,7 +64,7 @@ void render_geometry(struct geometry *geom, gpu_addr *vertex_attrs,
GL_UNSIGNED_INT, /* type */
(void*)0 /* element array buffer offset */
);
- /* printf("render_geometry %s\n", program->name); */
+ //printf("render_geometry %d %s\n", geom->num_indices, program->name);
check_gl();
}
else {
diff --git a/src/mdl.c b/src/mdl.c
@@ -41,7 +41,7 @@ void init_mdl_geometry(struct mdl_geometry *lgeom)
vec3_set(V3(0,0,0), lgeom->max);
}
-void save_mdl_fd(FILE *out, struct model *model, struct mdl_geometry *lgeom)
+void save_mdl_fd(FILE *out, struct mdl_geometry *lgeom)
{
struct make_geometry *mkgeom = &lgeom->mkgeom;
assert(mkgeom->vertices);
@@ -140,7 +140,7 @@ static inline int read_int(FILE *stream)
return val;
}
-#define MAX_MDL_ARRAY 128000 // only enforced at dev time for sanity
+#define MAX_MDL_ARRAY 1280000 // only enforced at dev time for sanity
static inline int read_nfloats(FILE *stream, int n, float *floats)
{
@@ -184,6 +184,7 @@ void load_mdl_fd(FILE *in, struct model *model, struct mdl_geometry *lgeom)
switch (tag) {
case MDL_POSITION:
mkgeom->num_verts = read_floats(in, &mkgeom->vertices) / 3;
+ printf("mdl verts %d\n", mkgeom->num_verts);
break;
case MDL_NORMAL:
@@ -235,11 +236,11 @@ void load_mdl_fd(FILE *in, struct model *model, struct mdl_geometry *lgeom)
}
}
-void save_mdl(const char *filename, struct model *model, struct mdl_geometry *lgeom)
+void save_mdl(const char *filename, struct mdl_geometry *lgeom)
{
FILE *out = fopen(filename, "wb");
assert(out);
- save_mdl_fd(out, model, lgeom);
+ save_mdl_fd(out, lgeom);
fclose(out);
}
diff --git a/src/mdl.h b/src/mdl.h
@@ -27,8 +27,8 @@ struct mdl_geometry {
};
-void save_mdl(const char *filename, struct model *model, struct mdl_geometry *geom);
-void save_mdl_fd(FILE *out, struct model *model, struct mdl_geometry *geom);
+void save_mdl(const char *filename, struct mdl_geometry *geom);
+void save_mdl_fd(FILE *out, struct mdl_geometry *geom);
void load_mdl(const char *filename, struct model *model, struct mdl_geometry *geom);
void load_mdl_fd(FILE *in, struct model *model, struct mdl_geometry *geom);
diff --git a/src/skybox.c b/src/skybox.c
@@ -82,6 +82,7 @@ void create_skybox(struct skybox *skybox, struct gpu_program *program) {
/* }; */
model->texture = create_cubemap(faces);
+ printf("cubemap texture %d\n", model->texture);
make_shader(GL_VERTEX_SHADER, SHADER("skybox.v.glsl"), &vertex);
check_gl();
diff --git a/src/terrain.c b/src/terrain.c
@@ -6,6 +6,9 @@
#include "vec3.h"
#include "perlin.h"
#include "poisson.h"
+#include "mdl.h"
+
+static const double pdist = 24.0;
static const float plane_verts[] = {
-1,-1,0, -1,1,0, 1,1,0, 1,-1,0
@@ -52,6 +55,13 @@ void reset_terrain(struct terrain *terrain, float size) {
assert(ent);
}
+double offset_fn(struct terrain* terrain, double x, double y) {
+ struct perlin_settings *perlin = &terrain->settings;
+ double ox = perlin->ox;
+ double oy = perlin->oy;
+ return old_noisy_boi(terrain, ox+x, oy+y);
+}
+
void init_terrain(struct terrain *terrain, float size) {
init_id(&terrain->entity_id);
@@ -72,18 +82,22 @@ void init_terrain(struct terrain *terrain, float size) {
/* node->pos[2] = 20.0; */
reset_terrain(terrain, size);
-}
-double offset_fn(struct terrain* terrain, double x, double y) {
- struct perlin_settings *perlin = &terrain->settings;
- double ox = perlin->ox;
- double oy = perlin->oy;
- return old_noisy_boi(terrain, ox+x, oy+y);
+ terrain->fn = offset_fn;
+ terrain->cell_size = pdist;
+ terrain->n_cells = round(size / terrain->cell_size) + 1;
+ debug("n_cells %d\n", terrain->n_cells);
+
+ struct terrain_cell *grid =
+ calloc(terrain->n_cells * terrain->n_cells, sizeof(struct terrain_cell));
+
+ terrain->grid = grid;
+
}
void gen_terrain_samples(struct terrain *terrain, float scale, const double pdist) {
- debug("generating terrain samples\n");
+ debug("generating terrain samples...\n");
if (terrain->samples)
free(terrain->samples);
@@ -93,9 +107,12 @@ void gen_terrain_samples(struct terrain *terrain, float scale, const double pdis
/* struct point *samples = */
/* uniform_samples(n_samples, game->terrain.size); */
+
struct point *samples =
poisson_disk_samples(pdist, terrain->size, 30, &n_samples);
+ debug("done generating terrain samples\n");
+
/* remap_samples(samples, n_samples, game->terrain.size); */
/* draw_samples(samples, pdist, n_samples, game->terrain.size); */
@@ -108,7 +125,6 @@ void gen_terrain_samples(struct terrain *terrain, float scale, const double pdis
static inline struct terrain_cell *index_terrain_cell(struct terrain *terrain, int x, int y)
{
if (x < 0 || y < 0 || x >= terrain->n_cells || y >= terrain->n_cells) {
- assert(!"terrain oob");
return NULL;
}
@@ -119,10 +135,11 @@ static inline struct terrain_cell *query_terrain_cell(struct terrain *terrain,
float x, float y,
int *grid_x, int *grid_y)
{
- assert(x >= 0);
- assert(y >= 0);
- assert(x < terrain->size);
- assert(y < terrain->size);
+ if (x < 0) return NULL;
+ if(y < 0) return NULL;
+ if(x >= terrain->size) return NULL;
+ if(y >= terrain->size) return NULL;
+
*grid_x = grid_index(terrain, x);
*grid_y = grid_index(terrain, y);
@@ -132,7 +149,7 @@ static inline struct terrain_cell *query_terrain_cell(struct terrain *terrain,
void query_terrain_grid(struct terrain *terrain, float x, float y,
struct terrain_cell *cells[9])
{
- int grid_x, grid_y;
+ int grid_x = 0, grid_y = 0;
// middle
cells[4] = query_terrain_cell(terrain, x, y, &grid_x, &grid_y);
@@ -203,45 +220,94 @@ static double distance_to_closest_edge(double size, double x, double y) {
return min(top, min(left, min(right, bottom)));
}
+static void compute_bounding(float *vertices, int num_verts, vec3 *min, vec3 *max)
+{
+ int i;
+ for (i = 0; i < num_verts; i++) {
+ }
+}
+
+void create_terrain_collision(struct terrain *terrain)
+{
+ double x, y;
+ int n;
+ u32 i;
+
+ for (i = 0; i < (u32)terrain->n_verts; i++) {
+ n = i*3;
+ /* double dx, dy; */
+
+ x = terrain->verts[n+0];
+ y = terrain->verts[n+1];
+
+ int grid_x = x / terrain->cell_size;
+ int grid_y = y / terrain->cell_size;
+
+ // clamp height at edge
+ printf("%f %f %f %d grid_x %d grid_y %f cell_size\n",
+ x, y, terrain->verts[n+2],
+ grid_x, grid_y, terrain->cell_size);
+
+ struct terrain_cell *cell =
+ index_terrain_cell(terrain, grid_x, grid_y);
+
+ insert_grid_vertex(cell, n);
+ }
+}
+
+
+void load_terrain(struct terrain *terrain)
+{
+ int seed;
+
+ assert(terrain->size > 0);
+ struct mdl_geometry terrain_mdl;
+ init_mdl_geometry(&terrain_mdl);
+ load_mdl("terrain.mdl", NULL, &terrain_mdl);
+
+ struct entity *ent = get_entity(&terrain->entity_id); assert(ent);
+ struct model *model = get_model(&ent->model_id); assert(model);
+ struct geometry *geom = get_geometry(&model->geom_id); assert(geom);
+
+ assert(terrain_mdl.mkgeom.joint_weights == 0);
+
+ make_buffer_geometry(&terrain_mdl.mkgeom, geom);
+
+ terrain->verts = terrain_mdl.mkgeom.vertices;
+ terrain->n_verts = terrain_mdl.mkgeom.num_verts;
+
+ //struct vert_tris *vert_tris = calloc(terrain->n_verts, sizeof(struct vert_tris));
+ //terrain->vtris = vert_tris;
+
+ //create_terrain_collision(terrain);
+}
+
void create_terrain(struct terrain *terrain, float scale, int seed) {
u32 i;
+ int n;
+ double x, y, z;
const double size = terrain->size;
- static const double pdist = 24.0;
terrain->settings.seed = seed;
float tmp1[3], tmp2[3];
if (!terrain->n_samples) {
gen_terrain_samples(terrain, scale, pdist);
- /* save_samples(terrain->samples, seed, terrain->n_samples); */
+ //save_samples(terrain->samples, seed, terrain->n_samples);
}
assert(terrain->n_samples > 0);
del_point2d_t *points = calloc(terrain->n_samples, sizeof(*points));
float *verts = calloc(terrain->n_samples * 3, sizeof(*verts));
- terrain->cell_size = pdist;
- terrain->n_cells = round(size / terrain->cell_size) + 1;
- debug("n_cells %d\n", terrain->n_cells);
-
- struct terrain_cell *grid =
- calloc(terrain->n_cells * terrain->n_cells, sizeof(struct terrain_cell));
-
- terrain->grid = grid;
- /* float *normals = calloc(terrain->n_samples * 3, sizeof(*verts)); */
-
- terrain->fn = offset_fn;
-
- // n random samples from our noise function
for (i = 0; i < (u32)terrain->n_samples; i++) {
- int n = i*3;
- double x, y;
- /* double dx, dy; */
-
+ n = i*3;
x = terrain->samples[i].x;
y = terrain->samples[i].y;
double z = terrain->fn(terrain, x, y);
+ double d = distance_to_closest_edge(size, x, y);
+ z *= (d / (size/2.0)) * 2.0;
points[i].x = x;
points[i].y = y;
@@ -249,28 +315,17 @@ void create_terrain(struct terrain *terrain, float scale, int seed) {
verts[n] = (float)x;
verts[n+1] = (float)y;
- int grid_x = verts[n] / terrain->cell_size;
- int grid_y = verts[n+1] / terrain->cell_size;
-
- // clamp height at edge
-
- double d = distance_to_closest_edge(size, x, y);
- z *= (d / (size/2.0)) * 2.0;
-
- struct terrain_cell *cell =
- index_terrain_cell(terrain, grid_x, grid_y);
-
- assert(cell);
-
- insert_grid_vertex(cell, n);
-
static const double limit = 1.4;
if (x < limit || x > size-limit || y < limit || y > size-limit)
- verts[n+2] = 0;
+ verts[n+2] = 0;
else
- verts[n+2] = (float)z;
+ verts[n+2] = (float)z;
}
+ /* float *normals = calloc(terrain->n_samples * 3, sizeof(*verts)); */
+
+ // n random samples from our noise function
+
delaunay2d_t *del = delaunay2d_from(points, terrain->n_samples);
tri_delaunay2d_t *tri = tri_delaunay2d_from(del);
@@ -335,20 +390,27 @@ void create_terrain(struct terrain *terrain, float scale, int seed) {
struct entity *ent = get_entity(&terrain->entity_id);
assert(ent);
- struct make_geometry mkgeom;
- init_make_geometry(&mkgeom);
+ struct mdl_geometry terrain_mdl;
+ init_mdl_geometry(&terrain_mdl);
+
+ struct make_geometry *mkgeom = &terrain_mdl.mkgeom;
- mkgeom.num_verts = num_verts;
- mkgeom.vertices = (float*)del_verts;
- mkgeom.normals = (float*)del_norms;
- mkgeom.indices = (u32*)del_indices;
- mkgeom.num_indices = num_verts;
+ mkgeom->num_verts = num_verts;
+ mkgeom->vertices = (float*)del_verts;
+ mkgeom->normals = (float*)del_norms;
+ mkgeom->indices = (u32*)del_indices;
+ mkgeom->num_indices = num_verts;
struct model *model = get_model(&ent->model_id); assert(model);
struct geometry *geom = get_geometry(&model->geom_id); assert(geom);
- assert(mkgeom.joint_weights == 0);
- make_buffer_geometry(&mkgeom, geom);
+ assert(mkgeom->joint_weights == 0);
+
+ make_buffer_geometry(mkgeom, geom);
+
+ compute_bounding(mkgeom->vertices, mkgeom->num_verts, terrain_mdl.min,
+ terrain_mdl.max);
+ save_mdl("terrain.mdl", &terrain_mdl);
delaunay2d_release(del);
tri_delaunay2d_release(tri);
@@ -363,6 +425,8 @@ void create_terrain(struct terrain *terrain, float scale, int seed) {
terrain->verts = verts;
terrain->n_verts = num_verts;
+ create_terrain_collision(terrain);
+
// we might need norms in memory eventually as well ?
free(del_norms);
free(del_indices);
diff --git a/src/terrain.h b/src/terrain.h
@@ -7,8 +7,8 @@
#include "model.h"
#include "debug.h"
-#define MAX_CELL_VERTS 4
-#define MAX_VERT_TRIS 20
+#define MAX_CELL_VERTS 16
+#define MAX_VERT_TRIS 32
struct point;
@@ -68,6 +68,7 @@ void gen_terrain_samples(struct terrain *terrain, float scale, const double pdis
void init_terrain(struct terrain *terrain, float size);
void reset_terrain(struct terrain *terrain, float size);
void create_terrain(struct terrain *terrain, float scale, int seed);
+void load_terrain(struct terrain *terrain);
void destroy_terrain(struct terrain *terrain);
void query_terrain_grid(struct terrain *terrain, float x, float y, struct terrain_cell *cells[9]);
diff --git a/src/terrain_collision.c b/src/terrain_collision.c
@@ -23,6 +23,8 @@ static void get_closest_verts(struct terrain *terrain,
{
for (int i = 0; i < 9; i++) {
struct terrain_cell *cell = cells[i];
+ if (!cell)
+ continue;
for (int j = 0; j < cell->vert_count; j++) {
vec3 *vpos = &terrain->verts[cell->verts_index[j]];
float d = vec3_distsq(pos, vpos);
diff --git a/src/update.c b/src/update.c
@@ -331,10 +331,13 @@ void orbit_update_from_mouse(struct orbit *camera, struct input *input,
camera->coords.azimuth += mx;
camera->coords.inclination += my;
- /* printf("coords azimuth %f inclination %f radius %f\n", */
- /* camera->coords.azimuth, */
- /* camera->coords.inclination, */
- /* camera->coords.radius); */
+
+ /*
+ printf("coords azimuth %f inclination %f radius %f\n",
+ camera->coords.azimuth,
+ camera->coords.inclination,
+ camera->coords.radius);
+ */
spherical_look_at(&camera->coords, target, cam_node->mat);
@@ -346,7 +349,7 @@ static void camera_keep_above_ground(struct terrain *terrain,
return;
float move[3];
float *camworld = node_world(camera);
- float pen;
+ float pen = 0.0;
static const float penlim = 1.0;
struct tri *tri = collide_terrain(terrain, camworld, move, &pen);
@@ -386,7 +389,7 @@ static void player_update(struct game *game, struct entity *player)
orbit_update_from_mouse(camera, &game->input, game->user_settings.mouse_sens,
player, game->dt);
- camera_keep_above_ground(&game->terrain, cam_node);
+ //camera_keep_above_ground(&game->terrain, cam_node);
// move player camera toward camera orientation
if (input_is_dragging(&game->input, SDL_BUTTON_RIGHT)) {
@@ -400,11 +403,11 @@ static void player_update(struct game *game, struct entity *player)
float move[3];
float pos[3];
- float pen;
+ float pen = 0.0;
vec3_copy(node_world(node), pos);
/* debug("node_world(player) %f %f %f\n", pos[0], pos[1], pos[2]); */
- struct tri *tri = collide_terrain(terrain, pos, move, &pen);
- //struct tri *tri = NULL;
+ //struct tri *tri = collide_terrain(terrain, pos, move, &pen);
+ struct tri *tri = NULL;
/* node_translate(node, move); */
if (tri) {
@@ -414,7 +417,7 @@ static void player_update(struct game *game, struct entity *player)
else if (pen < 0) {
node_translate(node, move);
/* vec3_all(player->velocity, 0); */
- vec3_scale(player->velocity, 0.1, player->velocity);
+ //vec3_scale(player->velocity, 0.1, player->velocity);
}
else {
player->flags &= ~ENT_ON_GROUND;
@@ -461,7 +464,7 @@ void update (struct game *game) {
float *time = &res->time;
float *light = res->light_dir;
- gravity(game);
+ //gravity(game);
if (needs_terrain_update) {
/* update_terrain(terrain); */
diff --git a/tools/compile-model.c b/tools/compile-model.c
@@ -60,7 +60,7 @@ int main(int argc, char *argv[])
int ok = parse_ply_with_mkgeom(filename, &mdl_geom);
assert(ok);
- save_mdl(outfile, &model, &mdl_geom);
+ save_mdl(outfile, &mdl_geom);
return 0;
}