public static HavokNavmeshResource ResourceFromNavmeshRoot(hkRootLevelContainer root) { var ret = new HavokNavmeshResource(); ret.HkxRoot = root; ret.LoadInternal(AccessLevel.AccessFull); return(ret); }
bool IResource._Load(byte[] bytes, AccessLevel al, GameType type) { BinaryReaderEx br = new BinaryReaderEx(false, bytes); var des = new HKX2.PackFileDeserializer(); HkxRoot = (hkRootLevelContainer)des.Deserialize(br); return(LoadInternal(al)); }
bool IResource._Load(string file, AccessLevel al, GameType type) { using (var s = File.OpenRead(file)) { var des = new HKX2.PackFileDeserializer(); HkxRoot = (hkRootLevelContainer)des.Deserialize(new BinaryReaderEx(false, s)); } return(LoadInternal(al)); }
public hkRootLevelContainer CookCollision() { // Root container var root = new hkRootLevelContainer(); root.m_namedVariants = new List <hkRootLevelContainerNamedVariant>(); // Named variant var variant = new hkRootLevelContainerNamedVariant(); variant.m_className = "hknpPhysicsSceneData"; variant.m_name = "Physics Scene Data"; root.m_namedVariants.Add(variant); // Physics scene data var physicsSceneData = new hknpPhysicsSceneData(); variant.m_variant = physicsSceneData; physicsSceneData.m_systemDatas = new List <hknpPhysicsSystemData>(); // Physics system data var physicsSystemData = new hknpPhysicsSystemData(); physicsSceneData.m_systemDatas.Add(physicsSystemData); physicsSystemData.m_name = "Default Physics System Data"; physicsSystemData.m_materials = new List <hknpMaterial>(); physicsSystemData.m_bodyCinfos = new List <hknpBodyCinfo>(); physicsSystemData.m_referencedObjects = new List <hkReferencedObject>(); foreach (var m in _meshes) { var mat = BuildMaterial(); var cbodyinfo = BuildBodyCInfo("l0000200"); cbodyinfo.m_shape = m; physicsSystemData.m_referencedObjects.Add(m); physicsSystemData.m_materials.Add(mat); physicsSystemData.m_bodyCinfos.Add(cbodyinfo); } return(root); }
private bool LoadInternal(AccessLevel al) { if (al == AccessLevel.AccessFull || al == AccessLevel.AccessGPUOptimizedOnly) { Bounds = new BoundingBox(); var mesh = HkxRoot.FindVariant <hkaiNavMesh>(); if (mesh != null) { ProcessMesh(mesh); } var graph = HkxRoot.FindVariant <hkaiDirectedGraphExplicitCost>(); if (graph != null) { ProcessGraph(graph); } } if (al == AccessLevel.AccessGPUOptimizedOnly) { HkxRoot = null; } return(true); }
public hkRootLevelContainer BuildNavmesh(BuildParams p, List <Vector3> verts, List <int> indices) { var root = new hkRootLevelContainer(); NavMeshNative.SetNavmeshBuildParams(p.Cellsize, p.Cellheight, p.SlopeAngle, p.AgentHeight, p.AgentClimb, p.AgentRadius, p.MinRegionArea); var buildSuccess = NavMeshNative.BuildNavmeshForMesh(verts.ToArray(), verts.Count, indices.ToArray(), indices.Count); if (!buildSuccess) { return(null); } var vcount = NavMeshNative.GetMeshVertCount(); var icount = NavMeshNative.GetMeshTriCount(); if (vcount == 0 || icount == 0) { return(null); } ushort[] bverts = new ushort[vcount * 3]; ushort[] bindices = new ushort[icount * 3 * 2]; Vector3[] vbverts = new Vector3[vcount]; NavMeshNative.GetMeshVerts(bverts); NavMeshNative.GetMeshTris(bindices); Vector3[] bounds = new Vector3[2]; NavMeshNative.GetBoundingBox(bounds); var nmesh = new hkaiNavMesh(); nmesh.m_aabb = new hkAabb(); nmesh.m_aabb.m_min = new Vector4(bounds[0].X, bounds[0].Y, bounds[0].Z, 1.0f); nmesh.m_aabb.m_max = new Vector4(bounds[1].X, bounds[1].Y, bounds[1].Z, 1.0f); nmesh.m_edgeData = new List <int>(); nmesh.m_edgeDataStriding = 1; nmesh.m_edges = new List <hkaiNavMeshEdge>(); nmesh.m_erosionRadius = 0.0f; nmesh.m_faceData = new List <int>(); nmesh.m_faceDataStriding = 1; nmesh.m_faces = new List <hkaiNavMeshFace>(); nmesh.m_flags = 0; nmesh.m_vertices = new List <Vector4>(); for (int i = 0; i < bverts.Length / 3; i++) { var vx = bverts[i * 3]; var vy = bverts[i * 3 + 1]; var vz = bverts[i * 3 + 2]; var vert = new Vector3(bounds[0].X + (float)vx * p.Cellsize, bounds[0].Y + (float)vy * p.Cellheight, bounds[0].Z + (float)vz * p.Cellsize); nmesh.m_vertices.Add(new Vector4(vert.X, vert.Y, vert.Z, 1.0f)); vbverts[i] = vert; } for (int t = 0; t < bindices.Length / 2; t += 3) { var f = new hkaiNavMeshFace(); f.m_clusterIndex = 0; f.m_numEdges = 3; f.m_startEdgeIndex = nmesh.m_edges.Count; f.m_startUserEdgeIndex = -1; f.m_padding = 0xCDCD; nmesh.m_faces.Add(f); nmesh.m_faceData.Add(0); for (int i = 0; i < 3; i++) { var e = new hkaiNavMeshEdge(); e.m_a = bindices[t * 2 + i]; e.m_b = bindices[t * 2 + ((i + 1) % 3)]; e.m_flags = 4; // Record adjacency if (bindices[t * 2 + 3 + i] == 0xFFFF) { // No adjacency e.m_oppositeEdge = 0xFFFFFFFF; e.m_oppositeFace = 0xFFFFFFFF; } else { e.m_oppositeFace = bindices[t * 2 + 3 + i]; // Find the edge that has this face as an adjancency for (int j = 0; j < 3; j++) { var edge = bindices[t * 2 + 3 + i] * 6 + 3 + j; if (bindices[edge] == (t / 3)) { e.m_oppositeEdge = (uint)bindices[t * 2 + 3 + i] * 3 + (uint)j; } } } nmesh.m_edges.Add(e); nmesh.m_edgeData.Add(0); } } root.m_namedVariants = new List <hkRootLevelContainerNamedVariant>(); var variant = new hkRootLevelContainerNamedVariant(); variant.m_className = "hkaiNavMesh"; variant.m_name = "hkaiNavMesh"; variant.m_variant = nmesh; root.m_namedVariants.Add(variant); // Next step: build a bvh var shortIndices = new ushort[bindices.Length / 2]; for (int i = 0; i < bindices.Length / 2; i += 3) { shortIndices[i] = bindices[i * 2]; shortIndices[i + 1] = bindices[i * 2 + 1]; shortIndices[i + 2] = bindices[i * 2 + 2]; } bool didbuild = BVHNative.BuildBVHForMesh(vbverts, vbverts.Length, shortIndices, shortIndices.Length); if (!didbuild) { return(null); } var nodecount = BVHNative.GetBVHSize(); var nsize = BVHNative.GetNodeSize(); var nodes = new NativeBVHNode[nodecount]; BVHNative.GetBVHNodes(nodes); // Rebuild in friendlier tree form List <BVNode> bnodes = new List <BVNode>((int)nodecount); foreach (var n in nodes) { var bnode = new BVNode(); bnode.Min = new Vector3(n.minX, n.minY, n.minZ); bnode.Max = new Vector3(n.maxX, n.maxY, n.maxZ); bnode.IsLeaf = n.isLeaf == 1; bnode.PrimitiveCount = n.primitiveCount; bnode.Primitive = n.firstChildOrPrimitive; bnodes.Add(bnode); } for (int i = 0; i < nodes.Length; i++) { if (nodes[i].isLeaf == 0) { bnodes[i].Left = bnodes[(int)nodes[i].firstChildOrPrimitive]; bnodes[i].Right = bnodes[(int)nodes[i].firstChildOrPrimitive + 1]; } } var bvhvariant = new hkRootLevelContainerNamedVariant(); bvhvariant.m_className = "hkcdStaticAabbTree"; bvhvariant.m_name = "hkcdStaticAabbTree"; var tree = new hkcdStaticAabbTree(); bvhvariant.m_variant = tree; root.m_namedVariants.Add(bvhvariant); tree.m_treePtr = new hkcdStaticTreeDefaultTreeStorage6(); tree.m_treePtr.m_nodes = bnodes[0].BuildAxis6Tree(); var min = bnodes[0].Min; var max = bnodes[0].Max; tree.m_treePtr.m_domain = new hkAabb(); tree.m_treePtr.m_domain.m_min = new Vector4(min.X, min.Y, min.Z, 1.0f); tree.m_treePtr.m_domain.m_max = new Vector4(max.X, max.Y, max.Z, 1.0f); // Build a dummy directed graph var gvariant = new hkRootLevelContainerNamedVariant(); gvariant.m_className = "hkaiDirectedGraphExplicitCost"; gvariant.m_name = "hkaiDirectedGraphExplicitCost"; var graph = new hkaiDirectedGraphExplicitCost(); gvariant.m_variant = graph; root.m_namedVariants.Add(gvariant); graph.m_nodes = new List <hkaiDirectedGraphExplicitCostNode>(); var node = new hkaiDirectedGraphExplicitCostNode(); node.m_numEdges = 0; node.m_startEdgeIndex = 0; graph.m_nodes.Add(node); graph.m_positions = new List <Vector4>(); var c = (max - min) / 2; graph.m_positions.Add(new Vector4(c.X, c.Y, c.Z, 1.0f)); return(root); }