PDA

View Full Version : Importing object from 3DS Max into Opengl.



Kazza92
07-22-2014, 12:05 PM
I have a few very basic models I want to import, I was just wondering if this is at all possible to do? And if so how to go about doing this?

Any help would be greatly appreciated, thank you :)

MtRoad
07-22-2014, 01:29 PM
You could try https://code.google.com/p/lib3ds/. The examples for the Graphics Gems 2 book (free online) use lib3ds, so they would provide example code. I don't have any experience with it myself. 3ds is getting quite old, so you may want to look into newer formats. The Unreal4 engine might have 3DS format loading.

If you are looking for simplicity the PowerVR SDK loads its own format right out of the box and comes with texture/model/text viewing/converting tools. My first day with PVR I had working models and onscreen text. It has good examples and it's free.

As an example: (it has a little objective-C mixed in, so don't hate me.)



// A quick model class I whipped up a few weeks ago for some demos.
class BBSimpleModel {
public:
BBSimpleModel() = delete;

/**
* Loads a model and builds the VBOs for static drawing.
*
* \param fileName_ location to tell PVR to find the model
* \throw Exception if model cannot be loaded or if model data is not interleaved
*/
explicit BBSimpleModel ( const char * fileName_ ) {
assert( fileName_ != nullptr );

CPVRTModelPOD scene;
SPODMesh * mesh;

// Get and set the read path for content files
NSString * resourcePath = [NSString stringWithFormat:@"%@/",[[NSBundle mainBundle] resourcePath] ];
CPVRTResourceFile::SetReadPath([resourcePath UTF8String]);

// Get and set the load/release functions for loading external files.
// In the majority of cases the PVRShell will return NULL function pointers implying that
// nothing special is required to load external files.
CPVRTResourceFile::SetLoadReleaseFunctions(NULL, NULL);

if( scene.ReadFromFile( fileName_ ) != PVR_SUCCESS ) {
std::cerr << "Unable to load model from " << fileName_ << std::endl;
throw "Unable to load model.";
}else {
// Grab the mesh from the scene
mesh = & scene.pMesh[0];

// Generate vertex VBO and indexed VBO
glGenBuffers( 1, & m_vertexVBO );
glGenBuffers( 1, & m_indexVBO );

if ( mesh->pInterleaved == 0 ) {
std::cerr << "ERORR: Mesh data is not interleaved." << std::endl;
throw "ERROR: Mesh data is not interleaved.";
}

// Saves vertex data into the vertex VBO
PVRTuint32 meshVerticesSizeBytes = mesh->nNumVertex * mesh->sVertex.nStride;
glBindBuffer( GL_ARRAY_BUFFER, m_vertexVBO );
glBufferData( GL_ARRAY_BUFFER, meshVerticesSizeBytes, mesh->pInterleaved, GL_STATIC_DRAW );

// Saves index data into the index VBO
PVRTuint32 meshIndicesSizeBytes = PVRTModelPODCountIndices( *mesh ) * mesh->sFaces.nStride;
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_indexVBO );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, meshIndicesSizeBytes, mesh->sFaces.pData, GL_STATIC_DRAW );

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

// Get position, & normal offsets, and vertex stride
m_offsetPosition = mesh->sVertex.pData;
m_offsetNormal = mesh->sNormals.pData;
m_vertexStride = mesh->sVertex.nStride;
m_numVertices = mesh->nNumFaces * 3;

// Get primitive type and index data type
m_indexDataType = (mesh->sFaces.eType == EPODDataUnsignedShort) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
// Assumes data is triangles. TODO: Handle other scenarios.

assert( m_numVertices > 0 );
assert( m_vertexStride > 0 );
assert( glIsBuffer( m_vertexVBO ) );
assert( glIsBuffer( m_indexVBO ) );
}

~ BBSimpleModel () {
glDeleteBuffers( 1, & m_vertexVBO );
glDeleteBuffers( 1, & m_indexVBO );
}

GLuint vertexVBO () const { return m_vertexVBO; }
GLuint indexVBO () const { return m_indexVBO; }

GLsizei vertexStride () const { return m_vertexStride; }
GLsizei numVertices () const { return m_numVertices; }
GLvoid* offsetPosition () const { return m_offsetPosition; }
GLvoid* offsetNormal () const { return m_offsetNormal; }
GLenum primitiveType () const { return GL_TRIANGLES; }
GLenum indexDataType () const { return m_indexDataType; }

void bindBuffers () {
glBindBuffer( GL_ARRAY_BUFFER, m_vertexVBO );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_indexVBO );
}


void unbindBuffers () {
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
}

private:
GLuint m_vertexVBO;
GLuint m_indexVBO;

PVRTuint32 m_vertexStride;
PVRTuint32 m_numVertices;
void * m_offsetPosition;
void * m_offsetNormal;
GLenum m_indexDataType;
};

// Drawing this mess:
// Yeah: I was lazy on this project and didn't use dynamic batching...
void
BBGraphics :: drawModelWithHemisphereLighting( BBSimpleModel * model_, mat4 modelMatrix_, vec3 materialColor_ ) {
// Check validity of block VBOs and block drawing program.
assert( glIsProgram( m_hemisphereLightingProgram->name() ) );
assert( model_ != nullptr );

// Enable ball VBO and program.
m_hemisphereLightingProgram->beginDrawing();

model_->bindBuffers();

GLsizei stride = model_->vertexStride();
glVertexAttribPointer( m_hemisphereLightingProgram->attribLocation("position"), 3, GL_FLOAT, 0, stride, model_->offsetPosition() );
glVertexAttribPointer( m_hemisphereLightingProgram->attribLocation("normal"), 3, GL_FLOAT, GL_FALSE, stride, model_->offsetNormal() );
mat4 mvp = m_camera.projectionTransform * m_camera.viewTransform * modelMatrix_;
mat3 normalMatrix = GLKMatrix3InvertAndTranspose( GLKMatrix4GetMatrix3( m_camera.viewTransform * modelMatrix_ ), nullptr );
glUniformMatrix4fv( m_hemisphereLightingProgram->uniformLocation("modelViewProjectionMatrix"), 1, 0, mvp.m );
glUniformMatrix3fv( m_hemisphereLightingProgram->uniformLocation("normalMatrix"), 1, 0, normalMatrix.m );
glUniform3fv( m_hemisphereLightingProgram->uniformLocation("skyColor"), 1, m_skyColor.v );
glUniform3fv( m_hemisphereLightingProgram->uniformLocation("groundColor"), 1, m_groundColor.v );
glUniform3fv( m_hemisphereLightingProgram->uniformLocation("north"), 1, m_north.v );
glUniform3fv( m_hemisphereLightingProgram->uniformLocation("materialColor"), 1, materialColor_.v );

glDrawElements( model_->primitiveType(), model_->numVertices(), model_->indexDataType(), 0 );

model_->unbindBuffers();
m_hemisphereLightingProgram->endDrawing();
}