예제 #1
0
        private List <GraphicsTriangle> projectVisibleTriangles()
        {
            //create a look at matrix to transfrom the environment objects from world space to view space
            Matrix4x4 viewMatrix = Matrix4x4.CreateLookAt(Position, Position + Direction, new Vector3(0, 1, 0));

            List <GraphicsTriangle> trianglesToRaster = new List <GraphicsTriangle>();

            //loops through each object in the environment and if any triangle of the object can be seen, it gets projected
            //to view space and clips them against the near plane (so objects behind the camera aren't rendered)
            foreach (EnvironmentObject e in Environment.EnvironmentObjects)
            {
                List <GraphicsTriangle> triangles = e.Mesh.GraphicsTriangles;
                for (int i = 0; i < triangles.Count; ++i)
                {
                    GraphicsTriangle t = triangles[i]; //Current triangle

                    //Creates vector from the camera position to the triangle, if the dot product is less than 0 then the camera
                    //can see the triangle so the projection and clipping can be done
                    if (GraphicsVector3.Dot(t.Normal, t.Points[0] - Position) < 0.0f)
                    {
                        GraphicsTriangle projected = t.Copy();
                        //Convert from world space to view space (Still 3D)
                        projected.TransformMatrix4x4(viewMatrix);

                        //Clip the triangle against the near plane while adding it to the list of triangles to raster
                        trianglesToRaster.AddRange(ClipTriangleAgainstPlane(new Vector3(0f, 0f, 0.1f), new Vector3(0f, 0f, 1f), projected));
                    }
                }
            }

            return(trianglesToRaster);
        }
예제 #2
0
        private void drawTrangle(Graphics graphics, GraphicsTriangle triangle, Color c, int lineWeight)
        {
            Line l1 = new Line((int)triangle.Points[0].Value.X, (int)triangle.Points[0].Value.Y, (int)triangle.Points[1].Value.X, (int)triangle.Points[1].Value.Y);
            Line l2 = new Line((int)triangle.Points[0].Value.X, (int)triangle.Points[0].Value.Y, (int)triangle.Points[2].Value.X, (int)triangle.Points[2].Value.Y);
            Line l3 = new Line((int)triangle.Points[1].Value.X, (int)triangle.Points[1].Value.Y, (int)triangle.Points[2].Value.X, (int)triangle.Points[2].Value.Y);

            drawLine(graphics, l1, c, lineWeight);
            drawLine(graphics, l2, c, lineWeight);
            drawLine(graphics, l3, c, lineWeight);
        }
예제 #3
0
 private GraphicsTriangle ConvertToScreenSpace(GraphicsTriangle triangle, float frameWidth, float frameHeight)
 {
     GraphicsVector3[] newPoints = new GraphicsVector3[3];
     for (int i = 0; i < 3; ++i)
     {
         GraphicsVector3 newPoint = GraphicsVector3.Transform(triangle.Points[i], projectionMatrix);
         newPoint.Value   /= newPoint.W;
         newPoint.Value.X += 1.0f;
         newPoint.Value.Y += 1.0f;
         newPoint.Value.X *= (0.5f * frameWidth);
         newPoint.Value.Y *= (0.5f * frameHeight);
         newPoints[i]      = newPoint;
     }
     return(new GraphicsTriangle(newPoints, triangle.TexturePoints, triangle.Normal, triangle.Color));
 }
예제 #4
0
 private void fillTriangle(Graphics graphics, GraphicsTriangle triangle, Color c, float brightness)
 {
     c = Color.FromArgb((int)(c.R * brightness), (int)(c.G * brightness), (int)(c.B * brightness));
     Array.Sort(triangle.Points, delegate(GraphicsVector3 vec1, GraphicsVector3 vec2) { return(vec1.Value.Y.CompareTo(vec2.Value.Y)); });
     if (triangle.Points[1].Value.Y == triangle.Points[2].Value.Y)
     {
         fillFlatBottomTriangle(graphics, triangle.Points, c);
     }
     else if (triangle.Points[0].Value.Y == triangle.Points[1].Value.Y)
     {
         fillFlatTopTriangle(graphics, triangle.Points, c);
     }
     else
     {
         GraphicsVector3 v4 = new GraphicsVector3(new Vector3((int)(triangle.Points[0].Value.X + (triangle.Points[1].Value.Y - triangle.Points[0].Value.Y) / (triangle.Points[2].Value.Y - triangle.Points[0].Value.Y) * (triangle.Points[2].Value.X - triangle.Points[0].Value.X)), triangle.Points[1].Value.Y, 1));
         fillFlatBottomTriangle(graphics, new GraphicsVector3[] { triangle.Points[0], triangle.Points[1], v4 }, c);
         fillFlatTopTriangle(graphics, new GraphicsVector3[] { triangle.Points[1], v4, triangle.Points[2] }, c);
     }
 }
