예제 #1
0
 public static int DeriveBorderSize(NMGenConfig config)
 {
     if (config.TileSize > 0)
     {
         return((int)Mathf.Ceil(
                    config.WalkableRadius / config.mRoot.xzCellSize) + 3);
     }
     return(0);
 }
예제 #2
0
        public static void OnGUIButtons(NavmeshBuild build
                                        , NMGenConfig config
                                        , bool isInspector)
        {
            if (!build)
            {
                return;
            }

            if (build.HasBuildData)
            {
                // Not an option if the build is in progress.
                return;
            }

            if (isInspector)
            {
                EditorGUILayout.BeginHorizontal();
            }

            if (GUILayout.Button("Clean"))
            {
                config.Clean();
                config.ApplyDecimalLimits();
                GUI.changed = true;
            }

            if (GUILayout.Button("Reset"))
            {
                config.Reset();
                GUI.changed = true;
            }

            if (!isInspector)
            {
                GUILayout.Space(2 * MarginSize);
            }

            if (build.HasInputData)
            {
                if (GUILayout.Button("Derive"))
                {
                    InputGeometry geom = build.InputGeom;

                    config.Derive(geom.BoundsMin, geom.BoundsMax);
                    config.ApplyDecimalLimits();

                    GUI.changed = true;
                }
            }

            if (isInspector)
            {
                EditorGUILayout.EndHorizontal();
            }
        }
예제 #3
0
        /// <summary>
        /// Duplicates the object.
        /// </summary>
        /// <returns>A duplicate of the object.</returns>
        public NMGenConfig Clone()
        {
            NMGenConfig result = new NMGenConfig();

            result.mRoot            = mRoot;
            result.mMaxEdgeLength   = mMaxEdgeLength;
            result.mMergeRegionArea = mMergeRegionArea;
            result.mMinRegionArea   = mMinRegionArea;
            result.mWalkableHeight  = mWalkableHeight;
            result.mWalkableRadius  = mWalkableRadius;
            result.mWalkableStep    = mWalkableStep;
            result.mBuildFlags      = mBuildFlags;
            return(result);
        }
예제 #4
0
        protected override void OnGUIMain()
        {
            NavmeshBuild build = Context.Build;

            if (!build)
            {
                return;
            }

            NMGenConfig config = build.Config;

            GUI.Box(Context.MainArea, "");

            Rect colA = Context.MainArea;

            colA.width = colA.width * 0.5f - 4 * MarginSize;

            Rect colB = colA;

            colA.x += MarginSize;

            colB.x += Context.MainArea.width * 0.5f + MarginSize;

            GUILayout.BeginArea(colA);

            OnGUIPrimary(build, config, false);

            if (GUI.changed)
            {
                // Conservative: Just in case the tile size was altered.
                DebugContext.NeedsRepaint = true;
            }

            GUILayout.EndArea();

            GUILayout.BeginArea(colB);
            OnGUIAdvanced(config, false);
            GUILayout.EndArea();

            if (GUI.changed)
            {
                build.IsDirty = true;
            }
        }
예제 #5
0
        public static int DeriveTileSize(
            NMGenConfig config
            , UnityEngine.Vector3 boundsMin
            , UnityEngine.Vector3 boundsMax)
        {
            UnityEngine.Vector3 diff = boundsMax - boundsMin;

            float maxXZLength = Mathf.Max(diff.x, diff.z);

            int maxCells = Mathf.CeilToInt(maxXZLength / config.XZCellSize);

            if (maxCells <= MaxCells)
            {
                return(0);
            }
            else
            {
                return(Mathf.Min(mStandardCells, maxCells / 2));
            }
        }
예제 #6
0
        public static float DeriveDetailSampleDistance(
            NMGenConfig config
            , UnityEngine.Vector3 boundsMin
            , UnityEngine.Vector3 boundsMax)
        {
            UnityEngine.Vector3 diff = boundsMax - boundsMin;

            float maxXZLength = Mathf.Max(diff.x, diff.z);

            int maxCells = Mathf.CeilToInt(maxXZLength / config.XZCellSize);

            if (config.TileSize == 0 || maxCells <= MaxCells)
            {
                return((float)Math.Round(
                           Mathf.Max(0.9f, maxXZLength / mSampleResolution), 2));
            }
            else
            {
                return((float)Math.Round(Mathf.Max(0.9f
                                                   , config.TileSize * config.XZCellSize / mSampleResolution), 2));
            }
        }
