Tuesday, June 15, 2010

Concise and Powerful

One of my biggest complaints and one of the things I've been criticized about most is my hatred for the complexities of using the majority of 3D engines today. To this end I've strived in Sgine to provide a much more simplistic and concise engine without sacrificing the power you would expect from a 3D engine.

When I was a developer on the jME (http://www.jmonkeyengine.com) project it is what led me to write "StandardGame" as far too commonly developers would end up with basically the same "Game" implementation for all their games, but it either consisted of a lot of copy and paste from other projects or a lot of re-writing the same code each time a new project was created.

If you look at previous posts the code has always been moderately simple and no more than a dozen or so lines of code to accomplish a basic task. However, I still had visions for improving further.

Perhaps I've gone a bit overboard in my agenda to simplify, but I've created a new trait in Sgine called "StandardDisplay" that is the spiritual successor to the ideas I put forth in jME years before. With Scala and Sgine a lot of possibilities for simplification have been opened up that were never possible before, such as putting the main method in a trait so it need not be explicitly defined. Further, one of the big problems with JRE applications today is deployment. Whether you want an Applet, a WebStart application, a desktop application, or all three it is a great deal of pain to get the end result you want. One of the goals of StandardDisplay is to be able to simply extend and execute in any display model you desire. Couple this with the idea of a deployment generation system I have yet to write and deployment of applications can be a simple afterthought instead of a major headache holding you back from getting your projects out.

Okay, I've droned on long enough without some actual code to show. If you've read this blog from the beginning you'll remember the very first post I made with an actual example with the following code to display an image of my dogs:

package org.sgine.render

import org.sgine.math.Matrix4

import javax.imageio._

import org.lwjgl.opengl.GL11._

object TestRenderer {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Renderer")
  
  val t = new Texture(700, 366)
  TextureUtil(t, ImageIO.read(getClass.getClassLoader.getResource("resource/puppies.jpg")), 0, 0, 700, 366)
  
  val m = Matrix4().translate(z = -1000.0)
  val i = Image(t)
  val fps = FPS(1.0)
  
  r.renderable := RenderList(MatrixState(m) :: i :: fps :: Nil)
  
  println("Renderer started!")
 }
}

That concept has firmed up a lot since then with the scenegraph system and the UI package to more recently look like:

package org.sgine.ui

import org.sgine.core.Resource

import org.sgine.render.Renderer
import org.sgine.render.scene.RenderableScene

import org.sgine.scene.GeneralNodeContainer
import org.sgine.scene.ext.ResolutionNode

object TestImage {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test RenderScene")
  
  val scene = new GeneralNodeContainer() with ResolutionNode
  scene.setResolution(1024, 768)
  
  val component = new Image()
  component.source := Resource("puppies.jpg")
  scene += component
  
  r.renderable := RenderableScene(scene)
 }
}

Though much more concise and simplified I still was not satisfied. After all, I just wanted to display a picture of my puppies on the screen. Enter StandardDisplay:

package org.sgine.ui

import org.sgine.core.Resource

import org.sgine.render.StandardDisplay

object TestImage extends StandardDisplay {
 def setup() = {
  val component = new Image(Resource("puppies.jpg"))
  scene += component
 }
}

That's right, two lines of actual logic code to display an Image with puppies. Yes, this technically could have been reduced to a single line, but the goal was concise, not showing how I used to write code in Perl. ;)

This can be executed as an application since StandardDisplay trait contains a "main" method that calls "start" and the only requirement is that a "setup" method be implemented. You can go much further than this if desired to customize and configure how and what you want to display but this is all that is required to get going.

There is still a lot of work to be done to support Applets, WebStart, etc. but the core is functional and pretty impressive if I do say so myself. :)

1 comment:

  1. I really like that last example! :)

    However, often you want to define your own main method for larger projects (for reading command line arguments and various initializations) - in that case it seems you can just create a subclass of StandardDisplay and call start on it.

    And support for webstart (and other deployment methods) will be great too!

    ReplyDelete

Scala Engine for high-performance interactive applications.