public TMat4x4 MulMat(TMat4x4 MatToMul) { TMat4x4 Result; Result.m00 = m00 * MatToMul.m00 + m01 * MatToMul.m10 + m02 * MatToMul.m20 + m03 * MatToMul.m30; Result.m01 = m00 * MatToMul.m01 + m01 * MatToMul.m11 + m02 * MatToMul.m21 + m03 * MatToMul.m31; Result.m02 = m00 * MatToMul.m02 + m01 * MatToMul.m12 + m02 * MatToMul.m22 + m03 * MatToMul.m32; Result.m03 = m00 * MatToMul.m03 + m01 * MatToMul.m13 + m02 * MatToMul.m23 + m03 * MatToMul.m33; Result.m10 = m10 * MatToMul.m00 + m11 * MatToMul.m10 + m12 * MatToMul.m20 + m13 * MatToMul.m30; Result.m11 = m10 * MatToMul.m01 + m11 * MatToMul.m11 + m12 * MatToMul.m21 + m13 * MatToMul.m31; Result.m12 = m10 * MatToMul.m02 + m11 * MatToMul.m12 + m12 * MatToMul.m22 + m13 * MatToMul.m32; Result.m13 = m10 * MatToMul.m03 + m11 * MatToMul.m13 + m12 * MatToMul.m23 + m13 * MatToMul.m33; Result.m20 = m20 * MatToMul.m00 + m21 * MatToMul.m10 + m22 * MatToMul.m20 + m23 * MatToMul.m30; Result.m21 = m20 * MatToMul.m01 + m21 * MatToMul.m11 + m22 * MatToMul.m21 + m23 * MatToMul.m31; Result.m22 = m20 * MatToMul.m02 + m21 * MatToMul.m12 + m22 * MatToMul.m22 + m23 * MatToMul.m32; Result.m23 = m20 * MatToMul.m03 + m21 * MatToMul.m13 + m22 * MatToMul.m23 + m23 * MatToMul.m33; Result.m30 = m30 * MatToMul.m00 + m31 * MatToMul.m10 + m32 * MatToMul.m20 + m33 * MatToMul.m30; Result.m31 = m30 * MatToMul.m01 + m31 * MatToMul.m11 + m32 * MatToMul.m21 + m33 * MatToMul.m31; Result.m32 = m30 * MatToMul.m02 + m31 * MatToMul.m12 + m32 * MatToMul.m22 + m33 * MatToMul.m32; Result.m33 = m30 * MatToMul.m03 + m31 * MatToMul.m13 + m32 * MatToMul.m23 + m33 * MatToMul.m33; return(Result); }
public void RotateOnAxis(float Angle) { TMat4x4 ArbitraryMat = TMat4x4.ZeroMat(); ArbitraryMat.SetArbitraryRot(TransformedAxisPointA, TransformedAxisPointB, Angle); SetMatrix(ArbitraryMat); }
private TMat4x4 GetFatherMat() { if (Father != null) { return(Father.CombinedMatrix); } return(TMat4x4.UnitMat()); }
public void SetPos(TVertex NewPos) { CurrentPos = NewPos; TMat4x4 TransMat = TMat4x4.ZeroMat(); TransMat.SetTrans(NewPos.X, NewPos.Y, NewPos.Z); SetMatrix(TransMat); }
public void SetPos(float X, float Y, float Z) { CurrentPos.Set(X, Y, Z); TMat4x4 TransMat = TMat4x4.ZeroMat(); TransMat.SetTrans(X, Y, Z); SetMatrix(TransMat); }
public void GotoNewPosXZ(TVertex NewPos) { TMat4x4 TransMat = TMat4x4.ZeroMat(); TMat4x4 RotMatY = TMat4x4.ZeroMat(); CurrentPos = NewPos; TransMat.SetTrans(NewPos.X, NewPos.Y, NewPos.Z); RotMatY.SetRotateY(Math3D.Deg2Rad(Orientation + OrientationOffset)); SetMatrix(RotMatY.MulMat(TransMat)); }
public void SetMatrix(TMat4x4 Mat) { ObjectMat = Mat; // Transform myself CombinedMatrix = ObjectMat.MulMat(GetFatherMat()); TransformAxis(ObjectMat); // Transform all child objects for (int i = 0; i < Children.Count; i++) { ((CObject3D)Children[i]).SetMatrix(((CObject3D)Children[i]).ObjectMat); } }
public void SetPosAndAngle(float X, float Y, float Z, float A, float B, float C) { TMat4x4 TransMat = TMat4x4.ZeroMat(); TMat4x4 RotMatX = TMat4x4.ZeroMat(); TMat4x4 RotMatY = TMat4x4.ZeroMat(); TMat4x4 RotMatZ = TMat4x4.ZeroMat(); CurrentPos.Set(X, Y, Z); CurrentRot.Set(A, B, C); TransMat.SetTrans(X, Y, Z); RotMatX.SetRotateX(A); RotMatY.SetRotateY(B); RotMatZ.SetRotateZ(C); SetMatrix(RotMatX.MulMat(RotMatY).MulMat(RotMatZ).MulMat(TransMat)); }
// Constructor public CRenderContext(int W, int H) { VScreen = new Bitmap(W, H); ZBuffer = new float[W * H]; // Prepare graphics canvases for the form and for the virtual screen VScreenCanvas = Graphics.FromImage(VScreen); BackgroundColor = DEFAULT_BACKGROUND_COLOR; PenForWireFrame = new Pen(DEFAULT_PEN_COLOR, 1); ViewMatrix = TMat4x4.UnitMat(); Width = W; Height = H; HalfWidth = Width / 2; HalfHeight = Height / 2; }
public void Assign(CObject3D CopyFrom) { ObjectMat = CopyFrom.ObjectMat; VertexTable = new TVertex[CopyFrom.VertexTable.Length]; Array.Copy(CopyFrom.VertexTable, VertexTable, VertexTable.Length); FaceTable = new TFace3D[CopyFrom.FaceTable.Length]; Array.Copy(CopyFrom.FaceTable, FaceTable, FaceTable.Length); ObjectMat = CopyFrom.ObjectMat; CombinedMatrix = CopyFrom.CombinedMatrix; Children = CopyFrom.Children; ChildrenAxes = CopyFrom.ChildrenAxes; Father = CopyFrom.Father; OriginalAxisPointA = CopyFrom.OriginalAxisPointA; OriginalAxisPointB = CopyFrom.OriginalAxisPointB; }
public void SetViewMat(TMat4x4 Mat) { ViewMatrix = Mat; }
// Perform rendering on a specific context public void Render(CRenderContext Context) { if (!Visible) { return; } // Calculate transform matrix TMat4x4 Mat = GetTransformMatrix(Context); // Calculate the inverse matrix TMat4x4 InverseMat = Mat.FindInverseMat(); // Clear translation effect InverseMat.ClearTranslation(); // Calculate the viewer position in object coordinates TVertex ViewDirection = Context.GetViewDirection(); TVertex ViewerPosInObjCoords = InverseMat.MulVertex(ViewDirection); float PerspectiveFactor = Context.GetPerspectiveFactor(); Color IlluminatedFaceColor; foreach (TFace3D Face in FaceTable) { bool FaceVisible; float FaceDotProd = 0; if (!Context.IsBackfaceCullingMode()) { // No backface culling, the face is always visible FaceVisible = true; } else { // Do backface culling FaceDotProd = Math3D.DotProduct(ViewerPosInObjCoords, Face.Normal); // Perspective mode if (Context.IsPerspectiveMode()) { // Remember if the face is visible FaceVisible = (FaceDotProd > THRESHOLD_FOR_CULLING); } else { FaceVisible = (FaceDotProd > 0); } } if (FaceVisible) { // Get current face vertices and transform to world coordinates TVertex[] FaceVertex = new TVertex[3] { Mat.MulVertex(VertexTable[Face.AIndex]), Mat.MulVertex(VertexTable[Face.BIndex]), Mat.MulVertex(VertexTable[Face.CIndex]) }; Point[] ScreenCoords = new Point[3]; if (TestForBackClipping(FaceVertex[0], FaceVertex[1], FaceVertex[2])) { bool PreventFaceDraw = false; // Perspective mode if (Context.IsPerspectiveMode()) { // Transform the from world coordinates to screen coordinates for (int i = 0; i < 3; i++) { if (Math.Abs(FaceVertex[i].Z) < POLYGON_Z_MIN_VALUE) { PreventFaceDraw = true; break; } ScreenCoords[i].X = (int)(FaceVertex[i].X * PerspectiveFactor / FaceVertex[i].Z); ScreenCoords[i].Y = (int)(FaceVertex[i].Y * PerspectiveFactor / FaceVertex[i].Z); if ((Math.Abs(ScreenCoords[i].X) > POLYGON_COORD_MAX_VALUE) || (Math.Abs(ScreenCoords[i].Y) > POLYGON_COORD_MAX_VALUE)) { PreventFaceDraw = true; break; } } } else // Orthogonal projection { PreventFaceDraw = false; // Transform the from world coordinates to screen coordinates for (int i = 0; i < 3; i++) { ScreenCoords[i].X = (int)(FaceVertex[i].X / ORTHO_PROJECTION_SCALING); ScreenCoords[i].Y = (int)(FaceVertex[i].Y / ORTHO_PROJECTION_SCALING); } } if (!PreventFaceDraw) { T2DTriangle ScreenTriangle = new T2DTriangle(ScreenCoords[0], ScreenCoords[1], ScreenCoords[2]); if (Context.IsWireFrameMode()) { Context.DrawTriangle(ScreenTriangle); } else // Filled triangles mode { float LightLevel = FaceDotProd + MIN_LIGHT_LEVEL; // Clip to maximum light level if (LightLevel > 1.0) { LightLevel = 1.0f; } // Calculate face color int ARGBColor = ClipColorChn(Face.Color.R, LightLevel); ARGBColor |= ClipColorChn(Face.Color.G, LightLevel) << 8; ARGBColor |= ClipColorChn(Face.Color.B, LightLevel) << 16; // Set maximum alpha channel value ARGBColor = (int)((uint)ARGBColor | 0xff000000); IlluminatedFaceColor = Color.FromArgb(ARGBColor); // Calculate factors for the polygon filling routine TVertex FaceNormal = Math3D.CalcFaceNormal(FaceVertex[0], FaceVertex[1], FaceVertex[2]); float M, N, K; CalculatePolygonFactors(FaceNormal, FaceVertex[1], PerspectiveFactor, out M, out N, out K); TriangleFiller.DrawFilledTriangle(ScreenTriangle, Context, IlluminatedFaceColor, M, N, K); } } } } } RenderChildObjects(Context); }
private void TransformAxis(TMat4x4 Mat) { TransformedAxisPointA = Mat.MulVertex(OriginalAxisPointA); TransformedAxisPointB = Mat.MulVertex(OriginalAxisPointB); }
public TMat4x4 FindInverseMat() { float Det; float[,] C = new float[4, 4]; C[0, 0] = m11 * (m22 * m33 - m23 * m32) - m12 * (m21 * m33 - m23 * m31) + m13 * (m21 * m32 - m22 * m31); C[0, 1] = -(m10 * (m22 * m33 - m23 * m32) - m12 * (m20 * m33 - m23 * m30) + m13 * (m20 * m32 - m22 * m30)); C[0, 2] = m10 * (m21 * m33 - m23 * m31) - m11 * (m20 * m33 - m23 * m30) + m13 * (m20 * m31 - m21 * m30); C[0, 3] = 0; C[1, 0] = -(m01 * (m22 * m33 - m23 * m32) - m02 * (m21 * m33 - m23 * m31) + m03 * (m21 * m32 - m22 * m31)); C[1, 1] = m00 * (m22 * m33 - m23 * m32) - m02 * (m20 * m33 - m23 * m30) + m03 * (m20 * m32 - m22 * m30); C[1, 2] = -(m00 * (m21 * m33 - m23 * m31) - m01 * (m20 * m33 - m23 * m30) + m03 * (m20 * m31 - m21 * m30)); C[1, 3] = 0; C[2, 0] = m01 * (m12 * m33 - m13 * m32) - m02 * (m11 * m33 - m13 * m31) + m03 * (m11 * m32 - m12 * m31); C[2, 1] = -(m00 * (m12 * m33 - m13 * m32) - m02 * (m10 * m33 - m13 * m30) + m03 * (m10 * m32 - m12 * m30)); C[2, 2] = m00 * (m11 * m33 - m13 * m31) - m01 * (m10 * m33 - m13 * m30) + m03 * (m10 * m31 - m11 * m30); C[2, 3] = 0; C[3, 0] = -(m01 * (m12 * m23 - m13 * m22) - m02 * (m11 * m23 - m13 * m21) + m03 * (m11 * m22 - m12 * m21)); C[3, 1] = m00 * (m12 * m23 - m13 * m22) - m02 * (m10 * m23 - m13 * m20) + m03 * (m10 * m22 - m12 * m20); C[3, 2] = -(m00 * (m11 * m23 - m13 * m21) - m01 * (m10 * m23 - m13 * m20) + m03 * (m10 * m21 - m11 * m20)); C[3, 3] = m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m12 * m20) + m02 * (m10 * m21 - m11 * m20); Det = 0; // Create a temporary array in order to ease calculations float[,] TmpM = ConvertToArray(); for (int i = 0; i < 4; i++) { Det += TmpM[0, i] * C[0, i]; } float[,] Result = new float[4, 4]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { Result[i, j] = C[j, i] / Det; } } Result[3, 3] = 1; for (int i = 0; i < 4; i++) { Result[i, 3] = 0; Result[3, i] = 0; for (int j = 0; j < 4; j++) { Result[3, i] = Result[3, i] + TmpM[3, j] * Result[j, i]; } Result[3, i] = -Result[3, i]; } TMat4x4 InverseMat = ZeroMat(); InverseMat.ConvertFromArray(Result); return(InverseMat); }
// Set rotation matrix around arbitrary axis public void SetArbitraryRot(TVertex P1, TVertex P2, float Angle) { TMat4x4 MTra = ZeroMat(), MRo_X = ZeroMat(), MRo_Y = ZeroMat(), MRo_Z = ZeroMat(), TempM = ZeroMat(); float D; // Find the direction cosines of the arbitrary axis P1-->P2 . // The direction cosines will be in C TVertex C = Math3D.CalcNormalizedVec(P1, P2); D = (float)Math.Sqrt(Math3D.Sqr(C.Y) + Math3D.Sqr(C.Z)); // Special case for the X axis if (D == 0) { MTra.SetTrans(-P1.X, -P1.Y, -P1.Z); MRo_X.SetRotateX(Angle); TempM = MTra.MulMat(MRo_X); MTra.SetTrans(P1.X, P1.Y, P1.Z); this = TempM.MulMat(MTra); } else { MTra.SetTrans(-P1.X, -P1.Y, -P1.Z); // Prepare matrix rotation about axis X with angle Alfa Cos(Alfa) = C.z / D Sin(Alfa) = C.y / D } MRo_X.SetUnit(); MRo_X.m11 = C.Z / D; MRo_X.m22 = MRo_X.m11; MRo_X.m12 = C.Y / D; MRo_X.m21 = -MRo_X.m12; // prepare matrix rotation about axis Y with angle Beta Cos(Beta) = D Sin(Beta) = -C.x MRo_Y.SetUnit(); MRo_Y.m00 = D; MRo_Y.m22 = MRo_Y.m00; MRo_Y.m02 = C.X; MRo_Y.m20 = -MRo_Y.m02; TMat4x4 M; // M= Trans * Rot about axis X * Rot about axis Y TempM = MTra.MulMat(MRo_X); M = TempM.MulMat(MRo_Y); // prepare matrix rotation about axis Z with angle Angle MRo_Z.SetRotateZ(Angle); // TempM= Trans * Rot axis X * Rot axis Y * Rot about axis Z by angle Angle TempM = M.MulMat(MRo_Z); // Find inverse Y matrix MRo_Y.m00 = D; MRo_Y.m22 = D; MRo_Y.m02 = -C.X; MRo_Y.m20 = C.X; M = TempM.MulMat(MRo_Y); // Find inverse x matrix MRo_X.m11 = C.Z / D; MRo_X.m22 = MRo_X.m11; MRo_X.m21 = C.Y / D; MRo_X.m12 = -MRo_X.m21; TempM = M.MulMat(MRo_X); // Find inverse translation matrix MTra.SetTrans(P1.X, P1.Y, P1.Z); this = TempM.MulMat(MTra); } }