Exemple #1
0
        private void NavCellsFromXML(XmlNode navMeshXml)
        {
            string[] navMeshStringRows = navMeshXml.InnerText.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            uint     rowCount          = (uint)navMeshStringRows.Length;
            uint     colomnCount       = (uint)navMeshStringRows[0].Length;

            // Compute derived room properties
            float    roomWidth        = (float)colomnCount * GameConstants.NAV_MESH_WORLD_UNITS_SIZE;
            float    roomHeight       = (float)rowCount * GameConstants.NAV_MESH_WORLD_UNITS_SIZE;
            BitArray navCellData      = new BitArray((int)(rowCount * colomnCount));
            int      navMeshDataIndex = 0;

            foreach (string rowString in navMeshStringRows)
            {
                foreach (char c in rowString)
                {
                    navCellData[navMeshDataIndex] = (c == '1');
                    ++navMeshDataIndex;
                }
            }

            m_colomnCount          = colomnCount;
            m_rowCount             = rowCount;
            m_nonEmptyNavCellCount = 0;
            m_roomKey     = null;
            m_boundingBox = new AABB3d();
            m_boundingBox.SetBounds2d(-roomWidth / 2.0f, -roomHeight / 2.0f, roomWidth / 2.0f, roomHeight / 2.0f);

            NavMesh.BuildNavCellConnectivityGrid(
                colomnCount,
                rowCount,
                navCellData,
                out m_navCells,
                out m_nonEmptyNavCellCount);
        }
    public List <IAABB> QueryOverlaps(IAABB obj)
    {
        List <IAABB> overlaps = new List <IAABB>();
        Stack <int>  stack    = new Stack <int>();
        AABB3d       testAabb = obj.GetAABBBounds();

        stack.Push(m_rootNodeIndex);
        while (stack.Count != 0)
        {
            int nodeIndex = stack.Pop();

            if (nodeIndex == NullIndex)
            {
                continue;
            }

            AABBTreeNode node = m_nodes[nodeIndex];
            if (node.m_bounds.Overlaps(testAabb))
            {
                if (node.IsLeaf() && node.m_object != obj)
                {
                    overlaps.Insert(0, node.m_object);
                }
                else
                {
                    stack.Push(node.m_leftNodeIndex);
                    stack.Push(node.m_rightNodeIndex);
                }
            }
        }

        return(overlaps);
    }
Exemple #3
0
    public static List <Model3d> Query(OctreeNode node, AABB3d aabb)
    {
        //std::vector<Model*> result;
        List <Model3d> result = new List <Model3d>();

        if (IntersectionTest3D.AABB3dWithAABB3d(aabb, node.m_bounds))
        {
            if (node.m_children == null)
            {
                for (int i = 0, size = node.m_models.Count; i < size; ++i)
                {
                    OBB3d bounds = node.m_models[i].GetOBB();
                    if (IntersectionTest3D.AABB3dWithOBB3d(aabb, bounds))
                    {
                        result.Add(node.m_models[i]);
                    }
                }
            }
            else
            {
                for (int i = 0; i < 8; ++i)
                {
                    List <Model3d> child = Query(node.m_children[i], aabb);
                    if (child.Count > 0)
                    {
                        //result.insert(result.end(), child.begin(), child.end());
                        result.AddRange(child);
                    }
                }
            }
        }

        return(result);
    }
Exemple #4
0
 public EnergyTankData()
 {
     energy_tank_id = -1;
     energy         = 0;
     ownership      = GameConstants.eFaction.neutral;
     position       = new Point3d();
     boundingBox    = new AABB3d();
     room_key       = new RoomKey();
 }
Exemple #5
0
 public NavMesh()
 {
     m_roomKey              = null;
     m_boundingBox          = new AABB3d();
     m_rowCount             = 0;
     m_colomnCount          = 0;
     m_nonEmptyNavCellCount = 0;
     m_navCells             = null;
     m_pvs = null;
 }
    public AABB3d Merge(AABB3d other)
    {
        Vector3L selfMin  = GetMin();
        Vector3L otherMin = other.GetMin();
        Vector3L selfMax  = GetMax();
        Vector3L otherMax = GetMax();

        Vector3L totalMin = new Vector3L(FixPointMath.Min(selfMin.x, otherMin.x), FixPointMath.Min(selfMin.y, otherMin.y), FixPointMath.Min(selfMin.z, otherMin.z));
        Vector3L totalMax = new Vector3L(FixPointMath.Max(selfMax.x, otherMax.x), FixPointMath.Max(selfMax.y, otherMax.y), FixPointMath.Max(selfMax.z, otherMax.z));

        return(new AABB3d((totalMin + totalMax) / 2, totalMax - totalMin));
    }
