public void Move__MeshGroup_Setting(Vector2 curMouseGL, Vector2 curMousePosW, Vector2 deltaMoveW, int btnIndex, bool isFirstMove) { if (Editor.Select.MeshGroup == null || !Editor.Select.IsMeshGroupSettingChangePivot) { return; } if (deltaMoveW.sqrMagnitude == 0.0f) { return; } apMatrix targetMatrix = null; object targetObj = null; apMatrix worldMatrix = null; apMatrix parentWorldMatrix = null; //Modifier가 적용이 안된 상태이므로 //World Matrix = ParentWorld x ToParent(Default) 가 성립한다. if (Editor.Select.SubMeshInGroup != null) { targetMatrix = Editor.Select.SubMeshInGroup._matrix; //=ToParent targetObj = Editor.Select.SubMeshInGroup; worldMatrix = new apMatrix(Editor.Select.SubMeshInGroup._matrix_TFResult_World); parentWorldMatrix = Editor.Select.SubMeshInGroup._matrix_TF_ParentWorld; } else if (Editor.Select.SubMeshGroupInGroup != null) { targetMatrix = Editor.Select.SubMeshGroupInGroup._matrix; //=ToParent targetObj = Editor.Select.SubMeshGroupInGroup; worldMatrix = new apMatrix(Editor.Select.SubMeshGroupInGroup._matrix_TFResult_World); parentWorldMatrix = Editor.Select.SubMeshGroupInGroup._matrix_TF_ParentWorld; } else { return; } worldMatrix._pos += deltaMoveW; worldMatrix.MakeMatrix(); worldMatrix.RInverse(parentWorldMatrix); //ParentWorld-1 x World = ToParent Vector2 newLocalPos = worldMatrix._pos; //Undo apEditorUtil.SetRecord(apUndoGroupData.ACTION.MeshGroup_Gizmo_MoveTransform, Editor.Select.MeshGroup, targetObj, false, Editor); //targetMatrix.SetPos(targetMatrix._pos.x + deltaMoveW.x, targetMatrix._pos.y + deltaMoveW.y); targetMatrix.SetPos(newLocalPos.x, newLocalPos.y); targetMatrix.MakeMatrix(); //Editor.RefreshControllerAndHierarchy(); }
public void TransformChanged_Position__MeshGroup_Setting(Vector2 pos, int depth) { if (Editor.Select.MeshGroup == null || !Editor.Select.IsMeshGroupSettingChangePivot) { return; } if (Editor.Select.SubMeshInGroup == null && Editor.Select.SubMeshGroupInGroup == null) { return; } apRenderUnit curRenderUnit = null; apMatrix curMatrixParam = null; object targetObj = null; if (Editor.Select.SubMeshInGroup != null) { curRenderUnit = Editor.Select.MeshGroup.GetRenderUnit(Editor.Select.SubMeshInGroup); curMatrixParam = Editor.Select.SubMeshInGroup._matrix; targetObj = Editor.Select.SubMeshInGroup; } else if (Editor.Select.SubMeshGroupInGroup != null) { curRenderUnit = Editor.Select.MeshGroup.GetRenderUnit(Editor.Select.SubMeshGroupInGroup); curMatrixParam = Editor.Select.SubMeshGroupInGroup._matrix; targetObj = Editor.Select.SubMeshGroupInGroup; } if (curRenderUnit == null) { return; } //Undo apEditorUtil.SetRecord(apUndoGroupData.ACTION.MeshGroup_Gizmo_MoveTransform, Editor.Select.MeshGroup, targetObj, false, Editor); bool bSort = false; if (curRenderUnit.GetDepth() != depth) { //curRenderUnit.SetDepth(depth); Editor.Select.MeshGroup.ChangeRenderUnitDetph(curRenderUnit, depth); bSort = true; } curMatrixParam.SetPos(pos); curMatrixParam.MakeMatrix(); if (bSort) { Editor.Select.MeshGroup.SortRenderUnits(true); } Editor.SetRepaint(); }
public void TransformChanged_Position__MeshGroup_Setting(Vector2 pos) { if (Editor.Select.MeshGroup == null || !Editor.Select.IsMeshGroupSettingChangePivot) { return; } if (Editor.Select.SubMeshInGroup == null && Editor.Select.SubMeshGroupInGroup == null) { return; } apRenderUnit curRenderUnit = null; apMatrix curMatrixParam = null; object targetObj = null; if (Editor.Select.SubMeshInGroup != null) { curRenderUnit = Editor.Select.MeshGroup.GetRenderUnit(Editor.Select.SubMeshInGroup); curMatrixParam = Editor.Select.SubMeshInGroup._matrix; targetObj = Editor.Select.SubMeshInGroup; } else if (Editor.Select.SubMeshGroupInGroup != null) { curRenderUnit = Editor.Select.MeshGroup.GetRenderUnit(Editor.Select.SubMeshGroupInGroup); curMatrixParam = Editor.Select.SubMeshGroupInGroup._matrix; targetObj = Editor.Select.SubMeshGroupInGroup; } if (curRenderUnit == null) { return; } //Undo apEditorUtil.SetRecord_MeshGroup(apUndoGroupData.ACTION.MeshGroup_Gizmo_MoveTransform, Editor, Editor.Select.MeshGroup, targetObj, false, true); curMatrixParam.SetPos(pos); curMatrixParam.MakeMatrix(); Editor.SetRepaint(); }
/// <summary> /// MeshGroup 메뉴 + Modifier 중 Rigging Modifier에서만 제어할 수 있다. /// Rigging 테스트를 위해 임시 WorldMatrix를 만들어서 움직인다. /// Rigging Modifier 활성할때마다 변수가 초기화됨. /// 자식 MeshGroup의 Bone도 제어 가능하다 (!) /// Default와 달리 IK Lock이 걸려있으므로 IK 계산을 해야한다. /// </summary> /// <param name="curMouseGL"></param> /// <param name="curMousePosW"></param> /// <param name="deltaMoveW"></param> /// <param name="btnIndex"></param> /// <param name="isFirstMove"></param> public void Move__Modifier_Rigging(Vector2 curMouseGL, Vector2 curMousePosW, Vector2 deltaMoveW, int btnIndex, bool isFirstMove) { if (Editor.Select.MeshGroup == null || Editor.Select.Bone == null || Editor._boneGUIRenderMode != apEditor.BONE_RENDER_MODE.Render || Editor.Select.Modifier == null || //<<Modifier가 null이면 안된다. !Editor.Controller.IsMouseInGUI(curMouseGL) || deltaMoveW.sqrMagnitude == 0.0f ) { return; } apBone bone = Editor.Select.Bone; apMeshGroup meshGroup = Editor.Select.MeshGroup; apMeshGroup boneParentMeshGroup = bone._meshGroup; //Bone이 속한 MeshGroup. 다를 수 있다. apModifierBase modifier = Editor.Select.Modifier; //선택한 Modifier if (modifier.ModifierType != apModifierBase.MODIFIER_TYPE.Rigging) { //리깅 Modifier가 아니라면 패스 return; } if (!Editor.Select.IsRigEditTestPosing) { //TestPosing이 허용되지 않았다면 패스 return; } _boneSelectPosW = curMousePosW; //Move로 제어 가능한 경우는 //1. IK Tail일 때 //2. Root Bone일때 (절대값) if (bone._isIKTail) { //Debug.Log("Request IK : " + _boneSelectPosW); float weight = 1.0f; if (deltaMoveW.sqrMagnitude < 5.0f) { //weight = 0.2f; } //bool successIK = bone.RequestIK(_boneSelectPosW, weight, !isFirstSelectBone); bool successIK = bone.RequestIK(_boneSelectPosW, weight, true); if (!successIK) { return; } apBone headBone = bone._IKHeaderBone; if (headBone != null) { apBone curBone = bone; //위로 올라가면서 IK 결과값을 Default에 적용하자 while (true) { float deltaAngle = curBone._IKRequestAngleResult; //float nextAngle = curBone._defaultMatrix._angleDeg + deltaAngle; float nextAngle = curBone._rigTestMatrix._angleDeg + deltaAngle; //Rig Test로 할 것 if (nextAngle < -180.0f) { nextAngle += 360.0f; } if (nextAngle > 180.0f) { nextAngle -= 360.0f; } //curBone._defaultMatrix.SetRotate(nextAngle); curBone._rigTestMatrix.SetRotate(nextAngle); curBone._isIKCalculated = false; curBone._IKRequestAngleResult = 0.0f; if (curBone == headBone) { break; } if (curBone._parentBone == null) { break; } curBone = curBone._parentBone; } //마지막으론 World Matrix 갱신 headBone.MakeWorldMatrix(true); headBone.GUIUpdate(true); } } else if (bone._parentBone == null) { apMatrix renderUnitMatrix = null; if (bone._renderUnit != null) { //Render Unit의 World Matrix를 참조하여 //로컬 값을 Default로 적용하자 renderUnitMatrix = bone._renderUnit.WorldMatrixWrap; } apMatrix localMatrix = bone._localMatrix; apMatrix newWorldMatrix = new apMatrix(bone._worldMatrix); newWorldMatrix.SetPos(newWorldMatrix._pos + deltaMoveW); if (renderUnitMatrix != null) { newWorldMatrix.RInverse(renderUnitMatrix); } newWorldMatrix.Subtract(localMatrix); //이건 Add로 연산된거라 Subtract해야한다. //bone._defaultMatrix.SetPos(newWorldMatrix._pos); bone._rigTestMatrix.SetPos(newWorldMatrix._pos - bone._defaultMatrix._pos); bone.MakeWorldMatrix(true); bone.GUIUpdate(true); } }
//------------------------------------------------------------------------------------------------------------ // Bone - Move (Default / Rigging Test / Modifier / AnimClip Modifier) // Local Move / IK 처리 옵션에 따라 변경 값이 다르다 // Local Move / IK는 "허용하는 경우" 서로 배타적으로 수정한다. (토글 버튼을 두자) // (1) Local Move : Parent에 상관없이 Local Position을 바꾼다. RootNode를 제외하고는 모두 Off. // (2) IK : 제어한 마우스 위치에 맞게 Parent들을 회전한다. 실제로 Local Postion이 바뀌진 않다. // IK가 설정되어있다면 다중 IK 처리를 하며, 그렇지 않다면 바로 위의 Parent만 IK를 적용한다. (Root 제외) //------------------------------------------------------------------------------------------------------------ /// <summary> /// MeshGroup 메뉴에서 Bone의 Default 편집 중의 이동 /// Edit Mode가 Select로 활성화되어있어야 한다. /// 선택한 Bone이 현재 선택한 MeshGroup에 속해있어야 한다. /// IK Lock 여부에 따라 값이 바뀐다. /// IK Lock이 걸려있을 때) Parent 본의 Default Rotate가 바뀐다. (해당 Bone의 World를 만들어주기 위해서) /// IK Lock이 걸려있지않을 때) 해당 Bone의 Default Pos가 바뀐다. /// </summary> /// <param name="curMouseGL"></param> /// <param name="curMousePosW"></param> /// <param name="deltaMoveW"></param> /// <param name="btnIndex"></param> /// <param name="isFirstMove"></param> public void Move__Bone_Default(Vector2 curMouseGL, Vector2 curMousePosW, Vector2 deltaMoveW, int btnIndex, bool isFirstMove) { if (Editor.Select.MeshGroup == null || Editor.Select.Bone == null || Editor._boneGUIRenderMode != apEditor.BONE_RENDER_MODE.Render || Editor.Select.BoneEditMode != apSelection.BONE_EDIT_MODE.SelectAndTRS || !Editor.Controller.IsMouseInGUI(curMouseGL) ) { return; } if (deltaMoveW.sqrMagnitude == 0.0f && !isFirstMove) { return; } apBone bone = Editor.Select.Bone; apMeshGroup meshGroup = Editor.Select.MeshGroup; if (bone._meshGroup != meshGroup) { //직접 속하지 않고 자식 MeshGroup의 Transform인 경우 제어할 수 없다. return; } if (isFirstMove) { apEditorUtil.SetRecord_MeshGroup(apUndoGroupData.ACTION.MeshGroup_BoneDefaultEdit, Editor, bone._meshGroup, null, false, false); } //bool isFirstSelectBone = false; //TODO.. if (_isBoneSelect_MovePosReset) { _boneSelectPosW = bone._worldMatrix._pos; _isBoneSelect_MovePosReset = false; //isFirstSelectBone = true; } else { _boneSelectPosW += deltaMoveW; //<<여기에 IK를 걸어주자 } _boneSelectPosW = curMousePosW; //Move로 제어 가능한 경우는 //1. IK Tail일 때 //2. Root Bone일때 (절대값) if (bone._isIKTail) { //Debug.Log("Request IK : " + _boneSelectPosW); float weight = 1.0f; if (deltaMoveW.sqrMagnitude < 5.0f) { //weight = 0.2f; } //bool successIK = bone.RequestIK(_boneSelectPosW, weight, !isFirstSelectBone); bool successIK = bone.RequestIK(_boneSelectPosW, weight, true); if (!successIK) { return; } apBone headBone = bone._IKHeaderBone; if (headBone != null) { apBone curBone = bone; //위로 올라가면서 IK 결과값을 Default에 적용하자 while (true) { float deltaAngle = curBone._IKRequestAngleResult; //if(Mathf.Abs(deltaAngle) > 30.0f) //{ // deltaAngle *= deltaAngle * 0.1f; //} float nextAngle = curBone._defaultMatrix._angleDeg + deltaAngle; nextAngle = apUtil.AngleTo180(nextAngle); curBone._defaultMatrix.SetRotate(nextAngle); curBone._isIKCalculated = false; curBone._IKRequestAngleResult = 0.0f; if (curBone == headBone) { break; } if (curBone._parentBone == null) { break; } curBone = curBone._parentBone; } //마지막으론 World Matrix 갱신 headBone.MakeWorldMatrix(true); headBone.GUIUpdate(true); } } else if (bone._parentBone == null || (bone._parentBone._IKNextChainedBone != bone)) { //수정 : Parent가 있지만 IK로 연결 안된 경우 / Parent가 없는 경우 2가지 모두 처리한다. apMatrix parentMatrix = null; if (bone._parentBone == null) { if (bone._renderUnit != null) { //Render Unit의 World Matrix를 참조하여 //로컬 값을 Default로 적용하자 parentMatrix = bone._renderUnit.WorldMatrixWrap; } } else { parentMatrix = bone._parentBone._worldMatrix; } apMatrix localMatrix = bone._localMatrix; apMatrix newWorldMatrix = new apMatrix(bone._worldMatrix); newWorldMatrix.SetPos(newWorldMatrix._pos + deltaMoveW); if (parentMatrix != null) { newWorldMatrix.RInverse(parentMatrix); } newWorldMatrix.Subtract(localMatrix); //이건 Add로 연산된거라 Subtract해야한다. bone._defaultMatrix.SetPos(newWorldMatrix._pos); bone.MakeWorldMatrix(true); bone.GUIUpdate(true); } }
public apMatrix GetSubInverseLayeredMatrix(apCalculatedLog targetLog, apCalculatedLog parentLog, apMatrix parentMatrix) { apMatrix invUpperLayerMatrix = new apMatrix(parentMatrix); apMatrix lowerLayerMatrix = new apMatrix(); //타겟보다 낮은 레이어는 따로 합을 구한다. LOG_TYPE layerLogType = targetLog._logType; int nLayers = 0; int iLayer = -1; if (layerLogType == LOG_TYPE.Layer_CalParamResult) { nLayers = parentLog._childCalParamResultLogs.Count; iLayer = parentLog._childCalParamResultLogs.IndexOf(targetLog); } else if (layerLogType == LOG_TYPE.Layer_ParamSetGroup) { nLayers = parentLog._childLayerLogs.Count; iLayer = parentLog._childLayerLogs.IndexOf(targetLog); } else { Debug.LogError("Layer가 없는 LogType [" + layerLogType + "] 이다"); return(null); } if (iLayer < 0) { Debug.LogError("존재하지 않는 Log [" + layerLogType + "]"); return(null); } lowerLayerMatrix.SetIdentity(); //Debug.LogWarning(">> Lower To Layer [0 > " + iLayer + "]"); //낮은 레이어에서는 값을 더하자 if (iLayer > 0) { for (int i = 0; i < iLayer; i++) { apCalculatedLog calLog = null; apMatrix calMatrix = null; switch (layerLogType) { case LOG_TYPE.Layer_CalParamResult: calLog = parentLog._childCalParamResultLogs[i]; calMatrix = calLog._calResultParam._result_Matrix; break; case LOG_TYPE.Layer_ParamSetGroup: calLog = parentLog._childLayerLogs[i]; calMatrix = calLog._paramSetGroup._tmpMatrix; break; } float weight = calLog._weight; if (!calLog._isWeight) { weight = 1.0f; } //string prevMatrix = lowerLayerMatrix.ToString(); if (i == 0) { lowerLayerMatrix.SetPos(calMatrix._pos * weight); lowerLayerMatrix.SetRotate(calMatrix._angleDeg * weight); lowerLayerMatrix.SetScale(calMatrix._scale * weight + Vector2.one * (1.0f - weight)); lowerLayerMatrix.MakeMatrix(); } else { switch (calLog._layerBlendType) { case BLEND_METHOD.Interpolation: BlendMatrix_ITP(lowerLayerMatrix, calMatrix, weight); //Debug.Log("[" + i + "] ITP/" + weight + " : " + prevMatrix + " >> " + calMatrix + " => " + lowerLayerMatrix); break; case BLEND_METHOD.Additive: BlendMatrix_Add(lowerLayerMatrix, calMatrix, weight); //Debug.Log("[" + i + "] ADD/" + weight + " : " + prevMatrix + " >> " + calMatrix + " => " + lowerLayerMatrix); break; } } } } //Debug.LogWarning(">> Upper To Layer [" + (nLayers - 1) + " > " + iLayer + "]"); //위 레이어에서는 값을 빼자 if (iLayer < nLayers - 1) { for (int i = (nLayers - 1); i >= iLayer + 1; i--) { apCalculatedLog calLog = null; apMatrix calMatrix = null; switch (layerLogType) { case LOG_TYPE.Layer_CalParamResult: calLog = parentLog._childCalParamResultLogs[i]; calMatrix = calLog._calResultParam._result_Matrix; break; case LOG_TYPE.Layer_ParamSetGroup: calLog = parentLog._childLayerLogs[i]; calMatrix = calLog._paramSetGroup._tmpMatrix; break; } float weight = calLog._weight; if (!calLog._isWeight) { weight = 1.0f; } switch (calLog._layerBlendType) { case BLEND_METHOD.Interpolation: InverseBlendMatrix_ITP(invUpperLayerMatrix, calMatrix, weight); break; case BLEND_METHOD.Additive: InverseBlendMatrix_Add(invUpperLayerMatrix, calMatrix, weight); break; } } } apMatrix result = null; float weight_calParam = targetLog._weight; if (!targetLog._isWeight) { weight_calParam = 1.0f; } apMatrix calTargetMatrix = null; switch (layerLogType) { case LOG_TYPE.Layer_CalParamResult: calTargetMatrix = targetLog._calResultParam._result_Matrix; break; case LOG_TYPE.Layer_ParamSetGroup: calTargetMatrix = targetLog._paramSetGroup._tmpMatrix; break; } switch (targetLog._layerBlendType) { case BLEND_METHOD.Additive: result = InverseBlendMatrixTarget_Add(invUpperLayerMatrix, lowerLayerMatrix, calTargetMatrix, weight_calParam); break; case BLEND_METHOD.Interpolation: result = InverseBlendMatrixTarget_ITP(invUpperLayerMatrix, lowerLayerMatrix, calTargetMatrix, weight_calParam); break; } if (result == null) { return(null); } return(result); }
public InverseResult World2ModLocalPos_TransformRotationScaling(float deltaRotateAngle, Vector2 deltaScale) { if (_modMesh == null) { Debug.LogError("World2ModLocalPos_Transform 실패 : ModMesh에서 호출하지 않았다."); return(null); } if (_modMesh._transform_Mesh == null) { Debug.LogError("World2ModLocalPos_Transform 실패 : ModMesh의 MeshTransform이 Null이다."); return(null); } //현재 위치를 받자 //이제 위로 하나씩 계산하면서 어떤 CalculateLog가 기록되었는지 확인하자 //StatckLResultLayer까지 올라가면 된다. (거기는 값이 고정이므로) apCalculatedLog modified = this; apCalculatedLog layer_ParamSetGroup = modified._parentLayerLog; apCalculatedLog layer_CalParamResult = layer_ParamSetGroup._parentLayerLog; apCalculatedLog stackLayer_MeshTransform = layer_CalParamResult._parentCalResultStackLayer; apCalculatedLog transform_Modified = stackLayer_MeshTransform._parentTF_Modified; //현재 posW 를 저장하자 Vector2 posW_prev = _modMesh._transform_Mesh._matrix_TFResult_World._pos; //일단 회전값/스케일을 추가하자 apMatrix RSModMatrix = new apMatrix(_modMesh._transform_Mesh._matrix_TF_LocalModified); RSModMatrix.SetRotate(RSModMatrix._angleDeg + deltaRotateAngle); RSModMatrix.SetScale(RSModMatrix._scale + deltaScale); apMatrix RSWorldMatrix = new apMatrix(_modMesh._transform_Mesh._matrix_TF_ToParent); RSWorldMatrix.RMultiply(RSModMatrix); RSWorldMatrix.RMultiply(_modMesh._transform_Mesh._matrix_TF_ParentWorld); //이 WorldMatrix의 계산 후 Position을 확인하자 Vector2 posW_rs = RSWorldMatrix._pos; //posW_rotated가 아닌 posW_prev로 돌려야 한다. 고치자. Vector2 deltaPosW = posW_prev - posW_rs; _inverseResult.Request(posW_rs, deltaPosW); //이제 역으로 내려오자 // ParentWorld <- Modified <- ToParent = World // [Modified <- ToParent] = [ParentWorld-1 <- World] // Modified = [ParentWorld-1 <- World <- ToParent-1] apMatrix worldMatrix_next = new apMatrix(RSWorldMatrix); worldMatrix_next.SetPos(worldMatrix_next._pos + deltaPosW); apMatrix modMatrix_next = transform_Modified._meshTransform._matrix_TF_ToParent.RInverseMatrix; modMatrix_next.RMultiply(worldMatrix_next); modMatrix_next.RInverse(transform_Modified._meshTransform._matrix_TF_ParentWorld); //위 수식은 "StackLayer-MeshTF" 레벨에서 계산된 것이다. //StackLayer -> CalParam -> ParamSetGroup으로 이동하자. apMatrix modMatrix_paramSet = GetInverseInterpolatedMatrix(layer_ParamSetGroup, layer_CalParamResult, stackLayer_MeshTransform, modMatrix_next); if (modMatrix_paramSet == null) { Debug.LogError("StackLayer -> CalParam -> ParamSetGroup 전환에 실패했다."); return(null); } //_inverseResult.SetResult(transform_Modified._meshTransform._matrix_TF_LocalModified._pos, // modMatrix_next._pos); _inverseResult.SetResult(transform_Modified._meshTransform._matrix_TF_LocalModified._pos, modMatrix_paramSet._pos); return(_inverseResult); }
/// <summary> /// Modified 단계에서 위로 검색하여 현재 World Position으로부터 다시 Local로 내려온다. /// 결과값은 ModMesh(TF)의 TransformMatrix에 사용될 값으로 변환된다. /// ModMesh에서 호출해야한다. /// </summary> /// <param name="deltaPosW"></param> /// <returns></returns> //public InverseResult World2ModLocalPos_TransformMove(Vector2 nextPosW) public InverseResult World2ModLocalPos_TransformMove(Vector2 nextPosW, Vector2 deltaPosW) { if (_modMesh == null) { Debug.LogError("World2ModLocalPos_Transform 실패 : ModMesh에서 호출하지 않았다."); return(null); } if (_modMesh._transform_Mesh == null) { Debug.LogError("World2ModLocalPos_Transform 실패 : ModMesh의 MeshTransform이 Null이다."); return(null); } //현재 위치를 받자 Vector2 posW_prev = _modMesh._transform_Mesh._matrix_TFResult_World._pos; //Vector2 deltaPosW = nextPosW - posW_prev; nextPosW = posW_prev + deltaPosW; _inverseResult.Request(posW_prev, deltaPosW); //이제 위로 하나씩 계산하면서 어떤 CalculateLog가 기록되었는지 확인하자 //StatckLResultLayer까지 올라가면 된다. (거기는 값이 고정이므로) apCalculatedLog modified = this; apCalculatedLog layer_ParamSetGroup = modified._parentLayerLog; apCalculatedLog layer_CalParamResult = layer_ParamSetGroup._parentLayerLog; apCalculatedLog stackLayer_MeshTransform = layer_CalParamResult._parentCalResultStackLayer; apCalculatedLog transform_Modified = stackLayer_MeshTransform._parentTF_Modified; //Debug.Log("Calculate Log"); //이제 역으로 내려오자 Vector2 posW_next = nextPosW; apMatrix worldMatrix = transform_Modified._meshTransform._matrix_TFResult_World; // ParentWorld <- Modified <- ToParent = World // [Modified <- ToParent] = [ParentWorld-1 <- World] // Modified = [ParentWorld-1 <- World <- ToParent-1] apMatrix worldMatrix_next = new apMatrix(worldMatrix); worldMatrix_next.SetPos(worldMatrix_next._pos + deltaPosW); apMatrix modMatrix_next = transform_Modified._meshTransform._matrix_TF_ToParent.RInverseMatrix; modMatrix_next.RMultiply(worldMatrix_next); modMatrix_next.RInverse(transform_Modified._meshTransform._matrix_TF_ParentWorld); //위 수식은 "StackLayer-MeshTF" 레벨에서 계산된 것이다. //StackLayer -> CalParam -> ParamSetGroup으로 이동하자. apMatrix modMatrix_paramSet = GetInverseInterpolatedMatrix(layer_ParamSetGroup, layer_CalParamResult, stackLayer_MeshTransform, modMatrix_next); if (modMatrix_paramSet == null) { Debug.LogError("StackLayer -> CalParam -> ParamSetGroup 전환에 실패했다."); return(null); } //_inverseResult.SetResult(transform_Modified._meshTransform._matrix_TF_LocalModified._pos, // modMatrix_next._pos); _inverseResult.SetResult(transform_Modified._meshTransform._matrix_TF_LocalModified._pos, modMatrix_paramSet._pos); return(_inverseResult); }