/** * Searches a geode for drawables containing texture coordinates. * Based on which texture units the coordinates are mapped to, * appropriate texture slots are extracted. * @param geode The geometry node to check. */ virtual void apply(osg::Geode &geode) { FindTextures(geode.getStateSet()); for (unsigned int i=0; i<geode.getNumDrawables(); i++) { osg::Geometry *geom = geode.getDrawable(i)->asGeometry(); if (geom != NULL) { FindTextures(geom->getStateSet()); unsigned int texCoordCount = geom->getNumTexCoordArrays(); if (texCoordCount > mMaxTexCoordArrayCount) mMaxTexCoordArrayCount = texCoordCount; } } traverse(geode); }
S3DModel* CAssParser::Load(const std::string& modelFilePath) { LOG_SL(LOG_SECTION_MODEL, L_INFO, "Loading model: %s", modelFilePath.c_str()); const std::string& modelPath = FileSystem::GetDirectory(modelFilePath); const std::string& modelName = FileSystem::GetBasename(modelFilePath); // Load the lua metafile. This contains properties unique to Spring models and must return a table std::string metaFileName = modelFilePath + ".lua"; if (!CFileHandler::FileExists(metaFileName, SPRING_VFS_ZIP)) { // Try again without the model file extension metaFileName = modelPath + '/' + modelName + ".lua"; } if (!CFileHandler::FileExists(metaFileName, SPRING_VFS_ZIP)) { LOG_SL(LOG_SECTION_MODEL, L_INFO, "No meta-file '%s'. Using defaults.", metaFileName.c_str()); } LuaParser metaFileParser(metaFileName, SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP); if (!metaFileParser.Execute()) { LOG_SL(LOG_SECTION_MODEL, L_ERROR, "'%s': %s. Using defaults.", metaFileName.c_str(), metaFileParser.GetErrorLog().c_str()); } // Get the (root-level) model table const LuaTable& modelTable = metaFileParser.GetRoot(); if (!modelTable.IsValid()) { LOG_SL(LOG_SECTION_MODEL, L_INFO, "No valid model metadata in '%s' or no meta-file", metaFileName.c_str()); } // Create a model importer instance Assimp::Importer importer; // Create a logger for debugging model loading issues Assimp::DefaultLogger::create("", Assimp::Logger::VERBOSE); Assimp::DefaultLogger::get()->attachStream(new AssLogStream(), ASS_LOGGING_OPTIONS); // Give the importer an IO class that handles Spring's VFS importer.SetIOHandler(new AssVFSSystem()); // Speed-up processing by skipping things we don't need importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, ASS_IMPORTER_OPTIONS); #ifndef BITMAP_NO_OPENGL { // Optimize VBO-Mesh sizes/ranges GLint maxIndices = 1024; GLint maxVertices = 1024; // FIXME returns non-optimal data, at best compute it ourselves (pre-TL cache size!) glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &maxIndices); glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &maxVertices); importer.SetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT, maxVertices); importer.SetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT, maxIndices / 3); } #endif // Read the model file to build a scene object LOG_SL(LOG_SECTION_MODEL, L_INFO, "Importing model file: %s", modelFilePath.c_str()); const aiScene* scene; { // ASSIMP spams many SIGFPEs atm in normal & tangent generation ScopedDisableFpuExceptions fe; scene = importer.ReadFile(modelFilePath, ASS_POSTPROCESS_OPTIONS); } if (scene != NULL) { LOG_SL(LOG_SECTION_MODEL, L_INFO, "Processing scene for model: %s (%d meshes / %d materials / %d textures)", modelFilePath.c_str(), scene->mNumMeshes, scene->mNumMaterials, scene->mNumTextures); } else { throw content_error("[AssimpParser] Model Import: " + std::string(importer.GetErrorString())); } S3DModel* model = new S3DModel(); model->name = modelFilePath; model->type = MODELTYPE_ASS; // Load textures FindTextures(model, scene, modelTable, modelPath, modelName); LOG_SL(LOG_SECTION_MODEL, L_INFO, "Loading textures. Tex1: '%s' Tex2: '%s'", model->tex1.c_str(), model->tex2.c_str()); texturehandlerS3O->LoadS3OTexture(model); // Load all pieces in the model LOG_SL(LOG_SECTION_MODEL, L_INFO, "Loading pieces from root node '%s'", scene->mRootNode->mName.data); LoadPiece(model, scene->mRootNode, scene, modelTable); // Update piece hierarchy based on metadata BuildPieceHierarchy(model); CalculateModelProperties(model, modelTable); // Verbose logging of model properties LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->name: %s", model->name.c_str()); LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->numobjects: %d", model->numPieces); LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->radius: %f", model->radius); LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->height: %f", model->height); LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->drawRadius: %f", model->drawRadius); LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->mins: (%f,%f,%f)", model->mins[0], model->mins[1], model->mins[2]); LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->maxs: (%f,%f,%f)", model->maxs[0], model->maxs[1], model->maxs[2]); LOG_SL(LOG_SECTION_MODEL, L_INFO, "Model %s Imported.", model->name.c_str()); return model; }
void LevelFactory::FindTextures(const char *aDirName) { DIR *dir; char buffer[PATH_MAX + 2]; char *p = buffer; const char *src; char *end = &buffer[PATH_MAX]; int ok; /* Copy directory name to buffer */ src = aDirName; while (p < end && *src != '\0') { *p++ = *src++; } *p = '\0'; /* Open directory stream */ dir = opendir(aDirName); if (dir != NULL) { struct dirent *ent; /* Print all files and directories within the directory */ while ((ent = readdir(dir)) != NULL) { char *q = p; char c; /* Get final character of directory name */ if (buffer < q) { c = q[-1]; } else { c = ':'; } /* Append directory separator if not already there */ if (c != ':' && c != '/' && c != '\\') { *q++ = '/'; } /* Append file name */ src = ent->d_name; while (q < end && *src != '\0') { *q++ = *src++; } *q = '\0'; /* Decide what to do with the directory entry */ switch (ent->d_type) { case DT_LNK: case DT_REG: /* Output file name with directory */ //printf("%s\n", buffer); LoadTexture(buffer); break; case DT_DIR: /* Scan sub-directory recursively */ if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { FindTextures(buffer); } break; default: /* Ignore device entries */ /*NOP*/; } } closedir(dir); ok = 1; } else { DL_ASSERT(CU::Concatenate("Cannot open directory %s", aDirName)); } }
void LevelFactory::ReadXML(const std::string& aFilePath) { Prism::Engine::GetInstance()->GetModelLoader()->Pause(); Prism::Engine::GetInstance()->myIsLoading = true; FindTextures("Data/Resource/Texture/Particle/"); myCurrentLevel->myScene = new Prism::Scene(); myCurrentLevel->myWeaponFactory = new WeaponFactory(); myCurrentLevel->myWeaponFactory->LoadWeapons("Data/Script/LI_list_weapon.xml"); myCurrentLevel->myWeaponFactory->LoadProjectiles("Data/Script/LI_list_projectile.xml"); myCurrentLevel->myEntityFactory = new EntityFactory(myCurrentLevel->myWeaponFactory); myCurrentLevel->myEntityFactory->LoadEntites("Data/Script/LI_list_entity.xml", myDifficults[myCurrentDifficultyID].myMultiplier); myCurrentLevel->myCollisionManager = new CollisionManager(); myCurrentLevel->myBulletManager = new BulletManager(*myCurrentLevel->myCollisionManager, *myCurrentLevel->myScene); myCurrentLevel->myBulletManager->LoadFromFactory(myCurrentLevel->myWeaponFactory, myCurrentLevel->myEntityFactory, "Data/Script/LI_list_projectile.xml"); myDirectionalLights.DeleteAll(); myPointLights.DeleteAll(); mySpotLights.DeleteAll(); LoadPlayer(); myCurrentLevel->myEmitterManager = new EmitterManager(myCurrentLevel->myPlayer); ReadLevelSettings(); myCurrentLevel->myEntities.Add(myCurrentLevel->myPlayer); myCurrentLevel->myCamera = new Prism::Camera(myCurrentLevel->myPlayer->myOrientation); myCurrentLevel->myPlayer->GetComponent<GUIComponent>()->SetCamera(myCurrentLevel->myCamera); myCurrentLevel->GetEmitterManager()->AddEmitter(myCurrentLevel->myPlayer->GetComponent<ParticleEmitterComponent>()); myCurrentLevel->myPlayer->SetPlayerScene(*myCurrentLevel->myScene); Sleep(10); XMLReader reader; reader.OpenDocument(aFilePath); tinyxml2::XMLElement* levelElement = reader.ForceFindFirstChild("root"); levelElement = reader.ForceFindFirstChild(levelElement, "scene"); std::string skySphere; std::string cubeMap; std::string missionXML; std::string eventXML; std::string conversationXML; reader.ForceReadAttribute(reader.ForceFindFirstChild(levelElement, "missionxml"), "source", missionXML); reader.ForceReadAttribute(reader.ForceFindFirstChild(levelElement, "eventxml"), "source", eventXML); reader.ForceReadAttribute(reader.ForceFindFirstChild(levelElement, "conversationxml"), "source", conversationXML); CU::Vector3<float> playerPos; CU::Vector3<float> playerRot; tinyxml2::XMLElement* playerPosElement; playerPosElement = reader.ForceFindFirstChild(levelElement, "PlayerStartTranslate"); playerPosElement = reader.ForceFindFirstChild(playerPosElement, "position"); reader.ForceReadAttribute(playerPosElement, "X", playerPos.x); reader.ForceReadAttribute(playerPosElement, "Y", playerPos.y); reader.ForceReadAttribute(playerPosElement, "Z", playerPos.z); playerPosElement = reader.ForceFindFirstChild(levelElement, "PlayerStartTranslate"); playerPosElement = reader.ForceFindFirstChild(playerPosElement, "rotation"); reader.ForceReadAttribute(playerPosElement, "X", playerRot.x); reader.ForceReadAttribute(playerPosElement, "Y", playerRot.y); reader.ForceReadAttribute(playerPosElement, "Z", playerRot.z); myCurrentLevel->myPlayer->myOrientation = CU::Matrix44f(); myCurrentLevel->myPlayer->myOrientation = myCurrentLevel->myPlayer->myOrientation.CreateRotateAroundX(playerRot.x) * myCurrentLevel->myPlayer->myOrientation; myCurrentLevel->myPlayer->myOrientation = myCurrentLevel->myPlayer->myOrientation.CreateRotateAroundY(playerRot.y) * myCurrentLevel->myPlayer->myOrientation; myCurrentLevel->myPlayer->myOrientation = myCurrentLevel->myPlayer->myOrientation.CreateRotateAroundZ(playerRot.z) * myCurrentLevel->myPlayer->myOrientation; myCurrentLevel->myPlayer->myOrientation = CU::GetOrientation(myCurrentLevel->myPlayer->myOrientation, playerRot); myCurrentLevel->myPlayer->myOrientation.SetPos(playerPos * 10.f); myCurrentLevel->myPlayer->myOriginalOrientation = myCurrentLevel->myPlayer->myOrientation; myCurrentLevel->myPlayer->Reset(); myCurrentLevel->myConversationManager = new ConversationManager(conversationXML); myCurrentLevel->myMissionManager = new MissionManager(*myCurrentLevel, *myCurrentLevel->myPlayer, missionXML); myCurrentLevel->myEventManager = new EventManager(eventXML, *myCurrentLevel->myConversationManager , *myCurrentLevel->myPlayer); reader.ReadAttribute(reader.ForceFindFirstChild(levelElement, "skysphere"), "source", skySphere); reader.ReadAttribute(reader.ForceFindFirstChild(levelElement, "cubemap"), "source", cubeMap); Prism::Engine::GetInstance()->GetEffectContainer()->SetCubeMap(cubeMap); SetSkySphere(skySphere, "Data/Resource/Shader/S_effect_skybox.fx"); LoadLights(reader, levelElement); LoadProps(reader, levelElement); LoadDefendables(reader, levelElement, myDifficults[myCurrentDifficultyID].myHealthMultiplier); LoadStructures(reader, levelElement); LoadTriggers(reader, levelElement); LoadPowerups(reader, levelElement); reader.CloseDocument(); myCurrentLevel->myEMPHexagon = new Entity(eEntityType::EMP, *myCurrentLevel->myScene, Prism::eOctreeType::STATIC , "EMP"); myCurrentLevel->myEMPHexagon->AddComponent<GraphicsComponent>()->Init("Data/Resource/Model/Weapon/SM_emp_hexasphere.fbx" , "Data/Resource/Shader/S_effect_emp.fx"); myCurrentLevel->myEMPHexagon2 = new Entity(eEntityType::EMP, *myCurrentLevel->myScene, Prism::eOctreeType::STATIC , "EMP"); myCurrentLevel->myEMPHexagon2->AddComponent<GraphicsComponent>()->Init("Data/Resource/Model/Weapon/SM_emp_hexasphere.fbx" , "Data/Resource/Shader/S_effect_emp.fx"); for (int i = 0; i < myCurrentLevel->myEntities.Size(); ++i) { if (myCurrentLevel->myEntities[i]->GetComponent<AIComponent>() != nullptr) { std::string targetName = myCurrentLevel->myEntities[i]->GetComponent<AIComponent>()->GetTargetName(); Entity* target = myCurrentLevel->GetEntityWithName(targetName); myCurrentLevel->myEntities[i]->GetComponent<AIComponent>()->SetEntityToFollow(myCurrentLevel->myPlayer, myCurrentLevel->myPlayer); if (target != nullptr) { myCurrentLevel->myEntities[i]->GetComponent<AIComponent>()->SetEntityToFollow(target, myCurrentLevel->myPlayer); } } if (myCurrentLevel->myEntities[i]->GetComponent<ParticleEmitterComponent>() != nullptr) { myCurrentLevel->myEmitterManager->AddEmitter(myCurrentLevel->myEntities[i]->GetComponent<ParticleEmitterComponent>()); } } for (int i = 0; i < static_cast<int>(eBulletType::COUNT); ++i) { if (i <= 8) { for (int j = 0; j < myCurrentLevel->myBulletManager->GetBullet(i)->myPlayerBullets.Size(); ++j) { if (myCurrentLevel->myBulletManager->GetBullet(i)->myPlayerBullets[j]->GetComponent<ParticleEmitterComponent>() != nullptr) { myCurrentLevel->myEmitterManager->AddEmitter(myCurrentLevel->myBulletManager->GetBullet(i)->myPlayerBullets[j]->GetComponent<ParticleEmitterComponent>()); } if (myCurrentLevel->myBulletManager->GetBullet(i)->myEnemyBullets[j]->GetComponent<ParticleEmitterComponent>() != nullptr) { myCurrentLevel->myEmitterManager->AddEmitter(myCurrentLevel->myBulletManager->GetBullet(i)->myEnemyBullets[j]->GetComponent<ParticleEmitterComponent>()); } } } } AddToScene(); myCurrentLevel->myMissionManager->Init(); myCurrentLevel->myPlayer->GetComponent<InputComponent>()->SetSkyPosition(); myCurrentLevel->myPlayer->GetComponent<GUIComponent>()->SetCockpitOrientation(); Prism::Engine::GetInstance()->GetModelLoader()->UnPause(); Prism::Engine::GetInstance()->GetModelLoader()->WaitUntilFinished(); Prism::Engine::GetInstance()->GetEffectContainer()->GetEffect("Data/Resource/Shader/S_effect_pbl.fx")->SetAmbientHue(myAmbientHue); Prism::Engine::GetInstance()->myIsLoading = false; myIsLoading = false; }
S3DModel* CAssParser::Load(const std::string& modelFilePath) { LOG_SL(LOG_SECTION_MODEL, L_INFO, "Loading model: %s", modelFilePath.c_str()); const std::string& modelPath = FileSystem::GetDirectory(modelFilePath); const std::string& modelName = FileSystem::GetBasename(modelFilePath); // Load the lua metafile. This contains properties unique to Spring models and must return a table std::string metaFileName = modelFilePath + ".lua"; if (!CFileHandler::FileExists(metaFileName, SPRING_VFS_ZIP)) { // Try again without the model file extension metaFileName = modelPath + '/' + modelName + ".lua"; } if (!CFileHandler::FileExists(metaFileName, SPRING_VFS_ZIP)) { LOG_SL(LOG_SECTION_MODEL, L_INFO, "No meta-file '%s'. Using defaults.", metaFileName.c_str()); } LuaParser metaFileParser(metaFileName, SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP); if (!metaFileParser.Execute()) { LOG_SL(LOG_SECTION_MODEL, L_INFO, "'%s': %s. Using defaults.", metaFileName.c_str(), metaFileParser.GetErrorLog().c_str()); } // Get the (root-level) model table const LuaTable& modelTable = metaFileParser.GetRoot(); if (!modelTable.IsValid()) { LOG_SL(LOG_SECTION_MODEL, L_INFO, "No valid model metadata in '%s' or no meta-file", metaFileName.c_str()); } // Create a model importer instance Assimp::Importer importer; // Give the importer an IO class that handles Spring's VFS importer.SetIOHandler(new AssVFSSystem()); // Speed-up processing by skipping things we don't need importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, ASS_IMPORTER_OPTIONS); #ifndef BITMAP_NO_OPENGL { importer.SetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT, maxVertices); importer.SetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT, maxIndices / 3); } #endif // Read the model file to build a scene object LOG_SL(LOG_SECTION_MODEL, L_INFO, "Importing model file: %s", modelFilePath.c_str()); const aiScene* scene = nullptr; { // ASSIMP spams many SIGFPEs atm in normal & tangent generation ScopedDisableFpuExceptions fe; scene = importer.ReadFile(modelFilePath, ASS_POSTPROCESS_OPTIONS); } if (scene != nullptr) { LOG_SL(LOG_SECTION_MODEL, L_INFO, "Processing scene for model: %s (%d meshes / %d materials / %d textures)", modelFilePath.c_str(), scene->mNumMeshes, scene->mNumMaterials, scene->mNumTextures); } else { throw content_error("[AssimpParser] Model Import: " + std::string(importer.GetErrorString())); } ModelPieceMap pieceMap; ParentNameMap parentMap; S3DModel* model = new S3DModel(); model->name = modelFilePath; model->type = MODELTYPE_ASS; // Load textures FindTextures(model, scene, modelTable, modelPath, modelName); LOG_SL(LOG_SECTION_MODEL, L_INFO, "Loading textures. Tex1: '%s' Tex2: '%s'", model->texs[0].c_str(), model->texs[1].c_str()); texturehandlerS3O->PreloadTexture(model, modelTable.GetBool("fliptextures", true), modelTable.GetBool("invertteamcolor", true)); // Load all pieces in the model LOG_SL(LOG_SECTION_MODEL, L_INFO, "Loading pieces from root node '%s'", scene->mRootNode->mName.data); LoadPiece(model, scene->mRootNode, scene, modelTable, pieceMap, parentMap); // Update piece hierarchy based on metadata BuildPieceHierarchy(model, pieceMap, parentMap); CalculateModelProperties(model, modelTable); // Verbose logging of model properties LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->name: %s", model->name.c_str()); LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->numobjects: %d", model->numPieces); LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->radius: %f", model->radius); LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->height: %f", model->height); LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->mins: (%f,%f,%f)", model->mins[0], model->mins[1], model->mins[2]); LOG_SL(LOG_SECTION_MODEL, L_DEBUG, "model->maxs: (%f,%f,%f)", model->maxs[0], model->maxs[1], model->maxs[2]); LOG_SL(LOG_SECTION_MODEL, L_INFO, "Model %s Imported.", model->name.c_str()); return model; }