Solved

Rubik's Cube creation in OpenGL and C#

Posted on 2007-03-20
8
9,127 Views
Last Modified: 2013-12-17
I am really new to OpenGL and I have a question about some code that I wrote. I am writting a Rubik's Cube program using C# .NET and OpenGL. I can generate the 27 individual cubes and I can use glRotate and glTranslate, but only when I call the resize event. I know that I am definitly doing something worng. Any help, or code about how to move the actual cube(s) not just the camera would be great! Thanks.

HERE'S what i have so far:
CUBE CLASS:
//**********************
// Namespace References
//**********************
using System;
using System.Drawing;
using System.Windows.Forms;
using CsGL.OpenGL;

namespace cube
{
    public class OurView : OpenGLControl
    {
        //**********************************************
        //Global Variable Declaration and Instantiation
        //**********************************************
        float xDeg = 0.0f;
        float yDeg = 0.0f;

        public OurView()
            : base()
        {
            //Creates our own Keyboard event.
            this.KeyDown += new KeyEventHandler(OurView_OnKeyDown);
        }

        public override void glDraw()
        {
            // Clear the buffers before drawing the cube.
            GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
            GL.glLoadIdentity();
            // Translate into the screen.
            GL.glTranslatef(0.0f, 0.0f, -10.0f);
            GL.glRotatef(xDeg, 1.0f, 0.0f, 0.0f);
            GL.glRotatef(yDeg, 0.0f, 1.0f, 0.0f);
            this.glDrawCube();
        }

