From 678136b970eaa34bf77c3e5c5195f25138bac8b2 Mon Sep 17 00:00:00 2001 From: MallocNull Date: Thu, 21 Jan 2021 19:35:39 -0600 Subject: [PATCH] test commit dont look --- rbm/rbm.py | 88 +++++++++++ rbm/rbs.py | 0 src/data/shaders/mesh.frag | 5 + src/data/shaders/mesh.vert | 5 + src/data/shaders/{test.frag => terrain.frag} | 0 src/data/shaders/{test.vert => terrain.vert} | 0 src/game/object.c | 3 + src/game/object.h | 28 ++++ src/main.c | 133 ++++++++++++----- src/okuu/font.c | 47 +++++- src/okuu/font.h | 4 + src/okuu/mesh.c | 13 +- src/okuu/mesh.h | 2 + src/okuu/obb.c | 56 +++++++ src/okuu/obb.h | 20 +++ src/okuu/terrain.c | 149 +++++++++++++------ src/okuu/terrain.h | 15 +- 17 files changed, 473 insertions(+), 95 deletions(-) create mode 100644 rbm/rbm.py create mode 100644 rbm/rbs.py create mode 100644 src/data/shaders/mesh.frag create mode 100644 src/data/shaders/mesh.vert rename src/data/shaders/{test.frag => terrain.frag} (100%) rename src/data/shaders/{test.vert => terrain.vert} (100%) create mode 100644 src/game/object.c create mode 100644 src/game/object.h create mode 100644 src/okuu/obb.c create mode 100644 src/okuu/obb.h diff --git a/rbm/rbm.py b/rbm/rbm.py new file mode 100644 index 0000000..952ba2a --- /dev/null +++ b/rbm/rbm.py @@ -0,0 +1,88 @@ +import os + +import bpy +import mathutils +import bpy_extras.io_utils + +BASE_PATH = "/home/malloc/Documents/link_test/" + +def bone_id(name: str): + if(len(name) < 3): + return None + + bid = name[0:3] + if(bid[2] != "."): + return None + + try: + bid = int(bid[0:2], 16) + except: + bid = None + return bid + + +def triangulate_mesh(mesh): + import bmesh + bm = bmesh.new() + bm.from_mesh(mesh) + bmesh.ops.triangulate(bm, faces=bm.faces) + bm.to_mesh(mesh) + bm.free() + + +def write_mesh(object): + vertices = weights = normals = texuvs = faces = bones = [] + mesh: bpy.types.Mesh = None + armature: bpy.types.Armature = None + + try: + mesh = object.to_mesh(bpy.data.scenes[0], False, + settings='PREVIEW', calc_tessface=False) + except: + print("Could not copy mesh.") + return + + if object.parent != None and object.parent.type == 'ARMATURE': + armature = object.parent.data + bones = [(bone_id(group.name), armature.bones[group.name]) + for group in object.vertex_groups] + check = [bone for bone in bones if bone[0] == None] + if len(check) > 0: + for bone in check: + print("Bone", bone[1].name, "is not named according to format 'XX.NAME'") + return + + triangulate_mesh(mesh) + mesh.transform(object.matrix_world) + + if(object.matrix_world.determinant() < 0.0): + mesh.flip_normals() + mesh.calc_normals_split() + + vertices = mesh.vertices[:] + if armature: + weights = [list( + (group.group, group.weight) + for group in vertex.groups) + for vertex in vertices] + normals = [vertex.normal for vertex in vertices] + + + tris = [(i, tri) for i, tri in enumerate(mesh.polygons)] + for i, tri in tris: + + + bpy.data.meshes.remove(mesh) + + +def write_armature(object): + pass + +#fw(b"\xDE\xAF\xB0\x0B") + +os.makedirs(BASE_PATH, exist_ok=True) +for object in bpy.data.objects: + if object.type == 'MESH' : + write_mesh(object) + elif object.type == 'ARMATURE': + write_armature(object) diff --git a/rbm/rbs.py b/rbm/rbs.py new file mode 100644 index 0000000..e69de29 diff --git a/src/data/shaders/mesh.frag b/src/data/shaders/mesh.frag new file mode 100644 index 0000000..eb84f43 --- /dev/null +++ b/src/data/shaders/mesh.frag @@ -0,0 +1,5 @@ +#version 100 + +void main() { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); +} diff --git a/src/data/shaders/mesh.vert b/src/data/shaders/mesh.vert new file mode 100644 index 0000000..591d745 --- /dev/null +++ b/src/data/shaders/mesh.vert @@ -0,0 +1,5 @@ +#version 100 + +void main() { + gl_Position = vec4(vec3(0.0), 1.0); +} diff --git a/src/data/shaders/test.frag b/src/data/shaders/terrain.frag similarity index 100% rename from src/data/shaders/test.frag rename to src/data/shaders/terrain.frag diff --git a/src/data/shaders/test.vert b/src/data/shaders/terrain.vert similarity index 100% rename from src/data/shaders/test.vert rename to src/data/shaders/terrain.vert diff --git a/src/game/object.c b/src/game/object.c new file mode 100644 index 0000000..0a58334 --- /dev/null +++ b/src/game/object.c @@ -0,0 +1,3 @@ +#include "object.h" + + diff --git a/src/game/object.h b/src/game/object.h new file mode 100644 index 0000000..257603a --- /dev/null +++ b/src/game/object.h @@ -0,0 +1,28 @@ +#ifndef SOSC_OBJECT_H +#define SOSC_OBJECT_H + +#include +#include "okuu/mesh.h" + +typedef struct { + mesh_t* mesh; + mat4 translate, scale, rotate; +} object_t; + +void object_create(mesh_t*); + +void object_reset_matrices(object_t*); +void object_reset_translate(object_t*); +void object_reset_scale(object_t*); +void object_reset_rotate(object_t*); + +void object_translate(object_t*, vec3); +void object_scale(object_t*, vec3, float); +void object_scale_uni(object_t*, vec3, float); +void object_rotate(object_t*, vec3, float); +void object_ +void object_model_matrix(object_t*, mat4); + +void object_destroy(object_t*); + +#endif diff --git a/src/main.c b/src/main.c index bcd6669..ef9e001 100644 --- a/src/main.c +++ b/src/main.c @@ -23,7 +23,6 @@ struct { int mode, running; int mouse[3]; - vec2 tlocs[10]; font_t* scape; text_t* text; mesh_t* monkey; @@ -44,13 +43,6 @@ int init(); void deinit(); void run(); -void reset_text_locs() { - for(int i = 0; i < 10; ++i) { - _g.tlocs[i][0] = rand() % (WINDOW_WIDTH / 2); - _g.tlocs[i][1] = rand() % WINDOW_HEIGHT; - } -} - int main(int argc, char* argv[]) { if(init() < 0) return -1; @@ -58,23 +50,27 @@ int main(int argc, char* argv[]) { font_init_subsystem(_g.window); _g.scape = font_load( - "data/fonts/scape.bmp", - "data/fonts/scape.dat", + "data/fonts/scape2.bmp", + "data/fonts/scape2.dat", GL_NEAREST ); font_set_default(_g.scape); _g.text = text_create(NULL); - text_set(_g.text, "flashwave is cool !!!"); - text_set_size(_g.text, 32); - text_set_rgb_hex(_g.text, 0x55007e); - reset_text_locs(); + //text_set(_g.text, "Welcome to Rune2006"); + text_set_size(_g.text, 16); + text_set_rgb_hex(_g.text, 0xffff00); _g.monkey = mesh_load("data/models/player.rbm"); + color_t path_colors[] = { + {0x60, 0x60, 0x60, 0xFF}, + {0x9C, 0x00, 0x0E, 0xFF} + }; _g.map = terrain_load( "data/terrains/map-heights.bmp", "data/terrains/map-colors.bmp", + path_colors, sizeof(path_colors) / sizeof(color_t), 10, 10 ); @@ -83,8 +79,8 @@ int main(int argc, char* argv[]) { "vertex", "texuv", "normal", "color" ); shader_source(_s_def.shader, SHADER_FILE, 2, - "data/shaders/test.vert", GL_VERTEX_SHADER, - "data/shaders/test.frag", GL_FRAGMENT_SHADER + "data/shaders/terrain.vert", GL_VERTEX_SHADER, + "data/shaders/terrain.frag", GL_FRAGMENT_SHADER ); shader_attribs(_s_def.shader, 3, "model", "view", "projection" @@ -100,13 +96,18 @@ int main(int argc, char* argv[]) { } void run() { - static mat4 model, map, view, projection; + static mat4 model, map, view, projection, mario; + static vec3 center, eye, pick; static float rot_up = 45, rot_around = 45; static float x = 0, y = 0; + static char debug[256] = ""; static int init = 1; if(init) { //glm_rotate_make(model, glm_rad(90), (vec3){ 0.f, -1.f, 0.f }); + //glm_translate_make(mario, (vec3){ 4.f, 4.f, 4.f }); + glm_scale_make(mario, (vec3){ 3.f, 3.f, 3.f }); + glm_mat4_identity(model); glm_mat4_identity(map); @@ -133,37 +134,43 @@ void run() { glClearColor(0.f, 0.f, 0.5f, 0.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + center[0] = -x; + center[1] = -(terrain_height(_g.map, x, y) + 2.f); + center[2] = -y; + float radius = 4.f + 4.f * (rot_up / 90.f); + eye[0] = cos(glm_rad(rot_up)) * radius * cos(glm_rad(rot_around)); + eye[1] = radius * sin(glm_rad(rot_up)); + eye[2] = cos(glm_rad(rot_up)) * radius * sin(glm_rad(rot_around)); + glm_lookat( - (vec3){ - cos(glm_rad(rot_up)) * radius * cos(glm_rad(rot_around)), - radius * sin(glm_rad(rot_up)), - cos(glm_rad(rot_up)) * radius * sin(glm_rad(rot_around)) - }, + eye, (vec3){0.f, 0.f, 0.f}, (vec3){0.f, 1.f, 0.f}, view ); - for(int i = 0; i < 10; ++i) { - text_move(_g.text, _g.tlocs[i]); - text_render(_g.text); - } + glm_translate(view, center); + glm_vec3_inv(center); + + text_set_rgb_hex(_g.text, 0xffff00); + text_shadow_xy(_g.text, 1, 1); shader_start(_s_def.shader); { glUniformMatrix4fv(_ATTR(DEF_VIEW), 1, GL_FALSE, (float*)view); - glm_translate_make(model, (vec3){-x, -(_g.map->heights[(int)y][(int)x] + 2.f), -y}); - glm_mat4_mul(model, map, model); - glUniformMatrix4fv(_ATTR(DEF_MODEL), 1, GL_FALSE, (float*)model); + glUniformMatrix4fv(_ATTR(DEF_MODEL), 1, GL_FALSE, (float*)map); glBindVertexArray(_g.map->vao); glDrawArrays(GL_TRIANGLES, 0, _g.map->tri_cnt * 3); + + glUniformMatrix4fv(_ATTR(DEF_MODEL), 1, GL_FALSE, (float*)mario); + mesh_bind(_g.monkey); + mesh_render(_g.monkey); + glBindVertexArray(0); } shader_stop(); - SDL_GL_SwapWindow(_g.window); - SDL_PumpEvents(); if(_g.keys[SDL_SCANCODE_ESCAPE]) @@ -198,17 +205,65 @@ void run() { else if(_g.keys[SDL_SCANCODE_A]) y -= .25; - if(_g.keys[SDL_SCANCODE_SPACE]) { + //if(_g.keys[SDL_SCANCODE_SPACE]) { terrain_move(_g.map, x, y); - glm_translate_make(map, (vec3){__MAX(0, x - CHUNK_SIZE / 2), 0, __MAX(0, y - CHUNK_SIZE / 2)}); - } - - if(_g.keys[SDL_SCANCODE_P]) - reset_text_locs(); + glm_translate_make(map, (vec3){_g.map->top_x, 0, _g.map->top_y}); + //} _g.mouse[2] = SDL_GetMouseState(&_g.mouse[0], &_g.mouse[1]); - if(_g.mouse[2] & SDL_BUTTON(SDL_BUTTON_LEFT)) { + float mx = (float)_g.mouse[0] / (float)WINDOW_WIDTH; + float my = (float)_g.mouse[1] / (float)WINDOW_HEIGHT; + vec4 mouse = {mx * 2 - 1, (1 - my) * 2 - 1, -1.f, 1.f}; + mat4 imat; + sprintf(debug, "NDC (%f, %f, %f, %f)", mouse[0], mouse[1], mouse[2], mouse[3]); + text_set(_g.text, debug); + text_move_xy(_g.text, 4, 4); + text_render(_g.text); + + glm_mat4_inv(projection, imat); + glm_mat4_mulv(imat, mouse, mouse); + mouse[2] = -1.f; + mouse[3] = 0.f; + + sprintf(debug, "EYE (%f, %f, %f, %f)", mouse[0], mouse[1], mouse[2], mouse[3]); + text_set(_g.text, debug); + text_move_xy(_g.text, 4, 24); + text_render(_g.text); + + glm_mat4_inv(view, imat); + glm_mat4_mulv(imat, mouse, mouse); + glm_vec4_normalize(mouse); + + sprintf(debug, "WORLD (%f, %f, %f, %f)", mouse[0], mouse[1], mouse[2], mouse[3]); + text_set(_g.text, debug); + text_move_xy(_g.text, 4, 44); + text_render(_g.text); + + vec3 pcam; + glm_vec3_copy(center, pcam); + + sprintf(debug, "PL1LOC (%f, %f, %f)", pcam[0], pcam[1], pcam[2]); + text_set(_g.text, debug); + text_move_xy(_g.text, 4, 64); + text_render(_g.text); + + glm_vec3_add(eye, pcam, pcam); + + sprintf(debug, "CAMLOC (%f, %f, %f)", pcam[0], pcam[1], pcam[2]); + text_set(_g.text, debug); + text_move_xy(_g.text, 4, 84); + text_render(_g.text); + + if(_g.mouse[2] & SDL_BUTTON(SDL_BUTTON_LEFT)) { + if(terrain_pick(_g.map, (vec3){ mouse[0], mouse[1], mouse[2] }, pcam, pick)) { + //glm_scale_make(mario, (vec3){ 3.f, 3.f, 3.f }); + pick[0] = (int)pick[0] + 0.5f; + pick[1] += 1.f; + pick[2] = (int)pick[2] + 0.5f; + glm_translate_make(mario, pick); + glm_scale(mario, (vec3){2.f, 2.f, 2.f}); + } } SDL_Event ev; @@ -239,6 +294,8 @@ void run() { }*/ } + + SDL_GL_SwapWindow(_g.window); } int init() { diff --git a/src/okuu/font.c b/src/okuu/font.c index d0fdcec..6cacf43 100644 --- a/src/okuu/font.c +++ b/src/okuu/font.c @@ -179,6 +179,8 @@ text_t* text_create(font_t* font) { text->vert_inv = text->texuv_inv = 1; + glm_vec2_fill(text->shadow, 0.f); + glm_mat4_identity(text->trans_mat); glGenVertexArrays(1, &text->vao); glGenBuffers(2, text->buffers); @@ -269,13 +271,14 @@ void text_set_rgba_hex(text_t* text, uint32_t color) { } void text_move(text_t* text, vec2 coords) { - vec3 coords3 = { coords[0], coords[1], 0.f }; - glm_translate_make(text->trans_mat, coords3); + glm_translate_make( + text->trans_mat, + (vec3){ coords[0], coords[1], 0.f } + ); } void text_move_xy(text_t* text, float x, float y) { - vec2 coords = { x, y }; - text_move(text, coords); + text_move(text, (vec2){ x, y }); } void text_wrap(text_t* text, uint32_t wrap) { @@ -283,6 +286,14 @@ void text_wrap(text_t* text, uint32_t wrap) { text->vert_inv = 1; } +void text_shadow(text_t* text, vec2 offset) { + glm_vec2_copy(offset, text->shadow); +} + +void text_shadow_xy(text_t* text, float x, float y) { + text_shadow(text, (vec2){ x, y }); +} + void text_redraw(text_t* text) { if(!text->vert_inv && !text->texuv_inv) return; @@ -391,9 +402,34 @@ void text_redraw(text_t* text) { } void text_render(text_t* text) { + const vec4 shadow = { 0.f, 0.f, 0.f, 1.f }; + mat4 trans_shadow; + text_redraw(text); shader_start(_ss.shader); + glActiveTexture(GL_TEXTURE0); + font_bind(text->font); + glBindVertexArray(text->vao); + + if(text->shadow[0] != 0 || text->shadow[1] != 0) { + glm_translate_make(trans_shadow, + (vec3){ text->shadow[0], text->shadow[1], -0.1f }); + glm_mat4_mul(trans_shadow, text->trans_mat, trans_shadow); + + glUniformMatrix4fv( + _ATTR(FONT_TRANS), + 1, GL_FALSE, + (float*)trans_shadow + ); + glUniform4fv( + _ATTR(FONT_COLOR), 1, + (float*)shadow + ); + + glDrawArrays(GL_TRIANGLES, 0, text->tri_cnt * 3); + } + glUniformMatrix4fv( _ATTR(FONT_TRANS), 1, GL_FALSE, @@ -403,10 +439,7 @@ void text_render(text_t* text) { _ATTR(FONT_COLOR), 1, (float*)text->color ); - glActiveTexture(GL_TEXTURE0); - font_bind(text->font); - glBindVertexArray(text->vao); glDrawArrays(GL_TRIANGLES, 0, text->tri_cnt * 3); } diff --git a/src/okuu/font.h b/src/okuu/font.h index 9366f14..c8543e9 100644 --- a/src/okuu/font.h +++ b/src/okuu/font.h @@ -35,6 +35,7 @@ typedef struct { uint32_t length, size, wrap, tri_cnt; + vec2 shadow; mat4 trans_mat; GLuint vao, buffers[2]; @@ -67,6 +68,9 @@ void text_move(text_t*, vec2); void text_move_xy(text_t*, float, float); void text_wrap(text_t*, uint32_t); +void text_shadow(text_t*, vec2); +void text_shadow_xy(text_t*, float, float); + void text_redraw(text_t*); void text_render(text_t*); diff --git a/src/okuu/mesh.c b/src/okuu/mesh.c index 67cce46..2e58ae7 100644 --- a/src/okuu/mesh.c +++ b/src/okuu/mesh.c @@ -9,8 +9,9 @@ typedef struct { } _tri_t; int _populate_pts - (_pt_t* data, FILE* fp, uint32_t length, int width) + (_pt_t* data, obb_t* obb, FILE* fp, uint32_t length, int width) { + obb_clear(obb); uint8_t buffer[4]; int chk; @@ -22,6 +23,8 @@ int _populate_pts data[i].data[j] = *(float*)ltoh(buffer, 4); } + + obb_parse_point(obb, data[i].data); } return 1; @@ -84,12 +87,13 @@ mesh_t* mesh_load(const char* file) { _tri_t *faces = malloc(sizeof(_tri_t) * counts[FACE_CNT]); int chk = 1; + obb_t obb; - chk &= _populate_pts(verts, fp, counts[VERT_CNT], 3); + chk &= _populate_pts(verts, &obb, fp, counts[VERT_CNT], 3); if(counts[TEX_CNT] > 0) - chk &= _populate_pts(texs, fp, counts[TEX_CNT], 2); + chk &= _populate_pts(texs, NULL, fp, counts[TEX_CNT], 2); if(counts[NORM_CNT] > 0) - chk &= _populate_pts(norms, fp, counts[NORM_CNT], 3); + chk &= _populate_pts(norms, NULL, fp, counts[NORM_CNT], 3); int index_length = counts[FACE_CNT] <= 0xFFFF ? 2 : 4; for(uint32_t i = 0; i < counts[FACE_CNT]; ++i) { @@ -201,6 +205,7 @@ mesh_t* mesh_load(const char* file) { glBindBuffer(GL_ARRAY_BUFFER, 0); mesh->tri_cnt = counts[FACE_CNT]; + mesh->obb = obb; return mesh; } diff --git a/src/okuu/mesh.h b/src/okuu/mesh.h index 1590e52..64f0f8a 100644 --- a/src/okuu/mesh.h +++ b/src/okuu/mesh.h @@ -11,11 +11,13 @@ #include #include +#include "obb.h" #include "koa/etc.h" typedef struct { GLuint buffers[3], vao; uint32_t tri_cnt; + obb_t obb; } mesh_t; mesh_t* mesh_load(const char*); diff --git a/src/okuu/obb.c b/src/okuu/obb.c new file mode 100644 index 0000000..82e64f5 --- /dev/null +++ b/src/okuu/obb.c @@ -0,0 +1,56 @@ +#include "obb.h" + +void obb_from_center(obb_t* obb, vec3 center, vec3 bounds) { + vec3 cbound; + + glm_vec3_abs(bounds, cbound); + glm_vec3_scale(cbound, 0.5f, cbound); + glm_vec3_sub(center, cbound, obb->min); + glm_vec3_add(center, cbound, obb->max); +} + +void obb_from_min(obb_t* obb, vec3 min, vec3 bounds) { + vec3 cbound; + + glm_vec3_abs(bounds, cbound); + glm_vec3_copy(min, obb->min); + glm_vec3_add(min, cbound, obb->max); +} + +void obb_from_max(obb_t* obb, vec3 max, vec3 bounds) { + vec3 cbound; + + glm_vec3_abs(bounds, cbound); + glm_vec3_copy(max, obb->max); + glm_vec3_sub(max, cbound, obb->min); +} + +void obb_clear(obb_t* obb) { + if(obb == NULL) + return; + + obb->min[0] = + obb->min[1] = + obb->min[2] = + obb->max[0] = + obb->max[1] = + obb->max[2] = NAN; +} + +void obb_parse_point(obb_t* obb, vec3 pt) { + if(obb == NULL) + return; + + if(obb->min[0] == NAN) { + glm_vec3_copy(pt, obb->min); + glm_vec3_copy(pt, obb->max); + } else { + obb->min[0] = __MIN(obb->min[0], pt[0]); + obb->min[1] = __MIN(obb->min[1], pt[1]); + obb->min[2] = __MIN(obb->min[2], pt[2]); + + obb->max[0] = __MIN(obb->max[0], pt[0]); + obb->max[1] = __MIN(obb->max[1], pt[1]); + obb->max[2] = __MIN(obb->max[2], pt[2]); + } +} \ No newline at end of file diff --git a/src/okuu/obb.h b/src/okuu/obb.h new file mode 100644 index 0000000..8e193de --- /dev/null +++ b/src/okuu/obb.h @@ -0,0 +1,20 @@ +#ifndef OKUU_OBB_H +#define OKUU_OBB_H + +#include +#include "koa/etc.h" + +typedef struct { + vec3 min, max; +} obb_t; + +void obb_from_center(obb_t*, vec3, vec3); +void obb_from_min(obb_t*, vec3, vec3); +void obb_from_max(obb_t*, vec3, vec3); + +void obb_clear(obb_t*); +void obb_parse_point(obb_t*, vec3); + +//int obb_pick(obb_t*, ...) + +#endif diff --git a/src/okuu/terrain.c b/src/okuu/terrain.c index 1fbd390..73dfafe 100644 --- a/src/okuu/terrain.c +++ b/src/okuu/terrain.c @@ -1,5 +1,7 @@ #include "terrain.h" +#define _TOP(A) (__MAX(0, A - CHUNK_SIZE / 2)) + #define _HGT_AT(A, X, Y) (A->bmps[0]->pixels[Y][X][_R_] / 10.f) #define _RWCOL_AT(A, X, Y) (A->bmps[1]->pixels[Y][X]) #define _RCOL_AT(A, X, Y, C) (_RWCOL_AT(A, X, Y)[C]) @@ -16,10 +18,11 @@ float _avg_hgt(terrain_t* map, int x, int y) { terrain_t* terrain_load (const char* heights, const char* colors, + const color_t* paths, int path_cnt, int center_x, int center_y) { - int top_x = __MAX(0, center_x - CHUNK_SIZE / 2), - top_y = __MAX(0, center_y - CHUNK_SIZE / 2); + int top_x = _TOP(center_x), + top_y = _TOP(center_y); bmp_t* heights_bmp = bmp_load_chunk(heights, top_x, top_y, CHUNK_SIZE, CHUNK_SIZE); @@ -36,41 +39,57 @@ terrain_t* terrain_load terrain_t* terrain = malloc(sizeof(terrain_t)); terrain->bmps[0] = heights_bmp; terrain->bmps[1] = colors_bmp; - terrain->center_x = terrain->center_y = -1; + terrain->top_x = terrain->top_y = -1; + + terrain->pick_dist = 20.f; + terrain->pick_depth = 10; + + terrain->paths = NULL; + terrain->path_cnt = 0; + + if(paths != NULL && path_cnt > 0) { + terrain->paths = malloc(sizeof(color_t) * path_cnt); + memcpy(terrain->paths, paths, sizeof(color_t) * path_cnt); + terrain->path_cnt = path_cnt; + } terrain_move(terrain, center_x, center_y); return terrain; } void terrain_move(terrain_t* terrain, int center_x, int center_y) { - int new_terrain = terrain->center_x == -1 || terrain->center_y == -1; + int new_terrain = + terrain->top_x == -1 + || terrain->top_y == -1; + + terrain->top_x = _TOP(center_x); + terrain->top_y = _TOP(center_y); if(new_terrain) { glGenVertexArrays(1, &terrain->vao); glGenBuffers(TERR_BUFFS, terrain->buffers); } else { - int top_x = __MAX(0, center_x - CHUNK_SIZE / 2), - top_y = __MAX(0, center_y - CHUNK_SIZE / 2); - bmp_reload_chunk - (terrain->bmps[0], top_x, top_y, CHUNK_SIZE, CHUNK_SIZE); + (terrain->bmps[0], terrain->top_x, terrain->top_y, + CHUNK_SIZE, CHUNK_SIZE); bmp_reload_chunk - (terrain->bmps[1], top_x, top_y, CHUNK_SIZE, CHUNK_SIZE); + (terrain->bmps[1], terrain->top_x, terrain->top_y, + CHUNK_SIZE, CHUNK_SIZE); } - terrain->center_x = center_x; - terrain->center_y = center_y; + terrain->width = terrain->bmps[0]->width; + terrain->height = terrain->bmps[0]->height; const int data_length = 12 * 3 * (CHUNK_SIZE - 1) * (CHUNK_SIZE - 1); - terrain->tri_cnt = data_length / 3; + terrain->tri_cnt = 4 * (terrain->width - 1) * (terrain->height - 1); float data[data_length]; - vec3 dir1, dir2, norm1, norm2, norm3; + vec3 dir1, dir2, norm; for(int i = 0; i < TERR_BUFFS; ++i) { int cnt = i == 1 ? 2 : 3; - for(int y = 0; y < CHUNK_SIZE - 1; ++y) { - for(int x = 0; x < CHUNK_SIZE - 1; ++x) { - int at = (y * (CHUNK_SIZE - 1) * 12 * cnt) + (x * 12 * cnt); + for(int y = 0; y < terrain->height - 1; ++y) { + for(int x = 0; x < terrain->width - 1; ++x) { + int at = (y * (terrain->width - 1) * 12 * cnt) + (x * 12 * cnt); switch(i) { case 0: @@ -177,11 +196,11 @@ void terrain_move(terrain_t* terrain, int center_x, int center_y) { (vec3){ x + 1, _HGT_AT(terrain, x + 1, y), y }, dir2 ); - glm_vec3_cross(dir1, dir2, norm1); - glm_vec3_normalize(norm1); - memcpy(&data[at], norm1, 3 * sizeof(float)); - memcpy(&data[at + 3], norm1, 3 * sizeof(float)); - memcpy(&data[at + 6], norm1, 3 * sizeof(float)); + glm_vec3_cross(dir1, dir2, norm); + glm_vec3_normalize(norm); + memcpy(&data[at], norm, 3 * sizeof(float)); + memcpy(&data[at + 3], norm, 3 * sizeof(float)); + memcpy(&data[at + 6], norm, 3 * sizeof(float)); glm_vec3_sub( (vec3){ x + 1, _HGT_AT(terrain, x + 1, y), y }, @@ -193,11 +212,11 @@ void terrain_move(terrain_t* terrain, int center_x, int center_y) { (vec3){ x + 1, _HGT_AT(terrain, x + 1, y + 1), y + 1 }, dir2 ); - glm_vec3_cross(dir1, dir2, norm1); - glm_vec3_normalize(norm1); - memcpy(&data[at + 9], norm1, 3 * sizeof(float)); - memcpy(&data[at + 12], norm1, 3 * sizeof(float)); - memcpy(&data[at + 15], norm1, 3 * sizeof(float)); + glm_vec3_cross(dir1, dir2, norm); + glm_vec3_normalize(norm); + memcpy(&data[at + 9], norm, 3 * sizeof(float)); + memcpy(&data[at + 12], norm, 3 * sizeof(float)); + memcpy(&data[at + 15], norm, 3 * sizeof(float)); glm_vec3_sub( (vec3){ x + 1, _HGT_AT(terrain, x + 1, y + 1), y + 1 }, @@ -209,11 +228,11 @@ void terrain_move(terrain_t* terrain, int center_x, int center_y) { (vec3){ x, _HGT_AT(terrain, x, y + 1), y + 1 }, dir2 ); - glm_vec3_cross(dir1, dir2, norm1); - glm_vec3_normalize(norm1); - memcpy(&data[at + 18], norm1, 3 * sizeof(float)); - memcpy(&data[at + 21], norm1, 3 * sizeof(float)); - memcpy(&data[at + 24], norm1, 3 * sizeof(float)); + glm_vec3_cross(dir1, dir2, norm); + glm_vec3_normalize(norm); + memcpy(&data[at + 18], norm, 3 * sizeof(float)); + memcpy(&data[at + 21], norm, 3 * sizeof(float)); + memcpy(&data[at + 24], norm, 3 * sizeof(float)); glm_vec3_sub( (vec3){ x, _HGT_AT(terrain, x, y), y }, @@ -225,11 +244,11 @@ void terrain_move(terrain_t* terrain, int center_x, int center_y) { (vec3){ x, _HGT_AT(terrain, x, y + 1), y + 1 }, dir2 ); - glm_vec3_cross(dir2, dir1, norm1); - glm_vec3_normalize(norm1); - memcpy(&data[at + 27], norm1, 3 * sizeof(float)); - memcpy(&data[at + 30], norm1, 3 * sizeof(float)); - memcpy(&data[at + 33], norm1, 3 * sizeof(float)); + glm_vec3_cross(dir2, dir1, norm); + glm_vec3_normalize(norm); + memcpy(&data[at + 27], norm, 3 * sizeof(float)); + memcpy(&data[at + 30], norm, 3 * sizeof(float)); + memcpy(&data[at + 33], norm, 3 * sizeof(float)); glm_vec3_add( data + at + 3, @@ -258,14 +277,14 @@ void terrain_move(terrain_t* terrain, int center_x, int center_y) { data[at + j * 3 + 2] = _COL_AT(terrain, x, y, _B_); } - const color_t path_colors[] = { - {0x60, 0x60, 0x60, 0xFF}, - {0x9C, 0x00, 0x0E, 0xFF} - }; + if(terrain->paths == NULL) + continue; int found = 0; - for(int j = 0; j < sizeof(path_colors) / sizeof(color_t); ++j) { - if(color_eqp(path_colors[j], _RWCOL_AT(terrain, x, y))) { + for(int j = 0; j < terrain->path_cnt; ++j) { + if(color_eqp(terrain->paths[j], + _RWCOL_AT(terrain, x, y))) + { found = 1; break; } @@ -339,7 +358,7 @@ void terrain_move(terrain_t* terrain, int center_x, int center_y) { } else { glBufferSubData( GL_ARRAY_BUFFER, 0, - data_length * sizeof(float), + terrain->tri_cnt * 3 * 3 * sizeof(float), data ); } @@ -348,6 +367,50 @@ void terrain_move(terrain_t* terrain, int center_x, int center_y) { glBindBuffer(GL_ARRAY_BUFFER, 0); } +float terrain_height(terrain_t* terrain, int x, int y) { + x -= terrain->top_x; + y -= terrain->top_y; + + if(x < 0 || y < 0 || x >= terrain->width || y >= terrain->height) + return NAN; + + return terrain->heights[y][x]; +} + +void terrain_pick_params(terrain_t* terrain, float distance, int depth) { + terrain->pick_dist = distance; + terrain->pick_depth = depth; +} + +int terrain_pick + (terrain_t* terrain, vec3 ray, vec3 camera, vec3 out) +{ + int intersect = 0; + float t = terrain->pick_dist / 2.f, delta = t; + + for(int i = 0; i < terrain->pick_depth; ++i) { + delta /= 2; + glm_vec3_scale(ray, t, out); + glm_vec3_add(out, camera, out); + + float height = terrain_height(terrain, out[0], out[2]); + if(height == NAN) + t = t - delta; + else { + if(height < out[1]) + t = t + delta; + else { + intersect = 1; + t = t - delta; + } + + out[1] = height; + } + } + + return intersect; +} + void terrain_unload(terrain_t* terrain) { bmp_unload(terrain->bmps[0]); bmp_unload(terrain->bmps[1]); diff --git a/src/okuu/terrain.h b/src/okuu/terrain.h index 2e04bed..dc9a13f 100644 --- a/src/okuu/terrain.h +++ b/src/okuu/terrain.h @@ -14,18 +14,27 @@ #include "koa/file.h" -#define CHUNK_SIZE 100 +#define CHUNK_SIZE 20 #define TERR_BUFFS 4 typedef struct { bmp_t* bmps[2]; - int center_x, center_y, tri_cnt; + color_t* paths; + int top_x, top_y, width, height, + tri_cnt, path_cnt; float heights[CHUNK_SIZE][CHUNK_SIZE]; GLuint buffers[TERR_BUFFS], vao; + + float pick_dist; + int pick_depth; } terrain_t; -terrain_t* terrain_load(const char*, const char*, int, int); +terrain_t* terrain_load + (const char*, const char*, const color_t*, int, int, int); void terrain_move(terrain_t*, int, int); +float terrain_height(terrain_t*, int, int); +void terrain_pick_params(terrain_t*, float, int); +int terrain_pick(terrain_t*, vec3, vec3, vec3); void terrain_unload(terrain_t*); #endif