using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Tao.OpenGl;
using Tao.Platform.Windows;

namespace Ornek2020
{
    public partial class Form1 : Form
    {
        OBJLoader Model;
        //Texture ModelTextures;

        float[] ambientLight    = { 0.2f, 0.2f, 0.2f, 1.0f };
        float[] diffuseLight    = { 0.5f, 0.5f, 0.5f, 1.0f };
        float[] specularLight   = { 1.0f, 1.0f, 1.0f, 1.0f };
        float[] specularLight2  = { 1.0f, 1.0f, 1.0f, 1.0f };
        float[] blueDiffuse     = { 0.0f, 0.0f, 0.3f, 1.0f };

        float[] lightpos0 = { 0.0f, 100.0f, 100.0f, 1.0f };
        float[] lightpos1 = { 0.0f, 100.0f, 0.0f, 1.0f };
        float[] lightpos2 = { 100.0f, 0.0f, 0.0f, 1.0f };
        float[] lightpos3 = { -100.0f, 0.0f, 0.0f, 1.0f };

        float[] grey = { 0.5f, 0.5f, 0.5f, 1.0f };
        float[] white = { 1.0f, 1.0f, 1.0f, 1.0f };

        float[] darkPlastic = { 0.2f, 0.2f, 0.2f, 1.0f };
        float[] brightPlastic = { 0.3f, 0.3f, 0.3f, 1.0f };
        float[] darkSeats = { 1.0f, 1.0f, 1.0f, 1.0f };
        float[] brightSeats = { 1.0f, 1.0f, 1.0f, 1.0f };

        float[] bodyAmb = { 0.1f, 0.0f, 0.1f, 1.0f };
        float[] bodyDif = { 0.8f, 0.8f, 0.0f, 1.0f };
        float[] bodySpe = { 0.8f, 0.8f, 0.0f, 1.0f };

        float[] metalAmb = { 0.1f, 0.1f, 0.1f, 1.0f };
        float[] metalDif = { 0.4f, 0.4f, 0.4f, 1.0f };
        float[] metalSpe = { 0.6f, 0.6f, 0.6f, 1.0f };

        float[] glassAmb = { 0.1f, 0.1f, 0.1f, 0.5f };
        float[] glassDif = { 0.4f, 0.4f, 0.4f, 0.5f };
        float[] glassSpe = { 0.6f, 0.6f, 0.6f, 0.5f };

        float[] insideAmb = { 0.2f, 0.1f, 0.0f, 1.0f };
        float[] insideDif = { 0.4f, 0.2f, 0.0f, 1.0f };
        float[] insideSpe = { 0.4f, 0.2f, 0.0f, 1.0f };

        float[] lambAmb = { 0.4f, 0.4f, 0.4f, 0.8f };
        float[] lambDif = { 0.8f, 0.8f, 0.8f, 0.8f };
        float[] lambSpe = { 1.0f, 1.0f, 1.0f, 0.8f };

