Click here to Skip to main content
Click here to Skip to main content
Articles » Multimedia » OpenGL » General » Downloads
 
Add your own
alternative version

Shading Subdivide Sphere

, 23 Mar 2008 CPOL
Flat and Smooth Shading
gl_shading_subdivide.zip
GL_shading_subdivide
GL_shading_subdivide
bin
Debug
csgl.dll
GL_shading_subdivide.exe
GL_shading_subdivide.vshost.exe
Properties
Settings.settings
GL_shading_subdivide.suo
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CsGL.OpenGL;
using CsGL.Util;
namespace GL_shading_subdivide
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Text += " - Press S F Left Right";
            float X = 0.525731112119133696f;
            float Z = 0.850650808352039932f;


            /* vertex data array */
            vdata = new float[12][] {
  new float[3]{-X, 0.0f, Z},  new float[3]{X, 0.0f, Z}, new float[3] {-X, 0.0f, -Z}, new float[3] {X, 0.0f, -Z},
  new float[3]{0.0f, Z, X}, new float[3] {0.0f, Z, -X}, new float[3] {0.0f, -Z, X}, new float[3] {0.0f, -Z, -X},
  new float[3] {Z, X, 0.0f}, new float[3] {-Z, X, 0.0f}, new float[3] {Z, -X, 0.0f}, new float[3] {-Z, -X, 0.0f}};


            /* triangle indices */
            tindices = new int[20][]{
  new int[3] {1,4,0}, new int[3] {4,9,0}, new int[3] {4,5,9}, new int[3] {8,5,4}, new int[3] {1,8,4},
  new int[3] {1,10,8}, new int[3] {10,3,8}, new int[3] {8,3,5}, new int[3] {3,2,5}, new int[3] {3,7,2},
  new int[3] {3,10,7}, new int[3] {10,6,7}, new int[3]  {6,11,7},  new int[3]{6,0,11}, new int[3] {6,1,0},
  new int[3] {10,1,6}, new int[3] {11,0,9}, new int[3] {2,11,9}, new int[3] {5,2,9}, new int[3] {11,2,7}};

            ClientSize = new Size(640, 480);
            init();
            reshape(640, 480);
        }


        /* vertex data array */
        float[][] vdata = new float[12][];

        /* triangle indices */
        int[][] tindices = new int[20][];


        float[] mat_specular = { 0.5f, 0.5f, 0.5f, 1.0f };
        float[] mat_diffuse = { 0.8f, 0.6f, 0.4f, 1.0f };
        float[] mat_ambient = { 0.8f, 0.6f, 0.4f, 1.0f };
        float mat_shininess = 20.0f;	// unused if specular is 0 

        float[] light_ambient = { 0.2f, 0.2f, 0.2f, 1.0f };
        float[] light_diffuse = { 1.0f, 1.0f, 1.0f, 1.0f };
        float[] light_specular = { 0.4f, 0.4f, 0.4f, 1.0f };

        //   float[] light_position = { 100f, 50f, -1.0f, 0.0f }; // directional

        int flat = 1;			/* 0 = smooth shading, 1 = flat shading */
        int subdiv = 0;			/* number of subdivisions */

        private void openGLControl1_Paint(object sender, PaintEventArgs e)
        {
            Draw();
        }

        void Draw()
        {

            GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
            GL.glLoadIdentity();
            GL.glTranslatef(0f, 0.0f, 0);
             //  GL.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, light_position);

            /* drawIco(); */
            /* drawSphere(); */
            GL.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, light_ambient);
            GL.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, light_diffuse);
            GL.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, light_specular);

            GL.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, mat_specular);
            GL.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT, mat_ambient);
            GL.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, mat_diffuse);
            GL.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, mat_shininess);


            GL.glEnable(GL.GL_LIGHTING);	/* enable lighting */
            GL.glEnable(GL.GL_LIGHT0);		/* enable light 0 */

            for (int i = 0; i < 20; i++)
            {

                subdivide(ref vdata[tindices[i][0]],
                          ref vdata[tindices[i][1]],
                          ref vdata[tindices[i][2]],
                             subdiv);

            }


            GL.glDisable(GL.GL_LIGHTING);	/* glDisable lighting */
            GL.glDisable(GL.GL_LIGHT0);		/* glDisable light 0 */

            GL.glFlush();

        }

        private void timer_Tick(object sender, EventArgs e)
        {
            openGLControl1.Invalidate();
        }

        void init()
        {
            GL.glShadeModel(GL.GL_SMOOTH);	/* enable smooth shading */

            GL.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
            GL.glClearDepth(1.0f);									        // Depth Buffer Setup

            GL.glEnable(GL.GL_DEPTH_TEST);							        // Enables Depth Testing
            GL.glDepthFunc(GL.GL_LEQUAL);								    // The Type Of Depth Testing To Do

        }
        void reshape(int w, int h)
        {
            float aspect = (float)w / (float)h;
            GL.glViewport(0, 0, w, h);

            GL.glMatrixMode(GL.GL_PROJECTION);
            GL.glLoadIdentity();
            if (w <= h)
                GL.glOrtho(-1.25, 1.25, -1.25 * aspect, 1.25 * aspect, -2.0, 2.0);
            else
                GL.glOrtho(-1.25 * aspect, 1.25 * aspect, -1.25, 1.25, -2.0, 2.0);
            GL.glMatrixMode(GL.GL_MODELVIEW);

            GL.gluLookAt(0.5, 0.5, -1.5, /* eye */
                    0.0, 0.0, 0.0,  /* at */
                0.0, 1.0, 0.0); /* up */

            GL.glMatrixMode(GL.GL_MODELVIEW);
            GL.glLoadIdentity();


        }

        /* normalize a vector of non-zero length */
        void normalize(float[] v)
        {
            float d = (float)Math.Sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
            /* omit explict check for division by zero */

            v[0] /= d; v[1] /= d; v[2] /= d;
        }

        /* normalized cross product of non-parallel vectors */
        void normCrossProd(float[] u, float[] v, float[] n)
        {
            n[0] = u[1] * v[2] - u[2] * v[1];
            n[1] = u[2] * v[0] - u[0] * v[2];
            n[2] = u[0] * v[1] - u[1] * v[0];
            normalize(n);
        }

        void normFace(float[] v1, float[] v2, float[] v3)
        {
            float[] d1 = new float[3], d2 = new float[3], n = new float[3];
            int k;
            for (k = 0; k < 3; k++)
            {
                d1[k] = v1[k] - v2[k];
                d2[k] = v2[k] - v3[k];
            }
            normCrossProd(d1, d2, n);
            GL.glNormal3fv(n);
        }

        /* draw triangle using face normals */
        void drawTriangleFlat(float[] v1, float[] v2, float[] v3)
        {

            GL.glBegin(GL.GL_TRIANGLES);
            normFace(v1, v2, v3);
            GL.glVertex3fv(v1);
            GL.glVertex3fv(v2);
            GL.glVertex3fv(v3);
            GL.glEnd();

        }

        /* draw triangle using sphere normals */
        void drawTriangleSmooth(float[] v1, float[] v2, float[] v3)
        {
            GL.glBegin(GL.GL_TRIANGLES);
            GL.glNormal3fv(v1);
            GL.glVertex3fv(v1);
            GL.glNormal3fv(v2);
            GL.glVertex3fv(v2);
            GL.glNormal3fv(v3);
            GL.glVertex3fv(v3);
            GL.glEnd();
        }


        /* recursively subdivide face depth times */
        /* and draw the resulting triangles */
        void subdivide(ref float[] v1, ref float[] v2, ref float[] v3, int depth)
        {
            float[] v12 = new float[3], v23 = new float[3], v31 = new float[3];


            if (depth == 0)
            {
                if (flat == 1)
                    drawTriangleFlat(v1, v2, v3);
                else
                    drawTriangleSmooth(v1, v2, v3);

            }


            /* calculate midpoints of each side */
            for (int i = 0; i < 3; i++)
            {
                v12[i] = (v1[i] + v2[i]) / 2.0f;
                v23[i] = (v2[i] + v3[i]) / 2.0f;
                v31[i] = (v3[i] + v1[i]) / 2.0f;
            }
            // extrude midpoints to lie on unit sphere 
            normalize(v12);
            normalize(v23);
            normalize(v31);

            // recursively subdivide new triangles 
            if (depth != 0)
            {
                subdivide(ref v1, ref v12, ref v31, depth - 1);
                subdivide(ref v2, ref v23, ref v12, depth - 1);
                subdivide(ref v3, ref v31, ref v23, depth - 1);
                subdivide(ref v12, ref v23, ref v31, depth - 1);
            }

        }

        protected override bool ProcessDialogKey(Keys keyData)
        {
            if (keyData == Keys.Left)
            {
                subdiv++;
                if (subdiv > 6)
                    subdiv = 6;
            }
            if (keyData == Keys.Right)
            { 
                subdiv--;
                if (subdiv < 0)
                    subdiv = 0;
            }

            if (keyData == Keys.F)
                flat = 1;

            if (keyData == Keys.S)
                flat = 0;

            return base.ProcessDialogKey(keyData);
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

salim_chaf
Web Developer
Algeria Algeria
No Biography provided

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.150123.1 | Last Updated 24 Mar 2008
Article Copyright 2008 by salim_chaf
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid