コード例 #1
0
ファイル: Compiler.cs プロジェクト: deplinenoise/blobc3
        private static void ResolveStructs(ParseResult result)
        {
            Dictionary <string, StructDef> allStructs = new Dictionary <string, StructDef>();

            foreach (StructDef structDef in result.Structs)
            {
                allStructs.Add(structDef.Name, structDef);
            }

            // Resolve all struct types used in fields to point to the structure definitions
            var fieldNames = new HashSet <string>();

            foreach (StructDef structDef in result.Structs)
            {
                fieldNames.Clear();
                foreach (FieldDef fieldDef in structDef.Fields)
                {
                    if (fieldNames.Contains(fieldDef.Name))
                    {
                        throw new TypeCheckException(fieldDef.Location, $"duplicate field name '{fieldDef.Name}'");
                    }

                    fieldNames.Add(fieldDef.Name);
                    fieldDef.Type.Resolve(allStructs);
                }
            }

            var structToWeightIndex = new Dictionary <StructDef, int>();

            WeightPair[] sortWeights = new WeightPair[result.Structs.Count];

            for (int i = 0; i < sortWeights.Length; ++i)
            {
                sortWeights[i] = new WeightPair {
                    Struct = result.Structs[i], Weight = -1
                };
                structToWeightIndex[result.Structs[i]] = i;
            }

            for (int i = 0; i < sortWeights.Length; ++i)
            {
                sortWeights[i].Weight = ComputeStructWeight(sortWeights, i, structToWeightIndex);
            }

            Array.Sort(sortWeights);

            // Replace array of structs with sorted result
            for (int i = 0; i < sortWeights.Length; ++i)
            {
                result.Structs[i] = sortWeights[i].Struct;
            }

            // Compute attributes for each struct
            foreach (StructDef structDef in result.Structs)
            {
                ComputeLayout(structDef);
            }
        }
コード例 #2
0
            // 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);
            }
コード例 #3
0
        /// <summary>
        /// WeightTable의 값과 연동을 하고 Sort를 한다.
        /// </summary>
        /// <param name="portrait"></param>
        public void LinkWeightPair(apPortrait portrait)
        {
            _totalWeight = 0.0f;
            WeightPair weightPair  = null;
            bool       isAnyRemove = false;

            for (int i = 0; i < _weightPairs.Count; i++)
            {
                weightPair = _weightPairs[i];
                if (weightPair._meshGroupID >= 0)
                {
                    weightPair._meshGroup = portrait.GetMeshGroup(weightPair._meshGroupID);
                    if (weightPair._meshGroup != null)
                    {
                        //<BONE_EDIT>
                        //weightPair._bone = weightPair._meshGroup.GetBone(weightPair._boneID);

                        //>>Recursive로 변경
                        weightPair._bone = weightPair._meshGroup.GetBoneRecursive(weightPair._boneID);
                        if (weightPair._bone == null)
                        {
                            isAnyRemove = true;
                            //Debug.LogError("Bone Weight가 없어졌다. Rigging 해제됨");
                        }
                        else
                        {
                            _totalWeight += weightPair._weight;
                        }
                    }
                    else
                    {
                        weightPair._bone = null;
                        isAnyRemove      = true;
                    }
                }
                else
                {
                    weightPair._meshGroup = null;
                    weightPair._bone      = null;
                    isAnyRemove           = true;
                }
            }
            if (isAnyRemove)
            {
                //뭔가 삭제할게 생겼다. 삭제하자
                _weightPairs.RemoveAll(delegate(WeightPair a)
                {
                    return(a._meshGroup == null || a._bone == null);
                });
            }
        }
