//FUNC public void loadFromObjFileAt(string fileName, double x, double y, double z) { string[] file = System.IO.File.ReadAllLines(fileName); List <vect3D> verts = new List <vect3D>(); // line = typeOfLine + v1 + v2 + v3 foreach (string line in file) { string[] lineValues = line.Split(' '); char typeOfLine = line[0]; //vertex if (typeOfLine == 'v') { vect3D vect = new vect3D(Convert.ToDouble(lineValues[1], System.Globalization.CultureInfo.InvariantCulture) + x, Convert.ToDouble(lineValues[2], System.Globalization.CultureInfo.InvariantCulture) + y, Convert.ToDouble(lineValues[3], System.Globalization.CultureInfo.InvariantCulture) + z); verts.Add(vect); } //triangle else if (typeOfLine == 'f') { int v1, v2, v3; // - 1 because all of the information in the file start counting from 1 v1 = Convert.ToInt32(lineValues[1]) - 1; v2 = Convert.ToInt32(lineValues[2]) - 1; v3 = Convert.ToInt32(lineValues[3]) - 1; tris.Add(new triangle(verts[v1], verts[v2], verts[v3])); } } }
public triangle(vect3D v1, vect3D v2, vect3D v3) { vect = new vect3D[3]; vect[0] = v1; vect[1] = v2; vect[2] = v3; }
public vect3D CrossProduct(vect3D vect) { vect3D v = new vect3D(); v.x = this.y * vect.z - this.z * vect.y; v.y = this.z * vect.x - this.x * vect.z; v.z = this.x * vect.y - this.y * vect.x; return(v); }
public static vect3D operator *(matrix4x4 m, vect3D v) { vect3D res = new vect3D(); res.x = v.x * m.m[0, 0] + v.y * m.m[1, 0] + v.z * m.m[2, 0] + v.w * m.m[3, 0]; res.y = v.x * m.m[0, 1] + v.y * m.m[1, 1] + v.z * m.m[2, 1] + v.w * m.m[3, 1]; res.z = v.x * m.m[0, 2] + v.y * m.m[1, 2] + v.z * m.m[2, 2] + v.w * m.m[3, 2]; res.w = v.x * m.m[0, 3] + v.y * m.m[1, 3] + v.z * m.m[2, 3] + v.w * m.m[3, 3]; return(res); }
public MainWindow() { vCamera = new vect3D(0, 0, 0); InitializeComponent(); initializeMatrix(); initializeObjects(); System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer(); timer.Tick += new EventHandler(timerTick); timer.Interval = new TimeSpan(0, 0, 0, 0, 1); timer.Start(); canvas.Focus(); }
protected override void OnKeyDown(KeyEventArgs e) { switch (e.Key) { //Forward case Key.Up: vCamera = vCamera + (vLookDir * 1.001); break; //Left case Key.Left: vCamera.x -= 1.0; break; //Right case Key.Right: vCamera.x += 1.0; break; //Back case Key.Down: vCamera = vCamera - (vLookDir * 1.001); break; // rotate up case Key.W: fXaw += 0.05; break; // rotate down case Key.S: fXaw -= 0.05; break; // turn left case Key.A: fYaw += 0.05; break; // turn right case Key.D: fYaw -= 0.05; break; } base.OnKeyDown(e); }
//FUNC matrix4x4 matrixPointAt(vect3D pos, vect3D target, vect3D up) { vect3D newForward = target - pos; newForward.Normalize(); // Calculate new Up direction vect3D a = newForward * up.DotProduct(newForward); vect3D newUp = up - a; newUp.Normalize(); // New Right direction is easy, its just cross product vect3D newRight = newUp.CrossProduct(newForward); // Construct Dimensioning and Translation Matrix matrix4x4 matrix = new matrix4x4(); matrix.m[0, 0] = newRight.x; matrix.m[0, 1] = newRight.y; matrix.m[0, 2] = newRight.z; matrix.m[0, 3] = 0.0f; matrix.m[1, 0] = newUp.x; matrix.m[1, 1] = newUp.y; matrix.m[1, 2] = newUp.z; matrix.m[1, 3] = 0.0f; matrix.m[2, 0] = newForward.x; matrix.m[2, 1] = newForward.y; matrix.m[2, 2] = newForward.z; matrix.m[2, 3] = 0.0f; matrix.m[3, 0] = pos.x; matrix.m[3, 1] = pos.y; matrix.m[3, 2] = pos.z; matrix.m[3, 3] = 1.0f; return(matrix); }
public double DotProduct(vect3D vect) { return(this.x * vect.x + this.y * vect.y + this.z * vect.z); }
private void timerTick(object sender, EventArgs e) { canvas.Children.Clear(); double deltaX = 0.2; double fDelta = 2 * Math.PI / (4 * r / deltaX); fTheta += fDelta; matrix4x4 matRotZ = getMatrixRotationZ(0); matrix4x4 matRotX = getMatrixRotationX(0); matrix4x4 matRotY = getMatrixRotationY(fTheta); if (Math.Abs(x) >= r) { isHalfRotated = !isHalfRotated; } x += isHalfRotated ? deltaX : -deltaX; double z = isHalfRotated ? -Math.Sqrt(r * r - x * x) : Math.Sqrt(r * r - x * x); z += 4 * r; matrix4x4 matTrans = getMatrixTranslation(x, 1, z);; // all the transformations that we need to do in this matrix matrix4x4 matWorld = createUnitMatrix(); matWorld = matRotZ * matRotX * matRotY; matWorld = matWorld * matTrans; //camera vect3D vUp = new vect3D(0, 1, 0); vect3D vTarget = new vect3D(0, 0, 1); matrix4x4 matCameraRot = getMatrixRotationY(fYaw) * getMatrixRotationX(fXaw); vLookDir = matCameraRot * vTarget; vTarget = vCamera + vLookDir; matrix4x4 matCamera = matrixPointAt(vCamera, vTarget, vUp); matrix4x4 matView = matrixQuickInverse(matCamera); List <triangle> trianglesToRaster = new List <triangle>(); foreach (triangle tri in meshCube.tris) { triangle triProjected = new triangle(); triangle triTransformed = new triangle(); triangle triViewed = new triangle(); triTransformed.vect[0] = matWorld * tri.vect[0]; triTransformed.vect[1] = matWorld * tri.vect[1]; triTransformed.vect[2] = matWorld * tri.vect[2]; vect3D normal = new vect3D(); vect3D line1 = new vect3D(); vect3D line2 = new vect3D(); line1 = triTransformed.vect[1] - triTransformed.vect[0]; line2 = triTransformed.vect[2] - triTransformed.vect[0]; normal = line1.CrossProduct(line2); normal.Normalize(); //projecting // объект виден если угол между нормалью к нему и нашей камерой меньше 90 градусов // будем проверять это с помощью скалярного произведения векторов // скалярное произведение векторов угол между которыми > 90 градусов будет < 0 if (normal.DotProduct(triTransformed.vect[0] - vCamera) < 0.0) { // illumination (all illumination cooming from direction, not from the point) // свет тем ярче чем меньше угол между нормалью поверхности с направлением света vect3D lightDirection = new vect3D(-5.0, -5.0, -5.0); lightDirection.Normalize(); double dp = normal.DotProduct(lightDirection); triProjected.luminosity = dp; triTransformed.luminosity = dp; triViewed.vect[0] = matView * triTransformed.vect[0]; triViewed.vect[1] = matView * triTransformed.vect[1]; triViewed.vect[2] = matView * triTransformed.vect[2]; triProjected.vect[0] = matProj * triViewed.vect[0]; triProjected.vect[1] = matProj * triViewed.vect[1]; triProjected.vect[2] = matProj * triViewed.vect[2]; triProjected.vect[0] = triProjected.vect[0] / triProjected.vect[0].w; triProjected.vect[1] = triProjected.vect[1] / triProjected.vect[1].w; triProjected.vect[2] = triProjected.vect[2] / triProjected.vect[2].w; //offset into visible mormalized space vect3D vOffsetView = new vect3D(1, 1, 0); triProjected.vect[0] = triProjected.vect[0] + vOffsetView; triProjected.vect[1] = triProjected.vect[1] + vOffsetView; triProjected.vect[2] = triProjected.vect[2] + vOffsetView; triProjected.vect[0].x *= canvas.Width / 2.0; triProjected.vect[0].y *= canvas.Height / 2.0; triProjected.vect[1].x *= canvas.Width / 2.0; triProjected.vect[1].y *= canvas.Height / 2.0; triProjected.vect[2].x *= canvas.Width / 2.0; triProjected.vect[2].y *= canvas.Height / 2.0; trianglesToRaster.Add(triProjected); } } // Sort triangles from back to front try { trianglesToRaster.Sort(); } catch (Exception ex) { } foreach (triangle t in trianglesToRaster) { DrawTriangle(t, true, true); } }