Java-Gaming.org
 Featured games (79) games approved by the League of Dukes Games in Showcase (498) games submitted by our members Games in WIP (424) games currently in development
 News: Read the Java Gaming Resources, or peek at the official Java tutorials
Pages: [1]
 ignore  |  Print
 LWJGL Tutorial Series - A Rotating Cube  (Read 4539 times) 0 Members and 2 Guests are viewing this topic.
SHC
 « Posted 2013-09-16 10:39:38 »

# LWJGL Tutorial Series - A Rotating Cube

Welcome to the eleventh part of the LWJGL Tutorial Series. In this tutorial, I'm going to show you how to create a cube after introducing you to a new type of OpenGL primitive called as triangle strip. This tutorial uses the perspective projection which is discussed in the previous article. If you haven't read it, I recommend you to read it to get an understanding of how the perspective projection works. If you've found any mistakes in this tutorial, please notify them to me with comments and I'll correct them.

# Setting up Perspective projection

Now let's setup the perspective projection. I'm using the
 `gluPerspective()`
function which I had explained in the previous tutorial. Now let me list the code.

 1  2  3  4  5  6  7  8  9  10 `// Initialize OpenGLglMatrixMode(GL_PROJECTION);gluPerspective(70f, 800f / 600f, 1, 1000);glViewport(0, 0, Display.getWidth(), Display.getHeight());glMatrixMode(GL_MODELVIEW);glLoadIdentity();// Enable Depth TestingglEnable(GL_DEPTH_TEST);`

This sets the perspective projection for us and now let us learn how to create a quad.

Since version 3.1 of OpenGL, the ability to create QUADS has been deprecated. This is because the GPU renders everything we create as triangles and that it doesn' t make sense now to support them. These QUADS are now removed from version 3.2 so we have to find another way to create them. The idea is to create a quad with two triangles so they will be visible like a quad. Like this.

So let me give the vertices of those two triangles that makes a quad.

 1  2  3  4  5  6  7  8  9 ` // First triangle -0.5f, +0.5f, +0.0f, +0.5f, +0.5f, +0.0f, -0.5f, -0.5f, +0.0f, // Second triangle +0.5f, +0.5f, +0.0f, -0.5f, -0.5f, +0.0f, +0.5f, -0.5f, +0.0f`

This creates the two triangles for a quad but do you notice two vertices being drawn twice? That could be an unnecessary overhead. So we're seeking help of another primitive called as
 `GL_TRIANGLE_STRIP`

# Triangle Strip Mode

So what are these triangle strips? Let's see a visual of them.

Easy right? We just specify the vertices in an order and OpenGL automatically constructs triangles with them. The only thing is the order of vertices which are denoted as V1, V2, V3 and so on. So now let's see the vertices of the quad we are going to create.

 1  2  3  4 ` -0.5f, +0.5f, +0.0f,  // Top left +0.5f, +0.5f, +0.0f,  // Top right -0.5f, -0.5f, +0.0f,  // Bottom left +0.5f, -0.5f, +0.0f   // Bottom right`

This creates the following. (I've included the vertex numbers so you don't confuse)

In this way, we create all the sides of the cube. After creation, we can render using

 1 `glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices);`

Easy right? Now lets turn this into a cube.

# Creating a Cube

