view tools/java3d-test/src/graff3d.java @ 13:0652ac3c8b5f

add two_obj
author axmo
date Mon, 11 Aug 2008 22:20:03 +0900
parents
children
line wrap: on
line source

// Draw the graph of a function
//		version 1.0  (c) K.Sasano

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.Font;
import java.awt.GraphicsConfiguration;
import java.util.Enumeration;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.applet.MainFrame; 
import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.behaviors.mouse.MouseTranslate;
import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
import com.sun.j3d.utils.geometry.Text2D;

public class graff3d extends Applet {

	// global variables
	float xwidth;
	float x0;
	float ywidth;
	float y0;
	float xdelta;
	float ydelta;
	float z0;
	float zwidth;
	float zvalue[][];
	float zcenter[][];
	Shape3D surfaceGraph;
	Shape3D meshGraph;
	Shape3D xyPlane;
	Shape3D xyzAxes;
	Shape3D xyzArrowHead;
	TransformGroup xyzAxesLabels;
	
	//key behavior
	public class KeyBehavior extends Behavior{
		
		private BranchGroup bg;
		private WakeupOnAWTEvent wue;

		KeyBehavior(BranchGroup bg){
			this.bg=bg;
		}
		
		public void initialize(){
			this.wakeupOn(wue = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));
		}
		