예제 #7
0
        public static void OnGUIAdvanced(NMGenConfig config
                                         , bool isInspector)
        {
            GUILayout.Label("Advanced Settings");

            EditorGUIUtility.LookLikeControls(170);

            float xz = config.XZCellSize;

            float a = xz * xz;
            float effective;

            /////////////////////////////////////////////////////////////

            GUILayout.Space(MarginSize);

            effective = Mathf.Ceil(config.MaxEdgeLength / xz) * xz;

            config.MaxEdgeLength = EditorGUILayout.FloatField(
                NMGenConfig.EdgeLenLabel + Effective(effective)
                , config.MaxEdgeLength);

            config.EdgeMaxDeviation = EditorGUILayout.FloatField(
                NMGenConfig.EdgeDevLabel
                , config.EdgeMaxDeviation);

            config.MaxVertsPerPoly = EditorGUILayout.IntSlider(
                NMGenConfig.MaxPolyVertLabel
                , config.MaxVertsPerPoly
                , 3
                , NMGen.MaxAllowedVertsPerPoly);

            effective = Mathf.Ceil(config.MergeRegionArea / a) * a;

            config.MergeRegionArea = EditorGUILayout.FloatField(
                NMGenConfig.MergeSizeLabel + Effective(effective)
                , config.MergeRegionArea);

            GUILayout.Space(MarginSize * 2);

            NMGenBuildFlag flags = config.BuildFlags;

            HandleFlagGUI(ref flags
                          , NMGenConfig.LedgeSpansLabel
                          , NMGenBuildFlag.LedgeSpansNotWalkable
                          , isInspector);

            HandleFlagGUI(ref flags
                          , NMGenConfig.LowHeightLabel
                          , NMGenBuildFlag.LowHeightSpansNotWalkable
                          , isInspector);

            HandleFlagGUI(ref flags
                          , NMGenConfig.LowObstacleLabel
                          , NMGenBuildFlag.LowObstaclesWalkable
                          , isInspector);

            ContourBuildFlags cflags = config.ContourOptions;

            HandleFlagGUI(ref cflags
                          , NMGenConfig.TessWallsLabel
                          , ContourBuildFlags.TessellateWallEdges
                          , isInspector);

            HandleFlagGUI(ref cflags
                          , NMGenConfig.TessAreasLabel
                          , ContourBuildFlags.TessellateAreaEdges
                          , isInspector);

            config.ContourOptions = cflags;

            if (isInspector)
            {
                config.UseMonotone = EditorGUILayout.Toggle(NMGenConfig.UseMonoLabel
                                                            , config.UseMonotone);
            }
            else
            {
                config.UseMonotone = GUILayout.Toggle(config.UseMonotone
                                                      , NMGenConfig.UseMonoLabel);
            }

            HandleFlagGUI(ref flags
                          , NMGenConfig.FlagPolysLabel
                          , NMGenBuildFlag.ApplyPolyFlags
                          , isInspector);

            bool includeDetail;

            if (isInspector)
            {
                includeDetail = EditorGUILayout.Toggle("Include Detail Mesh"
                                                       , (config.ResultOptions & NMGenAssetFlag.DetailMesh) != 0);
            }
            else
            {
                includeDetail = GUILayout.Toggle(
                    (config.ResultOptions & NMGenAssetFlag.DetailMesh) != 0
                    , "Include Detail Mesh");
            }

            if (includeDetail)
            {
                config.ResultOptions |= NMGenAssetFlag.DetailMesh;
            }
            else
            {
                config.ResultOptions &= ~NMGenAssetFlag.DetailMesh;
            }

            HandleFlagGUI(ref flags
                          , NMGenConfig.BVTreeLabel
                          , NMGenBuildFlag.BVTreeEnabled
                          , isInspector);

            config.BuildFlags = flags;
        }
 /// <summary>
 /// Duplicates the object.
 /// </summary>
 /// <returns>A duplicate of the object.</returns>
 public NMGenConfig Clone()
 {
     NMGenConfig result = new NMGenConfig();
     result.mRoot = mRoot;
     result.mMaxEdgeLength = mMaxEdgeLength;
     result.mMergeRegionArea = mMergeRegionArea;
     result.mMinRegionArea = mMinRegionArea;
     result.mWalkableHeight = mWalkableHeight;
     result.mWalkableRadius = mWalkableRadius;
     result.mWalkableStep = mWalkableStep;
     result.mBuildFlags = mBuildFlags;
     return result;
 }
        public static float DeriveDetailSampleDistance(
            NMGenConfig config
            , Vector3 boundsMin
            , Vector3 boundsMax)
        {
            Vector3 diff = boundsMax - boundsMin;

            float maxXZLength = Mathf.Max(diff.x, diff.z);

            int maxCells = Mathf.CeilToInt(maxXZLength / config.XZCellSize);

            if (config.TileSize == 0 || maxCells <= MaxCells)
            {
                return (float)Math.Round(
                    Mathf.Max(0.9f, maxXZLength / mSampleResolution), 2);
            }
            else
                return (float)Math.Round(Mathf.Max(0.9f
                    , config.TileSize * config.XZCellSize / mSampleResolution), 2);
        }
 public static float DeriveDetailMaxDeviation(NMGenConfig config)
 {
     return (float)Math.Round(config.YCellSize * mDeviationFactor, 2);
 }
