Fully functioning orbit camera
This commit is contained in:
parent
734100d52d
commit
359755aad1
127
src/nol/core.clj
127
src/nol/core.clj
@ -10,18 +10,25 @@
|
|||||||
[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 Vector3f]
|
[org.joml Matrix4f Vector2f 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
|
(def state (atom {:last-time 0.0
|
||||||
|
:drag-start-pos nil
|
||||||
:camera-pos (Vector3f. 0.0 0.0 10.0)
|
:camera-pos (Vector3f. 0.0 0.0 10.0)
|
||||||
:camera-yaw 0.0
|
:camera-yaw 0.0
|
||||||
:camera-pitch 0.0
|
:camera-pitch 0.0
|
||||||
:camera-target (Vector3f.)}))
|
:orbit-yaw 0.0
|
||||||
|
:orbit-pitch 0.0
|
||||||
|
:last-orbit-x 0.0
|
||||||
|
:last-orbit-y 0.0
|
||||||
|
:focus-point (Vector3f.)
|
||||||
|
:camera-target (Vector3f.)
|
||||||
|
:projection-matrix}))
|
||||||
|
|
||||||
(def gl-thread (atom nil))
|
(defonce gl-thread (atom nil))
|
||||||
|
|
||||||
(defmacro with-gl [& body]
|
(defmacro with-gl [& body]
|
||||||
`(let [result# (promise)]
|
`(let [result# (promise)]
|
||||||
@ -68,11 +75,11 @@
|
|||||||
(.mTransformation)
|
(.mTransformation)
|
||||||
(ai-matrix->matrix4f)))
|
(ai-matrix->matrix4f)))
|
||||||
|
|
||||||
(def loaded-scene (atom nil))
|
(defonce loaded-scene (atom nil))
|
||||||
(def uploaded-scene (atom nil))
|
(defonce uploaded-scene (atom nil))
|
||||||
(def shaders (atom nil))
|
(defonce shaders (atom nil))
|
||||||
|
|
||||||
(def cam-speed 0.03)
|
(def cam-speed 0.04)
|
||||||
|
|
||||||
(defn camera-forward [^double yaw ^double pitch]
|
(defn camera-forward [^double yaw ^double pitch]
|
||||||
(Vector3f. (* (Math/cos pitch) (Math/sin yaw))
|
(Vector3f. (* (Math/cos pitch) (Math/sin yaw))
|
||||||
@ -89,8 +96,27 @@
|
|||||||
(= (GLFW/glfwGetKey window key) GLFW/GLFW_PRESS))
|
(= (GLFW/glfwGetKey window key) GLFW/GLFW_PRESS))
|
||||||
|
|
||||||
(def ^Vector3f move-dir (Vector3f.))
|
(def ^Vector3f move-dir (Vector3f.))
|
||||||
|
(def ^Vector3f focus-distance 5.0)
|
||||||
|
|
||||||
(defn- handle-input! [window]
|
(defn- handle-key-actions! [_win key _scancode action _mods]
|
||||||
|
(when (= action GLFW/GLFW_PRESS)
|
||||||
|
(when (= key GLFW/GLFW_KEY_ESCAPE)
|
||||||
|
(swap! state assoc :should-close true))
|
||||||
|
(when (= key GLFW/GLFW_KEY_R)
|
||||||
|
(swap! state assoc
|
||||||
|
:camera-pos (Vector3f. 0.0 0.0 10.0)
|
||||||
|
:camera-yaw 0.0
|
||||||
|
:camera-pitch 0.0
|
||||||
|
:focus-point (Vector3f. 0.0 0.0 0.0)
|
||||||
|
:camera-target (Vector3f.)))))
|
||||||
|
|
||||||
|
(defn- drag-detected? [^double x1 ^double y1 ^double x2 ^double y2]
|
||||||
|
(let [threshold 10.0
|
||||||
|
dx (- x2 x1)
|
||||||
|
dy (- y2 y1)]
|
||||||
|
(< threshold (+ (* dx dx) (* dy dy)))))
|
||||||
|
|
||||||
|
(defn- handle-keyboard-state! [window]
|
||||||
(let [{:keys [camera-yaw camera-pitch ^Vector3f camera-pos]} @state]
|
(let [{:keys [camera-yaw camera-pitch ^Vector3f camera-pos]} @state]
|
||||||
(when (key-down? window GLFW/GLFW_KEY_W)
|
(when (key-down? window GLFW/GLFW_KEY_W)
|
||||||
(.add move-dir 0.0 0.0 1.0))
|
(.add move-dir 0.0 0.0 1.0))
|
||||||
@ -117,7 +143,24 @@
|
|||||||
(.add camera-pos velocity)))
|
(.add camera-pos velocity)))
|
||||||
(.set move-dir 0.0 0.0 0.0)))
|
(.set move-dir 0.0 0.0 0.0)))
|
||||||
|
|
||||||
(defn- handle-mouse-input! [window ^double xpos ^double ypos]
|
(defn- handle-mouse-move! [_window ^double xpos ^double ypos]
|
||||||
|
(when (:orbit-mode @state)
|
||||||
|
(let [{:keys [^double orbit-yaw ^double orbit-pitch]} @state
|
||||||
|
last-orbit-x (double (or (:last-orbit-x @state) xpos))
|
||||||
|
last-orbit-y (double (or (:last-orbit-y @state) ypos))
|
||||||
|
sensitivity 0.005
|
||||||
|
dx (- last-orbit-x xpos)
|
||||||
|
dy (- last-orbit-y ypos)]
|
||||||
|
(swap! state assoc
|
||||||
|
:last-orbit-x xpos
|
||||||
|
:last-orbit-y ypos
|
||||||
|
:orbit-yaw (- orbit-yaw (* dx sensitivity))
|
||||||
|
:orbit-pitch (-> (- orbit-pitch (* dy sensitivity))
|
||||||
|
(max (- (/ Math/PI 2)))
|
||||||
|
(min (/ Math/PI 2))))))
|
||||||
|
#_(when-let [cursor-pos ^Vector2f (:drag-start-pos @state)]
|
||||||
|
(when (and (drag-detected? xpos ypos (.x cursor-pos) (.y cursor-pos)))
|
||||||
|
(swap! state assoc :orbit-mode true)))
|
||||||
(when (:fps-mode @state)
|
(when (:fps-mode @state)
|
||||||
(let [{:keys [^double camera-yaw ^double camera-pitch]} @state
|
(let [{:keys [^double camera-yaw ^double camera-pitch]} @state
|
||||||
last-cursor-x (double (or (:last-cursor-x @state) xpos))
|
last-cursor-x (double (or (:last-cursor-x @state) xpos))
|
||||||
@ -131,6 +174,12 @@
|
|||||||
:camera-yaw (- camera-yaw (* dx sensitivity))
|
:camera-yaw (- camera-yaw (* dx sensitivity))
|
||||||
:camera-pitch (+ camera-pitch (* dy sensitivity))))))
|
:camera-pitch (+ camera-pitch (* dy sensitivity))))))
|
||||||
|
|
||||||
|
(defn- get-current-cursor-pos! ^Vector2f [^MemoryStack stack ^long window]
|
||||||
|
(let [xbuf (.mallocDouble stack 1)
|
||||||
|
ybuf (.mallocDouble stack 1)]
|
||||||
|
(GLFW/glfwGetCursorPos window xbuf ybuf)
|
||||||
|
(Vector2f. (.get xbuf 0) (.get ybuf 0))))
|
||||||
|
|
||||||
(defn- handle-mouse-buttons! [^long win button action mods]
|
(defn- handle-mouse-buttons! [^long win button action mods]
|
||||||
(cond
|
(cond
|
||||||
(and (= button GLFW/GLFW_MOUSE_BUTTON_RIGHT) (= action GLFW/GLFW_PRESS))
|
(and (= button GLFW/GLFW_MOUSE_BUTTON_RIGHT) (= action GLFW/GLFW_PRESS))
|
||||||
@ -144,13 +193,14 @@
|
|||||||
(GLFW/glfwSetInputMode win GLFW/GLFW_CURSOR GLFW/GLFW_CURSOR_NORMAL))
|
(GLFW/glfwSetInputMode win GLFW/GLFW_CURSOR GLFW/GLFW_CURSOR_NORMAL))
|
||||||
|
|
||||||
(and (= button GLFW/GLFW_MOUSE_BUTTON_LEFT) (= action GLFW/GLFW_PRESS))
|
(and (= button GLFW/GLFW_MOUSE_BUTTON_LEFT) (= action GLFW/GLFW_PRESS))
|
||||||
(let [cursor (GLFW/glfwCreateStandardCursor GLFW/GLFW_RESIZE_ALL_CURSOR)]
|
(do
|
||||||
(swap! state assoc :orbit-mode true)
|
(when (mods :ctrl)
|
||||||
(GLFW/glfwSetCursor win cursor))
|
(swap! state assoc :orbit-mode true))
|
||||||
|
(swap! state assoc :drag-start-pos (get-current-cursor-pos! (MemoryStack/stackGet) win)))
|
||||||
|
|
||||||
(and (= button GLFW/GLFW_MOUSE_BUTTON_LEFT) (= action GLFW/GLFW_RELEASE))
|
(and (= button GLFW/GLFW_MOUSE_BUTTON_LEFT) (= action GLFW/GLFW_RELEASE))
|
||||||
(let []
|
(let []
|
||||||
(swap! state assoc :orbit-mode false)
|
(swap! state assoc :orbit-mode false :drag-start-pos nil :last-orbit-x nil :last-orbit-y nil)
|
||||||
(GLFW/glfwSetCursor win MemoryUtil/NULL))))
|
(GLFW/glfwSetCursor win MemoryUtil/NULL))))
|
||||||
|
|
||||||
(defn render-scene [^MemoryStack stack scene node ^Matrix4f mtx]
|
(defn render-scene [^MemoryStack stack scene node ^Matrix4f mtx]
|
||||||
@ -160,7 +210,7 @@
|
|||||||
(.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
|
||||||
{:keys [program uniforms]} @shaders]
|
{:keys [_program uniforms]} @shaders]
|
||||||
(doseq [idx mesh-indices
|
(doseq [idx mesh-indices
|
||||||
:let [gl-mesh (nth gl-meshes idx)
|
:let [gl-mesh (nth gl-meshes idx)
|
||||||
mesh (:mesh gl-mesh)
|
mesh (:mesh gl-mesh)
|
||||||
@ -190,37 +240,42 @@
|
|||||||
(GL11/glClear GL11/GL_COLOR_BUFFER_BIT)
|
(GL11/glClear GL11/GL_COLOR_BUFFER_BIT)
|
||||||
(GL11/glClear (bit-or GL11/GL_COLOR_BUFFER_BIT GL11/GL_DEPTH_BUFFER_BIT))
|
(GL11/glClear (bit-or GL11/GL_COLOR_BUFFER_BIT GL11/GL_DEPTH_BUFFER_BIT))
|
||||||
|
|
||||||
;; (swap! state assoc :last-time t)
|
|
||||||
(try
|
(try
|
||||||
(when (and @uploaded-scene @shaders)
|
(when (and @uploaded-scene @shaders)
|
||||||
(handle-input! window)
|
(handle-keyboard-state! 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-z (* radius (Math/cos t))
|
|
||||||
{:keys [^double camera-yaw ^double camera-pitch ^Vector3f camera-pos camera-target]} @state
|
{:keys [^double camera-yaw ^double camera-pitch ^Vector3f camera-pos camera-target]} @state
|
||||||
fwd (camera-forward camera-yaw camera-pitch)
|
fwd ^Vector3f (camera-forward camera-yaw camera-pitch)
|
||||||
target ^Vector3f (:camera-target @state)
|
camera-pos (if (:orbit-mode @state)
|
||||||
|
(let [fwd ^Vector3f (camera-forward (:orbit-yaw @state) (:orbit-pitch @state))
|
||||||
|
orbit-pos (Vector3f. ^Vector3f (:focus-point @state))]
|
||||||
|
(.add orbit-pos (.mul (Vector3f. fwd) 8.0)))
|
||||||
|
camera-pos)
|
||||||
|
target (:camera-target @state)
|
||||||
_ (doto ^Vector3f target
|
_ (doto ^Vector3f target
|
||||||
(.set camera-pos)
|
(.set camera-pos)
|
||||||
(.add fwd))
|
(.add fwd))
|
||||||
vm (-> (Matrix4f.)
|
target (if (:orbit-mode @state)
|
||||||
|
(:focus-point @state)
|
||||||
|
target)
|
||||||
|
view (-> (Matrix4f.)
|
||||||
(.identity)
|
(.identity)
|
||||||
(.lookAt (.x camera-pos) (.y camera-pos) (.z camera-pos) ;; eye (camera position)
|
(.lookAt (.x camera-pos) (.y camera-pos) (.z camera-pos) ;; eye (camera position)
|
||||||
(.x target) (.y target) (.z target) ;; center (where to look)
|
(.x ^Vector3f target) (.y ^Vector3f target) (.z ^Vector3f target) ;; center (where to look)
|
||||||
0.0 1.0 0.0)) ;; up
|
0.0 1.0 0.0)) ;; up
|
||||||
pm (-> (Matrix4f.)
|
proj (-> (Matrix4f.)
|
||||||
(.identity)
|
(.identity)
|
||||||
(.perspective (float (Math/toRadians 45))
|
(.perspective (float (Math/toRadians 45))
|
||||||
(float (/ (float w) (float h)))
|
(float (/ (float w) (float h)))
|
||||||
(float 0.1)
|
(float 0.1)
|
||||||
(float 100.0)))]
|
(float 100.0)))]
|
||||||
(.get vm vbuf)
|
(.get view vbuf)
|
||||||
(.get pm pbuf)
|
(.get proj pbuf)
|
||||||
(GL20/glUniformMatrix4fv ^int (:mv uniforms) false vbuf)
|
(GL20/glUniformMatrix4fv ^int (:mv uniforms) false vbuf)
|
||||||
(GL20/glUniformMatrix4fv ^int (: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.)))))
|
||||||
@ -252,7 +307,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 400 #_#_1900 1100 "NOL" MemoryUtil/NULL MemoryUtil/NULL)]
|
(let [window (GLFW/glfwCreateWindow 960 500 #_#_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")))
|
||||||
@ -270,29 +325,31 @@
|
|||||||
(GLFW/glfwSetKeyCallback window
|
(GLFW/glfwSetKeyCallback window
|
||||||
(reify GLFWKeyCallbackI
|
(reify GLFWKeyCallbackI
|
||||||
(invoke [_ win key scancode action mods]
|
(invoke [_ win key scancode action mods]
|
||||||
#_(try
|
(try
|
||||||
(handle-input! win key scancode action mods)
|
(handle-key-actions! win key scancode action mods)
|
||||||
(catch Exception e
|
(catch Exception e
|
||||||
(println "GLFW Input error:" e)))
|
(println "Key Callback Exception:" e))))))
|
||||||
(when (and (= key GLFW/GLFW_KEY_ESCAPE) (= action GLFW/GLFW_PRESS))
|
|
||||||
(swap! state assoc :should-close true)))))
|
|
||||||
(when (GLFW/glfwRawMouseMotionSupported)
|
(when (GLFW/glfwRawMouseMotionSupported)
|
||||||
(GLFW/glfwSetInputMode window GLFW/GLFW_RAW_MOUSE_MOTION GLFW/GLFW_TRUE))
|
(GLFW/glfwSetInputMode window GLFW/GLFW_RAW_MOUSE_MOTION GLFW/GLFW_TRUE))
|
||||||
(GLFW/glfwSetCursorPosCallback window
|
(GLFW/glfwSetCursorPosCallback window
|
||||||
(reify org.lwjgl.glfw.GLFWCursorPosCallbackI
|
(reify org.lwjgl.glfw.GLFWCursorPosCallbackI
|
||||||
(invoke [_ win xpos ypos]
|
(invoke [_ win xpos ypos]
|
||||||
(try
|
(try
|
||||||
(handle-mouse-input! win xpos ypos)
|
(handle-mouse-move! win xpos ypos)
|
||||||
(catch Exception e
|
(catch Exception e
|
||||||
(println "Cursor Pos Callback Exception:" e))))))
|
(println "Cursor Pos Callback Exception:" e))))))
|
||||||
(GLFW/glfwSetMouseButtonCallback window
|
(GLFW/glfwSetMouseButtonCallback window
|
||||||
(reify org.lwjgl.glfw.GLFWMouseButtonCallbackI
|
(reify org.lwjgl.glfw.GLFWMouseButtonCallbackI
|
||||||
(invoke [_ win button action mods]
|
(invoke [_ win button action mods]
|
||||||
(try
|
(try
|
||||||
(handle-mouse-buttons! win button action mods)
|
(let [mods (cond-> #{}
|
||||||
|
(pos? (bit-and mods GLFW/GLFW_MOD_SHIFT)) (conj :shift)
|
||||||
|
(pos? (bit-and mods GLFW/GLFW_MOD_CONTROL)) (conj :ctrl)
|
||||||
|
(pos? (bit-and mods GLFW/GLFW_MOD_ALT)) (conj :alt)
|
||||||
|
(pos? (bit-and mods GLFW/GLFW_MOD_SUPER)) (conj :super))]
|
||||||
|
(handle-mouse-buttons! win button action mods))
|
||||||
(catch Exception e
|
(catch Exception e
|
||||||
(println "Mouse Button Callback Exception:" e))))))
|
(println "Mouse Button Callback Exception:" e))))))
|
||||||
|
|
||||||
(loop []
|
(loop []
|
||||||
(loop []
|
(loop []
|
||||||
(when-let [f (.poll render-queue)]
|
(when-let [f (.poll render-queue)]
|
||||||
@ -461,6 +518,6 @@
|
|||||||
(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
|
||||||
(GL11/glClearColor 0.0 0.0 0.0 1.0))
|
(GL11/glClearColor 0.2 0.25 0.3 1.0))
|
||||||
|
|
||||||
:-)
|
:-)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user