//----------------------------------------------------------------------------------- // 중요 //----------------------------------------------------------------------------------- /// <summary> /// ParamSet간의 Weight를 계산한다. [ControlParam이 입력값인 경우] /// </summary> private void CalculateWeight_ControlParam() { //if(_controlParam == null) if (_keyParamSetGroup == null || _keyParamSetGroup._keyControlParam == null) { Debug.LogError("Key ParamSet Group is Null / Key Control Param Is null"); return; } apControlParam controlParam = _keyParamSetGroup._keyControlParam; //1. 현재 값에 따라서 Dist 값을 넣자 float minDist = float.MaxValue; float maxDist = 0.0f; float dist = 0.0f; apCalculatedResultParam.ParamKeyValueSet curParamKeyValue = null; apCalculatedResultParam.ParamKeyValueSet nextParamKeyValue = null; //int nSubParamKeyValues = _subParamKeyValues.Count; _totalWeight = 0.0f; for (int i = 0; i < _subParamKeyValues.Count; i++) { curParamKeyValue = _subParamKeyValues[i]; dist = -10.0f; curParamKeyValue._isCalculated = false; #if UNITY_EDITOR //if (!curParamKeyValue._isActive_InEditorExclusive) if (!curParamKeyValue.IsActive) { //에디터에서 제한한 Paramkey면 curParamKeyValue._dist = -10.0f; curParamKeyValue._isCalculated = false; bool isKeyNull = false; bool isCalculateNotEnabled = false; if (curParamKeyValue._keyParamSetGroup == null) { isKeyNull = true; } else if (!curParamKeyValue._keyParamSetGroup.IsCalculateEnabled) { isCalculateNotEnabled = true; } //Debug.LogError("CalResultParamSubList Weight Failed : " + _parentResultParam._targetRenderUnit + " / " // + "ParamSetGroup Is Null : " + (isKeyNull) + " / Calculate Enabled : " + isCalculateNotEnabled); continue; } #endif //수식 1 : IDW 방식 (Inverse Distance Weighting) //----------------------------------------------- #region 수식 1 적용 switch (controlParam._valueType) { //case apControlParam.TYPE.Bool: // if (curParamKeyValue._paramSet._conSyncValue_Bool == controlParam._bool_Cur) // { // curParamKeyValue._dist = 0.0f; // curParamKeyValue._isCalculated = true; // } // else // { // curParamKeyValue._dist = -10.0f; // curParamKeyValue._isCalculated = false; // } // break; case apControlParam.TYPE.Int: dist = controlParam.GetNormalizedDistance_Int(curParamKeyValue._paramSet._conSyncValue_Int); break; case apControlParam.TYPE.Float: dist = controlParam.GetNormalizedDistance_Float(curParamKeyValue._paramSet._conSyncValue_Float); break; case apControlParam.TYPE.Vector2: dist = controlParam.GetNormalizedDistance_Vector2(curParamKeyValue._paramSet._conSyncValue_Vector2); break; //case apControlParam.TYPE.Vector3: // dist = controlParam.GetNormalizedDistance_Vector3(curParamKeyValue._paramSet._conSyncValue_Vector3); // break; //case apControlParam.TYPE.Color: // break; } if (dist < -1.0f) { //계산 안함 continue; } curParamKeyValue._dist = dist; curParamKeyValue._isCalculated = true; if (dist < minDist) { minDist = dist; //<<최소 값 } if (dist > maxDist) { maxDist = dist; //최대값 (가장 Weight가 적게 걸리는 값) } #endregion //----------------------------------------------- } if (maxDist - minDist < 0.0001f) { maxDist = minDist + 0.0001f; } _totalWeight = 0.0f; // 여러개의 키값을 사용할 거라면 #region [미사용 코드] 수식이 중복된다. //List<float> keepWeightRatios = new List<float>(); //for (int i = 0; i < _subParamKeyValues.Count; i++) //{ // curParamKeyValue = _subParamKeyValues[i]; // if(curParamKeyValue._dist < -1.0f) // { // continue; // } // float keepWeightRatio = Mathf.Clamp01((curParamKeyValue._dist - minDist) / (maxDist - minDist)); // keepWeightRatios.Add(keepWeightRatio); //} //keepWeightRatios.Sort(delegate (float a, float b) // { // return (int)((a * 1000.0f) - (b * 1000.0f)); // }); //bool isLimitedWeight = false; //float keepWeightRatio_Min = 0.0f; //float keepWeightRatio_Min2 = 0.0f; //float limitWeight = 1.0f; //if(keepWeightRatios.Count >= 2) //{ // isLimitedWeight = true; // keepWeightRatio_Min = keepWeightRatios[0]; // keepWeightRatio_Min2 = keepWeightRatios[1]; // if(keepWeightRatio_Min2 - keepWeightRatio_Min < 0.0001f) // { // keepWeightRatio_Min2 = keepWeightRatio_Min + 0.0001f; // } // limitWeight = Mathf.Clamp01(0.5f - keepWeightRatio_Min) * 2; //} #endregion #region [미사용 코드] 역 선형 수식이지만 오류가 있다. //for (int i = 0; i < _subParamKeyValues.Count; i++) //{ // curParamKeyValue = _subParamKeyValues[i]; // if (curParamKeyValue._dist < -1.0f) // { // curParamKeyValue._weight = 0.0f; // curParamKeyValue._isCalculated = false; // continue; // } // //ITP 계산 // //1 - Dist로 역 선형 보간을 사용한다. // //가장 가까운 포인트에서 MinDist를 구한다. // //Min Dist가 0일때 = 어느 점에 도달했을때 // //> 다른 Weight가 0이 되어야 하며, Min Point인 부분은 Weight가 보전되어야 한다. // //"보전률" = deltaMinDist가 작을수록 크다 (max를 구해야겠네) // //"Mul-Weight" : 보전률에 비례한다. 보전률이 0일땐 MinDist (Normalize)의 값을 가지고, 최대일땐 1의 값을 가진다. // float keepWeightRatio = 1.0f - Mathf.Clamp01((curParamKeyValue._dist - minDist) / (maxDist - minDist)); // // 가까우면 = 1 (감소 없음) / 멀면 minDist (포인트에 근접할 수록 0에 수렴) // float multiplyWeight = (1.0f * keepWeightRatio) + minDist * (1.0f - keepWeightRatio); // //만약, minDist가 일정 값 이하로 떨어지면 0으로 multiplyWeight가 아예 수렴해야한다. // //float revWeight = (maxDist - curParamKeyValue._dist) * multiplyWeight; // float revWeight = (2.0f - curParamKeyValue._dist) * multiplyWeight;//<<수정 : MaxDist가 아니라 Normalize 영역 크기(-1 ~ 1 = 2)로 빼야 적절하게 나온다. // _totalWeight += revWeight; // curParamKeyValue._weight = revWeight; // curParamKeyValue._isCalculated = true; //} #endregion for (int i = 0; i < _subParamKeyValues.Count; i++) { curParamKeyValue = _subParamKeyValues[i]; if (curParamKeyValue._dist < -1.0f) { curParamKeyValue._weight = 0.0f; curParamKeyValue._weightBase = 0.0f; curParamKeyValue._isCalculated = false; continue; } //변경 //Weight 시작값이 기본 1이 아니라, 거리에 따른 가중치로 바뀐다. curParamKeyValue._weight = 1.0f; if (_subParamKeyValues.Count <= 2) //if(true) { curParamKeyValue._weightBase = 1.0f; } else { curParamKeyValue._weightBase = controlParam.GetInterpolationWeight(curParamKeyValue._dist); } curParamKeyValue._isCalculated = true; //_totalWeight += 1.0f; _totalWeight += curParamKeyValue._weight; //변경! } if (_subParamKeyValues.Count >= 2) { _totalWeight = 0.0f; for (int i = 0; i < _subParamKeyValues.Count - 1; i++) { curParamKeyValue = _subParamKeyValues[i]; if (!curParamKeyValue._isCalculated) { continue; } if (curParamKeyValue._weight < 0.00001f) { continue; } for (int j = i + 1; j < _subParamKeyValues.Count; j++) { nextParamKeyValue = _subParamKeyValues[j]; if (!nextParamKeyValue._isCalculated) { continue; } float sumDist = curParamKeyValue._dist + nextParamKeyValue._dist; if (sumDist < 0.0001f) { curParamKeyValue._weight *= 1.0f; nextParamKeyValue._weight *= 1.0f; } else { float itp = Mathf.Clamp01((sumDist - curParamKeyValue._dist) / sumDist); //float baseWeight = (curParamKeyValue._weightBase + nextParamKeyValue._weightBase) * 0.5f; float baseWeight = Mathf.Clamp01(curParamKeyValue._weightBase + nextParamKeyValue._weightBase); //float baseWeight = curParamKeyValue._weightBase * nextParamKeyValue._weightBase; //float itp = apAnimCurve.GetSmoothInterpolation((sumDist - curParamKeyValue._dist) / sumDist); //curParamKeyValue._weight *= itp; //nextParamKeyValue._weight *= (1.0f - itp); curParamKeyValue._weight = curParamKeyValue._weight * ((1.0f - baseWeight) + itp * baseWeight); nextParamKeyValue._weight = nextParamKeyValue._weight * ((1.0f - baseWeight) + (1.0f - itp) * baseWeight); if (itp < 0.00001f) { break; } } } } for (int i = 0; i < _subParamKeyValues.Count; i++) { curParamKeyValue = _subParamKeyValues[i]; if (curParamKeyValue._isCalculated) { _totalWeight += curParamKeyValue._weight; } } } //공통 부분 if (_totalWeight > 0.0f) { for (int i = 0; i < _subParamKeyValues.Count; i++) { curParamKeyValue = _subParamKeyValues[i]; if (curParamKeyValue._isCalculated) { curParamKeyValue._weight /= _totalWeight; } else { curParamKeyValue._weight = 0.0f; } } } }
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; } } } }