GraysonPeddie's picture

Polygons Not Drawn According to Index and Vertex Data

Hi, everyone. My name is Grayson Peddie and I am brand new to the forum and I am transitioning away from Managed DirectX 1.1 to 2.0 to XNA and then to OpenTK, since I'd like to try out developing for OpenGL with OpenTK.

So, since this is my first post, I am having a problem with my code. Note that I am used to creating vertex and index buffer for a simple cube and with OpenTK/OpenGL, it's taking me a while to figure out what's going on but then I couldn't figure out my problem.

First, I'm going to preset you with my code with the following images.:

ushort[] indicesVboData = new ushort[]{
    0, 1, 2, 2, 3, 0,   // Front
    3, 2, 5, 5, 4, 3,   // Top
    1, 6, 5, 5, 2, 1,   // Right
    7, 6, 5, 5, 4, 7,   // Back
    7, 6, 1, 1, 0, 7,   // Bottom
    7, 0, 3, 3, 4, 7};  // Left

ushort[] indicesVboData = new ushort[]{
    0, 1, 2, 2, 3, 0,   // Front
    3, 2, 5, 5, 4, 3,   // Top
    1, 6, 5, 5, 2, 1,   // Right
    7, 6, 5, 5, 4, 7,   // Back
    7, 6, 1, 1, 0, 7/*,   // Bottom
    7, 0, 3, 3, 4, 7*/};  // Left

ushort[] indicesVboData = new ushort[]{
    0, 1, 2, 2, 3, 0,   // Front
    3, 2, 5, 5, 4, 3/*,   // Top
    1, 6, 5, 5, 2, 1,   // Right
    7, 6, 5, 5, 4, 7,   // Back
    7, 6, 1, 1, 0, 7,   // Bottom
    7, 0, 3, 3, 4, 7*/};  // Left
ushort[] indicesVboData = new ushort[]{
    0, 1, 2, 2, 3, 0/*,   // Front
    3, 2, 5, 5, 4, 3,   // Top
    1, 6, 5, 5, 2, 1,   // Right
    7, 6, 5, 5, 4, 7,   // Back
    7, 6, 1, 1, 0, 7,   // Bottom
    7, 0, 3, 3, 4, 7*/};  // Left

So, my question is, can anyone please tell me what's going on with my code as seen below?

using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
 
namespace HelloOpenGL
{
    class MainGame : GameWindow
    {
        string vertexShaderSource, fragmentShaderSource;
 
        int vertexShaderHandle,
            fragmentShaderHandle,
            shaderProgramHandle,
            worldMatrixLocation,
            viewMatrixLocation,
            projectionMatrixLocation;
 
        int vboHandle,
            indicesVboHandle;
 
        Vector3[] cubePositionData = new Vector3[]{
            new Vector3(-0.5f, -0.5f,  0.5f),
            new Vector3( 0.5f, -0.5f,  0.5f),
            new Vector3( 0.5f,  0.5f,  0.5f),
            new Vector3(-0.5f,  0.5f,  0.5f),
            new Vector3(-0.5f,  0.5f, -0.5f),
            new Vector3( 0.5f,  0.5f, -0.5f),
            new Vector3( 0.5f, -0.5f, -0.5f),
            new Vector3(-0.5f, -0.5f, -0.5f)};
 
        Vector3[] cubeNormalData = new Vector3[]{
            new Vector3( 0.0f,  0.0f,  1.0f),
            new Vector3( 0.0f,  1.0f,  0.0f),
            new Vector3( 1.0f,  0.0f,  0.0f),
            new Vector3( 0.0f,  0.0f, -1.0f),
            new Vector3( 0.0f, -1.0f,  0.0f),
            new Vector3(-1.0f,  0.0f,  0.0f)};
 
        VertexPositionNormal[] verts;
 
        Matrix4 matProjection, matView, matWorld;
 