Exemple #7
0
    public static Vector3L ClosestPointOfPoint3dWithAABB3d(Vector3L point, AABB3d aabb)
    {
        Vector3L result = point;
        Vector3L min    = aabb.GetMin();
        Vector3L max    = aabb.GetMax();

        result.x = (result.x < min.x) ? min.x : result.x;
        result.y = (result.y < min.x) ? min.y : result.y;
        result.z = (result.z < min.x) ? min.z : result.z;
        result.x = (result.x > max.x) ? max.x : result.x;
        result.y = (result.y > max.x) ? max.y : result.y;
        result.z = (result.z > max.x) ? max.z : result.z;
        return(result);
    }
Exemple #8
0
        public NavMesh(RoomKey roomKey, NavMesh navMeshTemplate)
        {
            m_roomKey     = new RoomKey(roomKey);
            m_boundingBox = new AABB3d(navMeshTemplate.m_boundingBox);

            m_rowCount             = navMeshTemplate.m_rowCount;
            m_colomnCount          = navMeshTemplate.m_colomnCount;
            m_nonEmptyNavCellCount = navMeshTemplate.m_nonEmptyNavCellCount;

            m_navCells = new NavCell[navMeshTemplate.m_navCells.Length];
            Array.Copy(navMeshTemplate.m_navCells, m_navCells, m_navCells.Length);

            m_pvs = new PotentiallyVisibleSet(navMeshTemplate.m_pvs);
        }
    public bool Contains(AABB3d other)
    {
        Vector3L selfMin  = GetMin();
        Vector3L otherMin = other.GetMin();
        Vector3L selfMax  = GetMax();
        Vector3L otherMax = GetMax();

        return(otherMin.x >= selfMin.x &&
               otherMax.x <= selfMax.x &&
               otherMin.y >= selfMin.y &&
               otherMax.y <= selfMax.y &&
               otherMin.z >= selfMin.z &&
               otherMax.z <= selfMax.z);
    }
    public bool Overlaps(AABB3d other)
    {
        Vector3L selfMin  = GetMin();
        Vector3L otherMin = other.GetMin();
        Vector3L selfMax  = GetMax();
        Vector3L otherMax = GetMax();

        // y is deliberately first in the list of checks below as it is seen as more likely than things
        // collide on x,z but not on y than they do on y thus we drop out sooner on a y fail
        return(selfMax.x > otherMin.x &&
               selfMin.x < otherMax.x &&
               selfMax.y > otherMin.y &&
               selfMin.y < otherMax.y &&
               selfMax.z > otherMin.z &&
               selfMin.z < otherMax.z);
    }
    void UpdateLeaf(int leafNodeIndex, AABB3d newAABB)
    {
        AABBTreeNode node = m_nodes[leafNodeIndex];

        // if the node contains the new aabb then we just leave things
        // TODO: when we add velocity this check should kick in as often an update will lie within the velocity fattened initial aabb
        // to support this we might need to differentiate between velocity fattened aabb and actual aabb
        if (node.m_bounds.Contains(newAABB))
        {
            return;
        }

        RemoveLeaf(leafNodeIndex);
        node.m_bounds = newAABB;
        InsertLeaf(leafNodeIndex);
    }
    public void SetContent(Mesh3d mesh)
    {
        m_mesh3d = mesh;

        Vector3L[] vertices = mesh.GetVertices();
        Vector3L   min      = vertices[0];
        Vector3L   max      = vertices[0];

        for (int i = 1; i < mesh.m_triangleList.Count * 3; ++i)
        {
            min.x = FixPointMath.Min(vertices[i].x, min.x);
            min.y = FixPointMath.Min(vertices[i].y, min.y);
            min.z = FixPointMath.Min(vertices[i].z, min.z);

            max.x = FixPointMath.Max(vertices[i].x, max.x);
            max.y = FixPointMath.Max(vertices[i].y, max.y);
            max.z = FixPointMath.Max(vertices[i].z, max.z);
        }
        m_aabb = Mesh3d.FromMinMax(min, max);
    }
Exemple #13
0
    public List <Model3d> Query(AABB3d aabb)
    {
        if (m_octree != null)
        {
            // :: lets the compiler know to look outside class scope
            return(Octree3d.Query(m_octree, aabb));
        }

        List <Model3d> result = new List <Model3d>();

        for (int i = 0, size = m_modleList.Count; i < size; ++i)
        {
            OBB3d bounds = m_modleList[i].GetOBB();
            if (IntersectionTest3D.AABB3dWithOBB3d(aabb, bounds))
            {
                result.Add(m_modleList[i]);
            }
        }
        return(result);
    }
