progs/objviewer: Wavefront .obj file loader/viewer demo

Adapted from code written by Nate Robins.  See README.txt.
This commit is contained in:
Brian Paul
2009-10-01 12:58:36 -06:00
parent e32a341be6
commit ca1bda552d
20 changed files with 764987 additions and 0 deletions
+161
View File
@@ -0,0 +1,161 @@
# Exported from Wings 3D 0.99.03
# Top flaps
newmtl BottomWing
Ns 100.0
d 1.0
illum 2
Kd 1.0 0.0 0.0
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd TopBotMap.rgb
newmtl CompBall_auv
Ns 100.0
d 1.0
illum 2
Kd 1.0 1.0 1.0
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd CompBall_auv.rgb
newmtl EngMat1
Ns 100.0
d 1.0
illum 2
Kd 0.334 0.334 0.334
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
newmtl EngMat2
Ns 100.0
d 1.0
illum 2
Kd 0.78688 0.78688 0.78688
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
newmtl Fuselage_auv
Ns 100.0
d 1.0
illum 2
Kd 1.0 1.0 1.0
Ka 0.0 0.0 0.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd SidesMap.rgb
newmtl Glass
Ns 100.0
d 0.5
illum 2
#Kd 0.5533333333333333 1.0 1.0
Kd 1.0 1.0 1.0
#Ka 0.37333333333333335 0.68 1.0
Ka 0.0 0.0 0.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
newmtl Grip
Ns 100.0
d 1.0
illum 2
Kd 0.47386 0.47386 0.47386
Ka 0.6203799999999999 0.6203799999999999 0.6203799999999999
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
newmtl Interior
Ns 100.0
d 1.0
illum 2
Kd 0.70696 0.70696 0.70696
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
newmtl Prop
Ns 100.0
d 1.0
illum 2
Kd 1.0 1.0 0.6266666666666667
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd PropMap.rgb
# Rudder
newmtl Sides
Ns 100.0
d 1.0
illum 2
Kd 1.0 0.0 0.0
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd SidesMap.rgb
newmtl TailHoriz
Ns 100.0
d 1.0
illum 2
Kd 1.0 0.0 0.0
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd TopBotMap.rgb
# Top wing, bot wing, fuselage
newmtl TopWing
Ns 100.0
d 1.0
illum 2
Kd 1.0 1.0 1.0
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd TopBotMap.rgb
newmtl Wheels
Ns 100.0
d 1.0
illum 2
Kd 0.0 0.0 0.0
Ka 0.0 0.0 0.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd WheelsMap.rgb
newmtl cylinder58_auv
Ns 100.0
d 1.0
illum 2
Kd 1.0 1.0 1.0
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd cylinder58_auv.rgb
newmtl default
Ns 100.0
d 1.0
illum 2
Kd 0.0 1.0 1.0
Ka 0.0 1.0 1.0
Ks 0.0 1.0 1.0
Ke 0.0 0.0 0.0
newmtl gage_auv
Ns 100.0
d 1.0
illum 2
Kd 1.0 1.0 1.0
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd gage_auv.rgb
File diff suppressed because it is too large Load Diff
+83
View File
@@ -0,0 +1,83 @@
TOP = ../..
include $(TOP)/configs/current
INCDIR = $(TOP)/include
LIBS = -L$(TOP)/$(LIB_DIR) -l$(GLUT_LIB) -l$(GLEW_LIB) \
-l$(GLU_LIB) -l$(GL_LIB) $(APP_LIB_DEPS)
# using : to avoid APP_CC pointing to CC loop
CC := $(APP_CC)
CFLAGS := -I$(INCDIR) $(CFLAGS)
LDLIBS = $(LIBS)
SOURCES = \
glm.c \
glmdraw.c \
objview.c \
trackball.c \
skybox.c \
readtex.c \
shaderutil.c
HEADERS = \
extfuncs.h \
readtex.h \
shaderutil.h \
trackball.h
OBJS = $(SOURCES:.c=.o)
PROG = objview
.c.o:
$(CC) -c $(CFLAGS) $< -o $@
default: $(PROG)
$(PROG): $(OBJS)
$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
$(OBJS): $(HEADERS)
### Extra dependencies
extfuncs.h: $(TOP)/progs/util/extfuncs.h
cp $< .
readtex.c: $(TOP)/progs/util/readtex.c
cp $< .
readtex.h: $(TOP)/progs/util/readtex.h
cp $< .
shaderutil.c: $(TOP)/progs/util/shaderutil.c
cp $< .
shaderutil.h: $(TOP)/progs/util/shaderutil.h
cp $< .
trackball.c: $(TOP)/progs/util/trackball.c
cp $< .
trackball.h: $(TOP)/progs/util/trackball.h
cp $< .
clean:
-rm -f $(PROG) $(OBJS)
-rm -f *.o *~
-rm -f extfuncs.h
-rm -f shaderutil.*
-rm -f trackball.*
-rm -f readtex.*
depend: $(SOURCES)
@$(MKDEP) $(MKDEP_OPTIONS) $(INCLUDE_DIRS) $(SOURCES) \
> /dev/null 2>/dev/null
-include depend
+15
View File
@@ -0,0 +1,15 @@
This .obj viewer is based on the "smooth" program by Nate Robins
found in the Kilgard GLUT package.
The alpine sky box textures come from http://www.hazelwhorley.com/skyboxtex3_bitmaps.html
The bunny.obj and buddha.obj models come from Stanford.
The GreatLakesBiplaneHP.obj model comes from http://www.sharecg.com/v/25978/3D-Model/Great-Lakes-Biplane-Model
The bobcat.obj model comes from http://www.sharecg.com/v/24771/3D-Model/Bobcat,3d-studio-and-wavefront-objects
The .obj file reader code in glm.c isn't perfect. Not all .obj files are
parsed correctly. There are often mistakes in material-to-triangle assignments.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+72
View File
@@ -0,0 +1,72 @@
# Exported from Wings 3D 0.99.00b
newmtl black
Ns 48.6667
d 1.00000
illum 2
Kd 1.00000e-3 1.00000e-3 1.00000e-3
Ka 1.00000 1.00000 1.00000
Ks 1.00000 1.00000 1.00000
Ka 0.00000 0.00000 0.00000
Ks 0.00000 0.00000 0.00000
Ke 0.00000e+0 0.00000e+0 0.00000e+0
newmtl blanco
Ns 100.000
d 1.00000
illum 2
Kd 1.00000 1.00000 1.00000
Ka 0.620380 0.620380 0.620380
Ks 0.806860 0.806860 0.806860
Ke 1.00000e-3 1.00000e-3 1.00000e-3
newmtl blue
Ns 100.000
d 1.00000
illum 2
Kd 0.105111 0.125293 0.366667
Ka 1.00000 1.00000 1.00000
Ks 1.00000 1.00000 1.00000
Ka 0.00000 0.00000 0.00000
Ks 0.00000 0.00000 0.00000
Ke 0.00000e+0 0.00000e+0 0.00000e+0
newmtl default
Ns 100.000
d 1.00000
illum 2
Kd 1.00000 1.00000 1.00000
Ka 1.00000 1.00000 1.00000
Ks 1.00000 1.00000 1.00000
Ka 0.10000 0.10000 0.10000
Ks 0.50000 0.50000 0.500000
Ke 0.00000e+0 0.00000e+0 0.00000e+0
newmtl gre
Ns 100.000
d 1.00000
illum 2
Kd 0.200800 0.200800 0.200800
Ka 1.00000 1.00000 1.00000
Ks 1.00000 1.00000 1.00000
Ka 0.00000 0.00000 0.00000
Ks 0.00000 0.00000 0.00000
Ke 0.00000e+0 0.00000e+0 0.00000e+0
newmtl red
Ns 100.000
d 1.00000
illum 2
Kd 0.460000 0.00000e+0 0.00000e+0
Ka 0.00000 0.00000 0.00000
Ks 0.00000 0.00000 0.00000
Ke 0.00000e+0 0.00000e+0 0.00000e+0
newmtl rojo
Ns 100.000
d 1.00000
illum 2
Kd 0.700000 0.00000e+0 0.00000e+0
Ka 0.00000 0.00000 0.00000
Ks 0.00000 0.00000 0.00000
Ke 1.00000e-3 1.00000e-3 1.00000e-3
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+287
View File
@@ -0,0 +1,287 @@
/*
* GLM library. Wavefront .obj file format reader/writer/manipulator.
*
* Written by Nate Robins, 1997.
* email: ndr@pobox.com
* www: http://www.pobox.com/~ndr
*/
#ifndef GLM_H
#define GLM_H
typedef unsigned int uint;
#ifndef M_PI
#define M_PI 3.14159265
#endif
/* defines */
#define GLM_NONE (0) /* render with only vertices */
#define GLM_FLAT (1 << 0) /* render with facet normals */
#define GLM_SMOOTH (1 << 1) /* render with vertex normals */
#define GLM_TEXTURE (1 << 2) /* render with texture coords */
#define GLM_COLOR (1 << 3) /* render with colors */
#define GLM_MATERIAL (1 << 4) /* render with materials */
/* structs */
/* GLMmaterial: Structure that defines a material in a model.
*/
typedef struct _GLMmaterial
{
char* name; /* name of material */
float diffuse[4]; /* diffuse component */
float ambient[4]; /* ambient component */
float specular[4]; /* specular component */
float emmissive[4]; /* emmissive component */
float shininess; /* specular exponent */
char *map_kd; /* diffuse texture map file */
uint texture_kd; /* diffuse texture map */
uint texture_ks; /* specular texture map */
int uDiffuse, uAmbient, uSpecular, uShininess, uDiffTex, uSpecTex;
uint prog;
} GLMmaterial;
/* GLMtriangle: Structure that defines a triangle in a model.
*/
typedef struct {
uint vindices[3]; /* array of triangle vertex indices */
uint nindices[3]; /* array of triangle normal indices */
uint tindices[3]; /* array of triangle texcoord indices*/
uint findex; /* index of triangle facet normal */
} GLMtriangle;
/* GLMgroup: Structure that defines a group in a model.
*/
typedef struct _GLMgroup {
char* name; /* name of this group */
uint numtriangles; /* number of triangles in this group */
uint* triangles; /* array of triangle indices */
uint material; /* index to material for group */
uint * triIndexes;
uint minIndex, maxIndex;
struct _GLMgroup* next; /* pointer to next group in model */
} GLMgroup;
/* GLMmodel: Structure that defines a model.
*/
typedef struct {
char* pathname; /* path to this model */
char* mtllibname; /* name of the material library */
uint numvertices; /* number of vertices in model */
float* vertices; /* array of vertices */
uint numnormals; /* number of normals in model */
float* normals; /* array of normals */
uint numtexcoords; /* number of texcoords in model */
float* texcoords; /* array of texture coordinates */
uint numfacetnorms; /* number of facetnorms in model */
float* facetnorms; /* array of facetnorms */
uint numtriangles; /* number of triangles in model */
GLMtriangle* triangles; /* array of triangles */
uint nummaterials; /* number of materials in model */
GLMmaterial* materials; /* array of materials */
uint numgroups; /* number of groups in model */
GLMgroup* groups; /* linked list of groups */
float position[3]; /* position of the model */
float scale;
uint vbo; /* OpenGL VBO for vertex data */
uint vertexSize; /* number of floats per vertex */
uint posOffset; /* offset of position within vertex, in bytes */
uint normOffset; /* offset of normal within vertex, in bytes */
uint texOffset; /* offset of texcoord within vertex, in bytes */
} GLMmodel;
/* public functions */
/* glmUnitize: "unitize" a model by translating it to the origin and
* scaling it to fit in a unit cube around the origin. Returns the
* scalefactor used.
*
* model - properly initialized GLMmodel structure
*/
float
glmUnitize(GLMmodel* model);
/* glmDimensions: Calculates the dimensions (width, height, depth) of
* a model.
*
* model - initialized GLMmodel structure
* dimensions - array of 3 floats (float dimensions[3])
*/
void
glmDimensions(GLMmodel* model, float* dimensions);
/* glmScale: Scales a model by a given amount.
*
* model - properly initialized GLMmodel structure
* scale - scalefactor (0.5 = half as large, 2.0 = twice as large)
*/
void
glmScale(GLMmodel* model, float scale);
/* glmReverseWinding: Reverse the polygon winding for all polygons in
* this model. Default winding is counter-clockwise. Also changes
* the direction of the normals.
*
* model - properly initialized GLMmodel structure
*/
void
glmReverseWinding(GLMmodel* model);
/* glmFacetNormals: Generates facet normals for a model (by taking the
* cross product of the two vectors derived from the sides of each
* triangle). Assumes a counter-clockwise winding.
*
* model - initialized GLMmodel structure
*/
void
glmFacetNormals(GLMmodel* model);
/* glmVertexNormals: Generates smooth vertex normals for a model.
* First builds a list of all the triangles each vertex is in. Then
* loops through each vertex in the the list averaging all the facet
* normals of the triangles each vertex is in. Finally, sets the
* normal index in the triangle for the vertex to the generated smooth
* normal. If the dot product of a facet normal and the facet normal
* associated with the first triangle in the list of triangles the
* current vertex is in is greater than the cosine of the angle
* parameter to the function, that facet normal is not added into the
* average normal calculation and the corresponding vertex is given
* the facet normal. This tends to preserve hard edges. The angle to
* use depends on the model, but 90 degrees is usually a good start.
*
* model - initialized GLMmodel structure
* angle - maximum angle (in degrees) to smooth across
*/
void
glmVertexNormals(GLMmodel* model, float angle);
/* glmLinearTexture: Generates texture coordinates according to a
* linear projection of the texture map. It generates these by
* linearly mapping the vertices onto a square.
*
* model - pointer to initialized GLMmodel structure
*/
void
glmLinearTexture(GLMmodel* model);
/* glmSpheremapTexture: Generates texture coordinates according to a
* spherical projection of the texture map. Sometimes referred to as
* spheremap, or reflection map texture coordinates. It generates
* these by using the normal to calculate where that vertex would map
* onto a sphere. Since it is impossible to map something flat
* perfectly onto something spherical, there is distortion at the
* poles. This particular implementation causes the poles along the X
* axis to be distorted.
*
* model - pointer to initialized GLMmodel structure
*/
void
glmSpheremapTexture(GLMmodel* model);
/* glmDelete: Deletes a GLMmodel structure.
*
* model - initialized GLMmodel structure
*/
void
glmDelete(GLMmodel* model);
/* glmReadOBJ: Reads a model description from a Wavefront .OBJ file.
* Returns a pointer to the created object which should be free'd with
* glmDelete().
*
* filename - name of the file containing the Wavefront .OBJ format data.
*/
GLMmodel*
glmReadOBJ(char* filename);
/* glmWriteOBJ: Writes a model description in Wavefront .OBJ format to
* a file.
*
* model - initialized GLMmodel structure
* filename - name of the file to write the Wavefront .OBJ format data to
* mode - a bitwise or of values describing what is written to the file
* GLM_NONE - write only vertices
* GLM_FLAT - write facet normals
* GLM_SMOOTH - write vertex normals
* GLM_TEXTURE - write texture coords
* GLM_FLAT and GLM_SMOOTH should not both be specified.
*/
void
glmWriteOBJ(GLMmodel* model, char* filename, uint mode);
/* glmDraw: Renders the model to the current OpenGL context using the
* mode specified.
*
* model - initialized GLMmodel structure
* mode - a bitwise OR of values describing what is to be rendered.
* GLM_NONE - render with only vertices
* GLM_FLAT - render with facet normals
* GLM_SMOOTH - render with vertex normals
* GLM_TEXTURE - render with texture coords
* GLM_FLAT and GLM_SMOOTH should not both be specified.
*/
void
glmDraw(GLMmodel* model, uint mode);
/* glmList: Generates and returns a display list for the model using
* the mode specified.
*
* model - initialized GLMmodel structure
* mode - a bitwise OR of values describing what is to be rendered.
* GLM_NONE - render with only vertices
* GLM_FLAT - render with facet normals
* GLM_SMOOTH - render with vertex normals
* GLM_TEXTURE - render with texture coords
* GLM_FLAT and GLM_SMOOTH should not both be specified.
*/
uint
glmList(GLMmodel* model, uint mode);
/* glmWeld: eliminate (weld) vectors that are within an epsilon of
* each other.
*
* model - initialized GLMmodel structure
* epsilon - maximum difference between vertices
* ( 0.00001 is a good start for a unitized model)
*
*/
void
glmWeld(GLMmodel* model, float epsilon);
void
glmReIndex(GLMmodel *model);
void
glmMakeVBOs(GLMmodel *model);
void
glmDrawVBO(GLMmodel *model);
void
glmPrint(const GLMmodel *model);
void
glmShaderMaterial(GLMmaterial *mat);
void
glmLoadTextures(GLMmodel *model);
void
glmSpecularTexture(GLMmodel *model, uint cubeTex);
#endif /* GLM_H */
+480
View File
@@ -0,0 +1,480 @@
/* */
#define GL_GLEXT_PROTOTYPES
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "glm.h"
#include "readtex.h"
#include "shaderutil.h"
/* defines */
#define T(x) model->triangles[(x)]
/* glmDraw: Renders the model to the current OpenGL context using the
* mode specified.
*
* model - initialized GLMmodel structure
* mode - a bitwise OR of values describing what is to be rendered.
* GLM_NONE - render with only vertices
* GLM_FLAT - render with facet normals
* GLM_SMOOTH - render with vertex normals
* GLM_TEXTURE - render with texture coords
* GLM_COLOR - render with colors (color material)
* GLM_MATERIAL - render with materials
* GLM_COLOR and GLM_MATERIAL should not both be specified.
* GLM_FLAT and GLM_SMOOTH should not both be specified.
*/
GLvoid
glmDraw(GLMmodel* model, GLuint mode)
{
GLuint i;
GLMgroup* group;
assert(model);
assert(model->vertices);
/* do a bit of warning */
if (mode & GLM_FLAT && !model->facetnorms) {
printf("glmDraw() warning: flat render mode requested "
"with no facet normals defined.\n");
mode &= ~GLM_FLAT;
}
if (mode & GLM_SMOOTH && !model->normals) {
printf("glmDraw() warning: smooth render mode requested "
"with no normals defined.\n");
mode &= ~GLM_SMOOTH;
}
if (mode & GLM_TEXTURE && !model->texcoords) {
printf("glmDraw() warning: texture render mode requested "
"with no texture coordinates defined.\n");
mode &= ~GLM_TEXTURE;
}
if (mode & GLM_FLAT && mode & GLM_SMOOTH) {
printf("glmDraw() warning: flat render mode requested "
"and smooth render mode requested (using smooth).\n");
mode &= ~GLM_FLAT;
}
if (mode & GLM_COLOR && !model->materials) {
printf("glmDraw() warning: color render mode requested "
"with no materials defined.\n");
mode &= ~GLM_COLOR;
}
if (mode & GLM_MATERIAL && !model->materials) {
printf("glmDraw() warning: material render mode requested "
"with no materials defined.\n");
mode &= ~GLM_MATERIAL;
}
if (mode & GLM_COLOR && mode & GLM_MATERIAL) {
printf("glmDraw() warning: color and material render mode requested "
"using only material mode\n");
mode &= ~GLM_COLOR;
}
if (mode & GLM_COLOR)
glEnable(GL_COLOR_MATERIAL);
if (mode & GLM_MATERIAL)
glDisable(GL_COLOR_MATERIAL);
glPushMatrix();
glTranslatef(model->position[0], model->position[1], model->position[2]);
glBegin(GL_TRIANGLES);
group = model->groups;
while (group) {
if (mode & GLM_MATERIAL) {
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,
model->materials[group->material].ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
model->materials[group->material].diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,
model->materials[group->material].specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS,
model->materials[group->material].shininess);
}
if (mode & GLM_COLOR) {
glColor3fv(model->materials[group->material].diffuse);
}
for (i = 0; i < group->numtriangles; i++) {
if (mode & GLM_FLAT)
glNormal3fv(&model->facetnorms[3 * T(group->triangles[i]).findex]);
if (mode & GLM_SMOOTH)
glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[0]]);
if (mode & GLM_TEXTURE)
glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[0]]);
glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[0]]);
#if 0
printf("%f %f %f\n",
model->vertices[3 * T(group->triangles[i]).vindices[0] + X],
model->vertices[3 * T(group->triangles[i]).vindices[0] + Y],
model->vertices[3 * T(group->triangles[i]).vindices[0] + Z]);
#endif
if (mode & GLM_SMOOTH)
glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[1]]);
if (mode & GLM_TEXTURE)
glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[1]]);
glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[1]]);
#if 0
printf("%f %f %f\n",
model->vertices[3 * T(group->triangles[i]).vindices[1] + X],
model->vertices[3 * T(group->triangles[i]).vindices[1] + Y],
model->vertices[3 * T(group->triangles[i]).vindices[1] + Z]);
#endif
if (mode & GLM_SMOOTH)
glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[2]]);
if (mode & GLM_TEXTURE)
glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[2]]);
glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[2]]);
#if 0
printf("%f %f %f\n",
model->vertices[3 * T(group->triangles[i]).vindices[2] + X],
model->vertices[3 * T(group->triangles[i]).vindices[2] + Y],
model->vertices[3 * T(group->triangles[i]).vindices[2] + Z]);
#endif
}
group = group->next;
}
glEnd();
glPopMatrix();
}
void
glmMakeVBOs(GLMmodel *model)
{
uint bytes, vertexFloats, i;
float *buffer;
vertexFloats = 3;
model->posOffset = 0;
if (model->numnormals > 0) {
assert(model->numnormals == model->numvertices);
model->normOffset = vertexFloats * sizeof(GLfloat);
vertexFloats += 3;
}
if (model->numtexcoords > 0) {
assert(model->numtexcoords == model->numvertices);
model->texOffset = vertexFloats * sizeof(GLfloat);
vertexFloats += 2;
}
model->vertexSize = vertexFloats;
bytes = (model->numvertices + 1) * vertexFloats * sizeof(float);
buffer = (float *) malloc(bytes);
for (i = 0; i < model->numvertices; i++) {
/* copy vertex pos */
uint j = 0;
buffer[i * vertexFloats + j++] = model->vertices[i * 3 + 0];
buffer[i * vertexFloats + j++] = model->vertices[i * 3 + 1];
buffer[i * vertexFloats + j++] = model->vertices[i * 3 + 2];
if (model->numnormals > 0) {
buffer[i * vertexFloats + j++] = model->normals[i * 3 + 0];
buffer[i * vertexFloats + j++] = model->normals[i * 3 + 1];
buffer[i * vertexFloats + j++] = model->normals[i * 3 + 2];
}
if (model->numtexcoords > 0) {
buffer[i * vertexFloats + j++] = model->texcoords[i * 2 + 0];
buffer[i * vertexFloats + j++] = model->texcoords[i * 2 + 1];
}
}
glGenBuffersARB(1, &model->vbo);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, model->vbo);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, bytes, buffer, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
free(buffer);
}
static void
_glmLoadTexture(GLMmaterial *mat)
{
if (mat->map_kd) {
GLint imgWidth, imgHeight;
GLenum imgFormat;
GLubyte *image = NULL;
glGenTextures(1, &mat->texture_kd);
image = LoadRGBImage( mat->map_kd, &imgWidth, &imgHeight, &imgFormat );
if (!image) {
/*fprintf(stderr, "Couldn't open texture %s\n", mat->map_kd);*/
free(mat->map_kd);
mat->map_kd = NULL;
mat->texture_kd = 0;
return;
}
if (0)
printf("load texture %s %d x %d\n", mat->map_kd, imgWidth, imgHeight);
glBindTexture(GL_TEXTURE_2D, mat->texture_kd);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, imgWidth, imgHeight,
imgFormat, GL_UNSIGNED_BYTE, image);
free(image);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}
}
void
glmLoadTextures(GLMmodel *model)
{
uint i;
for (i = 0; i < model->nummaterials; i++) {
GLMmaterial *mat = &model->materials[i];
_glmLoadTexture(mat);
}
}
void
glmDrawVBO(GLMmodel *model)
{
GLMgroup* group;
int mode = GLM_MATERIAL;
assert(model->vbo);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, model->vbo);
glVertexPointer(3, GL_FLOAT, model->vertexSize * sizeof(float),
(void *) model->posOffset);
glEnableClientState(GL_VERTEX_ARRAY);
if (model->numnormals > 0) {
glNormalPointer(GL_FLOAT, model->vertexSize * sizeof(float),
(void *) model->normOffset);
glEnableClientState(GL_NORMAL_ARRAY);
}
if (model->numtexcoords > 0) {
glTexCoordPointer(2, GL_FLOAT, model->vertexSize * sizeof(float),
(void *) model->texOffset);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
glPushMatrix();
glTranslatef(model->position[0], model->position[1], model->position[2]);
glScalef(model->scale, model->scale, model->scale);
for (group = model->groups; group; group = group->next) {
if (0&&strcmp(group->name, "Fuselage") != 0)
continue;
if (group->numtriangles > 0) {
if (model->materials && (mode & GLM_MATERIAL)) {
#if 0
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,
model->materials[group->material].ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
model->materials[group->material].diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,
model->materials[group->material].specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS,
model->materials[group->material].shininess);
#else
glmShaderMaterial(&model->materials[group->material]);
#endif
}
#if 0
glDrawElements(GL_TRIANGLES, 3 * group->numtriangles,
GL_UNSIGNED_INT, group->triIndexes);
#else
glDrawRangeElements(GL_TRIANGLES,
group->minIndex, group->maxIndex,
3 * group->numtriangles,
GL_UNSIGNED_INT, group->triIndexes);
#endif
glDisable(GL_BLEND);
}
}
glPopMatrix();
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
/* glmList: Generates and returns a display list for the model using
* the mode specified.
*
* model - initialized GLMmodel structure
* mode - a bitwise OR of values describing what is to be rendered.
* GLM_NONE - render with only vertices
* GLM_FLAT - render with facet normals
* GLM_SMOOTH - render with vertex normals
* GLM_TEXTURE - render with texture coords
* GLM_COLOR - render with colors (color material)
* GLM_MATERIAL - render with materials
* GLM_COLOR and GLM_MATERIAL should not both be specified.
* GLM_FLAT and GLM_SMOOTH should not both be specified.
*/
GLuint
glmList(GLMmodel* model, GLuint mode)
{
GLuint list;
list = glGenLists(1);
glNewList(list, GL_COMPILE);
glmDraw(model, mode);
glEndList();
return list;
}
static const char *VertexShader =
"varying vec3 normal; \n"
"void main() { \n"
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n"
" normal = gl_NormalMatrix * gl_Normal; \n"
" gl_TexCoord[0] = gl_MultiTexCoord0; \n"
"} \n";
/**
* Two %s substitutions:
* diffuse texture? true/false
* specular texture? true/false
*/
static const char *TexFragmentShader =
"uniform vec4 ambient, diffuse, specular; \n"
"uniform vec4 ambientLight, diffuseLight, specularLight; \n"
"uniform float shininess; \n"
"uniform sampler2D diffTex; \n"
"uniform samplerCube specTex; \n"
"varying vec3 normal; \n"
"\n"
"void main() \n"
"{ \n"
" vec4 diffTerm, specTerm; \n"
" float dotProd = max(dot(gl_LightSource[0].position.xyz, \n"
" normalize(normal)), 0.0);\n"
" float dotProd2 = max(dot(-gl_LightSource[0].position.xyz, \n"
" normalize(normal)), 0.0);\n"
" dotProd += dotProd2; \n"
" \n"
" diffTerm = diffuse * diffuseLight * dotProd; \n"
" if (%s) \n"
" diffTerm *= texture2D(diffTex, gl_TexCoord[0].st); \n"
" \n"
" specTerm = specular * specularLight * pow(dotProd, shininess); \n"
" if (%s) \n"
" specTerm *= textureCube(specTex, normal); \n"
" \n"
" gl_FragColor = ambient * ambientLight + diffTerm + specTerm; \n"
"} \n";
void
glmShaderMaterial(GLMmaterial *mat)
{
static const float ambientLight[4] = { 0.1, 0.1, 0.1, 0.0 };
static const float diffuseLight[4] = { 0.75, 0.75, 0.75, 1.0 };
static const float specularLight[4] = { 1.0, 1.0, 1.0, 0.0 };
if (!mat->prog) {
/* make shader now */
char newShader[10000];
GLuint vs, fs;
const char *diffuseTex = mat->texture_kd ? "true" : "false";
const char *specularTex = mat->texture_ks ? "true" : "false";
GLint uAmbientLight, uDiffuseLight, uSpecularLight;
/* replace %d with 0 or 1 */
sprintf(newShader, TexFragmentShader, diffuseTex, specularTex);
if (0)
printf("===== new shader =====\n%s\n============\n", newShader);
vs = CompileShaderText(GL_VERTEX_SHADER, VertexShader);
fs = CompileShaderText(GL_FRAGMENT_SHADER, newShader);
mat->prog = LinkShaders(vs, fs);
assert(mat->prog);
glUseProgram(mat->prog);
mat->uAmbient = glGetUniformLocation(mat->prog, "ambient");
mat->uDiffuse = glGetUniformLocation(mat->prog, "diffuse");
mat->uSpecular = glGetUniformLocation(mat->prog, "specular");
mat->uShininess = glGetUniformLocation(mat->prog, "shininess");
mat->uDiffTex = glGetUniformLocation(mat->prog, "diffTex");
mat->uSpecTex = glGetUniformLocation(mat->prog, "specTex");
uAmbientLight = glGetUniformLocation(mat->prog, "ambientLight");
uDiffuseLight = glGetUniformLocation(mat->prog, "diffuseLight");
uSpecularLight = glGetUniformLocation(mat->prog, "specularLight");
glUniform4fv(mat->uAmbient, 1, mat->ambient);
glUniform4fv(mat->uDiffuse, 1, mat->diffuse);
glUniform4fv(mat->uSpecular, 1, mat->specular);
glUniform1f(mat->uShininess, mat->shininess);
glUniform1i(mat->uDiffTex, 0);
glUniform1i(mat->uSpecTex, 1);
glUniform4fv(uAmbientLight, 1, ambientLight);
glUniform4fv(uDiffuseLight, 1, diffuseLight);
glUniform4fv(uSpecularLight, 1, specularLight);
}
glActiveTexture(GL_TEXTURE1);
if (mat->texture_ks)
glBindTexture(GL_TEXTURE_CUBE_MAP, mat->texture_ks);
else
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glActiveTexture(GL_TEXTURE0);
if (mat->texture_kd)
glBindTexture(GL_TEXTURE_2D, mat->texture_kd);
else
glBindTexture(GL_TEXTURE_2D, 0);
if (mat->diffuse[3] < 1.0) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else {
glDisable(GL_BLEND);
}
glUseProgram(mat->prog);
}
void
glmSpecularTexture(GLMmodel *model, uint cubeTex)
{
uint i;
for (i = 0; i < model->nummaterials; i++) {
model->materials[i].texture_ks = cubeTex;
}
}
+487
View File
@@ -0,0 +1,487 @@
/*
* .obj file viewer based on "smooth" by Nate Robins, 1997
*
* Brian Paul
* 1 Oct 2009
*/
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <stdarg.h>
#include <GL/glew.h>
#include <GL/glut.h>
#include "glm.h"
#include "readtex.h"
#include "skybox.h"
#include "trackball.h"
static char *Model_file = NULL; /* name of the obect file */
static GLMmodel *Model;
static GLfloat Scale = 4.0; /* scaling factor */
static GLboolean Performance = GL_FALSE;
static GLboolean Stats = GL_FALSE;
static GLboolean Animate = GL_TRUE;
static GLuint SkyboxTex;
static GLboolean Skybox = GL_TRUE;
static GLboolean Cull = GL_TRUE;
static GLboolean WireFrame = GL_FALSE;
static GLenum FrontFace = GL_CCW;
static GLfloat Yrot = 0.0;
static GLint WinWidth = 1024, WinHeight = 768;
static GLuint NumInstances = 1;
typedef struct
{
float CurQuat[4];
float Distance;
/* When mouse is moving: */
GLboolean Rotating, Translating;
GLint StartX, StartY;
float StartDistance;
} ViewInfo;
static ViewInfo View;
static void
InitViewInfo(ViewInfo *view)
{
view->Rotating = GL_FALSE;
view->Translating = GL_FALSE;
view->StartX = view->StartY = 0;
view->Distance = 12.0;
view->StartDistance = 0.0;
view->CurQuat[0] = 0.0;
view->CurQuat[1] = 1.0;
view->CurQuat[2] = 0.0;
view->CurQuat[3] = 0.0;
}
/* text: general purpose text routine. draws a string according to
* format in a stroke font at x, y after scaling it by the scale
* specified (scale is in window-space (lower-left origin) pixels).
*
* x - position in x (in window-space)
* y - position in y (in window-space)
* scale - scale in pixels
* format - as in printf()
*/
static void
text(GLuint x, GLuint y, GLfloat scale, char* format, ...)
{
va_list args;
char buffer[255], *p;
GLfloat font_scale = 119.05 + 33.33;
va_start(args, format);
vsprintf(buffer, format, args);
va_end(args);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, glutGet(GLUT_WINDOW_WIDTH), 0, glutGet(GLUT_WINDOW_HEIGHT));
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glTranslatef(x, y, 0.0);
glScalef(scale/font_scale, scale/font_scale, scale/font_scale);
for(p = buffer; *p; p++)
glutStrokeCharacter(GLUT_STROKE_ROMAN, *p);
glPopAttrib();
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
static float
ComputeFPS(void)
{
static double t0 = -1.0;
static int frames = 0;
double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
static float fps = 0;
frames++;
if (t0 < 0.0) {
t0 = t;
fps = 0.0;
}
else if (t - t0 >= 4.0) {
fps = (frames / (t - t0) + 0.5);
t0 = t;
frames = 0;
return fps;
}
return 0.0;
}
static void
init_model(void)
{
float objScale;
/* read in the model */
Model = glmReadOBJ(Model_file);
objScale = glmUnitize(Model);
glmFacetNormals(Model);
if (Model->numnormals == 0) {
GLfloat smoothing_angle = 90.0;
printf("Generating normals.");
glmVertexNormals(Model, smoothing_angle);
}
glmLoadTextures(Model);
glmReIndex(Model);
glmMakeVBOs(Model);
if (0)
glmPrint(Model);
}
static void
init_skybox(void)
{
SkyboxTex = LoadSkyBoxCubeTexture("alpine_east.rgb",
"alpine_west.rgb",
"alpine_up.rgb",
"alpine_down.rgb",
"alpine_south.rgb",
"alpine_north.rgb");
glmSpecularTexture(Model, SkyboxTex);
}
static void
init_gfx(void)
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_NORMALIZE);
glClearColor(0.3, 0.3, 0.9, 0.0);
}
static void
reshape(int width, int height)
{
float ar = 0.5 * (float) width / (float) height;
WinWidth = width;
WinHeight = height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -0.5, 0.5, 1.0, 300.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -3.0);
}
static void
Idle(void)
{
float q[4];
trackball(q, 100, 0, 99.99, 0);
add_quats(q, View.CurQuat, View.CurQuat);
glutPostRedisplay();
}
static void
display(void)
{
GLfloat rot[4][4];
float fps;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(0.0, 0.0, -View.Distance);
glRotatef(Yrot, 0, 1, 0);
build_rotmatrix(rot, View.CurQuat);
glMultMatrixf(&rot[0][0]);
glScalef(Scale, Scale, Scale );
glUseProgram(0);
if (Skybox)
DrawSkyBoxCubeTexture(SkyboxTex);
if (WireFrame)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
if (Cull)
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);
if (NumInstances == 1) {
glmDrawVBO(Model);
}
else {
/* draw > 1 instance */
float dr = 360.0 / NumInstances;
float r;
for (r = 0.0; r < 360.0; r += dr) {
glPushMatrix();
glRotatef(r, 0, 1, 0);
glTranslatef(1.4, 0.0, 0.0);
glmDrawVBO(Model);
glPopMatrix();
}
}
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_CULL_FACE);
glPopMatrix();
if (Stats) {
glColor3f(1.0, 1.0, 1.0);
text(5, glutGet(GLUT_WINDOW_HEIGHT) - (5+20*1), 20, "%s",
Model->pathname);
text(5, glutGet(GLUT_WINDOW_HEIGHT) - (5+20*2), 20, "%d vertices",
Model->numvertices);
text(5, glutGet(GLUT_WINDOW_HEIGHT) - (5+20*3), 20, "%d triangles",
Model->numtriangles);
text(5, glutGet(GLUT_WINDOW_HEIGHT) - (5+20*4), 20, "%d normals",
Model->numnormals);
text(5, glutGet(GLUT_WINDOW_HEIGHT) - (5+20*5), 20, "%d texcoords",
Model->numtexcoords);
text(5, glutGet(GLUT_WINDOW_HEIGHT) - (5+20*6), 20, "%d groups",
Model->numgroups);
text(5, glutGet(GLUT_WINDOW_HEIGHT) - (5+20*7), 20, "%d materials",
Model->nummaterials);
}
glutSwapBuffers();
fps = ComputeFPS();
if (fps)
printf("%f FPS\n", fps);
}
static void
keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 'h':
printf("help\n\n");
printf("a - Toggle animation\n");
printf("d/D - Decrease/Incrase number of models\n");
printf("w - Toggle wireframe/filled\n");
printf("c - Toggle culling\n");
printf("n - Toggle facet/smooth normal\n");
printf("r - Reverse polygon winding\n");
printf("p - Toggle performance indicator\n");
printf("s - Toggle skybox\n");
printf("z/Z - Scale model smaller/larger\n");
printf("i - Show model info/stats\n");
printf("q/escape - Quit\n\n");
break;
case 'a':
Animate = !Animate;
if (Animate)
glutIdleFunc(Idle);
else
glutIdleFunc(NULL);
break;
case 'd':
if (NumInstances > 1)
NumInstances--;
break;
case 'D':
NumInstances++;
break;
case 'i':
Stats = !Stats;
break;
case 'p':
Performance = !Performance;
break;
case 'w':
WireFrame = !WireFrame;
break;
case 'c':
Cull = !Cull;
printf("Polygon culling: %d\n", Cull);
break;
case 'r':
if (FrontFace == GL_CCW)
FrontFace = GL_CW;
else
FrontFace = GL_CCW;
glFrontFace(FrontFace);
printf("Front face:: %s\n", FrontFace == GL_CCW ? "CCW" : "CW");
break;
case 's':
Skybox = !Skybox;
if (Skybox)
glmSpecularTexture(Model, SkyboxTex);
else
glmSpecularTexture(Model, 0);
break;
case 'z':
Scale *= 0.9;
break;
case 'Z':
Scale *= 1.1;
break;
case 'q':
case 27:
exit(0);
break;
}
glutPostRedisplay();
}
static void
menu(int item)
{
keyboard((unsigned char)item, 0, 0);
}
/**
* Handle mouse button.
*/
static void
Mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON) {
if (state == GLUT_DOWN) {
View.StartX = x;
View.StartY = y;
View.Rotating = GL_TRUE;
}
else if (state == GLUT_UP) {
View.Rotating = GL_FALSE;
}
}
else if (button == GLUT_MIDDLE_BUTTON) {
if (state == GLUT_DOWN) {
View.StartX = x;
View.StartY = y;
View.StartDistance = View.Distance;
View.Translating = GL_TRUE;
}
else if (state == GLUT_UP) {
View.Translating = GL_FALSE;
}
}
}
/**
* Handle mouse motion
*/
static void
Motion(int x, int y)
{
int i;
if (View.Rotating) {
float x0 = (2.0 * View.StartX - WinWidth) / WinWidth;
float y0 = (WinHeight - 2.0 * View.StartY) / WinHeight;
float x1 = (2.0 * x - WinWidth) / WinWidth;
float y1 = (WinHeight - 2.0 * y) / WinHeight;
float q[4];
trackball(q, x0, y0, x1, y1);
View.StartX = x;
View.StartY = y;
for (i = 0; i < 1; i++)
add_quats(q, View.CurQuat, View.CurQuat);
glutPostRedisplay();
}
else if (View.Translating) {
float dz = 0.02 * (y - View.StartY);
View.Distance = View.StartDistance + dz;
glutPostRedisplay();
}
}
int
main(int argc, char** argv)
{
glutInitWindowSize(WinWidth, WinHeight);
glutInit(&argc, argv);
if (argc > 1) {
Model_file = argv[1];
}
if (!Model_file) {
fprintf(stderr, "usage: objview file.obj\n");
fprintf(stderr, "(using default bunny.obj)\n");
Model_file = "bunny.obj";
}
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutCreateWindow("objview");
glewInit();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMouseFunc(Mouse);
glutMotionFunc(Motion);
if (Animate)
glutIdleFunc(Idle);
glutCreateMenu(menu);
glutAddMenuEntry("[a] Toggle animate", 'a');
glutAddMenuEntry("[d] Fewer models", 'd');
glutAddMenuEntry("[D] More models", 'D');
glutAddMenuEntry("[w] Toggle wireframe/filled", 'w');
glutAddMenuEntry("[c] Toggle culling on/off", 'c');
glutAddMenuEntry("[r] Reverse polygon winding", 'r');
glutAddMenuEntry("[z] Scale model smaller", 'z');
glutAddMenuEntry("[Z] Scale model larger", 'Z');
glutAddMenuEntry("[p] Toggle performance indicator", 'p');
glutAddMenuEntry("[i] Show model stats", 'i');
glutAddMenuEntry("", 0);
glutAddMenuEntry("[q] Quit", 27);
glutAttachMenu(GLUT_RIGHT_BUTTON);
InitViewInfo(&View);
init_model();
init_skybox();
init_gfx();
glutMainLoop();
return 0;
}
+186
View File
@@ -0,0 +1,186 @@
#include <assert.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/glu.h>
#include "readtex.h"
#include "skybox.h"
static int
load(GLenum target, const char *filename,
GLboolean flipTB, GLboolean flipLR)
{
GLint w, h;
GLenum format;
GLubyte *img = LoadRGBImage( filename, &w, &h, &format );
if (!img) {
printf("Error: couldn't load texture image %s\n", filename);
return 0;
}
assert(format == GL_RGB);
printf("Load cube face 0x%x: %s %d x %d\n", target, filename, w, h);
/* <sigh> the way the texture cube mapping works, we have to flip
* images to make things look right.
*/
if (flipTB) {
const int stride = 3 * w;
GLubyte temp[3*1024];
int i;
for (i = 0; i < h / 2; i++) {
memcpy(temp, img + i * stride, stride);
memcpy(img + i * stride, img + (h - i - 1) * stride, stride);
memcpy(img + (h - i - 1) * stride, temp, stride);
}
}
if (flipLR) {
const int stride = 3 * w;
GLubyte temp[3];
GLubyte *row;
int i, j;
for (i = 0; i < h; i++) {
row = img + i * stride;
for (j = 0; j < w / 2; j++) {
int k = w - j - 1;
temp[0] = row[j*3+0];
temp[1] = row[j*3+1];
temp[2] = row[j*3+2];
row[j*3+0] = row[k*3+0];
row[j*3+1] = row[k*3+1];
row[j*3+2] = row[k*3+2];
row[k*3+0] = temp[0];
row[k*3+1] = temp[1];
row[k*3+2] = temp[2];
}
}
}
gluBuild2DMipmaps(target, GL_RGB, w, h, format, GL_UNSIGNED_BYTE, img);
free(img);
return 1;
}
GLuint
LoadSkyBoxCubeTexture(const char *filePosX,
const char *fileNegX,
const char *filePosY,
const char *fileNegY,
const char *filePosZ,
const char *fileNegZ)
{
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_X, filePosX, GL_TRUE, GL_TRUE))
return 0;
if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, fileNegX, GL_TRUE, GL_TRUE))
return 0;
if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, filePosY, 1+GL_FALSE, GL_TRUE))
return 0;
if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, fileNegY, 1+GL_FALSE, GL_TRUE))
return 0;
if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, filePosZ, GL_TRUE, GL_TRUE))
return 0;
if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, fileNegZ, GL_TRUE, GL_TRUE))
return 0;
return tex;
}
#define eps1 0.99
#define br 20.0 /* box radius */
void
DrawSkyBoxCubeTexture(GLuint tex)
{
struct vertex {
float x, y, z, s, t, r;
};
static const struct vertex verts[24] = {
/* +X side */
{ br, -br, -br, 1.0, -eps1, -eps1 },
{ br, -br, br, 1.0, -eps1, eps1 },
{ br, br, br, 1.0, eps1, eps1 },
{ br, br, -br, 1.0, eps1, -eps1 },
/* -X side */
{ -br, br, -br, -1.0, eps1, -eps1 },
{ -br, br, br, -1.0, eps1, eps1 },
{ -br, -br, br, -1.0, -eps1, eps1 },
{ -br, -br, -br, -1.0, -eps1, -eps1 },
/* +Y side */
{ br, br, -br, eps1, 1.0, -eps1 },
{ br, br, br, eps1, 1.0, eps1 },
{ -br, br, br, -eps1, 1.0, eps1 },
{ -br, br, -br, -eps1, 1.0, -eps1 },
/* -Y side */
{ -br, -br, -br, -eps1, -1.0, -eps1 },
{ -br, -br, br, -eps1, -1.0, eps1 },
{ br, -br, br, eps1, -1.0, eps1 },
{ br, -br, -br, eps1, -1.0, -eps1 },
/* +Z side */
{ br, -br, br, eps1, -eps1, 1.0 },
{ -br, -br, br, -eps1, -eps1, 1.0 },
{ -br, br, br, -eps1, eps1, 1.0 },
{ br, br, br, eps1, eps1, 1.0 },
/* -Z side */
{ br, br, -br, eps1, eps1, -1.0 },
{ -br, br, -br, -eps1, eps1, -1.0 },
{ -br, -br, -br, -eps1, -eps1, -1.0 },
{ br, -br, -br, eps1, -eps1, -1.0 },
};
static GLuint vbo = 0;
if (!vbo ) {
glGenBuffersARB(1, &vbo);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts,
GL_STATIC_DRAW_ARB);
}
else {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
}
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glVertexPointer(3, GL_FLOAT, sizeof(struct vertex),
(void *) offsetof(struct vertex, x));
glTexCoordPointer(3, GL_FLOAT, sizeof(struct vertex),
(void *) offsetof(struct vertex, s));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
glEnable(GL_TEXTURE_CUBE_MAP);
//glDisable(GL_LIGHTING);
glDisable(GL_BLEND);
glDrawArrays(GL_QUADS, 0, 24);
//glEnable(GL_LIGHTING);
glDisable(GL_TEXTURE_CUBE_MAP);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
+18
View File
@@ -0,0 +1,18 @@
#ifndef SKYBOX_H
#define SKYBOX_H
extern GLuint
LoadSkyBoxCubeTexture(const char *filePosX,
const char *fileNegX,
const char *filePosY,
const char *fileNegY,
const char *filePosZ,
const char *fileNegZ);
extern void
DrawSkyBoxCubeTexture(GLuint tex);
#endif /* SKYBOX_H */