//추가 : ModMeshSet을 이용한다.
 public ModWeightPair(apOptModifiedMesh_Vertex modMeshSet_Vertex)
 {
     _isCalculated      = false;
     _modMesh           = null;
     _modMeshSet_Vertex = modMeshSet_Vertex;
     _weight            = 0.0f;
 }
            public VertRigWeightTable(int vertIndex, apOptModifiedMesh modMesh)
            {
                apOptModifiedVertexRig.OptWeightPair[] weightPairs = modMesh._vertRigs[vertIndex]._weightPairs;

                _rigTable = new RigBoneWeightPair[weightPairs.Length];

                //float totalWeight = 0.0f;
                _totalRiggingWeight = 0.0f;
                for (int i = 0; i < weightPairs.Length; i++)
                {
                    _rigTable[i]         = new RigBoneWeightPair(modMesh._targetTransform, weightPairs[i]._bone, weightPairs[i]._weight);
                    _totalRiggingWeight += weightPairs[i]._weight;
                }
                //Debug.Log("VertRigWeightTable : " + totalWeight);

                //RiggingMatrix를 위해서는 무조건 Normalize를 해야한다.
                //주의 : _totalRiggingWeight이 값은 1이 아닌 원래의 Weight 합을 유지해야한다. 보간시 필요
                if (_totalRiggingWeight > 0.0f)
                {
                    for (int i = 0; i < _rigTable.Length; i++)
                    {
                        _rigTable[i]._weight /= _totalRiggingWeight;
                    }
                }
                _nRigTable = _rigTable.Length;
            }
        // Functions
        //-----------------------------------------------
        public void AddModMesh(apOptModifiedMesh modMesh)
        {
            if (_requestType == REQUEST_TYPE.VertLocal)
            {
                _modWeightPairs.Add(new ModWeightPair(modMesh));
                _nModWeightPairs = _modWeightPairs.Count;
            }
            else if (_requestType == REQUEST_TYPE.Rigging)
            {
                if (_rigBoneWeightTables != null)
                {
                    //??
                    //Rigging은 Static 타입이어서 ModMesh가 하나만 생성된다.
                    Debug.LogError("Overwritten Mod Mesh To Rigging");
                    return;
                }
                //_totalRiggingWeight = 0.0f;
                _rigBoneWeightTables = new VertRigWeightTable[modMesh._vertRigs.Length];

                for (int i = 0; i < modMesh._vertRigs.Length; i++)
                {
                    _rigBoneWeightTables[i] = new VertRigWeightTable(i, modMesh);
                    //_totalRiggingWeight += _rigBoneWeightTables[i]._totalRiggingWeight;//<<추가 RiggingWeight를 계산합시다.
                }
            }
        }
Beispiel #4
0
            /// <summary>
            /// ModMesh와 연동되는 ParamKeyValue 생성
            /// </summary>
            public OptParamKeyValueSet(apOptParamSetGroup keyParamSetGroup, apOptParamSet paramSet, apOptModifiedMesh modifiedMesh)
            {
                _keyParamSetGroup = keyParamSetGroup;
                _paramSet         = paramSet;
                _modifiedMesh     = modifiedMesh;
                _layerIndex       = _keyParamSetGroup._layerIndex;

                _modifiedBone = null;
            }
        public void Link(apOptModifiedMesh modifiedMesh, apOptTransform optTransform, apOptMesh mesh, apOptRenderVertex vertex)
        {
            _modifiedMesh = modifiedMesh;
            _mesh         = mesh;
            _vertex       = vertex;
            _optTransform = optTransform;

            if (_physicParam != null)
            {
                _physicParam.Link(modifiedMesh, this);
            }

            DampPhysicVertex();
        }
Beispiel #6
0
            /// <summary>
            /// ModBone과 연동되는 ParamKeyValue 생성
            /// </summary>
            public OptParamKeyValueSet(apOptParamSetGroup keyParamSetGroup, apOptParamSet paramSet, apOptModifiedBone modifiedBone)
            {
                _keyParamSetGroup = keyParamSetGroup;
                _paramSet         = paramSet;
                _modifiedMesh     = null;
                _layerIndex       = _keyParamSetGroup._layerIndex;

                _modifiedBone = modifiedBone;

                //추가 : RotationBias
                _isAnimRotationBias         = false;
                _animRotationBiasAngle      = 0;
                _animRotationBiasAngle_Prev = -1;
                _animRotationBiasedMatrix   = new apMatrix();
            }