In the same way, we create a cube by creating quads for all it's sides. Again, I'm listing the code to create the vertices and you should write the color data and create the VBO. If you are unsure, please read my previous articles and read the associated sourcecode.

 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 `vertexBuffer.put(new float[]{    // Front face    -0.5f, +0.5f, +0.5f,    +0.5f, +0.5f, +0.5f,    -0.5f, -0.5f, +0.5f,    +0.5f, -0.5f, +0.5f,    // Right face    +0.5f, +0.5f, +0.5f,    +0.5f, +0.5f, -0.5f,    +0.5f, -0.5f, +0.5f,    +0.5f, -0.5f, -0.5f,    // Back face    +0.5f, +0.5f, -0.5f,    -0.5f, +0.5f, -0.5f,    +0.5f, -0.5f, -0.5f,    -0.5f, -0.5f, -0.5f,    // Left face    -0.5f, +0.5f, -0.5f,    -0.5f, +0.5f, +0.5f,    -0.5f, -0.5f, -0.5f,    -0.5f, -0.5f, +0.5f,    // Top face    -0.5f, +0.5f, +0.5f,    +0.5f, +0.5f, +0.5f,    -0.5f, +0.5f, -0.5f,    +0.5f, +0.5f, -0.5f,    // Bottom face    -0.5f, -0.5f, +0.5f,    +0.5f, -0.5f, +0.5f,    -0.5f, -0.5f, -0.5f,     +0.5f, -0.5f, -0.5f});vertexBuffer.rewind();`

Also don't forget to write the dispose code before running. Now when you run it, you'll see just a blank window. What happened to my cube! Let's see.

# Making the cube appear and Rotating it

Why my cube has disappeared? It's because the method
 `gluPerspective()`
which we used to create a perspective projection creates it's camera at the origin. Since our object is centered around the origin, we cannot see it. So we need to move it back into the screen to make it appear. So before drawing, add a call to the
 `glTranslatef()`
function to send it back into the screen.

 1 `glTranslatef(0, 0, -2);`

And after drawing, you can translate it back. Now when you launch it, you'll see a quad on your screen. We need to rotate the cube inorder to see all its sides. Let's do that by calling
 `glRotatef()`
function. We are going to rotate on both the x and y axes to see all the sides.

 1 `glRotatef(1, 1, 1, 0);`

This creates the following cube on your screen.

You've the cube being rendered and you are now able to see all it's sides.

# Final Rendering Code

And here is the total render method.

 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 `public void render(){    // Clean both color and depth buffers    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    // Translate into the view    glTranslatef(0, 0, -2);    // Rotate on both x and y axes    glRotatef(1, 1, 1, 0);    // Bind the vertex VBO    glBindBuffer(GL_ARRAY_BUFFER, vboVertexID);    glVertexPointer(3, GL_FLOAT, 0, 0);    // Bind the color VBO    glBindBuffer(GL_ARRAY_BUFFER, vboColorID);    glColorPointer(3, GL_FLOAT, 0, 0);    // Draw the cube with triangle strip    glDrawArrays(GL_TRIANGLE_STRIP, 0, 24);    // Translate back    glTranslatef(0, 0, 2);}`

# Source Code

Tutorial11.java

Slyth2727

JGO Coder

Medals: 7
Projects: 4

"dd if=/dev/zero of=/dev/sda" = oh no..

 « Reply #1 - Posted 2013-09-17 15:48:28 »

Good job, I'm loving these

People are like dirt. They can either nourish you and help you grow as a person or they can stunt your growth and make you wilt and die.
Wise men speak because they have something to say; Fools because they have to say something.
- Plato
SHC
 « Reply #2 - Posted 2013-09-17 16:02:48 »

Thanks!

Rakiayn

Senior Newbie

 « Reply #3 - Posted 2013-09-25 12:31:13 »

If you make more cubes, lets say one in the center and one somewhere next to it.
will the second cube rotate around the other cube or around his own axis?
SHC
 « Reply #4 - Posted 2013-09-25 12:52:26 »

@Rakiayn

It depends on how you are using the glRotatef function. If you use it once and render all the cubes then revert back, the entire scene rotates around the origin. If you have multiple calls to that function before rendering each cube, then each cube will rotate on it's center.

Rakiayn

Senior Newbie

 « Reply #5 - Posted 2013-10-24 00:29:16 »

got another question
I have simulation in which objects are constantly created and destroyed.
how do I implent that in the vertexbuffer object?
the vertexbuffer has te be cleared every tick right?
can you make a tutorial with a  vertextbuffer object in which the vertex buffer is not static?
opiop65

