齿轮试验 : 齿轮 « 三维图形动画 « Java

En
Java
1. 图形用户界面
2. 三维图形动画
3. 高级图形
4. 蚂蚁编译
5. Apache类库
6. 统计图
7. 
8. 集合数据结构
9. 数据类型
10. 数据库JDBC
11. 设计模式
12. 开发相关类
13. EJB3
14. 电子邮件
15. 事件
16. 文件输入输出
17. 游戏
18. 泛型
19. GWT
20. Hibernate
21. 本地化
22. J2EE平台
23. 基于J2ME
24. JDK-6
25. JNDI的LDAP
26. JPA
27. JSP技术
28. JSTL
29. 语言基础知识
30. 网络协议
31. PDF格式RTF格式
32. 映射
33. 常规表达式
34. 脚本
35. 安全
36. Servlets
37. Spring
38. Swing组件
39. 图形用户界面
40. SWT-JFace-Eclipse
41. 线程
42. 应用程序
43. Velocity
44. Web服务SOA
45. 可扩展标记语言
Java 教程
Java » 三维图形动画 » 齿轮屏幕截图 
齿轮试验
齿轮试验

/*
 * @(#)GearTest.java 1.17 02/10/21 13:40:16
 
 * Copyright (c) 1996-2002 Sun Microsystems, Inc. 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. - Redistribution 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 Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
 * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
 * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
 * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
 * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
 * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGES.
 
 * You acknowledge that Software is not designed,licensed or intended for use in
 * the design, construction, operation or maintenance of any nuclear facility.
 */

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.GraphicsConfiguration;

import javax.media.j3d.Alpha;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.Background;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.Material;
import javax.media.j3d.QuadArray;
import javax.media.j3d.RotationInterpolator;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.TriangleFanArray;
import javax.media.j3d.TriangleStripArray;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;

import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.behaviors.vp.OrbitBehavior;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.universe.ViewingPlatform;

public class GearTest extends Applet {

  static final int defaultToothCount = 24;

  private int toothCount;

  private SimpleUniverse u = null;

  public BranchGroup createSceneGraph(int toothCount) {
    // Create the root of the branch graph
    BranchGroup objRoot = new BranchGroup();

    // Create a Transformgroup to scale all objects so they
    // appear in the scene.
    TransformGroup objScale = new TransformGroup();
    Transform3D t3d = new Transform3D();
    t3d.setScale(0.4);
    objScale.setTransform(t3d);
    objRoot.addChild(objScale);

    // Create a bounds for the background and lights
    BoundingSphere bounds = new BoundingSphere(new Point3d(0.00.00.0),
        100.0);

    // Set up the background
    Color3f bgColor = new Color3f(0.05f0.05f0.2f);
    Background bgNode = new Background(bgColor);
    bgNode.setApplicationBounds(bounds);
    objScale.addChild(bgNode);

    // Set up the global lights
    Color3f light1Color = new Color3f(1.0f1.0f0.9f);
    Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
    Color3f light2Color = new Color3f(0.3f0.3f0.4f);
    Vector3f light2Direction = new Vector3f(-6.0f, -2.0f, -1.0f);
    Color3f ambientColor = new Color3f(0.1f0.1f0.1f);

    AmbientLight ambientLightNode = new AmbientLight(ambientColor);
    ambientLightNode.setInfluencingBounds(bounds);
    objScale.addChild(ambientLightNode);

    DirectionalLight light1 = new DirectionalLight(light1Color,
        light1Direction);
    light1.setInfluencingBounds(bounds);
    objScale.addChild(light1);

    DirectionalLight light2 = new DirectionalLight(light2Color,
        light2Direction);
    light2.setInfluencingBounds(bounds);
    objScale.addChild(light2);

    // Create the transform group node and initialize it to the
    // identity. Enable the TRANSFORM_WRITE capability so that
    // our behavior code can modify it at runtime. Add it to the
    // root of the subgraph.
    TransformGroup objTrans = new TransformGroup();
    objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    objScale.addChild(objTrans);

    // Create an Appearance.
    Appearance look = new Appearance();
    Color3f objColor = new Color3f(0.5f0.5f0.6f);
    Color3f black = new Color3f(0.0f0.0f0.0f);
    Color3f white = new Color3f(1.0f1.0f1.0f);
    look
        .setMaterial(new Material(objColor, black, objColor, white,
            100.0f));

    // Create a gear, add it to the scene graph.
    //  SpurGear gear = new SpurGear(toothCount, 1.0f, 0.2f,
    SpurGear gear = new SpurGearThinBody(toothCount, 1.0f0.2f0.05f,
        0.05f0.3f0.28f, look);
    objTrans.addChild(gear);

    // Create a new Behavior object that will rotate the object and
    // add it into the scene graph.
    Transform3D yAxis = new Transform3D();
    Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 00,
        800000000);

    RotationInterpolator rotator = new RotationInterpolator(rotationAlpha,
        objTrans, yAxis, 0.0f(floatMath.PI * 2.0f);
    rotator.setSchedulingBounds(bounds);
    objTrans.addChild(rotator);

    // Have Java 3D perform optimizations on this scene graph.
    objRoot.compile();

    return objRoot;
  }

  public GearTest() {
    this(defaultToothCount);
  }

  public GearTest(int toothCount) {
    this.toothCount = toothCount;
  }

  public void init() {
    setLayout(new BorderLayout());
    GraphicsConfiguration config = SimpleUniverse
        .getPreferredConfiguration();

    Canvas3D c = new Canvas3D(config);
    add("Center", c);

    // Create a simple scene and attach it to the virtual universe
    BranchGroup scene = createSceneGraph(toothCount);
    u = new SimpleUniverse(c);

    // This will move the ViewPlatform back a bit so the
    // objects in the scene can be viewed.
    u.getViewingPlatform().setNominalViewingTransform();

    u.addBranchGraph(scene);
  }

  public void destroy() {
    u.cleanup();
  }

