bool MA_ReadVec3(idParser& parser, idVec3& vec) { idToken token; if(!parser.SkipUntilString("double3")) { throw idException( va("Maya Loader '%s': Invalid Vec3", parser.GetFileName()) ); } //We need to flip y and z because of the maya coordinate system vec.x = parser.ParseFloat(); vec.z = parser.ParseFloat(); vec.y = parser.ParseFloat(); return true; }
bool MA_ParseConnectAttr(idParser& parser) { idStr temp; idStr srcName; idStr srcType; idStr destName; idStr destType; idToken token; parser.ReadToken(&token); temp = token; int dot = temp.Find("."); if(dot == -1) { throw idException(va("Maya Loader '%s': Invalid Connect Attribute.", parser.GetFileName())); } srcName = temp.Left(dot); srcType = temp.Right(temp.Length()-dot-1); parser.ReadToken(&token); temp = token; dot = temp.Find("."); if(dot == -1) { throw idException(va("Maya Loader '%s': Invalid Connect Attribute.", parser.GetFileName())); } destName = temp.Left(dot); destType = temp.Right(temp.Length()-dot-1); if(srcType.Find("oc") != -1) { //Is this attribute a material node attribute maMaterialNode_t** matNode; maGlobal.model->materialNodes.Get(srcName, &matNode); if(matNode) { maMaterialNode_t** destNode; maGlobal.model->materialNodes.Get(destName, &destNode); if(destNode) { (*destNode)->child = *matNode; } } //Is this attribute a file node maFileNode_t** fileNode; maGlobal.model->fileNodes.Get(srcName, &fileNode); if(fileNode) { maMaterialNode_t** destNode; maGlobal.model->materialNodes.Get(destName, &destNode); if(destNode) { (*destNode)->file = *fileNode; } } } if(srcType.Find("iog") != -1) { //Is this an attribute for one of our meshes for(int i = 0; i < maGlobal.model->objects.Num(); i++) { if(!strcmp(maGlobal.model->objects[i]->name, srcName)) { //maGlobal.model->objects[i]->materialRef = MA_AddMaterial(destName); strcpy(maGlobal.model->objects[i]->materialName, destName); break; } } } return true; }
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; }
/* ================== idCommonLocal::Error ================== */ void idCommonLocal::Error( const char *fmt, ... ) { va_list argptr; static int lastErrorTime; static int errorCount; int currentTime; errorParm_t code = ERP_DROP; // always turn this off after an error com_refreshOnPrint = false; if ( com_productionMode.GetInteger() == 3 ) { Sys_Quit(); } // when we are running automated scripts, make sure we // know if anything failed if ( cvarSystem->GetCVarInteger( "fs_copyfiles" ) ) { code = ERP_FATAL; } // if we don't have GL running, make it a fatal error if ( !renderSystem->IsOpenGLRunning() ) { code = ERP_FATAL; } // if we got a recursive error, make it fatal if ( com_errorEntered ) { // if we are recursively erroring while exiting // from a fatal error, just kill the entire // process immediately, which will prevent a // full screen rendering window covering the // error dialog if ( com_errorEntered == ERP_FATAL ) { Sys_Quit(); } code = ERP_FATAL; } // if we are getting a solid stream of ERP_DROP, do an ERP_FATAL currentTime = Sys_Milliseconds(); if ( currentTime - lastErrorTime < 100 ) { if ( ++errorCount > 3 ) { code = ERP_FATAL; } } else { errorCount = 0; } lastErrorTime = currentTime; com_errorEntered = code; va_start (argptr,fmt); idStr::vsnPrintf( errorMessage, sizeof(errorMessage), fmt, argptr ); va_end (argptr); errorMessage[sizeof(errorMessage)-1] = '\0'; // copy the error message to the clip board Sys_SetClipboardData( errorMessage ); // add the message to the error list errorList.AddUnique( errorMessage ); Stop(); if ( code == ERP_DISCONNECT ) { com_errorEntered = ERP_NONE; throw idException( errorMessage ); } else if ( code == ERP_DROP ) { Printf( "********************\nERROR: %s\n********************\n", errorMessage ); com_errorEntered = ERP_NONE; throw idException( errorMessage ); } else { Printf( "********************\nERROR: %s\n********************\n", errorMessage ); } if ( cvarSystem->GetCVarBool( "r_fullscreen" ) ) { cmdSystem->BufferCommandText( CMD_EXEC_NOW, "vid_restart partial windowed\n" ); } Sys_Error( "%s", errorMessage ); }