JGO Wizard

Medals: 68
Projects: 4

Nishu Games

 « Reply #6 - Posted 2013-10-24 01:56:58 »

GL_STATIC just tells OpenGL to expect not many changes to the buffer. You still can modify the terrain a lot, and quite honestly, static terrain is most likely what you have. Unless you have a 3D world where there are constantly explosions/modifications to the terrain etc... Then you don't need to change anything.

SHC
 « Reply #7 - Posted 2013-10-24 02:56:54 »

@Rakiayn

There is a way. Make sure that the models are going to load only once. There can be many game objects (no models) in the game which holds a reference to the model, i.e., there will be a single model that will be referenced by many game objects. So whenever you are rendering them, translate to the position of the object and then render the model that is referenced by the object. In this way, you can constantly create them and destroy them.

Hope it helps.

Rakiayn

Senior Newbie

 « Reply #8 - Posted 2013-10-24 12:45:48 »

does that mean every model has its own VBO?
SHC
 « Reply #9 - Posted 2013-10-24 14:12:19 »

@Rakiayn

Yes. Every model has it's own vbo. The VBOs wont be updated but before rendering the model, we translate to the position using matrices. In the future, I'll be showing how to make a Transform class and the matrices it produce will be sent to the shaders and position will be applied at shader level.

quew8

Senior Member

Medals: 13

 « Reply #10 - Posted 2013-10-24 17:06:13 »

Actually, it is generally better to store several models in the same VBO. That way you don't have to keep switching between them and reassigning pointers (which can be quite a drain on the GPU).
SHC
 « Reply #11 - Posted 2013-10-24 17:18:41 »

@quew8

Can you give an example of how it's done? I think it may not be suitable since he wanted to create and destroy several objects at every step.

quew8

Senior Member

Medals: 13

 « Reply #12 - Posted 2013-10-24 18:40:18 »

Well like you said, creating / removing many objects is fine if you are referencing the same VBO the whole time. As an example, let me tell you how I'm currently doing things. I have several "Groups" consisting of a VBO and an IBO. Each Group is split up into "Sections" - the contents of a section share the same Texture and rendering mode (shader stuff and pointers mostly). Each Section has a list of "Handles" which point to areas within the index buffer. When it is told to draw, the section loops through the handles, asks it whether it needs to be drawn, and if so does so. In static sections it groups the draws into one OpenGL call.

In Summary:

For Each Group {
BindVBO();
BindIBO();
For Each Section {
SetupPointers();
For Each Handle() {
If Should Draw {
DrawFromTo(Handle.Start, Handle.End);
}
}
}
}
SHC
 « Reply #13 - Posted 2013-10-25 15:02:54 »

@quew8

Nice answer. I'd like to appreciate you but unable since there is no appreciate link on this board. shit.

quew8

Senior Member

Medals: 13

 « Reply #14 - Posted 2013-10-25 18:47:13 »

Thank you. Just find the stupidest post I've ever written and appreciate that.
matheus23

JGO Wizard

Medals: 82
Projects: 3

You think about my Avatar right now!

 « Reply #15 - Posted 2013-10-25 23:21:26 »

Thank you. Just find the stupidest post I've ever written and appreciate that.

call this URL and you'll appreciate that post (I think, haven't tested, though):
http://www.java-gaming.org/index.php?action=modifykarma;sa=applaud;uid=171910;topic=30755;m=287677;sesc=3bdc95a5d37c20ed37e603fb04dea415

See my:
My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
quew8

Senior Member

Medals: 13

 « Reply #16 - Posted 2013-10-26 00:25:23 »

Wow. I was just joking but thanks. I appreciate it.
Rakiayn

Senior Newbie

 « Reply #17 - Posted 2013-10-30 15:01:27 »

