Beispiel #1
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);
        }