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