示例#1
0
        /// <summary>
        /// Triangulate this csg and pack the triangulated data into buffers
        /// appropriate for use with gltf.
        /// </summary>
        internal static GraphicsBuffers Tessellate(this Csg.Solid csg)
        {
            var buffers = new GraphicsBuffers();

            ushort iCursor = 0;

            (Vector3 U, Vector3 V)basis;

            const float SEARCH_RADIUS = 0.001f;

            // Setup the octree to fit around the csg.
            // This requires one expensive initialization.
            var verts  = csg.Polygons.SelectMany(p => p.Vertices).Select(v => v.Pos.ToElementsVector()).ToArray();
            var bounds = new BBox3(verts);
            var center = bounds.Center();
            var origin = new Point((float)center.X, (float)center.Y, (float)center.Z);
            var size   = (float)bounds.Max.DistanceTo(bounds.Min);
            var octree = new PointOctree <(Vector3 position, Vector3 normal, ushort index)>(size, origin, SEARCH_RADIUS);

            foreach (var p in csg.Polygons)
            {
                var vertexIndices = new ushort[p.Vertices.Count];

                var a = p.Vertices[0].Pos.ToElementsVector();
                var b = p.Vertices[1].Pos.ToElementsVector();
                var c = p.Vertices[2].Pos.ToElementsVector();
                basis = ComputeBasisAndNormalForTriangle(a, b, c, out Vector3 normal);

                // Anything with 3 vertices is a triangle. Manually
                // tesselate triangles. For everything else, use
                // the tessellator.
                if (p.Vertices.Count > 2 && p.Vertices.Count <= 3)
                {
                    for (var i = 0; i < p.Vertices.Count; i++)
                    {
                        var v = p.Vertices[i];

                        var op = new Point((float)v.Pos.X, (float)v.Pos.Y, (float)v.Pos.Z);
                        var ep = v.Pos.ToElementsVector();
                        if (TryGetExistingVertex(op, ep, octree, normal, SEARCH_RADIUS, out ushort vertexIndex))
                        {
                            vertexIndices[i] = vertexIndex;
                            continue;
                        }

                        vertexIndices[i] = iCursor;
                        iCursor++;

                        var uu = basis.U.Dot(ep);
                        var vv = basis.V.Dot(ep);
                        buffers.AddVertex(ep, normal, new UV(uu, vv));

                        octree.Add((ep, normal, vertexIndices[i]), op);
示例#2
0
文件: Line.cs 项目: jmerlan/Elements
        /// <summary>
        /// Does this line touches or intersects the provided box in 3D?
        /// </summary>
        /// <param name="box"></param>
        /// <param name="results"></param>
        /// <param name="infinite">Treat the line as infinite?</param>
        /// <returns>True if the line touches or intersects the  box at least at one point, false otherwise.</returns>
        public bool Intersects(BBox3 box, out List <Vector3> results, bool infinite = false)
        {
            var d = End - Start;

            results = new List <Vector3>();

            // Solving the t parameter on line were it intersects planes of box in different coordinates.
            // If vector has no change in particular coordinate - just skip it as infinity.
            var t0x = double.NegativeInfinity;
            var t1x = double.PositiveInfinity;

            if (Math.Abs(d.X) > 1e-6)
            {
                t0x = (box.Min.X - Start.X) / d.X;
                t1x = (box.Max.X - Start.X) / d.X;
                // Line can reach min plane of box before reaching max.
                if (t1x < t0x)
                {
                    (t0x, t1x) = (t1x, t0x);
                }
            }

            var t0y = double.NegativeInfinity;
            var t1y = double.PositiveInfinity;

            if (Math.Abs(d.Y) > 1e-6)
            {
                t0y = (box.Min.Y - Start.Y) / d.Y;
                t1y = (box.Max.Y - Start.Y) / d.Y;
                if (t1y < t0y)
                {
                    (t0y, t1y) = (t1y, t0y);
                }
            }

            // If max hit of one coordinate is smaller then min hit of other - line hits planes outside the box.
            // In other words line just goes by.
            if (t0x > t1y || t0y > t1x)
            {
                return(false);
            }

            var tMin = Math.Max(t0x, t0y);
            var tMax = Math.Min(t1x, t1y);

            if (Math.Abs(d.Z) > 1e-6)
            {
                var t0z = (box.Min.Z - Start.Z) / d.Z;
                var t1z = (box.Max.Z - Start.Z) / d.Z;

                if (t1z < t0z)
                {
                    (t0z, t1z) = (t1z, t0z);
                }

                if (t0z > tMax || t1z < tMin)
                {
                    return(false);
                }

                tMin = Math.Max(t0z, tMin);
                tMax = Math.Min(t1z, tMax);
            }

            if (tMin == double.NegativeInfinity || tMin == double.PositiveInfinity)
            {
                return(false);
            }

            // Check if found parameters are within normalized line range.
            if (infinite || (tMin > -Vector3.EPSILON && tMin < 1 + Vector3.EPSILON))
            {
                results.Add(Start + d * tMin);
            }

            if (Math.Abs(tMax - tMin) > Vector3.EPSILON &&
                (infinite || (tMax > -Vector3.EPSILON && tMax < 1 + Vector3.EPSILON)))
            {
                results.Add(Start + d * tMax);
            }

            return(results.Any());
        }