Showing preview only (334K chars total). Download the full file or copy to clipboard to get everything.
Repository: javagl/Obj
Branch: master
Commit: da3e9878c667
Files: 63
Total size: 313.0 KB
Directory structure:
gitextract_1k6agy0g/
├── .gitignore
├── LICENSE.txt
├── README.md
├── pom.xml
└── src/
├── main/
│ └── java/
│ └── de/
│ └── javagl/
│ └── obj/
│ ├── AbstractWritableObj.java
│ ├── BasicWritableObj.java
│ ├── DefaultFloatTuple.java
│ ├── DefaultMtl.java
│ ├── DefaultObj.java
│ ├── DefaultObjFace.java
│ ├── DefaultObjGroup.java
│ ├── DefaultTextureOptions.java
│ ├── FloatTuple.java
│ ├── FloatTuples.java
│ ├── Mtl.java
│ ├── MtlReader.java
│ ├── MtlWriter.java
│ ├── Mtls.java
│ ├── Obj.java
│ ├── ObjData.java
│ ├── ObjFace.java
│ ├── ObjFaceParser.java
│ ├── ObjFaces.java
│ ├── ObjGroup.java
│ ├── ObjReader.java
│ ├── ObjSplitter.java
│ ├── ObjSplitting.java
│ ├── ObjUtils.java
│ ├── ObjWriter.java
│ ├── Objs.java
│ ├── ReadableObj.java
│ ├── TextureOptions.java
│ ├── Utils.java
│ ├── WritableObj.java
│ └── package-info.java
└── test/
├── java/
│ └── de/
│ └── javagl/
│ └── obj/
│ ├── TestMtlReader.java
│ ├── TestMtlWriter.java
│ ├── TestObjData.java
│ ├── TestObjReader.java
│ ├── TestObjSplitting.java
│ ├── TestObjUtilsAdd.java
│ ├── TestObjUtilsGroupToObj.java
│ ├── TestObjUtilsMakeTexCoordsUnique.java
│ ├── TestObjUtilsTriangulate.java
│ ├── TestObjWriter.java
│ └── TestObjsCreate.java
└── resources/
├── complexMaterial.mtl
├── fourTrianglesInMixedGroups.obj
├── fourTrianglesPartiallyInMaterialGroups.obj
├── mtlWithBrokenLines.mtl
├── mtlWithPbrProperties.mtl
├── mtlWithWhitespace.mtl
├── pbrMaterial.mtl
├── square.obj
├── squareAndTriangle.obj
├── squareAndTriangleInTwoGroups.obj
├── squareAndTriangleWithRelativeIndices.obj
├── squareTextured.obj
├── twoMaterialsA.mtl
├── twoMaterialsB.mtl
├── twoTrianglesOneInDefaultGroup.obj
├── twoTrianglesSharedInThreeGroups.obj
└── twoTrianglesWithAmbiguousTexCoords.obj
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
target/
.classpath
.project
.settings
================================================
FILE: LICENSE.txt
================================================
www.javagl.de - Obj
Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
# Obj - a simple Wavefront OBJ file loader and writer
Maven dependency:
<dependency>
<groupId>de.javagl</groupId>
<artifactId>obj</artifactId>
<version>0.4.0</version>
</dependency>
Direct JAR link: [https://oss.sonatype.org/content/repositories/releases/de/javagl/obj/0.4.0/obj-0.4.0.jar](https://oss.sonatype.org/content/repositories/releases/de/javagl/obj/0.4.0/obj-0.4.0.jar)
# Samples
Samples showing how to use this library are available in the [ObjSamples project](https://github.com/javagl/ObjSamples).
# Overview
This is a simple loader and writer for Wavefront `.OBJ` files. The elements
that are currently supported are
- Vertices
- Texture coordinates
- Normals
- Faces (with positive or negative indices)
- Groups
- Material groups
- MTL files
The `Obj` interface is basically an in-memory representation of an OBJ file.
It combines a `ReadableObj`, which provides the contents of the OBJ file,
and a `WritableObj`, which may receive elements like vertices and faces
in order to build an OBJ in memory.
The `ObjReader` class may either create a new `Obj` object directly
from an input stream, or pass the elements that are read from the input
stream to a `WritableObj`.
The `ObjWriter` class offers a method to write a `ReadableObj` object
to an output stream.
The `ObjData` class offers various methods to obtain the data that is
stored in a `ReadableObj` as plain arrays or *direct* buffers.
The `ObjUtils` class offers basic utility methods for general operations
on the OBJ data.
## Rendering OBJ data with OpenGL
The `ObjUtils` class contains methods that aim at preparing the OBJ so
that it may easily be rendered with OpenGL. These methods may...
- convert a single group of an OBJ into a new OBJ
- triangulate OBJ data
- make sure that texture coordinates or normal coordinates are unique
for each vertex
- convert an OBJ to an OBJ that is uses the same index sets for vertices,
texture coordinates and normals
The latter operations are also summarized in one dedicated method, namely
the `ObjUtils.convertToRenderable` method:
InputStream inputStream = ...;
Obj obj = ObjUtils.convertToRenderable(
ObjReader.read(inputStream));
IntBuffer indices = ObjData.getFaceVertexIndices(obj);
FloatBuffer vertices = ObjData.getVertices(obj);
FloatBuffer texCoords = ObjData.getTexCoords(obj, 2);
FloatBuffer normals = ObjData.getNormals(obj);
These buffers may directly be used as the data for vertex buffer objects (VBO)
in OpenGL.
### Extracting material groups
An OBJ may contain multiple material definitions. When such an OBJ should
be rendered with OpenGL, this usually means that there will be one shader
for each material - or at least, different textures may have to be used
for different parts of the objects. This library offers methods to extract
the parts of the OBJ that have the same material. In the OBJ format, these
groups consist of the triangles that follow one `usemtl` directive.
When such an OBJ file is read, the resulting material groups may be obtained
from the `ReadableObj` object, and each of them can be converted into a new
`Obj` object using the `ObjUtils#groupToObj` method.
The `ObjSplitting` class contains a convenience method for this:
Obj obj = ObjReader.read(...);
Map<String, Obj> mtlObjs = ObjSplitting.splitByMaterialGroups(obj);;
Each of these `Obj` objects may then be converted into a renderable OBJ,
using the `ObjUtils.convertToRenderable` method as described above,
and then be rendered with the appropriate shader for the respective
material.
### Limiting the number of vertices per OBJ
In certain environments, the number of vertices that may be involved in
one rendering call is limited. Particularly, in WebGL or OpenGL ES 2.0,
the indices that are used for indexed draw calls may only be of the type
`GL_UNSIGNED_SHORT`, which means that no object may have more than
65k vertices. In these cases, larger OBJ files have to be split into
multiple parts. Additionally, the index buffers that are passed to
the rendering API may not contain (4-byte) `int` elements, but only
(2-byte) `short` elements.
The `ObjSplitting` class contains a method that allows splitting an
OBJ into multiple parts, each having only a maximum number of vertices.
Additionally, the `ObjData` class contains methods for converting
an `IntBuffer` into a `ShortBuffer`.
So in order to split a large OBJ into multiple parts, and render each
part with WebGL or OpenGL ES 2.0, the following code can be used:
Obj largeObj = ObjReader.read(...);
Obj renderableObj = ObjUtils.convertToRenderable(largeObj);
if (renderableObj.getNumVertices() > 65000)
{
// If this has to be rendered with OpenGL ES 2.0, then
// the object may not contain more than 65k vertices!
// Split it into multiple parts:
List<Obj> renderableParts =
ObjSplitting.splitByMaxNumVertices(renderableObj, 65000);
for (Obj renderablePart : renderableParts)
{
// Obtain the indices as a "short" buffer that may
// be used for OpenGL rendering with the index
// type GL_UNSIGNED_SHORT
ShortBuffer indices = ObjData.convertToShortBuffer(
ObjData.getFaceVertexIndices(renderablePart));
...
sendToRenderer(indices, ...);
}
}
...
---
# Change log
**0.4.1-SNAPSHOT**
- ...
**0.4.0** (2023-03-04)
- Updated MTL handling to support additional options. This includes the
options that have been part of the original MTL specification, as well
as PBR (Physically Based Rendering) options.
- A new interface `TextureOptions` has been introduced. For texture
maps, the `Mtl` interface now has methods `getMap...Options()`
and `setMap...Options(...)`. This `TextureOptions` object
contains the parameters that are common for all texture maps, like
blending states, offsets, or scales, as described in the MTL specification.
- **API change**: The `Mtl#get...` methods will now return `null` when
no information was parsed from the input file.
Code that originally called one of these methods, like
```
float d = mtl.getD();
```
should now check whether these values are not `null`, as in
```
float d = 1.0f; // The default value for the opacity
if (mtl.getD() != null)
{
d = mtl.getD();
}
```
This will not affect clients that only read or write the `Mtl` with the
`MtlReader` or `MtlWriter`, because these classes will handle the
`null`-cases internally.
**0.3.0** (2018-01-12)
- Added `ObjSplitting` class for splitting OBJs
- Added `ObjData#convertToShortBuffer` method
- Added `ObjUtils#add` method for combining OBJs
**0.2.1** (2015-10-26)
- Bugfix: Made `AbstractWritableObj#addNormal(FloatTuple)` non-final
- Added methods in `ObjReader` and `MtlReader` that accept a `Reader`
instead of an `InputStream`, and methods in `ObjWriter` and
`MtlWriter` that accept a `Writer` instead of an `OutputStream`
- Added implementation of `ObjUtils.convertToRenderable` that
receives a `WritableObj`
**0.2.0** (2015-10-05) :
- Initial public release on GitHub and Maven Central
================================================
FILE: pom.xml
================================================
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.sonatype.oss</groupId>
<artifactId>oss-parent</artifactId>
<version>9</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>de.javagl</groupId>
<artifactId>obj</artifactId>
<version>0.4.1-SNAPSHOT</version>
<name>obj</name>
<url>https://github.com/javagl</url>
<developers>
<developer>
<name>Marco Hutter</name>
<email>javagl@javagl.de</email>
<roles>
<role>developer</role>
</roles>
</developer>
</developers>
<scm>
<connection>scm:git:git@github.com:javagl/Obj.git</connection>
<developerConnection>scm:git:git@github.com:javagl/Obj.git</developerConnection>
<url>git@github.com:javagl/Obj.git</url>
</scm>
<licenses>
<license>
<name>MIT</name>
<url>https://github.com/javagl/Obj/blob/master/LICENSE.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.1</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<description>A simple Wavefront OBJ file loader and writer</description>
</project>
================================================
FILE: src/main/java/de/javagl/obj/AbstractWritableObj.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
import java.util.Collection;
import java.util.Objects;
/**
* Abstract base implementation of a {@link WritableObj}. <br>
* <br>
* The final implementations of the methods in this class all delegate
* to the following (non-final) methods, which may be overridden by
* implementors:
* <ul>
* <li>{@link #addVertex(FloatTuple)}</li>
* <li>{@link #addTexCoord(FloatTuple)}</li>
* <li>{@link #addFace(ObjFace)}</li>
* <li>{@link #setActiveGroupNames(Collection)}</li>
* <li>{@link #setActiveMaterialGroupName(String)}</li>
* <li>{@link #setMtlFileNames(Collection)}</li>
* </ul>
*/
public class AbstractWritableObj implements WritableObj
{
/**
* Default constructor
*/
protected AbstractWritableObj()
{
// Default constructor
}
@Override
public final void addVertex(float x, float y, float z)
{
addVertex(FloatTuples.create(x, y, z));
}
@Override
public void addVertex(FloatTuple vertex)
{
// Empty default implementation
}
@Override
public final void addTexCoord(float x)
{
addTexCoord(FloatTuples.create(x));
}
@Override
public final void addTexCoord(float x, float y)
{
addTexCoord(FloatTuples.create(x, y));
}
@Override
public final void addTexCoord(float x, float y, float z)
{
addTexCoord(FloatTuples.create(x, y, z));
}
@Override
public void addTexCoord(FloatTuple texCoord)
{
// Empty default implementation
}
@Override
public void addNormal(FloatTuple normal)
{
// Empty default implementation
}
@Override
public final void addNormal(float x, float y, float z)
{
addNormal(FloatTuples.create(x, y, z));
}
@Override
public void setActiveGroupNames(
Collection<? extends String> groupNames)
{
// Empty default implementation
}
@Override
public void setActiveMaterialGroupName(String materialGroupName)
{
// Empty default implementation
}
@Override
public void addFace(ObjFace face)
{
// Empty default implementation
}
@Override
public final void addFace(int ... v)
{
addFace(v, null, null);
}
@Override
public final void addFaceWithTexCoords(int... v)
{
addFace(v, v, null);
}
@Override
public final void addFaceWithNormals(int... v)
{
addFace(v, null, v);
}
@Override
public final void addFaceWithAll(int... v)
{
addFace(v, v, v);
}
@Override
public final void addFace(int[] v, int[] vt, int[] vn)
{
Objects.requireNonNull(v, "The vertex indices are null");
addFace(ObjFaces.create(v, vt, vn));
}
@Override
public void setMtlFileNames(Collection<? extends String> mtlFileNames)
{
// Empty default implementation
}
}
================================================
FILE: src/main/java/de/javagl/obj/BasicWritableObj.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
import java.util.Collection;
import java.util.Objects;
import java.util.function.Consumer;
/**
* Basic implementation of a {@link WritableObj} that delegates all calls
* to consumer callbacks. <br>
* <br>
* The consumers for the elements of an OBJ are <code>null</code> by default,
* causing the respective elements to be ignored. The callbacks may be set
* individually. For example, in order to print all vertices and faces that
* are read from an OBJ file, the following may be used:
* <pre><code>
* BasicWritableObj obj = new BasicWritableObj();
* obj.setVertexConsumer(t -> System.out.println(t));
* obj.setFaceConsumer(t -> System.out.println(t));
* ObjReader.read(inputStream, obj);
* </code></pre>
*/
public class BasicWritableObj implements WritableObj
{
/**
* The vertex consumer
*/
private Consumer<? super FloatTuple> vertexConsumer;
/**
* The texture coordinate consumer
*/
private Consumer<? super FloatTuple> texCoordConsumer;
/**
* The normal consumer
*/
private Consumer<? super FloatTuple> normalConsumer;
/**
* The face consumer
*/
private Consumer<? super ObjFace> faceConsumer;
/**
* The consumer for group names
*/
private Consumer<? super Collection<? extends String>> groupNamesConsumer;
/**
* The consumer for material group names
*/
private Consumer<? super String> materialGroupNameConsumer;
/**
* The consumer for MTL file names
*/
private Consumer<? super Collection<? extends String>> mtlFileNamesConsumer;
/**
* Default constructor
*/
public BasicWritableObj()
{
// Default constructor
}
/**
* Set the vertex consumer
*
* @param vertexConsumer The consumer
*/
public void setVertexConsumer(Consumer<? super FloatTuple> vertexConsumer)
{
this.vertexConsumer = vertexConsumer;
}
/**
* Set the texture coordinate consumer
*
* @param texCoordConsumer The consumer
*/
public void setTexCoordConsumer(
Consumer<? super FloatTuple> texCoordConsumer)
{
this.texCoordConsumer = texCoordConsumer;
}
/**
* Set the normal consumer
*
* @param normalConsumer The consumer
*/
public void setNormalConsumer(Consumer<? super FloatTuple> normalConsumer)
{
this.normalConsumer = normalConsumer;
}
/**
* Set the face consumer
*
* @param faceConsumer The consumer
*/
public void setFaceConsumer(Consumer<? super ObjFace> faceConsumer)
{
this.faceConsumer = faceConsumer;
}
/**
* Set the group names consumer
*
* @param groupNamesConsumer The consumer
*/
public void setGroupNamesConsumer(
Consumer<? super Collection<? extends String>> groupNamesConsumer)
{
this.groupNamesConsumer = groupNamesConsumer;
}
/**
* Set the material group name consumer
*
* @param materialGroupNameConsumer The consumer
*/
public void setMaterialGroupNameConsumer(
Consumer<? super String> materialGroupNameConsumer)
{
this.materialGroupNameConsumer = materialGroupNameConsumer;
}
/**
* Set the MTL file names consumer
*
* @param mtlFileNamesConsumer The consumer
*/
public void setMtlFileNamesConsumer(
Consumer<? super Collection<? extends String>> mtlFileNamesConsumer)
{
this.mtlFileNamesConsumer = mtlFileNamesConsumer;
}
@Override
public final void addVertex(FloatTuple vertex)
{
if (vertexConsumer != null)
{
vertexConsumer.accept(vertex);
}
}
@Override
public final void addVertex(float x, float y, float z)
{
addVertex(FloatTuples.create(x, y, z));
}
@Override
public final void addTexCoord(FloatTuple texCoord)
{
if (texCoordConsumer != null)
{
texCoordConsumer.accept(texCoord);
}
}
@Override
public final void addTexCoord(float x)
{
addTexCoord(FloatTuples.create(x));
}
@Override
public final void addTexCoord(float x, float y)
{
addTexCoord(FloatTuples.create(x, y));
}
@Override
public final void addTexCoord(float x, float y, float z)
{
addTexCoord(FloatTuples.create(x, y, z));
}
@Override
public final void addNormal(FloatTuple normal)
{
if (normalConsumer != null)
{
normalConsumer.accept(normal);
}
}
@Override
public final void addNormal(float x, float y, float z)
{
addNormal(FloatTuples.create(x, y, z));
}
@Override
public final void setActiveGroupNames(
Collection<? extends String> groupNames)
{
if (groupNamesConsumer != null)
{
groupNamesConsumer.accept(groupNames);
}
}
@Override
public final void setActiveMaterialGroupName(String materialGroupName)
{
if (materialGroupNameConsumer != null)
{
materialGroupNameConsumer.accept(materialGroupName);
}
}
@Override
public final void addFace(ObjFace face)
{
if (faceConsumer != null)
{
faceConsumer.accept(face);
}
}
@Override
public final void addFace(int ... v)
{
addFace(v, null, null);
}
@Override
public final void addFaceWithTexCoords(int... v)
{
addFace(v, v, null);
}
@Override
public final void addFaceWithNormals(int... v)
{
addFace(v, null, v);
}
@Override
public final void addFaceWithAll(int... v)
{
addFace(v, v, v);
}
@Override
public final void addFace(int[] v, int[] vt, int[] vn)
{
Objects.requireNonNull(v, "The vertex indices are null");
if (faceConsumer != null)
{
addFace(ObjFaces.create(v, vt, vn));
}
}
@Override
public final void setMtlFileNames(Collection<? extends String> mtlFileNames)
{
if (mtlFileNamesConsumer != null)
{
mtlFileNamesConsumer.accept(mtlFileNames);
}
}
}
================================================
FILE: src/main/java/de/javagl/obj/DefaultFloatTuple.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
import java.util.Arrays;
/**
* Default implementation of a {@link FloatTuple}
*/
final class DefaultFloatTuple implements FloatTuple
{
/**
* The values of this tuple
*/
private final float[] values;
/**
* Creates a new DefaultFloatTuple with the given values
*
* @param values The values
*/
DefaultFloatTuple(float[] values)
{
this.values = values;
}
/**
* Creates a new DefaultFloatTuple with the given values
*
* @param x The x value
* @param y The y value
* @param z The z value
* @param w The w value
*/
DefaultFloatTuple(float x, float y, float z, float w)
{
this(new float[]{x,y,z,w});
}
/**
* Creates a new DefaultFloatTuple with the given values
*
* @param x The x value
* @param y The y value
* @param z The z value
*/
DefaultFloatTuple(float x, float y, float z)
{
this(new float[]{x,y,z});
}
/**
* Creates a new DefaultFloatTuple with the given values
*
* @param x The x value
* @param y The y value
*/
DefaultFloatTuple(float x, float y)
{
this(new float[]{x,y});
}
/**
* Creates a new DefaultFloatTuple with the given value
*
* @param x The x value
*/
DefaultFloatTuple(float x)
{
this(new float[]{x});
}
/**
* Copy constructor.
*
* @param other The other FloatTuple
*/
DefaultFloatTuple(FloatTuple other)
{
this(getValues(other));
}
/**
* Returns the values of the given {@link FloatTuple} as an array
*
* @param f The {@link FloatTuple}
* @return The values
*/
private static float[] getValues(FloatTuple f)
{
if (f instanceof DefaultFloatTuple)
{
DefaultFloatTuple other = (DefaultFloatTuple)f;
return other.values.clone();
}
float[] values = new float[f.getDimensions()];
for (int i=0; i<values.length; i++)
{
values[i] = f.get(i);
}
return values;
}
@Override
public float get(int index)
{
return values[index];
}
@Override
public float getX()
{
return values[0];
}
/**
* Set the given component of this tuple
*
* @param x The component to set
* @throws IndexOutOfBoundsException If this tuple has less than 1
* dimensions
*/
void setX(float x)
{
values[0] = x;
}
@Override
public float getY()
{
return values[1];
}
/**
* Set the given component of this tuple
*
* @param y The component to set
* @throws IndexOutOfBoundsException If this tuple has less than 2
* dimensions
*/
void setY(float y)
{
values[1] = y;
}
@Override
public float getZ()
{
return values[2];
}
/**
* Set the given component of this tuple
*
* @param z The component to set
* @throws IndexOutOfBoundsException If this tuple has less than 3
* dimensions
*/
void setZ(float z)
{
values[2] = z;
}
@Override
public float getW()
{
return values[3];
}
/**
* Set the given component of this tuple
*
* @param w The component to set
* @throws IndexOutOfBoundsException If this tuple has less than 4
* dimensions
*/
void setW(float w)
{
values[3] = w;
}
@Override
public int getDimensions()
{
return values.length;
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("(");
for (int i=0; i<getDimensions(); i++)
{
sb.append(get(i));
if (i < getDimensions()-1)
{
sb.append(",");
}
}
sb.append(")");
return sb.toString();
}
@Override
public int hashCode()
{
return Arrays.hashCode(values);
}
@Override
public boolean equals(Object object)
{
if (this == object)
{
return true;
}
if (object == null)
{
return false;
}
if (object instanceof DefaultFloatTuple)
{
DefaultFloatTuple other = (DefaultFloatTuple)object;
return Arrays.equals(values, other.values);
}
if (object instanceof FloatTuple)
{
FloatTuple other = (FloatTuple)object;
if (other.getDimensions() != getDimensions())
{
return false;
}
for (int i=0; i<getDimensions(); i++)
{
if (get(i) != other.get(i))
{
return false;
}
}
return true;
}
return false;
}
}
================================================
FILE: src/main/java/de/javagl/obj/DefaultMtl.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
import java.util.ArrayList;
import java.util.List;
/**
* Default implementation of an Mtl (material)
*/
final class DefaultMtl implements Mtl
{
/**
* The name of this material
*/
private final String name;
/**
* The illumination mode
*/
private Integer illum;
/**
* The optical density
*/
private Float ni;
/**
* The transmission filter
*/
private FloatTuple tf;
/**
* The sharpness of reflections
*/
private Float sharpness;
/**
* The ambient part of this material
*/
private FloatTuple ka;
/**
* The ambient map texture options
*/
private TextureOptions mapKaOptions;
/**
* The diffuse part of this material
*/
private FloatTuple kd;
/**
* The diffuse map texture options
*/
private TextureOptions mapKdOptions;
/**
* The specular part of this material
*/
private FloatTuple ks;
/**
* The specular map texture options
*/
private TextureOptions mapKsOptions;
/**
* The shininess of this material
*/
private Float ns;
/**
* The shininess map texture options
*/
private TextureOptions mapNsOptions;
/**
* The opacity of this material
*/
private Float d;
/**
* The halo flag for the opacity
*/
private Boolean halo;
/**
* The opacity map texture options
*/
private TextureOptions mapDOptions;
/**
* The bump map texture options
*/
private TextureOptions bumpOptions;
/**
* The displacement map texture options
*/
private TextureOptions dispOptions;
/**
* The decal map texture options
*/
private TextureOptions decalOptions;
/**
* The reflection map texture options
*/
private final List<TextureOptions> reflOptions;
// PBR Parameters:
/**
* The roughness of this material
*/
private Float pr;
/**
* The roughness map texture options
*/
private TextureOptions mapPrOptions;
/**
* The metallic part of this material
*/
private Float pm;
/**
* The metallic map texture options
*/
private TextureOptions mapPmOptions;
/**
* The sheen part of this material
*/
private Float ps;
/**
* The sheen map texture options
*/
private TextureOptions mapPsOptions;
/**
* The clearcoat thickness of this material
*/
private Float pc;
/**
* The clearcoat roughness of this material
*/
private Float pcr;
/**
* The emissive part of this material
*/
private FloatTuple ke;
/**
* The emissive map texture options
*/
private TextureOptions mapKeOptions;
/**
* The anisotropy of this material
*/
private Float aniso;
/**
* The anisotropy rotation of this material
*/
private Float anisor;
/**
* The normal map texture options
*/
private TextureOptions normOptions;
/**
* Creates a new material with the given name
*
* @param name The name of this material
*/
DefaultMtl(String name)
{
this.name = name;
this.reflOptions = new ArrayList<>();
}
@Override
public String getName()
{
return name;
}
@Override
public Integer getIllum()
{
return illum;
}
@Override
public void setIllum(Integer illum)
{
this.illum = illum;
}
@Override
public Float getNi()
{
return ni;
}
@Override
public void setNi(Float ni)
{
this.ni = ni;
}
@Override
public FloatTuple getTf()
{
return tf;
}
@Override
public void setTf(Float r, Float g, Float b)
{
this.tf = Utils.createRgbTuple(r, g, b);
}
@Override
public Float getSharpness()
{
return sharpness;
}
@Override
public void setSharpness(Float sharpness)
{
this.sharpness = sharpness;
}
@Override
public FloatTuple getKa()
{
return ka;
}
@Override
public void setKa(Float r, Float g, Float b)
{
this.ka = Utils.createRgbTuple(r, g, b);
}
@Override
public String getMapKa()
{
if (mapKaOptions == null)
{
return null;
}
return mapKaOptions.getFileName();
}
@Override
public void setMapKa(String mapKa)
{
if (mapKaOptions == null)
{
mapKaOptions = new DefaultTextureOptions();
}
mapKaOptions.setFileName(mapKa);
}
@Override
public TextureOptions getMapKaOptions()
{
return mapKaOptions;
}
@Override
public void setMapKaOptions(TextureOptions options)
{
this.mapKaOptions = options;
}
@Override
public FloatTuple getKd()
{
return kd;
}
@Override
public void setKd(Float r, Float g, Float b)
{
this.kd = Utils.createRgbTuple(r, g, b);
}
@Override
public String getMapKd()
{
if (mapKdOptions == null)
{
return null;
}
return mapKdOptions.getFileName();
}
@Override
public void setMapKd(String mapKd)
{
if (mapKdOptions == null)
{
mapKdOptions = new DefaultTextureOptions();
}
mapKdOptions.setFileName(mapKd);
}
@Override
public TextureOptions getMapKdOptions()
{
return mapKdOptions;
}
@Override
public void setMapKdOptions(TextureOptions options)
{
this.mapKdOptions = options;
}
@Override
public FloatTuple getKs()
{
return ks;
}
@Override
public void setKs(Float r, Float g, Float b)
{
this.ks = Utils.createRgbTuple(r, g, b);
}
@Override
public String getMapKs()
{
if (mapKsOptions == null)
{
return null;
}
return mapKsOptions.getFileName();
}
@Override
public void setMapKs(String mapKs)
{
if (mapKsOptions == null)
{
mapKsOptions = new DefaultTextureOptions();
}
mapKsOptions.setFileName(mapKs);
}
@Override
public TextureOptions getMapKsOptions()
{
return mapKsOptions;
}
@Override
public void setMapKsOptions(TextureOptions options)
{
this.mapKsOptions = options;
}
@Override
public Float getNs()
{
return ns;
}
@Override
public void setNs(Float ns)
{
this.ns = ns;
}
@Override
public String getMapNs()
{
if (mapNsOptions == null)
{
return null;
}
return mapNsOptions.getFileName();
}
@Override
public void setMapNs(String mapNs)
{
if (mapNsOptions == null)
{
mapNsOptions = new DefaultTextureOptions();
}
mapNsOptions.setFileName(mapNs);
}
@Override
public TextureOptions getMapNsOptions()
{
return mapNsOptions;
}
@Override
public void setMapNsOptions(TextureOptions options)
{
this.mapNsOptions = options;
}
@Override
public Float getD()
{
return d;
}
@Override
public void setD(Float d)
{
this.d = d;
}
@Override
public Boolean isHalo()
{
return halo;
}
@Override
public void setHalo(Boolean halo)
{
this.halo = halo;
}
@Override
public String getMapD()
{
if (mapDOptions == null)
{
return null;
}
return mapDOptions.getFileName();
}
@Override
public void setMapD(String mapD)
{
if (mapDOptions == null)
{
mapDOptions = new DefaultTextureOptions();
}
mapDOptions.setFileName(mapD);
}
@Override
public TextureOptions getMapDOptions()
{
return mapDOptions;
}
@Override
public void setMapDOptions(TextureOptions options)
{
this.mapDOptions = options;
}
@Override
public String getBump()
{
if (bumpOptions == null)
{
return null;
}
return bumpOptions.getFileName();
}
@Override
public void setBump(String bump)
{
if (bumpOptions == null)
{
bumpOptions = new DefaultTextureOptions();
}
bumpOptions.setFileName(bump);
}
@Override
public TextureOptions getBumpOptions()
{
return bumpOptions;
}
@Override
public void setBumpOptions(TextureOptions options)
{
this.bumpOptions = options;
}
@Override
public String getDisp()
{
if (dispOptions == null)
{
return null;
}
return dispOptions.getFileName();
}
@Override
public void setDisp(String disp)
{
if (dispOptions == null)
{
dispOptions = new DefaultTextureOptions();
}
dispOptions.setFileName(disp);
}
@Override
public TextureOptions getDispOptions()
{
return dispOptions;
}
@Override
public void setDispOptions(TextureOptions options)
{
this.dispOptions = options;
}
@Override
public String getDecal()
{
if (decalOptions == null)
{
return null;
}
return decalOptions.getFileName();
}
@Override
public void setDecal(String decal)
{
if (decalOptions == null)
{
decalOptions = new DefaultTextureOptions();
}
decalOptions.setFileName(decal);
}
@Override
public TextureOptions getDecalOptions()
{
return decalOptions;
}
@Override
public void setDecalOptions(TextureOptions options)
{
this.decalOptions = options;
}
@Override
public List<TextureOptions> getReflOptions()
{
return reflOptions;
}
// PRB parameters
@Override
public Float getPr()
{
return pr;
}
@Override
public void setPr(Float pr)
{
this.pr = pr;
}
@Override
public String getMapPr()
{
if (mapPrOptions == null)
{
return null;
}
return mapPrOptions.getFileName();
}
@Override
public void setMapPr(String mapPr)
{
if (mapPrOptions == null)
{
mapPrOptions = new DefaultTextureOptions();
}
mapPrOptions.setFileName(mapPr);
}
@Override
public TextureOptions getMapPrOptions()
{
return mapPrOptions;
}
@Override
public void setMapPrOptions(TextureOptions options)
{
this.mapPrOptions = options;
}
@Override
public Float getPm()
{
return pm;
}
@Override
public void setPm(Float pm)
{
this.pm = pm;
}
@Override
public String getMapPm()
{
if (mapPmOptions == null)
{
return null;
}
return mapPmOptions.getFileName();
}
@Override
public void setMapPm(String mapPm)
{
if (mapPmOptions == null)
{
mapPmOptions = new DefaultTextureOptions();
}
mapPmOptions.setFileName(mapPm);
}
@Override
public TextureOptions getMapPmOptions()
{
return mapPmOptions;
}
@Override
public void setMapPmOptions(TextureOptions options)
{
this.mapPmOptions = options;
}
@Override
public Float getPs()
{
return ps;
}
@Override
public void setPs(Float ps)
{
this.ps = ps;
}
@Override
public String getMapPs()
{
if (mapPsOptions == null)
{
return null;
}
return mapPsOptions.getFileName();
}
@Override
public void setMapPs(String mapPs)
{
if (mapPsOptions == null)
{
mapPsOptions = new DefaultTextureOptions();
}
mapPsOptions.setFileName(mapPs);
}
@Override
public TextureOptions getMapPsOptions()
{
return mapPsOptions;
}
@Override
public void setMapPsOptions(TextureOptions options)
{
this.mapPsOptions = options;
}
@Override
public Float getPc()
{
return pc;
}
@Override
public void setPc(Float pc)
{
this.pc = pc;
}
@Override
public Float getPcr()
{
return pcr;
}
@Override
public void setPcr(Float pcr)
{
this.pcr = pcr;
}
@Override
public FloatTuple getKe()
{
return ke;
}
@Override
public void setKe(Float r, Float g, Float b)
{
this.ke = Utils.createRgbTuple(r, g, b);
}
@Override
public String getMapKe()
{
if (mapKeOptions == null)
{
return null;
}
return mapKeOptions.getFileName();
}
@Override
public void setMapKe(String mapKe)
{
if (mapKeOptions == null)
{
mapKeOptions = new DefaultTextureOptions();
}
mapKeOptions.setFileName(mapKe);
}
@Override
public TextureOptions getMapKeOptions()
{
return mapKeOptions;
}
@Override
public void setMapKeOptions(TextureOptions options)
{
this.mapKeOptions = options;
}
@Override
public Float getAniso()
{
return aniso;
}
@Override
public void setAniso(Float aniso)
{
this.aniso = aniso;
}
@Override
public Float getAnisor()
{
return anisor;
}
@Override
public void setAnisor(Float anisor)
{
this.anisor = anisor;
}
@Override
public String getNorm()
{
if (normOptions == null)
{
return null;
}
return normOptions.getFileName();
}
@Override
public void setNorm(String norm)
{
if (normOptions == null)
{
normOptions = new DefaultTextureOptions();
}
normOptions.setFileName(norm);
}
@Override
public TextureOptions getNormOptions()
{
return normOptions;
}
@Override
public void setNormOptions(TextureOptions options)
{
this.normOptions = options;
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("Mtl");
sb.append("[");
sb.append("name=").append(getName());
sb.append("]");
return sb.toString();
}
}
================================================
FILE: src/main/java/de/javagl/obj/DefaultObj.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* Default implementation of an {@link Obj}
*/
final class DefaultObj implements Obj
{
/**
* The vertices in this Obj
*/
private final List<FloatTuple> vertices;
/**
* The texture coordinates in this Obj.
*/
private final List<FloatTuple> texCoords;
/**
* The normals in this Obj
*/
private final List<FloatTuple> normals;
/**
* The faces in this Obj.
*/
private final List<ObjFace> faces;
/**
* The groups in this Obj.
*/
private final List<ObjGroup> groups;
/**
* The material groups in this Obj.
*/
private final List<ObjGroup> materialGroups;
/**
* Maps a group name to a group
*/
private final Map<String, DefaultObjGroup> groupMap;
/**
* Maps a material name to a material group
*/
private final Map<String, DefaultObjGroup> materialGroupMap;
/**
* The names of the MTL files for this Obj.
*/
private List<String> mtlFileNames = Collections.emptyList();
/**
* A map from the faces to the names of the groups that started
* at this face
*/
private final Map<ObjFace, Set<String>> startedGroupNames;
/**
* A map from the faces to the name of the material group that started
* at this face
*/
private final Map<ObjFace, String> startedMaterialGroupNames;
/**
* The names for the groups that should be used for faces that are
* added subsequently
*/
private Set<String> nextActiveGroupNames = null;
/**
* The name for the material group that should be used for faces that are
* added subsequently
*/
private String nextActiveMaterialGroupName = null;
/**
* The groups that are currently active, and to which faces will be
* added
*/
private List<DefaultObjGroup> activeGroups = null;
/**
* The names of the groups that faces are currently added to
*/
private Set<String> activeGroupNames = null;
/**
* The material group that is currently active, and to which faces will be
* added
*/
private DefaultObjGroup activeMaterialGroup = null;
/**
* The name of the material group that is currently active
*/
private String activeMaterialGroupName = null;
/**
* Creates a new, empty DefaultObj.
*/
DefaultObj()
{
vertices = new ArrayList<>();
normals = new ArrayList<>();
texCoords = new ArrayList<>();
faces = new ArrayList<>();
groups = new ArrayList<>();
materialGroups = new ArrayList<>();
groupMap = new LinkedHashMap<>();
materialGroupMap = new LinkedHashMap<>();
startedGroupNames = new HashMap<>();
startedMaterialGroupNames = new HashMap<>();
setActiveGroupNames(Arrays.asList("default"));
getGroupInternal("default");
}
@Override
public int getNumVertices()
{
return vertices.size();
}
@Override
public FloatTuple getVertex(int index)
{
return vertices.get(index);
}
@Override
public int getNumTexCoords()
{
return texCoords.size();
}
@Override
public FloatTuple getTexCoord(int index)
{
return texCoords.get(index);
}
@Override
public int getNumNormals()
{
return normals.size();
}
@Override
public FloatTuple getNormal(int index)
{
return normals.get(index);
}
@Override
public int getNumFaces()
{
return faces.size();
}
@Override
public ObjFace getFace(int index)
{
return faces.get(index);
}
@Override
public Set<String> getActivatedGroupNames(ObjFace face)
{
return startedGroupNames.get(face);
}
@Override
public String getActivatedMaterialGroupName(ObjFace face)
{
return startedMaterialGroupNames.get(face);
}
@Override
public int getNumGroups()
{
return groups.size();
}
@Override
public ObjGroup getGroup(int index)
{
return groups.get(index);
}
@Override
public ObjGroup getGroup(String name)
{
return groupMap.get(name);
}
@Override
public int getNumMaterialGroups()
{
return materialGroups.size();
}
@Override
public ObjGroup getMaterialGroup(int index)
{
return materialGroups.get(index);
}
@Override
public ObjGroup getMaterialGroup(String name)
{
return materialGroupMap.get(name);
}
@Override
public List<String> getMtlFileNames()
{
return mtlFileNames;
}
@Override
public void addVertex(FloatTuple vertex)
{
Objects.requireNonNull(vertex, "The vertex is null");
vertices.add(vertex);
}
@Override
public void addVertex(float x, float y, float z)
{
vertices.add(new DefaultFloatTuple(x, y, z));
}
@Override
public void addTexCoord(FloatTuple texCoord)
{
Objects.requireNonNull(texCoord, "The texCoord is null");
texCoords.add(texCoord);
}
@Override
public void addTexCoord(float x)
{
texCoords.add(new DefaultFloatTuple(x));
}
@Override
public void addTexCoord(float x, float y)
{
texCoords.add(new DefaultFloatTuple(x, y));
}
@Override
public void addTexCoord(float x, float y, float z)
{
texCoords.add(new DefaultFloatTuple(x, y, z));
}
@Override
public void addNormal(FloatTuple normal)
{
Objects.requireNonNull(normal, "The normal is null");
normals.add(normal);
}
@Override
public void addNormal(float x, float y, float z)
{
normals.add(new DefaultFloatTuple(x, y, z));
}
@Override
public void setActiveGroupNames(Collection<? extends String> groupNames)
{
if (groupNames == null)
{
return;
}
if (groupNames.size() == 0)
{
groupNames = Arrays.asList("default");
}
else if (groupNames.contains(null))
{
throw new NullPointerException("The groupNames contains null");
}
nextActiveGroupNames =
Collections.unmodifiableSet(new LinkedHashSet<String>(groupNames));
}
@Override
public void setActiveMaterialGroupName(String materialGroupName)
{
if (materialGroupName == null)
{
return;
}
nextActiveMaterialGroupName = materialGroupName;
}
@Override
public void addFace(ObjFace face)
{
if (face == null)
{
throw new NullPointerException("The face is null");
}
if (nextActiveGroupNames != null)
{
activeGroups = getGroupsInternal(nextActiveGroupNames);
if (!nextActiveGroupNames.equals(activeGroupNames))
{
startedGroupNames.put(face, nextActiveGroupNames);
}
activeGroupNames = nextActiveGroupNames;
nextActiveGroupNames = null;
}
if (nextActiveMaterialGroupName != null)
{
activeMaterialGroup =
getMaterialGroupInternal(nextActiveMaterialGroupName);
if (!nextActiveMaterialGroupName.equals(activeMaterialGroupName))
{
startedMaterialGroupNames.put(face, nextActiveMaterialGroupName);
}
activeMaterialGroupName = nextActiveMaterialGroupName;
nextActiveMaterialGroupName = null;
}
faces.add(face);
if (activeMaterialGroup != null)
{
activeMaterialGroup.addFace(face);
}
for (DefaultObjGroup group : activeGroups)
{
group.addFace(face);
}
}
@Override
public void addFace(int ... v)
{
addFace(v, null, null);
}
@Override
public void addFaceWithTexCoords(int... v)
{
addFace(v, v, null);
}
@Override
public void addFaceWithNormals(int... v)
{
addFace(v, null, v);
}
@Override
public void addFaceWithAll(int... v)
{
addFace(v, v, v);
}
@Override
public void addFace(int[] v, int[] vt, int[] vn)
{
Objects.requireNonNull(v, "The vertex indices are null");
checkIndices(v, getNumVertices(), "Vertex");
checkIndices(vt, getNumTexCoords(), "TexCoord");
checkIndices(vn, getNumNormals(), "Normal");
DefaultObjFace face = new DefaultObjFace(v, vt, vn);
addFace(face);
}
@Override
public void setMtlFileNames(Collection<? extends String> mtlFileNames)
{
this.mtlFileNames = Collections.unmodifiableList(
new ArrayList<String>(mtlFileNames));
}
@Override
public String toString()
{
return "Obj[" +
"#vertices="+ vertices.size() + "," +
"#texCoords=" + texCoords.size() + "," +
"#normals=" + normals.size() + "," +
"#faces=" + faces.size() + "," +
"#groups=" + groups.size() + "," +
"#materialGroups=" + materialGroups.size() + "," +
"mtlFileNames=" + mtlFileNames + "]";
}
/**
* Returns a set containing all groups with the given names. If the
* groups with the given names do not exist, they are created and
* added to this Obj.
*
* @param groupNames The group names
* @return The groups
*/
private List<DefaultObjGroup> getGroupsInternal(
Collection<? extends String> groupNames)
{
List<DefaultObjGroup> groups =
new ArrayList<>(groupNames.size());
for (String groupName : groupNames)
{
DefaultObjGroup group = getGroupInternal(groupName);
groups.add(group);
}
return groups;
}
/**
* Returns the group with the given names. If the group with the given
* name does not exist, it is created and added to this Obj.
*
* @param groupName The group name
* @return The group
*/
private DefaultObjGroup getGroupInternal(String groupName)
{
DefaultObjGroup group = groupMap.get(groupName);
if (group == null)
{
group = new DefaultObjGroup(groupName);
groupMap.put(groupName, group);
groups.add(group);
}
return group;
}
/**
* Returns the material group with the given names. If the material group
* with the given name does not exist, it is created and added to this Obj.
*
* @param materialGroupName The material group name
* @return The material group
*/
private DefaultObjGroup getMaterialGroupInternal(String materialGroupName)
{
DefaultObjGroup group = materialGroupMap.get(materialGroupName);
if (group == null)
{
group = new DefaultObjGroup(materialGroupName);
materialGroupMap.put(materialGroupName, group);
materialGroups.add(group);
}
return group;
}
/**
* If the given indices are <code>null</code>, then this method will
* do nothing. Otherwise, it will check whether the given indices
* are valid, and throw an IllegalArgumentException if not. They
* are valid when they are all not negative, and all smaller than
* the given maximum.
*
* @param indices The indices
* @param max The maximum index, exclusive
* @param name The name of the index set
* @throws IllegalArgumentException If the given indices are not valid
*/
private static void checkIndices(int[] indices, int max, String name)
{
if (indices == null)
{
return;
}
for (int index : indices) {
if (index < 0) {
throw new IllegalArgumentException(
name + " index is negative: " + index);
}
if (index >= max) {
throw new IllegalArgumentException(
name + " index is " + index +
", but must be smaller than " + max);
}
}
}
}
================================================
FILE: src/main/java/de/javagl/obj/DefaultObjFace.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
/**
* Default implementation of an ObjFace
*/
final class DefaultObjFace implements ObjFace
{
/**
* The vertex indices of this face
*/
private final int[] vertexIndices;
/**
* The texture coordinate indices of this face
*/
private final int[] texCoordIndices;
/**
* The normal indices of this face
*/
private final int[] normalIndices;
/**
* Creates a face from the given parameters. References to the
* given objects will be stored.
*
* @param vertexIndices The vertex indices
* @param texCoordIndices The texture coordinate indices
* @param normalIndices The normal indices
*/
DefaultObjFace(
int[] vertexIndices, int[] texCoordIndices, int[] normalIndices)
{
this.vertexIndices = vertexIndices;
this.texCoordIndices = texCoordIndices;
this.normalIndices = normalIndices;
}
@Override
public boolean containsTexCoordIndices()
{
return texCoordIndices != null;
}
@Override
public boolean containsNormalIndices()
{
return normalIndices != null;
}
@Override
public int getVertexIndex(int number)
{
return this.vertexIndices[number];
}
@Override
public int getTexCoordIndex(int number)
{
return this.texCoordIndices[number];
}
@Override
public int getNormalIndex(int number)
{
return this.normalIndices[number];
}
/**
* Set the specified index to the given value
*
* @param n The index to set
* @param index The value of the index
*/
void setVertexIndex(int n, int index)
{
vertexIndices[n] = index;
}
/**
* Set the specified index to the given value
*
* @param n The index to set
* @param index The value of the index
*/
void setNormalIndex(int n, int index)
{
normalIndices[n] = index;
}
/**
* Set the specified index to the given value
*
* @param n The index to set
* @param index The value of the index
*/
void setTexCoordIndex(int n, int index)
{
texCoordIndices[n] = index;
}
@Override
public int getNumVertices()
{
return this.vertexIndices.length;
}
@Override
public String toString()
{
String result = "ObjFace[";
for(int i = 0; i < getNumVertices(); i++)
{
result += vertexIndices[i];
if(texCoordIndices != null || normalIndices != null)
{
result += "/";
}
if(texCoordIndices != null)
{
result += texCoordIndices[i];
}
if(normalIndices != null)
{
result += "/" + normalIndices[i];
}
if(i < getNumVertices() - 1)
{
result += " ";
}
}
result += "]";
return result;
}
}
================================================
FILE: src/main/java/de/javagl/obj/DefaultObjGroup.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
import java.util.ArrayList;
import java.util.List;
/**
* Default implementation of an ObjGroup
*/
final class DefaultObjGroup implements ObjGroup
{
/**
* The name of this group.
*/
private String name;
/**
* The faces in this group
*/
private List<ObjFace> faces;
/**
* Creates a new ObjGroup with the given name
*
* @param name The name of this ObjGroup
*/
DefaultObjGroup(String name)
{
this.name = name;
faces = new ArrayList<>();
}
@Override
public String getName()
{
return name;
}
/**
* Add the given face to this group
*
* @param face The face to add
*/
void addFace(ObjFace face)
{
faces.add(face);
}
@Override
public int getNumFaces()
{
return faces.size();
}
@Override
public ObjFace getFace(int index)
{
return faces.get(index);
}
@Override
public String toString()
{
return "ObjGroup[name=" + name + ",#faces=" + faces.size() + "]";
}
}
================================================
FILE: src/main/java/de/javagl/obj/DefaultTextureOptions.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
import java.util.Objects;
/**
* Default implementation of {@link TextureOptions}
*/
final class DefaultTextureOptions implements TextureOptions
{
/**
* The file name
*/
private String fileName;
/**
* The horizontal blending state
*/
private Boolean blendu;
/**
* The vertical blending state
*/
private Boolean blendv;
/**
* The color correction state
*/
private Boolean cc;
/**
* The mip-map boost value
*/
private Float boost;
/**
* The map modifiers
*/
private FloatTuple mm;
/**
* The origin offset
*/
private FloatTuple o;
/**
* The scale
*/
private FloatTuple s;
/**
* The turbulence
*/
private FloatTuple t;
/**
* The texture resolution
*/
private Float texres;
/**
* The clamping state
*/
private Boolean clamp;
/**
* The bump multiplier
*/
private Float bm;
/**
* The IMF channel
*/
private String imfchan;
/**
* The type
*/
private String type;
/**
* Default constructor
*/
DefaultTextureOptions()
{
// Default constructor
}
@Override
public String getFileName()
{
return fileName;
}
@Override
public void setFileName(String fileName)
{
this.fileName = fileName;
}
@Override
public Boolean isBlendu()
{
return blendu;
}
@Override
public void setBlendu(Boolean blendu)
{
this.blendu = blendu;
}
@Override
public Boolean isBlendv()
{
return blendv;
}
@Override
public void setBlendv(Boolean blendv)
{
this.blendv = blendv;
}
@Override
public Float getBoost()
{
return boost;
}
@Override
public Boolean isCc()
{
return cc;
}
@Override
public void setCc(Boolean cc)
{
this.cc = cc;
}
@Override
public void setBoost(Float boost)
{
this.boost = boost;
}
@Override
public FloatTuple getMm()
{
return mm;
}
@Override
public void setMm(Float base, Float gain)
{
if (base == null && gain == null)
{
this.mm = null;
}
float baseValue = (base == null ? 0.0f : base);
float gainValue = (gain == null ? 1.0f : gain);
this.mm = FloatTuples.create(baseValue, gainValue);
}
@Override
public FloatTuple getO()
{
return o;
}
@Override
public void setO(Float u, Float v, Float w)
{
this.o = Utils.createUvwTuple(u, v, w, 0.0f);
}
@Override
public FloatTuple getS()
{
return s;
}
@Override
public void setS(Float u, Float v, Float w)
{
this.s = Utils.createUvwTuple(u, v, w, 1.0f);
}
@Override
public FloatTuple getT()
{
return t;
}
@Override
public void setT(Float u, Float v, Float w)
{
this.t = Utils.createUvwTuple(u, v, w, 0.0f);
}
@Override
public Float getTexres()
{
return texres;
}
@Override
public void setTexres(Float texres)
{
this.texres = texres;
}
@Override
public Boolean isClamp()
{
return clamp;
}
@Override
public void setClamp(Boolean clamp)
{
this.clamp = clamp;
}
@Override
public Float getBm()
{
return bm;
}
@Override
public void setBm(Float bm)
{
this.bm = bm;
}
@Override
public String getImfchan()
{
return imfchan;
}
@Override
public void setImfchan(String imfchan)
{
this.imfchan = imfchan;
}
@Override
public String getType()
{
return type;
}
@Override
public void setType(String type)
{
this.type = type;
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("TextureOptions");
sb.append("[");
sb.append(MtlWriter.createString(this));
sb.append("]");
return sb.toString();
}
@Override
public int hashCode()
{
return Objects.hash(blendu, blendv, cc, bm, boost, clamp, fileName,
imfchan, mm, o, s, t, texres, type);
}
@Override
public boolean equals(Object object)
{
if (this == object)
{
return true;
}
if (object == null)
{
return false;
}
if (!(object instanceof TextureOptions))
{
return false;
}
TextureOptions other = (TextureOptions) object;
return
Objects.equals(isBlendu(), other.isBlendu()) &&
Objects.equals(isBlendv(), other.isBlendv()) &&
Objects.equals(isCc(), other.isCc()) &&
Objects.equals(getBm(), other.getBm()) &&
Objects.equals(getBoost(), other.getBoost()) &&
Objects.equals(isClamp(), other.isClamp()) &&
Objects.equals(getFileName(), other.getFileName()) &&
Objects.equals(getImfchan(), other.getImfchan()) &&
Objects.equals(getMm(), other.getMm()) &&
Objects.equals(getO(), other.getO()) &&
Objects.equals(getS(), other.getS()) &&
Objects.equals(getT(), other.getT()) &&
Objects.equals(getTexres(), other.getTexres()) &&
Objects.equals(getType(), other.getType());
}
}
================================================
FILE: src/main/java/de/javagl/obj/FloatTuple.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
/**
* Interface for tuples consisting of float values
*/
public interface FloatTuple
{
/**
* Return the x-component of this tuple
*
* @return The x-component of this tuple
* @throws IndexOutOfBoundsException If this tuple has less than 1
* dimension
*/
float getX();
/**
* Return the y-component of this tuple
*
* @return The y-component of this tuple
* @throws IndexOutOfBoundsException If this tuple has less than 2
* dimensions
*/
float getY();
/**
* Return the z-component of this tuple
*
* @return The z-component of this tuple
* @throws IndexOutOfBoundsException If this tuple has less than 3
* dimensions
*/
float getZ();
/**
* Return the w-component of this tuple
*
* @return The w-component of this tuple
* @throws IndexOutOfBoundsException If this tuple has less than 4
* dimensions
*/
float getW();
/**
* Return the specified component of this tuple
*
* @param index The index of the component
* @return The specified component of this tuple
* @throws IndexOutOfBoundsException If the given index is negative
* or not smaller than the {@link #getDimensions() dimensions}
*/
float get(int index);
/**
* Return the dimensions of this tuple
*
* @return The dimensions of this tuple
*/
int getDimensions();
}
================================================
FILE: src/main/java/de/javagl/obj/FloatTuples.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
/**
* Methods to create {@link FloatTuple} instances
*/
public class FloatTuples
{
/**
* Create a copy of the given {@link FloatTuple}
*
* @param other The other tuple
* @return The {@link FloatTuple}
*/
public static FloatTuple copy(FloatTuple other)
{
return new DefaultFloatTuple(other);
}
/**
* Create a new {@link FloatTuple} with the given coordinate
*
* @param x The x-coordinate
* @return The {@link FloatTuple}
*/
public static FloatTuple create(float x)
{
return new DefaultFloatTuple(x);
}
/**
* Create a new {@link FloatTuple} with the given coordinates
*
* @param x The x-coordinate
* @param y The y-coordinate
* @return The {@link FloatTuple}
*/
public static FloatTuple create(float x, float y)
{
return new DefaultFloatTuple(x, y);
}
/**
* Create a new {@link FloatTuple} with the given coordinates
*
* @param x The x-coordinate
* @param y The y-coordinate
* @param z The z-coordinate
* @return The {@link FloatTuple}
*/
public static FloatTuple create(float x, float y, float z)
{
return new DefaultFloatTuple(x, y, z);
}
/**
* Create a new {@link FloatTuple} with the given coordinates
*
* @param x The x-coordinate
* @param y The y-coordinate
* @param z The z-coordinate
* @param w The w-coordinate
* @return The {@link FloatTuple}
*/
public static FloatTuple create(float x, float y, float z, float w)
{
return new DefaultFloatTuple(x, y, z, w);
}
/**
* Returns the string for the given tuple that is used for representing
* the given tuple in an OBJ file
*
* @param tuple The tuple
* @return The string for the given tuple
*/
public static String createString(FloatTuple tuple)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < tuple.getDimensions(); i++)
{
if (i > 0)
{
sb.append(" ");
}
sb.append(tuple.get(i));
}
return sb.toString();
}
/**
* Private constructor to prevent instantiation
*/
private FloatTuples()
{
// Private constructor to prevent instantiation
}
}
================================================
FILE: src/main/java/de/javagl/obj/Mtl.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
import java.util.List;
/**
* An in-memory representation of an MTL file. For details about the
* semantics of the properties in this interface, refer to the MTL
* specification.
*/
public interface Mtl
{
/**
* Return the name of the material
*
* @return The name of the material
*/
String getName();
/**
* Returns the illumination mode (<code>-illum</code>) of the material,
* or <code>null</code> if it was not specified
*
* @return The illumination mode of the material.
*/
Integer getIllum();
/**
* Set the illumination mode of the material
*
* @param illum The illumination mode of the material.
*/
void setIllum(Integer illum);
/**
* Returns the optical density, also known as index of refraction, of
* the material, or <code>null</code> if it was not specified
*
* @return The optical density
*/
Float getNi();
/**
* Set the optical density of the material
*
* @param ni The optical density
*/
void setNi(Float ni);
/**
* Returns the transmission filter of the material,
* or <code>null</code> if it was not specified
*
* @return The transmission filter
*/
FloatTuple getTf();
/**
* Set the transmission filter of this material
*
* @param r The red component
* @param g The green component
* @param b The blue component
*/
void setTf(Float r, Float g, Float b);
/**
* Returns the sharpness of reflections from the reflection map,
* or <code>null</code> if it was not specified
*
* @return The sharpness
*/
Float getSharpness();
/**
* Set the sharpness of reflections
*
* @param sharpness The sharpness
*/
void setSharpness(Float sharpness);
//--------------------------------------------------------------------------
// Ambient
/**
* Returns the ambient component of the material,
* or <code>null</code> if it was not specified
*
* @return The ambient component of the material
*/
FloatTuple getKa();
/**
* Set the ambient part of this material
*
* @param r The red component
* @param g The green component
* @param b The blue component
*/
void setKa(Float r, Float g, Float b);
/**
* Returns the name of the ambient map of the material,
* or <code>null</code> if it has no such map.
*
* @return The name of the ambient map of the material
*/
String getMapKa();
/**
* Set the ambient map name of this material
*
* @param mapKa The ambient map name of this material
*/
void setMapKa(String mapKa);
/**
* Returns the ambient map options of the material,
* or <code>null</code> if it has no options.
*
* @return The ambient map {@link TextureOptions}
*/
TextureOptions getMapKaOptions();
/**
* Set the ambient map {@link TextureOptions}
*
* @param options The ambient map {@link TextureOptions}
*/
void setMapKaOptions(TextureOptions options);
//--------------------------------------------------------------------------
// Diffuse
/**
* Returns the diffuse component of the material,
* or <code>null</code> if it was not specified
*
* @return The diffuse component of the material
*/
FloatTuple getKd();
/**
* Set the diffuse part of this material
*
* @param r The red component
* @param g The green component
* @param b The blue component
*/
void setKd(Float r, Float g, Float b);
/**
* Returns the name of the diffuse map of the material,
* or <code>null</code> if it has no such map.
*
* @return The name of the diffuse map of the material
*/
String getMapKd();
/**
* Set the diffuse map name of this material
*
* @param mapKd The diffuse map name of this material
*/
void setMapKd(String mapKd);
/**
* Returns the diffuse map options of the material,
* or <code>null</code> if it has no options.
*
* @return The diffuse map {@link TextureOptions}
*/
TextureOptions getMapKdOptions();
/**
* Set the diffuse map {@link TextureOptions}
*
* @param options The diffuse map {@link TextureOptions}
*/
void setMapKdOptions(TextureOptions options);
//--------------------------------------------------------------------------
// Specular reflectivity
/**
* Returns the specular component of the material,
* or <code>null</code> if it was not specified
*
* @return The specular component of the material
*/
FloatTuple getKs();
/**
* Set the specular part of this material
*
* @param r The red component
* @param g The green component
* @param b The blue component
*/
void setKs(Float r, Float g, Float b);
/**
* Returns the name of the specular reflectivity map of the material,
* or <code>null</code> if it has no such map.
*
* @return The name of the specular reflectivity map of the material
*/
String getMapKs();
/**
* Set the specular reflectivity map name of this material
*
* @param mapKs The specular reflectivity map name of this material
*/
void setMapKs(String mapKs);
/**
* Returns the specular reflectivity map options of the material,
* or <code>null</code> if it has no options.
*
* @return The specular reflectivity map {@link TextureOptions}
*/
TextureOptions getMapKsOptions();
/**
* Set the specular reflectivity map {@link TextureOptions}
*
* @param options The specular reflectivity map {@link TextureOptions}
*/
void setMapKsOptions(TextureOptions options);
//--------------------------------------------------------------------------
// Specular exponent (shininess)
/**
* Returns the shininess of the material.
*
* @return The shininess of the material.
*/
Float getNs();
/**
* Set the shininess of this material,
* or <code>null</code> if it was not specified
*
* @param ns The shininess of this material
*/
void setNs(Float ns);
/**
* Returns the name of the shininess map of the material,
* or <code>null</code> if it has no map.
*
* @return The name of the shininess map of the material
*/
String getMapNs();
/**
* Set the shininess map name of this material
*
* @param mapNs The shininess map name of this material
*/
void setMapNs(String mapNs);
/**
* Returns the shininess map options of the material,
* or <code>null</code> if it has no options.
*
* @return The shininess map {@link TextureOptions}
*/
TextureOptions getMapNsOptions();
/**
* Set the shininess map {@link TextureOptions}
*
* @param options The shininess map {@link TextureOptions}
*/
void setMapNsOptions(TextureOptions options);
//--------------------------------------------------------------------------
// Opacity
/**
* Returns the opacity of the material,
* or <code>null</code> if it was not specified
*
* @return The opacity of the material.
*/
Float getD();
/**
* Set the opacity of the material
*
* @param d The opacity of the material
*/
void setD(Float d);
/**
* Returns whether dissolve (opacity) is dependent on the surface
* orientation relative to the viewer
*
* @return The halo flag
*/
Boolean isHalo();
/**
* Set the halo flag
*
* @param halo The halo flag
*/
void setHalo(Boolean halo);
/**
* Returns the name of the opacity map of the material,
* or <code>null</code> if it has no map.
*
* @return The name of the opacity map of the material
*/
String getMapD();
/**
* Set the opacity map name of this material
*
* @param mapD The opacity map name of this material
*/
void setMapD(String mapD);
/**
* Returns the opacity map options of the material,
* or <code>null</code> if it has no options.
*
* @return The opacity map {@link TextureOptions}
*/
TextureOptions getMapDOptions();
/**
* Set the opacity map {@link TextureOptions}
*
* @param options The opacity map {@link TextureOptions}
*/
void setMapDOptions(TextureOptions options);
//--------------------------------------------------------------------------
// Bump
/**
* Returns the name of the bump map of the material,
* or <code>null</code> if it has no map.
*
* @return The name of the bump map of the material
*/
String getBump();
/**
* Set the bump map name of this material
*
* @param bump The bump map name of this material
*/
void setBump(String bump);
/**
* Returns the bump map options of the material,
* or <code>null</code> if it has no options.
*
* @return The bump map {@link TextureOptions}
*/
TextureOptions getBumpOptions();
/**
* Set the bump map {@link TextureOptions}
*
* @param options The bump map {@link TextureOptions}
*/
void setBumpOptions(TextureOptions options);
//--------------------------------------------------------------------------
// Disp (displacement)
/**
* Returns the name of the displacement map of the material,
* or <code>null</code> if it has no map.
*
* @return The name of the displacement map of the material
*/
String getDisp();
/**
* Set the displacement map name of this material
*
* @param disp The displacement map name of this material
*/
void setDisp(String disp);
/**
* Returns the displacement map options of the material,
* or <code>null</code> if it has no options.
*
* @return The displacement map {@link TextureOptions}
*/
TextureOptions getDispOptions();
/**
* Set the displacement map {@link TextureOptions}
*
* @param options The displacement map {@link TextureOptions}
*/
void setDispOptions(TextureOptions options);
//--------------------------------------------------------------------------
// Decal
/**
* Returns the name of the decal map of the material,
* or <code>null</code> if it has no map.
*
* @return The name of the decal map of the material
*/
String getDecal();
/**
* Set the decal map name of this material
*
* @param decal The decal map name of this material
*/
void setDecal(String decal);
/**
* Returns the decal map options of the material,
* or <code>null</code> if it has no options.
*
* @return The decal map {@link TextureOptions}
*/
TextureOptions getDecalOptions();
/**
* Set the decal map {@link TextureOptions}
*
* @param options The decal map {@link TextureOptions}
*/
void setDecalOptions(TextureOptions options);
//--------------------------------------------------------------------------
// Refl (reflection)
/**
* Returns the list of {@link TextureOptions} objects for the reflection
* maps of the material. This will never be <code>null</code>, but may
* be an empty list if no reflection maps have been defined.
*
* @return The reflection map {@link TextureOptions}
*/
List<TextureOptions> getReflOptions();
//==========================================================================
// PBR parameters:
//--------------------------------------------------------------------------
// Roughness
/**
* Returns the roughness component of the material,
* or <code>null</code> if it was not specified
*
* @return The roughness component of the material
*/
Float getPr();
/**
* Set the roughness part of this material
*
* @param pr The roughness
*/
void setPr(Float pr);
/**
* Returns the name of the roughness map of the material,
* or <code>null</code> if it has no such map.
*
* @return The name of the roughness map of the material
*/
String getMapPr();
/**
* Set the roughness map name of this material
*
* @param mapPr The roughness map name of this material
*/
void setMapPr(String mapPr);
/**
* Returns the roughness map options of the material,
* or <code>null</code> if it has no options.
*
* @return The roughness map {@link TextureOptions}
*/
TextureOptions getMapPrOptions();
/**
* Set the roughness map {@link TextureOptions}
*
* @param options The roughness map {@link TextureOptions}
*/
void setMapPrOptions(TextureOptions options);
//--------------------------------------------------------------------------
// Metallic
/**
* Returns the metallic component of the material,
* or <code>null</code> if it was not specified
*
* @return The metallic component of the material
*/
Float getPm();
/**
* Set the metallic part of this material
*
* @param pm The metallic part
*/
void setPm(Float pm);
/**
* Returns the name of the metallic map of the material,
* or <code>null</code> if it has no such map.
*
* @return The name of the metallic map of the material
*/
String getMapPm();
/**
* Set the metallic map name of this material
*
* @param mapPm The metallic map name of this material
*/
void setMapPm(String mapPm);
/**
* Returns the metallic map options of the material,
* or <code>null</code> if it has no options.
*
* @return The metallic map {@link TextureOptions}
*/
TextureOptions getMapPmOptions();
/**
* Set the metallic map {@link TextureOptions}
*
* @param options The metallic map {@link TextureOptions}
*/
void setMapPmOptions(TextureOptions options);
//--------------------------------------------------------------------------
// Sheen
/**
* Returns the sheen component of the material,
* or <code>null</code> if it was not specified
*
* @return The sheen component of the material
*/
Float getPs();
/**
* Set the sheen part of this material
*
* @param ps The sheen part
*/
void setPs(Float ps);
/**
* Returns the name of the sheen map of the material,
* or <code>null</code> if it has no such map.
*
* @return The name of the sheen map of the material
*/
String getMapPs();
/**
* Set the sheen map name of this material
*
* @param mapPs The sheen map name of this material
*/
void setMapPs(String mapPs);
/**
* Returns the sheen map options of the material,
* or <code>null</code> if it has no options.
*
* @return The sheen map {@link TextureOptions}
*/
TextureOptions getMapPsOptions();
/**
* Set the sheen map {@link TextureOptions}
*
* @param options The sheen map {@link TextureOptions}
*/
void setMapPsOptions(TextureOptions options);
//--------------------------------------------------------------------------
// Pc (clearcoat thickness)
/**
* Returns the clearcoat thickness of the material,
* or <code>null</code> if it was not specified
*
* @return The clearcoat thickness
*/
Float getPc();
/**
* Set the clearcoat thickness of the material
*
* @param pc The clearcoat thickness
*/
void setPc(Float pc);
//--------------------------------------------------------------------------
// Pcr (clearcoat roughness)
/**
* Returns the clearcoat roughness of the material,
* or <code>null</code> if it was not specified
*
* @return The clearcoat roughness
*/
Float getPcr();
/**
* Set the clearcoat roughness of the material
*
* @param pcr The clearcoat roughness
*/
void setPcr(Float pcr);
//--------------------------------------------------------------------------
// Emissive
/**
* Returns the emissive component of the material,
* or <code>null</code> if it was not specified
*
* @return The emissive component of the material
*/
FloatTuple getKe();
/**
* Set the emissive part of this material
*
* @param r The red component
* @param g The green component
* @param b The blue component
*/
void setKe(Float r, Float g, Float b);
/**
* Returns the name of the emissive map of the material,
* or <code>null</code> if it has no such map.
*
* @return The name of the emissive map of the material
*/
String getMapKe();
/**
* Set the emissive map name of this material
*
* @param mapKe The emissive map name of this material
*/
void setMapKe(String mapKe);
/**
* Returns the emissive map options of the material,
* or <code>null</code> if it has no options.
*
* @return The emissive map {@link TextureOptions}
*/
TextureOptions getMapKeOptions();
/**
* Set the emissive map {@link TextureOptions}
*
* @param options The emissive map {@link TextureOptions}
*/
void setMapKeOptions(TextureOptions options);
//--------------------------------------------------------------------------
// aniso (anisotropy)
/**
* Returns the anisotropy of the material,
* or <code>null</code> if it was not specified
*
* @return The anisotropy
*/
Float getAniso();
/**
* Set the anisotropy of the material
*
* @param aniso The anisotropy
*/
void setAniso(Float aniso);
//--------------------------------------------------------------------------
// anisor (anisotropy rotation)
/**
* Returns the anisotropy rotation of the material,
* or <code>null</code> if it was not specified
*
* @return The anisotropy rotation
*/
Float getAnisor();
/**
* Set the anisotropy rotation of the material
*
* @param anisor The anisotropy rotation
*/
void setAnisor(Float anisor);
//--------------------------------------------------------------------------
// Normal
/**
* Returns the name of the normal map of the material,
* or <code>null</code> if it has no such map.
*
* @return The name of the normal map of the material
*/
String getNorm();
/**
* Set the normal map name of this material
*
* @param norm The normal map name of this material
*/
void setNorm(String norm);
/**
* Returns the normal map options of the material,
* or <code>null</code> if it has no options.
*
* @return The normal map {@link TextureOptions}
*/
TextureOptions getNormOptions();
/**
* Set the normal map {@link TextureOptions}
*
* @param options The normal map {@link TextureOptions}
*/
void setNormOptions(TextureOptions options);
}
================================================
FILE: src/main/java/de/javagl/obj/MtlReader.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
/**
* A class that may read MTL data, and return the materials as a
* list of {@link Mtl} objects.
*/
public class MtlReader
{
/**
* Read the MTL data from the given stream, and return
* it as {@link Mtl} objects.
* The caller is responsible for closing the given stream.
*
* @param inputStream The stream to read from.
* @return The list of Mtl object.
* @throws IOException If an IO error occurs
*/
public static List<Mtl> read(InputStream inputStream)
throws IOException
{
BufferedReader reader = new BufferedReader(
new InputStreamReader(inputStream));
return readImpl(reader);
}
/**
* Read the MTL data from the given reader, and return
* it as {@link Mtl} objects.
* The caller is responsible for closing the given reader.
*
* @param reader The reader to read from.
* @return The list of Mtl object.
* @throws IOException If an IO error occurs
*/
public static List<Mtl> read(Reader reader)
throws IOException
{
if (reader instanceof BufferedReader)
{
return readImpl((BufferedReader)reader);
}
return readImpl(new BufferedReader(reader));
}
/**
* Read the MTL data from the given reader, and return
* it as {@link Mtl} objects.
* The caller is responsible for closing the given reader.
*
* @param reader The reader to read from.
* @return The list of Mtl object.
* @throws IOException If an IO error occurs
*/
private static List<Mtl> readImpl(BufferedReader reader)
throws IOException
{
List<Mtl> mtlList = new ArrayList<>();
Mtl currentMtl = null;
while(true)
{
String line = reader.readLine();
if(line == null)
{
break;
}
line = line.trim();
//System.out.println("read line: "+line);
// Combine lines that have been broken
boolean finished = false;
while(line.endsWith("\\"))
{
line = line.substring(0, line.length() - 2);
String nextLine = reader.readLine();
if (nextLine == null)
{
finished = true;
break;
}
line += " " + nextLine;
}
if (finished)
{
break;
}
line = line.trim();
if (line.startsWith("newmtl"))
{
String name = line.substring("newmtl".length()).trim();
currentMtl = new DefaultMtl(name);
mtlList.add(currentMtl);
}
else if (!line.startsWith("#") && !line.isEmpty())
{
if (currentMtl == null)
{
throw new IOException(
"Missing newmtl statement before " + line);
}
processLine(currentMtl, line);
}
}
return mtlList;
}
/**
* Process one (trimmed) line that is part of a <code>newmtl</code>
* material definition, and write the result into the given {@link Mtl}.
*
* @param mtl The {@link Mtl}
* @param line The line
* @throws IOException If an IO error occurs
*/
private static void processLine(Mtl mtl, String line)
throws IOException
{
Queue<String> tokens =
new LinkedList<>(Arrays.asList(line.split("[ \t\n\r\f]+")));
String command = tokens.poll();
// Illumination mode
if (command.equalsIgnoreCase("illum"))
{
int value = Utils.parseInt(tokens.poll());
mtl.setIllum(value);
}
// Color values: R, and optional G and B
if (command.equalsIgnoreCase("Ka"))
{
Float[] values = Utils.parseFloats(tokens, 3);
mtl.setKa(values[0], values[1], values[2]);
}
else if (command.equalsIgnoreCase("Kd"))
{
Float[] values = Utils.parseFloats(tokens, 3);
mtl.setKd(values[0], values[1], values[2]);
}
else if (command.equalsIgnoreCase("Ks"))
{
Float[] values = Utils.parseFloats(tokens, 3);
mtl.setKs(values[0], values[1], values[2]);
}
else if (command.equalsIgnoreCase("Tf"))
{
Float[] values = Utils.parseFloats(tokens, 3);
mtl.setTf(values[0], values[1], values[2]);
}
// Color values for PBR
else if (command.equalsIgnoreCase("Ke"))
{
Float[] values = Utils.parseFloats(tokens, 3);
mtl.setKe(values[0], values[1], values[2]);
}
// Single float values
else if (command.equalsIgnoreCase("Tr"))
{
float value = Utils.parseFloat(tokens.poll());
mtl.setD(1.0f - value);
}
else if (command.equalsIgnoreCase("sharpness"))
{
float value = Utils.parseFloat(tokens.poll());
mtl.setSharpness(value);
}
else if (command.equalsIgnoreCase("d"))
{
String token = tokens.peek();
if ("-halo".equals(token))
{
mtl.setHalo(true);
tokens.poll();
}
float value = Utils.parseFloat(tokens.poll());
mtl.setD(value);
}
else if (command.equalsIgnoreCase("Ni"))
{
float value = Utils.parseFloat(tokens.poll());
mtl.setNi(value);
}
else if (command.equalsIgnoreCase("Ns"))
{
float value = Utils.parseFloat(tokens.poll());
mtl.setNs(value);
}
// Single float values for PBR
else if (command.equalsIgnoreCase("Pr"))
{
float value = Utils.parseFloat(tokens.poll());
mtl.setPr(value);
}
else if (command.equalsIgnoreCase("Pm"))
{
float value = Utils.parseFloat(tokens.poll());
mtl.setPm(value);
}
else if (command.equalsIgnoreCase("Ps"))
{
float value = Utils.parseFloat(tokens.poll());
mtl.setPs(value);
}
else if (command.equalsIgnoreCase("Pc"))
{
float value = Utils.parseFloat(tokens.poll());
mtl.setPc(value);
}
else if (command.equalsIgnoreCase("Pcr"))
{
float value = Utils.parseFloat(tokens.poll());
mtl.setPcr(value);
}
else if (command.equalsIgnoreCase("aniso"))
{
float value = Utils.parseFloat(tokens.poll());
mtl.setAniso(value);
}
else if (command.equalsIgnoreCase("anisor"))
{
float value = Utils.parseFloat(tokens.poll());
mtl.setAnisor(value);
}
// Texture map definitions
else
{
readTextureMap(mtl, command, tokens);
}
}
/**
* Process the line of an MTL file that is supposed to contain a
* texture map definition, and write the resulting texture
* information into the given {@link Mtl}.<br>
* <br>
* The texture definition will be determined from the given command,
* which may, for example, be <code>"map_Ka"</code> or
* <code>"refl"</code>
*
* @param mtl The {@link Mtl}
* @param command The command at the beginning of the line
* @param tokens The tokens that have been created from the line
* @throws IOException If an IO error occurs
*/
private static void readTextureMap(
Mtl mtl, String command, Queue<String> tokens)
throws IOException
{
if (command.equalsIgnoreCase("map_Ka"))
{
mtl.setMapKaOptions(readTextureOptions(tokens));
}
else if (command.equalsIgnoreCase("map_Kd"))
{
mtl.setMapKdOptions(readTextureOptions(tokens));
}
else if (command.equalsIgnoreCase("map_Ks"))
{
mtl.setMapKsOptions(readTextureOptions(tokens));
}
else if (command.equalsIgnoreCase("map_d"))
{
mtl.setMapDOptions(readTextureOptions(tokens));
}
else if (command.equalsIgnoreCase("map_Ns"))
{
mtl.setMapNsOptions(readTextureOptions(tokens));
}
else if (command.equalsIgnoreCase("bump")
|| command.equalsIgnoreCase("map_bump"))
{
mtl.setBumpOptions(readTextureOptions(tokens));
}
else if (command.equalsIgnoreCase("disp"))
{
mtl.setDispOptions(readTextureOptions(tokens));
}
else if (command.equalsIgnoreCase("decal"))
{
mtl.setDecalOptions(readTextureOptions(tokens));
}
else if (command.equalsIgnoreCase("refl"))
{
TextureOptions refl = readTextureOptions(tokens);
mtl.getReflOptions().add(refl);
}
// Texture map definitions for PBR
else if (command.equalsIgnoreCase("map_Pr"))
{
mtl.setMapPrOptions(readTextureOptions(tokens));
}
else if (command.equalsIgnoreCase("map_Pm"))
{
mtl.setMapPmOptions(readTextureOptions(tokens));
}
else if (command.equalsIgnoreCase("map_Ps"))
{
mtl.setMapPsOptions(readTextureOptions(tokens));
}
else if (command.equalsIgnoreCase("map_Ke"))
{
mtl.setMapKeOptions(readTextureOptions(tokens));
}
else if (command.equalsIgnoreCase("norm"))
{
mtl.setNormOptions(readTextureOptions(tokens));
}
}
/**
* Process the tokens in the given queue and construct a
* {@link TextureOptions} object from them
*
* @param tokens The input token
* @return The {@link TextureOptions}
* @throws IOException If an IO error occurs
*/
static TextureOptions readTextureOptions(Queue<String> tokens)
throws IOException {
DefaultTextureOptions textureOptions = new DefaultTextureOptions();
while (!tokens.isEmpty())
{
String optionName = tokens.poll();
if (optionName.equalsIgnoreCase("-blendu"))
{
boolean value = Utils.parseBoolean(tokens.poll());
textureOptions.setBlendu(value);
}
else if (optionName.equalsIgnoreCase("-blendv"))
{
boolean value = Utils.parseBoolean(tokens.poll());
textureOptions.setBlendv(value);
}
else if (optionName.equalsIgnoreCase("-boost"))
{
float value = Utils.parseFloat(tokens.poll());
textureOptions.setBoost(value);
}
else if (optionName.equalsIgnoreCase("-cc"))
{
boolean value = Utils.parseBoolean(tokens.poll());
textureOptions.setCc(value);
}
else if (optionName.equalsIgnoreCase("-mm"))
{
float base = Utils.parseFloat(tokens.poll());
float gain = Utils.parseFloat(tokens.poll());
textureOptions.setMm(base, gain);
}
else if (optionName.equalsIgnoreCase("-o"))
{
Float[] values = Utils.parseFloats(tokens, 3);
textureOptions.setO(values[0], values[1], values[2]);
}
else if (optionName.equalsIgnoreCase("-s"))
{
Float[] values = Utils.parseFloats(tokens, 3);
textureOptions.setS(values[0], values[1], values[2]);
}
else if (optionName.equalsIgnoreCase("-t"))
{
Float[] values = Utils.parseFloats(tokens, 3);
textureOptions.setT(values[0], values[1], values[2]);
}
else if (optionName.equalsIgnoreCase("-texres"))
{
float value = Utils.parseFloat(tokens.poll());
textureOptions.setTexres(value);
}
else if (optionName.equalsIgnoreCase("-clamp"))
{
boolean value = Utils.parseBoolean(tokens.poll());
textureOptions.setClamp(value);
}
else if (optionName.equalsIgnoreCase("-bm"))
{
float value = Utils.parseFloat(tokens.poll());
textureOptions.setBm(value);
}
else if (optionName.equalsIgnoreCase("-imfchan"))
{
String value = tokens.poll();
textureOptions.setImfchan(value);
}
else if (optionName.equalsIgnoreCase("-type"))
{
String value = tokens.poll();
textureOptions.setType(value);
}
else
{
textureOptions.setFileName(optionName);
}
}
return textureOptions;
}
/**
* Private constructor to prevent instantiation
*/
private MtlReader()
{
// Private constructor to prevent instantiation
}
}
================================================
FILE: src/main/java/de/javagl/obj/MtlWriter.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.List;
/**
* A class that may write {@link Mtl} objects into an MTL file
*/
public class MtlWriter
{
/**
* Write the given {@link Mtl} objects to the given stream. The caller
* is responsible for closing the stream.
*
* @param mtls The {@link Mtl} objects
* @param outputStream The stream to write to
* @throws IOException If an IO error occurs
*/
public static void write(
Iterable<? extends Mtl> mtls, OutputStream outputStream)
throws IOException
{
OutputStreamWriter outputStreamWriter =
new OutputStreamWriter(outputStream);
write(mtls, outputStreamWriter);
}
/**
* Write the given {@link Mtl} objects to the given writer. The caller
* is responsible for closing the writer.
*
* @param mtls The {@link Mtl} objects
* @param writer The writer to write to
* @throws IOException If an IO error occurs
*/
public static void write(
Iterable<? extends Mtl> mtls, Writer writer)
throws IOException
{
for (Mtl mtl : mtls)
{
write(mtl, writer);
}
}
/**
* Write the given {@link Mtl} to the given writer
*
* @param mtl The {@link Mtl}
* @param writer The writer
* @throws IOException If an IO error occurs
*/
private static void write(Mtl mtl, Writer writer)
throws IOException
{
writer.write(createString(mtl));
writer.flush();
}
/**
* Create the string representation of the given {@link Mtl}, as it
* is written into an MTL file
*
* @param mtl The {@link Mtl}
* @return The string representation
*/
private static String createString(Mtl mtl)
{
StringBuilder sb = new StringBuilder("newmtl ");
sb.append(mtl.getName()).append("\n");
append(sb, "illum", mtl.getIllum(), "\n");
append(sb, "Ns", mtl.getNs(), "\n");
append(sb, "Ni", mtl.getNi(), "\n");
Float opacity = mtl.getD();
if (opacity != null)
{
sb.append("d").append(" ");
if (Boolean.TRUE.equals(mtl.isHalo()))
{
sb.append("-halo").append(" ");
}
sb.append(opacity);
sb.append("\n");
}
appendTuple(sb, "Ka", mtl.getKa(), "\n");
appendTuple(sb, "Kd", mtl.getKd(), "\n");
appendTuple(sb, "Ks", mtl.getKs(), "\n");
appendTuple(sb, "Tf", mtl.getTf(), "\n");
append(sb, "sharpness", mtl.getSharpness(), "\n");
appendTextureOptions(sb, "map_Ka", mtl.getMapKaOptions());
appendTextureOptions(sb, "map_Kd", mtl.getMapKdOptions());
appendTextureOptions(sb, "map_Ks", mtl.getMapKsOptions());
appendTextureOptions(sb, "map_Ns", mtl.getMapNsOptions());
appendTextureOptions(sb, "map_d", mtl.getMapDOptions());
appendTextureOptions(sb, "bump", mtl.getBumpOptions());
appendTextureOptions(sb, "disp", mtl.getDispOptions());
appendTextureOptions(sb, "decal", mtl.getDecalOptions());
List<TextureOptions> refls = mtl.getReflOptions();
for (TextureOptions refl : refls)
{
appendTextureOptions(sb, "refl", refl);
}
// PBR parameters
append(sb, "Pr", mtl.getPr(), "\n");
appendTextureOptions(sb, "map_Pr", mtl.getMapPrOptions());
append(sb, "Pm", mtl.getPm(), "\n");
appendTextureOptions(sb, "map_Pm", mtl.getMapPmOptions());
append(sb, "Ps", mtl.getPs(), "\n");
appendTextureOptions(sb, "map_Ps", mtl.getMapPsOptions());
append(sb, "Pc", mtl.getPc(), "\n");
append(sb, "Pcr", mtl.getPcr(), "\n");
appendTuple(sb, "Ke", mtl.getKe(), "\n");
appendTextureOptions(sb, "map_Ke", mtl.getMapKeOptions());
append(sb, "aniso", mtl.getAniso(), "\n");
append(sb, "anisor", mtl.getAnisor(), "\n");
appendTextureOptions(sb, "norm", mtl.getNormOptions());
return sb.toString();
}
/**
* Append the given {@link TextureOptions} to the given string builder,
* if they are not <code>null</code>
*
* @param sb The string builder
* @param key The key
* @param options The {@link TextureOptions}
*/
private static void appendTextureOptions(
StringBuilder sb, String key, TextureOptions options)
{
if (options != null)
{
sb.append(key).append(" ");
sb.append(createString(options)).append("\n");
}
}
/**
* Create the string representation for the given {@link TextureOptions},
* as a single line that may be written to the MTL file
*
* @param options The {@link TextureOptions}
* @return The string representation
*/
static String createString(TextureOptions options)
{
StringBuilder sb = new StringBuilder();
append(sb, "-blendu", options.isBlendu(), " ");
append(sb, "-blendv", options.isBlendv(), " ");
append(sb, "-boost", options.getBoost(), " ");
appendTuple(sb, "-mm", options.getMm(), " ");
appendTuple(sb, "-o", options.getO(), " ");
appendTuple(sb, "-s", options.getS(), " ");
appendTuple(sb, "-t", options.getT(), " ");
append(sb, "-texres", options.getTexres(), " ");
append(sb, "-clamp", options.isClamp(), " ");
append(sb, "-bm", options.getBm(), " ");
append(sb, "-imfchan", options.getImfchan(), " ");
append(sb, "-type", options.getType(), " ");
sb.append(options.getFileName());
return sb.toString();
}
/**
* Append the given key-value mapping to the given string builder, if
* the given value is not <code>null</code>
*
* @param sb The string builder
* @param key The key
* @param value The value
* @param separator The separator to append after the value
*/
private static void append(
StringBuilder sb, String key, Object value, String separator)
{
if (value != null)
{
sb.append(key).append(" ");
sb.append(value);
sb.append(separator);
}
}
/**
* Append the given key-value mapping to the given string builder, if
* the given value is not <code>null</code>
*
* @param sb The string builder
* @param key The key
* @param value The value
* @param separator The separator to append after the value
*/
private static void append(
StringBuilder sb, String key, Boolean value, String separator)
{
if (value != null)
{
sb.append(key).append(" ");
if (value)
{
sb.append("on");
}
else
{
sb.append("off");
}
sb.append(separator);
}
}
/**
* Append the given key-value mapping to the given string builder, if
* the given value is not <code>null</code>
*
* @param sb The string builder
* @param key The key
* @param value The value
* @param separator The separator to append after the value
*/
private static void appendTuple(
StringBuilder sb, String key, FloatTuple value, String separator)
{
if (value != null)
{
sb.append(key).append(" ");
sb.append(FloatTuples.createString(value));
sb.append(separator);
}
}
/**
* Private constructor to prevent instantiation
*/
private MtlWriter()
{
// Private constructor to prevent instantiation
}
}
================================================
FILE: src/main/java/de/javagl/obj/Mtls.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
/**
* Methods to create {@link Mtl} instances
*/
public class Mtls
{
/**
* Creates a new default {@link Mtl}
*
* @param name The name of the material
* @return The {@link Mtl}
*/
public static Mtl create(String name)
{
return new DefaultMtl(name);
}
/**
* Private constructor to prevent instantiation
*/
private Mtls()
{
// Private constructor to prevent instantiation
}
}
================================================
FILE: src/main/java/de/javagl/obj/Obj.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
/**
* An in-memory representation of an OBJ file. This interface is only
* a combination of a {@link ReadableObj} and a {@link WritableObj}.<br>
* <br>
* An {@link Obj} may be created with the {@link Objs#create()} method.
* The {@link ObjReader#read(java.io.InputStream)} method may be used to
* create an {@link Obj} from an OBJ file.
*/
public interface Obj extends ReadableObj, WritableObj
{
// No additional methods
}
================================================
FILE: src/main/java/de/javagl/obj/ObjData.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
/**
* Methods to obtain the data from {@link ReadableObj}s as plain arrays
* or buffers
*/
public class ObjData
{
//=========================================================================
// Number of vertices
/**
* Returns an array containing the number of vertices of the faces
* of the given {@link ReadableObj}
*
* @param obj The {@link ReadableObj}
* @return The array containing the number of vertices of the faces
*/
private static int[] getNumFaceVertices(ReadableObj obj)
{
int[] numVerticesOfFaces = new int[obj.getNumFaces()];
for(int i = 0; i < obj.getNumFaces(); i++)
{
ObjFace face = obj.getFace(i);
numVerticesOfFaces[i] = face.getNumVertices();
}
return numVerticesOfFaces;
}
/**
* Returns the sum of all numbers of vertices of all faces in the given
* {@link ReadableObj}. If the given {@link ReadableObj} only contains
* triangles, this will be the same as <code>obj.getNumFaces() * 3</code>.
*
* @param obj The {@link ReadableObj}
* @return The number of face vertex indices
*/
public static int getTotalNumFaceVertices(ReadableObj obj)
{
return sum(getNumFaceVertices(obj));
}
/**
* Returns the sum of the elements of the given array
*
* @param array The array
* @return The sum of the elements of the given array
*/
private static int sum(int[] array)
{
int sum = 0;
for (int i : array)
{
sum += i;
}
return sum;
}
//=========================================================================
// Vertex indices
/**
* Returns the vertex indices from the faces of the given
* {@link ReadableObj} as an array. <br>
* <br>
* This method will compute the
* {@link #getTotalNumFaceVertices(ReadableObj) number of face vertex
* indices} and return an array with this size. If the number of vertices
* per face is known and equal for all faces,
* {@link #getFaceVertexIndices(ReadableObj,int)} may be used instead.
*
* @param obj The obj
* @return The face vertex indices
*/
public static int[] getFaceVertexIndicesArray(ReadableObj obj)
{
int[] array = new int[getTotalNumFaceVertices(obj)];
getFaceVertexIndices(obj, IntBuffer.wrap(array));
return array;
}
/**
* Returns the vertex indices from the faces of the given
* {@link ReadableObj} as direct IntBuffer. The position
* of the returned buffer will be 0, and its limit and
* capacity will match the stored data.<br>
* <br>
* This method will compute the
* {@link #getTotalNumFaceVertices(ReadableObj) number of face vertex
* indices} and return a buffer with this size. If the number of vertices
* per face is known and equal for all faces,
* {@link #getFaceVertexIndices(ReadableObj,int)} may be used instead.
*
* @param obj The obj
* @return The face vertex indices
*/
public static IntBuffer getFaceVertexIndices(ReadableObj obj)
{
IntBuffer buffer = createDirectIntBuffer(getTotalNumFaceVertices(obj));
getFaceVertexIndices(obj, buffer);
buffer.position(0);
return buffer;
}
/**
* Returns the vertex indices from the faces of the given
* {@link ReadableObj} as an array. <br>
* <br>
* This method assumes that all faces have the given number of vertices
*
* @param obj The {@link ReadableObj}
* @param numVerticesPerFace The number of vertices per face
* @return The face vertex indices
*/
public static int[] getFaceVertexIndicesArray(
ReadableObj obj, int numVerticesPerFace)
{
int[] array = new int[obj.getNumFaces() * numVerticesPerFace];
getFaceVertexIndices(obj, IntBuffer.wrap(array));
return array;
}
/**
* Returns the vertex indices from the faces of the given
* {@link ReadableObj} as direct IntBuffer. The position
* of the returned buffer will be 0, and its limit and
* capacity will match the stored data.<br>
* <br>
* This method assumes that all faces have the given number of vertices
*
* @param obj The {@link ReadableObj}
* @param numVerticesPerFace The number of vertices per face
* @return The face vertex indices
*/
public static IntBuffer getFaceVertexIndices(
ReadableObj obj, int numVerticesPerFace)
{
IntBuffer buffer = createDirectIntBuffer(
obj.getNumFaces() * numVerticesPerFace);
getFaceVertexIndices(obj, buffer);
buffer.position(0);
return buffer;
}
/**
* Stores the vertex indices of the faces of the given
* {@link ReadableObj} in the given buffer. The position
* of the given buffer will be advanced accordingly.<br>
* <br>
* This method assumes that the given buffer is sufficiently large
* to store all indices. The required size may be computed with
* {@link #getTotalNumFaceVertices(ReadableObj)}, or, if the number
* of vertices per face is known and equal for all faces, with
* <code>n = obj.getNumFaces() * numVerticesPerFace</code>
*
* @param obj The {@link ReadableObj}
* @param target The buffer that will store the result
* @throws BufferOverflowException If the buffer can not store the result
*/
public static void getFaceVertexIndices(
ReadableObj obj, IntBuffer target)
{
for(int i = 0; i < obj.getNumFaces(); i++)
{
ObjFace face = obj.getFace(i);
for (int j=0; j<face.getNumVertices(); j++)
{
target.put(face.getVertexIndex(j));
}
}
}
//=========================================================================
// TexCoord indices
/**
* Returns the texCoord indices from the faces of the given
* {@link ReadableObj} as an array. <br>
* <br>
* This method will compute the
* {@link #getTotalNumFaceVertices(ReadableObj) number of face vertices}
* and return an array with this size. If the number of vertices per
* face is known and equal for all faces,
* {@link #getFaceTexCoordIndices(ReadableObj,int)} may be used instead.
*
* @param obj The obj
* @return The face texCoord indices
*/
public static int[] getFaceTexCoordIndicesArray(ReadableObj obj)
{
int[] array = new int[getTotalNumFaceVertices(obj)];
getFaceTexCoordIndices(obj, IntBuffer.wrap(array));
return array;
}
/**
* Returns the texCoord indices from the faces of the given
* {@link ReadableObj} as a direct IntBuffer. The position
* of the returned buffer will be 0, and its limit and
* capacity will match the stored data.<br>
* <br>
* This method will compute the
* {@link #getTotalNumFaceVertices(ReadableObj) number of face vertices}
* and return a buffer with this size. If the number of vertices per
* face is known and equal for all faces,
* {@link #getFaceTexCoordIndices(ReadableObj,int)} may be used instead.
*
* @param obj The obj
* @return The face texCoord indices
*/
public static IntBuffer getFaceTexCoordIndices(ReadableObj obj)
{
IntBuffer buffer = createDirectIntBuffer(getTotalNumFaceVertices(obj));
getFaceTexCoordIndices(obj, buffer);
buffer.position(0);
return buffer;
}
/**
* Returns the texCoord indices from the faces of the given
* {@link ReadableObj} as an array. <br>
* <br>
* This method assumes that all faces have the given number of vertices.<br>
* <br>
* This method assumes that the faces contain texture coordinate indices.
*
* @param obj The {@link ReadableObj}
* @param numVerticesPerFace The number of vertices per face
* @return The face texCoord indices
*/
public static int[] getFaceTexCoordIndicesArray(
ReadableObj obj, int numVerticesPerFace)
{
int[] array = new int[obj.getNumFaces() * numVerticesPerFace];
getFaceTexCoordIndices(obj, IntBuffer.wrap(array));
return array;
}
/**
* Returns the texCoord indices from the faces of the given
* {@link ReadableObj} as a direct IntBuffer. The position
* of the returned buffer will be 0, and its limit and
* capacity will match the stored data.<br>
* <br>
* This method assumes that all faces have the given number of vertices.<br>
* <br>
* This method assumes that the faces contain texture coordinate indices.
*
* @param obj The {@link ReadableObj}
* @param numVerticesPerFace The number of vertices per face
* @return The face texCoord indices
*/
public static IntBuffer getFaceTexCoordIndices(
ReadableObj obj, int numVerticesPerFace)
{
IntBuffer buffer = createDirectIntBuffer(
obj.getNumFaces() * numVerticesPerFace);
getFaceTexCoordIndices(obj, buffer);
buffer.position(0);
return buffer;
}
/**
* Stores the texCoord indices of the faces of the given
* {@link ReadableObj} in the given buffer. The position
* of the given buffer will be advanced accordingly.<br>
* <br>
* This method assumes that the given buffer is sufficiently large
* to store all indices. The required size may be computed with
* {@link #getTotalNumFaceVertices(ReadableObj)}, or, if the number of
* vertices per face is known and equal for all faces, with
* <code>n = obj.getNumFaces() * numVerticesPerFace</code>.<br>
* <br>
* This method assumes that the faces contain texture coordinate indices.
*
*
* @param obj The {@link ReadableObj}
* @param target The buffer that will store the result
* @throws BufferOverflowException If the buffer can not store the result
*/
public static void getFaceTexCoordIndices(
ReadableObj obj, IntBuffer target)
{
for(int i = 0; i < obj.getNumFaces(); i++)
{
ObjFace face = obj.getFace(i);
for (int j=0; j<face.getNumVertices(); j++)
{
target.put(face.getTexCoordIndex(j));
}
}
}
//=========================================================================
// Normal indices
/**
* Returns the normal indices from the faces of the given
* {@link ReadableObj} as an array. <br>
* <br>
* This method will compute the
* {@link #getTotalNumFaceVertices(ReadableObj) number of face vertices}
* and return an array with this size. If the number of vertices per
* face is known and equal for all faces,
* {@link #getFaceNormalIndices(ReadableObj,int)} may be used instead.
*
* @param obj The {@link ReadableObj}
* @return The face normal indices
*/
public static int[] getFaceNormalIndicesArray(ReadableObj obj)
{
int[] array = new int[getTotalNumFaceVertices(obj)];
getFaceNormalIndices(obj, IntBuffer.wrap(array));
return array;
}
/**
* Returns the normal indices from the faces of the given
* {@link ReadableObj} as a direct IntBuffer. The position
* of the returned buffer will be 0, and its limit and
* capacity will match the stored data.<br>
* <br>
* This method will compute the
* {@link #getTotalNumFaceVertices(ReadableObj) number of face vertices}
* and return a buffer with this size. If the number of vertices per
* face is known and equal for all faces,
* {@link #getFaceNormalIndices(ReadableObj,int)} may be used instead.
*
* @param obj The {@link ReadableObj}
* @return The face normal indices
*/
public static IntBuffer getFaceNormalIndices(ReadableObj obj)
{
IntBuffer buffer = createDirectIntBuffer(getTotalNumFaceVertices(obj));
getFaceNormalIndices(obj, buffer);
buffer.position(0);
return buffer;
}
/**
* Returns the normal indices from the faces of the given
* {@link ReadableObj} as an array. <br>
* <br>
* This method assumes that all faces have the given number of vertices.<br>
* <br>
* This method assumes that the faces contain normal indices.
*
* @param obj The {@link ReadableObj}
* @param numVerticesPerFace The number of vertices per face
* @return The face normal indices
*/
public static int[] getFaceNormalIndicesArray(
ReadableObj obj, int numVerticesPerFace)
{
int[] array = new int[obj.getNumFaces() * numVerticesPerFace];
getFaceNormalIndices(obj, IntBuffer.wrap(array));
return array;
}
/**
* Returns the normal indices from the faces of the given
* {@link ReadableObj} as a direct IntBuffer. The position
* of the returned buffer will be 0, and its limit and
* capacity will match the stored data.<br>
* <br>
* This method assumes that all faces have the given number of vertices.<br>
* <br>
* This method assumes that the faces contain normal indices.
*
* @param obj The {@link ReadableObj}
* @param numVerticesPerFace The number of vertices per face
* @return The face normal indices
*/
public static IntBuffer getFaceNormalIndices(
ReadableObj obj, int numVerticesPerFace)
{
IntBuffer buffer = createDirectIntBuffer(
obj.getNumFaces() * numVerticesPerFace);
getFaceNormalIndices(obj, buffer);
buffer.position(0);
return buffer;
}
/**
* Stores the normal indices of the faces of the given
* {@link ReadableObj} in the given buffer. The position
* of the given buffer will be advanced accordingly.<br>
* <br>
* This method assumes that the given buffer is sufficiently large
* to store all indices. The required size may be computed with
* {@link #getTotalNumFaceVertices(ReadableObj)}, or, if the number of
* vertices per face is known and equal for all faces, with
* <code>n = obj.getNumFaces() * numVerticesPerFace</code>.<br>
* <br>
* This method assumes that the faces contain texture coordinate indices.
*
*
* @param obj The {@link ReadableObj}
* @param target The buffer that will store the result
* @throws BufferOverflowException If the buffer can not store the result
*/
public static void getFaceNormalIndices(
ReadableObj obj, IntBuffer target)
{
for(int i = 0; i < obj.getNumFaces(); i++)
{
ObjFace face = obj.getFace(i);
for (int j=0; j<face.getNumVertices(); j++)
{
target.put(face.getNormalIndex(j));
}
}
}
//=========================================================================
// Vertices
/**
* Returns all vertices of the given {@link ReadableObj} as an array.
* Three consecutive entries in the resulting array are the
* x,y,z coordinates of one vertex
*
* @param obj The {@link ReadableObj}
* @return The resulting array
*/
public static float[] getVerticesArray(ReadableObj obj)
{
float[] array = new float[obj.getNumVertices() * 3];
getVertices(obj, FloatBuffer.wrap(array));
return array;
}
/**
* Returns all vertices of the given {@link ReadableObj} as a direct
* FloatBuffer.
* Three consecutive entries in the resulting buffer are the
* x,y,z coordinates of one vertex. The position
* of the returned buffer will be 0, and its limit and
* capacity will match the stored data.
*
* @param obj The {@link ReadableObj}
* @return The resulting buffer
*/
public static FloatBuffer getVertices(ReadableObj obj)
{
FloatBuffer buffer = createDirectFloatBuffer(obj.getNumVertices() * 3);
getVertices(obj, buffer);
buffer.position(0);
return buffer;
}
/**
* Stores the vertices of the given {@link ReadableObj} in the given
* buffer. The position of the target will be increased by
* <code>obj.getNumVertices() * 3. The position
* of the given buffer will be advanced accordingly.</code>
*
* @param obj The obj
* @param target The target that will store the result
* @throws BufferOverflowException If the target can not store the result
*/
public static void getVertices(
ReadableObj obj, FloatBuffer target)
{
for(int i = 0; i < obj.getNumVertices(); i++)
{
FloatTuple tuple = obj.getVertex(i);
target.put(tuple.getX());
target.put(tuple.getY());
target.put(tuple.getZ());
}
}
//=========================================================================
// TexCoords
/**
* Returns all texture coordinates of the given
* {@link ReadableObj} as an array.
*
* @param obj The {@link ReadableObj}
* @param dimensions The dimensions that are assumed for the coordinates
* @return The resulting array
*/
public static float[] getTexCoordsArray(ReadableObj obj, int dimensions)
{
return getTexCoordsArray(obj, dimensions, false);
}
/**
* Returns all texture coordinates of the given
* {@link ReadableObj} as an array.
*
* @param obj The {@link ReadableObj}
* @param dimensions The dimensions that are assumed for the coordinates
* @param flipY Whether the texture coordinates should be flipped
* vertically. This means that the y-coordinates (at dimension index 1)
* will be replaced with <code>1.0f - y</code>. Most image loaders provide
* image data with the first pixel being the <i>upper left</i> pixel of
* the image. But OpenGL <code>glTexImage2D</code> calls expect the first
* pixel to be the <i>lower left</i>. Flipping the texture coordinates
* by passing <code>flipY=true</code> to this method allows to compensate
* for this mismatch.
* @return The resulting array
*/
public static float[] getTexCoordsArray(
ReadableObj obj, int dimensions, boolean flipY)
{
float[] array = new float[obj.getNumTexCoords() * dimensions];
getTexCoords(obj, FloatBuffer.wrap(array), dimensions, flipY);
return array;
}
/**
* Returns all texture coordinates of the given
* {@link ReadableObj} as direct FloatBuffer. The position
* of the returned buffer will be 0, and its limit and
* capacity will match the stored data.
*
* @param obj The {@link ReadableObj}
* @param dimensions The dimensions that are assumed for the coordinates
* @return The resulting buffer
*/
public static FloatBuffer getTexCoords(ReadableObj obj, int dimensions)
{
return getTexCoords(obj, dimensions, false);
}
/**
* Returns all texture coordinates of the given
* {@link ReadableObj} as direct FloatBuffer. The position
* of the returned buffer will be 0, and its limit and
* capacity will match the stored data.
*
* @param obj The {@link ReadableObj}
* @param dimensions The dimensions that are assumed for the coordinates
* @param flipY Whether the texture coordinates should be flipped
* vertically. This means that the y-coordinates (at dimension index 1)
* will be replaced with <code>1.0f - y</code>. Most image loaders provide
* image data with the first pixel being the <i>upper left</i> pixel of
* the image. But OpenGL <code>glTexImage2D</code> calls expect the first
* pixel to be the <i>lower left</i>. Flipping the texture coordinates
* by passing <code>flipY=true</code> to this method allows to compensate
* for this mismatch.
* @return The resulting buffer
*/
public static FloatBuffer getTexCoords(
ReadableObj obj, int dimensions, boolean flipY)
{
FloatBuffer buffer =
createDirectFloatBuffer(obj.getNumTexCoords() * dimensions);
getTexCoords(obj, buffer, dimensions, flipY);
buffer.position(0);
return buffer;
}
/**
* Stores the texture coordinates of the given {@link ReadableObj}
* in the given buffer. The position of the target will be increased by
* <code>obj.getNumTexCoords() * dimensions</code>. The position
* of the given buffer will be advanced accordingly.
*
* @param obj The {@link ReadableObj}
* @param target The target that will store the result
* @param dimensions The dimensions that are assumed for the coordinates
* @throws BufferOverflowException If the target can not store the result
*/
public static void getTexCoords(
ReadableObj obj, FloatBuffer target, int dimensions)
{
getTexCoords(obj, target, dimensions, false);
}
/**
* Stores the texture coordinates of the given {@link ReadableObj}
* in the given buffer. The position of the target will be increased by
* <code>obj.getNumTexCoords() * dimensions</code>. The position
* of the given buffer will be advanced accordingly.
*
* @param obj The {@link ReadableObj}
* @param target The target that will store the result
* @param dimensions The dimensions that are assumed for the coordinates
* @param flipY Whether the texture coordinates should be flipped
* vertically. This means that the y-coordinates (at dimension index 1)
* will be replaced with <code>1.0f - y</code>. Most image loaders provide
* image data with the first pixel being the <i>upper left</i> pixel of
* the image. But OpenGL <code>glTexImage2D</code> calls expect the first
* pixel to be the <i>lower left</i>. Flipping the texture coordinates
* by passing <code>flipY=true</code> to this method allows to compensate
* for this mismatch.
* @throws BufferOverflowException If the target can not store the result
*/
public static void getTexCoords(
ReadableObj obj, FloatBuffer target, int dimensions, boolean flipY)
{
if (flipY)
{
for(int i = 0; i < obj.getNumTexCoords(); i++)
{
FloatTuple tuple = obj.getTexCoord(i);
for (int j=0; j<dimensions; j++)
{
if (j == 1)
{
target.put(1.0f - tuple.get(j));
}
else
{
target.put(tuple.get(j));
}
}
}
}
else
{
for(int i = 0; i < obj.getNumTexCoords(); i++)
{
FloatTuple tuple = obj.getTexCoord(i);
for (int j=0; j<dimensions; j++)
{
target.put(tuple.get(j));
}
}
}
}
//=========================================================================
// Normals
/**
* Returns all normals of the given {@link ReadableObj} as an array.
* Three consecutive entries in the resulting array are the
* x,y,z coordinates of one normal.
*
* @param obj The {@link ReadableObj}
* @return The resulting array
*/
public static float[] getNormalsArray(ReadableObj obj)
{
float[] array = new float[obj.getNumNormals() * 3];
getNormals(obj, FloatBuffer.wrap(array));
return array;
}
/**
* Returns all normals of the given {@link ReadableObj} as an array.
* Three consecutive entries in the resulting buffer are the
* x,y,z coordinates of one normal. The position
* of the returned buffer will be 0, and its limit and
* capacity will match the stored data.
*
* @param obj The {@link ReadableObj}
* @return The resulting buffer
*/
public static FloatBuffer getNormals(ReadableObj obj)
{
FloatBuffer buffer = createDirectFloatBuffer(obj.getNumNormals() * 3);
getNormals(obj, buffer);
buffer.position(0);
return buffer;
}
/**
* Stores the normals of the given {@link ReadableObj} in the given
* buffer. The position of the target will be increased by
* <code>obj.getNumNormals() * 3</code>. The position
* of the given buffer will be advanced accordingly.
*
* @param obj The {@link ReadableObj}
* @param target The buffer that will store the result
* @throws BufferOverflowException If the target can not store the result
*/
public static void getNormals(
ReadableObj obj, FloatBuffer target)
{
for(int i = 0; i < obj.getNumNormals(); i++)
{
FloatTuple tuple = obj.getNormal(i);
target.put(tuple.getX());
target.put(tuple.getY());
target.put(tuple.getZ());
}
}
/**
* Convert the given IntBuffer to a (direct) ShortBuffer, by casting all
* elements to <code>short</code>. <br>
* <br>
* Note that these casts will be unchecked. If there is any value in the
* input buffer that is larger than the maximum value that a
* <b>signed</b> <code>short</code> can represent, then the
* <code>short</code> value will become negative. The resulting buffer
* will then still be valid for passing it to OpenGL when the index
* mode is <code>GL_UNSIGNED_SHORT</code>, because the bitwise
* representation is the same. When one of the integer values is larger
* than the value that can be represented with an <b>unsigned</b>
* <code>short</code>, then the resulting indices will be invalid
* and cause rendering artifacts.
*
* @param intBuffer The IntBuffer
* @return The ShortBuffer
*/
public static ShortBuffer convertToShortBuffer(IntBuffer intBuffer)
{
ShortBuffer shortBuffer = createDirectShortBuffer(intBuffer.capacity());
for (int i = 0; i < intBuffer.capacity(); i++)
{
shortBuffer.put(i, (short) intBuffer.get());
}
return shortBuffer;
}
/**
* Create a direct IntBuffer with the given size
*
* @param size The size
* @return The IntBuffer
*/
private static IntBuffer createDirectIntBuffer(int size)
{
return ByteBuffer.allocateDirect(size * 4)
.order(ByteOrder.nativeOrder())
.asIntBuffer();
}
/**
* Create a direct ShortBuffer with the given size
*
* @param size The size
* @return The ShortBuffer
*/
private static ShortBuffer createDirectShortBuffer(int size)
{
return ByteBuffer.allocateDirect(size * 2)
.order(ByteOrder.nativeOrder())
.asShortBuffer();
}
/**
* Create a direct FloatBuffer with the given size
*
* @param size The size
* @return The FloatBuffer
*/
private static FloatBuffer createDirectFloatBuffer(int size)
{
return ByteBuffer.allocateDirect(size * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
}
/**
* Private constructor to prevent instantiation
*/
private ObjData()
{
// Private constructor to prevent instantiation
}
}
================================================
FILE: src/main/java/de/javagl/obj/ObjFace.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
/**
* A single face that is stored in an OBJ file
*/
public interface ObjFace
{
/**
* Returns the number of vertices this face consists of.
*
* @return The number of vertices this face consists of.
*/
int getNumVertices();
/**
* Returns whether this face contains texture coordinate indices
*
* @return Whether this face contains texture coordinate indices
*/
boolean containsTexCoordIndices();
/**
* Returns whether this face contains normal indices
*
* @return Whether this face contains normal indices
*/
boolean containsNormalIndices();
/**
* Returns the index of the vertex with the given number.
* The index that is returned will be ZERO-based, in contrast
* to the ONE-based storage in the OBJ file.
*
* @param number The number of the vertex
* @return The index of the vertex.
* @throws IndexOutOfBoundsException If the given number is negative
* or not smaller than {@link #getNumVertices()}
*/
int getVertexIndex(int number);
/**
* Returns the index of the texture coordinate with the given number.
* The index that is returned will be ZERO-based, in contrast
* to the ONE-based storage in the OBJ file.
*
* @param number The number of the texture coordinate
* @return The index of the texture coordinate.
* @throws IndexOutOfBoundsException If the given number is negative
* or not smaller than {@link #getNumVertices()}
*/
int getTexCoordIndex(int number);
/**
* Returns the index of the normal with the given number.
* The index that is returned will be ZERO-based, in contrast
* to the ONE-based storage in the OBJ file.
*
* @param number The number of the normal
* @return The index of the normal.
* @throws IndexOutOfBoundsException If the given number is negative
* or not smaller than {@link #getNumVertices()}
*/
int getNormalIndex(int number);
}
================================================
FILE: src/main/java/de/javagl/obj/ObjFaceParser.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
import java.io.IOException;
import java.util.Arrays;
/**
* A class for reading the index data for an {@link ObjFace} from an
* <code>'f'</code>-line that was read from an OBJ file
*/
final class ObjFaceParser
{
/**
* The initial size for the index buffers
*/
private static final int INITIAL_BUFFER_SIZE = 6;
/**
* Buffer for vertex indices
*/
private int[] vertexIndexBuffer = new int[INITIAL_BUFFER_SIZE];
/**
* Buffer for texture coordinates
*/
private int[] texCoordIndexBuffer = new int[INITIAL_BUFFER_SIZE];
/**
* Buffer normal indices
*/
private int[] normalIndexBuffer = new int[INITIAL_BUFFER_SIZE];
/**
* Flag whether texture coordinates have been found during the last
* call to {@link #parse(String)}
*/
private boolean foundTexCoordIndices = false;
/**
* Flag whether normal indices have been found during the last
* call to {@link #parse(String)}
*/
private boolean foundNormalIndices = false;
/**
* Counter for the vertices
*/
private int vertexCounter = 0;
/**
* Index in the input array
*/
private int idx = 0;
/**
* The input array to parse
*/
private char[] lineData;
/**
* Parse the given <code>'f'</code>-line that was read from an OBJ file
*
* @param line The line
* @throws IOException If the given line can not be parsed
*/
void parse(String line) throws IOException
{
parseLine(line);
}
/**
* Returns a new array containing the vertex indices that have
* been parsed during the last call to
* {@link #parse(String)}.
*
* @return The vertex indices
*/
int[] getVertexIndices()
{
return Arrays.copyOf(vertexIndexBuffer, vertexCounter);
}
/**
* Returns a new array containing the texCoord indices that have
* been parsed during the last call to
* {@link #parse(String)}, or <code>null</code>
* if no texture coordinate indices have been read
*
* @return The texCord indices
*/
int[] getTexCoordIndices()
{
if (foundTexCoordIndices)
{
return Arrays.copyOf(texCoordIndexBuffer, vertexCounter);
}
return null;
}
/**
* Returns a new array containing the normal indices that have
* been parsed during the last call to
* {@link #parse(String)}, or <code>null</code>
* if no normal indices have been read
*
* @return The normal indices
*/
int[] getNormalIndices()
{
if(foundNormalIndices)
{
return Arrays.copyOf(normalIndexBuffer, vertexCounter);
}
return null;
}
/**
* Parse the Face from the given line <br>
* f v0/vt0/vn0 ... vN/vtN/vnN <br>
*
* @param line String
* @throws IOException If the line could not be parsed
*/
void parseLine(String line) throws IOException
{
foundTexCoordIndices = false;
foundNormalIndices = false;
vertexCounter = 0;
idx = 0;
lineData = line.toCharArray();
skipSpaces();
if(endOfInput())
{
// Empty line
return;
}
// Read the leading 'f' or 'F'
if(lineData[idx] != 'f' && lineData[idx] != 'F')
{
throw new IOException(
"Expected 'f' or 'F', but found '" + lineData[idx] +
" in \""+line+"\"");
}
idx++;
// Read all vertex v/vt/vn triples
int count = 0;
while(true)
{
skipSpaces();
if(endOfInput())
{
break;
}
// Read the vertex index
int vertexIndex = parseNonzeroInt();
if (vertexIndex == 0)
{
throw new IOException(
"Could not read vertex index in \""+line+"\"");
}
if (count >= vertexIndexBuffer.length)
{
vertexIndexBuffer =
Arrays.copyOf(vertexIndexBuffer, count+1);
texCoordIndexBuffer =
Arrays.copyOf(texCoordIndexBuffer, count+1);
normalIndexBuffer =
Arrays.copyOf(normalIndexBuffer, count+1);
}
if (vertexIndex != 0)
{
vertexIndexBuffer[count] = vertexIndex;
}
vertexCounter = count + 1;
skipSpaces();
if(endOfInput())
{
break;
}
// Read the texCoord index
if(lineData[idx] == '/')
{
idx++;
skipSpaces();
if(endOfInput())
{
throw new IOException(
"Unexpected end of input after '/' " +
"in \""+line+"\"");
}
int texCoordIndex = parseNonzeroInt();
// It is not an error if texCoordIndex == 0: The indices
// may be given as "1//2", and thus not contain an
// texCoordIndex
if(texCoordIndex != 0)
{
texCoordIndexBuffer[count] = texCoordIndex;
foundTexCoordIndices = true;
}
skipSpaces();
if(endOfInput())
{
break;
}
// Read the normal index
if(lineData[idx] == '/')
{
idx++;
skipSpaces();
if(endOfInput())
{
throw new IOException(
"Unexpected end of input after '/' " +
"in \""+line+"\"");
}
int normalIndex = parseNonzeroInt();
if(normalIndex == 0)
{
throw new IOException(
"Could not read normal index from \""+line+"\"");
}
foundNormalIndices = true;
if (normalIndex != 0)
{
normalIndexBuffer[count] = normalIndex;
}
}
}
count++;
}
}
/**
* Returns whether the end of the input was reached
*
* @return 'true' iff the end of the input was reached
*/
private boolean endOfInput()
{
return idx >= lineData.length;
}
/**
* Skips all space characters until the first non-space character is
* found or the end of the input is reached
*/
private void skipSpaces()
{
while (!endOfInput() && lineData[idx] == ' ')
{
idx++;
}
}
/**
* Returns the next int in the input, or 0 if no int could be
* read
*
* @return The next int in the input
*/
private int parseNonzeroInt()
{
int parsedInt = 0;
boolean negate = false;
if (lineData[idx] == '-')
{
negate = true;
idx++;
skipSpaces();
if(endOfInput())
{
return 0;
}
}
if(lineData[idx] >= '0' && lineData[idx] <= '9')
{
parsedInt = (lineData[idx] - '0');
idx++;
while(!endOfInput() &&
lineData[idx] >= '0' &&
lineData[idx] <= '9')
{
parsedInt *= 10;
parsedInt += (lineData[idx] - '0');
idx++;
}
}
return negate ? -parsedInt : parsedInt;
}
}
================================================
FILE: src/main/java/de/javagl/obj/ObjFaces.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
/**
* Methods for creating {@link ObjFace} instances
*/
public class ObjFaces
{
/**
* Create a copy of the given face.<br>
*
* @param face The input face
* @return The copy
*/
static DefaultObjFace create(ObjFace face)
{
int[] v = new int[face.getNumVertices()];
int[] vt = null;
int[] vn = null;
for(int i = 0; i < face.getNumVertices(); i++)
{
v[i] = face.getVertexIndex(i);
}
if(face.containsTexCoordIndices())
{
vt = new int[face.getNumVertices()];
for(int i = 0; i < face.getNumVertices(); i++)
{
vt[i] = face.getTexCoordIndex(i);
}
}
if(face.containsNormalIndices())
{
vn = new int[face.getNumVertices()];
for(int i = 0; i < face.getNumVertices(); i++)
{
vn[i] = face.getNormalIndex(i);
}
}
DefaultObjFace result = new DefaultObjFace(v, vt, vn);
return result;
}
/**
* Create a copy of the given face, adding the given offsets to the
* respective indices. If the given face does not contain texture
* coordinate or normal indices, then the respective offsets will
* be ignored.<br>
*
* @param face The input face
* @param verticesOffset The offset for the vertex indices
* @param texCoordsOffset The offset for the texture coordinate indices
* @param normalsOffset The offset for the normal indices
* @return The copy
*/
static DefaultObjFace createWithOffsets(ObjFace face,
int verticesOffset, int texCoordsOffset, int normalsOffset)
{
int[] v = new int[face.getNumVertices()];
int[] vt = null;
int[] vn = null;
for(int i = 0; i < face.getNumVertices(); i++)
{
v[i] = face.getVertexIndex(i) + verticesOffset;
}
if(face.containsTexCoordIndices())
{
vt = new int[face.getNumVertices()];
for(int i = 0; i < face.getNumVertices(); i++)
{
vt[i] = face.getTexCoordIndex(i) + texCoordsOffset;
}
}
if(face.containsNormalIndices())
{
vn = new int[face.getNumVertices()];
for(int i = 0; i < face.getNumVertices(); i++)
{
vn[i] = face.getNormalIndex(i) + normalsOffset;
}
}
DefaultObjFace result = new DefaultObjFace(v, vt, vn);
return result;
}
/**
* Create a copy of the given face, using only the specified vertices
* of the given face.
*
* @param face The input face
* @param n The vertices to use
* @return The copy
*/
static DefaultObjFace create(ObjFace face, int ... n)
{
int[] v = new int[n.length];
int[] vt = null;
int[] vn = null;
for(int i = 0; i < n.length; i++)
{
v[i] = face.getVertexIndex(n[i]);
}
if(face.containsTexCoordIndices())
{
vt = new int[n.length];
for(int i = 0; i < n.length; i++)
{
vt[i] = face.getTexCoordIndex(n[i]);
}
}
if(face.containsNormalIndices())
{
vn = new int[n.length];
for(int i = 0; i < n.length; i++)
{
vn[i] = face.getNormalIndex(n[i]);
}
}
DefaultObjFace result = new DefaultObjFace(v, vt, vn);
return result;
}
/**
* Create a face with the given indices. The texCoord indices and the
* normal indices may be <code>null</code>. In any case, it is assumed
* that all non-<code>null</code> arrays have equal length. References
* to the given arrays will be stored internally, so they should <b>not</b>
* be modified after they have been passed to this method.
*
* @param v The vertex indices
* @param vt The texCoord indices
* @param vn The normal indices
* @return The face
*/
public static ObjFace create(int[] v, int[] vt, int[] vn)
{
return createDefault(v, vt, vn);
}
/**
* Create a face with the given indices. The texCoord indices and the
* normal indices may be <code>null</code>. In any case, it is assumed
* that all non-<code>null</code> arrays have equal length. References
* to the given arrays will be stored internally, so they should <b>not</b>
* be modified after they have been passed to this method.
*
* @param v The vertex indices
* @param vt The texCoord indices
* @param vn The normal indices
* @return The face
*/
static DefaultObjFace createDefault(int[] v, int[] vt, int[] vn)
{
DefaultObjFace result = new DefaultObjFace(v, vt, vn);
return result;
}
/**
* Returns the string for the given face that makes up one 'f' line
* in an OBJ file
*
* @param face The face
* @return The string for the face
*/
public static String createString(ObjFace face)
{
StringBuilder sb = new StringBuilder("f ");
for(int i = 0; i < face.getNumVertices(); i++)
{
if (i > 0)
{
sb.append(" ");
}
sb.append(face.getVertexIndex(i) + 1);
if(face.containsTexCoordIndices() || face.containsNormalIndices())
{
sb.append("/");
}
if(face.containsTexCoordIndices())
{
sb.append(face.getTexCoordIndex(i) + 1);
}
if(face.containsNormalIndices())
{
sb.append("/").append(face.getNormalIndex(i) + 1);
}
}
return sb.toString();
}
/**
* Private constructor to prevent instantiation
*/
private ObjFaces()
{
// Private constructor to prevent instantiation
}
}
================================================
FILE: src/main/java/de/javagl/obj/ObjGroup.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
/**
* Interface describing a single group of an OBJ file. This may either
* be a geometry group that is identified by the <code>'g'</code> token,
* or a group that is implied by a common material, identified by the
* <code>'usemtl'</code> token.
*/
public interface ObjGroup
{
/**
* Returns the name of this group.
*
* @return The name of this group.
*/
String getName();
/**
* Returns the number of faces in this group.
*
* @return The number of faces in this group.
*/
int getNumFaces();
/**
* Returns the face with the given index.
*
* @param index The index of the face
* @return The face with the given index.
* @throws IndexOutOfBoundsException If the index is negative or not
* smaller than {@link #getNumFaces()}
*/
ObjFace getFace(int index);
}
================================================
FILE: src/main/java/de/javagl/obj/ObjReader.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
/**
* A class that may read OBJ data from a stream and
* store the read data in an {@link WritableObj}.
*/
public class ObjReader
{
/**
* Read the OBJ data from the given stream and return it as an {@link Obj}.
* The caller is responsible for closing the given stream.
*
* @param inputStream The stream to read from
* @return The {@link Obj}
* @throws IOException If an IO error occurs
*/
public static Obj read(InputStream inputStream) throws IOException
{
return read(inputStream, Objs.create());
}
/**
* Read the OBJ data from the given stream and store the read
* elements in the given {@link WritableObj}.
* The caller is responsible for closing the given stream.
*
* @param <T> The output type
* @param inputStream The stream to read from
* @param output The {@link WritableObj} to store the read data
* @return The output
* @throws IOException If an IO error occurs
*/
public static <T extends WritableObj> T read(
InputStream inputStream, T output)
throws IOException
{
BufferedReader reader = new BufferedReader(
new InputStreamReader(inputStream, StandardCharsets.US_ASCII));
return readImpl(reader, output);
}
/**
* Read the OBJ data from the given reader and return it as an {@link Obj}.
* The caller is responsible for closing the given reader.
*
* @param reader The reader to read from
* @return The {@link Obj}
* @throws IOException If an IO error occurs
*/
public static Obj read(Reader reader) throws IOException
{
return read(reader, Objs.create());
}
/**
* Read the OBJ data from the given reader and store the read
* elements in the given {@link WritableObj}.
* The caller is responsible for closing the given reader.
*
* @param <T> The output type
* @param reader The reader to read from
* @param output The {@link WritableObj} to store the read data
* @return The output
* @throws IOException If an IO error occurs
*/
public static <T extends WritableObj> T read(
Reader reader, T output)
throws IOException
{
if (reader instanceof BufferedReader)
{
return readImpl((BufferedReader)reader, output);
}
return readImpl(new BufferedReader(reader), output);
}
/**
* Read the OBJ data from the given reader and store the read
* elements in the given {@link WritableObj}.
* The caller is responsible for closing the given reader.
*
* @param <T> The output type
* @param reader The reader to read from
* @param output The {@link WritableObj} to store the read data
* @return The output
* @throws IOException If an IO error occurs
*/
private static <T extends WritableObj> T readImpl(
BufferedReader reader, T output)
throws IOException
{
ObjFaceParser objFaceParser = new ObjFaceParser();
int vertexCounter = 0;
int texCoordCounter = 0;
int normalCounter = 0;
while(true)
{
String line = reader.readLine();
if(line == null)
{
break;
}
line = line.trim();
//System.out.println("read line: "+line);
// Combine lines that have been broken
boolean finished = false;
while(line.endsWith("\\"))
{
line = line.substring(0, line.length() - 2);
String nextLine = reader.readLine();
if (nextLine == null)
{
finished = true;
break;
}
line += " " + nextLine;
}
if (finished)
{
break;
}
StringTokenizer st = new StringTokenizer(line);
if(!st.hasMoreTokens())
{
continue;
}
String identifier = st.nextToken().toLowerCase();
// v: Vertex coordinates
switch (identifier) {
case "v":
output.addVertex(Utils.readFloatTuple(st));
vertexCounter++;
break;
// vt: Texture coordinates for a vertex
case "vt":
output.addTexCoord(Utils.readFloatTuple(st));
texCoordCounter++;
break;
// vn: Vertex normal
case "vn":
output.addNormal(Utils.readFloatTuple(st));
normalCounter++;
break;
// mtllib: Name of the MTL file
case "mtllib": {
String s = line.substring(6).trim();
//output.setMtlFileNames(readStrings(s));
// According to the OBJ specification, the "mtllib" keyword
// may be followed by multiple file names, separated with
// whitespaces:
// "When you assign a material library using the Model
// program, only one map library per .obj file is allowed.
// You can assign multiple libraries using a text editor."
// However, to avoid problems with file names that contain
// whitespaces, only ONE file name is assumed here:
output.setMtlFileNames(Collections.singleton(s));
break;
}
// usemtl: Material groups
case "usemtl":
String materialGroupName = line.substring(6).trim();
output.setActiveMaterialGroupName(materialGroupName);
break;
// g: Geometry groups
case "g": {
String s = line.substring(1).trim();
String[] groupNames = readStrings(s);
output.setActiveGroupNames(Arrays.asList(groupNames));
break;
}
// f: A face definition
case "f":
objFaceParser.parse(line);
int[] v = objFaceParser.getVertexIndices();
int[] vt = objFaceParser.getTexCoordIndices();
int[] vn = objFaceParser.getNormalIndices();
makeIndicesAbsolute(v, vertexCounter);
makeIndicesAbsolute(vt, texCoordCounter);
makeIndicesAbsolute(vn, normalCounter);
output.addFace(ObjFaces.create(v, vt, vn));
break;
}
}
return output;
}
/**
* Convert the indices in the given array to be absolute (non-negative)
* and zero-based. This means that negative values are made positive
* by adding the given count, and positive values are decreased by one.
*
* @param array The array. If this is <code>null</code>, nothing will
* be done
* @param count The count
*/
private static void makeIndicesAbsolute(int[] array, int count)
{
if (array == null)
{
return;
}
for (int i=0; i<array.length; i++)
{
if (array[i] < 0)
{
array[i] = count + array[i];
}
else
{
array[i]--;
}
}
}
/**
* Read all tokens from the given input string that are separated
* by whitespaces
*
* @param input The input string
* @return The list of tokens
*/
private static String[] readStrings(String input)
{
StringTokenizer st = new StringTokenizer(input);
List<String> tokens = new ArrayList<>();
while (st.hasMoreTokens())
{
tokens.add(st.nextToken());
}
return tokens.toArray(new String[tokens.size()]);
}
/**
* Private constructor to prevent instantiation
*/
private ObjReader()
{
// Private constructor to prevent instantiation
}
}
================================================
FILE: src/main/java/de/javagl/obj/ObjSplitter.java
================================================
/*
* www.javagl.de - Obj
*
* Copyright (c) 2008-2017 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.obj;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Package-private class that can split an OBJ into multiple parts, based
* on its number of vertices. Many details abo
gitextract_1k6agy0g/
├── .gitignore
├── LICENSE.txt
├── README.md
├── pom.xml
└── src/
├── main/
│ └── java/
│ └── de/
│ └── javagl/
│ └── obj/
│ ├── AbstractWritableObj.java
│ ├── BasicWritableObj.java
│ ├── DefaultFloatTuple.java
│ ├── DefaultMtl.java
│ ├── DefaultObj.java
│ ├── DefaultObjFace.java
│ ├── DefaultObjGroup.java
│ ├── DefaultTextureOptions.java
│ ├── FloatTuple.java
│ ├── FloatTuples.java
│ ├── Mtl.java
│ ├── MtlReader.java
│ ├── MtlWriter.java
│ ├── Mtls.java
│ ├── Obj.java
│ ├── ObjData.java
│ ├── ObjFace.java
│ ├── ObjFaceParser.java
│ ├── ObjFaces.java
│ ├── ObjGroup.java
│ ├── ObjReader.java
│ ├── ObjSplitter.java
│ ├── ObjSplitting.java
│ ├── ObjUtils.java
│ ├── ObjWriter.java
│ ├── Objs.java
│ ├── ReadableObj.java
│ ├── TextureOptions.java
│ ├── Utils.java
│ ├── WritableObj.java
│ └── package-info.java
└── test/
├── java/
│ └── de/
│ └── javagl/
│ └── obj/
│ ├── TestMtlReader.java
│ ├── TestMtlWriter.java
│ ├── TestObjData.java
│ ├── TestObjReader.java
│ ├── TestObjSplitting.java
│ ├── TestObjUtilsAdd.java
│ ├── TestObjUtilsGroupToObj.java
│ ├── TestObjUtilsMakeTexCoordsUnique.java
│ ├── TestObjUtilsTriangulate.java
│ ├── TestObjWriter.java
│ └── TestObjsCreate.java
└── resources/
├── complexMaterial.mtl
├── fourTrianglesInMixedGroups.obj
├── fourTrianglesPartiallyInMaterialGroups.obj
├── mtlWithBrokenLines.mtl
├── mtlWithPbrProperties.mtl
├── mtlWithWhitespace.mtl
├── pbrMaterial.mtl
├── square.obj
├── squareAndTriangle.obj
├── squareAndTriangleInTwoGroups.obj
├── squareAndTriangleWithRelativeIndices.obj
├── squareTextured.obj
├── twoMaterialsA.mtl
├── twoMaterialsB.mtl
├── twoTrianglesOneInDefaultGroup.obj
├── twoTrianglesSharedInThreeGroups.obj
└── twoTrianglesWithAmbiguousTexCoords.obj
SYMBOL INDEX (633 symbols across 41 files)
FILE: src/main/java/de/javagl/obj/AbstractWritableObj.java
class AbstractWritableObj (line 48) | public class AbstractWritableObj implements WritableObj
method AbstractWritableObj (line 53) | protected AbstractWritableObj()
method addVertex (line 58) | @Override
method addVertex (line 64) | @Override
method addTexCoord (line 70) | @Override
method addTexCoord (line 76) | @Override
method addTexCoord (line 82) | @Override
method addTexCoord (line 88) | @Override
method addNormal (line 95) | @Override
method addNormal (line 101) | @Override
method setActiveGroupNames (line 107) | @Override
method setActiveMaterialGroupName (line 115) | @Override
method addFace (line 121) | @Override
method addFace (line 127) | @Override
method addFaceWithTexCoords (line 133) | @Override
method addFaceWithNormals (line 139) | @Override
method addFaceWithAll (line 145) | @Override
method addFace (line 151) | @Override
method setMtlFileNames (line 158) | @Override
FILE: src/main/java/de/javagl/obj/BasicWritableObj.java
class BasicWritableObj (line 49) | public class BasicWritableObj implements WritableObj
method BasicWritableObj (line 89) | public BasicWritableObj()
method setVertexConsumer (line 99) | public void setVertexConsumer(Consumer<? super FloatTuple> vertexConsu...
method setTexCoordConsumer (line 109) | public void setTexCoordConsumer(
method setNormalConsumer (line 120) | public void setNormalConsumer(Consumer<? super FloatTuple> normalConsu...
method setFaceConsumer (line 130) | public void setFaceConsumer(Consumer<? super ObjFace> faceConsumer)
method setGroupNamesConsumer (line 140) | public void setGroupNamesConsumer(
method setMaterialGroupNameConsumer (line 151) | public void setMaterialGroupNameConsumer(
method setMtlFileNamesConsumer (line 162) | public void setMtlFileNamesConsumer(
method addVertex (line 169) | @Override
method addVertex (line 178) | @Override
method addTexCoord (line 184) | @Override
method addTexCoord (line 193) | @Override
method addTexCoord (line 199) | @Override
method addTexCoord (line 205) | @Override
method addNormal (line 212) | @Override
method addNormal (line 221) | @Override
method setActiveGroupNames (line 227) | @Override
method setActiveMaterialGroupName (line 238) | @Override
method addFace (line 247) | @Override
method addFace (line 256) | @Override
method addFaceWithTexCoords (line 262) | @Override
method addFaceWithNormals (line 268) | @Override
method addFaceWithAll (line 274) | @Override
method addFace (line 280) | @Override
method setMtlFileNames (line 291) | @Override
FILE: src/main/java/de/javagl/obj/DefaultFloatTuple.java
class DefaultFloatTuple (line 35) | final class DefaultFloatTuple implements FloatTuple
method DefaultFloatTuple (line 47) | DefaultFloatTuple(float[] values)
method DefaultFloatTuple (line 60) | DefaultFloatTuple(float x, float y, float z, float w)
method DefaultFloatTuple (line 72) | DefaultFloatTuple(float x, float y, float z)
method DefaultFloatTuple (line 83) | DefaultFloatTuple(float x, float y)
method DefaultFloatTuple (line 93) | DefaultFloatTuple(float x)
method DefaultFloatTuple (line 104) | DefaultFloatTuple(FloatTuple other)
method getValues (line 115) | private static float[] getValues(FloatTuple f)
method get (line 130) | @Override
method getX (line 136) | @Override
method setX (line 149) | void setX(float x)
method getY (line 154) | @Override
method setY (line 167) | void setY(float y)
method getZ (line 172) | @Override
method setZ (line 185) | void setZ(float z)
method getW (line 190) | @Override
method setW (line 203) | void setW(float w)
method getDimensions (line 208) | @Override
method toString (line 215) | @Override
method hashCode (line 232) | @Override
method equals (line 238) | @Override
FILE: src/main/java/de/javagl/obj/DefaultMtl.java
class DefaultMtl (line 36) | final class DefaultMtl implements Mtl
method DefaultMtl (line 210) | DefaultMtl(String name)
method getName (line 216) | @Override
method getIllum (line 222) | @Override
method setIllum (line 228) | @Override
method getNi (line 234) | @Override
method setNi (line 240) | @Override
method getTf (line 246) | @Override
method setTf (line 252) | @Override
method getSharpness (line 258) | @Override
method setSharpness (line 264) | @Override
method getKa (line 271) | @Override
method setKa (line 277) | @Override
method getMapKa (line 283) | @Override
method setMapKa (line 293) | @Override
method getMapKaOptions (line 303) | @Override
method setMapKaOptions (line 309) | @Override
method getKd (line 315) | @Override
method setKd (line 321) | @Override
method getMapKd (line 327) | @Override
method setMapKd (line 337) | @Override
method getMapKdOptions (line 347) | @Override
method setMapKdOptions (line 353) | @Override
method getKs (line 359) | @Override
method setKs (line 365) | @Override
method getMapKs (line 371) | @Override
method setMapKs (line 381) | @Override
method getMapKsOptions (line 391) | @Override
method setMapKsOptions (line 397) | @Override
method getNs (line 403) | @Override
method setNs (line 409) | @Override
method getMapNs (line 415) | @Override
method setMapNs (line 425) | @Override
method getMapNsOptions (line 435) | @Override
method setMapNsOptions (line 441) | @Override
method getD (line 447) | @Override
method setD (line 453) | @Override
method isHalo (line 459) | @Override
method setHalo (line 465) | @Override
method getMapD (line 471) | @Override
method setMapD (line 481) | @Override
method getMapDOptions (line 491) | @Override
method setMapDOptions (line 497) | @Override
method getBump (line 503) | @Override
method setBump (line 513) | @Override
method getBumpOptions (line 523) | @Override
method setBumpOptions (line 529) | @Override
method getDisp (line 535) | @Override
method setDisp (line 545) | @Override
method getDispOptions (line 555) | @Override
method setDispOptions (line 561) | @Override
method getDecal (line 567) | @Override
method setDecal (line 577) | @Override
method getDecalOptions (line 587) | @Override
method setDecalOptions (line 593) | @Override
method getReflOptions (line 599) | @Override
method getPr (line 607) | @Override
method setPr (line 613) | @Override
method getMapPr (line 619) | @Override
method setMapPr (line 629) | @Override
method getMapPrOptions (line 639) | @Override
method setMapPrOptions (line 645) | @Override
method getPm (line 651) | @Override
method setPm (line 657) | @Override
method getMapPm (line 663) | @Override
method setMapPm (line 673) | @Override
method getMapPmOptions (line 683) | @Override
method setMapPmOptions (line 689) | @Override
method getPs (line 695) | @Override
method setPs (line 701) | @Override
method getMapPs (line 707) | @Override
method setMapPs (line 717) | @Override
method getMapPsOptions (line 727) | @Override
method setMapPsOptions (line 733) | @Override
method getPc (line 739) | @Override
method setPc (line 745) | @Override
method getPcr (line 751) | @Override
method setPcr (line 757) | @Override
method getKe (line 763) | @Override
method setKe (line 769) | @Override
method getMapKe (line 775) | @Override
method setMapKe (line 785) | @Override
method getMapKeOptions (line 795) | @Override
method setMapKeOptions (line 801) | @Override
method getAniso (line 807) | @Override
method setAniso (line 813) | @Override
method getAnisor (line 819) | @Override
method setAnisor (line 825) | @Override
method getNorm (line 831) | @Override
method setNorm (line 841) | @Override
method getNormOptions (line 851) | @Override
method setNormOptions (line 857) | @Override
method toString (line 863) | @Override
FILE: src/main/java/de/javagl/obj/DefaultObj.java
class DefaultObj (line 45) | final class DefaultObj implements Obj
method DefaultObj (line 141) | DefaultObj()
method getNumVertices (line 162) | @Override
method getVertex (line 168) | @Override
method getNumTexCoords (line 174) | @Override
method getTexCoord (line 180) | @Override
method getNumNormals (line 186) | @Override
method getNormal (line 192) | @Override
method getNumFaces (line 199) | @Override
method getFace (line 205) | @Override
method getActivatedGroupNames (line 211) | @Override
method getActivatedMaterialGroupName (line 217) | @Override
method getNumGroups (line 223) | @Override
method getGroup (line 229) | @Override
method getGroup (line 235) | @Override
method getNumMaterialGroups (line 241) | @Override
method getMaterialGroup (line 247) | @Override
method getMaterialGroup (line 253) | @Override
method getMtlFileNames (line 260) | @Override
method addVertex (line 269) | @Override
method addVertex (line 276) | @Override
method addTexCoord (line 282) | @Override
method addTexCoord (line 289) | @Override
method addTexCoord (line 295) | @Override
method addTexCoord (line 301) | @Override
method addNormal (line 308) | @Override
method addNormal (line 315) | @Override
method setActiveGroupNames (line 321) | @Override
method setActiveMaterialGroupName (line 341) | @Override
method addFace (line 351) | @Override
method addFace (line 391) | @Override
method addFaceWithTexCoords (line 397) | @Override
method addFaceWithNormals (line 403) | @Override
method addFaceWithAll (line 409) | @Override
method addFace (line 415) | @Override
method setMtlFileNames (line 427) | @Override
method toString (line 435) | @Override
method getGroupsInternal (line 456) | private List<DefaultObjGroup> getGroupsInternal(
method getGroupInternal (line 476) | private DefaultObjGroup getGroupInternal(String groupName)
method getMaterialGroupInternal (line 495) | private DefaultObjGroup getMaterialGroupInternal(String materialGroupN...
method checkIndices (line 519) | private static void checkIndices(int[] indices, int max, String name)
FILE: src/main/java/de/javagl/obj/DefaultObjFace.java
class DefaultObjFace (line 34) | final class DefaultObjFace implements ObjFace
method DefaultObjFace (line 59) | DefaultObjFace(
method containsTexCoordIndices (line 68) | @Override
method containsNormalIndices (line 74) | @Override
method getVertexIndex (line 80) | @Override
method getTexCoordIndex (line 86) | @Override
method getNormalIndex (line 92) | @Override
method setVertexIndex (line 104) | void setVertexIndex(int n, int index)
method setNormalIndex (line 115) | void setNormalIndex(int n, int index)
method setTexCoordIndex (line 126) | void setTexCoordIndex(int n, int index)
method getNumVertices (line 131) | @Override
method toString (line 137) | @Override
FILE: src/main/java/de/javagl/obj/DefaultObjGroup.java
class DefaultObjGroup (line 36) | final class DefaultObjGroup implements ObjGroup
method DefaultObjGroup (line 53) | DefaultObjGroup(String name)
method getName (line 59) | @Override
method addFace (line 70) | void addFace(ObjFace face)
method getNumFaces (line 75) | @Override
method getFace (line 81) | @Override
method toString (line 87) | @Override
FILE: src/main/java/de/javagl/obj/DefaultTextureOptions.java
class DefaultTextureOptions (line 34) | final class DefaultTextureOptions implements TextureOptions
method DefaultTextureOptions (line 109) | DefaultTextureOptions()
method getFileName (line 114) | @Override
method setFileName (line 120) | @Override
method isBlendu (line 126) | @Override
method setBlendu (line 132) | @Override
method isBlendv (line 138) | @Override
method setBlendv (line 144) | @Override
method getBoost (line 150) | @Override
method isCc (line 156) | @Override
method setCc (line 162) | @Override
method setBoost (line 168) | @Override
method getMm (line 174) | @Override
method setMm (line 180) | @Override
method getO (line 192) | @Override
method setO (line 198) | @Override
method getS (line 204) | @Override
method setS (line 210) | @Override
method getT (line 216) | @Override
method setT (line 222) | @Override
method getTexres (line 228) | @Override
method setTexres (line 234) | @Override
method isClamp (line 240) | @Override
method setClamp (line 246) | @Override
method getBm (line 252) | @Override
method setBm (line 258) | @Override
method getImfchan (line 264) | @Override
method setImfchan (line 270) | @Override
method getType (line 276) | @Override
method setType (line 282) | @Override
method toString (line 288) | @Override
method hashCode (line 299) | @Override
method equals (line 306) | @Override
FILE: src/main/java/de/javagl/obj/FloatTuple.java
type FloatTuple (line 33) | public interface FloatTuple
method getX (line 42) | float getX();
method getY (line 51) | float getY();
method getZ (line 60) | float getZ();
method getW (line 69) | float getW();
method get (line 79) | float get(int index);
method getDimensions (line 86) | int getDimensions();
FILE: src/main/java/de/javagl/obj/FloatTuples.java
class FloatTuples (line 32) | public class FloatTuples
method copy (line 40) | public static FloatTuple copy(FloatTuple other)
method create (line 51) | public static FloatTuple create(float x)
method create (line 63) | public static FloatTuple create(float x, float y)
method create (line 76) | public static FloatTuple create(float x, float y, float z)
method create (line 90) | public static FloatTuple create(float x, float y, float z, float w)
method createString (line 103) | public static String createString(FloatTuple tuple)
method FloatTuples (line 120) | private FloatTuples()
FILE: src/main/java/de/javagl/obj/Mtl.java
type Mtl (line 37) | public interface Mtl
method getName (line 44) | String getName();
method getIllum (line 52) | Integer getIllum();
method setIllum (line 59) | void setIllum(Integer illum);
method getNi (line 67) | Float getNi();
method setNi (line 74) | void setNi(Float ni);
method getTf (line 82) | FloatTuple getTf();
method setTf (line 91) | void setTf(Float r, Float g, Float b);
method getSharpness (line 99) | Float getSharpness();
method setSharpness (line 106) | void setSharpness(Float sharpness);
method getKa (line 118) | FloatTuple getKa();
method setKa (line 127) | void setKa(Float r, Float g, Float b);
method getMapKa (line 135) | String getMapKa();
method setMapKa (line 142) | void setMapKa(String mapKa);
method getMapKaOptions (line 150) | TextureOptions getMapKaOptions();
method setMapKaOptions (line 157) | void setMapKaOptions(TextureOptions options);
method getKd (line 171) | FloatTuple getKd();
method setKd (line 180) | void setKd(Float r, Float g, Float b);
method getMapKd (line 189) | String getMapKd();
method setMapKd (line 196) | void setMapKd(String mapKd);
method getMapKdOptions (line 204) | TextureOptions getMapKdOptions();
method setMapKdOptions (line 211) | void setMapKdOptions(TextureOptions options);
method getKs (line 224) | FloatTuple getKs();
method setKs (line 233) | void setKs(Float r, Float g, Float b);
method getMapKs (line 241) | String getMapKs();
method setMapKs (line 248) | void setMapKs(String mapKs);
method getMapKsOptions (line 256) | TextureOptions getMapKsOptions();
method setMapKsOptions (line 263) | void setMapKsOptions(TextureOptions options);
method getNs (line 275) | Float getNs();
method setNs (line 283) | void setNs(Float ns);
method getMapNs (line 291) | String getMapNs();
method setMapNs (line 298) | void setMapNs(String mapNs);
method getMapNsOptions (line 306) | TextureOptions getMapNsOptions();
method setMapNsOptions (line 313) | void setMapNsOptions(TextureOptions options);
method getD (line 325) | Float getD();
method setD (line 332) | void setD(Float d);
method isHalo (line 340) | Boolean isHalo();
method setHalo (line 347) | void setHalo(Boolean halo);
method getMapD (line 355) | String getMapD();
method setMapD (line 362) | void setMapD(String mapD);
method getMapDOptions (line 370) | TextureOptions getMapDOptions();
method setMapDOptions (line 377) | void setMapDOptions(TextureOptions options);
method getBump (line 389) | String getBump();
method setBump (line 396) | void setBump(String bump);
method getBumpOptions (line 404) | TextureOptions getBumpOptions();
method setBumpOptions (line 411) | void setBumpOptions(TextureOptions options);
method getDisp (line 424) | String getDisp();
method setDisp (line 431) | void setDisp(String disp);
method getDispOptions (line 439) | TextureOptions getDispOptions();
method setDispOptions (line 446) | void setDispOptions(TextureOptions options);
method getDecal (line 459) | String getDecal();
method setDecal (line 466) | void setDecal(String decal);
method getDecalOptions (line 474) | TextureOptions getDecalOptions();
method setDecalOptions (line 481) | void setDecalOptions(TextureOptions options);
method getReflOptions (line 494) | List<TextureOptions> getReflOptions();
method getPr (line 508) | Float getPr();
method setPr (line 515) | void setPr(Float pr);
method getMapPr (line 523) | String getMapPr();
method setMapPr (line 530) | void setMapPr(String mapPr);
method getMapPrOptions (line 538) | TextureOptions getMapPrOptions();
method setMapPrOptions (line 545) | void setMapPrOptions(TextureOptions options);
method getPm (line 557) | Float getPm();
method setPm (line 564) | void setPm(Float pm);
method getMapPm (line 572) | String getMapPm();
method setMapPm (line 579) | void setMapPm(String mapPm);
method getMapPmOptions (line 587) | TextureOptions getMapPmOptions();
method setMapPmOptions (line 594) | void setMapPmOptions(TextureOptions options);
method getPs (line 606) | Float getPs();
method setPs (line 613) | void setPs(Float ps);
method getMapPs (line 621) | String getMapPs();
method setMapPs (line 628) | void setMapPs(String mapPs);
method getMapPsOptions (line 636) | TextureOptions getMapPsOptions();
method setMapPsOptions (line 643) | void setMapPsOptions(TextureOptions options);
method getPc (line 655) | Float getPc();
method setPc (line 662) | void setPc(Float pc);
method getPcr (line 673) | Float getPcr();
method setPcr (line 680) | void setPcr(Float pcr);
method getKe (line 692) | FloatTuple getKe();
method setKe (line 701) | void setKe(Float r, Float g, Float b);
method getMapKe (line 709) | String getMapKe();
method setMapKe (line 716) | void setMapKe(String mapKe);
method getMapKeOptions (line 724) | TextureOptions getMapKeOptions();
method setMapKeOptions (line 731) | void setMapKeOptions(TextureOptions options);
method getAniso (line 743) | Float getAniso();
method setAniso (line 750) | void setAniso(Float aniso);
method getAnisor (line 761) | Float getAnisor();
method setAnisor (line 768) | void setAnisor(Float anisor);
method getNorm (line 780) | String getNorm();
method setNorm (line 787) | void setNorm(String norm);
method getNormOptions (line 795) | TextureOptions getNormOptions();
method setNormOptions (line 802) | void setNormOptions(TextureOptions options);
FILE: src/main/java/de/javagl/obj/MtlReader.java
class MtlReader (line 44) | public class MtlReader
method read (line 55) | public static List<Mtl> read(InputStream inputStream)
method read (line 72) | public static List<Mtl> read(Reader reader)
method readImpl (line 91) | private static List<Mtl> readImpl(BufferedReader reader)
method processLine (line 156) | private static void processLine(Mtl mtl, String line)
method readTextureMap (line 292) | private static void readTextureMap(
method readTextureOptions (line 368) | static TextureOptions readTextureOptions(Queue<String> tokens)
method MtlReader (line 453) | private MtlReader()
FILE: src/main/java/de/javagl/obj/MtlWriter.java
class MtlWriter (line 38) | public class MtlWriter
method write (line 48) | public static void write(
method write (line 65) | public static void write(
method write (line 82) | private static void write(Mtl mtl, Writer writer)
method createString (line 96) | private static String createString(Mtl mtl)
method appendTextureOptions (line 162) | private static void appendTextureOptions(
method createString (line 179) | static String createString(TextureOptions options)
method append (line 207) | private static void append(
method append (line 227) | private static void append(
method appendTuple (line 254) | private static void appendTuple(
method MtlWriter (line 268) | private MtlWriter()
FILE: src/main/java/de/javagl/obj/Mtls.java
class Mtls (line 32) | public class Mtls
method create (line 40) | public static Mtl create(String name)
method Mtls (line 48) | private Mtls()
FILE: src/main/java/de/javagl/obj/Obj.java
type Obj (line 37) | public interface Obj extends ReadableObj, WritableObj
FILE: src/main/java/de/javagl/obj/ObjData.java
class ObjData (line 40) | public class ObjData
method getNumFaceVertices (line 53) | private static int[] getNumFaceVertices(ReadableObj obj)
method getTotalNumFaceVertices (line 72) | public static int getTotalNumFaceVertices(ReadableObj obj)
method sum (line 83) | private static int sum(int[] array)
method getFaceVertexIndicesArray (line 110) | public static int[] getFaceVertexIndicesArray(ReadableObj obj)
method getFaceVertexIndices (line 132) | public static IntBuffer getFaceVertexIndices(ReadableObj obj)
method getFaceVertexIndicesArray (line 150) | public static int[] getFaceVertexIndicesArray(
method getFaceVertexIndices (line 170) | public static IntBuffer getFaceVertexIndices(
method getFaceVertexIndices (line 195) | public static void getFaceVertexIndices(
method getFaceTexCoordIndicesArray (line 226) | public static int[] getFaceTexCoordIndicesArray(ReadableObj obj)
method getFaceTexCoordIndices (line 248) | public static IntBuffer getFaceTexCoordIndices(ReadableObj obj)
method getFaceTexCoordIndicesArray (line 269) | public static int[] getFaceTexCoordIndicesArray(
method getFaceTexCoordIndices (line 292) | public static IntBuffer getFaceTexCoordIndices(
method getFaceTexCoordIndices (line 321) | public static void getFaceTexCoordIndices(
method getFaceNormalIndicesArray (line 351) | public static int[] getFaceNormalIndicesArray(ReadableObj obj)
method getFaceNormalIndices (line 373) | public static IntBuffer getFaceNormalIndices(ReadableObj obj)
method getFaceNormalIndicesArray (line 394) | public static int[] getFaceNormalIndicesArray(
method getFaceNormalIndices (line 417) | public static IntBuffer getFaceNormalIndices(
method getFaceNormalIndices (line 446) | public static void getFaceNormalIndices(
method getVerticesArray (line 470) | public static float[] getVerticesArray(ReadableObj obj)
method getVertices (line 488) | public static FloatBuffer getVertices(ReadableObj obj)
method getVertices (line 506) | public static void getVertices(
method getTexCoordsArray (line 533) | public static float[] getTexCoordsArray(ReadableObj obj, int dimensions)
method getTexCoordsArray (line 554) | public static float[] getTexCoordsArray(
method getTexCoords (line 572) | public static FloatBuffer getTexCoords(ReadableObj obj, int dimensions)
method getTexCoords (line 595) | public static FloatBuffer getTexCoords(
method getTexCoords (line 617) | public static void getTexCoords(
method getTexCoords (line 642) | public static void getTexCoords(
method getNormalsArray (line 687) | public static float[] getNormalsArray(ReadableObj obj)
method getNormals (line 704) | public static FloatBuffer getNormals(ReadableObj obj)
method getNormals (line 722) | public static void getNormals(
method convertToShortBuffer (line 752) | public static ShortBuffer convertToShortBuffer(IntBuffer intBuffer)
method createDirectIntBuffer (line 768) | private static IntBuffer createDirectIntBuffer(int size)
method createDirectShortBuffer (line 781) | private static ShortBuffer createDirectShortBuffer(int size)
method createDirectFloatBuffer (line 794) | private static FloatBuffer createDirectFloatBuffer(int size)
method ObjData (line 804) | private ObjData()
FILE: src/main/java/de/javagl/obj/ObjFace.java
type ObjFace (line 34) | public interface ObjFace
method getNumVertices (line 41) | int getNumVertices();
method containsTexCoordIndices (line 48) | boolean containsTexCoordIndices();
method containsNormalIndices (line 55) | boolean containsNormalIndices();
method getVertexIndex (line 67) | int getVertexIndex(int number);
method getTexCoordIndex (line 79) | int getTexCoordIndex(int number);
method getNormalIndex (line 91) | int getNormalIndex(int number);
FILE: src/main/java/de/javagl/obj/ObjFaceParser.java
class ObjFaceParser (line 37) | final class ObjFaceParser
method parse (line 93) | void parse(String line) throws IOException
method getVertexIndices (line 105) | int[] getVertexIndices()
method getTexCoordIndices (line 118) | int[] getTexCoordIndices()
method getNormalIndices (line 135) | int[] getNormalIndices()
method parseLine (line 151) | void parseLine(String line) throws IOException
method endOfInput (line 280) | private boolean endOfInput()
method skipSpaces (line 289) | private void skipSpaces()
method parseNonzeroInt (line 303) | private int parseNonzeroInt()
FILE: src/main/java/de/javagl/obj/ObjFaces.java
class ObjFaces (line 32) | public class ObjFaces
method create (line 40) | static DefaultObjFace create(ObjFace face)
method createWithOffsets (line 84) | static DefaultObjFace createWithOffsets(ObjFace face,
method create (line 129) | static DefaultObjFace create(ObjFace face, int ... n)
method create (line 174) | public static ObjFace create(int[] v, int[] vt, int[] vn)
method createDefault (line 191) | static DefaultObjFace createDefault(int[] v, int[] vt, int[] vn)
method createString (line 205) | public static String createString(ObjFace face)
method ObjFaces (line 234) | private ObjFaces()
FILE: src/main/java/de/javagl/obj/ObjGroup.java
type ObjGroup (line 36) | public interface ObjGroup
method getName (line 43) | String getName();
method getNumFaces (line 50) | int getNumFaces();
method getFace (line 60) | ObjFace getFace(int index);
FILE: src/main/java/de/javagl/obj/ObjReader.java
class ObjReader (line 45) | public class ObjReader
method read (line 55) | public static Obj read(InputStream inputStream) throws IOException
method read (line 71) | public static <T extends WritableObj> T read(
method read (line 88) | public static Obj read(Reader reader) throws IOException
method read (line 104) | public static <T extends WritableObj> T read(
method readImpl (line 127) | private static <T extends WritableObj> T readImpl(
method makeIndicesAbsolute (line 248) | private static void makeIndicesAbsolute(int[] array, int count)
method readStrings (line 275) | private static String[] readStrings(String input)
method ObjReader (line 289) | private ObjReader()
FILE: src/main/java/de/javagl/obj/ObjSplitter.java
class ObjSplitter (line 41) | class ObjSplitter
type Predicate (line 60) | private interface Predicate<T>
method test (line 68) | boolean test(T t);
method ObjSplitter (line 84) | ObjSplitter(final int maxNumVertices)
method split (line 103) | List<Obj> split(ReadableObj obj)
method splitSingle (line 151) | private static List<Obj> splitSingle(ReadableObj obj)
method split (line 204) | private static List<Obj> split(ReadableObj obj, List<ObjFace> allFaces)
method asGroup (line 226) | private static ObjGroup asGroup(final List<? extends ObjFace> faces)
method computeFacePredicate (line 257) | private static Predicate<ObjFace> computeFacePredicate(
method computeFaceCenters (line 321) | private static float[] computeFaceCenters(ReadableObj obj, int component)
method computeFaceCenter (line 342) | private static float computeFaceCenter(
method arithmeticMean (line 363) | private static float arithmeticMean(float[] array)
method variance (line 380) | private static float variance(float[] array, float mean)
FILE: src/main/java/de/javagl/obj/ObjSplitting.java
class ObjSplitting (line 37) | public class ObjSplitting
method splitByGroups (line 47) | public static Map<String, Obj> splitByGroups(ReadableObj obj)
method splitByMaterialGroups (line 82) | public static Map<String, Obj> splitByMaterialGroups(ReadableObj obj)
method splitByMaxNumVertices (line 126) | public static List<Obj> splitByMaxNumVertices(
method ObjSplitting (line 142) | private ObjSplitting()
FILE: src/main/java/de/javagl/obj/ObjUtils.java
class ObjUtils (line 40) | public class ObjUtils
method convertToRenderable (line 64) | public static Obj convertToRenderable(ReadableObj input)
method convertToRenderable (line 93) | public static <T extends WritableObj> T convertToRenderable(
method triangulate (line 113) | public static Obj triangulate(ReadableObj input)
method triangulate (line 130) | public static <T extends WritableObj> T triangulate(
method groupToObj (line 173) | public static Obj groupToObj(
method groupToObj (line 196) | public static <T extends WritableObj> T groupToObj(
type PropertyIndexAccessor (line 299) | private interface PropertyIndexAccessor
method getPropertyIndex (line 311) | int getPropertyIndex(
method hasProperty (line 321) | boolean hasProperty(ObjFace face);
method makeTexCoordsUnique (line 342) | public static Obj makeTexCoordsUnique(ReadableObj input)
method makeTexCoordsUnique (line 372) | public static <T extends WritableObj> T makeTexCoordsUnique(
method makeNormalsUnique (line 412) | public static Obj makeNormalsUnique(ReadableObj input)
method makeNormalsUnique (line 443) | public static <T extends WritableObj> T makeNormalsUnique(
method makePropertiesUnique (line 490) | private static void makePropertiesUnique(
method addAll (line 571) | private static void addAll(ReadableObj input, WritableObj output)
method add (line 599) | public static void add(ReadableObj input, Obj output)
method makeVertexIndexed (line 645) | public static Obj makeVertexIndexed(ReadableObj input)
method makeVertexIndexed (line 665) | public static <T extends WritableObj> T makeVertexIndexed(
method activateGroups (line 759) | private static void activateGroups(
method createInfoString (line 788) | public static String createInfoString(ReadableObj obj)
method ObjUtils (line 821) | private ObjUtils()
FILE: src/main/java/de/javagl/obj/ObjWriter.java
class ObjWriter (line 40) | public class ObjWriter
method write (line 50) | public static void write(ReadableObj input, OutputStream outputStream)
method write (line 66) | public static void write(ReadableObj input, Writer writer)
method ObjWriter (line 146) | private ObjWriter()
FILE: src/main/java/de/javagl/obj/Objs.java
class Objs (line 35) | public class Objs
method create (line 42) | public static Obj create()
method createFromIndexedTriangleData (line 68) | public static Obj createFromIndexedTriangleData(
method Objs (line 134) | private Objs()
FILE: src/main/java/de/javagl/obj/ReadableObj.java
type ReadableObj (line 45) | public interface ReadableObj
method getNumVertices (line 52) | int getNumVertices();
method getVertex (line 64) | FloatTuple getVertex(int index);
method getNumTexCoords (line 72) | int getNumTexCoords();
method getTexCoord (line 84) | FloatTuple getTexCoord(int index);
method getNumNormals (line 92) | int getNumNormals();
method getNormal (line 104) | FloatTuple getNormal(int index);
method getNumFaces (line 112) | int getNumFaces();
method getFace (line 122) | ObjFace getFace(int index);
method getActivatedGroupNames (line 134) | Set<String> getActivatedGroupNames(ObjFace face);
method getActivatedMaterialGroupName (line 146) | String getActivatedMaterialGroupName(ObjFace face);
method getNumGroups (line 153) | int getNumGroups();
method getGroup (line 163) | ObjGroup getGroup(int index);
method getGroup (line 172) | ObjGroup getGroup(String name);
method getNumMaterialGroups (line 181) | int getNumMaterialGroups();
method getMaterialGroup (line 191) | ObjGroup getMaterialGroup(int index);
method getMaterialGroup (line 200) | ObjGroup getMaterialGroup(String name);
method getMtlFileNames (line 211) | List<String> getMtlFileNames();
FILE: src/main/java/de/javagl/obj/TextureOptions.java
type TextureOptions (line 34) | public interface TextureOptions
method getFileName (line 41) | String getFileName();
method setFileName (line 48) | void setFileName(String fileName);
method isBlendu (line 56) | Boolean isBlendu();
method setBlendu (line 63) | void setBlendu(Boolean blendu);
method isBlendv (line 71) | Boolean isBlendv();
method setBlendv (line 78) | void setBlendv(Boolean blendv);
method isCc (line 86) | Boolean isCc();
method setCc (line 93) | void setCc(Boolean cc);
method getBoost (line 101) | Float getBoost();
method setBoost (line 108) | void setBoost(Float boost);
method getMm (line 116) | FloatTuple getMm();
method setMm (line 124) | void setMm(Float base, Float gain);
method getO (line 132) | FloatTuple getO();
method setO (line 141) | void setO(Float u, Float v, Float w);
method getS (line 149) | FloatTuple getS();
method setS (line 158) | void setS(Float u, Float v, Float w);
method getT (line 166) | FloatTuple getT();
method setT (line 175) | void setT(Float u, Float v, Float w);
method getTexres (line 183) | Float getTexres();
method setTexres (line 190) | void setTexres(Float texres);
method isClamp (line 198) | Boolean isClamp();
method setClamp (line 205) | void setClamp(Boolean clamp);
method getBm (line 213) | Float getBm();
method setBm (line 220) | void setBm(Float bm);
method getImfchan (line 228) | String getImfchan();
method setImfchan (line 235) | void setImfchan(String imfchan);
method getType (line 243) | String getType();
method setType (line 250) | void setType(String type);
FILE: src/main/java/de/javagl/obj/Utils.java
class Utils (line 36) | class Utils
method readFloatTuple (line 45) | static FloatTuple readFloatTuple(StringTokenizer st)
method parseFloat (line 77) | static float parseFloat(String s) throws IOException
method isFloat (line 96) | private static boolean isFloat(String s)
method parseFloats (line 123) | static Float[] parseFloats(Queue<String> tokens, int max)
method parseBoolean (line 146) | static boolean parseBoolean(String s)
method parseInt (line 168) | static int parseInt(String s) throws IOException
method createRgbTuple (line 193) | static FloatTuple createRgbTuple(Float r, Float g, Float b)
method createUvwTuple (line 227) | static FloatTuple createUvwTuple(
method Utils (line 244) | private Utils()
FILE: src/main/java/de/javagl/obj/WritableObj.java
type WritableObj (line 36) | public interface WritableObj
method addVertex (line 44) | void addVertex(FloatTuple vertex);
method addVertex (line 53) | void addVertex(float x, float y, float z);
method addTexCoord (line 62) | void addTexCoord(FloatTuple texCoord);
method addTexCoord (line 69) | void addTexCoord(float x);
method addTexCoord (line 77) | void addTexCoord(float x, float y);
method addTexCoord (line 86) | void addTexCoord(float x, float y, float z);
method addNormal (line 94) | void addNormal(FloatTuple normal);
method addNormal (line 103) | void addNormal(float x, float y, float z);
method setActiveGroupNames (line 116) | void setActiveGroupNames(Collection<? extends String> groupNames);
method setActiveMaterialGroupName (line 127) | void setActiveMaterialGroupName(String materialGroupName);
method addFace (line 139) | void addFace(ObjFace face);
method addFace (line 154) | void addFace(int ... v);
method addFaceWithTexCoords (line 169) | void addFaceWithTexCoords(int ... v);
method addFaceWithNormals (line 184) | void addFaceWithNormals(int ... v);
method addFaceWithAll (line 199) | void addFaceWithAll(int ... v);
method addFace (line 220) | void addFace(int[] v, int[] vt, int[] vn);
method setMtlFileNames (line 228) | void setMtlFileNames(Collection<? extends String> mtlFileNames);
FILE: src/test/java/de/javagl/obj/TestMtlReader.java
class TestMtlReader (line 13) | @SuppressWarnings("javadoc")
method readMtl (line 21) | @Test
method readMtlWithWhitespace (line 37) | @Test
method readMtlWithBrokenLines (line 56) | @Test
method readTextureOptionsWithAllOptions (line 75) | @Test
method readTextureOptionsWithSingleOriginOffsetValue (line 135) | @Test
method readTextureOptionsWithDoubleOriginOffsetValue (line 151) | @Test
method readMtlWithPbrProperties (line 167) | @Test
FILE: src/test/java/de/javagl/obj/TestMtlWriter.java
class TestMtlWriter (line 15) | @SuppressWarnings("javadoc")
method writeMtl (line 18) | @Test
method writeComplexMtl (line 35) | @Test
method writePbrMtl (line 52) | @Test
method readResourceAsString (line 70) | private static String readResourceAsString(String name)
method readAsString (line 79) | private static String readAsString(InputStream inputStream)
FILE: src/test/java/de/javagl/obj/TestObjData.java
class TestObjData (line 9) | @SuppressWarnings("javadoc")
method testGetVertices (line 12) | @Test
method testGetTexCoords (line 38) | @Test
method testGetTexCoordsFlipped (line 64) | @Test
FILE: src/test/java/de/javagl/obj/TestObjReader.java
class TestObjReader (line 11) | @SuppressWarnings("javadoc")
method readSquare (line 14) | @Test
method readSquareAndTriangle (line 29) | @Test
method readSquareAndTriangleInTwoGroups (line 44) | @Test
method readFourTrianglesInMixedGroups (line 59) | @Test
method readTwoTrianglesOneInDefaultGroup (line 75) | @Test
method readTwoTrianglesSharedInThreeGroups (line 91) | @Test
method readSquareAndTriangleWithRelativeIndices (line 107) | @Test
method readMtls (line 123) | @Test
FILE: src/test/java/de/javagl/obj/TestObjSplitting.java
class TestObjSplitting (line 11) | @SuppressWarnings("javadoc")
method testSplitByGroup (line 14) | @Test
method testSplitByGroupOnlyDefault (line 25) | @Test
method testSplitByMaterialGroup (line 36) | @Test
method testSplitByMaterialGroupWithoutMaterial (line 47) | @Test
method testSplitByMaterialGroupForPartialGroups (line 60) | @Test
method testSplitByNumVertices (line 73) | @Test
method testSplitByNumVerticesForInvalidInput (line 91) | @Test
FILE: src/test/java/de/javagl/obj/TestObjUtilsAdd.java
class TestObjUtilsAdd (line 9) | @SuppressWarnings("javadoc")
method testAdd (line 12) | @Test
method testAddDifferent (line 38) | @Test
method testAddWithMaterialGroups (line 76) | @Test
FILE: src/test/java/de/javagl/obj/TestObjUtilsGroupToObj.java
class TestObjUtilsGroupToObj (line 10) | @SuppressWarnings("javadoc")
method testGroupToObj (line 13) | @Test
FILE: src/test/java/de/javagl/obj/TestObjUtilsMakeTexCoordsUnique.java
class TestObjUtilsMakeTexCoordsUnique (line 10) | @SuppressWarnings("javadoc")
method testMakeTexCoordsUnique (line 13) | @Test
FILE: src/test/java/de/javagl/obj/TestObjUtilsTriangulate.java
class TestObjUtilsTriangulate (line 10) | @SuppressWarnings("javadoc")
method testTriangulateSquareAndTriangle (line 13) | @Test
FILE: src/test/java/de/javagl/obj/TestObjWriter.java
class TestObjWriter (line 13) | @SuppressWarnings("javadoc")
method readWriteSquare (line 16) | @Test
method readWriteSquareAndTriangle (line 33) | @Test
method readWriteSquareAndTriangleInTwoGroups (line 50) | @Test
method readWriteFourTrianglesInMixedGroups (line 67) | @Test
method readWriteTwoTrianglesOneInDefaultGroup (line 84) | @Test
method readTwoTrianglesSharedInThreeGroups (line 102) | @Test
method readResourceAsString (line 119) | private static String readResourceAsString(String name)
method readAsString (line 128) | private static String readAsString(InputStream inputStream)
FILE: src/test/java/de/javagl/obj/TestObjsCreate.java
class TestObjsCreate (line 11) | @SuppressWarnings("javadoc")
method createFromIndexedTriangleData (line 14) | @Test
Condensed preview — 63 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (347K chars).
[
{
"path": ".gitignore",
"chars": 38,
"preview": "target/\n.classpath\n.project\n.settings\n"
},
{
"path": "LICENSE.txt",
"chars": 1133,
"preview": "\r\nwww.javagl.de - Obj\r\n\r\nCopyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n\r\nPermission is hereby granted, fr"
},
{
"path": "README.md",
"chars": 7343,
"preview": "# Obj - a simple Wavefront OBJ file loader and writer\n\nMaven dependency:\n\n <dependency>\n <groupId>de.javagl</gro"
},
{
"path": "pom.xml",
"chars": 3114,
"preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocat"
},
{
"path": "src/main/java/de/javagl/obj/AbstractWritableObj.java",
"chars": 4366,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/BasicWritableObj.java",
"chars": 7883,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/DefaultFloatTuple.java",
"chars": 6516,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/DefaultMtl.java",
"chars": 16919,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n *\r\n * Permission is her"
},
{
"path": "src/main/java/de/javagl/obj/DefaultObj.java",
"chars": 14478,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/DefaultObjFace.java",
"chars": 4391,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/DefaultObjGroup.java",
"chars": 2395,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/DefaultTextureOptions.java",
"chars": 7160,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n *\r\n * Permission is her"
},
{
"path": "src/main/java/de/javagl/obj/FloatTuple.java",
"chars": 2752,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/FloatTuples.java",
"chars": 3736,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/Mtl.java",
"chars": 21565,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n *\r\n * Permission is her"
},
{
"path": "src/main/java/de/javagl/obj/MtlReader.java",
"chars": 15368,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n *\r\n * Permission is her"
},
{
"path": "src/main/java/de/javagl/obj/MtlWriter.java",
"chars": 9326,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n *\r\n * Permission is her"
},
{
"path": "src/main/java/de/javagl/obj/Mtls.java",
"chars": 1725,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/Obj.java",
"chars": 1683,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/ObjData.java",
"chars": 30104,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/ObjFace.java",
"chars": 3323,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/ObjFaceParser.java",
"chars": 9556,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/ObjFaces.java",
"chars": 7569,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/ObjGroup.java",
"chars": 2136,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/ObjReader.java",
"chars": 10104,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n *\r\n * Permission is her"
},
{
"path": "src/main/java/de/javagl/obj/ObjSplitter.java",
"chars": 12716,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2017 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/ObjSplitting.java",
"chars": 5959,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2017 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/ObjUtils.java",
"chars": 31715,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/ObjWriter.java",
"chars": 5342,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/Objs.java",
"chars": 4573,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/ReadableObj.java",
"chars": 6936,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/TextureOptions.java",
"chars": 6463,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n *\r\n * Permission is her"
},
{
"path": "src/main/java/de/javagl/obj/Utils.java",
"chars": 7377,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n *\r\n * Permission is her"
},
{
"path": "src/main/java/de/javagl/obj/WritableObj.java",
"chars": 8487,
"preview": "/*\r\n * www.javagl.de - Obj\r\n *\r\n * Copyright (c) 2008-2015 Marco Hutter - http://www.javagl.de\r\n * \r\n * Permission is he"
},
{
"path": "src/main/java/de/javagl/obj/package-info.java",
"chars": 459,
"preview": "/**\r\n * Classes for reading and writing Wavefront OBJ and MTL files.\r\n * <p>\r\n * {@link de.javagl.obj.Obj} objects may b"
},
{
"path": "src/test/java/de/javagl/obj/TestMtlReader.java",
"chars": 6280,
"preview": "package de.javagl.obj;\r\n\r\nimport static org.junit.Assert.assertEquals;\r\n\r\nimport java.io.IOException;\r\nimport java.util."
},
{
"path": "src/test/java/de/javagl/obj/TestMtlWriter.java",
"chars": 2571,
"preview": "package de.javagl.obj;\r\n\r\nimport static org.junit.Assert.assertEquals;\r\n\r\nimport java.io.ByteArrayInputStream;\r\nimport j"
},
{
"path": "src/test/java/de/javagl/obj/TestObjData.java",
"chars": 2832,
"preview": "package de.javagl.obj;\r\n\r\nimport static org.junit.Assert.*;\r\n\r\nimport java.io.IOException;\r\n\r\nimport org.junit.Test;\r\n\r\n"
},
{
"path": "src/test/java/de/javagl/obj/TestObjReader.java",
"chars": 4619,
"preview": "package de.javagl.obj;\r\n\r\nimport static org.junit.Assert.assertEquals;\r\n\r\nimport java.io.IOException;\r\nimport java.util."
},
{
"path": "src/test/java/de/javagl/obj/TestObjSplitting.java",
"chars": 3224,
"preview": "package de.javagl.obj;\r\n\r\nimport static org.junit.Assert.*;\r\n\r\nimport java.io.IOException;\r\nimport java.util.List;\r\nimpo"
},
{
"path": "src/test/java/de/javagl/obj/TestObjUtilsAdd.java",
"chars": 3796,
"preview": "package de.javagl.obj;\r\n\r\nimport static org.junit.Assert.assertEquals;\r\n\r\nimport java.io.IOException;\r\n\r\nimport org.juni"
},
{
"path": "src/test/java/de/javagl/obj/TestObjUtilsGroupToObj.java",
"chars": 1564,
"preview": "package de.javagl.obj;\r\n\r\nimport static org.junit.Assert.assertEquals;\r\n\r\nimport java.io.IOException;\r\n\r\nimport org.juni"
},
{
"path": "src/test/java/de/javagl/obj/TestObjUtilsMakeTexCoordsUnique.java",
"chars": 824,
"preview": "package de.javagl.obj;\r\n\r\nimport static org.junit.Assert.assertEquals;\r\n\r\nimport java.io.IOException;\r\n\r\nimport org.juni"
},
{
"path": "src/test/java/de/javagl/obj/TestObjUtilsTriangulate.java",
"chars": 1154,
"preview": "package de.javagl.obj;\r\n\r\nimport static org.junit.Assert.assertEquals;\r\n\r\nimport java.io.IOException;\r\n\r\nimport org.juni"
},
{
"path": "src/test/java/de/javagl/obj/TestObjWriter.java",
"chars": 4443,
"preview": "package de.javagl.obj;\r\n\r\nimport java.io.ByteArrayInputStream;\r\nimport java.io.ByteArrayOutputStream;\r\nimport java.io.IO"
},
{
"path": "src/test/java/de/javagl/obj/TestObjsCreate.java",
"chars": 1372,
"preview": "package de.javagl.obj;\r\n\r\nimport static org.junit.Assert.assertEquals;\r\n\r\nimport java.io.IOException;\r\nimport java.nio.F"
},
{
"path": "src/test/resources/complexMaterial.mtl",
"chars": 684,
"preview": "newmtl material0\r\nillum 3\r\nNs 500.0\r\nNi 2.3\r\nd 1.0\r\nKa 1.0 1.0 1.0\r\nKd 1.0 0.0 1.0\r\nKs 1.0 1.0 1.0\r\nTf 0.0 1.0 0.0\r\nshar"
},
{
"path": "src/test/resources/fourTrianglesInMixedGroups.obj",
"chars": 246,
"preview": "mtllib twoMaterialsA.mtl\r\nv 0.0 0.0 0.0\r\nv 4.0 0.0 0.0\r\nv 4.0 4.0 0.0\r\nv 0.0 4.0 0.0\r\nv 8.0 0.0 0.0\r\nv 8.0 4.0 0.0\r\ng gr"
},
{
"path": "src/test/resources/fourTrianglesPartiallyInMaterialGroups.obj",
"chars": 199,
"preview": "mtllib twoMaterialsA.mtl\r\nv 0.0 0.0 0.0\r\nv 4.0 0.0 0.0\r\nv 4.0 4.0 0.0\r\nv 0.0 4.0 0.0\r\nv 8.0 0.0 0.0\r\nv 8.0 4.0 0.0\r\nf 1 "
},
{
"path": "src/test/resources/mtlWithBrokenLines.mtl",
"chars": 167,
"preview": "# Some lines are broken with a backslash\r\nnewmtl material0 \r\nKa 1.0 \\\r\n 0.0 \\\r\n 0.0\r\nKd 1.0 1.0 0.0\r\nKs 1.0 1.0 1"
},
{
"path": "src/test/resources/mtlWithPbrProperties.mtl",
"chars": 252,
"preview": "# www.blender.org\n\nnewmtl Material.001\nKd 0.800000 0.304983 0.243147\nKs 0.500000 0.500000 0.500000\nKe 0.000000 0.000000 "
},
{
"path": "src/test/resources/mtlWithWhitespace.mtl",
"chars": 228,
"preview": "# Some lines have leading and trailing whitespace,\r\n# in form of space characters or tabs\r\n newmtl material0 \r\n "
},
{
"path": "src/test/resources/pbrMaterial.mtl",
"chars": 190,
"preview": "newmtl material1\nPr 0.12\nmap_Pr roughness.png\nPm 0.23\nmap_Pm metallic.png\nPs 0.34\nmap_Ps sheen.png\nPc 0.11\nPcr 0.222\nKe "
},
{
"path": "src/test/resources/square.obj",
"chars": 71,
"preview": "v 0.0 0.0 0.0\r\nv 4.0 0.0 0.0\r\nv 4.0 4.0 0.0\r\nv 0.0 4.0 0.0\r\nf 1 2 3 4\r\n"
},
{
"path": "src/test/resources/squareAndTriangle.obj",
"chars": 95,
"preview": "v 0.0 0.0 0.0\r\nv 4.0 0.0 0.0\r\nv 4.0 4.0 0.0\r\nv 0.0 4.0 0.0\r\nv 2.0 6.0 0.0\r\nf 1 2 3 4\r\nf 3 4 5\r\n"
},
{
"path": "src/test/resources/squareAndTriangleInTwoGroups.obj",
"chars": 117,
"preview": "v 0.0 0.0 0.0\r\nv 4.0 0.0 0.0\r\nv 4.0 4.0 0.0\r\nv 0.0 4.0 0.0\r\nv 2.0 6.0 0.0\r\ng group0 \r\nf 1 2 3 4\r\ng group1 \r\nf 3 4 5\r\n"
},
{
"path": "src/test/resources/squareAndTriangleWithRelativeIndices.obj",
"chars": 98,
"preview": "v 0.0 0.0 0.0\r\nv 4.0 0.0 0.0\r\nv 4.0 4.0 0.0\r\nv 0.0 4.0 0.0\r\nv 2.0 6.0 0.0\r\nf 1 -4 -3 4\r\nf 3 -2 5\r\n"
},
{
"path": "src/test/resources/squareTextured.obj",
"chars": 127,
"preview": "v 0.0 0.0 0.0\r\nv 4.0 0.0 0.0\r\nv 4.0 4.0 0.0\r\nv 0.0 4.0 0.0\r\nvt 0.0 0.0\r\nvt 1.0 0.0\r\nvt 1.0 1.0\r\nvt 0.0 1.0\r\nf 1/1 2/2 3/"
},
{
"path": "src/test/resources/twoMaterialsA.mtl",
"chars": 184,
"preview": "newmtl material0\r\nNs 500.0\r\nd 1.0\r\nKa 1.0 0.0 0.0\r\nKd 1.0 0.0 0.0\r\nKs 1.0 1.0 1.0\r\nnewmtl material1\r\nNs 0.0\r\nd 0.5\r\nKa 1"
},
{
"path": "src/test/resources/twoMaterialsB.mtl",
"chars": 128,
"preview": "newmtl material2\r\nKa 1 0 1 \r\nKd 1 0 1\r\nKs 1 1 1\r\nNs 200\r\n \r\nnewmtl material3\r\nKa 0 1 1\r\nKd 0 1 1\r\nKs 0 1 1\r\nNs 100\r\nd 0."
},
{
"path": "src/test/resources/twoTrianglesOneInDefaultGroup.obj",
"chars": 89,
"preview": "v 0.0 0.0 0.0\r\nv 4.0 0.0 0.0\r\nv 4.0 4.0 0.0\r\nv 0.0 4.0 0.0\r\nf 1 2 4\r\ng group0 \r\nf 2 3 4\r\n"
},
{
"path": "src/test/resources/twoTrianglesSharedInThreeGroups.obj",
"chars": 114,
"preview": "v 0.0 0.0 0.0\r\nv 4.0 0.0 0.0\r\nv 4.0 4.0 0.0\r\nv 0.0 4.0 0.0\r\ng group0 group1 \r\nf 1 2 4\r\ng group1 group2 \r\nf 2 3 4\r\n"
},
{
"path": "src/test/resources/twoTrianglesWithAmbiguousTexCoords.obj",
"chars": 104,
"preview": "v 0 0 0\r\nv 4 0 0\r\nv 4 4 0\r\nv 0 4 0\r\n\r\nvt 0 0\r\nvt 1 0\r\nvt 1 1\r\nvt 0 1\r\n\r\nf 1/1 2/2 4/4 \r\nf 2/1 3/3 4/4 \r\n"
}
]
About this extraction
This page contains the full source code of the javagl/Obj GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 63 files (313.0 KB), approximately 74.3k tokens, and a symbol index with 633 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.