note 03- scene node example

 

Scene Node Example , a walk through example

 

 

Main class WalkThrough

 

 

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;

import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLJPanel;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.event.MouseInputAdapter;


import jscene3D.Camera3D;
import jscene3D.CubeGeo;
import jscene3D.ObjectContainer3D;
import jscene3D.Primitive;
import jscene3D.UVConeGeo;
import jscene3D.UVCylinderGeo;
import jscene3D.UVSphereGeo;


public class WalkThroughPanel extends JPanel {
	
	private GLJPanel drawable;
	private JLabel msg;
	
	private ObjectContainer3D theWorld;
	private Camera3D viewer;
	
	private ObjectContainer3D cameraBox;
	
	
	public WalkThroughPanel(){
		
		
		
		GLEventListener glListener=new GLEventListener(){
			
			public void init(GLAutoDrawable drawable){
				GL2 gl=drawable.getGL().getGL2();
				gl.glClearColor(0,0,0.3f,1);
				
				gl.glEnable(GL2.GL_LIGHTING);
				gl.glEnable(GL2.GL_LIGHT0);
				
				gl.glEnable(GL2.GL_DEPTH_TEST);
				gl.glEnable(GL2.GL_COLOR_MATERIAL);
				gl.glEnable(GL2.GL_NORMALIZE);
				
				gl.glShadeModel(GL2.GL_SMOOTH);
			}
			
			public void display(GLAutoDrawable drawable){
				GL2 gl=drawable.getGL().getGL2();
				gl.glClear(GL2.GL_COLOR_BUFFER_BIT|GL2.GL_DEPTH_BUFFER_BIT);
				
				viewer.apply(gl);
				theWorld.draw(gl);
			}
			
			public void reshape(GLAutoDrawable drawable,int x,int y,int width,int height){
				
			}
			
			public void dispose(GLAutoDrawable drawable){
				
			}
		};
		
		
		
		MouseInputAdapter ma=new MouseInputAdapter(){
			
			public void mousePressed(MouseEvent e){
				requestFocus();
			}
		};
		
		
		FocusListener fl=new FocusListener(){
			
			public void focusLost(FocusEvent e){
				setBorder(BorderFactory.createLineBorder(Color.GRAY, 4));
				msg.setText("click to get focus");
			}
			
			public void focusGained(FocusEvent e){
				setBorder(BorderFactory.createLineBorder(Color.CYAN, 4));
				msg.setText("arrow keys=move; r=reset world; home=reset view");
			}
			
		};
		
		KeyAdapter ka=new KeyAdapter(){
			
//			public void keyPressed(KeyEvent e){
//				
//				int code=e.getKeyCode();
//				float angle=viewer.getRotation()[0];
//				float x;
//				float z;
//				float dx;
//				float dz;
//				
//				switch(code){
//				case KeyEvent.VK_UP:
//					dx=viewer.getPosition()[0];
//					dz=viewer.getPosition()[2];
//					x=(float)(0.2*Math.sin(angle*Math.PI/180));
//					z=(float)(0.2*Math.cos(angle*Math.PI/180));
//					viewer.setPosition((float)(dx-x), 0, (float)(dz-z));
//					break;
//					
//				case KeyEvent.VK_DOWN:
//					dx=viewer.getPosition()[0];
//					dz=viewer.getPosition()[2];
//					x=(float)(0.2*Math.sin(angle*Math.PI/180));
//					z=(float)(0.2*Math.cos(angle*Math.PI/180));
//					viewer.setPosition((float)(dx+x), 0, (float)(dz+z));
//					break;
//					
//				case KeyEvent.VK_LEFT:
//					angle=viewer.getRotation()[0];
//					viewer.setRotation(angle+1, 0, 1, 0);
//					break;
//					
//				case KeyEvent.VK_RIGHT:
//					angle=viewer.getRotation()[0];
//					viewer.setRotation(angle-1, 0, 1, 0);
//					break;
//					
//				case KeyEvent.VK_HOME:
//					viewer.setPosition(0, 0, 0);
//					break;
//					
//				case KeyEvent.VK_R:
//					buildWorld();
//					viewer.setPosition(0, 0, 0);
//				}
//				
//				drawable.repaint();
//				
//				
//				
//			}
			
			public void keyPressed(KeyEvent e){
				
				int code=e.getKeyCode();
				float angle=cameraBox.getRotation()[0];
				float x;
				float z;
				float dx;
				float dz;
				
				switch(code){
				case KeyEvent.VK_UP:
					dx=cameraBox.getPosition()[0];
					dz=cameraBox.getPosition()[2];
					x=(float)(0.2*Math.sin(angle*Math.PI/180));
					z=(float)(0.2*Math.cos(angle*Math.PI/180));
					cameraBox.setPosition((float)(dx-x), 0, (float)(dz-z));
					break;
					
				case KeyEvent.VK_DOWN:
					dx=cameraBox.getPosition()[0];
					dz=cameraBox.getPosition()[2];
					x=(float)(0.2*Math.sin(angle*Math.PI/180));
					z=(float)(0.2*Math.cos(angle*Math.PI/180));
					cameraBox.setPosition((float)(dx+x), 0, (float)(dz+z));
					break;
					
				case KeyEvent.VK_LEFT:
					angle=cameraBox.getRotation()[0];
					cameraBox.setRotation(angle+1, 0, 1, 0);
					break;
					
				case KeyEvent.VK_RIGHT:
					angle=cameraBox.getRotation()[0];
					cameraBox.setRotation(angle-1, 0, 1, 0);
					break;
					
				case KeyEvent.VK_HOME:
					cameraBox.setPosition(0, 0, 0);
					break;
					
				case KeyEvent.VK_R:
					buildWorld();
					cameraBox.setPosition(0, 0, 0);
				}
				
				drawable.repaint();
				
				
				
			}
			
		};
		
		
		
		
		drawable=new GLJPanel();
		drawable.setPreferredSize(new Dimension(600,350));
		drawable.addGLEventListener(glListener);
		
		this.setLayout(new BorderLayout());
		this.add(drawable,BorderLayout.CENTER);
		
		msg=new JLabel("Click to focus",JLabel.CENTER);
		msg.setOpaque(true);
		msg.setBackground(Color.LIGHT_GRAY);
		msg.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
		
		this.add(msg,BorderLayout.SOUTH);
		
		
		//hierarchical test 
		viewer=new Camera3D();
		viewer.setPerspectiveParameters(60,0.1f, 100);
		cameraBox=new ObjectContainer3D();
		cameraBox.addChild(viewer);
		
		Primitive sphere=new Primitive(new UVSphereGeo(0.05));
		sphere.setPosition(0, 0, -1);
		
		viewer.addChild(sphere);
//		viewer.removeChild(sphere);
		
		buildWorld();
		this.setBorder(BorderFactory.createLineBorder(Color.GRAY,4));
		
		this.addMouseListener(ma);
		this.addFocusListener(fl);
		this.addKeyListener(ka);
		
	}
	
	
	private void buildWorld(){
		
		ObjectContainer3D world=new ObjectContainer3D();
		world.addChild(new Primitive(new CubeGeo()).setScale(21, 1, 21).setColor(Color.WHITE).setPosition(0, -2, 0));
		
		for(int i=-20;i<=20;i++){
			for(int j=-20;j<=20;j++){
				if(Math.random()<0.02 && (Math.abs(i)>2|| Math.abs(j)>2)){
					ObjectContainer3D r;
					switch((int)(4*Math.random())){
					case 0:
						r=new Primitive(new CubeGeo()).setScale(0.5f,1.0f,0.5f);
						break;
					case 1:
						r=new Primitive(new UVSphereGeo()).setScale(0.5f);
						break;
					case 3:
						r=new Primitive(new UVConeGeo()).setRotation(90, -1, 0, 0).setPosition(0, -1, 0);
						break;
					default:
						r=new Primitive(new UVCylinderGeo()).setRotation(90,-1, 0, 0).setPosition(0, -1, 0);
					}
					
					Color c=Color.getHSBColor((float)Math.random(), (float)(0.5+0.5*Math.random()), 0.8f);
					world.addChild(r.setColor(c).setPosition(i, 0, j));
					//hierarchical test 
					world.addChild(cameraBox);
				}
			}
			
			theWorld=world;
		}
		
	}

}

 

 

 package jscene3D;