        ushort[] indicesVboData = new ushort[]{
            0, 1, 2, 2, 3, 0,   // Front
            3, 2, 5, 5, 4, 3,   // Top
            1, 6, 5, 5, 2, 1,   // Right
            7, 6, 5, 5, 4, 7,   // Back
            7, 6, 1, 1, 0, 7/*,   // Bottom
            7, 0, 3, 3, 4, 7*/};  // Left
 
        public MainGame()
            : base(1280, 720, new GraphicsMode(new ColorFormat(32)),
            "Hello OpenGL!", 0, DisplayDevice.Default,
            3, 1, GraphicsContextFlags.Debug)
        {
        }
 
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
 
            verts = new VertexPositionNormal[]{
                new VertexPositionNormal(cubePositionData[0], cubeNormalData[0]),
                new VertexPositionNormal(cubePositionData[1], cubeNormalData[0]),
                new VertexPositionNormal(cubePositionData[2], cubeNormalData[0]),
                new VertexPositionNormal(cubePositionData[3], cubeNormalData[0]),
                new VertexPositionNormal(cubePositionData[3], cubeNormalData[1]),
                new VertexPositionNormal(cubePositionData[2], cubeNormalData[1]),
                new VertexPositionNormal(cubePositionData[5], cubeNormalData[1]),
                new VertexPositionNormal(cubePositionData[4], cubeNormalData[1]),
                new VertexPositionNormal(cubePositionData[1], cubeNormalData[2]),
                new VertexPositionNormal(cubePositionData[6], cubeNormalData[2]),
                new VertexPositionNormal(cubePositionData[5], cubeNormalData[2]),
                new VertexPositionNormal(cubePositionData[2], cubeNormalData[2]),
                new VertexPositionNormal(cubePositionData[6], cubeNormalData[3]),
                new VertexPositionNormal(cubePositionData[7], cubeNormalData[3]),
                new VertexPositionNormal(cubePositionData[4], cubeNormalData[3]),
                new VertexPositionNormal(cubePositionData[5], cubeNormalData[3]),
                new VertexPositionNormal(cubePositionData[7], cubeNormalData[4]),
                new VertexPositionNormal(cubePositionData[6], cubeNormalData[4]),
                new VertexPositionNormal(cubePositionData[1], cubeNormalData[4]),
                new VertexPositionNormal(cubePositionData[0], cubeNormalData[4]),
                new VertexPositionNormal(cubePositionData[7], cubeNormalData[5]),
                new VertexPositionNormal(cubePositionData[0], cubeNormalData[5]),
                new VertexPositionNormal(cubePositionData[3], cubeNormalData[5]),
                new VertexPositionNormal(cubePositionData[4], cubeNormalData[5])};
 
            vertexShaderSource = ReadFileToString("Shaders\\main.vert");
            fragmentShaderSource = ReadFileToString("Shaders\\main.frag");
 
            CreateShaders();
            CreateProgram();
            GL.UseProgram(shaderProgramHandle);
 
            QueryMatrixLocations();
 
            float aspectRatio = (float)(ClientSize.Width) / (float)(ClientSize.Height);
 
            SetProjectionMatrix(Matrix4.CreatePerspectiveFieldOfView(
                ((float)(Math.PI) / 180.0f) * 45.0f, aspectRatio, 1.0f, 20.0f));
            SetViewMatrix(Matrix4.CreateRotationX(0.5f) * Matrix4.CreateTranslation(0, 0, -8));
 
            GL.GenBuffers(1, out vboHandle);
            GL.BindBuffer(BufferTarget.ArrayBuffer, vboHandle);
            GL.BufferData<VertexPositionNormal>(BufferTarget.ArrayBuffer,
                new IntPtr(verts.Length * VertexPositionNormal.SizeInBytes),
                verts, BufferUsageHint.StaticDraw);
 
