diff --git a/data/scene_schema.json b/data/scene_schema.json index 83c44b5..a74bdc6 100644 --- a/data/scene_schema.json +++ b/data/scene_schema.json @@ -39,9 +39,11 @@ "camera": { "type": "object", "properties": { - "position" : { "$ref": "#/definitions/vector3" }, - "rotation" : { "$ref": "#/definitions/vector4" } - } + "position": { "$ref": "#/definitions/vector3" }, + "target": { "$ref": "#/definitions/vector3" }, + "up": { "$ref": "#/definitions/vector3" } + }, + "required": ["position", "target", "up"] }, "hex_grid" : { diff --git a/data/test_scene.json b/data/test_scene.json index f414ccc..386ae31 100644 --- a/data/test_scene.json +++ b/data/test_scene.json @@ -1,16 +1,19 @@ { "camera" : { "position" : { - "x" : 0, + "x" : 640, "y" : 0, + "z" : 100 + }, + "target" : { + "x" : 640, + "y" : 500, "z" : 0 }, - - "rotation" : { + "up" : { "x" : 0, - "y" : 0, - "z" : 0, - "w" : 0 + "y" : 1, + "z" : 0 } }, @@ -25,7 +28,7 @@ "name" : "catepillar 1", "model_file" : "catepillar.dae", "position" : { - "x" : 640, + "x" : 740, "y" : 500, "z" : 0 }, diff --git a/src/camera.cpp b/src/camera.cpp new file mode 100644 index 0000000..791d3dc --- /dev/null +++ b/src/camera.cpp @@ -0,0 +1,28 @@ + +#include "camera.h" + + +void +cameraInitPerspective(camera& cam, glm::vec3 position, glm::vec3 target, glm::vec3 up) +{ + cam.position = position; + cam.target = target; + cam.up = up; + cam.projection = glm::infinitePerspective(glm::radians(FOV), ASPECT_RATIO, NEAR_CLIP_PLANE); + + cam.hAngle = 0; + cam.vAngle = glm::atan((cam.target.z - cam.position.z) / (cam.target.y - cam.position.y)); + + // FIXME: bug, camera always starts with forward pointing at positive 'z' axis + cam.forward = glm::normalize(glm::vec3( + glm::cos(cam.vAngle) * glm::sin(cam.hAngle), + glm::cos(cam.vAngle) * glm::cos(cam.hAngle), + glm::sin(cam.vAngle) + )); + cam.left = glm::normalize(glm::cross(cam.up, cam.forward)); + cam.up = glm::normalize(glm::cross(cam.forward, cam.left)); // get better "up" vector + + cam.view = glm::lookAt(cam.position, cam.position + cam.forward, cam.up); + cam.model = glm::mat4(1.0f); + cam.MVP = cam.projection * cam.view * cam.model; +} diff --git a/src/camera.h b/src/camera.h new file mode 100644 index 0000000..ddfa375 --- /dev/null +++ b/src/camera.h @@ -0,0 +1,41 @@ + +#pragma once +#include +#include +#include "util.h" + +// TODO: move other camera functions here from renderer.h and pass in camera references +// TODO: store scene matrices on camera struct instead of global in renderer.h + + +#define FOV 60.f +#define ASPECT_RATIO 16.f/9.f +#define NEAR_CLIP_PLANE 0.1f + +struct camera +{ + glm::vec3 position; + float hAngle; + float vAngle; + glm::vec3 target; + glm::vec3 forward; + glm::vec3 up; + glm::vec3 left; + + glm::mat4 model; + glm::mat4 view; + glm::mat4 projection; + glm::mat4 MVP; +}; + +enum projection_type +{ + PERSPECTIVE, + ORTHOGRAPHIC, +}; + + +void cameraInitPerspective(camera& cam, glm::vec3 position, glm::vec3 target, glm::vec3 up); +void cameraMove(bool up, bool left, bool down, bool right, bool forward, bool backward); +void CameraRotate(int32 xrel, int32 yrel); +void cameraRoll(bool CW, bool CCW); diff --git a/src/hexgame.cpp b/src/hexgame.cpp index dd12197..6a109d0 100644 --- a/src/hexgame.cpp +++ b/src/hexgame.cpp @@ -563,7 +563,7 @@ int main(int argc, char* argv[]) // testing scene_loader if (slLoadFile(DATA_DIR, DEFAULT_SCENE_FILE, SCENE_SCHEMA_FILE, - g_game_state->entities, g_game_state->entity_count, 1000)) + g_game_state->entities, g_game_state->entity_count, 1000, renGetCamera())) { // ??? } else { diff --git a/src/renderer.cpp b/src/renderer.cpp index 6e321b1..181d28d 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -20,7 +20,6 @@ #include "aixlog.hpp" #include "hexlib.h" -#include "hexgame.h" #include "renderer.h" #include "render_group.h" @@ -49,23 +48,6 @@ typedef struct gl_matrix_info glm::mat4 MVP; } gl_matrix_info; -enum projection_type -{ - PERSPECTIVE, - ORTHOGRAPHIC, -}; - -struct camera -{ - glm::vec3 position; - float hAngle; - float vAngle; - glm::vec3 target; - glm::vec3 forward; - glm::vec3 up; - glm::vec3 left; -}; - // forward declarations void initMatrices(projection_type p); @@ -192,6 +174,12 @@ addTexture(SDL_Handles &handles, const char * path) return true; } +camera& +renGetCamera() +{ + return g_camera; +} + v2f getUnprojectedCoords(int32 x, int32 y, int32 vp_width, int32 vp_height) { @@ -222,6 +210,7 @@ createScene(std::vector* hexes, Entity* entities, uint32 entity_count) entities[i].ren_group->shader = g_default_shader; } + // TODO: rename/alter this now that we init camera in sceneloader initMatrices(PROJ_TYPE); if (!initHexGridBuffers(hexes)) @@ -416,6 +405,12 @@ initMatrices(projection_type p) if (p == PERSPECTIVE) { + // TODO: replace referernces to g_scene_matrices with camera.matrix_name + g_scene_matrices.projection = g_camera.projection; + g_scene_matrices.view = g_camera.view; + //g_scene_matrices.model = g_camera.model; + //g_scene_matrices.MVP = g_camera.MVP; +#if 0 g_scene_matrices.projection = glm::infinitePerspective( glm::radians(60.f), // FoV 16.f / 9.f, // ascpect ratio @@ -454,6 +449,7 @@ initMatrices(projection_type p) g_camera.position + g_camera.forward, g_camera.up // "up" vector ); +#endif } else // ORTHO { diff --git a/src/renderer.h b/src/renderer.h index 360ed5d..1da5fb7 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -5,8 +5,10 @@ #include +#include "camera.h" +#include "entity.h" #include "util.h" -#include "hexgame.h" +#include "hexgame.h" // TODO: should move hex_info object out of hexgame.h struct renPointLight { @@ -20,6 +22,7 @@ struct renPointLight bool initRenderer(SDL_Handles &handles, v2i vpDims); bool addTexture(SDL_Handles &handles, const char * path); +camera& renGetCamera(); v2f getUnprojectedCoords(int32 x, int32 y, int32 vp_width, int32 vp_height); v3f getCameraPosition(); bool createScene(std::vector* hexes, Entity* entities, uint32 entity_count); diff --git a/src/scene_loader.cpp b/src/scene_loader.cpp index 136f78b..9679e36 100644 --- a/src/scene_loader.cpp +++ b/src/scene_loader.cpp @@ -15,6 +15,8 @@ // forward declarations bool parseFile(rapidjson::Document& doc, const char* data_dir, const char* file_name); +glm::vec3 parseVec3(const rapidjson::Value& node); +glm::vec4 parseVec4(const rapidjson::Value& node); bool validateScene(rapidjson::Document& schema_doc, rapidjson::Document& scene_doc, const char* scene_file); @@ -28,7 +30,8 @@ slLoadFile( const char* schema_file, Entity* entity_array, uint& entity_count, - uint max_entities) + uint max_entities, + camera& cam) { if (entity_array == nullptr) { LOG(ERROR) << "entity array not initialized\n"; @@ -44,31 +47,34 @@ slLoadFile( return false; // camera - const rapidjson::Value& cam = doc["camera"]; + const rapidjson::Value& json_cam = doc["camera"]; + cameraInitPerspective(cam, + parseVec3(json_cam["position"]), + parseVec3(json_cam["target"]), + parseVec3(json_cam["up"]) + ); // hex grid // entities - const rapidjson::Value& e = doc["entities"]; - if (e.Size() > max_entities) { - LOG(ERROR) << "entity count: " << e.Size() << ", was more than max_entities: " + const rapidjson::Value& entities = doc["entities"]; + if (entities.Size() > max_entities) { + LOG(ERROR) << "entity count: " << entities.Size() << ", was more than max_entities: " << max_entities << "\n"; return false; } - for (uint i = 0; i < e.Size(); i++) { + for (uint i = 0; i < entities.Size(); i++) { meMeshGroup mg; std::string model_path; - model_path.append(data_dir).append("/").append(e[i]["model_file"].GetString()); + model_path.append(data_dir).append("/").append(entities[i]["model_file"].GetString()); if (meLoadFromFile(model_path.c_str(), mg)) { - Entity& e = entity_array[entity_count]; + Entity& e = entity_array[i]; e.mesh_group = mg; - // - e.scale = glm::vec3(10,10,10); - e.translation = glm::vec3(640, 500, 0); - // + e.scale = parseVec3(entities[i]["scale"]); + e.translation = parseVec3(entities[i]["position"]); } else { LOG(ERROR) << "Error loading mesh file\n"; return false; @@ -122,8 +128,31 @@ validateScene(rapidjson::Document& schema_doc, rapidjson::Document& scene_doc, c LOG(ERROR) << "Invalid Document: " << sb.GetString() << "\n"; return false; } - + LOG(INFO) << "scene file: " << scene_file << " passed schema validation\n"; return true; } + +glm::vec3 +parseVec3(const rapidjson::Value& node) +{ + glm::vec3 v3; + v3.x = node["x"].GetFloat(); + v3.y = node["y"].GetFloat(); + v3.z = node["z"].GetFloat(); + + return v3; +} + +glm::vec4 +parseVec4(const rapidjson::Value& node) +{ + glm::vec4 v4; + v4.x = node["x"].GetFloat(); + v4.y = node["y"].GetFloat(); + v4.z = node["z"].GetFloat(); + v4.w = node["w"].GetFloat(); + + return v4; +} diff --git a/src/scene_loader.h b/src/scene_loader.h index e4148a9..3c5f878 100644 --- a/src/scene_loader.h +++ b/src/scene_loader.h @@ -1,4 +1,5 @@ +#include "camera.h" #include "util.h" /* @@ -10,4 +11,5 @@ bool slLoadFile( const char* schema_file, Entity* entity_array, uint& entity_count, - uint max_entities); + uint max_entities, + camera& cam); diff --git a/src/util.cpp b/src/util.cpp index b86d4ce..d222553 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -10,6 +10,8 @@ const uint MAX_FILESIZE = 2 * 1024 * 1024; // 2MB const uint MAX_STRING_LENGTH = 1024; +// TODO: don't use ftell() to get filesize +// https://wiki.sei.cmu.edu/confluence/display/c/FIO19-C.+Do+not+use+fseek%28%29+and+ftell%28%29+to+compute+the+size+of+a+regular+file char * utilDumpTextFile(const char* filename) { @@ -28,7 +30,7 @@ utilDumpTextFile(const char* filename) std::fread(buf, sizeof(char), length, fp); // TODO: check fp w/ ferror() here - + return buf; }