Search code examples
c#openglopentk

Create an Octahedron (Flip Pyramid Upside Down) OpenTK


I am using OpenTK to make an octahedron. I have a square pyramid created and need to translate another beneath the top one and flip it upside down to create the octahedron.

How do I flip the second pyramid upside down?

Here is my code so far:

#region --- Using Directives ---

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Threading;
using System.Drawing;

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Platform;

#endregion

namespace Octahedron
{

    public class Octahedron : GameWindow
    {
        #region --- Fields ---

        const float rotation_speed = 180.0f;
        float angle;

        #endregion

        #region --- Constructor ---

        public Octahedron()
            : base(800, 600)
        { }

        #endregion

        #region OnLoad

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            GL.ClearColor(Color.MidnightBlue);
            GL.Enable(EnableCap.DepthTest);
        }

        #endregion

        #region OnResize

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);

            GL.Viewport(0, 0, Width, Height);

            double aspect_ratio = Width / (double)Height;

            OpenTK.Matrix4 perspective = OpenTK.Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, (float)aspect_ratio, 1, 64);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadMatrix(ref perspective);
        }

        #endregion

        #region OnUpdateFrame

        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            base.OnUpdateFrame(e);

            var keyboard = OpenTK.Input.Keyboard.GetState();
            if (keyboard[OpenTK.Input.Key.Escape])
            {
                this.Exit();
                return;
            }
        }

        #endregion

        #region OnRenderFrame

        protected override void OnRenderFrame(FrameEventArgs e)
        {
            base.OnRenderFrame(e);

            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            Matrix4 lookat = Matrix4.LookAt(0, 5, 10, 0, 0, 2, 0, 5, 0);
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadMatrix(ref lookat);

            angle += rotation_speed * (float)e.Time;
            GL.Rotate(angle, 0.0f, 1.0f, 0.0f);
            DrawPyramid();

            GL.Translate(0.0f, -2.0f, 0.0f);
            DrawPyramid();

            this.SwapBuffers();
            Thread.Sleep(1);
        }

        #endregion

        #region private void DrawPyramid()

        private void DrawPyramid()
        {
            GL.Begin(PrimitiveType.Triangles);
       //Side0 (red)
                                                  //x,    y,    z
            GL.Color3(1.0f, 0.0f, 0.0f); GL.Vertex3(0.0f, 1.0f, 0.0f);//Top Vertex

                                                   //x,     y,    z
            GL.Color3(1.0f, 0.0f, 0.0f); GL.Vertex3(-1.0f, -1.0f, 1.0f);//Bottom Left Vertex

                                                  //x,     y,    z
            GL.Color3(1.0f, 0.0f, 0.0f); GL.Vertex3(1.0f, -1.0f, 1.0f);//Bottom Right Vertex

      //Side1 (blue)

                                                  //x,    y,    z
            GL.Color3(0.0f, 0.0f, 1.0f); GL.Vertex3(0.0f, 1.0f, 0.0f);//Top Vertex

                                                  //x,    y,    z
            GL.Color3(0.0f, 0.0f, 1.0f); GL.Vertex3(1.0f, -1.0f, 1.0f);//Bottom Left Vertex

                                                  //x,    y,    z
            GL.Color3(0.0f, 0.0f, 1.0f); GL.Vertex3(1.0f, -1.0f, -1.0f);//Bottom Right Vertex

      // Side2 (yellow)

                                                  //x,    y,    z
            GL.Color3(1.0f, 1.0f, 0.0f); GL.Vertex3(0.0f, 1.0f, 0.0f);

                                                  //x,     y,     z
            GL.Color3(1.0f, 1.0f, 0.0f); GL.Vertex3(1.0f, -1.0f, -1.0f);

                                                   //x,     y,     z
            GL.Color3(1.0f, 1.0f, 0.0f); GL.Vertex3(-1.0f, -1.0f, -1.0f);

      // Side3 (pink)

                                                  //x,    y,    z
            GL.Color3(1.0f, 0.0f, 1.0f); GL.Vertex3(0.0f, 1.0f, 0.0f);

                                                   //x,     y,     z
            GL.Color3(1.0f, 0.0f, 1.0f); GL.Vertex3(-1.0f, -1.0f, -1.0f);

                                                   //x,     y,    z
            GL.Color3(1.0f, 0.0f, 1.0f); GL.Vertex3(-1.0f, -1.0f, 1.0f);

     //Side4 (red)
                                                  //x,    y,    z
            GL.Color3(1.0f, 1.0f, 1.0f); GL.Vertex3(0.0f, 1.0f, 0.0f);//Top Vertex

                                                   //x,     y,    z
            GL.Color3(1.0f, 1.0f, 1.0f); GL.Vertex3(-1.0f, -1.0f, 1.0f);//Bottom Left Vertex

                                                  //x,     y,    z
            GL.Color3(1.0f, 1.0f, 1.0f); GL.Vertex3(1.0f, -1.0f, 1.0f);//Bottom Right Vertex

            GL.End();
        }

        #endregion


        #region public static void Main()

        [STAThread]
        public static void Main()
        {
            using (Octahedron oct = new Octahedron())
            {
                oct.Run(60.0, 0.0);
            }
        }

        #endregion
    }
}

Solution

  • Hint: for simple things which align neatly with a reference plane in x,y,z coordinate space (i.e the planes (x,y), (x,z), (y,z)), flipping something along a certain axis is equivalent to multiplying the particular coordinate by -1. In the more general case you can use a matrix multiplication, using a predefined matrix representing the proper rotation of all coordinates.