예제 #1
0
        public void Start()
        {
            camera = new Camera();
            draw   = new DrawString();

            input = new Thread(ManageInput);
            input.Start();

            // Perspective Projection

            /*Sources:
             * https://stackoverflow.com/questions/53245632/general-formula-for-perspective-projection-matrix
             * https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/building-basic-perspective-projection-matrix
             */

            float fovRad = 1.0f / (float)Math.Tan(camera.Fov * 0.5f * (Math.PI / 180.0f));

            perspProjection = new float[4, 4] {
                { fovRad *ASPECT_RATIO, 0, 0, 0 },
                { 0, fovRad, 0, 0 },
                { 0, 0, -camera.FarPlane / (camera.FarPlane - camera.NearPlane), -(camera.FarPlane * camera.NearPlane) / (camera.FarPlane - camera.NearPlane) },
                { 0, 0, 1, 0 }
            };

            // ######################
        }
예제 #2
0
        private Mat4x4 GetViewMatrix()
        {
            float cosPitch = (float)Math.Cos(Pitch * (Math.PI / 180.0f));
            float sinPitch = (float)Math.Sin(Pitch * (Math.PI / 180.0f));

            float cosYaw = (float)Math.Cos(Yaw * (Math.PI / 180.0f));
            float sinYaw = (float)Math.Sin(Yaw * (Math.PI / 180.0f));

            float cosRoll = (float)Math.Cos(Roll * (Math.PI / 180.0f));
            float sinRoll = (float)Math.Sin(Roll * (Math.PI / 180.0f));

            Mat4x4 rotX = new float[4, 4] {
                { 1, 0, 0, 0 },
                { 0, cosPitch, -sinPitch, 0 },
                { 0, sinPitch, cosPitch, 0 },
                { 0, 0, 0, 1 }
            };

            Mat4x4 rotY = new float[4, 4] {
                { cosYaw, 0, sinYaw, 0 },
                { 0, 1, 0, 0 },
                { -sinYaw, 0, cosYaw, 0 },
                { 0, 0, 0, 1 }
            };

            Mat4x4 rotZ = new float[4, 4] {
                { cosRoll, -sinRoll, 0, 0 },
                { sinRoll, cosRoll, 0, 0 },
                { 0, 0, 1, 0 },
                { 0, 0, 0, 1 }
            };

            Mat4x4 camRot = Mat4x4.MatMul(rotZ, rotY);

            camRot = Mat4x4.MatMul(camRot, rotX);

            Vector up     = new Vector(0, 1, 0);
            Vector target = new Vector(0, 0, 1);

            Vector lookDir = Mat4x4.MatMul(target, camRot);

            target = Position + lookDir;

            return(LookAt(Position, target, up));
        }
예제 #3
0
        // https://learnopengl.com/Getting-started/Camera
        public Mat4x4 LookAt(Vector worldPos, Vector targetPos, Vector newUp)
        {
            Forward = (targetPos - worldPos).Normalized;

            Up = (newUp - (Forward * Vector.DotProduct(newUp, Forward))).Normalized;

            Right = Vector.CrossProduct(Up, Forward);

            Mat4x4 rotation = new float[4, 4] {
                { Right.X, Right.Y, Right.Z, 0 },
                { Up.X, Up.Y, Up.Z, 0 },
                { Forward.X, Forward.Y, Forward.Z, 0 },
                { 0, 0, 0, 1 }
            };

            Mat4x4 translation = new float[4, 4] {
                { 1, 0, 0, -Position.X },
                { 0, 1, 0, -Position.Y },
                { 0, 0, 1, -Position.Z },
                { 0, 0, 0, 1 }
            };

            return(Mat4x4.MatMul(rotation, translation));
        }
예제 #4
0
        // Render 3D Objects
        private void Render3D()
        {
            //Mat4x4 camTranform = Mat4x4.MatMul(Mat4x4.VecToMat(camera.Position), Mat4x4.VecToMat())

            Light simpleLight = new Light {
                Direction = new Vector(0, 0, 1)
            };

            simpleLight.Direction.Normalize();

            Mat4x4 rotationX = new float[4, 4] {
                { 1, 0, 0, 0 },
                { 0, (float)Math.Cos(xAngle), (float)-Math.Sin(xAngle), 0 },
                { 0, (float)Math.Sin(xAngle), (float)Math.Cos(xAngle), 0 },
                { 0, 0, 0, 1 }
            };

            Mat4x4 rotationY = new float[4, 4] {
                { (float)Math.Cos(yAngle), 0, (float)Math.Sin(yAngle), 0 },
                { 0, 1, 0, 0 },
                { (float)-Math.Sin(yAngle), 0, (float)Math.Cos(yAngle), 0 },
                { 0, 0, 0, 1 }
            };

            Mat4x4 rotationZ = new float[4, 4] {
                { (float)Math.Cos(zAngle), (float)-Math.Sin(zAngle), 0, 0 },
                { (float)Math.Sin(zAngle), (float)Math.Cos(zAngle), 0, 0 },
                { 0, 0, 1, 0 },
                { 0, 0, 0, 1 }
            };

            // XYZ rotation = (((Z * Y) * X) * Vector) or (Z×Y×X)×V
            Mat4x4 rotMatrix = Mat4x4.MatMul(rotationZ, rotationY);

            rotMatrix = Mat4x4.MatMul(rotMatrix, rotationX);

            Mat4x4 mvp = ortho ? Mat4x4.MatMul(orthoProjection, camera.ViewMatrix) : Mat4x4.MatMul(perspProjection, camera.ViewMatrix);

            Triangle[] updatedTri = new Triangle[mesh.Polygons.Length];

            for (int i = 0; i < mesh.Polygons.Length; i++)
            {
                updatedTri[i] = new Triangle(new Vector[mesh.Polygons[i].VertexCount]);

                for (int j = 0; j < mesh.Polygons[i].VertexCount; j++)
                {
                    // Apply rotation to vertex
                    Vector rotated = Mat4x4.MatMul(mesh.Polygons[i][j], rotMatrix);

                    // Translate vertex (slightly) to not draw on top of camera
                    Vector translated = new Vector(rotated.X, rotated.Y, rotated.Z + 3.0f);

                    updatedTri[i][j] = translated;
                }

                float lightDP = Math.Max(0.1f, Vector.DotProduct(updatedTri[i].Normal, simpleLight.Direction));
                ShadeTri(ref updatedTri[i], lightDP);
            }

            Triangle[] projected = new Triangle[mesh.Polygons.Length];

            for (int i = 0; i < projected.Length; i++)
            {
                projected[i] = updatedTri[i];

                for (int j = 0; j < projected[i].VertexCount; j++)
                {
                    projected[i][j] = Mat4x4.MatMul(projected[i][j], mvp);

                    // Scale Vectors
                    projected[i][j] *= ortho ? 20.0f : projectionScale;  // Magic numbers :(
                }
            }

            if (rotate)
            {
                if (rotateX)
                {
                    xAngle -= 0.03f;
                }
                if (rotateY)
                {
                    yAngle -= 0.03f;
                }
                if (rotateZ)
                {
                    zAngle -= 0.03f;
                }
            }

            if (hasMesh && hasSurface)
            {
                // Plot Faces and Mesh

                // After testing with modified versions of the methods below
                // it's safe to assume this needs its own method

                // If implementation becomes unnecessary, remove this
            }
            else if (hasSurface)
            {
                draw.PlotFaces(projected);
            }
            else if (hasMesh)
            {
                draw.PlotMesh(projected);
            }
            else
            {
                draw.PlotVertices(projected);
            }
        }