Sie sind auf Seite 1von 7

MkKPage

http://fatcat.ftj.agh.edu.pl/~f8kolasi/?dir=examples&ex=JOGL&file=JO...

This page is under contruction. Home JOGL First Steps Drawing primitives Display Lists Matrices Interaction Numerical methods Euler algorithm MidPoint method Verlet method Also Examples list Articels archive Download About Gallery Select subject:

[ JOGL ]
Examples from: JOGL/Primitives tutorial.

NeHe openGL tutorial

1. Golden Spiralversion:01.01.1970
Draw the plate using golden spiral algorithm. replies ( 0 )ReadDownload

JOGL tutorial
based on NeHe lessons.

2. Torusversion:01.01.1970
Variations about torus. replies ( 0 )ReadDownload Examples from: JOGL/Display Lists tutorial.

Physics in Graphics

1. The Wallversion:01.01.1970
This short example shows how to use Display Lists. replies ( 0 )ReadDownload Examples from: JOGL/Picking tutorial.

1 von 7

4/15/2012 3:41 PM

MkKPage

http://fatcat.ftj.agh.edu.pl/~f8kolasi/?dir=examples&ex=JOGL&file=JO...

1. Picking Testversion:01.01.1970
You can find description to this example in First steps/Interaction article. replies ( 0 )

Read
Download Examples from: JOGL/Matrix tutorial.

1. Simple shadowversion:01.01.1970
Learn how to draw projective shadows using projection matrix. Before you start reading this article you have to know something about stencil buffer and lightning. replies ( 0 )ReadDownload

2. Camera ArcBallversion:01.01.1970
Learn how the ArcBall works. This simple implementation of ArcBall camera has some bugs but for testing at home it's good enough. replies ( 0 )ReadDownload

Astronomy picture of the day.

Example - Camera ArcBall [Matrices][Implementing ArcBall][ArcBall radius][Rotation] In this article I'm going to show you how to implement your own ArcBall camera into your program. Of course this algorithm is not bug free but it works good and it is very easy to implement even if you are openGL beginer. CameraArcBall class In the first step we are going to create new Java class, so run NetBeans IDE to create new project and add to scene some objects for testing. Add new Java class with name , in my case CameraArcBall. Add these lines to your new class (read the comments):
1 2 3 4 5 6 7 8 9 10 //implement all necessery Listeners to have control on the world public class CameraArcBall implements MouseListener,MouseMotionListener,MouseWheelListener{ private private private private Point mousePosition; //keep your current mouse position Vector cameraPosition; //determine where camera is located double mouseSensitivity = 1;//I think that this is clear :) int mouseButton = 1; //save number of mouse button which was pressed, ?

2 von 7

4/15/2012 3:41 PM

MkKPage

http://fatcat.ftj.agh.edu.pl/~f8kolasi/?dir=examples&ex=JOGL&file=JO...

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97

private Vector r = new Vector(),r1 = new Vector(),r2 = new Vector(),axis = new Vector(); //Vector r Its length keeps the ArcBall sphere radius, //r1,r2 temporary variables //axis keeps current rotation axis private float m_v[] = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 }; // // //this matrix will accumulate every rotation //we will use this array to multiply model //view matrix by it to achieve rotation effect //

