diff --git a/models/building-1.blend b/models/building-1.blend index 88f86cc..86c0e55 100644 Binary files a/models/building-1.blend and b/models/building-1.blend differ diff --git a/models/building-1.blend1 b/models/building-1.blend1 index 1952caf..4dc55fa 100644 Binary files a/models/building-1.blend1 and b/models/building-1.blend1 differ diff --git a/resources/building-1.glb b/resources/building-1.glb index e38919e..1e16ff4 100644 Binary files a/resources/building-1.glb and b/resources/building-1.glb differ diff --git a/resources/building_a.glb b/resources/building_a.glb deleted file mode 100644 index c6b7373..0000000 Binary files a/resources/building_a.glb and /dev/null differ diff --git a/resources/building_b.glb b/resources/building_b.glb deleted file mode 100644 index a149f69..0000000 Binary files a/resources/building_b.glb and /dev/null differ diff --git a/resources/building_c.glb b/resources/building_c.glb deleted file mode 100644 index b7af293..0000000 Binary files a/resources/building_c.glb and /dev/null differ diff --git a/resources/building_d.glb b/resources/building_d.glb deleted file mode 100644 index a850650..0000000 Binary files a/resources/building_d.glb and /dev/null differ diff --git a/src/camera_controller.c b/src/camera_controller.c index 23dac65..9aa1733 100644 --- a/src/camera_controller.c +++ b/src/camera_controller.c @@ -1,5 +1,4 @@ #include "camera_controller.h" -#include "core/camera_node.h" #include "utils/mirror.h" START_REFLECT(CameraController); @@ -19,11 +18,10 @@ SceneNode *CreateCameraController(Transformable target) { CameraController *self = new(CameraController); *self = (CameraController){ .transform = tc_null(Transformable), - .rotation_speed = 2.f, + .rotation_speed = 5.f, .max_speed_time = 4.f, .target = target, - .time_rotated = 0.f, - .camera = NULL, + .time_rotated = 0.f }; SceneNode *node = CreateSceneNode(CameraController_as_SceneNodeEntity(self)); return node; @@ -36,9 +34,6 @@ void DestroyCameraController(CameraController *self) { void CameraControllerEnterTree(CameraController *self) { self->transform = TC_CAST(self->node->parent->entity, Transformable); self->global = self->transform.tc->get_global_transform(self->transform.data); - SceneNode *camera_node = SceneNodeGetChildByTypeid(self->node->parent, GET_TYPEID(CameraNode), true); - self->camera = camera_node->entity.data; - self->camera->fov = 100; } void CameraControllerExitTree(CameraController *self) {} @@ -54,10 +49,11 @@ void CameraControllerTick(CameraController *self, double delta) { // ... and maximum frame step size float const step = self->rotation_speed * time_mul * delta; if(angle > 0.f) - target.rotation = QuaternionSlerp(current.rotation, target.rotation, step); + target.rotation = QuaternionSlerp(current.rotation, target.rotation, fminf(fminf(step, angle) / angle, 0.99f)); if(step > angle && self->time_rotated > delta) - self->time_rotated -= delta; - else - self->time_rotated += delta; + self->time_rotated -= 3.f * delta; + else if(step > angle) + self->time_rotated = 0.f; + self->time_rotated += delta; self->transform.tc->set_global_transform(self->transform.data, target); } diff --git a/src/camera_controller.h b/src/camera_controller.h index ca0d689..29b2279 100644 --- a/src/camera_controller.h +++ b/src/camera_controller.h @@ -14,7 +14,6 @@ typedef struct CameraController { float max_speed_time; Transformable target; float time_rotated; - CameraNode *camera; } CameraController; extern SceneNode *CreateCameraController(Transformable target); diff --git a/src/city_generator.c b/src/city_generator.c deleted file mode 100644 index e82cb69..0000000 --- a/src/city_generator.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "city_generator.h" -#include "core/mesh_render_entity.h" -#include "core/transform_node.h" - -static struct { - size_t x, y; -} const CITY_SIZE = {20, 20}; - -#define MODELS_LENGTH 4 -static ModelResource models[MODELS_LENGTH] = { - ResourceEmpty(Model), - ResourceEmpty(Model), - ResourceEmpty(Model), - ResourceEmpty(Model) -}; - -static void Internal_LoadModelsIfRequired() { - for(size_t i = 0; i < MODELS_LENGTH; ++i) - if(models[i].handle == NULL && GetModelResource(TextFormat("building_%c", 'a' + i), &models[i])) - LoadResource(models[i].handle); -} - -static SceneNode *Internal_CreateBuilding(size_t x, size_t y) { - size_t building_index = (3 * (x + y + GetRandomValue(0, 50))) % MODELS_LENGTH; // semi-random number based on the x,y coordinate - SceneNode *mesh_render_node = CreateMeshRenderEntity(TextFormat("building_%c", 'a' + building_index)); - SceneNode *transform_node = CreateTransformNode(); - SceneNodeAddChild(transform_node, mesh_render_node); - Transformable transform = TC_CAST(transform_node->entity, Transformable); - Transform local = transform.tc->get_transform(transform.data); - local.translation.x = (float)(x * 40); - local.translation.z = (float)(y * 40); - transform.tc->set_transform(transform.data, local); - return transform_node; -} - -SceneNode *GenerateCity() { - Internal_LoadModelsIfRequired(); - SceneNode *root = CreateTransformNode(); - for(size_t x = 0; x < CITY_SIZE.x; ++x) { - for(size_t y = 0; y < CITY_SIZE.y; ++y) { - SceneNodeAddChild(root, Internal_CreateBuilding(x, y)); - } - } - return root; -} diff --git a/src/city_generator.h b/src/city_generator.h deleted file mode 100644 index dffbfaa..0000000 --- a/src/city_generator.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CITY_GENERATOR_H -#define CITY_GENERATOR_H - -#include "core/scene.h" - -extern SceneNode *GenerateCity(); - -#endif // !CITY_GENERATOR_H diff --git a/src/core/camera_node.c b/src/core/camera_node.c index cef88ec..6d21434 100644 --- a/src/core/camera_node.c +++ b/src/core/camera_node.c @@ -20,11 +20,6 @@ impl_SceneNodeEntity_for(CameraNode, SceneNode *CreateCameraNode() { CameraNode *self = new(CameraNode); - *self = (CameraNode){ - .fov = 60, - .node = NULL, - .transform = tc_null(Transformable) - }; return CreateSceneNode(CameraNode_as_SceneNodeEntity(self)); } @@ -56,7 +51,7 @@ Camera3D CameraNodeGetCamera(CameraNode *self) { Vector3 forward = MATRIX_FORWARD(mat); // construct a new camera at the global transform location and facing the forward vector return (Camera3D){ - .fovy = self->fov, + .fovy = 90, .position = global_transform.translation, .projection = CAMERA_PERSPECTIVE, .target = Vector3Add(global_transform.translation, forward), diff --git a/src/core/camera_node.h b/src/core/camera_node.h index 79fd2b0..8837bfd 100644 --- a/src/core/camera_node.h +++ b/src/core/camera_node.h @@ -10,7 +10,6 @@ typedef struct CameraNode { SceneNode *node; Transformable transform; - float fov; } CameraNode; //! Instantiate new camera node diff --git a/src/core/render.c b/src/core/render.c index 1b6bd3b..6929335 100644 --- a/src/core/render.c +++ b/src/core/render.c @@ -54,6 +54,7 @@ void RenderNextFrame() { BeginMode3D(CameraNodeGetCamera(camera)); list_foreach(Renderable *,object, &g_render_objects) object->tc->draw(object->data); + DrawGrid(500, 1.f); // TODO Remove this (or make it a scene node entity) EndMode3D(); } DrawFPS(20, 20); diff --git a/src/core/resources.c b/src/core/resources.c index 7ed929e..57831f6 100644 --- a/src/core/resources.c +++ b/src/core/resources.c @@ -132,9 +132,9 @@ bool GetModelResource(char const *path, ModelResource *out) { ResourceContainer *container = hash_map_get_as(ResourceContainer, &g_resource_map, &path); *out = ResourceEmpty(Model); // assert some assumptions about the found resource - ASSERT_RETURN(container != NULL, false, "GetModelResource: Resource %s not in index.", path); - ASSERT_RETURN(container->type == RESOURCE_MODEL, false, "GetModelResource: Resource %s is not a Texture.", path); - ASSERT_RETURN(strcmp(container->name, path) == 0, false, "GetModelResource: Resource %s was loaded for path %s", container->name, path); + ASSERT_RETURN(container != NULL, false, "GetTextureResource: Resource %s not in index.", path); + ASSERT_RETURN(container->type == RESOURCE_MODEL, false, "GetTextureResource: Resource %s is not a Texture.", path); + ++container->use_counter; *out = (ModelResource) { .handle = container, .resource = &container->model @@ -174,20 +174,16 @@ bool IsResourceLoaded(ResourceHandle handle) { void LoadResource(ResourceHandle handle) { ASSERT_RETURN(handle != NULL,, "LoadResource: Resource handle invalid"); - if(!handle->is_loaded) { - g_load_functions[handle->type](handle); - handle->is_loaded = true; - } + g_load_functions[handle->type](handle); + handle->is_loaded = true; ++handle->use_counter; } void ReleaseResource(ResourceHandle handle) { ASSERT_RETURN(handle != NULL,, "ReleaseResource: Resource handle invalid"); ASSERT_RETURN_WARN(handle->is_loaded,, "ReleaseResource: Resource %s is not loaded.", handle->path); - if(handle->use_counter == 1) { - g_unload_functions[handle->type](handle); - handle->is_loaded = false; - } + g_unload_functions[handle->type](handle); + handle->is_loaded = false; --handle->use_counter; } diff --git a/src/core/scene.c b/src/core/scene.c index f252d14..f017c22 100644 --- a/src/core/scene.c +++ b/src/core/scene.c @@ -170,23 +170,8 @@ SceneNode *SceneNodeGetChildByTypeclass(SceneNode *self, char const *typeclass, SceneNodeEntity entity = (*child)->entity; if(mirror_get_function(entity.data, entity.mirror, typeclass)) return *child; - if(recurse) { - SceneNode *recursed = SceneNodeGetChildByTypeclass(*child, typeclass, recurse); - if(recursed != NULL) return recursed; - } - } - return NULL; -} - -SceneNode *SceneNodeGetChildByTypeid(SceneNode *self, typeid id, bool recurse) { - list_foreach(SceneNode **,child, &self->children) { - SceneNodeEntity entity = (*child)->entity; - if(entity.mirror->get_typeid() == id) - return *child; - if(recurse) { - SceneNode *recursed = SceneNodeGetChildByTypeid(*child, id, recurse); - if(recursed != NULL) return recursed; - } + if(recurse) + SceneNodeGetChildByTypeclass(*child, typeclass, recurse); } return NULL; } diff --git a/src/core/scene.h b/src/core/scene.h index 4e4826e..5ce6340 100644 --- a/src/core/scene.h +++ b/src/core/scene.h @@ -41,12 +41,10 @@ extern void SceneNodeRemoveChild(SceneNode *self, SceneNode *child); extern void SceneNodeAttachEntity(SceneNode *self, SceneNodeEntity entity); //! Detach an entity from a scene node extern SceneNodeEntity SceneNodeDetachEntity(SceneNode *self); -//! Returns the first child node with an entity that implements a specific typeclass. +//! Returns the first child node that implements a specific typeclass. //! Optionally recurses through the entire branch extern SceneNode *SceneNodeGetChildByTypeclass(SceneNode *self, char const *typeclass, bool recurse); -//! Returns the first child node with an entity that matches the given typeid. -//! Optionally recurses through the entire branch. -extern SceneNode *SceneNodeGetChildByTypeid(SceneNode *self, typeid id, bool recurse); + //! Instantiate a new scene with a root node. extern Scene *CreateScene(SceneNode *root); //! Destroy a node and it's scene tree. diff --git a/src/main.c b/src/main.c index 23c4de1..dc03fe6 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,6 @@ #include "raylib.h" #include "player_controller.h" #include "camera_controller.h" -#include "city_generator.h" #include "core/input.h" #include "core/camera_node.h" #include "core/engine_global.h" @@ -49,7 +48,6 @@ Scene *CreateInitialScene() { SceneNodeAddChild(root, model); SceneNodeAddChild(root, camera_scene); SceneNodeAddChild(camera_scene, CreateCameraController(TC_CAST(model->entity, Transformable))); - SceneNodeAddChild(root, GenerateCity()); return CreateScene(root); } @@ -58,10 +56,7 @@ void ConfigureInput() { AddAction("pitch_down", INPUT_LISTENER_KEY, 0, KEY_W); AddAction("roll_left", INPUT_LISTENER_KEY, 0, KEY_A); AddAction("roll_right", INPUT_LISTENER_KEY, 0, KEY_D); - AddAction("yaw_right", INPUT_LISTENER_KEY, 0, KEY_E); - AddAction("yaw_left", INPUT_LISTENER_KEY, 0, KEY_Q); - AddAction("brake", INPUT_LISTENER_KEY, 0, KEY_SPACE); - AddAction("boost", INPUT_LISTENER_KEY, 0, KEY_LEFT_SHIFT); + AddAction("stop", INPUT_LISTENER_KEY, 0, KEY_SPACE); } int main() { diff --git a/src/player_controller.c b/src/player_controller.c index 918f62d..4910ba6 100644 --- a/src/player_controller.c +++ b/src/player_controller.c @@ -1,8 +1,7 @@ #include "player_controller.h" #include "core/render.h" -#include "core/input.h" -#include "utils/typeclass_helpers.h" #include "utils/debug.h" +#include "core/input.h" #include "raylib.h" START_REFLECT(PlayerController); @@ -20,25 +19,10 @@ impl_SceneNodeEntity_for(PlayerController, PlayerControllerTick ) -static float const PLAYER_BASE_SPEED = 10.f; -static float const PLAYER_BASE_ACCELERATION = 10.f; -static float const PLAYER_BOOST_SPEED = 30.f; -static float const PLAYER_BOOST_ACCELERATION = 60.f; -static float const PLAYER_BRAKE_SPEED = 0.5f; -static float const PLAYER_BRAKE_DECELERATION = 10.f; -static float const PLAYER_FALL_SPEED = 10.f; -static float const PLAYER_FALL_ACCELERATION = 10.f; - SceneNode *CreatePlayerController() { PlayerController *self = new(PlayerController); - *self = (PlayerController) { - .node = NULL, - .transform = tc_null(Transformable), - .rotation = Vector3Zero(), - .fly_input = Vector3Zero(), - .speed = 10.f, - .brake = false - }; + self->rotation = self->fly_input = Vector2Zero(); + self->stopped = false; return CreateSceneNode(PlayerController_as_SceneNodeEntity(self)); } @@ -49,42 +33,32 @@ void DestroyPlayerController(PlayerController *self) { void PlayerControllerEnterTree(PlayerController *self) { self->transform = TC_CAST(self->node->parent->entity, Transformable); DisableCursor(); - AddListener("pitch_up", ButtonInputListener(self, PlayerControllerInputPitchUp)); - AddListener("pitch_down", ButtonInputListener(self, PlayerControllerInputPitchDown)); - AddListener("roll_left", ButtonInputListener(self, PlayerControllerInputRollLeft)); - AddListener("roll_right", ButtonInputListener(self, PlayerControllerInputRollRight)); - AddListener("yaw_left", ButtonInputListener(self, PlayerControllerInputYawLeft)); - AddListener("yaw_right", ButtonInputListener(self, PlayerControllerInputYawRight)); - AddListener("brake", ButtonInputListener(self, PlayerControllerInputBrake)); - AddListener("boost", ButtonInputListener(self, PlayerControllerInputBoost)); + AddListener("pitch_up", ButtonInputListener(self, PlayerControllerUpInput)); + AddListener("pitch_down", ButtonInputListener(self, PlayerControllerDownInput)); + AddListener("roll_left", ButtonInputListener(self, PlayerControllerLeftInput)); + AddListener("roll_right", ButtonInputListener(self, PlayerControllerRightInput)); + AddListener("stop", ButtonInputListener(self, PlayerControllerStopInput)); } void PlayerControllerExitTree(PlayerController *self) { RemoveAllListeners(self); } -static -float MoveTowards(float from, float to, float delta) { - if(from == to) return to; - float const diff = to - from; - float const sign = signbit(diff) ? -1.f : 1.f; - return from + sign * fminf(delta, fabsf(diff)); -} - //! angular acceleration limited to local X and Z axes static void PlayerControllerTickAngularAcceleration(PlayerController *self, double delta) { - self->rotation.x = MoveTowards(self->rotation.x, self->fly_input.x, delta * 4.f); - self->rotation.y = MoveTowards(self->rotation.y, self->fly_input.y, delta * 4.f); - self->rotation.z = MoveTowards(self->rotation.z, self->fly_input.z, delta * 4.f); + Vector2 diff = Vector2Subtract(self->fly_input, self->rotation); + float const length = Vector2Length(diff); + if(length != 0.f) + self->rotation = Vector2Add(self->rotation, Vector2Scale(diff, 1.0f/length * fminf(4.f * delta, length))); } //! linear acceleration limited to the local Z axis static void PlayerControllerTickLinearAcceleration(PlayerController *self, double delta) { - float const target = self->brake ? PLAYER_BRAKE_SPEED : (self->boost ? PLAYER_BOOST_SPEED : PLAYER_BASE_SPEED); - float const acceleration = target < self->speed ? PLAYER_BRAKE_DECELERATION : (self->boost ? PLAYER_BOOST_ACCELERATION : PLAYER_BASE_ACCELERATION); - self->speed = MoveTowards(self->speed, target, delta * acceleration); + float const target = self->stopped ? 10.f : (self->rotation.y == 0.f ? 30.f : 20.f); + float const speed_diff = target - self->speed; + self->speed = self->speed + copysignf(fminf(fabsf(speed_diff), 10.f * delta), speed_diff); } //! Update linear transform based on velocities @@ -92,11 +66,9 @@ static void PlayerControllerTickTransform(PlayerController *self, double delta) { Transform global_transform = self->transform.tc->get_global_transform(self->transform.data); Matrix global_matrix = TransformGetMatrix(global_transform); - float const rotate_speed = 1.f - 0.9f * self->speed / PLAYER_BOOST_SPEED; global_transform.translation = Vector3Add(global_transform.translation, Vector3Scale(MATRIX_FORWARD(global_matrix), self->speed * delta)); - global_transform.rotation = QuaternionMultiply(QuaternionFromAxisAngle(MATRIX_FORWARD(global_matrix), self->rotation.x * 1.25f * delta), global_transform.rotation); - global_transform.rotation = QuaternionMultiply(QuaternionFromAxisAngle(MATRIX_RIGHT(global_matrix), self->rotation.y * rotate_speed * 3.75f * delta), global_transform.rotation); - global_transform.rotation = QuaternionMultiply(QuaternionFromAxisAngle(MATRIX_UP(global_matrix), self->rotation.z * rotate_speed * 1.f * delta), global_transform.rotation); + global_transform.rotation = QuaternionMultiply(QuaternionFromAxisAngle(MATRIX_FORWARD(global_matrix), self->rotation.x * 2.f * delta), global_transform.rotation); + global_transform.rotation = QuaternionMultiply(QuaternionFromAxisAngle(MATRIX_RIGHT(global_matrix), self->rotation.y * 2.5f * delta), global_transform.rotation); self->transform.tc->set_global_transform(self->transform.data, global_transform); } @@ -106,34 +78,22 @@ void PlayerControllerTick(PlayerController *self, double delta) { PlayerControllerTickTransform(self, delta); } -void PlayerControllerInputRollLeft(PlayerController *self, bool value) { +void PlayerControllerLeftInput(PlayerController *self, bool value) { self->fly_input.x += value ? -1 : +1; } -void PlayerControllerInputRollRight(PlayerController *self, bool value) { +void PlayerControllerRightInput(PlayerController *self, bool value) { self->fly_input.x += value ? +1 : -1; } -void PlayerControllerInputPitchUp(PlayerController *self, bool value) { +void PlayerControllerUpInput(PlayerController *self, bool value) { self->fly_input.y += value ? -1 : +1; } -void PlayerControllerInputPitchDown(PlayerController *self, bool value) { +void PlayerControllerDownInput(PlayerController *self, bool value) { self->fly_input.y += value ? +1 : -1; } -void PlayerControllerInputYawRight(PlayerController *self, bool value) { - self->fly_input.z += value ? -1 : +1; -} - -void PlayerControllerInputYawLeft(PlayerController *self, bool value) { - self->fly_input.z += value ? +1 : -1; -} - -void PlayerControllerInputBrake(PlayerController *self, bool value) { - self->brake = value; -} - -void PlayerControllerInputBoost(PlayerController *self, bool value) { - self->boost = value; +void PlayerControllerStopInput(PlayerController *self, bool value) { + self->stopped = value; } diff --git a/src/player_controller.h b/src/player_controller.h index c6fc5ce..e20a724 100644 --- a/src/player_controller.h +++ b/src/player_controller.h @@ -12,11 +12,10 @@ typedef struct PlayerController { SceneNode *node; Transformable transform; - Vector3 fly_input; - Vector3 rotation; + Vector2 fly_input; + Vector2 rotation; float speed; - bool brake; - bool boost; + bool stopped; } PlayerController; SceneNode *CreatePlayerController(); @@ -26,14 +25,11 @@ extern void PlayerControllerEnterTree(PlayerController *self); extern void PlayerControllerExitTree(PlayerController *self); extern void PlayerControllerTick(PlayerController *self, double delta); -extern void PlayerControllerInputRollLeft(PlayerController *self, bool value); -extern void PlayerControllerInputRollRight(PlayerController *self, bool value); -extern void PlayerControllerInputPitchUp(PlayerController *self, bool value); -extern void PlayerControllerInputPitchDown(PlayerController *self, bool value); -extern void PlayerControllerInputYawRight(PlayerController *self, bool value); -extern void PlayerControllerInputYawLeft(PlayerController *self, bool value); -extern void PlayerControllerInputBrake(PlayerController *self, bool value); -extern void PlayerControllerInputBoost(PlayerController *self, bool value); +extern void PlayerControllerLeftInput(PlayerController *self, bool value); +extern void PlayerControllerRightInput(PlayerController *self, bool value); +extern void PlayerControllerUpInput(PlayerController *self, bool value); +extern void PlayerControllerDownInput(PlayerController *self, bool value); +extern void PlayerControllerStopInput(PlayerController *self, bool value); DECL_REFLECT(PlayerController); decl_typeclass_impl(SceneNodeEntity, PlayerController); diff --git a/src/utils b/src/utils index bb201d5..faf0463 160000 --- a/src/utils +++ b/src/utils @@ -1 +1 @@ -Subproject commit bb201d5085cfb2e54ebad9a0bf22347a5251f7a2 +Subproject commit faf0463e3791ee97dfc370282ecad4cd3b4ca475