Advertisement
liuwong

portal: PortalConstraint

May 4th, 2013
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package example.portal
  2. {
  3.     import nape.constraint.UserConstraint;
  4.     import nape.geom.Vec2;
  5.     import nape.geom.Vec3;
  6.     import nape.phys.Body;
  7.     import nape.util.Debug;
  8.    
  9.     /**
  10.      * ...
  11.      * @author liu wong
  12.      *
  13.      */
  14.    
  15.     public class PortalConstraint extends UserConstraint
  16.     {
  17.         public var body1:Body;
  18.         public var body2:Body;
  19.         public var portalBody1:Body;
  20.         public var portalBody2:Body;
  21.  
  22.         /*
  23.             Portal positions+directions defined locally to each portalBody
  24.         */
  25.         public var position1:Vec2;
  26.         public var position2:Vec2;
  27.         public var direction1:Vec2;
  28.         public var direction2:Vec2;
  29.        
  30.         /*
  31.         Portal scaling from portal1 to portal2
  32.         */
  33.         public var scale:Number;
  34.        
  35.         private var unit_dir1:Vec2;
  36.         private var unit_dir2:Vec2;
  37.        
  38.         private var p1:Vec2;
  39.         private var p2:Vec2;
  40.         private var s1:Vec2;
  41.         private var s2:Vec2;
  42.         private var n1:Vec2;
  43.         private var n2:Vec2;
  44.         private var a1:Number;
  45.         private var a2:Number;
  46.        
  47.         public function PortalConstraint(prtlBody1:Body, pos1:Vec2, dir1:Vec2,
  48.             prtlBody2:Body, pos2:Vec2, dir2:Vec2, scl:Number, bd1:Body, bd2:Body):void
  49.         {
  50.             super(3);
  51.            
  52.             this.portalBody1 = __registerBody(null, prtlBody1);
  53.             this.portalBody2 = __registerBody(null, prtlBody2);
  54.            
  55.             position1 = __bindVec2();
  56.             position1.set(pos1);
  57.            
  58.             position2 = __bindVec2();
  59.             position2.set(pos2);
  60.            
  61.             direction1 = __bindVec2();
  62.             direction1.set(dir1);
  63.            
  64.             direction2 = __bindVec2();
  65.             direction2.set(dir2);
  66.            
  67.             __invalidate();
  68.            
  69.             this.scale = scl;
  70.            
  71.             this.body1 = __registerBody(null,bd1);
  72.             this.body2 = __registerBody(null, bd2);
  73.  
  74.             //init Vec2's that are reused across methods
  75.             unit_dir1 = Vec2.get();
  76.             unit_dir2 = Vec2.get();
  77.  
  78.             p1 = Vec2.get();
  79.             p2 = Vec2.get();
  80.             s1 = Vec2.get();
  81.             s2 = Vec2.get();
  82.             n1 = Vec2.get();
  83.             n2 = Vec2.get();
  84.         }
  85.        
  86.         override public function __copy():UserConstraint
  87.         {
  88.             return new PortalConstraint(portalBody1, position1, direction1, portalBody2, position2, direction2, scale, body1, body2);
  89.         }
  90.        
  91.         override public function __validate():void
  92.         {
  93.             unit_dir1.set(direction1.mul(1/direction1.length, true));
  94.             unit_dir2.set(direction2.mul(1/direction2.length, true));
  95.         }
  96.        
  97.         override public function __prepare():void
  98.         {
  99.             p1.set(portalBody1.localVectorToWorld(position1, true));
  100.             p2.set(portalBody2.localVectorToWorld(position2, true));
  101.  
  102.             s1.set(body1.position.sub(p1,true).subeq(portalBody1.position));
  103.             s2.set(body2.position.sub(p2,true).subeq(portalBody2.position));
  104.  
  105.             n1.set(portalBody1.localVectorToWorld(unit_dir1, true));
  106.             n2.set(portalBody2.localVectorToWorld(unit_dir2, true));
  107.  
  108.             a1 = unit_dir1.angle + portalBody1.rotation;
  109.             a2 = unit_dir2.angle + portalBody2.rotation;
  110.         }
  111.        
  112.         public function setProperties(clone:Body, original:Body):void
  113.         {
  114.             //ensure our required pre-calced values are correct.
  115.             __validate();
  116.             __prepare();
  117.  
  118.             //compute velocity error so we can set velocity correctly.
  119.             var v:Vector.<Number> = new Vector.<Number>();
  120.             __velocity(v);
  121.  
  122.             //modify clone so that position and velocity errors are 0
  123.             if (clone == body2) {
  124.                 clone.position = portalBody2.position.add(p2,true);
  125.                 clone.position.x -= (n2.x * s1.dot(n1) + n2.y * s1.cross(n1))*scale;
  126.                 clone.position.y -= (n2.y * s1.dot(n1) - n2.x * s1.cross(n1))*scale;
  127.                 clone.rotation = -Math.PI + original.rotation - a1 + a2;
  128.  
  129.                 clone.velocity.x -= n2.x * v[0] + n2.y * v[1];
  130.                 clone.velocity.y -= n2.y * v[0] - n2.x * v[1];
  131.                 clone.angularVel += v[2];
  132.             }
  133.             else {
  134.                 clone.position = portalBody1.position.add(p1, true);
  135.                 clone.position.x -= (n1.x * s2.dot(n2) + n1.y * s2.cross(n2))/scale;
  136.                 clone.position.y -= (n1.y * s2.dot(n2) - n1.x * s2.cross(n2))/scale;
  137.                 clone.rotation = Math.PI + original.rotation - a2 + a1;
  138.  
  139.                 clone.velocity.x += (n1.x * v[0] + n1.y * v[1]) / scale;
  140.                 clone.velocity.y += (n1.y * v[0] - n1.x * v[1]) / scale;
  141.                 clone.angularVel += v[2];
  142.             }
  143.         }
  144.        
  145.         override public function __position(err:Vector.<Number>):void
  146.         {
  147.             err[0] = scale*s1.dot(n1) + s2.dot(n2);
  148.             err[1] = scale*s1.cross(n1) + s2.cross(n2);
  149.             err[2] = (body1.rotation - a1) - (body2.rotation - a2) - Math.PI;
  150.         }
  151.        
  152.         override public function __velocity(err:Vector.<Number>):void
  153.         {
  154.             var v1:Vec3 = body1.constraintVelocity;
  155.             var v2:Vec3 = body2.constraintVelocity;
  156.             var pv1:Vec3 = portalBody1.constraintVelocity;
  157.             var pv2:Vec3 = portalBody2.constraintVelocity;
  158.  
  159.             var u1:Vec2 = v1.xy().subeq(p1.perp(true).muleq(pv1.z)).subeq(pv1.xy(true));
  160.             var u2:Vec2 = v2.xy().subeq(p2.perp(true).muleq(pv2.z)).subeq(pv2.xy(true));
  161.  
  162.             err[0] = scale*(u1.dot(n1) + pv1.z*s1.cross(n1))
  163.                          + (u2.dot(n2) + pv2.z*s2.cross(n2));
  164.             err[1] = scale*(u1.cross(n1) + pv1.z*s1.dot(n1))
  165.                          + (u2.cross(n2) + pv2.z*s2.dot(n2));
  166.             err[2] = (v1.z - pv1.z) - (v2.z - pv2.z);
  167.  
  168.             u1.dispose();
  169.             u2.dispose();
  170.         }
  171.        
  172.         override public function __eff_mass(eff:Vector.<Number>):void
  173.         {
  174.             eff[0]=eff[3]=body1.constraintMass*scale*scale + body2.constraintMass;
  175.             eff[1]=eff[2]=eff[4] = 0.0;
  176.             eff[5]= body1.constraintInertia + body2.constraintInertia;
  177.         }
  178.        
  179.         override public function __impulse(imp:Vector.<Number>, body:Body, out:Vec3):void
  180.         {
  181.             if (body == portalBody1 || body == portalBody2)
  182.                 out.setxyz(0,0,0);
  183.             else
  184.             {
  185.                 var sc1:Number;
  186.                 var sc2:Number;
  187.                 var norm:Vec2;
  188.                 if (body == body1)
  189.                 {
  190.                     sc1 = scale;
  191.                     sc2 =  1.0;
  192.                     norm = n1;
  193.                 }
  194.                 else
  195.                 {
  196.                     sc1 = 1.0;
  197.                     sc2 = -1.0;
  198.                     norm = n2;
  199.                 }
  200.                 out.x = sc1*(norm.x*imp[0] + norm.y*imp[1]);
  201.                 out.y = sc1*(norm.y*imp[0] - norm.x*imp[1]);
  202.                 out.z = sc2*imp[2];
  203.             }
  204.         }
  205.        
  206.         override public function __draw(debug:Debug):void
  207.         {
  208.             __validate();
  209.             var p1:Vec2 = portalBody1.localPointToWorld(position1);
  210.             var p2:Vec2 = portalBody2.localPointToWorld(position2);
  211.  
  212.             debug.drawCircle(p1,2,0xff);
  213.             debug.drawCircle(p2,2,0xff0000);
  214.             debug.drawLine(p1,p1.add(portalBody1.localVectorToWorld(unit_dir1,true).muleq(20),true),0xff);
  215.             debug.drawLine(p2,p2.add(portalBody2.localVectorToWorld(unit_dir2,true).muleq(20),true),0xff0000);
  216.             debug.drawLine(p1,body1.position,0xffff);
  217.             debug.drawLine(p2,body2.position,0xff00ff);
  218.  
  219.             p1.dispose();
  220.             p2.dispose();
  221.         }
  222.     }
  223.    
  224. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement