aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ardor3d-examples/src/main/java/com/ardor3d/example/pipeline/SimpleOffExample.java2
-rw-r--r--ardor3d-extras/src/main/java/com/ardor3d/extension/model/off/OffImporter.java229
2 files changed, 182 insertions, 49 deletions
diff --git a/ardor3d-examples/src/main/java/com/ardor3d/example/pipeline/SimpleOffExample.java b/ardor3d-examples/src/main/java/com/ardor3d/example/pipeline/SimpleOffExample.java
index 46e0c29..c8b3f19 100644
--- a/ardor3d-examples/src/main/java/com/ardor3d/example/pipeline/SimpleOffExample.java
+++ b/ardor3d-examples/src/main/java/com/ardor3d/example/pipeline/SimpleOffExample.java
@@ -36,7 +36,7 @@ public class SimpleOffExample extends ExampleBase {
// Load the OFF scene
final long time = System.currentTimeMillis();
final OffImporter importer = new OffImporter();
- final OffGeometryStore storage = importer.load("off/toilet.off");
+ final OffGeometryStore storage = importer.load("off/cube.off");
System.out.println("Importing Took " + (System.currentTimeMillis() - time) + " ms");
final Node model = storage.getScene();
diff --git a/ardor3d-extras/src/main/java/com/ardor3d/extension/model/off/OffImporter.java b/ardor3d-extras/src/main/java/com/ardor3d/extension/model/off/OffImporter.java
index 10d837a..944cdeb 100644
--- a/ardor3d-extras/src/main/java/com/ardor3d/extension/model/off/OffImporter.java
+++ b/ardor3d-extras/src/main/java/com/ardor3d/extension/model/off/OffImporter.java
@@ -25,6 +25,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
+import java.util.stream.Stream;
import com.ardor3d.math.ColorRGBA;
import com.ardor3d.math.Vector2;
@@ -46,68 +47,142 @@ import com.ardor3d.util.resource.ResourceSource;
*/
public class OffImporter {
+ private enum OffKeywordVertexDataComponentId {
+ /**
+ * color
+ */
+ COLOR("C"),
+ /**
+ * normal
+ */
+ NORMAL("N"),
+ /**
+ * texture
+ */
+ TEXTURE("ST");
+
+ private final String keywordText;
+
+ private OffKeywordVertexDataComponentId(final String keywordText) {
+ this.keywordText = keywordText;
+ }
+
+ public String getKeywordText() {
+ return keywordText;
+ }
+ }
+
+ static {
+ // TODO use OffKeywordVertexDataComponentId to generate all possible combinations with OFF and 4OFF
+ for (final String componentId0 : Stream.concat(Stream.of(" "), Arrays
+ .stream(OffKeywordVertexDataComponentId.values()).map(OffKeywordVertexDataComponentId::getKeywordText))
+ .toArray(String[]::new)) {
+ for (final String componentId1 : Stream
+ .concat(Stream.of(" "), Arrays.stream(OffKeywordVertexDataComponentId.values())
+ .map(OffKeywordVertexDataComponentId::getKeywordText))
+ .toArray(String[]::new)) {
+ for (final String componentId2 : Stream
+ .concat(Stream.of(" "), Arrays.stream(OffKeywordVertexDataComponentId.values())
+ .map(OffKeywordVertexDataComponentId::getKeywordText))
+ .toArray(String[]::new)) {
+ // FIXME
+ if (!componentId0.equals(componentId1) && !componentId1.equals(componentId2)
+ && !componentId0.equals(componentId2)) {
+ for (final String offWithoutOrWithDim : new String[] { "OFF", "4OFF" }) {
+ System.out.println(
+ "_" + componentId0 + componentId1 + componentId2 + offWithoutOrWithDim + ",");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * The off keyword indicates which data is available for each vertex except vertex coordinates which are mandatory
+ */
private enum OffKeyword {
/**
- *
+ * colors + normals
*/
- _OFF("off", 3, 0, 0, 0),
+ _CNOFF(),
/**
- *
+ * colors + normals
*/
- _COFF("coff", 3, 0, 4, 0),
+ _CN4OFF(),
/**
- *
+ * colors
*/
- _CNOFF("cnoff", 3, 3, 4, 0),
+ _COFF(),
/**
- *
+ * colors
*/
- _NOFF("noff", 3, 3, 0, 0),
+ _C4OFF(),
/**
- *
- */
- _STCOFF("coff", 3, 0, 4, 2),
+ * normals
+ */
+ _NOFF(),
/**
- *
- */
- _STCNOFF("cnoff", 3, 3, 4, 2),
+ * normals + colors
+ */
+ _NCOFF(),
/**
- *
- */
- _STNOFF("noff", 3, 3, 0, 2),
+ * normals
+ */
+ _N4OFF(),
/**
*
*/
- _4OFF("4off", 4, 0, 0, 0),
+ _OFF(),
/**
- *
+ * texture coordinates + colors + normals
*/
- _C4OFF("c4off", 4, 0, 4, 0),
+ _STCNOFF(),
/**
- *
+ * texture coordinates + colors + normals
*/
- _CN4OFF("cn4off", 4, 4, 4, 0),
+ _STCN4OFF(),
/**
- *
+ * texture coordinates + colors
+ */
+ _STCOFF(),
+ /**
+ * texture coordinates + colors
*/
- _N4OFF("n4off", 4, 4, 0, 0),
+ _STC4OFF(),
/**
- *
- */
- _STC4OFF("c4off", 4, 0, 4, 2),
+ * texture coordinates + normals + colors
+ */
+ _STNCOFF(),
+ /**
+ * texture coordinates + normals + colors
+ */
+ _STNC4OFF(),
/**
- *
- */
- _STCN4OFF("cn4off", 4, 4, 4, 2),
+ * texture coordinates + normals
+ */
+ _STNOFF(),
/**
- *
- */
- _STN4OFF("n4off", 4, 4, 0, 2);
+ * texture coordinates + normals
+ */
+ _STN4OFF(),
+ /**
+ * texture coordinates
+ */
+ _STOFF(),
+ /**
+ * texture coordinates
+ */
+ _ST4OFF(),
+ /**
+ *
+ */
+ _4OFF();
/**
- * lowercase text of the keyword as found in the very beginning of the file
+ * text of the keyword as found in the very beginning of the file
*/
- private final String lowercaseKeywordText;
+ private final String keywordText;
/**
* vertex values per tuple, either 3 or 4
@@ -134,18 +209,75 @@ public class OffImporter {
*/
private final int textureValuesPerTuple;
- private OffKeyword(final String lowercaseKeywordText, final int vertexValuesPerTuple,
- final int normalValuesPerTuple, final int maxColorValuesPerTuple, final int textureValuesPerTuple) {
- this.lowercaseKeywordText = lowercaseKeywordText;
- this.vertexValuesPerTuple = vertexValuesPerTuple;
- this.normalValuesPerTuple = normalValuesPerTuple;
- minColorValuesPerTuple = Math.min(1, maxColorValuesPerTuple);
- this.maxColorValuesPerTuple = maxColorValuesPerTuple;
- this.textureValuesPerTuple = textureValuesPerTuple;
+ private OffKeyword() {
+ final String offSuffix;
+ if (name().endsWith("nOFF")) {
+ throw new UnsupportedOperationException("nOFF not supported, must end with either OFF or 4OFF");
+ } else if (name().endsWith("4OFF")) {
+ vertexValuesPerTuple = 4;
+ offSuffix = "4OFF";
+ } else if (name().endsWith("OFF")) {
+ vertexValuesPerTuple = 3;
+ offSuffix = "OFF";
+ } else {
+ throw new UnsupportedOperationException(
+ "Unsupported off keyword " + name() + ", must end with either OFF or 4OFF");
+ }
+ final String vertexDataComponentIds;
+ if (name().length() == offSuffix.length() + 1) {
+ vertexDataComponentIds = "";
+ } else {
+ vertexDataComponentIds = name().substring(1, name().length() - offSuffix.length());
+ }
+ if (vertexDataComponentIds.chars()
+ .anyMatch((final int vertexDataComponentId) -> IntStream.of('N', 'C', 'S', 'T')
+ .noneMatch((final int supportedChar) -> vertexDataComponentId == supportedChar))) {
+ throw new UnsupportedOperationException("Unsupported off keyword " + name()
+ + ", the first part should contain only the characters N, C, S and T at most once each");
+ }
+ int tmpNormalValuesPerTuple = 0;
+ int tmpMinColorValuesPerTuple = 0;
+ int tmpMaxColorValuesPerTuple = 0;
+ int tmpTextureValuesPerTuple = 0;
+ for (final String vertexDataComponentIdCandidate : new String[] { "N", "C", "ST" }) {
+ final int firstIndexOfVertexDataComponentIdCandidate = vertexDataComponentIds
+ .indexOf(vertexDataComponentIdCandidate);
+ if (firstIndexOfVertexDataComponentIdCandidate != -1) {
+ final int lastIndexOfVertexDataComponentIdCandidate = vertexDataComponentIds
+ .lastIndexOf(vertexDataComponentIdCandidate);
+ // if the candidate appears exactly once
+ if (firstIndexOfVertexDataComponentIdCandidate == lastIndexOfVertexDataComponentIdCandidate) {
+ switch (vertexDataComponentIdCandidate) {
+ case "N":
+ tmpNormalValuesPerTuple = vertexValuesPerTuple;
+ break;
+ case "C":
+ tmpMinColorValuesPerTuple = 1;// 1 color component for an index in a color map
+ tmpMaxColorValuesPerTuple = 4;// 4 color components for RGBA
+ break;
+ case "ST":
+ tmpTextureValuesPerTuple = 2;// u and v texture coordinates
+ break;
+ default:
+ // cannot happen
+ break;
+ }
+ } else {
+ throw new UnsupportedOperationException("Unsupported off keyword " + name()
+ + ", the first part should contain N, C and ST at most once each. "
+ + vertexDataComponentIdCandidate + " appears more than once.");
+ }
+ }
+ }
+ normalValuesPerTuple = tmpNormalValuesPerTuple;
+ minColorValuesPerTuple = tmpMinColorValuesPerTuple;
+ maxColorValuesPerTuple = tmpMaxColorValuesPerTuple;
+ textureValuesPerTuple = tmpTextureValuesPerTuple;
+ keywordText = name().substring(1);
}
- public String getLowercaseKeywordText() {
- return lowercaseKeywordText;
+ public String getKeywordText() {
+ return keywordText;
}
public int getVertexValuesPerTuple() {
@@ -186,7 +318,8 @@ public class OffImporter {
this.reader = reader;
resetSyntax();
eolIsSignificant(true);
- lowerCaseMode(true);
+ // doesn't modify the case to avoid ambiguities between nOFF and NOFF
+ lowerCaseMode(false);
// all printable ascii characters
wordChars('!', '~');
@@ -294,8 +427,8 @@ public class OffImporter {
"Premature end of file, expected an optional off keyword followed by three integers vertex_count face_count edge_count");
}
final String unhandledFirstParsedValue;
- final OffKeyword offKeywordInFile = Arrays.stream(OffKeyword.values()).filter(
- (final OffKeyword offKeyword) -> offKeyword.getLowercaseKeywordText().equals(parser.sval))
+ final OffKeyword offKeywordInFile = Arrays.stream(OffKeyword.values())
+ .filter((final OffKeyword offKeyword) -> offKeyword.getKeywordText().equals(parser.sval))
.findFirst().orElse(null);
// tries to read an (optional) off keyword
if (offKeywordInFile == null) {