Created
October 19, 2010 00:22
-
-
Save dlivingstone/633350 to your computer and use it in GitHub Desktop.
A loaddata program for OpenGL that will load and render a model stored in a particular matching format. Example model data and fragment shader available here: http://gist.github.com/629763 . This gist includes the main cpp file and the vertex shader only.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Vertex Shader – default light | |
// This is based (very closely!) on code extracted from the GLShaderManager provided | |
// by Richard Wright for the OpenGL SuperBible, 5th Edition | |
// The SuperBible source code is available http://www.starstonesoftware.com/OpenGL/ | |
///* GLShaderManager.h | |
// | |
//Copyright (c) 2009, Richard S. Wright Jr. | |
//All rights reserved. | |
// | |
//Redistribution and use in source and binary forms, with or without modification, | |
//are permitted provided that the following conditions are met: | |
// | |
//Redistributions of source code must retain the above copyright notice, this list | |
//of conditions and the following disclaimer. | |
// | |
//Redistributions in binary form must reproduce the above copyright notice, this list | |
//of conditions and the following disclaimer in the documentation and/or other | |
//materials provided with the distribution. | |
// | |
//Neither the name of Richard S. Wright Jr. nor the names of other contributors may be used | |
//to endorse or promote products derived from this software without specific prior | |
//written permission. | |
// | |
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY | |
//EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
//OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT | |
//SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
//TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
//BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
//CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
//*/ | |
#version 130 | |
uniform mat4 mvMatrix; | |
uniform mat4 pMatrix; | |
in vec3 in_Position; | |
in vec3 in_Normal; | |
in vec3 in_Color; | |
out vec3 ex_Color; | |
void main(void) { | |
mat3 mNormalMatrix; | |
mNormalMatrix[0] = mvMatrix[0].xyz; | |
mNormalMatrix[1] = mvMatrix[1].xyz; | |
mNormalMatrix[2] = mvMatrix[2].xyz; | |
vec3 vNorm = normalize(mNormalMatrix * in_Normal); | |
vec3 vLightDir = vec3(0.0, 0.0, 1.0); | |
float fDot = max(0.0, dot(vNorm, vLightDir)); | |
ex_Color.rgb = in_Color.rgb * fDot; | |
mat4 mvpMatrix; | |
mvpMatrix = pMatrix * mvMatrix; | |
gl_Position = mvpMatrix * vec4(in_Position,1.0); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// loaddata | |
// A simple app that loads model data from a custom data format | |
// the format is a (relatively) simple one based on how an individual | |
// mesh may be saved in a Collada file - currently the easiest way | |
// to make models, is with Google Sketchup, export to Collada, then | |
// manually hack the data and save. | |
// Daniel Livingstone, Oct 2010 | |
// | |
// On Windows, the following define can remove some compiler problems, | |
// but remove the line if compiling for other platforms! | |
// #ifdef WIN32 doesn't seem to always work under VS2010 otherwise | |
#define WIN32 | |
#include <GLTools.h> // OpenGL toolkit | |
// If you have math3d, glew & freeglut installed - but not GLTools, use the following | |
// two lines instead of the two above | |
//#include <math3d.h> | |
//#include <GL/glew.h> | |
#include <iostream> | |
#include <fstream> | |
#include <sstream> | |
#define FREEGLUT_STATIC | |
#include <GL/glut.h> | |
using namespace std; | |
// * Global Variables * | |
GLuint vertexArrayObjID[1]; // Just the one vertex array object | |
GLuint vertexBufferObjID[3];// 3 vertex buffer objects in this example | |
GLuint numVerts; // How many vertices in array? | |
GLfloat angle = 0.0f; // going to animate the object | |
GLuint program; // Global handle for shader program | |
// Functions | |
// loadFile - loads text file into char* fname (for loading shader programs) | |
// allocates memory - so will need to delete after use, size of file returned in fSize | |
char* loadFile(char *fname, GLint &fSize) | |
{ | |
ifstream::pos_type size; | |
char * memblock; | |
string text; | |
ifstream file (fname, ios::in|ios::binary|ios::ate); | |
if (file.is_open()) | |
{ | |
size = file.tellg(); | |
fSize = (GLuint) size; | |
memblock = new char [size]; | |
file.seekg (0, ios::beg); | |
file.read (memblock, size); | |
file.close(); | |
cout << "file " << fname << " loaded" << endl; | |
text.assign(memblock); | |
} | |
else | |
{ | |
cout << "Unable to open file " << fname << endl; | |
exit(1); | |
} | |
return memblock; | |
} | |
// printShaderInfoLog | |
// From OpenGL Shading Language 3rd Edition, p215-216 | |
// Display (hopefully) useful error messages if shader fails to compile | |
void printShaderInfoLog(GLint shader) | |
{ | |
int infoLogLen = 0; | |
int charsWritten = 0; | |
GLchar *infoLog; | |
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLen); | |
// should additionally check for OpenGL errors here | |
if (infoLogLen > 0) | |
{ | |
infoLog = new GLchar[infoLogLen]; | |
// error check for fail to allocate memory omitted | |
glGetShaderInfoLog(shader,infoLogLen, &charsWritten, infoLog); | |
cout << "InfoLog:" << endl << infoLog << endl; | |
delete [] infoLog; | |
} | |
// should additionally check for OpenGL errors here | |
} | |
GLuint initShaders(void) | |
{ | |
GLuint p, f, v; | |
char *vs,*fs; | |
v = glCreateShader(GL_VERTEX_SHADER); | |
f = glCreateShader(GL_FRAGMENT_SHADER); | |
// load shaders & get length of each | |
GLint vlen; | |
GLint flen; | |
vs = loadFile("default_light.vert",vlen); | |
fs = loadFile("minimal.frag",flen); | |
const char * vv = vs; | |
const char * ff = fs; | |
glShaderSource(v, 1, &vv,&vlen); | |
glShaderSource(f, 1, &ff,&flen); | |
GLint compiled; | |
glCompileShader(v); | |
glGetShaderiv(v, GL_COMPILE_STATUS, &compiled); | |
if (!compiled) | |
{ | |
cout << "Vertex shader not compiled." << endl; | |
printShaderInfoLog(v); | |
} | |
glCompileShader(f); | |
glGetShaderiv(f, GL_COMPILE_STATUS, &compiled); | |
if (!compiled) | |
{ | |
cout << "Fragment shader not compiled." << endl; | |
printShaderInfoLog(f); | |
} | |
p = glCreateProgram(); | |
glAttachShader(p,v); | |
glAttachShader(p,f); | |
glBindAttribLocation(p,0, "in_Position"); | |
glBindAttribLocation(p,1, "in_Normal"); | |
glBindAttribLocation(p,2, "in_Color"); | |
glLinkProgram(p); | |
GLint params[1]; | |
glGetProgramiv(p,GL_LINK_STATUS,params); | |
if (params[0] == GL_FALSE) | |
{ | |
cout << "Shader programs not linked" << endl; | |
printShaderInfoLog(f); | |
} | |
glUseProgram(p); | |
delete [] vs; // dont forget to free allocated memory | |
delete [] fs; // we allocated this in the loadFile function... | |
return p; | |
} | |
// loadData function | |
// this function *assumes* that the data matches the particular | |
// format expected, and will blow-up if it does not | |
void loadData(char* fname) | |
{ | |
ifstream::pos_type size; | |
char * memblock; | |
ifstream file (fname, ios::in|ios::binary|ios::ate); | |
if (file.is_open()) | |
{ | |
size = file.tellg(); | |
memblock = new char [size]; | |
file.seekg (0, ios::beg); | |
file.read (memblock, size); | |
file.close(); | |
cout << "file " << fname << " loaded" << endl; | |
} | |
else | |
{ // Would be desireable to load dummy data or something else instead | |
// to prevent program from simply closing or blowing up | |
cout << "Unable to open file " << fname << endl; | |
exit(1); | |
} | |
stringstream strstream(memblock); // Copy file into a stringstream | |
string magicnumber; // Basic check: is this a uwsm file? | |
strstream >> magicnumber; | |
if (magicnumber.compare(0,4,"uwsm")!=0) | |
{ // could also use the version number, but not doing that just now | |
cerr << "File " << fname << " is not a uwsm file." << endl; | |
exit (1); | |
} | |
// Allocate Vertex Array Object(s) | |
glGenVertexArrays(1, &vertexArrayObjID[0]); | |
// Setup first Vertex Array Object | |
glBindVertexArray(vertexArrayObjID[0]); | |
glGenBuffers(3, vertexBufferObjID); | |
// Read geometry | |
int i, count; //count is number of floats, ie verts x 3 | |
strstream >> count; | |
M3DVector3f *vertices = new M3DVector3f[count/3]; | |
for (i=0;i<count/3;i++) | |
strstream >> vertices[i][0] >> vertices[i][1] >> vertices[i][2]; | |
// VBO for vertex data | |
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[0]); | |
glBufferData(GL_ARRAY_BUFFER, count*3*sizeof(GLfloat), | |
vertices, GL_STATIC_DRAW); | |
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); | |
glEnableVertexAttribArray(0); | |
// Read normals | |
strstream >> count; // how many normals? need not be same as vertices | |
M3DVector3f *normals = new M3DVector3f[count/3]; | |
if (count > 0) // model has normals | |
for (i=0;i<count/3;i++) | |
strstream >> normals[i][0] >> normals[i][1] >> normals[i][2]; | |
// VBO for normal data | |
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[1]); | |
glBufferData(GL_ARRAY_BUFFER, count*3*sizeof(GLfloat), | |
normals, GL_STATIC_DRAW); | |
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0); | |
glEnableVertexAttribArray(1); | |
// Read texture coordinates | |
strstream >> count; // how many texture coords? need not be same as vertices | |
GLfloat nul; | |
if (count > 0) // model has texture coordinates | |
for (i=0;i<count;i++) | |
strstream >> nul; // not using these just now! | |
// Finished setting up the vertex array | |
glBindVertexArray(0); | |
// Now to fill the index array - another buffer object | |
int triangles; | |
strstream >> triangles; // how many *triangles* in mesh? | |
numVerts = triangles * 3; | |
GLuint *meshIndices = new GLuint[numVerts]; | |
for (i=0;i<numVerts;i++) | |
strstream >> meshIndices[i]; | |
// Note, the next buffer object is of type ELEMENT_ARRAY_BUFFER | |
// This is for storing the indices for drawing the geometry | |
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexBufferObjID[2]); | |
glBufferData(GL_ELEMENT_ARRAY_BUFFER, numVerts*sizeof(GLuint), | |
meshIndices, GL_STATIC_DRAW); | |
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); | |
delete [] memblock; | |
delete [] vertices; | |
delete [] normals; | |
delete [] meshIndices; | |
} | |
void reshape(GLint w, GLint h) | |
{ | |
glViewport(0, 0, w, h); | |
} | |
void display(void) | |
{ | |
// clear the screen | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); | |
M3DMatrix44f projection; | |
m3dLoadIdentity44(projection); | |
M3DMatrix44f modelview; | |
m3dLoadIdentity44(modelview); | |
M3DMatrix44f temp; | |
// set up the projection matrix | |
m3dMakePerspectiveMatrix(projection, m3dDegToRad(60), 1.0f, 0.5f, 100.0f); | |
// create a translation matrix | |
M3DMatrix44f translation; | |
m3dTranslationMatrix44(translation,0.0f,0.0f,-10.0f); | |
m3dCopyMatrix44(temp, modelview); | |
m3dMatrixMultiply44(modelview, temp, translation); | |
// create a rotation matrix | |
M3DMatrix44f rotation; | |
m3dRotationMatrix44(rotation, m3dDegToRad(-45), 1.0f, 0.0f, 0.0f); | |
m3dCopyMatrix44(temp, modelview); | |
m3dMatrixMultiply44(modelview, temp, rotation); | |
m3dRotationMatrix44(rotation, angle, 0.0f, 0.0f, 1.0f); | |
m3dCopyMatrix44(temp, modelview); | |
m3dMatrixMultiply44(modelview, temp, rotation); | |
angle += 0.01; | |
// create a scale matrix | |
M3DMatrix44f scale; | |
m3dScaleMatrix44(scale, 0.1f, 0.1f, 0.1f); | |
m3dCopyMatrix44(temp, modelview); | |
m3dMatrixMultiply44(modelview, temp, scale); | |
// Set up the uniform inputs | |
glUniformMatrix4fv(glGetUniformLocation(program,"mvMatrix"), | |
1,GL_FALSE,modelview); | |
glUniformMatrix4fv(glGetUniformLocation(program,"pMatrix"), | |
1,GL_FALSE,projection); | |
glBindVertexArray(vertexArrayObjID[0]); // First VAO | |
glEnableVertexAttribArray(0); // enable position attribue array | |
glEnableVertexAttribArray(1); // enable normal attribute array | |
glVertexAttrib3f((GLuint)2, 1.0, 0.0, 0.0); // set constant color attribute | |
// using index list, so use DrawElements instead of Draw Array | |
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexBufferObjID[2]); | |
glDrawElements(GL_TRIANGLES, numVerts, GL_UNSIGNED_INT, 0); | |
//If indices were *not* in a buffer, but in an array, the following would | |
//be used instead of the above two lines: | |
// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); | |
// glDrawElements(GL_TRIANGLES, numVerts, GL_UNSIGNED_INT, meshIndices); | |
glBindVertexArray(0); | |
glutPostRedisplay(); | |
glutSwapBuffers(); | |
} | |
void init(void) | |
{ | |
glClearColor(1.0f, 1.0f, 1.0f, 1.0f ); // white background | |
glEnable(GL_DEPTH_TEST); | |
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
loadData("blocks.uwsm"); | |
} | |
// Main function - program entry point | |
int main(int argc, char* argv[]) | |
{ | |
glutInit(&argc, argv); | |
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); | |
glutInitWindowSize(800, 600); | |
glutCreateWindow("simple3Dapp"); | |
GLenum err = glewInit(); | |
if (GLEW_OK != err) | |
{ | |
// Problem: glewInit failed, something is seriously wrong. | |
cerr << "Error: " << glewGetErrorString(err) << endl; | |
return 1; | |
} | |
glutReshapeFunc(reshape); | |
glutDisplayFunc(display); | |
init(); | |
program = initShaders(); | |
glutPostRedisplay(); // draw the scene once | |
glutMainLoop(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment