Hardcheese
Posts: 36
Joined: Sat Sep 01, 2012 12:25 pm

Creating 3D characters and making textures

Tue Oct 09, 2012 6:18 pm

Hi,

I am currently trying to make my own 3D game for the pi and I am using the Penguins Puzzle game as a guide. I was wondering how you go about making the level and 3D character binaries and how you make the texture images work with OpenGL ES. Thanks.

jmacey
Posts: 135
Joined: Thu May 31, 2012 1:05 pm

Re: Creating 3D characters and making textures

Thu Oct 11, 2012 6:02 pm

There are many ways to create models, you would usually use a package such as blender http://www.blender.org/ (open source) or maya http://usa.autodesk.com/maya/ (there is a free learning edition). To model your assets, unfortunately neither will work on the pi.

Once you have the models I would suggest exporting them using the obj file format http://en.wikipedia.org/wiki/Wavefront_.obj_file which is a simple text file format that is easy to parse and load.

There are also other 3rd party libraries which can load a whole lot of different file formats I would recommend http://assimp.sourceforge.net/

For texture images you can use any tool (under linux I would use the gimp) or photoshop, save these as Tiff or some other lossless format (TGA is actually easy to read and load and loads of textbooks use this). I personally use ImageMagick under the pi to do image processing stuff but you could also use DevIL or similar.

One really good place to look for models and textures is http://opengameart.org/ which has loads of free to use (non comercial) assets. There is also http://www.turbosquid.com/ but these are more commercially focused.

The process of using these is quite complex but the basic process is

LoadImage Texture (use a library like image magick)
Create an OpenGL texture Object and bind the image data to it (store the texture id for later use)
Load the Mesh Data (it should have Vertex, UV and possibly Normal information) and store to a Buffer Object.

Load a simple texture Shader (this will use the UV values from the mesh to lookup in the currently bound texture the colour)
For each Mesh
Make sure the correct texture and buffer object are bound
Call Draw Array (glDrawArrays or similar commands)

I'm afraid the process is quite complex but there are many tutorials around that do this and there are some on my website (but for Desktop OpenGL) http://nccastaff.bournemouth.ac.uk/jmacey/ I also have a more complex library which will do a lot of this work for you (piNGL also on my website).

If you need more detail let me know and I will see what I can find.

Good luck

jon

Hardcheese
Posts: 36
Joined: Sat Sep 01, 2012 12:25 pm

Re: Creating 3D characters and making textures

Fri Oct 12, 2012 2:41 pm

Thanks for the reply. I don't really get how I would draw the Characters In 3D could you give me an example piece of code which would draw a 3D line.

User avatar
jackokring
Posts: 816
Joined: Tue Jul 31, 2012 8:27 am
Location: London, UK
Contact: ICQ

Re: Creating 3D characters and making textures

Fri Oct 12, 2012 2:47 pm

Drawing a line would confuse, as filled triangles are the unit of textured drawing. If you need 2D line drawing maybe OpenVG is better. There are already many googleable examples of OpenGLES2.
Pi[NFA]=B256R0USB CL4SD8GB Raspbian Stock.
Pi[Work]=A+256 CL4SD8GB Raspbian Stock.
My favourite constant 1.65056745028

Hardcheese
Posts: 36
Joined: Sat Sep 01, 2012 12:25 pm

Re: Creating 3D characters and making textures

Fri Oct 12, 2012 11:44 pm

I have been on the OpenGameArt website and have downloaded a texture I want to use, but I understand you need to convert the blender file to Object code in order to use it. How would I do that on the Pi?

The Penguins Puzzle code does something like this to load the model:

#define MODELREF(x) extern char _binary_data_ ## x ## _pi_start
#define MODEL(x,p1,p2,p3) model_new(&_binary_data_ ## x ## _pi_start,p1,p2,p2)
MODELREF(iceblock);
MODEL(iceblock);

This uses the iceblock.o file to load the model. How would I get to a stage in my code in which this code would load my model? Thanks in advance for any replies.

jmacey
Posts: 135
Joined: Thu May 31, 2012 1:05 pm

Re: Creating 3D characters and making textures

