| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860 | /************************************************************************* *  Copyright © 2018-2023 Liwen All rights reserved. *------------------------------------------------------------------------ *  File         :  PagedLod.cs *  Description  :  update lod with cameradistance *------------------------------------------------------------------------ *  Author       :  Liwen *  Version      :  1.0.0 *  Date         :  1/5/2019 *  Description  :  Initial development version. *************************************************************************/using System.Collections;using System.Collections.Generic;using UnityEngine;using System.IO;using System.Runtime.InteropServices;using System;using System.Text;using System.Text.RegularExpressions;using LitJson;namespace AIPagedLod{    [System.Serializable]    public class PagedLodInfo    {        public string mFileName = string.Empty;        public PagedLod mPagedLod = null;        public bool mIsBasicInfoLoaded = false;        public bool mIsDownloaded = false;        public PagedLodRangeInfo mRangeValue = new PagedLodRangeInfo();    }    public class PagedLodLoaderInfo    {        public int mIndex = 0;        public PagedLodFileLoader mLoader = null;    }    [System.Serializable]    public class B3dmBasicInfo    {        public Vector3 mCenter;        public Vector3 mExtents;        public float mGeometricError;        public string mContent;        public Bounds mBounds;        public List<B3dmBasicInfo> mChildrenList = new List<B3dmBasicInfo>();    }    public class PagedLod : MonoBehaviour    {        public List<PagedLodInfo> mChildTileList = new List<PagedLodInfo>();        //初始化加载时赋值        public int mSelfLevel = 0;        public bool mIsRootTile = false;        public string mTileDirPath;        //osgb文件属性        public float mPixelValue;        public float mLoadChildPixelValue;        //固有基本属性        public float mOsgbBoundRadius; //缩放变化后需要重新求取,osgb库中求得,暂时不用        public Bounds mOsgbBounds;        //根据固有属性计算        public Vector3 mWorldCenter = Vector3.zero; //相对于父节点的局部中心坐标,仅在根节点中使用,位置变化后需要重新求取        public List<Vector3> mBoundsVertexList = new List<Vector3>();//位置及缩放变化后需要重新求取        public List<MeshRenderer> mMeshRenderers = new List<MeshRenderer>(); //根节点拥有,用于计算瓦片是否可见        public GameObject mRenderNode = null;        public bool mIsRenderNodeLoaded = false;        public bool mIsRenderNodeMeshLoaded = false;//Mesh网格节点是否加载        //每帧计算        public bool mIsVisiable = true;        private int mVisiableFrameNumber = 0;        private int mInRangeFrameNumber = 0;        private LoadPagedLodFromFileManager mManager = null;        private Camera mMainCamera = null;        //b3dm专有        public PagedLod mRootPagedLod = null;        public Dictionary<string, B3dmBasicInfo> mBasicInfoDict = new Dictionary<string, B3dmBasicInfo>();//根节点拥有        public List<B3dmBasicInfo> mBasicInfoList = new List<B3dmBasicInfo>();//根节点拥有        public B3dmBasicInfo mBasicInfo = new B3dmBasicInfo();        public float mScreenSpaceError = 0.0f;        public static int mMaxLoadLevel = 0;        private LoadPagedLodFromFileManager GetLodManager()        {            if (mManager == null)            {                mManager = transform.GetComponentInParent<LoadPagedLodFromFileManager>();            }            return mManager;        }        string GetDataPath()        {            return GetLodManager().GetDataPath() + "\\" + mTileDirPath;        }        public void InitBasicInfoDictFromList()        {            if (mBasicInfoDict.Count == 0)            {                for (int i = 0; i < mBasicInfoList.Count; ++i)                {                    mBasicInfoDict.Add(mBasicInfoList[i].mContent, mBasicInfoList[i]);                }            }        }        void ResetLod()        {            mChildTileList.Clear();            mMeshRenderers.Clear();            mVisiableFrameNumber = 0;            mInRangeFrameNumber = 0;            mSelfLevel = 0;            mManager = null;            mRootPagedLod = null;            mBasicInfoDict.Clear();            mIsRenderNodeLoaded = false;            mIsRenderNodeMeshLoaded = false;        }        #region UpdateTileVisiableStatus-----------------------        void UpdateTileVisiableStatus()        {            mIsVisiable = true;            if (mIsRootTile)            {                GetTileVisiableStatus();            }        }        void GetTileVisiableStatus()        {            if (mMeshRenderers.Count == 0)            {                mIsVisiable = true;                return;            }            if (mMainCamera == null) mMainCamera = Camera.main;            Plane[] planes = GeometryUtility.CalculateFrustumPlanes(mMainCamera);            for (int i = 0; i < mMeshRenderers.Count; ++i)            {                if (GeometryUtility.TestPlanesAABB(planes, mMeshRenderers[i].bounds))                {                    mIsVisiable = true;                    return;                }            }            mIsVisiable = false;        }        void UpdateInvisiableTiles()        {            if (!mRenderNode.activeSelf)                mRenderNode.SetActive(true);            if (!mIsRenderNodeLoaded)            {                LoadTileRenderNode();            }            if (Time.frameCount - mVisiableFrameNumber > PagedLodConfig.mInstance.mExpiryFrames)            {                if (mChildTileList.Count != 0 && mChildTileList[0].mPagedLod != null)                {                    CollectChildTiles();                }            }            else            {                if (mChildTileList.Count != 0 && mChildTileList[0].mPagedLod != null && mChildTileList[0].mPagedLod.gameObject.activeSelf)                {                    SetChildTilesActive(false);                }            }        }        #endregion UpdateTileVisiableStatus        #region CollectChildTiles-----------------------------        public void CollectChildTiles()        {            for (int i = 0; i < mChildTileList.Count; ++i)            {                PagedLod childLod = mChildTileList[i].mPagedLod;                if (childLod != null)                {                    PagedLod[] childPagedlods = childLod.transform.GetComponentsInChildren<PagedLod>(true);                    for (int j = 0; j < childPagedlods.Length; ++j)                    {#if UNITY_WEBGL                         GameObject.Destroy(childPagedlods[j].gameObject);                        PagedLodConfig.mInstance.mCollectCount++;#else                        childPagedlods[j].ResetLod();                        MeshRenderer[] renderers = childPagedlods[j].gameObject.GetComponentsInChildren<MeshRenderer>(true);                        for (int m = 0; m < renderers.Length; ++m)                        {                            MeshPool.mInstance.PushMeshObject(renderers[m].gameObject);                        }                        TileObjectPool.mInstance.PushTileObject(childPagedlods[j].gameObject);#endif                    }                }                mChildTileList[i].mPagedLod = null;                mChildTileList[i].mIsBasicInfoLoaded = false;#if UNITY_WEBGL                if (PagedLodConfig.mInstance.mCollectCount >= 100)                {                    StartCoroutine(DestoryTiles());                    PagedLodConfig.mInstance.mCollectCount = 0;                    //Debug.Log("-------------------UnloadUnusedAssets");                }#endif            }        }        IEnumerator DestoryTiles()        {            yield return new WaitForSeconds(0.1f);            Resources.UnloadUnusedAssets();//卸载未占用的asset资源            System.GC.Collect();//回收内存        }        #endregion        public bool UpdatePagedLod()        {            mMaxLoadLevel = (int)MathF.Max(mMaxLoadLevel,mSelfLevel);            //RecaculateBounds();            UpdateTileVisiableStatus();            if (!mIsVisiable) //不可见,则回收瓦片            {                UpdateInvisiableTiles();                return false;            }            else            {                mVisiableFrameNumber = Time.frameCount;                bool isLoadChildTile = false;                if (PagedLodConfig.mInstance.mTileDataType == TileDataType.OSGB)                {                    mPixelValue = GetPixelValue();//瓦片所占像素大小                    isLoadChildTile = mPixelValue > mLoadChildPixelValue;                }                else                {                    mScreenSpaceError = GetScreenSpaceError();                    isLoadChildTile = mScreenSpaceError > PagedLodConfig.mInstance.mMaxSSE;                }                if (isLoadChildTile)                {#if UNITY_WEBGL || UNITY_ANDROID                    LoadChildTilePagedLodFromUrl();#else                    if (PagedLodConfig.mInstance.mIsLoadFromUrl)                        LoadChildTilePagedLodFromUrl();                    else                        LoadChildTilePagedLod();#endif                    if (mRenderNode != null )                    {                        if (mRenderNode.activeSelf)                        {                            if(IsChildTilesLoaded())                            {                                mRenderNode.SetActive(false);                            }                        }                        //else                        //{                        //    mRenderNode.SetActive(true);                        //}                    }                    return true;                }                else //回收子瓦片                {                    UpdateCollectChildTiles();                    return false;                }            }        }#region LoadB3dmFile--------------------------------------        void LoadSelfRenderNodeFromUrl()        {            if (DownloadFileManager.mInstance.CanDownload())            {                mIsRenderNodeLoaded = true;                DownloadFileManager.mInstance.StartDownloadTileFile(this,GetLodManager().mConfig.mBaseUrl);            }        }        void LoadChildTilePagedLodFromUrl()        {            if (!DownloadFileManager.mInstance.CanDownload()) return;            for (int i = 0; i < mChildTileList.Count; ++i)            {                if (mChildTileList[i].mPagedLod != null)                {                    mChildTileList[i].mPagedLod.gameObject.SetActive(true);                }                else                {                    if (!mChildTileList[i].mIsBasicInfoLoaded)                    {                        PagedLodInfo pagedLodInfo = mChildTileList[i];                        B3dmFileLoader pagedLodLoader = new B3dmFileLoader();                        pagedLodLoader.mTileName = pagedLodInfo.mFileName.Replace(PagedLodConfig.mInstance.GetFileSufix(), "");                        pagedLodInfo.mIsBasicInfoLoaded = true;                        LoadTilePagedLod(pagedLodInfo, pagedLodLoader);                        break;                    }                }            }        }#endregion LoadB3dmFile#region LoadSelfRenderNode--------------------------------------        void UpdateCollectChildTiles()        {            if (!mIsRenderNodeLoaded)            {                LoadTileRenderNode();            }            else            {                if (mRenderNode != null && !mRenderNode.activeSelf)                {                    mRenderNode.SetActive(true);                }            }            //if (mIsRenderNodeLoaded && mRenderNode != null && mRenderNode.activeSelf)            if (mIsRenderNodeMeshLoaded)            {                if (Time.frameCount - mInRangeFrameNumber > PagedLodConfig.mInstance.mExpiryFrames)                {                    CollectChildTiles();                }                else                {                    SetChildTilesActive(false);                }            }        }        void LoadTileRenderNode()        {#if UNITY_WEBGL || UNITY_ANDROID            LoadSelfRenderNodeFromUrl();#else            if (PagedLodConfig.mInstance.mIsLoadFromUrl)                LoadSelfRenderNodeFromUrl();            else                LoadSelfRenderNode();#endif        }        PagedLodFileLoader GetSelfRenderNodeLoader()        {            PagedLodFileLoader pagedLodLoader = null;            string fileFullPath = GetDataPath() + "/" + gameObject.name + PagedLodConfig.mInstance.GetFileSufix();            fileFullPath = System.Text.RegularExpressions.Regex.Replace(fileFullPath, @"\p{C}+", "");            if (File.Exists(fileFullPath))            {                pagedLodLoader = PagedLodFileLoader.GetFileLoader(fileFullPath);                pagedLodLoader.mIsDaJiangData = GetLodManager().mConfig.mIsDaJiangData;            }            return pagedLodLoader;        }        void LoadSelfRenderNode()        {            if (!PagedLodThreadPool.IsQueueWorkItem()) return;            PagedLodFileLoader pagedLodLoader = GetSelfRenderNodeLoader();            if (pagedLodLoader == null) return;            mIsRenderNodeLoaded = true;            PagedLod targetPagedLod = this;            PagedLodThreadPool.RunAsync(() =>            {                pagedLodLoader.LoadObjectMeshInfo();                PagedLodThreadPool.QueueOnMainThread(() =>                {                    if (GetLodManager() != null)                    {                        if (targetPagedLod != null)                        {                            LoadTileAsyncManager.mInstance.StartLoadRenderNode(targetPagedLod, pagedLodLoader);                        }                        else                        {                            Debug.Log("targetPagedLod is null ************* ");                        }                    }                    else                    {                        pagedLodLoader.Dispose();                        pagedLodLoader = null;                    }                });            });        }#endregion#region LoadChildTilePagedLod------------------------------------        List<PagedLodLoaderInfo> GetNeedLoadChildTile()        {            List<PagedLodLoaderInfo> loaderList = new List<PagedLodLoaderInfo>();            for (int i = 0; i < mChildTileList.Count; ++i)            {                if (mChildTileList[i].mPagedLod != null)                {                    mChildTileList[i].mPagedLod.gameObject.SetActive(true);                }                else                {                    if (!mChildTileList[i].mIsBasicInfoLoaded)                    {                        PagedLodInfo pagedLodInfo = mChildTileList[i];                        string fileFullPath = GetDataPath() + "/" + mChildTileList[i].mFileName;                        fileFullPath = System.Text.RegularExpressions.Regex.Replace(fileFullPath, @"\p{C}+", "");                        if (File.Exists(fileFullPath))                        {                            PagedLodLoaderInfo info = new PagedLodLoaderInfo();                            PagedLodFileLoader pagedLodLoader = PagedLodFileLoader.GetFileLoader(fileFullPath);                            pagedLodLoader.mIsDaJiangData = GetLodManager().mConfig.mIsDaJiangData;                            FileInfo fileInfo = new FileInfo(pagedLodLoader.mFileName);                            pagedLodLoader.mTileName = fileInfo.Name.Replace(PagedLodConfig.mInstance.GetFileSufix(), "");                            pagedLodInfo.mIsBasicInfoLoaded = true;                            info.mLoader = pagedLodLoader;                            info.mIndex = i;                            loaderList.Add(info);                        }                    }                }            }            return loaderList;        }        void LoadChildTilePagedLod()        {            if (!PagedLodThreadPool.IsQueueWorkItem()) return;            List<PagedLodLoaderInfo> loaderList = GetNeedLoadChildTile();            PagedLod targetPagedLod = this;            PagedLodThreadPool.RunAsync(() =>            {                for (int i = 0; i < loaderList.Count; ++i)                {                    if (loaderList[i].mLoader != null)                    {                        loaderList[i].mLoader.LoadObjectBasicInfo();                    }                }                PagedLodThreadPool.QueueOnMainThread(() =>                {                    if (GetLodManager() != null && targetPagedLod != null)                    {                        for (int i = 0; i < loaderList.Count; ++i)                        {                            if (loaderList[i].mLoader != null)                            {                                LoadTileAsyncManager.mInstance.StartLoadChildTile(targetPagedLod,                                loaderList[i].mLoader, mChildTileList[loaderList[i].mIndex]);                            }                        }                    }                    else                    {                        for (int i = 0; i < loaderList.Count; ++i)                        {                            if (loaderList[i].mLoader != null)                            {                                loaderList[i].mLoader.Dispose();                                loaderList[i].mLoader = null;                            }                        }                    }                });            });        }        #endregion        //运行时调用        public void LoadTilePagedLod(PagedLodInfo info, PagedLodFileLoader pagedLodLoader)        {            GameObject tileObj = TileObjectPool.mInstance.GetTileObject();            PagedLod pagedLod = null;            if (tileObj == null)            {                tileObj = new GameObject();                pagedLod = tileObj.AddComponent<PagedLod>();            }            else            {                tileObj.SetActive(true);                pagedLod = tileObj.GetComponent<PagedLod>();            }            info.mPagedLod = pagedLod;            tileObj.name = pagedLodLoader.mTileName;            tileObj.transform.SetParent(transform);            tileObj.transform.localPosition = Vector3.zero;            tileObj.transform.localRotation = Quaternion.identity;            tileObj.transform.localScale = Vector3.one;            pagedLod.mSelfLevel = mSelfLevel + 1;            pagedLod.mTileDirPath = mTileDirPath;            if(mIsRootTile)            {                pagedLod.mRootPagedLod = this;            }            else            {                pagedLod.mRootPagedLod = mRootPagedLod;            }            if(PagedLodConfig.mInstance.mTileDataType == TileDataType.OSGB)            {                pagedLod.LoadOsgbBasicInfo(pagedLodLoader);            }            else            {                pagedLod.mBasicInfo = pagedLod.mRootPagedLod.GetTileBasicInfo(tileObj.name);                pagedLod.LoadB3dmBasicInfo(pagedLodLoader);            }        }        public void LoadOsgbBasicInfo(PagedLodFileLoader pagedLodLoader)        {            OsgbFileLoader osgbFileLoader = pagedLodLoader as OsgbFileLoader;            Vector3 center = GetLodManager().transform.TransformPoint(osgbFileLoader.mBoundsCenter);            Vector3 min = GetLodManager().transform.TransformPoint(osgbFileLoader.mBoundsBoxMin);            Vector3 max = GetLodManager().transform.TransformPoint(osgbFileLoader.mBoundsBoxMax);            mOsgbBoundRadius = osgbFileLoader.mBoundRadius;            mOsgbBounds.min = min;            mOsgbBounds.max = max;            //mWorldCenter = new Vector3(center.x, -center.y, center.z);            mWorldCenter = new Vector3(center.x, -center.z, -center.y);            InitOsgbChildFiles(this, pagedLodLoader);            GetBoundsVertexList();        }        public void LoadB3dmBasicInfo(PagedLodFileLoader pagedLodLoader)        {            mOsgbBounds = mBasicInfo.mBounds;            mWorldCenter = GetLodManager().transform.TransformPoint(mOsgbBounds.center);            mOsgbBoundRadius = mOsgbBounds.extents.magnitude;            InitB3dmChildFiles(this, pagedLodLoader);            GetBoundsVertexList();        }        public void RecaculateBounds()        {            Vector3 center = Vector3.zero;            if (mMeshRenderers.Count != 0)            {                Bounds bounds = new Bounds(center, Vector3.zero);                foreach (Renderer mr in mMeshRenderers)                {                    if (bounds.size == Vector3.zero)                    {                        bounds = mr.bounds;                    }                    else                    {                        bounds.Encapsulate(mr.bounds);                    }                }                mOsgbBounds = bounds;                mOsgbBoundRadius = Vector3.Distance(bounds.center, bounds.max);                mWorldCenter = bounds.center;                GetBoundsVertexList();            }        }        private void InitOsgbChildFiles(PagedLod pagedLod, PagedLodFileLoader pagedLodLoader)        {            OsgbFileLoader osgbFileLoader = pagedLodLoader as OsgbFileLoader;            pagedLod.mChildTileList.Clear();            float minPixelValue = float.MaxValue;            for (int i = 0; i < osgbFileLoader.mChildFiles.Count; ++i)            {                PagedLodInfo info = new PagedLodInfo();                string fileFullPath = pagedLod.GetDataPath() + "\\" + osgbFileLoader.mChildFiles[i];                fileFullPath = System.Text.RegularExpressions.Regex.Replace(fileFullPath, @"\p{C}+", "");                info.mFileName = osgbFileLoader.mChildFiles[i];                info.mRangeValue = osgbFileLoader.mChildRangeValues[i];                pagedLod.mChildTileList.Add(info);                minPixelValue = Mathf.Min(minPixelValue, info.mRangeValue.mChildMinValue);            }            pagedLod.mLoadChildPixelValue = minPixelValue;        }        private void InitB3dmChildFiles(PagedLod pagedLod, PagedLodFileLoader pagedLodLoader)        {            pagedLod.mChildTileList.Clear();            for (int i = 0; i < pagedLod.mBasicInfo.mChildrenList.Count; ++i)            {                B3dmBasicInfo childBasicInfo = pagedLod.mBasicInfo.mChildrenList[i];                PagedLodInfo info = new PagedLodInfo();                info.mFileName = childBasicInfo.mContent + PagedLodConfig.mInstance.GetFileSufix();                pagedLod.mChildTileList.Add(info);            }        }        public void LoadRenderNode(PagedLodFileLoader pagedLodLoader)        {            if (mRenderNode == null)            {                mRenderNode = new GameObject("RenderNode");                mRenderNode.transform.SetParent(transform);                mRenderNode.transform.localPosition = Vector3.zero;                mRenderNode.transform.localRotation = Quaternion.identity;                mRenderNode.transform.localScale = Vector3.one;            }            else            {                mRenderNode.SetActive(true);            }            pagedLodLoader.BuildObjectForThread(mRenderNode);            transform.localScale = Vector3.one;            mIsRenderNodeMeshLoaded = true;            GetMeshRenders();            RecaculateBounds();        }            public void GetMeshRenders()        {            mMeshRenderers = new List<MeshRenderer>(gameObject.GetComponentsInChildren<MeshRenderer>());        }        public void GetBoundsVertexList()        {            Vector3 center = mWorldCenter;            var targetBoundsExtents = mOsgbBounds.extents; //得到目标物包围盒范围:extents            List<Vector3> vertexList = new List<Vector3>();            float x = targetBoundsExtents.x;            float y = targetBoundsExtents.y;            float z = targetBoundsExtents.z;            vertexList.Add(center);            vertexList.Add(center + new Vector3(x, y, z));            vertexList.Add(center + new Vector3(x, -y, z));            vertexList.Add(center + new Vector3(x, y, -z));            vertexList.Add(center + new Vector3(x, -y, -z));            vertexList.Add(center + new Vector3(-x, y, z));            vertexList.Add(center + new Vector3(-x, -y, z));            vertexList.Add(center + new Vector3(-x, y, -z));            vertexList.Add(center + new Vector3(-x, -y, -z));            mBoundsVertexList = vertexList;        }        public bool IsChildTilesLoaded()        {            if (mIsVisiable)            {                for (int i = 0; i < mChildTileList.Count; ++i)                {                    if (mChildTileList[i].mPagedLod != null)                    {                        if (!mChildTileList[i].mPagedLod.gameObject.activeSelf) return false;                        bool flag = mChildTileList[i].mPagedLod.IsRenderNodeLoaded();                        if (!flag)                        {                            return false;                        }                    }                    else                    {                        return false;                    }                }            }            return true;        }        public bool IsRenderNodeLoaded()        {            bool isLoadChildTile = false;            if (PagedLodConfig.mInstance.mTileDataType == TileDataType.OSGB)            {                mPixelValue = GetPixelValue();//瓦片所占像素大小                isLoadChildTile = mPixelValue > mLoadChildPixelValue;            }            else            {                mScreenSpaceError = GetScreenSpaceError();                isLoadChildTile = mScreenSpaceError > PagedLodConfig.mInstance.mMaxSSE;            }            if (isLoadChildTile)            {                return IsChildTilesLoaded();            }            else            {                return mIsRenderNodeMeshLoaded;                //return mIsRenderNodeLoaded && mRenderNode != null && mRenderNode.activeSelf;            }        }        void SetChildTilesActive(bool flag)        {            for (int i = 0; i < mChildTileList.Count; ++i)            {                PagedLod childTile = mChildTileList[i].mPagedLod;                if (childTile != null && childTile.gameObject.activeSelf != flag)                {                    childTile.gameObject.SetActive(flag);                }            }        }        float GetMinCameraDistance()        {            if (mMainCamera == null) mMainCamera = Camera.main;            float distance = float.MaxValue;            for (int i = 0; i < mBoundsVertexList.Count; ++i)            {                float d = Vector3.Distance(mMainCamera.transform.position, mBoundsVertexList[i]);                distance = Mathf.Min(distance, d);            }            return distance;        }        public float mDistance = 0.0f;        float GetPixelValue()        {            if (mWorldCenter == Vector3.zero) return float.MinValue;            Vector3 center = mWorldCenter;            if (mMainCamera == null)            {                mMainCamera = Camera.main;            }            float distance = GetMinCameraDistance();            mDistance = distance;            float slope = Mathf.Tan(mMainCamera.fieldOfView * Mathf.Deg2Rad * 0.5f);            int pixelHeight = 1300;/*mMainCamera.pixelHeight*/;            float projFactor = (0.5f * pixelHeight) / (slope * distance);            float pixelValue = mOsgbBoundRadius * projFactor;            return pixelValue;        }        public bool IsMaxLevelTile()//最高级没有子节点        {            if (mRenderNode != null)            {                return mChildTileList.Count == 0;            }            return false;        }#region B3DM file Load-------------------------        float GetScreenSpaceError()        {            if (mWorldCenter == Vector3.zero) return float.MinValue;            Vector3 center = mWorldCenter;            if (mMainCamera == null)            {                mMainCamera = Camera.main;            }            float distance = Vector3.Distance(mMainCamera.transform.position, mWorldCenter); //GetMinCameraDistance();            mDistance = distance;            float slope = Mathf.Tan(mMainCamera.fieldOfView * Mathf.Deg2Rad * 0.5f);            int pixelHeight = 1300;/*mMainCamera.pixelHeight*/;            float es = (mBasicInfo.mGeometricError * pixelHeight) / (distance * 2.0f * slope);            return es;        }        //根节点调用,加载瓦片结构组织        public void LoadTileSetJsonFile()        {            if (mBasicInfoDict.Count == 0)            {                string tileSetJsonPath = GetDataPath() + "/tileset.json";                string jsonText = System.IO.File.ReadAllText(tileSetJsonPath);                B3dmBasicInfo rootTileInfo = null;                mBasicInfoDict = LoadTileSetJsonText(jsonText, ref rootTileInfo);                mBasicInfoList = new List<B3dmBasicInfo>(mBasicInfoDict.Values);                //mBasicInfo = rootTileInfo;                mBasicInfo = GetTileBasicInfo(gameObject.name);            }        }        public static Dictionary<string, B3dmBasicInfo> LoadTileSetJsonText(string jsonText,ref B3dmBasicInfo rootTileInfo)        {            JsonData resultJson = JsonMapper.ToObject(jsonText);            JsonData root = resultJson["root"];            Dictionary<string, B3dmBasicInfo> basicInfoDict = new Dictionary<string, B3dmBasicInfo>();            TraverseLoadTileBasicInfo(root, ref basicInfoDict,ref rootTileInfo);            return basicInfoDict;        }        static void TraverseLoadTileBasicInfo(JsonData tileJson, ref Dictionary<string, B3dmBasicInfo> basicInfoDict, ref B3dmBasicInfo rootTileInfo)        {            B3dmBasicInfo info = LoadTileBasicInfo(tileJson);            if(rootTileInfo == null)            {                rootTileInfo = info;            }            if (tileJson.Keys.Contains("children"))            {                JsonData children = tileJson["children"];                for (int i = 0; i < children.Count; ++i)                {                    B3dmBasicInfo childInfo = LoadTileBasicInfo(children[i]);                    info.mChildrenList.Add(childInfo);                    TraverseLoadTileBasicInfo(children[i], ref basicInfoDict,ref rootTileInfo);                }            }            basicInfoDict.Add(info.mContent, info);        }        public static B3dmBasicInfo LoadTileBasicInfo(JsonData tileJson)        {            JsonData boundingVolume = tileJson["boundingVolume"];            JsonData box = boundingVolume["box"];            float centerX = float.Parse(box[0].ToString());            float centerY = float.Parse(box[1].ToString());            float centerZ = float.Parse(box[2].ToString());            float extentX = float.Parse(box[3].ToString());            float extentY = float.Parse(box[7].ToString());            float extentZ = float.Parse(box[11].ToString());            B3dmBasicInfo info = new B3dmBasicInfo();            info.mCenter = new Vector3(centerX, centerZ, centerY);            info.mExtents = new Vector3(extentX, extentZ, extentY);            Bounds bounds = new Bounds();            bounds.center = info.mCenter;            bounds.extents = info.mExtents;            info.mBounds = bounds;            if (tileJson.Keys.Contains("content"))            {                info.mContent = tileJson["content"]["uri"].ToString();                info.mContent = info.mContent.Replace("./", "");                info.mContent = info.mContent.Replace(PagedLodConfig.mInstance.GetFileSufix(), "");            }            info.mGeometricError = float.Parse(tileJson["geometricError"].ToString());            return info;        }        public B3dmBasicInfo GetTileBasicInfo(string tileName)        {            if (mBasicInfoDict.ContainsKey(tileName))            {                return mBasicInfoDict[tileName];            }            return null;        }#endregion B3DM file Load    }}
 |