package com.bitwaffle.spaceguts.graphics.shapes;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import javax.vecmath.Point2f;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
public class VBOQuadric{
private int vaoHandle, numIndices;
public VBOQuadric(float radius, int slices, int stacks){
ArrayList<javax.vecmath.Vector3f> vertices = new ArrayList<javax.vecmath.Vector3f>();
ArrayList<javax.vecmath.Vector3f> normals = new ArrayList<javax.vecmath.Vector3f>();
ArrayList<Point2f> texCoords = new ArrayList<Point2f>();
float rho, theta;
float drho = (float)(Math.PI / (double)stacks);
float dtheta = (float)(2.0 * Math.PI / (double)slices);
float s;
float ds = 1.0f / (float)slices;
float dt = 1.0f / (float)stacks;
float t = 1.0f;
for(int i = 0; i < stacks; i++){
rho = i * drho;
s = 0.0f;
for(int j = 0; j <= slices; j++){
theta = (j == slices) ? 0.0f : j * dtheta;
float x = (float)(-Math.sin((double)theta) * Math.sin((double)rho));
float y = (float)(Math.cos((double)theta) * Math.sin((double)rho));
float z = (float)(Math.cos((double)rho));
normals.add(new javax.vecmath.Vector3f(x, y, z));
texCoords.add(new Point2f(s, t));
vertices.add(new javax.vecmath.Vector3f(x * radius, y * radius, z * radius));
x = (float)(-Math.sin(theta) * Math.sin(rho + drho));
y = (float)(Math.cos(theta) * Math.sin(rho + drho));
z = (float)(Math.cos(rho + drho));
normals.add(new javax.vecmath.Vector3f(x, y, z));
texCoords.add(new Point2f(s, t - dt));
vertices.add(new javax.vecmath.Vector3f(x * radius, y * radius, z * radius));
s += ds;
}
t -= dt;
}
numIndices = vertices.size();
FloatBuffer vertBuffer = BufferUtils.createFloatBuffer(vertices.size() * 3);
FloatBuffer normBuffer = BufferUtils.createFloatBuffer(normals.size() * 3);
FloatBuffer texBuffer = BufferUtils.createFloatBuffer(texCoords.size() * 2);
for(int i = 0; i < vertices.size(); i ++){
javax.vecmath.Vector3f vert0 = vertices.get(i);
javax.vecmath.Vector3f norm0 = normals.get(i);
Point2f texCoord0 = texCoords.get(i);
vertBuffer.put(vert0.x);
vertBuffer.put(vert0.y);
vertBuffer.put(vert0.z);
normBuffer.put(norm0.x);
normBuffer.put(norm0.y);
normBuffer.put(norm0.z);
texBuffer.put(texCoord0.x);
texBuffer.put(texCoord0.y);
}
vertBuffer.rewind();
normBuffer.rewind();
texBuffer.rewind();
vaoHandle = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vaoHandle);
IntBuffer vboHandles = BufferUtils.createIntBuffer(3);
GL15.glGenBuffers(vboHandles);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboHandles.get(0));
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertBuffer, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0L);
GL20.glEnableVertexAttribArray(0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboHandles.get(1));
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, normBuffer, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(1, 3, GL11.GL_FLOAT, false, 0, 0L);
GL20.glEnableVertexAttribArray(1);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboHandles.get(2));
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, texBuffer, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(2, 2, GL11.GL_FLOAT, false, 0, 0L);
GL20.glEnableVertexAttribArray(2);
}
public void draw(){
GL30.glBindVertexArray(vaoHandle);
GL11.glDrawArrays(GL11.GL_QUAD_STRIP, 0, numIndices);
GL30.glBindVertexArray(0);
}
}