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); }
// 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; }
//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()); } } } }