Showing posts with label text. Show all posts
Showing posts with label text. Show all posts

Sunday, July 18, 2010

Performance and Shapes

The functionality is really starting to come together on Sgine, but the performance has been a bit lower than I had hoped for large scenes. For simple games and business applications Sgine is performing quite well, but it's definitely not yet ready to write a first-person shooter on yet.

I've spent a bit of time doing performance tweaking and optimizations with YourKit and the performance is getting better, but still not where I'd like to see it. Right now I've got 400 cubes (which is made up of four independent Images for greater complexity) rotating and animating back and forth across the screen via easing effect at 38fps:



Not terrible, but over the next few weeks I'm hopeful I can get 4,000 cubes rendering at over 60fps.

Another quick note is that I've created a little Shape system in Sgine that will hopefully eventually be the core of all rendering as it auto-detects and uses additional capabilities of the video card for better performance. Additionally, I've added support for java.awt.Shape to ShapeData to draw nifty things like vector-text directly from a java.awt.Font to the screen. This is not the Shape-to-Texture cheating that most of the other engines do, this is direct to screen via tesselation. I've turned off any anti-aliasing so you can see it for yourself:



I've still got more work before I'm finished with the new Shape system, but once it is done I think this should help me get to the framerates I'm looking for.

Saturday, April 24, 2010

Label, Scale9, FontManager, and Resource

Yes, this is my third post today, but it's Saturday and I'm cranking through code now that I've gotten over the mouse-picking hurdle!

I have created a new component "Label" that is moderately self-explanatory, but represents a single-line of text. With this Resource comes to fruition as a simple lookup call "Resource(resourceName)" that will find a resource in the defined resource paths (defaults to look in "resource" path). Additionally I have created a FontManager that simplifies the management of fonts in the system. I have plans in the long-run to create a bitmap-font generator from AWT fonts, but for now getting a font is as easy as "FontManager("Arial")" presuming there's an AngelCode font definition in the Resource lookup path by the name of "Arial.fnt".

See the following test of Label:

package org.sgine.ui

import scala.io.Source

import org.sgine.input.event.MousePressEvent

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

import org.sgine.scene.GeneralNodeContainer

object TestLabel {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test RenderScene")
  
  val scene = new GeneralNodeContainer()
  val component = new Label()
  component.location.z := -500.0
  component.font := FontManager("Franklin")
  component.text := "Hello World!"
  scene += component
  
  r.renderable := RenderableScene(scene)
 }
}

Even more exciting is Scale-9 (a.k.a nine-slice) support that opens up more advanced skinning functionality and in the short-run allows creation of pretty buttons; bet you can guess what's up next. ;)

Anyway, here's a quick test using the new Scale9 component:

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

object TestScale9 {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Scale-9")
  
  val scene = new GeneralNodeContainer()
  
  val component = new Scale9()
  component(Resource("scale9/windows/button/hover.png"), 3.0, 3.0, 4.0, 5.0)
  component.width := 200.0
  component.height := 50.0
  component.location.z := -500.0
  scene += component
  
  r.renderable := RenderableScene(scene)
 }
}

Here's a screenshot of the application:



That's using a pretty Windows 7 skinned button in a hover state.

Mouse Picking

The reason for the delay since the last post has been the fact that I've been bogged down with mouse-picking for a while. Getting the math correct to properly handle ray-casting to 3D object space in a fast and efficient way took a while to wrap my head around, but finally, with quite a bit of help from my math guru of a wife I have a nice and efficient "translateLocal" method in Renderer:

def translateLocal(x: Double, y: Double, m: Matrix4, store: MutableVector3) = {
  synchronized {
   storeRay.origin.set(0.0, 0.0, 0.0)
   storeRay.direction.set(x, y, -nearDistance)
   
   storeMatrix.set(m)
   storeMatrix.invert()
   storeRay.transform(storeMatrix)
   storeRay.translateLocal(store)
   
   store
  }
 }

Today I'm working on integration of this within the Component architecture to support determination of hits within bounding regions. This does not create any additional garbage and I can run this on my machine about a million times in 700ms. Ideally I'd like the performance to be better than that, but since this does not absolutely have to be done within the rendering thread and with optimizations to limit the checks in the first place the performance should be fine.

Upgrading to LWJGL 2.4.2 from 2.2.2 gave me a framerate improvement of about 40% in my examples which is nice. :)

Next steps are to finish bounding support for BoundingQuad (what all my 2D UI components will use) and then start working on Scale-9 images, Label, TextInput, and multi-line text support with selection ability along with focus management.

