ObjTriangleMeshReader.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.geometry.io.euclidean.threed.obj;

  18. import java.io.Reader;
  19. import java.util.ArrayList;
  20. import java.util.Iterator;
  21. import java.util.List;

  22. import org.apache.commons.geometry.euclidean.threed.Vector3D;
  23. import org.apache.commons.geometry.euclidean.threed.mesh.SimpleTriangleMesh;
  24. import org.apache.commons.geometry.euclidean.threed.mesh.TriangleMesh;
  25. import org.apache.commons.numbers.core.Precision;

  26. /** Class for reading OBJ content as a {@link TriangleMesh triangle mesh}.
  27.  */
  28. public class ObjTriangleMeshReader extends AbstractObjPolygonReader {

  29.     /** Object used to construct the mesh. */
  30.     private final SimpleTriangleMesh.Builder meshBuilder;

  31.     /** List of normals discovered in the input. */
  32.     private final List<Vector3D> normals = new ArrayList<>();

  33.     /** Construct a new instance that reads OBJ content from the given reader.
  34.      * @param reader reader to read from
  35.      * @param precision precision context used to compare floating point numbers
  36.      */
  37.     public ObjTriangleMeshReader(final Reader reader, final Precision.DoubleEquivalence precision) {
  38.         super(reader);

  39.         this.meshBuilder = SimpleTriangleMesh.builder(precision);
  40.     }

  41.     /** Return a {@link TriangleMesh triangle mesh} constructed from all of the OBJ content
  42.      * from the underlying reader. Non-triangle faces are converted to triangles using a simple
  43.      * triangle fan. All vertices present in the OBJ content are also present in the returned mesh,
  44.      * regardless of whether or not they are used in a face.
  45.      * @return triangle mesh containing all data from the OBJ content
  46.      * @throws IllegalStateException if data format error occurs
  47.      * @throws java.io.UncheckedIOException if an I/O error occurs
  48.      */
  49.     public TriangleMesh readTriangleMesh() {
  50.         PolygonObjParser.Face face;
  51.         Vector3D definedNormal;
  52.         Iterator<PolygonObjParser.VertexAttributes> attrs;
  53.         while ((face = readFace()) != null) {
  54.             // get the face attributes in the proper counter-clockwise orientation
  55.             definedNormal = face.getDefinedCompositeNormal(normals::get);
  56.             attrs = face.getVertexAttributesCounterClockwise(definedNormal, meshBuilder::getVertex).iterator();

  57.             // add the face vertices using a triangle fan
  58.             final int p0 = attrs.next().getVertexIndex();
  59.             int p1 = attrs.next().getVertexIndex();
  60.             int p2;

  61.             while (attrs.hasNext()) {
  62.                 p2 = attrs.next().getVertexIndex();

  63.                 meshBuilder.addFace(p0, p1, p2);

  64.                 p1 = p2;
  65.             }
  66.         }

  67.         return meshBuilder.build();
  68.     }

  69.     /** {@inheritDoc} */
  70.     @Override
  71.     protected void handleVertex(final Vector3D vertex) {
  72.         meshBuilder.addVertex(vertex);
  73.     }

  74.     /** {@inheritDoc} */
  75.     @Override
  76.     protected void handleNormal(final Vector3D normal) {
  77.         normals.add(normal);
  78.     }
  79. }