예제 #1
0
 public void DoIntegrityCheckMergedEncapsulatingSamplingRects(List <MB_TexSet> distinctMaterialTextures)
 {
     if (MB3_MeshBakerRoot.DO_INTEGRITY_CHECKS)
     {
         for (int i = 0; i < distinctMaterialTextures.Count; i++)
         {
             MB_TexSet tx1 = distinctMaterialTextures[i];
             if (!tx1.allTexturesUseSameMatTiling)
             {
                 continue;
             }
             for (int matIdx = 0; matIdx < tx1.matsAndGOs.mats.Count; matIdx++)
             {
                 MatAndTransformToMerged mat = tx1.matsAndGOs.mats[matIdx];
                 DRect uvR  = mat.obUVRectIfTilingSame;
                 DRect matR = mat.materialTiling;
                 if (!MB2_TextureBakeResults.IsMeshAndMaterialRectEnclosedByAtlasRect(tx1.tilingTreatment, uvR.GetRect(), matR.GetRect(), tx1.ts[0].GetEncapsulatingSamplingRect().GetRect(), MB2_LogLevel.info))
                 {
                     Debug.LogErrorFormat("mesh " + tx1.matsAndGOs.mats[matIdx].objName + "\n" +
                                          " uv=" + uvR + "\n" +
                                          " mat=" + matR.GetRect().ToString("f5") + "\n" +
                                          " samplingRect=" + tx1.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling.GetRect().ToString("f4") + "\n" +
                                          " encapsulatingRect " + tx1.ts[0].GetEncapsulatingSamplingRect().GetRect().ToString("f4") + "\n");
                     Debug.LogErrorFormat(string.Format("Integrity check failed. " + tx1.matsAndGOs.mats[matIdx].objName + " Encapsulating sampling rect failed to contain potentialRect\n"));
                     MB2_TextureBakeResults.IsMeshAndMaterialRectEnclosedByAtlasRect(tx1.tilingTreatment, uvR.GetRect(), matR.GetRect(), tx1.ts[0].GetEncapsulatingSamplingRect().GetRect(), MB2_LogLevel.trace);
                     Debug.Assert(false);
                 }
             }
         }
     }
 }
            /// <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.
            /// </summary>
            public bool TryMapMaterialToUVRect(Material mat, Mesh m, int submeshIdx, int idxInResultMats,
                                               MB3_MeshCombinerSingle.MeshChannelsCache meshChannelCache,
                                               Dictionary <int, MB_Utility.MeshAnalysisResult[]> meshAnalysisCache,
                                               out MB_TextureTilingTreatment tilingTreatment,
                                               out Rect rectInAtlas,
                                               out Rect encapsulatingRectOut,
                                               out Rect sourceMaterialTilingOut,
                                               out int sliceIdx,
                                               ref String errorMsg,
                                               MB2_LogLevel logLevel)
            {
                if (textureBakeResults.version < MB2_TextureBakeResults.VERSION)
                {
                    textureBakeResults.UpgradeToCurrentVersion(textureBakeResults);
                }
                tilingTreatment = MB_TextureTilingTreatment.unknown;
                if (textureBakeResults.materialsAndUVRects.Length == 0)
                {
                    errorMsg                = "The 'Texture Bake Result' needs to be re-baked to be compatible with this version of Mesh Baker. Please re-bake using the MB3_TextureBaker.";
                    rectInAtlas             = new Rect();
                    encapsulatingRectOut    = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    sliceIdx                = -1;
                    return(false);
                }
                if (mat == null)
                {
                    rectInAtlas             = new Rect();
                    encapsulatingRectOut    = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    sliceIdx = -1;
                    errorMsg = String.Format("Mesh {0} Had no material on submesh {1} cannot map to a material in the atlas", m.name, submeshIdx);
                    return(false);
                }
                if (submeshIdx >= m.subMeshCount)
                {
                    errorMsg                = "Submesh index is greater than the number of submeshes";
                    rectInAtlas             = new Rect();
                    encapsulatingRectOut    = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    sliceIdx                = -1;
                    return(false);
                }

                //find the first index of this material
                int idx = -1;

                for (int i = 0; i < matsAndSrcUVRect.Length; i++)
                {
                    if (mat == matsAndSrcUVRect[i].material)
                    {
                        idx = i;
                        break;
                    }
                }
                // if couldn't find material
                if (idx == -1)
                {
                    rectInAtlas             = new Rect();
                    encapsulatingRectOut    = new Rect();
                    sourceMaterialTilingOut = new Rect();
                    sliceIdx = -1;
                    errorMsg = String.Format("Material {0} could not be found in the Texture Bake Result", mat.name);
                    return(false);
                }

                bool considerUVs = textureBakeResults.GetConsiderMeshUVs(idxInResultMats, mat);

                if (!considerUVs)
                {
                    if (numTimesMatAppearsInAtlas[idx] != 1)
                    {
                        Debug.LogError("There is a problem with this TextureBakeResults. FixOutOfBoundsUVs is false and a material appears more than once: " + matsAndSrcUVRect[idx].material + " appears: " + numTimesMatAppearsInAtlas[idx]);
                    }
                    MB_MaterialAndUVRect mr = matsAndSrcUVRect[idx];
                    rectInAtlas             = mr.atlasRect;
                    tilingTreatment         = mr.tilingTreatment;
                    encapsulatingRectOut    = mr.GetEncapsulatingRect();
                    sourceMaterialTilingOut = mr.GetMaterialTilingRect();
                    sliceIdx = mr.textureArraySliceIdx;
                    return(true);
                }
                else
                {
                    //todo what if no UVs
                    //Find UV rect in source mesh
                    MB_Utility.MeshAnalysisResult[] mar;
                    if (!meshAnalysisCache.TryGetValue(m.GetInstanceID(), out mar))
                    {
                        mar = new MB_Utility.MeshAnalysisResult[m.subMeshCount];
                        for (int j = 0; j < m.subMeshCount; j++)
                        {
                            Vector2[] uvss = meshChannelCache.GetUv0Raw(m);
                            MB_Utility.hasOutOfBoundsUVs(uvss, m, ref mar[j], j);
                        }
                        meshAnalysisCache.Add(m.GetInstanceID(), mar);
                    }

                    //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
                    bool found                = false;
                    Rect encapsulatingRect    = new Rect(0, 0, 0, 0);
                    Rect sourceMaterialTiling = new Rect(0, 0, 0, 0);
                    if (logLevel >= MB2_LogLevel.trace)
                    {
                        Debug.Log(String.Format("Trying to find a rectangle in atlas capable of holding tiled sampling rect for mesh {0} using material {1} meshUVrect={2}", m, mat, mar[submeshIdx].uvRect.ToString("f5")));
                    }
                    for (int i = idx; i < matsAndSrcUVRect.Length; i++)
                    {
                        MB_MaterialAndUVRect matAndUVrect = matsAndSrcUVRect[i];
                        if (matAndUVrect.material == mat)
                        {
                            if (matAndUVrect.allPropsUseSameTiling)
                            {
                                encapsulatingRect    = matAndUVrect.allPropsUseSameTiling_samplingEncapsulatinRect;
                                sourceMaterialTiling = matAndUVrect.allPropsUseSameTiling_sourceMaterialTiling;
                            }
                            else
                            {
                                encapsulatingRect    = matAndUVrect.propsUseDifferntTiling_srcUVsamplingRect;
                                sourceMaterialTiling = new Rect(0, 0, 1, 1);
                            }

                            if (MB2_TextureBakeResults.IsMeshAndMaterialRectEnclosedByAtlasRect(
                                    matAndUVrect.tilingTreatment,
                                    mar[submeshIdx].uvRect,
                                    sourceMaterialTiling,
                                    encapsulatingRect,
                                    logLevel))
                            {
                                if (logLevel >= MB2_LogLevel.trace)
                                {
                                    Debug.Log("Found rect in atlas capable of containing tiled sampling rect for mesh " + m + " at idx=" + i);
                                }
                                idx   = i;
                                found = true;
                                break;
                            }
                        }
                    }
                    if (found)
                    {
                        MB_MaterialAndUVRect mr = matsAndSrcUVRect[idx];
                        rectInAtlas             = mr.atlasRect;
                        tilingTreatment         = mr.tilingTreatment;
                        encapsulatingRectOut    = mr.GetEncapsulatingRect();
                        sourceMaterialTilingOut = mr.GetMaterialTilingRect();
                        sliceIdx = mr.textureArraySliceIdx;
                        return(true);
                    }
                    else
                    {
                        rectInAtlas             = new Rect();
                        encapsulatingRectOut    = new Rect();
                        sourceMaterialTilingOut = new Rect();
                        sliceIdx = -1;
                        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?", m.name, mat);
                        return(false);
                    }
                }
            }