lwjgl/src/java/org/lwjgl/util/glu/PartialDisk.java

359 lines
10 KiB
Java

/*
* Copyright (c) 2002-2008 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'LWJGL' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.lwjgl.util.glu;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.*;
/**
* PartialDisk.java
*
*
* Created 23-dec-2003
*
* @author Erik Duijs
*/
public class PartialDisk extends Quadric {
private static final int CACHE_SIZE = 240;
/**
* Constructor for PartialDisk.
*/
public PartialDisk() {
super();
}
/**
* renders a partial disk on the z=0 plane. A partial disk is similar to a
* full disk, except that only the subset of the disk from startAngle
* through startAngle + sweepAngle is included (where 0 degrees is along
* the +y axis, 90 degrees along the +x axis, 180 along the -y axis, and
* 270 along the -x axis).
*
* The partial disk has a radius of outerRadius, and contains a concentric
* circular hole with a radius of innerRadius. If innerRadius is zero, then
* no hole is generated. The partial disk is subdivided around the z axis
* into slices (like pizza slices), and also about the z axis into rings
* (as specified by slices and loops, respectively).
*
* With respect to orientation, the +z side of the partial disk is
* considered to be outside (see gluQuadricOrientation). This means that if
* the orientation is set to GLU.GLU_OUTSIDE, then any normals generated point
* along the +z axis. Otherwise, they point along the -z axis.
*
* If texturing is turned on (with gluQuadricTexture), texture coordinates
* are generated linearly such that where r=outerRadius, the value at (r, 0, 0)
* is (1, 0.5), at (0, r, 0) it is (0.5, 1), at (-r, 0, 0) it is (0, 0.5),
* and at (0, -r, 0) it is (0.5, 0).
*/
public void draw(
float innerRadius,
float outerRadius,
int slices,
int loops,
float startAngle,
float sweepAngle) {
int i, j;
float[] sinCache = new float[CACHE_SIZE];
float[] cosCache = new float[CACHE_SIZE];
float angle;
float sintemp, costemp;
float deltaRadius;
float radiusLow, radiusHigh;
float texLow = 0, texHigh = 0;
float angleOffset;
int slices2;
int finish;
if (slices >= CACHE_SIZE)
slices = CACHE_SIZE - 1;
if (slices < 2
|| loops < 1
|| outerRadius <= 0.0f
|| innerRadius < 0.0f
|| innerRadius > outerRadius) {
//gluQuadricError(qobj, GLU.GLU_INVALID_VALUE);
System.err.println("PartialDisk: GLU_INVALID_VALUE");
return;
}
if (sweepAngle < -360.0f)
sweepAngle = 360.0f;
if (sweepAngle > 360.0f)
sweepAngle = 360.0f;
if (sweepAngle < 0) {
startAngle += sweepAngle;
sweepAngle = -sweepAngle;
}
if (sweepAngle == 360.0f) {
slices2 = slices;
} else {
slices2 = slices + 1;
}
/* Compute length (needed for normal calculations) */
deltaRadius = outerRadius - innerRadius;
/* Cache is the vertex locations cache */
angleOffset = startAngle / 180.0f * PI;
for (i = 0; i <= slices; i++) {
angle = angleOffset + ((PI * sweepAngle) / 180.0f) * i / slices;
sinCache[i] = sin(angle);
cosCache[i] = cos(angle);
}
if (sweepAngle == 360.0f) {
sinCache[slices] = sinCache[0];
cosCache[slices] = cosCache[0];
}
switch (super.normals) {
case GLU_FLAT :
case GLU_SMOOTH :
if (super.orientation == GLU_OUTSIDE) {
glNormal3f(0.0f, 0.0f, 1.0f);
} else {
glNormal3f(0.0f, 0.0f, -1.0f);
}
break;
default :
case GLU_NONE :
break;
}
switch (super.drawStyle) {
case GLU_FILL :
if (innerRadius == .0f) {
finish = loops - 1;
/* Triangle strip for inner polygons */
glBegin(GL_TRIANGLE_FAN);
if (super.textureFlag) {
glTexCoord2f(0.5f, 0.5f);
}
glVertex3f(0.0f, 0.0f, 0.0f);
radiusLow = outerRadius - deltaRadius * ((float) (loops - 1) / loops);
if (super.textureFlag) {
texLow = radiusLow / outerRadius / 2;
}
if (super.orientation == GLU_OUTSIDE) {
for (i = slices; i >= 0; i--) {
if (super.textureFlag) {
glTexCoord2f(
texLow * sinCache[i] + 0.5f,
texLow * cosCache[i] + 0.5f);
}
glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
}
} else {
for (i = 0; i <= slices; i++) {
if (super.textureFlag) {
glTexCoord2f(
texLow * sinCache[i] + 0.5f,
texLow * cosCache[i] + 0.5f);
}
glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
}
}
glEnd();
} else {
finish = loops;
}
for (j = 0; j < finish; j++) {
radiusLow = outerRadius - deltaRadius * ((float) j / loops);
radiusHigh = outerRadius - deltaRadius * ((float) (j + 1) / loops);
if (super.textureFlag) {
texLow = radiusLow / outerRadius / 2;
texHigh = radiusHigh / outerRadius / 2;
}
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= slices; i++) {
if (super.orientation == GLU_OUTSIDE) {
if (super.textureFlag) {
glTexCoord2f(
texLow * sinCache[i] + 0.5f,
texLow * cosCache[i] + 0.5f);
}
glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
if (super.textureFlag) {
glTexCoord2f(
texHigh * sinCache[i] + 0.5f,
texHigh * cosCache[i] + 0.5f);
}
glVertex3f(
radiusHigh * sinCache[i],
radiusHigh * cosCache[i],
0.0f);
} else {
if (super.textureFlag) {
glTexCoord2f(
texHigh * sinCache[i] + 0.5f,
texHigh * cosCache[i] + 0.5f);
}
glVertex3f(
radiusHigh * sinCache[i],
radiusHigh * cosCache[i],
0.0f);
if (super.textureFlag) {
glTexCoord2f(
texLow * sinCache[i] + 0.5f,
texLow * cosCache[i] + 0.5f);
}
glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
}
}
glEnd();
}
break;
case GLU_POINT :
glBegin(GL_POINTS);
for (i = 0; i < slices2; i++) {
sintemp = sinCache[i];
costemp = cosCache[i];
for (j = 0; j <= loops; j++) {
radiusLow = outerRadius - deltaRadius * ((float) j / loops);
if (super.textureFlag) {
texLow = radiusLow / outerRadius / 2;
glTexCoord2f(
texLow * sinCache[i] + 0.5f,
texLow * cosCache[i] + 0.5f);
}
glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0f);
}
}
glEnd();
break;
case GLU_LINE :
if (innerRadius == outerRadius) {
glBegin(GL_LINE_STRIP);
for (i = 0; i <= slices; i++) {
if (super.textureFlag) {
glTexCoord2f(sinCache[i] / 2 + 0.5f, cosCache[i] / 2 + 0.5f);
}
glVertex3f(innerRadius * sinCache[i], innerRadius * cosCache[i], 0.0f);
}
glEnd();
break;
}
for (j = 0; j <= loops; j++) {
radiusLow = outerRadius - deltaRadius * ((float) j / loops);
if (super.textureFlag) {
texLow = radiusLow / outerRadius / 2;
}
glBegin(GL_LINE_STRIP);
for (i = 0; i <= slices; i++) {
if (super.textureFlag) {
glTexCoord2f(
texLow * sinCache[i] + 0.5f,
texLow * cosCache[i] + 0.5f);
}
glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
}
glEnd();
}
for (i = 0; i < slices2; i++) {
sintemp = sinCache[i];
costemp = cosCache[i];
glBegin(GL_LINE_STRIP);
for (j = 0; j <= loops; j++) {
radiusLow = outerRadius - deltaRadius * ((float) j / loops);
if (super.textureFlag) {
texLow = radiusLow / outerRadius / 2;
}
if (super.textureFlag) {
glTexCoord2f(
texLow * sinCache[i] + 0.5f,
texLow * cosCache[i] + 0.5f);
}
glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0f);
}
glEnd();
}
break;
case GLU_SILHOUETTE :
if (sweepAngle < 360.0f) {
for (i = 0; i <= slices; i += slices) {
sintemp = sinCache[i];
costemp = cosCache[i];
glBegin(GL_LINE_STRIP);
for (j = 0; j <= loops; j++) {
radiusLow = outerRadius - deltaRadius * ((float) j / loops);
if (super.textureFlag) {
texLow = radiusLow / outerRadius / 2;
glTexCoord2f(
texLow * sinCache[i] + 0.5f,
texLow * cosCache[i] + 0.5f);
}
glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0f);
}
glEnd();
}
}
for (j = 0; j <= loops; j += loops) {
radiusLow = outerRadius - deltaRadius * ((float) j / loops);
if (super.textureFlag) {
texLow = radiusLow / outerRadius / 2;
}
glBegin(GL_LINE_STRIP);
for (i = 0; i <= slices; i++) {
if (super.textureFlag) {
glTexCoord2f(
texLow * sinCache[i] + 0.5f,
texLow * cosCache[i] + 0.5f);
}
glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
}
glEnd();
if (innerRadius == outerRadius)
break;
}
break;
default :
break;
}
}
}