diff options
7 files changed, 603 insertions, 713 deletions
diff --git a/src/classes/share/com/sun/j3d/utils/geometry/Box.java b/src/classes/share/com/sun/j3d/utils/geometry/Box.java index 8a1627a..04dac4d 100644 --- a/src/classes/share/com/sun/j3d/utils/geometry/Box.java +++ b/src/classes/share/com/sun/j3d/utils/geometry/Box.java @@ -167,12 +167,14 @@ public class Box extends Primitive { zDim = zdim; flags = primflags; numTexUnit = numTexUnit; - + boolean texCoordYUp = (flags & GENERATE_TEXTURE_COORDS_YUP) != 0; + //Depending on whether normal inward bit is set. if ((flags & GENERATE_NORMALS_INWARD) != 0) - sign = -1.0; + sign = -1.0; else sign = 1.0; + // TransformGroup objTrans = new TransformGroup(); // objTrans.setCapability(ALLOW_CHILDREN_READ); // this.addChild(objTrans); @@ -200,7 +202,13 @@ public class Box extends Primitive { gbuf.normal3d( (double) normals[i].x*sign, (double) normals[i].y*sign, (double) normals[i].z*sign); - gbuf.texCoord2d(tcoords[i*8 + j*2], tcoords[i*8 + j*2 + 1]); + if (texCoordYUp) { + gbuf.texCoord2d(tcoords[i*8 + j*2], 1.0 - tcoords[i*8 + j*2 + 1]); + } + else { + gbuf.texCoord2d(tcoords[i*8 + j*2], tcoords[i*8 + j*2 + 1]); + } + gbuf.vertex3d( (double) verts[i*12 + j*3]*xdim, (double) verts[i*12+ j*3 + 1]*ydim, (double) verts[i*12+ j*3 + 2]*zdim ); @@ -209,7 +217,12 @@ public class Box extends Primitive { gbuf.normal3d( (double) normals[i].x*sign, (double) normals[i].y*sign, (double) normals[i].z*sign); - gbuf.texCoord2d(tcoords[i*8 + j*2], tcoords[i*8 + j*2 + 1]); + if (texCoordYUp) { + gbuf.texCoord2d(tcoords[i*8 + j*2], 1.0 - tcoords[i*8 + j*2 + 1]); + } + else { + gbuf.texCoord2d(tcoords[i*8 + j*2], tcoords[i*8 + j*2 + 1]); + } gbuf.vertex3d( (double) verts[i*12 + j*3]*xdim, (double) verts[i*12+ j*3 + 1]*ydim, (double) verts[i*12+ j*3 + 2]*zdim ); diff --git a/src/classes/share/com/sun/j3d/utils/geometry/Cone.java b/src/classes/share/com/sun/j3d/utils/geometry/Cone.java index 2097931..c98cae9 100644 --- a/src/classes/share/com/sun/j3d/utils/geometry/Cone.java +++ b/src/classes/share/com/sun/j3d/utils/geometry/Cone.java @@ -211,6 +211,7 @@ public class Cone extends Primitive { ydivisions = ydivision; flags = primflags; boolean outside = (flags & GENERATE_NORMALS_INWARD) == 0; + boolean texCoordYUp = (flags & GENERATE_TEXTURE_COORDS_YUP) != 0; Quadrics q = new Quadrics(); GeomBuffer gbuf = null; @@ -229,7 +230,7 @@ public class Cone extends Primitive { gbuf = q.coneTop((double)(height/2.0 - height/ydivisions), (double)(radius/ydivisions), height/ydivisions, xdivisions, 1.0-1.0/(double)ydivisions, - outside); + outside, texCoordYUp); shape[BODY] = new Shape3D(gbuf.getGeom(flags)); numVerts += gbuf.getNumVerts(); numTris += gbuf.getNumTris(); @@ -255,7 +256,7 @@ public class Cone extends Primitive { (double)(height/2.0-height/ydivisions), (double)radius, (double)(radius/ydivisions), xdivisions, ydivisions-1, 1.0/(double)ydivisions, - outside); + outside, texCoordYUp); shape[BODY].addGeometry(gbuf.getGeom(flags)); numVerts += gbuf.getNumVerts(); numTris += gbuf.getNumTris(); @@ -289,7 +290,7 @@ public class Cone extends Primitive { } else { gbuf = q.disk((double)radius, xdivision, -(double)height/2.0, - !outside); + !outside, texCoordYUp); shape[CAP] = new Shape3D(gbuf.getGeom(flags)); numVerts += gbuf.getNumVerts(); numTris += gbuf.getNumTris(); diff --git a/src/classes/share/com/sun/j3d/utils/geometry/Cylinder.java b/src/classes/share/com/sun/j3d/utils/geometry/Cylinder.java index 1be3d98..26b0cec 100644 --- a/src/classes/share/com/sun/j3d/utils/geometry/Cylinder.java +++ b/src/classes/share/com/sun/j3d/utils/geometry/Cylinder.java @@ -212,6 +212,7 @@ public class Cylinder extends Primitive{ this.ydivisions = ydivision; flags = primflags; boolean outside = (flags & GENERATE_NORMALS_INWARD) == 0; + boolean texCoordYUp = (flags & GENERATE_TEXTURE_COORDS_YUP) != 0; // Create many body of the cylinder. Quadrics q = new Quadrics(); GeomBuffer gbuf = null; @@ -228,7 +229,7 @@ public class Cylinder extends Primitive{ } else { gbuf = q.cylinder((double)height, (double)radius, - xdivision, ydivision, outside); + xdivision, ydivision, outside, texCoordYUp); shape[BODY] = new Shape3D(gbuf.getGeom(flags)); numVerts += gbuf.getNumVerts(); numTris += gbuf.getNumTris(); @@ -260,7 +261,7 @@ public class Cylinder extends Primitive{ } else { gbuf = q.disk((double)radius, xdivision, height/2.0, - outside); + outside, texCoordYUp); shape[TOP] = new Shape3D(gbuf.getGeom(flags)); numVerts += gbuf.getNumVerts(); numTris += gbuf.getNumTris(); @@ -293,7 +294,7 @@ public class Cylinder extends Primitive{ numTris += cache.getNumTris(); } else { - gbuf = q.disk((double)radius, xdivision, -height/2.0, !outside); + gbuf = q.disk((double)radius, xdivision, -height/2.0, !outside, texCoordYUp); shape[BOTTOM] = new Shape3D(gbuf.getGeom(flags)); numVerts += gbuf.getNumVerts(); numTris += gbuf.getNumTris(); diff --git a/src/classes/share/com/sun/j3d/utils/geometry/GeomBuffer.java b/src/classes/share/com/sun/j3d/utils/geometry/GeomBuffer.java index 897a79c..890f989 100644 --- a/src/classes/share/com/sun/j3d/utils/geometry/GeomBuffer.java +++ b/src/classes/share/com/sun/j3d/utils/geometry/GeomBuffer.java @@ -96,8 +96,6 @@ class GeomBuffer extends Object{ static final int TRIANGLE_STRIP = 0x20; private int flags; - static final int GENERATE_NORMALS = 0x01; - static final int GENERATE_TEXTURE_COORDS = 0x02; Point3f[] pts = null; Vector3f[] normals = null; @@ -285,9 +283,9 @@ class GeomBuffer extends Object{ if (debug >= 1) System.out.println("totalVerts " + totalVerts); int tsaFlags = TriangleStripArray.COORDINATES; - if ((flags & GENERATE_NORMALS) != 0) + if ((flags & Primitive.GENERATE_NORMALS) != 0) tsaFlags |= TriangleStripArray.NORMALS; - if ((flags & GENERATE_TEXTURE_COORDS) != 0) + if ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0) tsaFlags |= TriangleStripArray.TEXTURE_COORDINATE_2; // Create GeometryArray to pass back @@ -314,9 +312,9 @@ class GeomBuffer extends Object{ numTris += totalVerts - currPrimCnt * 2; obj.setCoordinates(0, newpts); - if ((flags & GENERATE_NORMALS) != 0) + if ((flags & Primitive.GENERATE_NORMALS) != 0) obj.setNormals(0, newnormals); - if ((flags & GENERATE_TEXTURE_COORDS) != 0) + if ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0) obj.setTextureCoordinates(0, 0, newtcoords); geometry = obj; @@ -335,8 +333,8 @@ class GeomBuffer extends Object{ if (debug >= 1) System.out.println("totalVerts " + totalVerts); - if (((flags & GENERATE_NORMALS) != 0) && - ((flags & GENERATE_TEXTURE_COORDS) != 0)){ + if (((flags & Primitive.GENERATE_NORMALS) != 0) && + ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0)){ obj = new QuadArray(totalVerts, QuadArray.COORDINATES | QuadArray.NORMALS | @@ -344,16 +342,16 @@ class GeomBuffer extends Object{ 1, texCoordSetMap); } else - if (((flags & GENERATE_NORMALS) == 0) && - ((flags & GENERATE_TEXTURE_COORDS) != 0)){ + if (((flags & Primitive.GENERATE_NORMALS) == 0) && + ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0)){ obj = new QuadArray(totalVerts, QuadArray.COORDINATES | QuadArray.TEXTURE_COORDINATE_2, 1, texCoordSetMap); } else - if (((flags & GENERATE_NORMALS) != 0) && - ((flags & GENERATE_TEXTURE_COORDS) == 0)){ + if (((flags & Primitive.GENERATE_NORMALS) != 0) && + ((flags & Primitive.GENERATE_TEXTURE_COORDS) == 0)){ obj = new QuadArray(totalVerts, QuadArray.COORDINATES | QuadArray.NORMALS); @@ -388,9 +386,9 @@ class GeomBuffer extends Object{ numVerts = currVert; obj.setCoordinates(0, newpts); - if ((flags & GENERATE_NORMALS) != 0) + if ((flags & Primitive.GENERATE_NORMALS) != 0) obj.setNormals(0, newnormals); - if ((flags & GENERATE_TEXTURE_COORDS) != 0) + if ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0) obj.setTextureCoordinates(0, 0, newtcoords); geometry = obj; @@ -409,8 +407,8 @@ class GeomBuffer extends Object{ if (debug >= 1) System.out.println("totalVerts " + totalVerts); - if (((flags & GENERATE_NORMALS) != 0) && - ((flags & GENERATE_TEXTURE_COORDS) != 0)){ + if (((flags & Primitive.GENERATE_NORMALS) != 0) && + ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0)){ obj = new TriangleArray(totalVerts, TriangleArray.COORDINATES | TriangleArray.NORMALS | @@ -418,16 +416,16 @@ class GeomBuffer extends Object{ 1, texCoordSetMap); } else - if (((flags & GENERATE_NORMALS) == 0) && - ((flags & GENERATE_TEXTURE_COORDS) != 0)){ + if (((flags & Primitive.GENERATE_NORMALS) == 0) && + ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0)){ obj = new TriangleArray(totalVerts, TriangleArray.COORDINATES | TriangleArray.TEXTURE_COORDINATE_2, 1, texCoordSetMap); } else - if (((flags & GENERATE_NORMALS) != 0) && - ((flags & GENERATE_TEXTURE_COORDS) == 0)){ + if (((flags & Primitive.GENERATE_NORMALS) != 0) && + ((flags & Primitive.GENERATE_TEXTURE_COORDS) == 0)){ obj = new TriangleArray(totalVerts, TriangleArray.COORDINATES | TriangleArray.NORMALS); @@ -456,9 +454,9 @@ class GeomBuffer extends Object{ numVerts = currVert; obj.setCoordinates(0, newpts); - if ((flags & GENERATE_NORMALS) != 0) + if ((flags & Primitive.GENERATE_NORMALS) != 0) obj.setNormals(0, newnormals); - if ((flags & GENERATE_TEXTURE_COORDS) != 0) + if ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0) obj.setTextureCoordinates(0, 0, newtcoords); geometry = obj; @@ -483,10 +481,10 @@ class GeomBuffer extends Object{ // figure out what flags we need int tfFlags = TriangleFanArray.COORDINATES; - if ((flags & GENERATE_NORMALS) != 0) { + if ((flags & Primitive.GENERATE_NORMALS) != 0) { tfFlags |= TriangleFanArray.NORMALS; } - if ((flags & GENERATE_TEXTURE_COORDS) != 0) { + if ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0) { tfFlags |= TriangleFanArray.TEXTURE_COORDINATE_2; } @@ -520,10 +518,10 @@ class GeomBuffer extends Object{ obj.setCoordinates(0, newpts); // set the normals and tex coords if necessary - if ((flags & GENERATE_NORMALS) != 0) { + if ((flags & Primitive.GENERATE_NORMALS) != 0) { obj.setNormals(0, newnormals); } - if ((flags & GENERATE_TEXTURE_COORDS) != 0) { + if ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0) { obj.setTextureCoordinates(0, 0, newtcoords); } geometry = obj; @@ -545,10 +543,10 @@ class GeomBuffer extends Object{ dpts[dloc] = new Point3f(spts[sloc]); - if ((flags & GENERATE_NORMALS) != 0){ + if ((flags & Primitive.GENERATE_NORMALS) != 0){ dnormals[dloc] = new Vector3f(snormals[sloc]); } - if ((flags & GENERATE_TEXTURE_COORDS) != 0){ + if ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0){ if (debug >= 2) System.out.println("final out tcoord"); dtcoords[dloc] = new TexCoord2f(stcoords[sloc]); } diff --git a/src/classes/share/com/sun/j3d/utils/geometry/Primitive.java b/src/classes/share/com/sun/j3d/utils/geometry/Primitive.java index bb14dce..4ba8094 100644 --- a/src/classes/share/com/sun/j3d/utils/geometry/Primitive.java +++ b/src/classes/share/com/sun/j3d/utils/geometry/Primitive.java @@ -80,6 +80,12 @@ public abstract class Primitive extends Group { */ public static final int GENERATE_NORMALS_INWARD = 0x04; + /** + * Specifies that texture coordinates are to be Y up. + */ + public static final int GENERATE_TEXTURE_COORDS_YUP = 0x08; + + /** * Specifies that the geometry being created will not be shared by * another scene graph node. By default all primitives created with diff --git a/src/classes/share/com/sun/j3d/utils/geometry/Quadrics.java b/src/classes/share/com/sun/j3d/utils/geometry/Quadrics.java index 929de37..015e506 100644 --- a/src/classes/share/com/sun/j3d/utils/geometry/Quadrics.java +++ b/src/classes/share/com/sun/j3d/utils/geometry/Quadrics.java @@ -52,671 +52,499 @@ import javax.vecmath.*; import java.math.*; class Quadrics extends Object { - - Quadrics (){ } - - // do not use this to make a cone. It uses too many triangles. The top of - // cone can be a triangle fan array - - GeomBuffer cylinder(double lowr, double highr, - double height, int xdivisions, int ydivisions, - boolean outside) - { - double r, sign; - - /* - * Cylinder is created by extruding the unit circle along the Z+ - * axis. The number of layers is controlled by ydivisions (which is - * actually zdivisions). For each consecutive sample points along the - * unit circle, we also sample along the height of the cylinder. Quads - * are created along the Z direction. When the unit circle at the base is - * completed, we also obtain the layers of quads along the height of the - * cylinder. - * - * Texture coordinates are created in a straight forward cylindrical - * mapping of the texture map. The texture is wrapped from the back of - * the cylinder. - */ - - if (outside) - sign = 1.0; - else - sign = -1.0; - //Compute the deltas - double dtheta = 2.0*Math.PI / xdivisions; - double dr = (highr - lowr) / ydivisions; - double dz = height / ydivisions; - double znormal = (lowr - highr) / height; - double du = 1.0 / xdivisions; - double dv = 1.0 / ydivisions; - - //Initialize geometry buffer. - GeomBuffer gbuf = new GeomBuffer(xdivisions*ydivisions*4); - - double s = 0.0, t = 0.0; - for (int i=0;i<xdivisions;i++) { - double px, py, qx, qy, z; - // (px,py) and (qx,qy) are consecutive sample points along the - // unit circle. We will create quads along the Z+ direction. - // we have to start at the back of the sphere, so add 90 degrees - px = Math.cos(i*dtheta + Math.PI/2.0); - py = Math.sin(i*dtheta + Math.PI/2.0); - qx = Math.cos((i+1)*dtheta + Math.PI/2.0); - qy = Math.sin((i+1)*dtheta + Math.PI/2.0); - // Initialize z,r,t - z = -1.0*height/2.0; r = lowr; t = 0.0; - - gbuf.begin( GeomBuffer.QUAD_STRIP ); - // For each consecutive two unit circle points, - // we obtain the layers of quads along the Z direction. Number of - // layers depends on ydivisions. - for (int j=0; j<=ydivisions; j++,z += dz,r += dr,t += dv){ - if ((j == ydivisions) && (highr == 0)) { - if (outside) { - gbuf.normal3d( 0.0, 0.0, znormal*sign ); - gbuf.texCoord2d(s, t); - gbuf.vertex3d( px*r, py*r, z ); - gbuf.normal3d( 0.0, 0.0, znormal*sign ); - gbuf.texCoord2d(s+du, t); - gbuf.vertex3d( qx*r, qy*r, z ); - } - else { - gbuf.normal3d( 0.0, 0.0, znormal*sign ); - gbuf.texCoord2d(s, t); - gbuf.vertex3d( qx*r, qy*r, z ); - gbuf.normal3d( 0.0, 0.0, znormal*sign ); - gbuf.texCoord2d(s+du, t); - gbuf.vertex3d( px*r, py*r, z ); - } - } else { - if (outside) { - gbuf.normal3d( px*sign, py*sign, znormal*sign ); - gbuf.texCoord2d(s, t); - gbuf.vertex3d( px*r, py*r, z ); - gbuf.normal3d( qx*sign, qy*sign, znormal*sign ); - gbuf.texCoord2d(s+du, t); - gbuf.vertex3d( qx*r, qy*r, z ); - } - else { - gbuf.normal3d( qx*sign, qy*sign, znormal*sign ); - gbuf.texCoord2d(s, t); - gbuf.vertex3d( qx*r, qy*r, z ); - gbuf.normal3d( px*sign, py*sign, znormal*sign ); - gbuf.texCoord2d(s+du, t); - gbuf.vertex3d( px*r, py*r, z ); - } - } - } - gbuf.end(); - s += du; - } - return gbuf; - } - - GeomBuffer disk(double r, int xdivisions, boolean outside) - { - double theta, dtheta, sign, sinTheta, cosTheta; - int i; - - /* - * Disk is created by evaluating points along the unit circle. Let - * theta be the angle about the Z axis. Then, for each theta, we - * obtain (cos(theta), sin(theta)) = (x,y) sample points. We create quad - * strips (or fan strips) from these sample points. - * - * Texture coordinates of the disk is gotten from a unit circle - * centered at (0.5, 0.5) in s,t space. Thus, portions of a texture is not - * used. - */ - - if (outside) - sign = 1.0; - else sign = -1.0; + Quadrics(){ } - dtheta = 2.0*Math.PI / xdivisions; - GeomBuffer gbuf = new GeomBuffer(xdivisions*4); - - // gbuf.begin(GeomBuffer.QUAD_STRIP); - gbuf.begin(GeomBuffer.TRIANGLE_FAN); - // the first point to add is the center of the fan - gbuf.normal3d( 0.0, 0.0, 1.0*sign ); - gbuf.texCoord2d(0.5,0.5); - gbuf.vertex3d(0.0, 0.0, 0.0); - if (outside) { - for (i = 0;i <= xdivisions;i++) { - theta = i * dtheta; - // add 90 degrees to theta so lines up with the body - sinTheta = Math.sin(theta + Math.PI/2.0); - cosTheta = Math.cos(theta + Math.PI/2.0); - // First point of quad - gbuf.normal3d( 0.0, 0.0, 1.0*sign ); - // Texture coord is centered at (0.5, 0.5) in s,t space. - gbuf.texCoord2d(0.5+cosTheta*0.5,0.5+sinTheta*0.5); - gbuf.vertex3d( r*cosTheta, r*sinTheta , 0.0); - - } - } - else { - for (i=xdivisions;i>=0;i--) { - theta = i * dtheta; - // add 90 degrees to theta so lines up with the body - sinTheta = Math.sin(theta + Math.PI/2.0); - cosTheta = Math.cos(theta + Math.PI/2.0); - gbuf.normal3d( 0.0, 0.0, 1.0*sign ); - // if not outside, texture coordinates need to be upside down - // to conform with VRML spec -// gbuf.texCoord2d(0.5-cosTheta*0.5, 0.5+sinTheta*0.5); - gbuf.texCoord2d(0.5+cosTheta*0.5, 0.5-sinTheta*0.5); - gbuf.vertex3d( r*cosTheta, r*sinTheta, 0.0 ); - } + // new disk code to remove transforms in the primitive code + GeomBuffer disk(double r, int xdiv, double y, boolean outside, boolean texCoordYUp) { + + double theta, dtheta, sign, sinTheta, cosTheta; + + if (outside) sign = 1.0; + else sign = -1.0; + + dtheta = 2.0*Math.PI / xdiv; + + GeomBuffer gbuf = new GeomBuffer(xdiv+2); + + gbuf.begin(GeomBuffer.TRIANGLE_FAN); + gbuf.normal3d(0.0, 1.0*sign, 0.0); + gbuf.texCoord2d(0.5, 0.5); + gbuf.vertex3d(0.0, y, 0.0); + + // create the disk by evaluating points along the unit circle. + // theta is the angle around the y-axis. Then we obtain + // (cos(theta), sin(theta)) = (x,z) sample points. The y value + // was passed in as a parameter. + // texture coordinates are obtain from the unit circle centered at + // (.5, .5) in s, t space. thus portions of the texture are not used. + + if (!outside) { + for (int i = 0; i <= xdiv; i++) { + theta = i * dtheta; + // add 90 degrees to theta so lines up wtih the body + sinTheta = Math.sin(theta - Math.PI/2.0); + cosTheta = Math.cos(theta - Math.PI/2.0); + gbuf.normal3d(0.0, 1.0*sign, 0.0); + if (texCoordYUp) { + gbuf.texCoord2d(0.5+cosTheta*0.5, 1.0 - (0.5+sinTheta*0.5)); + } + else { + gbuf.texCoord2d(0.5+cosTheta*0.5, 0.5+sinTheta*0.5); + } + gbuf.vertex3d(r*cosTheta, y, r*sinTheta); + } + } else { + for (int i = xdiv; i >= 0; i--) { + theta = i * dtheta; + // add 90 degrees to theta so lines up with the body + sinTheta = Math.sin(theta - Math.PI/2.0); + cosTheta = Math.cos(theta - Math.PI/2.0); + gbuf.normal3d(0.0, 1.0*sign, 0.0); + if (texCoordYUp) { + gbuf.texCoord2d(0.5+cosTheta*0.5, 1.0 - (0.5-sinTheta*0.5)); + } + else { + gbuf.texCoord2d(0.5+cosTheta*0.5, 0.5-sinTheta*0.5); + } + gbuf.vertex3d(cosTheta*r, y, sinTheta*r); + } + } + + gbuf.end(); + return gbuf; } - gbuf.end(); - return gbuf; - } - - // use this to make the top of the cone. It uses a triangle fan so there - // aren't extra triangles - - GeomBuffer coneTop(double coneRadius, double coneHeight, int xdivisions, - int ydivisions, boolean outside) { - - double sign; - double radius = coneRadius/(double)ydivisions; - - double bottom = coneHeight/2.0 - coneHeight/(double)ydivisions; - double top = coneHeight/2.0; - - if (outside) sign = 1.0; - else sign = -1.0; - - // compute the deltas - double dtheta = 2.0 * Math.PI / (double)xdivisions; - double znormal = radius/(top-bottom); - double du = 1.0/(double)xdivisions; - - // initialize geometry buffer - GeomBuffer gbuf = new GeomBuffer(xdivisions + 2); - gbuf.begin(GeomBuffer.TRIANGLE_FAN); - // add the tip, which is the center of the fan - gbuf.normal3d(0.0, 0.0, znormal*sign); - gbuf.texCoord2d(.5, 1); - gbuf.vertex3d(0.0, 0.0, top); - - // go around the circle and add the rest of the fan - double s = 0.0; - double t = 1.0 - 1.0/(double)ydivisions; - double px, py; - if (outside) { - for (int i = 0; i <= xdivisions; i++) { - // we have to start at the back of the sphere, so add 90 degrees - px = Math.cos(i*dtheta + Math.PI/2.0); - py = Math.sin(i*dtheta + Math.PI/2.0); - gbuf.normal3d(px*sign, py*sign, znormal*sign); - gbuf.texCoord2d(s, t); - gbuf.vertex3d(px*radius, py*radius, bottom); - s += du; - } - } - else { - for (int i = xdivisions; i >= 0; i--) { - px = Math.cos(i*dtheta + Math.PI/2.0); - py = Math.sin(i*dtheta + Math.PI/2.0); - gbuf.normal3d(px*sign, py*sign, znormal*sign); - gbuf.texCoord2d(s, t); - gbuf.vertex3d(px*radius, py*radius, bottom); - s += du; - } - } - gbuf.end(); - return gbuf; - } - - // use this to make the body of the cone. similar to cylinder, only allows - // you to leave off the top. - - GeomBuffer coneBody(double coneRadius, double height, - int xdivisions, int ydivisions, - boolean outside) - { - double r, sign; - - double bottom = -height/2.0; - double topRadius = coneRadius/(double)ydivisions; - - /* - * The cone body is created by extruding the unit circle along the Z+ - * axis. The number of layers is controlled by ydivisions (which is - * actually zdivisions). For each consecutive sample points along the - * unit circle, we also sample along the height of the cone. Quads - * are created along the Z direction. When the unit circle at the base is - * completed, we also obtain the layers of quads along the height of the - * cylinder. - * - * Texture coordinates are created in a straight forward cylindrical - * mapping of the texture map. The texture is wrapped from the back of - * the cylinder. - */ - - if (outside) - sign = 1.0; - else - sign = -1.0; - //Compute the deltas - double dtheta = 2.0*Math.PI / xdivisions; - double dr = -coneRadius / ydivisions; - double dz = height / ydivisions; - double znormal = coneRadius / height; - double du = 1.0 / xdivisions; - double dv = 1.0 / ydivisions; - - //Initialize geometry buffer. - GeomBuffer gbuf = new GeomBuffer(xdivisions*ydivisions*4); - - double s = 0.0, t = 0.0; - for (int i=0;i<xdivisions;i++) { - double px, py, qx, qy, z; - // (px,py) and (qx,qy) are consecutive sample points along the - // unit circle. We will create quads along the Z+ direction. - // we have to start at the back of the sphere, so add 90 degrees - px = Math.cos(i*dtheta + Math.PI/2.0); - py = Math.sin(i*dtheta + Math.PI/2.0); - qx = Math.cos((i+1)*dtheta + Math.PI/2.0); - qy = Math.sin((i+1)*dtheta + Math.PI/2.0); - // Initialize z,r,t - //z = -1.0*height/2.0; - r = coneRadius; t = 0.0; - z = bottom; - - gbuf.begin( GeomBuffer.QUAD_STRIP ); - // For each consecutive two unit circle points, - // we obtain the layers of quads along the Z direction. Number of - // layers depends on ydivisions. - for (int j=0; j<=ydivisions-1; j++,z += dz,r += dr,t += dv){ - if (outside) { - gbuf.normal3d( px*sign, py*sign, znormal*sign ); - gbuf.texCoord2d(s, t); - gbuf.vertex3d( px*r, py*r, z ); - gbuf.normal3d( qx*sign, qy*sign, znormal*sign ); - gbuf.texCoord2d(s+du, t); - gbuf.vertex3d( qx*r, qy*r, z ); - } - else { - gbuf.normal3d( qx*sign, qy*sign, znormal*sign ); - gbuf.texCoord2d(s, t); - gbuf.vertex3d( qx*r, qy*r, z ); - gbuf.normal3d( px*sign, py*sign, znormal*sign ); - gbuf.texCoord2d(s+du, t); - gbuf.vertex3d( px*r, py*r, z ); - } - } - gbuf.end(); - s += du; - } - return gbuf; - } - - // new disk code to remove transforms in the primitive code - GeomBuffer disk(double r, int xdiv, double y, boolean outside) { - - double theta, dtheta, sign, sinTheta, cosTheta; - - if (outside) sign = 1.0; - else sign = -1.0; - - dtheta = 2.0*Math.PI / xdiv; - - GeomBuffer gbuf = new GeomBuffer(xdiv+2); - - gbuf.begin(GeomBuffer.TRIANGLE_FAN); - gbuf.normal3d(0.0, 1.0*sign, 0.0); - gbuf.texCoord2d(0.5, 0.5); - gbuf.vertex3d(0.0, y, 0.0); - - // create the disk by evaluating points along the unit circle. - // theta is the angle around the y-axis. Then we obtain - // (cos(theta), sin(theta)) = (x,z) sample points. The y value - // was passed in as a parameter. - // texture coordinates are obtain from the unit circle centered at - // (.5, .5) in s, t space. thus portions of the texture are not used. - - if (!outside) { - for (int i = 0; i <= xdiv; i++) { - theta = i * dtheta; - // add 90 degrees to theta so lines up wtih the body - sinTheta = Math.sin(theta - Math.PI/2.0); - cosTheta = Math.cos(theta - Math.PI/2.0); - gbuf.normal3d(0.0, 1.0*sign, 0.0); - gbuf.texCoord2d(0.5+cosTheta*0.5, 0.5+sinTheta*0.5); - gbuf.vertex3d(r*cosTheta, y, r*sinTheta); - } - } - else { - for (int i = xdiv; i >= 0; i--) { - theta = i * dtheta; - // add 90 degrees to theta so lines up with the body - sinTheta = Math.sin(theta - Math.PI/2.0); - cosTheta = Math.cos(theta - Math.PI/2.0); - gbuf.normal3d(0.0, 1.0*sign, 0.0); - gbuf.texCoord2d(0.5+cosTheta*0.5, 0.5-sinTheta*0.5); - gbuf.vertex3d(cosTheta*r, y, sinTheta*r); - } - } - - gbuf.end(); - return gbuf; - } - - // new cylinder to remove transforms in the cylinder code and to optimize // by using triangle strip GeomBuffer cylinder(double height, double radius, - int xdiv, int ydiv, boolean outside) { - - double sign; - - if (outside) sign = 1.0; - else sign = -1.0; - - // compute the deltas - double dtheta = 2.0*Math.PI / (double)xdiv; - double dy = height / (double)ydiv; - double du = 1.0/(double)xdiv; - double dv = 1.0/(double)ydiv; - - GeomBuffer gbuf = new GeomBuffer(ydiv*2*(xdiv+1)); - - double s = 0.0, t = 0.0; - double px, pz, qx, qz; - double py = -height/2.0; - double qy; - -// int c; -// if (outside) c = ydiv*2*(xdiv+1) - 1; -// else c = 0; - - gbuf.begin(GeomBuffer.QUAD_STRIP); - - for (int i = 0; i < ydiv; i++) { - qy = py+dy; - if (outside) { - px = Math.cos(xdiv*dtheta - Math.PI/2.0); - pz = Math.sin(xdiv*dtheta - Math.PI/2.0); - qx = Math.cos((xdiv-1)*dtheta - Math.PI/2.0); - qz = Math.sin((xdiv-1)*dtheta - Math.PI/2.0); - - // vert 2 - gbuf.normal3d(px*sign, 0.0, pz*sign); - gbuf.texCoord2d(s, t+dv); - gbuf.vertex3d(px*radius, qy, pz*radius); - - // vert 1 - gbuf.normal3d(px*sign, 0.0, pz*sign); - gbuf.texCoord2d(s, t); - gbuf.vertex3d(px*radius, py, pz*radius); - - // vert 4 - gbuf.normal3d(qx*sign, 0.0, qz*sign); - gbuf.texCoord2d(s+du, t+dv); - gbuf.vertex3d(qx*radius, qy, qz*radius); - - // vert 3 - gbuf.normal3d(qx*sign, 0.0, qz*sign); - gbuf.texCoord2d(s+du, t); - gbuf.vertex3d(qx*radius, py, qz*radius); - - s += (du*2.0); - - for (int j = xdiv-2; j >=0; j--) { - px = Math.cos(j*dtheta - Math.PI/2.0); - pz = Math.sin(j*dtheta - Math.PI/2.0); - - // vert 6 - gbuf.normal3d(px*sign, 0.0, pz*sign); - gbuf.texCoord2d(s, t+dv); - gbuf.vertex3d(px*radius, qy, pz*radius); - - // vert 5 - gbuf.normal3d(px*sign, 0.0, pz*sign); - gbuf.texCoord2d(s, t); - gbuf.vertex3d(px*radius, py, pz*radius); - - s += du; - } - - } - else { + int xdiv, int ydiv, boolean outside, boolean texCoordYUp) { + + double sign; + + if (outside) sign = 1.0; + else sign = -1.0; + + // compute the deltas + double dtheta = 2.0*Math.PI / (double)xdiv; + double dy = height / (double)ydiv; + double du = 1.0/(double)xdiv; + double dv = 1.0/(double)ydiv; + + GeomBuffer gbuf = new GeomBuffer(ydiv*2*(xdiv+1)); + + double s = 0.0, t = 0.0; + double px, pz, qx, qz; + double py = -height/2.0; + double qy; + + gbuf.begin(GeomBuffer.QUAD_STRIP); + + for (int i = 0; i < ydiv; i++) { + qy = py+dy; + if (outside) { + px = Math.cos(xdiv*dtheta - Math.PI/2.0); + pz = Math.sin(xdiv*dtheta - Math.PI/2.0); + qx = Math.cos((xdiv-1)*dtheta - Math.PI/2.0); + qz = Math.sin((xdiv-1)*dtheta - Math.PI/2.0); + + // vert 2 + gbuf.normal3d(px*sign, 0.0, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t + dv); + } + else { + gbuf.texCoord2d(s, t+dv); + } + gbuf.vertex3d(px*radius, qy, pz*radius); + + // vert 1 + gbuf.normal3d(px*sign, 0.0, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t); + } else { + gbuf.texCoord2d(s, t); + } + gbuf.vertex3d(px*radius, py, pz*radius); + + // vert 4 + gbuf.normal3d(qx*sign, 0.0, qz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s+du, 1.0 - t + dv); + } + else { + gbuf.texCoord2d(s+du, t+dv); + } + gbuf.vertex3d(qx*radius, qy, qz*radius); + + // vert 3 + gbuf.normal3d(qx*sign, 0.0, qz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s+du, 1.0 - t); + } + else { + gbuf.texCoord2d(s+du, t); + } + gbuf.vertex3d(qx*radius, py, qz*radius); + + s += (du*2.0); + + for (int j = xdiv-2; j >=0; j--) { + px = Math.cos(j*dtheta - Math.PI/2.0); + pz = Math.sin(j*dtheta - Math.PI/2.0); + + // vert 6 + gbuf.normal3d(px*sign, 0.0, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t + dv); + } + else { + gbuf.texCoord2d(s, t+dv); + } + gbuf.vertex3d(px*radius, qy, pz*radius); + + // vert 5 + gbuf.normal3d(px*sign, 0.0, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t); + } + else { + gbuf.texCoord2d(s, t); + } + gbuf.vertex3d(px*radius, py, pz*radius); + + s += du; + } + + } else { // c = 0; - px = Math.cos(-Math.PI/2.0); - pz = Math.sin(-Math.PI/2.0); - qx = Math.cos(dtheta - Math.PI/2.0); - qz = Math.sin(dtheta - Math.PI/2.0); - - gbuf.normal3d(px*sign, 0.0, pz*sign); - gbuf.texCoord2d(s, t+dv); - gbuf.vertex3d(px*radius, qy, pz*radius); - - // vert 1 - gbuf.normal3d(px*sign, 0.0, pz*sign); - gbuf.texCoord2d(s, t); - gbuf.vertex3d(px*radius, py, pz*radius); - - gbuf.normal3d(qx*sign, 0.0, qz*sign); - gbuf.texCoord2d(s+du, t+dv); - gbuf.vertex3d(qx*radius, qy, qz*radius); - - gbuf.normal3d(qx*sign, 0.0, qz*sign); - gbuf.texCoord2d(s+du, t); - gbuf.vertex3d(qx*radius, py, qz*radius); - - s += (du*2.0); - - for (int j = 2; j <= xdiv; j++) { - px = Math.cos(j*dtheta - Math.PI/2.0); - pz = Math.sin(j*dtheta - Math.PI/2.0); - - gbuf.normal3d(px*sign, 0.0, pz*sign); - gbuf.texCoord2d(s, t+dv); - gbuf.vertex3d(px*radius, qy, pz*radius); - - gbuf.normal3d(px*sign, 0.0, pz*sign); - gbuf.texCoord2d(s, t); - gbuf.vertex3d(px*radius, py, pz*radius); - - s += du; - } - - } - s = 0.0; - t += dv; - py += dy; - } - - gbuf.end(); - - return gbuf; + px = Math.cos(-Math.PI/2.0); + pz = Math.sin(-Math.PI/2.0); + qx = Math.cos(dtheta - Math.PI/2.0); + qz = Math.sin(dtheta - Math.PI/2.0); + + gbuf.normal3d(px*sign, 0.0, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t + dv); + } + else { + gbuf.texCoord2d(s, t+dv); + } + gbuf.vertex3d(px*radius, qy, pz*radius); + + // vert 1 + gbuf.normal3d(px*sign, 0.0, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t); + } + else { + gbuf.texCoord2d(s, t); + } + gbuf.vertex3d(px*radius, py, pz*radius); + + gbuf.normal3d(qx*sign, 0.0, qz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s+du, 1.0 - t + dv); + } + else { + gbuf.texCoord2d(s+du, t+dv); + } + gbuf.vertex3d(qx*radius, qy, qz*radius); + + gbuf.normal3d(qx*sign, 0.0, qz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s+du, 1.0 - t); + } + else { + gbuf.texCoord2d(s+du, t); + } + gbuf.vertex3d(qx*radius, py, qz*radius); + + s += (du*2.0); + + for (int j = 2; j <= xdiv; j++) { + px = Math.cos(j*dtheta - Math.PI/2.0); + pz = Math.sin(j*dtheta - Math.PI/2.0); + + gbuf.normal3d(px*sign, 0.0, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t + dv); + } + else { + gbuf.texCoord2d(s, t+dv); + } + gbuf.vertex3d(px*radius, qy, pz*radius); + + gbuf.normal3d(px*sign, 0.0, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t); + } + else { + gbuf.texCoord2d(s, t); + } + gbuf.vertex3d(px*radius, py, pz*radius); + + s += du; + } + + } + s = 0.0; + t += dv; + py += dy; + } + + gbuf.end(); + + return gbuf; } - + // new coneBody method to remove transform in the Cone primitive // and to optimize by using triangle strip GeomBuffer coneBody(double bottom, double top, double bottomR, double topR, - int xdiv, int ydiv, double dv, boolean outside) { - - double r, sign; - - if (outside) sign = 1.0; - else sign = -1.0; - - // compute the deltas - double dtheta = 2.0*Math.PI/(double)xdiv; - double dr = (topR-bottomR)/(double)ydiv; - double height = top-bottom; - double dy = height/(double)ydiv; - double ynormal = (bottomR-topR)/height; - double du = 1.0/(double)xdiv; + int xdiv, int ydiv, double dv, boolean outside, boolean texCoordYUp) { + + double r, sign; + + if (outside) sign = 1.0; + else sign = -1.0; + + // compute the deltas + double dtheta = 2.0*Math.PI/(double)xdiv; + double dr = (topR-bottomR)/(double)ydiv; + double height = top-bottom; + double dy = height/(double)ydiv; + double ynormal = (bottomR-topR)/height; + double du = 1.0/(double)xdiv; // double dv = 1.0/(double)(ydiv+1); - - GeomBuffer gbuf = new GeomBuffer(ydiv*2*(xdiv+1)); - - double s = 0.0, t = 0.0; - double px, pz, qx, qz; - double py = bottom; - double qy; - r = bottomR; - - gbuf.begin(GeomBuffer.QUAD_STRIP); - - for (int i = 0; i < ydiv; i++) { - qy = py+dy; - if (outside) { - px = Math.cos(xdiv*dtheta - Math.PI/2.0); - pz = Math.sin(xdiv*dtheta - Math.PI/2.0); - qx = Math.cos((xdiv-1)*dtheta - Math.PI/2.0); - qz = Math.sin((xdiv-1)*dtheta - Math.PI/2.0); - - // vert2 - gbuf.normal3d(px*sign, ynormal*sign, pz*sign); - gbuf.texCoord2d(s, t+dv); - gbuf.vertex3d(px*(r+dr), qy, pz*(r+dr)); - - // vert1 - gbuf.normal3d(px*sign, ynormal*sign, pz*sign); - gbuf.texCoord2d(s, t); - gbuf.vertex3d(px*r, py, pz*r); - - // vert4 - gbuf.normal3d(qx*sign, ynormal*sign, qz*sign); - gbuf.texCoord2d(s+du, t+dv); - gbuf.vertex3d(qx*(r+dr), qy, qz*(r+dr)); - - // vert3 - gbuf.normal3d(qx*sign, ynormal*sign, qz*sign); - gbuf.texCoord2d(s+du, t); - gbuf.vertex3d(qx*r, py, qz*r); - - s += (du*2.0); - - for (int j = xdiv-2; j >= 0; j--) { - px = Math.cos(j*dtheta - Math.PI/2.0); - pz = Math.sin(j*dtheta - Math.PI/2.0); - - // vert 6 - gbuf.normal3d(px*sign, ynormal*sign, pz*sign); - gbuf.texCoord2d(s, t+dv); - gbuf.vertex3d(px*(r+dr), qy, pz*(r+dr)); - - // vert 5 - gbuf.normal3d(px*sign, ynormal*sign, pz*sign); - gbuf.texCoord2d(s, t); - gbuf.vertex3d(px*r, py, pz*r); - - s += du; - } - } - else { - px = Math.cos(-Math.PI/2.0); - pz = Math.sin(-Math.PI/2.0); - qx = Math.cos(dtheta - Math.PI/2.0); - qz = Math.sin(dtheta - Math.PI/2.0); - - // vert1 - gbuf.normal3d(px*sign, ynormal*sign, pz*sign); - gbuf.texCoord2d(s, t+dv); - gbuf.vertex3d(px*(r+dr), qy, pz*(r+dr)); - - gbuf.normal3d(px*sign, ynormal*sign, pz*sign); - gbuf.texCoord2d(s, t); - gbuf.vertex3d(px*r, py, pz*r); - - gbuf.normal3d(qx*sign, ynormal*sign, qz*sign); - gbuf.texCoord2d(s+du, t+dv); - gbuf.vertex3d(qx*(r+dr), qy, qz*(r+dr)); - - gbuf.normal3d(qx*sign, ynormal*sign, qz*sign); - gbuf.texCoord2d(s+du, t); - gbuf.vertex3d(qx*r, py, qz*r); - - s += (du*2.0); - - for (int j = 2; j <= xdiv; j++) { - px = Math.cos(j*dtheta - Math.PI/2.0); - pz = Math.sin(j*dtheta - Math.PI/2.0); - - gbuf.normal3d(px*sign, ynormal*sign, pz*sign); - gbuf.texCoord2d(s, t+dv); - gbuf.vertex3d(px*(r+dr), qy, pz*(r+dr)); - - gbuf.normal3d(px*sign, ynormal*sign, pz*sign); - gbuf.texCoord2d(s, t); - gbuf.vertex3d(px*r, py, pz*r); - - s += du; - } - } - s = 0.0; - t += dv; - py += dy; - r += dr; - } - gbuf.end(); - - return gbuf; + + GeomBuffer gbuf = new GeomBuffer(ydiv*2*(xdiv+1)); + + double s = 0.0, t = 0.0; + double px, pz, qx, qz; + double py = bottom; + double qy; + r = bottomR; + + gbuf.begin(GeomBuffer.QUAD_STRIP); + + for (int i = 0; i < ydiv; i++) { + qy = py+dy; + if (outside) { + px = Math.cos(xdiv*dtheta - Math.PI/2.0); + pz = Math.sin(xdiv*dtheta - Math.PI/2.0); + qx = Math.cos((xdiv-1)*dtheta - Math.PI/2.0); + qz = Math.sin((xdiv-1)*dtheta - Math.PI/2.0); + + // vert2 + gbuf.normal3d(px*sign, ynormal*sign, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t + dv); + } + else { + gbuf.texCoord2d(s, t+dv); + } + gbuf.vertex3d(px*(r+dr), qy, pz*(r+dr)); + + // vert1 + gbuf.normal3d(px*sign, ynormal*sign, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t); + } + else { + gbuf.texCoord2d(s, t); + } + gbuf.vertex3d(px*r, py, pz*r); + + // vert4 + gbuf.normal3d(qx*sign, ynormal*sign, qz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s+du, 1.0 - t + dv); + } + else { + gbuf.texCoord2d(s+du, t+dv); + } + gbuf.vertex3d(qx*(r+dr), qy, qz*(r+dr)); + + // vert3 + gbuf.normal3d(qx*sign, ynormal*sign, qz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s+du, 1.0 - t); + } + else { + gbuf.texCoord2d(s+du, t); + } + gbuf.vertex3d(qx*r, py, qz*r); + + s += (du*2.0); + + for (int j = xdiv-2; j >= 0; j--) { + px = Math.cos(j*dtheta - Math.PI/2.0); + pz = Math.sin(j*dtheta - Math.PI/2.0); + + // vert 6 + gbuf.normal3d(px*sign, ynormal*sign, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t + dv); + } else { + gbuf.texCoord2d(s, t+dv); + } + gbuf.vertex3d(px*(r+dr), qy, pz*(r+dr)); + + // vert 5 + gbuf.normal3d(px*sign, ynormal*sign, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t); + } + else { + gbuf.texCoord2d(s, t); + } + gbuf.vertex3d(px*r, py, pz*r); + + s += du; + } + } else { + px = Math.cos(-Math.PI/2.0); + pz = Math.sin(-Math.PI/2.0); + qx = Math.cos(dtheta - Math.PI/2.0); + qz = Math.sin(dtheta - Math.PI/2.0); + + // vert1 + gbuf.normal3d(px*sign, ynormal*sign, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t + dv); + } + else { + gbuf.texCoord2d(s, t+dv); + } + gbuf.vertex3d(px*(r+dr), qy, pz*(r+dr)); + + gbuf.normal3d(px*sign, ynormal*sign, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t); + } + else { + gbuf.texCoord2d(s, t); + } + gbuf.vertex3d(px*r, py, pz*r); + + gbuf.normal3d(qx*sign, ynormal*sign, qz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s+du, 1.0 - t + dv); + } + else { + gbuf.texCoord2d(s+du, t+dv); + } + gbuf.vertex3d(qx*(r+dr), qy, qz*(r+dr)); + + gbuf.normal3d(qx*sign, ynormal*sign, qz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s+du, 1.0 - t); + } + else { + gbuf.texCoord2d(s+du, t); + } + gbuf.vertex3d(qx*r, py, qz*r); + + s += (du*2.0); + + for (int j = 2; j <= xdiv; j++) { + px = Math.cos(j*dtheta - Math.PI/2.0); + pz = Math.sin(j*dtheta - Math.PI/2.0); + + gbuf.normal3d(px*sign, ynormal*sign, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t + dv); + } + else { + gbuf.texCoord2d(s, t+dv); + } + gbuf.vertex3d(px*(r+dr), qy, pz*(r+dr)); + + gbuf.normal3d(px*sign, ynormal*sign, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t); + } + else { + gbuf.texCoord2d(s, t); + } + gbuf.vertex3d(px*r, py, pz*r); + + s += du; + } + } + s = 0.0; + t += dv; + py += dy; + r += dr; + } + gbuf.end(); + + return gbuf; } - + // new coneTop method to remove transforms in the cone code GeomBuffer coneTop(double bottom, double radius, double height, - int xdiv,double t, boolean outside) { - - double sign; - - if (outside) sign = 1.0; - else sign = -1.0; - - // compute the deltas - double dtheta = 2.0*Math.PI/(double)xdiv; - double ynormal = radius/height; - double du = 1.0/(double)xdiv; - double top = bottom + height; - - // initialize the geometry buffer - GeomBuffer gbuf = new GeomBuffer(xdiv + 2); - gbuf.begin(GeomBuffer.TRIANGLE_FAN); - - // add the tip, which is the center of the fan - gbuf.normal3d(0.0, ynormal*sign, 0.0); - gbuf.texCoord2d(.5, 1.0); - gbuf.vertex3d(0.0, top, 0.0); - - // go around the circle and add the rest of the fan - double s = 0.0; - double px, pz; - if (outside) { -// for (int i = 0; i <= xdiv; i++) { - for (int i = xdiv; i >= 0; i--) { - px = Math.cos(i*dtheta - Math.PI/2.0); - pz = Math.sin(i*dtheta - Math.PI/2.0); - gbuf.normal3d(px*sign, ynormal*sign, pz*sign); - gbuf.texCoord2d(s, t); - gbuf.vertex3d(px*radius, bottom, pz*radius); - - s += du; - } - } - else { -// for (int i = xdiv; i >= 0; i--) { - for (int i = 0; i <= xdiv; i++) { - px = Math.cos(i*dtheta - Math.PI/2.0); - pz = Math.sin(i*dtheta - Math.PI/2.0); - gbuf.normal3d(px*sign, ynormal*sign, pz*sign); - gbuf.texCoord2d(s, t); - gbuf.vertex3d(px*radius, bottom, pz*radius); - s += du; - } - } - gbuf.end(); - return gbuf; + int xdiv,double t, boolean outside, boolean texCoordYUp) { + + double sign; + + if (outside) sign = 1.0; + else sign = -1.0; + + // compute the deltas + double dtheta = 2.0*Math.PI/(double)xdiv; + double ynormal = radius/height; + double du = 1.0/(double)xdiv; + double top = bottom + height; + + // initialize the geometry buffer + GeomBuffer gbuf = new GeomBuffer(xdiv + 2); + gbuf.begin(GeomBuffer.TRIANGLE_FAN); + + // add the tip, which is the center of the fan + gbuf.normal3d(0.0, ynormal*sign, 0.0); + if (texCoordYUp) { + gbuf.texCoord2d(.5, 0.0); + } + else { + gbuf.texCoord2d(.5, 1.0); + } + gbuf.vertex3d(0.0, top, 0.0); + + // go around the circle and add the rest of the fan + double s = 0.0; + double px, pz; + if (outside) { + for (int i = xdiv; i >= 0; i--) { + px = Math.cos(i*dtheta - Math.PI/2.0); + pz = Math.sin(i*dtheta - Math.PI/2.0); + gbuf.normal3d(px*sign, ynormal*sign, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t); + } else { + gbuf.texCoord2d(s, t); + } + gbuf.vertex3d(px*radius, bottom, pz*radius); + + s += du; + } + } else { + for (int i = 0; i <= xdiv; i++) { + px = Math.cos(i*dtheta - Math.PI/2.0); + pz = Math.sin(i*dtheta - Math.PI/2.0); + gbuf.normal3d(px*sign, ynormal*sign, pz*sign); + if (texCoordYUp) { + gbuf.texCoord2d(s, 1.0 - t); + } else { + gbuf.texCoord2d(s, t); + } + gbuf.vertex3d(px*radius, bottom, pz*radius); + s += du; + } + } + gbuf.end(); + return gbuf; } } diff --git a/src/classes/share/com/sun/j3d/utils/geometry/Sphere.java b/src/classes/share/com/sun/j3d/utils/geometry/Sphere.java index 90dbab8..95327e4 100644 --- a/src/classes/share/com/sun/j3d/utils/geometry/Sphere.java +++ b/src/classes/share/com/sun/j3d/utils/geometry/Sphere.java @@ -206,14 +206,15 @@ public class Sphere extends Primitive { */ flags = primflags; - + boolean texCoordYUp = (flags & GENERATE_TEXTURE_COORDS_YUP) != 0; + //Depending on whether normal inward bit is set. if ((flags & GENERATE_NORMALS_INWARD) != 0) { sign = -1; } else { sign = 1; } - + if (divisions < 4) { nstep = 1; n = 4; @@ -244,8 +245,8 @@ public class Sphere extends Primitive { GeomBuffer gbuf = new GeomBuffer(8*nstep*(nstep+2)); for (int i=0; i < 4; i++) { - buildQuadrant(gbuf, i*Math.PI/2, (i+1)*Math.PI/2, sign, nstep, n, true); - buildQuadrant(gbuf, i*Math.PI/2, (i+1)*Math.PI/2, sign, nstep, n, false); + buildQuadrant(gbuf, i*Math.PI/2, (i+1)*Math.PI/2, sign, texCoordYUp, nstep, n, true); + buildQuadrant(gbuf, i*Math.PI/2, (i+1)*Math.PI/2, sign, texCoordYUp, nstep, n, false); } shape = new Shape3D(gbuf.getGeom(flags)); @@ -354,7 +355,7 @@ public class Sphere extends Primitive { } void buildQuadrant(GeomBuffer gbuf, double startDelta, double endDelta, - int sign, int nstep, int n, boolean upperSphere) + int sign, boolean texCoordYUp, int nstep, int n, boolean upperSphere) { double ds, dt, theta, delta; @@ -415,17 +416,32 @@ public class Sphere extends Primitive { texCoord = gbuf.tcoords[index]; // connect with correspondent vertices from previous row gbuf.normal3d(norm.x, norm.y, norm.z); - gbuf.texCoord2d(texCoord.x, texCoord.y); + if(texCoordYUp) { + gbuf.texCoord2d(texCoord.x, 1.0 - texCoord.y); + } + else { + gbuf.texCoord2d(texCoord.x, texCoord.y); + } gbuf.vertex3d(pt.x, pt.y, pt.z); } else { gbuf.normal3d(0, sign*starth, 0); - if (sign > 0) { - gbuf.texCoord2d(0.75 - (startDelta + endDelta)/(4*Math.PI), - 1.0 - (theta - dt)/Math.PI); - } else { - gbuf.texCoord2d(0.75 - (startDelta + endDelta)/(4*Math.PI), - (theta - dt)/Math.PI); - } + if (sign > 0) { + if (texCoordYUp) { + gbuf.texCoord2d(0.75 - (startDelta + endDelta)/(4*Math.PI), + (theta - dt)/Math.PI); + } else { + gbuf.texCoord2d(0.75 - (startDelta + endDelta)/(4*Math.PI), + 1.0 - (theta - dt)/Math.PI); + } + } else { + if (texCoordYUp) { + gbuf.texCoord2d(0.75 - (startDelta + endDelta)/(4*Math.PI), + 1.0 - (theta - dt)/Math.PI); + } else { + gbuf.texCoord2d(0.75 - (startDelta + endDelta)/(4*Math.PI), + (theta - dt)/Math.PI); + } + } gbuf.vertex3d( 0, starth*radius, 0); } @@ -439,7 +455,12 @@ public class Sphere extends Primitive { vx = r*Math.cos(delta); vz = r*Math.sin(delta); gbuf.normal3d( vx*sign, h*sign, vz*sign ); - gbuf.texCoord2d(0.75 - delta/(2*Math.PI), t); + if(texCoordYUp) { + gbuf.texCoord2d(0.75 - delta/(2*Math.PI), 1.0 - t); + } + else { + gbuf.texCoord2d(0.75 - delta/(2*Math.PI), t); + } gbuf.vertex3d( vx*radius, h*radius, vz*radius); } else { delta = endDelta; @@ -451,7 +472,11 @@ public class Sphere extends Primitive { gbuf.normal3d( vx*sign, h*sign, vz*sign ); // Convert texture coordinate back to one // set in previous version - gbuf.texCoord2d(0.75 - delta/(2*Math.PI), t); + if(texCoordYUp) { + gbuf.texCoord2d(0.75 - delta/(2*Math.PI), 1.0 - t); + } else { + gbuf.texCoord2d(0.75 - delta/(2*Math.PI), t); + } gbuf.vertex3d( vx*radius, h*radius, vz*radius ); if (i > 1) { // get previous vertex from buffer @@ -460,17 +485,31 @@ public class Sphere extends Primitive { norm = gbuf.normals[index]; texCoord = gbuf.tcoords[index]; gbuf.normal3d(norm.x, norm.y, norm.z); - gbuf.texCoord2d(texCoord.x, texCoord.y); + if(texCoordYUp) { + gbuf.texCoord2d(texCoord.x, 1.0 - texCoord.y); + } else { + gbuf.texCoord2d(texCoord.x, texCoord.y); + } gbuf.vertex3d(pt.x, pt.y, pt.z); } else { gbuf.normal3d(0, sign*starth, 0); if (sign > 0) { - gbuf.texCoord2d(0.75 - (startDelta + endDelta)/(4*Math.PI), - 1.0 - (theta - dt)/Math.PI); - } else { - gbuf.texCoord2d(0.75 - (startDelta + endDelta)/(4*Math.PI), - (theta - dt)/Math.PI); - } + if (texCoordYUp) { + gbuf.texCoord2d(0.75 - (startDelta + endDelta)/(4*Math.PI), + (theta - dt)/Math.PI); + } else { + gbuf.texCoord2d(0.75 - (startDelta + endDelta)/(4*Math.PI), + 1.0 - (theta - dt)/Math.PI); + } + } else { + if (texCoordYUp) { + gbuf.texCoord2d(0.75 - (startDelta + endDelta)/(4*Math.PI), + 1.0 - (theta - dt)/Math.PI); + } else { + gbuf.texCoord2d(0.75 - (startDelta + endDelta)/(4*Math.PI), + (theta - dt)/Math.PI); + } + } gbuf.vertex3d( 0, starth*radius, 0); } @@ -481,11 +520,15 @@ public class Sphere extends Primitive { // for numerical accuracy we don't use delta // compute from above. delta = startDelta; - vx = r*Math.cos(delta); - vz = r*Math.sin(delta); - gbuf.normal3d( vx*sign, h*sign, vz*sign ); - gbuf.texCoord2d(0.75 - delta/(2*Math.PI), t); - gbuf.vertex3d( vx*radius, h*radius, vz*radius ); + vx = r*Math.cos(delta); + vz = r*Math.sin(delta); + gbuf.normal3d( vx*sign, h*sign, vz*sign ); + if(texCoordYUp) { + gbuf.texCoord2d(0.75 - delta/(2*Math.PI), 1.0 - t); + } else { + gbuf.texCoord2d(0.75 - delta/(2*Math.PI), t); + } + gbuf.vertex3d( vx*radius, h*radius, vz*radius ); } |