예제 #11
0
        public static void OnGUIButtons(NavmeshBuild build
            , NMGenConfig config
            , bool isInspector)
        {
            if (!build)
                return;

            if (build.HasBuildData)
                // Not an option if the build is in progress.
                return;

            if (isInspector)
                EditorGUILayout.BeginHorizontal();

            if (GUILayout.Button("Clean"))
            {
                config.Clean();
                config.ApplyDecimalLimits();
                GUI.changed = true;
            }

            if (GUILayout.Button("Reset"))
            {
                config.Reset();
                GUI.changed = true;
            }

            if (!isInspector)
                GUILayout.Space(2 * MarginSize);

            if (build.HasInputData)
            {
                if (GUILayout.Button("Derive"))
                {
                    InputGeometry geom = build.InputGeom;

                    config.Derive(geom.BoundsMin, geom.BoundsMax);
                    config.ApplyDecimalLimits();

                    GUI.changed = true;
                }
            }

            if (isInspector)
                EditorGUILayout.EndHorizontal();

        }
예제 #12
0
        public static void OnGUIAdvanced(NMGenConfig config
            , bool isInspector)
        {
            GUILayout.Label("Advanced Settings");

            EditorGUIUtility.LookLikeControls(170);

            float xz = config.XZCellSize;

            float a = xz * xz;
            float effective;

            /////////////////////////////////////////////////////////////

            GUILayout.Space(MarginSize);

            effective = Mathf.Ceil(config.MaxEdgeLength / xz) * xz;

            config.MaxEdgeLength = EditorGUILayout.FloatField(
                NMGenConfig.EdgeLenLabel + Effective(effective)
                , config.MaxEdgeLength);

            config.EdgeMaxDeviation = EditorGUILayout.FloatField(
                NMGenConfig.EdgeDevLabel
                , config.EdgeMaxDeviation);

            config.MaxVertsPerPoly = EditorGUILayout.IntSlider(
                NMGenConfig.MaxPolyVertLabel
                , config.MaxVertsPerPoly
                , 3
                , NMGen.MaxAllowedVertsPerPoly);

            effective = Mathf.Ceil(config.MergeRegionArea / a) * a;

            config.MergeRegionArea = EditorGUILayout.FloatField(
                NMGenConfig.MergeSizeLabel + Effective(effective)
                , config.MergeRegionArea);

            GUILayout.Space(MarginSize * 2);

            NMGenBuildFlag flags = config.BuildFlags;

            HandleFlagGUI(ref flags
                , NMGenConfig.LedgeSpansLabel
                , NMGenBuildFlag.LedgeSpansNotWalkable
                , isInspector);

            HandleFlagGUI(ref flags
                , NMGenConfig.LowHeightLabel
                , NMGenBuildFlag.LowHeightSpansNotWalkable
                , isInspector);

            HandleFlagGUI(ref flags
                , NMGenConfig.LowObstacleLabel
                , NMGenBuildFlag.LowObstaclesWalkable
                , isInspector);

            ContourBuildFlags cflags = config.ContourOptions;

            HandleFlagGUI(ref cflags
                , NMGenConfig.TessWallsLabel
                , ContourBuildFlags.TessellateWallEdges
                , isInspector);

            HandleFlagGUI(ref cflags
                , NMGenConfig.TessAreasLabel
                , ContourBuildFlags.TessellateAreaEdges
                , isInspector);

            config.ContourOptions = cflags;

            if (isInspector)
            {
                config.UseMonotone = EditorGUILayout.Toggle(NMGenConfig.UseMonoLabel
                    , config.UseMonotone);
            }
            else
            {
                config.UseMonotone = GUILayout.Toggle(config.UseMonotone
                    , NMGenConfig.UseMonoLabel);
            }

            HandleFlagGUI(ref flags
                , NMGenConfig.FlagPolysLabel
                , NMGenBuildFlag.ApplyPolyFlags
                , isInspector);

            bool includeDetail;
            if (isInspector)
            {
                includeDetail = EditorGUILayout.Toggle("Include Detail Mesh"
                    , (config.ResultOptions & NMGenAssetFlag.DetailMesh) != 0);
            }
            else
            {
                includeDetail = GUILayout.Toggle(
                    (config.ResultOptions & NMGenAssetFlag.DetailMesh) != 0
                    , "Include Detail Mesh");
            }

            if (includeDetail)
                config.ResultOptions |= NMGenAssetFlag.DetailMesh;
            else
                config.ResultOptions &= ~NMGenAssetFlag.DetailMesh;

            HandleFlagGUI(ref flags
                , NMGenConfig.BVTreeLabel
                , NMGenBuildFlag.BVTreeEnabled
                , isInspector);

            config.BuildFlags = flags;
        }
