/* * Copyright (C) 2007 The Android Open Source Project * * 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. */ package jo.util.jgl.obj.tri; import java.nio.FloatBuffer; import java.nio.ShortBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import jo.util.jgl.JGLUtils; import jo.vecmath.Color3f; import jo.vecmath.Point3f; import jo.vecmath.logic.Matrix4fLogic; import jo.vecmath.logic.Point3fLogic; /** * A vertex shaded cube. */ public class JGLObjSphere extends JGLObj { private static Map<Integer, FloatBuffer> mVertexBuffers; private static Map<Integer, FloatBuffer> mNormalBuffers; private static Map<Integer, ShortBuffer> mIndexBuffers; private static Map<Integer, Point3f> mHBounds; private static Map<Integer, Point3f> mLBounds; static { mVertexBuffers = new HashMap<>(); mNormalBuffers = new HashMap<>(); mIndexBuffers = new HashMap<>(); mHBounds = new HashMap<>(); mLBounds = new HashMap<>(); } private static float c = 1 / (float) Math.sqrt(5); private static float s = 2 / (float) Math.sqrt(5); private static float c1 = (float) Math.cos(2 * (float) Math.PI / 5); private static float s1 = (float) Math.sin(2 * (float) Math.PI / 5); private static float c2 = (float) Math.cos((float) Math.PI / 5); private static float s2 = (float) Math.sin((float) Math.PI / 5); private static final float[] vertices = { 0, 0, 1, // upper ring s, 0, c, s * c1, s * s1, c, -s * c2, s * s2, c, -s * c2, -s * s2, c, s * c1, -s * s1, c, // lower ring s * c2, s * s2, -c, -s * c1, s * s1, -c, -s, 0, -c, -s * c1, -s * s1, -c, s * c2, -s * s2, -c, 0, 0, -1,}; private static final short[] indices = { // top 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 1, // top middle 2, 1, 6, 3, 2, 7, 4, 3, 8, 5, 4, 9, 1, 5, 10, // bottom middle 6, 7, 2, 7, 8, 3, 8, 9, 4, 9, 10, 5, 10, 6, 1, // bottom 7, 6, 11, 8, 7, 11, 9, 8, 11, 10, 9, 11, 6, 10, 11,}; protected int mVertexCount = 0; protected int mFaceCount = 0; public JGLObjSphere(int depth, Color3f baseColor, Color3f deltaColor) { int numColors; if (depth == 0) { numColors = 12; } else if (depth == 1) { numColors = 42; } else if (depth == 2) { numColors = 162; } else { numColors = 642; } List<Color3f> colorArray = JGLUtils.rndColors(numColors, baseColor, deltaColor); init(depth, colorArray); } public JGLObjSphere(Point3f size, Point3f center) { this(2, new Color3f(.5f, .5f, .5f), new Color3f(.25f, .25f, .25f)); Matrix4fLogic.translate(getTransform(), center); Matrix4fLogic.scale(getTransform(), size); } public JGLObjSphere(int depth, List<Color3f> colors) { init(depth, colors); } @Override public void recycle() { if (mVertexBuffers != null) { mVertexBuffer = null; // these are cached, don't recycle } if (mIndexBuffers != null) { mIndexShortBuffer = null; } if (mNormalBuffers != null) { mNormalBuffer = null; } super.recycle(); } private void init(int depth, List<Color3f> colors) { List<Float> vertex = new ArrayList<>(); List<Short> index = new ArrayList<>(); List<Float> normal = new ArrayList<>(); List<Color3f> color = new ArrayList<>(); // initialize with zero-order for (float f : vertices) { vertex.add(f); normal.add(f); } mVertexCount = vertex.size() / 3; for (short i : indices) { index.add(i); } mFaceCount = index.size() / 3; for (Color3f c : colors) { color.add(c); } Map<String, Short> alreadySubdivided = new HashMap<>(); // subdivide while (depth-- > 0) { //System.out.println("Subdivision pass"); List<Short> oldIndex = index; index = new ArrayList<Short>(); for (int face = 0; face < oldIndex.size(); face += 3) { // get primary corners short i1 = oldIndex.get(face + 0); short i2 = oldIndex.get(face + 1); short i3 = oldIndex.get(face + 2); //System.out.println("subdividing "+i1+","+i2+","+i3); // create inbetweens Short i12 = calcInbetween(i1, i2, alreadySubdivided, vertex, normal, color); Short i23 = calcInbetween(i2, i3, alreadySubdivided, vertex, normal, color); Short i31 = calcInbetween(i3, i1, alreadySubdivided, vertex, normal, color); index.add(i1); index.add(i12); index.add(i31); index.add(i12); index.add(i2); index.add(i23); index.add(i31); index.add(i23); index.add(i3); index.add(i23); index.add(i31); index.add(i12); } } mVertexCount = vertex.size() / 3; mFaceCount = index.size() / 3; if ((mVertexBuffers != null) && mVertexBuffers.containsKey(depth)) { setVertexBuffer(mVertexBuffers.get(depth)); setHighBounds(mHBounds.get(depth)); setLowBounds(mLBounds.get(depth)); } else { setVertices(vertex); if (mVertexBuffers != null) { mVertexBuffers.put(depth, getVertexBuffer()); mHBounds.put(depth, getHighBounds()); mLBounds.put(depth, getLowBounds()); } } if ((mNormalBuffers != null) && mNormalBuffers.containsKey(depth)) { setNormalBuffer(mNormalBuffers.get(depth)); } else { setNormals(normal); if (mNormalBuffers != null) { mNormalBuffers.put(depth, getNormalBuffer()); } } if ((mIndexBuffers != null) && mIndexBuffers.containsKey(depth)) { setIndexShortBuffer(mIndexBuffers.get(depth)); } else { setIndices(index); if (mIndexBuffers != null) { mIndexBuffers.put(depth, getIndexShortBuffer()); } } setColors(color); } private Short calcInbetween(short i1, short i2, Map<String, Short> alreadySubdivided, List<Float> vertex, List<Float> normal, List<Color3f> color) { Point3f v1 = new Point3f(vertex.get(i1 * 3 + 0), vertex.get(i1 * 3 + 1), vertex.get(i1 * 3 + 2)); Point3f v2 = new Point3f(vertex.get(i2 * 3 + 0), vertex.get(i2 * 3 + 1), vertex.get(i2 * 3 + 2)); String k; if (i1 < i2) { k = i1 + "." + i2; } else { k = i2 + "." + i1; } Short i12 = alreadySubdivided.get(k); if (i12 == null) { i12 = (short) (vertex.size() / 3); alreadySubdivided.put(k, i12); //System.out.println("creating "+k); Point3f v12 = new Point3f(v1); v12.add(v2); v12.scale(.5f); Point3fLogic.normalize(v12); vertex.add((float) v12.getX()); vertex.add((float) v12.getY()); vertex.add((float) v12.getZ()); normal.add((float) v12.getX()); normal.add((float) v12.getY()); normal.add((float) v12.getZ()); Color3f c_1 = color.get(i1); Color3f c_2 = color.get(i2); Color3f c12 = new Color3f(c_1); c12.add(c_2); c12.scale(.5f); color.add(c12); } //else // System.out.println("reusing "+k); return i12; } }