Sat Oct 13, 2012 7:40 am

That code looks like it reads it's own data format which I presume is packed into penguinspuzzle.bin file. If you look in the data directory you can see all the models stored as json files and again I'm presuming that the .pi files in the data directory are the textures as raw RGB data.

Again not knowing how the system was written, I would think there is a tool somewhere that reads and packs this data into the bin file and that is what is used for the game. Without this code etc it would be difficult to reverse engineer the engine used here for your own needs

Hardcheese
Posts: 36
Joined: Sat Sep 01, 2012 12:25 pm

Re: Creating 3D characters and making textures

Sat Oct 13, 2012 8:34 am

How would you go about loading the models without the PenguinsPuzzle.bin file?

jmacey
Posts: 135
Joined: Thu May 31, 2012 1:05 pm

Re: Creating 3D characters and making textures

Sat Oct 13, 2012 8:56 am

What format are the models in?

Basically what OpenGL ES wants is a list of data about the models, usually this is presented in the format

Vertices (Vec3) this is the xyz position of the mesh point
Normals (Vec3) this is used in lighting calculations, if you only want textures you don't need this
UV (Vec2) these are the texture co-ordinates which map from 0-1 in both directions of the image you are loading.

If you are drawing using GL_TRIANGLES you would create an array of individual triangles for the mesh (loaded from your model's face information) where you would have for each triangle something like

Code: Select all

typedef struct
{
 GLfloat x;
 GLfloat y;
 GLfloat z;
 GLfloat nx;
 GLfloat ny;
 GLfloat nz;
 GLfloat u;
 GLfloat v;

}Vert;

Vert Model = new Vert[ num faces * 3]; // each tri face has 3 verts.
Next this must be send to OpenGL, this is best done using Vertex buffer objects

Code: Select all

GLuint vboID;
glGenBuffers(1, &vboID);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, sizeof(Model), &Model, GL_STATIC_DRAW);
You would now need to have shaders loaded to do your texturing (if your using GLES2) and map the vertex attributes from your program to the shader, this is done with

Code: Select all

glVertexAttribPointer ..
glEnableVertexAttribArray ..
glDrawArrays ..
As you can see it's quite a complex process and very dependant upon what context you are working in. For a more in depth example have a look at my piNGL library here http://code.google.com/p/pingl/ there is an example that loads in a mesh in OBJ format and textures it. There is a lot of code in the library that you can re-use and see how OpenGL works. I've also implemented my own version of the desktop VertexArrayObject in a class so it works more like desktop OpenGL as well.

Have a look at the slides here http://nccastaff.bournemouth.ac.uk/jmac ... index.html as well. The introduction to Modern OpenGL will give you more details.

jon

Hardcheese
Posts: 36
Joined: Sat Sep 01, 2012 12:25 pm

Re: Creating 3D characters and making textures

Sat Oct 13, 2012 9:04 am

The model is in .blend format. Would you need to convert it to object code to use it if so how?

jmacey
Posts: 135
Joined: Thu May 31, 2012 1:05 pm

Re: Creating 3D characters and making textures

Sat Oct 13, 2012 9:11 am

That is a blender file the format is here http://www.blender.org/development/arch ... le-format/ however it would be easier to load it in blender (you would need another computer as the pi will not run blender) and export it into an easier to read format such as obj

Hardcheese
Posts: 36
Joined: Sat Sep 01, 2012 12:25 pm

Re: Creating 3D characters and making textures

Sat Oct 13, 2012 3:03 pm

Once you have the .obj file containing all the vertices how do you compile your code with it? Also when you pass the argument &Model is that the obj file you are passing? How do you make sure your code has access to the obj file and can draw its vertices? Sorry, this has confused me a bit. Thanks for all your answers so far. :)

Hardcheese
Posts: 36
Joined: Sat Sep 01, 2012 12:25 pm

Re: Creating 3D characters and making textures

Sat Oct 13, 2012 4:11 pm

After doing a bit of searching around I have found that it is incredibly complicated to load obj files in Opengl ES as there is no easy function to do it. I guess what I need is a full code sample which would allow me to load the obj files so I can use them and then draw the vertices, I know this is quite a lot to ask. Your pingl example won't work for me as I am using C.

