From 89da0239f39f855e5afcc52402d3fe20df918786 Mon Sep 17 00:00:00 2001 From: Simon Leistikow Date: Fri, 15 Sep 2017 12:45:56 +0200 Subject: [PATCH] Fix #5 --- .../de/trac/spherical/rendering/Sphere.java | 92 ++++++++----------- 1 file changed, 36 insertions(+), 56 deletions(-) diff --git a/app/src/main/java/de/trac/spherical/rendering/Sphere.java b/app/src/main/java/de/trac/spherical/rendering/Sphere.java index 2d0f70a..df6b477 100644 --- a/app/src/main/java/de/trac/spherical/rendering/Sphere.java +++ b/app/src/main/java/de/trac/spherical/rendering/Sphere.java @@ -18,13 +18,15 @@ public class Sphere { public Sphere(float radius, int polyCountX, int polyCountY) { + final int polyCountXPitch = polyCountX + 1; + // Setup vertex buffer. - ByteBuffer buffer = ByteBuffer.allocateDirect((polyCountX*polyCountY+2)*2*3*4); + ByteBuffer buffer = ByteBuffer.allocateDirect((polyCountXPitch*polyCountY+2)*3*4); buffer.order(ByteOrder.nativeOrder()); vertexBuffer = buffer.asFloatBuffer(); // Setup texture coordinate buffer. - buffer = ByteBuffer.allocateDirect((polyCountX*polyCountY+2)*2*2*4); + buffer = ByteBuffer.allocateDirect((polyCountXPitch*polyCountY+2)*2*4); buffer.order(ByteOrder.nativeOrder()); textureCoordinatesBuffer = buffer.asFloatBuffer(); @@ -32,25 +34,19 @@ public class Sphere { buffer = ByteBuffer.allocateDirect(polyCountX*polyCountY*6*2); buffer.order(ByteOrder.nativeOrder()); indexBuffer = buffer.asShortBuffer(); - - int polyCountXPitch = polyCountX+1; // get to same vertex on next level - - int level = 0; - for (int p1 = 0; p1 < polyCountY-1; p1++) { - //main quads, top to bottom - for (int p2 = 0; p2 < polyCountX - 1; p2++) - { + for (int p1 = 0, level = 0; p1 < polyCountY-1; p1++) { + for (int p2 = 0; p2 < polyCountX-1; p2++) { final int curr = level + p2; indexBuffer.put((short)(curr + polyCountXPitch)); indexBuffer.put((short)(curr)); indexBuffer.put((short)(curr + 1)); + indexBuffer.put((short)(curr + polyCountXPitch)); - indexBuffer.put((short)(curr+1)); + indexBuffer.put((short)(curr + 1)); indexBuffer.put((short)(curr + 1 + polyCountXPitch)); } - // the connectors from front to end indexBuffer.put((short)(level + polyCountX - 1 + polyCountXPitch)); indexBuffer.put((short)(level + polyCountX - 1)); indexBuffer.put((short)(level + polyCountX)); @@ -65,28 +61,20 @@ public class Sphere { final int polyCountSq1 = polyCountSq + 1; // bottom point final int polyCountSqM1 = (polyCountY - 1) * polyCountXPitch; // last row's first vertex - for (int p2 = 0; p2 < polyCountX - 1; p2++) { - // create triangles which are at the top of the sphere - + for (int p2 = 0; p2 < polyCountX-1; p2++) { indexBuffer.put((short)(polyCountSq)); indexBuffer.put((short)(p2 + 1)); indexBuffer.put((short)(p2)); - // create triangles which are at the bottom of the sphere - indexBuffer.put((short)(polyCountSqM1 + p2)); indexBuffer.put((short)(polyCountSqM1 + p2 + 1)); indexBuffer.put((short)(polyCountSq1)); } - // create final triangle which is at the top of the sphere - indexBuffer.put((short)(polyCountSq)); indexBuffer.put((short)(polyCountX)); indexBuffer.put((short)(polyCountX-1)); - // create final triangle which is at the bottom of the sphere - indexBuffer.put((short)(polyCountSqM1 + polyCountX - 1)); indexBuffer.put((short)(polyCountSqM1)); indexBuffer.put((short)(polyCountSq1)); @@ -94,55 +82,47 @@ public class Sphere { // calculate the angle which separates all points in a circle final double AngleX = 2.0 * Math.PI / polyCountX; final double AngleY = Math.PI / polyCountY; + final double InvPI = 1.0 / Math.PI; - int i=0; - double axz; - - // we don't start at 0. double ay = 0;//AngleY / 2; for (int y = 0; y < polyCountY; y++) { - ay += AngleY; - final double sinay = Math.sin(ay); - axz = 0; - // calculate the necessary vertices without the doubled one - for (int xz = 0; xz < polyCountX; xz++) - { - float rx = (float) (radius * Math.cos(axz) * sinay); - float ry = (float) (radius * Math.cos(ay)); - float rz = (float) (radius * Math.sin(axz) * sinay); + ay += AngleY; + double axz = 0; + final double sinay = Math.sin(ay); + final float tv = (float) (ay*InvPI); + + for (int xz = 0; xz < polyCountX; xz++) { + + double nx = Math.cos(axz) * sinay; + double ny = Math.cos(ay); + double nz = Math.sin(axz) * sinay; // calculate texture coordinates via sphere mapping // tu is the same on each level, so only calculate once float tu = 0.5f; - if (y==0) - { - if (ry != -1.0f && ry != 1.0f) { - float len = (float) Math.sqrt(rx*rx + ry*ry + rz*rz); - tu = (float) (Math.acos(Math.max(Math.min(rx / len / sinay, 1.0), -1.0)) * 0.5 / Math.PI); - } - if (rz < 0.0f) - tu=1-tu; - } - else - tu = textureCoordinatesBuffer.get((i-polyCountXPitch)*2); + if (y == 0) { + if (ny != -1.0 && ny != 1.0) + tu = (float) (Math.acos(Math.max(Math.min(nx / sinay, 1.0), -1.0)) * 0.5 * InvPI); + if (nz < 0.0) + tu = 1.0f - tu; + } else + tu = textureCoordinatesBuffer.get(xz*2); - vertexBuffer.put(rx); - vertexBuffer.put(ry); - vertexBuffer.put(rz); + vertexBuffer.put((float) (radius * nx)); + vertexBuffer.put((float) (radius * ny)); + vertexBuffer.put((float) (radius * nz)); textureCoordinatesBuffer.put(tu); - textureCoordinatesBuffer.put((float)(ay/Math.PI)); + textureCoordinatesBuffer.put(tv); - i++; axz += AngleX; } - // This is the doubled vertex on the initial position - vertexBuffer.put(vertexBuffer.get((i-polyCountX)*3 + 0)); - vertexBuffer.put(vertexBuffer.get((i-polyCountX)*3 + 1)); - vertexBuffer.put(vertexBuffer.get((i-polyCountX)*3 + 2)); + + vertexBuffer.put(vertexBuffer.get((y*polyCountXPitch)*3 + 0)); + vertexBuffer.put(vertexBuffer.get((y*polyCountXPitch)*3 + 1)); + vertexBuffer.put(vertexBuffer.get((y*polyCountXPitch)*3 + 2)); textureCoordinatesBuffer.put(1.0f); - textureCoordinatesBuffer.put(0.0f); - i++; + textureCoordinatesBuffer.put(tv); } // Add the vertex at the top of the sphere.