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; }