/// <summary>
        /// 为材料平铺和采样矩形和UV平铺分配初始值
        /// </summary>
        /// <param name="allTexturesUseSameMatTiling"></param>
        /// <param name="matTiling"></param>
        public void AssignInitialValuesForMaterialTilingAndSamplingRectMatAndUVTiling(bool allTexturesUseSameMatTiling, DRect matTiling)
        {
            if (allTexturesUseSameMatTiling)
            {
                materialTiling = matTiling;
            }
            else
            {
                materialTiling = new DRect(0f, 0f, 1f, 1f);
            }
            DRect tmpMatTiling = materialTiling;
            DRect obUVrect     = obUVRectIfTilingSame;

            samplingRectMatAndUVTiling = UVRectUtility.CombineTransforms(ref obUVrect, ref tmpMatTiling);
        }
        public static Rect BuildTransformMeshUV2AtlasRect(
            bool considerMeshUVs,
            Rect _atlasRect,
            Rect _obUVRect,
            Rect _sourceMaterialTiling,
            Rect _encapsulatingRect)
        {
            DRect atlasRect = new DRect(_atlasRect);
            DRect obUVRect;

            if (considerMeshUVs)
            {
                obUVRect = new DRect(_obUVRect); //this is the uvRect in src mesh
            }
            else
            {
                obUVRect = new DRect(0.0, 0.0, 1.0, 1.0);
            }

            DRect sourceMaterialTiling = new DRect(_sourceMaterialTiling);

            //封装材质, UV 参数
            DRect encapsulatingRectMatAndUVTiling = new DRect(_encapsulatingRect);

            DRect encapsulatingRectMatAndUVTilingInverse = UVRectUtility.InverseTransform(ref encapsulatingRectMatAndUVTiling);

            DRect toNormalizedUVs = UVRectUtility.InverseTransform(ref obUVRect);

            DRect meshFullSamplingRect = UVRectUtility.CombineTransforms(ref obUVRect, ref sourceMaterialTiling);

            DRect shiftToFitInEncapsulating = UVRectUtility.GetShiftTransformToFitBinA(ref encapsulatingRectMatAndUVTiling, ref meshFullSamplingRect);

            meshFullSamplingRect = UVRectUtility.CombineTransforms(ref meshFullSamplingRect, ref shiftToFitInEncapsulating);

            //transform between full sample rect and encapsulating rect
            DRect relativeTrans = UVRectUtility.CombineTransforms(ref meshFullSamplingRect, ref encapsulatingRectMatAndUVTilingInverse);

            DRect trans = UVRectUtility.CombineTransforms(ref toNormalizedUVs, ref relativeTrans);

            trans = UVRectUtility.CombineTransforms(ref trans, ref atlasRect);
            Rect rr = trans.GetRect();

            return(rr);
        }
Example #3
0
        public void DrawRectsToMergeGizmos(Color encC, Color innerC)
        {
            DRect r = ts[0].GetEncapsulatingSamplingRect();

            r.Expand(.05f);
            Gizmos.color = encC;
            Gizmos.DrawWireCube(r.center.GetVector2(), r.size);
            for (int i = 0; i < matsAndGOs.mats.Count; i++)
            {
                DRect   rr    = matsAndGOs.mats[i].samplingRectMatAndUVTiling;
                DRect   trans = UVRectUtility.GetShiftTransformToFitBinA(ref r, ref rr);
                Vector2 xy    = UVRectUtility.TransformPoint(ref trans, rr.min);
                rr.x = xy.x;
                rr.y = xy.y;
                //Debug.Log("r " + r + " rr" + rr);
                Gizmos.color = innerC;
                Gizmos.DrawWireCube(rr.center.GetVector2(), rr.size);
            }
        }