예제 #13
0
        public static void OnGUIPrimary(NavmeshBuild build
            , NMGenConfig config
            , bool includeSlope)
        {
            if (!build)
                return;

            bool guiEnabled = GUI.enabled;

            EditorGUIUtility.LookLikeControls(155);

            float xz = config.XZCellSize;
            float y = config.YCellSize;
            float a = xz * xz;
            float effective;

            //////////////////////////////////////////////////////////////

            GUILayout.Label("Agent Settings");
            GUILayout.Space(MarginSize);

            TileBuildData tdata = build.BuildData;

            GUI.enabled = guiEnabled && (tdata == null);

            effective = (float)Mathf.Ceil(config.WalkableHeight / y) * y;

            config.WalkableHeight = EditorGUILayout.FloatField(
                NMGenConfig.HeightLabel + Effective(effective)
                , config.WalkableHeight);


            effective = (float)Mathf.Floor(config.WalkableStep / y) * y;
            config.WalkableStep = EditorGUILayout.FloatField(
                NMGenConfig.StepLabel + Effective(effective)
                , config.WalkableStep);

            effective = (float)Mathf.Ceil(config.WalkableRadius / xz) * xz;
            config.WalkableRadius = EditorGUILayout.FloatField(
                NMGenConfig.RadiusLabel + Effective(effective)
                , config.WalkableRadius);

            GUI.enabled = guiEnabled;

            if (includeSlope)
            {
                config.WalkableSlope = EditorGUILayout.FloatField(
                    NMGenConfig.SlopeLabel
                    , config.WalkableSlope);
            }

            /////////////////////////////////////////////////////////////////

            GUILayout.Space(2 * MarginSize);
            GUILayout.Label("Resolution and Tile Settings");
            GUILayout.Space(MarginSize);

            GUI.enabled = guiEnabled && (tdata == null);

            config.XZCellSize = EditorGUILayout.FloatField(
                NMGenConfig.XZSizeLabel
                , config.XZCellSize);

            config.YCellSize = EditorGUILayout.FloatField(
                NMGenConfig.YSizeLabel
                , config.YCellSize);

            config.TileSize = EditorGUILayout.IntField(
                NMGenConfig.TileSizeLabel
                    + " (" + config.TileSize * config.XZCellSize + ")"
                , config.TileSize);


            config.BorderSize = EditorGUILayout.IntField(
                NMGenConfig.HFBorderLabel
                , config.BorderSize);

            GUI.enabled = guiEnabled;

            int derBorderSize = NMGenConfig.DeriveBorderSize(config);
            float derXZ = NMGenConfig.DeriveXZCellSize(config);
            float derY = NMGenConfig.DeriveYCellSize(config);

            if ((config.TileSize == 0 && config.BorderSize != derBorderSize)
                || config.BorderSize < derBorderSize
                || config.XZCellSize > derXZ
                || config.YCellSize > derY)
            {
                GUILayout.Space(MarginSize);

                System.Text.StringBuilder sb = new System.Text.StringBuilder();

                sb.AppendLine("Recommendations:");

                if (config.XZCellSize > derXZ)
                    sb.AppendLine(NMGenConfig.XZSizeLabel + " of " + derXZ + " or less.");

                if (config.YCellSize > derY)
                    sb.AppendLine(NMGenConfig.YSizeLabel + " of " + derY + " or less.");

                if (config.TileSize == 0 && config.BorderSize != derBorderSize)
                    sb.AppendLine("Border Size of " + derBorderSize + ".");
                else if (config.BorderSize < derBorderSize)
                    sb.AppendLine("Border Size of " + derBorderSize + " or higher.");

                GUILayout.Box(sb.ToString().Trim(), EditorUtil.HelpStyle, GUILayout.ExpandWidth(true));
            }

            if (build.HasInputData)
            {
                InputGeometry geom = build.InputGeom;

                Vector3 bmin = geom.BoundsMin;
                Vector3 bmax = geom.BoundsMax;

                float w = bmax.x - bmin.x;
                float d = bmax.z - bmin.z;

                GUILayout.Space(MarginSize);

                int tw = Mathf.CeilToInt(w / xz);
                int td = Mathf.CeilToInt(d / xz);
                GUILayout.Label(string.Format("Cells: {0:N0} ({1:N0} x {2:N0})"
                    , tw * td, tw, td));

                if (config.TileSize > 0)
                {
                    tw = Mathf.Max(1, Mathf.CeilToInt((float)tw / config.TileSize));
                    td = Mathf.Max(1, Mathf.CeilToInt((float)td / config.TileSize));
                }
                else
                {
                    tw = 1;
                    td = 1;
                }
                GUILayout.Label(string.Format("Tiles: {0:N0} ({1:N0} x {2:N0})"
                    , tw * td, tw, td));
            }

            /////////////////////////////////////////////////////////////////

            GUILayout.Space(2 * MarginSize);
            GUILayout.Label("Miscellaneous Settings");
            GUILayout.Space(MarginSize);

            config.DetailSampleDistance = EditorGUILayout.FloatField(
                NMGenConfig.DetailSampleLabel
                , config.DetailSampleDistance);

            config.DetailMaxDeviation = EditorGUILayout.FloatField(
                NMGenConfig.DetailDevLabel
                , config.DetailMaxDeviation);

            effective = Mathf.Ceil(config.MinRegionArea / a) * a;
            config.MinRegionArea = EditorGUILayout.FloatField(
                NMGenConfig.IslandRegionLabel + Effective(effective)
                , config.MinRegionArea);
        }
