0
\$\begingroup\$

I have a file in my project that defines 2 numbers and 4 arrays:

#define NUM_TEAPOT_OBJECT_VERTEX 824
#define NUM_TEAPOT_OBJECT_INDEX 1024 * 3

static const float teapotVertices[NUM_TEAPOT_OBJECT_VERTEX * 3] =
{
    // ...
};

static const float teapotTexCoords[NUM_TEAPOT_OBJECT_VERTEX * 2] =
{
    // ...
};

static const float teapotNormals[NUM_TEAPOT_OBJECT_VERTEX * 3] =
{
    // ...
};

static const unsigned short teapotIndices[NUM_TEAPOT_OBJECT_INDEX] =
{
    // ...
};

These, together with a texture as jpeg, define a teapot 3D model.

How can I generate these arrays from a 3D model? Our 3D models are in .obj (and a .jpeg for texture).

I use these arrays in the following code:

Vuforia::Matrix44F modelViewMatrix = Vuforia::Tool::convertPose2GLMatrix(result->getPose());
// OpenGL 2
Vuforia::Matrix44F modelViewProjection;

VuforiaApplicationUtils::translatePoseMatrix(0.0f, 0.0f, kObjectScale, &modelViewMatrix.data[0]);
VuforiaApplicationUtils::scalePoseMatrix(kObjectScale, kObjectScale, kObjectScale, &modelViewMatrix.data[0]);
VuforiaApplicationUtils::multiplyMatrix(&projectionMatrix.data[0], &modelViewMatrix.data[0], &modelViewProjection.data[0]);

glUseProgram(shaderProgramID);

glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)teapotVertices);
glVertexAttribPointer(normalHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)teapotNormals);
glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)teapotTexCoords);

glEnableVertexAttribArray(vertexHandle);
glEnableVertexAttribArray(normalHandle);
glEnableVertexAttribArray(textureCoordHandle);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, augmentationTexture[0].textureID);
glUniformMatrix4fv(mvpMatrixHandle, 1, GL_FALSE, (const GLfloat*)&modelViewProjection.data[0]);
glUniform1i(texSampler2DHandle, 0 /*GL_TEXTURE0*/);
glDrawElements(GL_TRIANGLES, NUM_TEAPOT_OBJECT_INDEX, GL_UNSIGNED_SHORT, (const GLvoid*)teapotIndices);

glDisableVertexAttribArray(vertexHandle);
glDisableVertexAttribArray(normalHandle);
glDisableVertexAttribArray(textureCoordHandle);

If you know how I can adapt this code to load standard 3D models, such as .obj files, please help.

\$\endgroup\$
1
\$\begingroup\$

Your code seems like it works in a reasonable way to display a 3D model. What you're missing is actually reading in a .obj file. The .obj file format is a fairly well documented format. You need to read the vertex, texture coordinate, vertex normal, and index data from the file and construct your arrays to match how you've told OpenGL you've laid them out. The l, p, and f commands in the file tell you the index order for each of the other 3 types of data (vertex coordinates, texture coordinates, and normals). (And note that they don't have to match - you can have vertex index 1 with texture coordinate index 53 and vertex normal index 312.)

One strategy would be to do 2 passes. One that reads all the data in from the files, and another that then copies them into new arrays with the appropriate order so the indices match.

There probably already exist libraries to do this, though I've never personally used any. An internet search will surely turn up some.

\$\endgroup\$
  • \$\begingroup\$ Yes thank you, indexing the obj file was my biggest problem. I now know what those indices signify, but back then I could just not understand why there is an extra array that just does not exist in the obj format. \$\endgroup\$ – user1009013 Mar 16 '17 at 14:23
1
\$\begingroup\$

http://www.assimp.org/ Open Asset Import Library (short name: Assimp) is a portable Open Source library to import various well-known 3D model formats in a uniform manner. The most recent version also knows how to export 3d files and is therefore suitable as a general-purpose 3D model converter. See the feature list.

\$\endgroup\$
1
\$\begingroup\$

I would support @bobenko suggestion to use assimp. Also, there is a lot of code to be write, even if you have a scene graph as returned by assimp. Instead it is better if you can using an existing library to do the rendering for you at a higher level.

I would suggest using open frameworks, which also has an Assimp Model Loader.

You can find an example to load a model here. The two most important steps here in are to load the model and then draw it, the code for which really is:

ofxAssimpModelLoader model;
model.loadModel("file_name.3DS");

void ofApp::draw(){
   ofBackground(50, 50, 50, 0);
   ofSetColor(255, 255, 255, 255);

   model.setPosition(ofGetWidth()/2, (float)ofGetHeight() * 0.75 , 0);
   model.drawFaces();
}

You should be able to easily adapt the above linked example to load your .obj files.

\$\endgroup\$
  • \$\begingroup\$ That is literally the worst name for a library. \$\endgroup\$ – Krythic Mar 1 '17 at 17:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.