コード例 #4
0
        /// <summary>
        /// Normalize와 유사하지만, 해당 Pair를 일단 제쳐두고,
        /// "나머지 Weight"에 한해서 우선 Normalize
        /// 그리고 해당 Pair를 포함시킨다.
        /// 요청한 Pair의 Weight가 1이 넘으면 1로 맞추고 나머지는 0
        /// </summary>
        /// <param name="pair"></param>
        public void NormalizeExceptPair(WeightPair pair)
        {
            if (!_weightPairs.Contains(pair))
            {
                Normalize();
                return;
            }

            float reqWeight      = Mathf.Clamp01(pair._weight);
            float remainedWeight = 1.0f - reqWeight;

            float totalWeightExceptReq = 0.0f;

            for (int i = 0; i < _weightPairs.Count; i++)
            {
                if (_weightPairs[i] == pair)
                {
                    _weightPairs[i]._weight = reqWeight;
                }
                else
                {
                    totalWeightExceptReq += _weightPairs[i]._weight;
                }
            }

            if (totalWeightExceptReq > 0.0f)
            {
                //totalWeightExceptReq -> remainedWeight
                float convertRatio = remainedWeight / totalWeightExceptReq;

                for (int i = 0; i < _weightPairs.Count; i++)
                {
                    if (_weightPairs[i] == pair)
                    {
                        continue;
                    }
                    else
                    {
                        _weightPairs[i]._weight *= convertRatio;
                    }
                }
            }

            //그리고 마지막으로 Normalize
            Normalize();
        }
コード例 #5
0
        /// <summary>
        /// WeightTable의 값과 연동을 하고 Sort를 한다.
        /// </summary>
        /// <param name="portrait"></param>
        public void LinkWeightPair(apPortrait portrait)
        {
            _totalWeight = 0.0f;
            WeightPair weightPair  = null;
            bool       isAnyRemove = false;

            for (int i = 0; i < _weightPairs.Count; i++)
            {
                weightPair = _weightPairs[i];
                if (weightPair._meshGroupID >= 0)
                {
                    weightPair._meshGroup = portrait.GetMeshGroup(weightPair._meshGroupID);
                    if (weightPair._meshGroup != null)
                    {
                        weightPair._bone = weightPair._meshGroup.GetBone(weightPair._boneID);
                        if (weightPair._bone == null)
                        {
                            isAnyRemove = true;
                        }
                        else
                        {
                            _totalWeight += weightPair._weight;
                        }
                    }
                    else
                    {
                        weightPair._bone = null;
                        isAnyRemove      = true;
                    }
                }
                else
                {
                    weightPair._meshGroup = null;
                    weightPair._bone      = null;
                    isAnyRemove           = true;
                }
            }
            if (isAnyRemove)
            {
                //뭔가 삭제할게 생겼다. 삭제하자
                _weightPairs.RemoveAll(delegate(WeightPair a)
                {
                    return(a._meshGroup == null || a._bone == null);
                });
            }
        }
