Oct 06 2010
Graffiti Analysis Flash Test 2
Ok, j’avais laissé en plan le “graffiti analysis test” mais il fallait quand même que je règle ce problème de vecteur “UP”. J’ai donc trouvé la formule magique pour orienter les graffitis dans le “bon” sens.
En gros les applications qui enregistrent les tags doivent préciser un vecteur “UP” qui détermine l’orientation du graffiti. Certaines applications (ex : Coding With Attitude GML Drawer : MFF2010 ) ne le font pas donc on prendra l’axe Y par défaut, c’est l’orientation qui est la plus “normale”.
Mais d’autres applications (presque toutes d’ailleurs puisqu’il s’agit de portages) ont par défaut un vecteur “UP” sur l’axe des x : (1,0,0);
Si on opère pas de transformation, certains graffitis vont s’écrire de haut en bas et non pas de gauche à droite. La première solution est de choisir arbitrairement : “bon ben si c’est Y, on touche à rien et si c’est X ben on fait une rotation de -90° et c’est marre…” Mais on vaut quand même mieux que ça !
Donc la technique c’est de trouver l’axe et l’angle de rotation puis d’appliquer la transformation.
Le code est dans le “onload” du xml.
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix3D;
import flash.geom.Rectangle;
import flash.geom.Vector3D;
import flash.net.URLLoader;
import flash.net.URLRequest;
/**
* @author Turboconnard
*/
public class Test3D extends MovieClip {
private var yaxis : Sprite;
private var zaxis : Sprite;
private var xaxis : DisplayObject;
private var axe : Sprite;
private var container : Sprite;
private var graf : Sprite;
public function Test3D() {
//waiting for stage to be instanciate
addEventListener(Event.ADDED_TO_STAGE, _add);
}
private function _add(event : Event) : void {
/* remember 3D objects may have a z if you want transform thme */
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.addEventListener(Event.RESIZE,resize);
//creating global container
container = new Sprite();
container.z = 0;
graf = new Sprite();
graf.z = 0;
addChild(container);
container.addChild(graf);
//building 3D axis viewer
xaxis = getLine(0x0000ff);
yaxis = getLine(0x00ff00);
zaxis = getLine(0xff0000);
xaxis.z = 0;
yaxis.z = 0;
zaxis.z = 0;
yaxis.transform.matrix3D.appendRotation(90, Vector3D.Z_AXIS);
zaxis.transform.matrix3D.appendRotation(90, Vector3D.Y_AXIS);
axe = new Sprite();
axe.z = 0;
axe.addChild(xaxis);
axe.addChild(yaxis);
axe.addChild(zaxis);
addChild(axe);
//load a graffiti
load(null);
//resize
resize(null);
}
/**
* load a random graffiti
*/
public function load(e:MouseEvent) : void {
stage.removeEventListener(MouseEvent.CLICK,load);
alpha = 0.2;
var urlLoader : URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, _onLoad);
urlLoader.load(new URLRequest("http://000000book.com/data/" +"random"+ ".gml"));
}
/**
*
*/
private function _onLoad(event : Event) : void {
stage.addEventListener(MouseEvent.CLICK,load);
alpha = 1;
var gml:XML = XML(URLLoader(event.target).data);
var env:XMLList = gml.tag.environment;
//Some graffitis aren’t drawn with Y as up axis.
//we have to rotate our world to mach our Y up axis.
//my up vector in flash
var up:Vector3D = new Vector3D(0,1,0);
//graffiti’s up vector
var modelup:Vector3D;
if(int(env.up.x) + int(env.up.y) + int(env.up.z) == 0 ) modelup = new Vector3D(0,1,0);
else modelup = new Vector3D(env.up.x, env.up.y, env.up.z);
//looking for axis to rotate
var rotationaxis:Vector3D = up.crossProduct(modelup);
//looking for rotation angle
var angle:Number = Math.acos( up.dotProduct(modelup) );
//rotate objects
axe.transform.matrix3D = new Matrix3D();
graf.transform.matrix3D = new Matrix3D();
axe.transform.matrix3D.appendRotation(angle/Math.PI*180, rotationaxis);
graf.transform.matrix3D.appendRotation(angle/Math.PI*180, rotationaxis);
//draw graffiti
graf.graphics.clear();
graf.graphics.lineStyle(8,0);
for(var i:int=0;i<XMLList(gml.tag.drawing.stroke).length();i++){
var pts:XMLList = XMLList(gml.tag.drawing.stroke)[i].pt;
for(var k:int=0;k<pts.length();k++){
if(k==0) graf.graphics.moveTo(pts[k].x*env.screenBounds.x,pts[k].y*env.screenBounds.y);
else graf.graphics.lineTo(pts[k].x*env.screenBounds.x,pts[k].y*env.screenBounds.y);
}
}
resize(null);
}
/**
* resize
* @param e Event
*/
private function resize(e:Event) : void {
axe.x = stage.stageWidth/2;
axe.y = stage.stageHeight/2;
//moving objects to center
var box:Rectangle = container.getRect(container);
container.x = – box.x + stage.stageWidth/2 – box.width/2;
container.y = – box.y + stage.stageHeight/2 – box.height/2;
}
/**
* draw an arrow
* @param pColor arraow color
*/
public function getLine(pColor : uint) : Sprite {
var s : Sprite = new Sprite();
s.graphics.lineStyle(1, pColor,1,false,"none");
s.graphics.lineTo(20, 0);
s.graphics.lineTo(15, -2);
s.graphics.moveTo(20, 0);
s.graphics.lineTo(15, 2);
return s;
}
}
}

