Exemplo n.º 1
0
            /// <summary>
            /// Keyframe에 Rotation Bias 설정이 있는 경우 관련 변수를 갱신한다.
            /// </summary>
            /// <param name="rotationBias"></param>
            /// <param name="rotationCount"></param>
            public void SetAnimRotationBias(apAnimKeyframe.ROTATION_BIAS rotationBias, int rotationCount)
            {
                if (rotationBias == apAnimKeyframe.ROTATION_BIAS.CW)
                {
                    _isAnimRotationBias    = true;
                    _animRotationBiasAngle = -360 * rotationCount;
                }
                else if (rotationBias == apAnimKeyframe.ROTATION_BIAS.CCW)
                {
                    _isAnimRotationBias    = true;
                    _animRotationBiasAngle = 360 * rotationCount;
                }
                else
                {
                    _isAnimRotationBias    = false;
                    _animRotationBiasAngle = 0;
                }
                //에디터에서는 최적화가 아니라 언제 바뀔지 모르므로 항상 갱신
                //if(_animRotationBiasAngle_Prev != _animRotationBiasAngle && _isAnimRotationBias)
                if (_isAnimRotationBias)
                {
                    if (_animRotationBiasedMatrix == null)
                    {
                        _animRotationBiasedMatrix = new apMatrix();
                    }

                    if (_modifiedMesh != null)
                    {
                        _animRotationBiasedMatrix.SetTRS(
                            _modifiedMesh._transformMatrix._pos,
                            _modifiedMesh._transformMatrix._angleDeg + _animRotationBiasAngle,
                            _modifiedMesh._transformMatrix._scale
                            );
                    }
                    else if (_modifiedBone != null)
                    {
                        _animRotationBiasedMatrix.SetTRS(
                            _modifiedBone._transformMatrix._pos,
                            _modifiedBone._transformMatrix._angleDeg + _animRotationBiasAngle,
                            _modifiedBone._transformMatrix._scale
                            );
                    }
                    else
                    {
                        _animRotationBiasedMatrix.SetIdentity();
                    }

                    _animRotationBiasAngle_Prev = _animRotationBiasAngle;
                }
            }
        // 4) World Matrix를 만든다.
        // 이 함수는 Parent의 MeshGroupTransform이 연산된 후 -> Vertex가 연산되기 전에 호출되어야 한다.
        public void MakeWorldMatrix(bool isRecursive)
        {
            _localMatrix.SetIdentity();
            _localMatrix._pos      = _deltaPos;
            _localMatrix._angleDeg = _deltaAngle;
            _localMatrix._scale.x  = _deltaScale.x;
            _localMatrix._scale.y  = _deltaScale.y;

            _localMatrix.MakeMatrix();

            //World Matrix = ParentMatrix x LocalMatrix
            //Root인 경우에는 MeshGroup의 Matrix를 이용하자

            //_invWorldMatrix_NonModified.SetIdentity();

            if (_parentBone == null)
            {
                _worldMatrix.SetMatrix(_defaultMatrix);
                _worldMatrix.Add(_localMatrix);

                _worldMatrix_NonModified.SetMatrix(_defaultMatrix);                //Local Matrix 없이 Default만 지정


                if (_parentOptTransform != null)
                {
                    //Debug.Log("SetParentOptTransform Matrix : [" + _parentOptTransform.transform.name + "] : " + _parentOptTransform._matrix_TFResult_World.Scale2);
                    //Non Modified도 동일하게 적용
                    //렌더유닛의 WorldMatrix를 넣어주자
                    _worldMatrix.RMultiply(_parentOptTransform._matrix_TFResult_World);                    //RenderUnit의 WorldMatrixWrap의 Opt 버전

                    _worldMatrix_NonModified.RMultiply(_parentOptTransform._matrix_TFResult_WorldWithoutMod);
                }
            }
            else
            {
                _worldMatrix.SetMatrix(_defaultMatrix);
                _worldMatrix.Add(_localMatrix);
                _worldMatrix.RMultiply(_parentBone._worldMatrix);

                _worldMatrix_NonModified.SetMatrix(_defaultMatrix);                //Local Matrix 없이 Default만 지정
                _worldMatrix_NonModified.RMultiply(_parentBone._worldMatrix_NonModified);
            }


            //처리된 TRS
            _updatedWorldPos_NoRequest.x = _worldMatrix._pos.x;
            _updatedWorldPos_NoRequest.y = _worldMatrix._pos.y;

            _updatedWorldAngle_NoRequest = _worldMatrix._angleDeg;

            _updatedWorldScale_NoRequest.x = _worldMatrix._scale.x;
            _updatedWorldScale_NoRequest.y = _worldMatrix._scale.y;

            _updatedWorldPos   = _updatedWorldPos_NoRequest;
            _updatedWorldAngle = _updatedWorldAngle_NoRequest;
            _updatedWorldScale = _updatedWorldScale_NoRequest;


            if (_isIKCalculated)
            {
                _IKRequestAngleResult -= 90.0f;
                while (_IKRequestAngleResult > 180.0f)
                {
                    _IKRequestAngleResult -= 360.0f;
                }
                while (_IKRequestAngleResult < -180.0f)
                {
                    _IKRequestAngleResult += 360.0f;
                }

                //_updatedWorldAngle += _IKRequestAngleResult * _IKRequestWeight;
                _updatedWorldAngle = _updatedWorldAngle * (1.0f - _IKRequestWeight) + (_IKRequestAngleResult * _IKRequestWeight);
                //Debug.Log("Add IK [" + _name + "] : " + _IKRequestAngleResult);

                _IKRequestAngleResult = 0.0f;
                _IKRequestWeight      = 0.0f;
            }



            //스크립트로 외부에서 제어한 경우
            if (_isExternalUpdate_Position)
            {
                _updatedWorldPos.x = (_exUpdate_Pos.x * _externalUpdateWeight) + (_updatedWorldPos.x * (1.0f - _externalUpdateWeight));
                _updatedWorldPos.y = (_exUpdate_Pos.y * _externalUpdateWeight) + (_updatedWorldPos.y * (1.0f - _externalUpdateWeight));
            }

            if (_isExternalUpdate_Rotation)
            {
                _updatedWorldAngle = (_exUpdate_Angle * _externalUpdateWeight) + (_updatedWorldAngle * (1.0f - _externalUpdateWeight));
            }

            if (_isExternalUpdate_Scaling)
            {
                _updatedWorldScale.x = (_exUpdate_Scale.x * _externalUpdateWeight) + (_updatedWorldScale.x * (1.0f - _externalUpdateWeight));
                _updatedWorldScale.y = (_exUpdate_Scale.y * _externalUpdateWeight) + (_updatedWorldScale.y * (1.0f - _externalUpdateWeight));
            }

            if (_isIKCalculated || _isExternalUpdate_Position || _isExternalUpdate_Rotation || _isExternalUpdate_Scaling)
            {
                //WorldMatrix를 갱신해주자
                _worldMatrix.SetTRS(_updatedWorldPos.x, _updatedWorldPos.y,
                                    _updatedWorldAngle,
                                    _updatedWorldScale.x, _updatedWorldScale.y);

                _isIKCalculated            = false;
                _isExternalUpdate_Position = false;
                _isExternalUpdate_Rotation = false;
                _isExternalUpdate_Scaling  = false;
            }



            //World Matrix는 MeshGroup과 동일한 Space의 값을 가진다.
            //그러나 실제로 Bone World Matrix는
            //Root - MeshGroup...(Rec) - Bone Group - Bone.. (Rec <- 여기)
            //의 레벨을 가진다.
            //Root 밑으로는 모두 World에 대해서 동일한 Space를 가지므로
            //Root를 찾아서 Scale을 제어하자...?
            //일단 Parent에서 빼두자
            //_transformLocalMatrix.SetMatrix(_worldMatrix);


#if UNITY_EDITOR
            _shapePoint_End = new Vector2(0.0f, _shapeLength);


            _shapePoint_Mid1 = new Vector2(-_shapeWidth * 0.5f, _shapeLength * 0.2f);
            _shapePoint_Mid2 = new Vector2(_shapeWidth * 0.5f, _shapeLength * 0.2f);

            float taperRatio = Mathf.Clamp01((float)(100 - _shapeTaper) / 100.0f);

            _shapePoint_End1 = new Vector2(-_shapeWidth * 0.5f * taperRatio, _shapeLength);
            _shapePoint_End2 = new Vector2(_shapeWidth * 0.5f * taperRatio, _shapeLength);

            _shapePoint_End  = _worldMatrix.MtrxToSpace.MultiplyPoint(_shapePoint_End);
            _shapePoint_Mid1 = _worldMatrix.MtrxToSpace.MultiplyPoint(_shapePoint_Mid1);
            _shapePoint_Mid2 = _worldMatrix.MtrxToSpace.MultiplyPoint(_shapePoint_Mid2);
            _shapePoint_End1 = _worldMatrix.MtrxToSpace.MultiplyPoint(_shapePoint_End1);
            _shapePoint_End2 = _worldMatrix.MtrxToSpace.MultiplyPoint(_shapePoint_End2);
#endif


            //Rigging을 위해서 Matrix 통합 식을 만들자
            //실제 식
            // world * default_inv * VertPos W
            _vertWorld2BoneModWorldMatrix  = _worldMatrix.MtrxToSpace;
            _vertWorld2BoneModWorldMatrix *= _worldMatrix_NonModified.MtrxToLowerSpace;



            if (_socketTransform != null)
            {
                //소켓을 업데이트 하자
                _socketTransform.localPosition = new Vector3(_worldMatrix._pos.x, _worldMatrix._pos.y, 0);
                _socketTransform.localRotation = Quaternion.Euler(0.0f, 0.0f, _worldMatrix._angleDeg);
                _socketTransform.localScale    = new Vector3(_worldMatrix._scale.x, _worldMatrix._scale.y, 1.0f);
            }

            //Child도 호출해준다.
            if (isRecursive && _childBones != null)
            {
                for (int i = 0; i < _childBones.Length; i++)
                {
                    _childBones[i].MakeWorldMatrix(true);
                }
            }
        }
        /// <summary>
        /// CalculateStack을 업데이트 한다.
        /// Pre-Update이다. Rigging, VertWorld는 제외된다.
        /// </summary>
        public void UpdateCalculate_Pre()
        {
//#if UNITY_EDITOR
//			Profiler.BeginSample("Transform - 1. Stack Calculate");
//#endif

            //1. Calculated Stack 업데이트
            if (_calculatedStack != null)
            {
                _calculatedStack.Calculate_Pre();
            }

//#if UNITY_EDITOR
//			Profiler.EndSample();
//#endif


//#if UNITY_EDITOR
//			Profiler.BeginSample("Transform - 2. Matrix / Color");
//#endif

            //2. Calculated의 값 적용 + 계층적 Matrix 적용
            if (CalculatedStack.MeshWorldMatrixWrap != null)
            {
                //변경전
                //_calclateTmpMatrix.SRMultiply(_calculatedStack.MeshWorldMatrixWrap, true);
                //_matrix_TF_Cal_ToWorld = _calculateTmpMatrix.MtrxToSpace;

                //변경후
                _matrix_TF_LocalModified.SetMatrix(_calculatedStack.MeshWorldMatrixWrap);

                //if(_calculatedStack.MeshWorldMatrixWrap.Scale2.magnitude < 0.8f)
                //{
                //	Debug.Log(name + " : Low Scale : " + _calculatedStack.MeshWorldMatrixWrap.Scale2);
                //}
            }

            if (CalculatedStack.IsAnyColorCalculated)
            {
                _meshColor2X          = CalculatedStack.MeshColor;
                _isVisible            = CalculatedStack.IsMeshVisible;
                _isAnyColorCalculated = true;
            }
            else
            {
                _meshColor2X = _meshColor2X_Default;
                _isVisible   = _isVisible_Default;
            }
            if (!_isVisible)
            {
                _meshColor2X.a        = 0.0f;
                _isAnyColorCalculated = true;
            }


            if (_parentTransform != null)
            {
                //변경 전
                //_calculateTmpMatrix.SRMultiply(_parentTransform.CalculatedTmpMatrix, true);
                //_matrix_TF_Cal_ToWorld = _calculateTmpMatrix.MtrxToSpace;

                //변경 후
                _matrix_TF_ParentWorld.SetMatrix(_parentTransform._matrix_TFResult_World);
                _matrix_TF_ParentWorld_NonModified.SetMatrix(_parentTransform._matrix_TFResult_WorldWithoutMod);

                //색상은 2X 방식의 Add
                _meshColor2X.r  = Mathf.Clamp01(((float)(_meshColor2X.r) - 0.5f) + ((float)(_parentTransform._meshColor2X.r) - 0.5f) + 0.5f);
                _meshColor2X.g  = Mathf.Clamp01(((float)(_meshColor2X.g) - 0.5f) + ((float)(_parentTransform._meshColor2X.g) - 0.5f) + 0.5f);
                _meshColor2X.b  = Mathf.Clamp01(((float)(_meshColor2X.b) - 0.5f) + ((float)(_parentTransform._meshColor2X.b) - 0.5f) + 0.5f);
                _meshColor2X.a *= _parentTransform._meshColor2X.a;

                if (_parentTransform._isAnyColorCalculated)
                {
                    _isAnyColorCalculated = true;
                }
            }

            if (_meshColor2X.a < VISIBLE_ALPHA
                //|| !CalculatedStack.IsMeshVisible
                )
            {
                _isVisible            = false;
                _meshColor2X.a        = 0.0f;
                _isAnyColorCalculated = true;
            }

            //MakeTransformMatrix(); < 이 함수 부분
            //World Matrix를 만든다.
            _matrix_TFResult_World.RMultiply(_matrix_TF_ToParent);            //변경 : ToParent -> LocalModified -> ParentWorld 순으로 바꾼다.
            _matrix_TFResult_World.RMultiply(_matrix_TF_LocalModified);       //<<[R]


            //_matrix_TFResult_World.RMultiply(_matrix_TF_ToParent);//<<[R]

            _matrix_TFResult_World.RMultiply(_matrix_TF_ParentWorld);            //<<[R]

            //_matrix_TFResult_WorldWithoutMod.SRMultiply(_matrix_TF_ToParent, true);//ToParent는 넣지 않는다.
            //_matrix_TFResult_WorldWithoutMod.SRMultiply(_matrix_TF_ParentWorld, true);//<<[SR]

            //Without Mod는 계산하지 않았을 경우에만 계산한다.
            //바뀌지 않으므로
            if (!_isCalculateWithoutMod)
            {
                _matrix_TFResult_WorldWithoutMod.RMultiply(_matrix_TF_ToParent);                //<<[R]
                _matrix_TFResult_WorldWithoutMod.RMultiply(_matrix_TF_ParentWorld_NonModified); //<<[R]


                //리깅용 단축식을 추가한다.
                if (_childMesh != null)
                {
                    _vertLocal2MeshWorldMatrix  = _matrix_TFResult_WorldWithoutMod.MtrxToSpace;
                    _vertLocal2MeshWorldMatrix *= _childMesh._matrix_Vert2Mesh;

                    _vertWorld2MeshLocalMatrix  = _childMesh._matrix_Vert2Mesh_Inverse;
                    _vertWorld2MeshLocalMatrix *= _matrix_TFResult_WorldWithoutMod.MtrxToLowerSpace;

                    _vertMeshWorldNoModMatrix        = _matrix_TFResult_WorldWithoutMod.MtrxToSpace;
                    _vertMeshWorldNoModInverseMatrix = _matrix_TFResult_WorldWithoutMod.MtrxToLowerSpace;
                }

                _isCalculateWithoutMod = true;
            }



            //처리된 TRS
            _updatedWorldPos_NoRequest.x = _matrix_TFResult_World._pos.x;
            _updatedWorldPos_NoRequest.y = _matrix_TFResult_World._pos.y;

            _updatedWorldAngle_NoRequest = _matrix_TFResult_World._angleDeg;

            _updatedWorldScale_NoRequest.x = _matrix_TFResult_World._scale.x;
            _updatedWorldScale_NoRequest.y = _matrix_TFResult_World._scale.y;

            _updatedWorldPos   = _updatedWorldPos_NoRequest;
            _updatedWorldAngle = _updatedWorldAngle_NoRequest;
            _updatedWorldScale = _updatedWorldScale_NoRequest;



            //스크립트로 외부에서 제어한 경우
            if (_isExternalUpdate_Position)
            {
                _updatedWorldPos.x = (_exUpdate_Pos.x * _externalUpdateWeight) + (_updatedWorldPos.x * (1.0f - _externalUpdateWeight));
                _updatedWorldPos.y = (_exUpdate_Pos.y * _externalUpdateWeight) + (_updatedWorldPos.y * (1.0f - _externalUpdateWeight));
            }

            if (_isExternalUpdate_Rotation)
            {
                _updatedWorldAngle = (_exUpdate_Angle * _externalUpdateWeight) + (_updatedWorldAngle * (1.0f - _externalUpdateWeight));
            }

            if (_isExternalUpdate_Scaling)
            {
                _updatedWorldScale.x = (_exUpdate_Scale.x * _externalUpdateWeight) + (_updatedWorldScale.x * (1.0f - _externalUpdateWeight));
                _updatedWorldScale.y = (_exUpdate_Scale.y * _externalUpdateWeight) + (_updatedWorldScale.y * (1.0f - _externalUpdateWeight));
            }

            if (_isExternalUpdate_Position || _isExternalUpdate_Rotation || _isExternalUpdate_Scaling)
            {
                //WorldMatrix를 갱신해주자
                _matrix_TFResult_World.SetTRS(_updatedWorldPos.x, _updatedWorldPos.y,
                                              _updatedWorldAngle,
                                              _updatedWorldScale.x, _updatedWorldScale.y);

                _isExternalUpdate_Position = false;
                _isExternalUpdate_Rotation = false;
                _isExternalUpdate_Scaling  = false;
            }



            //추가 : 소켓도 만들어준다.
            //Vert World를 아직 계산하지 않았지만 Socket 처리에는 문제가 없다.
            if (_socketTransform != null)
            {
                _socketTransform.localPosition = new Vector3(_matrix_TFResult_World._pos.x, _matrix_TFResult_World._pos.y, 0);
                _socketTransform.localRotation = Quaternion.Euler(0.0f, 0.0f, _matrix_TFResult_World._angleDeg);
                _socketTransform.localScale    = new Vector3(_matrix_TFResult_World._scale.x, _matrix_TFResult_World._scale.y, 1.0f);
            }

//#if UNITY_EDITOR
//			Profiler.EndSample();
//#endif


            //[MeshUpdate]는 Post Update로 전달

            //3. 자식 호출
            //자식 객체도 업데이트를 한다.
            if (_childTransforms != null)
            {
                for (int i = 0; i < _childTransforms.Length; i++)
                {
                    _childTransforms[i].UpdateCalculate_Pre();
                }
            }
        }