		public void processStimulus(Enumeration criteria){
			AWTEvent ae = (wue.getAWTEvent())[0];
			char c=((KeyEvent)ae).getKeyChar();
			TransparencyAttributes 
				surftr = (surfaceGraph.getAppearance()).getTransparencyAttributes();
			TransparencyAttributes	
				meshtr = (meshGraph.getAppearance()).getTransparencyAttributes();
			TransparencyAttributes
				xytr = (xyPlane.getAppearance()).getTransparencyAttributes();
			
			if(c=='s'){ //Show/Erase surfacegraph
				addSurface=!addSurface;
				if(addSurface){
					surftr = new TransparencyAttributes(TransparencyAttributes.NONE,0.0f);
				}else{
					surftr = new TransparencyAttributes(TransparencyAttributes.NICEST,1.0f);
				}
			}
			if(c=='m'){ //Show/Erase meshgraph
				float tr;
				addMesh=!addMesh;
				if(addMesh){ tr= 0.0f; } else { tr=1.0f; }
				meshtr = new TransparencyAttributes(TransparencyAttributes.NICEST,tr);
			}
			if(c=='z'){ //Show/Erase xyplane
				float tr;
				addXYPlane=!addXYPlane;
				if(addXYPlane){ tr= 0.6f; } else { tr=1.0f; }
				xytr = new TransparencyAttributes(TransparencyAttributes.NICEST,tr);
			}
			(xyPlane.getAppearance()).setTransparencyAttributes(xytr);
			(meshGraph.getAppearance()).setTransparencyAttributes(meshtr);
			(surfaceGraph.getAppearance()).setTransparencyAttributes(surftr);

			this.wakeupOn(wue = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));
		}
	}
	
	//create scene
	public BranchGroup createSceneGraph() {
		BranchGroup objRoot = new BranchGroup();
		BoundingSphere bounds = new BoundingSphere();
		bounds.setRadius( 1000.0 );

		//prepare for movement
		TransformGroup objTrans = new TransformGroup();
		objRoot.addChild(objTrans);

		objTrans.setCapability( TransformGroup.ALLOW_TRANSFORM_READ );
		objTrans.setCapability( TransformGroup.ALLOW_TRANSFORM_WRITE );

		MouseRotate rotat = new MouseRotate( objTrans );
		MouseTranslate trans = new MouseTranslate( objTrans );
		MouseZoom zoom = new MouseZoom( objTrans );

		rotat.setSchedulingBounds( bounds );
		trans.setSchedulingBounds( bounds );
		zoom.setSchedulingBounds( bounds );

		objTrans.addChild(rotat);
		objTrans.addChild(trans);
		objTrans.addChild(zoom);

		//add xy-plane
		objTrans.addChild(xyPlane);
		
		//add graphs
		objTrans.addChild(surfaceGraph);
		objTrans.addChild(meshGraph);
		
		//add axes
		objTrans.addChild(xyzAxes);  //axis
		objTrans.addChild(xyzArrowHead);  //arrowhead
		objTrans.addChild(xyzAxesLabels);  //label
		
		//add key behavior
		KeyBehavior myKeyBehav=new KeyBehavior(objRoot);
		myKeyBehav.setSchedulingBounds( bounds );
		objRoot.addChild(myKeyBehav);

		//compile the object
		objRoot.compile();
		
		return objRoot;
	}

	//surface graph
	private Shape3D graph(){
		int totalN=6*n*n;
		
		Point3f coord[] = new Point3f[totalN];
		Color3f color[] = new Color3f[totalN];
		
		for(int i=0; i<n; i++){
			float xi=xmin+i*xdelta;
			float xii=xi+xdelta;
			float xcenter=xi+0.5f*xdelta;
			for(int j=0; j<n; j++){
				int tmp=6*(i*n+j);
				float yj=ymin+j*ydelta;
				float yjj=yj+ydelta;
				float ycenter=yj+0.5f*ydelta;

				coord[tmp]=new Point3f(xn(xcenter),yn(ycenter),zn(zcenter[i][j]));
				coord[tmp+1]=new Point3f(xn(xi),yn(yj),zn(zvalue[i][j]));
				coord[tmp+2]=new Point3f(xn(xii),yn(yj),zn(zvalue[i+1][j]));
				coord[tmp+3]=new Point3f(xn(xii),yn(yjj),zn(zvalue[i+1][j+1]));
				coord[tmp+4]=new Point3f(xn(xi),yn(yjj),zn(zvalue[i][j+1]));
				coord[tmp+5]=coord[tmp+1];
				
				color[tmp]=hcolor(zn(zcenter[i][j]));
				color[tmp+1]=hcolor(zn(zvalue[i][j]));
				color[tmp+2]=hcolor(zn(zvalue[i+1][j]));
				color[tmp+3]=hcolor(zn(zvalue[i+1][j+1]));
				color[tmp+4]=hcolor(zn(zvalue[i][j+1]));
				color[tmp+5]=color[tmp+1];
			}
		}
		
		int stripCounts[] = new int[n*n];
		for(int i=0; i<n*n; i++){stripCounts[i]=6;}
		
		TriangleFanArray tfa =
			new TriangleFanArray(
				totalN,
				TriangleFanArray.COORDINATES|TriangleFanArray.COLOR_3,
				stripCounts
			);
		tfa.setCoordinates(0,coord);
		tfa.setColors(0,color);
		
		//construct appearence
		TransparencyAttributes surftr;
		if(addSurface){
			surftr = new TransparencyAttributes(TransparencyAttributes.NONE,0.0f);
		}else{
			surftr = new TransparencyAttributes(TransparencyAttributes.NICEST,1.0f);
		}
		PolygonAttributes attr = new PolygonAttributes();
		attr.setCullFace(PolygonAttributes.CULL_NONE);
		attr.setPolygonMode(PolygonAttributes.POLYGON_FILL);

		Appearance appear = new Appearance();
		appear.setPolygonAttributes(attr);
		appear.setCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_READ);
		appear.setCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_WRITE);
		appear.setTransparencyAttributes(surftr);

		//construct Shape3D for surface graph
		Shape3D graphshape=new Shape3D();
		graphshape.removeGeometry(0);
		graphshape.addGeometry(tfa);
		graphshape.setAppearance(appear);
		graphshape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
		graphshape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);

		return graphshape;
	}
	
	//color data corresponding to the height
	private Color3f hcolor(float h){
		float r,g,b;
		h=h*2;
		if(h>1){ r=1.0f; g=0.5f; b=0.0f; }
		else if(h>0){ r=h*1.0f; g=0.75f-h*0.25f; b=0.0f; }
		else if(h>-1){ r=0.0f; g=(1+h)*0.75f; b= -h*0.75f; }
		else{ r=0.0f; g=0.0f; b=0.75f;}
		return new Color3f(r,g,b);
	}
	
	//mesh graph
	private Shape3D meshgraph(){
		//construct coordinat data
		int totalN=2*(nmesh+1)*(nmesh+1);
		
		Point3f coord[] = new Point3f[totalN];
		Color3f color[] = new Color3f[totalN];
		Color3f lcolor = new Color3f(1.0f, 1.0f, 1.0f);
		
		for(int i=0; i<=nmesh; i++){
			float xi=xmin+i*(xmax-xmin)/nmesh;

			for(int j=0; j<=nmesh; j++){
				int tmp=i*(nmesh+1)+j;
				int tmp1=j*(nmesh+1)+i+(nmesh+1)*(nmesh+1);
				float yj=ymin+j*(ymax-ymin)/nmesh;
				
				coord[tmp]=new Point3f(xn(xi),yn(yj),zn(f(xi,yj)));
				color[tmp]=lcolor;
				
				coord[tmp1]=coord[tmp];
				color[tmp1]=color[tmp];
				}
		}
		
		int stripCounts[];
		stripCounts= new int[2*(nmesh+1)];
		for(int i=0; i<=2*nmesh+1; i++){stripCounts[i]=nmesh+1;}
		
		LineStripArray lsa =
			new LineStripArray(
				totalN,
				LineStripArray.COORDINATES|LineStripArray.COLOR_3,
				stripCounts
			);
		lsa.setCoordinates(0,coord);
		lsa.setColors(0,color);
		
		//construct appearence
		LineAttributes attr = new LineAttributes();
		attr.setLineWidth(meshLineWidth);

		float tr;
		if(addMesh){ tr= 0.0f; } else { tr=1.0f; }
		TransparencyAttributes transAttrib;
		transAttrib = new TransparencyAttributes(TransparencyAttributes.NICEST,tr);

		Appearance appear = new Appearance();
		appear.setLineAttributes(attr);
		appear.setTransparencyAttributes(transAttrib);
		appear.setCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_READ);
		appear.setCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_WRITE);
		
		//construct Shape3D for meshgraph
		Shape3D graphshape=new Shape3D();
		graphshape.removeGeometry(0);
		graphshape.addGeometry(lsa);
		graphshape.setAppearance(appear);
		graphshape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
		graphshape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);

		return graphshape;
	}

	//xy-plane
	private Shape3D xyplane(){
		QuadArray xyp= new QuadArray(4,QuadArray.COORDINATES|QuadArray.COLOR_3);
		xyp.setCoordinate(0,new Point3f(0.5f,0.5f,zn(0.0f)));
		xyp.setCoordinate(1,new Point3f(-0.5f,0.5f,zn(0.0f)));
		xyp.setCoordinate(2,new Point3f(-0.5f,-0.5f,zn(0.0f)));
		xyp.setCoordinate(3,new Point3f(0.5f,-0.5f,zn(0.0f)));
		for(int i=0; i<4; i++){xyp.setColor(i, new Color3f(1.0f,1.0f,1.0f));}

		PolygonAttributes attrib = new PolygonAttributes();
		attrib.setCullFace(PolygonAttributes.CULL_NONE);
		attrib.setPolygonMode(PolygonAttributes.POLYGON_FILL);
		
		TransparencyAttributes transAttrib;
		float tr;
		if(addXYPlane){ tr= 0.6f; } else { tr=1.0f; }
		transAttrib = new TransparencyAttributes(TransparencyAttributes.NICEST,tr);

		Appearance appear = new Appearance();
		appear.setPolygonAttributes(attrib);
		appear.setTransparencyAttributes(transAttrib);
		appear.setCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_READ);
		appear.setCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_WRITE);

		Shape3D xyplaneshape=new Shape3D();
		xyplaneshape.removeGeometry(0);
		xyplaneshape.addGeometry(xyp);
		xyplaneshape.setAppearance(appear);
		xyplaneshape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
		xyplaneshape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);

		return xyplaneshape;
	}
	
	//axes
	private Shape3D axes(){
		LineArray a=new LineArray(6,LineArray.COORDINATES|LineArray.COLOR_3);
		a.setCoordinate(0,new Point3f(0.6f,yn(0.0f),zn(0.0f)));
		a.setCoordinate(1,new Point3f(-0.6f,yn(0.0f),zn(0.0f)));
		a.setCoordinate(2,new Point3f(xn(0.0f),0.6f,zn(0.0f)));
		a.setCoordinate(3,new Point3f(xn(0.0f),-0.6f,zn(0.0f)));
		a.setCoordinate(4,new Point3f(xn(0.0f),yn(0.0f),0.6f));
		a.setCoordinate(5,new Point3f(xn(0.0f),yn(0.0f),-0.6f));
		for(int i=0; i<6; i++){ a.setColor(i,new Color3f(1.0f,1.0f,0.0f));}
		
		LineAttributes att=new LineAttributes();
		att.setLineWidth(2.0f);
		Appearance appear = new Appearance();
		appear.setLineAttributes(att);

		Shape3D ax=new Shape3D();
		ax.removeGeometry(0);
		ax.addGeometry(a);
		ax.setAppearance(appear);
		
		return ax;
	}
	
	//arrowhead
	private Shape3D arrowhead(){
		int scounts[]= new int[3];
		for(int i=0; i<3; i++){scounts[i]=10;}
		
		TriangleFanArray ah=new TriangleFanArray(30,
			TriangleFanArray.COORDINATES|TriangleFanArray.COLOR_3,
			scounts);
		ah.setCoordinate(0,new Point3f(0.6f, yn(0.0f), zn(0.0f)));
		ah.setCoordinate(10,new Point3f(xn(0.0f),0.6f, zn(0.0f)));
		ah.setCoordinate(20,new Point3f(xn(0.0f), yn(0.0f), 0.6f));
		float d=(float)Math.PI/4;
		for(int i=0 ; i<=8; i++){
			ah.setCoordinate(i+1, 
				new Point3f(0.55f, yn(0.0f)+0.02f * (float)Math.cos(d*i), zn(0.0f)+0.02f *(float)Math.sin(d*i)));
			ah.setCoordinate(i+11, 
				new Point3f(xn(0.0f)+0.02f * (float)Math.cos(d*i), 0.55f, zn(0.0f)+0.02f *(float)Math.sin(d*i)));
			ah.setCoordinate(i+21, 
				new Point3f(xn(0.0f)+0.02f * (float)Math.cos(d*i), yn(0.0f)+0.02f *(float)Math.sin(d*i), 0.55f));
			}
		Color3f color[]=new Color3f[30];
		for(int i=0; i<30; i++){ color[i]=new Color3f(1.0f, 1.0f, 0.0f);}
		ah.setColors(0,color);
		
		return new Shape3D(ah);
	}
	
	//axes labels
	TransformGroup axeslabels(){
		TransformGroup tmp = new TransformGroup();
		
		PolygonAttributes polyAttrib = new PolygonAttributes();
		polyAttrib.setCullFace(PolygonAttributes.CULL_NONE);
		polyAttrib.setBackFaceNormalFlip(true);

		Transform3D xmov= (new Transform3D());
		xmov.set(new Vector3f(0.63f,yn(0.0f)-0.05f,zn(0.0f)));
		Text2D xlbl=new Text2D("x",new Color3f(1.0f,1.0f,0.0f),"Helvetica",24,Font.BOLD);
		(xlbl.getAppearance()).setPolygonAttributes(polyAttrib);
		TransformGroup xmovg=new TransformGroup(xmov);
		xmovg.addChild(xlbl);
		
		Transform3D ymov= new Transform3D();
		Transform3D tmpymov=new Transform3D();
		tmpymov.rotZ(Math.PI/2.0d);
		ymov.set(new Vector3f(xn(0.0f)+0.05f,0.63f,zn(0.0f)));
		ymov.mul(tmpymov);
		Text2D ylbl=new Text2D("y",new Color3f(1.0f,1.0f,0.0f),"Helvetica",24,Font.BOLD);
		(ylbl.getAppearance()).setPolygonAttributes(polyAttrib);
		TransformGroup ymovg=new TransformGroup(ymov);
		ymovg.addChild(ylbl);

		Transform3D zmov= new Transform3D();
		Transform3D tmpzmov=new Transform3D();
		tmpzmov.rotX(Math.PI/2.0d);
		zmov.set(new Vector3f(xn(0.0f)-0.02f,yn(0.0f),0.63f));
		zmov.mul(tmpzmov);
		Text2D zlbl=new Text2D("z",new Color3f(1.0f,1.0f,0.0f),"Helvetica",24,Font.BOLD);
		(zlbl.getAppearance()).setPolygonAttributes(polyAttrib);
		TransformGroup zmovg=new TransformGroup(zmov);
		zmovg.addChild(zlbl);

		tmp.addChild(xmovg);
		tmp.addChild(ymovg);
		tmp.addChild(zmovg);
		
		return tmp;
	}

	//get normalized coordinate
	float xn(float x){ return (x-x0)/xwidth;}
	float yn(float y){ return (y-y0)/ywidth;}
	float zn(float z){ return (z-z0)/zwidth;}
	
	//////////// main class ///////////////
	public graph3d() {	
		// preparation for numeric data
		xwidth=xmax-xmin;
		x0=(xmax+xmin)/2;
		ywidth=ymax-ymin;
		y0=(ymax+ymin)/2;
		xdelta=xwidth/n;
		ydelta=ywidth/n;
		
		zvalue = new float[n+1][n+1];
		zcenter = new float[n][n];
	
		int i; int j;
				
		for(i=0; i<=n; i++){
			for(j=0; j<=n; j++){
				zvalue[i][j]=f(xmin+i*xdelta, ymin+j*ydelta);
			}
		}
		for(i=0; i<n; i++){
			for(j=0; j<n; j++){
				zcenter[i][j]=f(xmin+(i+0.5f)*xdelta, ymin+(j+0.5f)*ydelta);
			}
		}
		
		// if necessary, determine zmin and zmax automatically
		if(zmin==0.0f && zmax==0.0f){
			zmin=Float.POSITIVE_INFINITY; zmax=Float.NEGATIVE_INFINITY;
			for(i=0; i<=n; i++){
				for(j=0; j<=n; j++){
					zmin=Math.min(zmin,zvalue[i][j]);
					zmax=Math.max(zmax,zvalue[i][j]);
				}
			}
			for(i=0; i<n; i++){
				for(j=0; j<n; j++){
					zmin=Math.min(zmin,zcenter[i][j]);
					zmax=Math.max(zmax,zcenter[i][j]);
				}
			}
		}
		
		zwidth=zmax-zmin;
		z0=(zmax+zmin)/2;

		/////////// main part ///////////
		setLayout(new BorderLayout());
	
		GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();

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

		SimpleUniverse universe = new SimpleUniverse(canvas);
		universe.getViewingPlatform().setNominalViewingTransform();
		
		//construct graphic objects
		surfaceGraph = graph();
		meshGraph = meshgraph();
		xyPlane = xyplane();
		xyzAxes = axes();
		xyzArrowHead = arrowhead();
		xyzAxesLabels = axeslabels();

		BranchGroup scene = createSceneGraph();
		universe.addBranchGraph(scene);
	}
	
	//main method to make both of Application and Applet	
	public static void main(String[] args) {
		Frame frame = new MainFrame(new graff3d(), 480, 480);
    }

