= 48 && inputChar <= 57){ // digit
state = STATE_FACE_VERTEX;
intNumber = inputChar - 48;
}
break;
case STATE_FACE_VERTEX:
switch(inputChar){
case 47: // /
FaceVertices[lastFace] = intNumber - 1;
intNumber = 0;
state = STATE_FACE_TEXTURE;
break;
case 9: // tab
case 32: // space
case 10: // LF
case 13: // CR
FaceVertices[lastFace] = intNumber - 1;
hasNormal = FALSE;
if(++lastFace == FaceVertices.SizeDim1) FaceVertices.SizeDim1 *= 2;
state = --nbOfParameters == 0 ? (state = inputChar == 10 ? STATE_INIT : STATE_COMMENT) : STATE_FACE;
break;
default: // digit
intNumber = intNumber * 10 + inputChar - 48;
}
break;
case STATE_FACE_TEXTURE:
switch(inputChar){
case 47: // /
state = STATE_FACE_NORMAL;
break;
case 9: // tab
case 32: // space
case 10: // LF
case 13: // CR
hasNormal = FALSE;
if(++lastFace == FaceVertices.SizeDim1) FaceVertices.SizeDim1 *= 2;
state = --nbOfParameters == 0 ? (state = inputChar == 10 ? STATE_INIT : STATE_COMMENT) : STATE_FACE;
break;
// numbers are ignored for texture coordinates
}
break;
case STATE_FACE_NORMAL:
switch(inputChar){
case 9: // tab
case 32: // space
case 10: // LF
case 13: // CR
FaceNormals[lastFace] = intNumber - 1;
if(FaceVertices[lastFace] != FaceNormals[lastFace]) unify = TRUE;
if(++lastFace == FaceNormals.SizeDim1) FaceVertices.SizeDim1 = FaceNormals.SizeDim1 *= 2;
state = --nbOfParameters == 0 ? (state = inputChar == 10 ? STATE_INIT : STATE_COMMENT) : STATE_FACE;
break;
default: // digit
intNumber = intNumber * 10 + inputChar - 48;
}
break;
case STATE_POSSIBLE_VERTEX:
if(inputChar == 110) // n - normal if previous v
state = STATE_NORMAL;
else
state = STATE_VERTEX;
nbOfParameters = 3;
sign = 1;
fractNumber = 0;
fractPosition = 0.1;
expNumber = 0;
break;
case STATE_VERTEX:
case STATE_NORMAL:
if(inputChar == 45) // -
sign = -1;
else if(inputChar >= 48 && inputChar <= 57){ // digit
state = state == STATE_VERTEX ? STATE_VERTEX_COORD : STATE_NORMAL_COORD;
intNumber = inputChar - 48;
floatNumberState = INTEGER_PART;
}
break;
case STATE_VERTEX_COORD:
case STATE_NORMAL_COORD:
switch(inputChar){
case 9: // tab
case 32: // space
case 10: // LF
case 13: // CR
// end of coordinate number
// adding number to Vertices or Normals, update indices, resize arrays if necessary
if(state == STATE_VERTEX_COORD){
// vertex
Vertices[lastVertex, 3 - nbOfParameters] = sign * (intNumber + fractNumber) * pow(10, expSign * expNumber);
if(--nbOfParameters == 0){
// last vertex coordinate
if(++lastVertex == Vertices.SizeDim1) Vertices.SizeDim1 *= 2;
state = inputChar == 10 ? STATE_INIT : STATE_COMMENT;
} else {
// continue parsing another coordinate
state = STATE_VERTEX;
sign = 1;
fractNumber = 0;
fractPosition = 0.1;
expNumber = 0;
}
} else {
// normal
Normals[lastNormal, 3 - nbOfParameters] = sign * (intNumber + fractNumber) * pow(10, expSign * expNumber);
if(--nbOfParameters == 0){
// last normal coordinate
if(++lastNormal == Normals.SizeDim1) Normals.SizeDim1 *= 2;
state = state = inputChar == 10 ? STATE_INIT : STATE_COMMENT;
} else {
// continue parsing another coordinate
state = STATE_NORMAL;
sign = 1;
fractNumber = 0;
fractPosition = 0.1;
expNumber = 0;
}
}
break;
default: // parsing floating-point number
switch(floatNumberState){
case INTEGER_PART:
if(inputChar == 46) // .
floatNumberState = FRACTIONAL_PART;
else
intNumber = intNumber * 10 + inputChar - 48; // digit
break;
case FRACTIONAL_PART:
if(inputChar == 69 || inputChar == 101){ // e or E
floatNumberState = EXPONENT_PART;
expSign = 1;
} else {
// digit of fraction part
fractNumber += (inputChar - 48) * fractPosition;
fractPosition /= 10;
}
break;
case EXPONENT_PART:
if(inputChar == 45) // -
expSign = -1;
else
expNumber = expNumber * 10 + inputChar - 48; // digit
break;
}
}
break;
} // end of switch state
} // end looping input char
// SET OpenGL VERTEX BUFFER OBJECTS
if(unify){
// unify vertex and normal arrays
if(lastNormal >= lastVertex){ // this is heuristics, not 100% sure
// reused vertices
// uniform vertex array use size of normals array
VerticesUniform.SizeDim1 = lastNormal;
// copy vertices to uniform vertex array to be aligned with normals
for(int i = 0; i < lastFace; i++){
int a = FaceNormals[i];
int b = FaceVertices[i];
VerticesUniform[a, 0] = Vertices[b, 0];
VerticesUniform[a, 1] = Vertices[b, 1];
VerticesUniform[a, 2] = Vertices[b, 2];
}
// vertices
glBindBuffer(GL_ARRAY_BUFFER, BuferIds[0]);
glBufferData(GL_ARRAY_BUFFER, lastNormal*4*FLOAT_LEN, VerticesUniform, GL_STATIC_DRAW);
// normals
glBindBuffer(GL_ARRAY_BUFFER, BuferIds[1]);
glBufferData(GL_ARRAY_BUFFER, lastNormal*4*FLOAT_LEN, Normals, GL_STATIC_DRAW);
// face index
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, BuferIds[2]); // face vertex index
glBufferData(GL_ELEMENT_ARRAY_BUFFER, lastFace*INT_LEN, FaceNormals, GL_STATIC_DRAW);
} else {
// reused normals
// uniform normal array use size of normals array
NormalsUniform.SizeDim1 = lastVertex;
// copy normals to uniform normalarray to be aligned with vertices
for(int i = 0; i < lastFace; i++){
int a = FaceVertices[i];
int b = FaceNormals[i];
NormalsUniform[a, 0] = Normals[b, 0];
NormalsUniform[a, 1] = Normals[b, 1];
NormalsUniform[a, 2] = Normals[b, 2];
}
// vertices
glBindBuffer(GL_ARRAY_BUFFER, BuferIds[0]);
glBufferData(GL_ARRAY_BUFFER, lastVertex*4*FLOAT_LEN, Vertices, GL_STATIC_DRAW);
// normals
glBindBuffer(GL_ARRAY_BUFFER, BuferIds[1]);
glBufferData(GL_ARRAY_BUFFER, lastVertex*4*FLOAT_LEN, NormalsUniform, GL_STATIC_DRAW);
// face index
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, BuferIds[2]); // face vertex index
glBufferData(GL_ELEMENT_ARRAY_BUFFER, lastFace*INT_LEN, FaceVertices, GL_STATIC_DRAW);
}
} else {
// no unification of vertices and normals necessary
// vertices
glBindBuffer(GL_ARRAY_BUFFER, BuferIds[0]);
glBufferData(GL_ARRAY_BUFFER, lastVertex*4*FLOAT_LEN, Vertices, GL_STATIC_DRAW);
// normals
if(hasNormal){
glBindBuffer(GL_ARRAY_BUFFER, BuferIds[1]);
glBufferData(GL_ARRAY_BUFFER, lastNormal*4*FLOAT_LEN, Normals, GL_STATIC_DRAW);
}
// face index
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, BuferIds[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, lastFace*INT_LEN, FaceVertices, GL_STATIC_DRAW);
}
// COPY TO GLOBALS
NumberOfVertices = lastVertex;
NumberOfFaces = lastFace;
HasNormals = hasNormal;]]>