예제 #5
0
 public void FillTriangle(GraphicsTriangle triangle, Color c, float brightness)
 {
     Instructions.Add(new GraphicsInstruction(GraphicsInstructions.FillTriangle, triangle, c, brightness));
 }
예제 #6
0
 public void DrawTriangle(GraphicsTriangle triangle, Color c, int lineWeight)
 {
     Instructions.Add(new GraphicsInstruction(GraphicsInstructions.DrawTriangle, triangle, c, lineWeight));
 }
예제 #7
0
        public override Frame GetFrame()
        {
            frame.Clear();

            Vector3 lightDirection = Vector3.Normalize(new Vector3(-0.75f, -1f, -0.5f));

            //Get all the triangles that can be seen by the camera projected to view space

            List <GraphicsTriangle> trianglesToRaster = projectVisibleTriangles();

            //Loop through all of the projected and clipped triangles
            foreach (GraphicsTriangle tri in trianglesToRaster)
            {
                //obtain the brightness value by evaluating the the dot product between the normal of the triangle's surface
                //and the direction of the light
                float brightness = Vector3.Dot(tri.Normal, lightDirection);
                if (brightness < 0)
                {
                    brightness = 0;
                }

                //converts the triangle in 3D view space into a normalized (x and y between -1 and 1) 2D screen space
                GraphicsTriangle nearPlaneClipped = ConvertToScreenSpace(tri.Copy(), FrameWidth, FrameHeight);

                //stores the triangles to clipped against the edges of the screen, so we put in the original to be clipped by the first edge
                //The size of this will change as the triangles in this list get clipped by the edges
                List <GraphicsTriangle> clipQueue = new List <GraphicsTriangle>()
                {
                    nearPlaneClipped
                };

                //loop through the four edges of screen
                for (int j = 0; j < 4; ++j)
                {
                    //holds the triangles that the triangles in clipQueue become as they are clipped by the current clipping edge
                    List <GraphicsTriangle> newTris = new List <GraphicsTriangle>();

                    //loop through all of the triangles in clipQueue in order to clip them be the current clipping edge
                    foreach (GraphicsTriangle current in clipQueue)
                    {
                        //to select the plane we are clipping based on the loop interation
                        switch (j)
                        {
                        case 0:
                            //clip against the top edge of the screen
                            newTris.AddRange(ClipTriangleAgainstPlane(new Vector3(0, 0, 0), new Vector3(0, -1, 0), current));
                            break;

                        case 1:
                            //clip against left edge of the screen
                            newTris.AddRange(ClipTriangleAgainstPlane(new Vector3(0, 0, 0), new Vector3(-1, 0, 0), current));
                            break;

                        case 2:
                            //clip against bottom edge of the screen
                            newTris.AddRange(ClipTriangleAgainstPlane(new Vector3(0, -FrameHeight, 0), new Vector3(0, 1, 0), current));
                            break;

                        case 3:
                            //clip against right edge of the screen
                            newTris.AddRange(ClipTriangleAgainstPlane(new Vector3(-FrameWidth, 0, 0), new Vector3(1, 0, 0), current));
                            break;
                        }
                    }

                    //once all of the triangles in clipQueue have been clipped by the edge, newTris will be populated by said clipped triangles
                    //But all of these clipped triangles also need to be clipped by the remaining edges so we must set the clipQueue to newTris
                    clipQueue.Clear();           //set it to a new list
                    clipQueue.AddRange(newTris); //add the clipped triangles
                }

                //once the loop of clipping the edges has completed, clipQueue should be full of the triangles that need to be rastered

                //Draw them all!
                foreach (GraphicsTriangle rasterReady in clipQueue)
                {
                    frame.FillTriangle(rasterReady, rasterReady.Color, brightness);
                    frame.DrawTriangle(rasterReady, Color.White, 2);
                }
            }

            return(frame);
        }
