2017-04-06 17 views
1

현재 진행중인 프로젝트에서는 게임 개발을 위해 사용자 정의 스크립팅 언어 (신이 왜 그렇게하는지 압니다)를 사용하고 있습니다. 세부 정보가 없으면 엔진은 기본적으로 Flash 또는 iOS로 해석하고 내보내기합니다.Affine Coord Space를 사용하여 사용자 정의 엔진을 사용하여 Spine2d 라이브러리 만들기

그래서이 프로젝트에서는 애니메이션 지원을 위해 Spine 라이브러리를 생성해야했습니다. 대부분의 경우, 우리 엔진이 AS3과 유사하기 때문에 쉽게 해석 할 수 없으므로 그리 어렵지 않습니다.

주요 문제 저는 현재 렌더링 중입니다. 이 스크립팅 언어의 제작자는 직위 등을 렌더링하기 위해 아핀 좌표 공간 시스템을 독점적으로 사용하기로 결정했습니다. 나는 그 주위에 머리를 감싸려고했지만, 그것이 어떻게 작동하는지에 대한 많은 지식이 없으면, 나는 그것을 고민하기 위해 고심하고있다. 내가 할 수있는 일은 x와 y로 수동으로 위치를 설정하고 각도로 회전을 수동으로 설정하는 것입니다. 도움이된다면 대단히 감사하겠습니다.

package engine.spine.render; 

//These have the same functionality as the Spine2d library for AS3 
import engine.spine.IGBone; 
import engine.spine.IGSkeleton; 
import engine.spine.IGSkeletonData; 
import engine.spine.IGSlot; 
import engine.spine.atlas.IGAtlasRegion; 
import engine.spine.attachments.IGRegionAttachment; 

//This stuff is our engine libraries 
import engine.graphics.*; 
import engine.gui.*; 
import engine.math.*; 
import engine.tween.*; 
import engine.util.IGFSM; 
import engine.IGApplication; 

public class IGSpineWidget extends IGUIWidget 
{ 
    private var m_skeleton : IGSkeleton; 
    private var m_lastTime : int; 
    private var m_image : IGImage; 
    private var m_wrappers : Map<IGRegionAttachment, IGSpinePosition> = new Map<IGRegionAttachment, IGSpinePosition>(); // Works the same way as a Dictionary in AS3 

    public function IGSpineWidget (skeletonData : IGSkeletonData, image : IGImage) 
    { 
     IGBone.yDown = true; 

     m_skeleton = new IGSkeleton(skeletonData); 
     m_skeleton.updateWorldTransform(); 
     m_image = image; 
    } 

    protected override function render(g : IGGraphics) : void 
    { 
     m_skeleton.update(IGApplication.delta_time) ; 
     var drawOrder : Vector<IGSlot> = skeleton.drawOrder; 
     for (var i : int = 0; i < drawOrder.length; i++) 
     { 
      g.push(); 
      { 

       var slot : IGSlot = drawOrder[i]; 
       if (slot.attachment != null && slot.attachment.type != IGRegionAttachment.Region()) { continue; } 
       var regionAttachment : IGRegionAttachment = IGRegionAttachment(slot.attachment); 
       var wrapper : IGSpinePosition = m_wrappers[regionAttachment]; 
       if(regionAttachment != null) { 
        if (wrapper == null) 
        { 
         wrapper = new IGSpinePosition(); 
         var region : IGAtlasRegion = IGAtlasRegion(regionAttachment.rendererObject); 
         var regionHeight : double = region.rotate ? region.width : region.height; 
         var regionWidth : double = region.rotate ? region.height : region.width; 
         wrapper.x = region.x; 
         wrapper.y = region.y; 
         wrapper.height = regionHeight; 
         wrapper.width = regionWidth; 

         // Rotate and scale using default registration point (top left corner, y-down, cw) instead of image center 
         wrapper.affine.rotate(regionAttachment.rotation * Math.PI/180); //This rotates the position of the drawn object, but I need to be able to set the actual rotation instead of translating a rotation 
         wrapper.affine.scale(regionAttachment.scaleX * (regionAttachment.width/region.width), regionAttachment.scaleY * (regionAttachment.height/region.height)); 

         // Position using attachment translation, shifted as if scale and rotation were at image center 
         var radians : double = -regionAttachment.rotation * Math.PI/180; 
         var cos : double = Math.cos(radians); 
         var sin : double = Math.sin(radians); 
         var shiftX : double = -regionAttachment.width/2 * regionAttachment.scaleX; 
         var shiftY : double = -regionAttachment.height/2 * regionAttachment.scaleY; 
         if (region.rotate) 
         { 
          wrapper.affine.rotate(90); // Again, I need to += the rotation by 90 degrees, but I dont have that functionality 
          shiftX += regionHeight * (regionAttachment.width/region.width); 
         } 

         wrapper.affine.translate(0, 0);//(regionAttachment.x + shiftX * cos - shiftY * sin, -regionAttachment.y + shiftX * sin + shiftY * cos); 
         m_wrappers[regionAttachment] = wrapper; 
        } 

        var bone : IGBone = slot.bone; 
        var flipX : int = skeleton.flipX ? -1 : 1; 
        var flipY : int = skeleton.flipY ? -1 : 1; 

        //This is the key part. I need to be able to set the wrapper's affine2d's x and y position, the the rotation by angle (ie. rotation = someAngle) 
        //wrapper.affine.translate(bone.worldX, bone.worldY); 
        //wrapper.affine.rotate(bone.worldRotationX * flipX * flipY); 

        wrapper.scaleX = bone.worldScaleX * flipX; 
        wrapper.scaleY = bone.worldScaleY * flipY; 

        g.scale(wrapper.scaleX/4, wrapper.scaleY/4); 
        g.translate(1000, 1600); // Set the position of the widget 
        g.rotate(bone.worldRotationX * flipX * flipY); 
        g.multTransform(wrapper.affine); 
        g.drawSubImage(m_image, wrapper.x, wrapper.y, wrapper.width, wrapper.height, 0, 0, wrapper.width, wrapper.height); 
       } 
      } 
      g.pop(); 
     } 

    } 

