//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); }
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); } }