Exemplo n.º 4
0
            /// <summary>
            /// Keyframe에 Rotation Bias 설정이 있는 경우 관련 변수를 갱신한다.
            /// </summary>
            /// <param name="rotationBias"></param>
            /// <param name="rotationCount"></param>
            public void SetAnimRotationBias(apAnimKeyframe.ROTATION_BIAS rotationBias, int rotationCount)
            {
                if (rotationBias == apAnimKeyframe.ROTATION_BIAS.CW)
                {
                    _isAnimRotationBias    = true;
                    _animRotationBiasAngle = -360 * rotationCount;
                }
                else if (rotationBias == apAnimKeyframe.ROTATION_BIAS.CCW)
                {
                    _isAnimRotationBias    = true;
                    _animRotationBiasAngle = 360 * rotationCount;
                }
                else
                {
                    _isAnimRotationBias    = false;
                    _animRotationBiasAngle = 0;
                }
                if (_animRotationBiasAngle_Prev != _animRotationBiasAngle && _isAnimRotationBias)
                {
                    if (_animRotationBiasedMatrix == null)
                    {
                        _animRotationBiasedMatrix = new apMatrix();
                    }

                    if (_modifiedMesh != null)
                    {
                        _animRotationBiasedMatrix.SetTRS(
                            _modifiedMesh._transformMatrix._pos,
                            _modifiedMesh._transformMatrix._angleDeg + _animRotationBiasAngle,
                            _modifiedMesh._transformMatrix._scale
                            );
                    }
                    else if (_modifiedMeshSet != null)
                    {
                        //추가됨 19.5.24 : ModMeshSet으로 계산하기
                        _subModMesh_Transform = _modifiedMeshSet.SubModMesh_Transform;
                        if (_subModMesh_Transform != null)
                        {
                            _animRotationBiasedMatrix.SetTRS(
                                _subModMesh_Transform._transformMatrix._pos,
                                _subModMesh_Transform._transformMatrix._angleDeg + _animRotationBiasAngle,
                                _subModMesh_Transform._transformMatrix._scale
                                );
                        }
                        else
                        {
                            Debug.LogError("TODO : 에러 : 애니메이션에 SubModMeshSet_Transform이 없다.");
                            _animRotationBiasedMatrix.SetIdentity();
                        }
                    }
                    else if (_modifiedBone != null)
                    {
                        _animRotationBiasedMatrix.SetTRS(
                            _modifiedBone._transformMatrix._pos,
                            _modifiedBone._transformMatrix._angleDeg + _animRotationBiasAngle,
                            _modifiedBone._transformMatrix._scale
                            );
                    }
                    else
                    {
                        _animRotationBiasedMatrix.SetIdentity();
                    }

                    _animRotationBiasAngle_Prev = _animRotationBiasAngle;
                }
            }
