com.sun.j3d.loaders.lw3d.LwoParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java3d-core Show documentation
Show all versions of java3d-core Show documentation
Java3D Core And Java3D Util Libraries
The newest version!
/*
* Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any
* kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
* EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
* NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
* USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
* ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
* CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
* REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
* INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed, licensed or
* intended for use in the design, construction, operation or
* maintenance of any nuclear facility.
*
*/
package com.sun.j3d.loaders.lw3d;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Vector;
import com.sun.j3d.loaders.IncorrectFormatException;
import com.sun.j3d.loaders.ParsingErrorException;
/**
* This class is responsible for parsing a binary Object file and storing
* the data. This class is not called directly, but is the parent class of
* J3dLwoObject. The subclass calls this class to parse the file, then it
* turns the resulting data into Java3D objects. LwoObject instantiates
* an LWOBFileReader object to parse the data. Then the class creates a
* list of ShapeHolder objects to hold all of the vertex/facet data and
* surface references and creates a list of LwoSurface objects to hold
* the data for each surface.
* Rather than describe in detail how the file is parsed for each method,
* I advise the user of this code to understand the lw3d file format
* specs, which are pretty clear.
*/
class LwoParser extends ParserObject {
LWOBFileReader theReader;
int currLength;
float coordsArray[];
float normalCoordsArray[];
int facetIndicesArray[];
int facetSizesArray[];
int normalIndicesArray[];
int red = 255, green = 255, blue = 255;
float diffuse = 0.0f, specular = 0.0f, transparency = 0.0f, luminosity = 0.0f;
int gloss = 128;
Vector surfNameList = null;
Vector surfaceList = new Vector(200);
Vector shapeList = new Vector(200);
/**
* Constructor: Creates file reader and calls parseFile() to actually
* read the file and grab the data
*/
LwoParser(String fileName, int debugVals)
throws FileNotFoundException {
super(debugVals);
debugOutputLn(TRACE, "parser()");
long start = System.currentTimeMillis();
theReader = new LWOBFileReader(fileName);
debugOutputLn(TIME, " file opened in " +
(System.currentTimeMillis() - start));
parseFile();
}
LwoParser(URL url, int debugVals)
throws FileNotFoundException {
super(debugVals);
debugOutputLn(TRACE, "parser()");
try {
long start = System.currentTimeMillis();
theReader = new LWOBFileReader(url);
debugOutputLn(TIME, " file opened in " +
(System.currentTimeMillis() - start));
}
catch (IOException ex) {
throw new FileNotFoundException(url.toString());
}
parseFile();
}
/**
* Detail polygons are currently not implemented by this loader. Their
* structure in geometry files is a bit complex, so there's this separate
* method for simply parsing through and ignoring the data for detail
* polygons
*/
int skipDetailPolygons(int numPolys) throws ParsingErrorException {
debugOutputLn(TRACE, "skipDetailPolygons(), numPolys = " + numPolys);
int lengthRead = 0;
int vert;
try {
for (int polyNum = 0; polyNum < numPolys; ++polyNum) {
debugOutputLn(VALUES, "polyNum = " + polyNum);
int numVerts = theReader.getShortInt();
theReader.skip(numVerts * 2 + 2); // skip indices plus surf
lengthRead += (numVerts * 2) + 4; // increment counter
}
}
catch (IOException e) {
debugOutputLn(EXCEPTION, "Exception in reading detail polys: " + e);
throw new ParsingErrorException(e.getMessage());
}
return lengthRead;
}
/**
* Returns already-existing ShapeHolder if one exists with the same
* surface and the same geometry type (point, line, or poly)
*/
ShapeHolder getAppropriateShape(int numSurf, int numVerts) {
for (Enumeration e = shapeList.elements();
e.hasMoreElements() ;) {
ShapeHolder shape = (ShapeHolder)e.nextElement();
if (shape.numSurf == numSurf)
if (shape.numVerts == numVerts ||
(shape.numVerts > 3 &&
numVerts > 3))
return shape;
}
return null;
}
/**
* Parse the file for all the data for a POLS object (polygon
* description)
*/
void getPols(int length) {
debugOutputLn(TRACE, "getPols(len), len = " + length);
int vert;
int lengthRead = 0;
int prevNumVerts = -1;
int prevNumSurf = 0;
Vector facetSizesList;
int facetIndicesArray[];
facetSizesList =
new Vector(length/6); // worst case size (every poly one vert)
// Note that our array sizes are hardcoded because we don't
// know until we're done how large they will be
facetIndicesArray = new int[length/2];
ShapeHolder shape = new ShapeHolder(debugPrinter.getValidOutput());
debugOutputLn(VALUES, "new shape = " + shape);
shape.coordsArray = coordsArray;
shape.facetSizesList = facetSizesList;
//shape.facetIndicesList = facetIndicesList;
shape.facetIndicesArray = facetIndicesArray;
shapeList.addElement(shape);
//long startTime = (new Date()).getTime();
boolean firstTime = true;
while (lengthRead < length) {
int numVerts = theReader.getShortInt();
lengthRead += 2;
int intArray[] = new int[numVerts];
for (int i = 0; i < numVerts; ++i) {
intArray[i] = theReader.getShortInt();
lengthRead += 2;
}
int numSurf = theReader.getShortInt();
lengthRead += 2;
long startTimeBuff = 0, startTimeList = 0;
if (!firstTime &&
(numSurf != prevNumSurf ||
((numVerts != prevNumVerts) &&
((prevNumVerts < 3) ||
(numVerts < 3))))) {
// If above true, then start new shape
shape = getAppropriateShape(numSurf, numVerts);
if (shape == null) {
//debugOutputLn(LINE_TRACE, "Starting new shape");
facetSizesList = new Vector(length/6);
facetIndicesArray = new int[length/2];
shape = new ShapeHolder(debugPrinter.getValidOutput());
shape.coordsArray = coordsArray;
shape.facetSizesList = facetSizesList;
//shape.facetIndicesList = facetIndicesList;
shape.facetIndicesArray = facetIndicesArray;
shape.numSurf = numSurf;
shape.numVerts = numVerts;
shapeList.addElement(shape);
}
else {
facetSizesList = shape.facetSizesList;
facetIndicesArray = shape.facetIndicesArray;
}
}
else {
shape.numSurf = numSurf;
shape.numVerts = numVerts;
}
prevNumVerts = numVerts;
prevNumSurf = numSurf;
facetSizesList.addElement(new Integer(numVerts));
int currPtr = 0;
System.arraycopy(intArray, 0,
facetIndicesArray, shape.currentNumIndices,
numVerts);
shape.currentNumIndices += numVerts;
if (numSurf < 0) { // neg number means detail poly
int numPolys = theReader.getShortInt();
lengthRead += skipDetailPolygons(numPolys);
shape.numSurf = ~shape.numSurf & 0xffff;
if (shape.numSurf == 0)
shape.numSurf = 1; // Can't have surface = 0
}
firstTime = false;
}
}
/**
* Parses file to get the names of all surfaces. Each polygon will
* be associated with a particular surface number, which is the index
* number of these names
*/
void getSrfs(int length) {
String surfName = new String();
surfNameList = new Vector(length/2); // worst case size (each name 2 chars long)
int lengthRead = 0;
int stopMarker = theReader.getMarker() + length;
int surfIndex = 0;
while (theReader.getMarker() < stopMarker) {
debugOutputLn(VALUES, "marker, stop = " +
theReader.getMarker() + ", " + stopMarker);
debugOutputLn(LINE_TRACE, "About to call getString");
surfName = theReader.getString();
debugOutputLn(VALUES, "Surfname = " + surfName);
surfNameList.addElement(surfName);
}
}
/**
* Parses file to get all vertices
*/
void getPnts(int length) throws ParsingErrorException {
int numVerts = length / 12;
float x, y, z;
coordsArray = new float[numVerts*3];
theReader.getVerts(coordsArray, numVerts);
}
/**
* Creates new LwoSurface object that parses file and gets all
* surface parameters for a particular surface
*/
void getSurf(int length) throws FileNotFoundException {
debugOutputLn(TRACE, "getSurf()");
// Create LwoSurface object to read and hold each surface, then
// store that surface in a vector of all surfaces.
LwoSurface surf = new LwoSurface(theReader, length,
debugPrinter.getValidOutput());
surfaceList.addElement(surf);
}
/**
* parses entire file.
* return -1 on error or 0 on completion
*/
int parseFile() throws FileNotFoundException, IncorrectFormatException {
debugOutputLn(TRACE, "parseFile()");
int length = 0;
int lengthRead = 0;
int fileLength = 100000;
long loopStartTime = System.currentTimeMillis();
// Every parsing unit begins with a four character string
String tokenString = theReader.getToken();
while (!(tokenString == null) &&
lengthRead < fileLength) {
long startTime = System.currentTimeMillis();
// Based on value of tokenString, go to correct parsing method
length = theReader.getInt();
lengthRead += 4;
//debugOutputLn(VALUES, "length, lengthRead, fileLength = " +
// length + ", " + lengthRead + ", " + fileLength);
//debugOutputLn(VALUES, "LWOB marker is at: " + theReader.getMarker());
if (tokenString.equals("FORM")) {
//debugOutputLn(LINE_TRACE, "got a form");
fileLength = length + 4;
length = 0;
tokenString = theReader.getToken();
lengthRead += 4;
if (!tokenString.equals("LWOB"))
throw new IncorrectFormatException(
"File not of FORM-length-LWOB format");
}
else if (tokenString.equals("PNTS")) {
//debugOutputLn(LINE_TRACE, "PNTS");
getPnts(length);
debugOutputLn(TIME, "done with " + tokenString + " in " +
(System.currentTimeMillis() - startTime));
}
else if (tokenString.equals("POLS")) {
//debugOutputLn(LINE_TRACE, "POLS");
getPols(length);
debugOutputLn(TIME, "done with " + tokenString + " in " +
(System.currentTimeMillis() - startTime));
}
else if (tokenString.equals("SRFS")) {
//debugOutputLn(LINE_TRACE, "SRFS");
getSrfs(length);
debugOutputLn(TIME, "done with " + tokenString + " in " +
(System.currentTimeMillis() - startTime));
}
else if (tokenString.equals("CRVS")) {
//debugOutputLn(LINE_TRACE, "CRVS");
theReader.skipLength(length);
//debugOutputLn(TIME, "done with " + tokenString + " in " +
// (System.currentTimeMillis() - startTime));
}
else if (tokenString.equals("PCHS")) {
//debugOutputLn(LINE_TRACE, "PCHS");
theReader.skipLength(length);
//debugOutputLn(TIME, "done with " + tokenString + " in " +
// (System.currentTimeMillis() - startTime));
}
else if (tokenString.equals("SURF")) {
//debugOutputLn(LINE_TRACE, "SURF");
getSurf(length);
//debugOutputLn(VALUES, "Done with SURF, marker = " + theReader.getMarker());
debugOutputLn(TIME, "done with " + tokenString + " in " +
(System.currentTimeMillis() - startTime));
}
else if (tokenString.equals("LWOB")) {
//debugOutputLn(LINE_TRACE, "LWOB");
}
else {
//debugOutputLn(LINE_TRACE, "Unknown object = " + tokenString);
theReader.skipLength(length);
//debugOutputLn(TIME, "done with " + tokenString + " in " +
// (System.currentTimeMillis() - startTime));
}
lengthRead += length;
if (lengthRead < fileLength) {
//debugOutputLn(VALUES, "end of parseFile, length, lengthRead = " +
// length + ", " + lengthRead);
tokenString = theReader.getToken();
lengthRead += 4;
//debugOutputLn(VALUES, "just got tokenString = " + tokenString);
}
}
debugOutputLn(TIME, "done with parseFile in " +
(System.currentTimeMillis() - loopStartTime));
return 0;
}
/**
* This method is used only for testing
*/
static void main(String[] args) {
String fileName;
if (args.length == 0)
fileName = "cube.obj";
else
fileName = args[0];
try {
LwoParser theParser = new LwoParser(fileName, 0);
}
catch (FileNotFoundException e) {
System.err.println(e.getMessage());
e.printStackTrace();
System.exit(1);
}
}
}