kick
/Users/morten/Programmering/cpp/kick/src/kick/assimp/assimp.cpp
00001 //
00002 //  assimp.cpp
00003 //  KickCPP
00004 //
00005 //  Created by Morten Nobel-Jørgensen on 12/25/14.
00006 //  Copyright (c) 2014 Morten Nobel-Joergensen. All rights reserved.
00007 //
00008 
00009 #include "kick/assimp/assimp.h"
00010 
00011 #ifndef NO_ASSIMP
00012 
00013 #include <assimp/Importer.hpp>      // C++ importer interface
00014 #include <assimp/scene.h>           // Output data structure
00015 #include <assimp/postprocess.h>     // Post processing flags
00016 #include <assimp/material.h>     // Post processing flags
00017 #include "kick/scene/light.h"
00018 #include "kick/core/debug.h"
00019 #include "kick/mesh/mesh.h"
00020 #include "kick/scene/mesh_renderer.h"
00021 #include <map>
00022 #include <fstream>
00023 
00024 
00025 
00026 namespace kick {
00027     namespace {
00028 
00029         glm::vec3 toVec3(aiVector3D v){
00030             return glm::vec3{v.x,v.y,v.z};
00031         }
00032 
00033         glm::vec2 toVec2(aiVector2D v){
00034             return glm::vec2{v.x,v.y};
00035         }
00036 
00037         glm::vec2 toVec2(aiVector3D v){
00038             return glm::vec2{v.x,v.y};
00039         }
00040 
00041         glm::vec3 toVec3(aiColor3D v){
00042             return glm::vec3{v.r,v.g,v.b};
00043         }
00044 
00045         void importNode(aiNode * node, Scene *scenePtr, Transform* parent, std::map<aiNode *,GameObject*>& nodeMap){
00046             // logInfo(std::string("Import node ")+node->mName.C_Str());
00047             for (int i=0;i<node->mNumChildren;i++){
00048                 aiNode * childNode = node->mChildren[i];
00049                 GameObject* go = scenePtr->createGameObject(childNode->mName.C_Str());
00050                 go->transform()->setParent(std::dynamic_pointer_cast<Transform>(parent->shared_from_this()));
00051                 nodeMap[childNode] = go;
00052 
00053                 aiMatrix4x4 aiMat4 = childNode->mTransformation;
00054                 aiVector3D scaling;
00055                 aiQuaternion rotation;
00056                 aiVector3D position;
00057                 aiMat4.Decompose(scaling, rotation, position);
00058 
00059                 go->transform()->setLocalRotation(glm::quat(rotation.w,rotation.x,rotation.y,rotation.z));
00060                 go->transform()->setLocalPosition(toVec3(position));
00061                 go->transform()->setLocalScale(toVec3(scaling));
00062                 // logInfo(std::string("RTS ")+/*glm::to_string(go->transform()->localRotation())+*/glm::to_string(go->transform()->localPosition())+glm::to_string(go->transform()->localScale()));
00063 
00064                 importNode(childNode, scenePtr, go->transform().get(), nodeMap);
00065             }
00066         }
00067 
00068         void assignMesh(aiNode * node, int meshIndex, std::shared_ptr<Mesh> mesh, Material * pMaterial, std::map<aiNode *,GameObject*>& nodeMap) {
00069             //logInfo(std::string("Assign mesh ")+node->mName.C_Str());
00070             for (int i=0;i<node->mNumChildren;i++){
00071                 aiNode *child = node->mChildren[i];
00072                 for (int j=0;j<child->mNumMeshes;j++){
00073                     if (child->mMeshes[j] == meshIndex){
00074                         GameObject *go = nodeMap[child];
00075                         auto mr = go->addComponent<MeshRenderer>();
00076                         mr->setMaterial(pMaterial);
00077                         mr->setMesh(mesh);
00078                     }
00079                 }
00080 
00081                 assignMesh(child, meshIndex, mesh, pMaterial, nodeMap);
00082             }
00083         }
00084 
00085         void doSceneProcessing(const aiScene* scene, Scene *scenePtr, AssImpSettings importSettings){
00086             std::map<aiNode *,GameObject*> nodeMap;
00087             std::vector<std::shared_ptr<Texture2D>> allTextures;
00088             // import nodes
00089             importNode(scene->mRootNode, scenePtr, nullptr, nodeMap);
00090 
00091             if (importSettings.cameras){
00092                 for (int i=0;i<scene->mNumCameras;i++){
00093                     auto camera = scene->mCameras[i];
00094                     auto cameraNode = scene->mRootNode->FindNode(camera->mName);
00095                     if (cameraNode){
00096                         GameObject* cameraGO = nodeMap[cameraNode];
00097                         auto perspective = cameraGO->addComponent<CameraPerspective>();
00098 
00099                         float aspect = camera->mAspect;
00100                         float fovH = camera->mHorizontalFOV;
00101                         // todo
00102                         perspective->setFar(camera->mClipPlaneFar);
00103                         perspective->setNear(camera->mClipPlaneNear);
00104                     } else {
00105                         logWarning(std::string("Could not find camera ")+camera->mName.C_Str());
00106                     }
00107                 }
00108             }
00109             if (importSettings.textures){
00110                 for (int i=0;i<scene->mNumTextures;i++){
00111                     aiTexture* texture = scene->mTextures[i];
00112                     bool compressed = texture->mHeight == 0;
00113                     std::shared_ptr<Texture2D> tex;
00114                     if (compressed){
00115                         tex = Project::loadTexture2DFromMemory((char *) texture->pcData, texture->mWidth);
00116                     } else {
00117                         tex = std::make_shared<Texture2D>();
00118                         tex->setData(texture->mWidth, texture->mHeight, (char *) texture->pcData);
00119                     }
00120                     allTextures.push_back(tex);
00121                 }
00122             }
00123             if (importSettings.lights){
00124                 glm::vec3 ambientLight{0};
00125                 for (int i=0;i<scene->mNumLights;i++){
00126 
00127                     aiLight* light = scene->mLights[i];
00128                     ambientLight += glm::vec3(toVec3(light->mColorAmbient));
00129                     auto lightNode = scene->mRootNode->FindNode(light->mName);
00130                     if (lightNode){
00131                         GameObject *lightGO = nodeMap[lightNode];
00132                         auto lightComponent = lightGO->addComponent<Light>();
00133                         lightComponent->setColor(toVec3(light->mColorDiffuse));
00134                         lightComponent->setAttenuation(glm::vec3(light->mAttenuationConstant, light->mAttenuationLinear, light->mAttenuationQuadratic));
00135                         light->mPosition; // todo
00136                         light->mDirection; // todo
00137 
00138                         switch (light->mType){
00139                             case aiLightSource_DIRECTIONAL:
00140                                 lightComponent->setLightType(LightType::Directional);
00141                                 break;
00142                             case aiLightSource_POINT:
00143                                 lightComponent->setLightType(LightType::Point);
00144                                 break;
00145                             case aiLightSource_SPOT:
00146                                 lightComponent->setLightType(LightType::Spot);
00147                                 break;
00148                             case aiLightSource_UNDEFINED:
00149                                 continue;
00150                         }
00151                     } else {
00152                         logWarning(std::string("Could not find light ")+light->mName.C_Str());
00153                     }
00154                 }
00155                 ambientLight *= 1.0f/scene->mNumLights;
00156                 scenePtr->createAmbientLight(1.0, ambientLight);
00157             }
00158             std::vector<Material*> mats;
00159             if (importSettings.materials){
00160                 for (int i=0;i<scene->mNumMaterials;i++){
00161                     aiMaterial* aiMaterial = scene->mMaterials[i];
00162                     Material *material = new Material();
00163 
00164                     float opacity = 1.0f;
00165                     aiMaterial->Get(AI_MATKEY_OPACITY, opacity);
00166                     float shininess = 0.0f;
00167                     aiMaterial->Get(AI_MATKEY_SHININESS, shininess);
00168 
00169 
00170                     aiColor3D color (0.f,0.f,0.f);
00171                     if (aiMaterial->Get(AI_MATKEY_COLOR_DIFFUSE, color)){
00172                         material->setUniform("mainColor", glm::vec4(toVec3(color), opacity));
00173                     }
00174                     int blend = 0;
00175                     aiMaterial->Get(AI_MATKEY_BLEND_FUNC,blend);
00176 
00177                     unsigned int numTextures = aiMaterial->GetTextureCount(aiTextureType_DIFFUSE);
00178                     aiString* texturePath = nullptr;
00179                     aiTextureMapping* mapping = nullptr;
00180                     unsigned int* uvindex = nullptr;
00181                     float* texBlend = nullptr;
00182                     aiTextureOp* op = nullptr;
00183                     aiTextureMapMode* mapmode = nullptr;
00184 
00185                     /*if (aiMaterial->GetTextureCount(aiTextureType_DIFFUSE) > 0 &&
00186                             aiMaterial->GetTexture(aiTextureType_DIFFUSE, 0, texturePath, mapping, uvindex, texBlend, op, mapmode) == AI_SUCCESS)
00187                     {
00188                         std::fstream file(texturePath->C_Str());
00189                         if (file.is_open()){
00190                             file.close();
00191                             auto tex = Project::loadTexture2D(texturePath->C_Str());
00192                             if (tex){
00193                                 material->setUniform("mainTexture", tex);
00194                             }
00195                         } else {
00196                             int textureIndex = atoi(texturePath->C_Str());
00197                             material->setUniform("mainTexture", allTextures[textureIndex]);
00198                         }
00199                     } */
00200 
00201                     if (blend){
00202                         if (shininess>0.0f) {
00203                             material->setShader(Project::loadShader("assets/shaders/transparent_specular.shader"));
00204                         } else {
00205                             material->setShader(Project::loadShader("assets/shaders/transparent_diffuse.shader"));
00206                         }
00207                     } else {
00208                         if (shininess>0.0f) {
00209                             material->setShader(Project::loadShader("assets/shaders/specular.shader"));
00210                         } else {
00211                             material->setShader(Project::loadShader("assets/shaders/diffuse.shader"));
00212                         }
00213                     }
00214 
00215                     mats.push_back(material);
00216                 }
00217             }
00218             if (importSettings.meshes){
00219                 for (int j=0;j<scene->mNumMeshes;j++){
00220                     aiMesh* aiMesh = scene->mMeshes[j];
00221                     std::shared_ptr<MeshData> meshData = std::make_shared<MeshData>();
00222                     std::shared_ptr<Mesh> mesh = std::make_shared<Mesh>();
00223                     // logInfo(std::string("Mesh ")+aiMesh->mName.C_Str());
00224                     if (aiMesh->HasPositions()){
00225                         std::vector<glm::vec3> pos;
00226                         for (int i=0;i<aiMesh->mNumVertices;i++){
00227                             pos.push_back(toVec3(aiMesh->mVertices[i]));
00228                         }
00229                         meshData->setPosition(pos);
00230                     }
00231                     if (aiMesh->HasNormals()){
00232                         std::vector<glm::vec3> norms;
00233                         for (int i=0;i<aiMesh->mNumVertices;i++){
00234                             norms.push_back(toVec3(aiMesh->mNormals[i]));
00235                         }
00236                         meshData->setNormal(norms);
00237                     }
00238                     if (aiMesh->GetNumUVChannels()>0){
00239                         std::vector<glm::vec2> norms;
00240                         for (int i=0;i<aiMesh->mNumVertices;i++){
00241                             norms.push_back(toVec2(aiMesh->mTextureCoords[0][i]));
00242                         }
00243                         meshData->setTexCoord0(norms);
00244                     }
00245                     if (aiMesh->GetNumUVChannels()>1){
00246                         std::vector<glm::vec2> norms;
00247                         for (int i=0;i<aiMesh->mNumVertices;i++){
00248                             norms.push_back(toVec2(aiMesh->mTextureCoords[1][i]));
00249                         }
00250                         meshData->setTexCoord1(norms);
00251                     }
00252                     if (aiMesh->HasFaces()){
00253                         std::vector<GLushort> indices;
00254                         for (int i=0;i<aiMesh->mNumFaces;i++){
00255                             for (int ii=0;ii< aiMesh->mFaces[i].mNumIndices;ii++){
00256                                 indices.push_back(aiMesh->mFaces[i].mIndices[ii]);
00257                             }
00258                         }
00259                         meshData->setSubmesh(0, indices, MeshType::Triangles);
00260                     }
00261                     meshData->recomputeBounds();
00262                     mesh->setMeshData(meshData);
00263                     assignMesh(scene->mRootNode, j, mesh, mats[aiMesh->mMaterialIndex], nodeMap);
00264                 }
00265             }
00266         }
00267     }
00268 
00269     bool AssImp::importData(std::string filename, Scene *scenePtr, AssImpSettings importSettings) {
00270         // Create an instance of the Importer class
00271         Assimp::Importer importer;
00272         bool missing = false;
00273         importer.SetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT, 64000, &missing);
00274 
00275         std::cout <<  missing<<std::endl;
00276         // And have it read the given file with some example postprocessing
00277         // Usually - if speed is not the most important aspect for you - you'll
00278         // propably to request more postprocessing than we do in this example.
00279         logInfo(std::string("Loading ")+filename);
00280         const aiScene* scene = importer.ReadFile( filename,
00281                 aiProcess_CalcTangentSpace       |
00282                         aiProcess_Triangulate            |
00283                         aiProcess_GenNormals            |
00284                         aiProcess_OptimizeMeshes        |
00285                         aiProcess_SplitLargeMeshes        |
00286                         aiProcess_GenUVCoords            |
00287                         aiProcess_JoinIdenticalVertices  |
00288                         aiProcess_SortByPType);
00289 
00290         // If the import failed, report it
00291         if( !scene)
00292         {
00293             logError(importer.GetErrorString());
00294             return false;
00295         } else {
00296             logInfo(std::string("Importing ")+filename);
00297         }
00298         // Now we can access the file's contents.
00299         doSceneProcessing(scene, scenePtr, importSettings);
00300 
00301         logInfo(std::string("Finished ")+filename);
00302 
00303         // We're done. Everything will be cleaned up by the importer destructor
00304         return true;
00305     }
00306 }
00307 
00308 #endif
 All Classes Functions Variables