コード例 #6
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);
        }
    /// <summary>
    /// Preprocess the terrain to clamp down on the number of splat maps which have weights on each control point. First pass
    /// limits the number of weights to the specified amount per control point. Since each rendered pixel is a blend of 4 possible
    /// control points, this still means a given pixel may need up to 4 weights even if the control point is clamped to 1 weight.
    /// In the second pass, we check all of the neighoring pixels to see if they have different weights- if they do, we clamp
    /// down to one less weight on this control point. The idea here is to create some extra headroom for the blend, but since
    /// you can still need 4 blend weights in some cases, there is no perfect solution to this issue when running with less than
    /// 4 blend weights. It does, however, greatly help when running under those constraints.
    ///
    /// </summary>
    /// <param name="bt">Bt.</param>
    /// <param name="maxWeights">Max weights.</param>
    /// <param name="secondPass">If set to <c>true</c> second pass.</param>
    public static void WeightLimitTerrain(MicroSplatTerrain bt, int maxWeights, bool secondPass = false)
    {
        Terrain t = bt.GetComponent <Terrain>();

        if (t == null)
        {
            return;
        }
        UnityEngine.TerrainData td = t.terrainData;
        if (td == null)
        {
            return;
        }

        int w = td.alphamapWidth;
        int h = td.alphamapHeight;
        int l = td.alphamapLayers;

        Undo.RegisterCompleteObjectUndo(t, "Weight Limit Terrain");

        var splats = td.GetAlphamaps(0, 0, w, h);

        float[]           data         = new float[16];
        List <WeightPair> sorted       = new List <WeightPair>();
        List <int>        validIndexes = new List <int>();

        for (int x = 0; x < w; ++x)
        {
            for (int y = 0; y < h; ++y)
            {
                // gather all weights
                for (int i = 0; i < l; ++i)
                {
                    data[i] = splats[x, y, i];
                }

                sorted.Clear();
                for (int i = 0; i < 16; ++i)
                {
                    var wp = new WeightPair();
                    wp.index  = i;
                    wp.weight = data[i];
                    sorted.Add(wp);
                }

                sorted.Sort((w0, w1) => w1.weight.CompareTo(w0.weight));

                // remove lower weights
                int allowedWeights = maxWeights;
                while (sorted.Count > allowedWeights)
                {
                    sorted.RemoveAt(sorted.Count - 1);
                }

                // generate valid index list
                validIndexes.Clear();
                for (int i = 0; i < sorted.Count; ++i)
                {
                    if (sorted[i].weight > 0)
                    {
                        validIndexes.Add(sorted[i].index);
                    }
                }
                // figure out if our neighbors have weights which we don't have- if so, clamp down harder to make room for blending..
                // if not, allow us to blend fully. We do this in a second pass so that small weights are reduced before we make
                // this decision..

                if (secondPass)
                {
                    for (int xm = -1; xm < 2; ++xm)
                    {
                        for (int ym = -1; ym < 2; ++ym)
                        {
                            int nx = x + xm;
                            int ny = y + ym;
                            if (nx >= 0 && ny >= 0 && nx < w && ny < y)
                            {
                                for (int layer = 0; layer < l; ++layer)
                                {
                                    float weight = splats[nx, ny, layer];
                                    if (weight > 0 && !validIndexes.Contains(layer))
                                    {
                                        allowedWeights = maxWeights - 1;
                                    }
                                }
                            }
                        }
                    }
                    while (sorted.Count > allowedWeights)
                    {
                        sorted.RemoveAt(sorted.Count - 1);
                    }
                    // generate valid index list
                    validIndexes.Clear();
                    for (int i = 0; i < sorted.Count; ++i)
                    {
                        if (sorted[i].weight > 0)
                        {
                            validIndexes.Add(sorted[i].index);
                        }
                    }
                }


                // clear non-valid indexes

                for (int j = 0; j < 16; ++j)
                {
                    if (!validIndexes.Contains(j))
                    {
                        data[j] = 0;
                    }
                }


                // now normalize weights so that they total one on each pixel

                float total = 0;
                for (int j = 0; j < 16; ++j)
                {
                    total += data[j];
                }
                float scale = 1.0f / total;
                for (int j = 0; j < 16; ++j)
                {
                    data[j] *= scale;
                }


                // now map back to splat data array
                for (int i = 0; i < l; ++i)
                {
                    splats[x, y, i] = data[i];
                }
            }
        }

        td.SetAlphamaps(0, 0, splats);
    }