예제 #8
0
        private GraphicsTriangle[] ClipTriangleAgainstPlane(Vector3 planePosition, Vector3 planeNormal, GraphicsTriangle triangle)
        {
            planeNormal = Vector3.Normalize(planeNormal);

            List <GraphicsVector3> insidePoints  = new List <GraphicsVector3>();
            List <GraphicsVector3> outsidePoints = new List <GraphicsVector3>();

            List <TextureVector> insideTexturePoints  = new List <TextureVector>();
            List <TextureVector> outsideTexturePoints = new List <TextureVector>();

            float[] distances = new float[3];
            for (int i = 0; i < 3; ++i)
            {
                distances[i] = GetShortestDistanceToPlane(triangle.Points[i], planePosition, planeNormal);
            }

            for (int i = 0; i < 3; ++i)
            {
                if (distances[i] >= 0)
                {
                    insidePoints.Add(triangle.Points[i]);
                    insideTexturePoints.Add(triangle.TexturePoints[i]);
                }
                else
                {
                    outsidePoints.Add(triangle.Points[i]);
                    outsideTexturePoints.Add(triangle.TexturePoints[i]);
                }
            }

            if (insidePoints.Count == 0)
            {
                return(new GraphicsTriangle[] { });
            }

            if (insidePoints.Count == 3)
            {
                return(new GraphicsTriangle[] { triangle });
            }

            if (insidePoints.Count == 1 && outsidePoints.Count == 2)
            {
                GraphicsVector3 p1  = insidePoints[0];
                TextureVector   tp1 = insideTexturePoints[0];

                float t;

                GraphicsVector3 p2  = LinePlaneIntersection(planePosition, planeNormal, p1, outsidePoints[0], out t);
                TextureVector   tp2 = clipTextureVector(insideTexturePoints[0], outsideTexturePoints[0], t);

                GraphicsVector3 p3  = LinePlaneIntersection(planePosition, planeNormal, p1, outsidePoints[1], out t);
                TextureVector   tp3 = clipTextureVector(insideTexturePoints[0], outsideTexturePoints[1], t);

                return(new GraphicsTriangle[] { new GraphicsTriangle(p1, p2, p3, tp1, tp2, tp3, triangle.Normal, triangle.Color) });
            }

            if (insidePoints.Count == 2 && outsidePoints.Count == 1)
            {
                float t;

                GraphicsVector3 t1p1 = insidePoints[0];
                GraphicsVector3 t1p2 = insidePoints[1];
                GraphicsVector3 t1p3 = LinePlaneIntersection(planePosition, planeNormal, t1p1, outsidePoints[0], out t);

                TextureVector t1tp1 = insideTexturePoints[0];
                TextureVector t1tp2 = insideTexturePoints[1];
                TextureVector t1tp3 = clipTextureVector(t1tp1, outsideTexturePoints[0], t);

                GraphicsVector3 t2p1 = insidePoints[1];
                GraphicsVector3 t2p2 = t1p3;
                GraphicsVector3 t2p3 = LinePlaneIntersection(planePosition, planeNormal, t2p1, outsidePoints[0], out t);

                TextureVector t2tp1 = insideTexturePoints[1];
                TextureVector t2tp2 = t1tp3;
                TextureVector t2tp3 = clipTextureVector(t2tp1, outsideTexturePoints[0], t);

                return(new GraphicsTriangle[] {
                    new GraphicsTriangle(t1p1, t1p3, t1p2, t1tp1, t1tp2, t1tp3, triangle.Normal, triangle.Color),
                    new GraphicsTriangle(t2p1, t2p2, t2p3, t2tp1, t2tp2, t2tp3, triangle.Normal, triangle.Color)
                });
            }
            return(null); //To satisfy the compliers :(
        }