Android Open Source - ObjViewer_Android Geom Builder






From Project

Back to project page ObjViewer_Android.

License

The source code is released under:

Apache License

If you think the Android project ObjViewer_Android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package nz.gen.geek_central.GLUseful;
/*//from  w ww .  j  av a  2 s.c  o m
    Easy construction and application of buffers needed for
    OpenGL-ES drawing.

    Copyright 2011, 2013 by Lawrence D'Oliveiro <ldo@geek-central.gen.nz>.

    Licensed under the Apache License, Version 2.0 (the "License"); you may not
    use this file except in compliance with the License. You may obtain a copy of
    the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    License for the specific language governing permissions and limitations under
    the License.
*/

import java.util.ArrayList;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.nio.ByteOrder;
import static nz.gen.geek_central.GLUseful.GLUseful.gl;

public class GeomBuilder
  /*
    Helper class for easier construction of geometrical
    objects. Instantiate this and tell it whether each vertex will
    also have a normal vector, a texture-coordinate vector or a
    colour. Then call Add to add vertex definitions (using class Vec3f
    to define points, and GeomBuilder.Color to define colours), and
    use the returned vertex indices to construct faces with AddTri and
    AddQuad. Finally, call MakeObj to obtain a GeomBuilder.Obj that
    has a Draw method that will render the resulting geometry into a
    specified GL context.
  */
  {

    public static class Color
      /* RGB colours with transparency */
      {
        public final float r, g, b, a;

        public Color
          (
            float r,
            float g,
            float b,
            float a
          )
          {
            this.r = r;
            this.b = b;
            this.g = g;
            this.a = a;
          } /*Color*/

      } /*Color*/

    private final boolean AutoNormals;
    private final ArrayList<Vec3f> TempPoints, TempPointTexCoords;
    private final ArrayList<Color> TempPointColors;
    private final ArrayList<Vec3f> Points, PointNormals, PointTexCoords;
    private final ArrayList<Color> PointColors;
    private final ArrayList<Integer> Faces;
    private Vec3f BoundMin, BoundMax;

    public GeomBuilder
      (
        boolean GotNormals, /* vertices will have normals specified, otherwise they will be automatically generated for flat shading */
        boolean GotTexCoords, /* vertices will have texture coordinates specified */
        boolean GotColors /* vertices will have colours specified */
      )
      {
        AutoNormals = !GotNormals;
        TempPoints = AutoNormals ? new ArrayList<Vec3f>() : null;
        Points = new ArrayList<Vec3f>();
        PointNormals = GotNormals || AutoNormals ? new ArrayList<Vec3f>() :  null;
        TempPointTexCoords = AutoNormals && GotTexCoords ? new ArrayList<Vec3f>() : null;
        PointTexCoords = GotTexCoords ? new ArrayList<Vec3f>() : null;
        TempPointColors = AutoNormals && GotColors ? new ArrayList<Color>() : null;
        PointColors = GotColors ? new ArrayList<Color>() : null;
        Faces = new ArrayList<Integer>();
        BoundMin = null;
        BoundMax = null;
      } /*GeomBuilder*/

    private int Add
      (
        Vec3f Vertex,
      /* following args are either mandatory or must be null, depending
        on respective flags passed to constructor */
        Vec3f Normal,
        Vec3f TexCoord,
        Color VertexColor,
        boolean AutoNormals
      )
      /* adds a new vertex, and returns its index for use in constructing faces. */
      {
        if
          (
                AutoNormals != (Normal == null)
            ||
                (PointColors == null) != (VertexColor == null)
            ||
                (PointTexCoords == null) != (TexCoord == null)
          )
          {
            throw new RuntimeException("missing or redundant args specified");
          } /*if*/
        final int Result = AutoNormals ? TempPoints.size() : Points.size();
        (AutoNormals ? TempPoints : Points).add(Vertex);
        if (!AutoNormals)
          {
            PointNormals.add(Normal);
          } /*if*/
        if (PointTexCoords != null)
          {
            (AutoNormals ? TempPointTexCoords : PointTexCoords).add(TexCoord);
          } /*if*/
        if (PointColors != null)
          {
            (AutoNormals ? TempPointColors : PointColors).add(VertexColor);
          } /*if*/
        if (AutoNormals == this.AutoNormals)
          {
            if (BoundMin != null)
              {
                BoundMin =
                    new Vec3f
                      (
                        Math.min(BoundMin.x, Vertex.x),
                        Math.min(BoundMin.y, Vertex.y),
                        Math.min(BoundMin.z, Vertex.z)
                      );
              }
            else
              {
                BoundMin = Vertex;
              } /*if*/
            if (BoundMax != null)
              {
                BoundMax =
                    new Vec3f
                      (
                        Math.max(BoundMax.x, Vertex.x),
                        Math.max(BoundMax.y, Vertex.y),
                        Math.max(BoundMax.z, Vertex.z)
                      );
              }
            else
              {
                BoundMax = Vertex;
              } /*if*/
          } /*if*/
        return
            Result;
      } /*Add*/

    public int Add
      (
        Vec3f Vertex,
      /* following args are either mandatory or must be null, depending
        on respective flags passed to constructor */
        Vec3f Normal,
        Vec3f TexCoord,
        Color VertexColor
      )
      /* adds a new vertex, and returns its index for use in constructing faces. */
      {
        return
            Add
              (
                /*Vertex =*/ Vertex,
                /*Normal =*/ Normal,
                /*TexCoord =*/ TexCoord,
                /*VertexColor =*/ VertexColor,
                /*AutoNormals =*/ AutoNormals
              );
      } /*Add*/

    private int AddActual
      (
        int VertIndex,
        Vec3f Normal
      )
      {
        if (!AutoNormals)
          {
            throw new RuntimeException("GeomBuilder.AddActual shouldnt be called if not AutoNormals");
          } /*if*/
        return
            Add
              (
                /*Vertex =*/ TempPoints.get(VertIndex),
                /*Normal =*/ Normal,
                /*TexCoord =*/ TempPointTexCoords != null ? TempPointTexCoords.get(VertIndex) : null,
                /*VertexColor =*/ TempPointColors != null ? TempPointColors.get(VertIndex) : null,
                /*AutoNormals =*/ false
              );
      } /*AddActual*/

    private void GenAutoNormal
      (
        int[] Vertices
          /* assume length at least 3 and coplanar if > 3, replaced with final generated vertices */
      )
      {
        if (!AutoNormals)
          {
            throw new RuntimeException("GeomBuilder.GenAutoNormal shouldnt be called if not AutoNormals");
          } /*if*/
        final Vec3f
            V1 = TempPoints.get(Vertices[0]),
            V2 = TempPoints.get(Vertices[1]),
            V3 = TempPoints.get(Vertices[2]);
        final Vec3f FaceNormal = (V2.sub(V1)).cross(V3.sub(V2)).unit();
        final int[] NewVertices = new int[Vertices.length];
        for (int i = 0; i < Vertices.length; ++i)
          {
            NewVertices[i] = AddActual(Vertices[i], FaceNormal);
          } /*for*/
        System.arraycopy(NewVertices, 0, Vertices, 0, Vertices.length);
      } /*GenAutoNormal*/

    private void AddTri
      (
        int V1,
        int V2,
        int V3,
        boolean AutoNormals
      )
      /* defines a triangular face. Args are indices as previously returned from calls to Add. */
      {
        if (AutoNormals)
          {
            final int[] Vertices = new int[] {V1, V2, V3};
            GenAutoNormal(Vertices);
            V1 = Vertices[0];
            V2 = Vertices[1];
            V3 = Vertices[2];
          } /*if*/
        Faces.add(V1);
        Faces.add(V2);
        Faces.add(V3);
      } /*AddTri*/

    public void AddTri
      (
        int V1,
        int V2,
        int V3
      )
      /* defines a triangular face. Args are indices as previously returned from calls to Add. */
      {
        AddTri(V1, V2, V3, AutoNormals);
      } /*AddTri*/

    public void AddQuad
      (
        int V1,
        int V2,
        int V3,
        int V4
      )
      /* Defines a quadrilateral face. Args are indices as previously returned from calls to Add. */
      {
        if (AutoNormals)
          {
            final int[] Vertices = new int[] {V1, V2, V3, V4};
            GenAutoNormal(Vertices);
            V1 = Vertices[0];
            V2 = Vertices[1];
            V3 = Vertices[2];
            V4 = Vertices[3];
          } /*if*/
        AddTri(V1, V2, V3, false);
        AddTri(V4, V1, V3, false);
      } /*AddQuad*/

    public void AddPoly
      (
        int[] V
      )
      /* Defines a polygonal face. Array elements are indices as previously
        returned from calls to Add. */
      {
        if (AutoNormals)
          {
            final int[] V2 = new int[V.length];
            System.arraycopy(V, 0, V2, 0, V.length);
            GenAutoNormal(V2);
            V = V2;
          } /*if*/
        for (int i = 1; i < V.length - 1; ++i)
          {
            AddTri(V[0], V[i], V[i + 1], false);
          } /*for*/
      } /*AddPoly*/

    public static class Obj
      /* representation of complete object geometry. */
      {
        private final IntBuffer VertexBuffer;
        private final IntBuffer NormalBuffer;
        private final IntBuffer TexCoordBuffer;
        private final IntBuffer ColorBuffer;
        private final ShortBuffer IndexBuffer;
        private final int NrIndexes;
        public final Vec3f BoundMin, BoundMax;

        private Obj
          (
            IntBuffer VertexBuffer,
            IntBuffer NormalBuffer, /* optional */
            IntBuffer TexCoordBuffer, /* optional */
            IntBuffer ColorBuffer, /* optional */
            ShortBuffer IndexBuffer,
            int NrIndexes,
            Vec3f BoundMin,
            Vec3f BoundMax
          )
          {
            this.VertexBuffer = VertexBuffer;
            this.NormalBuffer = NormalBuffer;
            this.TexCoordBuffer = TexCoordBuffer;
            this.ColorBuffer = ColorBuffer;
            this.IndexBuffer = IndexBuffer;
            this.NrIndexes = NrIndexes;
            this.BoundMin = BoundMin;
            this.BoundMax = BoundMax;
          } /*Obj*/

        public void Draw()
          /* actually renders the geometry into the specified GL context. */
          {
            gl.glEnableClientState(gl.GL_VERTEX_ARRAY);
            gl.glVertexPointer(3, gl.GL_FIXED, 0, VertexBuffer);
            if (NormalBuffer != null)
              {
                gl.glEnableClientState(gl.GL_NORMAL_ARRAY);
                gl.glNormalPointer(gl.GL_FIXED, 0, NormalBuffer);
              } /*if*/
            if (TexCoordBuffer != null)
              {
                gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY);
                gl.glTexCoordPointer(3, gl.GL_FIXED, 0, TexCoordBuffer);
              } /*if*/
            if (ColorBuffer != null)
              {
                gl.glEnableClientState(gl.GL_COLOR_ARRAY);
                gl.glColorPointer(4, gl.GL_FIXED, 0, ColorBuffer);
              } /*if*/
            gl.glDrawElements(gl.GL_TRIANGLES, NrIndexes, gl.GL_UNSIGNED_SHORT, IndexBuffer);
            gl.glDisableClientState(gl.GL_VERTEX_ARRAY);
            gl.glDisableClientState(gl.GL_NORMAL_ARRAY);
            gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY);
            gl.glDisableClientState(gl.GL_COLOR_ARRAY);
          } /*Draw*/

      } /*Obj*/;

    public Obj MakeObj()
      /* constructs and returns the final geometry ready for rendering. */
      {
        if (Points.size() == 0)
          {
            throw new RuntimeException("GeomBuilder: empty object");
          } /*if*/
        final int Fixed1 = 0x10000;
        final int[] Vertices = new int[Points.size() * 3];
        final int[] Normals = PointNormals != null ? new int[Points.size() * 3] : null;
        final int[] TexCoords = PointTexCoords != null ? new int[Points.size() * 3] : null;
        final int[] Colors = PointColors != null ? new int[Points.size() * 4] : null;
        int jv = 0, jn = 0, jt = 0, jc = 0;
        for (int i = 0; i < Points.size(); ++i)
          {
            final Vec3f Point = Points.get(i);
            Vertices[jv++] = (int)(Point.x * Fixed1);
            Vertices[jv++] = (int)(Point.y * Fixed1);
            Vertices[jv++] = (int)(Point.z * Fixed1);
            if (PointNormals != null)
              {
                final Vec3f PointNormal = PointNormals.get(i);
                Normals[jn++] = (int)(PointNormal.x * Fixed1);
                Normals[jn++] = (int)(PointNormal.y * Fixed1);
                Normals[jn++] = (int)(PointNormal.z * Fixed1);
              } /*if*/
            if (PointTexCoords != null)
              {
                final Vec3f Coord = PointTexCoords.get(i);
                TexCoords[jt++] = (int)(Coord.x * Fixed1);
                TexCoords[jt++] = (int)(Coord.y * Fixed1);
                TexCoords[jt++] = (int)(Coord.z * Fixed1);
              } /*if*/
            if (PointColors != null)
              {
                final Color ThisColor = PointColors.get(i);
                Colors[jc++] = (int)(ThisColor.r * Fixed1);
                Colors[jc++] = (int)(ThisColor.g * Fixed1);
                Colors[jc++] = (int)(ThisColor.b * Fixed1);
                Colors[jc++] = (int)(ThisColor.a * Fixed1);
              } /*if*/
          } /*for*/
        final short[] Indices = new short[Faces.size()];
        final int NrIndexes = Indices.length;
        for (int i = 0; i < NrIndexes; ++i)
          {
            Indices[i] = (short)(int)Faces.get(i);
          } /*for*/
      /* Need to use allocateDirect to allocate buffers so garbage
        collector won't move them. Also make sure byte order is
        always native. But direct-allocation and order-setting methods
        are only available for ByteBuffer. Which is why buffers
        are allocated as ByteBuffers and then converted to more
        appropriate types. */
        final IntBuffer VertexBuffer;
        final IntBuffer NormalBuffer;
        final IntBuffer TexCoordBuffer;
        final IntBuffer ColorBuffer;
        final ShortBuffer IndexBuffer;
        VertexBuffer =
            ByteBuffer.allocateDirect(Vertices.length * 4)
            .order(ByteOrder.nativeOrder())
            .asIntBuffer()
            .put(Vertices);
        VertexBuffer.position(0);
        if (PointNormals != null)
          {
            NormalBuffer =
                ByteBuffer.allocateDirect(Normals.length * 4)
                .order(ByteOrder.nativeOrder())
                .asIntBuffer()
                .put(Normals);
            NormalBuffer.position(0);
          }
        else
          {
            NormalBuffer = null;
          } /*if*/
        if (PointTexCoords != null)
          {
            TexCoordBuffer =
                ByteBuffer.allocateDirect(TexCoords.length * 4)
                .order(ByteOrder.nativeOrder())
                .asIntBuffer()
                .put(TexCoords);
            TexCoordBuffer.position(0);
          }
        else
          {
            TexCoordBuffer = null;
          } /*if*/
        if (PointColors != null)
          {
            ColorBuffer =
                ByteBuffer.allocateDirect(Colors.length * 4)
                .order(ByteOrder.nativeOrder())
                .asIntBuffer()
                .put(Colors);
            ColorBuffer.position(0);
          }
        else
          {
            ColorBuffer = null;
          } /*if*/
        IndexBuffer =
            ByteBuffer.allocateDirect(Indices.length * 2)
            .order(ByteOrder.nativeOrder())
            .asShortBuffer()
            .put(Indices);
        IndexBuffer.position(0);
        return
            new Obj
              (
                VertexBuffer,
                NormalBuffer,
                TexCoordBuffer,
                ColorBuffer,
                IndexBuffer,
                NrIndexes,
                BoundMin,
                BoundMax
              );
      } /*MakeObj*/

  } /*GeomBuilder*/;




Java Source Code List

nz.gen.geek_central.GLUseful.GLUseful.java
nz.gen.geek_central.GLUseful.GeomBuilder.java
nz.gen.geek_central.GLUseful.ObjReader.java
nz.gen.geek_central.GLUseful.Rotation.java
nz.gen.geek_central.GLUseful.Vec3f.java
nz.gen.geek_central.ObjViewer.Main.java
nz.gen.geek_central.ObjViewer.ObjectView.java
nz.gen.geek_central.ObjViewer.Picker.java
nz.gen.geek_central.ObjViewer.PolyAccelerationDecelerationInterpolator.java
nz.gen.geek_central.android.useful.BundledSavedState.java
nz.gen.geek_central.android.useful.Useful.java