aboutsummaryrefslogtreecommitdiff
path: root/samples/OpenGL/minimalvbo/minimalvbo.c
blob: 3440c88060c3d798171c80cc5f6877acaf0e1e58 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <GL/glew.h>
#include <GL/glut.h>

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <math.h>

void init();
void display();

/* With the introduction of Buffer Objects, a somewhat questionable decision
 * regarding the reuse of existing API was made. Specifically the reuse of the
 * gl...Pointer functions to supply integers through their `data` parameter
 * which is a pointer can lead to serious complications, should a compiler
 * decide to implement augmented or tagged pointers.
 *
 * In many OpenGL tutorials, and even the reference documentation one can
 * find that an iteger gets cast into a pointer. From the point of view of
 * the C language standard and the interpretation of integers cast to pointer
 * this practice should be strongly discouraged. The far better method
 * is not to cast the offset integer value to a pointer, but to cast the
 * gl...Pointer functions to a type signature that defines the `data` parameter
 * to be an integer. To keep the size of the `data` parameter consistent
 * use the C standard type `uintptr_t` which is guaranted to be large enough
 * to hold the integer representation of a pointer.
 *
 * The same also goes for the glDraw...Elements functions.
 *
 * Also see http://stackoverflow.com/a/8284829/524368
 */
void (*glfixVertexOffset)(GLint, GLenum, GLsizei, uintptr_t const)        = (void*)glVertexPointer;
void (*glfixTexCoordOffset)(GLint, GLenum, GLsizei, uintptr_t const)      = (void*)glTexCoordPointer;
void (*glfixDrawElementsOffset)(GLenum, GLsizei, GLenum, uintptr_t const) = (void*)glDrawElements;
/* Those three functions are part of OpenGL-1.1, hence in the OpenGL ABIs of
 * all operating systems with OpenGL support and thus available as symbols
 * of the interface library, without additional initialization.
 *
 * Don't use static const initialization for function pointer obtained
 * through the OpenGL extension mechanism!
 */

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );

	glutCreateWindow("Minimal VBO example");
	glutDisplayFunc(display);
	glutIdleFunc(glutPostRedisplay);

	glewInit();
	init();

	glutMainLoop();

	return 0;
}

GLuint vertexbufId;
GLuint elementbufId;

void init()
{
	glGenBuffers(1, &vertexbufId);
	glBindBuffer(GL_ARRAY_BUFFER, vertexbufId);

	float const cube[5*8]=
	{ /*	 X   Y   Z   U   V  */
		-1, -1, -1,  0,  0,
		 1, -1, -1,  1,  0,
		 1,  1, -1,  1,  1,
		-1,  1, -1,  0,  1,

		-1, -1,  1, -1,  0,
		 1, -1,  1,  0,  0,
		 1,  1,  1,  0,  1,
		-1,  1,  1, -1,  1,
	};

	glBufferData(GL_ARRAY_BUFFER, 5*8*sizeof(float), cube, GL_STATIC_DRAW);
	glBindBuffer(GL_ARRAY_BUFFER, 0);


	glGenBuffers(1, &elementbufId);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbufId);

	unsigned int faces[4*6]=
	{
		0, 1, 2, 3,
		1, 5, 6, 2,
		5, 4, 7, 6,
		4, 0, 3, 7,
		3, 2, 6, 7,
		4, 5, 1, 0
	};

	glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4*6*sizeof(float), faces, GL_STATIC_DRAW);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

static float a = 0., b = 0., c = 0.;

void display()
{
	  int const win_width  = glutGet(GLUT_WINDOW_WIDTH);
	  int const win_height = glutGet(GLUT_WINDOW_HEIGHT);
	float const win_aspect = (float)win_width / (float) win_height;

	glClearColor(0.5, 0.5, 1., 1.);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glViewport(0, 0, win_width, win_height);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glFrustum(-win_aspect, win_aspect, -1, 1, 1, 10);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0, 0, -3);
	glRotatef(a += 1.00, 1, 0, 0);
	glRotatef(b += 0.66, 0, 1, 0);
	glRotatef(c += 0.33, 0, 0, 1);
	
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	glBindBuffer(GL_ARRAY_BUFFER, vertexbufId);
	glfixVertexOffset(  3, GL_FLOAT, 5*sizeof(float), 0);
	glfixTexCoordOffset(2, GL_FLOAT, 5*sizeof(float), 3);
	/* After the data source of a Vertex Array has been set
	 * this setting stays persistent regardless of any other
	 * state changes. So we can unbind the VBO bufferId here
	 * without loosing the connection. We must not delete
	 * the VBO though.
	 */
	glBindBuffer(GL_ARRAY_BUFFER, 0),

	glColor4f(0., 0., 0., 1.),

	/* Just drawing a wireframe */
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbufId);
	glfixDrawElementsOffset(GL_QUADS, 24, GL_UNSIGNED_INT, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);

	glutSwapBuffers();
}