            LoadVertexType(0, "vertexPosition");
            LoadVertexType(1, "vertexNormal");
            indicesVboHandle = LoadIndexer();
 
 
            GL.Enable(EnableCap.DepthTest);
            GL.ClearColor(Color4.Black);
            Keyboard.KeyDown += new EventHandler<OpenTK.Input.KeyboardKeyEventArgs>(Keyboard_KeyDown);
            this.WindowBorder = OpenTK.WindowBorder.Fixed;
        }
 
 
 
        private string ReadFileToString(string fileName)
        {
            // This is for loading two files (main.vert and main.frag for vertex and
            // fragment shader. Nothing relevant.
        }
 
        private void CreateShaders()
        {
            vertexShaderHandle = GL.CreateShader(ShaderType.VertexShader);
            GL.ShaderSource(vertexShaderHandle, vertexShaderSource);
            GL.CompileShader(vertexShaderHandle);
 
            Console.WriteLine(GL.GetShaderInfoLog(vertexShaderHandle));
 
            fragmentShaderHandle = GL.CreateShader(ShaderType.FragmentShader);
            GL.ShaderSource(fragmentShaderHandle, fragmentShaderSource);
            GL.CompileShader(fragmentShaderHandle);
 
            Console.WriteLine(GL.GetShaderInfoLog(fragmentShaderHandle));
        }
 
        private void CreateProgram()
        {
            shaderProgramHandle = GL.CreateProgram();
 
            GL.AttachShader(shaderProgramHandle, vertexShaderHandle);
            GL.AttachShader(shaderProgramHandle, fragmentShaderHandle);
 
            GL.LinkProgram(shaderProgramHandle);
 
            Console.WriteLine(GL.GetProgramInfoLog(shaderProgramHandle));
        }
 
        private void QueryMatrixLocations()
        {
            projectionMatrixLocation = GL.GetUniformLocation(shaderProgramHandle, "projection_matrix");
            viewMatrixLocation = GL.GetUniformLocation(shaderProgramHandle, "view_matrix");
            worldMatrixLocation = GL.GetUniformLocation(shaderProgramHandle, "world_matrix");
        }
 
        private void SetWorldMatrix(Matrix4 matrix)
        {
            matWorld = matrix;
            GL.UniformMatrix4(worldMatrixLocation, false, ref matWorld);
        }
 
        private void SetViewMatrix(Matrix4 matrix)
        {
            matView = matrix;
            GL.UniformMatrix4(viewMatrixLocation, false, ref matView);
        }
 
        private void SetProjectionMatrix(Matrix4 matrix)
        {
            matProjection = matrix;
            GL.UniformMatrix4(projectionMatrixLocation, false, ref matProjection);
        }
 
        private void LoadVertexType(int index, string type)
        {
            GL.EnableVertexAttribArray(index);
            GL.BindAttribLocation(shaderProgramHandle, index, type);
            GL.VertexAttribPointer(index, 3, VertexAttribPointerType.Float, false, VertexPositionNormal.SizeInBytes, 0);
        }
 
        private int LoadIndexer()
        {
            int handle;
            GL.GenBuffers( 1, out handle );
            GL.BindBuffer( BufferTarget.ElementArrayBuffer, handle );
            GL.BufferData<ushort>( BufferTarget.ElementArrayBuffer,
                new IntPtr( indicesVboData.Length * sizeof(ushort) ),
                indicesVboData, BufferUsageHint.StaticDraw );
            return handle;
        }
 
        void Keyboard_KeyDown(object sender, OpenTK.Input.KeyboardKeyEventArgs e)
        {
            switch (e.Key)
            {
                case OpenTK.Input.Key.Escape: Exit(); break;
            }
        }
 
        protected override void OnUpdateFrame(FrameEventArgs e)
        {
 
        }
 
        float rotateY = 0;
 