Camera3D.java

 

 

package jscene3D;

import javax.media.opengl.GL2;
import javax.media.opengl.glu.GLU;

public class Camera3D extends ObjectContainer3D{
	
	private float fov=45;
	private float near=0.1f;
	private float far=100;
	
	private double eyex, eyey, eyez = 30;
	private double refx, refy, refz;
	private double upx, upy = 1, upz;
	
	private GLU glu=new GLU();
	
	private ObjectContainer3D node=new ObjectContainer3D();
	
	
	public Camera3D(){
		
	}
	
	public void setView(double eyeX, double eyeY, double eyeZ,
            double viewCenterX, double viewCenterY, double viewCenterZ,
            double viewUpX, double viewUpY, double viewUpZ) {
			eyex = eyeX;
			eyey = eyeY;
			eyez = eyeZ;
			refx = viewCenterX;
			refy = viewCenterY;
			refz = viewCenterZ;
			upx = viewUpX;
			upy = viewUpY;
			upz = viewUpZ;
	}
	
	public double[] getView() {
	      return new double[] { eyex, eyey, eyez, refx, refy, refz, upx, upy, upz };
	   }
	
	
	public void apply(GL2 gl){
		
		int[] viewport=new int[4];
		gl.glGetIntegerv(GL2.GL_VIEWPORT,viewport,0);
		
		float aspect=(float)viewport[2]/viewport[3];
		
		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluPerspective(fov, aspect, near, far);
		
		gl.glMatrixMode(GL2.GL_MODELVIEW);
		gl.glLoadIdentity();
		
		node=this;
		
		while(node!=null){
			node.applyInverseTransform(gl);
			node=node.getParent();
		}
		
	}
	
	
	public void setPerspectiveParameters(float fovIn,float nearIn,float farIn){
		if(fovIn<=0 || fov>=180){
			throw new IllegalArgumentException("field of view out of range.");
		}
		if(near<0){
			throw new IllegalArgumentException("near must >0");
		}
		if(far<near){
			throw new IllegalArgumentException("far must > near");
		}
		
		fov=fovIn;
		near=nearIn;
		far=farIn;
	}
	