    public function get skeleton() : IGSkeleton { 
     return m_skeleton; 
    } 
} 

그리고 이것은 Affine2d 클래스입니다 : 어떤 속도에서

, 여기에 (이것은 AS3 라이브러리에서 SkeletonSprite.as 클래스의 해제를 기반으로) 실제 척추 라이브러리 물건을 렌더링하는 내 코드입니다

package engine.math; 

public class IGAffine2D 
{ 
    ///////////////////////////////////////////////////////////////////// 
    // State 
    ///////////////////////////////////////////////////////////////////// 

    public var m0:double; 
    public var m1:double; 
    public var m2:double; 
    public var m3:double; 
    public var m4:double; 
    public var m5:double; 

    ///////////////////////////////////////////////////////////////////// 
    // Construction and Initialsation 
    ///////////////////////////////////////////////////////////////////// 
    public final function IGAffine2D() 
    { 
     this.init(); 
    } 


    public final function isIdentity() : bool 
    { 
     return m0 == 1 && m2 == 0 && m4 == 0 && 
       m1 == 0 && m3 == 1 && m5 == 0; 
    } 

    public final function init() : IGAffine2D 
    { 
     m0 = 1.0; 
     m1 = 0.0; 
     m2 = 0.0; 
     m3 = 1.0; 
     m4 = 0.0; 
     m5 = 0.0; 
     return this; 
    } 

    public final function initColumnMajor(
      a0 : double, a1 : double, a2 : double, 
      a3 : double, a4 : double, a5 : double) : IGAffine2D { 

     // represents the following 3x3 (2d affine) matrix 
     // m0 m2 m4 
     // m1 m3 m5 
     // 0 0 1 

     m0 = a0; 
     m1 = a1; 
     m2 = a2; 
     m3 = a3; 
     m4 = a4; 
     m5 = a5; 

     return this; 
    } 

    public final function initFromTransform(transform:IGAffine2D) : IGAffine2D 
    { 
     m0 = transform.m0; 
     m1 = transform.m1; 
     m2 = transform.m2; 
     m3 = transform.m3; 
     m4 = transform.m4; 
     m5 = transform.m5; 
     return this; 
    } 

    public final function initWithInverseFromTransform(other : IGAffine2D) : IGAffine2D 
    { 
     // this is 65 ops 
     var a : double= other.m0; 
     var b : double= other.m2; 
     var c : double= other.m1; 
     var d : double= other.m3; 

     var det_inv : double = 1.0/(a*d - b*c); 

     m0 = d * det_inv; 
     m1 = -c * det_inv; 
     m2 = -b * det_inv; 
     m3 = a * det_inv; 

     var x : double= other.m4; 
     var y : double= other.m5; 

     m4 = -(x * m0 + y * m2); 
     m5 = -(x * m1 + y * m3); 

     return this; 
    } 