        protected override void OnRenderFrame(FrameEventArgs e)
        {
            GL.Viewport(0, 0, this.Width, this.Height);
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
            matWorld = Matrix4.CreateTranslation(0, 0, 0);
 
            SetViewMatrix(matView);
            SetWorldMatrix(Matrix4.CreateRotationY((float)e.Time + rotateY) * Matrix4.CreateTranslation(0, 0, 0));
 
            GL.BindBuffer(BufferTarget.ArrayBuffer, vboHandle);
            GL.VertexPointer(3, VertexPointerType.Float, 0, 0);
            GL.NormalPointer(NormalPointerType.Float, 0, 0);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, indicesVboHandle);
 
            GL.EnableClientState(ArrayCap.VertexArray);
            GL.EnableClientState(ArrayCap.NormalArray);
            GL.EnableClientState(ArrayCap.IndexArray);
 
            GL.DrawElements(BeginMode.Triangles, indicesVboData.Length, DrawElementsType.UnsignedShort, 0);
 
            GL.DisableClientState(ArrayCap.VertexArray);
            GL.DisableClientState(ArrayCap.NormalArray);
            GL.DisableClientState(ArrayCap.IndexArray);
 
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
 
            rotateY += (float)Math.PI / 360.0f;
 
            GL.Flush();
            SwapBuffers();
        }
 
    }
}

Here's my struct of VertexPositionNormal.

namespace HelloOpenGL
{
    public struct VertexPositionNormal
    {
        public Vector3 position, normal;
 
        public VertexPositionNormal(float x, float y, float z, float nx, float ny, float nz)
        {
            position = new Vector3(x, y, z); normal = new Vector3(nx, ny, nz);
        }
 
        public VertexPositionNormal(Vector3 position, Vector3 normal)
        {
            this.position = position;
            this.normal = normal;
        }
 
        public static int SizeInBytes
        {
            get
            {
                return sizeof(float) * 6;
            }
        }
    }
}

Here's the visual of how the vertices are numbered:


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

One thing that stands out is that your winding order is incorrect - compare, for instance, your front and back faces. OpenGL (and D3D) use the winding order to distinguish between the front and back face of a polygon, following the right-hand rule.

GraysonPeddie's picture

Well, what about this winding order from this website:
http://www.opentk.com/node/1039

What I have is here:

        Vector3[] cubePositionData = new Vector3[]{
            new Vector3(-0.5f, -0.5f,  0.5f),
            new Vector3( 0.5f, -0.5f,  0.5f),
            new Vector3( 0.5f,  0.5f,  0.5f),
            new Vector3(-0.5f,  0.5f,  0.5f),
            new Vector3(-0.5f, -0.5f, -0.5f),
            new Vector3( 0.5f, -0.5f, -0.5f),
            new Vector3( 0.5f,  0.5f, -0.5f),
            new Vector3(-0.5f,  0.5f, -0.5f)};
 
        Vector3[] cubeNormalData = new Vector3[]{
            new Vector3( 0.0f,  0.0f,  1.0f),
            new Vector3( 0.0f,  1.0f,  0.0f),
            new Vector3( 1.0f,  0.0f,  0.0f),
            new Vector3( 0.0f,  0.0f, -1.0f),
            new Vector3( 0.0f, -1.0f,  0.0f),
            new Vector3(-1.0f,  0.0f,  0.0f)};
 
        VertexPositionNormal[] verts;
 
        Matrix4 matProjection, matView, matWorld;
 
        ushort[] indicesVboData = new ushort[]{
            0, 3, 2, 0, 2, 1,   // Front
            3, 2, 6, 6, 7, 3,   // Top
            7, 6, 5, 5, 4, 7,   // Back
            4, 0, 3, 3, 7, 4,   // Right
            0, 1, 5, 5, 4, 0,   // Bottom
            1, 5, 6, 6, 2, 1};  // Left
 
