示例#1
0
        public void FaceLineIntersectionTest()
        {
            var plane = new Plane(new Coordinate(0, 0, 1), 100);
            var face = new Face(1) {Plane = plane};
            var coords = new[]
                             {
                                 new Coordinate(-100, -100, 100),
                                 new Coordinate(100, -100, 100),
                                 new Coordinate(100, 100, 100),
                                 new Coordinate(-100, 100, 100)
                             };
            face.Vertices.AddRange(coords.Select(x => new Vertex(x, face)));
            face.CalculateTextureCoordinates(true);

            var passLine = new Line(new Coordinate(0, 0, 0), new Coordinate(0, 0, 200));
            var reversePassLine = passLine.Reverse();
            var failSegment = new Line(new Coordinate(0, 0, 0), new Coordinate(0, 0, 50));
            var failLine = new Line(new Coordinate(0, 0, 0), new Coordinate(1, 0, 0));
            var outsideFaceLine = new Line(new Coordinate(200, 0, 0), new Coordinate(200, 0, 200));

            var pass1 = face.GetIntersectionPoint(passLine);

            var fail1 = face.GetIntersectionPoint(reversePassLine);
            var fail2 = face.GetIntersectionPoint(failSegment);
            var fail3 = face.GetIntersectionPoint(failLine);
            var fail4 = face.GetIntersectionPoint(outsideFaceLine);

            Assert.IsNotNull(pass1);
            Assert.IsNull(fail1);
            Assert.IsNull(fail2);
            Assert.IsNull(fail3);
            Assert.IsNull(fail4);
        }
示例#2
0
        public void CalculateDecalGeometry()
        {
            _decalGeometry = new List<Face>();
            if (Decal == null) return; // Texture not found

            var boxRadius = Coordinate.One * 4;
            // Decals apply to all faces that intersect within an 8x8x8 bounding box
            // centered at the origin of the decal
            var box = new Box(Origin - boxRadius, Origin + boxRadius);
            var root = GetRoot(Parent);
            // Get the faces that intersect with the decal's radius
            var faces = root.GetAllNodesIntersectingWith(box).OfType<Solid>()
                .SelectMany(x => x.Faces).Where(x => x.IntersectsWithBox(box));
            var idg = new IDGenerator(); // Dummy generator
            foreach (var face in faces)
            {
                // Project the decal onto the face
                var center = face.Plane.Project(Origin);
                var texture = face.Texture.Clone();
                texture.Name = Decal.Name;
                texture.Texture = Decal;
                texture.XShift = -Decal.Width / 2m;
                texture.YShift = -Decal.Height / 2m;
                var decalFace = new Face(idg.GetNextFaceID())
                                    {
                                        Colour = Colour,
                                        IsSelected = IsSelected,
                                        IsHidden = IsCodeHidden,
                                        Plane = face.Plane,
                                        Texture = texture
                                    };
                // Re-project the vertices in case the texture axes are not on the face plane
                var xShift = face.Texture.UAxis * face.Texture.XScale * Decal.Width / 2;
                var yShift = face.Texture.VAxis * face.Texture.YScale * Decal.Height / 2;
                var verts = new[]
                                {
                                    new Vertex(face.Plane.Project(center + xShift - yShift), decalFace), // Bottom Right
                                    new Vertex(face.Plane.Project(center + xShift + yShift), decalFace), // Top Right
                                    new Vertex(face.Plane.Project(center - xShift + yShift), decalFace), // Top Left
                                    new Vertex(face.Plane.Project(center - xShift - yShift), decalFace)  // Bottom Left
                                };

                // Because the texture axes don't have to align to the face, we might have a reversed face here
                // If so, reverse the points to get a valid face for the plane.
                // TODO: Is there a better way to do this?
                var vertPlane = new Plane(verts[0].Location, verts[1].Location, verts[2].Location);
                if (!face.Plane.Normal.EquivalentTo(vertPlane.Normal))
                {
                    Array.Reverse(verts);
                }

                decalFace.Vertices.AddRange(verts);
                decalFace.UpdateBoundingBox();

                // Calculate the X and Y shift bases on the first vertex location (assuming U/V of first vertex is zero) - we dont want these to change
                var vtx = decalFace.Vertices[0];
                decalFace.Texture.XShift = -(vtx.Location.Dot(decalFace.Texture.UAxis)) / decalFace.Texture.XScale;
                decalFace.Texture.YShift = -(vtx.Location.Dot(decalFace.Texture.VAxis)) / decalFace.Texture.YScale;
                decalFace.CalculateTextureCoordinates();

                // Next, the decal geometry needs to be clipped to the face so it doesn't spill into the void
                // Create a fake solid out of the decal geometry and clip it against all the brush planes
                var fake = CreateFakeDecalSolid(decalFace);

                foreach (var f in face.Parent.Faces.Except(new[] { face }))
                {
                    Solid back, front;
                    fake.Split(f.Plane, out back, out front, idg);
                    fake = back ?? fake;
                }

                // Extract out the original face
                decalFace = fake.Faces.First(x => x.Plane.EquivalentTo(face.Plane, 0.05m));

                // Add a tiny bit to the normal axis to ensure the decal is rendered in front of the face
                var normalAdd = face.Plane.Normal * 0.2m;
                decalFace.Transform(new UnitTranslate(normalAdd), TransformFlags.TextureLock);

                _decalGeometry.Add(decalFace);
            }
        }
示例#3
0
 private void CreateFace(Polygon polygon, Solid parent, Face original)
 {
     var verts = polygon.Vertices;
     var f = new Face(Document.Map.IDGenerator.GetNextFaceID())
     {
         Parent = parent,
         Plane = new Plane(verts[0], verts[1], verts[2]),
         Colour = parent.Colour,
         Texture = original.Texture.Clone()
     };
     f.Vertices.AddRange(verts.Select(x => new Vertex(x, f)));
     f.UpdateBoundingBox();
     f.CalculateTextureCoordinates(true);
     parent.Faces.Add(f);
 }