    ////////////////////////////////////////////////////////////////////// 
    // Getting Properties of the Transform 
    ////////////////////////////////////////////////////////////////////// 
    public final function get translate_x() : double 
    { 
     return m4; 
    } 

    public final function get translate_y() : double 
    { 
     return m5; 
    } 

    public final function get scale_x() : double 
    { 
     return m0; 
    } 

    public final function get scale_y() : double 
    { 
     return m3; 
    } 

    /** 
    * Determines whether or not the translation applied by this matrix 
    * will result in the coordinate being integer bound for a point 
    * around the origin 
    **/ 
    public final function isIntegerTranslate() : bool 
    { 
     var tx : int = m4; 
     var ty : int = m5; 
     if (m0 == 1 && m1 == 0 && m2 == 0 && m3 == 1 && m4 == tx && m5 == ty) { 
      return true; 
     } 
     return false; 
    }  

    ////////////////////////////////////////////////////////////////////// 
    // Performing Transformations 
    ////////////////////////////////////////////////////////////////////// 
    public final function translate(dx:double, dy:double): void 
    { 
     m4 += (m0 * dx) + (m2 * dy); 
     m5 += (m1 * dx) + (m3 * dy); 

    } 

    public final function rotate (theta: double) : void 
    { 
     if(theta == 0) { 
      return; 
     } 

     var st :double = Math.sin(theta); 
     var ct :double = Math.cos(theta); 
     var r00 :double = (m0 * ct) + (m2 * st); 
     var r01 :double = (m0 * -st) + (m2 * ct); 
     var r02 :double = m4; 
     var r10 :double = (m1 * ct) + (m3 * st); 
     var r11 :double = (m1 * -st) + (m3 * ct); 
     var r12 :double = m5; 
     m0 = r00; 
     m2 = r01; 
     m4 = r02; 
     m1 = r10; 
     m3 = r11; 
     m5 = r12; 
    } 

    public final function scale(sx : double, sy : double) : void 
    { 
     m0 *= sx; 
     m1 *= sx; 

     m2 *= sy; 
     m3 *= sy; 
    } 

    // [m00 m01 m02] [1 shx 0] 
    // [m10 m11 m12] [shy 1 0] 
    // [ 0 0 1] [0 0 1] 
    public final function shear(shx:double, shy:double) : void 
    { 
     var r00 : double = m0  + m2 * shy; 
     var r01 : double = m0 * shx + m2; 
     var r02 : double = m4; 
     var r10 : double = m1  + m3 * shy; 
     var r11 : double = m1 * shx + m3; 
     var r12 : double = m5; 
     m0 = r00; 
     m2 = r01; 
     m4 = r02; 
     m1 = r10; 
     m3 = r11; 
     m5 = r12; 
    } 




    /** 
    * Performs a Translate/Scale/Rotate transformation around a pivot point. 
    * OPTIMIZED VERSION OF: 
    * - translate(dx + px, dy + py); 
    * - rotate(theta); 
    * - scale(sx, sy); 
    * - translate(-px, -py); 
    **/ 
    public final function TRS(dx : double, dy : double, 
         px : double, py : double, // positive pivot point 
         sx : double, sy : double, theta : double): IGAffine2D 
    { 
     // early abort for standard case 
     if (sx == 1.0 && sy == 1.0 && theta == 0) { 
      m4 += dx; 
      m5 += dy; 
      return this; 
     } 

     var l0 : double = m0; 
     var l1 : double = m1; 
     var l2 : double = m2; 
     var l3 : double = m3; 
     var l4 : double = m4 + (dx + px)*l0 + (dy + py)*l2; 
     var l5 : double = m5 + (dx + px)*l1 + (dy + py)*l3; 

     if (theta != 0) 
     { 
      var s : double = -Math.sin(theta); 
      var c : double = Math.cos(theta); 

      var r0 : double = c*sx; 
      var r1 : double = -s*sy; 
      var r2 : double = s*sx; 
      var r3 : double = c*sy; 

      m0 = l0 * r0 + l2 * r1; 
      m1 = l1 * r0 + l3 * r1; 

      m2 = l0 * r2 + l2 * r3; 
      m3 = l1 * r2 + l3 * r3; 

      m4 = l4 - m0 * px - m2 * py; 
      m5 = l5 - m1 * px - m3 * py; 
     } 
     else 
     { 
      m0 = l0 * sx ; 
      m1 = l1 * sx ; 
      m2 = l2 * sy; 
      m3 = l3 * sy; 

      m4 = l4 - (m0 * px) - (m2 * py); 
      m5 = l5 - (m1 * px) - (m3 * py); 
     } 

     return this; 
    } 


