matrix4x4 matrixQuickInverse(matrix4x4 m) { matrix4x4 matrix = new matrix4x4(); matrix.m[0, 0] = m.m[0, 0]; matrix.m[0, 1] = m.m[1, 0]; matrix.m[0, 2] = m.m[2, 0]; matrix.m[0, 3] = 0.0f; matrix.m[1, 0] = m.m[0, 1]; matrix.m[1, 1] = m.m[1, 1]; matrix.m[1, 2] = m.m[2, 1]; matrix.m[1, 3] = 0.0f; matrix.m[2, 0] = m.m[0, 2]; matrix.m[2, 1] = m.m[1, 2]; matrix.m[2, 2] = m.m[2, 2]; matrix.m[2, 3] = 0.0f; matrix.m[3, 0] = -(m.m[3, 0] * matrix.m[0, 0] + m.m[3, 1] * matrix.m[1, 0] + m.m[3, 2] * matrix.m[2, 0]); matrix.m[3, 1] = -(m.m[3, 0] * matrix.m[0, 1] + m.m[3, 1] * matrix.m[1, 1] + m.m[3, 2] * matrix.m[2, 1]); matrix.m[3, 2] = -(m.m[3, 0] * matrix.m[0, 2] + m.m[3, 1] * matrix.m[1, 2] + m.m[3, 2] * matrix.m[2, 2]); matrix.m[3, 3] = 1.0f; return(matrix); }
matrix4x4 createUnitMatrix() { matrix4x4 m = new matrix4x4(); m.m[0, 0] = 1.0; m.m[1, 1] = 1.0; m.m[2, 2] = 1.0; m.m[3, 3] = 1.0; return(m); }
//FUNC matrix4x4 getMatrixProjection(double fFovRad, double fAspectRation, double fNear, double fFar) { matrix4x4 matProj = new matrix4x4(); matProj.m[0, 0] = fAspectRation * fFovRad; matProj.m[1, 1] = fFovRad; matProj.m[2, 2] = fFar / (fFar - fNear); matProj.m[3, 2] = (-fFar * fNear) / (fFar - fNear); matProj.m[2, 3] = 1.0; matProj.m[3, 3] = 0.0; return(matProj); }
matrix4x4 getMatrixRotationY(double angle) { matrix4x4 matrix = new matrix4x4(); matrix.m[0, 0] = Math.Cos(angle); matrix.m[0, 2] = Math.Sin(angle); matrix.m[2, 0] = -Math.Sin(angle); matrix.m[1, 1] = 1.0f; matrix.m[2, 2] = Math.Cos(angle); matrix.m[3, 3] = 1.0f; return(matrix); }
matrix4x4 getMatrixRotationX(double angle) { matrix4x4 matRotX = new matrix4x4(); matRotX.m[0, 0] = 1; matRotX.m[1, 1] = Math.Cos(angle); matRotX.m[1, 2] = Math.Sin(angle); matRotX.m[2, 1] = -Math.Sin(angle); matRotX.m[2, 2] = Math.Cos(angle);; matRotX.m[3, 3] = 1; return(matRotX); }
//FUNC matrix4x4 getMatrixRotationZ(double angle) { matrix4x4 matRotZ = new matrix4x4(); matRotZ.m[0, 0] = Math.Cos(angle); matRotZ.m[0, 1] = Math.Sin(angle); matRotZ.m[1, 0] = -Math.Sin(angle); matRotZ.m[1, 1] = Math.Cos(angle); matRotZ.m[2, 2] = 1; matRotZ.m[3, 3] = 1; return(matRotZ); }
public static matrix4x4 operator *(matrix4x4 m1, matrix4x4 m2) { matrix4x4 res = new matrix4x4(); for (int c = 0; c < 4; c++) { for (int r = 0; r < 4; r++) { res.m[r, c] = m1.m[r, 0] * m2.m[0, c] + m1.m[r, 1] * m2.m[1, c] + m1.m[r, 2] * m2.m[2, c] + m1.m[r, 3] * m2.m[3, c]; } } return(res); }
//FUNC matrix4x4 getMatrixTranslation(double x, double y, double z) { matrix4x4 matrixTranslation = new matrix4x4(); matrixTranslation.m[0, 0] = 1.0; matrixTranslation.m[1, 1] = 1.0; matrixTranslation.m[2, 2] = 1.0; matrixTranslation.m[3, 3] = 1.0; matrixTranslation.m[3, 0] = x; matrixTranslation.m[3, 1] = y; matrixTranslation.m[3, 2] = z; return(matrixTranslation); }
//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); } }