コード例 #1
0
        private void UpdataAABB(double elapsed)
        {
            AABB.Clear();
            for (int i = 0; i < Count; i++)
            {
                float x = PointMassList[i].Position.X;
                float y = PointMassList[i].Position.Y;

                AABB.Add(x, y);

                x += (float)(PointMassList[i].Velocity.X * elapsed);
                y += (float)(PointMassList[i].Velocity.Y * elapsed);

                AABB.Add(x, y);
            }
        }
コード例 #2
0
        /// <summary> Add a primitive to the spatial bin and clip it </summary>
        /// <param name="primitive">The primitive to add to the bin</param>
        public void ClipAndAdd(Primitive primitive)
        {
            PrimitiveFragment?fragment = primitive.Clip(SplitPlaneLeft)?.Clip(SplitPlaneRight);

            if (fragment == null)
            {
                return;
            }
            Fragments.Add(fragment);
            AABB.Add(fragment);
        }
コード例 #3
0
    //----------------------------------------------------------------------------------------
    //
    //----------------------------------------------------------------------------------------
    public void Build(VOXLoader.VoxelData[] data, int max_primitive = 64, int max_depth = 32)
    {
        var Stopwatch = new Stopwatch();

        Stopwatch.Start();

        m_VoxelArray           = data;
        m_MaxPrimitivesPerLeaf = max_primitive;

        m_NumNodes      = 0;
        m_NumLeaves     = 0;
        m_NumPrimitives = 0;

        AABB RootAABB = new AABB(data[0].Pos, new Vector3(0.5f, 0.5f, 0.5f));

        for (int i = 1; i < data.Length; i++)
        {
            RootAABB.Add(new AABB(data[i].Pos, new Vector3(0.5f, 0.5f, 0.5f)));
        }

        m_RootNode = new TreeNode();
        m_NumNodes++;
        m_RootNode.m_AABB     = new AABB(Vector3.zero, Vector3.zero);
        m_RootNode.m_AABB.Min = RootAABB.Min;
        m_RootNode.m_AABB.Max = RootAABB.Max;

        m_ProcessedVoxelArray = new bool[m_VoxelArray.Length];
        for (int i = 0; i < m_ProcessedVoxelArray.Length; i++)
        {
            m_ProcessedVoxelArray[i] = false;
        }

        SplitNode(m_RootNode);

        ComputeTreeDepth();

        Serialize();

        Stopwatch.Stop();
        m_BuidTime = Stopwatch.ElapsedMilliseconds;
    }
コード例 #4
0
        // Combines multiple meshes into one
        #region Combine
        public static CSGMesh Combine(Vector3 offset, IDictionary <CSGNode, CSGMesh> brushMeshes)
        {
            var planeLookup  = new Dictionary <Plane, short>();
            var vertexLookup = new Dictionary <Vector3, short>();

            var planes   = new List <Plane>();
            var polygons = new List <Polygon>();
            var edges    = new List <HalfEdge>();
            var vertices = new List <Vector3>();

            var bounds = new AABB();

            bounds.Clear();
            int edgeIndex    = 0;
            int polygonIndex = 0;

            foreach (var item in brushMeshes)
            {
                var node        = item.Key;
                var translation = Vector3.Subtract(node.Translation, offset);
                var mesh        = item.Value;
                foreach (var edge in mesh.Edges)
                {
                    short vertexIndex;
                    var   vertex = Vector3.Add(mesh.Vertices[edge.VertexIndex], translation);
                    if (!vertexLookup.TryGetValue(vertex, out vertexIndex))
                    {
                        vertexIndex = (short)vertices.Count;
                        vertices.Add(vertex);
                        vertexLookup.Add(vertex, vertexIndex);
                    }

                    var newEdge = new HalfEdge();
                    newEdge.VertexIndex  = vertexIndex;
                    newEdge.NextIndex    = (short)(edge.NextIndex + edgeIndex);
                    newEdge.TwinIndex    = (short)(edge.TwinIndex + edgeIndex);
                    newEdge.PolygonIndex = (short)(edge.PolygonIndex + polygonIndex);

                    edges.Add(newEdge);
                }

                foreach (var polygon in mesh.Polygons)
                {
                    if (polygon.FirstIndex == -1)
                    {
                        continue;
                    }
                    short planeIndex;
                    var   plane = mesh.Planes[polygon.PlaneIndex];
                    if (!planeLookup.TryGetValue(plane, out planeIndex))
                    {
                        planeIndex = (short)planes.Count;
                        planes.Add(plane);
                        planeLookup.Add(plane, planeIndex);
                    }

                    var newPolygon = new Polygon();
                    newPolygon.PlaneIndex = planeIndex;
                    newPolygon.FirstIndex = (short)(polygon.FirstIndex + edgeIndex);
                    newPolygon.Category   = polygon.Category;
                    newPolygon.Visible    = polygon.Visible;
                    newPolygon.Bounds.Set(polygon.Bounds, translation);

                    polygons.Add(newPolygon);

                    if (newPolygon.Visible)
                    {
                        var first    = edges[newPolygon.FirstIndex];
                        var iterator = first;
                        do
                        {
                            bounds.Add(vertices[iterator.VertexIndex]);
                            iterator = edges[iterator.NextIndex];
                        } while (iterator != first);
                    }
                }
                edgeIndex    = edges.Count;
                polygonIndex = polygons.Count;
            }
            return(new CSGMesh(planes.ToArray(), polygons, edges, vertices, bounds));
        }