        protected override void InitGLContext()
        {
            GL.glShadeModel(GL.GL_SMOOTH);                                  // Set Smooth Shading  
            //GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);  // Clears the color buffer
            GL.glClearColor(0.4f, 0.4f, 0.4f, 0.0f);                        // BackGround Color        
            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 Test To Do    
            GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);     // Really Nice Perspective Calculations
        }
       
        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            Size s = Size;
            double aspect_ratio = (double)s.Width / (double)s.Height;
            GL.glMatrixMode(GL.GL_PROJECTION);                      // Select The Projection Matrix
            GL.glLoadIdentity();                                    // Reset The Projection Matrix
            GL.gluPerspective(45.0f, aspect_ratio, 0.1f, 100.0f);   // Calculate The Aspect Ratio Of The Window
            GL.glMatrixMode(GL.GL_MODELVIEW);                       // Select The Modelview Matrix
            GL.glLoadIdentity();                                    // Reset The Modelview Matrix
        }
       
        /**************************************************************************
         * glDrawCube
         *  - Description:
         *      - Contains the 3 loops for generating the 27 individual cublets.
         *  - Parameters:(None)
         *  - Local Variables
         *      - xMark = x coordinate; yMark = y coordinate; zMark = z coordinate
         *  -Returns:(void)
         **************************************************************************
         */
        public void glDrawCube()
        {
            float xMark = -1.0f;
            float yMark = -1.0f;
            float zMark = 1.0f;

            for (int i = 0; i < 3; i++)
            //moves back one unit on z-axis
            {
                for (int j = 0; j < 3; j++)
                //moves up one unit on y-axis
                {
                    for (int k = 0; k < 3; k++)
                    //builds 3 cubes along x-axis
                    {
                        buildCubeSolid(xMark, yMark, zMark);
                        buildCubeWire(xMark, yMark, zMark);
                        xMark++;
                    }
                    xMark = -1.0f;
                    yMark++;
                }
                yMark = -1.0f;
                zMark--;
            }
        }

        /************************************************************
         * buildCubeSolid
         *  - Description:
         *      - Draws the cublet using the OpenGL method GL_QUADS.
         *  - Parameters:
         *      - x: x coordinate to start drawing from.
         *      - y: y coordinate to start drawing from.
         *      - z: z coordinate to start drawing from.
         *  - Local Varibles:(none)
         *  - Returns(void)
         *************************************************************
         */
        public void buildCubeSolid(float x, float y, float z)
        {
            //draws a cube based on the center given
            GL.glBegin(GL.GL_QUADS);
            //TOP - GREEN
            GL.glColor3f(0.0f, 1.0f, 0.0f);
            GL.glVertex3f((x + .5f), (y + .5f), (z - .5f));
            GL.glVertex3f((x - .5f), (y + .5f), (z - .5f));
            GL.glVertex3f((x - .5f), (y + .5f), (z + .5f));
            GL.glVertex3f((x + .5f), (y + .5f), (z + .5f));
            //BOTTOM - ORANGE
            GL.glColor3f(1.0f, 0.5f, 0.0f);
            GL.glVertex3f((x + .5f), (y - .5f), (z - .5f));
            GL.glVertex3f((x - .5f), (y - .5f), (z - .5f));
            GL.glVertex3f((x - .5f), (y - .5f), (z + .5f));
            GL.glVertex3f((x + .5f), (y - .5f), (z + .5f));
            //FRONT - RED
            GL.glColor3f(1.0f, 0.0f, 0.0f);
            GL.glVertex3f((x + .5f), (y + .5f), (z + .5f));
            GL.glVertex3f((x - .5f), (y + .5f), (z + .5f));
            GL.glVertex3f((x - .5f), (y - .5f), (z + .5f));
            GL.glVertex3f((x + .5f), (y - .5f), (z + .5f));
            //BACK - YELLOW
            GL.glColor3f(1.0f, 1.0f, 0.0f);
            GL.glVertex3f((x + .5f), (y + .5f), (z - .5f));
            GL.glVertex3f((x - .5f), (y + .5f), (z - .5f));
            GL.glVertex3f((x - .5f), (y - .5f), (z - .5f));
            GL.glVertex3f((x + .5f), (y - .5f), (z - .5f));
            //LEFT - BLUE
            GL.glColor3f(0.0f, 0.0f, 1.0f);
            GL.glVertex3f((x - .5f), (y + .5f), (z + .5f));
            GL.glVertex3f((x - .5f), (y + .5f), (z - .5f));
            GL.glVertex3f((x - .5f), (y - .5f), (z - .5f));
            GL.glVertex3f((x - .5f), (y - .5f), (z + .5f));
            //RIGHT - VIOLET
            GL.glColor3f(1.0f, 0.0f, 1.0f);
            GL.glVertex3f((x + .5f), (y + .5f), (z + .5f));
            GL.glVertex3f((x + .5f), (y + .5f), (z - .5f));
            GL.glVertex3f((x + .5f), (y - .5f), (z - .5f));
            GL.glVertex3f((x + .5f), (y - .5f), (z + .5f));
            GL.glEnd();
        }

        /*******************************************************************************
         * buildCubeWire
         *  - Description:
         *      - Draws the outline of the cublet using the OpenGL method GL_LINE_LOOP.
         *  - Parameters:
         *      - x: x coordinate to start drawing from.
         *      - y: y coordinate to start drawing from.
         *      - z: z coordinate to start drawing from.
         *  - Local Varibles:(none)
         *  - Returns(void)
         *******************************************************************************
         */
        public void buildCubeWire(float x, float y, float z)
        {
            //draw black lines on all edges of the minicubes
            //TOP
            GL.glBegin(GL.GL_LINE_LOOP);
            GL.glColor3f(0.0f, 0.0f, 0.0f);
            GL.glVertex3f((x + .5f), (y + .5f), (z - .5f));
            GL.glVertex3f((x - .5f), (y + .5f), (z - .5f));
            GL.glVertex3f((x - .5f), (y + .5f), (z + .5f));
            GL.glVertex3f((x + .5f), (y + .5f), (z + .5f));
            GL.glEnd();
            //BOTTOM
            GL.glBegin(GL.GL_LINE_LOOP);
            GL.glColor3f(0.0f, 0.0f, 0.0f);
            GL.glVertex3f((x + .5f), (y - .5f), (z - .5f));
            GL.glVertex3f((x - .5f), (y - .5f), (z - .5f));
            GL.glVertex3f((x - .5f), (y - .5f), (z + .5f));
            GL.glVertex3f((x + .5f), (y - .5f), (z + .5f));
            GL.glEnd();
            //FRONT
            GL.glBegin(GL.GL_LINE_LOOP);
            GL.glColor3f(0.0f, 0.0f, 0.0f);
            GL.glVertex3f((x + .5f), (y + .5f), (z + .5f));
            GL.glVertex3f((x - .5f), (y + .5f), (z + .5f));
            GL.glVertex3f((x - .5f), (y - .5f), (z + .5f));
            GL.glVertex3f((x + .5f), (y - .5f), (z + .5f));
            GL.glEnd();
            //BACK
            GL.glBegin(GL.GL_LINE_LOOP);
            GL.glColor3f(0.0f, 0.0f, 0.0f);
            GL.glVertex3f((x + .5f), (y + .5f), (z - .5f));
            GL.glVertex3f((x - .5f), (y + .5f), (z - .5f));
            GL.glVertex3f((x - .5f), (y - .5f), (z - .5f));
            GL.glVertex3f((x + .5f), (y - .5f), (z - .5f));
            GL.glEnd();
            //LEFT
            GL.glBegin(GL.GL_LINE_LOOP);
            GL.glColor3f(0.0f, 0.0f, 0.0f);
            GL.glVertex3f((x - .5f), (y + .5f), (z + .5f));
            GL.glVertex3f((x - .5f), (y + .5f), (z - .5f));
            GL.glVertex3f((x - .5f), (y - .5f), (z - .5f));
            GL.glVertex3f((x - .5f), (y - .5f), (z + .5f));
            GL.glEnd();
            //RIGHT
            GL.glBegin(GL.GL_LINE_LOOP);
            GL.glColor3f(0.0f, 0.0f, 0.0f);
            GL.glVertex3f((x + .5f), (y + .5f), (z + .5f));
            GL.glVertex3f((x + .5f), (y + .5f), (z - .5f));
            GL.glVertex3f((x + .5f), (y - .5f), (z - .5f));
            GL.glVertex3f((x + .5f), (y - .5f), (z + .5f));
            GL.glEnd();
        }

        /*****************************************************************************
         * OurView_OnKeyDown
         *  - Description:
         *      - Contains a switch statement to do something based upon which key
         *          the user presses.
         *  - Parameters:
         *      - Sender: refernce to the window object
         *      - kea: class that contains refernces to all the keys on the keyboard
         *  - Local Varibles:(none)
         *  - Returns(void)
         *****************************************************************************
         */
        protected void OurView_OnKeyDown(object Sender, KeyEventArgs kea)
        {
            switch (kea.KeyCode)
            {
                case Keys.NumPad8:
                    xDeg += 10.0f;  
                    this.Height += 1;
                    break;
                case Keys.NumPad2:
                    xDeg -= 10.0f;
                    this.Height -= 1;
                    break;
                case Keys.NumPad4:
                    yDeg -= 10.0f;
                    this.Width -= 1;
                    break;
                case Keys.NumPad6:
                    yDeg += 10.0f;
                    this.Width += 1;
                    break;
                case Keys.Escape:
                    Application.Exit();
                    break;
            }
        }
}