jamesh
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 25019
Joined: Sat Jul 30, 2011 7:41 pm

Re: Creating 3D characters and making textures

Sat Oct 13, 2012 6:10 pm

Principal Software Engineer at Raspberry Pi (Trading) Ltd.
Contrary to popular belief, humorous signatures are allowed. Here's an example...
“I own the world’s worst thesaurus. Not only is it awful, it’s awful."

Hardcheese
Posts: 36
Joined: Sat Sep 01, 2012 12:25 pm

Re: Creating 3D characters and making textures

Sat Oct 13, 2012 10:34 pm

All those books listed look as though they would be good for OpenGL but OpenGL ES is quite different to OpenGL from my experience.

jmacey
Posts: 135
Joined: Thu May 31, 2012 1:05 pm

Re: Creating 3D characters and making textures

Sat Oct 13, 2012 11:37 pm

OpenGL ES is a subset of OpenGL and for what you are talking about are very similar.

I think the main conceptual problem you have is that OpenGL (all variants) are basically triangle renderers with a the ability to process either via the gpu and shaders of the fixed function pipeline lights and a little bit of other low level stuff.

The things your talking about (loading models and textures etc) are far outside of the OpenGL remit. So you need to think about how you would load and process these things to pass to OpenGL. If you want a game engine that will encapsulate all the hard stuff you should look at things like OGRE http://www.ogre3d.org/ not sure if it's been ported to the pi yet but if it has this would do most of the things you want.

On another note, if you read about the OBJ file format http://en.wikipedia.org/wiki/Wavefront_.obj_file it is actually really easy to write C code to parse and load it and that in itself is a good exercise when learning programming. Basically ( in c as you have no simple dynamic arrays)

Read the file and count each occurrence of v,vt and vn as well as the f.

Allocate memory for each and rewind the file to the beginning.

each time you find one of the symbols read the values and put it into the array (v,vt,vn).

The face data indexes into the other 3 arrays (make sure your subtract 1 from the index as the OBJ indices are from 1 and C uses 0) this will give the triangles for each face. This can then be loaded into OpenGL

Hardcheese
Posts: 36
Joined: Sat Sep 01, 2012 12:25 pm

Re: Creating 3D characters and making textures

Sun Oct 14, 2012 1:03 pm

Okay, thanks for your help. I'll see what I can do in terms of writing my own. My models obj file also comes with a file format called mtl included by the obj file. Will that complicate matters?

jmacey
Posts: 135
Joined: Thu May 31, 2012 1:05 pm

Re: Creating 3D characters and making textures

Sun Oct 14, 2012 6:02 pm

the mtl file is a material template file, it contains the parameters for shaders used in the creation of the model, you could use them in your glsl shaders as parameters for Ambient, Diffuse and Specular, look at the Obj spec here if you haven't already http://en.wikipedia.org/wiki/Wavefront_ ... te_library

User avatar
panik
Posts: 369
Joined: Fri Sep 23, 2011 12:29 pm
Location: Netherlands

Re: Creating 3D characters and making textures

Sun Oct 14, 2012 8:19 pm

Tip: export a standard cube as an .obj file, and load it up in a text editor. It's small enough to assemble a mental picture of what vertices/uv's/normals go where, and it's easier to see where your parsing goes wrong.

Start with exporting .obj's triangulated, so it's easier to draw with glDrawArrays(GL_TRIANGLES, start_pos, num_vertices), and see what you're doing. If you don't triangulate, an 'f' line can have more than 3 indices to vertices, and must be drawn differently (with GL_QUAD_STRIP or GL_POLYGON, for example).

A triangulated, uv-mapped standard Cube from Blender with normals, looks like this. It's 2x2x2 units big, with the pivotpoint at 0,0,0:

Code: Select all