        public Form1()
        {
            InitializeComponent();
            OpenGlControl.InitializeContexts();
 
            // OpenGL ilk işlemler
            Gl.glClearColor(0.2f, 0.2f, 0.0f, 0.0f);
 
            float fAspect = 1.0f;

            // Reset coordinate system
            Gl.glMatrixMode(Gl.GL_PROJECTION);
            Gl.glLoadIdentity();

            // Produce the perspective projection
            Glu.gluPerspective(45.0f, fAspect, 1.0, 400.0);

            Gl.glMatrixMode(Gl.GL_MODELVIEW);
            Gl.glLoadIdentity();

            Gl.glHint(Gl.GL_PERSPECTIVE_CORRECTION_HINT, Gl.GL_NICEST);// Really Nice Perspective Calculations

            // Objemiz yüklenir
            Model = new OBJLoader();
            Model.MessageBox = LabelMessage;
            Model.LoadOBJ("Toyota_Prius_LBW.obj");

            //ModelTextures = new Texture();
            //ModelTextures.LoadGlTexture("brickwall.bmp", 0);

            Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_AMBIENT, ambientLight);
            Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_DIFFUSE, diffuseLight);
            Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_SPECULAR, specularLight);
            Gl.glLighti(Gl.GL_LIGHT0, Gl.GL_SHININESS, 127);
            Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_POSITION, lightpos0);

            Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_AMBIENT, ambientLight);
            Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_DIFFUSE, diffuseLight);
            Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_SPECULAR, specularLight);
            Gl.glLighti(Gl.GL_LIGHT1, Gl.GL_SHININESS, 127);
            Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_POSITION, lightpos1);

            Gl.glEnable(Gl.GL_LIGHTING);
            Gl.glEnable(Gl.GL_LIGHT0);
            Gl.glEnable(Gl.GL_LIGHT1);
            Gl.glEnable(Gl.GL_DEPTH_TEST);
            Gl.glEnable(Gl.GL_NORMALIZE);
            //Gl.glEnable(Gl.GL_POLYGON_SMOOTH);
            Gl.glHint(Gl.GL_POLYGON_SMOOTH_HINT, Gl.GL_NICEST);
            Gl.glShadeModel(Gl.GL_SMOOTH);

            Gl.glTranslatef(0, 0, -8);
            Gl.glRotatef(-80, 1, 0, 0);
        }

        private void MyKeyDown(object sender, KeyEventArgs e)
        {
            float step = 0.2f;
            switch (e.KeyCode)
            {
                case (Keys.A):
                    Gl.glTranslatef(step, 0, 0); break;
                case (Keys.D):
                    Gl.glTranslatef(-step, 0, 0); break;
                case (Keys.W):
                    Gl.glTranslatef(0, -step, 0); break;
                case (Keys.S):
                    Gl.glTranslatef(0, step, 0); break;
                case (Keys.T):
                    Gl.glTranslatef(0, 0, -step); break;
                case (Keys.Z):
                    Gl.glTranslatef(0, 0, step); break;
            }
            OpenGlControl.Refresh();
        }

        private void MyPreviewKwyDown(object sender, PreviewKeyDownEventArgs e)
        {
            switch (e.KeyData)
            {
                case (Keys.Up):
                    Gl.glRotatef(1f, 1, 0, 0); break;
                case (Keys.Down):
                    Gl.glRotatef(-1f, 1, 0, 0); break;
                case (Keys.Left):
                    Gl.glRotatef(1f, 0, 0, 1); break;
                case (Keys.Right):
                    Gl.glRotatef(-1f, 0, 0, 1); break;
                default:
                    break;
            }
            OpenGlControl.Refresh();
        }

        void TheScene()
        {
            Gl.glEnable(Gl.GL_CULL_FACE);

            Gl.glPushMatrix();

            int ObjectNum = 0;
            while (ObjectNum < Model.ObjectList.Count)
            {
                Gl.glDisable(Gl.GL_BLEND);

                string mat = Model.ObjectList[ObjectNum].Material;

                if (mat == "plastic2" || mat == "PLASTIC2" || mat == "ZWHEEL_MISC" || mat == "TYRE"
                    || mat == "ZWHEEL_RIM" || mat == "dark" || mat == "int_plastic")
                {
                    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_AMBIENT, darkPlastic);
                    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_DIFFUSE, darkPlastic);
                    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_SPECULAR, brightPlastic);
                    Gl.glMateriali(Gl.GL_FRONT, Gl.GL_SHININESS, 128);
                }
                else if (mat == "int_leather")
                {
                    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_AMBIENT, darkSeats);
                    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_DIFFUSE, darkSeats);
                    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_SPECULAR, brightSeats);
                    Gl.glMateriali(Gl.GL_FRONT, Gl.GL_SHININESS, 32);
                }
                else if (mat == "carpaint")
                {
                    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_AMBIENT, bodySpe);
                    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_DIFFUSE, bodyDif);
                    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_SPECULAR, bodySpe);
                    Gl.glMateriali(Gl.GL_FRONT, Gl.GL_SHININESS, 128);
                }
                else if (mat == "EXT_GLASS" || mat == "hdl_light")
                {
                    Gl.glEnable(Gl.GL_BLEND);
                    //Gl.glBlendFunc(Gl.GL_SRC_COLOR, Gl.GL_DST_COLOR);
                    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_AMBIENT, glassAmb);
                    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_DIFFUSE, glassDif);
                    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_SPECULAR, glassSpe);
                    Gl.glMateriali(Gl.GL_FRONT, Gl.GL_SHININESS, 32);
                    Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
                }
                else
                {
                    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_AMBIENT, metalAmb);
                    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_DIFFUSE, metalDif);
                    Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_SPECULAR, metalSpe);
                    Gl.glMateriali(Gl.GL_FRONT, Gl.GL_SHININESS, 32);
                }

                for (int i = 0; i < Model.ObjectList[ObjectNum].FaceList.Count; i++)
                {
                    Face fc = Model.ObjectList[ObjectNum].FaceList[i];
                    Vertex v0 = Model.VertexList[fc.VertexIndex[0]];
                    Vertex v1 = Model.VertexList[fc.VertexIndex[1]];
                    Vertex v2 = Model.VertexList[fc.VertexIndex[2]];

                    Normal n0 = Model.NormalList[fc.NormalIndex[0]];
                    Normal n1 = Model.NormalList[fc.NormalIndex[1]];
                    Normal n2 = Model.NormalList[fc.NormalIndex[2]];

                    Gl.glBegin(Gl.GL_TRIANGLES);
                        Gl.glNormal3f(n0.Nx, n0.Ny, n0.Nz);
                        Gl.glVertex3f(v0.X, v0.Y, v0.Z);

                        Gl.glNormal3f(n1.Nx, n1.Ny, n1.Nz);
                        Gl.glVertex3f(v1.X, v1.Y, v1.Z);

                        Gl.glNormal3f(n2.Nx, n2.Ny, n2.Nz);
                        Gl.glVertex3f(v2.X, v2.Y, v2.Z);
                    Gl.glEnd();
                }
                ObjectNum++;
            }
            Gl.glPopMatrix();
        }

        private void MyPaint(object sender, PaintEventArgs e)
        {
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);    // clear screen

            Gl.glPushMatrix();
                Gl.glTranslatef(0, -2, 0);
                Gl.glRotatef(90, 1, 0, 0);
                Gl.glRotatef(40, 0, 1, 0);

                TheScene();
            Gl.glPopMatrix();
        }

        private void OpenGlControl_Load(object sender, EventArgs e)
        {

        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }
}