	public float getFov(){
		return fov;
	}
	
	public float getNear(){
		return near;
	}
	
	public float getFar(){
		return far;
	}

}

 

 

 

 

package jscene3D;

ObjectContainer3D.java

 

 

package jscene3D;

import java.awt.Color;
import java.util.ArrayList;

import javax.media.opengl.GL2;

public class ObjectContainer3D {
	
	private float scaleX=1, scaleY=1, scaleZ=1;
	private float rotation=0;
	private float rotationAxisX=0,rotationAxisY=0,rotationAxisZ=0;
	private float translateX=0,translateY=0,translateZ=0;
	
	private Color color;
	
	private ArrayList<ObjectContainer3D> childrenList=new ArrayList<ObjectContainer3D>();
	
	private ObjectContainer3D parent;
	
	
	public void ObjectContainer3D(){
		
	}
	
	public void draw(GL2 gl){
		
		float[] currentColor=new float[4];
		if(color!=null){
			//save the outside defined color first
			gl.glGetFloatv(GL2.GL_CURRENT_COLOR, currentColor, 0);
		}
		
		//save matrix
		gl.glPushMatrix();
		
		//affine transform first than linear transform 
		gl.glTranslated(translateX,translateY,translateZ);
		gl.glRotatef(rotation, rotationAxisX, rotationAxisY, rotationAxisZ);
		gl.glScalef(scaleX, scaleY, scaleZ);
		
		if(color!=null){
			float[] hsb=color.getColorComponents(null);
			gl.glColor3f(hsb[0], hsb[1], hsb[2]);
		}
		
		drawBasic(gl);
		gl.glPopMatrix();
		
		if(color!=null){
			gl.glColor3f(currentColor[0], currentColor[1], currentColor[2]);
		}
	}
	
	protected void drawBasic(GL2 gl){
		if(childrenList.size()!=0){
			for(ObjectContainer3D child : childrenList){
				child.draw(gl);
			}
		}
		else return;
	}
	
	
	public int turnOnLights(GL2 gl,int nextLightNumber){
		gl.glPushMatrix();
		gl.glTranslatef(translateX,translateY,translateZ);
		gl.glRotatef(rotation, rotationAxisX, rotationAxisY, rotationAxisZ);
		gl.glScaled(scaleX, scaleY, scaleZ);
		nextLightNumber=turnOnLightsBasic(gl,nextLightNumber);
		gl.glPopMatrix();
		return nextLightNumber;
	}
	
