From 4732089913b5ce876ac7005c9ef48b081a4d0ee3 Mon Sep 17 00:00:00 2001 From: Erik Duijs Date: Wed, 21 Jan 2004 17:27:49 +0000 Subject: [PATCH] Now it's at least implemented (but not tested). --- .../org/lwjgl/opengl/glu/PartialDisk.java | 331 ++++++++++++++++-- 1 file changed, 307 insertions(+), 24 deletions(-) diff --git a/src/java/org/lwjgl/opengl/glu/PartialDisk.java b/src/java/org/lwjgl/opengl/glu/PartialDisk.java index 0486be04..a61a5787 100644 --- a/src/java/org/lwjgl/opengl/glu/PartialDisk.java +++ b/src/java/org/lwjgl/opengl/glu/PartialDisk.java @@ -1,15 +1,19 @@ - package org.lwjgl.opengl.glu; +import org.lwjgl.opengl.GL11; + /** * PartialDisk.java * * * Created 23-dec-2003 + * * @author Erik Duijs */ public class PartialDisk extends Quadric implements GLUConstants { + private static final int CACHE_SIZE = 240; + /** * Constructor for PartialDisk. */ @@ -17,28 +21,307 @@ public class PartialDisk extends Quadric implements GLUConstants { 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_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). - */ + /** + * 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_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, max; + float[] sinCache = new float[CACHE_SIZE]; + float[] cosCache = new float[CACHE_SIZE]; + float angle; + float x, y; + 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_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) { + GL11.glNormal3f(0.0f, 0.0f, 1.0f); + } else { + GL11.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 */ + GL11.glBegin(GL11.GL_TRIANGLE_FAN); + if (super.textureFlag) { + GL11.glTexCoord2f(0.5f, 0.5f); + } + GL11.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) { + GL11.glTexCoord2f( + texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + GL11.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + } + } else { + for (i = 0; i <= slices; i++) { + if (super.textureFlag) { + GL11.glTexCoord2f( + texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + GL11.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + } + } + GL11.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; + } + + GL11.glBegin(GL11.GL_QUAD_STRIP); + for (i = 0; i <= slices; i++) { + if (super.orientation == GLU_OUTSIDE) { + if (super.textureFlag) { + GL11.glTexCoord2f( + texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + GL11.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + + if (super.textureFlag) { + GL11.glTexCoord2f( + texHigh * sinCache[i] + 0.5f, + texHigh * cosCache[i] + 0.5f); + } + GL11.glVertex3f( + radiusHigh * sinCache[i], + radiusHigh * cosCache[i], + 0.0f); + } else { + if (super.textureFlag) { + GL11.glTexCoord2f( + texHigh * sinCache[i] + 0.5f, + texHigh * cosCache[i] + 0.5f); + } + GL11.glVertex3f( + radiusHigh * sinCache[i], + radiusHigh * cosCache[i], + 0.0f); + + if (super.textureFlag) { + GL11.glTexCoord2f( + texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + GL11.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + } + } + GL11.glEnd(); + } + break; + case GLU_POINT : + GL11.glBegin(GL11.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; + + GL11.glTexCoord2f( + texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + GL11.glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0f); + } + } + GL11.glEnd(); + break; + case GLU_LINE : + if (innerRadius == outerRadius) { + GL11.glBegin(GL11.GL_LINE_STRIP); + + for (i = 0; i <= slices; i++) { + if (super.textureFlag) { + GL11.glTexCoord2f(sinCache[i] / 2 + 0.5f, cosCache[i] / 2 + 0.5f); + } + GL11.glVertex3f(innerRadius * sinCache[i], innerRadius * cosCache[i], 0.0f); + } + GL11.glEnd(); + break; + } + for (j = 0; j <= loops; j++) { + radiusLow = outerRadius - deltaRadius * ((float) j / loops); + if (super.textureFlag) { + texLow = radiusLow / outerRadius / 2; + } + + GL11.glBegin(GL11.GL_LINE_STRIP); + for (i = 0; i <= slices; i++) { + if (super.textureFlag) { + GL11.glTexCoord2f( + texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + GL11.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + } + GL11.glEnd(); + } + for (i = 0; i < slices2; i++) { + sintemp = sinCache[i]; + costemp = cosCache[i]; + GL11.glBegin(GL11.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) { + GL11.glTexCoord2f( + texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + GL11.glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0f); + } + GL11.glEnd(); + } + break; + case GLU_SILHOUETTE : + if (sweepAngle < 360.0f) { + for (i = 0; i <= slices; i += slices) { + sintemp = sinCache[i]; + costemp = cosCache[i]; + GL11.glBegin(GL11.GL_LINE_STRIP); + for (j = 0; j <= loops; j++) { + radiusLow = outerRadius - deltaRadius * ((float) j / loops); + + if (super.textureFlag) { + texLow = radiusLow / outerRadius / 2; + GL11.glTexCoord2f( + texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + GL11.glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0f); + } + GL11.glEnd(); + } + } + for (j = 0; j <= loops; j += loops) { + radiusLow = outerRadius - deltaRadius * ((float) j / loops); + if (super.textureFlag) { + texLow = radiusLow / outerRadius / 2; + } + + GL11.glBegin(GL11.GL_LINE_STRIP); + for (i = 0; i <= slices; i++) { + if (super.textureFlag) { + GL11.glTexCoord2f( + texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + GL11.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + } + GL11.glEnd(); + if (innerRadius == outerRadius) + break; + } + break; + default : + break; + } + } }