public void AddParamKeyValueSet(apOptCalculatedResultParam.OptParamKeyValueSet paramKeyValue) { if (_subParamKeyValues.Contains(paramKeyValue)) { return; } _subParamKeyValues.Add(paramKeyValue); _nSubParamKeyValues = _subParamKeyValues.Count; if (_isVertexLocalMorph || _isVertexRigging) { if (_vertexRequest == null) { _vertexRequest = new apOptVertexRequest(_isVertexLocalMorph ? apOptVertexRequest.REQUEST_TYPE.VertLocal : apOptVertexRequest.REQUEST_TYPE.Rigging); } //변경 19.5.24 : ModifiedMeshSet을 이용할지 여부 if (paramKeyValue._modifiedMesh != null) { _vertexRequest.AddModMesh(paramKeyValue._modifiedMesh); } else if (paramKeyValue._modifiedMeshSet != null) { _vertexRequest.AddModMeshSet(paramKeyValue._modifiedMeshSet); } } }
public void AddParamKeyValueSet(apOptCalculatedResultParam.OptParamKeyValueSet paramKeyValue) { if (_subParamKeyValues.Contains(paramKeyValue)) { return; } _subParamKeyValues.Add(paramKeyValue); _nSubParamKeyValues = _subParamKeyValues.Count; }
// Get / Set //-------------------------------------------- //------------------------------------------------------------------------------------------------- //Control Param 보간 관련 //-------------------------------------------------------------------------------------- private void MakeControlParamLerpAreas() { //1. ParamSetKeyValue => Point를 만든다. _cpLerpAreas.Clear(); _cpLerpPoints.Clear(); apControlParam controlParam = _keyParamSetGroup._keyControlParam; if (controlParam == null) { return; } List <float> fPosXList = new List <float>(); List <float> fPosYList = new List <float>(); float bias = 0.001f; if (controlParam._valueType == apControlParam.TYPE.Float) { bias = Mathf.Abs((controlParam._float_Max - controlParam._float_Min) * 0.05f); bias = Mathf.Clamp(bias, 0.0001f, 0.1f); } else if (controlParam._valueType == apControlParam.TYPE.Vector2) { bias = Mathf.Min(Mathf.Abs((controlParam._vec2_Max.x - controlParam._vec2_Min.x) * 0.05f), Mathf.Abs((controlParam._vec2_Max.y - controlParam._vec2_Min.y) * 0.05f)); bias = Mathf.Clamp(bias, 0.0001f, 0.1f); } for (int i = 0; i < _subParamKeyValues.Count; i++) { apOptCalculatedResultParam.OptParamKeyValueSet keyValueSet = _subParamKeyValues[i]; if (keyValueSet._paramSet == null) { continue; } apOptCalculatedLerpPoint newPoint = null; switch (controlParam._valueType) { case apControlParam.TYPE.Int: { int iPos = keyValueSet._paramSet._conSyncValue_Int; newPoint = new apOptCalculatedLerpPoint(iPos, true); } break; case apControlParam.TYPE.Float: { float fPos = keyValueSet._paramSet._conSyncValue_Float; newPoint = new apOptCalculatedLerpPoint(fPos, true); } break; case apControlParam.TYPE.Vector2: { Vector2 vPos = keyValueSet._paramSet._conSyncValue_Vector2; newPoint = new apOptCalculatedLerpPoint(vPos, true); //위치를 저장해둔다. AddLerpPos(vPos, fPosXList, fPosYList, bias); } break; } newPoint.AddPoint(keyValueSet, 1.0f); //실제 키는 Weight가 1이다. _cpLerpPoints.Add(newPoint); } //2-1 1차원 값이면 오름차순 정렬하는 걸로 끝 switch (controlParam._valueType) { case apControlParam.TYPE.Int: _cpLerpPoints.Sort(delegate(apOptCalculatedLerpPoint a, apOptCalculatedLerpPoint b) { return(a._iPos - b._iPos); }); break; case apControlParam.TYPE.Float: _cpLerpPoints.Sort(delegate(apOptCalculatedLerpPoint a, apOptCalculatedLerpPoint b) { return((int)((a._pos.x - b._pos.x) * (1.0f / bias) * 100.0f)); }); break; } //2-2. (Vector2인 경우) Rect Area를 만들자. if (controlParam._valueType == apControlParam.TYPE.Vector2) { //1) Min, Max 위치에 대해서 확인 후 가상 포인트를 추가하자 //2) X, Y 값에 대해서 정렬 //3) X, Y 좌표를 순회하면서 "포인트가 없다면" 가상 포인트를 추가하자 //4) X, Y 좌표 순회하면서 RectArea를 만들자. //1) float minX = controlParam._vec2_Min.x; float minY = controlParam._vec2_Min.y; float maxX = controlParam._vec2_Max.x; float maxY = controlParam._vec2_Max.y; MakeVirtualLerpPoint(new Vector2(minX, minY), bias); MakeVirtualLerpPoint(new Vector2(minX, minY), bias); MakeVirtualLerpPoint(new Vector2(minX, minY), bias); MakeVirtualLerpPoint(new Vector2(minX, minY), bias); //Min/Max 위치를 추가로 저장해둔다. AddLerpPos(new Vector2(minX, minY), fPosXList, fPosYList, bias); AddLerpPos(new Vector2(minX, maxY), fPosXList, fPosYList, bias); AddLerpPos(new Vector2(maxX, minY), fPosXList, fPosYList, bias); AddLerpPos(new Vector2(maxX, maxY), fPosXList, fPosYList, bias); //2) 위치 정렬 fPosXList.Sort(delegate(float a, float b) { return((int)((a - b) * (1.0f / bias) * 1000.0f)); }); fPosYList.Sort(delegate(float a, float b) { return((int)((a - b) * (1.0f / bias) * 1000.0f)); }); //3) 좌표 순회하면서 포인트 추가 for (int iX = 0; iX < fPosXList.Count; iX++) { for (int iY = 0; iY < fPosYList.Count; iY++) { MakeVirtualLerpPoint(new Vector2(fPosXList[iX], fPosYList[iY]), bias); } } apOptCalculatedLerpPoint pointLT = null; apOptCalculatedLerpPoint pointRT = null; apOptCalculatedLerpPoint pointLB = null; apOptCalculatedLerpPoint pointRB = null; //4) 좌표 순회하면서 RectArea 만들기 for (int iX = 0; iX < fPosXList.Count - 1; iX++) { for (int iY = 0; iY < fPosYList.Count - 1; iY++) { pointLT = GetLerpPoint(new Vector2(fPosXList[iX], fPosYList[iY]), bias); pointRT = GetLerpPoint(new Vector2(fPosXList[iX + 1], fPosYList[iY]), bias); pointLB = GetLerpPoint(new Vector2(fPosXList[iX], fPosYList[iY + 1]), bias); pointRB = GetLerpPoint(new Vector2(fPosXList[iX + 1], fPosYList[iY + 1]), bias); apOptCalculatedLerpArea lerpArea = new apOptCalculatedLerpArea(pointLT, pointRT, pointLB, pointRB); _cpLerpAreas.Add(lerpArea); } } } }
//--------------------------------------------------- // 계산함수 - KeyFrame //--------------------------------------------------- private void CalculateWeight_KeyFrame() { if (_keyParamSetGroup == null || _keyParamSetGroup._keyAnimTimelineLayer == null) { return; } apAnimTimelineLayer timlineLayer = _keyParamSetGroup._keyAnimTimelineLayer; apOptCalculatedResultParam.OptParamKeyValueSet curParamKeyValue = null; //9.26 : 이거 수정해야한다. //Int형 프레임과 Float형 프레임을 둘다 사용한다. int curFrame = timlineLayer._parentAnimClip.CurFrame; float curFrameFloat = timlineLayer._parentAnimClip.CurFrameFloat; //<<이건 실수형 bool isLoop = timlineLayer._parentAnimClip.IsLoop; //apAnimKeyframe firstKeyframe = timlineLayer._firstKeyFrame; //apAnimKeyframe lastKeyframe = timlineLayer._lastKeyFrame; _totalWeight = 0.0f; apAnimKeyframe curKeyframe = null; apAnimKeyframe prevKeyframe = null; apAnimKeyframe nextKeyframe = null; //int indexOffsetA = 0; //int indexOffsetB = 0; int lengthFrames = timlineLayer._parentAnimClip.EndFrame - timlineLayer._parentAnimClip.StartFrame; int tmpCurFrameInt = 0; float tmpCurFrameFloat = 0; for (int i = 0; i < _subParamKeyValues.Count; i++) { curParamKeyValue = _subParamKeyValues[i]; curParamKeyValue._dist = -10.0f; curParamKeyValue._isCalculated = false; curParamKeyValue._weight = 0.0f; //추가 12.5 curParamKeyValue._animKeyPos = apOptCalculatedResultParam.AnimKeyPos.NotCalculated; //유효하지 않은 키프레임이면 처리하지 않는다. if (curParamKeyValue._paramSet.SyncKeyframe == null || !curParamKeyValue._paramSet.SyncKeyframe._isActive) { //Debug.Log("[" + i + "] Not Active or Null Keyframe"); continue; } curKeyframe = curParamKeyValue._paramSet.SyncKeyframe; prevKeyframe = curParamKeyValue._paramSet.SyncKeyframe._prevLinkedKeyframe; nextKeyframe = curParamKeyValue._paramSet.SyncKeyframe._nextLinkedKeyframe; //1. 프레임이 같다. => 100% if (curFrame == curKeyframe._frameIndex || ((curKeyframe._isLoopAsStart || curKeyframe._isLoopAsEnd) && curFrame == curKeyframe._loopFrameIndex)) { curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = 1.0f; _totalWeight += 1.0f; //추가 12.5 : AnimKeyPos : 동일 프레임 curParamKeyValue._animKeyPos = apOptCalculatedResultParam.AnimKeyPos.ExactKey; } //else if(curFrame >= curKeyframe._activeFrameIndexMin && // curFrame < curKeyframe._frameIndex) else if (curKeyframe.IsFrameIn(curFrame, apAnimKeyframe.LINKED_KEY.Prev)) { //범위 안에 들었다. [Prev - Cur] if (prevKeyframe != null) { tmpCurFrameInt = curFrame; if (tmpCurFrameInt > curKeyframe._frameIndex) { tmpCurFrameInt -= lengthFrames; } tmpCurFrameFloat = curFrameFloat; if (tmpCurFrameFloat > curKeyframe._frameIndex) { tmpCurFrameFloat -= lengthFrames; } //[중요] 재생 프레임 -> 보간 가중치 계산 코드 //_cal_itp = curKeyframe._curveKey.GetItp_Int(tmpCurFrameInt, true);//기존 : Int _cal_itp = curKeyframe._curveKey.GetItp_Float(tmpCurFrameFloat, true, tmpCurFrameInt); //변경 : Float curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = _cal_itp; _totalWeight += _cal_itp; //추가 : Rotation Bias //Prev와 연결되었다면 Prev 설정을 적용한다. if (curKeyframe._prevRotationBiasMode != apAnimKeyframe.ROTATION_BIAS.None) { curParamKeyValue.SetAnimRotationBias(curKeyframe._prevRotationBiasMode, curKeyframe._prevRotationBiasCount); } //Debug.Log("[" + i + "] [Prev ~ Cur] " + itp); //Debug.Log("Prev ~ Next : " + itp); //추가 12.5 : AnimKeyPos - Next 프레임으로서 Prev 프레임과 보간이 된다. curParamKeyValue._animKeyPos = apOptCalculatedResultParam.AnimKeyPos.NextKey; } else { //연결된게 없다면 이게 100% 가중치를 갖는다. curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = 1.0f; _totalWeight += 1.0f; //Debug.Log("[" + i + "] [Prev ?? ~ Cur] 1.0"); //추가 12.5 : AnimKeyPos - 동일 프레임 curParamKeyValue._animKeyPos = apOptCalculatedResultParam.AnimKeyPos.ExactKey; } } //else if(curFrame > curKeyframe._frameIndex && // curFrame <= curKeyframe._activeFrameIndexMax) else if (curKeyframe.IsFrameIn(curFrame, apAnimKeyframe.LINKED_KEY.Next)) { //범위안에 들었다 [Cur - Next] if (nextKeyframe != null) { tmpCurFrameInt = curFrame; if (tmpCurFrameInt < curKeyframe._frameIndex) { tmpCurFrameInt += lengthFrames; } tmpCurFrameFloat = curFrameFloat; if (tmpCurFrameFloat < curKeyframe._frameIndex) { tmpCurFrameFloat += lengthFrames; } //[중요] 재생 프레임 -> 보간 가중치 계산 코드 //_cal_itp = curKeyframe._curveKey.GetItp_Int(tmpCurFrameInt, false);//기존 _cal_itp = curKeyframe._curveKey.GetItp_Float(tmpCurFrameFloat, false, tmpCurFrameInt); //변경 : Float //itp = 1.0f - itp;//결과가 B에 맞추어지므로 여기서는 Reverse curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = _cal_itp; _totalWeight += _cal_itp; //Debug.Log("[" + i + "] [Cur ~ Next] " + itp); //추가 : Rotation Bias //Next와 연결되었다면 Next 설정을 적용한다. if (curKeyframe._nextRotationBiasMode != apAnimKeyframe.ROTATION_BIAS.None) { curParamKeyValue.SetAnimRotationBias(curKeyframe._nextRotationBiasMode, curKeyframe._nextRotationBiasCount); } //추가 12.5 : AnimKeyPos - Prev 프레임으로서 Next 프레임과 보간이 된다. curParamKeyValue._animKeyPos = apOptCalculatedResultParam.AnimKeyPos.PrevKey; } else { //연결된게 없다면 이게 100% 가중치를 갖는다. curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = 1.0f; _totalWeight += 1.0f; //Debug.Log("[" + i + "] [Cur ~ Next ??] 1.0"); //추가 12.5 : AnimKeyPos - 동일 프레임 curParamKeyValue._animKeyPos = apOptCalculatedResultParam.AnimKeyPos.ExactKey; } } } if (_totalWeight > 0.0f) { //Debug.Log("Result --------------------------------"); for (int i = 0; i < _subParamKeyValues.Count; i++) { curParamKeyValue = _subParamKeyValues[i]; if (curParamKeyValue._isCalculated) { curParamKeyValue._weight /= _totalWeight; //Debug.Log("[" + curParamKeyValue._weight + "]"); } else { curParamKeyValue._weight = 0.0f; } } //Debug.Log("-------------------------------------"); } }
private void CalculateWeight_ControlParam_2D() { if (_keyParamSetGroup == null || _keyParamSetGroup._keyControlParam == null) { Debug.LogError("Key ParamSet Group is Null / Key Control Param Is null"); return; } _tmp_controlParam = _keyParamSetGroup._keyControlParam; //1. Param의 Weight를 모두 0으로 세팅 (+ 연산으로 Weight를 추가하는 방식) //2. 어느 RectArea에 있는지 결정한다. //3. Rect 안에서 itp를 계산한다. for (int i = 0; i < _subParamKeyValues.Count; i++) { _tmp_paramKeyValue = _subParamKeyValues[i]; _tmp_paramKeyValue._weight = 0.0f; _tmp_paramKeyValue._isCalculated = false; //<<나중에 이것도 true로 올리자 } Vector2 curValue = _tmp_controlParam._vec2_Cur; if (_cpLerpAreaLastSelected == null || !_cpLerpAreaLastSelected.IsInclude(curValue)) { _cpLerpAreaLastSelected = null; for (int i = 0; i < _cpLerpAreas.Count; i++) { if (_cpLerpAreas[i].IsInclude(curValue)) { _cpLerpAreaLastSelected = _cpLerpAreas[i]; break; } } //_cpLerpAreaLastSelected = _cpLerpAreas.Find(delegate (apOptCalculatedLerpArea a) //{ // return a.IsInclude(curValue); //}); } if (_cpLerpAreaLastSelected == null) { Debug.LogError("No Lerp Area"); return; //처리가 안되는데요; } _cpLerpAreaLastSelected.ReadyToCalculate(); float itpX = 0.0f; float itpY = 0.0f; float rectPosX_Min = _cpLerpAreaLastSelected._posLT.x; float rectPosX_Max = _cpLerpAreaLastSelected._posRB.x; float rectPosY_Min = _cpLerpAreaLastSelected._posLT.y; float rectPosY_Max = _cpLerpAreaLastSelected._posRB.y; itpX = 1.0f - Mathf.Clamp01((curValue.x - rectPosX_Min) / (rectPosX_Max - rectPosX_Min)); itpY = 1.0f - Mathf.Clamp01((curValue.y - rectPosY_Min) / (rectPosY_Max - rectPosY_Min)); _cpLerpAreaLastSelected._pointLT._calculatedWeight = itpX * itpY; _cpLerpAreaLastSelected._pointRT._calculatedWeight = (1.0f - itpX) * itpY; _cpLerpAreaLastSelected._pointLB._calculatedWeight = itpX * (1.0f - itpY); _cpLerpAreaLastSelected._pointRB._calculatedWeight = (1.0f - itpX) * (1.0f - itpY); _cpLerpAreaLastSelected._pointLT.CalculateITPWeight(); _cpLerpAreaLastSelected._pointRT.CalculateITPWeight(); _cpLerpAreaLastSelected._pointLB.CalculateITPWeight(); _cpLerpAreaLastSelected._pointRB.CalculateITPWeight(); _totalWeight = 0.0f; // 여러개의 키값을 사용할 거라면 for (int i = 0; i < _subParamKeyValues.Count; i++) { _tmp_paramKeyValue = _subParamKeyValues[i]; if (!_tmp_paramKeyValue._isCalculated) { _tmp_paramKeyValue._weight = 0.0f; continue; } //변경 //Weight 시작값이 기본 1이 아니라, 거리에 따른 가중치로 바뀐다. _totalWeight += _tmp_paramKeyValue._weight; } if (_totalWeight > 0.0f) { for (int i = 0; i < _subParamKeyValues.Count; i++) { _tmp_paramKeyValue = _subParamKeyValues[i]; if (_tmp_paramKeyValue._isCalculated) { _tmp_paramKeyValue._weight /= _totalWeight; } } } }
private void CalculateWeight_ControlParam_1D() { if (_keyParamSetGroup == null || _keyParamSetGroup._keyControlParam == null) { Debug.LogError("Key ParamSet Group is Null / Key Control Param Is null"); return; } _tmp_controlParam = _keyParamSetGroup._keyControlParam; for (int i = 0; i < _subParamKeyValues.Count; i++) { _tmp_paramKeyValue = _subParamKeyValues[i]; _tmp_paramKeyValue._weight = 0.0f; _tmp_paramKeyValue._isCalculated = false; //<<나중에 이것도 true로 올리자 } if (_cpLerpPoints.Count == 0) { return; //처리 불가; } if (_cpLerpPoints.Count == 1) { _cpLerpPoints[0]._calculatedWeight = 1.0f; _cpLerpPoints[0].CalculateITPWeight(); } else { //1) ITP를 계산할 두개의 Point (A, B)를 잡는다. //2) 두개의 포인트를 기준으로 ITP를 계산한다. //3) Total Weight 계산 후 적용 bool isRefreshLerpPointRange = false; if (_cpLerpPoint_A == null || _cpLerpPoint_B == null) { isRefreshLerpPointRange = true; } else { if (_tmp_controlParam._valueType == apControlParam.TYPE.Int) { if (_tmp_controlParam._int_Cur < _cpLerpPoint_A._iPos || _tmp_controlParam._int_Cur > _cpLerpPoint_B._iPos) { isRefreshLerpPointRange = true; } } else { if (_tmp_controlParam._float_Cur < _cpLerpPoint_A._pos.x || _tmp_controlParam._float_Cur > _cpLerpPoint_B._pos.x) { isRefreshLerpPointRange = true; } } } if (isRefreshLerpPointRange) { //0..1..2.. [value]..3...4 int iB = -1; if (_tmp_controlParam._valueType == apControlParam.TYPE.Int) { for (int i = 0; i < _cpLerpPoints.Count; i++) { if (_tmp_controlParam._int_Cur <= _cpLerpPoints[i]._iPos) { iB = i; break; } } } else { for (int i = 0; i < _cpLerpPoints.Count; i++) { if (_tmp_controlParam._float_Cur <= _cpLerpPoints[i]._pos.x) { iB = i; break; } } } if (iB < 0) { iB = _cpLerpPoints.Count - 1; } _cpLerpPoint_B = _cpLerpPoints[iB]; if (iB == 0) { _cpLerpPoint_A = _cpLerpPoints[0]; } else { _cpLerpPoint_A = _cpLerpPoints[iB - 1]; } } if (_cpLerpPoint_A == null || _cpLerpPoint_B == null) { return; } if (_cpLerpPoint_A == _cpLerpPoint_B) { _cpLerpPoint_A._calculatedWeight = 1.0f; _cpLerpPoint_A.CalculateITPWeight(); } else { float itp = 0.0f; if (_tmp_controlParam._valueType == apControlParam.TYPE.Int) { itp = 1.0f - Mathf.Clamp01((float)(_tmp_controlParam._int_Cur - _cpLerpPoint_A._iPos) / (float)(_cpLerpPoint_B._iPos - _cpLerpPoint_A._iPos)); } else { itp = 1.0f - Mathf.Clamp01((float)(_tmp_controlParam._float_Cur - _cpLerpPoint_A._pos.x) / (float)(_cpLerpPoint_B._pos.x - _cpLerpPoint_A._pos.x)); } _cpLerpPoint_A._calculatedWeight = itp; _cpLerpPoint_B._calculatedWeight = 1.0f - itp; _cpLerpPoint_A.CalculateITPWeight(); _cpLerpPoint_B.CalculateITPWeight(); } _totalWeight = 0.0f; for (int i = 0; i < _subParamKeyValues.Count; i++) { _tmp_paramKeyValue = _subParamKeyValues[i]; if (!_tmp_paramKeyValue._isCalculated) { _tmp_paramKeyValue._weight = 0.0f; continue; } _totalWeight += _tmp_paramKeyValue._weight; } if (_totalWeight > 0.0f) { for (int i = 0; i < _subParamKeyValues.Count; i++) { _tmp_paramKeyValue = _subParamKeyValues[i]; if (_tmp_paramKeyValue._isCalculated) { _tmp_paramKeyValue._weight /= _totalWeight; } } } } }
private void CalculateWeight_ControlParam() { if (_keyParamSetGroup._keyControlParam == null) { Debug.LogError("Null Key Control Param"); return; } //Debug.Log("Update Control Param : " + _keyParamSetGroup._keyControlParam._keyName); _cal_controlParam = _keyParamSetGroup._keyControlParam; //_cal_minDist = float.MaxValue; //_cal_maxDist = 0.0f; _cal_dist = 0.0f; _cal_curParamKeyValue = null; _totalWeight = 0.0f; //Debug.Log(_cal_controlParam._keyName + " : " + _cal_controlParam._vec2_Cur); for (int i = 0; i < _nSubParamKeyValues; i++) { _cal_curParamKeyValue = _subParamKeyValues[i]; _cal_dist = -10.0f; _cal_curParamKeyValue._isCalculated = false; switch (_cal_controlParam._valueType) { //case apControlParam.TYPE.Bool: // if(_cal_curParamKeyValue._paramSet._conSyncValue_Bool == _cal_controlParam._bool_Cur) // { // _cal_curParamKeyValue._dist = 0.0f; // _cal_curParamKeyValue._isCalculated = true; // } // else // { // _cal_curParamKeyValue._dist = -10.0f; // _cal_curParamKeyValue._isCalculated = false; // } // break; case apControlParam.TYPE.Int: _cal_dist = _cal_controlParam.GetNormalizedDistance_Int(_cal_curParamKeyValue._paramSet._conSyncValue_Int); break; case apControlParam.TYPE.Float: _cal_dist = _cal_controlParam.GetNormalizedDistance_Float(_cal_curParamKeyValue._paramSet._conSyncValue_Float); break; case apControlParam.TYPE.Vector2: _cal_dist = _cal_controlParam.GetNormalizedDistance_Vector2(_cal_curParamKeyValue._paramSet._conSyncValue_Vector2); break; //case apControlParam.TYPE.Vector3: // _cal_dist = _cal_controlParam.GetNormalizedDistance_Vector3(_cal_curParamKeyValue._paramSet._conSyncValue_Vector3); // break; } if (_cal_dist < -1.0f) { _cal_curParamKeyValue._dist = -10.0f; _cal_curParamKeyValue._isCalculated = false; _cal_curParamKeyValue._weight = 0.0f; continue; } //주의 : Runtime에서는 Matched가 없다. _cal_curParamKeyValue._dist = _cal_dist; _cal_curParamKeyValue._isCalculated = true; _cal_curParamKeyValue._weight = 1.0f; _totalWeight += 1.0f; } //----------------------------------------------- // Weight 계산 //선형 IDW 방식으로 계산한다. #region [미사용 코드] 역선형 보간 방식은 오류가 있다; //for (int i = 0; i < _nSubParamKeyvalues; i++) //{ // _cal_curParamKeyValue = _subParamKeyValues[i]; // if(!_cal_curParamKeyValue._isCalculated) // { // _cal_curParamKeyValue._weight = 0.0f; // continue; // } // _cal_keepWeightRatio = Mathf.Clamp01((_cal_curParamKeyValue._dist - _cal_minDist) / (_cal_maxDist - _cal_minDist)); // _cal_mulWeight = (_cal_minDist * _cal_keepWeightRatio) + (1.0f - _cal_keepWeightRatio); // //_cal_revWeight = (_cal_maxDist - _cal_curParamKeyValue._dist) * _cal_mulWeight; // _cal_revWeight = (2.0f - _cal_curParamKeyValue._dist) * _cal_mulWeight; // //_cal_revWeight = (1.0f / (_cal_curParamKeyValue._dist)) * _cal_mulWeight; // _totalWeight += _cal_revWeight; // _cal_curParamKeyValue._weight = _cal_revWeight; //} #endregion if (_nSubParamKeyValues >= 2) { _totalWeight = 0.0f; for (int i = 0; i < _nSubParamKeyValues; i++) { _cal_curParamKeyValue = _subParamKeyValues[i]; if (!_cal_curParamKeyValue._isCalculated || _cal_curParamKeyValue._weight < _zeroBias) { continue; } //다른 SubParam과의 Dist를 비교하여 내분 Weight를 하자 if (i + 1 < _nSubParamKeyValues) { for (int j = i + 1; j < _nSubParamKeyValues; j++) { _cal_nextParamKeyValue = _subParamKeyValues[j]; if (!_cal_nextParamKeyValue._isCalculated) { continue; } _cal_sumDist = _cal_curParamKeyValue._dist + _cal_nextParamKeyValue._dist; if (_cal_sumDist > _zeroBias) { _cal_itp = Mathf.Clamp01((_cal_sumDist - _cal_curParamKeyValue._dist) / _cal_sumDist); _cal_curParamKeyValue._weight *= _cal_itp; _cal_nextParamKeyValue._weight *= (1.0f - _cal_itp); } } } _totalWeight += _cal_curParamKeyValue._weight; } } if (_totalWeight > 0.0f) { for (int i = 0; i < _nSubParamKeyValues; i++) { _cal_curParamKeyValue = _subParamKeyValues[i]; if (_cal_curParamKeyValue._isCalculated) { _cal_curParamKeyValue._weight /= _totalWeight; } } } }
// Functions //----------------------------------------- public void AddPoint(apOptCalculatedResultParam.OptParamKeyValueSet point, float weight) { _refParams.Add(point); _refWeights.Add(weight); }
//--------------------------------------------------- // 계산함수 - KeyFrame //--------------------------------------------------- private void CalculateWeight_KeyFrame() { if (_keyParamSetGroup == null || _keyParamSetGroup._keyAnimTimelineLayer == null) { return; } apAnimTimelineLayer timlineLayer = _keyParamSetGroup._keyAnimTimelineLayer; apOptCalculatedResultParam.OptParamKeyValueSet curParamKeyValue = null; int curFrame = timlineLayer._parentAnimClip.CurFrame; bool isLoop = timlineLayer._parentAnimClip.IsLoop; apAnimKeyframe firstKeyframe = timlineLayer._firstKeyFrame; apAnimKeyframe lastKeyframe = timlineLayer._lastKeyFrame; //int firstFrame = -1; //int lastFrame = -1; //if(isLoop) //{ // if(firstKeyframe != null) // { // firstFrame = firstKeyframe._frameIndex; // } // if(lastKeyframe != null) // { // lastFrame = lastKeyframe._frameIndex; // } //} _totalWeight = 0.0f; apAnimKeyframe curKeyframe = null; apAnimKeyframe prevKeyframe = null; apAnimKeyframe nextKeyframe = null; //int indexOffsetA = 0; //int indexOffsetB = 0; int lengthFrames = timlineLayer._parentAnimClip.EndFrame - timlineLayer._parentAnimClip.StartFrame; int tmpCurFrame = 0; //Debug.Log("Calculated--------------------------------"); for (int i = 0; i < _subParamKeyValues.Count; i++) { curParamKeyValue = _subParamKeyValues[i]; curParamKeyValue._dist = -10.0f; curParamKeyValue._isCalculated = false; //유효하지 않은 키프레임이면 처리하지 않는다. if (curParamKeyValue._paramSet.SyncKeyframe == null || !curParamKeyValue._paramSet.SyncKeyframe._isActive) { //Debug.Log("[" + i + "] Not Active or Null Keyframe"); continue; } curKeyframe = curParamKeyValue._paramSet.SyncKeyframe; prevKeyframe = curParamKeyValue._paramSet.SyncKeyframe._prevLinkedKeyframe; nextKeyframe = curParamKeyValue._paramSet.SyncKeyframe._nextLinkedKeyframe; //1. 프레임이 같다. => 100% if (curFrame == curKeyframe._frameIndex || ((curKeyframe._isLoopAsStart || curKeyframe._isLoopAsEnd) && curFrame == curKeyframe._loopFrameIndex)) { curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = 1.0f; _totalWeight += 1.0f; //Debug.Log("[" + i + "] <Exact Frame>"); } //else if(curFrame >= curKeyframe._activeFrameIndexMin && // curFrame < curKeyframe._frameIndex) else if (curKeyframe.IsFrameIn(curFrame, true)) { //범위 안에 들었다. [Prev - Cur] if (prevKeyframe != null) { //indexOffsetA = 0; //indexOffsetB = 0; //if(prevKeyframe._frameIndex > curKeyframe._frameIndex) //{ // //Loop인 경우 Prev가 더 클 수 있다. // indexOffsetA = -lengthFrames; //} tmpCurFrame = curFrame; if (tmpCurFrame > curKeyframe._frameIndex) { tmpCurFrame -= lengthFrames; } //float itp = apAnimCurve.GetCurvedRelativeInterpolation(prevKeyframe._curveKey, curKeyframe._curveKey, curFrame, curKeyframe._curveKey._isPrevKeyUseDummyIndex, false); //이전 코드 //_cal_itp = apAnimCurve.GetCurvedRelativeInterpolation(curKeyframe._curveKey, prevKeyframe._curveKey, tmpCurFrame, true); //>> 다음 코드 _cal_itp = curKeyframe._curveKey.GetItp_Int(tmpCurFrame, true); curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = _cal_itp; _totalWeight += _cal_itp; //Debug.Log("[" + i + "] [Prev ~ Cur] " + itp); //Debug.Log("Prev ~ Next : " + itp); } else { //연결된게 없다면 이게 100% 가중치를 갖는다. curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = 1.0f; _totalWeight += 1.0f; //Debug.Log("[" + i + "] [Prev ?? ~ Cur] 1.0"); } } //else if(curFrame > curKeyframe._frameIndex && // curFrame <= curKeyframe._activeFrameIndexMax) else if (curKeyframe.IsFrameIn(curFrame, false)) { //범위안에 들었다 [Cur - Next] if (nextKeyframe != null) { //indexOffsetA = 0; //indexOffsetB = 0; //if(nextKeyframe._frameIndex < curKeyframe._frameIndex) //{ // //Loop인 경우 Next가 더 작을 수 있다. // indexOffsetB = lengthFrames; //} tmpCurFrame = curFrame; if (tmpCurFrame < curKeyframe._frameIndex) { tmpCurFrame += lengthFrames; } //float itp = apAnimCurve.GetCurvedRelativeInterpolation(curKeyframe._curveKey, nextKeyframe._curveKey, curFrame, false, curKeyframe._curveKey._isNextKeyUseDummyIndex); //이전 코드 //_cal_itp = apAnimCurve.GetCurvedRelativeInterpolation(curKeyframe._curveKey, nextKeyframe._curveKey, tmpCurFrame, false); //>> 다음 코드 _cal_itp = curKeyframe._curveKey.GetItp_Int(tmpCurFrame, false); //itp = 1.0f - itp;//결과가 B에 맞추어지므로 여기서는 Reverse curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = _cal_itp; _totalWeight += _cal_itp; //Debug.Log("[" + i + "] [Cur ~ Next] " + itp); } else { //연결된게 없다면 이게 100% 가중치를 갖는다. curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = 1.0f; _totalWeight += 1.0f; //Debug.Log("[" + i + "] [Cur ~ Next ??] 1.0"); } } } if (_totalWeight > 0.0f) { //Debug.Log("Result --------------------------------"); for (int i = 0; i < _subParamKeyValues.Count; i++) { curParamKeyValue = _subParamKeyValues[i]; if (curParamKeyValue._isCalculated) { curParamKeyValue._weight /= _totalWeight; //Debug.Log("[" + curParamKeyValue._weight + "]"); } else { curParamKeyValue._weight = 0.0f; } } //Debug.Log("-------------------------------------"); } }