bool slFileObj::ProcessFace(char* inbuf , Shader* curMaterial) { const int maxNumVerts = 256; //Phase 1 : Load vertex data into arrays //This array holds the vertex numbers for //(a) vertices, (b) texture coordinates, (c) vertex normals. long vertNums[3 * maxNumVerts]; //Use -1 for missing values bool missingNormals = false; bool missingTexCoords = false; int i; char* s = inbuf; for (i = 0; i < maxNumVerts + 1; i++) { s = ScanForNonwhite(s); if (s == 0) { break; } if (i >= maxNumVerts) { UnsupportedTooManyVerts(maxNumVerts); return false; } long scannedInt; int scanCode = sscanf(s, "%ld", &scannedInt); if (scanCode == 0) { return false; } //Negative indices refer to counting backwards vertNums[3 * i] = (scannedInt > 0) ? scannedInt : Vertices.Size() + scannedInt; if (vertNums[3 * i] < 1 || vertNums[3 * i] > Vertices.Size()) { return false; } s = ScanForWhiteOrSlash(s); if ((*s) != '/') { vertNums[3 * i + 1] = vertNums[3 * i + 2] = -1; //No texture ///coords or normal /// missingTexCoords = true; missingNormals = true; continue; } if ((*(s + 1)) == '/' || (*(s + 1)) == ' ' || (*(s + 1)) == 0) { vertNums[3 * i + 1] = -1; missingTexCoords = true; } else { scanCode = sscanf(s + 1, "%ld", &scannedInt); if (scanCode == 0) { return false; } //Negative indices refer to counting backwards vertNums[3 * i + 1] = (scannedInt > 0) ? scannedInt : TextureCoords.Size() + scannedInt; if (vertNums[3 * i + 1] < 1 || vertNums[3 * i + 1] > TextureCoords.Size()) { return false; } } s = ScanForWhiteOrSlash(s + 1); if ((*s) != '/') { vertNums[3 * i + 2] = -1; //No normal missingNormals = true; continue; } if ((*(s + 1)) == ' ' || (*(s + 1)) == 0) { vertNums[3 * i + 2] = -1; missingNormals = true; } else { scanCode = sscanf(s + 1, "%ld", vertNums + 3 * i + 2); if (scanCode != 1) { return false; } //Negative indices refer to counting backwards vertNums[3 * i + 2] = (scannedInt > 0) ? scannedInt : VertexNormals.Size() + scannedInt; //XXX TO DO: PUT THIS BACK ONCE NORMALS ARE SCANNED IN! //if (vertNums[3*i+2]<1 || //vertNums[3*i+2]>VertexNormals.Size()) { //return false; //} } s = ScanForWhite(s + 1); } int numVertsInFace = i; if (numVertsInFace < 3) { return false; } //Create the ViewableTriangles //Textures: At the moment, we do not support materials, so it does not //make any sense to support textures and texture coordinates. vec3 vA, vB, vC; //Check for perfect parallolgram first // if (numVertsInFace == 4) { // vec3 vD; // vA.SetFromHg(Vertices[vertNums[0] - 1]); // vB.SetFromHg(Vertices[vertNums[3] - 1]); // vC.SetFromHg(Vertices[vertNums[6] - 1]); // vD.SetFromHg(Vertices[vertNums[9] - 1]); // if ((vD - vA) == (vC - vB) && (vB - vA) == (vC - vD)) { // // //Add parallelogram // ViewableParallelogram* vp = new ViewableParallelogram(); // vp->Init(vA, vB, vC); // ScenePtr->AddViewable(vp); // return true; // } // } //Otherwise, add as (numVertsInFace-2) many triangles. int startIdx = 0; int stepIdx = 1; for (i = 0; i < numVertsInFace - 2; i++) { //Add i-th face of (numVertsInFace-2) total triangles. int idx2 = NextTriVertIdx(startIdx, &stepIdx, numVertsInFace); int idx3 = NextTriVertIdx(idx2, &stepIdx, numVertsInFace); int i1 = vertNums[3 * startIdx] - 1; int i2 = vertNums[3 * idx2] - 1; int i3 = vertNums[3 * idx3] - 1; if (i1 == i2 || i1 == i3 || i2 == i3) { //Format error: duplicated vertex in planar, convex polygon! return false; } else { vA.SetFromHg(Vertices[i1]); vB.SetFromHg(Vertices[i2]); vC.SetFromHg(Vertices[i3]); startIdx = idx3; assert(0 <= idx2 && idx2 < numVertsInFace); assert(0 <= idx3 && idx3 < numVertsInFace); prTriangle* vt = new prTriangle( vA, vB, vC, vec2(0.0,0.0), vec2(0.0,1.0), vec2(1.0,1.0), curMaterial ); ScenePtr->Primitives()->Add(vt); } } return true; }
bool NffFileLoader::Load( const char* filename, SceneDescription& theScene ) { Reset(); ScenePtr = &theScene; FILE* infile = fopen( filename, "r" ); FileLineNumber = 0; if ( !infile ) { fprintf(stderr, "LoadNffFile: Unable to open file: %s\n", filename); return false; } const Material* curMaterial = &Material::Default; // Information for view ("v") command int viewCmdStatus = false; // True if currently handling a "v" command VectorR3 viewPos; VectorR3 lookAtPos; VectorR3 upVector; double fovy; // Field of view angle (in radians) int screenWidth, screenHeight; double hither; char inbuffer[1026]; while ( true ) { if ( !fgets( inbuffer, 1026, infile ) ) { if ( viewCmdStatus ) { SetCameraViewInfo( theScene.GetCameraView(), viewPos, lookAtPos, upVector, fovy, screenWidth, screenHeight, hither ); } fclose( infile ); PrintCmdNotSupportedErrors(stderr); return true; } FileLineNumber++; char *findStart = PreparseNff( inbuffer ); if ( findStart==0 ) { // Ignore if a comment or a blank line if ( viewCmdStatus ) { SetCameraViewInfo( theScene.GetCameraView(), viewPos, lookAtPos, upVector, fovy, screenWidth, screenHeight, hither ); viewCmdStatus = false; } continue; } bool parseErrorOccurred = false; char theCommand[17]; int scanCode = sscanf( inbuffer, "%16s", theCommand ); if ( scanCode!=1 ) { parseErrorOccurred = true; } int cmdNum = GetCommandNumber( theCommand ); if ( cmdNum==-1 ) { AddUnsupportedCmd( theCommand ); continue; } if ( viewCmdStatus && cmdNum<8 ) { SetCameraViewInfo( theScene.GetCameraView(), viewPos, lookAtPos, upVector, fovy, screenWidth, screenHeight, hither ); viewCmdStatus = false; } char* args = ObjFileLoader::ScanForSecondField( findStart ); bool ok = true; switch ( cmdNum ) { case 0: // 'v' command viewCmdStatus = true; break; case 1: // 'b' command - background color { VectorR3 bgColor; scanCode = sscanf( args, "%lf %lf %lf", &(bgColor.x), &(bgColor.y), &(bgColor.z) ); if ( scanCode!=3 ) { ok = false; break; } theScene.SetBackGroundColor( bgColor ); } break; case 2: // 'l' command - positional light { VectorR3 lightPos, lightColor; scanCode = sscanf( args, "%lf %lf %lf %lf %lf %lf", &(lightPos.x), &(lightPos.y), &(lightPos.z), &(lightColor.x), &(lightColor.y), &(lightColor.z) ); if ( scanCode==3 || scanCode==6 ) { Light* aLight = new Light(); aLight->SetPosition( lightPos ); if ( scanCode==6 ) { aLight->SetColor( lightColor ); } theScene.AddLight( aLight ); } else { ok = false; } } break; case 3: // 'f' command - material properties { VectorR3 color; // Material color double Kd, Ks; // Diffuse and specular components double shininess; double transmission; // Transmission coefficient double indexOfRefraction; scanCode = sscanf( args, "%lf %lf %lf %lf %lf %lf %lf %lf", &color.x, &color.y, &color.z, &Kd, &Ks, &shininess, &transmission, &indexOfRefraction ); if ( scanCode==8 ) { Material* mat = new Material(); theScene.AddMaterial( mat ); // theScene can take of deleting this material mat->SetColorAmbientDiffuse( Kd*color ); mat->SetColorSpecular( Ks*color ); mat->SetShininess( shininess ); if ( transmission>0.0 ) { mat->SetColorTransmissive( transmission, transmission, transmission ); mat->SetIndexOfRefraction( indexOfRefraction ); } curMaterial = mat; } else { ok = false; } } break; case 4: // 'c' command - cylinder or cone or truncated cone { VectorR3 baseCenter; VectorR3 topCenter; double baseRadius; double topRadius; scanCode = sscanf( args, "%lf %lf %lf %lf %lf %lf %lf %lf", &baseCenter.x, &baseCenter.y, &baseCenter.z, &baseRadius, &topCenter.x, &topCenter.y, &topCenter.z, &topRadius ); if ( scanCode==8 ) { ProcessConeCylNFF( baseCenter, baseRadius, topCenter, topRadius ); } else { ok = false; } } case 5: // 's' command - sphere { VectorR3 sphereCenter; double radius; scanCode = sscanf( args, "%lf %lf %lf %lf", &sphereCenter.x, &sphereCenter.y, &sphereCenter.z, &radius ); if ( scanCode==4 && radius>0.0 ) { ViewableSphere* vs = new ViewableSphere( sphereCenter, radius, curMaterial ); theScene.AddViewable( vs ); } else { ok = false; } } break; case 7: // 'pp' command - normals will be ignored UnsupportedNormals(); // Fall thru to 'p' command. case 6: // 'p' command { int numVerts; const int maxNumVerts = 256; scanCode = sscanf( args, "%d", &numVerts ); if (scanCode!=1 || numVerts<3 ) { ok = false; } else if ( numVerts>maxNumVerts ) { UnsupportedTooManyVerts( maxNumVerts ); } else { ProcessFaceNFF( numVerts, curMaterial, infile ); } } break; case 8: // 'from' command { scanCode = sscanf( args, "%lf %lf %lf", &(viewPos.x), &(viewPos.y), &(viewPos.z) ); if ( scanCode!=3 || !viewCmdStatus ) { ok = false; viewCmdStatus = false; } break; } case 9: // 'lookat' command { scanCode = sscanf( args, "%lf %lf %lf", &(lookAtPos.x), &(lookAtPos.y), &(lookAtPos.z) ); if ( scanCode!=3 || !viewCmdStatus ) { ok = false; viewCmdStatus = false; } break; } case 10: // 'up' command { scanCode = sscanf( args, "%lf %lf %lf", &(upVector.x), &(upVector.y), &(upVector.z) ); if ( scanCode!=3 || !viewCmdStatus ) { ok = false; viewCmdStatus = false; } break; } case 11: // 'angle' command { scanCode = sscanf( args, "%lf", &fovy ); if ( scanCode!=1 || !viewCmdStatus ) { ok = false; viewCmdStatus = false; } else { fovy *= PI/180.0; // Convert to radians } break; } case 12: // 'hither' command { scanCode = sscanf( args, "%lf", &hither ); if ( scanCode!=1 || !viewCmdStatus ) { ok = false; viewCmdStatus = false; } break; } case 13: // 'resolution' command { scanCode = sscanf( args, "%d %d", &screenWidth, &screenHeight ); if ( scanCode!=2 || !viewCmdStatus ) { ok = false; viewCmdStatus = false; } break; } default: parseErrorOccurred = true; ok = false; break; } if ( !ok ) { fprintf(stderr, "Parse error in NFF file, line %ld: %40s.\n", FileLineNumber, inbuffer ); parseErrorOccurred = true; } } }