//private void DrawTriangle ( VertexPT [] triVs ) { // VertexPT [][] vss = ClipTriangleByZ ( // triVs, // nearZ, 1 ); // foreach ( VertexPT [] clippedVs in vss ) { // if ( culling != Culling.None ) { // //double3 n = GetPerspectiveTriangleNormal ( new double3 [] { clippedVs [0].P, clippedVs [1].P, clippedVs [2].P }, // // culling == Culling.Ccw ? CycleDir.Ccw : CycleDir.Cw ); // //if ( ( n & double3.UnitZ ) >= 0 ) // // return; // CycleDir triOrder = GetPerspectiveTriangleOrder ( new double3 [] { clippedVs [0].P, clippedVs [1].P, clippedVs [2].P } ); // if ( ( triOrder == CycleDir.Ccw && culling == Culling.Ccw ) || // ( triOrder == CycleDir.Cw && culling == Culling.Cw ) ) // return; // } // DrawClippedAndCulledTriangle ( clippedVs [0], clippedVs [1], clippedVs [2] ); // } //} void DrawClippedAndCulledTriangle(VertexPT v0, VertexPT v1, VertexPT v2) { double tpp = GetTexelsPerPixel(v0.P, v1.P, v2.P, v0.T, v1.T, v2.T, image.Size.width, image.Size.height, sampler.Map.Width, sampler.Map.Height); // Transform to screen space double2 halfWh = new double2(image.Size.width / 2, image.Size.height / 2); v0.P.xy /= v0.P.z; v1.P.xy /= v1.P.z; v2.P.xy /= v2.P.z; double3 screenP0 = new double3(halfWh + (v0.P.xy ^ halfWh), v0.P.z); double3 screenP1 = new double3(halfWh + (v1.P.xy ^ halfWh), v1.P.z); double3 screenP2 = new double3(halfWh + (v2.P.xy ^ halfWh), v2.P.z); // Invert vertically screenP0.y = image.Size.height - screenP0.y; screenP1.y = image.Size.height - screenP1.y; screenP2.y = image.Size.height - screenP2.y; image.DrawTexturedTriangle(new [] { screenP0, screenP1, screenP2 }, new [] { v0.T, v1.T, v2.T }, sampler, tpp); //image.DrawTriangle ( new [] { screenP0, screenP1, screenP2 }, color ); }
VertexPT [] TransformVertices(VertexPT [] vs, double4x4 m) { VertexPT [] tVs = new VertexPT [vs.Length]; for (int i = 0; i < vs.Length; i++) { tVs [i] = new VertexPT(m.Transform(vs [i].P), vs [i].T); } return(tVs); }
VertexPT [][] ClipTriangleByZ(VertexPT [] vs, double z, int insideSign) { // Warning: this algorithm generally does not preserve cw/ccw order Debug.Assert(insideSign == 1 || insideSign == -1); List <VertexPT> vsInside = new List <VertexPT> (vs); List <VertexPT> vsOutside = new List <VertexPT> (); for (int i = 0; i < vsInside.Count; i++) { if (vsInside [i].P.z.CompareTo(z) != insideSign) { vsOutside.Add(vsInside [i]); vsInside.RemoveAt(i--); } } if (vsOutside.Count == 0) { return new VertexPT [][] { ( VertexPT [] )vs.Clone() } } ; else if (vsOutside.Count == 3) { return new VertexPT [][] {} } ; else if (vsOutside.Count == 2) { VertexPT [] newVs = new VertexPT [3]; newVs [0] = vsInside [0]; double k1 = (z - vsOutside [0].P.z) / (vsInside [0].P.z - vsOutside [0].P.z); double k2 = (z - vsOutside [1].P.z) / (vsInside [0].P.z - vsOutside [1].P.z); newVs [1] = new VertexPT( k1.Lerp(vsOutside [0].P, vsInside [0].P), k1.Lerp(vsOutside [0].T, vsInside [0].T) ); newVs [2] = new VertexPT( k2.Lerp(vsOutside [1].P, vsInside [0].P), k2.Lerp(vsOutside [1].T, vsInside [0].T) ); return(new VertexPT [][] { newVs }); } else if (vsOutside.Count == 1) { double k1 = (z - vsOutside [0].P.z) / (vsInside [0].P.z - vsOutside [0].P.z); double k2 = (z - vsOutside [0].P.z) / (vsInside [1].P.z - vsOutside [0].P.z); VertexPT v1 = new VertexPT( k1.Lerp(vsOutside [0].P, vsInside [0].P), k1.Lerp(vsOutside [0].T, vsInside [0].T) ); VertexPT v2 = new VertexPT( k2.Lerp(vsOutside [0].P, vsInside [1].P), k2.Lerp(vsOutside [0].T, vsInside [1].T) ); return(new VertexPT [][] { new VertexPT [] { vsInside [0], v1, v2 }, new VertexPT [] { vsInside [0], vsInside [1], v2 } }); } throw new ArgumentException("Invalid vertex data."); }