/*
* GLM library. Wavefront .obj file format reader/writer/manipulator.
*
* Written by Nate Robins, 1997.
* email: ndr@pobox.com
* www: http://www.pobox.com/~ndr
*/
/* includes */
#include <cmath>
using namespace std;
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "glm.h"
/* Some <math.h> files do not define M_PI... */
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
/* defines */
#define T(x) model->triangles[(x)]
/* enums */
enum { X, Y, Z, W }; /* elements of a vertex */
/* global variables */
/*
GLubyte *_teximage_new;
static int _teximageWidth_new = 1, _teximageHeight_new = 1;
*/
#define MAX_TEXTURES 100
static GLuint textureArray[MAX_TEXTURES] = {0};
/* typedefs */
/* _GLMnode: general purpose node
*/
typedef struct _GLMnode {
GLuint index;
GLboolean averaged;
struct _GLMnode* next;
} GLMnode;
/* strdup is actually not a standard ANSI C or POSIX routine
so implement a private one. OpenVMS does not have a strdup; Linux's
standard libc doesn't declare strdup by default (unless BSD or SVID
interfaces are requested). */
static char *
stralloc(const char *string)
{
char *copy;
copy = (char*) malloc(strlen(string) + 1);
if (copy == NULL)
return NULL;
strcpy(copy, string);
return copy;
}
/* private functions */
/* _glmMax: returns the maximum of two floats */
static GLfloat
_glmMax(GLfloat a, GLfloat b)
{
if (a > b)
return a;
return b;
}
/* _glmAbs: returns the absolute value of a float */
static GLfloat
_glmAbs(GLfloat f)
{
if (f < 0)
return -f;
return f;
}
/* _glmDot: compute the dot product of two vectors
*
* u - array of 3 GLfloats (GLfloat u[3])
* v - array of 3 GLfloats (GLfloat v[3])
*/
static GLfloat
_glmDot(GLfloat* u, GLfloat* v)
{
assert(u);
assert(v);
/* compute the dot product */
return u[X] * v[X] + u[Y] * v[Y] + u[Z] * v[Z];
}
/* _glmCross: compute the cross product of two vectors
*
* u - array of 3 GLfloats (GLfloat u[3])
* v - array of 3 GLfloats (GLfloat v[3])
* n - array of 3 GLfloats (GLfloat n[3]) to return the cross product in
*/
static GLvoid
_glmCross(GLfloat* u, GLfloat* v, GLfloat* n)
{
assert(u);
assert(v);
assert(n);
/* compute the cross product (u x v for right-handed [ccw]) */
n[X] = u[Y] * v[Z] - u[Z] * v[Y];
n[Y] = u[Z] * v[X] - u[X] * v[Z];
n[Z] = u[X] * v[Y] - u[Y] * v[X];
}
/* _glmNormalize: normalize a vector
*
* n - array of 3 GLfloats (GLfloat n[3]) to be normalized
*/
static GLvoid
_glmNormalize(GLfloat* n)
{
GLfloat l;
assert(n);
/* normalize */
l = (GLfloat)sqrt(n[X] * n[X] + n[Y] * n[Y] + n[Z] * n[Z]);
n[0] /= l;
n[1] /= l;
n[2] /= l;
}
/* _glmEqual: compares two vectors and returns GL_TRUE if they are
* equal (within a certain threshold) or GL_FALSE if not. An epsilon
* that works fairly well is 0.000001.
*
* u - array of 3 GLfloats (GLfloat u[3])
* v - array of 3 GLfloats (GLfloat v[3])
*/
static GLboolean
_glmEqual(GLfloat* u, GLfloat* v, GLfloat epsilon)
{
if (_glmAbs(u[0] - v[0]) < epsilon &&
_glmAbs(u[1] - v[1]) < epsilon &&
_glmAbs(u[2] - v[2]) < epsilon)
{
return GL_TRUE;
}
return GL_FALSE;
}
/* _glmWeldVectors: eliminate (weld) vectors that are within an
* epsilon of each other.
*
* vectors - array of GLfloat[3]'s to be welded
* numvectors - number of GLfloat[3]'s in vectors
* epsilon - maximum difference between vectors
*
*/
GLfloat*
_glmWeldVectors(GLfloat* vectors, GLuint* numvectors, GLfloat epsilon)
{
GLfloat* copies;
GLuint copied;
GLuint i, j;
copies = (GLfloat*)malloc(sizeof(GLfloat) * 3 * (*numvectors + 1));
memcpy(copies, vectors, (sizeof(GLfloat) * 3 * (*numvectors + 1)));
copied = 1;
for (i = 1; i <= *numvectors; i++) {
for (j = 1; j <= copied; j++) {
if (_glmEqual(&vectors[3 * i], &copies[3 * j], epsilon)) {
goto duplicate;
}
}
/* must not be any duplicates -- add to the copies array */
copies[3 * copied + 0] = vectors[3 * i + 0];
copies[3 * copied + 1] = vectors[3 * i + 1];
copies[3 * copied + 2] = vectors[3 * i + 2];
j = copied; /* pass this along for below */
copied++;
duplicate:
/* set the first component of this vector to point at the correct
index into the new copies array */
vectors[3 * i + 0] = (GLfloat)j;
}
*numvectors = copied-1;
return copies;
}
/* _glmFindGroup: Find a group in the model
*/
GLMgroup*
_glmFindGroup(GLMmodel* model, char* name)
{
GLMgroup* group;
assert(model);
group = model->groups;
while(group) {
if (!strcmp(name, group->name))
break;
group = group->next;
}
return group;
}
/* _glmAddGroup: Add a group to the model
*/
GLMgroup*
_glmAddGroup(GLMmodel* model, char* name)
{
GLMgroup* group;
group = _glmFindGroup(model, name);
if (!group) {
group = (GLMgroup*)malloc(sizeof(GLMgroup));
group->name = stralloc(name);
group->material = 0;
group->numtriangles = 0;
group->triangles = NULL;
group->next = model->groups;
model->groups = group;
model->numgroups++;
}
return group;
}
/* _glmFindGroup: Find a material in the model
*/
GLuint
_glmFindMaterial(GLMmodel* model, char* name)
{
GLuint i;
for (i = 0; i < model->nummaterials; i++) {
if (!strcmp(model->materials[i].name, name))
goto found;
}
/* didn't find the name, so set it as the default material */
printf("_glmFindMaterial(): can't find material \"%s\".\n", name);
i = 0;
found:
return i;
}
/* _glmDirName: return the directory given a path
*
* path - filesystem path
*
* The return value should be free'd.
*/
static char*
_glmDirName(char* path)
{
char* dir;
char* s;
dir = stralloc(path);
s = strrchr(dir, '/');
if (s)
s[1] = '\0';
else
dir[0] = '\0';
return dir;
}
/* _glmReadBMP: read a BMP texture image file
*
* filename - filename of the BMP texture
*
* return
* whether the BMP is read correctly
*/
/*
int _glmReadBMP(GLuint textureArray[], char* filename, int textureID)
{
// Read the BMP
int h = 0;
int w = 0;
GLubyte* _teximage = ReadBitmapRGB( STLstring2LPCTSTC( string(filename) ), w, h );
if ( !_teximage )
{
printf("Cannot open the BMP texture!!\n");
return 0;
}
static int _teximageWidth=w;
static int _teximageHeight=h;
glGenTextures(1, &textureArray[textureID]);
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, textureArray[textureID]);
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_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, w, h, GL_BGR,
GL_UNSIGNED_BYTE, (GLvoid*)_teximage);
printf("texture %d : %s is loaded\n", textureArray[textureID], filename);
// delete [] _teximage;
return 1;
}*/
/* _glmReadPPM: read a PPM texture image file
*
* filename - filename of the PPM texture
*
* return:
* whether the PPM is read correctly
*/
int _glmReadPPM(GLuint textureArray[], char* filename, int textureID)
{
int h, w, i;
//int no_read;
char buf[200], temp[80];
FILE *fp;
static int _teximageWidth, _teximageHeight;
GLubyte *_teximage;
if ((fp = fopen(filename, "r"))==NULL) {
printf("File cannot open!!\n");
return 0;
/*exit(1);*/
}