package transp;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import javax.swing.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.universe.*;
public class TestTransp extends JApplet
{
boolean isStandalone = false;
static JFrame frame = null;
/**Get a parameter value*/
public String getParameter(String key, String def)
{
return isStandalone ? System.getProperty(key, def) :
(getParameter(key) != null ? getParameter(key) : def);
}
/**Construct the applet*/
public TestTransp()
{
}
/**Initialize the applet*/
public void init()
{
try
{
jbInit();
}
catch(Exception e)
{
e.printStackTrace();
}
} // end init()
/**Component initialization*/
private void jbInit() throws Exception
{
try
{
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} // end try part
catch(Exception e)
{
System.out.println("Error setting Windows LAF: " + e);
} // end catch part
if (frame == null) setupFrame();
// Build the initial scene.
Canvas3D the3DCanvas = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
SimpleUniverse theSimpleUniverse = new SimpleUniverse(the3DCanvas);
BranchGroup scene = createInitialSceneGraph(theSimpleUniverse);
theSimpleUniverse.addBranchGraph(scene);
// Put objects into frame window.
frame.getContentPane().add("Center", the3DCanvas);
frame.setVisible(true);
} // end jbInit()
void setupFrame()
{
Toolkit theKit = this.getToolkit();
Dimension windowSize = theKit.getScreenSize();
frame = new JFrame()
{
protected void processWindowEvent(WindowEvent e)
{
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING)
{
System.exit(0);
}
}
public synchronized void setTitle(String title)
{
super.setTitle(title);
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
}
};
frame.getContentPane().setBackground(Color.black);
frame.setSize(new Dimension(windowSize.width / 2, windowSize.height / 2));
frame.getContentPane().setLayout(new BorderLayout());
} // end setupFrame
/**Start the applet*/
public void start()
{
}
/**Stop the applet*/
public void stop()
{
}
/**Destroy the applet*/
public void destroy()
{
}
/**Get Applet information*/
public String getAppletInfo()
{
return "Applet Information";
}
/**Get parameter info*/
public String[][] getParameterInfo()
{
return null;
}
/**Main method*/
public static void main(String[] args)
{
TestTransp applet = new TestTransp();
applet.isStandalone = true;
// I like seperate window for 3D stuff.
if (frame == null) applet.setupFrame();
applet.init();
applet.start();
} // end main
/////////////////////////////////////////
// Methods for creating various objects
// for testing transparency.
public BranchGroup createInitialSceneGraph(SimpleUniverse SU)
{
// Create the root of the branch graph
BranchGroup objRoot = new BranchGroup();
BoundingSphere worldBounds = new BoundingSphere(new Point3d( 0.0, 0.0, 0.0 ), 10000.0 );
// Create an (ambient) light source
TransformGroup lightTG = new TransformGroup();
Transform3D lightT3D = new Transform3D();
lightT3D.set(new Vector3d(20.0, 0.0, 0.0));
DirectionalLight DL = new DirectionalLight(new Color3f(1.0f, 1.0f, 1.0f),
new Vector3f(-1.0f, 0.0f, 0.0f));
DL.setInfluencingBounds(worldBounds);
lightTG.setTransform(lightT3D);
lightTG.addChild(DL);
objRoot.addChild(lightTG);
AmbientLight lightA = new AmbientLight();
lightA.setInfluencingBounds(worldBounds);
objRoot.addChild(lightA);
// Set the initial viewing platform location
TransformGroup vpTG = null;
Transform3D vpT3D = new Transform3D();
vpTG = SU.getViewingPlatform().getViewPlatformTransform();
vpT3D.lookAt(new Point3d(20.0, 0.0, 0.0),
new Point3d(0.0, 0.0, 0.0),
new Vector3d(0.0, 0.0, 1.0));
vpT3D.invert();
vpTG.setTransform(vpT3D);
// For transparency, make sure everything is rendered in correct depth order.
// SU.getViewer().getView().setDepthBufferFreezeTransparent(false);
SU.getViewer().getView().setDepthBufferFreezeTransparent(true);
SU.getViewer().getView().setTransparencySortingPolicy(View.TRANSPARENCY_SORT_GEOMETRY);
SU.getViewer().getView().setBackClipDistance(100.0);
// Create background.
Background BGround = new Background();
BGround.setApplicationBounds(worldBounds);
objRoot.addChild(BGround);
// Make the objects to be displayed.
TransformGroup objTG = new TransformGroup();
Transform3D objT3D = new Transform3D();
objT3D.rotY(d2r(30.0));
objTG.setTransform(objT3D);
objTG.addChild(makeObjects());
objRoot.addChild(objTG);
return(objRoot);
} // end of createSceneGraph method
BranchGroup makeObjects()
{
BranchGroup BG = new BranchGroup();
// Create the torus
Shape3D Torus;
////////////////////////////////////////////
// Create the torus-like geometry.
// Outer
Shape3D Torus1 = createTorusGeometry2(10.0f, 85.0f, 5.0f, 0.5f);
Torus1.setAppearance(createTorusAppearance(Color.red));
// Middle
Shape3D Torus2 = createTorusGeometry2(15.0f, 80.0f, 4.0f, 0.7f);
Torus2.setAppearance(createTorusAppearance(Color.blue));
// Inner most torus
Shape3D Torus3 = createTorusGeometry2(20.0f, 70.0f, 3.0f, 0.9f);
Torus3.setAppearance(createTorusAppearance(Color.green));
// Use an ordered group so *we* control the order in which objects
// get rendered.
OrderedGroup OBG = new OrderedGroup();
OBG.addChild(Torus3); // render this one 1st
OBG.addChild(Torus2); // render this one 2nd
OBG.addChild(Torus1); // render this one 3rd
BG.addChild(OBG);
return BG;
} // end makeObjects
Shape3D createTorusGeometry2(float startTheta, float endTheta,
float radius, float funnelRadius)
{
// This method creates one QuadArray for the entire object.
// The QuadArray will have many quad coordinates and normals defined.
Shape3D theShape3D = new Shape3D();
float thetaInc = 5.0f; // 5 degree increaments.
float phiInc = 5.0f; // 5 degree increaments.
int numThetaDiv = (int)((endTheta - startTheta) / thetaInc) + 1;
int numPhiDiv = (int)(360.0f / phiInc);
Vector3f[][] thePoints = new Vector3f[numPhiDiv][numThetaDiv+1];
// populate the first longitude circle.
float x;
float y;
float z;
int i = 0;
int j = 0;
for (float phi=0.0f; phi<360.0f; phi=phi+phiInc)
{
j = 0;
for (float theta=startTheta; theta<=endTheta; theta=theta+thetaInc)
{
// calculate the inside funnel point.
if (j == 0)
{
x = (float)(funnelRadius * Math.cos(d2r(phi)));
y = (float)(funnelRadius * Math.sin(d2r(phi)));
z = (float)(radius * Math.cos(d2r(endTheta)));
thePoints[i][j] = new Vector3f(x, y, z);
j = j + 1;
} // end if statement
x = (float)(radius * Math.sin(d2r(theta)) * Math.cos(d2r(phi)));
y = (float)(radius * Math.sin(d2r(theta)) * Math.sin(d2r(phi)));
z = (float)(radius * Math.cos(d2r(theta)));
thePoints[i][j] = new Vector3f(x, y, z);
j = j + 1;
} // end for theta statement
i = i + 1;
} // end for phi statement
// We now have all the points to make the geometry.
Vector3f hld1 = new Vector3f(0.0f, 0.0f, 0.0f);
Vector3f hld2 = new Vector3f(0.0f, 0.0f, 0.0f);
System.out.println("i: "+i+" j: "+j);
int numPoints = 2 * (4 * i * j );
Point3f[] coord = new Point3f[numPoints];
Vector3f[] norms = new Vector3f[numPoints];
QuadArray qa = new QuadArray(numPoints, QuadArray.COORDINATES | QuadArray.NORMALS);
int p = 0;
for (int m=0; m<i; m++)
{
for (int n=0; n<j; n++)
{
int a = m+1;
if (a == i) a = 0;
int b = n+1;
if (b == j) b = 0;
coord[p+0] = new Point3f(thePoints[m][n]);
coord[p+1] = new Point3f(thePoints[m][b]);
coord[p+2] = new Point3f(thePoints[a][b]);
coord[p+3] = new Point3f(thePoints[a][n]);
hld1 = new Vector3f((coord[p+0].x - coord[p+1].x),
(coord[p+0].y - coord[p+1].y),
(coord[p+0].z - coord[p+1].z));
hld2 = new Vector3f((coord[p+2].x - coord[p+1].x),
(coord[p+2].y - coord[p+1].y),
(coord[p+2].z - coord[p+1].z));
norms[p+0] = new Vector3f(0.0f, 0.0f, 0.0f);
norms[p+0].cross(hld2, hld1);
norms[p+0].normalize();
norms[p+1] = new Vector3f(norms[p+0]);
norms[p+2] = new Vector3f(norms[p+0]);
norms[p+3] = new Vector3f(norms[p+0]);
p = p + 4;
// negative z part
coord[p+0] = new Point3f(thePoints[m][n].x, thePoints[m][n].y, -thePoints[m][n].z);
coord[p+1] = new Point3f(thePoints[m][b].x, thePoints[m][b].y, -thePoints[m][b].z);
coord[p+2] = new Point3f(thePoints[a][b].x, thePoints[a][b].y, -thePoints[a][b].z);
coord[p+3] = new Point3f(thePoints[a][n].x, thePoints[a][n].y, -thePoints[a][n].z);
hld1 = new Vector3f((coord[p+0].x - coord[p+1].x),
(coord[p+0].y - coord[p+1].y),
(coord[p+0].z - coord[p+1].z));
hld2 = new Vector3f((coord[p+2].x - coord[p+1].x),
(coord[p+2].y - coord[p+1].y),
(coord[p+2].z - coord[p+1].z));
norms[p+0] = new Vector3f(0.0f, 0.0f, 0.0f);
norms[p+0].cross(hld2, hld1);
norms[p+0].normalize();
norms[p+1] = new Vector3f(norms[p+0]);
norms[p+2] = new Vector3f(norms[p+0]);
norms[p+3] = new Vector3f(norms[p+0]);
p = p + 4;
} // end for j statement
} // end for i statement
qa.setCoordinates(0, coord);
qa.setNormals(0, norms);
theShape3D.addGeometry(qa);
return(theShape3D);
} // end createTorusGeometry2()
Appearance createTorusAppearance(Color theColor)
{
// This is the Appearance used to color the object (Shape3D).
// It assigns the transparency attributes.
// Playing with the various transparency settings tofigure
// out if there is a transparency problem or a coding problem.
float red = theColor.getRed() / 255.0f;
float green = theColor.getGreen() / 255.0f;
float blue = theColor.getBlue() / 255.0f;
Appearance A = new Appearance();
RenderingAttributes RA = new RenderingAttributes();
RA.setDepthBufferEnable(true);
A.setRenderingAttributes(RA);
// We want the color to be defined by using materials.
Material theMaterial = new Material();
theMaterial.setLightingEnable(true);
theMaterial.setShininess(5.0f);
theMaterial.setDiffuseColor(red, green, blue);
theMaterial.setAmbientColor(0.1f, 0.1f, 0.1f);
theMaterial.setEmissiveColor(0.0f, 0.0f, 0.0f);
theMaterial.setSpecularColor(0.08f, 0.08f, 0.08f);
A.setMaterial(theMaterial);
// Setup polygon attributes
PolygonAttributes PA = new PolygonAttributes(PolygonAttributes.POLYGON_FILL,
PolygonAttributes.CULL_BACK, 0.01f, true);
A.setPolygonAttributes(PA);
// Setup Treansparency
TransparencyAttributes TA = new TransparencyAttributes(TransparencyAttributes.NICEST, 0.5f);
A.setTransparencyAttributes(TA);
return(A);
} // end createAppearancePlane
static public double d2r(double angle)
{
return (angle * 2.0 * Math.PI / 360.0 );
} // end d2r
static public double r2d(double angle)
{
return (angle * 360.0) / (2.0 * Math.PI);
} // end r2d
}