public void Bake(apOptBone parentBone, int effectorBoneID, apBoneIKController.CONTROLLER_TYPE controllerType, float defaultMixWeight, bool isWeightByControlParam, int weightControlParamID) { _parentBone = parentBone; _effectorBoneID = effectorBoneID; switch (controllerType) { case apBoneIKController.CONTROLLER_TYPE.None: _controllerType = CONTROLLER_TYPE.None; break; case apBoneIKController.CONTROLLER_TYPE.Position: _controllerType = CONTROLLER_TYPE.Position; break; case apBoneIKController.CONTROLLER_TYPE.LookAt: _controllerType = CONTROLLER_TYPE.LookAt; break; } _defaultMixWeight = defaultMixWeight; _effectorBone = null; _isWeightByControlParam = isWeightByControlParam; _weightControlParamID = weightControlParamID; _weightControlParam = null; }
/// <summary> /// 재활용을 위해 OptNode를 리턴한다. /// 용도는 Bone 소켓 /// </summary> /// <param name="parentOptBone"></param> /// <returns></returns> public apOptNode FindOptBoneSocket(apOptBone parentOptBone) { //_stopwatches[TIMER_TYPE.OptNode].Start(); apBakeLinkParam resultLinkParam = null; resultLinkParam = _totalParams_OptNode.Find(delegate(apBakeLinkParam a) { if (!a._isRecycled && a._isOptGameObject && a._optNode != null && a._parentLinkParam != null) { if (a._parentLinkParam._optBone != null && a._parentLinkParam._optBone == parentOptBone) { return(true); } } return(false); }); //_stopwatches[TIMER_TYPE.OptNode].Stop(); //_timerCalls[TIMER_TYPE.OptNode] = _timerCalls[TIMER_TYPE.OptNode] + 1; if (resultLinkParam == null) { return(null); } resultLinkParam._isRecycled = true; //<<Recycle 된걸로 전환 return(resultLinkParam._optNode); }
public bool Link(apPortrait portrait, apCache <apOptTransform> cache) { _bone = null; //Cache를 통해서 일단 MeshGroup에 해당하는 optTransform을 찾자 apOptTransform meshGroup = null; if (cache.IsContain(_meshGroupID)) { meshGroup = cache.Get(_meshGroupID); } else { meshGroup = portrait.GetOptTransformAsMeshGroup(_meshGroupID); if (meshGroup == null) { Debug.LogError("VertRig Bake 실패 : MeshGroup을 찾을 수 없다. [" + _meshGroupID + "]"); return(false); } //캐시에 담고 cache.Add(_meshGroupID, meshGroup); } //본을 찾자 _bone = meshGroup.GetBone(_boneID); if (_bone == null) { Debug.LogError("VertRig Bake 실패 : Bone을 찾을 수 없다. [" + _boneID + "]"); return(false); } return(true); }
public apOptBone GetBoneRecursive(int uniqueID) { if (_boneList_All != null) { for (int i = 0; i < _boneList_All.Length; i++) { if (_boneList_All[i]._uniqueID == uniqueID) { return(_boneList_All[i]); } } } apOptBone result = null; if (_childTransforms == null) { //Debug.LogError("Child가 없다. [Opt Transform : " + _name + "]"); return(null); } for (int i = 0; i < _childTransforms.Length; i++) { result = _childTransforms[i].GetBoneRecursive(uniqueID); if (result != null) { return(result); } } return(null); }
// Functions //--------------------------------------------------------------- // Get / Set //--------------------------------------------------------------- /// <summary> /// boneID를 가지는 Bone을 자식 노드로 두고 있는가. /// 재귀적으로 찾는다. /// </summary> /// <param name="boneID"></param> /// <returns></returns> public apOptBone GetChildBoneRecursive(int boneID) { if (_childBones == null) { return(null); } //바로 아래의 자식 노드를 검색 for (int i = 0; i < _childBones.Length; i++) { if (_childBones[i]._uniqueID == boneID) { return(_childBones[i]); } } //못찾았다면.. //재귀적으로 검색해보자 for (int i = 0; i < _childBones.Length; i++) { apOptBone result = _childBones[i].GetChildBoneRecursive(boneID); if (result != null) { return(result); } } return(null); }
/// <summary> /// 자식 Bone 중에서 특정 Target Bone을 재귀적인 자식으로 가지는 시작 Bone을 찾는다. /// </summary> /// <param name="targetBoneID"></param> /// <returns></returns> public apOptBone FindNextChainedBone(int targetBoneID) { //바로 아래의 자식 노드를 검색 if (_childBones == null) { return(null); } for (int i = 0; i < _childBones.Length; i++) { if (_childBones[i]._uniqueID == targetBoneID) { return(_childBones[i]); } } //못찾았다면.. //재귀적으로 검색해서, 그 중에 실제로 Target Bone을 포함하는 Child Bone을 리턴하자 for (int i = 0; i < _childBones.Length; i++) { apOptBone result = _childBones[i].GetChildBoneRecursive(targetBoneID); if (result != null) { //return result; return(_childBones[i]); //<<Result가 아니라, ChildBone을 리턴 } } return(null); }
public bool Bake(apModifiedBone srcModBone, apPortrait portrait) { _portrait = portrait; _meshGroupID_Bone = srcModBone._meshGropuUniqueID_Bone; apOptTransform meshGroupTransform = portrait.GetOptTransformAsMeshGroup(_meshGroupID_Bone); if (meshGroupTransform == null) { Debug.LogError("[ModBone] Bake 실패 : 찾을 수 없는 OptTransform [" + _meshGroupID_Bone + "]"); return(false); } _transformUniqueID = meshGroupTransform._transformID; _meshGroup_Bone = meshGroupTransform; _boneID = srcModBone._boneID; _bone = meshGroupTransform.GetBone(_boneID); if (_bone == null) { Debug.LogError("[ModBone] Bake 실패 : 찾을 수 없는 Bone [" + _boneID + "]"); return(false); } _transformMatrix = new apMatrix(srcModBone._transformMatrix); return(true); }
// Functions //------------------------------------------------- public apOptBoneIKChainUnit(apOptBone baseBone, apOptBone targetBone, apOptBone parentBone) { _baseBone = baseBone; _targetBone = targetBone; _parentBone = parentBone; _parentChainUnit = null; _childChainUnit = null; _isPreferredAngleAdapted = false; }
//Link 함수의 내용은 Bake 시에 진행해야한다. public void Bake(apBone bone) { _uniqueID = bone._uniqueID; _meshGroupID = bone._meshGroupID; _defaultMatrix.SetMatrix(bone._defaultMatrix); _deltaPos = Vector2.zero; _deltaAngle = 0.0f; _deltaScale = Vector2.one; _localMatrix.SetIdentity(); _worldMatrix.SetIdentity(); _color = bone._color; _shapeWidth = bone._shapeWidth; _shapeLength = bone._shapeLength; _shapeTaper = bone._shapeTaper; _optionLocalMove = bone._optionLocalMove; _optionIK = bone._optionIK; _isIKTail = bone._isIKTail; _IKTargetBoneID = bone._IKTargetBoneID; _IKTargetBone = null; //<<나중에 링크 _IKNextChainedBoneID = bone._IKNextChainedBoneID; _IKNextChainedBone = null; //<<나중에 링크 _IKHeaderBoneID = bone._IKHeaderBoneID; _IKHeaderBone = null; //<<나중에 링크 _isIKAngleRange = bone._isIKAngleRange; _IKAngleRange_Lower = bone._IKAngleRange_Lower; _IKAngleRange_Upper = bone._IKAngleRange_Upper; _IKAnglePreferred = bone._IKAnglePreferred; _isIKCalculated = false; _IKRequestAngleResult = 0.0f; _transformLocalMatrix.SetIdentity(); }
public bool Link(apPortrait portrait) { _meshGroup = portrait.GetOptTransformAsMeshGroup(_meshGroupID); if (_meshGroup == null) { Debug.LogError("VertRig Bake 실패 : MeshGroup을 찾을 수 없다. [" + _meshGroupID + "]"); return(false); } _bone = _meshGroup.GetBone(_boneID); if (_bone == null) { Debug.LogError("VertRig Bake 실패 : Bone을 찾을 수 없다. [" + _boneID + "]"); return(false); } return(true); }
// Init //-------------------------------------------- public apOptCalculatedResultParam(apCalculatedResultParam.CALCULATED_VALUE_TYPE calculatedValueType, apCalculatedResultParam.CALCULATED_SPACE calculatedSpace, apOptModifierUnitBase linkedModifier, apOptTransform targetOptTranform, apOptMesh targetOptMesh, apOptBone targetBone, //<<추가 apOptParamSetGroupVertWeight weightedVertData) { _calculatedValueType = calculatedValueType; _calculatedSpace = calculatedSpace; //TODO 여기서부터 작업하자 _linkedModifier = linkedModifier; _targetOptTransform = targetOptTranform; _targetOptMesh = targetOptMesh; _targetBone = targetBone; //<<추가 _weightedVertexData = weightedVertData; //Vertex 데이터가 들어간 경우 Vert 리스트를 만들어주자 if ((int)(_calculatedValueType & apCalculatedResultParam.CALCULATED_VALUE_TYPE.VertexPos) != 0) { int nPos = 0; if (_targetOptMesh.LocalVertPositions != null) { nPos = _targetOptMesh.LocalVertPositions.Length; } _result_Positions = new List <Vector2>(); _tmp_Positions = new List <Vector2>(); for (int i = 0; i < nPos; i++) { _result_Positions.Add(Vector2.zero); _tmp_Positions.Add(Vector2.zero); } } }
public void LinkEffector(apOptBone effectorBone) { //if(_controllerType != CONTROLLER_TYPE.None) //{ // Debug.Log("Link Effector : " + _parentBone.name + " : " + (effectorBone != null ? effectorBone.name : " <None>")); //} _effectorBone = effectorBone; if (_effectorBone == null) { _effectorBoneID = -1; } else { _effectorBoneID = _effectorBone._uniqueID; } if (_effectorBone == null) { //Effector Bone이 없으면 처리 무효 _controllerType = CONTROLLER_TYPE.None; } }
// Get / Set //------------------------------------------------ public apOptBone GetBone(string name) { //일단 빠른 검색부터 if (_optBonesMap.ContainsKey(name)) { return(_optBonesMap[name]); } apOptBone resultBone = _optBones.Find(delegate(apOptBone a) { return(string.Equals(a._name, name)); }); if (resultBone == null) { return(null); } //빠른 검색 리스트에 넣고 _optBonesMap.Add(name, resultBone); return(resultBone); }
public void Link(apOptTransform targetOptTransform) { _parentOptTransform = targetOptTransform; if (_parentOptTransform == null) { //?? Debug.LogError("[" + transform.name + "] OptBone의 ParentOptTransform이 Null이다. [" + _meshGroupID + "]"); _IKTargetBone = null; _IKNextChainedBone = null; _IKHeaderBone = null; //LinkBoneChaining(); return; } _IKTargetBone = _parentOptTransform.GetBone(_IKTargetBoneID); _IKNextChainedBone = _parentOptTransform.GetBone(_IKNextChainedBoneID); _IKHeaderBone = _parentOptTransform.GetBone(_IKHeaderBoneID); //LinkBoneChaining(); }
public apOptBone GetBoneRecursive(int uniqueID) { for (int i = 0; i < _boneList_All.Length; i++) { if (_boneList_All[i]._uniqueID == uniqueID) { return(_boneList_All[i]); } } apOptBone result = null; for (int i = 0; i < _childTransforms.Length; i++) { result = _childTransforms[i].GetBoneRecursive(uniqueID); if (result != null) { return(result); } } return(null); }
// Init //------------------------------------------------------------ public apOptBoneIKChainSet(apOptBone bone) { _bone = bone; _nLoop = 0; }
//여기서는 LinkBoneChaining만 진행 /// <summary> /// Bone Chaining 직후에 재귀적으로 호출한다. /// Tail이 가지는 -> Head로의 IK 리스트를 만든다. /// /// </summary> public void LinkBoneChaining() { if (_localMatrix == null) { _localMatrix = new apMatrix(); } if (_worldMatrix == null) { _worldMatrix = new apMatrix(); } if (_worldMatrix_NonModified == null) { _worldMatrix_NonModified = new apMatrix(); } if (_isIKTail) { apOptBone curParentBone = _parentBone; apOptBone headBone = _IKHeaderBone; bool isParentExist = (curParentBone != null); bool isHeaderExist = (headBone != null); bool isHeaderIsInParents = false; if (isParentExist && isHeaderExist) { isHeaderIsInParents = (GetParentRecursive(headBone._uniqueID) != null); } if (isParentExist && isHeaderExist && isHeaderIsInParents) { if (_IKChainSet == null) { _IKChainSet = new apOptBoneIKChainSet(this); } //Chain을 Refresh한다. _IKChainSet.RefreshChain(); } else { _IKChainSet = null; Debug.LogError("[" + transform.name + "] IK Chaining Error : Parent -> Chain List 연결시 데이터가 누락되었다. " + "[ Parent : " + isParentExist + " / Header : " + isHeaderExist + " / IsHeader Is In Parent : " + isHeaderIsInParents + " ]"); } } else { _IKChainSet = null; } if (_childBones != null) { for (int i = 0; i < _childBones.Length; i++) { _childBones[i].LinkBoneChaining(); } } }
public void AddChildBone(apOptBone bone) { _optBones.Add(bone); }
public OptBoneAndModParamPair(apOptBone bone) { _keyBone = bone; }
public RigBoneWeightPair(apOptTransform optTransform, apOptBone bone, float weight) { _optTransform = optTransform; _bone = bone; _weight = weight; }
//Link 함수의 내용은 Bake 시에 진행해야한다. /// <summary> /// [Please do not use it] /// </summary> /// <param name="bone"></param> public void Bake(apBone bone) { _name = bone._name; _uniqueID = bone._uniqueID; _meshGroupID = bone._meshGroupID; _defaultMatrix.SetMatrix(bone._defaultMatrix); _deltaPos = Vector2.zero; _deltaAngle = 0.0f; _deltaScale = Vector2.one; _localMatrix.SetIdentity(); _worldMatrix.SetIdentity(); _worldMatrix_NonModified.SetIdentity(); _vertWorld2BoneModWorldMatrix.SetIdentity(); _color = bone._color; _shapeWidth = bone._shapeWidth; _shapeLength = bone._shapeLength; _shapeTaper = bone._shapeTaper; _optionLocalMove = bone._optionLocalMove; _optionIK = bone._optionIK; _isIKTail = bone._isIKTail; _IKTargetBoneID = bone._IKTargetBoneID; _IKTargetBone = null; //<<나중에 링크 _IKNextChainedBoneID = bone._IKNextChainedBoneID; _IKNextChainedBone = null; //<<나중에 링크 _IKHeaderBoneID = bone._IKHeaderBoneID; _IKHeaderBone = null; //<<나중에 링크 _isIKAngleRange = bone._isIKAngleRange; //이게 기존 코드 //_IKAngleRange_Lower = bone._IKAngleRange_Lower; //_IKAngleRange_Upper = bone._IKAngleRange_Upper; //_IKAnglePreferred = bone._IKAnglePreferred; //이게 변경된 IK 코드 _IKAngleRange_Lower = bone._defaultMatrix._angleDeg + bone._IKAngleRange_Lower; _IKAngleRange_Upper = bone._defaultMatrix._angleDeg + bone._IKAngleRange_Upper; _IKAnglePreferred = bone._defaultMatrix._angleDeg + bone._IKAnglePreferred; _isIKCalculated = false; _IKRequestAngleResult = 0.0f; _IKRequestWeight = 0.0f; _socketTransform = null; _transformLocalMatrix.SetIdentity(); _childBones = null; _isIKChainInit = false; }
public void LinkOpt(apAnimClip animClip, apAnimTimeline timeline) { _parentAnimClip = animClip; _parentTimeline = timeline; _linkType = _parentTimeline._linkType; if (_parentAnimClip == null) { Debug.Log("Parent Anim Clip이 Null이다."); } else if (_parentAnimClip._targetOptTranform == null) { Debug.LogError("Parent Anim Clip TargetOptTranform이 Null이다."); } switch (_linkType) { case apAnimClip.LINK_TYPE.AnimatedModifier: { switch (_linkModType) { case LINK_MOD_TYPE.MeshTransform: //수정 : 재귀적으로 링크를 수행한다. _linkedOptTransform = _parentAnimClip._targetOptTranform.GetMeshTransformRecursive(_transformID); if (_linkedOptTransform == null) { Debug.LogError("Opt TimelineLayer MeshTransform 연결 실패 : " + _transformID); _transformID = -1; } break; case LINK_MOD_TYPE.MeshGroupTransform: //수정 : 재귀적으로 링크를 수행한다. _linkedOptTransform = _parentAnimClip._targetOptTranform.GetMeshGroupTransformRecursive(_transformID); if (_linkedOptTransform == null) { Debug.LogError("Opt TimelineLayer MeshGroupTransform 연결 실패 : " + _transformID); _transformID = -1; } break; case LINK_MOD_TYPE.Bone: //TODO : Bone 타입 연결을 해야한다. _linkedOptBone = _parentAnimClip._targetOptTranform.GetBoneRecursive(_boneID); break; case LINK_MOD_TYPE.None: _linkedOptTransform = null; _transformID = -1; _boneID = -1; break; } } break; case apAnimClip.LINK_TYPE.ControlParam: { _linkedControlParam = _parentAnimClip._portrait.GetControlParam(_controlParamID); if (_linkedControlParam == null) { _controlParamID = -1; } } break; //case apAnimClip.LINK_TYPE.Bone: // { // Debug.LogError("TODO : TimelineLayer의 Bone 타입 연동하기"); // } // break; } for (int i = 0; i < _keyframes.Count; i++) { _keyframes[i].Link(this); } SortAndRefreshKeyframes(); }
// Functions //------------------------------------------------------------ /// <summary> /// Bone Hierarchy에 맞추어서 다시 Chain을 만든다. /// </summary> public void RefreshChain() { _chainUnits.Clear(); _headChainUnit = null; _tailChainUnit = null; if (!_bone._isIKTail) { return; } //Bone으로부터 Head가 나올때까지 Chain을 추가하자 //[Parent] .... [Cur Bone] ----> [Target Bone < 이것 부터 시작] apOptBone parentBone = null; apOptBone curBone = null; apOptBone targetBone = _bone; string strBoneNames = ""; //int curLevel = 0; while (true) { curBone = targetBone._parentBone; if (curBone == null) { //? 왜 여기서 끊기지.. break; } parentBone = curBone._parentBone; //<<이건 Null 일 수 있다. //apBoneIKChainUnit newUnit = new apBoneIKChainUnit(curBone, targetBone, parentBone, curLevel); apOptBoneIKChainUnit newUnit = new apOptBoneIKChainUnit(curBone, targetBone, parentBone); _chainUnits.Add(newUnit); strBoneNames += curBone.transform.name + ", "; //끝났당 if (curBone == _bone._IKHeaderBone) { break; } //하나씩 위로 탐색하자 targetBone = curBone; //curLevel++; } if (_chainUnits.Count == 0) { return; } ////전체 Unit 개수를 넣어주자 //for (int i = 0; i < _chainUnits.Count; i++) //{ // _chainUnits[i].SetTotalChainLevel(_chainUnits.Count); //} //Debug.Log("Refresh Chain : [" + _bone._name + "] " + strBoneNames); //앞쪽이 Tail이다. _tailChainUnit = _chainUnits[0]; _headChainUnit = _chainUnits[_chainUnits.Count - 1]; //Chain Unit간의 연결을 한다. apOptBoneIKChainUnit curUnit = null; for (int i = 0; i < _chainUnits.Count; i++) { curUnit = _chainUnits[i]; if (i > 0) { curUnit.SetChild(_chainUnits[i - 1]); } if (i < _chainUnits.Count - 1) { curUnit.SetParent(_chainUnits[i + 1]); } curUnit.SetTail(_tailChainUnit); } if (_chainUnits.Count == 0) { _nLoop = 0; } else { // 얼마나 연산을 반복할 것인지 결정 (연산 횟수는 루프 단위로 결정한다) _nLoop = MAX_CALCULATE_LOOP_EDITOR; if (_chainUnits.Count * _nLoop > MAX_TOTAL_UNIT_CALCULATE) { //전체 계산 횟수 (Unit * Loop)가 제한을 넘겼을 때 _nLoop = MAX_TOTAL_UNIT_CALCULATE / _chainUnits.Count; if (_nLoop < 2) { _nLoop = 2; } } } _isContinuousPrevPos = false; }
public void Parse(GameObject targetGameObject, apBakeLinkParam parentLinkParam) { _prevGameObject = targetGameObject; _isRecycled = false; _isReGroupCompleted = false; //Parent-Child를 서로 연결하자 _parentLinkParam = parentLinkParam; if (parentLinkParam != null) { if (_parentLinkParam._childLinkParams == null) { _parentLinkParam._childLinkParams = new List <apBakeLinkParam>(); } _parentLinkParam._childLinkParams.Add(this); } //Component를 보고 이 객체의 성격을 정의하자 _isOptGameObject = false; _optRoot = null; _optNode = null; _optBone = null; _optTransform = null; _optMesh = null; _meshRenderer = null; _meshFilter = null; _isOtherComponentExist = false; MeshRenderer compMeshRenderer = null; MeshFilter compMeshFilter = null; Component[] components = _prevGameObject.GetComponents(typeof(Component)); if (components != null) { Component curComp = null; for (int i = 0; i < components.Length; i++) { curComp = components[i]; if (curComp is Transform) { //? 이건 필수로 들어가는 겁니더.. continue; } if (curComp is apOptRootUnit) { _optRoot = curComp as apOptRootUnit; } else if (curComp is apOptTransform) { _optTransform = curComp as apOptTransform; } else if (curComp is apOptNode) { _optNode = curComp as apOptNode; } else if (curComp is apOptBone) { _optBone = curComp as apOptBone; } else if (curComp is apOptMesh) { _optMesh = curComp as apOptMesh; } else if (curComp is MeshRenderer) { compMeshRenderer = curComp as MeshRenderer; } else if (curComp is MeshFilter) { compMeshFilter = curComp as MeshFilter; } else { //알 수 없는 컴포넌트가 있다. _isOtherComponentExist = true; } } } if (_optRoot != null || _optNode != null || _optBone != null || _optTransform != null || _optMesh != null) { // Opt 계열의 컴포넌트가 있다면 _isOptGameObject = true; } //만약 MeshRenderer/MeshFilter가 있을때 //_optMesh가 있다면 포함가능, //그 외에는 "알 수 없는 컴포넌트"로 지정한다. if (compMeshRenderer != null) { if (_optMesh != null) { _meshRenderer = compMeshRenderer; } else { _isOtherComponentExist = true; } } if (compMeshFilter != null) { if (_optMesh != null) { _meshFilter = compMeshFilter; } else { _isOtherComponentExist = true; } } }
/// <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 } }
// Init //-------------------------------------------- public apOptCalculatedResultParam(apCalculatedResultParam.CALCULATED_VALUE_TYPE calculatedValueType, apCalculatedResultParam.CALCULATED_SPACE calculatedSpace, apOptModifierUnitBase linkedModifier, apOptTransform targetOptTranform, apOptTransform ownerOptTranform, apOptMesh targetOptMesh, apOptBone targetBone, //<<추가 apOptParamSetGroupVertWeight weightedVertData) { _calculatedValueType = calculatedValueType; _calculatedSpace = calculatedSpace; //TODO 여기서부터 작업하자 _linkedModifier = linkedModifier; _targetOptTransform = targetOptTranform; _ownerOptTransform = ownerOptTranform; _targetOptMesh = targetOptMesh; _targetBone = targetBone; //<<추가 _paramKeyValues.Clear(); _subParamKeyValueList.Clear(); _weightedVertexData = weightedVertData; _isVertexLocalMorph = false; _isVertexRigging = false; //Vertex 데이터가 들어간 경우 Vert 리스트를 만들어주자 if ((int)(_calculatedValueType & apCalculatedResultParam.CALCULATED_VALUE_TYPE.VertexPos) != 0) { int nPos = 0; if (_targetOptMesh.LocalVertPositions != null) { nPos = _targetOptMesh.LocalVertPositions.Length; } _result_Positions = new Vector2[nPos]; _tmp_Positions = new Vector2[nPos]; for (int i = 0; i < nPos; i++) { _result_Positions[i] = Vector2.zero; _tmp_Positions[i] = Vector2.zero; } if (_linkedModifier._modifierType == apModifierBase.MODIFIER_TYPE.Rigging) { _result_VertMatrices = new apMatrix3x3[nPos]; _tmp_VertMatrices = new apMatrix3x3[nPos]; for (int i = 0; i < nPos; i++) { _result_VertMatrices[i].SetIdentity(); _tmp_VertMatrices[i].SetIdentity(); } } //if(_linkedModifier._modifierType == apModifierBase.MODIFIER_TYPE.Morph || // _linkedModifier._modifierType == apModifierBase.MODIFIER_TYPE.AnimatedMorph) //{ // //최적화를 위한 VertLocalPair를 만든다. 개수는 ParamSetGroup 만큼 // _result_VertLocalPairs = new apOptVertexRequest[_linkedModifier._paramSetGroupList.Count]; // for (int iVLP = 0; iVLP < _result_VertLocalPairs.Length; iVLP++) // { // apOptVertexRequest newRequest = new apOptVertexRequest(); // newRequest.InitVertLocalPair(_linkedModifier._paramSetGroupList[iVLP]); // _result_VertLocalPairs[iVLP] = newRequest; // } //} if (_linkedModifier._modifierType == apModifierBase.MODIFIER_TYPE.AnimatedMorph || _linkedModifier._modifierType == apModifierBase.MODIFIER_TYPE.Morph) { _isVertexLocalMorph = true; } else if (_linkedModifier._modifierType == apModifierBase.MODIFIER_TYPE.Rigging) { _isVertexRigging = true; } } }
/// <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()); } } } }