kick
|
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