Exemple #1
0
        public void RenderFace(Shader Shader, ObjectState State, MeshFace Face, Matrix4D modelMatrix, Matrix4D modelViewMatrix, bool IsDebugTouchMode = false)
        {
            if (State.Prototype.Mesh.Vertices.Length < 1)
            {
                return;
            }

            MeshMaterial      material = State.Prototype.Mesh.Materials[Face.Material];
            VertexArrayObject VAO      = (VertexArrayObject)State.Prototype.Mesh.VAO;

            if (lastVAO != VAO.handle)
            {
                VAO.Bind();
                lastVAO = VAO.handle;
            }

            if (!OptionBackFaceCulling || (Face.Flags & MeshFace.Face2Mask) != 0)
            {
                GL.Disable(EnableCap.CullFace);
            }
            else if (OptionBackFaceCulling)
            {
                if ((Face.Flags & MeshFace.Face2Mask) == 0)
                {
                    GL.Enable(EnableCap.CullFace);
                }
            }

            // matrix

            Shader.SetCurrentModelViewMatrix(modelViewMatrix);
            Shader.SetCurrentTextureMatrix(State.TextureTranslation);

            if (OptionWireFrame || IsDebugTouchMode)
            {
                if (material.Color != lastColor)
                {
                    Shader.SetMaterialAmbient(material.Color);
                    lastColor = material.Color;
                }
                Shader.SetOpacity(1.0f);
                Shader.SetBrightness(1.0f);
                VAO.Draw(PrimitiveType.LineLoop, Face.IboStartIndex, Face.Vertices.Length);
                return;
            }

            // lighting
            if (OptionLighting)
            {
                if (material.Color != lastColor)
                {
                    Shader.SetMaterialAmbient(material.Color);
                    Shader.SetMaterialDiffuse(material.Color);
                    Shader.SetMaterialSpecular(material.Color);
                    //TODO: Ambient and specular colors are not set by any current parsers
                }

                if ((material.Flags & MeshMaterial.EmissiveColorMask) != 0)
                {
                    Shader.SetMaterialEmission(material.EmissiveColor);
                    Shader.SetMaterialEmissive(true);
                }
                else
                {
                    Shader.SetMaterialEmissive(false);
                }

                Shader.SetMaterialShininess(1.0f);
            }
            else
            {
                if (material.Color != lastColor)
                {
                    Shader.SetMaterialAmbient(material.Color);
                }
                //As lighting is disabled, the face cannot be emitting light....
                Shader.SetMaterialEmissive(false);
            }

            lastColor = material.Color;
            PrimitiveType DrawMode;

            switch (Face.Flags & MeshFace.FaceTypeMask)
            {
            case MeshFace.FaceTypeTriangles:
                DrawMode = PrimitiveType.Triangles;
                break;

            case MeshFace.FaceTypeTriangleStrip:
                DrawMode = PrimitiveType.TriangleStrip;
                break;

            case MeshFace.FaceTypeQuads:
                DrawMode = PrimitiveType.Quads;
                break;

            case MeshFace.FaceTypeQuadStrip:
                DrawMode = PrimitiveType.QuadStrip;
                break;

            default:
                DrawMode = PrimitiveType.Polygon;
                break;
            }

            // daytime polygon
            {
                // texture
                if (material.DaytimeTexture != null && currentHost.LoadTexture(material.DaytimeTexture, (OpenGlTextureWrapMode)material.WrapMode))
                {
                    Shader.SetIsTexture(true);
                    if (LastBoundTexture != material.DaytimeTexture.OpenGlTextures[(int)material.WrapMode])
                    {
                        GL.BindTexture(TextureTarget.Texture2D,
                                       material.DaytimeTexture.OpenGlTextures[(int)material.WrapMode].Name);
                        LastBoundTexture = material.DaytimeTexture.OpenGlTextures[(int)material.WrapMode];
                    }
                }
                else
                {
                    Shader.SetIsTexture(false);
                }

                // Calculate the brightness of the poly to render
                float factor;
                if (material.BlendMode == MeshMaterialBlendMode.Additive)
                {
                    //Additive blending- Full brightness
                    factor = 1.0f;
                    GL.Enable(EnableCap.Blend);
                    GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.One);
                    Shader.SetIsFog(false);
                }
                else if ((material.Flags & MeshMaterial.EmissiveColorMask) != 0)
                {
                    //As material is emitting light, it must be at full brightness
                    factor = 1.0f;
                }
                else if (material.NighttimeTexture == null || material.NighttimeTexture == material.DaytimeTexture)
                {
                    //No nighttime texture or both are identical- Darken the polygon to match the light conditions
                    float blend = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount;
                    if (blend > 1.0f)
                    {
                        blend = 1.0f;
                    }

                    factor = 1.0f - 0.7f * blend;
                }
                else
                {
                    //Valid nighttime texture- Blend the two textures by DNB at max brightness
                    factor = 1.0f;
                }
                Shader.SetBrightness(factor);

                float alphaFactor;
                GlowAttenuationMode mode = GlowAttenuationMode.None;
                if (material.GlowAttenuationData != 0)
                {
                    alphaFactor = (float)Glow.GetDistanceFactor(modelMatrix, State.Prototype.Mesh.Vertices, ref Face, material.GlowAttenuationData, out mode);
                }
                else
                {
                    alphaFactor = 1.0f;
                }

                if (material.BlendMode == MeshMaterialBlendMode.Additive)
                {
                    Shader.SetMaterialAdditive(1 + (int)mode);
                }
                else
                {
                    Shader.SetMaterialAdditive(0);
                }

                Shader.SetOpacity(inv255 * material.Color.A * alphaFactor);

                // render polygon
                VAO.Draw(DrawMode, Face.IboStartIndex, Face.Vertices.Length);
            }

            // nighttime polygon
            if (material.NighttimeTexture != null && material.NighttimeTexture != material.DaytimeTexture && currentHost.LoadTexture(material.NighttimeTexture, (OpenGlTextureWrapMode)material.WrapMode))
            {
                // texture
                Shader.SetIsTexture(true);
                if (LastBoundTexture != material.NighttimeTexture.OpenGlTextures[(int)material.WrapMode])
                {
                    GL.BindTexture(TextureTarget.Texture2D, material.NighttimeTexture.OpenGlTextures[(int)material.WrapMode].Name);
                    LastBoundTexture = material.NighttimeTexture.OpenGlTextures[(int)material.WrapMode];
                }


                GL.Enable(EnableCap.Blend);

                // alpha test
                GL.Enable(EnableCap.AlphaTest);
                GL.AlphaFunc(AlphaFunction.Greater, 0.0f);

                // blend mode
                float alphaFactor;
                if (material.GlowAttenuationData != 0)
                {
                    alphaFactor = (float)Glow.GetDistanceFactor(modelMatrix, State.Prototype.Mesh.Vertices, ref Face, material.GlowAttenuationData);
                    float blend = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount;
                    if (blend > 1.0f)
                    {
                        blend = 1.0f;
                    }

                    alphaFactor *= blend;
                }
                else
                {
                    alphaFactor = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount;
                    if (alphaFactor > 1.0f)
                    {
                        alphaFactor = 1.0f;
                    }
                }

                Shader.SetOpacity(inv255 * material.Color.A * alphaFactor);

                // render polygon
                VAO.Draw(DrawMode, Face.IboStartIndex, Face.Vertices.Length);
                RestoreBlendFunc();
                RestoreAlphaFunc();
            }


            // normals
            if (OptionNormals)
            {
                Shader.SetIsTexture(false);
                Shader.SetBrightness(1.0f);
                Shader.SetOpacity(1.0f);
                VertexArrayObject NormalsVAO = (VertexArrayObject)State.Prototype.Mesh.NormalsVAO;
                NormalsVAO.Bind();
                lastVAO = NormalsVAO.handle;
                NormalsVAO.Draw(PrimitiveType.Lines, Face.NormalsIboStartIndex, Face.Vertices.Length * 2);
            }

            // finalize
            if (material.BlendMode == MeshMaterialBlendMode.Additive)
            {
                RestoreBlendFunc();
                Shader.SetIsFog(OptionFog);
            }
        }
