From 4eedd52004f1d68b94727a00e584ee41914af7eb Mon Sep 17 00:00:00 2001 From: Redacted Date: Sat, 18 Nov 2023 09:04:45 -0500 Subject: [PATCH] initial commit --- .gitignore | 2 + CMakeLists.txt | 21 ++++++ LICENSE | 24 +++++++ run.sh | 2 + src/engine/engine.h | 152 +++++++++++++++++++++++++++++++++++++++++ src/engine/render.h | 129 ++++++++++++++++++++++++++++++++++ src/engine/tick.h | 39 +++++++++++ src/main.cpp | 10 +++ src/types/camera.h | 85 +++++++++++++++++++++++ src/types/entity.h | 19 ++++++ src/types/entityList.h | 28 ++++++++ src/types/geometry.h | 10 +++ src/types/player.h | 21 ++++++ src/types/skybox.h | 48 +++++++++++++ src/types/vector3.h | 69 +++++++++++++++++++ src/types/vertex.h | 45 ++++++++++++ src/types/world.h | 0 17 files changed, 704 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100755 run.sh create mode 100644 src/engine/engine.h create mode 100644 src/engine/render.h create mode 100644 src/engine/tick.h create mode 100644 src/main.cpp create mode 100644 src/types/camera.h create mode 100644 src/types/entity.h create mode 100644 src/types/entityList.h create mode 100644 src/types/geometry.h create mode 100644 src/types/player.h create mode 100644 src/types/skybox.h create mode 100644 src/types/vector3.h create mode 100644 src/types/vertex.h create mode 100644 src/types/world.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f88b18 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/cmake-build-debug +/.idea diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..18f79a5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.18) +project(SDL3D) + +set(CMAKE_CXX_STANDARD 20) + +add_executable(SDL3D src/main.cpp + src/types/entity.h + src/types/camera.h + src/types/world.h + src/engine/engine.h + src/types/vector3.h + src/types/player.h + src/types/entityList.h + src/engine/render.h + src/engine/tick.h + src/types/vertex.h + src/types/skybox.h + src/types/geometry.h) + +find_package(OpenGL) +target_link_libraries(SDL3D SDL2 freeimage ${OPENGL_LIBRARIES}) \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fdddb29 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..6a7f658 --- /dev/null +++ b/run.sh @@ -0,0 +1,2 @@ +sleep 0.5 +vblank_mode=0 mangohud --dlsym /home/william/Documents/GitHub/SDL3D/cmake-build-debug/SDL3D diff --git a/src/engine/engine.h b/src/engine/engine.h new file mode 100644 index 0000000..a7ff092 --- /dev/null +++ b/src/engine/engine.h @@ -0,0 +1,152 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include + +enum class gamestate: uint8_t { + NORMAL = 0, //Gameplay. + IN_MAIN_MENU = 1, + IN_PAUSE_MENU = 2, + IN_LEVEL_ANIMATION = 3, //A cutscene which moves entities in the world and cannot be interrupted. + IN_QUIT = 4, //The game should close. + NULL_ = 7 +}; + +class Engine { +public: + gamestate gameState = gamestate::NULL_; + bool debug = true; + bool takingScreenshot = false; //Because + SDL_Window *window = nullptr; + uint16_t windowWidth = 1152; + uint16_t windowHeight = 864; + ulong tickCount = 0; + float tickDelta = NULL; + ulong frameCount = 0; + float frameDelta = NULL; + uint16_t minimumTickDelta = 15625; + GLenum glError = GL_NO_ERROR; + SDL_GLContext glContext = nullptr; + float nearPlane = 0.01f; + float farPlane = 100.0f; + float fov = 70.0f; + SDL_Event event; + + + [[nodiscard]] float framerate() const { + return 1.f / this->frameDelta; + } + + void takeScreenshot() { + if (!this->takingScreenshot) + return; + FreeImage_Initialise(); + auto* fbData = new GLubyte[this->windowWidth * this->windowHeight * 3]; + glReadPixels(0, 0, this->windowWidth, this->windowHeight, GL_RGB, GL_UNSIGNED_BYTE, fbData); + FIBITMAP* image = FreeImage_ConvertFromRawBits(fbData, this->windowWidth, this->windowHeight, this->windowWidth * 3, 24, 0xFF0000, 0x00FF00, 0x0000FF, false); + FreeImage_Save(FIF_BMP, image, std::to_string(this->frameCount).c_str(), 0); + FreeImage_Unload(image); + delete[] fbData; + FreeImage_DeInitialise(); + this->takingScreenshot = false; + } + + void takeScreenshot(const char* filename) { + if (!this->takingScreenshot) + return; + FreeImage_Initialise(); + auto* fbData = new GLubyte[this->windowWidth * this->windowHeight * 3]; + glReadPixels(0, 0, this->windowWidth, this->windowHeight, GL_RGB, GL_UNSIGNED_BYTE, fbData); + FIBITMAP* image = FreeImage_ConvertFromRawBits(fbData, this->windowWidth, this->windowHeight, this->windowWidth * 3, 24, 0xFF0000, 0x00FF00, 0x0000FF, false); + FreeImage_Save(FIF_BMP, image, filename, 0); + FreeImage_Unload(image); + delete[] fbData; + FreeImage_DeInitialise(); + this->takingScreenshot = false; + } + + void quit() { + SDL_DestroyWindow(this->window); + SDL_Quit(); + exit(0); + } + static float getGLVersion() { + std::string str = reinterpret_cast(glGetString(GL_VERSION)); + str.erase(str.begin()+3,str.end()); + return std::stof(str); + } + + void initGL() { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + //glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -0.5f, 0.5f); + gluPerspective(this->fov, this->windowWidth / this->windowHeight, this->nearPlane, this->farPlane); + this->glError = glGetError(); + + if (glError != GL_NO_ERROR) { + std::cerr << "OpenGL: " << gluErrorString(glError); + exit (1); + } + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + if (glError != GL_NO_ERROR) { + std::cerr << "OpenGL: " << gluErrorString(glError); + exit (1); + } + glClearColor(0.f, 0.f, 0.f, 1.f); + glViewport(0,0,this->windowWidth,this->windowHeight); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glDepthMask(GL_TRUE); + glClearDepth(1.0f); + glDisable(GL_CULL_FACE); + //glDepthRange(-0.5f,0.5f); + } + + void initVideo() { + + Uint32 sdl_initializer_flags = SDL_INIT_VIDEO;// | SDL_INIT_AUDIO; + + // Start SDL, check for errors + if (SDL_Init(sdl_initializer_flags) < 0) { + std::cerr << "SDL_Error: " << SDL_GetError() << std::endl; + exit(1); + } + + // Create the window, set resizable, check for errors + SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 1); + SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 4); + SDL_GL_SetSwapInterval(0); + this->window = SDL_CreateWindow("SDL3D", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, this->windowWidth, this->windowHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); + SDL_SetWindowResizable(this->window,SDL_FALSE); + this->glContext = SDL_GL_CreateContext(window); + + if (isless(this->getGLVersion(),1.4f)) { + std::cerr << "Driver OpenGL version: " << this->getGLVersion() << std::endl; + std::cerr << "OpenGL >= 1.4 is required." << std::endl; + exit(1); + } + + if (this->window == nullptr) { + std::cerr << "SDL_Error: " << SDL_GetError() << std::endl; + exit(1); + } + } + + void debugInfo() { + if (this->debug) { + std::cout << "Last tick completed in: " << (tickDelta / 1000) << "ms, " << "sleeping " << ((minimumTickDelta - tickDelta) / 1000) << "ms." << std::endl; + std::cout << "Last frame dT: " << this->frameDelta << std::endl; + std::cout << "Framerate: " << framerate() << std::endl;; + //std::cout << "EntityCount: " << entityList.list.size() << std::endl; + //std::cout << "Camera Position: " << "X " << entityList.getCamera()->position.x << " Y " << entityList.getCamera()->position.y << " Z " << entityList.getCamera()->position.z << std::endl; + } + } +}; + +auto* engine = new(Engine); \ No newline at end of file diff --git a/src/engine/render.h b/src/engine/render.h new file mode 100644 index 0000000..1695419 --- /dev/null +++ b/src/engine/render.h @@ -0,0 +1,129 @@ +#pragma once +#include +#include +#include "engine.h" +#include "../types/camera.h" +#include "../types/entityList.h" + + +void process_sdl_events() { + while (SDL_PollEvent(&engine->event)) { + // TODO: Consider switch statements as opposed to ifs + // This adds control flow in the form of "break" statement. + // Which will save checking every single event type unnecessarily + + if (engine->event.type == SDL_QUIT) {engine->quit();} + if (engine->event.type == SDL_DROPFILE) {} + + // Window Events + if (engine->event.type == SDL_WINDOWEVENT) { + auto window_ev = engine->event.window; + auto ev_type = window_ev.event; + if (ev_type == SDL_WINDOWEVENT_FOCUS_LOST) {} + if (ev_type == SDL_WINDOWEVENT_FOCUS_GAINED) {} + if (ev_type == SDL_WINDOWEVENT_CLOSE) {} + if (ev_type == SDL_WINDOWEVENT_SHOWN) {} + if (ev_type == SDL_WINDOWEVENT_HIDDEN) {} + if (ev_type == SDL_WINDOWEVENT_EXPOSED) {} + if (ev_type == SDL_WINDOWEVENT_MOVED) {} + if (ev_type == SDL_WINDOWEVENT_RESIZED) {} + if (ev_type == SDL_WINDOWEVENT_SIZE_CHANGED) {} + if (ev_type == SDL_WINDOWEVENT_MINIMIZED) {} + if (ev_type == SDL_WINDOWEVENT_MAXIMIZED) {} + if (ev_type == SDL_WINDOWEVENT_RESTORED) {} + if (ev_type == SDL_WINDOWEVENT_ENTER) {} + if (ev_type == SDL_WINDOWEVENT_LEAVE) {} + } + } +} + +void pre_render() { + if(engine->frameCount == 0) { + engine->initVideo(); + engine->initGL(); + auto camera = new(Camera); + entityList.storeEntity(camera); + entityList.getCamera()->position.set(0.0f,0.0f,5.0f); + } + + process_sdl_events(); + engine->frameCount++; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + entityList.getCamera()->render(); +} + +void render() { + + glBegin(GL_QUADS); + glColor3f(1,0.5,1); + // Front face + glVertex3f(-0.5f, -0.5f, 0.5f); + glVertex3f(0.5f, -0.5f, 0.5f); + glVertex3f(0.5f, 0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, 0.5f); + + // Back face + glVertex3f(-0.5f, -0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, -0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(-0.5f, 0.5f, -0.5f); + + // Left face + glVertex3f(-0.5f, -0.5f, -0.5f); + glVertex3f(-0.5f, -0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, -0.5f); + + // Right face + glVertex3f(0.5f, -0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, 0.5f); + glVertex3f(0.5f, 0.5f, 0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + + // Top face + glVertex3f(-0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, 0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, 0.5f); + + // Bottom face + glVertex3f(-0.5f, -0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, 0.5f); + glVertex3f(-0.5f, -0.5f, 0.5f); + glEnd(); + + glPopMatrix(); + glPushMatrix(); + + + //glBegin(GL_QUADS); + //glColor3f(0,1,0); + //glVertex3f(-0.25f, -0.75f,0.0); + //glVertex3f(0.25f, -0.75f,0.0); + //glVertex3f(0.25f, 0.75f,0.0); + //glVertex3f(-0.25f, 0.75f,0.0); + //glEnd(); +} + +void post_render() { + SDL_GL_SwapWindow(engine->window); + engine->takeScreenshot(); + + //Resets all of the transformations for the next frame. + glPopMatrix(); + glPushMatrix(); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); +} + +[[noreturn]] void render_loop() { + while (true) { + auto start = std::chrono::high_resolution_clock::now(); + pre_render(); + render(); + post_render(); + auto stop = std::chrono::high_resolution_clock::now(); + float dT = (std::chrono::duration_cast(stop - start).count()); + engine->frameDelta = dT / 1000000; + } +} \ No newline at end of file diff --git a/src/engine/tick.h b/src/engine/tick.h new file mode 100644 index 0000000..d95b022 --- /dev/null +++ b/src/engine/tick.h @@ -0,0 +1,39 @@ +#pragma once +#include +#include +#include "engine.h" +#include "../types/entityList.h" + +[[noreturn]] void gameTick() { + while (true) { + auto start = std::chrono::high_resolution_clock::now(); + //do stuff + + engine->tickCount++; + switch (engine->gameState) { + case gamestate::NORMAL: + break; + case gamestate::IN_MAIN_MENU: + break; + case gamestate::IN_PAUSE_MENU: + break; + case gamestate::IN_LEVEL_ANIMATION: + break; + case gamestate::IN_QUIT: + engine->quit(); + break; + } + + if (engine->tickCount % 64 == 0) + engine->debugInfo(); + if(engine->frameCount > 0) + entityList.getCamera()->update(); + auto stop = std::chrono::high_resolution_clock::now(); + //limit to 64 ticks per second. + if ((int) engine->tickDelta < engine->minimumTickDelta) + std::this_thread::sleep_for( + std::chrono::microseconds(engine->minimumTickDelta - (uint16_t) engine->tickDelta)); + //Pause without potential deSync issues. + engine->tickDelta = std::chrono::duration_cast(stop - start).count(); + } +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..3a90977 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,10 @@ +#include +#include "engine/tick.h" +#include "engine/render.h" +int main() { + std::thread renderThread(render_loop); + std::thread tickThread (gameTick); + renderThread.join(); + tickThread.join(); + return 0; +} diff --git a/src/types/camera.h b/src/types/camera.h new file mode 100644 index 0000000..16a35b3 --- /dev/null +++ b/src/types/camera.h @@ -0,0 +1,85 @@ +#pragma once +#include "entity.h" +#include "../engine/engine.h" + +enum class cameramode: uint8_t { + FREECAM = 0, + FOLLOW_PLAYER = 1 +}; +class Camera : public entity { +public: + uint8_t mode = 0; + void move(vector3 offset) { + position.x += offset.x; + position.y += offset.y; + position.z += offset.z; + } + + void move(float x, float y, float z) { + position.x += x; + position.y += y; + position.z += z; + } + + void update() { + if (mode == 0) { + const Uint8* keyState = SDL_GetKeyboardState(nullptr); + //TODO: Make the direction that is considered "forward" not a set axis direction + //But instead determined by the yaw. + if (keyState[SDL_SCANCODE_S] == 1) { + this->position.z = this->position.z+0.1f; + } + if (keyState[SDL_SCANCODE_W] == 1) { + this->position.z = this->position.z-0.1f; + } + if (keyState[SDL_SCANCODE_A] == 1) { + this->position.x = this->position.x-0.025f;; + } + if (keyState[SDL_SCANCODE_D] == 1) { + this->position.x = this->position.x+0.025f; + } + + if (keyState[SDL_SCANCODE_SPACE] == 1) { + this->position.y -= 0.025; + } + + if (keyState[SDL_SCANCODE_LSHIFT] == 1) { + this->position.y += 0.025; + } + + if (keyState[SDL_SCANCODE_LEFT] == 1) { + this->angles.y +=2.0f; + } + if (keyState[SDL_SCANCODE_RIGHT] == 1) { + this->angles.y -=2.0f; + //std::cout << this->angles.y << std::endl; + } + if (keyState[SDL_SCANCODE_UP] == 1) { + this->angles.x +=2.0f; + //std::cout << this->angles.x << std::endl; + } + if (keyState[SDL_SCANCODE_DOWN] == 1) { + this->angles.x -=2.0f; + //std::cout << this->angles.x << std::endl; + } + } + this->angles.clamp(); + } + + void render() { + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + //glTranslatef(-position.x, -position.y, -position.z); + // up vector + glRotatef(-angles.x,1.0f, 0.0f, 0.0f); + glRotatef(-angles.y,0.0f, 1.0f, 0.0f); + + glTranslatef(0.0f, 0.0f, 0.0f); + gluLookAt(position.x, position.y, position.z, // camera position + position.x, position.y, -engine->farPlane+position.z, // target position, We're always *looking at* the far plane straight ahead so the camera never turns around. + 0.0f, 1.0f, 0.0f); + std::cout << "Camera:" << std::endl; + std::cout << "X: " << position.x << " Y: " << position.y << " Z: " << position.z << std::endl; + std::cout << "Pitch: " << angles.x << " Yaw: " << angles.y << " Roll: " << angles.z << std::endl; + } +}; \ No newline at end of file diff --git a/src/types/entity.h b/src/types/entity.h new file mode 100644 index 0000000..3997a7c --- /dev/null +++ b/src/types/entity.h @@ -0,0 +1,19 @@ +#pragma once +#include +#include "vector3.h" + +class entity { +public: + bool draw; + bool collidable; + uint32_t ticksAlive; //At 64tps it'd take 776 days to overflow. + Position position; //X Y Z + angle angles = {0,0,0}; //Pitch Yaw Roll, The orientation of the entity in the world, + angle velAngles = {0,0,0}; //The angle of an entities velocity. + void destruct() { + //TODO: Search entity list for this entity and remove it to avoid use-after-free. + delete this; + } + + virtual ~entity() {} +}; \ No newline at end of file diff --git a/src/types/entityList.h b/src/types/entityList.h new file mode 100644 index 0000000..9263cb7 --- /dev/null +++ b/src/types/entityList.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include "entity.h" +#include "player.h" +#include "camera.h" +class entitylist { +public: + std::vector list; + + inline player* getPlayer() { + for (auto& e : this->list) + if (auto* p = dynamic_cast(e) ) + return dynamic_cast(e); + } + + inline Camera* getCamera() { + for (auto& e : this->list) + if (auto* p = dynamic_cast(e) ) + return dynamic_cast(e); + } + + inline void storeEntity(entity* e) { + this->list.push_back(e); + } +}; + +//the primary entity list. +entitylist entityList; \ No newline at end of file diff --git a/src/types/geometry.h b/src/types/geometry.h new file mode 100644 index 0000000..43153e6 --- /dev/null +++ b/src/types/geometry.h @@ -0,0 +1,10 @@ +#pragma once +#include +#include +class Geometry { +public: + //I would use array for this, But from what I've read array of unknown size + //as a member of class was removed after c++99. + std::vector vertices; + std::vector indices; +}; \ No newline at end of file diff --git a/src/types/player.h b/src/types/player.h new file mode 100644 index 0000000..1801e38 --- /dev/null +++ b/src/types/player.h @@ -0,0 +1,21 @@ +#pragma once +#include "entity.h" + +class player : public entity { +public: + bool alive; + uint8_t health; + uint8_t state; + Position cameraTarget; //The point where the 3rd-person camera will want to look at. + + //Each type of entity will have an "update" function and a "render" function. + //These will be declared in each type of entity and not in the base entity because + //It'll be different for each one. + void update() { + + } + + void render() { + + } +}; \ No newline at end of file diff --git a/src/types/skybox.h b/src/types/skybox.h new file mode 100644 index 0000000..1826334 --- /dev/null +++ b/src/types/skybox.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include "entity.h" +#include "geometry.h" +class skybox : public entity { +public: + const Geometry geometry = { + {0.000f, 1.000f, 0.000f, + 0.894f, 0.2235f, 0.000f, + 0.276f, 0.2235f, -0.4255f, + -0.724f, 0.2235f, -0.263f, + -0.724f, 0.2235f, 0.263f, + 0.276f, 0.2235f, 0.4255f, + 0.724f, -0.2235f, -0.263f, + -0.276f, -0.2235f, -0.4255f, + -0.894f, -0.2235f, 0.000f, + -0.276f, -0.2235f, 0.4255f, + 0.724f, -0.2235f, 0.263f, + 0.000f, -1.000f, 0.000f}, + + {0, 1, 2, + 0, 2, 3, + 0, 3, 4, + 0, 4, 5, + 0, 5, 1, + 1, 6, 2, + 2, 7, 3, + 3, 8, 4, + 4, 9, 5, + 5, 10, 1, + 11, 6, 1, + 11, 7, 2, + 11, 8, 3, + 11, 9, 4, + 11, 10, 5, + 6, 7, 2, + 7, 8, 3, + 8, 9, 4, + 9, 10, 5, + 10, 6, 1} + }; + + void render() { + //TODO: Teleport the sphere such that the center of the sphere is the cameras position every frame. + } + +}; \ No newline at end of file diff --git a/src/types/vector3.h b/src/types/vector3.h new file mode 100644 index 0000000..810d456 --- /dev/null +++ b/src/types/vector3.h @@ -0,0 +1,69 @@ +#pragma once +#include +#include +#include + +class vector3{ +public: + float x = 0; //pitch + float y = 0; //yaw + float z = 0; //roll +}; + +class angle : public vector3 { +public: + void clamp() { + if (this->x > 89.0f) + this->x = 89.0f; + if (this->x <= -89.0f) + this->x = -89.0f; + + //TODO: Make this seamless by getting the amount they rotated passed -180 and +180 by. + if (this->y <= -180.0f) + this->y = 180.0f; + if (this->y >= 180.01f) + this->y = -179.9f; + + if (this->z >= 360.0f) + this->z = 0.0; + if(this->z <= -360.0f) + this->z = 0.0; + } +}; + +class Position : public vector3 { +public: + + Position* get() { + return this; + } + + void set(Position p) { + this->x = p.x; + this->y = p.y; + this->z = p.z; + } + + void set(Position* p) { + this->x = p->x; + this->y = p->y; + this->z = p->z; + } + + void set(vector3 v) { + this->x = v.x; + this->y = v.y; + this->z = v.z; + } + + void set(vector3* v) { + this->x = v->x; + this->y = v->y; + this->z = v->z; + } + void set(float x, float y, float z) { + this->x = x; + this->y = y; + this->z = z; + } +}; \ No newline at end of file diff --git a/src/types/vertex.h b/src/types/vertex.h new file mode 100644 index 0000000..605a7ea --- /dev/null +++ b/src/types/vertex.h @@ -0,0 +1,45 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include + +struct vertex { + GLfloat x, y, z; +}; + +class vertexarray { +public: + std::vector vertices; + std::vector indices; + + void load(const char* file) { + //This will take a .obj + std::ifstream f(file); + std::string line; + while (std::getline(f, line)) { + std::istringstream iss(line); + std::string prefix; + iss >> prefix; + + if (prefix == "v") { + vertex v; + iss >> v.x >> v.y >> v.z; + this->vertices.push_back(v); + } + else if (prefix == "f") { + unsigned int v1, v2, v3; + char slash; + iss >> v1 >> slash >> slash >> v2 >> slash >> slash >> v3; + this->indices.push_back(v1 - 1); + this->indices.push_back(v2 - 1); + this->indices.push_back(v3 - 1); + } + } + f.close(); + } +}; \ No newline at end of file diff --git a/src/types/world.h b/src/types/world.h new file mode 100644 index 0000000..e69de29