3

I am creating an animation in Maya that is a minute long, and I intend to render it in OpenGL. I'm doing this is as a project at college.

The scene consists of just a human face making distorted expressions. The mesh has about 2200 quad faces.

I found a perl script that converts Wavefront object files to vertex and normal arrays. I intend to animate in Maya at 24fps, then export the mesh in every frame to a Wavefront object file, and then run all of them through the perl script which will give me vertex and normal arrays.

So, to test the feasibility, I converted two frames of the animation in Maya to object files and ran it through the script (after tweaking it) which gave me thousands of glVertex and glNormal calls. I copied all that to my C++ program and compiled it. It runs smoothly.

Considering how large the program will be when I copy 60sec*24frame worth of glVertex and glNormal statements into the program, I want to try using VBOs. So, I read about it but I'm not quite grasping the implementation.

So my first question is : What is best method to implement VBOs in this case?

I'm thinking of 2D arrays for both vertices and normals, one for every frame; and GL_STATIC_DRAW_ARB for the "usage" parameter of the glBufferDataARB().

Say, if my animation is 5 frames long, my face mesh consists of 2200 vertices and normals, then I'll create:

GLfloat face_vertices[5][2200] = {.....};
GLfloat face_normals[5][2200] = {.....};

My second question : Will the above code work or perform "well" with VBOs?

Also, I'm unsure if this information is important, but my computer is running on an Intel 82945G graphic card, and I'm pretty sure the PCs at my college are running on Intel as well. Just thought I'd mention that.

UPDATE

Performance is also a concern.

adi
  • 69
  • 3
  • How did you do your rig? Are the vertexes mapped linearly to joints? If yes, you could easily export mesh with bones and animation into a Wavefront file and have it read by one of the many game engines. Some of them are capable of playing the animation on hardware shaders, but i'm not sure whether the Intel is on the supported list. – Rekin Apr 18 '12 at 20:11
  • Oh, i made quite a mental jump out there. As for your VBO optimisations - they only work for static meshes with the old (fixed, e.g. no shaders) pipeline. So, if the intel is not very capable, all you could do is to use a number of VBO's - each for one frame. – Rekin Apr 18 '12 at 20:14
  • @Rekin *"they only work for static meshes with the old pipeline"* - Huh? Now what do you mean with that? By the way, he doesn't use any rigging, but a simple morphing anmimation. – Christian Rau Apr 22 '12 at 14:36

2 Answers2

1

I'm thinking of 2D arrays for both vertices and normals, one for every frame; and

I think that's incorrect solution. With this amount of data it makes sense to stream it. For example, keep 1 second of animation in memory, load the rest on demand. I believe there's GL_STREAM_**** flags for this scenario.

The better solution would be to export bones from maya and their animation. (In this case you'll need one mesh that will never change)

The only situation in which you would have to export frame-by-frame per-vertex animation is when you export something insanely computationally expensive. The only realistic scenario I can think of is 3D fluid meshes (topology change very frame, etc) - everything else can be computed either on CPU or on GPU. However, your post does not indicate that this is your scenario. So, By murphy's law I'll have to assume that you're using inefficient solution for a problem that can be solved differently.

: Will the above code work or perform "well" with VBOs?

Impossible to answer, because you didn't say how you're going to draw the data. It is possible to bring any machine to its knees even with simple geometry by abusing shaders, alpha blending, or rendering same thing MANY times.

SigTerm
  • 26,089
  • 6
  • 66
  • 115
1

If you could run smoothly two frames of your animation, you could run smoothly 60*24 frames "worth of glVertex and glNormal statements", if you can automatically generate the GL calls from your Maya animation. The only problem of this approach is that you source code and binary executable would be insanely huge. This is the issue that makes your approach "bad".

So, first, instead of one glVertex call for every vertex data, you could well have your data in an array (or std::vector, for that matter), and iterate through it using a simple loop:

std::vector<int> idx;
std::vector<vertex> frame_data;
...
glBegin(GL_QUADS);
for(int i = 0; i < idx.size(); ++i) {
  glVertex3f(frame_data[idx].x, frame_data[idx].y, frame_data[idx].z);
  glNormal3f(frame_data[idx].nx, frame_data[idx].ny, frame_data[idx].nz);
}
glEnd();

Idx represents the faces, each 4 elements in the idx forms a quad. Frame_data is the specific vertex data for that frame, you must have one such array for each frame, and this data is indexed by idx. This way, the only problem you have to solve is how to read this data into your application. If you can generate the glVertex calls from your mesh file, you could instead generate a file that you can easily load inside your application using C++ fstream, and build the arrays of data, then just iterate through them and make the drawing calls.

You would not see the performance difference between using glBegin()/glEnd() and VBOs in this case, because 2200 quads is a too low count to make any difference, but it would be an interesting exercise for you. Organizing the data in the arrays I told you (idx and vertex_data) is the first step to use VBO. You must pack all data relative to one vertex inside a single structure:

struct vertex {
  float x, y, z; // Position
  float nx, ny, nz; // Normal
};
...
vertex frame_data[v_count];
uint16_t idx[2200 * 4]; // 4 vertices makes one face

Notice that v_count is not 2200. This is your quads count, so this number is relative to idx size, not the frame_data, i.e. the same vertex may be used in multiple quad faces.

You will need two buffers, one static to hold the idx (a GL_ELEMENT_ARRAY_BUFFER with GL_STATIC_DRAW), because this won't change during the execution, and another "stream" buffer to hold the vertex data (GL_ARRAY_BUFFER with GL_STREAM_DRAW). The last uses "GL_STREAM_DRAW" because you would need to rewrite its content each frame, for the animation. See glBufferData.

lvella
  • 12,754
  • 11
  • 54
  • 106
  • thanks for all your replies, I will look into them.....kind of swamped right now. see UPDATE @SigTerm, I intend to draw it with glDrawElements(). – adi Apr 25 '12 at 17:35