// ...
 
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
 
            verts = new VertexPositionNormal[]{
                new VertexPositionNormal(cubePositionData[0], cubeNormalData[0]),
                new VertexPositionNormal(cubePositionData[1], cubeNormalData[0]),
                new VertexPositionNormal(cubePositionData[2], cubeNormalData[0]),
                new VertexPositionNormal(cubePositionData[3], cubeNormalData[0]),
                new VertexPositionNormal(cubePositionData[3], cubeNormalData[1]),
                new VertexPositionNormal(cubePositionData[2], cubeNormalData[1]),
                new VertexPositionNormal(cubePositionData[6], cubeNormalData[1]),
                new VertexPositionNormal(cubePositionData[7], cubeNormalData[1]),
                new VertexPositionNormal(cubePositionData[7], cubeNormalData[3]),
                new VertexPositionNormal(cubePositionData[6], cubeNormalData[3]),
                new VertexPositionNormal(cubePositionData[5], cubeNormalData[3]),
                new VertexPositionNormal(cubePositionData[4], cubeNormalData[3]),
                new VertexPositionNormal(cubePositionData[4], cubeNormalData[5]),
                new VertexPositionNormal(cubePositionData[0], cubeNormalData[5]),
                new VertexPositionNormal(cubePositionData[3], cubeNormalData[5]),
                new VertexPositionNormal(cubePositionData[7], cubeNormalData[5]),
                new VertexPositionNormal(cubePositionData[0], cubeNormalData[4]),
                new VertexPositionNormal(cubePositionData[1], cubeNormalData[4]),
                new VertexPositionNormal(cubePositionData[5], cubeNormalData[4]),
                new VertexPositionNormal(cubePositionData[4], cubeNormalData[4]),
                new VertexPositionNormal(cubePositionData[1], cubeNormalData[2]),
                new VertexPositionNormal(cubePositionData[5], cubeNormalData[2]),
                new VertexPositionNormal(cubePositionData[6], cubeNormalData[2]),
                new VertexPositionNormal(cubePositionData[2], cubeNormalData[2])};
 
// ...

I'm only seeing 5 out of 12 polygons

c2woody's picture
Quote:

I'm only seeing 5 out of 12 polygons

Why did you change the front face indices? If you want to reproduce the working example, stick to the exact data.

GraysonPeddie's picture

Well, I was going to modify it and that code above works the same as the example.

c2woody's picture

Can't follow you. Check the examples in the OpenTK example browser, the OpenGL 3.x example uses indexed drawing based on what you referenced. See if that works out of the box.

flopoloco's picture

What they said

Vector3[] positionVboData = new Vector3[]{
            new Vector3(-1.0f, -1.0f,  1.0f),
            new Vector3( 1.0f, -1.0f,  1.0f),
            new Vector3( 1.0f,  1.0f,  1.0f),
            new Vector3(-1.0f,  1.0f,  1.0f),
            new Vector3(-1.0f, -1.0f, -1.0f),
            new Vector3( 1.0f, -1.0f, -1.0f), 
            new Vector3( 1.0f,  1.0f, -1.0f),
            new Vector3(-1.0f,  1.0f, -1.0f) };
 
        int[] indicesVboData = new int[]{
             // front face
                0, 1, 2, 2, 3, 0,
                // top face
                3, 2, 6, 6, 7, 3,
                // back face
                7, 6, 5, 5, 4, 7,
                // left face
                4, 0, 3, 3, 7, 4,
                // bottom face
                0, 1, 5, 5, 4, 0,
                // right face
                1, 5, 6, 6, 2, 1, };
GraysonPeddie's picture

Hi, guys. I finally got my cube rendered properly. It seems you'll need to have 24 vertices instead of 8 if you're going to have 4 vertices per side of the cube, since this will allow you to have individual control of texture coordinates and normals.

ushort[] indicesVboData = new ushort[]{
    0, 3, 2, 0, 2, 1,   // Front
    4, 5, 6, 6, 7, 4,   // Top
    8, 9, 10, 10, 11, 8,   // Back
    12, 13, 14, 14, 15, 12,   // Right
    16, 17, 18, 18, 19, 16,   // Bottom
    20, 21, 22, 22, 23, 20};  // Left

I apologize if anyone is not following me here.