public void AddCalculatedResultParam(apOptCalculatedResultParam calculatedResultParam)
 {
     if (!_resultParams.Contains(calculatedResultParam))
     {
         _resultParams.Add(calculatedResultParam);
     }
 }
        public apMatrix3x3 GetDeferredRiggingMatrix(int vertexIndex)
        {
            _tmpMatrix.SetZero3x2();

            for (int iParam = 0; iParam < _resultParams_Rigging.Count; iParam++)
            {
                _cal_resultParam = _resultParams_Rigging[iParam];
                for (int iVR = 0; iVR < _cal_resultParam._result_VertLocalPairs.Count; iVR++)
                {
                    _cal_vertRequest = _cal_resultParam._result_VertLocalPairs[iVR];
                    if (!_cal_vertRequest._isCalculated || _cal_vertRequest._totalWeight == 0.0f)
                    {
                        continue;
                    }

                    _tmpVertRigWeightTable = _cal_vertRequest._rigBoneWeightTables[vertexIndex];
                    if (_tmpVertRigWeightTable._nRigTable == 0)
                    {
                        continue;
                    }

                    for (int iRig = 0; iRig < _tmpVertRigWeightTable._nRigTable; iRig++)
                    {
                        _tmpVertRigWeightTable._rigTable[iRig].CalculateMatrix();
                        _tmpMatrix.AddMatrixWithWeight(_tmpVertRigWeightTable._rigTable[iRig]._boneMatrix, _tmpVertRigWeightTable._rigTable[iRig]._weight);
                    }
                }
            }

            return(_tmpMatrix);
        }
            public bool Remove(apOptCalculatedResultParam calculatedResultParam)
            {
                bool isAnyClearedParam = false;

                for (int i = 0; i < _modParamPairs.Count; i++)
                {
                    _modParamPairs[i].Remove(calculatedResultParam);
                    if (_modParamPairs[i]._resultParams.Count == 0)
                    {
                        isAnyClearedParam = true;
                    }
                }
                if (isAnyClearedParam)
                {
                    //Param이 없는 Pair는 삭제하고, Dictionary를 다시 만들어주자
                    _modParamPairs_ModKey.Clear();
                    _modParamPairs.RemoveAll(delegate(OptModifierAndResultParamListPair a)
                    {
                        return(a._resultParams.Count == 0);
                    });

                    for (int i = 0; i < _modParamPairs.Count; i++)
                    {
                        OptModifierAndResultParamListPair modPair = _modParamPairs[i];

                        //빠른 참조를 위해 Dictionary도 세팅해주자
                        if (!_modParamPairs_ModKey.ContainsKey(modPair._keyModifier))
                        {
                            _modParamPairs_ModKey.Add(modPair._keyModifier, modPair);
                        }
                    }
                }

                return(isAnyClearedParam);
            }
        public Vector2 GetDeferredLocalPos(int vertexIndex)
        {
            _tmpPos = Vector2.zero;

            for (int iParam = 0; iParam < _resultParams_VertLocal.Count; iParam++)
            {
                _cal_resultParam = _resultParams_VertLocal[iParam];
                for (int iVR = 0; iVR < _cal_resultParam._result_VertLocalPairs.Count; iVR++)
                {
                    _cal_vertRequest = _cal_resultParam._result_VertLocalPairs[iVR];
                    if (!_cal_vertRequest._isCalculated || _cal_vertRequest._totalWeight == 0.0f)
                    {
                        continue;
                    }

                    for (int iModPair = 0; iModPair < _cal_vertRequest._nModWeightPairs; iModPair++)
                    {
                        _cal_vertRequestModWeightPair = _cal_vertRequest._modWeightPairs[iModPair];
                        if (!_cal_vertRequestModWeightPair._isCalculated)
                        {
                            continue;
                        }
                        _tmpPos += _cal_vertRequestModWeightPair._modMesh._vertices[vertexIndex]._deltaPos * _cal_vertRequestModWeightPair._weight;
                    }
                }
            }

            return(_tmpPos);
        }
