diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 640f88d..2dd4b40 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -144,6 +144,7 @@ add_subdirectory(libvitaboy) if(BUILD_EXAMPLES) add_subdirectory(renderdemo_ray) + add_subdirectory(rlgldemo) endif() unset(BUILD_SHARED_LIBS CACHE) diff --git a/library/libvitaboy/Renderer.cpp b/library/libvitaboy/Renderer.cpp index 49b38eb..e52548c 100644 --- a/library/libvitaboy/Renderer.cpp +++ b/library/libvitaboy/Renderer.cpp @@ -251,14 +251,14 @@ static void BlendVertices() static void DrawMeshes() { - glPointSize(2.0); + //glPointSize(2.0); glColor3f(1.0, 1.0, 1.0); glPushMatrix(); glLoadIdentity(); - //TransformVertices(Skeleton.Bones[0]); + TransformVertices(Skeleton.Bones[0]); glPopMatrix(); BlendVertices(); - + glEnable(GL_TEXTURE_2D); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); @@ -424,7 +424,7 @@ static int Startup() ReadAnimation(Animation); free(InData); - //AdvanceFrame(Skeleton, Animation, 0); + AdvanceFrame(Skeleton, Animation, 0); return 1; } diff --git a/library/renderdemo_ray/main.cpp b/library/renderdemo_ray/main.cpp index d905829..2d66ff3 100644 --- a/library/renderdemo_ray/main.cpp +++ b/library/renderdemo_ray/main.cpp @@ -2,8 +2,6 @@ #include "raymath.h" // Required for: Vector3, Quaternion and Matrix functionality #include "utils.h" // Required for: TRACELOG(), LoadFileData(), LoadFileText(), SaveFileText() -#include -#include #include #include #include "../libvitaboy/libvitaboy.hpp" @@ -15,7 +13,6 @@ //we dont look in this mess for now #pragma region TSO - //util static bool Read(const char* Filename, uint8_t** InData) { *InData = File::ReadFile(Filename); @@ -32,22 +29,20 @@ static Skeleton_t Skeleton; static Model box_model; static void DrawBonesSkeleton(Bone_t& Bone, const Matrix& M) { - Vector3 bonePos = Vector3{ Bone.Translation.x, Bone.Translation.y, Bone.Translation.z }; - - const Vector3 scale = { 1.f, 1.f, 1.f }; Vector3 axis{ Vector3Zero()}; float angle{ 0 }; const Quaternion rotation = Quaternion{ Bone.Rotation.x, Bone.Rotation.y, Bone.Rotation.z, Bone.Rotation.w }; QuaternionToAxisAngle(rotation, &axis, &angle); - Matrix matScale = MatrixScale(scale.x, scale.y, scale.z); - Matrix matRotation = MatrixRotate(axis, angle); - Matrix matTranslation = MatrixTranslate(bonePos.x, bonePos.y, bonePos.z); + // A normalized quaternion(called a "versor") consisting of X, Y, Z, W coordinates, each a 32 - bit little - endian float, + // specifying the default rotation of this bone to be applied after translation. + Matrix matRotation = MatrixRotate(axis, angle * DEG2RAD); + // X,Y,Z coordinates, each a 32-bit little-endian float, + // specifying the distance from the joint with the parent to the distal end of this bone after the default rotation has been applied + Matrix matTranslation = MatrixTranslate(Bone.Translation.x, Bone.Translation.y, Bone.Translation.z); - //this order is correct, see - //Matrix matTransform = MatrixMultiply(MatrixMultiply(matScale, matTranslation), matRotation); - Matrix matTransform = MatrixMultiply(matScale, matTranslation); - Matrix modelMatrix = MatrixMultiply(M, matTransform); + Matrix matTransform = MatrixMultiply(matTranslation, matRotation); + Matrix modelMatrix = MatrixMultiply(M, matTranslation); Color color; if(!strcmp(Bone.Name, "ROOT")) @@ -62,34 +57,27 @@ static void DrawBonesSkeleton(Bone_t& Bone, const Matrix& M) { color = GREEN; } - DrawModel(box_model, Vector3Transform(bonePos, M), 1.f, color); + const Vector3 position{ modelMatrix.m12, modelMatrix.m13, modelMatrix.m14 }; + DrawModel(box_model, position, 1.f, color); - for (unsigned i = 0; i < Bone.ChildrenCount; i++) + if (Bone.ChildrenCount == 1) { - DrawBonesSkeleton(*Bone.Children[i], modelMatrix); + DrawBonesSkeleton(*Bone.Children[0], M); + } + else if (Bone.ChildrenCount > 1) + { + for (unsigned i = 0; i < Bone.ChildrenCount; i++) + { + DrawBonesSkeleton(*Bone.Children[i], modelMatrix); + } } } static int counter = 0; static void DrawTest(const Matrix& M) { - Vector3 rootPosition = Vector3Transform(Vector3{ 0.f, 0.f, 0.f }, M); - DrawModel (box_model, //root - rootPosition, - 1.f, YELLOW); - DrawModel(box_model, //x - Vector3Transform(Vector3{ 1.f, 0.f, 0.f }, M), - 1.f, RED); - DrawModel(box_model, //y - Vector3Transform(Vector3{ 0.f, 1.f, 0.f }, M), - 1.f, GREEN); - DrawModel(box_model, //z - Vector3Transform(Vector3{ 0.f, 0.f, 1.f }, M), - 1.f, BLUE); - Vector3 scale = { 1.f, 1.f, 1.f }; Vector3 rotationAxis = { 0.0f, 0.0f, 1.0f }; - Matrix matScale = MatrixScale(scale.x, scale.y, scale.z); Matrix matRotation = MatrixRotate(rotationAxis, 45.f * DEG2RAD); Matrix matTranslation = MatrixTranslate(5.f, 0.f, 0.f); //transform 5 in the X direction @@ -98,7 +86,21 @@ static void DrawTest(const Matrix& M) // SRT = iTRS, for absolute // STR = iRTS, for local transforms Matrix matTransform = MatrixMultiply(MatrixMultiply(matScale, matTranslation), matRotation); - Matrix modelMatrix = MatrixMultiply(M, matTransform); + Matrix modelMatrix = MatrixMultiply(matTransform, M); + + DrawModel (box_model, //root + Vector3Transform(Vector3{ 0.f, 0.f, 0.f }, modelMatrix), + 1.f, YELLOW); + DrawModel(box_model, //x + Vector3Transform(Vector3{ 1.f, 0.f, 0.f }, modelMatrix), + 1.f, RED); + DrawModel(box_model, //y + Vector3Transform(Vector3{ 0.f, 1.f, 0.f }, modelMatrix), + 1.f, GREEN); + DrawModel(box_model, //z + Vector3Transform(Vector3{ 0.f, 0.f, 1.f }, modelMatrix), + 1.f, BLUE); + if (counter < 3) { @@ -117,7 +119,8 @@ static void AdvanceFrame(Skeleton_t& Skeleton, Animation_t& Animation, float Tim AnimationTime += TimeDelta; AnimationTime = fmodf(AnimationTime, Duration); //Loop the animation - for(unsigned i=0; i 1) + { + for (unsigned i = 0; i < Bone.ChildrenCount; i++) + { + TransformVertices(*Bone.Children[i], matTransform); + } + } +} + +static void BlendVertices() +{ + for (unsigned i = 0; i < MeshCount; i++) + { + Mesh_t& Mesh = Meshes[i]; + for (unsigned i = 0; i < Mesh.BlendVertexCount; i++) + { + Vertex_t& BlendVertex = Mesh.TransformedVertexData[Mesh.RealVertexCount + i]; + float Weight = BlendVertex.BlendData.Weight; + Vertex_t& RealVertex = Mesh.TransformedVertexData[BlendVertex.BlendData.OtherVertex]; + RealVertex.Coord.x = + Weight * BlendVertex.Coord.x + + (1 - Weight) * RealVertex.Coord.x; + RealVertex.Coord.y = + Weight * BlendVertex.Coord.y + + (1 - Weight) * RealVertex.Coord.y; + RealVertex.Coord.z = + Weight * BlendVertex.Coord.z + + (1 - Weight) * RealVertex.Coord.z; + } + } +} #pragma endregion TSO #pragma region custom_ray @@ -206,8 +305,6 @@ namespace CustomRay model.materials = (Material*)RL_CALLOC(model.materialCount, sizeof(Material)); model.meshMaterial[0] = 0; // By default, assign material 0 to each mesh - //TODO: reassign bone IDS with a map - ///load the textures for (int i = 0; i < model.materialCount; i++) { @@ -233,9 +330,12 @@ namespace CustomRay for (unsigned j = 0; j < ray_mesh.vertexCount; j++) { //vertices? - ray_mesh.vertices[j * 3 + 0] = tso_mesh.VertexData[j].Coord.x; - ray_mesh.vertices[j * 3 + 1] = tso_mesh.VertexData[j].Coord.y; - ray_mesh.vertices[j * 3 + 2] = tso_mesh.VertexData[j].Coord.z + (i * 2.f); + ray_mesh.vertices[j * 3 + 0] = tso_mesh.TransformedVertexData[j].Coord.x; + ray_mesh.vertices[j * 3 + 1] = tso_mesh.TransformedVertexData[j].Coord.y; + ray_mesh.vertices[j * 3 + 2] = tso_mesh.TransformedVertexData[j].Coord.z; + //ray_mesh.vertices[j * 3 + 0] = tso_mesh.VertexData[j].Coord.x; + //ray_mesh.vertices[j * 3 + 1] = tso_mesh.VertexData[j].Coord.y; + //ray_mesh.vertices[j * 3 + 2] = tso_mesh.VertexData[j].Coord.z + (i * 1.f); //offset for now so we can see them //coords ray_mesh.texcoords[j * 2 + 0] = tso_mesh.TransformedVertexData[j].TextureCoord.u; ray_mesh.texcoords[j * 2 + 1] = -tso_mesh.TransformedVertexData[j].TextureCoord.v; @@ -248,8 +348,12 @@ namespace CustomRay for (unsigned j = 0; j < ray_mesh.triangleCount; j++) { ray_mesh.indices[j * 3 + 0] = (unsigned short)tso_mesh.FaceData[j].VertexA; + //counter clock wise ray_mesh.indices[j * 3 + 1] = (unsigned short)tso_mesh.FaceData[j].VertexC; ray_mesh.indices[j * 3 + 2] = (unsigned short)tso_mesh.FaceData[j].VertexB; + //Clock wise + //ray_mesh.indices[j * 3 + 1] = (unsigned short)tso_mesh.FaceData[j].VertexB; + //ray_mesh.indices[j * 3 + 2] = (unsigned short)tso_mesh.FaceData[j].VertexC; } //select the textures model.meshMaterial[i] = Mesh_UseTexture[i]; @@ -285,7 +389,14 @@ namespace CustomRay ModelAnimation LoadModelAnimationsTSO() { ModelAnimation result; + // Translation data - For each translation: + // Translation - X, Y, Z coordinates, each a 32 - bit little - endian float, specifying new, + // REPLACEMENT translation values for the bones of the skeleton.These values are stored absolute. + // Rotation data - For each rotation : + // Rotation - A normalized quaternion(called a "versor") consisting of X, Y, Z, W coordinates, each a 32 - bit little - endian float, specifying new, + // replacement rotation values for the bones of the skeleton.These values are stored absolute. + // These values assume a left - handed coordinate system, meaning that for a right - handed coordinate system(like OpenGL and XNA), you have to mirror the quaternion by negating Y and Z. return result; } @@ -371,13 +482,13 @@ static int Startup() ReadAnimation(Animation); free(InData); - //AdvanceFrame(Skeleton, Animation, 0); + AdvanceFrame(Skeleton, Animation, 0); return 1; } //settings static bool ShowTextures = false; -static bool ShowMesh = false; +static bool ShowMesh = true; static bool ShowSkeleton = true; int main(void) { @@ -401,8 +512,13 @@ int main(void) printf("=================RAY==================\n"); printf("======================================\n"); + const Matrix& matIdentity = MatrixIdentity(); const float size = 0.1f; box_model = LoadModelFromMesh( GenMeshCube(size, size, size) ); + + //do this once! + TransformVertices(Skeleton.Bones[0], matIdentity); + BlendVertices(); Model model = CustomRay::LoadModelTSO(); CustomRay::LoadSkeletonTSO(model); @@ -424,6 +540,10 @@ int main(void) { ShowSkeleton = !ShowSkeleton; } + if (IsKeyPressed(KEY_TWO)) + { + ShowMesh = !ShowMesh; + } } BeginDrawing(); @@ -432,17 +552,18 @@ int main(void) BeginMode3D(camera); { DrawGrid(10, 5.0f); + if(ShowSkeleton) { - Matrix M = MatrixIdentity(); - DrawBonesSkeleton(Skeleton.Bones[0], M); + DrawBonesSkeleton(Skeleton.Bones[0], matIdentity); } if (ShowMesh) { const Vector3 position{ 0.0f, 0.0f, 0.0f }; // Set model position const float scale = 1.f; - DrawModel(model, position, scale, WHITE); + + //DrawModel(model, position, scale, WHITE); } Matrix M = MatrixIdentity(); diff --git a/library/rlgldemo/CMakeLists.txt b/library/rlgldemo/CMakeLists.txt new file mode 100644 index 0000000..4e92f44 --- /dev/null +++ b/library/rlgldemo/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.0) +project(rlgldemo) + +# Adding Raylib +include(FetchContent) +set(FETCHCONTENT_QUIET FALSE) +set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) # don't build the supplied examples +set(BUILD_GAMES OFF CACHE BOOL "" FORCE) # don't build the supplied example games + +#set raylib settings +add_compile_definitions(SUPPORT_FILEFORMAT_JPG) + +FetchContent_Declare( + raylib + GIT_REPOSITORY "https://github.com/raysan5/raylib.git" + GIT_TAG "master" + GIT_PROGRESS TRUE +) +FetchContent_MakeAvailable(raylib) + +include_directories(${FILEHANDLER_INCLUDE}) +include_directories(${VITABOY_INCLUDE}) + +# Adding our source files +file(GLOB_RECURSE PROJECT_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_LIST_DIR}/*.cpp") # Define PROJECT_SOURCES as a list of all source files +set(PROJECT_INCLUDE "${CMAKE_CURRENT_LIST_DIR}/*.h") # Define PROJECT_INCLUDE to be the path to the include directory of the project + +# Declaring our executable +add_executable(${PROJECT_NAME}) +target_sources(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCES}) +target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_INCLUDE}) +target_link_libraries(${PROJECT_NAME} PRIVATE raylib libvitaboy_static FileHandler_static) + +# Setting ASSETS_PATH +target_compile_definitions(${PROJECT_NAME} PUBLIC ASSETS_PATH="${CMAKE_CURRENT_SOURCE_DIR}/assets/") # Set the asset path macro to the absolute path on the dev machine +#target_compile_definitions(${PROJECT_NAME} PUBLIC ASSETS_PATH="./assets") # Set the asset path macro in release mode to a relative path that assumes the assets folder is in the same directory as the game executable \ No newline at end of file diff --git a/library/rlgldemo/main.cpp b/library/rlgldemo/main.cpp new file mode 100644 index 0000000..0a4f581 --- /dev/null +++ b/library/rlgldemo/main.cpp @@ -0,0 +1,617 @@ +/* + libvitaboy - Open source Openrl TSO character animation library + Renderer.cpp - Copyright (c) 2012 Niotso Project + Author(s): Fatbag + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NErlIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +#include "raylib.h" +#include "raymath.h" // Required for: Vector3, Quaternion and Matrix functionality +#include "utils.h" // Required for: TRACELOG(), LoadFileData(), LoadFileText(), SaveFileText() +#include "rlgl.h" + +#include +#include +#include "../libvitaboy/libvitaboy.hpp" + +#define SCREEN_WIDTH (800) +#define SCREEN_HEIGHT (600) +#define WINDOW_TITLE "libvitaboy - Renderer - Ray" + + +struct BasicVertex_t { + float x, y, z; +}; +struct CharacterPlacement_t { + BasicVertex_t Translation; + BasicVertex_t Rotation; +}; +static CharacterPlacement_t Character = {{0,-3,0}, {0,0,0}}; + +static Skeleton_t Skeleton; + +static Animation_t Animation; +static float AnimationTime = 0; + +static void DisplayFileError(const char * Filename){ + const char * Message; + switch(File::Error){ + case FERR_NOT_FOUND: + Message = "%s does not exist."; + break; + case FERR_OPEN: + Message = "%s could not be opened for reading."; + break; + case FERR_BLANK: + case FERR_UNRECOGNIZED: + case FERR_INVALIDDATA: + Message = "%s is corrupt or invalid."; + break; + case FERR_MEMORY: + Message = "Memory for %s could not be allocated."; + break; + default: + Message = "%s could not be read."; + break; + } + + char Buffer[1024]; + sprintf(Buffer, Message, Filename); +} + +static bool Read(const char* Filename, uint8_t** InData) { + *InData = File::ReadFile(Filename); + if (*InData != NULL) { + VBFile.set(*InData, File::FileSize); + return true; + } + + DisplayFileError(Filename); + return false; +} + +//textures +static Texture2D textures[3]; +enum { Texture_Body, Texture_Head, Texture_Hand }; +static const char* const TexturePaths[] = { "body.jpg", "head.jpg", "hand.jpg" }; + +static bool LoadTextures() +{ + for (int i = 0; i < 3; i++) + { + textures[i] = LoadTexture(TexturePaths[i]); + } + return true; +} + +static bool UnloadTextures() +{ + for (int i = 0; i < 3; i++) + { + UnloadTexture(textures[i]); + } + return true; +} + +//meshes +static const unsigned MeshCount = 4; +static Mesh_t Meshes[4]; +enum { Mesh_Body, Mesh_Head, Mesh_LHand, Mesh_RHand }; +static const char* const MeshPaths[] = { "body.mesh", "head.mesh", "lhand.mesh", "rhand.mesh" }; +static const unsigned Mesh_UseTexture[] = { Texture_Body, Texture_Head, Texture_Hand, Texture_Hand }; +static const char* const MeshActivate[] = { NULL, "HEAD", "L_HAND", "R_HAND" }; + +// Generate a simple triangle mesh from code +static Mesh CreateMesh(const Mesh_t& tso_mesh) +{ + Mesh ray_mesh = { 0 }; + ray_mesh.vertexCount = tso_mesh.RealVertexCount; + ray_mesh.triangleCount = tso_mesh.FaceCount; // Face count (triangulated) + ray_mesh.vertices = (float*)RL_CALLOC(ray_mesh.vertexCount * 3, sizeof(float)); + ray_mesh.texcoords = (float*)RL_CALLOC(ray_mesh.vertexCount * 2, sizeof(float)); + ray_mesh.normals = (float*)RL_CALLOC(ray_mesh.vertexCount * 3, sizeof(float)); + ray_mesh.indices = (unsigned short*)RL_CALLOC(ray_mesh.triangleCount * 3, sizeof(unsigned short)); + + // Process all mesh faces + //vertex data + for (unsigned j = 0; j < ray_mesh.vertexCount; j++) + { + //vertices? + ray_mesh.vertices[j * 3 + 0] = tso_mesh.TransformedVertexData[j].Coord.x; + ray_mesh.vertices[j * 3 + 1] = tso_mesh.TransformedVertexData[j].Coord.y; + ray_mesh.vertices[j * 3 + 2] = tso_mesh.TransformedVertexData[j].Coord.z; + //coords + ray_mesh.texcoords[j * 2 + 0] = tso_mesh.TransformedVertexData[j].TextureCoord.u; + ray_mesh.texcoords[j * 2 + 1] = -tso_mesh.TransformedVertexData[j].TextureCoord.v; + //normals + ray_mesh.normals[j * 3 + 0] = tso_mesh.TransformedVertexData[j].NormalCoord.x; + ray_mesh.normals[j * 3 + 0] = tso_mesh.TransformedVertexData[j].NormalCoord.y; + ray_mesh.normals[j * 3 + 0] = tso_mesh.TransformedVertexData[j].NormalCoord.z; + } + //indices + for (unsigned j = 0; j < ray_mesh.triangleCount; j++) + { + ray_mesh.indices[j * 3 + 0] = (unsigned short)tso_mesh.FaceData[j].VertexA; + //counter clock wise + ray_mesh.indices[j * 3 + 1] = (unsigned short)tso_mesh.FaceData[j].VertexC; + ray_mesh.indices[j * 3 + 2] = (unsigned short)tso_mesh.FaceData[j].VertexB; + //Clock wise + //ray_mesh.indices[j * 3 + 1] = (unsigned short)tso_mesh.FaceData[j].VertexB; + //ray_mesh.indices[j * 3 + 2] = (unsigned short)tso_mesh.FaceData[j].VertexC; + } + + // Upload mesh data from CPU (RAM) to GPU (VRAM) memory + UploadMesh(&ray_mesh, true); //check the dynamic flag if we have to keep creating the mesh + return ray_mesh; +} + +static bool LoadMeshes() +{ + uint8_t* InData; + for (unsigned i = 0; i < MeshCount; i++) + { + if (!Read(MeshPaths[i], &InData)) + { + return false; + } + ReadMesh(Meshes[i]); + free(InData); + } + return true; +} + +static int ResizeScene(uint16_t width, uint16_t height) +{ + rlViewport(0, 0, width, height); + + rlMatrixMode(RL_PROJECTION); + rlLoadIdentity(); + + // Calculate The Aspect Ratio Of The Window + //rluPerspective(45.0f, (rlfloat)width/(rlfloat)height, 0.1f, 100.0f); + // rlScalef(-1.0f, 1.0f, 1.0f); + + rlMatrixMode(RL_MODELVIEW); + rlLoadIdentity(); + return 1; +} + +static bool InitRLGL() +{ + rlglInit(SCREEN_WIDTH, SCREEN_HEIGHT); + + //rlSetCullFace(); + //rlEnable(rl_CULL_FACE); + rlDisableBackfaceCulling(); + //rlDisable(rl_BLEND); + rlEnableColorBlend(); + //rlDepthFunc(rl_LEQUAL); //default + //rlHint(rl_PERSPECTIVE_CORRECTION_HINT, rl_NICEST); //default + + //cant change this + //rlFrontFace(rl_CW); + ResizeScene(SCREEN_WIDTH, SCREEN_HEIGHT); + return true; +} + +static void TransformVertices(Bone_t& Bone) +{ + rlTranslatef(Bone.Translation.x, Bone.Translation.y, Bone.Translation.z); + float matRotation[16]; + FindQuaternionMatrix(matRotation, &Bone.Rotation); + rlMultMatrixf(matRotation); + + unsigned MeshIndex = 0; + unsigned BoneIndex; + + for(unsigned i=1; i 1){ + for(unsigned i=0; i 1){ + for(unsigned i=0; i=-10.0f) zoom-=0.05f; }*/ zoom -= 3 * dt; + if (IsKeyDown(KEY_UP)) { if ((Character.Rotation.x -= 60 * dt) <= -360) Character.Rotation.x += 360; } + if (IsKeyDown(KEY_DOWN)) { if ((Character.Rotation.x += 60 * dt) >= 360) Character.Rotation.x -= 360; } + if (IsKeyDown(KEY_LEFT)) { if ((Character.Rotation.y -= 60 * dt) <= -360) Character.Rotation.y += 360; } + if (IsKeyDown(KEY_RIGHT)) { if ((Character.Rotation.y += 60 * dt) >= 360) Character.Rotation.y -= 360; } + if (IsKeyDown(KEY_X)) { if ((Character.Rotation.z -= 60 * dt) <= -360) Character.Rotation.z += 360; } + if (IsKeyDown(KEY_Z)) { if ((Character.Rotation.z += 60 * dt) >= 360) Character.Rotation.z -= 360; } + if (IsKeyDown(KEY_K)) { Character.Translation.y -= 3 * dt; } + if (IsKeyDown(KEY_I)) { Character.Translation.y += 3 * dt; } + if (IsKeyDown(KEY_J)) { Character.Translation.x -= 3 * dt; } + if (IsKeyDown(KEY_L)) { Character.Translation.x += 3 * dt; } + if (IsKeyPressed(KEY_ONE)){ ShowSkeleton = !ShowSkeleton; } + if (IsKeyPressed(KEY_TWO)) { ShowMesh = !ShowMesh; } + if (IsKeyDown(KEY_N)) { AdvanceFrame(Skeleton, Animation, dt); } + } + + //rlClearScreenBuffers(); //Clear the screen and the depth buffer + + BeginDrawing(); + { + ClearBackground(BLACK); + BeginMode3D(camera); + { + DrawGrid(10, 5.0f); + + //Avatar + { + if (ShowMesh) + { + //rlEnableWireMode(); + //rlColor3f(1.0, 1.0, 1.0); + //DrawMeshes(); + //rlDisableWireMode(); + const Vector3 position{ 0.0f, 0.0f, 0.0f }; + const float scale = 1.f; + DrawModel(model, position, scale, WHITE); + } + + if (ShowSkeleton) + { + DrawSkeleton(); + } + } + } + EndMode3D(); + + } + EndDrawing(); + } + + UnloadTextures(); + CloseWindow(); + return 0; +} \ No newline at end of file