#include <GL/glut.h>
#include <OMA/oma.h>
#include <OMA/omaut.h>

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

/*
	Yeah, in a perfect world it'd be time based, but it's not that
	big of a deal; this is only a demo of OMA, after all.
*/
#define MAGIC_ROTATION_RATE 0.06f

OMAsizei ModelChunkCount;
OMAuint Model, *ModelChunks, ObjectChunk = 123456;

void DisplayFunc(void) {
	static float r=0.0f;

	glClear(GL_COLOR_BUFFER_BIT);

	glLoadIdentity();
	glTranslatef(0.0f,0.0f,-5.0f);
	glRotatef(r += MAGIC_ROTATION_RATE,0.31f,0.54f,0.78f);

	{
		omaBindChunk(ObjectChunk);
		omautGLDrawObject();
	}

	glutSwapBuffers();
}

void ReshapeFunc(int Width, int Height) {
	glViewport(0,0,Width,Height);
	glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45, (float)Width/(float)Height, 1.0f, 5000.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void KeyboardFunc(unsigned char Key, int X, int Y) {
	switch(Key) {
		case 27: /* Escape */
		case 'q':
		case 'Q':
			exit(0);
			break;
		default:
			break;
	}
}

int LoadModel(void) {
	static const OMAubyte buffer[] =
		"<?xml version='1.0' ?>\n"
		"<oma>\n"
		"	<float id=\"1\">\n"
		"		<x>1</x><y>-1</y><z>-1</z>\n"
		"		<x>1</x><y>-1</y><z>1</z>\n"
		"		<x>-1</x><y>-1</y><z>1</z>\n"
		"		<x>-1</x><y>-1</y><z>-1</z>\n"
		"		<x>1</x><y>1</y><z>-1</z>\n"
		"		<x>-1</x><y>1</y><z>-1</z>\n"
		"		<x>-1</x><y>1</y><z>1</z>\n"
		"		<x>1</x><y>1</y><z>1</z>\n"
		"		<x>1</x><y>-1</y><z>-1</z>\n"
		"		<x>1</x><y>1</y><z>-1</z>\n"
		"		<x>1</x><y>1</y><z>1</z>\n"
		"		<x>1</x><y>-1</y><z>1</z>\n"
		"		<x>1</x><y>-1</y><z>1</z>\n"
		"		<x>1</x><y>1</y><z>1</z>\n"
		"		<x>-1</x><y>1</y><z>1</z>\n"
		"		<x>-1</x><y>-1</y><z>1</z>\n"
		"		<x>-1</x><y>-1</y><z>1</z>\n"
		"		<x>-1</x><y>1</y><z>1</z>\n"
		"		<x>-1</x><y>1</y><z>-1</z>\n"
		"		<x>-1</x><y>-1</y><z>-1</z>\n"
		"		<x>1</x><y>1</y><z>-1</z>\n"
		"		<x>1</x><y>-1</y><z>-1</z>\n"
		"		<x>-1</x><y>-1</y><z>-1</z>\n"
		"		<x>-1</x><y>1</y><z>-1</z>\n"
		"	</float>\n"
		"	<int id=\"2\">\n"
		"		<x>0</x><x>1</x><x>3</x><x>2</x>\n"
		"		<x>4</x><x>5</x><x>7</x><x>6</x>\n"
		"		<x>0</x><x>1</x><x>5</x><x>4</x>\n"
		"		<x>2</x><x>3</x><x>7</x><x>6</x>\n"
		"		<x>0</x><x>2</x><x>6</x><x>4</x>\n"
		"		<x>1</x><x>3</x><x>7</x><x>5</x>\n"
		"	</int>\n"
		"	<frame id=\"3\">\n"
		"		<item type=\"quads\">\n"
		"			<vertices id=\"1\" />\n"
		"			<indices id=\"2\" />\n"
		"		</item>\n"
		"	</frame>\n"
		"	<object id=\"5\">\n"
		"		<item>\n"
		"			<frame id=\"3\" index=\"0\" />\n"
		"		</item>\n"
		"	</object>\n"
		"</oma>\n";
	unsigned int a;

	omaGenChunks(1, &Model);
	omaBindChunk(Model);

	/* sizeof-1 to avoid including NULL terminator */
	omaLoadBuffer(OMA_OMX, buffer, sizeof(buffer)-1);

	ModelChunkCount = omaGetChunkParameteri(OMA_CHUNK_ELEM_COUNT);
	ModelChunks     = omaMapChunk(OMA_READ_ONLY);

	/* Find the first object chunk */
	for(a=0; a<ModelChunkCount; ++a) {
		omaBindChunk(ModelChunks[a]);
		
		if(omaGetChunkParameteri(OMA_CHUNK_TYPE) == OMA_OBJECT) {
			ObjectChunk = ModelChunks[a];
			break;
		}
	}
}

int FreeModel(void) {
	omaDeleteChunks(ModelChunkCount, ModelChunks);
	omaDeleteChunks(1, &Model);
}

void Init(void) {
	{
		glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
		glutInitWindowSize(400,400);
		glutCreateWindow("OMA OpenGL Demo");
		glutDisplayFunc(DisplayFunc);
		glutIdleFunc(DisplayFunc);
		glutReshapeFunc(ReshapeFunc);
		glutKeyboardFunc(KeyboardFunc);
	}
	{
		glShadeModel(GL_SMOOTH);
		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

		glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);

		glDisable(GL_CULL_FACE);
		glLineWidth(3.0f);

		glColor4f(1.0f,1.0f,1.0f,1.0f);
	}
	{
		omaInit();
	}
	{
		LoadModel();
	}
}

void Shutdown(void) {
	{
		FreeModel();
	}
	{
		omaShutdown();
	}
}

int main(int argc, char **argv) {
	glutInit(&argc,argv);

	{
		Init();
		atexit(Shutdown);
	}
	{
		glutMainLoop();
	}

	return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1