MAIN:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Threading;
using CsGL.OpenGL;
using System.Windows.Forms;

namespace cube
{
    public partial class frmMain : Form
    {
         //Declarations
        private cube.OurView view;
        private about ab;
        private static Thread thrOpenGL;
 
        public frmMain()
        {
            InitializeComponent();
            this.view = new cube.OurView();
            this.view.Parent = this;
            this.view.Dock = DockStyle.Fill ; // Will fill top of the form
            thrOpenGL = new Thread(new ThreadStart(OpenGL_Start));
            thrOpenGL.Start();
       
        }
        private void OpenGL_Start()
        {
           // for (; ; ) // infinity loop for rendering
           // {
                this.view.glDraw();
           // }
        }

        private void m_exit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void m_about_Click(object sender, EventArgs e)
        {
            ab = new about();
            ab.Show();
        }
    }
}
0
Comment
Question by:the_mickster
  • 5
  • 3
8 Comments
 
LVL 5

Assisted Solution

by:thegilb
thegilb earned 500 total points
ID: 18757932
Looks like your code is going quite well so far! You might find the following links quite useful also as about 4/5 of the way down there's a tutorial you may find useful.:
http://darcs.haskell.org/packages/GLUT/doc/tutorial.xml

This page presents a really nice and fast (And simple) algorithm for solving a rubiks cube.
http://lar5.com/cube/
0
 
LVL 1

Author Comment

by:the_mickster
ID: 18764969
I took a look at the first website that you suggested, and the code in the website isn't even C#. The second website doesn't do much becuase i don't need to know how to solve it because I have Prolog code to do that. My real question has to deal with whether or not OpenGL has a way of storing the points that I generate and second a way to move the cube that I create, not just moving the camera around the object.
0
 
LVL 1

Author Comment

by:the_mickster
ID: 18765002
I will only award point for suggestions in C# on how to successfully move my cube. I'm sorry, but that's what i really need. Thanks.
0
 
LVL 5

Accepted Solution

by:
thegilb earned 500 total points
ID: 18765178
You can use display lists to 'save' your geometry to a temporary buffer. This cuts down on the number of function calls and thus makes your code run faster. You may find a link with accompanying C# source code here:
http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=12

You also need to know about rotation, another link (C# code link at the end of the tutorial again):
http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=04

The general idea is that you position the camera so it is looking at the origin, then construct your cubes so that they are centered around the origin. Then you can rotate all of the cubes around the origin and you will get the results you wanted.
0
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 
LVL 1

Author Comment

by:the_mickster
ID: 18765727
These two tutorials look like they may help me out a bunch. I will take a look at them in the next few hours and get back to you. Thanks.
0
 
LVL 1

Author Comment

by:the_mickster
ID: 18769028
Those two tutorials helped somewhat. Is there anyone who is experienced with structures and arrays within structs that could help me out with some code or tutorials??
0
 
LVL 5

Expert Comment

by:thegilb
ID: 18769920
Just explain in more detail what you want to know and I will tell you.
0
 
LVL 1

Author Comment

by:the_mickster
ID: 18793830
Okay. Here's what I'm going after right now.
1.) I am starting to make a struct for each of the 27 cublets. The struct will have a unique ID, an array that stores that face colors for the cube. and an array for all the points of the cube.

2.) I'm having trouble wrapping my mind around the array that needs to store all the points and then manipulating the points.

3.) I plan on using the face color array and the points array to move the slices of the cube just like you are playing the game.

Thanks for all of your help by the way!
0

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Cisco MRA Phones 4 63
Linq Help 1 34
Not showing page correctly 3 29
Where can I ask about my ASP.NET MVC project? 6 12
Welcome my friends to the second instalment and follow-up to our Minify and Concatenate Your Scripts and Stylesheets (http://www.experts-exchange.com/Programming/Languages/.NET/ASP.NET/A_4334-Minify-and-Concatenate-Your-Scripts-and-Stylesheets.html)…
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

932 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now