/**
* Copyright (C) 2011 JogAmp Community. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.jogamp.opengl.test.junit.jogl.demos;
import java.nio.FloatBuffer;
import com.jogamp.opengl.GL;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.util.GLArrayDataServer;
/**
* GearsObject.java <BR>
* @author Brian Paul (converted to Java by Ron Cemer and Sven Gothel) <P>
*/
public abstract class GearsObject {
public static final FloatBuffer red = Buffers.newDirectFloatBuffer( new float[] { 0.8f, 0.1f, 0.0f, 0.7f } );
public static final FloatBuffer green = Buffers.newDirectFloatBuffer( new float[] { 0.0f, 0.8f, 0.2f, 0.7f } );
public static final FloatBuffer blue = Buffers.newDirectFloatBuffer( new float[] { 0.2f, 0.2f, 1.0f, 0.7f } );
public static final float M_PI = (float)Math.PI;
public final FloatBuffer gearColor;
public GLArrayDataServer frontFace;
public GLArrayDataServer frontSide;
public GLArrayDataServer backFace;
public GLArrayDataServer backSide;
public GLArrayDataServer outwardFace;
public GLArrayDataServer insideRadiusCyl;
public boolean isShared;
protected boolean validateBuffers = false;
public abstract GLArrayDataServer createInterleaved(boolean useMappedBuffers, int comps, int dataType, boolean normalized, int initialSize, int vboUsage);
public abstract void addInterleavedVertexAndNormalArrays(GLArrayDataServer array, int components);
public abstract void draw(GL gl, float x, float y, float angle);
private GLArrayDataServer createInterleavedClone(final GLArrayDataServer ads) {
final GLArrayDataServer n = new GLArrayDataServer(ads);
n.setInterleavedOffset(0);
return n;
}
private void init(final GL gl, final GLArrayDataServer array) {
array.enableBuffer(gl, true);
array.enableBuffer(gl, false);
}
public void destroy(final GL gl) {
if(!isShared) {
// could be already destroyed by shared configuration
if(null != frontFace) {
frontFace.destroy(gl);
}
if(null != frontSide) {
frontSide.destroy(gl);
}
if(null != backFace) {
backFace.destroy(gl);
}
if(null != backSide) {
backSide.destroy(gl);
}
if(null != outwardFace) {
outwardFace.destroy(gl);
}
if(null != insideRadiusCyl) {
insideRadiusCyl.destroy(gl);
}
}
frontFace=null;
frontSide=null;
backFace=null;
backSide=null;
outwardFace=null;
insideRadiusCyl=null;
isShared = false;
}
public GearsObject ( final GearsObject shared ) {
isShared = true;
validateBuffers = shared.validateBuffers;
frontFace = createInterleavedClone(shared.frontFace);
addInterleavedVertexAndNormalArrays(frontFace, 3);
backFace = createInterleavedClone(shared.backFace);
addInterleavedVertexAndNormalArrays(backFace, 3);
frontSide = createInterleavedClone(shared.frontSide);
addInterleavedVertexAndNormalArrays(frontSide, 3);
backSide= createInterleavedClone(shared.backSide);
addInterleavedVertexAndNormalArrays(backSide, 3);
outwardFace = createInterleavedClone(shared.outwardFace);
addInterleavedVertexAndNormalArrays(outwardFace, 3);
insideRadiusCyl = createInterleavedClone(shared.insideRadiusCyl);
addInterleavedVertexAndNormalArrays(insideRadiusCyl, 3);
gearColor = shared.gearColor;
}
public GearsObject (
final GL gl,
final boolean useMappedBuffers,
final FloatBuffer gearColor,
final float inner_radius,
final float outer_radius,
final float width, final int teeth, final float tooth_depth, final boolean validateBuffers)
{
final float dz = width * 0.5f;
int i;
float r0, r1, r2;
float angle, da;
float u, v, len;
final float s[] = new float[5];
final float c[] = new float[5];
final float normal[] = new float[3];
// final int tris_per_tooth = 32;
this.validateBuffers = validateBuffers;
this.isShared = false;
this.gearColor = gearColor;
r0 = inner_radius;
r1 = outer_radius - tooth_depth / 2.0f;
r2 = outer_radius + tooth_depth / 2.0f;
da = 2.0f * (float) Math.PI / teeth / 4.0f;
s[4] = 0; // sin(0f)
c[4] = 1; // cos(0f)
final int vboUsage = GL.GL_STATIC_DRAW;
frontFace = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 4*teeth+2, vboUsage);
addInterleavedVertexAndNormalArrays(frontFace, 3);
backFace = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 4*teeth+2, vboUsage);
addInterleavedVertexAndNormalArrays(backFace, 3);
frontSide = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 6*teeth, vboUsage);
addInterleavedVertexAndNormalArrays(frontSide, 3);
backSide = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 6*teeth, vboUsage);
addInterleavedVertexAndNormalArrays(backSide, 3);
outwardFace = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 4*4*teeth+2, vboUsage);
addInterleavedVertexAndNormalArrays(outwardFace, 3);
insideRadiusCyl = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 2*teeth+2, vboUsage);
addInterleavedVertexAndNormalArrays(insideRadiusCyl, 3);
if( useMappedBuffers ) {
frontFace.mapStorage(gl, GL.GL_WRITE_ONLY);
backFace.mapStorage(gl, GL.GL_WRITE_ONLY);
frontSide.mapStorage(gl, GL.GL_WRITE_ONLY);
backSide.mapStorage(gl, GL.GL_WRITE_ONLY);
outwardFace.mapStorage(gl, GL.GL_WRITE_ONLY);
insideRadiusCyl.mapStorage(gl, GL.GL_WRITE_ONLY);
}
for (i = 0; i < teeth; i++) {
angle = i * 2.0f * M_PI / teeth;
sincos(angle + da * 0f, s, 0, c, 0);
sincos(angle + da * 1f, s, 1, c, 1);
sincos(angle + da * 2f, s, 2, c, 2);
sincos(angle + da * 3f, s, 3, c, 3);
/* front */
normal[0] = 0.0f;
normal[1] = 0.0f;
normal[2] = 1.0f;
/* front face - GL.GL_TRIANGLE_STRIP */
vert(frontFace, r0 * c[0], r0 * s[0], dz, normal);
vert(frontFace, r1 * c[0], r1 * s[0], dz, normal);
vert(frontFace, r0 * c[0], r0 * s[0], dz, normal);
vert(frontFace, r1 * c[3], r1 * s[3], dz, normal);
/* front sides of teeth - GL.GL_TRIANGLES */
vert(frontSide, r1 * c[0], r1 * s[0], dz, normal);
vert(frontSide, r2 * c[1], r2 * s[1], dz, normal);
vert(frontSide, r2 * c[2], r2 * s[2], dz, normal);
vert(frontSide, r1 * c[0], r1 * s[0], dz, normal);
vert(frontSide, r2 * c[2], r2 * s[2], dz, normal);
vert(frontSide, r1 * c[3], r1 * s[3], dz, normal);
/* back */
normal[0] = 0.0f;
normal[1] = 0.0f;
normal[2] = -1.0f;
/* back face - GL.GL_TRIANGLE_STRIP */
vert(backFace, r1 * c[0], r1 * s[0], -dz, normal);
vert(backFace, r0 * c[0], r0 * s[0], -dz, normal);
vert(backFace, r1 * c[3], r1 * s[3], -dz, normal);
vert(backFace, r0 * c[0], r0 * s[0], -dz, normal);
/* back sides of teeth - GL.GL_TRIANGLES*/
vert(backSide, r1 * c[3], r1 * s[3], -dz, normal);
vert(backSide, r2 * c[2], r2 * s[2], -dz, normal);
vert(backSide, r2 * c[1], r2 * s[1], -dz, normal);
vert(backSide, r1 * c[3], r1 * s[3], -dz, normal);
vert(backSide, r2 * c[1], r2 * s[1], -dz, normal);
vert(backSide, r1 * c[0], r1 * s[0], -dz, normal);
/* outward faces of teeth */
u = r2 * c[1] - r1 * c[0];
v = r2 * s[1] - r1 * s[0];
len = (float)Math.sqrt(u * u + v * v);
u /= len;
v /= len;
normal[0] = v;
normal[1] = -u;
normal[2] = 0.0f;
vert(outwardFace, r1 * c[0], r1 * s[0], dz, normal);
vert(outwardFace, r1 * c[0], r1 * s[0], -dz, normal);
vert(outwardFace, r2 * c[1], r2 * s[1], dz, normal);
vert(outwardFace, r2 * c[1], r2 * s[1], -dz, normal);
normal[0] = c[0];
normal[1] = s[0];
vert(outwardFace, r2 * c[1], r2 * s[1], dz, normal);
vert(outwardFace, r2 * c[1], r2 * s[1], -dz, normal);
vert(outwardFace, r2 * c[2], r2 * s[2], dz, normal);
vert(outwardFace, r2 * c[2], r2 * s[2], -dz, normal);
normal[0] = ( r1 * s[3] - r2 * s[2] );
normal[1] = ( r1 * c[3] - r2 * c[2] ) * -1.0f ;
vert(outwardFace, r2 * c[2], r2 * s[2], dz, normal);
vert(outwardFace, r2 * c[2], r2 * s[2], -dz, normal);
vert(outwardFace, r1 * c[3], r1 * s[3], dz, normal);
vert(outwardFace, r1 * c[3], r1 * s[3], -dz, normal);
normal[0] = c[0];
normal[1] = s[0];
vert(outwardFace, r1 * c[3], r1 * s[3], dz, normal);
vert(outwardFace, r1 * c[3], r1 * s[3], -dz, normal);
vert(outwardFace, r1 * c[0], r1 * s[0], dz, normal);
vert(outwardFace, r1 * c[0], r1 * s[0], -dz, normal);
/* inside radius cylinder */
normal[0] = c[0] * -1.0f;
normal[1] = s[0] * -1.0f;
normal[2] = 0.0f;
vert(insideRadiusCyl, r0 * c[0], r0 * s[0], -dz, normal);
vert(insideRadiusCyl, r0 * c[0], r0 * s[0], dz, normal);
}
/* finish front face */
normal[0] = 0.0f;
normal[1] = 0.0f;
normal[2] = 1.0f;
vert(frontFace, r0 * c[4], r0 * s[4], dz, normal);
vert(frontFace, r1 * c[4], r1 * s[4], dz, normal);
frontFace.seal(true);
/* finish back face */
normal[2] = -1.0f;
vert(backFace, r1 * c[4], r1 * s[4], -dz, normal);
vert(backFace, r0 * c[4], r0 * s[4], -dz, normal);
backFace.seal(true);
backSide.seal(true);
frontSide.seal(true);
/* finish outward face */
sincos(da * 1f, s, 1, c, 1);
u = r2 * c[1] - r1 * c[4];
v = r2 * s[1] - r1 * s[4];
len = (float)Math.sqrt(u * u + v * v);
u /= len;
v /= len;
normal[0] = v;
normal[1] = -u;
normal[2] = 0.0f;
vert(outwardFace, r1 * c[4], r1 * s[4], dz, normal);
vert(outwardFace, r1 * c[4], r1 * s[4], -dz, normal);
outwardFace.seal(true);
/* finish inside radius cylinder */
normal[0] = c[4] * -1.0f;
normal[1] = s[4] * -1.0f;
normal[2] = 0.0f;
vert(insideRadiusCyl, r0 * c[4], r0 * s[4], -dz, normal);
vert(insideRadiusCyl, r0 * c[4], r0 * s[4], dz, normal);
insideRadiusCyl.seal(true);
if( useMappedBuffers ) {
frontFace.unmapStorage(gl);
backFace.unmapStorage(gl);
frontSide.unmapStorage(gl);
backSide.unmapStorage(gl);
outwardFace.unmapStorage(gl);
insideRadiusCyl.unmapStorage(gl);
} else {
/** Init VBO and data .. */
init(gl, frontFace);
init(gl, frontSide);
init(gl, backFace);
init(gl, backSide);
init(gl, outwardFace);
init(gl, insideRadiusCyl);
}
}
@Override
public String toString() {
final int ffVBO = null != frontFace ? frontFace.getVBOName() : 0;
final int fsVBO = null != frontSide ? frontSide.getVBOName() : 0;
final int bfVBO = null != backFace ? backFace.getVBOName() : 0;
final int bsVBO = null != backSide ? backSide.getVBOName() : 0;
return "GearsObj[0x"+Integer.toHexString(hashCode())+", vbo ff "+ffVBO+", fs "+fsVBO+", bf "+bfVBO+", bs "+bsVBO+"]";
}
static void vert(final GLArrayDataServer array, final float x, final float y, final float z, final float n[]) {
array.putf(x);
array.putf(y);
array.putf(z);
array.putf(n[0]);
array.putf(n[1]);
array.putf(n[2]);
}
static void sincos(final float x, final float sin[], final int sinIdx, final float cos[], final int cosIdx) {
sin[sinIdx] = (float) Math.sin(x);
cos[cosIdx] = (float) Math.cos(x);
}
}