commit d61efe796c61bc8dfbc0a38bdbe3cd151bb5e42d Author: Safariminer Date: Sun Jun 1 16:26:04 2025 -0400 Initial Commit. Hello world! diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c8b3ffa --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.vs +.vscode +x84 +x64 +*.exe +*.ipch +Release +Debug +deps diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..091ee72 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Safariminer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +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 OR COPYRIGHT HOLDERS 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. diff --git a/ProjectMorault.sln b/ProjectMorault.sln new file mode 100644 index 0000000..1e350df --- /dev/null +++ b/ProjectMorault.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35527.113 d17.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProjectMorault", "ProjectMorault\ProjectMorault.vcxproj", "{A20204CF-23C4-4386-A432-A135319786DC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A20204CF-23C4-4386-A432-A135319786DC}.Debug|x64.ActiveCfg = Debug|x64 + {A20204CF-23C4-4386-A432-A135319786DC}.Debug|x64.Build.0 = Debug|x64 + {A20204CF-23C4-4386-A432-A135319786DC}.Debug|x86.ActiveCfg = Debug|Win32 + {A20204CF-23C4-4386-A432-A135319786DC}.Debug|x86.Build.0 = Debug|Win32 + {A20204CF-23C4-4386-A432-A135319786DC}.Release|x64.ActiveCfg = Release|x64 + {A20204CF-23C4-4386-A432-A135319786DC}.Release|x64.Build.0 = Release|x64 + {A20204CF-23C4-4386-A432-A135319786DC}.Release|x86.ActiveCfg = Release|Win32 + {A20204CF-23C4-4386-A432-A135319786DC}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ProjectMorault/Morault_Map.h b/ProjectMorault/Morault_Map.h new file mode 100644 index 0000000..30e8889 --- /dev/null +++ b/ProjectMorault/Morault_Map.h @@ -0,0 +1,9 @@ +#pragma once + +namespace Morault { + namespace Maps { + class Map { + + }; + } +} \ No newline at end of file diff --git a/ProjectMorault/Morault_Player.cpp b/ProjectMorault/Morault_Player.cpp new file mode 100644 index 0000000..2a80169 --- /dev/null +++ b/ProjectMorault/Morault_Player.cpp @@ -0,0 +1,72 @@ +#include "Morault_Player.h" +#include + + +Morault::Gameplay::Player::Player() +{ +} + +Morault::Gameplay::Player::Player(PlayerData a, PlayerController b) +{ + data = a; controller = b; // self explanatory <3 +} + +Morault::Gameplay::Player::~Player() +{ +} + +Morault::Gameplay::PlayerController::PlayerController() +{ + camera = { 0 }; + camera.fovy = 90; + camera.position = { -10,5,0 }; + camera.target = { 0,5,0 }; + camera.up = { 0,1,0 }; + camera.projection = CAMERA_PERSPECTIVE; + rotation = { 10,0,0 }; +} + +Morault::Gameplay::PlayerController::PlayerController(Vector3 position) +{ + camera = { 0 }; + camera.fovy = 90; + camera.position = position; + camera.target = { 0, position.y,0 }; + camera.up = { 0,1,0 }; + camera.projection = CAMERA_PERSPECTIVE; + rotation = { 1,0,0 }; +} +int collfloor = 5; + +float gravity = 0; + +void Morault::Gameplay::PlayerController::UpdatePlayerController(bool focus) +{ + if (focus) { + rotation = Vector3RotateByAxisAngle(rotation, { 0,1,0 }, -GetMouseDelta().x * 0.05 * sensitivityMultiplier); + rotation.y = Clamp(rotation.y - GetMouseDelta().y * 0.3 * sensitivityMultiplier, -15, 15); + + camera.target = Vector3Add(camera.position, rotation); + if (IsKeyDown(KEY_W)) camera.position = Vector3Add(camera.position, Vector3Multiply({rotation.x, 0, rotation.z}, {GetFrameTime(), GetFrameTime(), GetFrameTime()})); + if (IsKeyDown(KEY_S)) camera.position = Vector3Subtract(camera.position, Vector3Multiply({ rotation.x, 0, rotation.z }, { GetFrameTime(), GetFrameTime(), GetFrameTime() })); + + if (IsKeyDown(KEY_A)) camera.position = Vector3Add(camera.position, Vector3Multiply(Vector3RotateByAxisAngle({ rotation.x, 0, rotation.z }, {0,1,0}, DEG2RAD*90), {GetFrameTime(), GetFrameTime(), GetFrameTime()})); + if (IsKeyDown(KEY_D)) camera.position = Vector3Add(camera.position, Vector3Multiply(Vector3RotateByAxisAngle({ rotation.x, 0, rotation.z }, { 0,1,0 }, DEG2RAD * -90), { GetFrameTime(), GetFrameTime(), GetFrameTime() })); + if (IsKeyPressed(KEY_SPACE)) { + gravity -= 5; + } + + + } + camera.position.y -= gravity*GetFrameTime(); + gravity += 10*GetFrameTime(); + if (camera.position.y < collfloor) { + camera.position.y = collfloor; + gravity = 0; + } +} + +Morault::Gameplay::PlayerController::~PlayerController() +{ + camera = { 0 }; +} diff --git a/ProjectMorault/Morault_Player.h b/ProjectMorault/Morault_Player.h new file mode 100644 index 0000000..9c9f95b --- /dev/null +++ b/ProjectMorault/Morault_Player.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include + +namespace Morault { + namespace Gameplay { + typedef enum { + CITY, + MALL, + AWAITING_GAME, + IN_GAME, + AFTER_GAME + }; + struct PlayerData { + std::string playerName = ""; + int hp = 100, xp = 0; + // eventually: std::vector items; + // eventually: Item* primaryWeapon; + // eventually: Item* secondaryWeapon; + // eventually: Item* cosmetics; + }; + class PlayerController { + public: + + PlayerController(); + PlayerController(Vector3 position); + Vector3 rotation; + Camera camera; + float sensitivityMultiplier = 0.5; + void UpdatePlayerController(bool focus); + ~PlayerController(); + }; + class Player { + public: + Player(); + Player(PlayerData, PlayerController); + PlayerData data; + PlayerController controller; + ~Player(); + }; + } +} \ No newline at end of file diff --git a/ProjectMorault/Morault_Resources.cpp b/ProjectMorault/Morault_Resources.cpp new file mode 100644 index 0000000..4204af6 --- /dev/null +++ b/ProjectMorault/Morault_Resources.cpp @@ -0,0 +1,137 @@ +#include "Morault_Resources.h" +#include "Morault_Utils.h" +#include +#include +#include +#include +std::map __models_map; +Morault::Resources::_ResourceRequest Morault::Resources::load(std::string modelName) +{ + _ResourceRequest retval; + retval.type = _ResourceRequestType::LOAD; + retval.req = modelName; + return retval; +} + +Morault::Resources::_ResourceRequest Morault::Resources::get(std::string modelName) +{ + _ResourceRequest retval; + retval.type = _ResourceRequestType::GET; + retval.req = modelName; + return retval; +} + +Morault::Resources::_ResourceRequest Morault::Resources::unload(std::string modelName) +{ + _ResourceRequest retval; + retval.type = _ResourceRequestType::UNLOAD; + retval.req = modelName; + return retval; +} + +Morault::Resources::_ResourceRequest Morault::Resources::reload(std::string modelName) +{ + _ResourceRequest retval; + retval.type = _ResourceRequestType::RELOAD; + retval.req = modelName; + return retval; +} + +std::variant Morault::Resources::Models(_ResourceRequest request) +{ + switch (request.type) { + case LOAD: + __models_map[request.req] = LoadModel(request.req.c_str()); + return true; + break; + case GET: + return __models_map[request.req]; + break; + case UNLOAD: + UnloadModel(__models_map[request.req]); + return true; + break; + case RELOAD: + UnloadModel(__models_map[request.req]); + __models_map[request.req] = LoadModel(request.req.c_str()); + return true; + break; + } +} + +Image Morault::Resources::GenTestImage() +{ + Image retval = GenImageColor(256, 256, BLANK); + + for (int y = 0; y < 256; y++) { + for (int x = 0; x < 256; x++) { + ImageDrawPixel(&retval, x, y, { (unsigned char)x, (unsigned char)y, (unsigned char)(255 - x), 255 }); + } + } + return retval; +} + + +Morault::Resources::WAD::WAD() +{ + std::cout << "Warning: Empty WAD instance created.\n"; +} + +Morault::Resources::WAD::WAD(std::string path) +{ + LoadWAD(path); +} + +void Morault::Resources::WAD::LoadWAD(std::string path) +{ + loaded = false; + lumps.clear(); + lumpCount = 0; + std::cout << "Loading file " << path << "...\n"; + std::ifstream file(path, std::ios::binary); + std::string filedata; + std::stringstream filestream; filestream << file.rdbuf(); + filedata = filestream.str(); + if ( + + + Morault::Utils::Strings::IterativeComp(filedata, 0, "IWAD")) { + wadType = IWAD; + std::cout << "File is an IWAD\n"; + } + else if (Morault::Utils::Strings::IterativeComp(filedata, 0, "PWAD")) { + wadType = PWAD; + std::cout << "File is a PWAD\n"; + } + else { + throw std::runtime_error("Invalid WAD file: Error at header start(IWAD/PWAD)\n"); + } + lumpCount = Morault::Utils::Strings::StringIndexToInteger_4b_le(filedata, 4); + + std::cout << "File has " << lumpCount << " lumps\n"; + int directoryPointer = Morault::Utils::Strings::StringIndexToInteger_4b_le(filedata, 8); + + std::string directory = Morault::Utils::Strings::IterativeStringExcerpt(filedata, directoryPointer, 16 * lumpCount); + + for (int i = 0; i < lumpCount; i++) { + Lump lump; + std::string lumpIndex = Morault::Utils::Strings::IterativeStringExcerpt(directory, i * 16, 16); + int lumpPointer = Morault::Utils::Strings::StringIndexToInteger_4b_le(lumpIndex, 0); + int lumpSize = Morault::Utils::Strings::StringIndexToInteger_4b_le(lumpIndex, 4); + lump.name = "", lump.data = ""; + for (int j = 0; j < 8; j++) { + if (lumpIndex.at(8 + j) != 0x0) lump.name += lumpIndex.at(8 + j); + } + + lump.data = Morault::Utils::Strings::IterativeStringExcerpt(filedata, lumpPointer, lumpSize); + + lumps.push_back(lump); + + std::cout << "(" << i << "/" << lumpCount << ")" << "Loaded lump \"" << lump.name << "\" of size " << lumpSize << "\n"; + } + loaded = true; +} + +Morault::Resources::WAD::~WAD() +{ +} \ No newline at end of file diff --git a/ProjectMorault/Morault_Resources.h b/ProjectMorault/Morault_Resources.h new file mode 100644 index 0000000..a9e216a --- /dev/null +++ b/ProjectMorault/Morault_Resources.h @@ -0,0 +1,56 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace Morault { + namespace Resources { + + typedef enum { + GET, + LOAD, + UNLOAD, + RELOAD + } _ResourceRequestType; + + struct _ResourceRequest { // to use as std::get(Models(get("test.obj"))); + _ResourceRequestType type; + std::string req; + }; + + _ResourceRequest load(std::string modelName); + _ResourceRequest get(std::string modelName); + _ResourceRequest unload(std::string modelName); + _ResourceRequest reload(std::string modelName); + + std::variant Models(_ResourceRequest request); + + + + typedef enum { + INVALID, IWAD, PWAD + } WADType; + struct Lump { + std::string name, data; + }; + + class WAD { + std::vector lumps; + public: + bool loaded = false; + WADType wadType; + int lumpCount; + WAD(); + WAD(std::string path); + void LoadWAD(std::string path); + std::vector getLumps() { + return lumps; + } + ~WAD(); + }; + Image GenTestImage(); + } +} \ No newline at end of file diff --git a/ProjectMorault/Morault_UDMF.cpp b/ProjectMorault/Morault_UDMF.cpp new file mode 100644 index 0000000..edfd88f --- /dev/null +++ b/ProjectMorault/Morault_UDMF.cpp @@ -0,0 +1,757 @@ +#include "Morault_UDMF.h" +#include +#include "Morault_Utils.h" +#include +#include +#include +void Morault::UDMF::UDMFMap::LoadMap(std::string textmap) +{ + std::stringstream text(textmap); + std::string previousLine; + std::string line; + std::string blockType; + bool inblock = false; + + Linedef linedef; + Sidedef sidedef; + Vertex vertex; + Sector sector; + + while (std::getline(text, line)) { + + auto [key, val] = Morault::Utils::Strings::ParseCLineIntoKeyVal(line); + if (key == "namespace") udmfNamespace = val; + if (key == "") { + if (line == "{") { + blockType = Morault::Utils::Strings::SingleWordTrimmer(previousLine); + if (blockType == "linedef") linedef = Linedef(); + if (blockType == "sidedef") sidedef = Sidedef(); + if (blockType == "vertex") vertex = Vertex(); + if (blockType == "sector") sector = Sector(); + inblock = true; + if (blockType != "linedef" && blockType != "sidedef" && blockType != "vertex" && blockType != "sector") { + std::cout << "Unsupported block type " << blockType << "\n"; + inblock = false; + } + } + if (line == "}") { + inblock = false; + if (blockType == "linedef") linedefs.push_back(linedef); + if (blockType == "sidedef") sidedefs.push_back(sidedef); + if (blockType == "vertex") vertexes.push_back(vertex); + if (blockType == "sector") sectors.push_back(sector); + } + } + else { + if (inblock) { + if (blockType == "linedef") { + if (key == "v1") linedef.v1 = std::stoi(val); + if (key == "v2") linedef.v2 = std::stoi(val); + if (key == "sidefront") linedef.sidefront = std::stoi(val); + + if (key == "sideback") linedef.sideback = std::stoi(val); + //was if (key == "sideback") linedef.sidefront = std::stoi(val); + + + if (key == "blocking") linedef.blocking = val == "true"; + } + if (blockType == "sidedef") { + if (key == "sector") sidedef.sector = std::stoi(val); + if (key == "texturemiddle") sidedef.texturemiddle = val; + } + if (blockType == "vertex") { + if (key == "x") vertex.x = std::stof(val); + if (key == "y") vertex.y = std::stof(val); + } + if (blockType == "sector") { + if (key == "texturefloor") sector.texturefloor = val; + if (key == "textureceiling") sector.textureceiling = val; + if (key == "heightceiling") sector.heightceiling = std::stoi(val); + if (key == "heightfloor") sector.heightfloor = std::stoi(val); + } + } + } + + // std::cout << "Key " << key << " as " << val << std::endl; + previousLine = line; + } + std::cout << "Linedefs: " << linedefs.size() << "\n"; + std::cout << "Sidedefs: " << sidedefs.size() << "\n"; + std::cout << "Vertexes: " << vertexes.size() << "\n"; + std::cout << "Sectors: " << sectors.size() << "\n"; + +} + +Model Morault::UDMF::LoadModelUDMFWalls(UDMFMap map) +{ + std::string vertices = ""; + int verticeCount = 0; + std::string vertexnormals = ""; + int vertexNormalsCount = 0; + std::string faces = ""; + + + for (int i = 0; i < map.linedefs.size(); i++) { + // DrawLine(map.vertexes[map.linedefs[i].v1].x + offset.x, map.vertexes[map.linedefs[i].v1].y + offset.y, map.vertexes[map.linedefs[i].v2].x + offset.x, map.vertexes[map.linedefs[i].v2].y + offset.y, YELLOW); + + bool valuesUninitialized = true; + float lowestPoint = 0; + float midLowestPoint = 0; + float midHighestPoint = 0; + float highestPoint = 0; + if (map.linedefs[i].sidefront != -1) { + lowestPoint = map.sectors[map.sidedefs[map.linedefs[i].sidefront].sector].heightfloor; + highestPoint = map.sectors[map.sidedefs[map.linedefs[i].sidefront].sector].heightceiling; + midLowestPoint = lowestPoint; + midHighestPoint = highestPoint; + valuesUninitialized = false; + } + if (map.linedefs[i].sideback != -1) { + if (valuesUninitialized) { + // std::cout << "values uninit\n"; + lowestPoint = map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightfloor; + highestPoint = map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightceiling; + midLowestPoint = lowestPoint; + midHighestPoint = highestPoint; + } + else { + // lowestPoint = map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightfloor < lowestPoint ? map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightfloor : lowestPoint; + // highestPoint = map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightceiling > highestPoint ? map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightceiling : highestPoint; + int lowPoint = map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightfloor; + int highPoint = map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightceiling; + + if (lowPoint < lowestPoint) lowestPoint = lowPoint; + else midLowestPoint = lowPoint; + + + if (highPoint > highestPoint) highestPoint = highPoint; + else midHighestPoint = highPoint; + + } + valuesUninitialized = false; + + } + // std::cout << lowestPoint << " " << midLowestPoint << " " << midHighestPoint << " " << highestPoint << "\n"; + if (map.linedefs[i].sidefront != -1) { + + + + if (map.sidedefs[map.linedefs[i].sidefront].texturemiddle != "") { + /*DrawTriangle3D( + { + -1 * map.vertexes[map.linedefs[i].v1].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sidefront].sector].heightceiling, + map.vertexes[map.linedefs[i].v1].y + }, + { + -1 * map.vertexes[map.linedefs[i].v1].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sidefront].sector].heightfloor, + map.vertexes[map.linedefs[i].v1].y + }, + { + -1 * map.vertexes[map.linedefs[i].v2].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sidefront].sector].heightfloor, + map.vertexes[map.linedefs[i].v2].y + }, + ColorLerp({ 255,0,0,255 }, { 0,0,255,255 }, (float)i / (float)map.linedefs.size()) + + );*/ + + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sidefront].sector].heightceiling, + map.vertexes[map.linedefs[i].v1].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sidefront].sector].heightfloor, + map.vertexes[map.linedefs[i].v1].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sidefront].sector].heightfloor, + map.vertexes[map.linedefs[i].v2].y); + + + vertexNormalsCount++; + vertexnormals += TextFormat("vn %f %f %f\n", (map.vertexes[map.linedefs[i].v2].y - map.vertexes[map.linedefs[i].v1].y), 0, -(map.vertexes[map.linedefs[i].v2].x - map.vertexes[map.linedefs[i].v1].x)); + + faces += TextFormat("f %i//%i %i//%i %i//%i\n", verticeCount + 1, vertexNormalsCount, verticeCount + 2, vertexNormalsCount, verticeCount + 3, vertexNormalsCount); + verticeCount += 3; + + /*DrawTriangle3D( + { + -1 * map.vertexes[map.linedefs[i].v1].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sidefront].sector].heightceiling, + map.vertexes[map.linedefs[i].v1].y + }, + { + -1 * map.vertexes[map.linedefs[i].v2].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sidefront].sector].heightfloor, + map.vertexes[map.linedefs[i].v2].y + }, + { + -1 * map.vertexes[map.linedefs[i].v2].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sidefront].sector].heightceiling, + map.vertexes[map.linedefs[i].v2].y + }, + ColorLerp({ 255,0,0,255 }, { 0,255,0,255 }, (float)i / (float)map.linedefs.size()) + + );*/ + + + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sidefront].sector].heightceiling, + map.vertexes[map.linedefs[i].v1].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sidefront].sector].heightfloor, + map.vertexes[map.linedefs[i].v2].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sidefront].sector].heightceiling, + map.vertexes[map.linedefs[i].v2].y); + + vertexNormalsCount++; + vertexnormals += TextFormat("vn %f %f %f\n", (map.vertexes[map.linedefs[i].v2].y - map.vertexes[map.linedefs[i].v1].y), 0, -(map.vertexes[map.linedefs[i].v2].x - map.vertexes[map.linedefs[i].v1].x)); + + faces += TextFormat("f %i//%i %i//%i %i//%i\n", verticeCount + 1, vertexNormalsCount, verticeCount + 2, vertexNormalsCount, verticeCount + 3, vertexNormalsCount); + verticeCount += 3; + + } + + /*DrawTriangle3D( + { + -1 * map.vertexes[map.linedefs[i].v1].x, + highestPoint, + map.vertexes[map.linedefs[i].v1].y + }, + { + -1 * map.vertexes[map.linedefs[i].v1].x, + midHighestPoint, + map.vertexes[map.linedefs[i].v1].y + }, + { + -1 * map.vertexes[map.linedefs[i].v2].x, + midHighestPoint, + map.vertexes[map.linedefs[i].v2].y + }, + ColorLerp({ 255,0,0,255 }, { 0,0,255,255 }, (float)i / (float)map.linedefs.size()) + + );*/ + + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + highestPoint, + map.vertexes[map.linedefs[i].v1].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + midHighestPoint, + map.vertexes[map.linedefs[i].v1].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + midHighestPoint, + map.vertexes[map.linedefs[i].v2].y); + + vertexNormalsCount++; + vertexnormals += TextFormat("vn %f %f %f\n", (map.vertexes[map.linedefs[i].v2].y - map.vertexes[map.linedefs[i].v1].y), 0, -(map.vertexes[map.linedefs[i].v2].x - map.vertexes[map.linedefs[i].v1].x)); + + faces += TextFormat("f %i//%i %i//%i %i//%i\n", verticeCount + 1, vertexNormalsCount, verticeCount + 2, vertexNormalsCount, verticeCount + 3, vertexNormalsCount); + verticeCount += 3; + + + + + /*DrawTriangle3D( + { + -1 * map.vertexes[map.linedefs[i].v1].x, + highestPoint, + map.vertexes[map.linedefs[i].v1].y + }, + { + -1 * map.vertexes[map.linedefs[i].v2].x, + midHighestPoint, + map.vertexes[map.linedefs[i].v2].y + }, + { + -1 * map.vertexes[map.linedefs[i].v2].x, + highestPoint, + map.vertexes[map.linedefs[i].v2].y + }, + ColorLerp({ 255,0,0,255 }, { 0,255,0,255 }, (float)i / (float)map.linedefs.size()) + + );*/ + + + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + highestPoint, + map.vertexes[map.linedefs[i].v1].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + midHighestPoint, + map.vertexes[map.linedefs[i].v2].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + highestPoint, + map.vertexes[map.linedefs[i].v2].y); + + vertexNormalsCount++; + vertexnormals += TextFormat("vn %f %f %f\n", (map.vertexes[map.linedefs[i].v2].y - map.vertexes[map.linedefs[i].v1].y), 0, -(map.vertexes[map.linedefs[i].v2].x - map.vertexes[map.linedefs[i].v1].x)); + + faces += TextFormat("f %i//%i %i//%i %i//%i\n", verticeCount + 1, vertexNormalsCount, verticeCount + 2, vertexNormalsCount, verticeCount + 3, vertexNormalsCount); + verticeCount += 3; + + + // --- + /*DrawTriangle3D( + { + -1 * map.vertexes[map.linedefs[i].v1].x, + midLowestPoint, + map.vertexes[map.linedefs[i].v1].y + }, + { + -1 * map.vertexes[map.linedefs[i].v1].x, + lowestPoint, + map.vertexes[map.linedefs[i].v1].y + }, + { + -1 * map.vertexes[map.linedefs[i].v2].x, + lowestPoint, + map.vertexes[map.linedefs[i].v2].y + }, + ColorLerp({ 255,0,0,255 }, { 0,0,255,255 }, (float)i / (float)map.linedefs.size()) + + );*/ + + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + midLowestPoint, + map.vertexes[map.linedefs[i].v1].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + lowestPoint, + map.vertexes[map.linedefs[i].v1].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + lowestPoint, + map.vertexes[map.linedefs[i].v2].y); + + vertexNormalsCount++; + vertexnormals += TextFormat("vn %f %f %f\n", (map.vertexes[map.linedefs[i].v2].y - map.vertexes[map.linedefs[i].v1].y), 0, -(map.vertexes[map.linedefs[i].v2].x - map.vertexes[map.linedefs[i].v1].x)); + + faces += TextFormat("f %i//%i %i//%i %i//%i\n", verticeCount + 1, vertexNormalsCount, verticeCount + 2, vertexNormalsCount, verticeCount + 3, vertexNormalsCount); + verticeCount += 3; + + /*DrawTriangle3D( + { + -1 * map.vertexes[map.linedefs[i].v1].x, + midLowestPoint, + map.vertexes[map.linedefs[i].v1].y + }, + { + -1 * map.vertexes[map.linedefs[i].v2].x, + lowestPoint, + map.vertexes[map.linedefs[i].v2].y + }, + { + -1 * map.vertexes[map.linedefs[i].v2].x, + midLowestPoint, + map.vertexes[map.linedefs[i].v2].y + }, + ColorLerp({ 255,0,0,255 }, { 0,255,0,255 }, (float)i / (float)map.linedefs.size()) + + );*/ + + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + midLowestPoint, + map.vertexes[map.linedefs[i].v1].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + lowestPoint, + map.vertexes[map.linedefs[i].v2].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + midLowestPoint, + map.vertexes[map.linedefs[i].v2].y); + + vertexNormalsCount++; + vertexnormals += TextFormat("vn %f %f %f\n", (map.vertexes[map.linedefs[i].v2].y - map.vertexes[map.linedefs[i].v1].y), 0, -(map.vertexes[map.linedefs[i].v2].x - map.vertexes[map.linedefs[i].v1].x)); + + faces += TextFormat("f %i//%i %i//%i %i//%i\n", verticeCount + 1, vertexNormalsCount, verticeCount + 2, vertexNormalsCount, verticeCount + 3, vertexNormalsCount); + verticeCount += 3; + + } + if (map.linedefs[i].sideback != -1) { + + + + + if (map.sidedefs[map.linedefs[i].sideback].texturemiddle != "") { + /*DrawTriangle3D( + { + -1 * map.vertexes[map.linedefs[i].v2].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightceiling, + map.vertexes[map.linedefs[i].v2].y + }, + { + -1 * map.vertexes[map.linedefs[i].v2].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightfloor, + map.vertexes[map.linedefs[i].v2].y + }, + { + -1 * map.vertexes[map.linedefs[i].v1].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightfloor, + map.vertexes[map.linedefs[i].v1].y + }, + ColorLerp({ 255,0,0,255 }, { 0,0,255,255 }, i / map.linedefs.size()) + + );*/ + + + vertices += TextFormat("v %f %f %f\n", // it's at this point i realized I should've probably made this a function + -1 * map.vertexes[map.linedefs[i].v2].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightceiling, + map.vertexes[map.linedefs[i].v2].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightfloor, + map.vertexes[map.linedefs[i].v2].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightfloor, + map.vertexes[map.linedefs[i].v1].y); + + vertexNormalsCount++; + vertexnormals += TextFormat("vn %f %f %f\n", (map.vertexes[map.linedefs[i].v2].y - map.vertexes[map.linedefs[i].v1].y), 0, -(map.vertexes[map.linedefs[i].v2].x - map.vertexes[map.linedefs[i].v1].x)); + + faces += TextFormat("f %i//%i %i//%i %i//%i\n", verticeCount + 1, vertexNormalsCount, verticeCount + 2, vertexNormalsCount, verticeCount + 3, vertexNormalsCount); + verticeCount += 3; + + /*DrawTriangle3D( + { + -1 * map.vertexes[map.linedefs[i].v2].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightceiling, + map.vertexes[map.linedefs[i].v2].y + }, + { + -1 * map.vertexes[map.linedefs[i].v1].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightfloor, + map.vertexes[map.linedefs[i].v1].y + }, + { + -1 * map.vertexes[map.linedefs[i].v1].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightceiling, + map.vertexes[map.linedefs[i].v1].y + }, + ColorLerp({ 255,0,0,255 }, { 0,0,255,255 }, (float)i / (float)map.linedefs.size()) + + );*/ + + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightceiling, + map.vertexes[map.linedefs[i].v2].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightfloor, + map.vertexes[map.linedefs[i].v1].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + (float)map.sectors[map.sidedefs[map.linedefs[i].sideback].sector].heightceiling, + map.vertexes[map.linedefs[i].v1].y); + + vertexNormalsCount++; + vertexnormals += TextFormat("vn %f %f %f\n", (map.vertexes[map.linedefs[i].v2].y - map.vertexes[map.linedefs[i].v1].y), 0, -(map.vertexes[map.linedefs[i].v2].x - map.vertexes[map.linedefs[i].v1].x)); + + faces += TextFormat("f %i//%i %i//%i %i//%i\n", verticeCount + 1, vertexNormalsCount, verticeCount + 2, vertexNormalsCount, verticeCount + 3, vertexNormalsCount); + verticeCount += 3; + + } + + /*DrawTriangle3D( + { + -1 * map.vertexes[map.linedefs[i].v2].x, + midHighestPoint, + map.vertexes[map.linedefs[i].v2].y + }, + + { + -1 * map.vertexes[map.linedefs[i].v1].x, + midHighestPoint, + map.vertexes[map.linedefs[i].v1].y + }, + { + -1 * map.vertexes[map.linedefs[i].v1].x, + highestPoint, + map.vertexes[map.linedefs[i].v1].y + }, + ColorLerp({ 255,0,0,255 }, { 0,0,255,255 }, (float)i / (float)map.linedefs.size()) + + );*/ + + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + midHighestPoint, + map.vertexes[map.linedefs[i].v2].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + midHighestPoint, + map.vertexes[map.linedefs[i].v1].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + highestPoint, + map.vertexes[map.linedefs[i].v1].y); + + vertexNormalsCount++; + vertexnormals += TextFormat("vn %f %f %f\n", (map.vertexes[map.linedefs[i].v2].y - map.vertexes[map.linedefs[i].v1].y), 0, -(map.vertexes[map.linedefs[i].v2].x - map.vertexes[map.linedefs[i].v1].x)); + + faces += TextFormat("f %i//%i %i//%i %i//%i\n", verticeCount + 1, vertexNormalsCount, verticeCount + 2, vertexNormalsCount, verticeCount + 3, vertexNormalsCount); + verticeCount += 3; + + /*DrawTriangle3D( + { + -1 * map.vertexes[map.linedefs[i].v2].x, + highestPoint, + map.vertexes[map.linedefs[i].v2].y + }, + + { + -1 * map.vertexes[map.linedefs[i].v2].x, + midHighestPoint, + map.vertexes[map.linedefs[i].v2].y + }, + { + -1 * map.vertexes[map.linedefs[i].v1].x, + highestPoint, + map.vertexes[map.linedefs[i].v1].y + }, + ColorLerp({ 255,0,0,255 }, { 0,255,0,255 }, (float)i / (float)map.linedefs.size()) + + );*/ + + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + highestPoint, + map.vertexes[map.linedefs[i].v2].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + midHighestPoint, + map.vertexes[map.linedefs[i].v2].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + highestPoint, + map.vertexes[map.linedefs[i].v1].y); + + vertexNormalsCount++; + vertexnormals += TextFormat("vn %f %f %f\n", (map.vertexes[map.linedefs[i].v2].y - map.vertexes[map.linedefs[i].v1].y), 0, -(map.vertexes[map.linedefs[i].v2].x - map.vertexes[map.linedefs[i].v1].x)); + + faces += TextFormat("f %i//%i %i//%i %i//%i\n", verticeCount + 1, vertexNormalsCount, verticeCount + 2, vertexNormalsCount, verticeCount + 3, vertexNormalsCount); + verticeCount += 3; + + // --- + /*DrawTriangle3D( + { + -1 * map.vertexes[map.linedefs[i].v2].x, + lowestPoint, + map.vertexes[map.linedefs[i].v2].y + }, + { + -1 * map.vertexes[map.linedefs[i].v1].x, + lowestPoint, + map.vertexes[map.linedefs[i].v1].y + }, + + { + -1 * map.vertexes[map.linedefs[i].v1].x, + midLowestPoint, + map.vertexes[map.linedefs[i].v1].y + }, + ColorLerp({ 255,0,0,255 }, { 0,0,255,255 }, (float)i / (float)map.linedefs.size()) + + );*/ + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + lowestPoint, + map.vertexes[map.linedefs[i].v2].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + lowestPoint, + map.vertexes[map.linedefs[i].v1].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + midLowestPoint, + map.vertexes[map.linedefs[i].v1].y); + + vertexNormalsCount++; + vertexnormals += TextFormat("vn %f %f %f\n", (map.vertexes[map.linedefs[i].v2].y - map.vertexes[map.linedefs[i].v1].y), 0, -(map.vertexes[map.linedefs[i].v2].x - map.vertexes[map.linedefs[i].v1].x)); + + faces += TextFormat("f %i//%i %i//%i %i//%i\n", verticeCount + 1, vertexNormalsCount, verticeCount + 2, vertexNormalsCount, verticeCount + 3, vertexNormalsCount); + verticeCount += 3; + + /*DrawTriangle3D( + { + -1 * map.vertexes[map.linedefs[i].v2].x, + midLowestPoint, + map.vertexes[map.linedefs[i].v2].y + }, + + { + -1 * map.vertexes[map.linedefs[i].v2].x, + lowestPoint, + map.vertexes[map.linedefs[i].v2].y + }, + { + -1 * map.vertexes[map.linedefs[i].v1].x, + midLowestPoint, + map.vertexes[map.linedefs[i].v1].y + }, + ColorLerp({ 255,0,0,255 }, { 0,255,0,255 }, (float)i / (float)map.linedefs.size()) + + );*/ + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + midLowestPoint, + map.vertexes[map.linedefs[i].v2].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v2].x, + lowestPoint, + map.vertexes[map.linedefs[i].v2].y); + vertices += TextFormat("v %f %f %f\n", + -1 * map.vertexes[map.linedefs[i].v1].x, + midLowestPoint, + map.vertexes[map.linedefs[i].v1].y); + + vertexNormalsCount++; + vertexnormals += TextFormat("vn %f %f %f\n", (map.vertexes[map.linedefs[i].v2].y - map.vertexes[map.linedefs[i].v1].y), 0, -(map.vertexes[map.linedefs[i].v2].x - map.vertexes[map.linedefs[i].v1].x)); + + faces += TextFormat("f %i//%i %i//%i %i//%i\n", verticeCount + 1, vertexNormalsCount, verticeCount + 2, vertexNormalsCount, verticeCount + 3, vertexNormalsCount); + verticeCount += 3; + } + + + } + + SetRandomSeed(time(NULL)); + + + std::string randomNumber = std::to_string(GetRandomValue(0, INT_MAX)); + std::string appdata = ".";// getenv("LOCALAPPDATA"); + std::filesystem::create_directory(appdata + "\\ProjectMorault"); + std::filesystem::create_directory(appdata + "\\ProjectMorault\\__udmfCache"); + std::ofstream cacheModel(appdata + "\\ProjectMorault\\__udmfCache\\" + randomNumber + ".obj"); + std::cout << "Outputting cache model to " << appdata + "\\ProjectMorault\\__udmfCache\\" + randomNumber + ".obj" << "\n"; + + cacheModel << vertices; + cacheModel << vertexnormals; + cacheModel << faces; + cacheModel.close(); + + std::string p = appdata + "\\ProjectMorault\\__udmfCache\\" + randomNumber + ".obj"; + + Model retval = LoadModel(p.c_str()); + + return retval; +} + +Model Morault::UDMF::LoadModelUDMFFlats(UDMFMap map) +{ + int vertexCount = 0; // number of vertices + std::string vertices = ""; // straight wavefront data for the vertices + int vertexNormalsCount = 0; // number of vertex normals + std::string vertexNormals = ""; // straight wavefront data for vertexNormals + std::string faces; // straight wavefront data for faces + + + for (int sc = 0; sc < map.sectors.size(); sc++) { + std::vector* verticesVector = new std::vector(); + for (int sd = 0; sd < map.sidedefs.size(); sd++) { + if(map.sidedefs[sd].sector == sc){ + for (int ld = 0; ld < map.linedefs.size(); ld++) { + + if (map.linedefs[ld].sidefront == sd) { + verticesVector->push_back(map.vertexes[map.linedefs[ld].v1]); + verticesVector->push_back(map.vertexes[map.linedefs[ld].v2]); + } + else if (map.linedefs[ld].sideback == sd) { // you, in theory, shouldn't be able to have both the back and front of a linedef be the same. + verticesVector->push_back(map.vertexes[map.linedefs[ld].v2]);// invert vertices if sideback + verticesVector->push_back(map.vertexes[map.linedefs[ld].v1]); + } + } + } + } + + // calculating ceilings + /* + vertexNormalsCount++; + vertexNormals += "vn 0 1 0\n";*/ + + + /*faces += "f "; + for (int i = 0; i < verticesVector->size(); i++) { + vertices += TextFormat("v %f %f %f\n", -1 * verticesVector->at(i).x, (float)map.sectors[sc].heightceiling, verticesVector->at(i).y); + faces += TextFormat("%i//%i ", vertexCount + i + 1, vertexNormalsCount); + if (i % 3 == 0 && i != 0) { + faces.pop_back(); + faces += "\nf "; + } + } + + faces.pop_back(); + if (faces.at(faces.size() - 1) == 'f') { + faces.pop_back(); + } + else { + faces += TextFormat(" %i//%i", vertexCount + 1, vertexNormalsCount); + } + faces += "\n"; + + vertexCount += verticesVector->size();*/ + + + // calculating floors + vertexNormalsCount++; + vertexNormals += "vn 0 1 0\n"; + + + faces += "f "; + for (int i = 0; i < verticesVector->size(); i++) { + vertices += TextFormat("v %f %f %f\n", -1 * verticesVector->at(verticesVector->size() - 1 - i).x, (float)map.sectors[sc].heightfloor, verticesVector->at(verticesVector->size() - 1 - i).y); + faces += TextFormat("%i//%i ", vertexCount + i + 1, vertexNormalsCount); + if (i % 3 == 0 && i != 0) { + faces.pop_back(); + faces += "\nf "; + } + } + + faces.pop_back(); + if (faces.at(faces.size() - 1) == 'f') { + faces.pop_back(); + } + else { + faces += TextFormat(" %i//%i", vertexCount + 1, vertexNormalsCount); + } + faces += "\n"; + + vertexCount += verticesVector->size(); + delete verticesVector; + } + + std::string randomNumber = std::to_string(GetRandomValue(0, INT_MAX)); + std::string appdata = ".";// getenv("LOCALAPPDATA"); + std::filesystem::create_directory(appdata + "\\ProjectMorault"); + std::filesystem::create_directory(appdata + "\\ProjectMorault\\__udmfCache"); + std::ofstream cacheModel(appdata + "\\ProjectMorault\\__udmfCache\\" + randomNumber + ".obj"); + std::cout << "Outputting cache model to " << appdata + "\\ProjectMorault\\__udmfCache\\" + randomNumber + ".obj" << "\n"; + + cacheModel << vertices; + cacheModel << vertexNormals; + cacheModel << faces; + cacheModel.close(); + + std::string p = appdata + "\\ProjectMorault\\__udmfCache\\" + randomNumber + ".obj"; + + Model retval = LoadModel(p.c_str()); + + return retval; +} diff --git a/ProjectMorault/Morault_UDMF.h b/ProjectMorault/Morault_UDMF.h new file mode 100644 index 0000000..789ea26 --- /dev/null +++ b/ProjectMorault/Morault_UDMF.h @@ -0,0 +1,51 @@ +#pragma once +#include + +#include +#include + + +namespace Morault { + namespace UDMF { // DEPRECATED, DO NOT USE. + + struct Linedef { + int v1, v2, sidefront = -1, sideback = -1; + bool blocking; + + }; + + struct Sidedef { + int sector; + std::string texturetop = ""; + std::string texturemiddle = ""; + std::string texturebottom = ""; + }; + + struct Vertex { + float x, y; + }; + + struct Sector { + std::string texturefloor; + std::string textureceiling; + int heightceiling = 128; + int heightfloor = 0; + + }; + + class UDMFMap { + public: + std::string udmfNamespace; + std::vector linedefs; + std::vector sidedefs; + std::vector vertexes; + std::vector sectors; + + void LoadMap(std::string textmap); + + }; + + Model LoadModelUDMFWalls(UDMFMap map); + Model LoadModelUDMFFlats(UDMFMap map); + } +} \ No newline at end of file diff --git a/ProjectMorault/Morault_Utils.cpp b/ProjectMorault/Morault_Utils.cpp new file mode 100644 index 0000000..3bdf182 --- /dev/null +++ b/ProjectMorault/Morault_Utils.cpp @@ -0,0 +1,123 @@ +#include "Morault_Utils.h" +#include +#include +#include +bool Morault::Utils::Strings::IterativeComp(std::string originalString, int startPointer, std::string toCompare) +{ + bool retVal = true; + for (int i = 0; i < toCompare.length(); i++) { + retVal = originalString.at(startPointer + i) == toCompare.at(i); + if (retVal == false) break; + } + return retVal; +} + +std::string Morault::Utils::Strings::IterativeStringExcerpt(std::string originalString, int startPointer, int length) +{ + std::string retval = ""; + if (startPointer == -1) return retval; + for (int i = 0; i < length; i++) { + retval += originalString[startPointer + i]; + } + + return retval; +} + +int32_t Morault::Utils::Strings::StringIndexToInteger_4b_le(std::string originalString, int startPointer) +{ + int32_t retval; + + retval = (unsigned char)originalString.at(startPointer + 3) << 24; + retval += (unsigned char)originalString.at(startPointer + 2) << 16; + retval += (unsigned char)originalString.at(startPointer + 1) << 8; + retval += (unsigned char)originalString.at(startPointer); + + + return retval; +} + +int32_t Morault::Utils::Strings::StringIndexToInteger_2b_le(std::string originalString, int startPointer) +{ + int32_t retval; + + retval = (unsigned char)originalString.at(startPointer + 1) << 8; + retval += (unsigned char)originalString.at(startPointer); + + + return retval; +} + +std::tuple Morault::Utils::Strings::ParseCLineIntoKeyVal(std::string originalString) +{ + std::tuple retval; + + int equPos = -1, valstartpos = -1, valendpos = -1; + bool inQuotes = false; + + for (int i = 0; i < originalString.size(); i++) { + if (originalString[i] == '=' and equPos == -1) { + equPos = i; + valstartpos = i + 1; + } + if (originalString[i] == '"') { + if (inQuotes) { + valendpos = i - 1; + break; + } + if (valstartpos == -1) { + valstartpos = i + 1; + inQuotes = true; + } + } + if (originalString[i] == ';' and not inQuotes) { + valendpos = i - 1; + } + + } + + try { + retval = std::make_tuple(IterativeStringExcerpt(originalString, 0, equPos), IterativeStringExcerpt(originalString, valstartpos, valendpos - valstartpos + 1)); + } + catch(...){ + retval = std::make_tuple("", ""); + } + return retval; +} + +std::string Morault::Utils::Strings::SingleWordTrimmer(std::string originalString) +{ + for (int i = 0; i < originalString.size(); i++) { + if (originalString[i] == ' ' or originalString[i] == '/') return IterativeStringExcerpt(originalString, 0, i); + } + + return originalString; +} + +std::basic_string Morault::Utils::Geometry::TesselateVertexString(VertexString vs) +{ + + std::basic_string retval; + + /*GLUtesselator* tess = gluNewTess(); + + + gluTessBeginPolygon(tess, 0); + + for (int i = 0; i < vs.size(); i++) { + GLdouble* coords; + coords[0] = static_cast(vs[i].x); + coords[1] = 0; + coords[2] = static_cast(vs[i].y); + gluTessVertex(tess, coords, coords); + } + gluTessEndPolygon(tess); + + + + gluDeleteTess(tess); + + */ + throw; + + return retval; +} diff --git a/ProjectMorault/Morault_Utils.h b/ProjectMorault/Morault_Utils.h new file mode 100644 index 0000000..22156a9 --- /dev/null +++ b/ProjectMorault/Morault_Utils.h @@ -0,0 +1,26 @@ +#pragma once +#include + +namespace Morault { + namespace Utils { + namespace Geometry { + struct Vertex2D { + float x, y; + }; + struct Triangle2D { + float a, b, c; + }; + using VertexString = std::basic_string; + + std::basic_string TesselateVertexString(VertexString vs); + } + namespace Strings { + bool IterativeComp(std::string originalString, int startPointer, std::string toCompare); + std::string IterativeStringExcerpt(std::string originalString, int startPointer, int length); + int32_t StringIndexToInteger_4b_le(std::string originalString, int startPointer); + int32_t StringIndexToInteger_2b_le(std::string originalString, int startPointer); + std::tuple ParseCLineIntoKeyVal(std::string originalString); + std::string SingleWordTrimmer(std::string originalString); + } + } +} \ No newline at end of file diff --git a/ProjectMorault/ProjectMorault.vcxproj b/ProjectMorault/ProjectMorault.vcxproj new file mode 100644 index 0000000..b920807 --- /dev/null +++ b/ProjectMorault/ProjectMorault.vcxproj @@ -0,0 +1,154 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {a20204cf-23c4-4386-a432-a135319786dc} + ProjectMorault + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SOLUTIONDIR)deps/include + stdcpp20 + + + Console + true + $(SOLUTIONDIR)deps/lib + raylib.lib;winmm.lib;gdi32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) + + + + + Level3 + true + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SOLUTIONDIR)deps/include + stdcpp20 + + + Console + true + true + true + $(SOLUTIONDIR)deps/lib + raylib.lib;winmm.lib;gdi32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ProjectMorault/ProjectMorault.vcxproj.filters b/ProjectMorault/ProjectMorault.vcxproj.filters new file mode 100644 index 0000000..0b968f2 --- /dev/null +++ b/ProjectMorault/ProjectMorault.vcxproj.filters @@ -0,0 +1,51 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/ProjectMorault/ProjectMorault.vcxproj.user b/ProjectMorault/ProjectMorault.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/ProjectMorault/ProjectMorault.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ProjectMorault/main.cpp b/ProjectMorault/main.cpp new file mode 100644 index 0000000..f1d2593 --- /dev/null +++ b/ProjectMorault/main.cpp @@ -0,0 +1,129 @@ +#include +#include +#include "Morault_Resources.h" +#include "Morault_Player.h" +#include "Morault_UDMF.h" +#include +#include + +#define MORAULT_MAP_RENDER_SCALE 0.1f +int main(int argc, char** argv) { + InitWindow(1280, 720, "ProjectMorault"); + // SetTargetFPS(60); + SetExitKey(0); + + // if (!std::get(Morault::Resources::Models(Morault::Resources::load("data/baseblock.glb")))) throw std::runtime_error("couldn't load baseblock"); + + + DisableCursor(); + + Morault::Gameplay::Player player; + player.data.playerName = "TestPlayer0001"; + player.data.hp = 100; + player.data.xp = 0; + bool gamePaused = false; + + + Vector2 offset = { 0,0 }; + + + /*Morault::Resources::WAD wad("data/testmall.wad"); + + Morault::UDMF::UDMFMap map; + map.LoadMap(wad.getLumps()[1].data); + + Model mapModel = Morault::UDMF::LoadModelUDMFWalls(map); + mapModel.materials[0].maps[MATERIAL_MAP_ALBEDO].texture = LoadTextureFromImage(Morault::Resources::GenTestImage()); + // Model mapFlatModel = Morault::UDMF::LoadModelUDMFFlats(map); + */ + while (!WindowShouldClose()) { + player.controller.UpdatePlayerController(!gamePaused); + + if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) { + offset = Vector2Add(offset, GetMouseDelta()); + } + std::vector floorModels; + BeginDrawing(); + ClearBackground(BLACK); + BeginMode3D(player.controller.camera); + DrawGrid(100, 10); + EndMode3D(); + /*DrawModel(mapModel, {0,0,0}, MORAULT_MAP_RENDER_SCALE, WHITE); + + for (int sc = 0; sc < map.sectors.size(); sc++) { + std::vector* verticesVector = new std::vector(); + std::vector meshVector; + for (int sd = 0; sd < map.sidedefs.size(); sd++) { + if (map.sidedefs[sd].sector == sc) { + for (int ld = 0; ld < map.linedefs.size(); ld++) { + + if (map.linedefs[ld].sidefront == sd) { + verticesVector->push_back(map.vertexes[map.linedefs[ld].v1]); + verticesVector->push_back(map.vertexes[map.linedefs[ld].v2]); + } + if (map.linedefs[ld].sideback == sd) { // you, in theory, shouldn't be able to have both the back and front of a linedef be the same. + verticesVector->push_back(map.vertexes[map.linedefs[ld].v1]);// invert vertices if sideback + verticesVector->push_back(map.vertexes[map.linedefs[ld].v2]); + } + } + } + } + + for (int i = 0; i < verticesVector->size(); i++) { + meshVector.push_back({ + (float)verticesVector->at(i).x * -1 * MORAULT_MAP_RENDER_SCALE, + (float)map.sectors[sc].heightfloor * MORAULT_MAP_RENDER_SCALE, + (float)verticesVector->at(i).y * MORAULT_MAP_RENDER_SCALE + }); + } + + DrawTriangleStrip3D(meshVector.data(), meshVector.size(), {((unsigned char)((float)255*(float)(sc/map.sectors.size()))), 255, 255, 255}); + + /*Mesh fMesh = { + .vertexCount = (int)verticesVector->size(), + .triangleCount = 1, + .vertices = (float*)MemAlloc(verticesVector->size() * 3 * sizeof(float)), + }; + + + + for (int i = 0; i < verticesVector->size(); i++) { + fMesh.vertices[i * 3 + 0] = verticesVector->at(i).x * MORAULT_MAP_RENDER_SCALE * -1; + fMesh.vertices[i * 3 + 1] = map.sectors[sc].heightfloor * MORAULT_MAP_RENDER_SCALE; + fMesh.vertices[i * 3 + 2] = verticesVector->at(i).y * MORAULT_MAP_RENDER_SCALE; + } + UploadMesh(&fMesh, false); + floorModels.push_back(LoadModelFromMesh(fMesh)); + delete verticesVector; + } + /*for (int i = 0; i < floorModels.size(); i++) DrawModel(floorModels[i], { 0,0,0 }, 1, WHITE); + + //DrawModel(std::get(Morault::Resources::Models(Morault::Resources::get("data/baseblock.glb"))), { 0,0,0 }, 1, WHITE); + + /*DrawText(TextFormat("Camera offset: %i;%i", (int)offset.x, (int)offset.y), 0, 30, 20, WHITE); + DrawText(TextFormat("Mouse pos on map: %i;%i", (int)offset.x + GetMouseX(), (int)offset.y + GetMouseY()), 0, 50, 20, WHITE); + DrawText(TextFormat("Camera offset: %i;%i", (int)player.controller.camera.position.x, (int)player.controller.camera.position.z), 0, 30, 20, WHITE); + DrawText(TextFormat("Linedefs: %i", map.linedefs.size()), 0, 70, 20, WHITE); + DrawText(TextFormat("Sidedefs: %i", map.sidedefs.size()), 0, 90, 20, WHITE); + DrawText(TextFormat("Vertices: %i", map.vertexes.size()), 0, 110, 20, WHITE); + DrawText(TextFormat("Sectors: %i", map.sectors.size()), 0, 130, 20, WHITE); + + */ + DrawFPS(0, 0); + EndDrawing(); + + /*for (int i = 0; i < floorModels.size(); i++) UnloadModel(floorModels[i]); + floorModels.clear();*/ + + if (IsKeyPressed(KEY_P)) { + int x, y; + std::cin >> x >> y; + player.controller.camera.position.x = x; + player.controller.camera.position.z = y; + } + + } + + + CloseWindow(); +} \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..43a6445 --- /dev/null +++ b/readme.md @@ -0,0 +1,27 @@ +# Project Morault +## A source-available attempt at a humanist and persistent live-service game + +Project Morault is a source-available attempt at a humanist and persistent live-service game. + +## Goals +### Ideological +- Establish open standards for items, trading, markets, and user interaction +- Create healthier game environments and ranking systems overall + +### Technical +- Create an engine that allows any device to run the game at competitive framerates +- Create a simpler map format inspired by UDMF to simplify rendering and collision maths to achieve better performance + +## Why say source-available and not open-source? + +Collaboration is more or less only open to other tilde.town users for the time being. Forking and modding outside of tilde.town, however, are both allowed and encouraged. + +## Dependencies +- C++20 +- raylib 5.5 + +## Building for Windows (VS2022) +Compiling on Windows with Visual Studio 2022 is relatively straight-forward. Simply clone the repository, then create a ``deps`` folder at the root of the repo. Inside your new folder, create an ``include`` folder and a ``lib`` folder. Then, follow the instructions for each dependency. Afterwards, simply open the ``ProjectMorault.sln`` solution using Visual Studio 2022 and run. + +### raylib 5.5 +First, download [raylib 5.5 built for x64 MSVC from GitHub](https://github.com/raysan5/raylib/releases/download/5.5/raylib-5.5_win64_msvc16.zip). Then, place the contents of the ``include`` folder of the archive within your ``deps/include`` folder. Then, place the contents of the ``lib`` folder of the archive within your ``deps/lib`` folder. \ No newline at end of file