  //
  // The following allows GearTest to be run as an application
  // as well as an applet
  //
  public static void main(String[] args) {
    int value;

    if (args.length > 1) {
      System.out.println("Usage: java GearTest [#teeth]");
      System.exit(0);
    else if (args.length == 0) {
      new MainFrame(new GearTest()700700);
    else {
      try {
        value = Integer.parseInt(args[0]);
      catch (NumberFormatException e) {
        System.out.println("Illegal integer specified");
        System.out.println("Usage: java GearTest [#teeth]");
        value = 0;
        System.exit(0);
      }
      if (value <= 0) {
        System.out.println("Integer must be positive (> 0)");
        System.out.println("Usage: java GearBox [#teeth]");
        System.exit(0);
      }
      new MainFrame(new GearTest(value)700700);
    }
  }
}

class Gear extends javax.media.j3d.TransformGroup {

  // Specifiers determining whether to generate outward facing normals or
  // inward facing normals.
  static final int OutwardNormals = 1;

  static final int InwardNormals = -1;

  // The number of teeth in the gear
  int toothCount;

  // Gear start differential angle. All gears are constructed with the
  // center of a tooth at Z-axis angle = 0.
  double gearStartAngle;

  // The Z-rotation angle to place the tooth center at theta = 0
  float toothTopCenterAngle;

  // The Z-rotation angle to place the valley center at theta = 0
  float valleyCenterAngle;

  // The angle about Z subtended by one tooth and its associated valley
  float circularPitchAngle;

  // Increment angles
  float toothValleyAngleIncrement;

  // Front and rear facing normals for the gear's body
  final Vector3f frontNormal = new Vector3f(0.0f0.0f, -1.0f);

  final Vector3f rearNormal = new Vector3f(0.0f0.0f1.0f);

  Gear(int toothCount) {
    this.toothCount = toothCount;
  }

  void addBodyDisks(float shaftRadius, float bodyOuterRadius,
      float thickness, Appearance look) {
    int gearBodySegmentVertexCount; // #(segments) per tooth-unit
    int gearBodyTotalVertexCount; // #(vertices) in a gear face
    int gearBodyStripCount[] new int[1]// per strip (1) vertex count

    // A ray from the gear center, used in normal calculations
    float xDirection, yDirection;

    // The x and y coordinates at each point of a facet and at each
    // point on the gear: at the shaft, the root of the teeth, and
    // the outer point of the teeth
    float xRoot0, yRoot0, xShaft0, yShaft0;
    float xRoot3, yRoot3, xShaft3, yShaft3;
    float xRoot4, yRoot4, xShaft4, yShaft4;

    // Temporary variables for storing coordinates and vectors
    Point3f coordinate = new Point3f(0.0f0.0f0.0f);

    // Gear start differential angle. All gears are constructed with the
    // center of a tooth at Z-axis angle = 0.
    double gearStartAngle = -1.0 * toothTopCenterAngle;

    // Temporaries that store start angle for each portion of tooth facet
    double toothStartAngle, toothTopStartAngle, toothDeclineStartAngle, toothValleyStartAngle, nextToothStartAngle;

    Shape3D newShape;
    int index;

    // The z coordinates for the body disks
    final float frontZ = -0.5f * thickness;
    final float rearZ = 0.5f * thickness;

    /*
     * Construct the gear's front body (front facing torus disk) __2__ - | -
     * 4 - /| /- / / | /| \ 0\ / | / / > \ / | / | > \ / | / / | \ / ____|/ | >
     * \-- --__/ | 1 3 5
     *  
     */
    gearBodySegmentVertexCount = 4;
    gearBodyTotalVertexCount = + gearBodySegmentVertexCount * toothCount;
    gearBodyStripCount[0= gearBodyTotalVertexCount;

    TriangleStripArray frontGearBody = new TriangleStripArray(
        gearBodyTotalVertexCount, GeometryArray.COORDINATES
            | GeometryArray.NORMALS, gearBodyStripCount);

    xDirection = (floatMath.cos(gearStartAngle);
    yDirection = (floatMath.sin(gearStartAngle);
    xShaft0 = shaftRadius * xDirection;
    yShaft0 = shaftRadius * yDirection;
    xRoot0 = bodyOuterRadius * xDirection;
    yRoot0 = bodyOuterRadius * yDirection;

    coordinate.set(xRoot0, yRoot0, frontZ);
    frontGearBody.setCoordinate(0, coordinate);
    frontGearBody.setNormal(0, frontNormal);

    coordinate.set(xShaft0, yShaft0, frontZ);
    frontGearBody.setCoordinate(1, coordinate);
    frontGearBody.setNormal(1, frontNormal);

    for (int count = 0; count < toothCount; count++) {
      index = + count * 4;
      toothStartAngle = gearStartAngle + circularPitchAngle
          (doublecount;
      toothValleyStartAngle = toothStartAngle + toothValleyAngleIncrement;
      nextToothStartAngle = toothStartAngle + circularPitchAngle;

      xDirection = (floatMath.cos(toothValleyStartAngle);
      yDirection = (floatMath.sin(toothValleyStartAngle);
      xShaft3 = shaftRadius * xDirection;
      yShaft3 = shaftRadius * yDirection;
      xRoot3 = bodyOuterRadius * xDirection;
      yRoot3 = bodyOuterRadius * yDirection;

      xDirection = (floatMath.cos(nextToothStartAngle);
      yDirection = (floatMath.sin(nextToothStartAngle);
      xShaft4 = shaftRadius * xDirection;
      yShaft4 = shaftRadius * yDirection;
      xRoot4 = bodyOuterRadius * xDirection;
      yRoot4 = bodyOuterRadius * yDirection;

      coordinate.set(xRoot3, yRoot3, frontZ);
      frontGearBody.setCoordinate(index, coordinate);
      frontGearBody.setNormal(index, frontNormal);

      coordinate.set(xShaft3, yShaft3, frontZ);
      frontGearBody.setCoordinate(index + 1, coordinate);
      frontGearBody.setNormal(index + 1, frontNormal);

      coordinate.set(xRoot4, yRoot4, frontZ);
      frontGearBody.setCoordinate(index + 2, coordinate);
      frontGearBody.setNormal(index + 2, frontNormal);

      coordinate.set(xShaft4, yShaft4, frontZ);
      frontGearBody.setCoordinate(index + 3, coordinate);
      frontGearBody.setNormal(index + 3, frontNormal);
    }
    newShape = new Shape3D(frontGearBody, look);
    this.addChild(newShape);

    // Construct the gear's rear body (rear facing torus disc)
    TriangleStripArray rearGearBody = new TriangleStripArray(
        gearBodyTotalVertexCount, GeometryArray.COORDINATES
            | GeometryArray.NORMALS, gearBodyStripCount);
    xDirection = (floatMath.cos(gearStartAngle);
    yDirection = (floatMath.sin(gearStartAngle);
    xShaft0 = shaftRadius * xDirection;
    yShaft0 = shaftRadius * yDirection;
    xRoot0 = bodyOuterRadius * xDirection;
    yRoot0 = bodyOuterRadius * yDirection;

    coordinate.set(xShaft0, yShaft0, rearZ);
    rearGearBody.setCoordinate(0, coordinate);
    rearGearBody.setNormal(0, rearNormal);

    coordinate.set(xRoot0, yRoot0, rearZ);
    rearGearBody.setCoordinate(1, coordinate);
    rearGearBody.setNormal(1, rearNormal);

    for (int count = 0; count < toothCount; count++) {
      index = + count * 4;
      toothStartAngle = gearStartAngle + circularPitchAngle
          (doublecount;
      toothValleyStartAngle = toothStartAngle + toothValleyAngleIncrement;
      nextToothStartAngle = toothStartAngle + circularPitchAngle;

      xDirection = (floatMath.cos(toothValleyStartAngle);
      yDirection = (floatMath.sin(toothValleyStartAngle);
      xShaft3 = shaftRadius * xDirection;
      yShaft3 = shaftRadius * yDirection;
      xRoot3 = bodyOuterRadius * xDirection;
      yRoot3 = bodyOuterRadius * yDirection;

      xDirection = (floatMath.cos(nextToothStartAngle);
      yDirection = (floatMath.sin(nextToothStartAngle);
      xShaft4 = shaftRadius * xDirection;
      yShaft4 = shaftRadius * yDirection;
      xRoot4 = bodyOuterRadius * xDirection;
      yRoot4 = bodyOuterRadius * yDirection;

      coordinate.set(xShaft3, yShaft3, rearZ);
      rearGearBody.setCoordinate(index, coordinate);
      rearGearBody.setNormal(index, rearNormal);

      coordinate.set(xRoot3, yRoot3, rearZ);
      rearGearBody.setCoordinate(index + 1, coordinate);
      rearGearBody.setNormal(index + 1, rearNormal);

      coordinate.set(xShaft4, yShaft4, rearZ);
      rearGearBody.setCoordinate(index + 2, coordinate);
      rearGearBody.setNormal(index + 2, rearNormal);

      coordinate.set(xRoot4, yRoot4, rearZ);
      rearGearBody.setCoordinate(index + 3, coordinate);
      rearGearBody.setNormal(index + 3, rearNormal);

    }
    newShape = new Shape3D(rearGearBody, look);
    this.addChild(newShape);
  }

  void addCylinderSkins(float shaftRadius, float length, int normalDirection,
      Appearance look) {
    int insideShaftVertexCount; // #(vertices) for shaft
    int insideShaftStripCount[] new int[1]// #(vertices) in strip/strip
    double toothStartAngle, nextToothStartAngle, toothValleyStartAngle;

    // A ray from the gear center, used in normal calculations
    float xDirection, yDirection;

    // The z coordinates for the body disks
    final float frontZ = -0.5f * length;
    final float rearZ = 0.5f * length;

    // Temporary variables for storing coordinates, points, and vectors
    float xShaft3, yShaft3, xShaft4, yShaft4;
    Point3f coordinate = new Point3f(0.0f0.0f0.0f);
    Vector3f surfaceNormal = new Vector3f();

    Shape3D newShape;
    int index;
    int firstIndex;
    int secondIndex;

    /*
     * Construct gear's inside shaft cylinder First the tooth's up, flat
     * outer, and down distances Second the tooth's flat inner distance
     
     * Outward facing vertex order: 0_______2____4 | /| /| | / | / | | / | / |
     * |/______|/___| 1 3 5
     
     * Inward facing vertex order: 1_______3____5 |\ |\ | | \ | \ | | \ | \ |
     * |______\|___\| 0 2 4
     */
    insideShaftVertexCount = * toothCount + 2;
    insideShaftStripCount[0= insideShaftVertexCount;

    TriangleStripArray insideShaft = new TriangleStripArray(
        insideShaftVertexCount, GeometryArray.COORDINATES
            | GeometryArray.NORMALS, insideShaftStripCount);
    xShaft3 = shaftRadius * (floatMath.cos(gearStartAngle);
    yShaft3 = shaftRadius * (floatMath.sin(gearStartAngle);

    if (normalDirection == OutwardNormals) {
      surfaceNormal.set(1.0f0.0f0.0f);
      firstIndex = 1;
      secondIndex = 0;
    else {
      surfaceNormal.set(-1.0f0.0f0.0f);
      firstIndex = 0;
      secondIndex = 1;
    }

    // Coordinate labeled 0 in the strip
    coordinate.set(shaftRadius, 0.0f, frontZ);
    insideShaft.setCoordinate(firstIndex, coordinate);
    insideShaft.setNormal(firstIndex, surfaceNormal);

    // Coordinate labeled 1 in the strip
    coordinate.set(shaftRadius, 0.0f, rearZ);
    insideShaft.setCoordinate(secondIndex, coordinate);
    insideShaft.setNormal(secondIndex, surfaceNormal);

    for (int count = 0; count < toothCount; count++) {
      index = + count * 4;

      toothStartAngle = circularPitchAngle * (doublecount;
      toothValleyStartAngle = toothStartAngle + toothValleyAngleIncrement;
      nextToothStartAngle = toothStartAngle + circularPitchAngle;

      xDirection = (floatMath.cos(toothValleyStartAngle);
      yDirection = (floatMath.sin(toothValleyStartAngle);
      xShaft3 = shaftRadius * xDirection;
      yShaft3 = shaftRadius * yDirection;
      if (normalDirection == OutwardNormals)
        surfaceNormal.set(xDirection, yDirection, 0.0f);
      else
        surfaceNormal.set(-xDirection, -yDirection, 0.0f);

      // Coordinate labeled 2 in the strip
      coordinate.set(xShaft3, yShaft3, frontZ);
      insideShaft.setCoordinate(index + firstIndex, coordinate);
      insideShaft.setNormal(index + firstIndex, surfaceNormal);

      // Coordinate labeled 3 in the strip
      coordinate.set(xShaft3, yShaft3, rearZ);
      insideShaft.setCoordinate(index + secondIndex, coordinate);
      insideShaft.setNormal(index + secondIndex, surfaceNormal);

      xDirection = (floatMath.cos(nextToothStartAngle);
      yDirection = (floatMath.sin(nextToothStartAngle);
      xShaft4 = shaftRadius * xDirection;
      yShaft4 = shaftRadius * yDirection;
      if (normalDirection == OutwardNormals)
        surfaceNormal.set(xDirection, yDirection, 0.0f);
      else
        surfaceNormal.set(-xDirection, -yDirection, 0.0f);

      // Coordinate labeled 4 in the strip
      coordinate.set(xShaft4, yShaft4, frontZ);
      insideShaft.setCoordinate(index + + firstIndex, coordinate);
      insideShaft.setNormal(index + + firstIndex, surfaceNormal);

      // Coordinate labeled 5 in the strip
      coordinate.set(xShaft4, yShaft4, rearZ);
      insideShaft.setCoordinate(index + + secondIndex, coordinate);
      insideShaft.setNormal(index + + secondIndex, surfaceNormal);

    }
    newShape = new Shape3D(insideShaft, look);
    this.addChild(newShape);
  }

  public float getToothTopCenterAngle() {
    return toothTopCenterAngle;
  }

  public float getValleyCenterAngle() {
    return valleyCenterAngle;
  }

  public float getCircularPitchAngle() {
    return circularPitchAngle;
  }
}

class GearBox extends Applet {

  static final int defaultToothCount = 48;

  private int toothCount;

  private SimpleUniverse u = null;

  public BranchGroup createGearBox(int toothCount) {
    Transform3D tempTransform = new Transform3D();

    // Create the root of the branch graph
    BranchGroup branchRoot = createBranchEnvironment();

    // Create a Transformgroup to scale all objects so they
    // appear in the scene.
    TransformGroup objScale = new TransformGroup();
    Transform3D t3d = new Transform3D();
    t3d.setScale(0.4);
    objScale.setTransform(t3d);
    branchRoot.addChild(objScale);

    // Create an Appearance.
    Appearance look = new Appearance();
    Color3f objColor = new Color3f(0.5f0.5f0.6f);
    Color3f black = new Color3f(0.0f0.0f0.0f);
    Color3f white = new Color3f(1.0f1.0f1.0f);
    look
        .setMaterial(new Material(objColor, black, objColor, white,
            100.0f));

    // Create the transform group node and initialize it to the
    // identity. Enable the TRANSFORM_WRITE capability so that
    // our behavior code can modify it at runtime. Add it to the
    // root of the subgraph.
    TransformGroup gearboxTrans = new TransformGroup();
    gearboxTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    gearboxTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
    objScale.addChild(gearboxTrans);

    // Create a bounds for the mouse behavior methods
    BoundingSphere bounds = new BoundingSphere(new Point3d(0.00.00.0),
        100.0);

    // Define the shaft base information
    int shaftCount = 4;
    int secondsPerRevolution = 8000;

    // Create the Shaft(s)
    Shaft shafts[] new Shaft[shaftCount];
    TransformGroup shaftTGs[] new TransformGroup[shaftCount];
    Alpha shaftAlphas[] new Alpha[shaftCount];
    RotationInterpolator shaftRotors[] new RotationInterpolator[shaftCount];
    Transform3D shaftAxis[] new Transform3D[shaftCount];

    // Note: the following arrays we're incorporated to make changing
    // the gearbox easier.
    float shaftRatios[] new float[shaftCount];
    shaftRatios[01.0f;
    shaftRatios[10.5f;
    shaftRatios[20.75f;
    shaftRatios[35.0f;

    float shaftRadius[] new float[shaftCount];
    shaftRadius[00.2f;
    shaftRadius[10.2f;
    shaftRadius[20.2f;
    shaftRadius[30.2f;

    float shaftLength[] new float[shaftCount];
    shaftLength[01.8f;
    shaftLength[10.8f;
    shaftLength[20.8f;
    shaftLength[30.8f;

    float shaftDirection[] new float[shaftCount];
    shaftDirection[01.0f;
    shaftDirection[1= -1.0f;
    shaftDirection[21.0f;
    shaftDirection[3= -1.0f;

    Vector3d shaftPlacement[] new Vector3d[shaftCount];
    shaftPlacement[0new Vector3d(-0.75, -0.90.0);
    shaftPlacement[1new Vector3d(0.75, -0.90.0);
    shaftPlacement[2new Vector3d(0.750.350.0);
    shaftPlacement[3new Vector3d(-0.750.60, -0.7);

    // Create the shafts.
    for (int i = 0; i < shaftCount; i++) {
      shafts[inew Shaft(shaftRadius[i], shaftLength[i]25, look);
    }

    // Create a transform group node for placing each shaft
    for (int i = 0; i < shaftCount; i++) {
      shaftTGs[inew TransformGroup();
      gearboxTrans.addChild(shaftTGs[i]);
      shaftTGs[i].getTransform(tempTransform);
      tempTransform.setTranslation(shaftPlacement[i]);
      shaftTGs[i].setTransform(tempTransform);
      shaftTGs[i].addChild(shafts[i]);
    }

    // Add rotation interpolators to rotate the shaft in the appropriate
    // direction and at the appropriate rate
    for (int i = 0; i < shaftCount; i++) {
      shaftAlphas[inew Alpha(-1, Alpha.INCREASING_ENABLE, 00,
          (long) (secondsPerRevolution * shaftRatios[i])0000,
          0);
      shaftAxis[inew Transform3D();
      shaftAxis[i].rotX(Math.PI / 2.0);
      shaftRotors[inew RotationInterpolator(shaftAlphas[i],
          shafts[i], shaftAxis[i]0.0f, shaftDirection[i]
              (floatMath.PI * 2.0f);
      shaftRotors[i].setSchedulingBounds(bounds);
      shaftTGs[i].addChild(shaftRotors[i]);
    }

    // Define the gear base information. Again, these arrays exist to
    // make the process of changing the GearBox via an editor faster
    int gearCount = 5;
    float valleyToCircularPitchRatio = .15f;
    float pitchCircleRadius = 1.0f;
    float addendum = 0.05f;
    float dedendum = 0.05f;
    float gearThickness = 0.3f;
    float toothTipThickness = 0.27f;

    // Create an array of gears and their associated information
    SpurGear gears[] new SpurGear[gearCount];
    TransformGroup gearTGs[] new TransformGroup[gearCount];

    int gearShaft[] new int[gearCount];
    gearShaft[00;
    gearShaft[11;
    gearShaft[22;
    gearShaft[30;
    gearShaft[43;

    float ratio[] new float[gearCount];
    ratio[01.0f;
    ratio[10.5f;
    ratio[20.75f;
    ratio[30.25f;
    ratio[41.25f;

    Vector3d placement[] new Vector3d[gearCount];
    placement[0new Vector3d(0.00.00.0);
    placement[1new Vector3d(0.00.00.0);
    placement[2new Vector3d(0.00.00.0);
    placement[3new Vector3d(0.00.0, -0.7);
    placement[4new Vector3d(0.00.00.0);

    // Create the gears.
    for (int i = 0; i < gearCount; i++) {
      gears[inew SpurGearThinBody(
          ((int) ((floattoothCount * ratio[i])), pitchCircleRadius
              * ratio[i], shaftRadius[0], addendum, dedendum,
          gearThickness, toothTipThickness,
          valleyToCircularPitchRatio, look);
    }

    // Create a transform group node for arranging the gears on a shaft
    // and attach the gear to its associated shaft
    for (int i = 0; i < gearCount; i++) {
      gearTGs[inew TransformGroup();
      gearTGs[i].getTransform(tempTransform);
      tempTransform
          .rotZ((shaftDirection[gearShaft[i]] == -1.0? gears[i]
              .getCircularPitchAngle()
              / -2.0f 0.0f);
      tempTransform.setTranslation(placement[i]);
      gearTGs[i].setTransform(tempTransform);
      gearTGs[i].addChild(gears[i]);
      shafts[gearShaft[i]].addChild(gearTGs[i]);
    }

    // Have Java 3D perform optimizations on this scene graph.
    branchRoot.compile();

    return branchRoot;
  }

  BranchGroup createBranchEnvironment() {
    // Create the root of the branch graph
    BranchGroup branchRoot = new BranchGroup();

    // Create a bounds for the background and lights
    BoundingSphere bounds = new BoundingSphere(new Point3d(0.00.00.0),
        100.0);

    // Set up the background
    Color3f bgColor = new Color3f(0.05f0.05f0.5f);
    Background bgNode = new Background(bgColor);
    bgNode.setApplicationBounds(bounds);
    branchRoot.addChild(bgNode);

    // Set up the ambient light
    Color3f ambientColor = new Color3f(0.1f0.1f0.1f);
    AmbientLight ambientLightNode = new AmbientLight(ambientColor);
    ambientLightNode.setInfluencingBounds(bounds);
    branchRoot.addChild(ambientLightNode);

    // Set up the directional lights
    Color3f light1Color = new Color3f(1.0f1.0f0.9f);
    Vector3f light1Direction = new Vector3f(1.0f1.0f1.0f);
    Color3f light2Color = new Color3f(1.0f1.0f0.9f);
    Vector3f light2Direction = new Vector3f(-1.0f, -1.0f, -1.0f);

    DirectionalLight light1 = new DirectionalLight(light1Color,
        light1Direction);
    light1.setInfluencingBounds(bounds);
    branchRoot.addChild(light1);

    DirectionalLight light2 = new DirectionalLight(light2Color,
        light2Direction);
    light2.setInfluencingBounds(bounds);
    branchRoot.addChild(light2);

    return branchRoot;
  }

  public GearBox() {
    this(defaultToothCount);
  }

  public GearBox(int toothCount) {
    this.toothCount = toothCount;
  }

  public void init() {
    setLayout(new BorderLayout());
    GraphicsConfiguration config = SimpleUniverse
        .getPreferredConfiguration();

    Canvas3D c = new Canvas3D(config);
    add("Center", c);

    // Create the gearbox and attach it to the virtual universe
    BranchGroup scene = createGearBox(toothCount);
    u = new SimpleUniverse(c);

    // add mouse behaviors to the ViewingPlatform
    ViewingPlatform viewingPlatform = u.getViewingPlatform();

    // This will move the ViewPlatform back a bit so the
    // objects in the scene can be viewed.
    viewingPlatform.setNominalViewingTransform();

    // add orbit behavior to the ViewingPlatform
    OrbitBehavior orbit = new OrbitBehavior(c, OrbitBehavior.REVERSE_ALL);
    BoundingSphere bounds = new BoundingSphere(new Point3d(0.00.00.0),
        100.0);
    orbit.setSchedulingBounds(bounds);
    viewingPlatform.setViewPlatformBehavior(orbit);

    u.addBranchGraph(scene);
  }

  public void destroy() {
    u.cleanup();
  }

  //
  // The following allows GearBox to be run as an application
  // as well as an applet
  //
  public static void main(String[] args) {
    int value;

    if (args.length > 1) {
      System.out.println("Usage: java GearBox  #teeth (LCD 4)");
      System.exit(0);
    else if (args.length == 0) {
      new MainFrame(new GearBox()700700);
    else {
      try {
        value = Integer.parseInt(args[0]);
      catch (NumberFormatException e) {
        System.out.println("Illegal integer specified");
        System.out.println("Usage: java GearBox  #teeth (LCD 4)");
        value = 0;
        System.exit(0);
      }
      if (value <= (value % 4!= 0) {
        System.out.println("Integer not a positive multiple of 4");
        System.out.println("Usage: java GearBox  #teeth (LCD 4)");
        System.exit(0);
      }
      new MainFrame(new GearBox(value)700700);
    }
  }
}

class SpurGear extends Gear {

  float toothTopAngleIncrement;

  float toothDeclineAngleIncrement;

  float rootRadius;

  float outsideRadius;

  //The angle subtended by the ascending or descending portion of a tooth
  float circularToothEdgeAngle;

  // The angle subtended by a flat (either a tooth top or a valley
  // between teeth
  float circularToothFlatAngle;

  /**
   * internal constructor for SpurGear, used by subclasses to establish
   * SpurGear's required state
   
   @return a new spur gear that contains sufficient information to continue
   *         building
   @param toothCount
   *            number of teeth
   @param pitchCircleRadius
   *            radius at center of teeth
   @param addendum
   *            distance from pitch circle to top of teeth
   @param dedendum
   *            distance from pitch circle to root of teeth
   @param toothToValleyAngleRatio
   *            the ratio of the angle subtended by the tooth to the angle
   *            subtended by the valley (must be <= .25)
   */
  SpurGear(int toothCount, float pitchCircleRadius, float addendum,
      float dedendum, float toothToValleyAngleRatio) {

    super(toothCount);

    // The angle about Z subtended by one tooth and its associated valley
    circularPitchAngle = (float) (2.0 * Math.PI / (doubletoothCount);

    // The angle subtended by a flat (either a tooth top or a valley
    // between teeth
    circularToothFlatAngle = circularPitchAngle * toothToValleyAngleRatio;

    //The angle subtended by the ascending or descending portion of a tooth
    circularToothEdgeAngle = circularPitchAngle / 2.0f
        - circularToothFlatAngle;

    // Increment angles
    toothTopAngleIncrement = circularToothEdgeAngle;
    toothDeclineAngleIncrement = toothTopAngleIncrement
        + circularToothFlatAngle;
    toothValleyAngleIncrement = toothDeclineAngleIncrement
        + circularToothEdgeAngle;

    // Differential angles for offsetting to the center of tooth's top
    // and valley
    toothTopCenterAngle = toothTopAngleIncrement + circularToothFlatAngle
        2.0f;
    valleyCenterAngle = toothValleyAngleIncrement + circularToothFlatAngle
        2.0f;

    // Gear start differential angle. All gears are constructed with the
    // center of a tooth at Z-axis angle = 0.
    gearStartAngle = -1.0 * toothTopCenterAngle;

    // The radial distance to the root and top of the teeth, respectively
    rootRadius = pitchCircleRadius - dedendum;
    outsideRadius = pitchCircleRadius + addendum;

    // Allow this object to spin. etc.
    this.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  }

  /**
   * Construct a SpurGear;
   
   @return a new spur gear that conforms to the input paramters
   @param toothCount
   *            number of teeth
   @param pitchCircleRadius
   *            radius at center of teeth
   @param shaftRadius
   *            radius of hole at center
   @param addendum
   *            distance from pitch circle to top of teeth
   @param dedendum
   *            distance from pitch circle to root of teeth
   @param gearThickness
   *            thickness of the gear
   */
  public SpurGear(int toothCount, float pitchCircleRadius, float shaftRadius,
      float addendum, float dedendum, float gearThickness) {
    this(toothCount, pitchCircleRadius, shaftRadius, addendum, dedendum,
        gearThickness, gearThickness, 0.25fnull);
  }

  /**
   * Construct a SpurGear;
   
   @return a new spur gear that conforms to the input paramters
   @param toothCount
   *            number of teeth
   @param pitchCircleRadius
   *            radius at center of teeth
   @param shaftRadius
   *            radius of hole at center
   @param addendum
   *            distance from pitch circle to top of teeth
   @param dedendum
   *            distance from pitch circle to root of teeth
   @param gearThickness
   *            thickness of the gear
   @param look
   *            the gear's appearance
   */
  public SpurGear(int toothCount, float pitchCircleRadius, float shaftRadius,
      float addendum, float dedendum, float gearThickness, Appearance look) {
    this(toothCount, pitchCircleRadius, shaftRadius, addendum, dedendum,
        gearThickness, gearThickness, 0.25f, look);
  }

  /**
   * Construct a SpurGear;
   
   @return a new spur gear that conforms to the input paramters
   @param toothCount
   *            number of teeth
   @param pitchCircleRadius
   *            radius at center of teeth
   @param shaftRadius
   *            radius of hole at center
   @param addendum
   *            distance from pitch circle to top of teeth
   @param dedendum
   *            distance from pitch circle to root of teeth
   @param gearThickness
   *            thickness of the gear
   @param toothTipThickness
   *            thickness of the tip of the tooth
   @param look
   *            the gear's appearance
   */
  public SpurGear(int toothCount, float pitchCircleRadius, float shaftRadius,
      float addendum, float dedendum, float gearThickness,
      float toothTipThickness, Appearance look) {
    this(toothCount, pitchCircleRadius, shaftRadius, addendum, dedendum,
        gearThickness, toothTipThickness, 0.25f, look);
  }

  /**
   * Construct a SpurGear;
   
   @return a new spur gear that conforms to the input paramters
   @param toothCount
   *            number of teeth
   @param pitchCircleRadius
   *            radius at center of teeth
   @param shaftRadius
   *            radius of hole at center
   @param addendum
   *            distance from pitch circle to top of teeth
   @param dedendum
   *            distance from pitch circle to root of teeth
   @param gearThickness
   *            thickness of the gear
   @param toothTipThickness
   *            thickness of the tip of the tooth
   @param toothToValleyAngleRatio
   *            the ratio of the angle subtended by the tooth to the angle
   *            subtended by the valley (must be <= .25)
   @param look
   *            the gear's appearance object
   */
  public SpurGear(int toothCount, float pitchCircleRadius, float shaftRadius,
      float addendum, float dedendum, float gearThickness,
      float toothTipThickness, float toothToValleyAngleRatio,
      Appearance look) {

    this(toothCount, pitchCircleRadius, addendum, dedendum,
        toothToValleyAngleRatio);

    // Generate the gear's body disks
    addBodyDisks(shaftRadius, rootRadius, gearThickness, look);

    // Generate the gear's interior shaft
    addCylinderSkins(shaftRadius, gearThickness, InwardNormals, look);

    // Generate the gear's teeth
    addTeeth(pitchCircleRadius, rootRadius, outsideRadius, gearThickness,
        toothTipThickness, toothToValleyAngleRatio, look);
  }

  /**
   * Construct a SpurGear's teeth by adding the teeth shape nodes
   
   @param pitchCircleRadius
   *            radius at center of teeth
   @param rootRadius
   *            distance from pitch circle to top of teeth
   @param outsideRadius
   *            distance from pitch circle to root of teeth
   @param gearThickness
   *            thickness of the gear
   @param toothTipThickness
   *            thickness of the tip of the tooth
   @param toothToValleyAngleRatio
   *            the ratio of the angle subtended by the tooth to the angle
   *            subtended by the valley (must be <= .25)
   @param look
   *            the gear's appearance object
   */
  void addTeeth(float pitchCircleRadius, float rootRadius,
      float outsideRadius, float gearThickness, float toothTipThickness,
      float toothToValleyAngleRatio, Appearance look) {
    int index;
    Shape3D newShape;

    // Temporaries that store start angle for each portion of tooth facet
    double toothStartAngle, toothTopStartAngle, toothDeclineStartAngle, toothValleyStartAngle, nextToothStartAngle;

    // The x and y coordinates at each point of a facet and at each
    // point on the gear: at the shaft, the root of the teeth, and
    // the outer point of the teeth
    float xRoot0, yRoot0;
    float xOuter1, yOuter1;
    float xOuter2, yOuter2;
    float xRoot3, yRoot3;
    float xRoot4, yRoot4;

    // The z coordinates for the gear
    final float frontZ = -0.5f * gearThickness;
    final float rearZ = 0.5f * gearThickness;

    // The z coordinates for the tooth tip of the gear
    final float toothTipFrontZ = -0.5f * toothTipThickness;
    final float toothTipRearZ = 0.5f * toothTipThickness;

    int toothFacetVertexCount; // #(vertices) per tooth facet
    int toothFacetCount; // #(facets) per tooth
    int toothFaceTotalVertexCount; // #(vertices) in all teeth
    int toothFaceStripCount[] new int[toothCount];
    // per tooth vertex count
    int topVertexCount; // #(vertices) for teeth tops
    int topStripCount[] new int[1]// #(vertices) in strip/strip

    // Front and rear facing normals for the teeth faces
    Vector3f frontToothNormal = new Vector3f(0.0f0.0f, -1.0f);
    Vector3f rearToothNormal = new Vector3f(0.0f0.0f1.0f);

    // Normals for teeth tops up incline, tooth top, and down incline
    Vector3f leftNormal = new Vector3f(-1.0f0.0f0.0f);
    Vector3f rightNormal = new Vector3f(1.0f0.0f0.0f);
    Vector3f outNormal = new Vector3f(1.0f0.0f0.0f);
    Vector3f inNormal = new Vector3f(-1.0f0.0f0.0f);

    // Temporary variables for storing coordinates and vectors
    Point3f coordinate = new Point3f(0.0f0.0f0.0f);
    Point3f tempCoordinate1 = new Point3f(0.0f0.0f0.0f);
    Point3f tempCoordinate2 = new Point3f(0.0f0.0f0.0f);
    Point3f tempCoordinate3 = new Point3f(0.0f0.0f0.0f);
    Vector3f tempVector1 = new Vector3f(0.0f0.0f0.0f);
    Vector3f tempVector2 = new Vector3f(0.0f0.0f0.0f);

    /*
     * Construct the gear's front facing teeth facets 0______2 / /\ / / \ / / \
     * //___________\ 1 3
     */
    toothFacetVertexCount = 4;
    toothFaceTotalVertexCount = toothFacetVertexCount * toothCount;
    for (int i = 0; i < toothCount; i++)
      toothFaceStripCount[i= toothFacetVertexCount;

    TriangleStripArray frontGearTeeth = new TriangleStripArray(
        toothFaceTotalVertexCount, GeometryArray.COORDINATES
            | GeometryArray.NORMALS, toothFaceStripCount);

    for (int count = 0; count < toothCount; count++) {
      index = count * toothFacetVertexCount;

      toothStartAngle = gearStartAngle + circularPitchAngle
          (doublecount;
      toothTopStartAngle = toothStartAngle + toothTopAngleIncrement;
      toothDeclineStartAngle = toothStartAngle
          + toothDeclineAngleIncrement;
      toothValleyStartAngle = toothStartAngle + toothValleyAngleIncrement;

      xRoot0 = rootRadius * (floatMath.cos(toothStartAngle);
      yRoot0 = rootRadius * (floatMath.sin(toothStartAngle);
      xOuter1 = outsideRadius * (floatMath.cos(toothTopStartAngle);
      yOuter1 = outsideRadius * (floatMath.sin(toothTopStartAngle);
      xOuter2 = outsideRadius * (floatMath.cos(toothDeclineStartAngle);
      yOuter2 = outsideRadius * (floatMath.sin(toothDeclineStartAngle);
      xRoot3 = rootRadius * (floatMath.cos(toothValleyStartAngle);
      yRoot3 = rootRadius * (floatMath.sin(toothValleyStartAngle);

      tempCoordinate1.set(xRoot0, yRoot0, frontZ);
      tempCoordinate2.set(xRoot3, yRoot3, frontZ);
      tempVector1.sub(tempCoordinate2, tempCoordinate1);

      tempCoordinate2.set(xOuter1, yOuter1, toothTipFrontZ);
      tempVector2.sub(tempCoordinate2, tempCoordinate1);

      frontToothNormal.cross(tempVector1, tempVector2);
      frontToothNormal.normalize();

      coordinate.set(xOuter1, yOuter1, toothTipFrontZ);
      frontGearTeeth.setCoordinate(index, coordinate);
      frontGearTeeth.setNormal(index, frontToothNormal);

      coordinate.set(xRoot0, yRoot0, frontZ);
      frontGearTeeth.setCoordinate(index + 1, coordinate);
      frontGearTeeth.setNormal(index + 1, frontToothNormal);

      coordinate.set(xOuter2, yOuter2, toothTipFrontZ);
      frontGearTeeth.setCoordinate(index + 2, coordinate);
      frontGearTeeth.setNormal(index + 2, frontToothNormal);

      coordinate.set(xRoot3, yRoot3, frontZ);
      frontGearTeeth.setCoordinate(index + 3, coordinate);
      frontGearTeeth.setNormal(index + 3, frontToothNormal);
    }
    newShape = new Shape3D(frontGearTeeth, look);
    this.addChild(newShape);

    /*
     * Construct the gear's rear facing teeth facets (Using Quads) 1______2 / \ / \ / \
     * /____________\ 0 3
     */
    toothFacetVertexCount = 4;
    toothFaceTotalVertexCount = toothFacetVertexCount * toothCount;

    QuadArray rearGearTeeth = new QuadArray(toothCount
        * toothFacetVertexCount, GeometryArray.COORDINATES
        | GeometryArray.NORMALS);

    for (int count = 0; count < toothCount; count++) {

      index = count * toothFacetVertexCount;
      toothStartAngle = gearStartAngle + circularPitchAngle
          (doublecount;
      toothTopStartAngle = toothStartAngle + toothTopAngleIncrement;
      toothDeclineStartAngle = toothStartAngle
          + toothDeclineAngleIncrement;
      toothValleyStartAngle = toothStartAngle + toothValleyAngleIncrement;

      xRoot0 = rootRadius * (floatMath.cos(toothStartAngle);
      yRoot0 = rootRadius * (floatMath.sin(toothStartAngle);
      xOuter1 = outsideRadius * (floatMath.cos(toothTopStartAngle);
      yOuter1 = outsideRadius * (floatMath.sin(toothTopStartAngle);
      xOuter2 = outsideRadius * (floatMath.cos(toothDeclineStartAngle);
      yOuter2 = outsideRadius * (floatMath.sin(toothDeclineStartAngle);
      xRoot3 = rootRadius * (floatMath.cos(toothValleyStartAngle);
      yRoot3 = rootRadius * (floatMath.sin(toothValleyStartAngle);

      tempCoordinate1.set(xRoot0, yRoot0, rearZ);
      tempCoordinate2.set(xRoot3, yRoot3, rearZ);
      tempVector1.sub(tempCoordinate2, tempCoordinate1);
      tempCoordinate2.set(xOuter1, yOuter1, toothTipRearZ);
      tempVector2.sub(tempCoordinate2, tempCoordinate1);
      rearToothNormal.cross(tempVector2, tempVector1);
      rearToothNormal.normalize();

      coordinate.set(xRoot0, yRoot0, rearZ);
      rearGearTeeth.setCoordinate(index, coordinate);
      rearGearTeeth.setNormal(index, rearToothNormal);

      coordinate.set(xOuter1, yOuter1, toothTipRearZ);
      rearGearTeeth.setCoordinate(index + 1, coordinate);
      rearGearTeeth.setNormal(index + 1, rearToothNormal);

      coordinate.set(xOuter2, yOuter2, toothTipRearZ);
      rearGearTeeth.setCoordinate(index + 2, coordinate);
      rearGearTeeth.setNormal(index + 2, rearToothNormal);

      coordinate.set(xRoot3, yRoot3, rearZ);
      rearGearTeeth.setCoordinate(index + 3, coordinate);
      rearGearTeeth.setNormal(index + 3, rearToothNormal);

    }
    newShape = new Shape3D(rearGearTeeth, look);
    this.addChild(newShape);

    /*
     * Construct the gear's top teeth faces (As seen from above) Root0
     * Outer1 Outer2 Root3 Root4 (RearZ) 0_______3 2_______5 4_______7
     * 6_______9 |0 3| |4 7| |8 11| |12 15| | | | | | | | | | | | | | | | |
     * |1_____2| |5_____6| |9____10| |13___14| 1 2 3 4 5 6 7 8 Root0 Outer1
     * Outer2 Root3 Root4 (FrontZ)
     
     * Quad 0123 uses a left normal Quad 2345 uses an out normal Quad 4567
     * uses a right normal Quad 6789 uses an out normal
     */
    topVertexCount = * toothCount + 2;
    topStripCount[0= topVertexCount;

    toothFacetVertexCount = 4;
    toothFacetCount = 4;

    QuadArray topGearTeeth = new QuadArray(toothCount
        * toothFacetVertexCount * toothFacetCount,
        GeometryArray.COORDINATES | GeometryArray.NORMALS);

    for (int count = 0; count < toothCount; count++) {
      index = count * toothFacetCount * toothFacetVertexCount;
      toothStartAngle = gearStartAngle + circularPitchAngle
          (doublecount;
      toothTopStartAngle = toothStartAngle + toothTopAngleIncrement;
      toothDeclineStartAngle = toothStartAngle
          + toothDeclineAngleIncrement;
      toothValleyStartAngle = toothStartAngle + toothValleyAngleIncrement;
      nextToothStartAngle = toothStartAngle + circularPitchAngle;

      xRoot0 = rootRadius * (floatMath.cos(toothStartAngle);
      yRoot0 = rootRadius * (floatMath.sin(toothStartAngle);
      xOuter1 = outsideRadius * (floatMath.cos(toothTopStartAngle);
      yOuter1 = outsideRadius * (floatMath.sin(toothTopStartAngle);
      xOuter2 = outsideRadius * (floatMath.cos(toothDeclineStartAngle);
      yOuter2 = outsideRadius * (floatMath.sin(toothDeclineStartAngle);
      xRoot3 = rootRadius * (floatMath.cos(toothValleyStartAngle);
      yRoot3 = rootRadius * (floatMath.sin(toothValleyStartAngle);
      xRoot4 = rootRadius * (floatMath.cos(nextToothStartAngle);
      yRoot4 = rootRadius * (floatMath.sin(nextToothStartAngle);

      // Compute normal for quad 1
      tempCoordinate1.set(xRoot0, yRoot0, frontZ);
      tempCoordinate2.set(xOuter1, yOuter1, toothTipFrontZ);
      tempVector1.sub(tempCoordinate2, tempCoordinate1);
      leftNormal.cross(frontNormal, tempVector1);
      leftNormal.normalize();

      // Coordinate labeled 0 in the quad
      coordinate.set(xRoot0, yRoot0, rearZ);
      topGearTeeth.setCoordinate(index, coordinate);
      topGearTeeth.setNormal(index, leftNormal);

      // Coordinate labeled 1 in the quad
      coordinate.set(tempCoordinate1);
      topGearTeeth.setCoordinate(index + 1, coordinate);
      topGearTeeth.setNormal(index + 1, leftNormal);

      // Coordinate labeled 2 in the quad
      topGearTeeth.setCoordinate(index + 2, tempCoordinate2);
      topGearTeeth.setNormal(index + 2, leftNormal);
      topGearTeeth.setCoordinate(index + 5, tempCoordinate2);

      // Coordinate labeled 3 in the quad
      coordinate.set(xOuter1, yOuter1, toothTipRearZ);
      topGearTeeth.setCoordinate(index + 3, coordinate);
      topGearTeeth.setNormal(index + 3, leftNormal);
      topGearTeeth.setCoordinate(index + 4, coordinate);

      // Compute normal for quad 2
      tempCoordinate1.set(xOuter1, yOuter1, toothTipFrontZ);
      tempCoordinate2.set(xOuter2, yOuter2, toothTipFrontZ);
      tempVector1.sub(tempCoordinate2, tempCoordinate1);
      outNormal.cross(frontNormal, tempVector1);
      outNormal.normalize();

      topGearTeeth.setNormal(index + 4, outNormal);
      topGearTeeth.setNormal(index + 5, outNormal);

      // Coordinate labeled 4 in the quad
      topGearTeeth.setCoordinate(index + 6, tempCoordinate2);
      topGearTeeth.setNormal(index + 6, outNormal);
      topGearTeeth.setCoordinate(index + 9, tempCoordinate2);

      // Coordinate labeled 5 in the quad
      coordinate.set(xOuter2, yOuter2, toothTipRearZ);
      topGearTeeth.setCoordinate(index + 7, coordinate);
      topGearTeeth.setNormal(index + 7, outNormal);
      topGearTeeth.setCoordinate(index + 8, coordinate);

      // Compute normal for quad 3
      tempCoordinate1.set(xOuter2, yOuter2, toothTipFrontZ);
      tempCoordinate2.set(xRoot3, yRoot3, frontZ);
      tempVector1.sub(tempCoordinate2, tempCoordinate1);
      rightNormal.cross(frontNormal, tempVector1);
      rightNormal.normalize();

      topGearTeeth.setNormal(index + 8, rightNormal);
      topGearTeeth.setNormal(index + 9, rightNormal);

      // Coordinate labeled 7 in the quad
      topGearTeeth.setCoordinate(index + 10, tempCoordinate2);
      topGearTeeth.setNormal(index + 10, rightNormal);
      topGearTeeth.setCoordinate(index + 13, tempCoordinate2);

      // Coordinate labeled 6 in the quad
      coordinate.set(xRoot3, yRoot3, rearZ);
      topGearTeeth.setCoordinate(index + 11, coordinate);
      topGearTeeth.setNormal(index + 11, rightNormal);
      topGearTeeth.setCoordinate(index + 12, coordinate);

      // Compute normal for quad 4
      tempCoordinate1.set(xRoot3, yRoot3, frontZ);
      tempCoordinate2.set(xRoot4, yRoot4, frontZ);
      tempVector1.sub(tempCoordinate2, tempCoordinate1);
      outNormal.cross(frontNormal, tempVector1);
      outNormal.normalize();

      topGearTeeth.setNormal(index + 12, outNormal);
      topGearTeeth.setNormal(index + 13, outNormal);

      // Coordinate labeled 9 in the quad
      topGearTeeth.setCoordinate(index + 14, tempCoordinate2);
      topGearTeeth.setNormal(index + 14, outNormal);

      // Coordinate labeled 8 in the quad
      coordinate.set(xRoot4, yRoot4, rearZ);
      topGearTeeth.setCoordinate(index + 15, coordinate);
      topGearTeeth.setNormal(index + 15, outNormal);

      // Prepare for the loop by computing the new normal
      toothTopStartAngle = nextToothStartAngle + toothTopAngleIncrement;
      xOuter1 = outsideRadius * (floatMath.cos(toothTopStartAngle);
      yOuter1 = outsideRadius * (floatMath.sin(toothTopStartAngle);

      tempCoordinate1.set(xRoot4, yRoot4, toothTipFrontZ);
      tempCoordinate2.set(xOuter1, yOuter1, toothTipFrontZ);
      tempVector1.sub(tempCoordinate2, tempCoordinate1);
      leftNormal.cross(frontNormal, tempVector1);
      leftNormal.normalize();
    }
    newShape = new Shape3D(topGearTeeth, look);
    this.addChild(newShape);
  }

}

class SpurGearThinBody extends SpurGear {

  /**
   * Construct a SpurGearThinBody;
   
   @return a new spur gear that conforms to the input paramters
   @param toothCount
   *            number of teeth
   @param pitchCircleRadius
   *            radius at center of teeth
   @param shaftRadius
   *            radius of hole at center
   @param addendum
   *            distance from pitch circle to top of teeth
   @param dedendum
   *            distance from pitch circle to root of teeth
   @param gearThickness
   *            thickness of the gear
   */
  public SpurGearThinBody(int toothCount, float pitchCircleRadius,
      float shaftRadius, float addendum, float dedendum,
      float gearThickness) {
    this(toothCount, pitchCircleRadius, shaftRadius, addendum, dedendum,
        gearThickness, gearThickness, 0.25fnull);
  }

  /**
   * Construct a SpurGearThinBody;
   
   @return a new spur gear that conforms to the input paramters
   @param toothCount
   *            number of teeth
   @param pitchCircleRadius
   *            radius at center of teeth
   @param shaftRadius
   *            radius of hole at center
   @param addendum
   *            distance from pitch circle to top of teeth
   @param dedendum
   *            distance from pitch circle to root of teeth
   @param gearThickness
   *            thickness of the gear
   @param look
   *            the gear's appearance
   */
  public SpurGearThinBody(int toothCount, float pitchCircleRadius,
      float shaftRadius, float addendum, float dedendum,
      float gearThickness, Appearance look) {
    this(toothCount, pitchCircleRadius, shaftRadius, addendum, dedendum,
        gearThickness, gearThickness, 0.25f, look);
  }

  /**
   * Construct a SpurGearThinBody;
   
   @return a new spur gear that conforms to the input paramters
   @param toothCount
   *            number of teeth
   @param pitchCircleRadius
   *            radius at center of teeth
   @param shaftRadius
   *            radius of hole at center
   @param addendum
   *            distance from pitch circle to top of teeth
   @param dedendum
   *            distance from pitch circle to root of teeth
   @param gearThickness
   *            thickness of the gear
   @param toothTipThickness
   *            thickness of the tip of the tooth
   @param look
   *            the gear's appearance
   */
  public SpurGearThinBody(int toothCount, float pitchCircleRadius,
      float shaftRadius, float addendum, float dedendum,
      float gearThickness, float toothTipThickness, Appearance look) {
    this(toothCount, pitchCircleRadius, shaftRadius, addendum, dedendum,
        gearThickness, toothTipThickness, 0.25f, look);
  }

  /**
   * Construct a SpurGearThinBody;
   
   @return a new spur gear that conforms to the input paramters
   @param toothCount
   *            number of teeth
   @param pitchCircleRadius
   *            radius at center of teeth
   @param shaftRadius
   *            radius of hole at center
   @param addendum
   *            distance from pitch circle to top of teeth
   @param dedendum
   *            distance from pitch circle to root of teeth
   @param gearThickness
   *            thickness of the gear
   @param toothTipThickness
   *            thickness of the tip of the tooth
   @param toothToValleyRatio
   *            ratio of tooth valley to circular pitch (must be <= .25)
   @param look
   *            the gear's appearance object
   */
  public SpurGearThinBody(int toothCount, float pitchCircleRadius,
      float shaftRadius, float addendum, float dedendum,
      float gearThickness, float toothTipThickness,
      float toothToValleyAngleRatio, Appearance look) {

    this(toothCount, pitchCircleRadius, shaftRadius, addendum, dedendum,
        gearThickness, toothTipThickness, 0.25f, look,
        0.6f * gearThickness, 0.75f (pitchCircleRadius - shaftRadius));
  }

  /**
   * Construct a SpurGearThinBody;
   
   @return a new spur gear that conforms to the input paramters
   @param toothCount
   *            number of teeth
   @param pitchCircleRadius
   *            radius at center of teeth
   @param shaftRadius
   *            radius of hole at center
   @param addendum
   *            distance from pitch circle to top of teeth
   @param dedendum
   *            distance from pitch circle to root of teeth
   @param gearThickness
   *            thickness of the gear
   @param toothTipThickness
   *            thickness of the tip of the tooth
   @param toothToValleyRatio
   *            ratio of tooth valley to circular pitch (must be <= .25)
   @param look
   *            the gear's appearance object
   @param bodyThickness
   *            the thickness of the gear body
   @param crossSectionWidth
   *            the width of the depressed portion of the gear's body
   */
  public SpurGearThinBody(int toothCount, float pitchCircleRadius,
      float shaftRadius, float addendum, float dedendum,
      float gearThickness, float toothTipThickness,
      float toothToValleyAngleRatio, Appearance look,
      float bodyThickness, float crossSectionWidth) {

    super(toothCount, pitchCircleRadius, addendum, dedendum,
        toothToValleyAngleRatio);

    float diskCrossSectionWidth = (rootRadius - shaftRadius - crossSectionWidth2.0f;
    float outerShaftRadius = shaftRadius + diskCrossSectionWidth;
    float innerToothRadius = rootRadius - diskCrossSectionWidth;

    // Generate the gear's body disks, first by the shaft, then in
    // the body and, lastly, by the teeth
    addBodyDisks(shaftRadius, outerShaftRadius, gearThickness, look);
    addBodyDisks(innerToothRadius, rootRadius, gearThickness, look);
    addBodyDisks(outerShaftRadius, innerToothRadius, bodyThickness, look);

    // Generate the gear's "shaft" equivalents the two at the teeth
    // and the two at the shaft
    addCylinderSkins(innerToothRadius, gearThickness, InwardNormals, look);
    addCylinderSkins(outerShaftRadius, gearThickness, OutwardNormals, look);

    // Generate the gear's interior shaft
    addCylinderSkins(shaftRadius, gearThickness, InwardNormals, look);

    // Generate the gear's teeth
    addTeeth(pitchCircleRadius, rootRadius, outsideRadius, gearThickness,
        toothTipThickness, toothToValleyAngleRatio, look);
  }

}

class Shaft extends javax.media.j3d.TransformGroup {

  /**
   * Construct a Shaft;
   
   @return a new shaft that with the specified radius centered about the
   *         origin an laying in the XY plane and of a specified length
   *         extending in the Z dimension
   @param radius
   *            radius of shaft
   @param length
   *            shaft length shaft extends from -length/2 to length/2 in the Z
   *            dimension
   @param segmentCount
   *            number of segments for the shaft face
   @param look
   *            the Appearance to associate with this shaft
   */
  public Shaft(float radius, float length, int segmentCount, Appearance look) {
    // The direction of the ray from the shaft's center
    float xDirection, yDirection;
    float xShaft, yShaft;

    // The z coordinates for the shaft's faces (never change)
    float frontZ = -0.5f * length;
    float rearZ = 0.5f * length;

    int shaftFaceVertexCount; // #(vertices) per shaft face
    int shaftFaceTotalVertexCount; // total #(vertices) in all teeth
    int shaftFaceStripCount[] new int[1]// per shaft vertex count
    int shaftVertexCount; // #(vertices) for shaft
    int shaftStripCount[] new int[1]// #(vertices) in strip/strip

    // Front and rear facing normals for the shaft's faces
    Vector3f frontNormal = new Vector3f(0.0f0.0f, -1.0f);
    Vector3f rearNormal = new Vector3f(0.0f0.0f1.0f);
    // Outward facing normal
    Vector3f outNormal = new Vector3f(1.0f0.0f0.0f);

    // Temporary variables for storing coordinates and vectors
    Point3f coordinate = new Point3f(0.0f0.0f0.0f);
    Shape3D newShape;

    // The angle subtended by a single segment
    double segmentAngle = 2.0 * Math.PI / segmentCount;
    double tempAngle;

    // Allow this object to spin. etc.
    this.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

    /*
     * for the forward facing fan: ___3___ - | - / | \ 4/\ | /\2 / \ | / \ / \ | / \ : \ | / :
     * |--------------- *----------------| 5 0 1
     
     * for backward facing fan exchange 1 with 5; 2 with 4, etc.
     */

    // Construct the shaft's front and rear face
    shaftFaceVertexCount = segmentCount + 2;
    shaftFaceStripCount[0= shaftFaceVertexCount;

    TriangleFanArray frontShaftFace = new TriangleFanArray(
        shaftFaceVertexCount, GeometryArray.COORDINATES
            | GeometryArray.NORMALS, shaftFaceStripCount);

    TriangleFanArray rearShaftFace = new TriangleFanArray(
        shaftFaceVertexCount, GeometryArray.COORDINATES
            | GeometryArray.NORMALS, shaftFaceStripCount);

    coordinate.set(0.0f0.0f, frontZ);
    frontShaftFace.setCoordinate(0, coordinate);
    frontShaftFace.setNormal(0, frontNormal);

    coordinate.set(0.0f0.0f, rearZ);
    rearShaftFace.setCoordinate(0, coordinate);
    rearShaftFace.setNormal(0, rearNormal);

    for (int index = 1; index < segmentCount + 2; index++) {

      tempAngle = segmentAngle * -(doubleindex;
      coordinate.set(radius * (floatMath.cos(tempAngle), radius
          (floatMath.sin(tempAngle), frontZ);
      frontShaftFace.setCoordinate(index, coordinate);
      frontShaftFace.setNormal(index, frontNormal);

      tempAngle = -tempAngle;
      coordinate.set(radius * (floatMath.cos(tempAngle), radius
          (floatMath.sin(tempAngle), rearZ);
      rearShaftFace.setCoordinate(index, coordinate);
      rearShaftFace.setNormal(index, rearNormal);
    }
    newShape = new Shape3D(frontShaftFace, look);
    this.addChild(newShape);
    newShape = new Shape3D(rearShaftFace, look);
    this.addChild(newShape);

    // Construct shaft's outer skin (the cylinder body)
    shaftVertexCount = * segmentCount + 2;
    shaftStripCount[0= shaftVertexCount;

    TriangleStripArray shaft = new TriangleStripArray(shaftVertexCount,
        GeometryArray.COORDINATES | GeometryArray.NORMALS,
        shaftStripCount);

    outNormal.set(1.0f0.0f0.0f);

    coordinate.set(radius, 0.0f, rearZ);
    shaft.setCoordinate(0, coordinate);
    shaft.setNormal(0, outNormal);

    coordinate.set(radius, 0.0f, frontZ);
    shaft.setCoordinate(1, coordinate);
    shaft.setNormal(1, outNormal);

    for (int count = 0; count < segmentCount; count++) {
      int index = + count * 2;

      tempAngle = segmentAngle * (double) (count + 1);
      xDirection = (floatMath.cos(tempAngle);
      yDirection = (floatMath.sin(tempAngle);
      xShaft = radius * xDirection;
      yShaft = radius * yDirection;
      outNormal.set(xDirection, yDirection, 0.0f);

      coordinate.set(xShaft, yShaft, rearZ);
      shaft.setCoordinate(index, coordinate);
      shaft.setNormal(index, outNormal);

      coordinate.set(xShaft, yShaft, frontZ);
      shaft.setCoordinate(index + 1, coordinate);
      shaft.setNormal(index + 1, outNormal);
    }
    newShape = new Shape3D(shaft, look);
    this.addChild(newShape);
  }
}




           
       
Related examples in the same category
www.java2java.com | Contact Us
Copyright 2010 - 2030 Java Source and Support. All rights reserved.
All other trademarks are property of their respective owners.