Bonjour,
Avec l'aide d'un ami, nous essayons actuellement de "simuler" un plan texturé en 3D sur pixi.js.
Puisque la perspective n'est pas possible, nous avons fait de la transformation affine d'images.
Pour cela, nous découpons un plan en n*n morceaux, chacun de ces morceaux sont constitués de 2 triangles.
Chaque triangle est un masque permettant d'afficher son morceau du sprite correspondant (déformé).
La fonction updateTransform est une fonction de DisplayObject permettant a la base d'afficher un objet en prenant compte de sa rotation.
Voici la fonction initiale de pixi.js :
Nous avons donc réécrit cette fonction et nous l'avons appliquée a tous les objets concernés (Ici, c'est seulement la fonction pour les triangles inférieurs).
Voici une petite demo: http://ks3355883.kimsufi.com/Train3/test2.html
(Demo avec une découpe = 8, soit 8² x2 = 128 triangles)
Malheureusement, les performances ne sont pas bonnes (fps inferieurs a 60, sur une marchine basique, avec une découpe = 3), y aurait-il un moyen d'optimiser ce code ?
Il semblerait que l'utilisation de masques y soit pour beaucoup, mais nous n'avons pas trouvé d'autres moyen pour découper un sprite (De la meme manière que le clip(), de canvas).
Merci d'avance
Ps: Escusez pour l'indentation, elle est propre sur notepad++ mais ici elle est horrible x)
Avec l'aide d'un ami, nous essayons actuellement de "simuler" un plan texturé en 3D sur pixi.js.
Puisque la perspective n'est pas possible, nous avons fait de la transformation affine d'images.
Pour cela, nous découpons un plan en n*n morceaux, chacun de ces morceaux sont constitués de 2 triangles.
Chaque triangle est un masque permettant d'afficher son morceau du sprite correspondant (déformé).
La fonction updateTransform est une fonction de DisplayObject permettant a la base d'afficher un objet en prenant compte de sa rotation.
Voici la fonction initiale de pixi.js :
Code :
PIXI.DisplayObject.prototype.updateTransform = function()
{
// TODO OPTIMIZE THIS!! with dirty
if(this.rotation !== this.rotationCache)
{
this.rotationCache = this.rotation;
this._sr = Math.sin(this.rotation);
this._cr = Math.cos(this.rotation);
}
// var localTransform = this.localTransform//.toArray();
var parentTransform = this.parent.worldTransform;//.toArray();
var worldTransform = this.worldTransform;//.toArray();
var px = this.pivot.x;
var py = this.pivot.y;
var a00 = this._cr * this.scale.x,
a01 = -this._sr * this.scale.y,
a10 = this._sr * this.scale.x,
a11 = this._cr * this.scale.y,
a02 = this.position.x - a00 * px - py * a01,
a12 = this.position.y - a11 * py - px * a10,
b00 = parentTransform.a, b01 = parentTransform.b,
b10 = parentTransform.c, b11 = parentTransform.d;
worldTransform.a = b00 * a00 + b01 * a10;
worldTransform.b = b00 * a01 + b01 * a11;
worldTransform.tx = b00 * a02 + b01 * a12 + parentTransform.tx;
worldTransform.c = b10 * a00 + b11 * a10;
worldTransform.d = b10 * a01 + b11 * a11;
worldTransform.ty = b10 * a02 + b11 * a12 + parentTransform.ty;
this.worldAlpha = this.alpha * this.parent.worldAlpha;
};
Nous avons donc réécrit cette fonction et nous l'avons appliquée a tous les objets concernés (Ici, c'est seulement la fonction pour les triangles inférieurs).
Code :
scope.sprite[k][l].updateTransform = function(){
var i = this.idI;
var j = this.idJ;
var n = scope.n;
var w = scope.w;
var h = scope.h;
var xm = scope.xm;
var ym = scope.ym;
var zm = scope.zm;
var c = Math.cos(scope.angle);
var s = Math.sin(scope.angle);
var axe = scope.axe;
var ux = axe[0]/Math.sqrt(axe[0]*axe[0]+axe[1]*axe[1]+axe[2]*axe[2]);
var uy = axe[1]/Math.sqrt(axe[0]*axe[0]+axe[1]*axe[1]+axe[2]*scope.axe[2]);
var uz = axe[2]/Math.sqrt(axe[0]*axe[0]+axe[1]*axe[1]+axe[2]*axe[2]);
var r00 = ux*ux+(1-ux*ux)*c,
r01 = ux*uy*(1-c)-uz*s,
r02 = ux*uz*(1-c)+uy*s,
r10 = ux*uy*(1-c)+uz*s,
r11 = uy*uy+(1-uy*uy)*c,
r12 = uy*uz*(1-c)-ux*s,
r20 = ux*uz*(1-c)-uy*s,
r21 = uy*uz*(1-c)+ux*s,
r22 = uz*uz+-(1-uz*uz)*c;
var x = -r00*w/2-r01*h/2+xm;
var y = -r10*w/2-r11*h/2+ym;
var z = -r20*w/2-r21*h/2+zm;
var imagetriangle = [transformPoint([r00*(-w/2+i*(w/n))+r01*(h/2-(n-j)*h/n)+r02*0+xm,r10*(-w/2+i*(w/n))+r11*(h/2-(n-j)*h/n)+r12*0+ym,r20*(-w/2+i*(w/n))+r21*(h/2-(n-j)*h/n)+r22*0+zm]),transformPoint([r00*(-w/2+(i+1)*(w/n))+r01*(h/2-(n-j)*h/n)+r02*0+xm,r10*(-w/2+(i+1)*(w/n))+r11*(h/2-(n-j)*h/n)+r12*0+ym,r20*(-w/2+(i+1)*(w/n))+r21*(h/2-(n-j)*h/n)+r22*0+zm]),transformPoint([r00*(-w/2+i*(w/n))+r01*(h/2-(n-j-1)*h/n)+r02*0+xm,r10*(-w/2+i*(w/n))+r11*(h/2-(n-j-1)*h/n)+r12*0+ym,r20*(-w/2+i*(w/n))+r21*(h/2-(n-j-1)*h/n)+r22*0+zm])];
this.myMask.clear();
this.myMask.beginFill();
this.myMask.moveTo(imagetriangle[0][0],imagetriangle[0][1]);
this.myMask.lineTo(imagetriangle[1][0],imagetriangle[1][1]);
this.myMask.lineTo(imagetriangle[2][0],imagetriangle[2][1]);
this.myMask.endFill();
this.position.x = imagetriangle[2][0]+(n-j-1)*(imagetriangle[2][0]-imagetriangle[0][0])-i*(imagetriangle[1][0]-imagetriangle[0][0]);
this.position.y = imagetriangle[2][1]-i*(imagetriangle[1][1]-imagetriangle[0][1])+(n-j-1)*(imagetriangle[2][1]-imagetriangle[0][1]);
var parentTransform = this.parent.worldTransform;
var worldTransform = this.worldTransform;
var a00 = (imagetriangle[1][0]-imagetriangle[0][0])*n/w,
a10 = (imagetriangle[1][1]-imagetriangle[0][1])*n/w,
a01 = -(imagetriangle[2][0]-imagetriangle[0][0])*n/h,
a11 = -(imagetriangle[2][1]-imagetriangle[0][1])*n/h,
a02 = this.position.x,
a12 = this.position.y,
b00 = parentTransform.a, b01 = parentTransform.b,
b10 = parentTransform.c, b11 = parentTransform.d;
worldTransform.a = b00 * a00 + b01 * a10;
worldTransform.b = b00 * a01 + b01 * a11;
worldTransform.tx = b00 * a02 + b01 * a12 + parentTransform.tx;
worldTransform.c = b10 * a00 + b11 * a10;
worldTransform.d = b10 * a01 + b11 * a11;
worldTransform.ty = b10 * a02 + b11 * a12 + parentTransform.ty;
this.worldAlpha = this.alpha * this.parent.worldAlpha;
}
Voici une petite demo: http://ks3355883.kimsufi.com/Train3/test2.html
(Demo avec une découpe = 8, soit 8² x2 = 128 triangles)
Malheureusement, les performances ne sont pas bonnes (fps inferieurs a 60, sur une marchine basique, avec une découpe = 3), y aurait-il un moyen d'optimiser ce code ?
Il semblerait que l'utilisation de masques y soit pour beaucoup, mais nous n'avons pas trouvé d'autres moyen pour découper un sprite (De la meme manière que le clip(), de canvas).
Merci d'avance
Ps: Escusez pour l'indentation, elle est propre sur notepad++ mais ici elle est horrible x)