public static Mesh.point3 cross(Mesh.point3 a, Mesh.point3 b) { Mesh.point3 resultant; resultant.x = a.y * b.z - a.z * b.y; resultant.y = a.z * b.x - a.x * b.z; resultant.z = a.x * b.y - a.y * b.x; return(resultant); }
public Mesh.point3 multiply(Mesh.point3 vector) { Mesh.point3 pNew; pNew.x = vector.x * m_i[0, 0] + vector.y * m_i[0, 1] + vector.z * m_i[0, 2]; pNew.y = vector.x * m_i[1, 0] + vector.y * m_i[1, 1] + vector.z * m_i[1, 2]; pNew.z = vector.x * m_i[2, 0] + vector.y * m_i[2, 1] + vector.z * m_i[2, 2]; return(pNew); }
static Mesh loadObj(string loc) { StreamReader r = new StreamReader(loc + ".obj"); List <Mesh.point3> loadedVerts = new List <Mesh.point3>(); List <Mesh.point2> loadedUvs = new List <Mesh.point2>(); List <Mesh.triangle> loadedFaces = new List <Mesh.triangle>(); List <Mesh.triangle> loadedUvFaces = new List <Mesh.triangle>(); List <Material> mtls = new List <Material>(); int vertCount = 0; int faceCount = 0; while (!r.EndOfStream) { string e1 = r.ReadLine(); if (e1 != "") { if (e1[0] == 'v' && e1[1] == 't')//texture verticies { string temp = e1.Substring(3, e1.Length - 3); string[] coords = temp.Split(' '); Mesh.point2 p = new Mesh.point2(float.Parse(coords[0]), float.Parse(coords[1])); loadedUvs.Add(p); } else if (e1[0] == 'v')//vertex { vertCount++; string temp = e1.Substring(3, e1.Length - 3); string[] coords = temp.Split(' '); Mesh.point3 p = new Mesh.point3(float.Parse(coords[0]) * 100, float.Parse(coords[1]) * 100, float.Parse(coords[2])); //if z is positive it's off screen, z=0 we clip loadedVerts.Add(p); } else if (e1[0] == 'u') {//use this mtl for rest of faces faces material Material m = new Material(e1.Substring(7, e1.Length - 7)); mtls.Add(m); } else if (e1[0] == 'f')//edge { faceCount++; string temp = e1.Substring(2, e1.Length - 2); string[] coords = temp.Split(' ', '/'); Mesh.triangle f = new Mesh.triangle(int.Parse(coords[0]) - 1, int.Parse(coords[2]) - 1, int.Parse(coords[4]) - 1, /*UV ID's*/ int.Parse(coords[1]) - 1, int.Parse(coords[3]) - 1, int.Parse(coords[5]) - 1, mtls.Count); // Mesh.triangle uvf = new Mesh.triangle(int.Parse(coords[1]), int.Parse(coords[3]), int.Parse(coords[5])); loadedFaces.Add(f); // loadedUvFaces.Add(uvf); } } } return(new Mesh(loadedVerts.ToArray(), loadedFaces.ToArray(), loadedUvs.ToArray(), mtls.ToArray())); }
private byte[,] drawTriangle(byte[,] image, Mesh.point3[] points, Mesh.point2[] uvs, byte[] brightness = null) { /* * A * B------- * C * */ //sort by lowest y value (highest on screen) Mesh.point3[] unsortedPoints = new Mesh.point3[3]; points.CopyTo(unsortedPoints, 0); if (points[1].y < points[0].y) {//swap point[1] and point[0] swap(ref points[0].y, ref points[1].y); swap(ref points[0].x, ref points[1].x); } if (points[2].y < points[0].y) {//swap point[0] and point[2] swap(ref points[0].y, ref points[2].y); swap(ref points[0].x, ref points[2].x); } if (points[2].y < points[1].y) {//swap point[1] & point[2] swap(ref points[1].y, ref points[2].y); swap(ref points[1].x, ref points[2].x); } if (points[0].y == points[1].y) {//flat top image = fillFlatTop(image, points, unsortedPoints, brightness, uvs); } else if (points[1].y == points[2].y) {//flat bottom image = fillFlatBottom(image, points, unsortedPoints, brightness, uvs); } else {//nontrivial Mesh.point3 midpoint = new Mesh.point3((int)(Math.Ceiling(points[0].x + ((float)(points[1].y - points[0].y) / (float)(points[2].y - points[0].y)) * (points[2].x - points[0].x))), points[1].y); fillFlatBottom(image, new Mesh.point3[] { points[0], points[1], midpoint }, unsortedPoints, brightness, uvs); fillFlatTop(image, new Mesh.point3[] { points[1], midpoint, points[2] }, unsortedPoints, brightness, uvs); } return(image); }
public light(float x, float y, float z, float setIntensity) { coords = new Mesh.point3(x, y, z); intensity = setIntensity; }
static Mesh loadObj(string loc) { StreamReader r = new StreamReader(loc + ".obj"); List<Mesh.point3> loadedVerts = new List<Mesh.point3>(); List<Mesh.point2> loadedUvs = new List<Mesh.point2>(); List<Mesh.triangle> loadedFaces = new List<Mesh.triangle>(); List<Mesh.triangle> loadedUvFaces = new List<Mesh.triangle>(); List<Material> mtls = new List<Material>(); int vertCount = 0; int faceCount = 0; while (!r.EndOfStream) { string e1 = r.ReadLine(); if (e1 != "") { if (e1[0] == 'v' && e1[1] == 't')//texture verticies { string temp = e1.Substring(3, e1.Length - 3); string[] coords = temp.Split(' '); Mesh.point2 p = new Mesh.point2(float.Parse(coords[0]), float.Parse(coords[1])); loadedUvs.Add(p); } else if (e1[0] == 'v')//vertex { vertCount++; string temp = e1.Substring(3, e1.Length - 3); string[] coords = temp.Split(' '); Mesh.point3 p = new Mesh.point3(float.Parse(coords[0]) * 100, float.Parse(coords[1]) * 100, float.Parse(coords[2])); //if z is positive it's off screen, z=0 we clip loadedVerts.Add(p); } else if (e1[0] == 'u') {//use this mtl for rest of faces faces material Material m = new Material(e1.Substring(7, e1.Length - 7)); mtls.Add(m); } else if (e1[0] == 'f')//edge { faceCount++; string temp = e1.Substring(2, e1.Length - 2); string[] coords = temp.Split(' ', '/'); Mesh.triangle f = new Mesh.triangle(int.Parse(coords[0]) - 1, int.Parse(coords[2]) - 1, int.Parse(coords[4]) - 1, /*UV ID's*/ int.Parse(coords[1]) - 1, int.Parse(coords[3]) - 1, int.Parse(coords[5]) - 1, mtls.Count); // Mesh.triangle uvf = new Mesh.triangle(int.Parse(coords[1]), int.Parse(coords[3]), int.Parse(coords[5])); loadedFaces.Add(f); // loadedUvFaces.Add(uvf); } } } return (new Mesh(loadedVerts.ToArray(), loadedFaces.ToArray(), loadedUvs.ToArray(), mtls.ToArray())); }
public byte[,] renderSolid() { byte[,] image = new byte[RENDER_WIDTH, RENDER_HEIGHT];// for (int x = 0; x < RENDER_WIDTH; x++) { for (int y = 0; y < RENDER_HEIGHT; y++) { image[x, y] = 32; //space character is drawn faster than the null character (0) zBuffer[x, y] = -100; //far clipping plane } } foreach (Mesh.triangle f in someShape.faces) { targFace = f; Mesh.point3 a = Matrix.add(someShape.verts[f.vertIDs[0]], new Mesh.point3(-someShape.verts[f.vertIDs[2]].x, -someShape.verts[f.vertIDs[2]].y, -someShape.verts[f.vertIDs[2]].z)); Mesh.point3 b = Matrix.add(someShape.verts[f.vertIDs[0]], new Mesh.point3(-someShape.verts[f.vertIDs[1]].x, -someShape.verts[f.vertIDs[1]].y, -someShape.verts[f.vertIDs[1]].z)); Mesh.point3 surfaceNorm1 = Matrix.cross(a, b); surfaceNorm1 = Matrix.normalize(surfaceNorm1); Mesh.point3 lightNorm1 = Matrix.add(light1.coords, new Mesh.point3(-someShape.verts[f.vertIDs[0]].x, -someShape.verts[f.vertIDs[0]].y, -someShape.verts[f.vertIDs[0]].z));//arbitrary vert lightNorm1 = Matrix.normalize(lightNorm1); //////////////////////////////////// Mesh.point3 a1 = Matrix.add(someShape.verts[f.vertIDs[1]], new Mesh.point3(-someShape.verts[f.vertIDs[2]].x, -someShape.verts[f.vertIDs[2]].y, -someShape.verts[f.vertIDs[2]].z)); Mesh.point3 b1 = Matrix.add(someShape.verts[f.vertIDs[1]], new Mesh.point3(-someShape.verts[f.vertIDs[0]].x, -someShape.verts[f.vertIDs[0]].y, -someShape.verts[f.vertIDs[0]].z)); Mesh.point3 surfaceNorm2 = Matrix.cross(a1, b1); surfaceNorm2 = Matrix.normalize(surfaceNorm2); Mesh.point3 lightNorm2 = Matrix.add(light1.coords, new Mesh.point3(-someShape.verts[f.vertIDs[1]].x, -someShape.verts[f.vertIDs[1]].y, -someShape.verts[f.vertIDs[1]].z));//arbitrary vert lightNorm2 = Matrix.normalize(lightNorm2); ////////////////////////////////////////////// Mesh.point3 a2 = Matrix.add(someShape.verts[f.vertIDs[2]], new Mesh.point3(-someShape.verts[f.vertIDs[0]].x, -someShape.verts[f.vertIDs[0]].y, -someShape.verts[f.vertIDs[0]].z)); Mesh.point3 b2 = Matrix.add(someShape.verts[f.vertIDs[2]], new Mesh.point3(-someShape.verts[f.vertIDs[1]].x, -someShape.verts[f.vertIDs[1]].y, -someShape.verts[f.vertIDs[1]].z)); Mesh.point3 surfaceNorm3 = Matrix.cross(a2, b2); surfaceNorm3 = Matrix.normalize(surfaceNorm3); Mesh.point3 lightNorm3 = Matrix.add(light1.coords, new Mesh.point3(-someShape.verts[f.vertIDs[2]].x, -someShape.verts[f.vertIDs[2]].y, -someShape.verts[f.vertIDs[2]].z));//arbitrary vert lightNorm3 = Matrix.normalize(lightNorm3); //////////////////////////////////////////// //perspective projection float[] depth = { someShape.verts[f.vertIDs[0]].z, someShape.verts[f.vertIDs[1]].z, someShape.verts[f.vertIDs[2]].z }; if (depth[0] < 0 && depth[1] < 0 && depth[2] < 0) { //>= one vertex is in screen int x0 = (int)((RENDER_WIDTH / 2) + someShape.verts[f.vertIDs[0]].x / depth[0]); int y0 = (int)(((RENDER_HEIGHT - 15) / 2) + someShape.verts[f.vertIDs[0]].y / depth[0]); int x1 = (int)((RENDER_WIDTH / 2) + someShape.verts[f.vertIDs[1]].x / depth[1]); int y1 = (int)(((RENDER_HEIGHT - 15) / 2) + someShape.verts[f.vertIDs[1]].y / depth[1]); int x2 = (int)((RENDER_WIDTH / 2) + someShape.verts[f.vertIDs[2]].x / depth[2]); int y2 = (int)(((RENDER_HEIGHT - 15) / 2) + someShape.verts[f.vertIDs[2]].y / depth[2]); Mesh.point2[] uvs = new Mesh.point2[] { someShape.uvVerts[f.uvIds[0]], someShape.uvVerts[f.uvIds[1]], someShape.uvVerts[f.uvIds[2]] }; Mesh.point3[] projPoints = new Mesh.point3[] { new Mesh.point3(x0, y0, depth[0]), new Mesh.point3(x1, y1, depth[1]), new Mesh.point3(x2, y2, depth[2]) }; byte[] colors = { (byte)(light1.intensity * Math.Max(0, Matrix.dot(surfaceNorm1, lightNorm1))), (byte)(light1.intensity * Math.Max(0, Matrix.dot(surfaceNorm2, lightNorm2))), (byte)(light1.intensity * Math.Max(0, Matrix.dot(surfaceNorm3, lightNorm3))) }; image = drawTriangle(image, projPoints, uvs, colors); } } return(image); }
public static float dot(Mesh.point3 a, Mesh.point3 b) { return(a.x * b.x + a.y * b.y + a.z * b.z); }
public static Mesh.point3 add(Mesh.point3 a, Mesh.point3 b) { return(new Mesh.point3((a.x + b.x), (a.y + b.y), (a.z + b.z))); }
public static Mesh.point3 normalize(Mesh.point3 a) { float norm = (float)Math.Sqrt(a.x * a.x + a.y * a.y + a.z * a.z); return(new Mesh.point3(a.x / norm, a.y / norm, a.z / norm)); }
public static float magnitude(Mesh.point3 a) { return((float)Math.Sqrt(dot(a, a))); }
private byte[,] drawTriangle(byte[,] image, Mesh.point3[] points, Mesh.point2[] uvs, byte[] brightness = null) { /* * A * B------- * C * */ //sort by lowest y value (highest on screen) Mesh.point3[] unsortedPoints = new Mesh.point3[3]; points.CopyTo(unsortedPoints, 0); if (points[1].y < points[0].y) {//swap point[1] and point[0] swap(ref points[0].y, ref points[1].y); swap(ref points[0].x, ref points[1].x); } if (points[2].y < points[0].y) {//swap point[0] and point[2] swap(ref points[0].y, ref points[2].y); swap(ref points[0].x, ref points[2].x); } if (points[2].y < points[1].y) {//swap point[1] & point[2] swap(ref points[1].y, ref points[2].y); swap(ref points[1].x, ref points[2].x); } if (points[0].y == points[1].y) {//flat top image = fillFlatTop(image, points, unsortedPoints, brightness, uvs); } else if (points[1].y == points[2].y) {//flat bottom image = fillFlatBottom(image, points, unsortedPoints, brightness, uvs); } else {//nontrivial Mesh.point3 midpoint = new Mesh.point3((int)(Math.Ceiling(points[0].x + ((float)(points[1].y - points[0].y) / (float)(points[2].y - points[0].y)) * (points[2].x - points[0].x))), points[1].y); fillFlatBottom(image, new Mesh.point3[] { points[0], points[1], midpoint }, unsortedPoints, brightness, uvs); fillFlatTop(image, new Mesh.point3[] { points[1], midpoint, points[2] }, unsortedPoints, brightness, uvs); } return (image); }
public byte[,] renderSolid() { byte[,] image = new byte[RENDER_WIDTH, RENDER_HEIGHT];// for (int x = 0; x < RENDER_WIDTH; x++) for (int y = 0; y < RENDER_HEIGHT; y++) { image[x, y] = 32; //space character is drawn faster than the null character (0) zBuffer[x, y] = -100; //far clipping plane } foreach (Mesh.triangle f in someShape.faces) { targFace = f; Mesh.point3 a = Matrix.add(someShape.verts[f.vertIDs[0]], new Mesh.point3(-someShape.verts[f.vertIDs[2]].x, -someShape.verts[f.vertIDs[2]].y, -someShape.verts[f.vertIDs[2]].z)); Mesh.point3 b = Matrix.add(someShape.verts[f.vertIDs[0]], new Mesh.point3(-someShape.verts[f.vertIDs[1]].x, -someShape.verts[f.vertIDs[1]].y, -someShape.verts[f.vertIDs[1]].z)); Mesh.point3 surfaceNorm1 = Matrix.cross(a, b); surfaceNorm1 = Matrix.normalize(surfaceNorm1); Mesh.point3 lightNorm1 = Matrix.add(light1.coords, new Mesh.point3(-someShape.verts[f.vertIDs[0]].x, -someShape.verts[f.vertIDs[0]].y, -someShape.verts[f.vertIDs[0]].z));//arbitrary vert lightNorm1 = Matrix.normalize(lightNorm1); //////////////////////////////////// Mesh.point3 a1 = Matrix.add(someShape.verts[f.vertIDs[1]], new Mesh.point3(-someShape.verts[f.vertIDs[2]].x, -someShape.verts[f.vertIDs[2]].y, -someShape.verts[f.vertIDs[2]].z)); Mesh.point3 b1 = Matrix.add(someShape.verts[f.vertIDs[1]], new Mesh.point3(-someShape.verts[f.vertIDs[0]].x, -someShape.verts[f.vertIDs[0]].y, -someShape.verts[f.vertIDs[0]].z)); Mesh.point3 surfaceNorm2 = Matrix.cross(a1, b1); surfaceNorm2 = Matrix.normalize(surfaceNorm2); Mesh.point3 lightNorm2 = Matrix.add(light1.coords, new Mesh.point3(-someShape.verts[f.vertIDs[1]].x, -someShape.verts[f.vertIDs[1]].y, -someShape.verts[f.vertIDs[1]].z));//arbitrary vert lightNorm2 = Matrix.normalize(lightNorm2); ////////////////////////////////////////////// Mesh.point3 a2 = Matrix.add(someShape.verts[f.vertIDs[2]], new Mesh.point3(-someShape.verts[f.vertIDs[0]].x, -someShape.verts[f.vertIDs[0]].y, -someShape.verts[f.vertIDs[0]].z)); Mesh.point3 b2 = Matrix.add(someShape.verts[f.vertIDs[2]], new Mesh.point3(-someShape.verts[f.vertIDs[1]].x, -someShape.verts[f.vertIDs[1]].y, -someShape.verts[f.vertIDs[1]].z)); Mesh.point3 surfaceNorm3 = Matrix.cross(a2, b2); surfaceNorm3 = Matrix.normalize(surfaceNorm3); Mesh.point3 lightNorm3 = Matrix.add(light1.coords, new Mesh.point3(-someShape.verts[f.vertIDs[2]].x, -someShape.verts[f.vertIDs[2]].y, -someShape.verts[f.vertIDs[2]].z));//arbitrary vert lightNorm3 = Matrix.normalize(lightNorm3); //////////////////////////////////////////// //perspective projection float[] depth = {someShape.verts[f.vertIDs[0]].z, someShape.verts[f.vertIDs[1]].z, someShape.verts[f.vertIDs[2]].z}; if (depth[0] < 0 && depth[1] < 0 && depth[2] < 0) { //>= one vertex is in screen int x0 = (int)((RENDER_WIDTH / 2) + someShape.verts[f.vertIDs[0]].x / depth[0]); int y0 = (int)(((RENDER_HEIGHT - 15) / 2) + someShape.verts[f.vertIDs[0]].y / depth[0]); int x1 = (int)((RENDER_WIDTH / 2) + someShape.verts[f.vertIDs[1]].x / depth[1]); int y1 = (int)(((RENDER_HEIGHT - 15) / 2) + someShape.verts[f.vertIDs[1]].y / depth[1]); int x2 = (int)((RENDER_WIDTH / 2) + someShape.verts[f.vertIDs[2]].x / depth[2]); int y2 = (int)(((RENDER_HEIGHT - 15) / 2) + someShape.verts[f.vertIDs[2]].y / depth[2]); Mesh.point2[] uvs = new Mesh.point2[] { someShape.uvVerts[f.uvIds[0]], someShape.uvVerts[f.uvIds[1]], someShape.uvVerts[f.uvIds[2]] }; Mesh.point3[] projPoints = new Mesh.point3[] {new Mesh.point3(x0, y0, depth[0]), new Mesh.point3(x1, y1, depth[1]), new Mesh.point3(x2, y2, depth[2])}; byte[] colors = {(byte)(light1.intensity * Math.Max(0, Matrix.dot(surfaceNorm1, lightNorm1))), (byte)(light1.intensity * Math.Max(0, Matrix.dot(surfaceNorm2, lightNorm2))), (byte)(light1.intensity * Math.Max(0, Matrix.dot(surfaceNorm3, lightNorm3)))}; image = drawTriangle(image, projPoints, uvs, colors); } } return (image); }