

import java.lang.Math.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import javax.media.j3d.Text3D;
import java.awt.Font;
import com.sun.j3d.utils.geometry.Cylinder;


public class AxisBody extends TransformGroup {
     
    float length, radius;
    int nsegs;
    Appearance app;
    
     float xDirection, yDirection;
     float xVecBody, yVecBody;
     float endcapPos;
     float basecapPos;
     
     private String fontName = "TestFont";
     int nFaces;          // #(vertices) per VecBody face
     int VecBodyFaceTotalVertexCount;     // total #(vertices) in all teeth
     int nStrips[] = new int[1]; // per VecBody vertex count
     
     int VecBodyVertexCount;      // #(vertices) for VecBody
     int VecBodyStripCount[] = new int[1]; // #(vertices) in strip/strip
      
     Point3f coord = new Point3f(0.0f, 0.0f, 0.0f);
     
        
        // The angle subtended by a single segment
        double segmentAngle = 2.0 * Math.PI/nsegs;
        double tempAngle;        
    
 
        
        
    public AxisBody(int nsegs, float length, float radius, Appearance app) {
        
        this.nsegs = nsegs;
        this.length = length;
        this.radius = radius;

        this.app = app;
        
        //allow capability to write and read at runtime
        
        this.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        this.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
     
        Transform3D tempTrans = new Transform3D();
        Transform3D t2 = new Transform3D();
        //create an empty shape to add Geometry
          
        //Shape3D zaxis =  new Shape3D();
        //zaxis.setAppearance(app);
        //zaxis.addGeometry(this.makeBody(-length/2, length/2));          
       // this.addChild(zaxis);
            
        this.addChild(new Cylinder(radius,length,app));
     //   Point3f ylabelpt = new Point3f( 0.f, 0.f, 0.f );
       // this.addChild(MakeLabels("Y",ylabelpt));     
 
        TransformGroup xTG = new TransformGroup();
        tempTrans.rotX(Math.PI/2);
 
        t2.rotZ(Math.PI/2);
        tempTrans.mul(t2);
        
        xTG.setTransform(tempTrans);
        xTG.addChild(new Cylinder(radius,length));
     //   Point3f xlabelpt = new Point3f( length*.52f, 0.f, 0.f);
     //   xTG.addChild(MakeLabels("X",xlabelpt)); 
        
        this.addChild(xTG);
      
        tempTrans.setIdentity();
        t2.setIdentity();
        TransformGroup zTG = new TransformGroup();
        
        tempTrans.rotX(Math.PI/2);
        zTG.setTransform(tempTrans);
   
        zTG.addChild(new Cylinder(radius,length));
       // Point3f zlabelpt = new Point3f( 0.f, 0.f, .05f*length*.52f);
      //  zTG.addChild(MakeLabels("Z",zlabelpt));     
 
        
        this.addChild(zTG);
    }      
    public TransformGroup MakeLabels(String s, Point3f p) {
        
        Font3D f3d = new Font3D(new Font(fontName, Font.PLAIN, 1),
                                new FontExtrusion());
        
        int sl = s.length();

        Appearance apText = new Appearance();
        
        
        Text3D txt = new Text3D(f3d, s, p); 
        Shape3D textShape = new Shape3D();
        textShape.setGeometry(txt);
        textShape.setAppearance(apText);

        TransformGroup textTG = new TransformGroup();
        Transform3D ttext = new Transform3D();
        ttext.setScale(0.05f);
        textTG.setTransform(ttext);
        textTG.addChild(textShape);
   
        // Using billboard behavior on text3d

   
      
        TransformGroup bbTransPt = new TransformGroup();
        //bbTransPt.setTransform(ttext);
        bbTransPt.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        bbTransPt.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        Billboard bboardPt = new Billboard( bbTransPt );
        this.addChild( bboardPt );
        BoundingSphere bounds =
            new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
 
        bboardPt.setSchedulingBounds( bounds );
        bboardPt.setAlignmentMode(Billboard.ROTATE_ABOUT_POINT);

        // text is centered around 0, 3, 0.  Make it rotate around 0,5,0
        //Point3f rotationPt = new Point3f(0.0f, 5.f, 0.0f);
        //bboardPt.setRotationPoint(p);
        bbTransPt.addChild( textTG );
        
        return bbTransPt;
    }
               
  
 public Geometry makeDisk(float dirmult, float facePosition) {    
      
     System.out.println("makeDisk");
     Vector3f faceNormal = new Vector3f(0.0f, 0.0f, 1.0f);
     nFaces = nsegs + 2;
        nStrips[0] = nFaces;
        
     TriangleFanArray endCap
            = new TriangleFanArray(nFaces,
                                     GeometryArray.COORDINATES
                                    | GeometryArray.NORMALS,
                                     nStrips);

     coord.set(0.0f, 0.0f, facePosition);

     endCap.setCoordinate(0, coord);
     endCap.setNormal(0, faceNormal);
   

     for (int ii = 1; ii < nsegs+2; ii++) {
          tempAngle = dirmult * segmentAngle * -(double)ii;
          
          coord.set(radius * (float)Math.cos(tempAngle),
                            radius * (float)Math.sin(tempAngle),
                            facePosition);
          endCap.setCoordinate(ii, coord);
          endCap.setNormal(ii, faceNormal);            
    }
        
    return endCap;       
 }  
     
 public Geometry makeBody(float basePos, float endPos) {
         
         // Outward facing normal
        Vector3f outNormal = new Vector3f(1.0f, 0.0f, 0.0f);
        // Construct VecBody's outer skin (the cylinder body)
        VecBodyVertexCount = 2 * nsegs + 2;
        VecBodyStripCount[0] = VecBodyVertexCount;

        TriangleStripArray vecBody
            = new TriangleStripArray(VecBodyVertexCount,
                                     GeometryArray.COORDINATES
                                     | GeometryArray.NORMALS,
                                     VecBodyStripCount);


        coord.set(radius, 0.0f, basePos);
        vecBody.setCoordinate(0, coord);
        vecBody.setNormal(0, outNormal);

        coord.set(radius, 0.0f, endPos);
        vecBody.setCoordinate(1, coord);
        vecBody.setNormal(1, outNormal);

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

            tempAngle = segmentAngle * (double)(count + 1);
            xDirection = (float)Math.cos(tempAngle);
            yDirection = (float)Math.sin(tempAngle);
            xVecBody = radius * xDirection;
            yVecBody = radius * yDirection;
            outNormal.set(xDirection, yDirection, 0.0f);

            coord.set(xVecBody, yVecBody, basePos);
            vecBody.setCoordinate(index, coord);
            vecBody.setNormal(index, outNormal);
            
            coord.set(xVecBody, yVecBody, endPos);
            vecBody.setCoordinate(index + 1, coord);
            vecBody.setNormal(index + 1, outNormal);
        }
        
       return vecBody;  
    }  //end method
} //end class
