public void loadBuffers() { SurfCell curSurf; // the current surface being worked with PolyCell curPoly; // the current polygon in the surface VertListCell curVertLC; curSurf = surfHead; int vertCount; while (curSurf != null) { int vertsPerPrim; vertCount = 0; curPoly = curSurf.polyHead; // vertCount += curPoly.numVerts; vertsPerPrim = curPoly.numVerts; while (curPoly != null) { vertCount += curPoly.numVerts; if (curPoly.numVerts != vertsPerPrim) { System.out.printf("Surface %s: Unequal number of vertices ", curSurf.name); System.out.printf( "\n First prim had %d Cur Prim has %d\n", curPoly.numVerts, vertsPerPrim); return; } curPoly = curPoly.next; } curSurf.numVerts = vertCount; float vertices[] = new float[vertCount * 3]; int vInd = 0; float normals[] = new float[vertCount * 3]; int nInd = 0; curPoly = curSurf.polyHead; while (curPoly != null) { curVertLC = curPoly.vert; while (curVertLC != null) { // for(int i = 0; i < curPoly.numVerts; i++);{ VertCell curVert = vertArray.get(curVertLC.vert); vertices[vInd++] = (float) curVert.worldPos.x; vertices[vInd++] = (float) curVert.worldPos.y; vertices[vInd++] = (float) curVert.worldPos.z; normals[nInd++] = (float) vertNormArray[curVertLC.vert].x; normals[nInd++] = (float) vertNormArray[curVertLC.vert].y; normals[nInd++] = (float) vertNormArray[curVertLC.vert].z; curVertLC = curVertLC.next; } curPoly = curPoly.next; } // now put vertices and normals into VertexArray or Buffer curSurf.vertexBuffer = Buffers.newDirectFloatBuffer(vertices.length); curSurf.vertexBuffer.put(vertices); curSurf.vertexBuffer.rewind(); curSurf.normalBuffer = Buffers.newDirectFloatBuffer(normals.length); curSurf.normalBuffer.put(normals); curSurf.normalBuffer.rewind(); curSurf = curSurf.next; } }
private void addPolyToSurf(SurfCell curSurf, String line, boolean inSmooth) { int curIndex = 0; StringTokenizer tokens; StringTokenizer vertTokens; PolyCell curPoly; PolyListCell curVertPoly; VertListCell curVert; tokens = new StringTokenizer(line); line = tokens.nextToken(); // "eat" up the f at the beginning of the line if (curSurf.polyHead == null) // This is the first polygon in the surface { curSurf.polyHead = new PolyCell(); curPoly = curSurf.polyHead; } else // Other polygons are already in the surface { curPoly = curSurf.polyHead; // Begin at the first polygon while (curPoly.next != null) // Move to the next polygon as long as it exists curPoly = curPoly.next; curPoly.next = new PolyCell(); // Create a new polygon at the end of the list curPoly = curPoly.next; } curPoly.numVerts = 0; // At this point, we are dealing with an entirely new polygon! curPoly.parentSurf = curSurf; while (tokens .hasMoreTokens()) // Loop for constructing an entire polygon...one vertex at a time! { line = tokens.nextToken(); vertTokens = new StringTokenizer(line, "/"); // A tokenizer separated by '/' curIndex = Integer.parseInt(vertTokens.nextToken()); // Grab the first number (a vertex index) if (curPoly.vert == null) // This is our first vertex in the polygon { curPoly.vert = new VertListCell(); curVert = curPoly.vert; } else // Other vertices have already been added { curVert = curPoly.vert; while (curVert.next != null) curVert = curVert.next; curVert.next = new VertListCell(); curVert = curVert.next; } // NOTE: copying of vertices should not be necessary since each surface is drawn by itself and // * each surface will either be drawn smoothed or flat and either way the correct normal will // be // * set and used for each polygon - if a surface is flat no vertex normals will be calculated // - could // * still be a problem if indeed vertices are reused in smoothed surfaces but that is // apparently not true?? //////// All wrong - vertex normals are not recalculated at draw time so any vertex can NOT be // in ////////// multiple surfaces ////// CHECK for vertex copy here // if inSmooth then go ahead and setup the vertex references without regard to // what is in vertexUsedArray // if !inSmooth then this is a one poly surface and if the vertex has already been // used (as indicated in vertexUsedArray then a new copy of the vertex must be made if (!inSmooth) { // we are in an unsmoothed surface [often a one poly surface] -check to see // if vertex(curIndex-1) has // already been used in another surface if (curIndex <= vertUsedArray.size() && vertUsedArray.get(curIndex - 1) != null) { // make a copy of the vertex that curIndex-1 indicates vertArray.add(numVerts, new VertCell(vertArray.get(curIndex - 1))); // vertNormArray.add(numNorms++, new Double3D(vertNormArray.get(curIndex-1))); vertUsedArray.add(numVerts++, curSurf); curIndex = numVerts; } } else if (vertUsedArray.get(curIndex - 1) != null && vertUsedArray.get(curIndex - 1) != curSurf) { // we are in a smoothing group // but this vertex has already been used in another surface // so find out if there is already a copy in this surface int copyIndex = findCopyInSurf(curSurf, vertArray.get(curIndex - 1).worldPos); if (copyIndex == -1) { // make a copy of the vertex that curIndex-1 indicates vertArray.add(numVerts, new VertCell(vertArray.get(curIndex - 1))); // vertNormArray.add(numNorms++, new Double3D(vertNormArray.get(curIndex-1))); vertUsedArray.add(numVerts++, curSurf); curIndex = numVerts; } else { curIndex = copyIndex + 1; } } curVert.vert = curIndex - 1; // Assign the vertex index // curPoly.numVerts++; vertUsedArray.set(curIndex - 1, curSurf); /* * If we are not in a smoothing group at the moment do not build the * linked list specifying polygon membership for the vertex - when normals * are calculated any vertex with no list will be assumed to be part of a * polygon which is to be flat shaded and the polygon normal will be used * for the vertex normals of each vertex. */ if (inSmooth) { if (vertArray.get(curIndex - 1).polys == null) { vertArray.get(curIndex - 1).polys = new PolyListCell(); curVertPoly = vertArray.get(curIndex - 1).polys; } else { curVertPoly = vertArray.get(curIndex - 1).polys; while (curVertPoly.next != null) curVertPoly = curVertPoly.next; curVertPoly.next = new PolyListCell(); curVertPoly = curVertPoly.next; } curVertPoly.poly = curPoly; } else vertArray.get(curIndex - 1).polys = null; curIndex = line.indexOf('/'); // Find the first '/' if it exists if (curIndex > -1) { if (line.charAt(curIndex + 1) != '/') { curIndex = Integer.parseInt(vertTokens.nextToken()); // Grab the texture vertex index curVert.tex = curIndex - 1; } // end check for second / ////////////////////////////////////////////////////////////////////////////////////////////// } // end check for ANY /'s } // end while } // end method addPolyToSurf
private void readSurfaces(String filepath) { // System.out.println("\nBuilding surfaces..."); // This method is the last to be called out of all of the methods in this class. Once all // of the vertex information has been read in, as well as the materials, they are arranged // into the surfaces and polygons that form that object itself...See the included file // CustomOBJSpecs.txt for more details int curMat = 0; // this is a reference to the current material to be used // int curIndex = 0; //This is a temporary variable for reading in vertices of polygons SurfCell curSurf; // the current surface being worked with // PolyCell curPoly; //the current polygon in the surface String matName; // This is the material name from the obj file. It will be used to find the // material in the list String line; // the current line being analyzed StringTokenizer token; // For tokenizing the string to grab the different components of the line // StringTokenizer vertTokens; //For tokenizing the vertex entries in a polygon (surface) line FileReader fr; // Just a file reading stream for the file BufferedReader objFile; // this wraps around the file reader so we can do things like readLine() boolean inSmooth = false; // a flag for whether or not a given face is in a surface try { fr = new FileReader(filepath); objFile = new BufferedReader(fr); line = objFile.readLine(); curSurf = surfHead; while (line != null) { if (line.length() > 0) { switch (line.charAt(0)) { case '#': case '!': case '$': case '\n': case 'v': // These are all comments or vertex info...skip them :-) break; case 'u': token = new StringTokenizer(line); line = token.nextToken(); // "eat" up the usemtl keyword matName = token.nextToken(); // actually grab the material name boolean found = false; int i = 0; while (!found && i < numMats) // for(int i = 0; i < numMats; i++) { // simply compare the stored material name to the name retrieved from the OBJ file. // if they match, set curMat to whatever index that material is at if (materials[i].materialName.toUpperCase().compareTo(matName.toUpperCase()) == 0) { curMat = i; // Set curMat to the current material index found = true; } i++; } if (!found) { System.out.printf( "Group %s material %s not found - using default\n", curSurf.name, matName); curSurf.material = 0; } else curSurf.material = curMat; break; case 's': token = new StringTokenizer(line); line = token.nextToken(); // "eat" up the s at the beginning of the line // If there are more tokens on the line (specifically, the word "off") // then we will read them in. The only one that we really care about is if it's // an "off" but it must be read if it's there. if (token.hasMoreTokens()) line = token.nextToken(); // if smooth groups are turned off and no new smooth group is specified... if (line.toUpperCase().compareTo("OFF") == 0) { inSmooth = false; } else // We are simply starting a new smooth group { inSmooth = true; // curSurf.smooth = inSmooth; } // end else break; case 'f': if (curSurf != null) { addPolyToSurf(curSurf, line, inSmooth); } else // no active surface - create a "default" surface and add this poly to it { System.out.printf("ReadSurfaces: No active surface available\n"); System.out.printf("Creating a default surface\n"); if (inSmooth) surfHead = new SurfCell("default"); else surfHead = new SurfCell("default"); curSurf = surfHead; addPolyToSurf(curSurf, line, inSmooth); } curSurf.numPoly++; // Surface level count of the polygons numPolys++; // PMesh level count of the polygons break; case 'g': // Starts a new surface - if inSmooth is true set the smooth flag in // that surface token = new StringTokenizer(line); line = token.nextToken(); // "eat" up the g at the beginning of the line // If there are more tokens on the line (specifically a group name) // then we will read it in. if (token.hasMoreTokens()) line = token.nextToken(); if (line == null) line = new String("Group" + numSurf); if (surfHead == null) // Create first surface { surfHead = new SurfCell(line); curSurf = surfHead; } else // Advance to next surface { curSurf.next = new SurfCell(line); curSurf = curSurf.next; } // Assign beginning variables numSurf++; // PMesh level count of surfaces break; default: break; } // end switch } // end if(line.length() > 0) line = objFile.readLine(); // grab the next line for reading } // end while(line != null) objFile.close(); fr.close(); } // end try catch (IOException exception) { System.out.println("Error while reading surface data from: " + filepath); } // end catch System.out.printf("\n %d vertices %d surfaces\n", numVerts, numSurf); // System.out.println("\n" + numSurf + " surfaces found"); } // end method readSurfaces