Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (576)
games submitted by our members
Games in WIP (497)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  LWJGL Tutorial Series - A Rotating Cube  (Read 11163 times)
0 Members and 1 Guest are viewing this topic.
Offline 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 OpenGL
glMatrixMode(GL_PROJECTION);
gluPerspective(70f, 800f / 600f, 1, 1000);
glViewport(0, 0, Display.getWidth(), Display.getHeight());

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// Enable Depth Testing
glEnable(GL_DEPTH_TEST);

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

Creating QUADS


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);
}

That's it and you have your rotating cube. That's the end of this tutorial and in the next part, let's learn about shaders. If you've found any mistakes in this articles, please notify me with comments.

Source Code


Tutorial11.java

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

Good job, I'm loving these Smiley

Check out Escaping Vox, a 3D
|\ _\  voxel based puzzler!
 \|_|
Offline SHC
« Reply #2 - Posted 2013-09-17 16:02:48 »

Thanks!

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline 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?
Offline 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.

Offline 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?
Online opiop65

JGO Kernel


Medals: 123
Projects: 7
Exp: 3 years


Team Alluminum


« 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.

Offline 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.

Offline Rakiayn

Senior Newbie





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

does that mean every model has its own VBO?
Offline 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.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline quew8

JGO Coder


Medals: 23



« 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).
Offline 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.

Offline quew8

JGO Coder


Medals: 23



« 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();
        BindAndSetupShader();
        For Each Handle() {
            If Should Draw {
                DrawFromTo(Handle.Start, Handle.End);
            }
        }
    }
}
Offline 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.

Offline quew8

JGO Coder


Medals: 23



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

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

JGO Wizard


Medals: 96
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
Offline quew8

JGO Coder


Medals: 23



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

Wow. I was just joking but thanks. I appreciate it.
Offline 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.
Offline 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

Your link doesn't work unfortunately. It is saying 'Session expired'.

Offline quew8

JGO Coder


Medals: 23



« 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.
Offline 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.
Offline quew8

JGO Coder


Medals: 23



« 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.
Offline lcass
« Reply #22 - Posted 2014-01-04 19:19:14 »

would you be able to do one to show how you can render textures on these without a model
Online opiop65

JGO Kernel


Medals: 123
Projects: 7
Exp: 3 years


Team Alluminum


« Reply #23 - Posted 2014-01-04 19:24:42 »

You can't "render" textures in OpenGL without vertices.

Offline lcass
« Reply #24 - Posted 2014-01-06 20:52:31 »

I mean how to map textures to the faces of the cuboid.
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.

xsi3rr4x (11 views)
2014-04-15 18:08:23

BurntPizza (10 views)
2014-04-15 03:46:01

UprightPath (23 views)
2014-04-14 17:39:50

UprightPath (10 views)
2014-04-14 17:35:47

Porlus (27 views)
2014-04-14 15:48:38

tom_mai78101 (49 views)
2014-04-10 04:04:31

BurntPizza (107 views)
2014-04-08 23:06:04

tom_mai78101 (207 views)
2014-04-05 13:34:39

trollwarrior1 (176 views)
2014-04-04 12:06:45

CJLetsGame (182 views)
2014-04-01 02:16:10
List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:05:20
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!