예제 #14
0
        public bool QueueTask(int tx, int tz, int priority, BuildContext logger)
        {
            // Check for existing task and purge it.

            NavmeshBuild build = Build;

            if (!build)
            {
                return(false);
            }

            TileBuildData tdata = build.BuildData;

            if (build.TileSetDefinition == null && (tx > 0 || tz > 0))
            {
                logger.LogError("Tile build requested, but no tile set found.", this);
                return(false);
            }

            if (AbortRequest(tx, tz, "Overriden by new task."))
            {
                tdata.ClearUnbaked(tx, tz);

                logger.LogWarning(string.Format(
                                      "Existing build task overridden by new task. ({0}, {1})"
                                      , tx, tz), this);
            }

            IncrementalBuilder builder;
            NMGenConfig        config = build.Config;

            if (build.TileSetDefinition == null)
            {
                InputGeometry geom = build.InputGeom;

                if (geom == null)
                {
                    logger.LogError("Input geometry not available.", this);
                    tdata.SetAsFailed(tx, tz);
                    return(false);
                }

                builder = IncrementalBuilder.Create(config.GetConfig()
                                                    , config.ResultOptions
                                                    , geom
                                                    , build.NMGenProcessors);
            }
            else
            {
                builder = IncrementalBuilder.Create(tx, tz
                                                    , config.ResultOptions
                                                    , build.TileSetDefinition
                                                    , build.NMGenProcessors);
            }

            if (builder == null)
            {
                logger.LogError(string.Format("Tile set did not produce a builder. Tile: ({0},{1})"
                                              , tx, tz)
                                , this);
                return(false);
            }

            NMGenTask task = NMGenTask.Create(builder, priority);

            if (!mTaskProcessor.QueueTask(task))
            {
                logger.LogError(string.Format("Processor rejected task. Tile: ({0},{1})"
                                              , tx, tz), this);
                return(false);
            }

            mNMGenTasks.Add(task);
            tdata.SetAsQueued(tx, tz);

            return(true);
        }
