fireshadow4126's picture

Mesh Class with Vertices, Normals, and TexCoords?

Hi all,

It's been a while since I've been on these forums because I decided to try my hand at native code and raw OpenGL. That didn't work out too well, so here I am with OpenTK again. I have this mesh class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
 
using SurviveEngine.Graphics;
using SurviveEngine.ResourceMgmt.MeshFormats;
 
namespace SurviveEngine.ResourceMgmt
{
    public class SurviveMesh : ISurviveResource
    {
        public String FileName
        {
            get;
            set;
        }
        private SurviveVertexPNT[] vertices;
        private ushort[] elements;
        private VBO handle;
        public struct VBO
        {
            public int VBO_ID, IBO_ID, NumElements;
        }
 
        public void Read()
        {
            if (FileName == String.Empty)
            {
                throw new SurviveResourceException("Cannot load resource because no filename was specified.");
            }
            if (FileName.StartsWith("cube"))
            {
                this.vertices = SurvivePrimitives.GetCubeVertices(1.0f).ToArray();
                this.elements = SurvivePrimitives.GetCubeIndices().ToArray();
            }
        }
 
        public void Write()
        {
            throw new NotImplementedException();
        }
 
        public void Draw()
        {
            GL.EnableClientState(ArrayCap.VertexArray);
            GL.EnableClientState(ArrayCap.NormalArray);
            GL.EnableClientState(ArrayCap.TextureCoordArray);
            GL.BindBuffer(BufferTarget.ArrayBuffer, handle.VBO_ID);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, handle.IBO_ID);
            int offset = 0;
            GL.VertexPointer(3, VertexPointerType.Float, BlittableValueType.StrideOf(vertices), new IntPtr(offset));
            offset += 12;
            GL.NormalPointer(NormalPointerType.Float, BlittableValueType.StrideOf(vertices), new IntPtr(offset));
            offset += 12;
            GL.TexCoordPointer(2, TexCoordPointerType.Float, BlittableValueType.StrideOf(vertices), new IntPtr(offset));
 
            GL.DrawElements(BeginMode.Triangles, handle.NumElements, DrawElementsType.UnsignedShort, IntPtr.Zero);
        }
 
        private void LoadVBO(SurviveVertexPNT[] vertices, ushort[] elements)
        {
            handle = new VBO();
            int size;
            this.vertices = vertices;
            this.elements = elements;
 
            GL.GenBuffers(1, out handle.VBO_ID);
            GL.BindBuffer(BufferTarget.ArrayBuffer, handle.VBO_ID);
            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * BlittableValueType.StrideOf(vertices)),
                vertices, BufferUsageHint.StaticDraw);
            GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out size);
            if (vertices.Length * BlittableValueType.StrideOf(vertices) != size)
            {
                throw new ApplicationException("Vertex data not uploaded correctly.");
            }
            GL.GenBuffers(1, out handle.IBO_ID);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, handle.IBO_ID);
            GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(elements.Length * sizeof(short)),
                elements, BufferUsageHint.StaticDraw);
            GL.GetBufferParameter(BufferTarget.ElementArrayBuffer, BufferParameterName.BufferSize, out size);
            if (elements.Length * sizeof(short) != size)
            {
                throw new ApplicationException("Element data not uploaded correctly.");
            }
 
            handle.NumElements = elements.Length;
        }
    }
}

SurvivePrimitives.GetCubeVertices() is this:

public static IList<SurviveVertexPNT> GetCubeVertices(float radius)
        {
            List<SurviveVertexPNT> verts = new List<SurviveVertexPNT>();
            verts.Add(new SurviveVertexPNT(
                new Vector3(-radius, radius, -radius),
                new Vector3(),
                new Vector2()));
            verts.Add(new SurviveVertexPNT(
                new Vector3(radius, radius, -radius),
                new Vector3(),
                new Vector2()));
            verts.Add(new SurviveVertexPNT(
                new Vector3(radius, -radius, -radius),
                new Vector3(),
                new Vector2()));
            verts.Add(new SurviveVertexPNT(
                new Vector3(-radius, -radius, -radius),
                new Vector3(),
                new Vector2()));
            verts.Add(new SurviveVertexPNT(
                new Vector3(-radius, -radius, radius),
                new Vector3(),
                new Vector2()));
            verts.Add(new SurviveVertexPNT(
                new Vector3(radius, -radius, radius),
                new Vector3(),
                new Vector2()));
            verts.Add(new SurviveVertexPNT(
                new Vector3(radius, radius, radius),
                new Vector3(),
                new Vector2()));
            verts.Add(new SurviveVertexPNT(
                new Vector3(-radius, radius, radius),
                new Vector3(),
                new Vector2()));
            return verts;
        }

My question is that I can't figure out how I would put in normals and such because I don't know how to specify a normal per index. What should I do?

P.S. My graphics card supports GL3, no later.