public void Bake_VertexRigs(apOptTransform rootTransform, apOptTransform targetTransform, apOptMesh targetMesh, List <apModifiedVertexRig> modVertRigs) { //_targetType = apModifiedMesh.TARGET_TYPE.VertexWithMeshTransform; _rootTransform = rootTransform; _targetTransform = targetTransform; _targetMesh = targetMesh; if (_targetMesh == null) { Debug.LogError("Vert Rig인데 Target Mesh가 Null"); Debug.LogError("Target Transform [" + _targetTransform.transform.name + "]"); } _nVertRigs = modVertRigs.Count; _vertRigs = new apOptModifiedVertexRig[_nVertRigs]; for (int i = 0; i < _nVertRigs; i++) { apOptModifiedVertexRig optModVertRig = new apOptModifiedVertexRig(); apModifiedVertexRig srcModVertRig = modVertRigs[i]; optModVertRig.Bake(srcModVertRig, _targetMesh, _portrait); _vertRigs[i] = optModVertRig; } _meshColor = Color.gray; _isVisible = true; }
public override bool Save(object target, string strParam) { base.Save(target, strParam); if (!(target is apModifiedVertexRig)) { return(false); } apModifiedVertexRig vertRig = target as apModifiedVertexRig; if (vertRig == null) { return(false); } _weightPairs.Clear(); for (int i = 0; i < vertRig._weightPairs.Count; i++) { apModifiedVertexRig.WeightPair srcWP = vertRig._weightPairs[i]; _weightPairs.Add(new WeightPair(srcWP._bone, srcWP._meshGroup, srcWP._weight)); } return(true); }
public void AddNearVertRig(apModifiedVertexRig vertRig, bool isOnlyForCheck) { _nearVertRigs_OnlyForCheck.Add(vertRig); if (!isOnlyForCheck) { _nearVertRigs.Add(vertRig); } }
//-------------------------------------------------------------------- // 3. Vertex Rigging //-------------------------------------------------------------------- public void Copy_VertRig(apModifiedVertexRig modVertRig, string snapShotName) { _clipboard_VertRig = new apSnapShotStackUnit(snapShotName); bool result = _clipboard_VertRig.SetSnapShot_VertRig(modVertRig, "Clipboard"); if (!result) { _clipboard_VertRig = null; //<<저장 불가능하다. } }
// Bake //---------------------------------------------------------------- public bool Bake(apModifiedVertexRig srcModVert) { //변경 : 8.2 유효한 Weight Pair만 전달하자 List <apModifiedVertexRig.WeightPair> validSrcWeightPairs = new List <apModifiedVertexRig.WeightPair>(); for (int i = 0; i < srcModVert._weightPairs.Count; i++) { apModifiedVertexRig.WeightPair srcWeightPair = srcModVert._weightPairs[i]; if (srcWeightPair == null) { continue; } if (srcWeightPair._weight <= 0.00001f) { continue; ; } validSrcWeightPairs.Add(srcWeightPair); } _weightPairs = new WeightPair[validSrcWeightPairs.Count]; for (int i = 0; i < validSrcWeightPairs.Count; i++) { apModifiedVertexRig.WeightPair srcWeightPair = validSrcWeightPairs[i]; WeightPair optWeightPair = new WeightPair(); optWeightPair.Bake(srcWeightPair); _weightPairs[i] = optWeightPair; } //Normalize를 하자 float totalWeight = 0.0f; for (int i = 0; i < _weightPairs.Length; i++) { totalWeight += _weightPairs[i]._weight; } //Noamlize는 1 이상일 때에만 //if (totalWeight > 0.0f) if (totalWeight > 1.0f) { for (int i = 0; i < _weightPairs.Length; i++) { _weightPairs[i]._weight /= totalWeight; } } return(true); }
// Init - Bake //-------------------------------------------- public void Bake(List <apModifiedVertexRig> modVertRigs) { _nVertRigs = modVertRigs.Count; _vertRigs = new VertexRig[_nVertRigs]; for (int i = 0; i < _nVertRigs; i++) { apModifiedVertexRig srcModVertRig = modVertRigs[i]; VertexRig vertRig = new VertexRig(); vertRig.Bake(srcModVertRig); _vertRigs[i] = vertRig; } }
public override bool Load(object targetObj) { apModifiedVertexRig vertRig = targetObj as apModifiedVertexRig; if (vertRig == null) { return(false); } //일단 값을 모두 초기화한다. for (int i = 0; i < vertRig._weightPairs.Count; i++) { vertRig._weightPairs[i]._weight = 0.0f; } //저장된 값을 넣어준다. for (int iSrc = 0; iSrc < _weightPairs.Count; iSrc++) { WeightPair src = _weightPairs[iSrc]; if (src._bone == null || src._meshGroup == null) { continue; } apModifiedVertexRig.WeightPair dstWeightPair = vertRig._weightPairs.Find(delegate(apModifiedVertexRig.WeightPair a) { return(a._bone == src._bone); }); if (dstWeightPair == null) { apModifiedVertexRig.WeightPair newWP = new apModifiedVertexRig.WeightPair(src._bone); newWP._weight = src._weight; vertRig._weightPairs.Add(newWP); } else { dstWeightPair._weight = src._weight; } } vertRig.CalculateTotalWeight(); return(true); }
//ModVertRig > WeightPairData public void SetModVertRig(apModifiedVertexRig modVertRig) { //위치 저장 (Modifier 적용 없이) _posWorld = modVertRig._renderVertex._pos_World_NoMod; //WeightPair 리스트를 저장한다. if (_weightPairs == null) { _weightPairs = new List <WeightPairData>(); } _weightPairs.Clear(); if (modVertRig._weightPairs.Count == 0) { return; } float totalWeight = 0.0f; for (int iSrc = 0; iSrc < modVertRig._weightPairs.Count; iSrc++) { apModifiedVertexRig.WeightPair srcWeightPair = modVertRig._weightPairs[iSrc]; if (srcWeightPair._bone == null) { continue; } totalWeight += srcWeightPair._weight; _weightPairs.Add(new WeightPairData(srcWeightPair._bone, srcWeightPair._weight)); } if (_weightPairs.Count > 0 && totalWeight > 0.0f) { //Normalize를 하자 for (int i = 0; i < _weightPairs.Count; i++) { _weightPairs[i]._weight /= totalWeight; } } //Debug.Log("Pos-Copy : " + _posWorld + " / Pairs : " + _weightPairs.Count); }
public bool IsPastable(apModifiedVertexRig vertRig) { if (vertRig == null) { return(false); } if (_clipboard_VertRig == null) { return(false); } //만약, 복사-붙여넣기 불가능한 객체이면 생략한다. bool isKeySync = _clipboard_VertRig.IsKeySyncable(vertRig); if (!isKeySync) { return(false); } return(true); }
public bool Bake(apModifiedVertexRig srcModVert, apOptMesh mesh, apPortrait portrait) { _vertexUniqueID = srcModVert._vertexUniqueID; _vertIndex = srcModVert._vertIndex; _mesh = mesh; _weightPairs = new OptWeightPair[srcModVert._weightPairs.Count]; for (int i = 0; i < srcModVert._weightPairs.Count; i++) { apModifiedVertexRig.WeightPair srcWeightPair = srcModVert._weightPairs[i]; OptWeightPair optWeightPair = new OptWeightPair(srcWeightPair); optWeightPair.Link(portrait); _weightPairs[i] = optWeightPair; } return(true); }
//저장된 값을 대상 ModVertRig에 복사한다. public void PasteToModVertRig(apMeshGroup keyMeshGroup, apModifiedVertexRig targetModVertRig) { if (targetModVertRig == null) { return; } targetModVertRig._weightPairs.Clear(); for (int iSrcPair = 0; iSrcPair < _weightPairs.Count; iSrcPair++) { WeightPairData srcPair = _weightPairs[iSrcPair]; apModifiedVertexRig.WeightPair dstPair = new apModifiedVertexRig.WeightPair(srcPair._bone); dstPair._meshGroup = keyMeshGroup; dstPair._meshGroupID = keyMeshGroup._uniqueID; dstPair._weight = srcPair._weight; targetModVertRig._weightPairs.Add(dstPair); } }
public bool Paste_VertRig(apModifiedVertexRig targetModVertRig) { if (targetModVertRig == null) { return(false); } if (_clipboard_VertRig == null) { return(false); } //만약, 복사-붙여넣기 불가능한 객체이면 생략한다. bool isKeySync = _clipboard_VertRig.IsKeySyncable(targetModVertRig); if (!isKeySync) { return(false); } return(_clipboard_VertRig.Load(targetModVertRig)); }
//VertRig가 등록된 상태에서 Size 계산하기 public void CalculateSize() { float maxDist = 0.0f; apModifiedVertexRig curVertRig = null; float dst = 0.0f; for (int iVert = 0; iVert < _nearVertRigs_OnlyForCheck.Count; iVert++) { curVertRig = _nearVertRigs_OnlyForCheck[iVert]; dst = GetDistance(curVertRig._renderVertex._pos_World_NoMod); if (dst > maxDist) { maxDist = dst; } } if (maxDist <= 0.0f) { maxDist = 0.01f; } //"가장 먼 거리의 버텍스"가 Envelope의 크기 _size = maxDist; //if (!_isHelper) //{ // if(_size > _length) // { // _size = _length; // } //} //Debug.LogError("Bone Envelope Info : " + _bone._name); //Debug.Log("Positon : " + _posStart + ", " + _posEnd); //Debug.Log("Length : " + _length); //Debug.Log("Size : " + _size); }
public bool Bake(apModifiedVertexRig srcModVert, apOptMesh mesh, apPortrait portrait) { _vertexUniqueID = srcModVert._vertexUniqueID; _vertIndex = srcModVert._vertIndex; _mesh = mesh; //변경 : 8.2 유효한 Weight Pair만 전달하자 List <apModifiedVertexRig.WeightPair> validSrcWeightPairs = new List <apModifiedVertexRig.WeightPair>(); for (int i = 0; i < srcModVert._weightPairs.Count; i++) { apModifiedVertexRig.WeightPair srcWeightPair = srcModVert._weightPairs[i]; if (srcWeightPair == null) { continue; } if (srcWeightPair._weight <= 0.00001f) { continue;; } validSrcWeightPairs.Add(srcWeightPair); } _weightPairs = new OptWeightPair[validSrcWeightPairs.Count]; //변경 : 8.2 유효한 Vertex가 없어도 일단 Bake는 되어야 한다. //if(srcModVert._weightPairs.Count == 0) //{ // //Rig가 안된 Vertex가 있다. // Debug.LogError("AnyPortrait : There is a vertex with no rigging data. The Rigging Modifier is not applied to this mesh [" + mesh.name + "]. Check the Rigging value."); // return false; //} //for (int i = 0; i < srcModVert._weightPairs.Count; i++) for (int i = 0; i < validSrcWeightPairs.Count; i++) { //apModifiedVertexRig.WeightPair srcWeightPair = srcModVert._weightPairs[i]; apModifiedVertexRig.WeightPair srcWeightPair = validSrcWeightPairs[i]; //추가 : 유효한 Weight만 추가 > 이 코드가 버그를 발생시킨다. //if(srcWeightPair._weight <= 0.00001f) //{ // continue; //} OptWeightPair optWeightPair = new OptWeightPair(srcWeightPair); optWeightPair.Link(portrait); _weightPairs[i] = optWeightPair; } //변경 : 8.2 0개라도 Bake를 하는 것으로 변경 //if(_weightPairs.Length == 0) //{ // //처리된 Pair가 없으면 false // Debug.LogError("AnyPortrait : There is a vertex with no valid rigging data. The Rigging Modifier is not applied to this mesh [" + mesh.name + "]. Check the Rigging value."); // return false; //} //추가 : Normalize를 하자 float totalWeight = 0.0f; for (int i = 0; i < _weightPairs.Length; i++) { totalWeight += _weightPairs[i]._weight; } //Noamlize는 1 이상일 때에만 //if (totalWeight > 0.0f) if (totalWeight > 1.0f) { //if(totalWeight > 1.0f) //{ // Debug.LogError("OPT Rigging Weight Normalize [" + totalWeight + "]"); //} for (int i = 0; i < _weightPairs.Length; i++) { //Debug.LogError("[" + i + "] : " + _weightPairs[i]._weight + " >> " + (_weightPairs[i]._weight / totalWeight)); _weightPairs[i]._weight /= totalWeight; } } //변경 8.2 : Weight 에러는 없다. //else //{ // //전체 Weight가 0이다? // Debug.LogError("AnyPortrait : There is a vertex with a sum of Rigging values of zero. The Rigging Modifier is not applied to this mesh [" + mesh.name + "]. Check the Rigging value."); // return false; //} return(true); }
public bool SetSnapShot_VertRig(apModifiedVertexRig vertRig, string strParam) { _snapShot = new apSnapShot_VertRig(); return(_snapShot.Save(vertRig, strParam)); }
public static float GetVertRigWeight(apModifiedVertexRig targetVertRig, EnvelopeInfo envInfo, EnvelopeInfo nearestEnvInfo) { Vector2 pos = targetVertRig._renderVertex._pos_World_NoMod; bool isExtendedArea = envInfo._nearVertRigs.Contains(targetVertRig) || IsIn2LevelLinkedBone(envInfo._bone, nearestEnvInfo._bone); //연결된 본이면 확장 영역으로 체크해야한다. //isExtendedArea = true; //Debug.LogError("Vert Rig : " + pos + " -->> EnvInfo : " + envInfo._bone._name); //Debug.LogWarning("[Env Info] Pos Start : " + envInfo._posStart + " / End " + envInfo._posEnd + " ( Center : " + envInfo._posCenter + ")"); //Debug.LogWarning("[Env Info] Size : " + envInfo._size); //4가지 Weight가 있다. //1) Distance 배수 : 거리에 따른 배수. 최대 영역 밖으로 나가면 실패값 리턴 //2) Center 배수 : Center를 기점으로 Box인 경우, 직교하는 위치에서의 거리, Circle인 경우 전체 거리를 기준으로 배수를 정한다. (Helper인 경우 1) //3) Angle 배수 : Circle에 위치한 경우, 각도가 90도에서 0도로 갈수록 감소. (Box에 위치한 경우 1) //4) Linked 배수 : 연결된 본이 있는 경우, 해당 각도로의 리깅을 제한한다. //Distance 배수 //- 확장) 기존 영역까지 1 > 0.7 / 확장 영역까지 0.7 > 0 (Pow2) //- 기본) 기존 영역까지 1 > 0 //Center 배수 //- Helper인 경우 1 //- 거리값은 "직교위치"(CosA) //- 확장) 최대 거리 Center ~ [Length/2 + Size*2] / [Length/2 + Size]까지 1 > 0.7 / [추가 Size]까지 0.7 > 0.4 //- 기본) 최대 거리 Center ~ [Length/2 + Size] / [Length/2 + Size]까지 1 > 0.7 //Angle 배수 //- Box나 Helper인 경우 1 //- [Start->End] 벡터와 [End 또는 Start -> Pos]벡터의 각도 / 각도가 90 > 0으로 1 > 0.8 //Linked 배수 //- Helper인 경우 1 //- 현재 위치가 Start 또는 End 방향일 때, 해당 방향의 "연결된 EnvelopeInfo"가 있는 경우 //- 연결된 EnvInfo의 중심점 까지의 Cos 거리를 계산하여 [Length/2]까진 1, [Linked Center]까지 0으로 값이 감소한다. //- 연결된 본이 2개 이상이라면, 각각의 본에 대해 계산한 후, 그 값을 모두 곱한다. float Multiplier_Dst = 1.0f; //Distance 배수 float Multiplier_Center = 1.0f; //Center 배수 float Multiplier_Angle = 1.0f; //Angle 배수 float Multiplier_Linked = 1.0f; //Linked 배수 //계산을 위한 속성들 float dst = 0.0f; //Capsule 방식의 거리 bool isBox = false; //위치한 곳이 Box인지 Circle인지 float dstFromCenter = 0.0f; //선분에 직교한 위치와 Center로부터의 거리 float angle = 0.0f; //Circle에 위치한 경우 Vector2 centerPos = (envInfo._posStart * 0.5f) + (envInfo._posEnd * 0.5f); //미리 필요한 속성들을 계산하자. if (envInfo._isHelper) { dst = Vector2.Distance(pos, envInfo._posStart); isBox = false; dstFromCenter = 0.0f; angle = 0.0f; } else { float dotA = Vector2.Dot(pos - envInfo._posStart, (envInfo._posEnd - envInfo._posStart).normalized); float dotB = Vector2.Dot(pos - envInfo._posEnd, (envInfo._posStart - envInfo._posEnd).normalized); if (dotA < 0.0f) { //Start쪽 반원에 있다. dst = Vector2.Distance(envInfo._posStart, pos); isBox = false; if (dst < 0.0001f) { //너무 짧다면 Angle은 90으로 강제 angle = 90.0f; } else { angle = Mathf.Abs(Vector2.Angle(envInfo._posEnd - envInfo._posStart, pos - envInfo._posStart)); if (angle > 90.0f) { angle = 180.0f - angle; } } } else if (dotB < 0.0f) { //End쪽 반원에 있다. dst = Vector2.Distance(envInfo._posEnd, pos); isBox = false; angle = Vector2.Angle(envInfo._posEnd - envInfo._posStart, pos - envInfo._posEnd); if (dst < 0.0001f) { //너무 짧다면 Angle은 90으로 강제 angle = 90.0f; } else { angle = Mathf.Abs(Vector2.Angle(envInfo._posEnd - envInfo._posStart, pos - envInfo._posEnd)); if (angle > 90.0f) { angle = 180.0f - angle; } } } else { //Box에 위치한다. dst = Vector2.Distance((envInfo._posStart + (envInfo._posEnd - envInfo._posStart).normalized * dotA), pos); isBox = true; angle = 0.0f; } Vector2 center2PosVec = pos - centerPos; float angleFromCenter = Mathf.Abs(Vector2.Angle(center2PosVec, envInfo._posEnd - envInfo._posStart)); if (angleFromCenter > 90.0f) { angleFromCenter = 180.0f - angleFromCenter; } dstFromCenter = Mathf.Abs(Mathf.Cos(angleFromCenter * Mathf.Deg2Rad) * center2PosVec.magnitude); } //Debug.Log("> Distance : " + dst); //Debug.Log("> Distance From Center : " + dstFromCenter); //Debug.Log("> Is Box : " + isBox); float lerp = 0.0f; //1. Distance 배수 //- 확장) 기존 영역까지 1 > 0.7 / 확장 영역까지 0.7 > 0 (Pow2) //- 기본) 기존 영역까지 1 > 0 float normalArea = Mathf.Max(envInfo._size, 0.001f); if (isExtendedArea) { float extendedArea = normalArea * 2; if (dst < normalArea) { lerp = dst / normalArea; Multiplier_Dst = (1.0f * (1.0f - lerp)) + (0.7f * lerp); //1 ~ 0.7 } else if (dst < extendedArea) { lerp = Mathf.Pow((dst - normalArea) / (extendedArea - normalArea), 2); //Pow2 타입의 보간 Multiplier_Dst = (0.7f * (1.0f - lerp)) + (0.0f * lerp); //0.7 ~ 0 } else { //영역 밖 return(-1.0f); } } else { if (dst < normalArea) { lerp = dst / normalArea; Multiplier_Dst = (1.0f * (1.0f - lerp)) + (0.0f * lerp); //1 ~ 0 } else { //영역 밖 return(-1.0f); } } //Center 배수 //- Helper인 경우 1 //- 거리값은 "직교위치"(CosA) //- 확장) 최대 거리 Center ~ [Length/2 + Size*2] / [Length/2 + Size]까지 1 > 0.7 / [추가 Size]까지 0.7 > 0.4 //- 기본) 최대 거리 Center ~ [Length/2 + Size] / [Length/2 + Size]까지 1 > 0.7 if (envInfo._isHelper) { Multiplier_Center = 1.0f; } else { float boneLength = Vector2.Distance(envInfo._posEnd, envInfo._posStart); float normalLength = (boneLength * 0.5f) + envInfo._size; if (isExtendedArea) { float extendedLength = normalLength + envInfo._size; if (dstFromCenter < normalLength) { lerp = dstFromCenter / normalLength; Multiplier_Center = (1.0f * (1.0f - lerp)) + (0.7f * lerp); //1 > 0.7f } else if (dstFromCenter < extendedLength) { lerp = (dstFromCenter - normalLength) / (extendedLength - normalLength); Multiplier_Center = (0.7f * (1.0f - lerp)) + (0.4f * lerp); //0.7 > 0.4f } else { Multiplier_Center = 0.4f; } } else { if (dstFromCenter < normalLength) { lerp = dstFromCenter / normalLength; Multiplier_Center = (1.0f * (1.0f - lerp)) + (0.7f * lerp); //1 > 0.7f } else { Multiplier_Center = 0.7f; } } } //Angle 배수 //- Box나 Helper인 경우 1 //- [Start->End] 벡터와 [End 또는 Start -> Pos]벡터의 각도 / 각도가 90 > 0으로 1 > 0.8 //- 거리에 따라서 한번 더 계산한다. (거리가 0이면 배수는 1이 되고, 거리가 normalLength 이상일 때 Angle 배수 이용) if (isBox || envInfo._isHelper) { Multiplier_Angle = 1.0f; } else { float dstMul = 0.0f; if (dst < envInfo._size) { dstMul = dst / envInfo._size; } else { dstMul = 1.0f; } if (angle > 90.0f) { Multiplier_Angle = 1.0f; } else { lerp = angle / 90.0f; Multiplier_Angle = (0.8f * (1.0f - lerp)) + (1.0f * lerp); //0도일때 0.8로 더 작다. } Multiplier_Angle = (1.0f * (1.0f - dstMul)) + (Multiplier_Angle * dstMul); } //Linked 배수 //- Helper인 경우 1 //- 현재 위치가 Start 또는 End 방향일 때, 해당 방향의 "연결된 EnvelopeInfo"가 있는 경우 //- 연결된 EnvInfo의 중심점 까지의 Cos 거리를 계산하여 [Length/2]까진 1, [Linked Center]까지 0으로 값이 감소한다. //- 연결된 본이 2개 이상이라면, 각각의 본에 대해 계산한 후, 그 값을 모두 곱한다. if (envInfo._isHelper) { Multiplier_Linked = 1.0f; } else { //일단 현재 좌표가 Start 방향인지, End 방향인지 확인하자. Vector2 vecCenter2Pos = pos - centerPos; float angleToStart = Vector2.Angle(vecCenter2Pos, envInfo._posStart - envInfo._posEnd); float angleToEnd = Vector2.Angle(vecCenter2Pos, envInfo._posEnd - envInfo._posStart); //Debug.Log("Angle : Center->Pos / Start : " + angleToStart); //Debug.Log("Angle : Center->Pos / End : " + angleToEnd); List <EnvelopeInfo> linkedEnvInfoList = null; if (angleToStart < angleToEnd) { //Start 방향에 있다. //Debug.Log("Vert가 Start 방향에 있다. [" + envInfo._linkedEnvInfo_ToStart.Count + "]"); if (envInfo._linkedEnvInfo_ToStart.Count > 0) { linkedEnvInfoList = envInfo._linkedEnvInfo_ToStart; } } else if (angleToEnd < angleToStart) { //End 방향에 있다. //Debug.Log("Vert가 End 방향에 있다. [" + envInfo._linkedEnvInfo_ToEnd.Count + "]"); if (envInfo._linkedEnvInfo_ToEnd.Count > 0) { linkedEnvInfoList = envInfo._linkedEnvInfo_ToEnd; } } if (linkedEnvInfoList == null) { //Linked 계산이 힘들다. Multiplier_Linked = 1.0f; } else { Multiplier_Linked = 1.0f; EnvelopeInfo linkedEnvInfo = null; Vector2 linkedPosCenter = Vector2.zero; float length2LinkedCenter = 0.0f; Vector2 vecCenter2LinkedCenter = Vector2.zero; float angleFromLinkedVector = 0.0f; float distCosLinked = 0.0f; for (int iLinked = 0; iLinked < linkedEnvInfoList.Count; iLinked++) { linkedEnvInfo = linkedEnvInfoList[iLinked]; //Debug.Log("[" + iLinked + "] : " + linkedEnvInfo._bone._name); linkedPosCenter = linkedEnvInfo._posCenter; //Center 2 Center를 구한다. length2LinkedCenter = Vector2.Distance(centerPos, linkedPosCenter); //Debug.Log("Center > Linked Center 거리 : " + length2LinkedCenter); //만약 거리가 너무 짧다면 무시 if (length2LinkedCenter < 0.0001f) { //Debug.LogError("너무 짧은 거리"); continue; } vecCenter2LinkedCenter = linkedPosCenter - centerPos; angleFromLinkedVector = Vector2.Angle(vecCenter2Pos, vecCenter2LinkedCenter); //Debug.Log("[Center > Pos]와 [Center > Linked Center]의 각도 : " + angleFromLinkedVector); //연결된 Center까지 벡터 상에서의 거리 distCosLinked = vecCenter2Pos.magnitude * Mathf.Cos(angleFromLinkedVector * Mathf.Deg2Rad); float boneLength = Vector2.Distance(envInfo._posEnd, envInfo._posStart); float normalLength = (boneLength * 0.5f); float limitLength = length2LinkedCenter; if (limitLength < normalLength) { //Debug.LogError("Center 2 Center가 너무 짧음 : " + limitLength + " >> " + normalLength * 1.5f); limitLength = normalLength * 1.5f; } //Debug.Log("Cos 거리 : " + distCosLinked); //Debug.Log("기본 거리 제한 (Bone Length / 2) : " + normalLength); //Debug.Log("전체 거리 제한 : " + length2LinkedCenter); if (distCosLinked < normalLength) { Multiplier_Linked *= 1.0f; //배수는 1 //Debug.Log("- 기본 범위 안에 들어감 : x1"); } else if (distCosLinked < limitLength) { lerp = (distCosLinked - normalLength) / (limitLength - normalLength); //1에서 0으로 감소 float ratio = 1.0f * (1.0f - lerp) + 0.0f * lerp; Multiplier_Linked *= ratio; //Debug.LogWarning("- 제한 범위 안에 들어감 : x" + ratio); } else { Multiplier_Linked *= 0.0f; //Debug.LogError("- 범위 밖"); } //Debug.Log(">>> 현재 Linked 값 : " + Multiplier_Linked); } } } //Debug.LogWarning("[Multiplier Dst] : " + Multiplier_Dst); //Debug.LogWarning("[Multiplier Center] : " + Multiplier_Center); //Debug.LogWarning("[Multiplier Angle] : " + Multiplier_Angle); //Debug.LogWarning("[Multiplier Linked] : " + Multiplier_Linked); float resultWeight = Multiplier_Dst * Multiplier_Center * Multiplier_Angle * Multiplier_Linked; if (resultWeight < 0.0001f) { return(-1.0f); } //Debug.LogWarning(">> Result : " + resultWeight); return(resultWeight); }
public void RefreshVertexRigs(apPortrait portrait) { if (_transform_Mesh._mesh != null) { bool isSameVerts = true; if (_vertRigs.Count == 0 || _vertRigs.Count != _transform_Mesh._mesh._vertexData.Count) { isSameVerts = false; } else { //전부 비교해볼까나.. //빠르게 단순 링크를 시도해보고, 한번이라도 실패하면 다시 리스트를 만들어야한다. List <apVertex> meshVertList = _transform_Mesh._mesh._vertexData; apVertex meshVert = null; apModifiedVertexRig modVertRig = null; for (int i = 0; i < meshVertList.Count; i++) { meshVert = meshVertList[i]; modVertRig = _vertRigs[i]; if (modVertRig._vertexUniqueID != meshVert._uniqueID) { //버텍스 리스트 갱신이 필요하다 isSameVerts = false; break; } modVertRig.Link(this, _transform_Mesh._mesh, meshVert); modVertRig.LinkWeightPair(portrait); } } if (!isSameVerts) { //유효한 Vertex만 찾아서 넣어준다. //유효하면 - Link //유효하지 않다면 - Pass (Link 안된거 삭제) //없는건 - Add //순서는.. Index를 넣어서 //1. 일단 기존 데이터 복사 - 없어진 Vertex를 빼자 if (_vertRigs.Count != 0) { apModifiedVertexRig modVertRig = null; for (int i = 0; i < _vertRigs.Count; i++) { modVertRig = _vertRigs[i]; apVertex existVert = _transform_Mesh._mesh._vertexData.Find(delegate(apVertex a) { return(a._uniqueID == modVertRig._vertexUniqueID); }); if (existVert != null) { //유효하다면 Link modVertRig.Link(this, _transform_Mesh._mesh, existVert); modVertRig.LinkWeightPair(portrait); } else { //유효하지 않다면.. Unlink -> 나중에 삭제됨 modVertRig._vertex = null; } } //이제 존재하지 않는 Vertex에 대해서는 삭제 _vertRigs.RemoveAll(delegate(apModifiedVertexRig a) { return(a._vertex == null); }); List <apVertex> meshVertList = _transform_Mesh._mesh._vertexData; apVertex meshVert = null; for (int i = 0; i < meshVertList.Count; i++) { meshVert = meshVertList[i]; //해당 Vertex가 있었는가 bool isLinked = _vertRigs.Exists(delegate(apModifiedVertexRig a) { return(a._vertex == meshVert); }); //없으면 추가 if (!isLinked) { apModifiedVertexRig newVertRig = new apModifiedVertexRig(); newVertRig.Init(meshVert._uniqueID, meshVert); newVertRig.Link(this, _transform_Mesh._mesh, meshVert); newVertRig.LinkWeightPair(portrait); _vertRigs.Add(newVertRig); //<<새로 추가할 리스트에 넣어준다. } } //Vertex Index에 맞게 정렬 _vertRigs.Sort(delegate(apModifiedVertexRig a, apModifiedVertexRig b) { return(a._vertIndex - b._vertIndex); }); } else { //2. 아예 리스트가 없을 때 _vertRigs.Clear(); List <apVertex> meshVertList = _transform_Mesh._mesh._vertexData; apVertex meshVert = null; for (int i = 0; i < meshVertList.Count; i++) { meshVert = meshVertList[i]; apModifiedVertexRig newVertRig = new apModifiedVertexRig(); newVertRig.Init(meshVert._uniqueID, meshVert); newVertRig.Link(this, _transform_Mesh._mesh, meshVert); newVertRig.LinkWeightPair(portrait); _vertRigs.Add(newVertRig); //<<새로 추가할 리스트에 넣어준다. } } } for (int i = 0; i < _vertRigs.Count; i++) { _vertRigs[i].RefreshModMeshAndRenderVertex(this); } } }
/// <summary> /// Rigging Modifier 내에서의 Gizmo 이벤트 : Vertex 선택 또는 Bone 선택 [단일 선택] /// </summary> /// <param name="mousePosGL"></param> /// <param name="mousePosW"></param> /// <param name="btnIndex"></param> /// <param name="selectType"></param> /// <returns></returns> public apGizmos.SelectResult Select__Modifier_Rigging(Vector2 mousePosGL, Vector2 mousePosW, int btnIndex, apGizmos.SELECT_TYPE selectType) { if (Editor.Select.MeshGroup == null || Editor.Select.Modifier == null) { return(null); } // 선택은 Test Posing 상관없이 수행한다. // - Vertex > (선택 못했어도 일단 이전에 선택한 Vertex를 해제하지 않는다.) // - Bone > (선택 못했으면 이전에 선택한 Bone 해제) // Vertex나 Bone 선택이 되지 않았다면, 이전에 선택했던 Vertex, Bone을 모두 해제한다. // - Mesh Transform 선택 (Lock이 안걸린 경우. 이건 리턴하지 않는다) // (아무것도 선택하지 않은 경우) -> Vertex, Bone, Mesh Transform 해제 bool isAnySelected = false; if (Editor.Select.ModRenderVertListOfMod == null) { return(null); } if (!Editor.Controller.IsMouseInGUI(mousePosGL)) { if (Editor.Select.ModRenderVertListOfMod.Count > 0) { return(apGizmos.SelectResult.Main.SetMultiple <apSelection.ModRenderVert>(Editor.Select.ModRenderVertListOfMod)); } if (Editor.Select.Bone != null) { return(apGizmos.SelectResult.Main.SetSingle(Editor.Select.Bone)); } return(null); } int prevSelectedVertex = Editor.Select.ModRenderVertListOfMod.Count; bool isAnyVertexSelected = false; bool isAnyBoneSelected = false; List <apSelection.ModRenderVert> prevSelectedVertices = new List <apSelection.ModRenderVert>(); for (int i = 0; i < Editor.Select.ModRenderVertListOfMod.Count; i++) { prevSelectedVertices.Add(Editor.Select.ModRenderVertListOfMod[i]); } //1. 버텍스 선택을 먼저 bool isChildMeshTransformSelectable = Editor.Select.Modifier.IsTarget_ChildMeshTransform; if (Editor.Select.ExKey_ModMesh != null && Editor.Select.MeshGroup != null) { //bool selectVertex = false; //일단 선택한 Vertex가 클릭 가능한지 체크 if (Editor.Select.ModRenderVertOfMod != null) { if (Editor.Select.ModRenderVertListOfMod.Count == 1) { if (Editor.Controller.IsVertexClickable(apGL.World2GL(Editor.Select.ModRenderVertOfMod._renderVert._pos_World), mousePosGL)) { if (selectType == apGizmos.SELECT_TYPE.Subtract) { //삭제인 경우 //ModVert가 아니라 ModVertRig인 점 주의 Editor.Select.RemoveModVertexOfModifier(null, Editor.Select.ModRenderVertOfMod._modVertRig, null, Editor.Select.ModRenderVertOfMod._renderVert); //return apGizmos.SELECT_RESULT.None; } else { //그 외에는 => 그대로 갑시다. isAnySelected = true; //return apGizmos.SELECT_RESULT.SameSelected; } //return Editor.Select.ModRenderVertListOfMod.Count; return(apGizmos.SelectResult.Main.SetMultiple <apSelection.ModRenderVert>(Editor.Select.ModRenderVertListOfMod)); } } else { //여러개라고 하네요. List <apSelection.ModRenderVert> modRenderVerts = Editor.Select.ModRenderVertListOfMod; for (int iModRenderVert = 0; iModRenderVert < modRenderVerts.Count; iModRenderVert++) { apSelection.ModRenderVert modRenderVert = modRenderVerts[iModRenderVert]; if (Editor.Controller.IsVertexClickable(apGL.World2GL(modRenderVert._renderVert._pos_World), mousePosGL)) { if (selectType == apGizmos.SELECT_TYPE.Subtract) { //삭제인 경우 //하나 지우고 끝 //결과는 List의 개수 Editor.Select.RemoveModVertexOfModifier(null, modRenderVert._modVertRig, null, modRenderVert._renderVert); } else if (selectType == apGizmos.SELECT_TYPE.Add) { //Add 상태에서 원래 선택된걸 누른다면 //추가인 경우 => 그대로 isAnySelected = true; } else { //만약... new 라면? //다른건 초기화하고 //얘만 선택해야함 apRenderVertex selectedRenderVert = modRenderVert._renderVert; apModifiedVertexRig selectedModVertRig = modRenderVert._modVertRig; Editor.Select.SetModVertexOfModifier(null, null, null, null); Editor.Select.SetModVertexOfModifier(null, selectedModVertRig, null, selectedRenderVert); //return apGizmos.SELECT_RESULT.NewSelected; //return Editor.Select.ModRenderVertOfModList.Count; } //return Editor.Select.ModRenderVertListOfMod.Count; return(apGizmos.SelectResult.Main.SetMultiple <apSelection.ModRenderVert>(Editor.Select.ModRenderVertListOfMod)); } } } } //이부분 주의 //일단 날리되, "Bone을 선택했다면 이전에 선택한 vertex를 유지한다"를 지켜야한다. if (selectType == apGizmos.SELECT_TYPE.New) { //Add나 Subtract가 아닐땐, 잘못 클릭하면 선택을 해제하자 (전부) Editor.Select.SetModVertexOfModifier(null, null, null, null); } if (selectType != apGizmos.SELECT_TYPE.Subtract) { if (Editor.Select.ExKey_ModMesh._transform_Mesh != null && Editor.Select.ExKey_ModMesh._vertRigs != null) { //선택된 RenderUnit을 고르자 apRenderUnit targetRenderUnit = Editor.Select.MeshGroup.GetRenderUnit(Editor.Select.ExKey_ModMesh._transform_Mesh); if (targetRenderUnit != null) { for (int iVert = 0; iVert < targetRenderUnit._renderVerts.Count; iVert++) { apRenderVertex renderVert = targetRenderUnit._renderVerts[iVert]; bool isClick = Editor.Controller.IsVertexClickable(apGL.World2GL(renderVert._pos_World), mousePosGL); if (isClick) { apModifiedVertexRig selectedModVertRig = Editor.Select.ExKey_ModMesh._vertRigs.Find(delegate(apModifiedVertexRig a) { return(renderVert._vertex._uniqueID == a._vertexUniqueID); }); if (selectedModVertRig != null) { if (selectType == apGizmos.SELECT_TYPE.New) { Editor.Select.SetModVertexOfModifier(null, selectedModVertRig, null, renderVert); } else if (selectType == apGizmos.SELECT_TYPE.Add) { Editor.Select.AddModVertexOfModifier(null, selectedModVertRig, null, renderVert); } isAnySelected = true; isAnyVertexSelected = true; //result = apGizmos.SELECT_RESULT.NewSelected; break; } } } Editor.RefreshControllerAndHierarchy(); //Editor.Repaint(); Editor.SetRepaint(); } } } if (isAnySelected) { Editor.Select.AutoSelectModMeshOrModBone(); } } if (!Editor.Select.IsLockExEditKey) { if (!isAnySelected) { //2. Bone을 선택하자 //Bone은 Select Mode가 Subtract가 아닌 이상 무조건 작동을 한다. //만약, 잠금 버튼이 눌렸다면 -> Bone 선택하지 않았어도 해제를 하지 않는다. apMeshGroup meshGroup = Editor.Select.MeshGroup; apBone prevBone = Editor.Select.Bone; List <apBone> boneList = meshGroup._boneList_All; apBone bone = null; for (int i = 0; i < boneList.Count; i++) { bone = boneList[i]; if (IsBoneClick(bone, mousePosW, mousePosGL, Editor._boneGUIRenderMode == apEditor.BONE_RENDER_MODE.RenderOutline)) { //Debug.Log("Selected : " + bone._name); if (selectType != apGizmos.SELECT_TYPE.Subtract) { Editor.Select.SetBone(bone); isAnySelected = true; } else { Editor.Select.SetBone(null); } isAnyBoneSelected = true; break; } } if (!isAnySelected) { Editor.Select.SetBone(null); if (Editor.Select.IsLockExEditKey) { Editor.Select.SetBone(prevBone); //복구 } } else { //Bone을 선택했다면 //Vertex를 복구해주자 for (int i = 0; i < prevSelectedVertices.Count; i++) { apSelection.ModRenderVert modRenderVert = prevSelectedVertices[i]; Editor.Select.AddModVertexOfModifier(modRenderVert._modVert, modRenderVert._modVertRig, null, modRenderVert._renderVert); } } if (prevBone != Editor.Select.Bone) { _isBoneSelect_MovePosReset = true; Editor.RefreshControllerAndHierarchy(); } } } if (!Editor.Select.IsLockExEditKey) { if (!isAnySelected && selectType == apGizmos.SELECT_TYPE.New) { //3. Mesh Transform을 선택하자 //이건 선택 영역에 포함되지 않는다. apTransform_Mesh selectedMeshTransform = null; List <apRenderUnit> renderUnits = Editor.Select.MeshGroup._renderUnits_All; //<<정렬된 Render Unit for (int iUnit = 0; iUnit < renderUnits.Count; iUnit++) { apRenderUnit renderUnit = renderUnits[iUnit]; if (renderUnit._meshTransform != null && renderUnit._meshTransform._mesh != null) { if (renderUnit._meshTransform._isVisible_Default && renderUnit._meshColor2X.a > 0.1f) //Alpha 옵션 추가 { //Debug.LogError("TODO : Mouse Picking 바꿀것"); bool isPick = apEditorUtil.IsMouseInRenderUnitMesh( mousePosGL, renderUnit); if (isPick) { selectedMeshTransform = renderUnit._meshTransform; //찾았어도 계속 찾는다. //뒤의 아이템이 "앞쪽"에 있는 것이기 때문 } } } } if (selectedMeshTransform != null) { //만약 ChildMeshGroup에 속한 거라면, //Mesh Group 자체를 선택해야 한다. <- 추가 : Child Mesh Transform이 허용되는 경우 그럴 필요가 없다. apMeshGroup parentMeshGroup = Editor.Select.MeshGroup.FindParentMeshGroupOfMeshTransform(selectedMeshTransform); if (parentMeshGroup == null || parentMeshGroup == Editor.Select.MeshGroup || isChildMeshTransformSelectable) { Editor.Select.SetSubMeshInGroup(selectedMeshTransform); } else { apTransform_MeshGroup childMeshGroupTransform = Editor.Select.MeshGroup.FindChildMeshGroupTransform(parentMeshGroup); if (childMeshGroupTransform != null) { Editor.Select.SetSubMeshGroupInGroup(childMeshGroupTransform); } else { Editor.Select.SetSubMeshInGroup(selectedMeshTransform); } } } else { Editor.Select.SetSubMeshInGroup(null); } Editor.RefreshControllerAndHierarchy(); //Editor.Repaint(); Editor.SetRepaint(); } } if (isAnySelected) { if (Editor.Select.ModRenderVertListOfMod != null && Editor.Select.ModRenderVertListOfMod.Count > 0) { //return Editor.Select.ModRenderVertListOfMod.Count; return(apGizmos.SelectResult.Main.SetMultiple <apSelection.ModRenderVert>(Editor.Select.ModRenderVertListOfMod)); } if (Editor.Select.Bone != null) { return(apGizmos.SelectResult.Main.SetSingle(Editor.Select.Bone)); } } return(null); }
public bool Paste(apMeshGroup meshGroup, List <apModifiedVertexRig> targetModVertRigs) { if (meshGroup == null || targetModVertRigs == null || targetModVertRigs.Count == 0) { return(false); } if (_keyMeshGroup == null || _keyMeshGroup != meshGroup || _posWeightPairs.Count == 0) { return(false); } //Debug.LogError("Paste Start----"); apModifiedVertexRig targetModVertRig = null; Vector2 targetPosW = Vector2.zero; PosWeightPair src = null; Vector2 srcPosW = Vector2.zero; PosWeightPair near_mX = null; PosWeightPair near_pX = null; PosWeightPair near_mY = null; PosWeightPair near_pY = null; float minDst_mX = 0.0f; float minDst_pX = 0.0f; float minDst_mY = 0.0f; float minDst_pY = 0.0f; float dst = 0.0f; //알고리즘 변경 //1. 일단 -X, +X, -Y, +Y 방향으로 가장 가까운 포인트를 찾는다. (축값이 아닌 실제 Dst임) //2. 최대 4개의 포인트에 대하여 "최대 거리"를 구한다 //3. 4개의 포인트를 포함하여 최대 거리 안에 포함된 포인트들을 리스트에 넣는다. //4. 포인트를 3개씩 묶어서 "삼각형"이 되어 이 점을 포함하는지 확인 //5. "삼각형"이 되는 경우, 전체 Dist의 합이 가장 작은 삼각형을 선택한다. //6. 최적화된 삼각형을 찾은 상태에서 Barycentric 방식으로 보간한다. for (int iTarget = 0; iTarget < targetModVertRigs.Count; iTarget++) { targetModVertRig = targetModVertRigs[iTarget]; targetPosW = targetModVertRig._renderVertex._pos_World_NoMod; near_mX = null; near_pX = null; near_mY = null; near_pY = null; minDst_mX = 0.0f; minDst_pX = 0.0f; minDst_mY = 0.0f; minDst_pY = 0.0f; for (int iSrc = 0; iSrc < _posWeightPairs.Count; iSrc++) { src = _posWeightPairs[iSrc]; srcPosW = src._posWorld; dst = Vector2.Distance(srcPosW, targetPosW); if (srcPosW.x < targetPosW.x) { //-X에 대해서 if (dst < minDst_mX || near_mX == null) { near_mX = src; minDst_mX = dst; } } else { //+X에 대해서 if (dst < minDst_pX || near_pX == null) { near_pX = src; minDst_pX = dst; } } if (srcPosW.y < targetPosW.y) { //-Y에 대해서 if (dst < minDst_mY || near_mY == null) { near_mY = src; minDst_mY = dst; } } else { //+Y에 대해서 if (dst < minDst_pY || near_pY == null) { near_pY = src; minDst_pY = dst; } } } //아주 가까운 점이 있다면 그 점을 그대로 대입한다. if (near_mX != null && near_mX.IsApproxPos(targetPosW)) { near_mX.PasteToModVertRig(meshGroup, targetModVertRig); //Debug.Log(">> Case0 : 1개의 겹치는 점 대입"); continue; } if (near_pX != null && near_pX.IsApproxPos(targetPosW)) { near_pX.PasteToModVertRig(meshGroup, targetModVertRig); //Debug.Log(">> Case0 : 1개의 겹치는 점 대입"); continue; } if (near_mY != null && near_mY.IsApproxPos(targetPosW)) { near_mY.PasteToModVertRig(meshGroup, targetModVertRig); //Debug.Log(">> Case0 : 1개의 겹치는 점 대입"); continue; } if (near_pY != null && near_pY.IsApproxPos(targetPosW)) { near_pY.PasteToModVertRig(meshGroup, targetModVertRig); //Debug.Log(">> Case0 : 1개의 겹치는 점 대입"); continue; } //2. 최대 4개의 포인트에 대하여 "최대 거리"를 구한다 //3. 4개의 포인트를 포함하여 최대 거리 안에 포함된 포인트들을 리스트에 넣는다. List <PosWeightPair> pairList = new List <PosWeightPair>(); float maxDist = 0.0f; if (near_mX != null) { pairList.Add(near_mX); maxDist = Mathf.Max(minDst_mX, maxDist); } if (near_pX != null && !pairList.Contains(near_pX)) { pairList.Add(near_pX); maxDist = Mathf.Max(minDst_pX, maxDist); } if (near_mY != null && !pairList.Contains(near_mY)) { pairList.Add(near_mY); maxDist = Mathf.Max(minDst_mY, maxDist); } if (near_pY != null && !pairList.Contains(near_pY)) { pairList.Add(near_pY); maxDist = Mathf.Max(minDst_pY, maxDist); } if (pairList.Count < 3) { maxDist *= 2; } //이제 다시 돌면서 maxDist 거리 안에 있는 모든 포인트를 리스트에 넣는다. for (int iSrc = 0; iSrc < _posWeightPairs.Count; iSrc++) { src = _posWeightPairs[iSrc]; if (pairList.Contains(src)) { //이미 추가되었다. continue; } srcPosW = src._posWorld; dst = Vector2.Distance(srcPosW, targetPosW); if (dst < maxDist) { pairList.Add(src); } } if (pairList.Count == 0) { //1개도 없다면 continue; } if (pairList.Count == 1) { //가까운 점이 1개라면 //그대로 대입 pairList[0].PasteToModVertRig(meshGroup, targetModVertRig); //Debug.Log(">> Case1 : 1개의 점 대입"); continue; } PosWeightPair pairResult = new PosWeightPair(); if (pairList.Count == 2) { //4-1. 가까운 점이 2개라면 //두개의 거리 비로 계산한다. PosWeightPair pairA = pairList[0]; PosWeightPair pairB = pairList[0]; float dstA = Vector2.Distance(pairA._posWorld, targetPosW); float dstB = Vector2.Distance(pairB._posWorld, targetPosW); if (dstA + dstB > 0.0f) { pairResult.Lerp(pairA, pairB, dstA / (dstA + dstB)); } else { pairResult.Lerp(pairA, pairB, 0.5f); } pairResult.PasteToModVertRig(meshGroup, targetModVertRig); //Debug.Log(">> Case2 : 2개의 점 대입"); continue; } //4-2. 포인트를 3개씩 묶어서 "삼각형"이 되어 이 점을 포함하는지 확인 //Recursive 함수를 이용하자 List <TriangleSet> triSet = GetTriangleSet_LV1(targetPosW, pairList, 0); if (triSet.Count == 0) { //삼각형 메시에 포함되지 않았다면, //가장 가까운 3개의 점을 보간하자 pairList.Sort(delegate(PosWeightPair a, PosWeightPair b) { float dstA = Vector2.Distance(a._posWorld, targetPosW); float dstB = Vector2.Distance(b._posWorld, targetPosW); return((int)((dstA - dstB) * 1000.0f)); }); pairResult.Interpolation3_NotTri(pairList[0], pairList[1], pairList[2], targetPosW); pairResult.PasteToModVertRig(meshGroup, targetModVertRig); //Debug.Log(">> Case3 : 삼각형이 안되는 3개의 점 대입"); continue; } //5. "삼각형"이 되는 경우, 전체 Dist의 합이 가장 작은 삼각형을 선택한다. TriangleSet minTriSet = null; float minTriSize = 0.0f; TriangleSet curTriSet = null; for (int iTri = 0; iTri < triSet.Count; iTri++) { curTriSet = triSet[iTri]; if (minTriSet == null || curTriSet._totalDist < minTriSize) { minTriSet = curTriSet; minTriSize = curTriSet._totalDist; } } //6. 최적화된 삼각형을 찾은 상태에서 Barycentric 방식으로 보간한다. minTriSet.CalculateBaryCentricWeights(targetPosW); pairResult.AddPosWeightPair(minTriSet._pair_A, minTriSet._baryCentricWeightA); pairResult.AddPosWeightPair(minTriSet._pair_B, minTriSet._baryCentricWeightB); pairResult.AddPosWeightPair(minTriSet._pair_C, minTriSet._baryCentricWeightC); pairResult.Normalize(); pairResult.PasteToModVertRig(meshGroup, targetModVertRig); //Debug.Log(">> Case4 : 삼각형 보간 대입"); } return(true); }
/// <summary> /// Rigging Modifier내에서의 Gizmo 이벤트 : Vertex 다중 선택. Bone은 선택하지 않는다. /// </summary> /// <param name="mousePosGL_Min"></param> /// <param name="mousePosGL_Max"></param> /// <param name="mousePosW_Min"></param> /// <param name="mousePosW_Max"></param> /// <param name="areaSelectType"></param> /// <returns></returns> public apGizmos.SelectResult MultipleSelect__Modifier_Rigging(Vector2 mousePosGL_Min, Vector2 mousePosGL_Max, Vector2 mousePosW_Min, Vector2 mousePosW_Max, apGizmos.SELECT_TYPE areaSelectType) { if (Editor.Select.MeshGroup == null || Editor.Select.Modifier == null) { return(null); } if (Editor.Select.ModRenderVertListOfMod == null) { return(null); } // 이건 다중 버텍스 선택밖에 없다. //Transform 선택은 없음 //if (!Editor.Controller.IsMouseInGUI(mousePosGL)) //{ // return apGizmos.SELECT_RESULT.None; //} //apGizmos.SELECT_RESULT result = apGizmos.SELECT_RESULT.None; bool isAnyChanged = false; if (Editor.Select.ExKey_ModMesh != null && Editor.Select.MeshGroup != null) { //선택된 RenderUnit을 고르자 apRenderUnit targetRenderUnit = Editor.Select.MeshGroup.GetRenderUnit(Editor.Select.ExKey_ModMesh._transform_Mesh); if (targetRenderUnit != null) { for (int iVert = 0; iVert < targetRenderUnit._renderVerts.Count; iVert++) { apRenderVertex renderVert = targetRenderUnit._renderVerts[iVert]; bool isSelectable = (mousePosW_Min.x < renderVert._pos_World.x && renderVert._pos_World.x < mousePosW_Max.x) && (mousePosW_Min.y < renderVert._pos_World.y && renderVert._pos_World.y < mousePosW_Max.y); if (isSelectable) { apModifiedVertexRig selectedModVertRig = Editor.Select.ExKey_ModMesh._vertRigs.Find(delegate(apModifiedVertexRig a) { return(renderVert._vertex._uniqueID == a._vertexUniqueID); }); if (selectedModVertRig != null) { if (areaSelectType == apGizmos.SELECT_TYPE.Add || areaSelectType == apGizmos.SELECT_TYPE.New) { Editor.Select.AddModVertexOfModifier(null, selectedModVertRig, null, renderVert); } else { Editor.Select.RemoveModVertexOfModifier(null, selectedModVertRig, null, renderVert); } isAnyChanged = true; //result = apGizmos.SELECT_RESULT.NewSelected; //break; } } } Editor.RefreshControllerAndHierarchy(); //Editor.Repaint(); Editor.SetRepaint(); } } if (isAnyChanged) { Editor.Select.AutoSelectModMeshOrModBone(); } //return Editor.Select.ModRenderVertListOfMod.Count; return(apGizmos.SelectResult.Main.SetMultiple <apSelection.ModRenderVert>(Editor.Select.ModRenderVertListOfMod)); }