private void AddFaceToZBuffer( Face face, int meshDimension, ref Matrix4x4 modelToView, ref Matrix4x4 viewToScreen, ref Matrix4x4 screenToWindow) { // Reset the vertices to model space values face.ResetVertices(); // Draw outline if needed ?? if (face.DrawOutline) { DrawEdge(face.p1, face.p2, Color.Black, ref modelToView, ref viewToScreen); DrawEdge(face.p1, face.p3, Color.Black, ref modelToView, ref viewToScreen); DrawEdge(face.p2, face.p3, Color.Black, ref modelToView, ref viewToScreen); } // Move the face from model space to view space face.ApplyMatrix(modelToView); if (meshDimension == 3) { // Discard the face if it is not visible from the camera's point of view if ((Vector3D)face.p1 * Vector3D.NormalFromPlane((Vector3D)face.p1, (Vector3D)face.p2, (Vector3D)face.p3) >= 0) { return; } } // Clip the face in view space Queue <Face> faceClip = new(); faceClip.Enqueue(face); if (!Clipping.ClipFaces(faceClip, this.ViewClippingPlanes)) { return; } // Move the new triangles from view space to screen space, including a correction for perspective foreach (Face clippedFace in faceClip) { clippedFace.ApplyMatrix(viewToScreen); if (this is PerspectiveCamera) { clippedFace.p1 /= clippedFace.p1.w; clippedFace.p2 /= clippedFace.p2.w; clippedFace.p3 /= clippedFace.p3.w; if (face.HasTexture) { clippedFace.t1 /= clippedFace.p1.w; clippedFace.t2 /= clippedFace.p2.w; clippedFace.t3 /= clippedFace.p3.w; } } } // Clip the face in screen space if (Settings.Screen_Space_Clip && !Clipping.ClipFaces(faceClip, ScreenClippingPlanes)) { return; } // anything outside cube? foreach (Face clippedFace in faceClip) { // Skip the face if it is flat if ((clippedFace.p1.x == clippedFace.p2.x && clippedFace.p2.x == clippedFace.p3.x) || (clippedFace.p1.y == clippedFace.p2.y && clippedFace.p2.y == clippedFace.p3.y)) { continue; } // Move the new triangles from screen space to window space clippedFace.ApplyMatrix(screenToWindow); // Round the vertices int x1 = clippedFace.p1.x.RoundToInt(); int y1 = clippedFace.p1.y.RoundToInt(); float z1 = clippedFace.p1.z; int x2 = clippedFace.p2.x.RoundToInt(); int y2 = clippedFace.p2.y.RoundToInt(); float z2 = clippedFace.p2.z; int x3 = clippedFace.p3.x.RoundToInt(); int y3 = clippedFace.p3.y.RoundToInt(); float z3 = clippedFace.p3.z; // Check if the face has a texture if (face.HasTexture) { // Scale the texture co-ordinates int textureWidth = face.Texture_Object.File.Width - 1; int textureHeight = face.Texture_Object.File.Height - 1; // afterwards? float tx1 = face.T1.x * textureWidth; float ty1 = face.T1.y * textureHeight; float tz1 = face.T1.z; float tx2 = face.T2.x * textureWidth; float ty2 = face.T2.y * textureHeight; float tz2 = face.T2.z; float tx3 = face.T3.x * textureWidth; float ty3 = face.T3.y * textureHeight; float tz3 = face.T3.z; // Sort the vertices by their y-co-ordinate NumericManipulation.TexturedSortByY ( ref x1, ref y1, ref tx1, ref ty1, ref tz1, ref x2, ref y2, ref tx2, ref ty2, ref tz2, ref x3, ref y3, ref tx3, ref ty3, ref tz3 ); // Generate z-buffer Textured_Triangle ( face.Texture_Object.File, x1, y1, tx1, ty1, tz1, x2, y2, tx2, ty2, tz2, x3, y3, tx3, ty3, tz3 ); } else { // Sort the vertices by their y-co-ordinate NumericManipulation.SortByY ( ref x1, ref y1, ref z1, ref x2, ref y2, ref z2, ref x3, ref y3, ref z3 ); // Generate z-buffer Interpolation.InterpolateTriangle ( ZBufferCheck, face.Colour, x1, y1, z1, x2, y2, z2, x3, y3, z3 ); } } }
private void CalculateDepth( Face face, int meshDimension, ref Matrix4x4 modelToView) { // Reset the vertices to model space values face.ResetVertices(); // Move the face from model space to view space face.ApplyMatrix(modelToView); if (meshDimension == 3) { // Discard the face if it is not visible from the light's point of view if ((Vector3D)face.p1 * Vector3D.NormalFromPlane((Vector3D)face.p1, (Vector3D)face.p2, (Vector3D)face.p3) >= 0) { return; } } // Clip the face in view space Queue <Face> faceClip = new(); faceClip.Enqueue(face); if (!Clipping.ClipFaces(faceClip, ViewClippingPlanes)) { return; } // Move the new triangles from view space to screen space, including a correction for perspective foreach (Face clippedFace in faceClip) { clippedFace.ApplyMatrix(ViewToScreen); if (this is PointLight or Spotlight) { clippedFace.p1 /= clippedFace.p1.w; clippedFace.p2 /= clippedFace.p2.w; clippedFace.p3 /= clippedFace.p3.w; } } // Clip the face in screen space if (Settings.Screen_Space_Clip && !Clipping.ClipFaces(faceClip, ScreenClippingPlanes)) { return; } foreach (Face clippedFace in faceClip) { // Don't draw anything if the face is flat if ((clippedFace.p1.x == clippedFace.p2.x && clippedFace.p2.x == clippedFace.p3.x) || (clippedFace.p1.y == clippedFace.p2.y && clippedFace.p2.y == clippedFace.p3.y)) { continue; } // Move the new triangles from screen space to window space clippedFace.ApplyMatrix(ScreenToWindow); // Round the vertices int x1 = clippedFace.p1.x.RoundToInt(); int y1 = clippedFace.p1.y.RoundToInt(); float z1 = clippedFace.p1.z; int x2 = clippedFace.p2.x.RoundToInt(); int y2 = clippedFace.p2.y.RoundToInt(); float z2 = clippedFace.p2.z; int x3 = clippedFace.p3.x.RoundToInt(); int y3 = clippedFace.p3.y.RoundToInt(); float z3 = clippedFace.p3.z; // Sort the vertices by their y-co-ordinate NumericManipulation.SortByY ( ref x1, ref y1, ref z1, ref x2, ref y2, ref z2, ref x3, ref y3, ref z3 ); // Interpolate each point in the triangle Interpolation.InterpolateTriangle ( MeshDepthFromLight, null, x1, y1, z1, x2, y2, z2, x3, y3, z3 ); } }