So you want to render a 3d model in libGDX, in Clojure?

Well, so did I so you’ve come to the right place.
Finding this information online was difficult since the use of libGdx is rarely common in Clojure. What I did find is a decent intro code sample for rendering a triangle mesh. This really helped kick things off for me, but below I’ll show you one better and branch off that code to show you how to create an AssetManager and load in model instances, thanks to Xoppa’s tutorial and explanations. This post is basically a mostly-close replica of the java tut by Xoppa, re-written in clojure.

(see this post about the new repo location)

First make sure your new app created from lein includes these dependencies:
[com.badlogicgames.gdx/gdx "0.9.9-SNAPSHOT"]
[com.badlogicgames.gdx/gdx-backend-lwjgl "0.9.9-SNAPSHOT"]
[com.badlogicgames.gdx/gdx-platform "0.9.9-SNAPSHOT" :classifier "natives-desktop"]

As well include this:
:repositories [["libgdx" "https://oss.sonatype.org/content/repositories/snapshots/"]]
This way it knows where to look for these special repos.

(ns libgdx-example.core
  (:import (com.badlogic.gdx ApplicationListener Gdx Graphics)
           (com.badlogic.gdx.graphics GL10 Color Camera PerspectiveCamera)
           (com.badlogic.gdx.backends.lwjgl LwjglApplication)
           (com.badlogic.gdx.assets AssetManager)
           (com.badlogic.gdx.graphics.g3d Model ModelBatch ModelInstance)
           (com.badlogic.gdx.graphics.g3d.lights Lights DirectionalLight)
           (com.badlogic.gdx.graphics.g3d.utils CameraInputController))
 
  (:gen-class))
 
 
(declare cam,camcontrol,lights,AM,MI,MB)
(def assetloaded false)
 
 
(defn display []
  (.update camcontrol)
 
  (doto (Gdx/gl)
    (.glViewport 0,0,(.getWidth Gdx/graphics),(.getHeight Gdx/graphics))
    (.glClear GL10/GL_COLOR_BUFFER_BIT)
    (.glClear GL10/GL_DEPTH_BUFFER_BIT))
 
  (.begin MB cam)
    (doto MB (.render MI lights))
  (.end MB)
  )
 
(defn app-listener []
  (proxy [ApplicationListener] []
    (resize [w h] )
    (create []
 
      (def lights (Lights. 0.4 0.4 0.4))
      (.add lights (.set (PointLight.) 50 90 120 0 0 0 20)) ;r g b, x y z, intensity
 
      (def cam (new PerspectiveCamera 75  (.getWidth Gdx/graphics) (.getWidth Gdx/graphics)))
      (doto (.position cam) (.set 1 1 1))
      (.lookAt cam 0 0 0)
      (set! (.far cam) 300)
      (.update cam)
 
      (def camcontrol (new CameraInputController cam))
      (doto (Gdx/input) (.setInputProcessor camcontrol))
 
      (def MB (new ModelBatch))
      (def AM (new AssetManager))
      (doto AM (.load "resources/ship.obj" Model))
     )
 
    (render []
      (do 
        (if (.update AM)
          (if assetloaded
            (display)
            (do
              (prn "loading!!")
 
              (def MI (new ModelInstance (.get AM "resources/ship.obj" Model)))
 
              (prn "assets loaded!")
              (def assetloaded true))))
 
        ))
    (pause [] )
    (resume [] )
    (dispose [] (.dispose MB)(.dispose AM)) ;should find a way to clear our MI
 ))
 
 
(defn app []
  (LwjglApplication. (app-listener) "Clojure 3d Game" 800 600 false))
 
 
 
 
(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  ;; work around dangerous default behaviour in Clojure
  (alter-var-root #'*read-eval* (constantly false))
  (app))

Some things that need attention are lighting, I noticed my calls via directional lights do not seem to work and even remove point light sources– this should be investigated. Java-interop is not my favorite, specially after writing in either Java or Clojure alone for the last few months. Figuring out how to call certain things was definitely the hardest part of this.
If you understand java well, it’s worthwhile reading xoppa’s tut as it features descriptions of what is doing what.
My liberal use of def during the runtime is not great in my opinion, but makes for easy work. 3D, game programming with heavy java-interop is not exactly smooth sailing in clojure and anyone who has been enjoying FP will probably cringe at some of this code. I welcome anyone to modify this code with something better but similar enough to keep its beginner feel for libGdx :)

clone the libgdx example here: https://github.com/viperscape/libgdx-example

have fun!

One thought on “So you want to render a 3d model in libGDX, in Clojure?

  1. Pingback: Running LibGdx (as a Clojure game) in Android | Junco Blog

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Current month ye@r day *