/// <summary>
        /// edge p0 -> p1 is Anti aliased the others are not
        /// </summary>
        /// <param name="aaEdgeP0"></param>
        /// <param name="aaEdgeP1"></param>
        /// <param name="nonAaPoint"></param>
        public void Draw1EdgeTriangle(Vector2 aaEdgeP0, Vector2 aaEdgeP1, Vector2 nonAaPoint)
        {
            if (aaEdgeP0 == aaEdgeP1 || aaEdgeP1 == nonAaPoint || nonAaPoint == aaEdgeP0)
            {
                return;
            }

            Vector2 edgeP0P1Vector = aaEdgeP1 - aaEdgeP0;
            Vector2 edgeP0P1Normal = edgeP0P1Vector;

            edgeP0P1Normal.Normalize();

            Vector2 normal    = edgeP0P1Normal.GetPerpendicularRight();
            double  edgeDotP3 = Vector2.Dot(normal, nonAaPoint - aaEdgeP0);

            if (edgeDotP3 < 0)
            {
                edgeDotP3 = -edgeDotP3;
            }
            else
            {
                normal = -normal;
            }

            Vector2 edgeP0Offset;
            Vector2 edgeP1Offset;

            if (world != null)
            {
                // If world reference available, adjust the offset distance to screen space
                double unitsPerPixel;

                unitsPerPixel = world.GetWorldUnitsPerScreenPixelAtPosition(new Vector3(aaEdgeP0));
                edgeP0Offset  = aaEdgeP0 + (normal * unitsPerPixel);

                unitsPerPixel = world.GetWorldUnitsPerScreenPixelAtPosition(new Vector3(aaEdgeP1));
                edgeP1Offset  = aaEdgeP1 + (normal * unitsPerPixel);
            }
            else
            {
                edgeP0Offset = aaEdgeP0 + normal;
                edgeP1Offset = aaEdgeP1 + normal;
            }

            Vector2 texP0           = new Vector2(1 / 1023.0, .25);
            Vector2 texP1           = new Vector2(1 / 1023.0, .75);
            Vector2 texP2           = new Vector2((1 + edgeDotP3) / 1023.0, .25);
            Vector2 texEdgeP0Offset = new Vector2(0, .25);
            Vector2 texEdgeP1Offset = new Vector2(0, .75);

            FanStart(texP0, aaEdgeP0, texEdgeP0Offset, edgeP0Offset);
            FanDo(texEdgeP1Offset, edgeP1Offset);
            FanDo(texP1, aaEdgeP1);
            FanDo(texP2, nonAaPoint);
        }
Пример #2
0
        public void WorldViewPerspectiveProjectionTests()
        {
            var world = new WorldView(1, 1);

            Assert.IsTrue(world.EyePosition.Equals(Vector3.UnitZ * 7, 1e-3));
            world.CalculatePerspectiveMatrixOffCenter(567, 123, -200, 5, 55);
            Assert.IsTrue(world.GetScreenPosition(new Vector3(0, 0, 0)).Equals(new Vector2((567 - 200) / 2.0, 123 / 2.0), 1e-3));
            Assert.AreEqual(5, world.NearZ, 1e-3);
            Assert.AreEqual(55, world.FarZ, 1e-3);
            Assert.AreEqual(4.14213562373095, world.NearPlaneHeightInViewspace, 1e-3);
            var ray = world.GetRayForLocalBounds(new Vector2((567 - 200) / 2.0, 123));             // top center

            Assert.AreEqual(WorldView.DefaultPerspectiveVFOVDegrees / 2, MathHelper.RadiansToDegrees(Math.Atan2(ray.directionNormal.Y, -ray.directionNormal.Z)), 1e-3);
            Assert.IsTrue((Vector3.UnitZ * 7).Equals(ray.origin, 1e-3));
            Assert.AreEqual(world.NearPlaneHeightInViewspace * 2, world.GetViewspaceHeightAtPosition(new Vector3(1, 1, -10)), 1e-3);
            world.Scale = 3;
            Assert.AreEqual(world.NearPlaneHeightInViewspace * 2 / 3, world.GetWorldUnitsPerScreenPixelAtPosition(new Vector3(1, 1, (7 - 10) / 3.0)) * 123, 1e-3);
        }
