Techblog

Tech Blog

Our latest geek adventures!

Archive for February, 2008

14 February Javascript & XML

Posted by Gert-Jan in Javascript

Recently I’ve been working with Javascript in combination with XML and I found these methods quite usefull to switch between a string and a xml object.

function stringToXML( pString ){
	var lXML;
	// IE
	if( window.ActiveXObject ){
		lXML = new ActiveXObject( 'Microsoft.XMLDOM' );
		lXML.async = 'false';
		lXML.loadXML( pString );
	// no IE
	} else {
		var lParser = new DOMParser();
		lXML = lParser.parseFromString( pString, 'text/xml' );
	}
	return lXML;
}

function xmlToString( pXML ){
	// IE
	if( window.ActiveXObject ){
		return pXML.xml;
	// no IE
	} else {
		return ( new XMLSerializer() ).serializeToString( pXML );
	}
}

No Comments -

10 February Papervision3D – FrustumCamera3D

Posted by Tim in Papervision3D

Yesterday I updated the FrustumCamera3D class of Papervision3D. Time for a short tutorial on this camera!

The main difference between this camera and the other 2 cameras (Camera3D and FreeCamera3D) is that this camera uses a ‘real’ projection matrix, analogue to OpenGL. The FrustumCamera3D has 2 types of projection matrices: perspective and orthographic.

