WASD + Free Camera look, fix double free, callbacks with exception handling
This commit is contained in:
parent
e9a19baa84
commit
734100d52d
171
src/nol/core.clj
171
src/nol/core.clj
@ -10,12 +10,16 @@
|
|||||||
[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 Vector3f]
|
||||||
[org.lwjgl.system MemoryStack MemoryUtil]))
|
[org.lwjgl.system MemoryStack MemoryUtil]))
|
||||||
|
|
||||||
(def ^LinkedBlockingQueue render-queue (LinkedBlockingQueue.))
|
(def ^LinkedBlockingQueue render-queue (LinkedBlockingQueue.))
|
||||||
|
|
||||||
(def state (atom {:last-time 0.0 :window nil}))
|
(def state (atom {:last-time 0.0
|
||||||
|
:camera-pos (Vector3f. 0.0 0.0 10.0)
|
||||||
|
:camera-yaw 0.0
|
||||||
|
:camera-pitch 0.0
|
||||||
|
:camera-target (Vector3f.)}))
|
||||||
|
|
||||||
(def gl-thread (atom nil))
|
(def gl-thread (atom nil))
|
||||||
|
|
||||||
@ -64,16 +68,91 @@
|
|||||||
(.mTransformation)
|
(.mTransformation)
|
||||||
(ai-matrix->matrix4f)))
|
(ai-matrix->matrix4f)))
|
||||||
|
|
||||||
(defn node-matrix [^AINode c]
|
|
||||||
(-> c
|
|
||||||
(.mTransformation)
|
|
||||||
(ai-matrix->matrix4f)
|
|
||||||
(matrix4f->vectors)))
|
|
||||||
|
|
||||||
(def loaded-scene (atom nil))
|
(def loaded-scene (atom nil))
|
||||||
(def uploaded-scene (atom nil))
|
(def uploaded-scene (atom nil))
|
||||||
(def shaders (atom nil))
|
(def shaders (atom nil))
|
||||||
|
|
||||||
|
(def cam-speed 0.03)
|
||||||
|
|
||||||
|
(defn camera-forward [^double yaw ^double pitch]
|
||||||
|
(Vector3f. (* (Math/cos pitch) (Math/sin yaw))
|
||||||
|
(Math/sin pitch)
|
||||||
|
(- (* (Math/cos pitch) (Math/cos yaw)))))
|
||||||
|
|
||||||
|
(defn camera-right [^double yaw]
|
||||||
|
(Vector3f. (Math/cos yaw) 0.0 (Math/sin yaw)))
|
||||||
|
|
||||||
|
(defn camera-up [^Vector3f forward ^Vector3f right]
|
||||||
|
(-> (Vector3f. forward) (.cross right)))
|
||||||
|
|
||||||
|
(defn- key-down? [window key]
|
||||||
|
(= (GLFW/glfwGetKey window key) GLFW/GLFW_PRESS))
|
||||||
|
|
||||||
|
(def ^Vector3f move-dir (Vector3f.))
|
||||||
|
|
||||||
|
(defn- handle-input! [window]
|
||||||
|
(let [{:keys [camera-yaw camera-pitch ^Vector3f camera-pos]} @state]
|
||||||
|
(when (key-down? window GLFW/GLFW_KEY_W)
|
||||||
|
(.add move-dir 0.0 0.0 1.0))
|
||||||
|
(when (key-down? window GLFW/GLFW_KEY_S)
|
||||||
|
(.add move-dir 0.0 0.0 -1.0))
|
||||||
|
(when (key-down? window GLFW/GLFW_KEY_A)
|
||||||
|
(.add move-dir -1.0 0.0 0.0))
|
||||||
|
(when (key-down? window GLFW/GLFW_KEY_D)
|
||||||
|
(.add move-dir 1.0 0.0 0.0))
|
||||||
|
(when (key-down? window GLFW/GLFW_KEY_Q)
|
||||||
|
(.add move-dir 0.0 1.0 0.0))
|
||||||
|
(when (key-down? window GLFW/GLFW_KEY_E)
|
||||||
|
(.add move-dir 0.0 -1.0 0.0))
|
||||||
|
(when (> (.length move-dir) 0.0)
|
||||||
|
(.normalize move-dir)
|
||||||
|
(let [forward ^Vector3f (camera-forward camera-yaw camera-pitch)
|
||||||
|
right ^Vector3f (camera-right camera-yaw)
|
||||||
|
up ^Vector3f (camera-up forward right)
|
||||||
|
velocity ^Vector3f (-> (Vector3f. right)
|
||||||
|
(.mul (.x move-dir))
|
||||||
|
(.fma (.z move-dir) forward)
|
||||||
|
(.fma (.y move-dir) up)
|
||||||
|
(.mul ^double cam-speed))]
|
||||||
|
(.add camera-pos velocity)))
|
||||||
|
(.set move-dir 0.0 0.0 0.0)))
|
||||||
|
|
||||||
|
(defn- handle-mouse-input! [window ^double xpos ^double ypos]
|
||||||
|
(when (:fps-mode @state)
|
||||||
|
(let [{:keys [^double camera-yaw ^double camera-pitch]} @state
|
||||||
|
last-cursor-x (double (or (:last-cursor-x @state) xpos))
|
||||||
|
last-cursor-y (double (or (:last-cursor-y @state) ypos))
|
||||||
|
sensitivity 0.001
|
||||||
|
dx (- last-cursor-x xpos)
|
||||||
|
dy (- last-cursor-y ypos)]
|
||||||
|
(swap! state assoc
|
||||||
|
:last-cursor-x xpos
|
||||||
|
:last-cursor-y ypos
|
||||||
|
:camera-yaw (- camera-yaw (* dx sensitivity))
|
||||||
|
:camera-pitch (+ camera-pitch (* dy sensitivity))))))
|
||||||
|
|
||||||
|
(defn- handle-mouse-buttons! [^long win button action mods]
|
||||||
|
(cond
|
||||||
|
(and (= button GLFW/GLFW_MOUSE_BUTTON_RIGHT) (= action GLFW/GLFW_PRESS))
|
||||||
|
(let []
|
||||||
|
(swap! state assoc :fps-mode true)
|
||||||
|
(GLFW/glfwSetInputMode win GLFW/GLFW_CURSOR GLFW/GLFW_CURSOR_DISABLED))
|
||||||
|
|
||||||
|
(and (= button GLFW/GLFW_MOUSE_BUTTON_RIGHT) (= action GLFW/GLFW_RELEASE))
|
||||||
|
(let []
|
||||||
|
(swap! state assoc :fps-mode false :last-cursor-x nil :last-cursor-y nil)
|
||||||
|
(GLFW/glfwSetInputMode win GLFW/GLFW_CURSOR GLFW/GLFW_CURSOR_NORMAL))
|
||||||
|
|
||||||
|
(and (= button GLFW/GLFW_MOUSE_BUTTON_LEFT) (= action GLFW/GLFW_PRESS))
|
||||||
|
(let [cursor (GLFW/glfwCreateStandardCursor GLFW/GLFW_RESIZE_ALL_CURSOR)]
|
||||||
|
(swap! state assoc :orbit-mode true)
|
||||||
|
(GLFW/glfwSetCursor win cursor))
|
||||||
|
|
||||||
|
(and (= button GLFW/GLFW_MOUSE_BUTTON_LEFT) (= action GLFW/GLFW_RELEASE))
|
||||||
|
(let []
|
||||||
|
(swap! state assoc :orbit-mode false)
|
||||||
|
(GLFW/glfwSetCursor win MemoryUtil/NULL))))
|
||||||
|
|
||||||
(defn render-scene [^MemoryStack stack scene node ^Matrix4f 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.)]
|
||||||
@ -114,19 +193,26 @@
|
|||||||
;; (swap! state assoc :last-time t)
|
;; (swap! state assoc :last-time t)
|
||||||
(try
|
(try
|
||||||
(when (and @uploaded-scene @shaders)
|
(when (and @uploaded-scene @shaders)
|
||||||
|
(handle-input! window)
|
||||||
(let [scene @uploaded-scene
|
(let [scene @uploaded-scene
|
||||||
{:keys [program uniforms]} @shaders]
|
{:keys [program uniforms]} @shaders]
|
||||||
(GL20/glUseProgram program)
|
(GL20/glUseProgram program)
|
||||||
(let [vbuf (.mallocFloat stack 16)
|
(let [vbuf (.mallocFloat stack 16)
|
||||||
pbuf (.mallocFloat stack 16)
|
pbuf (.mallocFloat stack 16)
|
||||||
radius 10.0
|
radius 10.0
|
||||||
cam-x (* radius (Math/sin t))
|
;; cam-x (* radius (Math/sin t))
|
||||||
cam-z (* radius (Math/cos t))
|
;; cam-z (* radius (Math/cos t))
|
||||||
|
{:keys [^double camera-yaw ^double camera-pitch ^Vector3f camera-pos camera-target]} @state
|
||||||
|
fwd (camera-forward camera-yaw camera-pitch)
|
||||||
|
target ^Vector3f (:camera-target @state)
|
||||||
|
_ (doto ^Vector3f target
|
||||||
|
(.set camera-pos)
|
||||||
|
(.add fwd))
|
||||||
vm (-> (Matrix4f.)
|
vm (-> (Matrix4f.)
|
||||||
(.identity)
|
(.identity)
|
||||||
(.lookAt (float cam-x) (float 0.0) (float cam-z)
|
(.lookAt (.x camera-pos) (.y camera-pos) (.z camera-pos) ;; eye (camera position)
|
||||||
(float 0.0) (float 0.0) (float 0.0)
|
(.x target) (.y target) (.z target) ;; center (where to look)
|
||||||
(float 0.0) (float 1.0) (float 0.0)))
|
0.0 1.0 0.0)) ;; up
|
||||||
pm (-> (Matrix4f.)
|
pm (-> (Matrix4f.)
|
||||||
(.identity)
|
(.identity)
|
||||||
(.perspective (float (Math/toRadians 45))
|
(.perspective (float (Math/toRadians 45))
|
||||||
@ -147,20 +233,16 @@
|
|||||||
(GLFW/glfwSwapBuffers window)))
|
(GLFW/glfwSwapBuffers window)))
|
||||||
|
|
||||||
(defn stop! []
|
(defn stop! []
|
||||||
(with-gl
|
(when @uploaded-scene
|
||||||
(when @uploaded-scene
|
(doseq [{:keys [^int vbo ^int vao ^int 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 [^int 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
|
|
||||||
(GL20/glDeleteProgram (:program @shaders)))
|
|
||||||
(GLFW/glfwSetWindowShouldClose
|
|
||||||
(:window @state) true))
|
|
||||||
(reset! uploaded-scene nil)
|
(reset! uploaded-scene nil)
|
||||||
(reset! shaders nil))
|
(reset! shaders nil)
|
||||||
|
(swap! state assoc :should-close true))
|
||||||
|
|
||||||
(defn -main []
|
(defn -main []
|
||||||
(when-not (GLFW/glfwInit)
|
(when-not (GLFW/glfwInit)
|
||||||
@ -170,7 +252,7 @@
|
|||||||
(GLFW/glfwWindowHint GLFW/GLFW_CONTEXT_VERSION_MINOR 5)
|
(GLFW/glfwWindowHint GLFW/GLFW_CONTEXT_VERSION_MINOR 5)
|
||||||
(GLFW/glfwWindowHint GLFW/GLFW_OPENGL_PROFILE GLFW/GLFW_OPENGL_CORE_PROFILE)
|
(GLFW/glfwWindowHint GLFW/GLFW_OPENGL_PROFILE GLFW/GLFW_OPENGL_CORE_PROFILE)
|
||||||
|
|
||||||
(let [window (GLFW/glfwCreateWindow 960 300 #_#_1900 1100 "NOL" MemoryUtil/NULL MemoryUtil/NULL)]
|
(let [window (GLFW/glfwCreateWindow 960 400 #_#_1900 1100 "NOL" MemoryUtil/NULL MemoryUtil/NULL)]
|
||||||
(when (= window MemoryUtil/NULL)
|
(when (= window MemoryUtil/NULL)
|
||||||
(GLFW/glfwTerminate)
|
(GLFW/glfwTerminate)
|
||||||
(throw (RuntimeException. "Failed to create window")))
|
(throw (RuntimeException. "Failed to create window")))
|
||||||
@ -188,8 +270,28 @@
|
|||||||
(GLFW/glfwSetKeyCallback window
|
(GLFW/glfwSetKeyCallback window
|
||||||
(reify GLFWKeyCallbackI
|
(reify GLFWKeyCallbackI
|
||||||
(invoke [_ win key scancode action mods]
|
(invoke [_ win key scancode action mods]
|
||||||
|
#_(try
|
||||||
|
(handle-input! win key scancode action mods)
|
||||||
|
(catch Exception e
|
||||||
|
(println "GLFW Input error:" e)))
|
||||||
(when (and (= key GLFW/GLFW_KEY_ESCAPE) (= action GLFW/GLFW_PRESS))
|
(when (and (= key GLFW/GLFW_KEY_ESCAPE) (= action GLFW/GLFW_PRESS))
|
||||||
(swap! state assoc :should-close true)))))
|
(swap! state assoc :should-close true)))))
|
||||||
|
(when (GLFW/glfwRawMouseMotionSupported)
|
||||||
|
(GLFW/glfwSetInputMode window GLFW/GLFW_RAW_MOUSE_MOTION GLFW/GLFW_TRUE))
|
||||||
|
(GLFW/glfwSetCursorPosCallback window
|
||||||
|
(reify org.lwjgl.glfw.GLFWCursorPosCallbackI
|
||||||
|
(invoke [_ win xpos ypos]
|
||||||
|
(try
|
||||||
|
(handle-mouse-input! win xpos ypos)
|
||||||
|
(catch Exception e
|
||||||
|
(println "Cursor Pos Callback Exception:" e))))))
|
||||||
|
(GLFW/glfwSetMouseButtonCallback window
|
||||||
|
(reify org.lwjgl.glfw.GLFWMouseButtonCallbackI
|
||||||
|
(invoke [_ win button action mods]
|
||||||
|
(try
|
||||||
|
(handle-mouse-buttons! win button action mods)
|
||||||
|
(catch Exception e
|
||||||
|
(println "Mouse Button Callback Exception:" e))))))
|
||||||
|
|
||||||
(loop []
|
(loop []
|
||||||
(loop []
|
(loop []
|
||||||
@ -206,6 +308,7 @@
|
|||||||
(MemoryStack/stackPop))))
|
(MemoryStack/stackPop))))
|
||||||
(recur)))
|
(recur)))
|
||||||
|
|
||||||
|
(stop!)
|
||||||
(GLFW/glfwDestroyWindow window)
|
(GLFW/glfwDestroyWindow window)
|
||||||
(GLFW/glfwTerminate)))
|
(GLFW/glfwTerminate)))
|
||||||
|
|
||||||
@ -326,7 +429,6 @@
|
|||||||
(GL45/glTextureSubImage2D tex-id 0 0 0 ^int w ^int h GL11/GL_RGBA GL11/GL_UNSIGNED_BYTE ^ByteBuffer (: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 ^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)))
|
||||||
@ -342,17 +444,20 @@
|
|||||||
:mv (GL20/glGetUniformLocation ^int program "uView")
|
:mv (GL20/glGetUniformLocation ^int program "uView")
|
||||||
:mp (GL20/glGetUniformLocation ^int program "uProjection")}}))
|
:mp (GL20/glGetUniformLocation ^int program "uProjection")}}))
|
||||||
|
|
||||||
(reset! loaded-scene (load-scene "assets/model.glb"))
|
|
||||||
|
|
||||||
(comment
|
(comment
|
||||||
(start!)
|
(start!)
|
||||||
(stop!)
|
(with-gl (stop!))
|
||||||
|
|
||||||
|
(reset! loaded-scene
|
||||||
|
(do
|
||||||
|
(when @loaded-scene
|
||||||
|
(doseq [tex (:textures @loaded-scene)]
|
||||||
|
(when-let [data (:data tex)]
|
||||||
|
(STBImage/stbi_image_free ^ByteBuffer data))))
|
||||||
|
(load-scene "assets/model.glb")))
|
||||||
(reset! uploaded-scene (with-gl (upload-scene! @loaded-scene)))
|
(reset! uploaded-scene (with-gl (upload-scene! @loaded-scene)))
|
||||||
(reset! shaders (with-gl (load-shaders! "shaders/base.vert" "shaders/base.frag")))
|
(reset! shaders (with-gl (load-shaders! "shaders/base.vert" "shaders/base.frag")))
|
||||||
|
|
||||||
(with-gl
|
|
||||||
(GL11/glClear (bit-or GL11/GL_COLOR_BUFFER_BIT GL11/GL_DEPTH_BUFFER_BIT)))
|
|
||||||
(with-gl
|
(with-gl
|
||||||
(GL11/glClearColor 0.392 0.584 0.929 1.0))
|
(GL11/glClearColor 0.392 0.584 0.929 1.0))
|
||||||
(with-gl
|
(with-gl
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user