Пример #3
0
        public void WorldViewOrthographicProjectionTests()
        {
            var world = new WorldView(1, 1);

            Assert.IsTrue(world.EyePosition.Equals(Vector3.UnitZ * 7, 1e-3));
            world.CalculateOrthogrphicMatrixOffCenterWithViewspaceHeight(680, 240, -200, 128, 5, 55);
            Assert.IsTrue(world.GetScreenPosition(new Vector3(0, 0, 0)).Equals(new Vector2((680 - 200) / 2.0, 240 / 2.0), 1e-3));
            Assert.IsTrue(world.GetScreenPosition(new Vector3(128, 64, 0)).Equals(new Vector2(680 - 200, 240), 1e-3));
            Assert.IsTrue(world.GetScreenPosition(new Vector3(-128, -64, 0)).Equals(new Vector2(0, 0), 1e-3));
            Assert.AreEqual(5, world.NearZ, 1e-3);
            Assert.AreEqual(55, world.FarZ, 1e-3);
            Assert.AreEqual(128, world.NearPlaneHeightInViewspace, 1e-3);
            var ray = world.GetRayForLocalBounds(new Vector2((680 - 200) / 2.0, 240));             // top center

            Assert.IsTrue(Vector3.UnitZ.Equals(-ray.directionNormal.GetNormal(), 1e-3));
            Assert.IsTrue(new Vector3(0, 64, 2).Equals(ray.origin, 1e-3));
            Assert.AreEqual(world.NearPlaneHeightInViewspace, world.GetViewspaceHeightAtPosition(new Vector3(1, 1, -10)), 1e-3);
            world.Scale = 3;
            Assert.AreEqual(world.NearPlaneHeightInViewspace / 3, world.GetWorldUnitsPerScreenPixelAtPosition(new Vector3(1, 1, (7 - 10) / 3.0)) * 240, 1e-3);
        }
Пример #4
0
        private void RenderSelection(IObject3D item, Color selectionColor, WorldView world)
        {
            if (item.Mesh == null)
            {
                return;
            }

            // Turn off lighting
            GL.Disable(EnableCap.Lighting);
            // Only render back faces
            GL.CullFace(CullFaceMode.Front);

            // Expand the object
            var    worldMatrix = item.WorldMatrix();
            var    worldBounds = item.Mesh.GetAxisAlignedBoundingBox(worldMatrix);
            var    worldCenter = worldBounds.Center;
            double distBetweenPixelsWorldSpace = world.GetWorldUnitsPerScreenPixelAtPosition(worldCenter);
            var    pixelsAccross = worldBounds.Size / distBetweenPixelsWorldSpace;
            var    pixelsWant    = pixelsAccross + Vector3.One * 4 * Math.Sqrt(2);

            var wantMm = pixelsWant * distBetweenPixelsWorldSpace;

            var scaleMatrix = worldMatrix.ApplyAtPosition(worldCenter, Matrix4X4.CreateScale(
                                                              wantMm.X / worldBounds.XSize,
                                                              wantMm.Y / worldBounds.YSize,
                                                              wantMm.Z / worldBounds.ZSize));

            GLHelper.Render(item.Mesh,
                            selectionColor,
                            scaleMatrix,
                            RenderTypes.Shaded,
                            null,
                            darkWireframe);

            // restore settings
            GL.CullFace(CullFaceMode.Back);
            GL.Enable(EnableCap.Lighting);
        }
Пример #5
0
        public static void Render3DLineNoPrep(this WorldView world, Frustum clippingFrustum, Vector3 start, Vector3 end, Color color, double width = 1)
        {
            if (clippingFrustum.ClipLine(ref start, ref end))
            {
                double unitsPerPixelStart = world.GetWorldUnitsPerScreenPixelAtPosition(start);
                double unitsPerPixelEnd   = world.GetWorldUnitsPerScreenPixelAtPosition(end);

                Vector3   delta           = start - end;
                var       deltaLength     = delta.Length;
                Matrix4X4 rotateTransform = Matrix4X4.CreateRotation(new Quaternion(Vector3.UnitX + new Vector3(.0001, -.00001, .00002), -delta / deltaLength));
                Matrix4X4 scaleTransform  = Matrix4X4.CreateScale(deltaLength, 1, 1);
                Vector3   lineCenter      = (start + end) / 2;
                Matrix4X4 lineTransform   = scaleTransform * rotateTransform * Matrix4X4.CreateTranslation(lineCenter);

                var startScale = unitsPerPixelStart * width;
                var endScale   = unitsPerPixelEnd * width;
                for (int i = 0; i < unscaledLineMesh.Vertices.Count; i++)
                {
                    var vertexPosition = unscaledLineMesh.Vertices[i];
                    if (vertexPosition.X < 0)
                    {
                        scaledLineMesh.Vertices[i] = new Vector3Float(vertexPosition.X, vertexPosition.Y * startScale, vertexPosition.Z * startScale);
                    }
                    else
                    {
                        scaledLineMesh.Vertices[i] = new Vector3Float(vertexPosition.X, vertexPosition.Y * endScale, vertexPosition.Z * endScale);
                    }
                }

                if (true)
                {
                    GL.Color4(color.Red0To255, color.Green0To255, color.Blue0To255, color.Alpha0To255);

                    if (color.Alpha0To1 < 1)
                    {
                        GL.Enable(EnableCap.Blend);
                    }
                    else
                    {
                        //GL.Disable(EnableCap.Blend);
                    }

                    GL.MatrixMode(MatrixMode.Modelview);
                    GL.PushMatrix();
                    GL.MultMatrix(lineTransform.GetAsFloatArray());

                    GL.Begin(BeginMode.Triangles);
                    for (int faceIndex = 0; faceIndex < scaledLineMesh.Faces.Count; faceIndex++)
                    {
                        var face     = scaledLineMesh.Faces[faceIndex];
                        var vertices = scaledLineMesh.Vertices;
                        var position = vertices[face.v0];
                        GL.Vertex3(position.X, position.Y, position.Z);
                        position = vertices[face.v1];
                        GL.Vertex3(position.X, position.Y, position.Z);
                        position = vertices[face.v2];
                        GL.Vertex3(position.X, position.Y, position.Z);
                    }
                    GL.End();
                    GL.PopMatrix();
                }
                else
                {
                    scaledLineMesh.MarkAsChanged();

                    GLHelper.Render(scaledLineMesh, color, lineTransform, RenderTypes.Shaded);
                }
            }
        }