예제 #15
0
        protected override void OnGUIButtons()
        {
            NavmeshBuild build = Context.Build;

            if (!build)
            {
                return;
            }

            NMGenConfig config = build.Config;

            // Buttons area.

            ControlUtil.BeginButtonArea(Context.ButtonArea);

            // Standard config buttons.

            OnGUIButtons(build, config, false);

            // Build initialialization buttons.

            bool guiEnabled = GUI.enabled;

            bool targetOK = build.CanLoadFromTarget(null, false);

            GUILayout.Space(MarginSize * 2);

            if (build.BuildState == NavmeshBuildState.Buildable)
            {
                GUI.enabled = (Context.TaskCount == 0);

                if (GUILayout.Button("Reinitialize Builder"))
                {
                    build.DiscardBuildData();
                }
            }
            else if (build.HasInputData)
            {
                if (targetOK)
                {
                    if (GUILayout.Button("Load Target's Config"))
                    {
                        if (!build.SetConfigFromTarget(Logger))
                        {
                            Logger.PostError("Could not load target config.", Context.Build);
                        }
                        Logger.ResetLog();
                    }

                    GUILayout.Space(MarginSize);
                    GUILayout.Label("Initialize Build:");
                    GUILayout.Space(MarginSize);

                    if (GUILayout.Button("From Scratch", ControlUtil.HighlightedButton))
                    {
                        InitializeBuild(false);
                    }

                    if (GUILayout.Button("Based on Target"))
                    {
                        InitializeBuild(true);
                    }

                    GUILayout.Space(MarginSize);
                    GUILayout.Box("Basing your build on the target's navigation"
                                  + " mesh will automatically lock you in to the"
                                  + " target's configuration settings."
                                  , EditorUtil.HelpStyle
                                  , GUILayout.ExpandWidth(true));
                }
                else
                {
                    if (GUILayout.Button("Ready to Build", ControlUtil.HighlightedButton))
                    {
                        InitializeBuild(false);
                    }
                }
            }

            GUI.enabled = guiEnabled;

            ViewOption option = build.HasInputData
                ? (ViewOption.Grid | ViewOption.Input) : 0;

            DebugContext.SetViews(option);

            ControlUtil.OnGUIStandardButtons(Context, DebugContext, true);

            ControlUtil.EndButtonArea();

            if (GUI.changed)
            {
                build.IsDirty = true;
            }
        }
 public static float DeriveXZCellSize(NMGenConfig config)
 {
     return (float)Math.Round(Mathf.Max(0.05f, config.WalkableRadius / 2), 2);
 }
 public static float DeriveYCellSize(NMGenConfig config)
 {
     return (float)Math.Round(Mathf.Max(0.05f, config.WalkableStep / 3), 2);
 }
예제 #18
0
 public static float DeriveXZCellSize(NMGenConfig config)
 {
     return((float)Math.Round(Mathf.Max(0.05f, config.WalkableRadius / 2), 2));
 }
 public static int DeriveBorderSize(NMGenConfig config)
 {
     if (config.TileSize > 0)
     {
         return (int)Mathf.Ceil(
             config.WalkableRadius / config.mRoot.xzCellSize) + 3;
     }
     return 0;
 }
예제 #20
0
 public static float DeriveYCellSize(NMGenConfig config)
 {
     return((float)Math.Round(Mathf.Max(0.05f, config.WalkableStep / 3), 2));
 }
        public static int DeriveTileSize(
            NMGenConfig config
            , Vector3 boundsMin
            , Vector3 boundsMax)
        {
            Vector3 diff = boundsMax - boundsMin;

            float maxXZLength = Mathf.Max(diff.x, diff.z);

            int maxCells = Mathf.CeilToInt(maxXZLength / config.XZCellSize);

            if (maxCells <= MaxCells)
                return 0;
            else
                return Mathf.Min(mStandardCells, maxCells / 2);
        }
예제 #22
0
 public static float DeriveDetailMaxDeviation(NMGenConfig config)
 {
     return((float)Math.Round(config.YCellSize * mDeviationFactor, 2));
 }