Exemplo n.º 5
0
        // File To Bone
        //---------------------------------------------------
        public bool DecodeData(string strSrc)
        {
            try
            {
                if (strSrc.Length < 3)
                {
                    return(false);
                }
                int nName = int.Parse(strSrc.Substring(0, 3));
                _name = strSrc.Substring(3, nName);

                strSrc = strSrc.Substring(3 + nName);

                //나머지는 델리미터를 이용한다.
                string[] strUnits = strSrc.Split(new string[] { "/" }, StringSplitOptions.None);
                int      iStr     = 0;
                _unitID = int.Parse(strUnits[iStr]);
                iStr++;

                _parentUnitID = int.Parse(strUnits[iStr]);
                iStr++;

                _level = int.Parse(strUnits[iStr]);
                iStr++;

                _depth = int.Parse(strUnits[iStr]);
                iStr++;

                _childUnitID.Clear();
                int nChild = int.Parse(strUnits[iStr]);
                iStr++;

                for (int i = 0; i < nChild; i++)
                {
                    _childUnitID.Add(int.Parse(strUnits[iStr]));
                    iStr++;
                }

                _defaultMatrix.SetIdentity();
                _defaultMatrix.SetTRS(
                    new Vector2(float.Parse(strUnits[iStr]), float.Parse(strUnits[iStr + 1])),
                    float.Parse(strUnits[iStr + 2]),
                    new Vector2(float.Parse(strUnits[iStr + 3]), float.Parse(strUnits[iStr + 4]))
                    );

                iStr += 5;

                _color.r = float.Parse(strUnits[iStr]);
                _color.g = float.Parse(strUnits[iStr + 1]);
                _color.b = float.Parse(strUnits[iStr + 2]);
                _color.a = float.Parse(strUnits[iStr + 3]);
                iStr    += 4;

                _shapeWidth  = int.Parse(strUnits[iStr]);
                _shapeLength = int.Parse(strUnits[iStr + 1]);
                _shapeTaper  = int.Parse(strUnits[iStr + 2]);
                iStr        += 3;

                _optionIK = (apBone.OPTION_IK) int.Parse(strUnits[iStr]);
                _isIKTail = (int.Parse(strUnits[iStr + 1]) == 1) ? true : false;
                iStr     += 2;

                _IKTargetBoneUnitID      = int.Parse(strUnits[iStr]);
                _IKNextChainedBoneUnitID = int.Parse(strUnits[iStr + 1]);
                _IKHeaderBoneUnitID      = int.Parse(strUnits[iStr + 2]);
                iStr += 3;

                _isIKAngleRange     = (int.Parse(strUnits[iStr]) == 1) ? true : false;
                _IKAngleRange_Lower = float.Parse(strUnits[iStr + 1]);
                _IKAngleRange_Upper = float.Parse(strUnits[iStr + 2]);
                _IKAnglePreferred   = float.Parse(strUnits[iStr + 3]);
                iStr += 4;

                _isSocketEnabled = (int.Parse(strUnits[iStr]) == 1) ? true : false;

                _isImportEnabled = true;
                _isIKEnabled     = true;
                _isShapeEnabled  = true;
            }
            catch (Exception ex)
            {
                Debug.LogError("Decode Exception : " + ex);
                return(false);
            }


            return(true);
        }