private boolean mousePressed = false;// private boolean mouseDragged = false;// /////////////////////////////////////////////////////////////////////////////////////////// public CameraArcBall(GLCanvas canvas){//send to constructor GLcanvas canvas.addMouseListener(this); //makes your mouse buttons work canvas.addMouseMotionListener(this);//mouse movement canvas.addMouseWheelListener(this); // and wheel mousePosition = new Point(); // cameraPosition = new Vector(0,0,8);//initial camera translation } public void mouseEntered(MouseEvent e) { //NOT IMPORTANT } public void mouseExited(MouseEvent e) { //NOT IMPORTANT } public void mouseClicked(MouseEvent e) { //NOT IMPORTANT } /////////////////////////////////////////////////////////////////////////////////////////// /** *Determine what happens if you will press the mouse button */ public void mousePressed(MouseEvent e) { updateMousePosition(e); //update mouse position mouseButton = e.getButton(); //save mouse pressed button mousePressed = true; //change the mousePressed status } /////////////////////////////////////////////////////////////////////////////////////////// public void mouseReleased(MouseEvent e) { updateMousePosition(e); //not important but I added this line mousePressed = false; //it says that mouse is not pressed mouseDragged = false; //or dragged mouseButton = 1; //assume that 1 means no button is pressed } /////////////////////////////////////////////////////////////////////////////////////////// public void mouseDragged(MouseEvent e) { updateMousePosition(e); if(mouseButton==1){ mouseDragged = true; //set mouse dragged status to true } } /////////////////////////////////////////////////////////////////////////////////////////// public void mouseMoved(MouseEvent e) { updateMousePosition(e); //your move is watched } /////////////////////////////////////////////////////////////////////////////////////////// public void mouseWheelMoved(MouseWheelEvent e) { if(e.getWheelRotation() < 0){ cameraPosition.z+=1; //increase zdistance of camera }else { cameraPosition.z=1; //decreasing } } /////////////////////////////////////////////////////////////////////////////////////////// public void updateCamera(GL gl){ gl.glLoadIdentity(); gl.glTranslated(cameraPosition.x, cameraPosition.y, cameraPosition.z); gl.glMultMatrixf(m_v, 0); //mutliply model view matrix by rotations //for now this line does nothing because it's //the identity matrix } /////////////////////////////////////////////////////////////////////////////////////////// private void updateMousePosition(MouseEvent e){ mousePosition.x = e.getX(); mousePosition.y = e.getY(); } }

As you see, functions which control the mouse behaviour take most place in the code. If you decide to copy the code above you will have to add some imports. Next pass Now we are going to create some usefull methods. First will be the transpose() method. But why do we need it ? As you know, or not :), openGL saves matrices to arrays in diffrent way to what we learn at school. What is the difference shows picture below:

So if you want to multiply your matrix by openGL's you have to transpose one of these. I suggest to write transpose method like that:
1 2 3 4 5 6 private float[] transpose(float m[]){ float matrix[] = { m[e(0,0)],m[e(1,0)],m[e(2,0)],m[e(3,0)], m[e(0,1)],m[e(1,1)],m[e(2,1)],m[e(3,1)], m[e(0,2)],m[e(1,2)],m[e(2,2)],m[e(3,2)], ?

3 von 7

4/15/2012 3:41 PM

MkKPage

http://fatcat.ftj.agh.edu.pl/~f8kolasi/?dir=examples&ex=JOGL&file=JO...

7 8 9 10 11 12 13 14 15

m[e(0,3)],m[e(1,3)],m[e(2,3)],m[e(3,3)] }; return matrix; } //auxiliary method private int e(int row,int col){ return row*4+col; }

The second method multiplies two matrices. We will use it to multiply matrix which accumulates rotations by current matrix rotation generated by mouse dragging. By multiplying matrices I mean mutliply the first matrix by the second one from the left side. We can define multiplying two matrices 4x4 by simple equation:

