Fix reflection warnings, add aot jar building

This commit is contained in:
Joseph Ferano 2026-03-16 09:14:23 +07:00
parent 7dc8ebf8b2
commit e9a19baa84
4 changed files with 61 additions and 45 deletions

2
.gitignore vendored
View File

@ -2,3 +2,5 @@
/.nrepl-port
/.clj-kondo/
/.lsp/
/target/
*.jsa

14
build.clj Normal file
View File

@ -0,0 +1,14 @@
(ns build
(:require [clojure.tools.build.api :as b]))
(def basis (delay (b/create-basis {:project "deps.edn"})))
(defn uberjar [_]
(b/delete {:path "target"})
(b/compile-clj {:basis @basis
:src-dirs ["src"]
:class-dir "target/classes"})
(b/uber {:class-dir "target/classes"
:uber-file "target/nol.jar"
:basis @basis
:main 'nol.core}))

View File

@ -11,4 +11,7 @@
org.lwjgl/lwjgl-assimp$natives-linux {:mvn/version "3.3.3"}
org.joml/joml {:mvn/version "1.10.7"}}
:paths ["src"]
:aliases {:dev {:jvm-opts ["-Djdk.attach.allowAttachSelf=true"]}}}
:aliases {:dev {:jvm-opts ["-Djdk.attach.allowAttachSelf=true"]}
:build {:extra-deps {io.github.clojure/tools.build {:mvn/version "0.10.6"}}
:jvm-opts ["-Dclojure.compiler.direct-linking=true"]
:ns-default build}}}

View File