Exemplo n.º 6
0
        /// <summary>
        /// CalculateStack을 업데이트 한다.
        /// Pre-Update이다. Rigging, VertWorld는 제외된다.
        /// </summary>
        public void UpdateCalculate_Pre()
        {
//#if UNITY_EDITOR
//			Profiler.BeginSample("Transform - 1. Stack Calculate");
//#endif

            //1. Calculated Stack 업데이트
            if (_calculatedStack != null)
            {
                _calculatedStack.Calculate_Pre();
            }

//#if UNITY_EDITOR
//			Profiler.EndSample();
//#endif


//#if UNITY_EDITOR
//			Profiler.BeginSample("Transform - 2. Matrix / Color");
//#endif

            //2. Calculated의 값 적용 + 계층적 Matrix 적용
            if (CalculatedStack.MeshWorldMatrixWrap != null)
            {
                //변경전
                //_calclateTmpMatrix.SRMultiply(_calculatedStack.MeshWorldMatrixWrap, true);
                //_matrix_TF_Cal_ToWorld = _calculateTmpMatrix.MtrxToSpace;

                //변경후
                _matrix_TF_LocalModified.SetMatrix(_calculatedStack.MeshWorldMatrixWrap);

                //if(_calculatedStack.MeshWorldMatrixWrap.Scale2.magnitude < 0.8f)
                //{
                //	Debug.Log(name + " : Low Scale : " + _calculatedStack.MeshWorldMatrixWrap.Scale2);
                //}
            }

            if (CalculatedStack.IsAnyColorCalculated)
            {
                _meshColor2X          = CalculatedStack.MeshColor;
                _isVisible            = CalculatedStack.IsMeshVisible;
                _isAnyColorCalculated = true;
            }
            else
            {
                _meshColor2X = _meshColor2X_Default;
                _isVisible   = _isVisible_Default;
            }
            if (!_isVisible)
            {
                _meshColor2X.a        = 0.0f;
                _isAnyColorCalculated = true;
            }


            //추가 11.30 : Extra Option
            if (_calculatedStack.IsExtraDepthChanged)
            {
                if (_func_ExtraDepthChanged != null)
                {
                    _func_ExtraDepthChanged(this, _calculatedStack.ExtraDeltaDepth);
                }
            }
            if (_calculatedStack.IsExtraTextureChanged)
            {
                _isExtraTextureChanged = true;
                _extraTextureData      = _calculatedStack.ExtraTextureData;
                if (_extraTextureData == null)
                {
                    _isExtraTextureChanged = false;
                }
            }

            if (_isExtraTextureChanged_Prev != _isExtraTextureChanged ||
                _extraTextureData_Prev != _extraTextureData)
            {
#if UNITY_EDITOR
                if (Application.isPlaying)
                {
#endif
                //Extra-Texture 이벤트가 발생하거나 해지되어서 상태가 바뀌었을 경우
                //또는 새로운 텍스쳐가 발생했을 경우
                if (_childMesh != null)
                {
                    if (_isExtraTextureChanged)
                    {
                        //> 텍스쳐 교체 이벤트가 발생했다.
                        //현재 처리중인 텍스쳐를 먼저 저장한 뒤, 교체
                        _extraDefaultTexture = _childMesh.GetCurrentProcessedTexture();
                        _childMesh.SetExtraChangedTexture(_extraTextureData._texture);
                    }
                    else
                    {
                        //>텍스쳐를 해지해야한다. 저장했던 값으로 되돌린다.
                        _childMesh.SetExtraChangedTexture(_extraDefaultTexture);
                    }
                }
#if UNITY_EDITOR
            }
#endif
                _isExtraTextureChanged_Prev = _isExtraTextureChanged;
                if (_isExtraTextureChanged)
                {
                    _extraTextureData_Prev = _extraTextureData;
                }
                else
                {
                    _extraTextureData_Prev = null;
                }
            }



            if (_parentTransform != null)
            {
                //변경 전
                //_calculateTmpMatrix.SRMultiply(_parentTransform.CalculatedTmpMatrix, true);
                //_matrix_TF_Cal_ToWorld = _calculateTmpMatrix.MtrxToSpace;

                //변경 후
                _matrix_TF_ParentWorld.SetMatrix(_parentTransform._matrix_TFResult_World);
                _matrix_TF_ParentWorld_NonModified.SetMatrix(_parentTransform._matrix_TFResult_WorldWithoutMod);

                //색상은 2X 방식의 Add
                _meshColor2X.r  = Mathf.Clamp01(((float)(_meshColor2X.r) - 0.5f) + ((float)(_parentTransform._meshColor2X.r) - 0.5f) + 0.5f);
                _meshColor2X.g  = Mathf.Clamp01(((float)(_meshColor2X.g) - 0.5f) + ((float)(_parentTransform._meshColor2X.g) - 0.5f) + 0.5f);
                _meshColor2X.b  = Mathf.Clamp01(((float)(_meshColor2X.b) - 0.5f) + ((float)(_parentTransform._meshColor2X.b) - 0.5f) + 0.5f);
                _meshColor2X.a *= _parentTransform._meshColor2X.a;

                if (_parentTransform._isAnyColorCalculated)
                {
                    _isAnyColorCalculated = true;
                }
            }

            if (_meshColor2X.a < VISIBLE_ALPHA
                //|| !CalculatedStack.IsMeshVisible
                )
            {
                _isVisible            = false;
                _meshColor2X.a        = 0.0f;
                _isAnyColorCalculated = true;
            }

            //MakeTransformMatrix(); < 이 함수 부분
            //World Matrix를 만든다.
            _matrix_TFResult_World.RMultiply(_matrix_TF_ToParent);            //변경 : ToParent -> LocalModified -> ParentWorld 순으로 바꾼다.
            _matrix_TFResult_World.RMultiply(_matrix_TF_LocalModified);       //<<[R]


            //_matrix_TFResult_World.RMultiply(_matrix_TF_ToParent);//<<[R]

            _matrix_TFResult_World.RMultiply(_matrix_TF_ParentWorld);            //<<[R]

            //_matrix_TFResult_WorldWithoutMod.SRMultiply(_matrix_TF_ToParent, true);//ToParent는 넣지 않는다.
            //_matrix_TFResult_WorldWithoutMod.SRMultiply(_matrix_TF_ParentWorld, true);//<<[SR]

            //Without Mod는 계산하지 않았을 경우에만 계산한다.
            //바뀌지 않으므로
            if (!_isCalculateWithoutMod)
            {
                _matrix_TFResult_WorldWithoutMod.RMultiply(_matrix_TF_ToParent);                //<<[R]
                _matrix_TFResult_WorldWithoutMod.RMultiply(_matrix_TF_ParentWorld_NonModified); //<<[R]


                //리깅용 단축식을 추가한다.
                if (_childMesh != null)
                {
                    _vertLocal2MeshWorldMatrix  = _matrix_TFResult_WorldWithoutMod.MtrxToSpace;
                    _vertLocal2MeshWorldMatrix *= _childMesh._matrix_Vert2Mesh;

                    _vertWorld2MeshLocalMatrix  = _childMesh._matrix_Vert2Mesh_Inverse;
                    _vertWorld2MeshLocalMatrix *= _matrix_TFResult_WorldWithoutMod.MtrxToLowerSpace;

                    _vertMeshWorldNoModMatrix        = _matrix_TFResult_WorldWithoutMod.MtrxToSpace;
                    _vertMeshWorldNoModInverseMatrix = _matrix_TFResult_WorldWithoutMod.MtrxToLowerSpace;
                }

                _isCalculateWithoutMod = true;
            }

            //_convert2TargetMatrix4x4 = Matrix4x4.identity;
            //_convert2TargetMatrix3x3 = apMatrix3x3.identity;
            _isCamOrthoCorrection = false;
            if (_portrait._billboardType != apPortrait.BILLBOARD_TYPE.None && _childMesh != null)
            {
                Camera curCamera = _portrait.GetCamera();
                if (curCamera != null && !curCamera.orthographic)
                {
                    //Perspective 카메라라면

                    Vector3 pos_Cam = curCamera.worldToCameraMatrix.MultiplyPoint3x4(_childMesh.transform.position);
                    //Vector3 pos_Cam = (curCamera.worldToCameraMatrix * transform.localToWorldMatrix).MultiplyPoint3x4(new Vector3(_matrix_TFResult_World._pos.x, _matrix_TFResult_World._pos.y, 0));
                    float zDepth = pos_Cam.z;
                    float zRatio = zDepth / _portrait.GetZDepth();


                    //Debug.Log("pos_Cam : " + pos_Cam + " / " + zRatio);
                    //transform.tr//>>TODO
                    _isCamOrthoCorrection = true;

                    Matrix4x4 orthoConvertMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(zRatio, zRatio, 1));
                    _convert2TargetMatrix4x4 = _childMesh.transform.worldToLocalMatrix * curCamera.cameraToWorldMatrix * orthoConvertMatrix * curCamera.worldToCameraMatrix * _childMesh.transform.localToWorldMatrix;

                    _convert2TargetMatrix3x3      = apMatrix3x3.identity;
                    _convert2TargetMatrix3x3._m00 = _convert2TargetMatrix4x4.m00;
                    _convert2TargetMatrix3x3._m01 = _convert2TargetMatrix4x4.m01;
                    _convert2TargetMatrix3x3._m02 = _convert2TargetMatrix4x4.m03;

                    _convert2TargetMatrix3x3._m10 = _convert2TargetMatrix4x4.m10;
                    _convert2TargetMatrix3x3._m11 = _convert2TargetMatrix4x4.m11;
                    _convert2TargetMatrix3x3._m12 = _convert2TargetMatrix4x4.m13;

                    _convert2TargetMatrix3x3._m20 = _convert2TargetMatrix4x4.m30;
                    _convert2TargetMatrix3x3._m21 = _convert2TargetMatrix4x4.m31;
                    _convert2TargetMatrix3x3._m22 = _convert2TargetMatrix4x4.m23;

                    //Debug.Log("_convert2TargetMatrix4x4 : \n " + _convert2TargetMatrix4x4.ToString() + "\n" + "_convert2TargetMatrix3x3 : \n " + _convert2TargetMatrix3x3.ToString());
                }
            }


            //처리된 TRS
            _updatedWorldPos_NoRequest.x = _matrix_TFResult_World._pos.x;
            _updatedWorldPos_NoRequest.y = _matrix_TFResult_World._pos.y;

            _updatedWorldAngle_NoRequest = _matrix_TFResult_World._angleDeg;

            _updatedWorldScale_NoRequest.x = _matrix_TFResult_World._scale.x;
            _updatedWorldScale_NoRequest.y = _matrix_TFResult_World._scale.y;

            _updatedWorldPos   = _updatedWorldPos_NoRequest;
            _updatedWorldAngle = _updatedWorldAngle_NoRequest;
            _updatedWorldScale = _updatedWorldScale_NoRequest;



            //스크립트로 외부에서 제어한 경우
            if (_isExternalUpdate_Position)
            {
                _updatedWorldPos.x = (_exUpdate_Pos.x * _externalUpdateWeight) + (_updatedWorldPos.x * (1.0f - _externalUpdateWeight));
                _updatedWorldPos.y = (_exUpdate_Pos.y * _externalUpdateWeight) + (_updatedWorldPos.y * (1.0f - _externalUpdateWeight));
            }

            if (_isExternalUpdate_Rotation)
            {
                _updatedWorldAngle = (_exUpdate_Angle * _externalUpdateWeight) + (_updatedWorldAngle * (1.0f - _externalUpdateWeight));
            }

            if (_isExternalUpdate_Scaling)
            {
                _updatedWorldScale.x = (_exUpdate_Scale.x * _externalUpdateWeight) + (_updatedWorldScale.x * (1.0f - _externalUpdateWeight));
                _updatedWorldScale.y = (_exUpdate_Scale.y * _externalUpdateWeight) + (_updatedWorldScale.y * (1.0f - _externalUpdateWeight));
            }

            if (_isExternalUpdate_Position || _isExternalUpdate_Rotation || _isExternalUpdate_Scaling)
            {
                //WorldMatrix를 갱신해주자
                _matrix_TFResult_World.SetTRS(_updatedWorldPos.x, _updatedWorldPos.y,
                                              _updatedWorldAngle,
                                              _updatedWorldScale.x, _updatedWorldScale.y);

                _isExternalUpdate_Position = false;
                _isExternalUpdate_Rotation = false;
                _isExternalUpdate_Scaling  = false;
            }



            //추가 : 소켓도 만들어준다.
            //Vert World를 아직 계산하지 않았지만 Socket 처리에는 문제가 없다.
            if (_socketTransform != null)
            {
                _socketTransform.localPosition = new Vector3(_matrix_TFResult_World._pos.x, _matrix_TFResult_World._pos.y, 0);
                _socketTransform.localRotation = Quaternion.Euler(0.0f, 0.0f, _matrix_TFResult_World._angleDeg);
                _socketTransform.localScale    = new Vector3(_matrix_TFResult_World._scale.x, _matrix_TFResult_World._scale.y, 1.0f);
            }

//#if UNITY_EDITOR
//			Profiler.EndSample();
//#endif


            //[MeshUpdate]는 Post Update로 전달

            //3. 자식 호출
            //자식 객체도 업데이트를 한다.
            if (_childTransforms != null)
            {
                for (int i = 0; i < _childTransforms.Length; i++)
                {
                    _childTransforms[i].UpdateCalculate_Pre();
                }
            }
        }