Where c_ij is a cell of result matrix. My implementation of multiply method looks like that:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private float[] mutliplyMatrixAByMatrixB(float ma[],float mb[]){ float m[] = new float[16]; for(int rowB=0;rowB < 4;rowB++){//row of matrix B for(int colA=0;colA < 4;colA++){ //column of matrix A for(int i=0;i < 4;i++){ m[rowB*4+colA]+=mb[rowB*4+i]*ma[i*4+colA]; } } } return m; //returns matrix C } ?

This approach gives us possibility to extend this method to any square matrices. Now it will be good idea to test our class and check if everything works fine. If you know how to implement CameraArcBall in your project you can skip next paragraph. Implementing CameraArcBall in project If you create your project with Netbeans IDE you will have to open the main class. By "main" I mean the class in which is the main() method located. Now at the begining you should find lines:
1 2 3 4 5 6 7 8 9 10 11 12 13 public CameraTest() { initComponents(); setTitle("Camera test"); canvas.addGLEventListener(new GLRenderer());//Sending to GLCanvas GLRenderer //which implements all GL events animator = new Animator(canvas); // This is a workaround for the GLCanvas not adjusting its size, when the frame is resized. canvas.setMinimumSize(new Dimension()); this.addWindowListener(new WindowAdapter() { .... ... ?

We have to send somehow our camera to GLRenderer class to have access to GLCanvas listeners. Change the lines:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public CameraTest() { initComponents(); setTitle("Camera test"); canvas.addGLEventListener(new GLRenderer(canvas));//new animator = new Animator(canvas); animator.start(); //without this display method in GLRenderer will not refreshed //so camera too. // This is a workaround for the GLCanvas not adjusting its size, when the frame is resized. canvas.setMinimumSize(new Dimension()); this.addWindowListener(new WindowAdapter() { .... ... ?

Now we have to create new variable constructor in GLRenderer file:


1 2 3 4 CameraArcBall camera; public GLRenderer(GLCanvas canvas){ camera = new CameraArcBall(canvas); } ?

Now we have access to GLCanvas by ClassArcBall class reference. At least we have to change one line in display method:
1 2 3 4 ... //gl.glLoadIdentity(); cam.updateCamera(gl); ... ?

Run your program and test whether your mouse wheel button works because now you should be able to change view distance by scrolling mouse wheel. Controling the invisible ArcBall radius. At the begining I'm going to warn you that this is my own idea which came to me when I discovered some bugs when ArcBall radius was constant in time. What was the bug? To answer this question I start from the explanation how the ArcBall algorithm

4 von 7

4/15/2012 3:41 PM

MkKPage

http://fatcat.ftj.agh.edu.pl/~f8kolasi/?dir=examples&ex=JOGL&file=JO...

works. So we have to find two points on the sphere in the place where mouse was pressed and where mouse was pressed before, then calculate rotation axis vector by calculating the cross product and then create current rotation matrix and at least, multiply global rotation matrix by it. The problem is where we press the mouse (I'm writing about the location on the screen). When we press outside Arcball the program will crash, why I think its easy to explain it on the pictures:

When ArcBall sphere radius is big and we are close there is no problem to find point on sphere for each pixel.

But when we zoom out the ArcBall Sphere size get smaller and on the corners will appear place where pixel assignation with point on shere is impossible. We can fix this bug by auto changing the ArcbBall sphere size with zooming. To control ArcBall radius I used gluProject() to know what is the distance between screen and centre of coordinate frame and gluUnProject() to find coordinates of special point which is located on the same depth as the center of ArcBall sphere. Look at the code below and read comments:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 /** *px , py are points on the screen if you use px = 0 and py = 0 you will point on * leftup corner of screen */ private Vector updateRadius(int px,int py,GL gl){ GLU glu = new GLU(); gl.glLoadIdentity();//reset the modelview matrix to identity gl.glTranslated(cameraPosition.x, cameraPosition.y, cameraPosition.z);//zoom outin camera //get viewport int viewport[] = new int[4]; gl.glGetIntegerv(GL.GL_VIEWPORT,viewport,0); //get modelview matrix double modelViewM[] = new double[16]; gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX, modelViewM, 0); //get projection matrix double projectionM[] = new double[16]; gl.glGetDoublev(GL.GL_PROJECTION_MATRIX, projectionM, 0); //get coordinates of point screen using gluProject function //mp[0],mp[1] contains x,y components , mp[2]contains value from 01 and mean what is the //distance between point on screen (zdist) //and in this case point [0,0,0] double mp[] = new double[3]; glu.gluProject(0, 0, 0, modelViewM, 0, projectionM, 0, viewport, 0, mp, 0); //now when you know zdistance you can find coordinates of each point on the same depth // as the centre of ArcBall sphere is double coordinates[] = new double[3]; glu.gluUnProject(px, viewport[3]py, mp[2], modelViewM,0, projectionM,0, viewport, 0, coordinates, 0); //this is the ArcBall sphere radius vector Vector r0 = new Vector(coordinates[0],coordinates[1],coordinates[2]); gl.glLoadIdentity(); return r0; } ?

If you read comments and don't understand how it exactly works we can do another test. So change your updateCamera() method:
1 2 3 4 5 6 public void updateCamera(GL gl){ GLU glu = new GLU(); GLUquadric quadric = glu.gluNewQuadric(); r = updateRadius(0,0,gl);//point in the left up corner of //the screen. Try other values and see what happens. ?

5 von 7

4/15/2012 3:41 PM

MkKPage

http://fatcat.ftj.agh.edu.pl/~f8kolasi/?dir=examples&ex=JOGL&file=JO...

7 8 9 10 11 12 13 14 15

gl.glLoadIdentity(); gl.glTranslated(cameraPosition.x, cameraPosition.y, cameraPosition.z); gl.glMultMatrixf(m_v, 0); //draw visible ArcBall Sphere glu.gluQuadricDrawStyle(quadric, GLU.GLU_LINE); glu.gluSphere(quadric, r.length, 20, 20); }

Very funny effect, the ArcBall is all the time in the same place and does not change the size. It works that way because updateRadius returns radius vector which is propotional to z-distance. Now we can go further and add some rotation. Rotation When we press mouse button we have to get the first mouse position on the sphere. We can do it by using updateRadius function which will return vector lying on the same plane what ArcBall radius then we will use simple school equation: R^2 = x^2+y^2+z^2 to calculate z component of this vector on sphere:

By pressing mouse button we find r1 vector and calculate point on sphere using R^2 = x^2+y^2+z^2. During mouse dragging we will do the same but for vector r2. Then we will be able to calculate axis vector.This is how updateCamera method should finally look like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 public void updateCamera(GL gl){ GLU glu = new GLU(); GLUquadric quadric = glu.gluNewQuadric(); r = updateRadius(0,0,gl); if(mousePressed){ r1 = updateRadius(mousePosition.x,mousePosition.y,gl); //calcualate z component from sphere equation Double z = Math.sqrt(r.length*r.lengthr1.x*r1.xr1.y*r1.y); r1.z = z; } if(mouseDragged){ mousePressed = false; mouseDragged = false; r2 = updateRadius(mousePosition.x,mousePosition.y,gl); //calcualate z component from sphere equation Double z = Math.sqrt(r.length*r.lengthr2.x*r2.xr2.y*r2.y); if(z.isNaN()) z = 0.0; r2.z = z; //calculate rotation axis and normalize it axis = r1.cross(r2); axis.normalize(); //replace old r1 vector with new r2 r1 = r2; //rotate world gl.glRotated(mouseSensitivity,axis.x,axis.y,axis.z); //get new modelview matrix float m[] = new float[16]; gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, m, 0); //mutliply rotation matrix by current rotation m_v = mutliplyMatrixAByMatrixB(transpose(m_v),transpose(m)); m_v = transpose(m_v); } ///////////////////////uncomment those lines and see what happens///////////////// // gl.glLoadIdentity(); // axis = axis.scale(.9); // gl.glRotated(mouseSensitivity*axis.length,axis.x,axis.y,axis.z); // float m[] = new float[16]; // gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, m, 0); // m_v = mutliplyMatrixAByMatrixB(transpose(m_v),transpose(m)); // m_v = transpose(m_v); ////////////////////////////////////////////////////////////////////////////////// gl.glLoadIdentity(); gl.glTranslated(cameraPosition.x, cameraPosition.y, cameraPosition.z); gl.glMultMatrixf(m_v, 0); glu.gluQuadricDrawStyle(quadric, GLU.GLU_LINE); glu.gluSphere(quadric, r.length, 20, 20); ?

6 von 7

4/15/2012 3:41 PM

MkKPage

http://fatcat.ftj.agh.edu.pl/~f8kolasi/?dir=examples&ex=JOGL&file=JO...

56 57

Of course this method has some bugs but for home using and testing this simple class is good enough. You can extends this class by adding for example min z-distance of camera or check time between each mouse pressing to implement in your algorithm mouse speed sensibility Angle can be proportional to mouse sensitivity and also to mouse speed. You can also add some physics adding resistance force to rotation. Thanks for reading.

back

Leave reply :)

Suggestions/Questions: Your NicK:

Please enter code from the image. Avialable tags: < br/> - new line < q > </ q> - quote < i > </ i> - italics < b > </ b> - bold < a > </ a> - link

Copyright 2010

7 von 7

4/15/2012 3:41 PM

Das könnte Ihnen auch gefallen