Example #4
0
        //assumes all materials use the same obUVrects.
        //假设所有材料都使用相同的obUVrects。
        internal void CalcInitialFullSamplingRects(bool fixOutOfBoundsUVs)
        {
            DRect validFullSamplingRect = new DRect(0, 0, 1, 1);

            if (fixOutOfBoundsUVs)
            {
                validFullSamplingRect = obUVrect;
            }

            for (int propIdx = 0; propIdx < ts.Length; propIdx++)
            {
                if (!ts[propIdx].isNull)
                {
                    DRect matTiling = ts[propIdx].matTilingRect;
                    DRect ruv;
                    if (fixOutOfBoundsUVs)
                    {
                        ruv = obUVrect;
                    }
                    else
                    {
                        ruv = new DRect(0.0, 0.0, 1.0, 1.0);
                    }

                    ts[propIdx].SetEncapsulatingSamplingRect(this, UVRectUtility.CombineTransforms(ref ruv, ref matTiling));
                    validFullSamplingRect = ts[propIdx].GetEncapsulatingSamplingRect();
                }
            }

            //if some of the textures were null make them match the sampling of one of the other textures
            for (int propIdx = 0; propIdx < ts.Length; propIdx++)
            {
                if (ts[propIdx].isNull)
                {
                    ts[propIdx].SetEncapsulatingSamplingRect(this, validFullSamplingRect);
                }
            }
        }
        /// <summary>
        /// A material can appear more than once in an atlas if using fixOutOfBoundsUVs.
        /// in this case you need to use the UV rect of the mesh to find the correct rectangle.
        /// If the all properties on the mat use the same tiling then
        /// encapsulatingRect can be larger and will include baked UV and material tiling
        /// If mat uses different tiling for different maps then encapsulatingRect is the uvs of
        /// source mesh used to bake atlas and sourceMaterialTilingOut is 0,0,1,1. This works because
        /// material tiling was baked into the atlas.
        /// 尝试获取源物体材质在合并材质中的映射信息
        /// 如果使用fixOutOfBoundsUVs,一个材质可以在图集中出现多次。在这种情况下,您需要使用网格的UV矩形来找到正确的矩形。
        /// 如果材质上的所有属性都使用相同的拼贴,则 encapsulatingRect 可以更大,并将包含烘焙的UV和材质平铺
        /// 如果mat 对不同映射使用不同的tiling,则 encapsulatingRect 是用于烘焙图集的 uvs 且 sourceMaterialTilingOut 为0,0,1,1。
        /// 材质 tiling 烘焙到 atlas 中。
        /// </summary>
        public bool TryGetMaterialToUVRectMap(Material sourceMat,
                                              Mesh sourceMesh,
                                              int submeshIdx,
                                              int idxInResultMats,
                                              MeshChannelsCache meshChannelCache,
                                              Dictionary <int, MeshAnalysisResult[]> meshAnalysisCache,
                                              out TextureTilingTreatment tilingTreatment,
                                              out Rect rectInAtlas,
                                              out Rect encapsulatingRectOut,
                                              out Rect sourceMaterialTilingOut,
                                              ref string errorMsg)
        {
            for (int i = 0; i < resultAsset.materialsAndUVRects.Length; i++)
            {
                resultAsset.materialsAndUVRects[i].allPropsUseSameTiling = true;
            }

            tilingTreatment = TextureTilingTreatment.unknown;
            if (resultAsset.materialsAndUVRects.Length == 0)
            {
                errorMsg                = "Texture Bake Result 资源中的 材质UVRect 映射信息为空,需重新合并";
                rectInAtlas             = new Rect();
                encapsulatingRectOut    = new Rect();
                sourceMaterialTilingOut = new Rect();
                return(false);
            }
            if (sourceMat == null)
            {
                rectInAtlas             = new Rect();
                encapsulatingRectOut    = new Rect();
                sourceMaterialTilingOut = new Rect();
                errorMsg = string.Format("网格 {0} 的子网格 {1} 缺少材质,无法获取映射关系", sourceMesh.name, submeshIdx);
                return(false);
            }
            if (submeshIdx >= sourceMesh.subMeshCount)
            {
                errorMsg                = "参数错误 :Submesh index 大于子网格数量";
                rectInAtlas             = new Rect();
                encapsulatingRectOut    = new Rect();
                sourceMaterialTilingOut = new Rect();
                return(false);
            }

            //源材质在 matsAndSrcUVRect 的 ID
            int idx = -1;

            for (int i = 0; i < matsAndSrcUVRect.Length; i++)
            {
                if (sourceMat == matsAndSrcUVRect[i].material)
                {
                    idx = i;
                    break;
                }
            }
            if (idx == -1)
            {
                rectInAtlas             = new Rect();
                encapsulatingRectOut    = new Rect();
                sourceMaterialTilingOut = new Rect();
                errorMsg = string.Format("Material {0} 在 Texture Bake Result 中无法找到", sourceMat.name);
                return(false);
            }

            //不处理网格 UVs
            if (!resultAsset.resultMaterials[idxInResultMats].considerMeshUVs)
            {
                if (numTimesMatAppearsInAtlas[idx] != 1)
                {
                    Debug.LogError("TextureBakeResults 资源错误,FixOutOfBoundsUVs is false and a material appears more than once.");
                }
                MaterialAndUVRect mr = matsAndSrcUVRect[idx];
                rectInAtlas             = mr.atlasRect;
                tilingTreatment         = mr.tilingTreatment;
                encapsulatingRectOut    = mr.GetEncapsulatingRect();
                sourceMaterialTilingOut = mr.GetMaterialTilingRect();
                return(true);
            }
            else
            {
                //todo what if no UVs
                //Find UV rect in source mesh
                //源网格分析,并缓存
                MeshAnalysisResult[] meshAnalysisInfo;
                if (!meshAnalysisCache.TryGetValue(sourceMesh.GetInstanceID(), out meshAnalysisInfo))
                {
                    meshAnalysisInfo = new MeshAnalysisResult[sourceMesh.subMeshCount];
                    for (int j = 0; j < sourceMesh.subMeshCount; j++)
                    {
                        Vector2[] uvss = meshChannelCache.GetUv0Raw(sourceMesh);
                        MeshBakerUtility.hasOutOfBoundsUVs(uvss, sourceMesh, ref meshAnalysisInfo[j], j);
                    }
                    meshAnalysisCache.Add(sourceMesh.GetInstanceID(), meshAnalysisInfo);
                }

                //this could be a mesh that was not used in the texture baking that has huge UV tiling too big for the rect that was baked
                //find a record that has an atlas uvRect capable of containing this
                //这可能是未在纹理烘焙中使用的网格,该网格的UV贴图对于烘焙的rect而言太大
                //找到一条记录,该记录具有能够包含此图集的uvRect
                bool found                = false;
                Rect encapsulatingRect    = new Rect(0, 0, 0, 0);
                Rect sourceMaterialTiling = new Rect(0, 0, 0, 0);

                //Debug.Log(string.Format("尝试在图集中查找能够使用材质{1}保持网格{0}的平铺采样rect的矩形",
                //    m, sourceMat, meshAnalysisInfo[submeshIdx].uvRect.ToString("f5")));

                for (int i = idx; i < matsAndSrcUVRect.Length; i++)
                {
                    MaterialAndUVRect matAndUVrect = matsAndSrcUVRect[i];
                    if (matAndUVrect.material == sourceMat)
                    {
                        if (matAndUVrect.allPropsUseSameTiling)
                        {
                            encapsulatingRect    = matAndUVrect.allPropsUseSameTiling_samplingEncapsulatinRect;
                            sourceMaterialTiling = matAndUVrect.allPropsUseSameTiling_sourceMaterialTiling;
                        }
                        else
                        {
                            encapsulatingRect    = matAndUVrect.propsUseDifferntTiling_srcUVsamplingRect;
                            sourceMaterialTiling = new Rect(0, 0, 1, 1);
                        }

                        if (UVRectUtility.IsMeshAndMaterialRectEnclosedByAtlasRect(
                                matAndUVrect.tilingTreatment,
                                meshAnalysisInfo[submeshIdx].uvRect,
                                sourceMaterialTiling,
                                encapsulatingRect))
                        {
                            Debug.Log("在图集中找到" + "ID 为 " + i + "包含" + sourceMesh + "  的 tiled sampling 的 Rect");
                            idx   = i;
                            found = true;
                            break;
                        }
                    }
                }
                if (found)
                {
                    MaterialAndUVRect mr = matsAndSrcUVRect[idx];
                    rectInAtlas             = mr.atlasRect;
                    tilingTreatment         = mr.tilingTreatment;
                    encapsulatingRectOut    = mr.GetEncapsulatingRect();
                    sourceMaterialTilingOut = mr.GetMaterialTilingRect();
                    return(true);
                }
                else
                {
                    rectInAtlas             = new Rect();
                    encapsulatingRectOut    = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    errorMsg = string.Format("Could not find a tiled rectangle in the atlas capable of containing the uv and material tiling on mesh {0} for material {1}. " +
                                             "Was this mesh included when atlases were baked?", sourceMesh.name, sourceMat);
                    return(false);
                }
            }
        }
        public void MergeOverlappingDistinctMaterialTexturesAndCalcMaterialSubrects(List <MaterialPropTexturesSet> distinctMaterialTextures)
        {
            int numMerged = 0;

            // IMPORTANT: Note that the verts stored in the mesh are NOT Normalized UV Coords. They are normalized * [UVTrans]. To get normalized UV
            // coords we must multiply them by [invUVTrans]. Need to do this to the verts in the mesh before we do any transforms with them.
            // Also check that all textures use same tiling. This is a prerequisite for merging.
            // Mark MB3_TexSet that are mergable (allTexturesUseSameMatTiling)
            //存储在网格中的顶点不是归一化UV坐标。 它们已归一化 * [UVTrans]。
            //获得归一化的 UV 坐标必须将其乘以[invUVTrans]。
            //在对它们进行任何转换之前,需要对网格中的顶点执行此操作。


            //检查所有纹理是否使用相同的拼贴。 这是合并的先决条件。
            //标记可合并的TexSet(allTexturesUseSameMatTiling)
            for (int i = 0; i < distinctMaterialTextures.Count; i++)
            {
                MaterialPropTexturesSet matPropsTextureSet = distinctMaterialTextures[i];
                int   idxOfFirstNotNull = -1;
                bool  allAreSame        = true;
                DRect firstRect         = new DRect();

                //判断不是相同的 texture 资源
                for (int propIdx = 0; propIdx < matPropsTextureSet.ts.Length; propIdx++)
                {
                    if (idxOfFirstNotNull != -1)
                    {
                        if (!matPropsTextureSet.ts[propIdx].isNull && firstRect != matPropsTextureSet.ts[propIdx].matTilingRect)
                        {
                            allAreSame = false;
                        }
                    }
                    //先找第一个非空纹理,设置为 idxOfFirstNotNull
                    else if (!matPropsTextureSet.ts[propIdx].isNull)
                    {
                        idxOfFirstNotNull = propIdx;
                        firstRect         = matPropsTextureSet.ts[propIdx].matTilingRect;
                    }
                }
                if (LOG_LEVEL_TRACE_MERGE_MAT_SUBRECTS == true)
                {
                    if (allAreSame)
                    {
                        Debug.LogFormat("TextureSet {0} allTexturesUseSameMatTiling = {1}", i, allAreSame);
                    }
                    else
                    {
                        Debug.Log(string.Format("Textures in material(s) do not all use the same material tiling. " +
                                                "This set of textures will not be considered for merge: {0} ", matPropsTextureSet.GetDescription()));
                    }
                }
                if (allAreSame)
                {
                    matPropsTextureSet.SetAllTexturesUseSameMatTilingTrue();
                }
            }

            //设置 材质Obj 名称
            for (int i = 0; i < distinctMaterialTextures.Count; i++)
            {
                MaterialPropTexturesSet matPropsTextureSet = distinctMaterialTextures[i];
                for (int matIdx = 0; matIdx < matPropsTextureSet.matsAndGOs.mats.Count; matIdx++)
                {
                    if (matPropsTextureSet.matsAndGOs.gos.Count > 0)
                    {
                        matPropsTextureSet.matsAndGOs.mats[matIdx].objName = matPropsTextureSet.matsAndGOs.gos[0].name;
                    }
                    else if (matPropsTextureSet.ts[0] != null)
                    {
                        matPropsTextureSet.matsAndGOs.mats[matIdx].objName = string.Format("[objWithTx:{0} atlasBlock:{1} matIdx{2}]", matPropsTextureSet.ts[0].GetTexName(), i, matIdx);
                    }
                    else
                    {
                        matPropsTextureSet.matsAndGOs.mats[matIdx].objName = string.Format("[objWithTx:{0} atlasBlock:{1} matIdx{2}]", "Unknown", i, matIdx);
                    }
                }

                matPropsTextureSet.CalcInitialFullSamplingRects(fixOutOfBoundsUVs);
                matPropsTextureSet.CalcMatAndUVSamplingRects();
            }

            // need to calculate the srcSampleRect for the complete tiling in the atlas
            // for each material need to know what the subrect would be in the atlas if material UVRect was 0,0,1,1 and Merged uvRect was full tiling
            //需要为图集中的完整切片计算src SampleRect
            //对于每种材料,如果材料UVRect为0,0,1,1并且合并的uvRect为完整平铺,则需要知道该图集在图集中的位置
            List <int> MarkedForDeletion = new List <int>();

            for (int i = 0; i < distinctMaterialTextures.Count; i++)
            {
                MaterialPropTexturesSet tx2 = distinctMaterialTextures[i];
                for (int j = i + 1; j < distinctMaterialTextures.Count; j++)
                {
                    MaterialPropTexturesSet tx1 = distinctMaterialTextures[j];
                    if (tx1.AllTexturesAreSameForMerge(tx2, _considerNonTextureProperties, resultMaterialTextureBlender))
                    {
                        double accumulatedAreaCombined    = 0f;
                        double accumulatedAreaNotCombined = 0f;
                        DRect  encapsulatingRectMerged    = new DRect();
                        int    idxOfFirstNotNull          = -1;
                        for (int propIdx = 0; propIdx < tx2.ts.Length; propIdx++)
                        {
                            if (!tx2.ts[propIdx].isNull)
                            {
                                if (idxOfFirstNotNull == -1)
                                {
                                    idxOfFirstNotNull = propIdx;
                                }
                            }
                        }

                        if (idxOfFirstNotNull != -1)
                        {
                            // only in here if all properties use the same tiling so don't need to worry about which propIdx we are dealing with
                            //Get the rect that encapsulates all material and UV tiling for materials and meshes in tx1
                            //如果所有属性都使用相同的tiling,因此无需担心我们正在处理哪个propIdx
                            //获取将所有材料和UV平铺封装为rect的rect在tx1中
                            DRect encapsulatingRect1 = tx1.matsAndGOs.mats[0].samplingRectMatAndUVTiling;
                            for (int matIdx = 1; matIdx < tx1.matsAndGOs.mats.Count; matIdx++)
                            {
                                DRect tmpSsamplingRectMatAndUVTilingTx1 = tx1.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling;
                                encapsulatingRect1 = UVRectUtility.GetEncapsulatingRectShifted(ref encapsulatingRect1, ref tmpSsamplingRectMatAndUVTilingTx1);
                            }
                            //same for tx2
                            DRect encapsulatingRect2 = tx2.matsAndGOs.mats[0].samplingRectMatAndUVTiling;
                            for (int matIdx = 1; matIdx < tx2.matsAndGOs.mats.Count; matIdx++)
                            {
                                DRect tmpSsamplingRectMatAndUVTilingTx2 = tx2.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling;
                                encapsulatingRect2 = UVRectUtility.GetEncapsulatingRectShifted(ref encapsulatingRect2, ref tmpSsamplingRectMatAndUVTilingTx2);
                            }

                            encapsulatingRectMerged     = UVRectUtility.GetEncapsulatingRectShifted(ref encapsulatingRect1, ref encapsulatingRect2);
                            accumulatedAreaCombined    += encapsulatingRectMerged.width * encapsulatingRectMerged.height;
                            accumulatedAreaNotCombined += encapsulatingRect1.width * encapsulatingRect1.height + encapsulatingRect2.width * encapsulatingRect2.height;
                        }
                        else
                        {
                            encapsulatingRectMerged = new DRect(0f, 0f, 1f, 1f);
                        }

                        //the distinct material textures may overlap.
                        //if the area of these rectangles combined is less than the sum of these areas of these rectangles then merge these distinctMaterialTextures
                        if (accumulatedAreaCombined < accumulatedAreaNotCombined)
                        {
                            // merge tx2 into tx1
                            numMerged++;
                            StringBuilder sb = null;

                            sb = new StringBuilder();
                            sb.AppendFormat("About To Merge:\n   TextureSet1 {0}\n   TextureSet2 {1}\n", tx1.GetDescription(), tx2.GetDescription());

                            for (int matIdx = 0; matIdx < tx1.matsAndGOs.mats.Count; matIdx++)
                            {
                                sb.AppendFormat("tx1 Mat {0} matAndMeshUVRect {1} fullSamplingRect {2}\n",
                                                tx1.matsAndGOs.mats[matIdx].mat, tx1.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling, tx1.ts[0].GetEncapsulatingSamplingRect());
                            }
                            for (int matIdx = 0; matIdx < tx2.matsAndGOs.mats.Count; matIdx++)
                            {
                                sb.AppendFormat("tx2 Mat {0} matAndMeshUVRect {1} fullSamplingRect {2}\n",
                                                tx2.matsAndGOs.mats[matIdx].mat, tx2.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling, tx2.ts[0].GetEncapsulatingSamplingRect());
                            }

                            //copy game objects over
                            for (int k = 0; k < tx2.matsAndGOs.gos.Count; k++)
                            {
                                if (!tx1.matsAndGOs.gos.Contains(tx2.matsAndGOs.gos[k]))
                                {
                                    tx1.matsAndGOs.gos.Add(tx2.matsAndGOs.gos[k]);
                                }
                            }

                            //copy materials over from tx2 to tx1
                            for (int matIdx = 0; matIdx < tx2.matsAndGOs.mats.Count; matIdx++)
                            {
                                tx1.matsAndGOs.mats.Add(tx2.matsAndGOs.mats[matIdx]);
                            }

                            tx1.SetEncapsulatingSamplingRectWhenMergingTexSets(encapsulatingRectMerged);
                            if (!MarkedForDeletion.Contains(i))
                            {
                                MarkedForDeletion.Add(i);
                            }

                            sb.AppendFormat("=== After Merge TextureSet {0}\n", tx1.GetDescription());
                            for (int matIdx = 0; matIdx < tx1.matsAndGOs.mats.Count; matIdx++)
                            {
                                sb.AppendFormat("tx1 Mat {0} matAndMeshUVRect {1} fullSamplingRect {2}\n",
                                                tx1.matsAndGOs.mats[matIdx].mat, tx1.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling, tx1.ts[0].GetEncapsulatingSamplingRect());
                            }
                            //Integrity check that sampling rects fit into enapsulating rects
                            if (MeshBakerRoot.DO_INTEGRITY_CHECKS)
                            {
                                if (MeshBakerRoot.DO_INTEGRITY_CHECKS)
                                {
                                    DoIntegrityCheckMergedEncapsulatingSamplingRects(distinctMaterialTextures);
                                }
                            }

                            Debug.Log(sb.ToString());

                            break;


                            Debug.Log(string.Format("Considered merging {0} and {1} but there was not enough overlap. It is more efficient to bake these to separate rectangles.", tx1.GetDescription(), tx2.GetDescription()));
                        }
                    }
                }
                //remove distinctMaterialTextures that were merged
                for (int j = MarkedForDeletion.Count - 1; j >= 0; j--)
                {
                    distinctMaterialTextures.RemoveAt(MarkedForDeletion[j]);
                }
                MarkedForDeletion.Clear();

                Debug.Log(string.Format("MergeOverlappingDistinctMaterialTexturesAndCalcMaterialSubrects complete merged {0} now have {1}", numMerged, distinctMaterialTextures.Count));

                if (MeshBakerRoot.DO_INTEGRITY_CHECKS)
                {
                    DoIntegrityCheckMergedEncapsulatingSamplingRects(distinctMaterialTextures);
                }
            }
        }