예제 #23
0
        private bool BuildSingleTile()
        {
            TileBuildData tdata  = mBuild.BuildData;
            NMGenConfig   config = mBuild.Config;
            InputGeometry geom   = mBuild.InputGeom;

            mContext.ResetLog();

            /*
             * Design note:
             *
             * Not using the build task since it doesn't provide enough progress
             * feedback for a single tile.
             *
             */

            // Create the NMGen builder.

            IncrementalBuilder builder = IncrementalBuilder.Create(config.GetConfig()
                                                                   , config.ResultOptions
                                                                   , geom
                                                                   , mBuild.NMGenProcessors);

            if (builder == null)
            {
                mContext.PostError("Unexpected failure creating NMGen builder.", mBuild);
                tdata.SetAsFailed(0, 0);
                return(false);
            }
            else if (builder.IsFinished)
            {
                if (builder.State == NMGenState.NoResult)
                {
                    mContext.PostError("NMGen build did not produce a result. (Early exit.)"
                                       , builder.GetMessages(), mBuild);
                    tdata.SetAsFailed(0, 0);
                    return(false);
                }
                else
                {
                    mContext.PostError("Unexpected NMGen builder completion."
                                       , builder.GetMessages(), mBuild);
                    tdata.SetAsFailed(0, 0);
                    return(false);
                }
            }

            mBuild.BuildData.SetAsInProgress(0, 0);

            // Run the NMGen builder.

            while (!builder.IsFinished)
            {
                if (EditorUtility.DisplayCancelableProgressBar("Build Single Tile Mesh"
                                                               , IncrementalBuilder.ToLabel(builder.State)
                                                               , IncrementalBuilder.ToProgress(builder.State)))
                {
                    return(false);
                }

                builder.Build();
            }

            // Handle NMGen failures.

            mContext.Log(builder.GetMessages());   // Single tile build.  So go ahead an record.

            switch (builder.State)
            {
            case NMGenState.Aborted:

                mContext.PostError("NMGen build failed.", mBuild);
                tdata.SetAsFailed(0, 0);
                return(false);

            case NMGenState.NoResult:

                mContext.PostError("NMGen build did not produce a result.", mBuild);
                tdata.SetAsFailed(0, 0);
                return(false);
            }

            mContext.Log(string.Format("Completed NMGen build: {0} polygons."
                                       , builder.Result.PolyMesh.PolyCount)
                         , mBuild);

            // Build the tile.

            NMGenAssets result = builder.Result;

            if (result.DetailMesh == null)
            {
                Debug.LogError("result.DetailMesh ==null!");
            }

            NavmeshTileBuildData tbd = org.critterai.nmbuild.NMBuild.GetBuildData(
                mContext, 0, 0
                , result.PolyMesh.GetData(false), result.DetailMesh.GetData(false)
                , mBuild.Connections
                , (config.BuildFlags & NMGenBuildFlag.BVTreeEnabled) != 0);

            if (tbd == null)
            {
                // No need to log the error.  The above method takes care of that.
                tdata.SetAsFailed(0, 0);
                return(false);
            }

            NavmeshTileData td = NavmeshTileData.Create(tbd);

            if (td.Size == 0)
            {
                mContext.PostError(
                    "Could not create {0} object. Cause unknown." + typeof(NavmeshTileData)
                    , mBuild);
                tdata.SetAsFailed(0, 0);
                return(false);
            }

            // Finalize the tile.

            tdata.SetWorkingData(0, 0, result.PolyMesh, result.DetailMesh);
            tdata.SetWorkingData(0, 0, td, tbd.PolyCount);

            mContext.PostTrace("Completed single tile build.", mBuild);

            return(true);
        }