# Blender v2.62 (sub 0) OBJ File: ''
# www.blender.org
mtllib cube.mtl
o Cube
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
v 1.000000 1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn -0.000000 -0.000000 1.000000
vn -1.000000 -0.000000 -0.000000
vn 0.000000 0.000000 -1.000000
usemtl Material
s off
f 1/1/1 2/2/1 3/3/1
f 1/1/1 3/3/1 4/4/1
f 5/1/2 8/2/2 7/3/2
f 5/1/2 7/3/2 6/4/2
f 1/1/3 5/2/3 6/3/3
f 1/1/3 6/3/3 2/4/3
f 2/1/4 6/2/4 7/3/4
f 2/1/4 7/3/4 3/4/4
f 3/1/5 7/2/5 8/3/5
f 3/1/5 8/3/5 4/4/5
f 5/1/6 1/2/6 4/3/6
f 5/1/6 4/3/6 8/4/6
Also have a look at how a cube is drawn in /opt/vc/src/hello_pi/hello_triangle.c and cube_texture_and_coords.h (with 6 quads, instead of 12 triangles like above). It's probably an easier to understand example, but I admit I haven't seen the PenguinsPuzzle code yet.

Edit: unlike the hello_triangle.c example, you only have to call glDrawArrays() once, and refer to *all* the triangles for each model. The example calls glDrawArrays() for each quad, which is not very efficient.

Hardcheese
Posts: 36
Joined: Sat Sep 01, 2012 12:25 pm

Re: Creating 3D characters and making textures

Mon Oct 15, 2012 5:12 pm

I have the vertex data in an array. For example if you wanted face 3 vertex 2 to retrieve it you would use the following code:

Code: Select all

model->TriangleArray[3].Vertex[1]
How do I pass that data to OpenGL ES and then draw the vertices.

User avatar
panik
Posts: 369
Joined: Fri Sep 23, 2011 12:29 pm
Location: Netherlands

Re: Creating 3D characters and making textures

Mon Oct 15, 2012 6:10 pm

If you convert the array you have into a continuous array of floats, it should be something like this:

Code: Select all

// pass the data to OpenGL ES
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, my_array_of_vertex_data);

// draw the vertices
GLsizei count = number_of_triangles * 3;
glDrawArrays(GL_TRIANGLES, 0, count);

Hardcheese
Posts: 36
Joined: Sat Sep 01, 2012 12:25 pm

Re: Creating 3D characters and making textures

Mon Oct 15, 2012 7:04 pm

I'm not sure whether it's just me being stupid but it seems incredibly difficult to convert the arrays into one continuous array without the use of dynamic arrays.

User avatar
hexelpdkk
Posts: 177
Joined: Fri Feb 24, 2012 4:40 pm

Re: Creating 3D characters and making textures

Mon Oct 15, 2012 7:11 pm

For some fairly straight forward example code, have a look at https://github.com/chriscamacho/gles2framework. In particular, this has code that converts wavefront .obj format files into binary objects, it handles the models, shaders and textures as loadable resources, and has simple demo code for all of it. It also has font and sprite routines. It was a good starting point for me - I've been doing simple stuff by exporting blender files as wavefront .obj format, and loading them in this.

User avatar
panik
Posts: 369
Joined: Fri Sep 23, 2011 12:29 pm
Location: Netherlands

Re: Creating 3D characters and making textures

Mon Oct 15, 2012 7:16 pm

You do know the number of triangles up front. Right?

Code: Select all

GLfloat * my_array_of_vertex_data = new GLfloat[number_of_triangles*3];
Then fill the array by looping through the array you have now?
I hope I understand you correctly. I was where you are now about 2 months ago :D

Hardcheese
Posts: 36
Joined: Sat Sep 01, 2012 12:25 pm

Re: Creating 3D characters and making textures

Mon Oct 15, 2012 7:41 pm

Yes, I know the number of triangles. The problem is that I am using C and I can't access the array outside the loop if I declare it in the loop.

Narishma
Posts: 151
Joined: Wed Nov 23, 2011 1:29 pm

Re: Creating 3D characters and making textures

Mon Oct 15, 2012 8:26 pm

In C,

Code: Select all

GLfloat *array = (GLfloat *)malloc(number_of_triangles * 3 * sizeof(GLfloat));
And declare it outside the loop.

Return to “OpenGLES”