bool MA_ParseTVert( idParser &parser, maAttribHeader_t *header ) { maMesh_t *pMesh = &maGlobal.currentObject->mesh; idToken token; //This is not the texture coordinates. It is just the name so ignore it if( strstr( header->name, "uvsn" ) ) { return true; } //Allocate enough space for all the data if( !pMesh->tvertexes ) { pMesh->numTVertexes = header->size; pMesh->tvertexes = ( idVec2 * ) Mem_Alloc( sizeof( idVec2 ) * pMesh->numTVertexes ); } //Get the start and end index for this attribute int minIndex, maxIndex; if( !MA_ParseHeaderIndex( header, minIndex, maxIndex, "TextureCoordHeader", "uvsp" ) ) { //This was just a header return true; } parser.ReadToken( &token ); if( !token.Icmp( "-" ) ) { idToken tk2; parser.ReadToken( &tk2 ); if( !tk2.Icmp( "type" ) ) { parser.SkipUntilString( "float2" ); } else { parser.UnreadToken( &tk2 ); parser.UnreadToken( &token ); } } else { parser.UnreadToken( &token ); } //Read each tvert for( int i = minIndex; i <= maxIndex; i++ ) { pMesh->tvertexes[i].x = parser.ParseFloat(); pMesh->tvertexes[i].y = 1.0f - parser.ParseFloat(); } return true; }
bool MA_ParseNormal(idParser& parser, maAttribHeader_t* header) { maMesh_t* pMesh = &maGlobal.currentObject->mesh; idToken token; //Allocate enough space for all the verts if this is the first attribute for verticies if(!pMesh->normals) { pMesh->numNormals = header->size; pMesh->normals = (idVec3 *)Mem_Alloc( sizeof( idVec3 ) * pMesh->numNormals ); } //Get the start and end index for this attribute int minIndex, maxIndex; if(!MA_ParseHeaderIndex(header, minIndex, maxIndex, "NormalHeader", NULL)) { //This was just a header return true; } parser.ReadToken(&token); if(!token.Icmp("-")) { idToken tk2; parser.ReadToken(&tk2); if(!tk2.Icmp("type")) { parser.SkipUntilString("float3"); } else { parser.UnreadToken(&tk2); parser.UnreadToken(&token); } } else { parser.UnreadToken(&token); } //Read each vert for(int i = minIndex; i <= maxIndex; i++) { pMesh->normals[i].x = parser.ParseFloat(); //Adjust the normals for the change in coordinate systems pMesh->normals[i].z = parser.ParseFloat(); pMesh->normals[i].y = -parser.ParseFloat(); pMesh->normals[i].Normalize(); } pMesh->normalsParsed = true; pMesh->nextNormal = 0; return true; }
bool MA_ParseVertexTransforms(idParser& parser, maAttribHeader_t* header) { maMesh_t* pMesh = &maGlobal.currentObject->mesh; idToken token; //Allocate enough space for all the verts if this is the first attribute for verticies if(!pMesh->vertTransforms) { if(header->size == 0) { header->size = 1; } pMesh->numVertTransforms = header->size; pMesh->vertTransforms = (idVec4 *)Mem_Alloc( sizeof( idVec4 ) * pMesh->numVertTransforms ); pMesh->nextVertTransformIndex = 0; } //Get the start and end index for this attribute int minIndex, maxIndex; if(!MA_ParseHeaderIndex(header, minIndex, maxIndex, "VertexTransformHeader", NULL)) { //This was just a header return true; } parser.ReadToken(&token); if(!token.Icmp("-")) { idToken tk2; parser.ReadToken(&tk2); if(!tk2.Icmp("type")) { parser.SkipUntilString("float3"); } else { parser.UnreadToken(&tk2); parser.UnreadToken(&token); } } else { parser.UnreadToken(&token); } //Read each vert for(int i = minIndex; i <= maxIndex; i++) { pMesh->vertTransforms[pMesh->nextVertTransformIndex].x = parser.ParseFloat(); pMesh->vertTransforms[pMesh->nextVertTransformIndex].z = parser.ParseFloat(); pMesh->vertTransforms[pMesh->nextVertTransformIndex].y = -parser.ParseFloat(); //w hold the vert index pMesh->vertTransforms[pMesh->nextVertTransformIndex].w = i; pMesh->nextVertTransformIndex++; } return true; }
/* ================ idTypeInfoGen::ParseConstantValue ================ */ void idTypeInfoGen::ParseConstantValue( const char *scope, idParser &src, idStr &value ) { idToken token; idStr constantString; int indent = 0; while( src.ReadToken( &token ) ) { if ( token == "(" ) { indent++; } else if ( token == ")" ) { indent--; } else if ( indent == 0 && ( token == ";" || token == "," || token == "}" ) ) { src.UnreadToken( &token ); break; } else if ( token.type == TT_NAME ) { constantString = token; while( src.CheckTokenString( "::" ) ) { src.ExpectTokenType( TT_NAME, 0, &token ); constantString += "::" + token; } value += va( "%d", GetIntegerConstant( scope, constantString, src ) ); continue; } value += token; } }
bool MA_ParseTransform(idParser& parser) { maNodeHeader_t header; maTransform_t* transform; memset(&header, 0, sizeof(header)); //Allocate room for the transform transform = (maTransform_t *)Mem_Alloc( sizeof( maTransform_t ) ); memset(transform, 0, sizeof(maTransform_t)); transform->scale.x = transform->scale.y = transform->scale.z = 1; //Get the header info from the transform MA_ParseNodeHeader(parser, &header); //Read the transform attributes idToken token; while(parser.ReadToken(&token)) { if(IsNodeComplete(token)) { parser.UnreadToken(&token); break; } if(!token.Icmp("setAttr")) { parser.ReadToken(&token); if(!token.Icmp(".t")) { if(!MA_ReadVec3(parser, transform->translate)) { return false; } transform->translate.y *= -1; } else if (!token.Icmp(".r")) { if(!MA_ReadVec3(parser, transform->rotate)) { return false; } } else if (!token.Icmp(".s")) { if(!MA_ReadVec3(parser, transform->scale)) { return false; } } else { parser.SkipRestOfLine(); } } } if(header.parent[0] != 0) { //Find the parent maTransform_t** parent; maGlobal.model->transforms.Get(header.parent, &parent); if(parent) { transform->parent = *parent; } } //Add this transform to the list maGlobal.model->transforms.Set(header.name, transform); return true; }
void MA_ParseFileNode( idParser &parser ) { //Get the header info from the node maNodeHeader_t header; MA_ParseNodeHeader( parser, &header ); //Read the transform attributes idToken token; while( parser.ReadToken( &token ) ) { if( IsNodeComplete( token ) ) { parser.UnreadToken( &token ); break; } if( !token.Icmp( "setAttr" ) ) { maAttribHeader_t attribHeader; MA_ParseAttribHeader( parser, &attribHeader ); if( strstr( attribHeader.name, ".ftn" ) ) { parser.SkipUntilString( "string" ); parser.ReadToken( &token ); if( !token.Icmp( "(" ) ) { parser.ReadToken( &token ); } maFileNode_t *fileNode; fileNode = ( maFileNode_t * ) Mem_Alloc( sizeof( maFileNode_t ) ); strcpy( fileNode->name, header.name ); strcpy( fileNode->path, token.c_str() ); maGlobal.model->fileNodes.Set( fileNode->name, fileNode ); } else { parser.SkipRestOfLine(); } } } }
void MA_ParseMesh(idParser& parser) { maObject_t *object; object = (maObject_t *)Mem_Alloc( sizeof( maObject_t ) ); memset( object, 0, sizeof( maObject_t ) ); maGlobal.model->objects.Append( object ); maGlobal.currentObject = object; object->materialRef = -1; //Get the header info from the mesh maNodeHeader_t header; MA_ParseNodeHeader(parser, &header); //Find my parent if(header.parent[0] != 0) { //Find the parent maTransform_t** parent; maGlobal.model->transforms.Get(header.parent, &parent); if(parent) { maGlobal.currentObject->mesh.transform = *parent; } } strcpy(object->name, header.name); //Read the transform attributes idToken token; while(parser.ReadToken(&token)) { if(IsNodeComplete(token)) { parser.UnreadToken(&token); break; } if(!token.Icmp("setAttr")) { maAttribHeader_t header; MA_ParseAttribHeader(parser, &header); if(strstr(header.name, ".vt")) { MA_ParseVertex(parser, &header); } else if (strstr(header.name, ".ed")) { MA_ParseEdge(parser, &header); } else if (strstr(header.name, ".pt")) { MA_ParseVertexTransforms(parser, &header); } else if (strstr(header.name, ".n")) { MA_ParseNormal(parser, &header); } else if (strstr(header.name, ".fc")) { MA_ParseFace(parser, &header); } else if (strstr(header.name, ".clr")) { MA_ParseColor(parser, &header); } else if (strstr(header.name, ".uvst")) { MA_ParseTVert(parser, &header); } else { parser.SkipRestOfLine(); } } } maMesh_t* pMesh = &maGlobal.currentObject->mesh; //Get the verts from the edge for(int i = 0; i < pMesh->numFaces; i++) { for(int j = 0; j < 3; j++) { int edge = pMesh->faces[i].edge[j]; if(edge < 0) { edge = idMath::Fabs(edge)-1; pMesh->faces[i].vertexNum[j] = pMesh->edges[edge].y; } else { pMesh->faces[i].vertexNum[j] = pMesh->edges[edge].x; } } } //Get the normals if(pMesh->normalsParsed) { for(int i = 0; i < pMesh->numFaces; i++) { for(int j = 0; j < 3; j++) { //Is this vertex shared int sharedFace = -1; int sharedVert = -1; if(MA_QuickIsVertShared(i, j)) { MA_GetSharedFace(i, j, sharedFace, sharedVert); } if(sharedFace != -1) { //Get the normal from the share pMesh->faces[i].vertexNormals[j] = pMesh->faces[sharedFace].vertexNormals[sharedVert]; } else { //The vertex is not shared so get the next normal if(pMesh->nextNormal >= pMesh->numNormals) { //We are using more normals than exist throw idException(va("Maya Loader '%s': Invalid Normals Index.", parser.GetFileName())); } pMesh->faces[i].vertexNormals[j] = pMesh->normals[pMesh->nextNormal]; pMesh->nextNormal++; } } } } //Now that the normals are good...lets reorder the verts to make the tris face the right way for(int i = 0; i < pMesh->numFaces; i++) { int tmp = pMesh->faces[i].vertexNum[1]; pMesh->faces[i].vertexNum[1] = pMesh->faces[i].vertexNum[2]; pMesh->faces[i].vertexNum[2] = tmp; idVec3 tmpVec = pMesh->faces[i].vertexNormals[1]; pMesh->faces[i].vertexNormals[1] = pMesh->faces[i].vertexNormals[2]; pMesh->faces[i].vertexNormals[2] = tmpVec; tmp = pMesh->faces[i].tVertexNum[1]; pMesh->faces[i].tVertexNum[1] = pMesh->faces[i].tVertexNum[2]; pMesh->faces[i].tVertexNum[2] = tmp; tmp = pMesh->faces[i].vertexColors[1]; pMesh->faces[i].vertexColors[1] = pMesh->faces[i].vertexColors[2]; pMesh->faces[i].vertexColors[2] = tmp; } //Now apply the pt transformations for(int i = 0; i < pMesh->numVertTransforms; i++) { pMesh->vertexes[(int)pMesh->vertTransforms[i].w] += pMesh->vertTransforms[i].ToVec3(); } MA_VERBOSE((va("MESH %s - parent %s\n", header.name, header.parent))); MA_VERBOSE((va("\tverts:%d\n",maGlobal.currentObject->mesh.numVertexes))); MA_VERBOSE((va("\tfaces:%d\n",maGlobal.currentObject->mesh.numFaces))); }
bool MA_ParseFace(idParser& parser, maAttribHeader_t* header) { maMesh_t* pMesh = &maGlobal.currentObject->mesh; idToken token; //Allocate enough space for all the verts if this is the first attribute for verticies if(!pMesh->faces) { pMesh->numFaces = header->size; pMesh->faces = (maFace_t *)Mem_Alloc( sizeof( maFace_t ) * pMesh->numFaces ); } //Get the start and end index for this attribute int minIndex, maxIndex; if(!MA_ParseHeaderIndex(header, minIndex, maxIndex, "FaceHeader", NULL)) { //This was just a header return true; } //Read the face data int currentFace = minIndex-1; while(parser.ReadToken(&token)) { if(IsNodeComplete(token)) { parser.UnreadToken(&token); break; } if(!token.Icmp("f")) { int count = parser.ParseInt(); if(count != 3) { throw idException(va("Maya Loader '%s': Face is not a triangle.", parser.GetFileName())); } //Increment the face number because a new face always starts with an "f" token currentFace++; //We cannot reorder edges until later because the normal processing //assumes the edges are in the original order pMesh->faces[currentFace].edge[0] = parser.ParseInt(); pMesh->faces[currentFace].edge[1] = parser.ParseInt(); pMesh->faces[currentFace].edge[2] = parser.ParseInt(); //Some more init stuff pMesh->faces[currentFace].vertexColors[0] = pMesh->faces[currentFace].vertexColors[1] = pMesh->faces[currentFace].vertexColors[2] = -1; } else if(!token.Icmp("mu")) { /* int uvstIndex = */ parser.ParseInt(); int count = parser.ParseInt(); if(count != 3) { throw idException(va("Maya Loader '%s': Invalid texture coordinates.", parser.GetFileName())); } pMesh->faces[currentFace].tVertexNum[0] = parser.ParseInt(); pMesh->faces[currentFace].tVertexNum[1] = parser.ParseInt(); pMesh->faces[currentFace].tVertexNum[2] = parser.ParseInt(); } else if(!token.Icmp("mf")) { int count = parser.ParseInt(); if(count != 3) { throw idException(va("Maya Loader '%s': Invalid texture coordinates.", parser.GetFileName())); } pMesh->faces[currentFace].tVertexNum[0] = parser.ParseInt(); pMesh->faces[currentFace].tVertexNum[1] = parser.ParseInt(); pMesh->faces[currentFace].tVertexNum[2] = parser.ParseInt(); } else if(!token.Icmp("fc")) { int count = parser.ParseInt(); if(count != 3) { throw idException(va("Maya Loader '%s': Invalid vertex color.", parser.GetFileName())); } pMesh->faces[currentFace].vertexColors[0] = parser.ParseInt(); pMesh->faces[currentFace].vertexColors[1] = parser.ParseInt(); pMesh->faces[currentFace].vertexColors[2] = parser.ParseInt(); } } return true; }
/* ================ idTypeInfoGen::ParseScope ================ */ void idTypeInfoGen::ParseScope( const char *scope, bool isTemplate, idParser &src, idClassTypeInfo *typeInfo ) { int indent; idToken token; idClassTypeInfo *classInfo; idEnumTypeInfo *enumInfo; idStr varType; bool isConst = false; bool isStatic = false; indent = 1; while( indent ) { if ( !src.ReadToken( &token ) ) { break; } if ( token == "{" ) { do { if ( token == "{" ) { indent++; } else if ( token == "}" ) { indent--; } varType += token + " "; } while( indent > 1 && src.ReadToken( &token ) ); } else if ( token == "}" ) { assert( indent == 1 ); indent--; } else if ( token == "<" ) { do { if ( token == "<" ) { indent++; } else if ( token == ">" ) { indent--; } varType += token + " "; } while( indent > 1 && src.ReadToken( &token ) ); } else if ( token == ";" ) { varType = ""; isConst = false; isStatic = false; } else if ( token == "public" || token == "protected" || token == "private" ) { if ( !src.ExpectTokenString( ":" ) ) { break; } varType = ""; isConst = false; isStatic = false; } else if ( token == "friend" ) { // skip friend classes/methods while( src.ReadToken( &token ) ) { if ( token == "{" ) { indent++; } else if ( token == "}" ) { indent--; if ( indent == 1 ) { break; } } else if ( token == ";" && indent == 1 ) { break; } } varType = ""; isConst = false; isStatic = false; } else if ( token == "template" ) { varType = ""; if ( src.CheckTokenString( "<" ) ) { int indent = 1; varType += "< "; while( src.ReadToken( &token ) ) { if ( token == "<" ) { indent++; } else if ( token == ">" ) { indent--; if ( indent == 0 ) { break; } } varType += token + " "; } varType += ">"; } if ( src.CheckTokenString( "class" ) ) { // parse template class classInfo = ParseClassType( scope, varType, true, false, src ); if ( classInfo ) { classes.Append( classInfo ); } } else { // skip template methods while( src.ReadToken( &token ) ) { if ( token == "{" ) { indent++; } else if ( token == "}" ) { indent--; if ( indent == 1 ) { break; } } else if ( token == ";" && indent == 1 ) { break; } } } varType = ""; isConst = false; isStatic = false; } else if ( token == "namespace" ) { // parse namespace classInfo = ParseClassType( scope, "", isTemplate, false, src ); delete classInfo; } else if ( token == "class" ) { // parse class classInfo = ParseClassType( scope, "", isTemplate, false, src ); if ( classInfo ) { classes.Append( classInfo ); } } else if ( token == "struct" ) { // parse struct classInfo = ParseClassType( scope, "", isTemplate, false, src ); if ( classInfo ) { classes.Append( classInfo ); varType = classInfo->scope + classInfo->typeName; } } else if ( token == "union" ) { // parse union classInfo = ParseClassType( scope, "", isTemplate, false, src ); if ( classInfo ) { classes.Append( classInfo ); } } else if ( token == "enum" ) { // parse enum enumInfo = ParseEnumType( scope, isTemplate, false, src ); if ( enumInfo ) { enums.Append( enumInfo ); varType = enumInfo->scope + enumInfo->typeName; } } else if ( token == "typedef" ) { if ( token == "class" ) { // parse typedef class classInfo = ParseClassType( scope, "", isTemplate, true, src ); if ( classInfo ) { classes.Append( classInfo ); } } else if ( src.CheckTokenString( "struct" ) ) { // parse typedef struct classInfo = ParseClassType( scope, "", isTemplate, true, src ); if ( classInfo ) { classes.Append( classInfo ); } } else if ( src.CheckTokenString( "union" ) ) { // parse typedef union classInfo = ParseClassType( scope, "", isTemplate, true, src ); if ( classInfo ) { classes.Append( classInfo ); } } else if ( src.CheckTokenString( "enum" ) ) { // parse typedef enum enumInfo = ParseEnumType( scope, isTemplate, true, src ); if ( enumInfo ) { enums.Append( enumInfo ); } } else { // skip other typedefs while( src.ReadToken( &token ) ) { if ( token == "{" ) { indent++; } else if ( token == "}" ) { indent--; } else if ( token == ";" && indent == 1 ) { break; } } } varType = ""; isConst = false; isStatic = false; } else if ( token == "const" ) { varType += token + " "; isConst = true; } else if ( token == "static" ) { varType += token + " "; isStatic = true; } else if ( token.type == TT_NAME ) { assert( indent == 1 ); // if this is a class operator if ( token == "operator" ) { while( src.ReadToken( &token ) ) { if ( token == "(" ) { src.UnreadToken( &token ); break; } } } // if this is a class method if ( src.CheckTokenString( "(" ) ) { indent++; while( indent > 1 && src.ReadToken( &token ) ) { if ( token == "(" ) { indent++; } else if ( token == ")" ) { indent--; } } if ( src.CheckTokenString( "(" ) ) { indent++; while( indent > 1 && src.ReadToken( &token ) ) { if ( token == "(" ) { indent++; } else if ( token == ")" ) { indent--; } } } if ( src.CheckTokenString( "const" ) ) { } if ( src.CheckTokenString( "=" ) ) { src.ExpectTokenString( "0" ); } else if ( src.CheckTokenString( "{" ) ) { indent++; while( indent > 1 && src.ReadToken( &token ) ) { if ( token == "{" ) { indent++; } else if ( token == "}" ) { indent--; } } } varType = ""; isConst = false; isStatic = false; } else if ( ( isStatic || isConst ) && src.CheckTokenString( "=" ) ) { // constant idConstantInfo *constantInfo = new idConstantInfo; constantInfo->name = scope + token; constantInfo->type = varType; constantInfo->type.StripTrailing( ' ' ); ParseConstantValue( scope, src, constantInfo->value ); constants.Append( constantInfo ); } else if ( isStatic ) { // static class variable varType += token + " "; } else { // check for class variables while( 1 ) { int arraySize = ParseArraySize( scope, src ); if ( arraySize ) { idClassVariableInfo var; var.name = token; var.type = varType; var.type.StripTrailing( ' ' ); var.type += va( "[%d]", arraySize ); var.bits = 0; typeInfo->variables.Append( var ); if ( !src.CheckTokenString( "," ) ) { varType = ""; isConst = false; isStatic = false; break; } varType.StripTrailing( "* " ); } else { int bits = 0; if ( src.CheckTokenString( ":" ) ) { idToken bitSize; src.ExpectTokenType( TT_NUMBER, TT_INTEGER, &bitSize ); bits = bitSize.GetIntValue(); } if ( src.CheckTokenString( "," ) ) { idClassVariableInfo var; var.name = token; var.type = varType; var.type.StripTrailing( ' ' ); var.bits = bits; typeInfo->variables.Append( var ); varType.StripTrailing( "* " ); } else if ( src.CheckTokenString( ";" ) ) { idClassVariableInfo var; var.name = token; var.type = varType; var.type.StripTrailing( ' ' ); var.bits = bits; typeInfo->variables.Append( var ); varType = ""; isConst = false; isStatic = false; break; } else { varType += token + " "; break; } } while( src.CheckTokenString( "*" ) ) { varType += "* "; } if ( !src.ExpectTokenType( TT_NAME, 0, &token ) ) { break; } } } } else { varType += token + " "; } } }