예제 #24
0
        public static void OnGUIPrimary(NavmeshBuild build
                                        , NMGenConfig config
                                        , bool includeSlope)
        {
            if (!build)
            {
                return;
            }

            bool guiEnabled = GUI.enabled;

            EditorGUIUtility.LookLikeControls(155);

            float xz = config.XZCellSize;
            float y  = config.YCellSize;
            float a  = xz * xz;
            float effective;

            //////////////////////////////////////////////////////////////

            GUILayout.Label("Agent Settings");
            GUILayout.Space(MarginSize);

            TileBuildData tdata = build.BuildData;

            GUI.enabled = guiEnabled && (tdata == null);

            effective = (float)Mathf.Ceil(config.WalkableHeight / y) * y;

            config.WalkableHeight = EditorGUILayout.FloatField(
                NMGenConfig.HeightLabel + Effective(effective)
                , config.WalkableHeight);


            effective           = (float)Mathf.Floor(config.WalkableStep / y) * y;
            config.WalkableStep = EditorGUILayout.FloatField(
                NMGenConfig.StepLabel + Effective(effective)
                , config.WalkableStep);

            effective             = (float)Mathf.Ceil(config.WalkableRadius / xz) * xz;
            config.WalkableRadius = EditorGUILayout.FloatField(
                NMGenConfig.RadiusLabel + Effective(effective)
                , config.WalkableRadius);

            GUI.enabled = guiEnabled;

            if (includeSlope)
            {
                config.WalkableSlope = EditorGUILayout.FloatField(
                    NMGenConfig.SlopeLabel
                    , config.WalkableSlope);
            }

            /////////////////////////////////////////////////////////////////

            GUILayout.Space(2 * MarginSize);
            GUILayout.Label("Resolution and Tile Settings");
            GUILayout.Space(MarginSize);

            GUI.enabled = guiEnabled && (tdata == null);

            config.XZCellSize = EditorGUILayout.FloatField(
                NMGenConfig.XZSizeLabel
                , config.XZCellSize);

            config.YCellSize = EditorGUILayout.FloatField(
                NMGenConfig.YSizeLabel
                , config.YCellSize);

            config.TileSize = EditorGUILayout.IntField(
                NMGenConfig.TileSizeLabel
                + " (" + config.TileSize * config.XZCellSize + ")"
                , config.TileSize);


            config.BorderSize = EditorGUILayout.IntField(
                NMGenConfig.HFBorderLabel
                , config.BorderSize);

            GUI.enabled = guiEnabled;

            int   derBorderSize = NMGenConfig.DeriveBorderSize(config);
            float derXZ         = NMGenConfig.DeriveXZCellSize(config);
            float derY          = NMGenConfig.DeriveYCellSize(config);

            if ((config.TileSize == 0 && config.BorderSize != derBorderSize) ||
                config.BorderSize < derBorderSize ||
                config.XZCellSize > derXZ ||
                config.YCellSize > derY)
            {
                GUILayout.Space(MarginSize);

                System.Text.StringBuilder sb = new System.Text.StringBuilder();

                sb.AppendLine("Recommendations:");

                if (config.XZCellSize > derXZ)
                {
                    sb.AppendLine(NMGenConfig.XZSizeLabel + " of " + derXZ + " or less.");
                }

                if (config.YCellSize > derY)
                {
                    sb.AppendLine(NMGenConfig.YSizeLabel + " of " + derY + " or less.");
                }

                if (config.TileSize == 0 && config.BorderSize != derBorderSize)
                {
                    sb.AppendLine("Border Size of " + derBorderSize + ".");
                }
                else if (config.BorderSize < derBorderSize)
                {
                    sb.AppendLine("Border Size of " + derBorderSize + " or higher.");
                }

                GUILayout.Box(sb.ToString().Trim(), EditorUtil.HelpStyle, GUILayout.ExpandWidth(true));
            }

            if (build.HasInputData)
            {
                InputGeometry geom = build.InputGeom;

                Vector3 bmin = geom.BoundsMin;
                Vector3 bmax = geom.BoundsMax;

                float w = bmax.x - bmin.x;
                float d = bmax.z - bmin.z;

                GUILayout.Space(MarginSize);

                int tw = Mathf.CeilToInt(w / xz);
                int td = Mathf.CeilToInt(d / xz);
                GUILayout.Label(string.Format("Cells: {0:N0} ({1:N0} x {2:N0})"
                                              , tw * td, tw, td));

                if (config.TileSize > 0)
                {
                    tw = Mathf.Max(1, Mathf.CeilToInt((float)tw / config.TileSize));
                    td = Mathf.Max(1, Mathf.CeilToInt((float)td / config.TileSize));
                }
                else
                {
                    tw = 1;
                    td = 1;
                }
                GUILayout.Label(string.Format("Tiles: {0:N0} ({1:N0} x {2:N0})"
                                              , tw * td, tw, td));
            }

            /////////////////////////////////////////////////////////////////

            GUILayout.Space(2 * MarginSize);
            GUILayout.Label("Miscellaneous Settings");
            GUILayout.Space(MarginSize);

            config.DetailSampleDistance = EditorGUILayout.FloatField(
                NMGenConfig.DetailSampleLabel
                , config.DetailSampleDistance);

            config.DetailMaxDeviation = EditorGUILayout.FloatField(
                NMGenConfig.DetailDevLabel
                , config.DetailMaxDeviation);

            effective            = Mathf.Ceil(config.MinRegionArea / a) * a;
            config.MinRegionArea = EditorGUILayout.FloatField(
                NMGenConfig.IslandRegionLabel + Effective(effective)
                , config.MinRegionArea);
        }