View Javadoc

    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
    19  import java.io.Reader;
    20  import java.util.ArrayList;
    21  import java.util.Iterator;
    22  import java.util.List;
    23
    24  import org.apache.commons.geometry.euclidean.threed.Vector3D;
    25  import org.apache.commons.geometry.euclidean.threed.mesh.SimpleTriangleMesh;
    26  import org.apache.commons.geometry.euclidean.threed.mesh.TriangleMesh;
    27  import org.apache.commons.numbers.core.Precision;
    28
    29  /** Class for reading OBJ content as a {@link TriangleMesh triangle mesh}.
    30   */
    31  public class ObjTriangleMeshReader extends AbstractObjPolygonReader {
    32
    33      /** Object used to construct the mesh. */
    34      private final SimpleTriangleMesh.Builder meshBuilder;
    35
    36      /** List of normals discovered in the input. */
    37      private final List<Vector3D> normals = new ArrayList<>();
    38
    39      /** Construct a new instance that reads OBJ content from the given reader.
    40       * @param reader reader to read from
    41       * @param precision precision context used to compare floating point numbers
    42       */
    43      public ObjTriangleMeshReader(final Reader reader, final Precision.DoubleEquivalence precision) {
    44          super(reader);
    45
    46          this.meshBuilder = SimpleTriangleMesh.builder(precision);
    47      }
    48
    49      /** Return a {@link TriangleMesh triangle mesh} constructed from all of the OBJ content
    50       * from the underlying reader. Non-triangle faces are converted to triangles using a simple
    51       * triangle fan. All vertices present in the OBJ content are also present in the returned mesh,
    52       * regardless of whether or not they are used in a face.
    53       * @return triangle mesh containing all data from the OBJ content
    54       * @throws IllegalStateException if data format error occurs
    55       * @throws java.io.UncheckedIOException if an I/O error occurs
    56       */
    57      public TriangleMesh readTriangleMesh() {
    58          PolygonObjParser.Face face;
    59          Vector3D definedNormal;
    60          Iterator<PolygonObjParser.VertexAttributes> attrs;
    61          while ((face = readFace()) != null) {
    62              // get the face attributes in the proper counter-clockwise orientation
    63              definedNormal = face.getDefinedCompositeNormal(normals::get);
    64              attrs = face.getVertexAttributesCounterClockwise(definedNormal, meshBuilder::getVertex).iterator();
    65
    66              // add the face vertices using a triangle fan
    67              final int p0 = attrs.next().getVertexIndex();
    68              int p1 = attrs.next().getVertexIndex();
    69              int p2;
    70
    71              while (attrs.hasNext()) {
    72                  p2 = attrs.next().getVertexIndex();
    73
    74                  meshBuilder.addFace(p0, p1, p2);
    75
    76                  p1 = p2;
    77              }
    78          }
    79
    80          return meshBuilder.build();
    81      }
    82
    83      /** {@inheritDoc} */
    84      @Override
    85      protected void handleVertex(final Vector3D vertex) {
    86          meshBuilder.addVertex(vertex);
    87      }
    88
    89      /** {@inheritDoc} */
    90      @Override
    91      protected void handleNormal(final Vector3D normal) {
    92          normals.add(normal);
    93      }
    94  }