我们用前面用过的知识,画一个运动的机器人.
效果如下:
主窗体类:
package com.gl3dgame.robot; //要是想使用默认包,请去掉这行 import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.media.opengl.*; import com.sun.opengl.util.Animator; import com.sun.opengl.util.FPSAnimator; public class RobotMain extends JFrame { GLRender listener=new GLRender(); static FPSAnimator animator=null; public RobotMain() throws HeadlessException { super("画机器人:活用长方体"); setSize(600,480); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); GLCapabilities glcaps=new GLCapabilities(); GLCanvas canvas=new GLCanvas(glcaps); canvas.addGLEventListener(listener); //canvas.addMouseListener(listener); getContentPane().add(canvas, BorderLayout.CENTER); animator=new FPSAnimator(canvas,60,true); centerWindow(this); } private void centerWindow(Component frame) { // 居中窗体 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension frameSize = frame.getSize(); if (frameSize.width > screenSize.width) frameSize.width = screenSize.width; if (frameSize.height > screenSize.height) frameSize.height = screenSize.height; frame.setLocation((screenSize.width - frameSize.width) >> 1, (screenSize.height - frameSize.height) >> 1); } public static void main(String[] args) { final RobotMain app = new RobotMain(); // 显示窗体 SwingUtilities.invokeLater(new Runnable() { public void run() { app.setVisible(true); } }); // 动画线程开始 SwingUtilities.invokeLater(new Runnable() { public void run() { animator.start(); } }); } }
GL控制类:
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.gl3dgame.robot; import java.awt.Component; import javax.media.opengl.GL; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; import javax.media.opengl.glu.GLU; /** * * @author Administrator */ public class GLRender implements GLEventListener { private GL gl; private GLU glu; private Robot robot; private float rotationAngle; public void init(GLAutoDrawable drawable) { gl = drawable.getGL(); glu = new GLU(); robot = new Robot(gl); rotationAngle = 0.0f; gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); gl.glEnable(GL.GL_DEPTH_TEST); gl.glDepthFunc(GL.GL_LEQUAL); gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); int w = ((Component) drawable).getWidth(); int h = ((Component) drawable).getHeight(); gl.glViewport(0, 0, w, h); // 设置视点大小reset the viewport to new dimensions gl.glMatrixMode(GL.GL_PROJECTION); //设置当前矩阵模式 set projection matrix current matrix gl.glLoadIdentity(); //把当前绘画点移动到屏幕中心 reset projection matrix //设置摄像机的拍摄性能 calculate aspect ratio of window glu.gluPerspective(52.0f, (float) w / (float) h, 1.0f, 1000.0f); gl.glMatrixMode(GL.GL_MODELVIEW); //设置当前矩阵模式 set modelview matrix gl.glLoadIdentity(); //把当前绘画点移动到屏幕中心 reset modelview matrix //播放音乐,不要就注释掉 //new AePlayWave("wave/run.wav").start(); } public void display(GLAutoDrawable drawable) { //刷新背景颜色 clear screen and depth buffer gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); //把当前绘画点移动到屏幕中心 load the identity matrix (clear to default position and orientation) gl.glLoadIdentity(); gl.glPushMatrix(); //保存当前矩阵 put current matrix on stack gl.glLoadIdentity(); //把当前绘画点移动到屏幕中心 reset matrix gl.glTranslatef(0.0f, 0.0f, -30.0f); //把当前绘画点移动到(x,y,z) move to (0, 0, -30) gl.glRotatef(rotationAngle, 0.0f, 1.0f, 0.0f); //旋转(角度值,x轴,Y轴,Z轴) rotate the robot on its y-axis robot.DrawRobot(0.0f, 0.0f, 0.0f); //画机器人 draw the robot gl.glPopMatrix(); this.Prepare(0.2f); //刷新机器人动作 } public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { } public void Prepare(float dt) { rotationAngle += 45.0f * dt; // increase our rotation angle counter if (rotationAngle >= 360.0f) // if we've gone in a circle, reset counter { rotationAngle = 0.0f; } robot.Prepare(dt); } }
机器人类:
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.gl3dgame.robot; import javax.media.opengl.GL; /** * * @author Administrator */ public class Robot { private GL gl; private String[] legStates = new String[2]; private String[] armStates = new String[2]; private float[] legAngles = new float[2]; private float[] armAngles = new float[2]; final int LEFT = 0; final int RIGHT = 1; public Robot(GL gl) { this.gl = gl; armAngles[LEFT] = 0.0f; armAngles[RIGHT] = 0.0f; legAngles[LEFT] = 0.0f; legAngles[RIGHT] = 0.0f; armStates[LEFT] = "FORWARD_STATE"; armStates[RIGHT] = "BACKWARD_STATE"; legStates[LEFT] = "FORWARD_STATE"; legStates[RIGHT] = "BACKWARD_STATE"; } private void DrawCube(float xPos, float yPos, float zPos) { gl.glPushMatrix(); gl.glTranslatef(xPos, yPos, zPos); gl.glBegin(GL.GL_POLYGON); gl.glVertex3f(0.0f, 0.0f, 0.0f); // top face gl.glVertex3f(0.0f, 0.0f, -1.0f); gl.glVertex3f(-1.0f, 0.0f, -1.0f); gl.glVertex3f(-1.0f, 0.0f, 0.0f); gl.glVertex3f(0.0f, 0.0f, 0.0f); // front face gl.glVertex3f(-1.0f, 0.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, 0.0f); gl.glVertex3f(0.0f, -1.0f, 0.0f); gl.glVertex3f(0.0f, 0.0f, 0.0f); // right face gl.glVertex3f(0.0f, -1.0f, 0.0f); gl.glVertex3f(0.0f, -1.0f, -1.0f); gl.glVertex3f(0.0f, 0.0f, -1.0f); gl.glVertex3f(-1.0f, 0.0f, 0.0f); // left face gl.glVertex3f(-1.0f, 0.0f, -1.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f); gl.glVertex3f(-1.0f, -1.0f, 0.0f); gl.glVertex3f(0.0f, 0.0f, 0.0f); // bottom face gl.glVertex3f(0.0f, -1.0f, -1.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f); gl.glVertex3f(-1.0f, -1.0f, 0.0f); gl.glVertex3f(0.0f, 0.0f, 0.0f); // back face gl.glVertex3f(-1.0f, 0.0f, -1.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f); gl.glVertex3f(0.0f, -1.0f, -1.0f); gl.glEnd(); gl.glPopMatrix(); } private void DrawArm(float xPos, float yPos, float zPos) { gl.glPushMatrix(); gl.glColor3f(1.0f, 0.0f, 0.0f); // red gl.glTranslatef(xPos, yPos, zPos); gl.glScalef(1.0f, 4.0f, 1.0f); // arm is a 1x4x1 cube DrawCube(0.0f, 0.0f, 0.0f); gl.glPopMatrix(); } private void DrawHead(float xPos, float yPos, float zPos) { gl.glPushMatrix(); // white gl.glTranslatef(xPos, yPos, zPos); gl.glScalef(2.0f, 2.0f, 2.0f); // head is a 2x2x2 cube gl.glColor3f(1.0f, 1.0f, 1.0f); DrawCube(0.0f, 0.0f, 0.0f); gl.glPopMatrix(); } private void DrawTorso(float xPos, float yPos, float zPos) { gl.glPushMatrix(); gl.glColor3f(0.0f, 0.0f, 1.0f); // blue gl.glTranslatef(xPos, yPos, zPos); gl.glScalef(3.0f, 5.0f, 2.0f); // torso is a 3x5x2 cube DrawCube(0.0f, 0.0f, 0.0f); gl.glPopMatrix(); } private void DrawLeg(float xPos, float yPos, float zPos) { gl.glPushMatrix(); gl.glTranslatef(xPos, yPos, zPos); // draw the foot gl.glPushMatrix(); gl.glTranslatef(0.0f, -0.5f, 0.0f); DrawFoot(0.0f, -5.0f, 0.0f); gl.glPopMatrix(); gl.glScalef(1.0f, 5.0f, 1.0f); // leg is a 1x5x1 cube gl.glColor3f(1.0f, 1.0f, 0.0f); // yellow DrawCube(0.0f, 0.0f, 0.0f); gl.glPopMatrix(); } private void DrawFoot(float xPos, float yPos, float zPos) { gl.glPushMatrix(); gl.glColor3f(1.0f, 1.0f, 1.0f); gl.glTranslatef(xPos, yPos, zPos); gl.glScalef(1.0f, 0.5f, 3.0f); DrawCube(0.0f, 0.0f, 0.0f); gl.glPopMatrix(); } public void DrawRobot(float xPos, float yPos, float zPos) { gl.glPushMatrix(); gl.glTranslatef(xPos, yPos, zPos); // draw robot at desired coordinates //画头 draw head and torso parts DrawHead(1.0f, 2.0f, 0.0f); DrawTorso(1.5f, 0.0f, 0.0f); //画左手 move the left arm away from the torso and rotate it to give "walking" effect gl.glPushMatrix(); gl.glTranslatef(0.0f, -0.5f, 0.0f); gl.glRotatef(armAngles[LEFT], 1.0f, 0.0f, 0.0f); DrawArm(2.5f, 0.0f, -0.5f); gl.glPopMatrix(); //画右手 move the right arm away from the torso and rotate it to give "walking" effect gl.glPushMatrix(); gl.glTranslatef(0.0f, -0.5f, 0.0f); gl.glRotatef(armAngles[RIGHT], 1.0f, 0.0f, 0.0f); DrawArm(-1.5f, 0.0f, -0.5f); gl.glPopMatrix(); //画左脚 move the left leg away from the torso and rotate it to give "walking" effect gl.glPushMatrix(); gl.glTranslatef(0.0f, -0.5f, 0.0f); gl.glRotatef(legAngles[LEFT], 1.0f, 0.0f, 0.0f); DrawLeg(-0.5f, -5.0f, -0.5f); gl.glPopMatrix(); //画右脚 move the right leg away from the torso and rotate it to give "walking" effect gl.glPushMatrix(); gl.glTranslatef(0.0f, -0.5f, 0.0f); gl.glRotatef(legAngles[RIGHT], 1.0f, 0.0f, 0.0f); DrawLeg(1.5f, -5.0f, -0.5f); gl.glPopMatrix(); gl.glPopMatrix(); // pop back to original coordinate system } public void Prepare(float dt) { //机器人动作,实际就是按规则旋转手脚 // if leg is moving forward, increase angle, else decrease angle for (char side = 0; side < 2; side++) { // arms if (armStates[side] == "FORWARD_STATE") { armAngles[side] += 20.0f * dt; } else { armAngles[side] -= 20.0f * dt; } // change state if exceeding angles if (armAngles[side] >= 15.0f) { armStates[side] = "BACKWARD_STATE"; } else if (armAngles[side] <= -15.0f) { armStates[side] = "FORWARD_STATE"; } // legs if (legStates[side] == "FORWARD_STATE") { legAngles[side] += 20.0f * dt; } else { legAngles[side] -= 20.0f * dt; } // change state if exceeding angles if (legAngles[side] >= 15.0f) { legStates[side] = "BACKWARD_STATE"; } else if (legAngles[side] <= -15.0f) { legStates[side] = "FORWARD_STATE"; } } } }
实现原理就是在画所有长方前,先用gl.glRotatef(rotationAngle, 0.0f, 1.0f, 0.0f);//旋转(角度值,x轴,Y轴,Z轴) 使矩阵里的物体旋转,,也就像地球和八大行星围绕太阳公转,,,然后各手脚自转,类似地球自转.
分享自己的技术论坛http://www.itneng.com/forum.php