    public final function initFromTransformWithOffset(other : IGAffine2D, dx : double, dy : double) : IGAffine2D 
    { 
     m0 = other.m0; 
     m1 = other.m1; 
     m2 = other.m2; 
     m3 = other.m3; 
     m4 = other.m4 + dx * m0 + dy * m2; 
     m5 = other.m5 + dx * m1 + dy * m3; 
     return this; 
    } 

    public final function initFromTransformWithTRS(
         other : IGAffine2D, 
         dx : double, dy : double, 
         px : double, py : double, // positive pivot point 
         sx : double, sy : double, theta : double): IGAffine2D 
    { 

     var s :double = 0; 
     var c :double = 1; 

     if (theta != 0) 
     { 
      s = -Math.sin(theta); 
      c = Math.cos(theta); 
     } 

     var l0 : double = other.m0; 
     var l1 : double = other.m1; 
     var l2 : double = other.m2; 
     var l3 : double = other.m3; 
     var l4 : double = other.m4 + (dx + px)*l0 + (dy + py)*l2; 
     var l5 : double = other.m5 + (dx + px)*l1 + (dy + py)*l3; 

     var r0 : double = c*sx; 
     var r1 : double = -s*sy; 
     var r2 : double = s*sx; 
     var r3 : double = c*sy; 

     m0 = l0 * r0 + l2 * r1; 
     m1 = l1 * r0 + l3 * r1; 

     m2 = l0 * r2 + l2 * r3; 
     m3 = l1 * r2 + l3 * r3; 

     m4 = l4 - m0 * px - m2 * py; 
     m5 = l5 - m1 * px - m3 * py; 

     return this; 
    } 


    ////////////////////////////////////////////////////////////////////// 
    // Performing Other Operations 
    ////////////////////////////////////////////////////////////////////// 
    public final function invert(): IGAffine2D 
    { 
     var a : double= m0; 
     var b : double= m2; 
     var c : double= m1; 
     var d : double= m3; 

     var det_inv : double = 1.0/(a*d - b*c); 

     m0 = d * det_inv; 
     m1 = -c * det_inv; 
     m2 = -b * det_inv; 
     m3 = a * det_inv; 

     var x : double= m4; 
     var y : double= m5; 

     m4 = -x * m0 + -y * m2; 
     m5 = -x * m1 + -y * m3; 

     return this; 
    }  




    public final function concat(t : IGAffine2D): IGAffine2D 
    { 
     var r00 : double = (m0 * t.m0) + (m2 * t.m1); 
     var r01 : double = (m0 * t.m2) + (m2 * t.m3); 
     var r02 : double = (m0 * t.m4) + (m2 * t.m5) + m4; 
     var r10 : double = (m1 * t.m0) + (m3 * t.m1); 
     var r11 : double = (m1 * t.m2) + (m3 * t.m3); 
     var r12 : double = (m1 * t.m4) + (m3 * t.m5) + m5; 
     m0 = r00; 
     m2 = r01; 
     m4 = r02; 
     m1 = r10; 
     m3 = r11; 
     m5 = r12; 
     return this; 
    } 


    ////////////////////////////////////////////////////////////////////// 
    // 
    ////////////////////////////////////////////////////////////////////// 
    public final function transformVector2(pin : IGVector2, pout : IGVector2): void 
    { 
     var x:double = pin.x * m0 + pin.y * m2 + m4; 
     var y:double = pin.x * m1 + pin.y * m3 + m5; 
     pout.x = x; 
     pout.y = y; 
    } 


    public final function debug() : String 
    { 
     return m0 + " \t" + m2 + "\t" + m4 + "\n" + m1 + "\t" + m3 + "\t" + m5; 
    } 

} 

답변

0

알아 냈습니다. 위치를 기반으로 다시 그리기해야하는 각 호출에서, 나는 어파 인 좌표를 리셋 한 다음 변환하고 한 번 올바른 위치로 회전시킵니다.