Beispiel #7
0
        /// <summary>
        /// Linked Vertex의 객체를 Link한다.
        /// </summary>
        /// <param name="parentModMesh"></param>
        public void Link(apOptModifiedMesh parentModMesh, apOptModifiedVertexWeight parentModVertWeight)
        {
            _parentModMesh = parentModMesh;
            //_parentModVertWeight = parentModVertWeight;

            if (_linkedVertices == null)
            {
                _linkedVertices = new List <OptLinkedVertex>();
            }


            apOptMesh mesh = parentModMesh._targetMesh;

            //이미 Bake 되었으므로 바로 Link하면 된다.
            for (int i = 0; i < _linkedVertices.Count; i++)
            {
                OptLinkedVertex           linkedVert     = _linkedVertices[i];
                apOptRenderVertex         renderVert     = mesh.RenderVertices[linkedVert._vertIndex];
                apOptModifiedVertexWeight linkVertWeight = _parentModMesh._vertWeights[linkedVert._vertIndex];
                linkedVert.Link(renderVert, linkVertWeight);
            }
        }
            public VertRigWeightTable(int vertIndex, apOptModifiedMesh modMesh)
            {
                apOptModifiedVertexRig.OptWeightPair[] weightPairs = modMesh._vertRigs[vertIndex]._weightPairs;


                _rigTable = new RigBoneWeightPair[weightPairs.Length];

                float totalWeight = 0.0f;

                for (int i = 0; i < weightPairs.Length; i++)
                {
                    _rigTable[i] = new RigBoneWeightPair(modMesh._targetTransform, weightPairs[i]._bone, weightPairs[i]._weight);
                    totalWeight += weightPairs[i]._weight;
                }

                if (totalWeight < 1.0f && totalWeight > 0.0f)
                {
                    for (int i = 0; i < _rigTable.Length; i++)
                    {
                        _rigTable[i]._weight /= totalWeight;
                    }
                }
                _nRigTable = _rigTable.Length;
            }
Beispiel #9
0
        /// <summary>
        /// ParamSet을 받아서 SubList와 연동한다.
        /// </summary>
        /// <param name="paramSet"></param>
        /// <returns></returns>
        public void AddParamSetAndModifiedValue(apOptParamSetGroup paramSetGroup,
                                                apOptParamSet paramSet,
                                                apOptModifiedMesh modifiedMesh,
                                                apOptModifiedBone modifiedBone)
        {
            OptParamKeyValueSet existSet = GetParamKeyValue(paramSet);

            if (existSet != null)
            {
                //이미 존재한 값이라면 패스
                return;
            }

            //새로운 KeyValueSet을 만들어서 리스트에 추가하자
            //Mod Mesh 또는 Mod Bone 둘중 하나를 넣어서 ParamKeyValueSet을 구성하자
            OptParamKeyValueSet newKeyValueSet = null;

            if (modifiedMesh != null)
            {
                newKeyValueSet = new OptParamKeyValueSet(paramSetGroup, paramSet, modifiedMesh);
            }
            else if (modifiedBone != null)
            {
                newKeyValueSet = new OptParamKeyValueSet(paramSetGroup, paramSet, modifiedBone);
            }
            else
            {
                Debug.LogError("AddParamSetAndModifiedMesh Error : ModifiedMesh와 ModifiedBone이 모두 Null이다.");
                return;
            }

            _paramKeyValues.Add(newKeyValueSet);

            apOptCalculatedResultParamSubList targetSubList = null;

            apOptCalculatedResultParamSubList existSubList = _subParamKeyValueList.Find(delegate(apOptCalculatedResultParamSubList a)
            {
                return(a._keyParamSetGroup == paramSetGroup);
            });

            //같이 묶여서 작업할 SubList가 있는가
            if (existSubList != null)
            {
                targetSubList = existSubList;
            }
            else
            {
                //없으면 만든다.
                targetSubList = new apOptCalculatedResultParamSubList(this, _isVertexLocalMorph, _isVertexRigging);
                targetSubList.SetParamSetGroup(paramSetGroup);

                _subParamKeyValueList.Add(targetSubList);

                if (_isVertexLocalMorph || _isVertexRigging)
                {
                    //VertexRequest를 전체 리스트로 추가하여 관리하자
                    if (_result_VertLocalPairs == null)
                    {
                        _result_VertLocalPairs = new List <apOptVertexRequest>();
                    }

                    _result_VertLocalPairs.Add(targetSubList._vertexRequest);
                }
            }

            //해당 SubList에 위에서 만든 KeyValueSet을 추가하자
            if (targetSubList != null)
            {
                targetSubList.AddParamKeyValueSet(newKeyValueSet);
            }

            _isAnimModifier = (paramSetGroup._syncTarget == apModifierParamSetGroup.SYNC_TARGET.KeyFrame);
        }