Exemple #14
0
        private void NavCellsFromCompressedRawByteArray(
            byte[] compressedNavCells)
        {
            byte[] header       = new byte[COMPRESSED_DATA_HEADER_BYTE_COUNT];
            byte[] uncompressed =
                CompressionUtilities.RunLengthDecodeByteArray(
                    compressedNavCells,
                    CompressionUtilities.eEncodeType.Zeros,
                    header);
            BitArray navCellData = new BitArray(uncompressed);

            // Read out the header
            Debug.Assert(COMPRESSED_DATA_HEADER_BYTE_COUNT == 2);
            uint colomnCount = (uint)header[0];
            uint rowCount    = (uint)header[1];

            // Compute derived room properties
            int   navCellCount = (int)(rowCount * colomnCount);
            float roomWidth    = (float)colomnCount * GameConstants.NAV_MESH_WORLD_UNITS_SIZE;
            float roomHeight   = (float)rowCount * GameConstants.NAV_MESH_WORLD_UNITS_SIZE;

            // Initialize the nav cell derived data
            m_colomnCount          = colomnCount;
            m_rowCount             = rowCount;
            m_nonEmptyNavCellCount = 0;
            m_roomKey     = null;
            m_boundingBox = new AABB3d();
            m_boundingBox.SetBounds2d(-roomWidth / 2.0f, -roomHeight / 2.0f, roomWidth / 2.0f, roomHeight / 2.0f);

            // Truncate extra bits added due to the bit array getting rounded up to the nearest byte
            navCellData.Length = navCellCount;

            // Compute the connectivity data from the nav cell bit array
            NavMesh.BuildNavCellConnectivityGrid(
                colomnCount,
                rowCount,
                navCellData,
                out m_navCells,
                out m_nonEmptyNavCellCount);
        }
Exemple #15
0
        public void AppendAABB(AABB3d aabb)
        {
            Point3d p0 = aabb.Min;
            Point3d p1 = aabb.Max;

            int start = vertices.Count + 1;                                  // Vertex indices are 1-based, not 0-based

            vertices.Add(new Point3d(p0.x, p0.y, p0.z));                     // 0
            vertices.Add(new Point3d(p1.x, p0.y, p0.z));                     // 1
            vertices.Add(new Point3d(p1.x, p1.y, p0.z));                     // 2
            vertices.Add(new Point3d(p0.x, p1.y, p0.z));                     // 3
            vertices.Add(new Point3d(p0.x, p0.y, p1.z));                     // 4
            vertices.Add(new Point3d(p1.x, p0.y, p1.z));                     // 5
            vertices.Add(new Point3d(p1.x, p1.y, p1.z));                     // 6
            vertices.Add(new Point3d(p0.x, p1.y, p1.z));                     // 7

            faces.Add(new Face(start + 0, start + 1, start + 5, start + 4)); // -Y face
            faces.Add(new Face(start + 1, start + 2, start + 6, start + 5)); // +X face
            faces.Add(new Face(start + 2, start + 3, start + 7, start + 6)); // +Y face
            faces.Add(new Face(start + 3, start + 0, start + 4, start + 7)); // -X face
            faces.Add(new Face(start + 4, start + 5, start + 6, start + 7)); // +Z face
            faces.Add(new Face(start + 0, start + 3, start + 2, start + 1)); // -Z face
        }
        private void DumpLayoutGeometry(
            string dumpGeometryPath,
            DungeonLayout layout)
        {
            GeometryFileWriter fileWriter = new GeometryFileWriter();
            string             filename   = string.Format("DungeonLayout_Game{0}_Size{1}", layout.GameID, layout.LayoutWorldTemplate.dungeon_size);
            string             header     = string.Format("DungeonLayout for GameID:{0} DungeonSize: {1}", layout.GameID, layout.LayoutWorldTemplate.dungeon_size);
            string             result     = SuccessMessages.GENERAL_SUCCESS;
            Vector3d           roomSize   = new Vector3d(WorldConstants.ROOM_X_SIZE, WorldConstants.ROOM_Y_SIZE, WorldConstants.ROOM_Z_SIZE);

            for (DungeonLayout.RoomIndexIterator iterator = new DungeonLayout.RoomIndexIterator(layout.RoomGrid);
                 iterator.Valid;
                 iterator.Next())
            {
                DungeonLayout.RoomIndex roomIndex = iterator.Current;
                Room   room           = layout.GetRoomByIndex(roomIndex);
                AABB3d roomAABB       = new AABB3d(room.world_position, room.world_position + roomSize);
                AABB3d shrunkRoomAABB = roomAABB.ScaleAboutCenter(0.5f);
                AABB3d centerAABB     = roomAABB.ScaleAboutCenter(0.05f);

                // Add the AABB for this room
                fileWriter.AppendAABB(shrunkRoomAABB);

                // Create portal AABBs to all adjacent rooms
                for (MathConstants.eSignedDirection roomSide = MathConstants.eSignedDirection.first;
                     roomSide < MathConstants.eSignedDirection.count;
                     ++roomSide)
                {
                    if (room.RoomHasPortalOnSide(roomSide))
                    {
                        DungeonLayout.RoomIndex neighborRoomIndex = null;
                        switch (roomSide)
                        {
                        case MathConstants.eSignedDirection.positive_x:
                            neighborRoomIndex = roomIndex.Offset(1, 0, 0);
                            break;

                        case MathConstants.eSignedDirection.negative_x:
                            neighborRoomIndex = roomIndex.Offset(-1, 0, 0);
                            break;

                        case MathConstants.eSignedDirection.positive_y:
                            neighborRoomIndex = roomIndex.Offset(0, 1, 0);
                            break;

                        case MathConstants.eSignedDirection.negative_y:
                            neighborRoomIndex = roomIndex.Offset(0, -1, 0);
                            break;

                        case MathConstants.eSignedDirection.positive_z:
                            neighborRoomIndex = roomIndex.Offset(0, 0, 1);
                            break;

                        case MathConstants.eSignedDirection.negative_z:
                            neighborRoomIndex = roomIndex.Offset(0, 0, -1);
                            break;
                        }

                        Room   neighborRoom       = layout.GetRoomByIndex(neighborRoomIndex);
                        AABB3d neighborRoomAABB   = new AABB3d(neighborRoom.world_position, neighborRoom.world_position + roomSize);
                        AABB3d neighborCenterAABB = neighborRoomAABB.ScaleAboutCenter(0.05f);
                        AABB3d portalAABB         = centerAABB.EncloseAABB(neighborCenterAABB);

                        fileWriter.AppendAABB(portalAABB);
                    }
                }

                // TODO: DumpLayoutGeometry: Color the rooms by teleporter pair
            }

            if (!fileWriter.SaveFile(dumpGeometryPath, filename, header, out result))
            {
                _logger.WriteLine("DungeonValidator: WARNING: Failed to save layout geometry file");
                _logger.WriteLine(result);
            }
        }
