Saturday, May 22, 2010

ResolutionNode

I'm back from a week long cruise to the Caribbean without cell phones, computers, or internet access. It was a great break from technology, but now I'm back, refreshed, and ready to crank out more functionality into Sgine.

What I have today is called ResolutionNode. If you look back at all the blogged examples below you'll notice all the 'z' translation stuff on the components. The reason for that is because Sgine (and OpenGL generally) is configured to have 'z' at 0.0 have a distance of -1.0 to 1.0 both vertically and horizontally. Further, anything between 0.0 and -1.0 (negative to back further into the screen) is clipped for mathematical precision reasons. So by pushing the the components to something like -1000.0 for 'z' causes it to appear much smaller because its depth is so far back into the projection.

This is fine for games and general 3D applications, but can be a pain in the neck when you want to have a normal graphics-based UI and you're expecting a specific resolution (e.g. 1024x768) to design graphics and layout for. To this end I have created a trait called ResolutionNode. It gives the ability to specify a resolution (e.g. 1024x768) and modifies the world matrix for that Node to properly display that resolution to fit to the screen. Not only does this give you the benefit of managing the resolution for the screen, but it also keeps you from having to worry about the *actual* resolution as this will scale-to-fit so even if you are running 1920x1200 resolution if you specify 1024x768 internally you'll end up with everything being stretched to fit.

This is actually part of a larger UI design concept I've been developing that I'll go into more on as the functionality is finalized in Sgine, but for now I give you my example.

The following code takes a 1024x768 image and a 640x480 image and displays them overlayed on top of each other. The cool thing here though is that you can see that using a ResolutionNode container for each I am able to see both of them at the exact same size.

package org.sgine.ui

import org.sgine.core.Color
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 TestResolution {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Resolution")
  r.verticalSync := false
  
  val scene = new GeneralNodeContainer()
  
  val r1024 = new GeneralNodeContainer() with ResolutionNode
  r1024.setResolution(1024.0, 768.0)
  scene += r1024
  
  val c1024 = new Image()
  c1024.source := Resource("1024.jpg")
  c1024.alpha := 0.5
  r1024 += c1024
  
  val r640 = new GeneralNodeContainer() with ResolutionNode
  r640.setResolution(640.0, 480.0)
  scene += r640
  
  val c640 = new Image()
  c640.source := Resource("640.jpg")
  c640.alpha := 0.5
  r640 += c640
  
  r.renderable := RenderableScene(scene)
 }
}

The two images I'm using are:



and:



The resulting screenshot is as follows:

1 comment:

  1. Hi Matt,

    Scale of 2.071 works better for me, pixel perfect.
    worldMatrix().scaleAll(2.071 / height)

    My frame is 1920 width by 1080 height.

    So I change ResolutionNode to:

    trait ResolutionNode extends WorldMatrixNode {
    def setResolution(width: Double, height: Double) = {
    worldMatrix().identity()
    worldMatrix().translate(z = -101.0)
    worldMatrix().scaleAll(2.071 / height)
    }
    }

    ReplyDelete

Scala Engine for high-performance interactive applications.