コード例 #8
0
        /// <summary>
        /// Normalize와 유사하지만, 해당 Pair를 일단 제쳐두고,
        /// "나머지 Weight"에 한해서 우선 Normalize
        /// 그리고 해당 Pair를 포함시킨다.
        /// 요청한 Pair의 Weight가 1이 넘으면 1로 맞추고 나머지는 0
        /// </summary>
        /// <param name="pair"></param>
        public void NormalizeExceptPair(WeightPair pair, bool isSetOtherRigValue0or1 = false)
        {
            if (!_weightPairs.Contains(pair))
            {
                Normalize();
                return;
            }

            float reqWeight = Mathf.Clamp01(pair._weight);

            //변경 19.7.27 : 리깅 데이터에 Lock이 걸리면 Normalize에서 값 보정이 안된다.
            //락 여부에 따라서 각각 RigData의 개수와 Weight 총합 구하기
            int   nPair_Locked        = 0;
            int   nPair_Unlocked      = 0;
            float prevWeight_Locked   = 0.0f;
            float prevWeight_Unlocked = 0.0f;

            WeightPair curPair = null;

            for (int i = 0; i < _weightPairs.Count; i++)
            {
                curPair = _weightPairs[i];
                if (curPair == pair)
                {
                    continue;
                }
                else if (curPair._bone == null)
                {
                    continue;
                }
                else if (curPair._bone._isRigLock)
                {
                    //Lock이 걸린 Bone이다.
                    nPair_Locked++;
                    prevWeight_Locked += curPair._weight;
                }
                else
                {
                    //Lock이 걸리지 않은 Bone이다.
                    nPair_Unlocked++;
                    prevWeight_Unlocked += curPair._weight;
                }
            }
            prevWeight_Locked   = Mathf.Clamp01(prevWeight_Locked);
            prevWeight_Unlocked = Mathf.Clamp01(prevWeight_Unlocked);

            //float remainedWeight = 1.0f - reqWeight;//기존

            //변경 : Unlocked된 Bone에 대해서만 계산한다.
            if (reqWeight + prevWeight_Locked > 1.0f)
            {
                //Lock + 요청된 Weight의 합이 1이 넘으면 정상적으로 값을 설정할 수 없다.
                //요청값을 감소시킨다.
                reqWeight = 1.0f - prevWeight_Locked;
            }

            float remainedWeight = 1.0f - (reqWeight + prevWeight_Locked);

            if (remainedWeight < 0.0f)
            {
                //요청된 Weight를 적용할 수 없다.
                remainedWeight = 0.0f;
            }

            //float totalWeightExceptReq = 0.0f;
            //int nOtherPairs = 0;
            for (int i = 0; i < _weightPairs.Count; i++)
            {
                curPair = _weightPairs[i];
                if (curPair == pair)
                {
                    curPair._weight = reqWeight;
                    break;
                }
                //else
                //{
                //	totalWeightExceptReq += _weightPairs[i]._weight;
                //	nOtherPairs++;
                //}
            }

            //나머지 Unlocked Pair에 값을 지정해야하는 경우
            if (nPair_Unlocked > 0)
            {
                if (prevWeight_Unlocked > 0.0f)
                {
                    //Unlocked Pair의 값의 합이 0보다 큰 경우 (Normalize를 위한 준비 필요)
                    float convertRatio = remainedWeight / prevWeight_Unlocked;

                    for (int i = 0; i < _weightPairs.Count; i++)
                    {
                        curPair = _weightPairs[i];
                        if (curPair == pair || curPair._bone == null || curPair._bone._isRigLock)
                        {
                            //Unlocked Bone이 아닌 경우
                            continue;
                        }
                        else
                        {
                            //Weight를 변경하자
                            curPair._weight *= convertRatio;
                        }
                    }
                }
                else if (isSetOtherRigValue0or1)
                {
                    //Unlocked Pair의 값이 0이었으나, 남은 Weight를 1/n로 나누어서 분배할 필요가 있는 경우
                    float perWeight = remainedWeight / nPair_Unlocked;

                    for (int i = 0; i < _weightPairs.Count; i++)
                    {
                        curPair = _weightPairs[i];
                        if (curPair == pair || curPair._bone == null || curPair._bone._isRigLock)
                        {
                            //Unlocked Bone이 아닌 경우
                            continue;
                        }
                        else
                        {
                            _weightPairs[i]._weight = perWeight;
                        }
                    }
                }
            }

            //그리고 마지막으로 Normalize
            Normalize();
        }