	protected int turnOnLightsBasic(GL2 gl,int nextLightNumber){
		return nextLightNumber;
	}
	
	
	public void applyInverseTransform(GL2 gl){
		float sx=(scaleX==0? 1:1/scaleX);
		float sy=(scaleY==0? 1:1/scaleY);
		float sz=(scaleZ==0? 1:1/scaleZ);
		
		//linear transform first than
		gl.glScalef(sx,sy,sz);
		gl.glRotatef(-rotation, rotationAxisX, rotationAxisY, rotationAxisZ);
		
		//than the affine transform
		gl.glTranslatef(-translateX, -translateY, -translateZ);
	}
	
	
	
	public void addChild(ObjectContainer3D child){
		if(child==null) {
			throw new IllegalArgumentException("Can't add a null object");
		}
		childrenList.add(child);
		
		child.setParent(this);
		
	}
	
	public void removeChild(ObjectContainer3D child){
		if(child==null) {
			throw new IllegalArgumentException("Can't add a null object");
		}
		childrenList.remove(child);
		
		child.setParent(null);
	}
	
	public boolean contains(ObjectContainer3D child){
		if(childrenList.contains(child)){
			return true;
		}
		return false;
	}
	
	public int numChildren(){
		return childrenList.size();
	}
	
	
	
	public ObjectContainer3D setScale(float uniformScaleFactor){
		scaleX=scaleY=scaleZ=uniformScaleFactor;
		return this;
	}
	
	public ObjectContainer3D setScale(float scaleXIn,float scaleYIn,float scaleZIn){
		scaleX=scaleXIn;
		scaleY=scaleYIn;
		scaleZ=scaleZIn;
		return this;
	}
	
	public ObjectContainer3D setPosition(float x,float y,float z){
		translateX=x;
		translateY=y;
		translateZ=z;
		return this;
	}
	
	public ObjectContainer3D setRotation(float angle,float xAxis,float yAxis,float zAxis){
		rotation=angle;
		rotationAxisX=xAxis;
		rotationAxisY=yAxis;
		rotationAxisZ=zAxis;
		return this;
	}
	
	public float[] getPosition(){
		return new float[]{translateX,translateY,translateZ};
	}
	
	public float[] getRotation(){
		return new float[]{rotation,rotationAxisX,rotationAxisY,rotationAxisZ};
	}
	
	public float[] getScale(){
		return new float[]{scaleX,scaleY,scaleZ};
	}
	
	
	public ObjectContainer3D setColor(Color color){
		this.color=color;
		return this;
	}
	
	public Color getColor(){
		return color;
	}

	public ObjectContainer3D getParent() {
		return parent;
	}

	public void setParent(ObjectContainer3D parent) {
		this.parent = parent;
	}
	
	
	
	

}
   

package jscene3D;

Entity.java

 

extends ObjectContainer3D and can be set shading

 

 

package jscene3D;

import java.awt.Color;
import java.util.ArrayList;

import javax.media.opengl.GL2;

public class Entity extends ObjectContainer3D{
	
	private float scaleX=1, scaleY=1, scaleZ=1;
	private float rotation=0;
	private float rotationAxisX=0,rotationAxisY=0,rotationAxisZ=0;
	private float translateX=0,translateY=0,translateZ=0;
	
	private ArrayList<ObjectContainer3D> childrenList=new ArrayList<ObjectContainer3D>();
	
	private ObjectContainer3D parent;
	   
	private float[] color;
	private float[] specularColor, diffuseColor, ambientColor, emissionColor;
	   
