In: Computer Science
I want to draw a sphere and I want to rotate it, How can I do it in JOGL? ( I am working on a program to visualize the sun )
please provide a pic of the code.
import net.java.games.jogl.GL;
import net.java.games.jogl.GLU;
import net.java.games.jogl.GLUquadric;
...
GLUquadric quad = glu.gluNewQuadric();
glu.gluSphere(quad, 2, 10, 15);
glu.gluDeleteQuadric(quad);
or try this
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import com.jogamp.opengl.*;
import com.jogamp.opengl.awt.GLJPanel;
import com.jogamp.opengl.util.GLBuffers;
import java.nio.FloatBuffer;
/**
* A Jogl/OpenGL application that an 11-by-11-by-11 cube of
* spheres in different colors. Five rendering methods are
* available, selected using a popup menu. The rendering time
* to draw the scene is shown. Use the mouse to rotate
* the scene and force a redraw. (You can also force a redraw
* by resizing the window.) This program requires OpenGL 1.5
* or higher for support of vertex buffer objects.
*/
public class ColorCubeOfSpheres extends JPanel implements GLEventListener, ActionListener {
public static void main(String[] args) {
JFrame window = new JFrame("Color Cube of Spheres -- USE MOUSE TO ROTATE");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setContentPane(new ColorCubeOfSpheres());
window.pack();
window.setLocation(50,50);
window.setVisible(true);
}
private Camera camera;
private int sphereDisplayList; // A display list for drawing one sphere.
private FloatBuffer sphereVertexBuffer; // Holds the vertex coords, for use with glDrawArrays
private FloatBuffer sphereNormalBuffer; // Holds the normal vectors, for use with glDrawArrays
private float[] sphereVertexArray; // The same data as in sphereVertexBuffer, stored in an array.
private float[] sphereNormalArray; // The same data as in sphereNormalBuffer, stored in an array.
private int vertexVboId; // identifier for the Vertex Buffer Object to hold the vertex coords
private int normalVboId; // identifier for the Vertex Buffer Object to hold the normla vectors
private JComboBox<String> renderModeSelect; // For selecting the type of rendering
private JLabel message; // Displays the elapsed time in milliseconds for the most
// recent rendering of the display.
private int currentRenderMode; // Which of the five render modes is selected.
private int renderCount; // Number of time image has been rendered using current render technique.
private double renderTimeSum; // Sum of the rendering times (since the current technique was selected).
/**
* Make a regular JPanel to hold the GLJPanel, Add a small panel at the
* bottom to hold a check box that determines whether a display list is used
* for rendering and a label that displays the rendering time of the most
* recent display of the GLJPanel. The user can rotate the view with the
* mouse.
*/
public ColorCubeOfSpheres() {
renderModeSelect = new JComboBox<String>();
renderModeSelect.addItem("Direct Draw, Recomputing Vertex Data");
renderModeSelect.addItem("Direct Draw, Precomputed Data");
renderModeSelect.addItem("Use Display List");
renderModeSelect.addItem("Use DrawArrays");
renderModeSelect.addItem("Use DrawArrays with VBOs");
renderModeSelect.setSelectedIndex(2);
renderModeSelect.addActionListener(this);
currentRenderMode = 2;
message = new JLabel("Average Render time:");
JPanel bottom = new JPanel();
bottom.setLayout(new BorderLayout(20,20));
bottom.add(renderModeSelect, BorderLayout.WEST);
bottom.add(message, BorderLayout.CENTER);
bottom.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
GLJPanel drawable = new GLJPanel();
drawable.setPreferredSize(new Dimension(600,600));
drawable.addGLEventListener(this);
setLayout(new BorderLayout());
add(drawable, BorderLayout.CENTER);
add(bottom, BorderLayout.SOUTH);
camera = new Camera();
camera.setLimits(-10,10,-10,10,-10,10);
camera.installTrackball(this);
}
public void actionPerformed(ActionEvent evt) {
repaint();
}
/**
* This method will be called when the GLJPanel is first
* created. It can be used to initialize the GL context.
*/
public void init(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glEnable(GL2.GL_LIGHTING);
gl.glEnable(GL2.GL_LIGHT0);
gl.glEnable(GL2.GL_DEPTH_TEST);
gl.glShadeModel(GL2.GL_SMOOTH);
gl.glEnable(GL2.GL_COLOR_MATERIAL);
gl.glClearColor(0.5f,0.5f,0.5f,1);
/* Create a display list that contains all the OpenGL
* commands that are generated when the sphere is drawn.
*/
sphereDisplayList = gl.glGenLists(1);
gl.glNewList(sphereDisplayList, GL2.GL_COMPILE);
uvSphere(gl, 0.4, 32, 16, false);
gl.glEndList();
/* Create the data for glDrawArrays, for render modes 2 and 3
*/
createSphereArraysAndVBOs(gl);
}
/**
* Draw a color cube of spheres, 11 spheres on each side, using
* different colors. Each of the red, green, and blue components
* of the color varies along one dimension of the cube.
*/
public void display(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
camera.apply(gl);
int mode = renderModeSelect.getSelectedIndex();
if (mode != currentRenderMode) {
currentRenderMode = mode; // Change mode, and reset timing variables.
renderCount = 0;
renderTimeSum = 0;
}
long start = System.currentTimeMillis(); // Starting time for rendering.
if (mode == 4 || mode == 3) {
// We need to enable the vertex and normal arrays, and set
// the vertex and normal points for these modes.
gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL2.GL_NORMAL_ARRAY);
if (mode == 4) {
// When using VBOs, the vertex and normal pointers
// refer to data in the VBOs.
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexVboId);
gl.glVertexPointer(3,GL.GL_FLOAT,0,0);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, normalVboId);
gl.glNormalPointer(GL.GL_FLOAT,0,0);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
}
else {
// When not using VBOs, the points point to the FloatBuffers.
gl.glVertexPointer(3,GL.GL_FLOAT,0,sphereVertexBuffer);
gl.glNormalPointer(GL.GL_FLOAT,0,sphereNormalBuffer);
}
}
for (int i = 0; i <= 10; i++) {
float r = i/10.0f;
for (int j = 0; j <= 10; j++) {
float g = j/10.0f;
for (int k = 0; k <= 10; k++) {
float b = k/10.0f;
gl.glColor3f(r,g,b);
gl.glPushMatrix();
gl.glTranslatef(i-5,j-5,k-5);
if (mode == 0)
uvSphere(gl, 0.4, 32, 16, false); // Draw sphere directly.
else if (mode == 1)
drawSphereDirectWithDataFromArrays(gl);
else if (mode == 2)
gl.glCallList(sphereDisplayList); // Draw by calling a display list.
else
drawSphereWithDrawArrays(gl); // Draw using DrawArrays
gl.glPopMatrix();
}
}
}
if (mode == 4 || mode == 3) {
gl.glDisableClientState(GL2.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL2.GL_NORMAL_ARRAY);
}
gl.glFlush(); // Make sure all commands are sent to graphics card.
gl.glFinish(); // Wait for all commands to complete, before checking time.
long time = System.currentTimeMillis() - start;
renderCount++;
renderTimeSum += time;
String text = String.format("Average Render Time = %1.2f", renderTimeSum/renderCount);
message.setText(text);
}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
}
public void dispose(GLAutoDrawable drawable) {
}
//----------------- for glDrawArrays and Vertex Buffer Object ----------------------------------
/**
* Creates the vertex coordinate and normal vectors for a sphere.
* The data is stored in the FloatBuffers sphereVertexBuffer and
* sphereNormalBuffer. In addition, VBOs are created to hold
* the data and the data is copied from the FloatBuffers into
* the VBOs. (Note: The VBOs are used for render mode 4; the
* FloatBuffers are used for render mode 3.)
*/
private void createSphereArraysAndVBOs(GL2 gl) {
double radius = 0.4;
int stacks = 16;
int slices = 32;
int size = stacks * (slices+1) * 2 * 3;
sphereVertexBuffer = GLBuffers.newDirectFloatBuffer(size);
sphereNormalBuffer = GLBuffers.newDirectFloatBuffer(size);
sphereVertexArray = new float[size];
sphereNormalArray = new float[size];
for (int j = 0; j < stacks; j++) {
double latitude1 = (Math.PI/stacks) * j - Math.PI/2;
double latitude2 = (Math.PI/stacks) * (j+1) - Math.PI/2;
double sinLat1 = Math.sin(latitude1);
double cosLat1 = Math.cos(latitude1);
double sinLat2 = Math.sin(latitude2);
double cosLat2 = Math.cos(latitude2);
for (int i = 0; i <= slices; i++) {
double longitude = (2*Math.PI/slices) * i;
double sinLong = Math.sin(longitude);
double cosLong = Math.cos(longitude);
double x1 = cosLong * cosLat1;
double y1 = sinLong * cosLat1;
double z1 = sinLat1;
double x2 = cosLong * cosLat2;
double y2 = sinLong * cosLat2;
double z2 = sinLat2;
sphereNormalBuffer.put( (float)x2 );
sphereNormalBuffer.put( (float)y2 );
sphereNormalBuffer.put( (float)z2 );
sphereVertexBuffer.put( (float)(radius*x2) );
sphereVertexBuffer.put( (float)(radius*y2) );
sphereVertexBuffer.put( (float)(radius*z2) );
sphereNormalBuffer.put( (float)x1 );
sphereNormalBuffer.put( (float)y1 );
sphereNormalBuffer.put( (float)z1 );
sphereVertexBuffer.put( (float)(radius*x1) );
sphereVertexBuffer.put( (float)(radius*y1) );
sphereVertexBuffer.put( (float)(radius*z1) );
}
}
for (int i = 0; i < size; i++) {
sphereVertexArray[i] = sphereVertexBuffer.get(i);
sphereNormalArray[i] = sphereNormalBuffer.get(i);
}
sphereVertexBuffer.rewind();
sphereNormalBuffer.rewind();
int[] bufferIDs = new int[2];
gl.glGenBuffers(2, bufferIDs,0);
vertexVboId = bufferIDs[0];
normalVboId = bufferIDs[1];
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vertexVboId);
gl.glBufferData(GL2.GL_ARRAY_BUFFER, size*4, sphereVertexBuffer, GL2.GL_STATIC_DRAW);
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, normalVboId);
gl.glBufferData(GL2.GL_ARRAY_BUFFER, size*4, sphereNormalBuffer, GL2.GL_STATIC_DRAW);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
}
/**
* Draw one sphere. The VertexPointer and NormalPointer must already
* be set to point to the data for the sphere, and they must be enabled.
*/
private void drawSphereWithDrawArrays(GL2 gl) {
int slices = 32;
int stacks = 16;
int vertices = (slices+1)*2;
for (int i = 0; i < stacks; i++) {
int pos = i*(slices+1)*2;
gl.glDrawArrays(GL2.GL_QUAD_STRIP, pos, vertices);
}
}
void drawSphereDirectWithDataFromArrays(GL2 gl) {
int i,j;
int slices = 32;
int stacks = 16;
int vertices = (slices+1)*2;
for (i = 0; i < stacks; i++) {
int pos = i*(slices+1)*2*3;
gl.glBegin(GL2.GL_QUAD_STRIP);
for (j = 0; j < vertices; j++) {
// gl.glNormal3fv(sphereNormalArray, pos+3*j); /* This worked but took 3 times as long!!! */
// gl.glVertex3fv(sphereVertexArray, pos+3*j);
gl.glNormal3f(sphereNormalArray[pos+3*j],sphereNormalArray[pos+3*j+1],sphereNormalArray[pos+3*j+2]);
gl.glVertex3f(sphereVertexArray[pos+3*j],sphereVertexArray[pos+3*j+1],sphereVertexArray[pos+3*j+2]);
}
gl.glEnd();
}
}
/**
* Draw a sphere with a given radius, number of slices, and number
* of stacks. The number of slices is the number of lines of longitude
* (like the slices of an orange). The number of stacks is the number
* of divisions perpendicular the axis; the lines of latitude are the
* dividing lines between stacks, so there are stacks-1 lines of latitude.
* The last parameter tells whether or not to generate texture
* coordinates for the sphere. The texture wraps once around the sphere.
* The sphere is centered at (0,0,0), and its axis lies along the z-axis.
* (Copied from TexturedShapes.uvSphere().)
*/
public static void uvSphere(GL2 gl, double radius, int slices, int stacks, boolean makeTexCoords) {
if (radius <= 0)
throw new IllegalArgumentException("Radius must be positive.");
if (slices < 3)
throw new IllegalArgumentException("Number of slices must be at least 3.");
if (stacks < 2)
throw new IllegalArgumentException("Number of stacks must be at least 2.");
for (int j = 0; j < stacks; j++) {
double latitude1 = (Math.PI/stacks) * j - Math.PI/2;
double latitude2 = (Math.PI/stacks) * (j+1) - Math.PI/2;
double sinLat1 = Math.sin(latitude1);
double cosLat1 = Math.cos(latitude1);
double sinLat2 = Math.sin(latitude2);
double cosLat2 = Math.cos(latitude2);
gl.glBegin(GL2.GL_QUAD_STRIP);
for (int i = 0; i <= slices; i++) {
double longitude = (2*Math.PI/slices) * i;
double sinLong = Math.sin(longitude);
double cosLong = Math.cos(longitude);
double x1 = cosLong * cosLat1;
double y1 = sinLong * cosLat1;
double z1 = sinLat1;
double x2 = cosLong * cosLat2;
double y2 = sinLong * cosLat2;
double z2 = sinLat2;
gl.glNormal3d(x2,y2,z2);
if (makeTexCoords)
gl.glTexCoord2d(1.0/slices * i, 1.0/stacks * (j+1));
gl.glVertex3d(radius*x2,radius*y2,radius*z2);
gl.glNormal3d(x1,y1,z1);
if (makeTexCoords)
gl.glTexCoord2d(1.0/slices * i, 1.0/stacks * j);
gl.glVertex3d(radius*x1,radius*y1,radius*z1);
}
gl.glEnd();
}
} // end uvSphere
}