Пример #6
0
        public static void Render3DLineNoPrep(this WorldView world,
                                              Frustum clippingFrustum,
                                              Vector3 start,
                                              Vector3 end,
                                              Color color,
                                              double width    = 1,
                                              bool startArrow = false,
                                              bool endArrow   = false)
        {
            if (clippingFrustum.ClipLine(ref start, ref end))
            {
                double startScale = world.GetWorldUnitsPerScreenPixelAtPosition(start);
                double endScale   = world.GetWorldUnitsPerScreenPixelAtPosition(end);

                Vector3 delta       = start - end;
                var     normal      = delta.GetNormal();
                var     arrowWidth  = 3 * width;
                var     arrowLength = 6 * width;
                if (startArrow || endArrow)
                {
                    // move the start and end points
                    if (startArrow)
                    {
                        start -= normal * startScale * arrowLength;
                    }

                    if (endArrow)
                    {
                        end += normal * endScale * arrowLength;
                    }

                    delta = start - end;
                }

                var       deltaLength     = delta.Length;
                var       rotateTransform = Matrix4X4.CreateRotation(new Quaternion(Vector3.UnitX + new Vector3(.0001, -.00001, .00002), -delta / deltaLength));
                var       scaleTransform  = Matrix4X4.CreateScale(deltaLength, 1, 1);
                Vector3   lineCenter      = (start + end) / 2;
                Matrix4X4 lineTransform   = scaleTransform * rotateTransform * Matrix4X4.CreateTranslation(lineCenter);

                var startWidth = startScale * width;
                var endWidth   = endScale * width;
                for (int i = 0; i < unscaledLineMesh.Vertices.Count; i++)
                {
                    var vertexPosition = unscaledLineMesh.Vertices[i];
                    if (vertexPosition.X < 0)
                    {
                        scaledLineMesh.Vertices[i] = new Vector3Float(vertexPosition.X, vertexPosition.Y * startWidth, vertexPosition.Z * startWidth);
                    }
                    else
                    {
                        scaledLineMesh.Vertices[i] = new Vector3Float(vertexPosition.X, vertexPosition.Y * endWidth, vertexPosition.Z * endWidth);
                    }
                }

                // render the line mesh directly
                GL.Color4(color.Red0To255, color.Green0To255, color.Blue0To255, color.Alpha0To255);
                GL.Enable(EnableCap.Blend);

                GL.MatrixMode(MatrixMode.Modelview);
                GL.PushMatrix();
                GL.MultMatrix(lineTransform.GetAsFloatArray());

                GL.Begin(BeginMode.Triangles);
                for (int faceIndex = 0; faceIndex < scaledLineMesh.Faces.Count; faceIndex++)
                {
                    var face     = scaledLineMesh.Faces[faceIndex];
                    var vertices = scaledLineMesh.Vertices;
                    var position = vertices[face.v0];
                    GL.Vertex3(position.X, position.Y, position.Z);
                    position = vertices[face.v1];
                    GL.Vertex3(position.X, position.Y, position.Z);
                    position = vertices[face.v2];
                    GL.Vertex3(position.X, position.Y, position.Z);
                }
                GL.End();

                GL.PopMatrix();

                // render the arrows if any
                if (startArrow)
                {
                    RenderHead(start, startScale, normal, arrowWidth, arrowLength, false);
                }

                if (endArrow)
                {
                    RenderHead(end, startScale, normal, arrowWidth, arrowLength, true);
                }
            }
        }