コード例 #5
0
        public static CSGMesh CreateFromPlanes(Plane[] brushPlanes)
        {
            var planes = new Plane[brushPlanes.Length];

            for (int i = 0; i < brushPlanes.Length; i++)
            {
                var plane = brushPlanes[i];
                planes[i] = new Plane(plane.A, plane.B, plane.C, plane.D);
            }

            var pointIntersections = new List <PointIntersection>(planes.Length * planes.Length);
            var intersectingPlanes = new List <short>();
            var vertices           = new List <Vector3>();
            var edges = new List <HalfEdge>();

            // Find all point intersections where 3 (or more planes) intersect
            for (short planeIndex1 = 0; planeIndex1 < planes.Length - 2; planeIndex1++)
            {
                var plane1 = planes[planeIndex1];
                for (short planeIndex2 = (short)(planeIndex1 + 1); planeIndex2 < planes.Length - 1; planeIndex2++)
                {
                    var plane2 = planes[planeIndex2];
                    for (short planeIndex3 = (short)(planeIndex2 + 1); planeIndex3 < planes.Length; planeIndex3++)
                    {
                        var plane3 = planes[planeIndex3];

                        // Calculate the intersection
                        var vertex = Plane.Intersection(plane1, plane2, plane3);

                        // Check if the intersection is valid
                        if (float.IsNaN(vertex.X) || float.IsNaN(vertex.Y) || float.IsNaN(vertex.Z) ||
                            float.IsInfinity(vertex.X) || float.IsInfinity(vertex.Y) || float.IsInfinity(vertex.Z))
                        {
                            continue;
                        }

                        intersectingPlanes.Clear();
                        intersectingPlanes.Add(planeIndex1);
                        intersectingPlanes.Add(planeIndex2);
                        intersectingPlanes.Add(planeIndex3);

                        for (short planeIndex4 = 0; planeIndex4 < planes.Length; planeIndex4++)
                        {
                            if (planeIndex4 == planeIndex1 ||
                                planeIndex4 == planeIndex2 ||
                                planeIndex4 == planeIndex3)
                            {
                                continue;
                            }

                            var plane4 = planes[planeIndex4];
                            var side   = plane4.OnSide(vertex);
                            if (side == PlaneSideResult.Intersects)
                            {
                                if (planeIndex4 < planeIndex3)
                                {
                                    // Already found this vertex
                                    goto SkipIntersection;
                                }

                                // We've found another plane which goes trough our found intersection point
                                intersectingPlanes.Add(planeIndex4);
                            }
                            else
                            if (side == PlaneSideResult.Outside)
                            {
                                // Intersection is outside of brush
                                goto SkipIntersection;
                            }
                        }

                        var vertexIndex = (short)vertices.Count;
                        vertices.Add(vertex);

                        // Add intersection point to our list
                        pointIntersections.Add(new PointIntersection(vertexIndex, intersectingPlanes));

SkipIntersection:
                        ;
                    }
                }
            }

            var foundPlanes = new short[2];

            // Find all our intersection edges which are formed by a pair of planes
            // (this could probably be done inside the previous loop)
            for (int i = 0; i < pointIntersections.Count; i++)
            {
                var pointIntersectionA = pointIntersections[i];
                for (int j = i + 1; j < pointIntersections.Count; j++)
                {
                    var pointIntersectionB = pointIntersections[j];
                    var planesIndicesA     = pointIntersectionA.PlaneIndices;
                    var planesIndicesB     = pointIntersectionB.PlaneIndices;

                    short foundPlaneIndex = 0;
                    foreach (var currentPlaneIndex in planesIndicesA)
                    {
                        if (!planesIndicesB.Contains(currentPlaneIndex))
                        {
                            continue;
                        }

                        foundPlanes[foundPlaneIndex] = currentPlaneIndex;
                        foundPlaneIndex++;

                        if (foundPlaneIndex == 2)
                        {
                            break;
                        }
                    }

                    // If foundPlaneIndex is 0 or 1 then either this combination does not exist,
                    // or only goes trough one point
                    if (foundPlaneIndex < 2)
                    {
                        continue;
                    }

                    // Create our found intersection edge
                    var halfEdgeA      = new HalfEdge();
                    var halfEdgeAIndex = (short)edges.Count;
                    edges.Add(halfEdgeA);

                    var halfEdgeB      = new HalfEdge();
                    var halfEdgeBIndex = (short)edges.Count;
                    edges.Add(halfEdgeB);

                    halfEdgeA.TwinIndex = halfEdgeBIndex;
                    halfEdgeB.TwinIndex = halfEdgeAIndex;

                    halfEdgeA.VertexIndex = pointIntersectionA.VertexIndex;
                    halfEdgeB.VertexIndex = pointIntersectionB.VertexIndex;

                    // Add it to our points
                    pointIntersectionA.Edges.Add(new EdgeIntersection(
                                                     halfEdgeA,
                                                     foundPlanes[0],
                                                     foundPlanes[1]));
                    pointIntersectionB.Edges.Add(new EdgeIntersection(
                                                     halfEdgeB,
                                                     foundPlanes[0],
                                                     foundPlanes[1]));
                }
            }


            var polygons = new List <Polygon>();

            for (short i = 0; i < (short)planes.Length; i++)
            {
                var polygon = new Polygon();
                polygon.PlaneIndex = i;
                polygons.Add(polygon);
            }

            var bounds    = new AABB();
            var direction = new Vector3();

            for (int i = pointIntersections.Count - 1; i >= 0; i--)
            {
                var pointIntersection = pointIntersections[i];
                var pointEdges        = pointIntersection.Edges;

                // Make sure that we have at least 2 edges ...
                // This may happen when a plane only intersects at a single edge.
                if (pointEdges.Count <= 2)
                {
                    pointIntersections.RemoveAt(i);
                    continue;
                }

                var vertexIndex = pointIntersection.VertexIndex;
                var vertex      = vertices[vertexIndex];

                for (int j = 0; j < pointEdges.Count - 1; j++)
                {
                    var edge1 = pointEdges[j];
                    for (int k = j + 1; k < pointEdges.Count; k++)
                    {
                        var edge2 = pointEdges[k];

                        int planeIndex1 = -1;
                        int planeIndex2 = -1;

                        // Determine if and which of our 2 planes are identical
                        if (edge1.PlaneIndices[0] == edge2.PlaneIndices[0])
                        {
                            planeIndex1 = 0; planeIndex2 = 0;
                        }
                        else
                        if (edge1.PlaneIndices[0] == edge2.PlaneIndices[1])
                        {
                            planeIndex1 = 0; planeIndex2 = 1;
                        }
                        else
                        if (edge1.PlaneIndices[1] == edge2.PlaneIndices[0])
                        {
                            planeIndex1 = 1; planeIndex2 = 0;
                        }
                        else
                        if (edge1.PlaneIndices[1] == edge2.PlaneIndices[1])
                        {
                            planeIndex1 = 1; planeIndex2 = 1;
                        }
                        else
                        {
                            continue;
                        }

                        HalfEdge ingoing;
                        HalfEdge outgoing;
                        short    outgoingIndex;

                        var shared_plane = planes[edge1.PlaneIndices[planeIndex1]];
                        var edge1_plane  = planes[edge1.PlaneIndices[1 - planeIndex1]];
                        var edge2_plane  = planes[edge2.PlaneIndices[1 - planeIndex2]];

                        direction = Vector3.Cross(shared_plane.Normal, edge1_plane.Normal);

                        // Determine the orientation of our two edges to determine
                        // which edge is in-going, and which one is out-going
                        if (Vector3.Dot(direction, edge2_plane.Normal) < 0)
                        {
                            ingoing       = edge2.Edge;
                            outgoingIndex = edge1.Edge.TwinIndex;
                            outgoing      = edges[outgoingIndex];
                        }
                        else
                        {
                            ingoing       = edge1.Edge;
                            outgoingIndex = edge2.Edge.TwinIndex;
                            outgoing      = edges[outgoingIndex];
                        }


                        // Link the out-going half-edge to the in-going half-edge
                        ingoing.NextIndex = outgoingIndex;


                        // Add reference to polygon to half-edge, and make sure our
                        // polygon has a reference to a half-edge
                        // Since a half-edge, in this case, serves as a circular
                        // linked list this just works.
                        var polygonIndex = edge1.PlaneIndices[planeIndex1];

                        ingoing.PolygonIndex  = polygonIndex;
                        outgoing.PolygonIndex = polygonIndex;

                        var polygon = polygons[polygonIndex];
                        polygon.FirstIndex = outgoingIndex;
                        polygon.Bounds.Add(vertex);
                    }
                }

                // Add the intersection point to the area of our bounding box
                bounds.Add(vertex);
            }

            return(new CSGMesh(planes, polygons, edges, vertices, bounds));
        }