@ -1,24 +1,27 @@
(ns nol.core
(:gen-class)
(:require
[clojure.math])
(:import
[java.nio FloatBuffer IntBuffer]
[org.lwjgl.assimp AIColor4D AIMaterial AIMatrix4x4 AIMesh AINode AIScene AIString AITexture Assimp]
[java.nio ByteBuffer FloatBuffer IntBuffer]
[java.util.concurrent LinkedBlockingQueue]
[org.lwjgl PointerBuffer]
[org.lwjgl.assimp AIColor4D AIFace AIMaterial AIMatrix4x4 AIMesh AINode AIScene AIString AITexture AIVector3D Assimp]
[org.lwjgl.glfw GLFW GLFWKeyCallbackI]
[org.lwjgl.opengl GL GL11 GL20 GL30 GL45]
[org.lwjgl.stb STBImage]
[org.joml Matrix4f]
[org.lwjgl.system MemoryStack MemoryUtil]))
(def render-queue (java.util.concurrent.LinkedBlockingQueue.))
(def ^LinkedBlockingQueue render-queue (LinkedBlockingQueue.))
(def state (atom {:last-time (GLFW/glfwGetTime) :window nil}))
(def state (atom {:last-time 0.0 :window nil}))
(def gl-thread (atom nil))
(defmacro with-gl [& body]
`(let [result# (promise)]
(when-not (and @gl-thread (.isAlive @gl-thread))
(when-not (and @gl-thread (.isAlive ^Thread @gl-thread))
(throw (RuntimeException. "GL thread is not running")))
(.put render-queue #(deliver result# (try (do ~@body)
(catch Exception e# e#))))
@ -44,12 +47,6 @@
(throw (RuntimeException. (str "Program link error: " (GL20/glGetProgramInfoLog program)))))
program))
#_(defn ai-matrix->matrix4f [^AIMatrix4x4 m]
(Matrix4f. (.a1 m) (.a2 m) (.a3 m) (.a4 m)
(.b1 m) (.b2 m) (.b3 m) (.b4 m)
(.c1 m) (.c2 m) (.c3 m) (.c4 m)
(.d1 m) (.d2 m) (.d3 m) (.d4 m)))
(defn ai-matrix->matrix4f [^AIMatrix4x4 m]
(Matrix4f. (.a1 m) (.b1 m) (.c1 m) (.d1 m)
(.a2 m) (.b2 m) (.c2 m) (.d2 m)
@ -77,10 +74,10 @@
(def uploaded-scene (atom nil))
(def shaders (atom nil))
(defn render-scene [stack scene node mtx]
(defn render-scene [^MemoryStack stack scene node ^Matrix4f mtx]
(let [buf (.mallocFloat stack 16)
model-mtx (Matrix4f.)]
(.mul mtx (:transform node) model-mtx)
(.mul mtx ^Matrix4f (:transform node) model-mtx)
(.get model-mtx buf)
(when-let [mesh-indices (seq (:meshes node))]
(let [{:keys [gl-meshes gl-textures]} scene
@ -91,7 +88,7 @@
[r g b a] (:color mesh)
tex-idx (:texture-idx mesh)]]
(GL20/glUniform4f (:color uniforms) r g b a)
(GL20/glUniformMatrix4fv (:mm uniforms) false buf)
(GL20/glUniformMatrix4fv ^int (:mm uniforms) false buf)
(GL30/glBindVertexArray (:vao gl-mesh))
(when tex-idx
(let [tex-id (:gl-id (nth gl-textures tex-idx))]
@ -103,10 +100,10 @@
(doseq [child children]
(render-scene stack scene child model-mtx)))))
(defn- update-loop [window stack data]
(defn- update-loop [window ^MemoryStack stack data]
(let [w-buf (.mallocInt stack 1)
h-buf (.mallocInt stack 1)
_ (GLFW/glfwGetFramebufferSize window w-buf h-buf)
_ (GLFW/glfwGetFramebufferSize ^long window w-buf h-buf)
w (.get w-buf 0)
h (.get h-buf 0)
t (GLFW/glfwGetTime)]
@ -138,8 +135,8 @@
(float 100.0)))]
(.get vm vbuf)
(.get pm pbuf)
(GL20/glUniformMatrix4fv (:mv uniforms) false vbuf)
(GL20/glUniformMatrix4fv (:mp uniforms) false pbuf)
(GL20/glUniformMatrix4fv ^int (:mv uniforms) false vbuf)
(GL20/glUniformMatrix4fv ^int (:mp uniforms) false pbuf)
(render-scene stack scene (:hiearchy scene) (Matrix4f.)))))
(catch Exception e
(println "Update Loop GL thread error:" e)))
@ -152,11 +149,11 @@
(defn stop! []
(with-gl
(when @uploaded-scene
(doseq [{:keys [vbo vao ebo]} (:gl-meshes @uploaded-scene)]
(doseq [{:keys [^int vbo ^int vao ^int ebo]} (:gl-meshes @uploaded-scene)]
(GL45/glDeleteBuffers vbo)
(GL45/glDeleteBuffers ebo)
(GL30/glDeleteVertexArrays vao))
(doseq [{:keys [gl-id]} (:gl-textures @uploaded-scene)]
(doseq [{:keys [^int gl-id]} (:gl-textures @uploaded-scene)]
(GL11/glDeleteTextures gl-id)))
(when @shaders
(GL20/glDeleteProgram (:program @shaders)))
@ -213,7 +210,7 @@
(GLFW/glfwTerminate)))
(defn start! []
(when (and @gl-thread (.isAlive @gl-thread))
(when (and @gl-thread (.isAlive ^Thread @gl-thread))
(throw (RuntimeException. "Already running")))
(reset! gl-thread
(doto (Thread. (fn []
@ -225,13 +222,13 @@
(.setDaemon true)
(.start))))
(defn load-model [path]
(defn load-model [^String path]
(let [flags (bit-or Assimp/aiProcess_Triangulate
Assimp/aiProcess_FlipUVs)]
(Assimp/aiImportFile path flags)))
(defn extract-mesh [^AIScene scene idx]
(let [meshes (.mMeshes scene)]
(defn extract-mesh [^AIScene scene ^long idx]
(let [meshes ^PointerBuffer (.mMeshes scene)]
(let [mesh (AIMesh/create (long (.get meshes idx)))
mat-idx (.mMaterialIndex mesh)
mat-ptr ^long (.get (.mMaterials scene) mat-idx)
@ -251,16 +248,16 @@
idx-arr (int-array (* 3 nf))
uvs (.mTextureCoords mesh 0)]
(dotimes [i n]
(let [vert (.get verts i)
(let [vert ^AIVector3D (.get verts i)
uv (when uvs (.get uvs i))
[^float u ^float v] (if uvs [(.x uv) (.y uv)] [0.0 0.0])]
[^float u ^float v] (if uvs [(.x ^AIVector3D uv) (.y ^AIVector3D uv)] [0.0 0.0])]
(aset vert-arr (+ (* i 5) 0) (.x vert))
(aset vert-arr (+ (* i 5) 1) (.y vert))
(aset vert-arr (+ (* i 5) 2) (.z vert))
(aset vert-arr (+ (* i 5) 3) u)
(aset vert-arr (+ (* i 5) 4) v)))
(dotimes [i nf]
(let [face (.get faces i)
(let [face ^AIFace (.get faces i)
idxs (.mIndices face)]
(aset idx-arr (+ (* i 3) 0) (.get idxs 0))
(aset idx-arr (+ (* i 3) 1) (.get idxs 1))
@ -273,20 +270,20 @@
(defn traverse [^AINode node]
{:node node
:meshes (let [buf (.mMeshes node)]
(mapv #(.get buf %) (range (.mNumMeshes node))))
(mapv #(.get buf ^int %) (range (.mNumMeshes node))))
:transform (node-matrix4f node)
:children (mapv #(traverse (AINode/create ^long (.get (.mChildren node) %)))
:children (mapv #(traverse (AINode/create ^long (.get (.mChildren node) ^int %)))
(range (.mNumChildren node)))})
(defn load-scene [path]
(let [scene (load-model path)
(let [scene ^AIScene (load-model path)
meshes (doall
(for [i (range (.mNumMeshes scene))]
(extract-mesh scene i)))
textures (let [texs (.mTextures scene)]
(doall
(for [i (range (.mNumTextures scene))]
(let [ai-tex (AITexture/create (.get texs i))
(let [ai-tex (AITexture/create (.get texs ^int i))
buf (.pcDataCompressed ai-tex)
w (int-array 1)
h (int-array 1)
@ -300,11 +297,11 @@
(defn upload-scene! [scene]
(let [gl-meshes
(mapv
#(let [vbo (GL45/glCreateBuffers)
ebo (GL45/glCreateBuffers)
vao (GL45/glCreateVertexArrays)]
(GL45/glNamedBufferStorage vbo (:verts %) GL45/GL_DYNAMIC_STORAGE_BIT)
(GL45/glNamedBufferStorage ebo (:indices %) GL45/GL_DYNAMIC_STORAGE_BIT)
#(let [vbo ^int (GL45/glCreateBuffers)
ebo ^int (GL45/glCreateBuffers)
vao ^int (GL45/glCreateVertexArrays)]
(GL45/glNamedBufferStorage vbo ^floats (:verts %) GL45/GL_DYNAMIC_STORAGE_BIT)
(GL45/glNamedBufferStorage ebo ^ints (:indices %) GL45/GL_DYNAMIC_STORAGE_BIT)
(GL45/glVertexArrayElementBuffer vao ebo)
(GL45/glVertexArrayVertexBuffer vao 0 vbo 0 (* 5 Float/BYTES))
@ -318,7 +315,7 @@
(GL45/glEnableVertexArrayAttrib vao 1)
{:vbo vbo :vao vao :ebo ebo
:mesh %
:indices-count (alength (:indices %))})
:indices-count (alength ^ints (:indices %))})
(:meshes scene))
gl-textures
(mapv
@ -326,10 +323,10 @@
h (:h %)
tex-id (GL45/glCreateTextures GL11/GL_TEXTURE_2D)]
(GL45/glTextureStorage2D tex-id 1 GL11/GL_RGBA8 w h)
(GL45/glTextureSubImage2D tex-id 0 0 0 w h GL11/GL_RGBA GL11/GL_UNSIGNED_BYTE (:data %))
(GL45/glTextureSubImage2D tex-id 0 0 0 ^int w ^int h GL11/GL_RGBA GL11/GL_UNSIGNED_BYTE ^ByteBuffer (:data %))
(GL45/glTextureParameteri tex-id GL11/GL_TEXTURE_MIN_FILTER GL11/GL_LINEAR)
(GL45/glTextureParameteri tex-id GL11/GL_TEXTURE_MAG_FILTER GL11/GL_LINEAR)
(STBImage/stbi_image_free (:data %))
(STBImage/stbi_image_free ^ByteBuffer (:data %))
(assoc % :gl-id tex-id))
(:textures scene))]
(assoc scene :gl-textures gl-textures :gl-meshes gl-meshes)))
@ -339,11 +336,11 @@
frag (compile-shader GL20/GL_FRAGMENT_SHADER (slurp frag-path))
program (link-program vert frag)]
{:program program
:uniforms {:color (GL20/glGetUniformLocation program "uColor")
:tex (GL20/glGetUniformLocation program "texture_id")
:mm (GL20/glGetUniformLocation program "uModel")
:mv (GL20/glGetUniformLocation program "uView")
:mp (GL20/glGetUniformLocation program "uProjection")}}))
:uniforms {:color (GL20/glGetUniformLocation ^int program "uColor")
:tex (GL20/glGetUniformLocation ^int program "texture_id")
:mm (GL20/glGetUniformLocation ^int program "uModel")
:mv (GL20/glGetUniformLocation ^int program "uView")
:mp (GL20/glGetUniformLocation ^int program "uProjection")}}))
(reset! loaded-scene (load-scene "assets/model.glb"))