void MigrateCharacterControllerProperties(ShapeComponent physX, ShapeComponent havok) { havok.SetPropertyValue("Max_Slope", physX.GetPropertyValue("m_fSlopeLimit", false)); float fRadius = (float)physX.GetPropertyValue("m_fRadius", false); float fHeight = (float)physX.GetPropertyValue("m_fHeight", false); if (fRadius > 0.0f && fHeight > 0.0f) { havok.SetPropertyValue("Capsule_Radius", fRadius); Vector3F top = new Vector3F(0.0f, 0.0f, fHeight + fRadius); havok.SetPropertyValue("Character_Top", top); Vector3F bottom = new Vector3F(0.0f, 0.0f, fRadius); havok.SetPropertyValue("Character_Bottom", bottom); } havok.SetPropertyValue("Debug", physX.GetPropertyValue("DebugRendering", false)); }
/// <summary> /// Map properties from the START_VAR_TABLE(vPhysXRigidBody,... to the counterparts in START_VAR_TABLE(vHavokRigidBody... /// </summary> /// <param name="physX">Input physX rigid body property</param> /// <param name="havok">output havok component</param> void MigrateRigidBodyProperties(ShapeComponent physX, ShapeComponent havok) { { // Havok: "Dynamic/Keyframed/Fixed/Sphere Inertia/Box Inertia/Thin Box Inertia/Character" // PhysX: "Dynamic/Static/Kinematic" string sValue = (string)physX.GetPropertyValue("m_ePhysicsType", false); // since it is an enum, we get it as a string if (sValue == "Static") { sValue = "Fixed"; } else if (sValue == "Kinematic") { sValue = "Keyframed"; } havok.SetPropertyValue("Havok_MotionType", sValue, false); } { // Havok: "Box/Sphere/Convex Hull/File/Capsule/Cylinder/Mesh" // PhysX: "Box/Sphere/File/Hull/Mesh" string sValue = (string)physX.GetPropertyValue("m_ePhysicsGeom", false); // since it is an enum, we get it as a string if (sValue == "Hull" || sValue == "File") { sValue = "Convex Hull"; // since "PhysXFile" + "Havok_FileResourceName" does not match, convert "File" to "Convex Hull" } havok.SetPropertyValue("Shape_Type", sValue, false); } // mass of zero is not legal for dynamic rigid bodies in Havok float fMass = (float)physX.GetPropertyValue("m_fMass", false); if (fMass > 0.0f) { havok.SetPropertyValue("Havok_Mass", fMass); } havok.SetPropertyValue("Shape_Height", physX.GetPropertyValue("m_fHeight", false)); havok.SetPropertyValue("Shape_Radius", physX.GetPropertyValue("m_fRadius", false)); havok.SetPropertyValue("Shape_PivotOffset", physX.GetPropertyValue("m_vLocalOffset", false)); havok.SetPropertyValue("Shape_BoxSize", physX.GetPropertyValue("m_bboxSize", false)); havok.SetPropertyValue("Debug_Render", physX.GetPropertyValue("DebugRendering", false)); }
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); }
/// <summary> /// Map properties from the START_VAR_TABLE(vPhysXRigidBody,... to the counterparts in START_VAR_TABLE(vHavokRigidBody... /// </summary> /// <param name="physX">Input physX rigid body property</param> /// <param name="havok">output havok component</param> void MigrateRigidBodyProperties(ShapeComponent physX, ShapeComponent havok) { { // Havok: "Dynamic/Keyframed/Fixed/Sphere Inertia/Box Inertia/Thin Box Inertia/Character" // PhysX: "Dynamic/Static/Kinematic" string sValue = (string)physX.GetPropertyValue("m_ePhysicsType", false); // since it is an enum, we get it as a string if (sValue == "Static") sValue = "Fixed"; else if (sValue == "Kinematic") sValue = "Keyframed"; havok.SetPropertyValue("Havok_MotionType", sValue, false); } { // Havok: "Box/Sphere/Convex Hull/File/Capsule/Cylinder/Mesh" // PhysX: "Box/Sphere/File/Hull/Mesh" string sValue = (string)physX.GetPropertyValue("m_ePhysicsGeom", false); // since it is an enum, we get it as a string if (sValue == "Hull" || sValue == "File") sValue = "Convex Hull"; // since "PhysXFile" + "Havok_FileResourceName" does not match, convert "File" to "Convex Hull" havok.SetPropertyValue("Shape_Type", sValue, false); } // mass of zero is not legal for dynamic rigid bodies in Havok float fMass = (float)physX.GetPropertyValue("m_fMass", false); if (fMass > 0.0f) havok.SetPropertyValue("Havok_Mass", fMass); havok.SetPropertyValue("Shape_Height", physX.GetPropertyValue("m_fHeight", false)); havok.SetPropertyValue("Shape_Radius", physX.GetPropertyValue("m_fRadius", false)); havok.SetPropertyValue("Shape_PivotOffset", physX.GetPropertyValue("m_vLocalOffset", false)); havok.SetPropertyValue("Shape_BoxSize", physX.GetPropertyValue("m_bboxSize", false)); havok.SetPropertyValue("Debug_Render", physX.GetPropertyValue("DebugRendering", false)); }
void MigrateCharacterControllerProperties(ShapeComponent physX, ShapeComponent havok) { havok.SetPropertyValue("Max_Slope", physX.GetPropertyValue("m_fSlopeLimit", false)); float fRadius = (float)physX.GetPropertyValue("m_fRadius", false); float fHeight = (float)physX.GetPropertyValue("m_fHeight", false); if (fRadius > 0.0f && fHeight > 0.0f) { havok.SetPropertyValue("Capsule_Radius", fRadius); Vector3F top = new Vector3F(0.0f, 0.0f, fHeight + fRadius); havok.SetPropertyValue("Character_Top", top); Vector3F bottom = new Vector3F(0.0f, 0.0f, fRadius); havok.SetPropertyValue("Character_Bottom", bottom); } havok.SetPropertyValue("Debug", physX.GetPropertyValue("DebugRendering", false)); }