コード例 #6
0
    //----------------------------------------------------------------------------------------
    //
    //----------------------------------------------------------------------------------------
    void SplitNode(TreeNode node)
    {
        Axis SelectedAxis;

        Vector3 Size = node.m_AABB.Max - node.m_AABB.Min;

        if (Size.x >= Size.y && Size.x >= Size.z)
        {
            SelectedAxis = Axis.Axis_X;
        }
        else if (Size.y >= Size.x && Size.y >= Size.z)
        {
            SelectedAxis = Axis.Axis_Y;
        }
        else
        {
            SelectedAxis = Axis.Axis_Z;
        }

        AABB LAABB = new AABB(Vector3.zero, Vector3.zero);
        AABB RAABB = new AABB(Vector3.zero, Vector3.zero);

        float Len, LLen, RLen;

        switch (SelectedAxis)
        {
        case Axis.Axis_X:
            Len       = (node.m_AABB.Max.x - node.m_AABB.Min.x);
            LLen      = UnityEngine.Mathf.Ceil(Len * 0.5f);
            LAABB.Min = node.m_AABB.Min;
            LAABB.Max = new Vector3(LAABB.Min.x + LLen, node.m_AABB.Max.y, node.m_AABB.Max.z);

            RLen      = Len - LLen;
            RAABB.Max = node.m_AABB.Max;
            RAABB.Min = new Vector3(RAABB.Max.x - RLen, node.m_AABB.Min.y, node.m_AABB.Min.z);
            break;

        case Axis.Axis_Y:
            Len       = (node.m_AABB.Max.y - node.m_AABB.Min.y);
            LLen      = UnityEngine.Mathf.Ceil(Len * 0.5f);
            LAABB.Min = node.m_AABB.Min;
            LAABB.Max = new Vector3(node.m_AABB.Max.x, LAABB.Min.y + LLen, node.m_AABB.Max.z);

            RLen      = Len - LLen;
            RAABB.Max = node.m_AABB.Max;
            RAABB.Min = new Vector3(node.m_AABB.Min.x, RAABB.Max.y - RLen, node.m_AABB.Min.z);
            break;

        case Axis.Axis_Z:
            Len       = (node.m_AABB.Max.z - node.m_AABB.Min.z);
            LLen      = UnityEngine.Mathf.Ceil(Len * 0.5f);
            LAABB.Min = node.m_AABB.Min;
            LAABB.Max = new Vector3(node.m_AABB.Max.x, node.m_AABB.Max.y, LAABB.Min.z + LLen);

            RLen      = Len - LLen;
            RAABB.Max = node.m_AABB.Max;
            RAABB.Min = new Vector3(node.m_AABB.Min.x, node.m_AABB.Min.y, RAABB.Max.z - RLen);
            break;
        }

        List <int> VoxelList = new List <int>();

        AABB NodeAABB = new AABB(Vector3.zero, Vector3.zero);

        for (int v = 0; v < m_VoxelArray.Length; v++)
        {
            if (!m_ProcessedVoxelArray[v])
            {
                if (m_VoxelArray[v].Pos.x >= LAABB.Min.x && m_VoxelArray[v].Pos.x <= LAABB.Max.x &&
                    m_VoxelArray[v].Pos.y >= LAABB.Min.y && m_VoxelArray[v].Pos.y <= LAABB.Max.y &&
                    m_VoxelArray[v].Pos.z >= LAABB.Min.z && m_VoxelArray[v].Pos.z <= LAABB.Max.z)
                {
                    VoxelList.Add(v);
                    if (VoxelList.Count == 1)
                    {
                        NodeAABB.Min = m_VoxelArray[v].Pos - new Vector3(0.5f, 0.5f, 0.5f);
                        NodeAABB.Max = m_VoxelArray[v].Pos + new Vector3(0.5f, 0.5f, 0.5f);
                    }
                    else
                    {
                        NodeAABB.Add(new AABB(m_VoxelArray[v].Pos, new Vector3(0.5f, 0.5f, 0.5f)));
                    }
                }
            }
        }
        if (VoxelList.Count <= m_MaxPrimitivesPerLeaf) //is leaf
        {
            node.m_LNode            = new TreeNode();
            node.m_LNode.m_AABB     = new AABB(Vector3.zero, Vector3.zero);
            node.m_LNode.m_AABB.Min = NodeAABB.Min;
            node.m_LNode.m_AABB.Max = NodeAABB.Max;

            node.m_LNode.m_Leaf = new TreeLeaf();
            m_NumLeaves++;
            node.m_LNode.m_Leaf.m_RimitiveList = new List <int>();
            for (int v = 0; v < VoxelList.Count; v++)
            {
                node.m_LNode.m_Leaf.m_RimitiveList.Add(VoxelList[v]);
                m_ProcessedVoxelArray[VoxelList[v]] = true;
            }

            m_NumPrimitives += node.m_LNode.m_Leaf.m_RimitiveList.Count;
        }
        else
        {
            node.m_LNode = new TreeNode();
            m_NumNodes++;
            node.m_LNode.m_AABB     = new AABB(Vector3.zero, Vector3.zero);
            node.m_LNode.m_AABB.Min = NodeAABB.Min;
            node.m_LNode.m_AABB.Max = NodeAABB.Max;
            SplitNode(node.m_LNode);
        }

        VoxelList.Clear();
        for (int v = 0; v < m_VoxelArray.Length; v++)
        {
            if (!m_ProcessedVoxelArray[v])
            {
                if (m_VoxelArray[v].Pos.x >= RAABB.Min.x && m_VoxelArray[v].Pos.x <= RAABB.Max.x &&
                    m_VoxelArray[v].Pos.y >= RAABB.Min.y && m_VoxelArray[v].Pos.y <= RAABB.Max.y &&
                    m_VoxelArray[v].Pos.z >= RAABB.Min.z && m_VoxelArray[v].Pos.z <= RAABB.Max.z)
                {
                    VoxelList.Add(v);
                    if (VoxelList.Count == 1)
                    {
                        NodeAABB.Min = m_VoxelArray[v].Pos - new Vector3(0.5f, 0.5f, 0.5f);
                        NodeAABB.Max = m_VoxelArray[v].Pos + new Vector3(0.5f, 0.5f, 0.5f);
                    }
                    else
                    {
                        NodeAABB.Add(new AABB(m_VoxelArray[v].Pos, new Vector3(0.5f, 0.5f, 0.5f)));
                    }
                }
            }
        }
        if (VoxelList.Count <= m_MaxPrimitivesPerLeaf) //is leaf
        {
            node.m_RNode            = new TreeNode();
            node.m_RNode.m_AABB     = new AABB(Vector3.zero, Vector3.zero);
            node.m_RNode.m_AABB.Min = NodeAABB.Min;
            node.m_RNode.m_AABB.Max = NodeAABB.Max;

            node.m_RNode.m_Leaf = new TreeLeaf();
            m_NumLeaves++;
            node.m_RNode.m_Leaf.m_RimitiveList = new List <int>();
            for (int v = 0; v < VoxelList.Count; v++)
            {
                node.m_RNode.m_Leaf.m_RimitiveList.Add(VoxelList[v]);
                m_ProcessedVoxelArray[VoxelList[v]] = true;
            }

            m_NumPrimitives += node.m_RNode.m_Leaf.m_RimitiveList.Count;
        }
        else
        {
            node.m_RNode = new TreeNode();
            m_NumNodes++;
            node.m_RNode.m_AABB     = new AABB(Vector3.zero, Vector3.zero);
            node.m_RNode.m_AABB.Min = NodeAABB.Min;
            node.m_RNode.m_AABB.Max = NodeAABB.Max;
            SplitNode(node.m_RNode);
        }
    }