Exemple #2
0
        private static void RenderFace(ref MeshMaterial Material, VertexTemplate[] Vertices, OpenGlTextureWrapMode wrap, ref MeshFace Face, double CameraX, double CameraY, double CameraZ)
        {
            // texture
            if (Material.DaytimeTexture != null)
            {
                if (Textures.LoadTexture(Material.DaytimeTexture, wrap))
                {
                    if (!TexturingEnabled)
                    {
                        GL.Enable(EnableCap.Texture2D);
                        TexturingEnabled = true;
                    }
                    if (Material.DaytimeTexture.OpenGlTextures[(int)wrap] != LastBoundTexture)
                    {
                        GL.BindTexture(TextureTarget.Texture2D, Material.DaytimeTexture.OpenGlTextures[(int)wrap].Name);
                        LastBoundTexture = Material.DaytimeTexture.OpenGlTextures[(int)wrap];
                    }
                }
                else
                {
                    if (TexturingEnabled)
                    {
                        GL.Disable(EnableCap.Texture2D);
                        TexturingEnabled = false;
                        LastBoundTexture = null;
                    }
                }
            }
            else
            {
                if (TexturingEnabled)
                {
                    GL.Disable(EnableCap.Texture2D);
                    TexturingEnabled = false;
                    LastBoundTexture = null;
                }
            }
            // blend mode
            float factor;

            if (Material.BlendMode == MeshMaterialBlendMode.Additive)
            {
                factor = 1.0f;
                if (!BlendEnabled)
                {
                    GL.Enable(EnableCap.Blend);
                }
                GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.One);
                if (FogEnabled)
                {
                    GL.Disable(EnableCap.Fog);
                }
            }
            else if (Material.NighttimeTexture == null)
            {
                float blend = inv255 * (float)Material.DaytimeNighttimeBlend + 1.0f - OptionLightingResultingAmount;
                if (blend > 1.0f)
                {
                    blend = 1.0f;
                }
                factor = 1.0f - 0.7f * blend;
            }
            else
            {
                factor = 1.0f;
            }
            if (Material.NighttimeTexture != null)
            {
                if (LightingEnabled)
                {
                    GL.Disable(EnableCap.Lighting);
                    LightingEnabled = false;
                }
            }
            else
            {
                if (OptionLighting & !LightingEnabled)
                {
                    GL.Enable(EnableCap.Lighting);
                    LightingEnabled = true;
                }
            }
            // render daytime polygon
            int FaceType = Face.Flags & MeshFace.FaceTypeMask;

            switch (FaceType)
            {
            case MeshFace.FaceTypeTriangles:
                GL.Begin(PrimitiveType.Triangles);
                break;

            case MeshFace.FaceTypeTriangleStrip:
                GL.Begin(PrimitiveType.TriangleStrip);
                break;

            case MeshFace.FaceTypeQuads:
                GL.Begin(PrimitiveType.Quads);
                break;

            case MeshFace.FaceTypeQuadStrip:
                GL.Begin(PrimitiveType.QuadStrip);
                break;

            default:
                GL.Begin(PrimitiveType.Polygon);
                break;
            }
            if (Material.GlowAttenuationData != 0)
            {
                float alphafactor = (float)GetDistanceFactor(Vertices, ref Face, Material.GlowAttenuationData, CameraX, CameraY, CameraZ);
                if (OptionWireframe)
                {
                    GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, 1.0f);
                }
                else
                {
                    GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, inv255 * (float)Material.Color.A * alphafactor);
                }
            }
            else
            {
                if (OptionWireframe)
                {
                    GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, 1.0f);
                }
                else
                {
                    GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, inv255 * (float)Material.Color.A);
                }
            }
            if ((Material.Flags & MeshMaterial.EmissiveColorMask) != 0)
            {
                GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new float[] { inv255 *(float)Material.EmissiveColor.R, inv255 * (float)Material.EmissiveColor.G, inv255 * (float)Material.EmissiveColor.B, 1.0f });
            }
            else
            {
                GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new float[] { 0.0f, 0.0f, 0.0f, 1.0f });
            }
            if (Material.DaytimeTexture != null)
            {
                if (LightingEnabled)
                {
                    for (int j = 0; j < Face.Vertices.Length; j++)
                    {
                        GL.Normal3(Face.Vertices[j].Normal.X, Face.Vertices[j].Normal.Y, Face.Vertices[j].Normal.Z);
                        GL.TexCoord2(Vertices[Face.Vertices[j].Index].TextureCoordinates.X, Vertices[Face.Vertices[j].Index].TextureCoordinates.Y);
                        if (Vertices[Face.Vertices[j].Index] is ColoredVertex)
                        {
                            ColoredVertex v = (ColoredVertex)Vertices[Face.Vertices[j].Index];
                            GL.Color3(v.Color.R, v.Color.G, v.Color.B);
                        }
                        GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ));
                    }
                }
                else
                {
                    for (int j = 0; j < Face.Vertices.Length; j++)
                    {
                        GL.TexCoord2(Vertices[Face.Vertices[j].Index].TextureCoordinates.X, Vertices[Face.Vertices[j].Index].TextureCoordinates.Y);
                        if (Vertices[Face.Vertices[j].Index] is ColoredVertex)
                        {
                            ColoredVertex v = (ColoredVertex)Vertices[Face.Vertices[j].Index];
                            GL.Color3(v.Color.R, v.Color.G, v.Color.B);
                        }
                        GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ));
                    }
                }
            }
            else
            {
                if (LightingEnabled)
                {
                    for (int j = 0; j < Face.Vertices.Length; j++)
                    {
                        GL.Normal3(Face.Vertices[j].Normal.X, Face.Vertices[j].Normal.Y, Face.Vertices[j].Normal.Z);
                        if (Vertices[Face.Vertices[j].Index] is ColoredVertex)
                        {
                            ColoredVertex v = (ColoredVertex)Vertices[Face.Vertices[j].Index];
                            GL.Color3(v.Color.R, v.Color.G, v.Color.B);
                        }
                        GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ));
                    }
                }
                else
                {
                    for (int j = 0; j < Face.Vertices.Length; j++)
                    {
                        if (Vertices[Face.Vertices[j].Index] is ColoredVertex)
                        {
                            ColoredVertex v = (ColoredVertex)Vertices[Face.Vertices[j].Index];
                            GL.Color3(v.Color.R, v.Color.G, v.Color.B);
                        }
                        GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ));
                    }
                }
            }
            GL.End();
            // render nighttime polygon
            if (Material.NighttimeTexture != null && Textures.LoadTexture(Material.NighttimeTexture, wrap))
            {
                if (!TexturingEnabled)
                {
                    GL.Enable(EnableCap.Texture2D);
                    TexturingEnabled = true;
                }
                if (!BlendEnabled)
                {
                    GL.Enable(EnableCap.Blend);
                }
                GL.BindTexture(TextureTarget.Texture2D, Material.NighttimeTexture.OpenGlTextures[(int)wrap].Name);
                LastBoundTexture = null;
                GL.AlphaFunc(AlphaFunction.Greater, 0.0f);
                GL.Enable(EnableCap.AlphaTest);
                switch (FaceType)
                {
                case MeshFace.FaceTypeTriangles:
                    GL.Begin(PrimitiveType.Triangles);
                    break;

                case MeshFace.FaceTypeTriangleStrip:
                    GL.Begin(PrimitiveType.TriangleStrip);
                    break;

                case MeshFace.FaceTypeQuads:
                    GL.Begin(PrimitiveType.Quads);
                    break;

                case MeshFace.FaceTypeQuadStrip:
                    GL.Begin(PrimitiveType.QuadStrip);
                    break;

                default:
                    GL.Begin(PrimitiveType.Polygon);
                    break;
                }
                float alphafactor;
                if (Material.GlowAttenuationData != 0)
                {
                    alphafactor = (float)GetDistanceFactor(Vertices, ref Face, Material.GlowAttenuationData, CameraX, CameraY, CameraZ);
                    float blend = inv255 * (float)Material.DaytimeNighttimeBlend + 1.0f - OptionLightingResultingAmount;
                    if (blend > 1.0f)
                    {
                        blend = 1.0f;
                    }
                    alphafactor *= blend;
                }
                else
                {
                    alphafactor = inv255 * (float)Material.DaytimeNighttimeBlend + 1.0f - OptionLightingResultingAmount;
                    if (alphafactor > 1.0f)
                    {
                        alphafactor = 1.0f;
                    }
                }
                if (OptionWireframe)
                {
                    GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, 1.0f);
                }
                else
                {
                    GL.Color4(inv255 * (float)Material.Color.R * factor, inv255 * Material.Color.G * factor, inv255 * (float)Material.Color.B * factor, inv255 * (float)Material.Color.A * alphafactor);
                }

                if ((Material.Flags & MeshMaterial.EmissiveColorMask) != 0)
                {
                    GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new float[] { inv255 *(float)Material.EmissiveColor.R, inv255 * (float)Material.EmissiveColor.G, inv255 * (float)Material.EmissiveColor.B, 1.0f });
                }
                else
                {
                    GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new float[] { 0.0f, 0.0f, 0.0f, 1.0f });
                }
                for (int j = 0; j < Face.Vertices.Length; j++)
                {
                    GL.TexCoord2(Vertices[Face.Vertices[j].Index].TextureCoordinates.X, Vertices[Face.Vertices[j].Index].TextureCoordinates.Y);
                    if (Vertices[Face.Vertices[j].Index] is ColoredVertex)
                    {
                        ColoredVertex v = (ColoredVertex)Vertices[Face.Vertices[j].Index];
                        GL.Color3(v.Color.R, v.Color.G, v.Color.B);
                    }
                    GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ));
                }
                GL.End();
                RestoreAlphaFunc();
                if (!BlendEnabled)
                {
                    GL.Disable(EnableCap.Blend);
                }
            }
            // normals
            if (OptionNormals)
            {
                if (TexturingEnabled)
                {
                    GL.Disable(EnableCap.Texture2D);
                    TexturingEnabled = false;
                }
                for (int j = 0; j < Face.Vertices.Length; j++)
                {
                    GL.Begin(PrimitiveType.Lines);
                    GL.Color4(inv255 * (float)Material.Color.R, inv255 * (float)Material.Color.G, inv255 * (float)Material.Color.B, 1.0f);
                    GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z - CameraZ));
                    GL.Vertex3((float)(Vertices[Face.Vertices[j].Index].Coordinates.X + Face.Vertices[j].Normal.X - CameraX), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Y + Face.Vertices[j].Normal.Y - CameraY), (float)(Vertices[Face.Vertices[j].Index].Coordinates.Z + Face.Vertices[j].Normal.Z - CameraZ));
                    GL.End();
                }
            }
            // finalize
            if (Material.BlendMode == MeshMaterialBlendMode.Additive)
            {
                GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
                if (!BlendEnabled)
                {
                    GL.Disable(EnableCap.Blend);
                }
                if (FogEnabled)
                {
                    GL.Enable(EnableCap.Fog);
                }
            }
        }
