OGRE Wiki
Support and community documentation for Ogre3D
Ogre Forums
ogre3d.org
Log in
Username:
Password:
CapsLock is on.
Remember me (for 1 year)
Log in
Home
Tutorials
Tutorials Home
Basic Tutorials
Intermediate Tutorials
Mad Marx Tutorials
In Depth Tutorials
Older Tutorials
External Tutorials
Cookbook
Cookbook Home
CodeBank
Snippets
Experiences
Ogre Articles
Libraries
Libraries Home
Alternative Languages
Assembling A Toolset
Development Tools
OGRE Libraries
List of Libraries
Tools
Tools Home
DCC Tools
DCC Tutorials
DCC Articles
DCC Resources
Assembling a production pipeline
Development
Development Home
Roadmap
Building Ogre
Installing the Ogre SDK
Setting Up An Application
Ogre Wiki Tutorial Framework
Frequently Asked Questions
Google Summer Of Code
Help Requested
Ogre Core Articles
Community
Community Home
Projects Using Ogre
Recommended Reading
Contractors
Wiki
Immediate Wiki Tasklist
Wiki Ideas
Wiki Guidelines
Article Writing Guidelines
Wiki Styles
Wiki Page Tracker
Ogre Wiki Help
Ogre Wiki Help Overview
Help - Basic Syntax
Help - Images
Help - Pages and Structures
Help - Wiki Plugins
Toolbox
Freetags
Categories
List Pages
Structures
Trackers
Statistics
Rankings
List Galleries
Ogre Lexicon
Comments
History: How to Load Object with Assimp
View page
Source of version: 36
(current)
{img fileId="2306" thumb="y" rel="box[g]"} :::First of all English is not my first language, correct me where your find mistakes. This Tutorial will show how to load models with a popular Library known as __ASSIMP__. __It's a famous library that currently supports 40+ different formats!__ With this, you can just browse for models online and quickly load them into your app without going through the process of conversion with external tools. As for now the code being used has some minor bugs.Anyone is welcome to help rectify them. (BUG:Cannot load complex models correctly, i'm attaching a simple {ATTACH(name="231")}model{ATTACH} which does load correctly, please test with other models) I am making this tutorial because I know how hard it is for users to load other data formats into __OGRE__ . This method will not require the use of any external programs , neither will it require you to manually convert your models with tools like blender,all you will need is adding some code to your app, and you can load any model by it's filename. Unfortunately the code is not currently able to load textures(fix when we complete). In the long run I intend to make this functionality into a plugin, if you are familiar with how __OGRE__ and __ASSIMP__ work, you can also help us speed up the process. ''ASSIMP''-__Open Asset Import Library Repository__ (Official Repo [https://github.com/assimp/assimp|https://github.com/assimp/assimp]) The Bug we are currently facing [https://github.com/assimp/assimp/issues/1368|Complex_Model_Bug] I believe this is the first step to win back users into the __OGRE__ project. Lets get started. To do this, you have to build and install ''ASSIMP'', for windows users you don't need to install it only specify the directory where the library and files will be put. My implementation only needs 2 source files,this however might change in the future. You will have to copy them into your application's source dirs and add ''ASSIMP'' include dir and library dir into your application. The files are attached below. To load a model You just need to add the following code into your app::: First create the following two files and paste the code into them. {CODE(caption="Assimp.h")} #include <assimp/Importer.hpp> #include <assimp/scene.h> #include <assimp/postprocess.h> #include <assimp/matrix4x4.h> #include <assimp/cimport.h> #include <Windows.h> #include <iostream> #include <stdint.h> #include <vector> class ModelManager { public: ModelManager(); ~ModelManager(void); bool loadModel(std::string file); bool processData(); std::vector<float> *getVertexData(); std::vector<uint16_t> *getIndexData(); private: bool assimpGetMeshData(const aiMesh *mesh); private: Assimp::Importer importer; const aiScene *modelScene; const aiNode *modelNode; const aiMesh *modelMesh; const aiFace *modelFace; std::vector<float> vertexBuff; std::vector<uint16_t> indexBuff; std::vector<const aiNode*> nodeBuff; unsigned int numNodeBuff; }; {CODE} {CODE(caption="Assimp.cpp")} #include "Assimp.h" ModelManager::ModelManager() { vertexBuff.clear(); indexBuff.clear(); std::cout << "=======Mesh Manager initialized======="<<std::endl; } ModelManager::~ModelManager(void) { std::cout<<"ModelManager destroyed" << std::endl; } bool ModelManager::loadModel(std::string file) { modelScene = importer.ReadFile(file, aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_PreTransformVertices | aiProcess_CalcTangentSpace | aiProcess_GenSmoothNormals | aiProcess_Triangulate | aiProcess_FixInfacingNormals | aiProcess_FindInvalidData | aiProcess_ValidateDataStructure | 0 ); if (!modelScene) { MessageBoxA(NULL, importer.GetErrorString(), "Error: ", MB_ICONERROR); return false; } else processData(); return true; } bool ModelManager::assimpGetMeshData(const aiMesh *mesh) { aiFace *face; for (unsigned int v = 0; v < mesh->mNumVertices; v++) { vertexBuff.push_back(mesh->mVertices[v].x); vertexBuff.push_back(mesh->mVertices[v].y); vertexBuff.push_back(mesh->mVertices[v].z); vertexBuff.push_back(mesh->mNormals[v].x); vertexBuff.push_back(mesh->mNormals[v].y); vertexBuff.push_back(mesh->mNormals[v].z); if(mesh->HasTextureCoords(0)){ vertexBuff.push_back(mesh->mTextureCoords[0][v].x); vertexBuff.push_back(mesh->mTextureCoords[0][v].y); } else { vertexBuff.push_back(0); vertexBuff.push_back(0); } /* vertexBuff.push_back(mesh->mTangents[v].x); vertexBuff.push_back(mesh->mTangents[v].y); vertexBuff.push_back(mesh->mTangents[v].z);*/ } for (unsigned int f = 0; f<mesh->mNumFaces; f++) { face = &mesh->mFaces[f]; indexBuff.push_back(face->mIndices[0]); indexBuff.push_back(face->mIndices[1]); indexBuff.push_back(face->mIndices[2]); } return true; } bool ModelManager::processData() { bool repeat = true; nodeBuff.push_back(modelScene->mRootNode); /* if (modelScene->mNumMeshes > 0) { for (unsigned int m=0;m<modelScene->mNumMeshes;m++) this->assimpGetMeshData(modelScene->mMeshes[m]); }*/ // I raise all nodes tree to the root level while (repeat) { for (unsigned int a = 0; a<nodeBuff.size(); a++) { modelNode = nodeBuff.at(a); if (modelNode->mNumChildren > 0) for (unsigned int c = 0; c < modelNode->mNumChildren; c++) { nodeBuff.push_back(modelNode->mChildren[c]); } else repeat = false; } } // Get node information from the root level (all nodes) for (unsigned int a = 0; a<nodeBuff.size(); a++) { modelNode = nodeBuff.at(a); if (modelNode->mNumMeshes>0) for (unsigned int b = 0; b < modelNode->mNumMeshes; b++) { assimpGetMeshData(modelScene->mMeshes[b]); //std::cout << "::::::::PROCESSING =>" << modelScene->mMeshes[b]->mName; } } return true; } std::vector<float> *ModelManager::getVertexData() { return &vertexBuff; } std::vector<uint16_t> *ModelManager::getIndexData() { return &indexBuff; } {CODE} {CODE(caption="include the file below")}#include "Assimp.h"{CODE} Then define this function where you have your createscene: {CODE(caption="")="cpp"} void makeMesh(Ogre::String meshFile, Ogre::String meshName) { Ogre::MeshPtr Mesh = Ogre::MeshManager::getSingleton().createManual(meshName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); Ogre::SubMesh *subMesh = Mesh->createSubMesh("subMesh"); Ogre::VertexDeclaration *vertexDeclaration; Ogre::HardwareVertexBufferSharedPtr vertexBuffer; Ogre::HardwareIndexBufferSharedPtr indexBuffer; stringstream stringBuffer; size_t offset = 0; /* // Get file name and extension from the Ogre Resource Manager Ogre::FileInfoListPtr fileInfoListPtr(Ogre::ResourceGroupManager::getSingleton().findResourceFileInfo(Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, meshFile, false)); Ogre::FileInfoList *fileInfoList = fileInfoListPtr.getPointer(); Ogre::FileInfo &fileInfo = fileInfoList->front(); stringBuffer << fileInfo.archive->getName().c_str() << meshFile; */ // ************** From Assimp code *************************** ModelManager manager; manager.loadModel(meshFile); std::vector<float> *vData = manager.getVertexData(); std::vector<uint16_t> *iData = manager.getIndexData(); // ******************************************************************** Mesh->sharedVertexData = new Ogre::VertexData; // Organizo la memoria de video vertexDeclaration = Mesh->sharedVertexData->vertexDeclaration; vertexDeclaration->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); vertexDeclaration->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); vertexDeclaration->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); // Make vertex buffer vertexBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDeclaration->getVertexSize(0), vData->size() / 8, Ogre::HardwareBuffer::HBU_STATIC); // Write the vertex buffer with the target data of vData->data() located in assimp code vertexBuffer.getPointer()->writeData(0, vertexBuffer.getPointer()->getSizeInBytes(), vData->data()); // Make index buffer indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, iData->size(), Ogre::HardwareBuffer::HBU_STATIC); indexBuffer.getPointer()->writeData(0, indexBuffer.getPointer()->getSizeInBytes(), iData->data()); Mesh->sharedVertexData->vertexBufferBinding->setBinding(0, vertexBuffer); Mesh->sharedVertexData->vertexCount = vertexBuffer.getPointer()->getNumVertices(); Mesh->sharedVertexData->vertexStart = 0; subMesh->useSharedVertices = true; subMesh->indexData->indexBuffer = indexBuffer; subMesh->indexData->indexCount = indexBuffer.getPointer()->getNumIndexes(); subMesh->indexData->indexStart = 0; //if (manager.hasmaterial()) { // oSceneManager->getEntity(entityName)->setMaterialName(manager.material_name()); // } // I don't get real AABB from object, this is ok for probe Mesh->_setBounds(Ogre::AxisAlignedBox(-400, -400, -400, 400, 400, 400)); Mesh->load(); std::cout << "total de vertices: " << vData->size() / 8 << "\n"; std::cout << "total de faces: " << indexBuffer.getPointer()->getNumIndexes() / 3 << "\n"; } {CODE} Then go to where you create your ogre entities(After creating the scene) and add the following {CODE()} makeMesh("..//models//jin.obj", "mesh"); {CODE} Example {CODE(caption="Example")}void createScene() { // Set the scene's ambient light mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f)); makeMesh("..//models//jin.obj", "mesh"); //Here mesh is the name of our mesh in ogre resourcegroup. Ogre::Entity* HeadEntity= mSceneMgr->createEntity("MyEntity", "mesh"); //This will create a new entity called MyEntity and assign the mesh we created earlier. HeadEntity->setMaterialName("test.mat"); //You must put this code regardless of wheather you have a valid material or not, otherwise ogre will crash. Ogre::SceneNode* headSceneNode =mSceneMgr->getRootSceneNode()->createChildSceneNode("headscene"); //Create Child scene node for the new entity. headSceneNode->attachObject(HeadEntity); //Attach our HeadEntity to the scene node we just created. headSceneNode->setPosition(0, 0, 0); //Set the position of our headscene. // Create a Light and set its position Ogre::Light* light = mSceneMgr->createLight("MainLight"); light->setPosition(20.0f, 80.0f, 500.0f); };{CODE} That will place your object. position (0,0,0) on the screen. Expect this code to be updated in the future, it will also be possible to load materials automatically without adding the code manually. Please help improve this code and make __OGRE__ users happy. After all __OGRE__ is growing more powerfull each the day. You can also visit the issue on github and help out [https://github.com/assimp/assimp/issues/1362|https://github.com/assimp/assimp/issues/1362] Ogre Forum page where you can discuss this code or report problems is at [http://ogre3d.org/forums/viewtopic.php?f=1&t=93145|Assimp -> Ogre adaptor]
Search by Tags
Search Wiki by Freetags
Latest Changes
Minimal Ogre Collision
Artifex Terra
OpenMB
Advanced Mogre Framework
MogreSocks
Critter AI
Mogre Add-ons
MOGRE
Mogre MyGUI wrapper
MOGRE Editable Terrain Manager
...more
Search
Find
Advanced
Search Help
Online Users
57 online users