public override ShapeBase CreateShapeInstance()
        {
            HavokNavMeshCarverShape shape = new HavokNavMeshCarverShape("NavMesh_Carver");

            shape.Position = EditorManager.Scene.CurrentShapeSpawnPosition;
            return(shape);
        }
        public override ShapeBase Clone()
        {
            HavokNavMeshCarverShape copy = base.Clone() as HavokNavMeshCarverShape;

            copy._hotSpotSizeX = null;
            copy._hotSpotSizeY = null;
            copy._hotSpotSizeZ = null;
            System.Diagnostics.Debug.Assert(!copy.Selected); // turned off in ShapeBase

            return(copy);
        }
 public override ShapeBase CreateShapeInstance()
 {
     HavokNavMeshCarverShape shape = new HavokNavMeshCarverShape("NavMesh_Carver");
     shape.Position = EditorManager.Scene.CurrentShapeSpawnPosition;
     return shape;
 }
Example #4
0
        public bool Build(ShapeCollection staticGeometries, ref int numGeometryVertices, ref int numGeometryTriangles)
        {
            if (!HasEngineInstance())
            {
                return(false);
            }

            EngineNavMesh.ClearNavMesh();
            EngineNavMesh.ClearGeometry();
            EngineNavMesh.ClearCarvers();
            EngineNavMesh.ClearSeedPoints();
            EngineNavMesh.ClearLocalSettings();
            EngineNavMesh.ClearDecorationCapsules();
            SetEngineInstanceBaseProperties();

            HavokNavMeshGlobalSettings globalSettings = GetGlobalSettings();

            if (globalSettings == null)
            {
                return(false);
            }

            BoundingBox parentZoneBbox = new BoundingBox();

            if (globalSettings.RestrictToInputGeometryFromSameZone && ParentZone != null)
            {
                parentZoneBbox = ParentZone.CalculateBoundingBox();
            }

            // check if there's a parent zone
            foreach (ShapeBase shape in staticGeometries)
            {
                // treat as cutter if flag is set and if in different zone
                bool potentiallyTreatAsCutter = globalSettings.RestrictToInputGeometryFromSameZone && (shape.ParentZone != ParentZone);

                if (shape is EntityShape)
                {
                    EntityShape   entity = shape as EntityShape;
                    eNavMeshUsage usage  = entity.GetNavMeshUsage();

                    // exclude entities that have a vHavokRigidBody component with "Motion Type" != "Fixed"
                    ShapeComponentType compType = (ShapeComponentType)EditorManager.EngineManager.ComponentClassManager.GetCollectionType("vHavokRigidBody");
                    if (compType != null && entity.Components != null)
                    {
                        ShapeComponent comp = entity.Components.GetComponentByType(compType);
                        if (comp != null)
                        {
                            string propValue = comp.GetPropertyValue("Motion Type") as string;
                            if (string.Compare(propValue, "Fixed") != 0)
                            {
                                usage = eNavMeshUsage.ExcludeFromNavMesh;
                            }
                        }
                    }

                    // potentially override usage
                    if (potentiallyTreatAsCutter && (usage == eNavMeshUsage.IncludeInNavMesh))
                    {
                        usage = eNavMeshUsage.CutterOnly;
                    }

                    if (usage != eNavMeshUsage.ExcludeFromNavMesh)
                    {
                        EngineNavMesh.AddEntityGeometry(entity.EngineEntity.GetNativeObject(), (int)usage, parentZoneBbox);
                    }
                }
                else if (shape is StaticMeshShape)
                {
                    StaticMeshShape staticMesh = shape as StaticMeshShape;
                    eNavMeshUsage   usage      = staticMesh.GetNavMeshUsage();

                    // potentially override usage
                    if (potentiallyTreatAsCutter && (usage == eNavMeshUsage.IncludeInNavMesh))
                    {
                        usage = eNavMeshUsage.CutterOnly;
                    }


                    if (usage != eNavMeshUsage.ExcludeFromNavMesh)
                    {
                        EngineNavMesh.AddStaticMeshGeometry(staticMesh.EngineMesh.GetNativeObject(), (int)usage, parentZoneBbox);
                    }
                }
                else if (shape is TerrainShape)
                {
                    TerrainShape  terrain = shape as TerrainShape;
                    eNavMeshUsage usage   = terrain.GetNavMeshUsage();

                    // potentially override usage
                    if (potentiallyTreatAsCutter && (usage == eNavMeshUsage.IncludeInNavMesh))
                    {
                        usage = eNavMeshUsage.CutterOnly;
                    }


                    if (usage != eNavMeshUsage.ExcludeFromNavMesh)
                    {
                        EngineNavMesh.AddTerrainGeometry(terrain.EngineTerrain.GetNativeObject(), (int)usage, parentZoneBbox);
                    }
                }
#if !HK_ANARCHY
                else if (shape is DecorationGroupShape)
                {
                    DecorationGroupShape decorationGroup = shape as DecorationGroupShape;

                    // Please note that currently the native HavokAiEnginePlugin only supports decoration capsules as cutters.
                    if (decorationGroup.GetNavMeshLimitedUsage() == DecorationGroupShape.eNavMeshLimitedUsage.CutterOnly)
                    {
                        EngineNavMesh.AddDecorationGroupCapsules(decorationGroup.EngineGroup.GetGroupsObject());
                    }
                }
#endif
#if USE_SPEEDTREE
                else if (shape is Speedtree6GroupShape)
                {
                    Speedtree6GroupShape trees = shape as Speedtree6GroupShape;
                    if (trees.EnableCollisions)
                    {
                        EngineNavMesh.AddSpeedTree6Capsules(trees.EngineGroup.GetGroupsObject());
                    }
                }
#endif
            }
            numGeometryVertices  = EngineNavMesh.GetNumGeometryVertices();
            numGeometryTriangles = EngineNavMesh.GetNumGeometryTriangles();

            // Add carvers
            ShapeCollection carvers = EditorManager.Scene.AllShapesOfType(typeof(HavokNavMeshCarverShape));
            foreach (ShapeBase shape in carvers)
            {
                HavokNavMeshCarverShape carver    = shape as HavokNavMeshCarverShape;
                BoundingBox             localBbox = null;
                carver.GetLocalBoundingBox(ref localBbox);
                localBbox.vMin.X *= carver.ScaleX;
                localBbox.vMin.Y *= carver.ScaleY;
                localBbox.vMin.Z *= carver.ScaleZ;
                localBbox.vMax.X *= carver.ScaleX;
                localBbox.vMax.Y *= carver.ScaleY;
                localBbox.vMax.Z *= carver.ScaleZ;
                EngineNavMesh.AddBoxCarver(localBbox.vMin, localBbox.vMax, carver.Position, carver.RotationMatrix, carver.IsInverted());
            }

            // Add seed points
            ShapeCollection seedPoints = EditorManager.Scene.AllShapesOfType(typeof(HavokNavMeshSeedPointShape));
            foreach (ShapeBase shape in seedPoints)
            {
                HavokNavMeshSeedPointShape seedPoint = shape as HavokNavMeshSeedPointShape;
                EngineNavMesh.AddSeedPoint(seedPoint.Position);
            }

            // Add local settings
            ShapeCollection localSettings = EditorManager.Scene.AllShapesOfType(typeof(HavokNavMeshLocalSettingsShape));
            foreach (ShapeBase shape in localSettings)
            {
                HavokNavMeshLocalSettingsShape ls = shape as HavokNavMeshLocalSettingsShape;
                BoundingBox bbox = null;
                ls.GetLocalBoundingBox(ref bbox);
                bbox.vMin.X *= ls.ScaleX;
                bbox.vMin.Y *= ls.ScaleY;
                bbox.vMin.Z *= ls.ScaleZ;
                bbox.vMax.X *= ls.ScaleX;
                bbox.vMax.Y *= ls.ScaleY;
                bbox.vMax.Z *= ls.ScaleZ;

                // Nav Mesh Generation Settings
                EngineNavMesh.m_maxWalkableSlope = ls.MaxWalkableSlope / 180.0f * 3.14159f;

                // Nav Mesh Edge Matching Settings
                EngineNavMesh.m_maxStepHeight             = ls.MaxStepHeight;
                EngineNavMesh.m_maxSeparation             = ls.MaxSeparation;
                EngineNavMesh.m_maxOverhang               = ls.MaxOverhang;
                EngineNavMesh.m_cosPlanarAlignmentAngle   = (float)Math.Cos(ls.PlanarAlignmentAngle / 180.0f * 3.14159f);
                EngineNavMesh.m_cosVerticalAlignmentAngle = (float)Math.Cos(ls.VerticalAlignmentAngle / 180.0f * 3.14159f);
                EngineNavMesh.m_minEdgeOverlap            = ls.MinEdgeOverlap;

                // Nav Mesh Simplification Settings
                EngineNavMesh.m_maxBorderSimplifyArea        = ls.MaxBorderSimplifyArea;
                EngineNavMesh.m_maxConcaveBorderSimplifyArea = ls.MaxConcaveBorderSimplifyArea;
                EngineNavMesh.m_useHeightPartitioning        = ls.UseHeightPartitioning;
                EngineNavMesh.m_maxPartitionHeightError      = ls.MaxPartitionHeightError;

                // Nav Mesh Simplification Settings (Advanced)
                EngineNavMesh.m_minCorridorWidth                  = ls.MinCorridorWidth;
                EngineNavMesh.m_maxCorridorWidth                  = ls.MaxCorridorWidth;
                EngineNavMesh.m_holeReplacementArea               = ls.HoleReplacementArea;
                EngineNavMesh.m_maxLoopShrinkFraction             = ls.MaxLoopShrinkFraction;
                EngineNavMesh.m_maxBorderHeightError              = ls.MaxBorderHeightError;
                EngineNavMesh.m_maxBorderDistanceError            = ls.MaxBorderDistanceError;
                EngineNavMesh.m_maxPartitionSize                  = ls.MaxPartitionSize;
                EngineNavMesh.m_useConservativeHeightPartitioning = ls.UseConservativeHeightPartitioning;
                EngineNavMesh.m_hertelMehlhornHeightError         = ls.HertelMehlhornHeightError;
                EngineNavMesh.m_cosPlanarityThreshold             = (float)Math.Cos(ls.PlanarityThreshold / 180 * 3.14159f);
                EngineNavMesh.m_nonconvexityThreshold             = ls.NonconvexityThreshold;
                EngineNavMesh.m_boundaryEdgeFilterThreshold       = ls.BoundaryEdgeFilterThreshold;
                EngineNavMesh.m_maxSharedVertexHorizontalError    = ls.MaxSharedVertexHorizontalError;
                EngineNavMesh.m_maxSharedVertexVerticalError      = ls.MaxSharedVertexVerticalError;
                EngineNavMesh.m_maxBoundaryVertexHorizontalError  = ls.MaxBoundaryVertexHorizontalError;
                EngineNavMesh.m_maxBoundaryVertexVerticalError    = ls.MaxBoundaryVertexVerticalError;
                EngineNavMesh.m_mergeLongestEdgesFirst            = ls.MergeLongestEdgesFirst;

                EngineNavMesh.AddLocalSettings(bbox.vMin, bbox.vMax, ls.Position, ls.RotationMatrix);
            }

            // todo: figure out how to pass class instances between here and EngineNavMesh.
            // basically the settings members of EngineNavMesh are reused for transferring the local settings to
            // EngineNavMesh. this should be harmless due to the following call which will revert any changes.
            SetEngineInstanceBaseProperties();

            string fullSnapshotPath = Path.Combine(CSharpFramework.EditorManager.Scene.Project.ProjectDir, m_snapshotFilename);
            bool   ret = EngineNavMesh.BuildNavMeshFromGeometry(m_saveInputSnapshot, fullSnapshotPath);

            EngineNavMesh.ClearGeometry();
            EngineNavMesh.ClearCarvers();
            EngineNavMesh.ClearSeedPoints();
            EngineNavMesh.ClearLocalSettings();
            EngineNavMesh.ClearDecorationCapsules();
            return(ret);
        }