Exemple #3
0
        public void RenderFaceImmediateMode(ObjectState State, MeshFace Face, bool IsDebugTouchMode = false)
        {
            if (State.Prototype.Mesh.Vertices.Length < 1)
            {
                return;
            }

            VertexTemplate[] vertices = State.Prototype.Mesh.Vertices;
            MeshMaterial     material = State.Prototype.Mesh.Materials[Face.Material];

            if (!OptionBackFaceCulling || (Face.Flags & MeshFace.Face2Mask) != 0)
            {
                GL.Disable(EnableCap.CullFace);
            }
            else if (OptionBackFaceCulling)
            {
                if ((Face.Flags & MeshFace.Face2Mask) == 0)
                {
                    GL.Enable(EnableCap.CullFace);
                }
            }
            Matrix4D modelMatrix = State.ModelMatrix * Camera.TranslationMatrix;

            // matrix
            unsafe
            {
                GL.MatrixMode(MatrixMode.Projection);
                GL.PushMatrix();
                fixed(double *matrixPointer = &CurrentProjectionMatrix.Row0.X)
                {
                    GL.LoadMatrix(matrixPointer);
                }

                GL.MatrixMode(MatrixMode.Modelview);
                GL.PushMatrix();
                fixed(double *matrixPointer = &CurrentViewMatrix.Row0.X)
                {
                    GL.LoadMatrix(matrixPointer);
                }

                double *matrixPointer2 = &modelMatrix.Row0.X;
                {
                    GL.MultMatrix(matrixPointer2);
                }

                GL.MatrixMode(MatrixMode.Texture);
                GL.PushMatrix();
                fixed(double *matrixPointer = &State.TextureTranslation.Row0.X)
                {
                    GL.LoadMatrix(matrixPointer);
                }
            }


            if (OptionWireFrame)
            {
                GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
            }

            // lighting
            if (material.NighttimeTexture == null)
            {
                if (OptionLighting)
                {
                    GL.Enable(EnableCap.Lighting);
                }
            }

            if ((material.Flags & MeshMaterial.EmissiveColorMask) != 0)
            {
                GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new Color4(material.EmissiveColor.R, material.EmissiveColor.G, material.EmissiveColor.B, 255));
            }
            else
            {
                GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new Color4(0.0f, 0.0f, 0.0f, 1.0f));
            }

            // fog
            if (OptionFog)
            {
                GL.Enable(EnableCap.Fog);
            }

            PrimitiveType DrawMode;

            switch (Face.Flags & MeshFace.FaceTypeMask)
            {
            case MeshFace.FaceTypeTriangles:
                DrawMode = PrimitiveType.Triangles;
                break;

            case MeshFace.FaceTypeTriangleStrip:
                DrawMode = PrimitiveType.TriangleStrip;
                break;

            case MeshFace.FaceTypeQuads:
                DrawMode = PrimitiveType.Quads;
                break;

            case MeshFace.FaceTypeQuadStrip:
                DrawMode = PrimitiveType.QuadStrip;
                break;

            default:
                DrawMode = PrimitiveType.Polygon;
                break;
            }

            // daytime polygon
            {
                // texture
                if (material.DaytimeTexture != null)
                {
                    if (currentHost.LoadTexture(material.DaytimeTexture, (OpenGlTextureWrapMode)material.WrapMode))
                    {
                        GL.Enable(EnableCap.Texture2D);
                        if (LastBoundTexture != material.DaytimeTexture.OpenGlTextures[(int)material.WrapMode])
                        {
                            GL.BindTexture(TextureTarget.Texture2D, material.DaytimeTexture.OpenGlTextures[(int)material.WrapMode].Name);
                            LastBoundTexture = material.DaytimeTexture.OpenGlTextures[(int)material.WrapMode];
                        }
                    }
                }

                // blend mode
                float factor;
                if (material.BlendMode == MeshMaterialBlendMode.Additive)
                {
                    factor = 1.0f;
                    GL.Enable(EnableCap.Blend);
                    GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.One);
                    GL.Disable(EnableCap.Fog);
                }
                else if (material.NighttimeTexture == null)
                {
                    float blend = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount;

                    if (blend > 1.0f)
                    {
                        blend = 1.0f;
                    }

                    factor = 1.0f - 0.7f * blend;
                }
                else
                {
                    factor = 1.0f;
                }

                float alphaFactor;
                if (material.GlowAttenuationData != 0)
                {
                    alphaFactor = (float)Glow.GetDistanceFactor(modelMatrix, vertices, ref Face, material.GlowAttenuationData);
                }
                else
                {
                    alphaFactor = 1.0f;
                }

                GL.Begin(DrawMode);

                if (OptionWireFrame)
                {
                    GL.Color4(inv255 * material.Color.R * factor, inv255 * material.Color.G * factor, inv255 * material.Color.B * factor, 1.0f);
                }
                else
                {
                    GL.Color4(inv255 * material.Color.R * factor, inv255 * material.Color.G * factor, inv255 * material.Color.B * factor, inv255 * material.Color.A * alphaFactor);
                }

                for (int i = 0; i < Face.Vertices.Length; i++)
                {
                    GL.Normal3(Face.Vertices[i].Normal.X, Face.Vertices[i].Normal.Y, -Face.Vertices[i].Normal.Z);
                    GL.TexCoord2(vertices[Face.Vertices[i].Index].TextureCoordinates.X, vertices[Face.Vertices[i].Index].TextureCoordinates.Y);

                    if (vertices[Face.Vertices[i].Index] is ColoredVertex)
                    {
                        ColoredVertex v = (ColoredVertex)vertices[Face.Vertices[i].Index];
                        GL.Color3(v.Color.R, v.Color.G, v.Color.B);
                    }

                    GL.Vertex3(vertices[Face.Vertices[i].Index].Coordinates.X, vertices[Face.Vertices[i].Index].Coordinates.Y, -vertices[Face.Vertices[i].Index].Coordinates.Z);
                }
                GL.End();
            }

            // nighttime polygon
            if (material.NighttimeTexture != null && currentHost.LoadTexture(material.NighttimeTexture, (OpenGlTextureWrapMode)material.WrapMode))
            {
                // texture
                GL.Enable(EnableCap.Texture2D);
                if (LastBoundTexture != material.NighttimeTexture.OpenGlTextures[(int)material.WrapMode])
                {
                    GL.BindTexture(TextureTarget.Texture2D, material.NighttimeTexture.OpenGlTextures[(int)material.WrapMode].Name);
                    LastBoundTexture = material.NighttimeTexture.OpenGlTextures[(int)material.WrapMode];
                }

                GL.Enable(EnableCap.Blend);

                // alpha test
                GL.Enable(EnableCap.AlphaTest);
                GL.AlphaFunc(AlphaFunction.Greater, 0.0f);

                // blend mode
                float alphaFactor;
                if (material.GlowAttenuationData != 0)
                {
                    alphaFactor = (float)Glow.GetDistanceFactor(modelMatrix, vertices, ref Face, material.GlowAttenuationData);
                    float blend = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount;
                    if (blend > 1.0f)
                    {
                        blend = 1.0f;
                    }

                    alphaFactor *= blend;
                }
                else
                {
                    alphaFactor = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount;
                    if (alphaFactor > 1.0f)
                    {
                        alphaFactor = 1.0f;
                    }
                }

                GL.Begin(DrawMode);

                if (OptionWireFrame)
                {
                    GL.Color4(inv255 * material.Color.R, inv255 * material.Color.G, inv255 * material.Color.B, 1.0f);
                }
                else
                {
                    GL.Color4(inv255 * material.Color.R, inv255 * material.Color.G, inv255 * material.Color.B, inv255 * material.Color.A * alphaFactor);
                }

                for (int i = 0; i < Face.Vertices.Length; i++)
                {
                    GL.Normal3(Face.Vertices[i].Normal.X, Face.Vertices[i].Normal.Y, -Face.Vertices[i].Normal.Z);
                    GL.TexCoord2(vertices[Face.Vertices[i].Index].TextureCoordinates.X, vertices[Face.Vertices[i].Index].TextureCoordinates.Y);

                    if (vertices[Face.Vertices[i].Index] is ColoredVertex)
                    {
                        ColoredVertex v = (ColoredVertex)vertices[Face.Vertices[i].Index];
                        GL.Color3(v.Color.R, v.Color.G, v.Color.B);
                    }

                    GL.Vertex3(vertices[Face.Vertices[i].Index].Coordinates.X, vertices[Face.Vertices[i].Index].Coordinates.Y, -vertices[Face.Vertices[i].Index].Coordinates.Z);
                }

                GL.End();
                RestoreBlendFunc();
                RestoreAlphaFunc();
            }

            GL.Disable(EnableCap.Texture2D);

            // normals
            if (OptionNormals)
            {
                for (int i = 0; i < Face.Vertices.Length; i++)
                {
                    GL.Begin(PrimitiveType.Lines);
                    GL.Color4(new Color4(material.Color.R, material.Color.G, material.Color.B, 255));
                    GL.Vertex3(vertices[Face.Vertices[i].Index].Coordinates.X, vertices[Face.Vertices[i].Index].Coordinates.Y, -vertices[Face.Vertices[i].Index].Coordinates.Z);
                    GL.Vertex3(vertices[Face.Vertices[i].Index].Coordinates.X + Face.Vertices[i].Normal.X, vertices[Face.Vertices[i].Index].Coordinates.Y + +Face.Vertices[i].Normal.Z, -(vertices[Face.Vertices[i].Index].Coordinates.Z + Face.Vertices[i].Normal.Z));
                    GL.End();
                }
            }

            // finalize
            if (OptionWireFrame)
            {
                GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
            }

            if (material.BlendMode == MeshMaterialBlendMode.Additive)
            {
                RestoreBlendFunc();
            }

            GL.PopMatrix();

            GL.MatrixMode(MatrixMode.Modelview);
            GL.PopMatrix();

            GL.MatrixMode(MatrixMode.Projection);
            GL.PopMatrix();
        }