/// <summary> /// Keyframe에 Rotation Bias 설정이 있는 경우 관련 변수를 갱신한다. /// </summary> /// <param name="rotationBias"></param> /// <param name="rotationCount"></param> public void SetAnimRotationBias(apAnimKeyframe.ROTATION_BIAS rotationBias, int rotationCount) { if (rotationBias == apAnimKeyframe.ROTATION_BIAS.CW) { _isAnimRotationBias = true; _animRotationBiasAngle = -360 * rotationCount; } else if (rotationBias == apAnimKeyframe.ROTATION_BIAS.CCW) { _isAnimRotationBias = true; _animRotationBiasAngle = 360 * rotationCount; } else { _isAnimRotationBias = false; _animRotationBiasAngle = 0; } //에디터에서는 최적화가 아니라 언제 바뀔지 모르므로 항상 갱신 //if(_animRotationBiasAngle_Prev != _animRotationBiasAngle && _isAnimRotationBias) if (_isAnimRotationBias) { if (_animRotationBiasedMatrix == null) { _animRotationBiasedMatrix = new apMatrix(); } if (_modifiedMesh != null) { _animRotationBiasedMatrix.SetTRS( _modifiedMesh._transformMatrix._pos, _modifiedMesh._transformMatrix._angleDeg + _animRotationBiasAngle, _modifiedMesh._transformMatrix._scale ); } else if (_modifiedBone != null) { _animRotationBiasedMatrix.SetTRS( _modifiedBone._transformMatrix._pos, _modifiedBone._transformMatrix._angleDeg + _animRotationBiasAngle, _modifiedBone._transformMatrix._scale ); } else { _animRotationBiasedMatrix.SetIdentity(); } _animRotationBiasAngle_Prev = _animRotationBiasAngle; } }
// 4) World Matrix를 만든다. // 이 함수는 Parent의 MeshGroupTransform이 연산된 후 -> Vertex가 연산되기 전에 호출되어야 한다. public void MakeWorldMatrix(bool isRecursive) { _localMatrix.SetIdentity(); _localMatrix._pos = _deltaPos; _localMatrix._angleDeg = _deltaAngle; _localMatrix._scale.x = _deltaScale.x; _localMatrix._scale.y = _deltaScale.y; _localMatrix.MakeMatrix(); //World Matrix = ParentMatrix x LocalMatrix //Root인 경우에는 MeshGroup의 Matrix를 이용하자 //_invWorldMatrix_NonModified.SetIdentity(); if (_parentBone == null) { _worldMatrix.SetMatrix(_defaultMatrix); _worldMatrix.Add(_localMatrix); _worldMatrix_NonModified.SetMatrix(_defaultMatrix); //Local Matrix 없이 Default만 지정 if (_parentOptTransform != null) { //Debug.Log("SetParentOptTransform Matrix : [" + _parentOptTransform.transform.name + "] : " + _parentOptTransform._matrix_TFResult_World.Scale2); //Non Modified도 동일하게 적용 //렌더유닛의 WorldMatrix를 넣어주자 _worldMatrix.RMultiply(_parentOptTransform._matrix_TFResult_World); //RenderUnit의 WorldMatrixWrap의 Opt 버전 _worldMatrix_NonModified.RMultiply(_parentOptTransform._matrix_TFResult_WorldWithoutMod); } } else { _worldMatrix.SetMatrix(_defaultMatrix); _worldMatrix.Add(_localMatrix); _worldMatrix.RMultiply(_parentBone._worldMatrix); _worldMatrix_NonModified.SetMatrix(_defaultMatrix); //Local Matrix 없이 Default만 지정 _worldMatrix_NonModified.RMultiply(_parentBone._worldMatrix_NonModified); } //처리된 TRS _updatedWorldPos_NoRequest.x = _worldMatrix._pos.x; _updatedWorldPos_NoRequest.y = _worldMatrix._pos.y; _updatedWorldAngle_NoRequest = _worldMatrix._angleDeg; _updatedWorldScale_NoRequest.x = _worldMatrix._scale.x; _updatedWorldScale_NoRequest.y = _worldMatrix._scale.y; _updatedWorldPos = _updatedWorldPos_NoRequest; _updatedWorldAngle = _updatedWorldAngle_NoRequest; _updatedWorldScale = _updatedWorldScale_NoRequest; if (_isIKCalculated) { _IKRequestAngleResult -= 90.0f; while (_IKRequestAngleResult > 180.0f) { _IKRequestAngleResult -= 360.0f; } while (_IKRequestAngleResult < -180.0f) { _IKRequestAngleResult += 360.0f; } //_updatedWorldAngle += _IKRequestAngleResult * _IKRequestWeight; _updatedWorldAngle = _updatedWorldAngle * (1.0f - _IKRequestWeight) + (_IKRequestAngleResult * _IKRequestWeight); //Debug.Log("Add IK [" + _name + "] : " + _IKRequestAngleResult); _IKRequestAngleResult = 0.0f; _IKRequestWeight = 0.0f; } //스크립트로 외부에서 제어한 경우 if (_isExternalUpdate_Position) { _updatedWorldPos.x = (_exUpdate_Pos.x * _externalUpdateWeight) + (_updatedWorldPos.x * (1.0f - _externalUpdateWeight)); _updatedWorldPos.y = (_exUpdate_Pos.y * _externalUpdateWeight) + (_updatedWorldPos.y * (1.0f - _externalUpdateWeight)); } if (_isExternalUpdate_Rotation) { _updatedWorldAngle = (_exUpdate_Angle * _externalUpdateWeight) + (_updatedWorldAngle * (1.0f - _externalUpdateWeight)); } if (_isExternalUpdate_Scaling) { _updatedWorldScale.x = (_exUpdate_Scale.x * _externalUpdateWeight) + (_updatedWorldScale.x * (1.0f - _externalUpdateWeight)); _updatedWorldScale.y = (_exUpdate_Scale.y * _externalUpdateWeight) + (_updatedWorldScale.y * (1.0f - _externalUpdateWeight)); } if (_isIKCalculated || _isExternalUpdate_Position || _isExternalUpdate_Rotation || _isExternalUpdate_Scaling) { //WorldMatrix를 갱신해주자 _worldMatrix.SetTRS(_updatedWorldPos.x, _updatedWorldPos.y, _updatedWorldAngle, _updatedWorldScale.x, _updatedWorldScale.y); _isIKCalculated = false; _isExternalUpdate_Position = false; _isExternalUpdate_Rotation = false; _isExternalUpdate_Scaling = false; } //World Matrix는 MeshGroup과 동일한 Space의 값을 가진다. //그러나 실제로 Bone World Matrix는 //Root - MeshGroup...(Rec) - Bone Group - Bone.. (Rec <- 여기) //의 레벨을 가진다. //Root 밑으로는 모두 World에 대해서 동일한 Space를 가지므로 //Root를 찾아서 Scale을 제어하자...? //일단 Parent에서 빼두자 //_transformLocalMatrix.SetMatrix(_worldMatrix); #if UNITY_EDITOR _shapePoint_End = new Vector2(0.0f, _shapeLength); _shapePoint_Mid1 = new Vector2(-_shapeWidth * 0.5f, _shapeLength * 0.2f); _shapePoint_Mid2 = new Vector2(_shapeWidth * 0.5f, _shapeLength * 0.2f); float taperRatio = Mathf.Clamp01((float)(100 - _shapeTaper) / 100.0f); _shapePoint_End1 = new Vector2(-_shapeWidth * 0.5f * taperRatio, _shapeLength); _shapePoint_End2 = new Vector2(_shapeWidth * 0.5f * taperRatio, _shapeLength); _shapePoint_End = _worldMatrix.MtrxToSpace.MultiplyPoint(_shapePoint_End); _shapePoint_Mid1 = _worldMatrix.MtrxToSpace.MultiplyPoint(_shapePoint_Mid1); _shapePoint_Mid2 = _worldMatrix.MtrxToSpace.MultiplyPoint(_shapePoint_Mid2); _shapePoint_End1 = _worldMatrix.MtrxToSpace.MultiplyPoint(_shapePoint_End1); _shapePoint_End2 = _worldMatrix.MtrxToSpace.MultiplyPoint(_shapePoint_End2); #endif //Rigging을 위해서 Matrix 통합 식을 만들자 //실제 식 // world * default_inv * VertPos W _vertWorld2BoneModWorldMatrix = _worldMatrix.MtrxToSpace; _vertWorld2BoneModWorldMatrix *= _worldMatrix_NonModified.MtrxToLowerSpace; if (_socketTransform != null) { //소켓을 업데이트 하자 _socketTransform.localPosition = new Vector3(_worldMatrix._pos.x, _worldMatrix._pos.y, 0); _socketTransform.localRotation = Quaternion.Euler(0.0f, 0.0f, _worldMatrix._angleDeg); _socketTransform.localScale = new Vector3(_worldMatrix._scale.x, _worldMatrix._scale.y, 1.0f); } //Child도 호출해준다. if (isRecursive && _childBones != null) { for (int i = 0; i < _childBones.Length; i++) { _childBones[i].MakeWorldMatrix(true); } } }
/// <summary> /// CalculateStack을 업데이트 한다. /// Pre-Update이다. Rigging, VertWorld는 제외된다. /// </summary> public void UpdateCalculate_Pre() { //#if UNITY_EDITOR // Profiler.BeginSample("Transform - 1. Stack Calculate"); //#endif //1. Calculated Stack 업데이트 if (_calculatedStack != null) { _calculatedStack.Calculate_Pre(); } //#if UNITY_EDITOR // Profiler.EndSample(); //#endif //#if UNITY_EDITOR // Profiler.BeginSample("Transform - 2. Matrix / Color"); //#endif //2. Calculated의 값 적용 + 계층적 Matrix 적용 if (CalculatedStack.MeshWorldMatrixWrap != null) { //변경전 //_calclateTmpMatrix.SRMultiply(_calculatedStack.MeshWorldMatrixWrap, true); //_matrix_TF_Cal_ToWorld = _calculateTmpMatrix.MtrxToSpace; //변경후 _matrix_TF_LocalModified.SetMatrix(_calculatedStack.MeshWorldMatrixWrap); //if(_calculatedStack.MeshWorldMatrixWrap.Scale2.magnitude < 0.8f) //{ // Debug.Log(name + " : Low Scale : " + _calculatedStack.MeshWorldMatrixWrap.Scale2); //} } if (CalculatedStack.IsAnyColorCalculated) { _meshColor2X = CalculatedStack.MeshColor; _isVisible = CalculatedStack.IsMeshVisible; _isAnyColorCalculated = true; } else { _meshColor2X = _meshColor2X_Default; _isVisible = _isVisible_Default; } if (!_isVisible) { _meshColor2X.a = 0.0f; _isAnyColorCalculated = true; } if (_parentTransform != null) { //변경 전 //_calculateTmpMatrix.SRMultiply(_parentTransform.CalculatedTmpMatrix, true); //_matrix_TF_Cal_ToWorld = _calculateTmpMatrix.MtrxToSpace; //변경 후 _matrix_TF_ParentWorld.SetMatrix(_parentTransform._matrix_TFResult_World); _matrix_TF_ParentWorld_NonModified.SetMatrix(_parentTransform._matrix_TFResult_WorldWithoutMod); //색상은 2X 방식의 Add _meshColor2X.r = Mathf.Clamp01(((float)(_meshColor2X.r) - 0.5f) + ((float)(_parentTransform._meshColor2X.r) - 0.5f) + 0.5f); _meshColor2X.g = Mathf.Clamp01(((float)(_meshColor2X.g) - 0.5f) + ((float)(_parentTransform._meshColor2X.g) - 0.5f) + 0.5f); _meshColor2X.b = Mathf.Clamp01(((float)(_meshColor2X.b) - 0.5f) + ((float)(_parentTransform._meshColor2X.b) - 0.5f) + 0.5f); _meshColor2X.a *= _parentTransform._meshColor2X.a; if (_parentTransform._isAnyColorCalculated) { _isAnyColorCalculated = true; } } if (_meshColor2X.a < VISIBLE_ALPHA //|| !CalculatedStack.IsMeshVisible ) { _isVisible = false; _meshColor2X.a = 0.0f; _isAnyColorCalculated = true; } //MakeTransformMatrix(); < 이 함수 부분 //World Matrix를 만든다. _matrix_TFResult_World.RMultiply(_matrix_TF_ToParent); //변경 : ToParent -> LocalModified -> ParentWorld 순으로 바꾼다. _matrix_TFResult_World.RMultiply(_matrix_TF_LocalModified); //<<[R] //_matrix_TFResult_World.RMultiply(_matrix_TF_ToParent);//<<[R] _matrix_TFResult_World.RMultiply(_matrix_TF_ParentWorld); //<<[R] //_matrix_TFResult_WorldWithoutMod.SRMultiply(_matrix_TF_ToParent, true);//ToParent는 넣지 않는다. //_matrix_TFResult_WorldWithoutMod.SRMultiply(_matrix_TF_ParentWorld, true);//<<[SR] //Without Mod는 계산하지 않았을 경우에만 계산한다. //바뀌지 않으므로 if (!_isCalculateWithoutMod) { _matrix_TFResult_WorldWithoutMod.RMultiply(_matrix_TF_ToParent); //<<[R] _matrix_TFResult_WorldWithoutMod.RMultiply(_matrix_TF_ParentWorld_NonModified); //<<[R] //리깅용 단축식을 추가한다. if (_childMesh != null) { _vertLocal2MeshWorldMatrix = _matrix_TFResult_WorldWithoutMod.MtrxToSpace; _vertLocal2MeshWorldMatrix *= _childMesh._matrix_Vert2Mesh; _vertWorld2MeshLocalMatrix = _childMesh._matrix_Vert2Mesh_Inverse; _vertWorld2MeshLocalMatrix *= _matrix_TFResult_WorldWithoutMod.MtrxToLowerSpace; _vertMeshWorldNoModMatrix = _matrix_TFResult_WorldWithoutMod.MtrxToSpace; _vertMeshWorldNoModInverseMatrix = _matrix_TFResult_WorldWithoutMod.MtrxToLowerSpace; } _isCalculateWithoutMod = true; } //처리된 TRS _updatedWorldPos_NoRequest.x = _matrix_TFResult_World._pos.x; _updatedWorldPos_NoRequest.y = _matrix_TFResult_World._pos.y; _updatedWorldAngle_NoRequest = _matrix_TFResult_World._angleDeg; _updatedWorldScale_NoRequest.x = _matrix_TFResult_World._scale.x; _updatedWorldScale_NoRequest.y = _matrix_TFResult_World._scale.y; _updatedWorldPos = _updatedWorldPos_NoRequest; _updatedWorldAngle = _updatedWorldAngle_NoRequest; _updatedWorldScale = _updatedWorldScale_NoRequest; //스크립트로 외부에서 제어한 경우 if (_isExternalUpdate_Position) { _updatedWorldPos.x = (_exUpdate_Pos.x * _externalUpdateWeight) + (_updatedWorldPos.x * (1.0f - _externalUpdateWeight)); _updatedWorldPos.y = (_exUpdate_Pos.y * _externalUpdateWeight) + (_updatedWorldPos.y * (1.0f - _externalUpdateWeight)); } if (_isExternalUpdate_Rotation) { _updatedWorldAngle = (_exUpdate_Angle * _externalUpdateWeight) + (_updatedWorldAngle * (1.0f - _externalUpdateWeight)); } if (_isExternalUpdate_Scaling) { _updatedWorldScale.x = (_exUpdate_Scale.x * _externalUpdateWeight) + (_updatedWorldScale.x * (1.0f - _externalUpdateWeight)); _updatedWorldScale.y = (_exUpdate_Scale.y * _externalUpdateWeight) + (_updatedWorldScale.y * (1.0f - _externalUpdateWeight)); } if (_isExternalUpdate_Position || _isExternalUpdate_Rotation || _isExternalUpdate_Scaling) { //WorldMatrix를 갱신해주자 _matrix_TFResult_World.SetTRS(_updatedWorldPos.x, _updatedWorldPos.y, _updatedWorldAngle, _updatedWorldScale.x, _updatedWorldScale.y); _isExternalUpdate_Position = false; _isExternalUpdate_Rotation = false; _isExternalUpdate_Scaling = false; } //추가 : 소켓도 만들어준다. //Vert World를 아직 계산하지 않았지만 Socket 처리에는 문제가 없다. if (_socketTransform != null) { _socketTransform.localPosition = new Vector3(_matrix_TFResult_World._pos.x, _matrix_TFResult_World._pos.y, 0); _socketTransform.localRotation = Quaternion.Euler(0.0f, 0.0f, _matrix_TFResult_World._angleDeg); _socketTransform.localScale = new Vector3(_matrix_TFResult_World._scale.x, _matrix_TFResult_World._scale.y, 1.0f); } //#if UNITY_EDITOR // Profiler.EndSample(); //#endif //[MeshUpdate]는 Post Update로 전달 //3. 자식 호출 //자식 객체도 업데이트를 한다. if (_childTransforms != null) { for (int i = 0; i < _childTransforms.Length; i++) { _childTransforms[i].UpdateCalculate_Pre(); } } }
/// <summary> /// Keyframe에 Rotation Bias 설정이 있는 경우 관련 변수를 갱신한다. /// </summary> /// <param name="rotationBias"></param> /// <param name="rotationCount"></param> public void SetAnimRotationBias(apAnimKeyframe.ROTATION_BIAS rotationBias, int rotationCount) { if (rotationBias == apAnimKeyframe.ROTATION_BIAS.CW) { _isAnimRotationBias = true; _animRotationBiasAngle = -360 * rotationCount; } else if (rotationBias == apAnimKeyframe.ROTATION_BIAS.CCW) { _isAnimRotationBias = true; _animRotationBiasAngle = 360 * rotationCount; } else { _isAnimRotationBias = false; _animRotationBiasAngle = 0; } if (_animRotationBiasAngle_Prev != _animRotationBiasAngle && _isAnimRotationBias) { if (_animRotationBiasedMatrix == null) { _animRotationBiasedMatrix = new apMatrix(); } if (_modifiedMesh != null) { _animRotationBiasedMatrix.SetTRS( _modifiedMesh._transformMatrix._pos, _modifiedMesh._transformMatrix._angleDeg + _animRotationBiasAngle, _modifiedMesh._transformMatrix._scale ); } else if (_modifiedMeshSet != null) { //추가됨 19.5.24 : ModMeshSet으로 계산하기 _subModMesh_Transform = _modifiedMeshSet.SubModMesh_Transform; if (_subModMesh_Transform != null) { _animRotationBiasedMatrix.SetTRS( _subModMesh_Transform._transformMatrix._pos, _subModMesh_Transform._transformMatrix._angleDeg + _animRotationBiasAngle, _subModMesh_Transform._transformMatrix._scale ); } else { Debug.LogError("TODO : 에러 : 애니메이션에 SubModMeshSet_Transform이 없다."); _animRotationBiasedMatrix.SetIdentity(); } } else if (_modifiedBone != null) { _animRotationBiasedMatrix.SetTRS( _modifiedBone._transformMatrix._pos, _modifiedBone._transformMatrix._angleDeg + _animRotationBiasAngle, _modifiedBone._transformMatrix._scale ); } else { _animRotationBiasedMatrix.SetIdentity(); } _animRotationBiasAngle_Prev = _animRotationBiasAngle; } }
// File To Bone //--------------------------------------------------- public bool DecodeData(string strSrc) { try { if (strSrc.Length < 3) { return(false); } int nName = int.Parse(strSrc.Substring(0, 3)); _name = strSrc.Substring(3, nName); strSrc = strSrc.Substring(3 + nName); //나머지는 델리미터를 이용한다. string[] strUnits = strSrc.Split(new string[] { "/" }, StringSplitOptions.None); int iStr = 0; _unitID = int.Parse(strUnits[iStr]); iStr++; _parentUnitID = int.Parse(strUnits[iStr]); iStr++; _level = int.Parse(strUnits[iStr]); iStr++; _depth = int.Parse(strUnits[iStr]); iStr++; _childUnitID.Clear(); int nChild = int.Parse(strUnits[iStr]); iStr++; for (int i = 0; i < nChild; i++) { _childUnitID.Add(int.Parse(strUnits[iStr])); iStr++; } _defaultMatrix.SetIdentity(); _defaultMatrix.SetTRS( new Vector2(float.Parse(strUnits[iStr]), float.Parse(strUnits[iStr + 1])), float.Parse(strUnits[iStr + 2]), new Vector2(float.Parse(strUnits[iStr + 3]), float.Parse(strUnits[iStr + 4])) ); iStr += 5; _color.r = float.Parse(strUnits[iStr]); _color.g = float.Parse(strUnits[iStr + 1]); _color.b = float.Parse(strUnits[iStr + 2]); _color.a = float.Parse(strUnits[iStr + 3]); iStr += 4; _shapeWidth = int.Parse(strUnits[iStr]); _shapeLength = int.Parse(strUnits[iStr + 1]); _shapeTaper = int.Parse(strUnits[iStr + 2]); iStr += 3; _optionIK = (apBone.OPTION_IK) int.Parse(strUnits[iStr]); _isIKTail = (int.Parse(strUnits[iStr + 1]) == 1) ? true : false; iStr += 2; _IKTargetBoneUnitID = int.Parse(strUnits[iStr]); _IKNextChainedBoneUnitID = int.Parse(strUnits[iStr + 1]); _IKHeaderBoneUnitID = int.Parse(strUnits[iStr + 2]); iStr += 3; _isIKAngleRange = (int.Parse(strUnits[iStr]) == 1) ? true : false; _IKAngleRange_Lower = float.Parse(strUnits[iStr + 1]); _IKAngleRange_Upper = float.Parse(strUnits[iStr + 2]); _IKAnglePreferred = float.Parse(strUnits[iStr + 3]); iStr += 4; _isSocketEnabled = (int.Parse(strUnits[iStr]) == 1) ? true : false; _isImportEnabled = true; _isIKEnabled = true; _isShapeEnabled = true; } catch (Exception ex) { Debug.LogError("Decode Exception : " + ex); return(false); } return(true); }
/// <summary> /// CalculateStack을 업데이트 한다. /// Pre-Update이다. Rigging, VertWorld는 제외된다. /// </summary> public void UpdateCalculate_Pre() { //#if UNITY_EDITOR // Profiler.BeginSample("Transform - 1. Stack Calculate"); //#endif //1. Calculated Stack 업데이트 if (_calculatedStack != null) { _calculatedStack.Calculate_Pre(); } //#if UNITY_EDITOR // Profiler.EndSample(); //#endif //#if UNITY_EDITOR // Profiler.BeginSample("Transform - 2. Matrix / Color"); //#endif //2. Calculated의 값 적용 + 계층적 Matrix 적용 if (CalculatedStack.MeshWorldMatrixWrap != null) { //변경전 //_calclateTmpMatrix.SRMultiply(_calculatedStack.MeshWorldMatrixWrap, true); //_matrix_TF_Cal_ToWorld = _calculateTmpMatrix.MtrxToSpace; //변경후 _matrix_TF_LocalModified.SetMatrix(_calculatedStack.MeshWorldMatrixWrap); //if(_calculatedStack.MeshWorldMatrixWrap.Scale2.magnitude < 0.8f) //{ // Debug.Log(name + " : Low Scale : " + _calculatedStack.MeshWorldMatrixWrap.Scale2); //} } if (CalculatedStack.IsAnyColorCalculated) { _meshColor2X = CalculatedStack.MeshColor; _isVisible = CalculatedStack.IsMeshVisible; _isAnyColorCalculated = true; } else { _meshColor2X = _meshColor2X_Default; _isVisible = _isVisible_Default; } if (!_isVisible) { _meshColor2X.a = 0.0f; _isAnyColorCalculated = true; } //추가 11.30 : Extra Option if (_calculatedStack.IsExtraDepthChanged) { if (_func_ExtraDepthChanged != null) { _func_ExtraDepthChanged(this, _calculatedStack.ExtraDeltaDepth); } } if (_calculatedStack.IsExtraTextureChanged) { _isExtraTextureChanged = true; _extraTextureData = _calculatedStack.ExtraTextureData; if (_extraTextureData == null) { _isExtraTextureChanged = false; } } if (_isExtraTextureChanged_Prev != _isExtraTextureChanged || _extraTextureData_Prev != _extraTextureData) { #if UNITY_EDITOR if (Application.isPlaying) { #endif //Extra-Texture 이벤트가 발생하거나 해지되어서 상태가 바뀌었을 경우 //또는 새로운 텍스쳐가 발생했을 경우 if (_childMesh != null) { if (_isExtraTextureChanged) { //> 텍스쳐 교체 이벤트가 발생했다. //현재 처리중인 텍스쳐를 먼저 저장한 뒤, 교체 _extraDefaultTexture = _childMesh.GetCurrentProcessedTexture(); _childMesh.SetExtraChangedTexture(_extraTextureData._texture); } else { //>텍스쳐를 해지해야한다. 저장했던 값으로 되돌린다. _childMesh.SetExtraChangedTexture(_extraDefaultTexture); } } #if UNITY_EDITOR } #endif _isExtraTextureChanged_Prev = _isExtraTextureChanged; if (_isExtraTextureChanged) { _extraTextureData_Prev = _extraTextureData; } else { _extraTextureData_Prev = null; } } if (_parentTransform != null) { //변경 전 //_calculateTmpMatrix.SRMultiply(_parentTransform.CalculatedTmpMatrix, true); //_matrix_TF_Cal_ToWorld = _calculateTmpMatrix.MtrxToSpace; //변경 후 _matrix_TF_ParentWorld.SetMatrix(_parentTransform._matrix_TFResult_World); _matrix_TF_ParentWorld_NonModified.SetMatrix(_parentTransform._matrix_TFResult_WorldWithoutMod); //색상은 2X 방식의 Add _meshColor2X.r = Mathf.Clamp01(((float)(_meshColor2X.r) - 0.5f) + ((float)(_parentTransform._meshColor2X.r) - 0.5f) + 0.5f); _meshColor2X.g = Mathf.Clamp01(((float)(_meshColor2X.g) - 0.5f) + ((float)(_parentTransform._meshColor2X.g) - 0.5f) + 0.5f); _meshColor2X.b = Mathf.Clamp01(((float)(_meshColor2X.b) - 0.5f) + ((float)(_parentTransform._meshColor2X.b) - 0.5f) + 0.5f); _meshColor2X.a *= _parentTransform._meshColor2X.a; if (_parentTransform._isAnyColorCalculated) { _isAnyColorCalculated = true; } } if (_meshColor2X.a < VISIBLE_ALPHA //|| !CalculatedStack.IsMeshVisible ) { _isVisible = false; _meshColor2X.a = 0.0f; _isAnyColorCalculated = true; } //MakeTransformMatrix(); < 이 함수 부분 //World Matrix를 만든다. _matrix_TFResult_World.RMultiply(_matrix_TF_ToParent); //변경 : ToParent -> LocalModified -> ParentWorld 순으로 바꾼다. _matrix_TFResult_World.RMultiply(_matrix_TF_LocalModified); //<<[R] //_matrix_TFResult_World.RMultiply(_matrix_TF_ToParent);//<<[R] _matrix_TFResult_World.RMultiply(_matrix_TF_ParentWorld); //<<[R] //_matrix_TFResult_WorldWithoutMod.SRMultiply(_matrix_TF_ToParent, true);//ToParent는 넣지 않는다. //_matrix_TFResult_WorldWithoutMod.SRMultiply(_matrix_TF_ParentWorld, true);//<<[SR] //Without Mod는 계산하지 않았을 경우에만 계산한다. //바뀌지 않으므로 if (!_isCalculateWithoutMod) { _matrix_TFResult_WorldWithoutMod.RMultiply(_matrix_TF_ToParent); //<<[R] _matrix_TFResult_WorldWithoutMod.RMultiply(_matrix_TF_ParentWorld_NonModified); //<<[R] //리깅용 단축식을 추가한다. if (_childMesh != null) { _vertLocal2MeshWorldMatrix = _matrix_TFResult_WorldWithoutMod.MtrxToSpace; _vertLocal2MeshWorldMatrix *= _childMesh._matrix_Vert2Mesh; _vertWorld2MeshLocalMatrix = _childMesh._matrix_Vert2Mesh_Inverse; _vertWorld2MeshLocalMatrix *= _matrix_TFResult_WorldWithoutMod.MtrxToLowerSpace; _vertMeshWorldNoModMatrix = _matrix_TFResult_WorldWithoutMod.MtrxToSpace; _vertMeshWorldNoModInverseMatrix = _matrix_TFResult_WorldWithoutMod.MtrxToLowerSpace; } _isCalculateWithoutMod = true; } //_convert2TargetMatrix4x4 = Matrix4x4.identity; //_convert2TargetMatrix3x3 = apMatrix3x3.identity; _isCamOrthoCorrection = false; if (_portrait._billboardType != apPortrait.BILLBOARD_TYPE.None && _childMesh != null) { Camera curCamera = _portrait.GetCamera(); if (curCamera != null && !curCamera.orthographic) { //Perspective 카메라라면 Vector3 pos_Cam = curCamera.worldToCameraMatrix.MultiplyPoint3x4(_childMesh.transform.position); //Vector3 pos_Cam = (curCamera.worldToCameraMatrix * transform.localToWorldMatrix).MultiplyPoint3x4(new Vector3(_matrix_TFResult_World._pos.x, _matrix_TFResult_World._pos.y, 0)); float zDepth = pos_Cam.z; float zRatio = zDepth / _portrait.GetZDepth(); //Debug.Log("pos_Cam : " + pos_Cam + " / " + zRatio); //transform.tr//>>TODO _isCamOrthoCorrection = true; Matrix4x4 orthoConvertMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(zRatio, zRatio, 1)); _convert2TargetMatrix4x4 = _childMesh.transform.worldToLocalMatrix * curCamera.cameraToWorldMatrix * orthoConvertMatrix * curCamera.worldToCameraMatrix * _childMesh.transform.localToWorldMatrix; _convert2TargetMatrix3x3 = apMatrix3x3.identity; _convert2TargetMatrix3x3._m00 = _convert2TargetMatrix4x4.m00; _convert2TargetMatrix3x3._m01 = _convert2TargetMatrix4x4.m01; _convert2TargetMatrix3x3._m02 = _convert2TargetMatrix4x4.m03; _convert2TargetMatrix3x3._m10 = _convert2TargetMatrix4x4.m10; _convert2TargetMatrix3x3._m11 = _convert2TargetMatrix4x4.m11; _convert2TargetMatrix3x3._m12 = _convert2TargetMatrix4x4.m13; _convert2TargetMatrix3x3._m20 = _convert2TargetMatrix4x4.m30; _convert2TargetMatrix3x3._m21 = _convert2TargetMatrix4x4.m31; _convert2TargetMatrix3x3._m22 = _convert2TargetMatrix4x4.m23; //Debug.Log("_convert2TargetMatrix4x4 : \n " + _convert2TargetMatrix4x4.ToString() + "\n" + "_convert2TargetMatrix3x3 : \n " + _convert2TargetMatrix3x3.ToString()); } } //처리된 TRS _updatedWorldPos_NoRequest.x = _matrix_TFResult_World._pos.x; _updatedWorldPos_NoRequest.y = _matrix_TFResult_World._pos.y; _updatedWorldAngle_NoRequest = _matrix_TFResult_World._angleDeg; _updatedWorldScale_NoRequest.x = _matrix_TFResult_World._scale.x; _updatedWorldScale_NoRequest.y = _matrix_TFResult_World._scale.y; _updatedWorldPos = _updatedWorldPos_NoRequest; _updatedWorldAngle = _updatedWorldAngle_NoRequest; _updatedWorldScale = _updatedWorldScale_NoRequest; //스크립트로 외부에서 제어한 경우 if (_isExternalUpdate_Position) { _updatedWorldPos.x = (_exUpdate_Pos.x * _externalUpdateWeight) + (_updatedWorldPos.x * (1.0f - _externalUpdateWeight)); _updatedWorldPos.y = (_exUpdate_Pos.y * _externalUpdateWeight) + (_updatedWorldPos.y * (1.0f - _externalUpdateWeight)); } if (_isExternalUpdate_Rotation) { _updatedWorldAngle = (_exUpdate_Angle * _externalUpdateWeight) + (_updatedWorldAngle * (1.0f - _externalUpdateWeight)); } if (_isExternalUpdate_Scaling) { _updatedWorldScale.x = (_exUpdate_Scale.x * _externalUpdateWeight) + (_updatedWorldScale.x * (1.0f - _externalUpdateWeight)); _updatedWorldScale.y = (_exUpdate_Scale.y * _externalUpdateWeight) + (_updatedWorldScale.y * (1.0f - _externalUpdateWeight)); } if (_isExternalUpdate_Position || _isExternalUpdate_Rotation || _isExternalUpdate_Scaling) { //WorldMatrix를 갱신해주자 _matrix_TFResult_World.SetTRS(_updatedWorldPos.x, _updatedWorldPos.y, _updatedWorldAngle, _updatedWorldScale.x, _updatedWorldScale.y); _isExternalUpdate_Position = false; _isExternalUpdate_Rotation = false; _isExternalUpdate_Scaling = false; } //추가 : 소켓도 만들어준다. //Vert World를 아직 계산하지 않았지만 Socket 처리에는 문제가 없다. if (_socketTransform != null) { _socketTransform.localPosition = new Vector3(_matrix_TFResult_World._pos.x, _matrix_TFResult_World._pos.y, 0); _socketTransform.localRotation = Quaternion.Euler(0.0f, 0.0f, _matrix_TFResult_World._angleDeg); _socketTransform.localScale = new Vector3(_matrix_TFResult_World._scale.x, _matrix_TFResult_World._scale.y, 1.0f); } //#if UNITY_EDITOR // Profiler.EndSample(); //#endif //[MeshUpdate]는 Post Update로 전달 //3. 자식 호출 //자식 객체도 업데이트를 한다. if (_childTransforms != null) { for (int i = 0; i < _childTransforms.Length; i++) { _childTransforms[i].UpdateCalculate_Pre(); } } }