示例#1
0
        public static TVertex CrossProduct(TVertex P1, TVertex P2)
        {
            TVertex Result = new TVertex(P1.Y * P2.Z - P1.Z * P2.Y,
                                         P1.Z * P2.X - P1.X * P2.Z,
                                         P1.X * P2.Y - P1.Y * P2.X);

            return(Result);
        }
示例#2
0
 public void AddChildObject(CObject3D ChildObj, TVertex AxisPointA, TVertex AxisPointB)
 {
     Children.Add(ChildObj);
     ChildObj.Father                = this;
     ChildObj.OriginalAxisPointA    = AxisPointA;
     ChildObj.TransformedAxisPointA = AxisPointA;
     ChildObj.OriginalAxisPointB    = AxisPointB;
     ChildObj.TransformedAxisPointB = AxisPointB;
 }
示例#3
0
        public void SetPos(TVertex NewPos)
        {
            CurrentPos = NewPos;

            TMat4x4 TransMat = TMat4x4.ZeroMat();

            TransMat.SetTrans(NewPos.X, NewPos.Y, NewPos.Z);
            SetMatrix(TransMat);
        }
示例#4
0
        public TVertex MulVertex(TVertex v)
        {
            TVertex Result;

            Result.X = v.X * m00 + v.Y * m10 + v.Z * m20 + m30;
            Result.Y = v.X * m01 + v.Y * m11 + v.Z * m21 + m31;
            Result.Z = v.X * m02 + v.Y * m12 + v.Z * m22 + m32;

            return(Result);
        }
示例#5
0
        public TVertex FindNewPosXZ(float DeltaStep)
        {
            float AngleInRad = Math3D.Deg2Rad(Orientation);

            TVertex Result = new TVertex(CurrentPos.X + (float)Math.Sin(AngleInRad) * DeltaStep,
                                         CurrentPos.Y,
                                         CurrentPos.Z + (float)Math.Cos(AngleInRad) * DeltaStep);

            return(Result);
        }
示例#6
0
        // Return a normalized vector
        public static TVertex CalcNormalizedVec(TVertex p1, TVertex p2)
        {
            float   Mag;
            TVertex Result;

            Mag      = (float)Math.Sqrt(Sqr(p1.X - p2.X) + Sqr(p1.Y - p2.Y) + Sqr(p1.Z - p2.Z));
            Result.X = (p2.X - p1.X) / Mag;
            Result.Y = (p2.Y - p1.Y) / Mag;
            Result.Z = (p2.Z - p1.Z) / Mag;

            return(Result);
        }
示例#7
0
        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));
        }
示例#8
0
        public static TVertex CalcFaceNormal(TVertex P1, TVertex P2, TVertex P3)
        {
            P2.X = P2.X - P1.X;
            P2.Y = P2.Y - P1.Y;
            P2.Z = P2.Z - P1.Z;

            P3.X = P3.X - P1.X;
            P3.Y = P3.Y - P1.Y;
            P3.Z = P3.Z - P1.Z;

            return(CrossProduct(P2, P3));
        }
示例#9
0
        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;
        }
示例#10
0
        private void CalculatePolygonFactors(TVertex Normal, TVertex PointOnPlane, float PerspFactor, out float M, out float N, out float K)
        {
            float A, B, C, D;

            A = Normal.X;
            B = Normal.Y;
            C = Normal.Z;
            D = Math3D.DotProduct(Normal, PointOnPlane);

            if (D != 0)
            {
                M = A / (D * PerspFactor);
                N = B / (D * PerspFactor);
                K = C / D;
            }
            else
            {
                M = 0;
                N = 0;
                K = 0;
            }
        }
示例#11
0
 public TVertex TransformVertex(TVertex v)
 {
     return(CombinedMatrix.MulVertex(v));
 }
示例#12
0
        // 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);
            }
        }
示例#13
0
 public static float DotProduct(TVertex P1, TVertex P2)
 {
     return(P1.X * P2.X + P1.Y * P2.Y + P1.Z * P2.Z);
 }
示例#14
0
 // The distance from point P1 to P2
 public static float PointDistance(TVertex P1, TVertex P2)
 {
     return((float)Math.Sqrt(Sqr(P1.X - P2.X) + Sqr(P1.Y - P2.Y) + Sqr(P1.Z - P2.Z)));
 }
示例#15
0
 private void TransformAxis(TMat4x4 Mat)
 {
     TransformedAxisPointA = Mat.MulVertex(OriginalAxisPointA);
     TransformedAxisPointB = Mat.MulVertex(OriginalAxisPointB);
 }
示例#16
0
 private bool TestForBackClipping(TVertex V1, TVertex V2, TVertex V3)
 {
     return(!((V1.Z < 0) && (V2.Z < 0) && (V3.Z < 0)));
 }
示例#17
0
        // 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);
        }