	private int shininess = -1;
	
	
	
	
	public Entity(){
		
	}
	
	
	public void draw(GL2 gl){
		
		boolean hasColor=(color!=null || specularColor!=null || ambientColor!=null || diffuseColor!=null ||
				emissionColor!=null || shininess>=0);
		
		if(hasColor){
			gl.glPushAttrib(GL2.GL_LIGHTING_BIT|GL2.GL_CURRENT_BIT);
			if(color!=null){
				gl.glGetFloatv(GL2.GL_CURRENT_COLOR, color,0);
			}
			if(ambientColor!=null){
				gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_AMBIENT, ambientColor,0);
			}
			if(diffuseColor!=null){
				gl.glMaterialfv(GL2.GL_FRONT_AND_BACK,GL2.GL_DIFFUSE,diffuseColor,0);
			}
			if(specularColor!=null){
				gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_SPECULAR, specularColor,0);
			}
			if(emissionColor!=null){
				gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_EMISSION, emissionColor, 0);
			}
			if(shininess>=0){
				gl.glMateriali(GL2.GL_FRONT_AND_BACK,GL2.GL_SHININESS,shininess);
			}
			
			gl.glPushMatrix();
			gl.glTranslatef(translateX, translateY, translateZ);
			gl.glRotated(rotation, rotationAxisX, rotationAxisY, rotationAxisZ);
			gl.glScalef(scaleX, scaleY, scaleZ);
			
			drawBasic(gl);
			
			gl.glPopMatrix();
			if(hasColor){
				gl.glPopAttrib();
			}
			
		}
	}
	
	
	
	
	public Entity setColor(Color color) {
	      this.color = color == null? null : color.getRGBColorComponents(null);
	      return this;
	}
	   
	   
	public Entity setColor(float r, float g, float b) {
	      this.color = new float[] { r, g, b, 1 };
	      return this;
	}
	   
	   
	public Entity setColor(float r, float g, float b, float alpha) {
	      this.color = new float[] { r, g, b, alpha };
	      return this;
	}
	   
	public float[] getColorf() {
	      return color;
	}
	   
	   
	public Entity setAmbientAndDiffuseColor(Color c) {
	      this.ambientColor = c == null? null : c.getRGBColorComponents(null);
	      this.diffuseColor = c == null? null : c.getRGBColorComponents(null);
	      return this;
	}

	   
	public Entity setAmbientAndDiffuseColor(float r, float g, float b) {
	      this.ambientColor = new float[] { r, g, b, 1 };
	      this.diffuseColor = new float[] { r, g, b, 1 };
	      return this;
	}
	
	public Entity setAmbientAndDiffuseColor(float r, float g, float b, float alpha) {
	      this.ambientColor = new float[] { r, g, b, alpha };
	      this.diffuseColor = new float[] { r, g, b, alpha };
	      return this;
	}
	   
	public Entity setAmbientColor(Color c) {
	      this.ambientColor = c == null? null : c.getRGBColorComponents(null);
	      return this;
	}

	   
	public Entity setAmbientColor(float r, float g, float b) {
	      this.ambientColor = new float[] { r, g, b, 1 };
	      return this;
	}

	   
	public Entity setAmbientColor(float r, float g, float b, float alpha) {
	      this.ambientColor = new float[] { r, g, b, alpha };
	      return this;
	}
	   
	public float[] getAmbientColor() {
	      return ambientColor;
	}

	   
	public Entity setDiffuseColor(Color c) {
	      this.diffuseColor = c == null? null : c.getRGBColorComponents(null);
	      return this;
	}

	   
	public Entity setDiffuseColor(float r, float g, float b) {
	      this.diffuseColor = new float[] { r, g, b, 1 };
	      return this;
	}

	   
	public Entity setDiffuseColor(float r, float g, float b, float alpha) {
	      this.diffuseColor = new float[] { r, g, b, alpha };
	      return this;
	}
	   
	public float[] getDiffuseColor() {
	      return diffuseColor;
	}

	   
	public Entity setSpecularColor(Color c) {
	      this.specularColor = c == null? null : c.getRGBColorComponents(null);
	      return this;
	}

	   
	public Entity setSpecularColor(float r, float g, float b) {
	      this.specularColor = new float[] { r, g, b, 1 };
	      return this;
	}

	public Entity setSpecularColor(float r, float g, float b, float alpha) {
	      this.specularColor = new float[] { r, g, b, alpha };
	      return this;
	}
	   
	public float[] getSpecularColor() {
	      return specularColor;
	}

	   
	public Entity setEmissionColor(Color c) {
	      this.emissionColor = c == null? null : c.getRGBColorComponents(null);
	      return this;
	}

	   
	public Entity setEmissionColor(float r, float g, float b) {
	      this.emissionColor = new float[] { r, g, b, 1 };
	      return this;
	}

	 
	public Entity setEmissionColor(float r, float g, float b, float alpha) {
	      this.emissionColor = new float[] { r, g, b, alpha };
	      return this;
	}
	   
	public float[] getEmissionColor() {
	      return emissionColor;
	}
	   
	   
	public Entity setShininess(int shininess) {
	      if (shininess < 0)
	         this.shininess = -1;
	      else
	         this.shininess = Math.max(128, shininess);
	      return this;
	}
	   
	   
	public int getShininess() {
	      return shininess;
	}
	

}
 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值