Beispiel #10
0
 public ModWeightPair(apOptModifiedMesh modMesh)
 {
     _isCalculated = false;
     _modMesh      = modMesh;
     _weight       = 0.0f;
 }
        public void BakeModifierParamSet(apModifierParamSet srcParamSet, apPortrait portrait)
        {
            //switch (srcParamSet._syncTarget)
            //{
            //	case apModifierParamSet.SYNC_TARGET.Static:
            //		_syncTarget = SYNC_TARGET.Static;
            //		break;

            //	case apModifierParamSet.SYNC_TARGET.Controller:
            //		_syncTarget = SYNC_TARGET.Controller;
            //		break;

            //	case apModifierParamSet.SYNC_TARGET.KeyFrame:
            //		_syncTarget = SYNC_TARGET.KeyFrame;
            //		break;

            //	default:
            //		Debug.LogError("연동 에러 : ParamSet에 정의되지 않은 타입 : " + srcParamSet._syncTarget);
            //		break;
            //}

            //_controlKeyName = srcParamSet._controlKeyName;

            //_conSyncValue_Bool = srcParamSet._conSyncValue_Bool;
            _conSyncValue_Int     = srcParamSet._conSyncValue_Int;
            _conSyncValue_Float   = srcParamSet._conSyncValue_Float;
            _conSyncValue_Vector2 = srcParamSet._conSyncValue_Vector2;
            //_conSyncValue_Vector3 = srcParamSet._conSyncValue_Vector3;
            //_conSyncValue_Color = srcParamSet._conSyncValue_Color;


            _keyframeUniqueID = srcParamSet._keyframeUniqueID;
            _syncKeyframe     = null;

            _overlapWeight = srcParamSet._overlapWeight;            //OverlapWeight를 집어넣자

            _meshData.Clear();
            _boneData.Clear();


            //SrcModifier ParamSet의 ModMesh, ModBone을 Bake해주자
            //Debug.LogError("TODO : Bone 데이터 연동");
            for (int i = 0; i < srcParamSet._meshData.Count; i++)
            {
                apModifiedMesh    srcModMesh = srcParamSet._meshData[i];
                apOptModifiedMesh optModMesh = new apOptModifiedMesh();
                bool isResult = optModMesh.Bake(srcModMesh, portrait);
                if (isResult)
                {
                    _meshData.Add(optModMesh);
                }
            }

            //추가 : ModBone
            for (int i = 0; i < srcParamSet._boneData.Count; i++)
            {
                apModifiedBone    srcModBone = srcParamSet._boneData[i];
                apOptModifiedBone optModBone = new apOptModifiedBone();
                bool isResult = optModBone.Bake(srcModBone, portrait);
                if (isResult)
                {
                    _boneData.Add(optModBone);
                }
            }
        }
        //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이 연결이 안되었다");
            }
        }
Beispiel #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);
                }
            }
        }
        public void BakeModifierParamSet(apModifierParamSet srcParamSet, apPortrait portrait, bool isUseModMeshSet)
        {
            _conSyncValue_Int     = srcParamSet._conSyncValue_Int;
            _conSyncValue_Float   = srcParamSet._conSyncValue_Float;
            _conSyncValue_Vector2 = srcParamSet._conSyncValue_Vector2;


            _keyframeUniqueID = srcParamSet._keyframeUniqueID;
            _syncKeyframe     = null;

            _overlapWeight = srcParamSet._overlapWeight;            //OverlapWeight를 집어넣자

            _meshData.Clear();
            _boneData.Clear();

            //19.5.23 : meshSetData 추가
            if (_meshSetData == null)
            {
                _meshSetData = new List <apOptModifiedMeshSet>();
            }
            _meshSetData.Clear();
            _isUseModMeshSet = isUseModMeshSet;            //<<이 값이 1.1.7부터는 true가 된다.


            if (!_isUseModMeshSet)
            {
                //이전버전
                //SrcModifier ParamSet의 ModMesh, ModBone을 Bake해주자
                for (int i = 0; i < srcParamSet._meshData.Count; i++)
                {
                    apModifiedMesh    srcModMesh = srcParamSet._meshData[i];
                    apOptModifiedMesh optModMesh = new apOptModifiedMesh();
                    bool isResult = optModMesh.Bake(srcModMesh, portrait);
                    if (isResult)
                    {
                        _meshData.Add(optModMesh);
                    }
                }
            }
            else
            {
                //변경된 버전 : 19.5.23 (v.1.1.7)
                for (int i = 0; i < srcParamSet._meshData.Count; i++)
                {
                    apModifiedMesh       srcModMesh    = srcParamSet._meshData[i];
                    apOptModifiedMeshSet optModMeshSet = new apOptModifiedMeshSet();
                    bool isResult = optModMeshSet.Bake(
                        srcParamSet._parentParamSetGroup._parentModifier,
                        srcParamSet._parentParamSetGroup,
                        srcModMesh,
                        portrait);
                    if (isResult)
                    {
                        _meshSetData.Add(optModMeshSet);
                    }
                }
            }


            //ModBone
            for (int i = 0; i < srcParamSet._boneData.Count; i++)
            {
                apModifiedBone    srcModBone = srcParamSet._boneData[i];
                apOptModifiedBone optModBone = new apOptModifiedBone();
                bool isResult = optModBone.Bake(srcModBone, portrait);
                if (isResult)
                {
                    _boneData.Add(optModBone);
                }
            }
        }