Exemple #5
0
        // Init
        //--------------------------------------------
        public apOptCalculatedResultParamSubList(apOptCalculatedResultParam parentResultParam, bool isLocalMorph, bool isRigging)
        {
            _parentResultParam = parentResultParam;
            _subParamKeyValues.Clear();
            _nSubParamKeyValues = 0;

            _isVertexLocalMorph = isLocalMorph;
            _isVertexRigging    = isRigging;
            if (_isVertexLocalMorph)
            {
                _vertexRequest = new apOptVertexRequest(apOptVertexRequest.REQUEST_TYPE.VertLocal);
            }
            else if (_isVertexRigging)
            {
                _vertexRequest = new apOptVertexRequest(apOptVertexRequest.REQUEST_TYPE.Rigging);
            }
        }
            public void AddCalculatedResultParam(apOptCalculatedResultParam calculatedResultParam)
            {
                apOptModifierUnitBase modifier = calculatedResultParam._linkedModifier;

                if (modifier == null)
                {
                    return;
                }

                OptModifierAndResultParamListPair modParamPair = null;

                if (!_modParamPairs_ModKey.ContainsKey(modifier))
                {
                    modParamPair = new OptModifierAndResultParamListPair(modifier);
                    _modParamPairs_ModKey.Add(modifier, modParamPair);
                    _modParamPairs.Add(modParamPair);
                }
                else
                {
                    modParamPair = _modParamPairs_ModKey[modifier];
                }
                modParamPair.AddCalculatedResultParam(calculatedResultParam);
            }
        /// <summary>
        /// Calculate Result Statck의 업데이트 부분
        /// Pre-Update로서 VertWorld와 Rigging이 제외된다.
        /// </summary>
        public void Calculate_Post()
        {
            //bool isFirstDebug = true;
            _cal_prevWeight  = 0.0f;
            _cal_curWeight   = 0.0f;
            _cal_resultParam = null;
            _cal_posVerts    = null;


            // Rigging
            if (_isAnyRigging)
            {
//#if UNITY_EDITOR
//				Profiler.BeginSample("Calcuate Result Stack - 0. Rigging");
//#endif
                _cal_prevWeight  = 0.0f;
                _cal_curWeight   = 0.0f;
                _cal_resultParam = null;
                //_cal_posVerts = null;
                //_cal_vertMatrices = null;

                _iCalculatedParam = 0;


                _cal_vertRequestList = null;
                _cal_vertRequest     = null;

                _result_RiggingWeight = 0.0f;



                for (int iParam = 0; iParam < _resultParams_Rigging.Count; iParam++)
                {
                    _cal_resultParam = _resultParams_Rigging[iParam];
                    _cal_resultParam._resultWeight = 0.0f;
                    _cal_curWeight = _cal_resultParam.ModifierWeight;

                    if (!_cal_resultParam.IsModifierAvailable || _cal_curWeight <= 0.001f)
                    {
                        continue;
                    }

                    _cal_resultParam._resultWeight = 1.0f;                    //<<일단 Weight를 1로 두고 계산 시작



                    _result_RiggingWeight += _cal_curWeight;

                    // Blend 방식에 맞게 Pos를 만들자
                    if (_cal_resultParam.ModifierBlendMethod == apModifierBase.BLEND_METHOD.Interpolation || _iCalculatedParam == 0)
                    {
                        //Interpolation : Prev * (1-weight) + Next * weight
                        _cal_resultParam._resultWeight = _cal_curWeight;
                        for (int iPrev = 0; iPrev < iParam - 1; iPrev++)
                        {
                            _resultParams_Rigging[iPrev]._resultWeight *= (1.0f - _cal_curWeight);
                        }
                    }
                    else
                    {
                        //Additive : Prev + Next * weight
                        _cal_resultParam._resultWeight = _cal_curWeight;
                    }

                    _iCalculatedParam++;
                }

                if (_result_RiggingWeight > 1.0f)
                {
                    _result_RiggingWeight = 1.0f;
                }

                //이제 계산된 Weight를 모두 입력해주자
                for (int iParam = 0; iParam < _resultParams_Rigging.Count; iParam++)
                {
                    _cal_resultParam     = _resultParams_Rigging[iParam];
                    _cal_vertRequestList = _cal_resultParam._result_VertLocalPairs;
                    for (int iVR = 0; iVR < _cal_vertRequestList.Count; iVR++)
                    {
                        _cal_vertRequestList[iVR].MultiplyWeight(_cal_resultParam._resultWeight);
                    }
                }

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



            // 4. World Morph
            if (_isAnyVertWorld)
            {
//#if UNITY_EDITOR
//				Profiler.BeginSample("Calcuate Result Stack - 4. Vert World");
//#endif
                _cal_prevWeight  = 0.0f;
                _cal_curWeight   = 0.0f;
                _cal_resultParam = null;
                _cal_posVerts    = null;

                _iCalculatedParam = 0;

                for (int iParam = 0; iParam < _resultParams_VertWorld.Count; iParam++)
                {
                    _cal_resultParam = _resultParams_VertWorld[iParam];
                    _cal_curWeight   = _cal_resultParam.ModifierWeight;

                    if (!_cal_resultParam.IsModifierAvailable || _cal_curWeight <= 0.001f)
                    {
                        continue;
                    }

                    //Debug.Log("Vert World [" + iParam + "] (" + _cal_curWeight + ")");

                    _cal_posVerts = _cal_resultParam._result_Positions;
                    if (_cal_posVerts.Length != _result_VertWorld.Length)
                    {
                        //결과가 잘못 들어왔다 갱신 필요
                        Debug.LogError("Wrong Vert World Result (Cal : " + _cal_posVerts.Length + " / Verts : " + _result_VertWorld.Length + ")");
                        continue;
                    }

                    // Blend 방식에 맞게 Pos를 만들자
                    if (_cal_resultParam.ModifierBlendMethod == apModifierBase.BLEND_METHOD.Interpolation || _iCalculatedParam == 0)
                    {
                        for (int i = 0; i < _cal_posVerts.Length; i++)
                        {
                            _result_VertWorld[i] = BlendPosition_ITP(_result_VertWorld[i], _cal_posVerts[i], _cal_curWeight);
                        }

                        _cal_prevWeight += _cal_curWeight;
                    }
                    else
                    {
                        for (int i = 0; i < _cal_posVerts.Length; i++)
                        {
                            _result_VertWorld[i] = BlendPosition_Add(_result_VertWorld[i], _cal_posVerts[i], _cal_curWeight);
                        }
                    }


                    _iCalculatedParam++;
                }

//#if UNITY_EDITOR
//				Profiler.EndSample();
//#endif
                //Debug.Log(" >> Vert World");
            }
        }
        /// <summary>
        /// Calculate Result Statck의 업데이트 부분
        /// Pre-Update로서 VertWorld와 Rigging이 제외된다.
        /// </summary>
        public void Calculate_Pre()
        {
            //bool isFirstDebug = true;
            _cal_prevWeight  = 0.0f;
            _cal_curWeight   = 0.0f;
            _cal_resultParam = null;
            _cal_posVerts    = null;


            //Debug.Log("Is Any Vert Local : " + _isAnyVertLocal + " [" + _resultParams_VertLocal.Count +"]");
            // 1. Local Morph
            if (_isAnyVertLocal)
            {
//#if UNITY_EDITOR
//				Profiler.BeginSample("Calcuate Result Stack - 1. Vert Local");
//#endif
                _cal_prevWeight      = 0.0f;
                _cal_curWeight       = 0.0f;
                _cal_resultParam     = null;
                _cal_posVerts        = null;
                _cal_vertRequestList = null;
                _cal_vertRequest     = null;

                _iCalculatedParam = 0;                //<<추가 : 첫 모디파이어는 무조건 Interpolation으로 만들자


                #region [미사용 코드 : 최적화 전]
                //이전 코드
                //for (int iParam = 0; iParam < _resultParams_VertLocal.Count; iParam++)
                //{
                //	_cal_resultParam = _resultParams_VertLocal[iParam];
                //	_cal_curWeight = _cal_resultParam.ModifierWeight;

                //	if (!_cal_resultParam.IsModifierAvailable || _cal_curWeight <= 0.001f)
                //	{ continue; }


                //	_cal_posVerts = _cal_resultParam._result_Positions;
                //	if (_result_VertLocal == null)
                //	{
                //		Debug.LogError("Result Vert Local is Null");
                //	}
                //	if (_cal_posVerts == null)
                //	{
                //		Debug.LogError("Cal Pos Vert is Null");
                //	}
                //	if (_cal_posVerts.Length != _result_VertLocal.Length)
                //	{
                //		//결과가 잘못 들어왔다 갱신 필요
                //		Debug.LogError("Wrong Vert Local Result (Cal : " + _cal_posVerts.Length + " / Verts : " + _result_VertLocal.Length + ")");
                //		continue;
                //	}

                //	// Blend 방식에 맞게 Pos를 만들자
                //	if (_cal_resultParam.ModifierBlendMethod == apModifierBase.BLEND_METHOD.Interpolation || _iCalculatedParam == 0)
                //	{
                //		for (int i = 0; i < _cal_posVerts.Length; i++)
                //		{
                //			_result_VertLocal[i] = BlendPosition_ITP(_result_VertLocal[i], _cal_posVerts[i], _cal_curWeight);
                //		}

                //		_cal_prevWeight += _cal_curWeight;
                //	}
                //	else
                //	{
                //		for (int i = 0; i < _cal_posVerts.Length; i++)
                //		{
                //			_result_VertLocal[i] = BlendPosition_Add(_result_VertLocal[i], _cal_posVerts[i], _cal_curWeight);
                //		}
                //	}
                //	_iCalculatedParam++;
                //}
                #endregion

                //최적화된 코드.
                //Vertex Pos를 건드리지 않고 보간식을 중첩한다.
                for (int iParam = 0; iParam < _resultParams_VertLocal.Count; iParam++)
                {
                    _cal_resultParam = _resultParams_VertLocal[iParam];
                    _cal_resultParam._resultWeight = 0.0f;
                    _cal_curWeight = _cal_resultParam.ModifierWeight;

                    if (!_cal_resultParam.IsModifierAvailable || _cal_curWeight <= 0.001f)
                    {
                        continue;
                    }

                    _cal_resultParam._resultWeight = 1.0f;                    //<<일단 Weight를 1로 두고 계산 시작


                    // Blend 방식에 맞게 Pos를 만들자
                    if (_cal_resultParam.ModifierBlendMethod == apModifierBase.BLEND_METHOD.Interpolation || _iCalculatedParam == 0)
                    {
                        //Interpolation : Prev * (1-weight) + Next * weight
                        _cal_resultParam._resultWeight = _cal_curWeight;
                        for (int iPrev = 0; iPrev < iParam - 1; iPrev++)
                        {
                            _resultParams_VertLocal[iPrev]._resultWeight *= (1.0f - _cal_curWeight);
                        }
                    }
                    else
                    {
                        //Additive : Prev + Next * weight
                        _cal_resultParam._resultWeight = _cal_curWeight;
                    }
                    _iCalculatedParam++;
                }

                //이제 계산된 Weight를 모두 입력해주자
                for (int iParam = 0; iParam < _resultParams_VertLocal.Count; iParam++)
                {
                    _cal_resultParam     = _resultParams_VertLocal[iParam];
                    _cal_vertRequestList = _cal_resultParam._result_VertLocalPairs;
                    for (int iVR = 0; iVR < _cal_vertRequestList.Count; iVR++)
                    {
                        _cal_vertRequestList[iVR].MultiplyWeight(_cal_resultParam._resultWeight);
                    }
                }

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

            // 2. Mesh / MeshGroup Transformation
            if (_isAnyTransformation)
            {
//#if UNITY_EDITOR
//				Profiler.BeginSample("Calcuate Result Stack - 2. MeshGroup Transformation");
//#endif
                _cal_prevWeight  = 0.0f;
                _cal_curWeight   = 0.0f;
                _cal_resultParam = null;

                _iCalculatedParam = 0;

                //Debug.Log("Update TF - OPT");
                for (int iParam = 0; iParam < _resultParams_Transform.Count; iParam++)
                {
                    _cal_resultParam = _resultParams_Transform[iParam];
                    _cal_curWeight   = _cal_resultParam.ModifierWeight;

                    if (!_cal_resultParam.IsModifierAvailable || _cal_curWeight <= 0.001f)
                    {
                        continue;
                    }



                    // Blend 방식에 맞게 Matrix를 만들자 하자
                    if (_cal_resultParam.ModifierBlendMethod == apModifierBase.BLEND_METHOD.Interpolation || _iCalculatedParam == 0)
                    {
                        //Debug.Log("Cal TF [ITP] : " + _cal_resultParam._result_Matrix.Pos3 + " (Weight : " + _cal_curWeight + ")");

                        BlendMatrix_ITP(_result_MeshTransform, _cal_resultParam._result_Matrix, _cal_curWeight);

                        //if (_cal_resultParam._result_Matrix.Scale2.magnitude < 0.5f || _cal_curWeight < 0.5f)
                        //{
                        //	Debug.Log("Cal TF [ITP] : " + _cal_resultParam._result_Matrix.Scale2 + " > " + _result_MeshTransform.Scale2 + " (Weight : " + _cal_curWeight + ")");
                        //}

                        _cal_prevWeight += _cal_curWeight;
                    }
                    else
                    {
                        BlendMatrix_Add(_result_MeshTransform, _cal_resultParam._result_Matrix, _cal_curWeight);
                    }

                    _iCalculatedParam++;
                }

                _result_MeshTransform.MakeMatrix();

                if (_result_MeshTransform._scale.magnitude < 0.5f)
                {
                    Debug.Log("Cal TF [ITP] : " + _result_MeshTransform._scale + " (Total Weight : " + _cal_prevWeight + ")");
                }

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

            // 3. Mesh Color
            if (_isAnyMeshColor)
            {
//#if UNITY_EDITOR
//				Profiler.BeginSample("Calcuate Result Stack - 3. Mesh Color");
//#endif
                _cal_prevWeight  = 0.0f;
                _cal_curWeight   = 0.0f;
                _cal_resultParam = null;

                _iCalculatedParam = 0;

                _result_IsVisible       = false;
                _nMeshColorCalculated   = 0;
                _result_CalculatedColor = false;

                for (int iParam = 0; iParam < _resultParams_MeshColor.Count; iParam++)
                {
                    _cal_resultParam = _resultParams_MeshColor[iParam];
                    _cal_curWeight   = Mathf.Clamp01(_cal_resultParam.ModifierWeight);

                    if (!_cal_resultParam.IsModifierAvailable ||
                        _cal_curWeight <= 0.001f ||
                        !_cal_resultParam.IsColorValueEnabled ||
                        !_cal_resultParam._isColorCalculated                           //<<추가 : Color로 등록했지만 아예 계산이 안되었을 수도 있다.
                        )
                    {
                        continue;
                    }                    //<<TODO


                    // Blend 방식에 맞게 Matrix를 만들자 하자
                    if (_cal_resultParam.ModifierBlendMethod == apModifierBase.BLEND_METHOD.Interpolation || _iCalculatedParam == 0)
                    {
                        //_result_Color = BlendColor_ITP(_result_Color, _cal_resultParam._result_Color, _cal_prevWeight, _cal_curWeight);
                        _result_Color    = apUtil.BlendColor_ITP(_result_Color, _cal_resultParam._result_Color, _cal_curWeight);
                        _cal_prevWeight += _cal_curWeight;
                    }
                    else
                    {
                        _result_Color = apUtil.BlendColor_Add(_result_Color, _cal_resultParam._result_Color, _cal_curWeight);
                    }

                    _result_IsVisible |= _cal_resultParam._result_IsVisible;
                    _nMeshColorCalculated++;

                    _result_CalculatedColor = true;                    //<<"계산된 MeshColor" Result가 있음을 알린다.

                    _iCalculatedParam++;
                }

                if (_nMeshColorCalculated == 0)
                {
                    _result_IsVisible = true;
                }


//#if UNITY_EDITOR
//				Profiler.EndSample();
//#endif
            }
            else
            {
                _result_IsVisible = true;
            }

            //AnyBoneTransform
            if (_isAnyBoneTransform)
            {
//#if UNITY_EDITOR
//				Profiler.BeginSample("Calcuate Result Stack - 5. Bone Transform");
//#endif
                _cal_prevWeight  = 0.0f;
                _cal_curWeight   = 0.0f;
                _cal_resultParam = null;


                OptBoneAndModParamPair boneModPair = null;
                apOptBone targetBone = null;
                List <OptModifierAndResultParamListPair> modParamPairs = null;


                for (int iBonePair = 0; iBonePair < _resultParams_BoneTransform.Count; iBonePair++)
                {
                    boneModPair   = _resultParams_BoneTransform[iBonePair];
                    targetBone    = boneModPair._keyBone;
                    modParamPairs = boneModPair._modParamPairs;

                    if (targetBone == null || modParamPairs.Count == 0)
                    {
                        continue;
                    }


                    _iCalculatedParam = 0;
                    _result_BoneTransform.SetIdentity();

                    for (int iModParamPair = 0; iModParamPair < modParamPairs.Count; iModParamPair++)
                    {
                        OptModifierAndResultParamListPair modParamPair = modParamPairs[iModParamPair];

                        for (int iParam = 0; iParam < modParamPair._resultParams.Count; iParam++)
                        {
                            _cal_resultParam = modParamPair._resultParams[iParam];

                            _cal_curWeight = _cal_resultParam.ModifierWeight;

                            if (!_cal_resultParam.IsModifierAvailable || _cal_curWeight <= 0.001f)
                            {
                                continue;
                            }

                            //if(_cal_resultParam._result_Matrix._scale.magnitude < 0.3f)
                            //{
                            //	Debug.LogError("[" + targetBone.name + "] 너무 작은 Cal Matrix : " + _cal_resultParam._linkedModifier._name);
                            //}
                            // Blend 방식에 맞게 Matrix를 만들자 하자
                            if (_cal_resultParam.ModifierBlendMethod == apModifierBase.BLEND_METHOD.Interpolation || _iCalculatedParam == 0)
                            {
                                BlendMatrix_ITP(_result_BoneTransform, _cal_resultParam._result_Matrix, _cal_curWeight);
                                _cal_prevWeight += _cal_curWeight;
                            }
                            else
                            {
                                BlendMatrix_Add(_result_BoneTransform, _cal_resultParam._result_Matrix, _cal_curWeight);
                            }

                            _iCalculatedParam++;
                        }
                    }

                    //참조된 본에 직접 값을 넣어주자
                    targetBone.UpdateModifiedValue(_result_BoneTransform._pos, _result_BoneTransform._angleDeg, _result_BoneTransform._scale);
                }

//#if UNITY_EDITOR
//				Profiler.EndSample();
//#endif
            }
        }
        // Functions
        //--------------------------------------------

        // Add / Remove / Sort
        //----------------------------------------------------------------------
        public void AddCalculatedResultParam(apOptCalculatedResultParam resultParam)
        {
            if ((int)(resultParam._calculatedValueType & apCalculatedResultParam.CALCULATED_VALUE_TYPE.VertexPos) != 0)
            {
                if (resultParam._calculatedSpace == apCalculatedResultParam.CALCULATED_SPACE.Object)
                {
                    if (!_resultParams_VertLocal.Contains(resultParam))
                    {
                        _resultParams_VertLocal.Add(resultParam);
                    }
                    _isAnyVertLocal = true;
                }
                else if (resultParam._calculatedSpace == apCalculatedResultParam.CALCULATED_SPACE.World)
                {
                    if (!_resultParams_VertWorld.Contains(resultParam))
                    {
                        _resultParams_VertWorld.Add(resultParam);
                    }
                    _isAnyVertWorld = true;
                }
                else if (resultParam._calculatedSpace == apCalculatedResultParam.CALCULATED_SPACE.Rigging)                //<<추가
                {
                    if (!_resultParams_Rigging.Contains(resultParam))
                    {
                        _resultParams_Rigging.Add(resultParam);
                    }
                    _isAnyRigging = true;
                }
            }
            if ((int)(resultParam._calculatedValueType & apCalculatedResultParam.CALCULATED_VALUE_TYPE.TransformMatrix) != 0)
            {
                //변경 : Bone타입과 일반 Transform타입으로 나뉜다.
                if (resultParam._targetBone != null)
                {
                    //Bone 타입이다.
                    //Modifier + ResultParam Pair로 저장해야한다.
                    OptBoneAndModParamPair modParamPair = _resultParams_BoneTransform.Find(delegate(OptBoneAndModParamPair a)
                    {
                        return(a._keyBone == resultParam._targetBone);
                    });
                    if (modParamPair == null)
                    {
                        modParamPair = new OptBoneAndModParamPair(resultParam._targetBone);
                        _resultParams_BoneTransform.Add(modParamPair);
                    }

                    modParamPair.AddCalculatedResultParam(resultParam);
                    _isAnyBoneTransform = true;

                    //이전 코드
                    //if(!_resultParams_BoneTransform.Contains(resultParam))
                    //{
                    //	_resultParams_BoneTransform.Add(resultParam);
                    //	_isAnyBoneTransform = true;
                    //}
                }
                else
                {
                    //Mesh/MeshGroup Transform 타입이다.
                    if (!_resultParams_Transform.Contains(resultParam))
                    {
                        _resultParams_Transform.Add(resultParam);
                        _isAnyTransformation = true;
                    }
                }
            }
            if ((int)(resultParam._calculatedValueType & apCalculatedResultParam.CALCULATED_VALUE_TYPE.Color) != 0)
            {
                if (!_resultParams_MeshColor.Contains(resultParam))
                {
                    _resultParams_MeshColor.Add(resultParam);
                    _isAnyMeshColor = true;
                }
            }
        }
 public void Remove(apOptCalculatedResultParam calculatedResultParam)
 {
     _resultParams.Remove(calculatedResultParam);
 }
        //Link가 모두 끝난 후 실행시켜준다.
        //Modifier -> Target Tranform (=RenderUnit)을 CalculatedParam을 이용해 연결해준다.
        public void LinkModifierStackToRenderUnitCalculateStack(bool isRoot, apOptTransform rootOptTransform, bool isRecursive)
        {
            //RenderUnit => OptTransform
            //전체 Modifier중에서 RenderUnit을 포함한 Modifer를 찾는다.
            //그 중, RenderUnit에 대한것만 처리할 CalculateResultParam을 만들고 연동한다.
            //ResultParam을 RenderUnit의 CalculateStack에 넣는다.

            //if (_parentTransform != null)
            //{
            //	Debug.Log(">> [Opt] LinkModifierStackToRenderUnitCalculateStack - " + _parentTransform._name + "(Root : " + rootOptTransform._name + ")");
            //}
            //else if(isRoot)
            //{
            //	Debug.Log(">> [Opt] LinkModifierStackToRenderUnitCalculateStack - " + rootOptTransform._name + " - Root");
            //}
            //여기서 버그가 발생되었다.
            if (_nModifiers != _modifiers.Count)
            {
                _nModifiers = _modifiers.Count;
            }

            for (int iMod = 0; iMod < _nModifiers; iMod++)
            {
                //Modifier ->..
                apOptModifierUnitBase modifier = _modifiers[iMod];

                bool isUseModMeshSet = modifier._isUseModMeshSet;                //19.5.24 추가

                List <apOptParamSetGroup> paramSetGroups = modifier._paramSetGroupList;

                for (int iGroup = 0; iGroup < paramSetGroups.Count; iGroup++)
                {
                    //Modifier -> ParamSetGroup ->..
                    apOptParamSetGroup paramSetGroup = paramSetGroups[iGroup];

                    List <apOptParamSet> paramSets = paramSetGroup._paramSetList;

                    for (int iParam = 0; iParam < paramSets.Count; iParam++)
                    {
                        //Modifier -> ParamSetGroup -> ParamSet ->...
                        apOptParamSet paramSet = paramSets[iParam];

                        List <apOptModifiedMesh> modMeshes = paramSet._meshData;
                        List <apOptModifiedBone> modBones  = paramSet._boneData;

                        //추가 19.5.24 < ModMesh대신 ModMeshSet을 사용하자
                        List <apOptModifiedMeshSet> modMeshSets = paramSet._meshSetData;

                        //변경 19.5.24
                        //기존의 ModMesh가 불필요하게 데이터를 모두 가지고 있어서 용량이 많았다.
                        //개선된 ModMeshSet으로 변경하여 최적화
                        if (isUseModMeshSet)
                        {
                            //개선된 ModMeshSet을 사용하는 경우
                            apOptModifiedMeshSet modMeshSet = null;
                            for (int iModMeshSet = 0; iModMeshSet < modMeshSets.Count; iModMeshSet++)
                            {
                                modMeshSet = modMeshSets[iModMeshSet];
                                if (modMeshSet._targetTransform != null)
                                {
                                    //이미 만든 Calculate Param이 있는지 확인
                                    apOptCalculatedResultParam existParam = modifier.GetCalculatedResultParam(modMeshSet._targetTransform);

                                    if (existParam != null)
                                    {
                                        //이미 존재하는 Calculated Param이 있다.
                                        existParam.AddParamSetAndModifiedValue(paramSetGroup, paramSet, null, null, modMeshSet);

                                        //추가 12.5
                                        //이미 추가된 ResultParam에 ParamKeyValue가 추가될 때 CalculateStack이 갱신되는 경우가 있다.
                                        modMeshSet._targetTransform.CalculatedStack.OnParamKeyValueAddedOnCalculatedResultParam(existParam);
                                    }
                                    else
                                    {
                                        //새로 Calculated Param을 만들어야 한다.
                                        apOptCalculatedResultParam newCalParam = new apOptCalculatedResultParam(
                                            modifier._calculatedValueType,
                                            modifier._calculatedSpace,
                                            modifier,
                                            modMeshSet._targetTransform,
                                            modMeshSet._targetTransform,
                                            modMeshSet._targetMesh,
                                            null
                                            //weightedVertexData//<<사용 안함 19.5.20
                                            );

                                        newCalParam.AddParamSetAndModifiedValue(paramSetGroup, paramSet, null, null, modMeshSet);

                                        //Modifier에 등록하고
                                        modifier._calculatedResultParams.Add(newCalParam);

                                        //OptTranform에도 등록하자
                                        modMeshSet._targetTransform.CalculatedStack.AddCalculatedResultParam(newCalParam);
                                    }
                                }
                            }
                        }
                        else
                        {
                            //기존의 ModMesh를 사용하는 경우

                            for (int iModMesh = 0; iModMesh < modMeshes.Count; iModMesh++)
                            {
                                //[핵심]
                                //Modifier -> ParamSetGroup -> ParamSet -> ModMeh
                                //이제 이 ModMesh와 타겟 Transform을 연결하자.
                                //연결할땐 Calculated 오브젝트를 만들어서 연결
                                apOptModifiedMesh modMesh = modMeshes[iModMesh];

                                if (modMesh._targetTransform != null)
                                {
                                    //이미 만든 Calculate Param이 있는지 확인
                                    apOptCalculatedResultParam existParam = modifier.GetCalculatedResultParam(modMesh._targetTransform);

                                    // 삭제 19.5.20 : apOptParamSetGroupVertWeight는 더이상 사용하지 않음
                                    //apOptParamSetGroupVertWeight weightedVertexData = null;
                                    //if (modMesh._targetMesh != null)
                                    //{
                                    //	weightedVertexData = paramSetGroup.GetWeightVertexData(modMesh._targetTransform);
                                    //}

                                    if (existParam != null)
                                    {
                                        //이미 존재하는 Calculated Param이 있다.
                                        existParam.AddParamSetAndModifiedValue(paramSetGroup, paramSet, modMesh, null, null);

                                        //추가 12.5
                                        //이미 추가된 ResultParam에 ParamKeyValue가 추가될 때 CalculateStack이 갱신되는 경우가 있다.
                                        modMesh._targetTransform.CalculatedStack.OnParamKeyValueAddedOnCalculatedResultParam(existParam);
                                    }
                                    else
                                    {
                                        //새로 Calculated Param을 만들어야 한다.
                                        apOptCalculatedResultParam newCalParam = new apOptCalculatedResultParam(
                                            modifier._calculatedValueType,
                                            modifier._calculatedSpace,
                                            modifier,
                                            modMesh._targetTransform,
                                            modMesh._targetTransform,
                                            modMesh._targetMesh,
                                            null
                                            //weightedVertexData//<<사용 안함 19.5.20
                                            );

                                        newCalParam.AddParamSetAndModifiedValue(paramSetGroup, paramSet, modMesh, null, null);

                                        //Modifier에 등록하고
                                        modifier._calculatedResultParams.Add(newCalParam);

                                        //OptTranform에도 등록하자
                                        modMesh._targetTransform.CalculatedStack.AddCalculatedResultParam(newCalParam);
                                    }
                                }
                            }
                        }


                        //변경 10.2 :
                        //기존 : ModBone의 _meshGroup_Bone에 해당하는 OptTransform에 연결했다.
                        //변경 : ModBone은 항상 RootBone에 연결한다.
                        for (int iModBone = 0; iModBone < modBones.Count; iModBone++)
                        {
                            apOptModifiedBone modBone = modBones[iModBone];
                            if (modBone._bone == null || modBone._meshGroup_Bone == null)
                            {
                                Debug.LogError("ModBone -> Calculate Link (Opt) 실패");
                                continue;
                            }

                            //<BONE_EDIT>
                            //apOptCalculatedResultParam existParam = modifier.GetCalculatedResultParam_Bone(
                            //										modBone._meshGroup_Bone, modBone._bone);

                            //변경
                            apOptCalculatedResultParam existParam = modifier.GetCalculatedResultParam_Bone(
                                rootOptTransform, modBone._bone, modBone._meshGroup_Bone);


                            if (existParam != null)
                            {
                                //이미 있다면 ModBone만 추가해주자
                                existParam.AddParamSetAndModifiedValue(paramSetGroup, paramSet, null, modBone, null);
                                //Debug.LogWarning(" < Exist > - Mod Bone [" + modBone._bone._name + " << " + modBone._meshGroup_Bone._name + "]");
                            }
                            else
                            {
                                //Debug.Log("Mod Bone -> Calculate Param 등록");
                                //새로 CalculateParam을 만들고
                                //<BONE_EDIT>
                                //apOptCalculatedResultParam newCalParam = new apOptCalculatedResultParam(
                                //	modifier._calculatedValueType,
                                //	modifier._calculatedSpace,
                                //	modifier,
                                //	modBone._meshGroup_Bone,
                                //	modBone._meshGroup_Bone._childMesh,
                                //	modBone._bone,
                                //	null//WeightedVertex
                                //	);

                                //Debug.LogError(" < New > - Mod Bone [" + modBone._bone._name + " << " + modBone._meshGroup_Bone._name + "]");

                                apOptCalculatedResultParam newCalParam = new apOptCalculatedResultParam(
                                    modifier._calculatedValueType,
                                    modifier._calculatedSpace,
                                    modifier,
                                    rootOptTransform,                                    //<<변경
                                    modBone._meshGroup_Bone,                             //추가
                                    modBone._meshGroup_Bone._childMesh,
                                    modBone._bone
                                    //null//WeightedVertex > 19.5.20 : 삭제
                                    );

                                newCalParam.AddParamSetAndModifiedValue(paramSetGroup, paramSet, null, modBone, null);

                                // Modifier에 등록하고
                                modifier._calculatedResultParams.Add(newCalParam);

                                //RenderUnit에도 등록을 하자
                                //<BONE_EDIT>
                                //modBone._meshGroup_Bone.CalculatedStack.AddCalculatedResultParam(newCalParam);

                                //변경
                                rootOptTransform.CalculatedStack.AddCalculatedResultParam(newCalParam);
                            }
                        }
                    }
                }

                //Modifier에서
                //SubList를 한번 정렬하자
                for (int iCal = 0; iCal < modifier._calculatedResultParams.Count; iCal++)
                {
                    modifier._calculatedResultParams[iCal].SortSubList();
                }
            }


            //추가>>
            //하위 객체에 대해서도 Link를 자동으로 수행한다.
            //다 끝나고 Sort
            apOptTransform childTransform = null;

            if (_parentTransform != null)
            {
                if (isRecursive)
                {
                    if (_parentTransform._childTransforms != null && _parentTransform._childTransforms.Length > 0)
                    {
                        for (int i = 0; i < _parentTransform._childTransforms.Length; i++)
                        {
                            childTransform = _parentTransform._childTransforms[i];
                            if (childTransform._unitType == apOptTransform.UNIT_TYPE.Group)
                            {
                                if (childTransform != _parentTransform)
                                {
                                    //<<여기서도 같이 수행

                                    childTransform._modifierStack.LinkModifierStackToRenderUnitCalculateStack(false, rootOptTransform, true);
                                }
                            }
                        }
                    }
                }

                if (isRoot)
                {
                    //Root인 경우
                    //RenderUnit들을 검사하면서 Calculated Stack에 대해서 Sort를 해주자
                    SortAllCalculatedStack(_parentTransform);
                }
            }
            else
            {
                Debug.LogError("<<<< Error : Mod Link시 Parent Transform이 연결이 안되었다");
            }
        }
        private apOptCalculatedLerpArea _cpLerpAreaLastSelected = null;        //빠른 처리를 위해 "이전에 참조된 Area"를 저장하자.



        // Init
        //--------------------------------------------
        public apOptCalculatedResultParamSubList(apOptCalculatedResultParam parentResultParam)
        {
            _parentResultParam = parentResultParam;
            _subParamKeyValues.Clear();
            _nSubParamKeyValues = 0;
        }
Exemple #13
0
        //Link가 모두 끝난 후 실행시켜준다.
        //Modifier -> Target Tranform (=RenderUnit)을 CalculatedParam을 이용해 연결해준다.
        public void LinkModifierStackToRenderUnitCalculateStack(bool isRoot = true)
        {
            //RenderUnit => OptTransform
            //전체 Modifier중에서 RenderUnit을 포함한 Modifer를 찾는다.
            //그 중, RenderUnit에 대한것만 처리할 CalculateResultParam을 만들고 연동한다.
            //ResultParam을 RenderUnit의 CalculateStack에 넣는다.

            for (int iMod = 0; iMod < _nModifiers; iMod++)
            {
                //Modifier ->..
                apOptModifierUnitBase modifier = _modifiers[iMod];

                List <apOptParamSetGroup> paramSetGroups = modifier._paramSetGroupList;

                for (int iGroup = 0; iGroup < paramSetGroups.Count; iGroup++)
                {
                    //Modifier -> ParamSetGroup ->..
                    apOptParamSetGroup paramSetGroup = paramSetGroups[iGroup];

                    List <apOptParamSet> paramSets = paramSetGroup._paramSetList;

                    for (int iParam = 0; iParam < paramSets.Count; iParam++)
                    {
                        //Modifier -> ParamSetGroup -> ParamSet ->...
                        apOptParamSet paramSet = paramSets[iParam];

                        List <apOptModifiedMesh> modMeshes = paramSet._meshData;
                        List <apOptModifiedBone> modBones  = paramSet._boneData;

                        for (int iModMesh = 0; iModMesh < modMeshes.Count; iModMesh++)
                        {
                            //[핵심]
                            //Modifier -> ParamSetGroup -> ParamSet -> ModMeh
                            //이제 이 ModMesh와 타겟 Transform을 연결하자.
                            //연결할땐 Calculated 오브젝트를 만들어서 연결
                            apOptModifiedMesh modMesh = modMeshes[iModMesh];

                            if (modMesh._targetTransform != null)
                            {
                                //이미 만든 Calculate Param이 있는지 확인
                                apOptCalculatedResultParam existParam = modifier.GetCalculatedResultParam(modMesh._targetTransform);

                                apOptParamSetGroupVertWeight weightedVertexData = null;
                                if (modMesh._targetMesh != null)
                                {
                                    weightedVertexData = paramSetGroup.GetWeightVertexData(modMesh._targetTransform);
                                }

                                if (existParam != null)
                                {
                                    //이미 존재하는 Calculated Param이 있다.
                                    existParam.AddParamSetAndModifiedValue(paramSetGroup, paramSet, modMesh, null);
                                }
                                else
                                {
                                    //새로 Calculated Param을 만들어야 한다.
                                    apOptCalculatedResultParam newCalParam = new apOptCalculatedResultParam(
                                        modifier._calculatedValueType,
                                        modifier._calculatedSpace,
                                        modifier,
                                        modMesh._targetTransform,
                                        modMesh._targetMesh,
                                        null,
                                        weightedVertexData);

                                    newCalParam.AddParamSetAndModifiedValue(paramSetGroup, paramSet, modMesh, null);

                                    //Modifier에 등록하고
                                    modifier._calculatedResultParams.Add(newCalParam);

                                    //OptTranform에도 등록하자
                                    modMesh._targetTransform.CalculatedStack.AddCalculatedResultParam(newCalParam);
                                }
                            }
                        }

                        for (int iModBone = 0; iModBone < modBones.Count; iModBone++)
                        {
                            apOptModifiedBone modBone = modBones[iModBone];
                            if (modBone._bone == null || modBone._meshGroup_Bone == null)
                            {
                                Debug.LogError("ModBone -> Calculate Link (Opt) 실패");
                                continue;
                            }


                            apOptCalculatedResultParam existParam = modifier.GetCalculatedResultParam_Bone(
                                modBone._meshGroup_Bone, modBone._bone);

                            if (existParam != null)
                            {
                                //이미 있다면 ModBone만 추가해주자
                                existParam.AddParamSetAndModifiedValue(paramSetGroup, paramSet, null, modBone);
                            }
                            else
                            {
                                //Debug.Log("Mod Bone -> Calculate Param 등록");
                                //새로 CalculateParam을 만들고
                                apOptCalculatedResultParam newCalParam = new apOptCalculatedResultParam(
                                    modifier._calculatedValueType,
                                    modifier._calculatedSpace,
                                    modifier,
                                    modBone._meshGroup_Bone,
                                    modBone._meshGroup_Bone._childMesh,
                                    modBone._bone,
                                    null                                    //WeightedVertex
                                    );

                                newCalParam.AddParamSetAndModifiedValue(paramSetGroup, paramSet, null, modBone);

                                // Modifier에 등록하고
                                modifier._calculatedResultParams.Add(newCalParam);

                                //RenderUnit에도 등록을 하자
                                modBone._meshGroup_Bone.CalculatedStack.AddCalculatedResultParam(newCalParam);
                            }
                        }
                    }
                }

                //Modifier에서
                //SubList를 한번 정렬하자
                for (int iCal = 0; iCal < modifier._calculatedResultParams.Count; iCal++)
                {
                    modifier._calculatedResultParams[iCal].SortSubList();
                }
            }

            //추가>>
            //하위 객체에 대해서도 Link를 자동으로 수행한다.
            //다 끝나고 Sort
            apOptTransform childTransform = null;

            if (_parentTransform != null)
            {
                if (_parentTransform._childTransforms != null && _parentTransform._childTransforms.Length > 0)
                {
                    for (int i = 0; i < _parentTransform._childTransforms.Length; i++)
                    {
                        childTransform = _parentTransform._childTransforms[i];
                        if (childTransform._unitType == apOptTransform.UNIT_TYPE.Group)
                        {
                            if (childTransform != _parentTransform)
                            {
                                childTransform._modifierStack.LinkModifierStackToRenderUnitCalculateStack(false);                                //<<여기서도 같이 수행
                            }
                        }
                    }
                }

                if (isRoot)
                {
                    //Root인 경우
                    //RenderUnit들을 검사하면서 Calculated Stack에 대해서 Sort를 해주자
                    SortAllCalculatedStack(_parentTransform);
                }
            }
        }
        /// <summary>
        /// Calculate Result Statck의 업데이트 부분
        /// Pre-Update로서 VertWorld와 Rigging이 제외된다.
        /// </summary>
        public void Calculate_Post()
        {
            //bool isFirstDebug = true;
            _cal_prevWeight  = 0.0f;
            _cal_curWeight   = 0.0f;
            _cal_resultParam = null;
            _cal_posVerts    = null;


            // Rigging
            if (_isAnyRigging)
            {
                _cal_prevWeight  = 0.0f;
                _cal_curWeight   = 0.0f;
                _cal_resultParam = null;
                _cal_posVerts    = null;

                _iCalculatedParam = 0;

                _result_RiggingWeight = 0.0f;

                for (int iParam = 0; iParam < _resultParams_Rigging.Count; iParam++)
                {
                    _cal_resultParam = _resultParams_Rigging[iParam];
                    _cal_curWeight   = _cal_resultParam.ModifierWeight;

                    if (!_cal_resultParam.IsModifierAvailable || _cal_curWeight <= 0.001f)
                    {
                        continue;
                    }


                    _cal_posVerts = _cal_resultParam._result_Positions;
                    if (_cal_posVerts.Count != _result_Rigging.Length)
                    {
                        //결과가 잘못 들어왔다 갱신 필요
                        Debug.LogError("Wrong Vert Local Result (Cal : " + _cal_posVerts.Count + " / Verts : " + _result_Rigging.Length + ")");
                        continue;
                    }

                    _result_RiggingWeight += _cal_curWeight;

                    // Blend 방식에 맞게 Pos를 만들자
                    if (_cal_resultParam.ModifierBlendMethod == apModifierBase.BLEND_METHOD.Interpolation || _iCalculatedParam == 0)
                    {
                        for (int i = 0; i < _cal_posVerts.Count; i++)
                        {
                            _result_Rigging[i] = BlendPosition_ITP(_result_Rigging[i], _cal_posVerts[i], _cal_curWeight);
                        }

                        _cal_prevWeight += _cal_curWeight;
                    }
                    else
                    {
                        for (int i = 0; i < _cal_posVerts.Count; i++)
                        {
                            _result_Rigging[i] = BlendPosition_Add(_result_Rigging[i], _cal_posVerts[i], _cal_curWeight);
                        }
                    }

                    //Debug.Log("[" + resultParam._targetRenderUnit.Name + "] : " + resultParam._linkedModifier.DisplayName + " / " + resultParam._paramKeyValues.Count);
                    _iCalculatedParam++;
                }

                if (_result_RiggingWeight > 1.0f)
                {
                    _result_RiggingWeight = 1.0f;
                }
            }



            // 4. World Morph
            if (_isAnyVertWorld)
            {
                //Debug.Log("Vert World >> ");
#if UNITY_EDITOR
                Profiler.BeginSample("Calcuate Result Stack - 4. Vert World");
#endif
                _cal_prevWeight  = 0.0f;
                _cal_curWeight   = 0.0f;
                _cal_resultParam = null;
                List <Vector2> posVerts = null;


                _iCalculatedParam = 0;

                for (int iParam = 0; iParam < _resultParams_VertWorld.Count; iParam++)
                {
                    _cal_resultParam = _resultParams_VertWorld[iParam];
                    _cal_curWeight   = _cal_resultParam.ModifierWeight;

                    if (!_cal_resultParam.IsModifierAvailable || _cal_curWeight <= 0.001f)
                    {
                        continue;
                    }

                    //Debug.Log("Vert World [" + iParam + "] (" + _cal_curWeight + ")");

                    posVerts = _cal_resultParam._result_Positions;
                    if (posVerts.Count != _result_VertWorld.Length)
                    {
                        //결과가 잘못 들어왔다 갱신 필요
                        Debug.LogError("Wrong Vert World Result (Cal : " + posVerts.Count + " / Verts : " + _result_VertWorld.Length + ")");
                        continue;
                    }

                    // Blend 방식에 맞게 Pos를 만들자
                    if (_cal_resultParam.ModifierBlendMethod == apModifierBase.BLEND_METHOD.Interpolation || _iCalculatedParam == 0)
                    {
                        for (int i = 0; i < posVerts.Count; i++)
                        {
                            _result_VertWorld[i] = BlendPosition_ITP(_result_VertWorld[i], posVerts[i], _cal_curWeight);
                        }

                        _cal_prevWeight += _cal_curWeight;
                    }
                    else
                    {
                        for (int i = 0; i < posVerts.Count; i++)
                        {
                            _result_VertWorld[i] = BlendPosition_Add(_result_VertWorld[i], posVerts[i], _cal_curWeight);
                        }
                    }


                    _iCalculatedParam++;
                }

#if UNITY_EDITOR
                Profiler.EndSample();
#endif
                //Debug.Log(" >> Vert World");
            }
        }
        /// <summary>
        /// Calculate Result Statck의 업데이트 부분
        /// Pre-Update로서 VertWorld와 Rigging이 제외된다.
        /// </summary>
        public void Calculate_Pre()
        {
            //bool isFirstDebug = true;
            _cal_prevWeight  = 0.0f;
            _cal_curWeight   = 0.0f;
            _cal_resultParam = null;
            _cal_posVerts    = null;


            //Debug.Log("Is Any Vert Local : " + _isAnyVertLocal + " [" + _resultParams_VertLocal.Count +"]");
            // 1. Local Morph
            if (_isAnyVertLocal)
            {
#if UNITY_EDITOR
                Profiler.BeginSample("Calcuate Result Stack - 1. Vert Local");
#endif
                _cal_prevWeight  = 0.0f;
                _cal_curWeight   = 0.0f;
                _cal_resultParam = null;
                _cal_posVerts    = null;

                _iCalculatedParam = 0;                //<<추가 : 첫 모디파이어는 무조건 Interpolation으로 만들자

                for (int iParam = 0; iParam < _resultParams_VertLocal.Count; iParam++)
                {
                    _cal_resultParam = _resultParams_VertLocal[iParam];
                    _cal_curWeight   = _cal_resultParam.ModifierWeight;

                    if (!_cal_resultParam.IsModifierAvailable || _cal_curWeight <= 0.001f)
                    {
                        continue;
                    }

                    _cal_posVerts = _cal_resultParam._result_Positions;
                    if (_result_VertLocal == null)
                    {
                        Debug.LogError("Result Vert Local is Null");
                    }
                    if (_cal_posVerts == null)
                    {
                        Debug.LogError("Cal Pos Vert is Null");
                    }
                    if (_cal_posVerts.Count != _result_VertLocal.Length)
                    {
                        //결과가 잘못 들어왔다 갱신 필요
                        Debug.LogError("Wrong Vert Local Result (Cal : " + _cal_posVerts.Count + " / Verts : " + _result_VertLocal.Length + ")");
                        continue;
                    }

                    // Blend 방식에 맞게 Pos를 만들자
                    if (_cal_resultParam.ModifierBlendMethod == apModifierBase.BLEND_METHOD.Interpolation || _iCalculatedParam == 0)
                    {
                        for (int i = 0; i < _cal_posVerts.Count; i++)
                        {
                            _result_VertLocal[i] = BlendPosition_ITP(_result_VertLocal[i], _cal_posVerts[i], _cal_curWeight);

                            //if (isFirstDebug)
                            //{
                            //	if (_result_VertLocal[i].sqrMagnitude > 0.0f)
                            //	{
                            //		Debug.Log("Valid Result Local : " + _result_VertLocal[i]);
                            //		isFirstDebug = false;
                            //	}
                            //}
                        }

                        _cal_prevWeight += _cal_curWeight;
                    }
                    else
                    {
                        for (int i = 0; i < _cal_posVerts.Count; i++)
                        {
                            _result_VertLocal[i] = BlendPosition_Add(_result_VertLocal[i], _cal_posVerts[i], _cal_curWeight);
                        }
                    }

                    _iCalculatedParam++;
                }

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

            // 2. Mesh / MeshGroup Transformation
            if (_isAnyTransformation)
            {
#if UNITY_EDITOR
                Profiler.BeginSample("Calcuate Result Stack - 2. MeshGroup Transformation");
#endif
                _cal_prevWeight  = 0.0f;
                _cal_curWeight   = 0.0f;
                _cal_resultParam = null;

                _iCalculatedParam = 0;

                //Debug.Log("Update TF - OPT");
                for (int iParam = 0; iParam < _resultParams_Transform.Count; iParam++)
                {
                    _cal_resultParam = _resultParams_Transform[iParam];
                    _cal_curWeight   = _cal_resultParam.ModifierWeight;

                    if (!_cal_resultParam.IsModifierAvailable || _cal_curWeight <= 0.001f)
                    {
                        continue;
                    }



                    // Blend 방식에 맞게 Matrix를 만들자 하자
                    if (_cal_resultParam.ModifierBlendMethod == apModifierBase.BLEND_METHOD.Interpolation || _iCalculatedParam == 0)
                    {
                        //Debug.Log("Cal TF [ITP] : " + _cal_resultParam._result_Matrix.Pos3 + " (Weight : " + _cal_curWeight + ")");

                        BlendMatrix_ITP(_result_MeshTransform, _cal_resultParam._result_Matrix, _cal_curWeight);

                        //if (_cal_resultParam._result_Matrix.Scale2.magnitude < 0.5f || _cal_curWeight < 0.5f)
                        //{
                        //	Debug.Log("Cal TF [ITP] : " + _cal_resultParam._result_Matrix.Scale2 + " > " + _result_MeshTransform.Scale2 + " (Weight : " + _cal_curWeight + ")");
                        //}

                        _cal_prevWeight += _cal_curWeight;
                    }
                    else
                    {
                        BlendMatrix_Add(_result_MeshTransform, _cal_resultParam._result_Matrix, _cal_curWeight);
                    }

                    _iCalculatedParam++;
                }

                _result_MeshTransform.MakeMatrix();

                if (_result_MeshTransform._scale.magnitude < 0.5f)
                {
                    Debug.Log("Cal TF [ITP] : " + _result_MeshTransform._scale + " (Total Weight : " + _cal_prevWeight + ")");
                }

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

            // 3. Mesh Color
            if (_isAnyMeshColor)
            {
#if UNITY_EDITOR
                Profiler.BeginSample("Calcuate Result Stack - 3. Mesh Color");
#endif
                _cal_prevWeight  = 0.0f;
                _cal_curWeight   = 0.0f;
                _cal_resultParam = null;

                _iCalculatedParam = 0;

                _result_IsVisible       = false;
                _nMeshColorCalculated   = 0;
                _result_CalculatedColor = false;

                for (int iParam = 0; iParam < _resultParams_MeshColor.Count; iParam++)
                {
                    _cal_resultParam = _resultParams_MeshColor[iParam];
                    _cal_curWeight   = Mathf.Clamp01(_cal_resultParam.ModifierWeight);

                    if (!_cal_resultParam.IsModifierAvailable ||
                        _cal_curWeight <= 0.001f ||
                        !_cal_resultParam.IsColorValueEnabled ||
                        !_cal_resultParam._isColorCalculated                           //<<추가 : Color로 등록했지만 아예 계산이 안되었을 수도 있다.
                        )
                    {
                        continue;
                    }                    //<<TODO


                    // Blend 방식에 맞게 Matrix를 만들자 하자
                    if (_cal_resultParam.ModifierBlendMethod == apModifierBase.BLEND_METHOD.Interpolation || _iCalculatedParam == 0)
                    {
                        //_result_Color = BlendColor_ITP(_result_Color, _cal_resultParam._result_Color, _cal_prevWeight, _cal_curWeight);
                        _result_Color    = apUtil.BlendColor_ITP(_result_Color, _cal_resultParam._result_Color, _cal_curWeight);
                        _cal_prevWeight += _cal_curWeight;
                    }
                    else
                    {
                        _result_Color = apUtil.BlendColor_Add(_result_Color, _cal_resultParam._result_Color, _cal_curWeight);
                    }

                    _result_IsVisible |= _cal_resultParam._result_IsVisible;
                    _nMeshColorCalculated++;

                    _result_CalculatedColor = true;                    //<<"계산된 MeshColor" Result가 있음을 알린다.

                    _iCalculatedParam++;
                }

                if (_nMeshColorCalculated == 0)
                {
                    _result_IsVisible = true;
                }


#if UNITY_EDITOR
                Profiler.EndSample();
#endif
            }
            else
            {
                _result_IsVisible = true;
            }

            //AnyBoneTransform
            if (_isAnyBoneTransform)
            {
                _cal_prevWeight  = 0.0f;
                _cal_curWeight   = 0.0f;
                _cal_resultParam = null;

                for (int iBonePair = 0; iBonePair < _resultParams_BoneTransform.Count; iBonePair++)
                {
                    OptBoneAndModParamPair boneModPair = _resultParams_BoneTransform[iBonePair];
                    apOptBone targetBone = boneModPair._keyBone;
                    List <OptModifierAndResultParamListPair> modParamPairs = boneModPair._modParamPairs;
                    if (targetBone == null || modParamPairs.Count == 0)
                    {
                        continue;
                    }

                    _iCalculatedParam = 0;
                    _result_BoneTransform.SetIdentity();

                    apMatrix lastMatrix = new apMatrix();
                    for (int iModParamPair = 0; iModParamPair < modParamPairs.Count; iModParamPair++)
                    {
                        OptModifierAndResultParamListPair modParamPair = modParamPairs[iModParamPair];

                        for (int iParam = 0; iParam < modParamPair._resultParams.Count; iParam++)
                        {
                            _cal_resultParam = modParamPair._resultParams[iParam];

                            _cal_curWeight = _cal_resultParam.ModifierWeight;

                            if (!_cal_resultParam.IsModifierAvailable || _cal_curWeight <= 0.001f)
                            {
                                continue;
                            }



                            // Blend 방식에 맞게 Matrix를 만들자 하자
                            if (_cal_resultParam.ModifierBlendMethod == apModifierBase.BLEND_METHOD.Interpolation || _iCalculatedParam == 0)
                            {
                                BlendMatrix_ITP(_result_BoneTransform, _cal_resultParam._result_Matrix, _cal_curWeight);
                                _cal_prevWeight += _cal_curWeight;
                            }
                            else
                            {
                                BlendMatrix_Add(_result_BoneTransform, _cal_resultParam._result_Matrix, _cal_curWeight);
                            }
                            lastMatrix.SetMatrix(_cal_resultParam._result_Matrix);

                            _iCalculatedParam++;
                        }
                    }

                    //참조된 본에 직접 값을 넣어주자
                    targetBone.UpdateModifiedValue(_result_BoneTransform._pos, _result_BoneTransform._angleDeg, _result_BoneTransform._scale);

                    if (_result_BoneTransform._scale.magnitude < 0.3f && targetBone.name.Contains("Pelvis"))
                    {
                        Debug.LogError("본 사이즈가 너무 작다 : " + targetBone.name + " / Num CalParam : " + _iCalculatedParam + " / 마지막 Weight : " + _cal_curWeight + " / 마지막 Matrix : " + lastMatrix.ToString());
                    }
                }
            }
        }