From 44434852db4c83bd589022cc8283104375e33140 Mon Sep 17 00:00:00 2001 From: kvxd Date: Wed, 24 Sep 2025 20:28:28 +0200 Subject: [PATCH 1/3] feat(core): Resource Loading Implement a simple resource system --- .../dev/mtctx/foresst/resource/ContentType.kt | 26 +++++++++++ .../foresst/resource/InputStreamFilePairs.kt | 24 ++++++++++ .../dev/mtctx/foresst/resource/Resource.kt | 45 +++++++++++++++++++ .../mtctx/foresst/resource/ResourceLoader.kt | 32 +++++++++++++ .../mtctx/foresst/resource/type/ByteArray.kt | 33 ++++++++++++++ .../mtctx/foresst/resource/type/RawFile.kt | 31 +++++++++++++ .../dev/mtctx/foresst/resource/type/Text.kt | 32 +++++++++++++ 7 files changed, 223 insertions(+) create mode 100644 core/src/main/kotlin/dev/mtctx/foresst/resource/ContentType.kt create mode 100644 core/src/main/kotlin/dev/mtctx/foresst/resource/InputStreamFilePairs.kt create mode 100644 core/src/main/kotlin/dev/mtctx/foresst/resource/Resource.kt create mode 100644 core/src/main/kotlin/dev/mtctx/foresst/resource/ResourceLoader.kt create mode 100644 core/src/main/kotlin/dev/mtctx/foresst/resource/type/ByteArray.kt create mode 100644 core/src/main/kotlin/dev/mtctx/foresst/resource/type/RawFile.kt create mode 100644 core/src/main/kotlin/dev/mtctx/foresst/resource/type/Text.kt diff --git a/core/src/main/kotlin/dev/mtctx/foresst/resource/ContentType.kt b/core/src/main/kotlin/dev/mtctx/foresst/resource/ContentType.kt new file mode 100644 index 0000000..68300cf --- /dev/null +++ b/core/src/main/kotlin/dev/mtctx/foresst/resource/ContentType.kt @@ -0,0 +1,26 @@ +/* + * Foresst: Resource.kt + * Copyright (C) 2025 mtctx + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.resource + +import java.io.File +import java.io.InputStream + +interface ContentType { + fun convert(isp: Pair): T +} \ No newline at end of file diff --git a/core/src/main/kotlin/dev/mtctx/foresst/resource/InputStreamFilePairs.kt b/core/src/main/kotlin/dev/mtctx/foresst/resource/InputStreamFilePairs.kt new file mode 100644 index 0000000..7689143 --- /dev/null +++ b/core/src/main/kotlin/dev/mtctx/foresst/resource/InputStreamFilePairs.kt @@ -0,0 +1,24 @@ +/* + * Foresst: InputStreamFilePairs.kt + * Copyright (C) 2025 mtctx + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.resource + +object InputStreamFilePairs { + val Pair.inputStream get() = first + val Pair<*, Y>.file get() = second +} \ No newline at end of file diff --git a/core/src/main/kotlin/dev/mtctx/foresst/resource/Resource.kt b/core/src/main/kotlin/dev/mtctx/foresst/resource/Resource.kt new file mode 100644 index 0000000..efa6df6 --- /dev/null +++ b/core/src/main/kotlin/dev/mtctx/foresst/resource/Resource.kt @@ -0,0 +1,45 @@ +/* + * Foresst: Resource.kt + * Copyright (C) 2025 mtctx + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.resource + +import java.io.File +import java.io.InputStream +import java.nio.file.Files +import java.nio.file.Path + +class Resource(resourcePath: String) { + + private val inputStream: InputStream = + ResourceLoader.getResourceAsStream(resourcePath) + ?: throw IllegalStateException("Resource $resourcePath not found.") + + private val tempFile: Path by lazy { + val tempFile = Files.createTempFile("foresst-", ".tmp") + tempFile.toFile().deleteOnExit() + Files.copy(inputStream, tempFile, java.nio.file.StandardCopyOption.REPLACE_EXISTING) + tempFile + } + + val file: File + get() = tempFile.toFile() + + fun typed(type: ContentType): T { + return type.convert(Pair(inputStream, file)) + } +} \ No newline at end of file diff --git a/core/src/main/kotlin/dev/mtctx/foresst/resource/ResourceLoader.kt b/core/src/main/kotlin/dev/mtctx/foresst/resource/ResourceLoader.kt new file mode 100644 index 0000000..908fc0f --- /dev/null +++ b/core/src/main/kotlin/dev/mtctx/foresst/resource/ResourceLoader.kt @@ -0,0 +1,32 @@ +/* + * Foresst: ResourceLoader.kt + * Copyright (C) 2025 mtctx + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.resource + +import java.io.InputStream + +object ResourceLoader { + + fun getResourceAsStream(resourcePath: String): InputStream? { + return ResourceLoader::class.java.classLoader.getResourceAsStream(resourcePath) + } +} + +fun import(resourcePath: String): Resource { + return Resource(resourcePath) +} \ No newline at end of file diff --git a/core/src/main/kotlin/dev/mtctx/foresst/resource/type/ByteArray.kt b/core/src/main/kotlin/dev/mtctx/foresst/resource/type/ByteArray.kt new file mode 100644 index 0000000..759a977 --- /dev/null +++ b/core/src/main/kotlin/dev/mtctx/foresst/resource/type/ByteArray.kt @@ -0,0 +1,33 @@ +/* + * Foresst: BinaryArray.kt + * Copyright (C) 2025 mtctx + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.resource.type + +import dev.mtctx.foresst.resource.ContentType +import dev.mtctx.foresst.resource.InputStreamFilePairs +import java.io.File +import java.io.InputStream +import kotlin.ByteArray + +object ByteArray : ContentType { + + override fun convert(isp: Pair): ByteArray = + with(InputStreamFilePairs) { + return isp.inputStream.readBytes() + } +} \ No newline at end of file diff --git a/core/src/main/kotlin/dev/mtctx/foresst/resource/type/RawFile.kt b/core/src/main/kotlin/dev/mtctx/foresst/resource/type/RawFile.kt new file mode 100644 index 0000000..8cb10c1 --- /dev/null +++ b/core/src/main/kotlin/dev/mtctx/foresst/resource/type/RawFile.kt @@ -0,0 +1,31 @@ +/* + * Foresst: RawFile.kt + * Copyright (C) 2025 mtctx + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.resource.type + +import dev.mtctx.foresst.resource.ContentType +import dev.mtctx.foresst.resource.InputStreamFilePairs.file +import java.io.File +import java.io.InputStream + +object RawFile : ContentType { + + override fun convert(isp: Pair): File { + return isp.file + } +} \ No newline at end of file diff --git a/core/src/main/kotlin/dev/mtctx/foresst/resource/type/Text.kt b/core/src/main/kotlin/dev/mtctx/foresst/resource/type/Text.kt new file mode 100644 index 0000000..7d42cd2 --- /dev/null +++ b/core/src/main/kotlin/dev/mtctx/foresst/resource/type/Text.kt @@ -0,0 +1,32 @@ +/* + * Foresst: Text.kt + * Copyright (C) 2025 mtctx + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.resource.type + +import dev.mtctx.foresst.resource.ContentType +import dev.mtctx.foresst.resource.InputStreamFilePairs +import java.io.File +import java.io.InputStream + +object Text : ContentType { + + override fun convert(isp: Pair): String = + with(InputStreamFilePairs) { + return isp.file.readText() + } +} \ No newline at end of file From f86393f0f8ebc6e763c41dbe351ced67477a5572 Mon Sep 17 00:00:00 2001 From: kvxd Date: Wed, 24 Sep 2025 20:30:07 +0200 Subject: [PATCH 2/3] feat(graphics): Initial Graphics implementation using OpenGL Various GL abstractions have been added to ease further development and avoid native opengl calls entirely. --- graphics/build.gradle.kts | 3 + .../dev/mtctx/foresst/graphics/Graphics.kt | 86 ++++++++ .../dev/mtctx/foresst/graphics/Renderable.kt | 27 +++ .../dev/mtctx/foresst/graphics/Renderer.kt | 26 +++ .../dev/mtctx/foresst/graphics/Window.kt | 63 ++++++ .../mtctx/foresst/graphics/gl/GLDataType.kt | 44 ++++ .../dev/mtctx/foresst/graphics/gl/GLShader.kt | 189 ++++++++++++++++++ .../mtctx/foresst/graphics/gl/GLShaderType.kt | 26 +++ .../foresst/graphics/gl/GLVertexArray.kt | 96 +++++++++ .../graphics/gl/buffer/GLBufferElement.kt | 27 +++ .../graphics/gl/buffer/GLBufferLayout.kt | 49 +++++ .../graphics/gl/buffer/GLIndexBuffer.kt | 55 +++++ .../graphics/gl/buffer/GLVertexBuffer.kt | 54 +++++ .../graphics/renderers/VoxelRenderer.kt | 86 ++++++++ .../graphics/utils/TranslationUtils.kt | 32 +++ graphics/src/main/resources/frag.fs | 7 + graphics/src/main/resources/vert.vs | 9 + graphics/src/test/kotlin/main.kt | 24 +++ 18 files changed, 903 insertions(+) create mode 100644 graphics/src/main/kotlin/dev/mtctx/foresst/graphics/Graphics.kt create mode 100644 graphics/src/main/kotlin/dev/mtctx/foresst/graphics/Renderable.kt create mode 100644 graphics/src/main/kotlin/dev/mtctx/foresst/graphics/Renderer.kt create mode 100644 graphics/src/main/kotlin/dev/mtctx/foresst/graphics/Window.kt create mode 100644 graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLDataType.kt create mode 100644 graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLShader.kt create mode 100644 graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLShaderType.kt create mode 100644 graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLVertexArray.kt create mode 100644 graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/buffer/GLBufferElement.kt create mode 100644 graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/buffer/GLBufferLayout.kt create mode 100644 graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/buffer/GLIndexBuffer.kt create mode 100644 graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/buffer/GLVertexBuffer.kt create mode 100644 graphics/src/main/kotlin/dev/mtctx/foresst/graphics/renderers/VoxelRenderer.kt create mode 100644 graphics/src/main/kotlin/dev/mtctx/foresst/graphics/utils/TranslationUtils.kt create mode 100644 graphics/src/main/resources/frag.fs create mode 100644 graphics/src/main/resources/vert.vs create mode 100644 graphics/src/test/kotlin/main.kt diff --git a/graphics/build.gradle.kts b/graphics/build.gradle.kts index 24fecc1..b63ec37 100644 --- a/graphics/build.gradle.kts +++ b/graphics/build.gradle.kts @@ -81,6 +81,9 @@ dependencies { implementation("org.lwjgl", "lwjgl-openal", classifier = lwjglNatives) implementation("org.lwjgl", "lwjgl-opengl", classifier = lwjglNatives) implementation("org.lwjgl", "lwjgl-stb", classifier = lwjglNatives) + + implementation("io.github.kotlin-graphics:glm:0.9.9.1-12") + testImplementation(kotlin("test")) } diff --git a/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/Graphics.kt b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/Graphics.kt new file mode 100644 index 0000000..16c974c --- /dev/null +++ b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/Graphics.kt @@ -0,0 +1,86 @@ +/* + * Foresst: Graphics.kt + * Copyright (C) 2025 mtctx, kvxd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.graphics + +import dev.mtctx.foresst.graphics.gl.GLShader +import dev.mtctx.foresst.graphics.gl.GLShaderType +import dev.mtctx.foresst.graphics.renderers.VoxelRenderer +import dev.mtctx.foresst.resource.Resource +import org.lwjgl.glfw.GLFW.* +import org.lwjgl.glfw.GLFWErrorCallback +import org.lwjgl.opengl.GL +import org.lwjgl.opengl.GL46.* + + +// TERRIBLE CODE AHEAD; WATCH YOUR STEP +object Graphics { + + lateinit var window: Window + lateinit var shader: GLShader + private val renderers = mutableListOf() + + fun run() { + init() + render() + } + + fun init() { + GLFWErrorCallback.createPrint(System.err).set() + check(glfwInit()) { "Unable to initialize GLFW" } + window = Window() + GL.createCapabilities() + + val fragment = Resource("frag.fs") + val vertex = Resource("vert.vs") + + shader = GLShader( + listOf( + GLShader.ShaderModule( + fragment, + GLShaderType.FRAGMENT + ), + GLShader.ShaderModule( + vertex, + GLShaderType.VERTEX + ) + ) + ) + + renderers.add(VoxelRenderer(shader)) + } + + fun render() { + while (!glfwWindowShouldClose(window.handle)) { + glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT) + + val deltaTime = glfwGetTime().toFloat() + + renderers.forEach { + it.update(deltaTime) + it.render() + } + + glfwSwapBuffers(window.handle) + glfwPollEvents() + } + + renderers.forEach(Renderer::close) + } + +} \ No newline at end of file diff --git a/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/Renderable.kt b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/Renderable.kt new file mode 100644 index 0000000..9c29be6 --- /dev/null +++ b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/Renderable.kt @@ -0,0 +1,27 @@ +/* + * Foresst: Renderable.kt + * Copyright (C) 2025 mtctx + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.graphics + +import java.io.Closeable + +interface Renderable: Closeable { + + fun render() + +} \ No newline at end of file diff --git a/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/Renderer.kt b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/Renderer.kt new file mode 100644 index 0000000..7066707 --- /dev/null +++ b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/Renderer.kt @@ -0,0 +1,26 @@ +/* + * Foresst: Renderer.kt + * Copyright (C) 2025 mtctx, kvxd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.graphics + +interface Renderer : AutoCloseable { + + fun render() + fun update(deltaTime: Float) {} + +} \ No newline at end of file diff --git a/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/Window.kt b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/Window.kt new file mode 100644 index 0000000..903a39c --- /dev/null +++ b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/Window.kt @@ -0,0 +1,63 @@ +/* + * Foresst: Window.kt + * Copyright (C) 2025 mtctx, kvxd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.graphics + +import java.io.Closeable + +import org.lwjgl.glfw.Callbacks +import org.lwjgl.glfw.GLFW.* +import org.lwjgl.opengl.GL46.* +import org.lwjgl.system.MemoryUtil + +class Window( + var width: Int = 800, + var height: Int = 600, + var handle: Long = -1 +) : Closeable { + + init { + glfwDefaultWindowHints() + glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE) + glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE) + + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4) + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6) + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE) + + handle = glfwCreateWindow(width, height, "Keaengine", MemoryUtil.NULL, MemoryUtil.NULL) + if (handle == MemoryUtil.NULL) throw RuntimeException("Failed to create the GLFW window") + + glfwMakeContextCurrent(handle) + glfwSwapInterval(1) + + glfwShowWindow(handle) + + glfwSetFramebufferSizeCallback(handle) { _: Long, newWidth: Int, newHeight: Int -> + this.width = newWidth + this.height = newHeight + glViewport(0, 0, width, height) + } + } + + override fun close() { + Callbacks.glfwFreeCallbacks(handle) + glfwDestroyWindow(handle) + } + +} \ No newline at end of file diff --git a/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLDataType.kt b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLDataType.kt new file mode 100644 index 0000000..057f34f --- /dev/null +++ b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLDataType.kt @@ -0,0 +1,44 @@ +/* + * Foresst: GLDataType.kt + * Copyright (C) 2025 mtctx, kvxd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.graphics.gl + +import org.lwjgl.opengl.GL46.* + +enum class GLDataType(val size: Int, val glType: Int) { + + Float(1, GL_FLOAT), + Integer(1, GL_INT), + Boolean(1, GL_BOOL), + Vec2(2, GL_FLOAT), + Vec3(3, GL_FLOAT), + Vec4(4, GL_FLOAT), + Mat2(2 * 2, GL_FLOAT), + Mat3(3 * 3, GL_FLOAT), + Mat4(4 * 4, GL_FLOAT); + + fun byteSize(): Int = + size * when (glType) { + GL_INT -> Int.SIZE_BYTES + GL_FLOAT -> kotlin.Float.SIZE_BYTES + GL_DOUBLE -> Double.SIZE_BYTES + GL_BOOL -> Byte.SIZE_BYTES + else -> throw IllegalArgumentException("Unsupported GL type: $glType") + } + +} \ No newline at end of file diff --git a/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLShader.kt b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLShader.kt new file mode 100644 index 0000000..b9c14c2 --- /dev/null +++ b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLShader.kt @@ -0,0 +1,189 @@ +/* + * Foresst: GLShader.kt + * Copyright (C) 2025 mtctx, kvxd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.graphics.gl + +import dev.mtctx.foresst.graphics.Renderable +import dev.mtctx.foresst.resource.Resource +import dev.mtctx.foresst.resource.type.Text +import glm_.mat2x2.Mat2 +import glm_.mat3x3.Mat3 +import glm_.mat4x4.Mat4 +import glm_.vec2.Vec2 +import glm_.vec3.Vec3 +import glm_.vec4.Vec4 +import org.lwjgl.opengl.GL46.* + +class GLShader( + modules: List +) : Renderable { + + private var program: Int = 0 + private val uniformLocationCache = mutableMapOf() + + init { + if (modules.isEmpty()) throw IllegalArgumentException("No shader modules provided") + + val duplicates = modules.groupingBy { it.shaderType } + .eachCount() + .filterValues { it > 1 } + .keys + + if (duplicates.isNotEmpty()) { + throw IllegalArgumentException("Duplicate shader modules for types: ${duplicates.joinToString()}") + } + + program = glCreateProgram().also { if (it == 0) throw RuntimeException("glCreateProgram returned 0") } + + val shaderIds = mutableListOf() + try { + for (module in modules) { + val shaderId = compileModule(module) + shaderIds += shaderId + glAttachShader(program, shaderId) + } + + glLinkProgram(program) + val linkStatus = glGetProgrami(program, GL_LINK_STATUS) + if (linkStatus == GL_FALSE) { + val infoLog = glGetProgramInfoLog(program) + throw RuntimeException("Failed to link program: $infoLog") + } + + for (id in shaderIds) { + glDetachShader(program, id) + glDeleteShader(id) + } + + } catch (e: Exception) { + for (id in shaderIds) { + if (glIsShader(id)) glDeleteShader(id) + } + if (glIsProgram(program)) { + glDeleteProgram(program) + program = 0 + } + throw e + } + } + + private fun compileModule(module: ShaderModule): Int { + val shaderId = glCreateShader(module.shaderType.id) + if (shaderId == 0) throw RuntimeException("glCreateShader returned 0 for type=${module.shaderType}") + + glShaderSource(shaderId, module.res.typed(Text)) + glCompileShader(shaderId) + + val status = glGetShaderi(shaderId, GL_COMPILE_STATUS) + if (status == GL_FALSE) { + val infoLog = glGetShaderInfoLog(shaderId) + glDeleteShader(shaderId) + throw RuntimeException("Failed to compile shader (${module.name ?: module.shaderType}): $infoLog") + } + + return shaderId + } + + fun use(block: Context.() -> Unit) { + bind() + try { + Context(this).block() + } finally { + unbind() + } + } + + fun bind() { + if (program == 0) throw IllegalStateException("Program has been deleted") + glUseProgram(program) + } + + fun unbind() { + glUseProgram(0) + } + + override fun render() { + bind() + } + + override fun close() { + unbind() + } + + fun delete() { + if (program != 0 && glIsProgram(program)) { + glDeleteProgram(program) + program = 0 + } + } + + data class ShaderModule(val res: Resource, val shaderType: GLShaderType, val name: String? = null) + + class Context internal constructor(private val shader: GLShader) { + + private fun getLocation(name: String): Int = + shader.uniformLocationCache.getOrPut(name) { + glGetUniformLocation(shader.program, name) + } + + fun uniformInt(name: String, value: Int) { + val loc = getLocation(name) + if (loc != -1) glUniform1i(loc, value) + } + + fun uniformFloat(name: String, value: Float) { + val loc = getLocation(name) + if (loc != -1) glUniform1f(loc, value) + } + + fun uniformVec2(name: String, value: Vec2) { + val loc = getLocation(name) + if (loc != -1) glUniform2f(loc, value.x, value.y) + } + + fun uniformVec3(name: String, value: Vec3) { + val loc = getLocation(name) + if (loc != -1) glUniform3f(loc, value.x, value.y, value.z) + } + + fun uniformVec4(name: String, value: Vec4) { + val loc = getLocation(name) + if (loc != -1) glUniform4f(loc, value.x, value.y, value.z, value.w) + } + + fun uniformMat2(name: String, value: Mat2) { + val loc = getLocation(name) + if (loc != -1) glUniformMatrix2fv(loc, false, value.array) + } + + fun uniformMat3(name: String, value: Mat3) { + val loc = getLocation(name) + if (loc != -1) glUniformMatrix3fv(loc, false, value.array) + } + + fun uniformMat4(name: String, value: Mat4) { + val loc = getLocation(name) + if (loc != -1) glUniformMatrix4fv(loc, false, value.array) + } + + fun uniformIntArray(name: String, values: IntArray) { + val loc = getLocation(name) + if (loc != -1) glUniform1iv(loc, values) + } + } +} diff --git a/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLShaderType.kt b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLShaderType.kt new file mode 100644 index 0000000..4a2acb6 --- /dev/null +++ b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLShaderType.kt @@ -0,0 +1,26 @@ +/* + * Foresst: GLShaderType.kt + * Copyright (C) 2025 mtctx, kvxd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.graphics.gl + +import org.lwjgl.opengl.GL20 + +enum class GLShaderType(val id : Int) { + FRAGMENT(GL20.GL_FRAGMENT_SHADER), + VERTEX(GL20.GL_VERTEX_SHADER) +} \ No newline at end of file diff --git a/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLVertexArray.kt b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLVertexArray.kt new file mode 100644 index 0000000..9bb1d71 --- /dev/null +++ b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLVertexArray.kt @@ -0,0 +1,96 @@ +/* + * Foresst: GLVertexArray.kt + * Copyright (C) 2025 mtctx, kvxd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.graphics.gl + +import dev.mtctx.foresst.graphics.Renderable +import dev.mtctx.foresst.graphics.gl.buffer.GLIndexBuffer +import dev.mtctx.foresst.graphics.gl.buffer.GLVertexBuffer +import org.lwjgl.opengl.GL46.* + +class GLVertexArray(private val indexBuffer: GLIndexBuffer? = null, private val mode: Int = GL_TRIANGLES) : Renderable { + + private var id: Int = 0 + private val vertexBuffers = mutableListOf() + + init { + id = glCreateVertexArrays() + glBindVertexArray(id) + + indexBuffer?.bind() + + // unbind after setup + glBindVertexArray(0) + } + + fun addVertexBuffer(vertexBuffer: GLVertexBuffer) { + if (vertexBuffer in vertexBuffers) return + + bind() + vertexBuffer.bind() + + check(vertexBuffer.layout.bufferElements.isNotEmpty()) { "Layout contains no elements" } + + vertexBuffer.layout.bufferElements.forEachIndexed { index, element -> + glEnableVertexAttribArray(index) + glVertexAttribPointer( + index, + element.dataType.size, + element.dataType.glType, + false, + vertexBuffer.layout.stride, + element.offset.toLong() + ) + } + + vertexBuffers += vertexBuffer + } + + fun removeVertexBuffer(vertexBuffer: GLVertexBuffer) { + bind() + vertexBuffer.bind() + vertexBuffer.close() + + vertexBuffers -= vertexBuffer + } + + fun bind() { + glBindVertexArray(id) + } + + override fun render() { + bind() + + if (indexBuffer != null && indexBuffer.count > 0) { + glDrawElements(mode, indexBuffer.count, GL_UNSIGNED_INT, 0) + } else { + vertexBuffers.forEach { vertexBuffer -> + glDrawArrays(mode, 0, vertexBuffer.count) + } + } + } + + override fun close() { + glBindVertexArray(0) + + vertexBuffers.forEach(GLVertexBuffer::close) + indexBuffer?.close() + glDeleteVertexArrays(id) + } + +} \ No newline at end of file diff --git a/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/buffer/GLBufferElement.kt b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/buffer/GLBufferElement.kt new file mode 100644 index 0000000..8c14845 --- /dev/null +++ b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/buffer/GLBufferElement.kt @@ -0,0 +1,27 @@ +/* + * Foresst: GLBufferElement.kt + * Copyright (C) 2025 mtctx, kvxd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.graphics.gl.buffer + +import dev.mtctx.foresst.graphics.gl.GLDataType + +data class GLBufferElement( + val name: String, + val dataType: GLDataType, + var offset: Int = 0 +) \ No newline at end of file diff --git a/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/buffer/GLBufferLayout.kt b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/buffer/GLBufferLayout.kt new file mode 100644 index 0000000..a2f2d63 --- /dev/null +++ b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/buffer/GLBufferLayout.kt @@ -0,0 +1,49 @@ +/* + * Foresst: GLBufferLayout.kt + * Copyright (C) 2025 mtctx, kvxd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.graphics.gl.buffer + +import dev.mtctx.foresst.graphics.gl.GLDataType + +class GLBufferLayout(map: Map) { + + var stride: Int = 0 + var bufferElements = mutableListOf() + + init { + require(map.isNotEmpty()) { "Can't create buffer layout with empty map" } + + calculateOffsets(map) + + // stride represents the byte offset between consecutive elements within the buffer + stride = + bufferElements.lastOrNull()?.let { + it.offset + it.dataType.byteSize() + } ?: 0 + } + + private fun calculateOffsets(map: Map) { + var offset = 0 + map.forEach { (name, dataType) -> + val bufferElement = GLBufferElement(name, dataType, offset) + bufferElements += bufferElement + offset += dataType.byteSize() + } + } + +} \ No newline at end of file diff --git a/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/buffer/GLIndexBuffer.kt b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/buffer/GLIndexBuffer.kt new file mode 100644 index 0000000..ac9bf08 --- /dev/null +++ b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/buffer/GLIndexBuffer.kt @@ -0,0 +1,55 @@ +/* + * Foresst: GLIndexBuffer.kt + * Copyright (C) 2025 mtctx, kvxd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.graphics.gl.buffer + +import dev.mtctx.foresst.graphics.Renderable +import org.lwjgl.opengl.GL46.* + +class GLIndexBuffer(indices: IntArray) : Renderable { + + private var id: Int = 0 + var count: Int = 0 + + init { + count = indices.size * Int.SIZE_BYTES + + id = glCreateBuffers() + bind() + + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices, GL_STATIC_DRAW) + } + + fun bind() { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id) + } + + fun clear() { + glDeleteBuffers(id) + } + + override fun render() { + bind() + } + + override fun close() { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) + clear() + } + +} \ No newline at end of file diff --git a/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/buffer/GLVertexBuffer.kt b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/buffer/GLVertexBuffer.kt new file mode 100644 index 0000000..c4c2114 --- /dev/null +++ b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/buffer/GLVertexBuffer.kt @@ -0,0 +1,54 @@ +/* + * Foresst: GLVertexBuffer.kt + * Copyright (C) 2025 mtctx, kvxd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.graphics.gl.buffer + +import dev.mtctx.foresst.graphics.Renderable +import org.lwjgl.opengl.GL46.* + +class GLVertexBuffer(vertices: FloatArray, val layout: GLBufferLayout) : Renderable { + + private var id: Int = 0 + var count: Int = vertices.size + + init { + id = glCreateBuffers() + bind() + + glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW) + } + + fun bind() { + glBindBuffer(GL_ARRAY_BUFFER, id) + } + + fun update(vertices: FloatArray) { + bind() + glBufferSubData(GL_ARRAY_BUFFER, 0, vertices) + count = vertices.size + } + + override fun render() { + bind() + } + + override fun close() { + glDeleteBuffers(id) + } + +} \ No newline at end of file diff --git a/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/renderers/VoxelRenderer.kt b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/renderers/VoxelRenderer.kt new file mode 100644 index 0000000..964f360 --- /dev/null +++ b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/renderers/VoxelRenderer.kt @@ -0,0 +1,86 @@ +/* + * Foresst: VoxelRenderer.kt + * Copyright (C) 2025 mtctx, kvxd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.graphics.renderers + +import dev.mtctx.foresst.graphics.Renderer +import dev.mtctx.foresst.graphics.gl.GLShader +import dev.mtctx.foresst.graphics.gl.GLVertexArray +import dev.mtctx.foresst.graphics.gl.buffer.GLBufferLayout +import dev.mtctx.foresst.graphics.gl.buffer.GLVertexBuffer +import dev.mtctx.foresst.graphics.gl.buffer.GLIndexBuffer +import dev.mtctx.foresst.graphics.gl.GLDataType +import glm_.glm +import glm_.mat4x4.Mat4 +import glm_.vec3.Vec3 + +class VoxelRenderer(private val shader: GLShader) : Renderer { + + private val vao: GLVertexArray + + private var model: Mat4 = Mat4(1.0f) + private var view: Mat4 = glm.lookAt( + Vec3(2f, 2f, 2f), + Vec3(0f, 0f, 0f), + Vec3(0f, 1f, 0f) + ) + private var projection: Mat4 = glm.perspective(glm.radians(45f), 800f / 600f, 0.1f, 100f) + + init { + // Cube vertices + val vertices = floatArrayOf( + -0.5f, -0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, + 0.5f, 0.5f, -0.5f, + -0.5f, 0.5f, -0.5f, + -0.5f, -0.5f, 0.5f, + 0.5f, -0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, + -0.5f, 0.5f, 0.5f + ) + + val indices = intArrayOf( + 0, 1, 2, 2, 3, 0, + 4, 5, 6, 6, 7, 4, + 0, 1, 5, 5, 4, 0, + 2, 3, 7, 7, 6, 2, + 0, 3, 7, 7, 4, 0, + 1, 2, 6, 6, 5, 1 + ) + + val layout = GLBufferLayout(mapOf("position" to GLDataType.Vec3)) + val vbo = GLVertexBuffer(vertices, layout) + val ibo = GLIndexBuffer(indices) + + vao = GLVertexArray(ibo) + vao.addVertexBuffer(vbo) + } + + override fun render() { + shader.use { + val mvp = projection * view * model + uniformMat4("mvp", mvp) + + vao.render() + } + } + + override fun close() { + vao.close() + } +} diff --git a/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/utils/TranslationUtils.kt b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/utils/TranslationUtils.kt new file mode 100644 index 0000000..82f3122 --- /dev/null +++ b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/utils/TranslationUtils.kt @@ -0,0 +1,32 @@ +/* + * Foresst: TranslationUtils.kt + * Copyright (C) 2025 mtctx, kvxd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package dev.mtctx.foresst.graphics.utils + +import glm_.func.toRadians +import glm_.mat4x4.Mat4 +import glm_.vec3.Vec3 + +fun calculateModelMatrix(pos: Vec3, rotation: Vec3): Mat4 = + Mat4().identity().translateAssign(pos) + .rotateXassign(toRadians(-rotation.x)) + .rotateYassign(toRadians(-rotation.y)) + .rotateZassign(toRadians(-rotation.z)) + +fun calculateModelMatrix(): Mat4 = + calculateModelMatrix(Vec3(0, 0, 0), Vec3(0, 0, 0)) \ No newline at end of file diff --git a/graphics/src/main/resources/frag.fs b/graphics/src/main/resources/frag.fs new file mode 100644 index 0000000..dad22a9 --- /dev/null +++ b/graphics/src/main/resources/frag.fs @@ -0,0 +1,7 @@ +#version 330 core + +out vec4 FragColor; + +void main() { + FragColor = vec4(1.0, 1.0, 1.0, 1.0); +} diff --git a/graphics/src/main/resources/vert.vs b/graphics/src/main/resources/vert.vs new file mode 100644 index 0000000..0790cc3 --- /dev/null +++ b/graphics/src/main/resources/vert.vs @@ -0,0 +1,9 @@ +#version 330 core + +layout(location = 0) in vec3 aPos; + +uniform mat4 mvp; + +void main() { + gl_Position = mvp * vec4(aPos, 1.0); +} diff --git a/graphics/src/test/kotlin/main.kt b/graphics/src/test/kotlin/main.kt new file mode 100644 index 0000000..8371737 --- /dev/null +++ b/graphics/src/test/kotlin/main.kt @@ -0,0 +1,24 @@ +import dev.mtctx.foresst.graphics.Graphics + +/* + * Foresst: main.kt + * Copyright (C) 2025 mtctx, kvxd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +fun main(args: Array) { + Graphics + .run() +} \ No newline at end of file From 342e7fdcf197b75c0c92c5e04123bd305d43c355 Mon Sep 17 00:00:00 2001 From: kvxd Date: Wed, 24 Sep 2025 20:51:53 +0200 Subject: [PATCH 3/3] refactor(core): Resource content types Use extension functions like asText rather than .typed() for retrieving content from a resource --- .../dev/mtctx/foresst/resource/Resource.kt | 8 ++--- .../{ContentType.kt => conversion.kt} | 23 +++++++++---- .../mtctx/foresst/resource/type/ByteArray.kt | 33 ------------------- .../mtctx/foresst/resource/type/RawFile.kt | 31 ----------------- .../dev/mtctx/foresst/resource/type/Text.kt | 32 ------------------ .../dev/mtctx/foresst/graphics/gl/GLShader.kt | 4 +-- 6 files changed, 22 insertions(+), 109 deletions(-) rename core/src/main/kotlin/dev/mtctx/foresst/resource/{ContentType.kt => conversion.kt} (57%) delete mode 100644 core/src/main/kotlin/dev/mtctx/foresst/resource/type/ByteArray.kt delete mode 100644 core/src/main/kotlin/dev/mtctx/foresst/resource/type/RawFile.kt delete mode 100644 core/src/main/kotlin/dev/mtctx/foresst/resource/type/Text.kt diff --git a/core/src/main/kotlin/dev/mtctx/foresst/resource/Resource.kt b/core/src/main/kotlin/dev/mtctx/foresst/resource/Resource.kt index efa6df6..9410930 100644 --- a/core/src/main/kotlin/dev/mtctx/foresst/resource/Resource.kt +++ b/core/src/main/kotlin/dev/mtctx/foresst/resource/Resource.kt @@ -20,8 +20,10 @@ package dev.mtctx.foresst.resource import java.io.File import java.io.InputStream +import java.nio.charset.Charset import java.nio.file.Files import java.nio.file.Path +import java.nio.file.StandardCopyOption class Resource(resourcePath: String) { @@ -32,14 +34,10 @@ class Resource(resourcePath: String) { private val tempFile: Path by lazy { val tempFile = Files.createTempFile("foresst-", ".tmp") tempFile.toFile().deleteOnExit() - Files.copy(inputStream, tempFile, java.nio.file.StandardCopyOption.REPLACE_EXISTING) + Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING) tempFile } val file: File get() = tempFile.toFile() - - fun typed(type: ContentType): T { - return type.convert(Pair(inputStream, file)) - } } \ No newline at end of file diff --git a/core/src/main/kotlin/dev/mtctx/foresst/resource/ContentType.kt b/core/src/main/kotlin/dev/mtctx/foresst/resource/conversion.kt similarity index 57% rename from core/src/main/kotlin/dev/mtctx/foresst/resource/ContentType.kt rename to core/src/main/kotlin/dev/mtctx/foresst/resource/conversion.kt index 68300cf..4cb6791 100644 --- a/core/src/main/kotlin/dev/mtctx/foresst/resource/ContentType.kt +++ b/core/src/main/kotlin/dev/mtctx/foresst/resource/conversion.kt @@ -1,6 +1,6 @@ /* - * Foresst: Resource.kt - * Copyright (C) 2025 mtctx + * Foresst: conversion.kt + * Copyright (C) 2025 mtctx, kvxd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,9 +18,20 @@ package dev.mtctx.foresst.resource -import java.io.File import java.io.InputStream +import java.nio.charset.Charset -interface ContentType { - fun convert(isp: Pair): T -} \ No newline at end of file +fun Resource.asText(charset: String = "UTF-8"): String = + file.readText(Charset.forName(charset)) + +fun Resource.asByteArray(): ByteArray = + file.readBytes() + +fun Resource.asInputStream(): InputStream = + file.inputStream() + +fun Resource.asReader(charset: String = "UTF-8") = + file.reader(Charset.forName(charset)) + +fun Resource.asLines(charset: String = "UTF-8"): Sequence = + file.useLines(Charset.forName(charset)) { it.toList() }.asSequence() \ No newline at end of file diff --git a/core/src/main/kotlin/dev/mtctx/foresst/resource/type/ByteArray.kt b/core/src/main/kotlin/dev/mtctx/foresst/resource/type/ByteArray.kt deleted file mode 100644 index 759a977..0000000 --- a/core/src/main/kotlin/dev/mtctx/foresst/resource/type/ByteArray.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Foresst: BinaryArray.kt - * Copyright (C) 2025 mtctx - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package dev.mtctx.foresst.resource.type - -import dev.mtctx.foresst.resource.ContentType -import dev.mtctx.foresst.resource.InputStreamFilePairs -import java.io.File -import java.io.InputStream -import kotlin.ByteArray - -object ByteArray : ContentType { - - override fun convert(isp: Pair): ByteArray = - with(InputStreamFilePairs) { - return isp.inputStream.readBytes() - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/dev/mtctx/foresst/resource/type/RawFile.kt b/core/src/main/kotlin/dev/mtctx/foresst/resource/type/RawFile.kt deleted file mode 100644 index 8cb10c1..0000000 --- a/core/src/main/kotlin/dev/mtctx/foresst/resource/type/RawFile.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Foresst: RawFile.kt - * Copyright (C) 2025 mtctx - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package dev.mtctx.foresst.resource.type - -import dev.mtctx.foresst.resource.ContentType -import dev.mtctx.foresst.resource.InputStreamFilePairs.file -import java.io.File -import java.io.InputStream - -object RawFile : ContentType { - - override fun convert(isp: Pair): File { - return isp.file - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/dev/mtctx/foresst/resource/type/Text.kt b/core/src/main/kotlin/dev/mtctx/foresst/resource/type/Text.kt deleted file mode 100644 index 7d42cd2..0000000 --- a/core/src/main/kotlin/dev/mtctx/foresst/resource/type/Text.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Foresst: Text.kt - * Copyright (C) 2025 mtctx - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package dev.mtctx.foresst.resource.type - -import dev.mtctx.foresst.resource.ContentType -import dev.mtctx.foresst.resource.InputStreamFilePairs -import java.io.File -import java.io.InputStream - -object Text : ContentType { - - override fun convert(isp: Pair): String = - with(InputStreamFilePairs) { - return isp.file.readText() - } -} \ No newline at end of file diff --git a/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLShader.kt b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLShader.kt index b9c14c2..eea857c 100644 --- a/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLShader.kt +++ b/graphics/src/main/kotlin/dev/mtctx/foresst/graphics/gl/GLShader.kt @@ -20,7 +20,7 @@ package dev.mtctx.foresst.graphics.gl import dev.mtctx.foresst.graphics.Renderable import dev.mtctx.foresst.resource.Resource -import dev.mtctx.foresst.resource.type.Text +import dev.mtctx.foresst.resource.asText import glm_.mat2x2.Mat2 import glm_.mat3x3.Mat3 import glm_.mat4x4.Mat4 @@ -86,7 +86,7 @@ class GLShader( val shaderId = glCreateShader(module.shaderType.id) if (shaderId == 0) throw RuntimeException("glCreateShader returned 0 for type=${module.shaderType}") - glShaderSource(shaderId, module.res.typed(Text)) + glShaderSource(shaderId, module.res.asText()) glCompileShader(shaderId) val status = glGetShaderi(shaderId, GL_COMPILE_STATUS)