Friday, April 2, 2010

AngelCode Fonts - Kerning

I already did most of the legwork earlier this week, but hadn't gotten around to turning on support for kerning, but that's all changed now:



Pretty easy to see the benefits of kerning here. However, this example also shows I seem to have a little problem with my low-hanging characters like 'g' and 'p'. Hopefully that will be fixed in the next update.

For now, here's the source:

package org.sgine.render

import org.sgine.math.mutable.Matrix4

import javax.imageio.ImageIO

import org.lwjgl.opengl.GL11._

import scala.io.Source

object TestFonts {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Fonts")
  
  val m1 = Matrix4().translate(x = -200.0, z = -1000.0)
  val m2 = Matrix4().translate(x = -200.0, y = -25.0, z = -1000.0)
  val fps = FPS(1.0)
  
  val font = AngelCodeFont(Source.fromURL(getClass.getClassLoader.getResource("resource/Arial.fnt")), getClass.getClassLoader.getResource("resource/Arial.png"))
  
  val a = new Array[() => Unit](5)
  a(0) = MatrixState(m1)
  a(1) = () => font.drawString("VAST Kerning Example Enabled", true)
  a(2) = MatrixState(m2)
  a(3) = () => font.drawString("VAST Kerning Example Disabled", false)
  a(4) = fps
  r.renderable := RenderList(a)
 }
}

A couple more days of effort and we can hopefully dig into some much more interesting features. :)

Wednesday, March 31, 2010

AngelCode Fonts - Second Steps

I was determined to get some more work done on this today after my sorry screenshot I posted last night. I've added parsing support to kerning but have not implemented it graphically. Hopefully I'll get around to that tomorrow. However, the xOffset, yOffset, and xAdvance functionality is working now and I have a much better screenshot to post:



I've also cleaned up the process by adding a "drawString" method to AngelCodeFont. See the following example code:

package org.sgine.render

import org.sgine.math.mutable.Matrix4

import javax.imageio.ImageIO

import org.lwjgl.opengl.GL11._

import scala.io.Source

object TestFonts {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Fonts")
  
  val m = Matrix4().translate(x = -70.0, z = -1000.0)
  val fps = FPS(1.0)
  
  val font = AngelCodeFont(Source.fromURL(getClass.getClassLoader.getResource("resource/Arial.fnt")), getClass.getClassLoader.getResource("resource/Arial.png"))
  
  val a = new Array[() => Unit](3)
  a(0) = MatrixState(m)
  a(1) = () => font.drawString("Hello World!")
  a(2) = fps
  r.renderable := RenderList(a)
 }
}

Tuesday, March 30, 2010

AngelCode Fonts - First Steps

I spent a little bit of time the past couple of evenings writing a parser in Scala to process AngelCode font files so sgine could support bitmap fonts and though the actual results look a bit sad, the progress is quite nice. :)

Now, I know this looks ugly, but for a combined time of less than two hours I think it's some decent progress:



You'll notice the x and y offsets are not specified, and I sort of hard-coded multi-character rendering, but still, it's a start. :)

Here's the code required:
package org.sgine.render

import org.sgine.math.mutable.Matrix4

import javax.imageio._

import org.lwjgl.opengl.GL11._

import scala.io.Source

object TestFonts {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Fonts")
  
  val m = Matrix4().translate(z = -1000.0)
  val fps = FPS(1.0)
  
  val font = AngelCodeFont(Source.fromURL(getClass.getClassLoader.getResource("resource/Arial.fnt")), getClass.getClassLoader.getResource("resource/Arial.png"))
  
  val a = new Array[() => Unit](13)
  a(0) = MatrixState(m)
  a(1) = () => font('H').draw(-60.0)
  a(2) = () => font('e').draw(-40.0)
  a(3) = () => font('l').draw(-20.0)
  a(4) = () => font('l').draw(0.0)
  a(5) = () => font('o').draw(20.0)
  a(6) = () => font(' ').draw(40.0)
  a(7) = () => font('W').draw(60.0)
  a(8) = () => font('o').draw(80.0)
  a(9) = () => font('r').draw(100.0)
  a(10) = () => font('l').draw(120.0)
  a(11) = () => font('d').draw(140.0)
  a(12) = fps
  r.renderable := RenderList(a)
  
  println("Renderer started! " + 81.asInstanceOf[Char] + " - " + font.face + ", " + font.size)
 }
}

Next step is to properly support drawing of Strings correctly. More to come soon.
Scala Engine for high-performance interactive applications.