Ejemplo n.º 1
0
        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;
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
 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;
            }
        }
Ejemplo n.º 7
0
        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);
        }
Ejemplo n.º 8
0
            //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);
        }
Ejemplo n.º 10
0
        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);
        }
Ejemplo n.º 11
0
            //저장된 값을 대상 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));
        }
Ejemplo n.º 13
0
            //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);
            }
Ejemplo n.º 14
0
        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);
        }
Ejemplo n.º 15
0
 public bool SetSnapShot_VertRig(apModifiedVertexRig vertRig, string strParam)
 {
     _snapShot = new apSnapShot_VertRig();
     return(_snapShot.Save(vertRig, strParam));
 }
Ejemplo n.º 16
0
        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);
        }
Ejemplo n.º 17
0
        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);
                }
            }
        }
Ejemplo n.º 18
0
        /// <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);
        }
Ejemplo n.º 19
0
        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);
        }
Ejemplo n.º 20
0
        /// <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));
        }