Checkout the example belonging to this tutorial (well: the code below IS the tutorial :-) .

 
package {
 
import flash.display.Sprite;
import flash.events.*;
import flash.geom.Point;
import flash.text.TextField;
import flash.text.TextFormat;
 
import org.papervision3d.Papervision3D;
import org.papervision3d.cameras.*;
import org.papervision3d.core.math.*;
import org.papervision3d.core.proto.*;
import org.papervision3d.materials.*;
import org.papervision3d.materials.utils.*;
import org.papervision3d.objects.*;
import org.papervision3d.objects.primitives.*;
import org.papervision3d.render.*;
import org.papervision3d.scenes.*;
import org.papervision3d.view.*;
 
/**
 * @author timknip
 */
public class TutoFrustumCamera3D extends Sprite {
 
	/** The PV3D scene to render */
	public var scene : Scene3D;
 
	/** This PV3D camera */
	public var camera : FrustumCamera3D;
 
	/** The PV3D renderer */
	public var renderer : BasicRenderEngine;
 
	/** The PV3D viewport */
	public var viewport : Viewport3D;
 
	/** Show info */
	public var status : TextField;
 
	/**
	 * Constructor.
	 */
	public function TutoFrustumCamera3D() : void {
		init();
	}
 
	/**
	 * Init.
	 */
	private function init() : void {
 
		// add a textfield
		initStatusLine();
 
		// used by orbiting / zooming
		_lastMouse = new Point();
 
		// create a viewport
		viewport = new Viewport3D(800, 600);
 
		// add
		addChild(viewport);
 
		// create a frustum camera with FOV=60, near=10, far=10000
		camera = new FrustumCamera3D(viewport, 60, 10, 10000);
 
		// create a renderer
		renderer = new BasicRenderEngine();
 
		// create the scene
		scene = new Scene3D();
 
		// init the scene
		initScene();
 
		// mouse listeners
		stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
		stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
		stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
 
		// key listener
		stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
 
		// render on each frame
		addEventListener(Event.ENTER_FRAME, render);
 
		showInfo();
	}
 
	/**
	 * Init the scene.
	 */
	private function initScene() : void {
 
		var materials : MaterialsList = new MaterialsList();
 
		materials.addMaterial(new WireframeMaterial(0xff0000), "front");
		materials.addMaterial(new WireframeMaterial(0x0000ff), "back");
		materials.addMaterial(new WireframeMaterial(0xffff00), "left");
		materials.addMaterial(new WireframeMaterial(0x00ffff), "right");
		materials.addMaterial(new WireframeMaterial(0x00ff00), "top");
		materials.addMaterial(new WireframeMaterial(0xff00ff), "bottom");
 
		var cube : Cube = new Cube(materials);
 
		scene.addChild(cube);
	}
 
	/**
	 * Add a textfield.
	 */
	private function initStatusLine() : void {
		status = new TextField();
		addChild(status);
		status.x = status.y = 5;
		status.width = 500;
		status.height = 200;
		status.multiline = true;
		status.selectable = false;
		status.defaultTextFormat = new TextFormat("Arial", 12, 0xffff00);
		status.text = "";
	}
 
		/**
	 * Render!
	 */
	private function render( event : Event = null ) : void {
 
		// orbit the camera
		camera.orbit(_camTarget, _camPitch, _camYaw, _camDist);
 
		// render
		renderer.renderScene(scene, camera, viewport);
	}
 
	/**
	 * Show some info;
	 */
	private function showInfo() : void {
		var msg : String = "usage:\ndrag to rotate, drag-shift to zoom\n";
		msg += "- o: toggle ortho / perspective mode\n";
		msg += "- v: increase / decrease(+shift) FOV\n";
		msg += "- f: increase / decrease(+shift) camera far-plane\n";
		msg += "- n: increase / decrease(+shift) camera near-plane\n\n";
 
		msg += "camera\n- projection mode: " + (camera.ortho?"ortho":"perspective") + "\n";
		msg += "- fov: " + camera.fov + " near: " + camera.near + " far: " + camera.far + "\n";
 
		status.text = msg;
	}
 
	/**
	 *
	 * @param	event
	 */
	private function keyUpHandler( event : KeyboardEvent ) : void {
 
		switch(event.keyCode) {
			case 70: // f
				if(!camera.ortho) {
					if(event.shiftKey)
						camera.far -= 10;
					else
						camera.far += 10;
				}
				break;
 
			case 78: // n
				if(!camera.ortho) {
					if(event.shiftKey)
						camera.near -= 10;
					else
						camera.near += 10;
				}
				break;
 
			case 79: // o
				camera.ortho = !camera.ortho;
				break;
 
			case 86: // v
				if(!camera.ortho) {
					if(event.shiftKey)
						camera.fov -= 5;
					else
						camera.fov += 5;
				}
				break;
 
			default:
				break;
		}
 
		showInfo();
	}
 
	/**
	 *
	 * @param	event
	 */
	private function mouseDownHandler( event : MouseEvent ) : void {
		_lastMouse.x = event.stageX;
		_lastMouse.y = event.stageY;
		if(event.shiftKey)
			_zooming = true;
		else
			_orbiting = true;
	}
 
	/**
	 *
	 * @param	event
	 */
	private function mouseMoveHandler( event : MouseEvent ) : void {
		var dx:Number = _lastMouse.x - event.stageX;
		var dy:Number = _lastMouse.y - event.stageY;
 
		if(_orbiting)	{
			_camYaw += dx * (Math.PI/180);
 
			_camPitch -= dy * (Math.PI/180);
			_camPitch = _camPitch < 0.001 ? 0.001 : _camPitch;
			_camPitch = _camPitch > Math.PI/2 ? Math.PI/2 : _camPitch;
 
			_lastMouse.x = event.stageX;
			_lastMouse.y = event.stageY;
		} else if(!camera.ortho && _zooming) {
			if(_camDist - dy > 10)
				_camDist -= dy;
		} else if(camera.ortho && _zooming) {
			// this is the essential bit to zoom the camera in ortho-mode!
			camera.orthoScale += (dy * 0.0005);
		}
 
		render();
 
		event.updateAfterEvent();
	}
 
	/**
	 *
	 * @param	event
	 */
	private function mouseUpHandler( event : MouseEvent ) : void {
		_orbiting = _zooming = false;
	}
 
	/** Are we orbiting the camera? */
	private var _orbiting			: Boolean = false;
 
	/** Are we zooming the camera? */
	private var _zooming			: Boolean = false;
 
	/** A Point to keep track of mouse coords */
	private var _lastMouse			: Point;
 
	/** Camera Yaw */
	private var _camYaw				: Number = -Math.PI/2;
 
	/** Camera Pitch */
	private var _camPitch			: Number = Math.PI/2;
 
	/** Camera distance */
	private var _camDist			: Number = 2000;
 
	/** Camera target */
	private var _camTarget			: DisplayObject3D = DisplayObject3D.ZERO;
}
}

4 Comments -

8 February Loading swf’s faster

Last week we wanted to see if we could speed up the loading of the Floorplanner Flash app. The Flash app (AS2) consists of 1 main app that loads several swf forms (the windows you see, like the library). The library itself holds a lot of furniture elements, which are separate swf files that are loaded one by one.

When a user creates a floor plan and adds furniture to it, it’s not strange that the design holds more than 50 furniture elements. Though all elements are small swf files, it takes a lot of time to handle all resource requests on our server. We thought it would be nice if we didn’t have to load all the elements one by one, but that we could bundle them into one big swf file. Then the generated bundle-swf is loaded into the flash app and the furniture elements are loaded from the bundle-swf.

We looked at Swfmill and Ming, and we did manage to create a setup that could dynamically bundle the furniture elements into one big swf. The problem was that it didn’t work for all our furniture elements. Almost 10% failed.

In the Flash app we also experienced some unexpected issues. You can only add mc’s (furniture elements) from the library to the stage by using attachMovie(). That means that all elements must have the same parent mc (AS2). So you can only use one bundle-swf, because if you load another, your attached mc’s will be removed.

With all the issues we encountered we decided to keep things as they are right now, and tackle this issue when we’re upgrading to AS3.

No Comments -