I appreciate your answers.  but I dont understand much of it, looks like I have a lot to learn.
at the moment I have one VBO that handles all models in the game.
1. at the start of the gameloop the VBO vertex gets cleared.
2. then when the objects get updated they add their vertex point coordinates to the VBO vertex.
3. then the VBO renders.
4. then it restarts to point 1.

Is this a good way of rendering? it seems kind of slow to me.
SHC
 « Reply #18 - Posted 2013-10-30 17:36:53 »

@Rakiayn

It makes a lot slower than you think. Every object has a position and a reference to it's model like this example.

 1  2  3  4  5 `public class GameObject{    private Vector3f position;    private Model model;}`

Every update, you move the objects, the models are untouched. Then after moving the objects, you translate to the position before drawing it's model.

 1  2  3  4  5  6  7 `for (GameObject obj : objects){    obj.update();    Camera.translate(obj.getPosition());    obj.getModel().render();    Camera.translate(-obj.getPosition());}`

You get it? Just try to read the code line by line and this is how I use (In my benchmarking, I got more than 1750 fps).

@quew8

I can't find the stupidiest post you are referring to. I gave a medal in your other topic though.

@mathues23

quew8

Senior Member

Medals: 13

 « Reply #19 - Posted 2013-10-30 17:47:42 »

@Rakiayn Also I'd just like to add that when you do need to update the VBO data, there is no point "clearing" it first. Just overwrite the data that's already there.

@SHC Yeah sometimes that post is hard to differentiate from the others. They're all pretty stupid. Cheers though.
Rakiayn

Senior Newbie

 « Reply #20 - Posted 2013-10-30 21:45:18 »

@SHC
yes I understand , thanks for the explanation and for these tutorials.
I am looking forward to your other tutorials.

@quew8
I clear it because the objects vertex data are added at the end of the array leading to object being rendered double if it is not cleared.
but I guess if every object has its own positions in the array for its vertexes, you could just overwrite it.
quew8

Senior Member

Medals: 13

 « Reply #21 - Posted 2013-10-31 10:48:12 »

@Rakiayn Exactly. That way, you are only updating what absolutely needs to be updated. But I would stress as @SHC said, only change the data in the VBO when it is a permanent change. Like the model's colour has changed or something (depends on your game really). If it's just moving then use matrix transforms.
Pages: [1]
 ignore  |  Print

 Add your game by posting it in the WIP section, or publish it in Showcase. The first screenshot will be displayed as a thumbnail.
 CodeHead (11 views) 2013-12-10 22:53:11 Phased (24 views) 2013-12-07 10:06:59 wessles (52 views) 2013-11-28 23:37:31 wreed12345 (61 views) 2013-11-23 17:42:34 Damocles (109 views) 2013-11-15 12:23:59 StumpyStrust (87 views) 2013-11-14 14:42:32 StumpyStrust (82 views) 2013-11-14 14:41:43 EliwoodL (94 views) 2013-11-11 10:52:42 EliwoodL (87 views) 2013-11-11 10:52:33 EliwoodL (87 views) 2013-11-11 10:51:49
 opiop65 26x Spasi 15x wessles 15x CodeHead 14x Groboclown 13x theagentd 12x ctomni231 11x HeroesGraveDev 11x Roquen 10x Riven 10x SHC 10x saucymeatman 8x Luffaren 8x Varkas 7x jmguillemette 7x ags1 7x
 HotSpot Intrinsicsby Roquen2013-11-25 17:44:34How do I start Java Game Development?by Nate2013-11-18 18:35:15Concurrencyby Roquen2013-11-08 22:39:59Concurrencyby Roquen2013-11-08 20:43:31Concurrencyby Roquen2013-11-08 15:31:17Concurrencyby Roquen2013-11-08 15:20:42Concurrencyby Roquen2013-11-08 15:00:50Resources for learning software design.2013-10-17 16:25:24