Exemple #17
0
 public RoomPortal()
 {
     portal_id        = -1;
     target_portal_id = -1;
     boundingBox      = new AABB3d();
 }
Exemple #18
0
    public List <Model3d> CullByFrustum(Frustum3d frustum)
    {
        List <Model3d> result = new List <Model3d>();

        foreach (var iter in m_modleList)
        {
            iter.m_cullFlag = false;
        }

        if (m_octree == null)
        {
            foreach (var iter in m_modleList)
            {
                OBB3d bounds = iter.GetOBB();
                if (IntersectionTest3D.Frustum3dWithOBB3d(frustum, bounds))
                {
                    result.Add(iter);
                }
            }
        }
        else
        {
            List <OctreeNode> nodes = new List <OctreeNode>();
            nodes.Add(m_octree);

            while (nodes.Count > 0)
            {
                OctreeNode active = nodes[0];
                nodes.RemoveAt(0);

                if (active.m_children != null)
                {
                    // Has child nodes
                    for (int i = 0; i < 8; ++i)
                    {
                        AABB3d bounds = active.m_children[i].m_bounds;
                        if (IntersectionTest3D.Frustum3dWithAABB3d(frustum, bounds))
                        {
                            nodes.Add(active.m_children[i]);
                        }
                    }
                }
                else
                {
                    // Is leaf node
                    for (int i = 0; i < active.m_models.Count; ++i)
                    {
                        if (!active.m_models[i].m_cullFlag)
                        {
                            OBB3d bounds = active.m_models[i].GetOBB();
                            if (IntersectionTest3D.Frustum3dWithOBB3d(frustum, bounds))
                            {
                                active.m_models[i].m_cullFlag = true;
                                result.Add(active.m_models[i]);
                            }
                        }
                    }
                }
            }
        }

        return(result);
    }
    void InsertLeaf(int leafNodeIndex)
    {
        // make sure we're inserting a new leaf
        DebugHelper.Assert(m_nodes[leafNodeIndex].m_parentNodeIndex == NullIndex);
        DebugHelper.Assert(m_nodes[leafNodeIndex].m_leftNodeIndex == NullIndex);
        DebugHelper.Assert(m_nodes[leafNodeIndex].m_rightNodeIndex == NullIndex);

        // if the tree is empty then we make the root the leaf
        if (m_rootNodeIndex == NullIndex)
        {
            m_rootNodeIndex = leafNodeIndex;
            return;
        }

        // search for the best place to put the new leaf in the tree
        // we use surface area and depth as search heuristics
        int          treeNodeIndex = m_rootNodeIndex;
        AABBTreeNode leafNode      = m_nodes[leafNodeIndex];

        while (!m_nodes[treeNodeIndex].IsLeaf())
        {
            // because of the test in the while loop above we know we are never a leaf inside it
            AABBTreeNode treeNode       = m_nodes[treeNodeIndex];
            int          leftNodeIndex  = treeNode.m_leftNodeIndex;
            int          rightNodeIndex = treeNode.m_rightNodeIndex;
            AABBTreeNode leftNode       = m_nodes[leftNodeIndex];
            AABBTreeNode rightNode      = m_nodes[rightNodeIndex];

            AABB3d combinedAabb = treeNode.m_bounds.Merge(leafNode.m_bounds);

            FloatL newParentNodeCost   = 2.0f * combinedAabb.CalculateSurfaceArea();
            FloatL minimumPushDownCost = 2.0f * (combinedAabb.CalculateSurfaceArea() - treeNode.m_bounds.CalculateSurfaceArea());

            // use the costs to figure out whether to create a new parent here or descend
            FloatL costLeft;
            FloatL costRight;
            if (leftNode.IsLeaf())
            {
                costLeft = leafNode.m_bounds.Merge(leftNode.m_bounds).CalculateSurfaceArea() + minimumPushDownCost;
            }
            else
            {
                AABB3d newLeftAabb = leafNode.m_bounds.Merge(leftNode.m_bounds);
                costLeft = (newLeftAabb.CalculateSurfaceArea() - leftNode.m_bounds.CalculateSurfaceArea()) + minimumPushDownCost;
            }
            if (rightNode.IsLeaf())
            {
                costRight = leafNode.m_bounds.Merge(rightNode.m_bounds).CalculateSurfaceArea() + minimumPushDownCost;
            }
            else
            {
                AABB3d newRightAabb = leafNode.m_bounds.Merge(rightNode.m_bounds);
                costRight = (newRightAabb.CalculateSurfaceArea() - rightNode.m_bounds.CalculateSurfaceArea()) + minimumPushDownCost;
            }

            // if the cost of creating a new parent node here is less than descending in either direction then
            // we know we need to create a new parent node, errrr, here and attach the leaf to that
            if (newParentNodeCost < costLeft && newParentNodeCost < costRight)
            {
                break;
            }

            // otherwise descend in the cheapest direction
            if (costLeft < costRight)
            {
                treeNodeIndex = leftNodeIndex;
            }
            else
            {
                treeNodeIndex = rightNodeIndex;
            }
        }

        // the leafs sibling is going to be the node we found above and we are going to create a new
        // parent node and attach the leaf and this item
        int          leafSiblingIndex = treeNodeIndex;
        AABBTreeNode leafSibling      = m_nodes[leafSiblingIndex];
        int          oldParentIndex   = leafSibling.m_parentNodeIndex;
        int          newParentIndex   = AllocateNode();
        AABBTreeNode newParent        = m_nodes[newParentIndex];

        newParent.m_parentNodeIndex   = oldParentIndex;
        newParent.m_bounds            = leafNode.m_bounds.Merge(leafSibling.m_bounds); // the new parents aabb is the leaf aabb combined with it's siblings aabb
        newParent.m_leftNodeIndex     = leafSiblingIndex;
        newParent.m_rightNodeIndex    = leafNodeIndex;
        leafNode.m_parentNodeIndex    = newParentIndex;
        leafSibling.m_parentNodeIndex = newParentIndex;

        if (oldParentIndex == NullIndex)
        {
            // the old parent was the root and so this is now the root
            m_rootNodeIndex = newParentIndex;
        }
        else
        {
            // the old parent was not the root and so we need to patch the left or right index to
            // point to the new node
            AABBTreeNode oldParent = m_nodes[oldParentIndex];
            if (oldParent.m_leftNodeIndex == leafSiblingIndex)
            {
                oldParent.m_leftNodeIndex = newParentIndex;
            }
            else
            {
                oldParent.m_rightNodeIndex = newParentIndex;
            }
        }

        // finally we need to walk back up the tree fixing heights and areas
        treeNodeIndex = leafNode.m_parentNodeIndex;
        FixUpwardsTree(treeNodeIndex);
    }