/////////////////////////////////////////////////
// define our function and give necessary data //
/////////////////////////////////////////////////
	
	// our function
	float f(float x, float y){
		return x*x-y*y;
		//return x*x*x + y*y*y - 3*x*y;
		//return (y-x*x)*(y-2*x*x);
		//return (float)Math.sin(x*x+y*y);
		//if(x==0.0f){ return 0.0f; } else { return y*y/x; }
		//if((x==0.0f) && (y==0.0f)){ return 0.5f; } else {return x*y/(x*x+y*y);}
	}
	
	// domain of definition
	float xmin=-1.0f;	// min of x
	float xmax=1.0f;	// max of x
	float ymin=-1.0f;	// min of y
	float ymax=1.0f;	// max of y
	
	// range of the value
	//     If both of zmin and zmax are set to 0.0f, then zmin and zmax
	//     are calculated automatically.
	float zmin=0.0f;	// min of z
	float zmax=0.0f;	// max of z
	
	int n=20;		// number of divisions for surface graph
	int nmesh=20;	// number of divisions for mesh graph
	
	float meshLineWidth=2.0f;	// width of lines in mesh graph
	
	boolean addSurface=true;	// FLAG : show/erase surface graph
	boolean addMesh=true;		// FLAG : show/erase mesh graph
	boolean addXYPlane=false;	// FLAG : show/erase xy-plane
}