void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) { Ogre::SceneNode* insert = ptr.getRefData().getBaseNode(); assert(insert); Ogre::AxisAlignedBox bounds = Ogre::AxisAlignedBox::BOX_NULL; NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(insert, NULL, mesh); for(size_t i = 0;i < entities.mEntities.size();i++) { const Ogre::AxisAlignedBox &tmp = entities.mEntities[i]->getBoundingBox(); bounds.merge(Ogre::AxisAlignedBox(insert->_getDerivedPosition() + tmp.getMinimum(), insert->_getDerivedPosition() + tmp.getMaximum()) ); } Ogre::Vector3 extents = bounds.getSize(); extents *= insert->getScale(); float size = std::max(std::max(extents.x, extents.y), extents.z); bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) && Settings::Manager::getBool("limit small object distance", "Viewing distance"); // do not fade out doors. that will cause holes and look stupid if (ptr.getTypeName().find("Door") != std::string::npos) small = false; if (mBounds.find(ptr.getCell()) == mBounds.end()) mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL; mBounds[ptr.getCell()].merge(bounds); bool transparent = false; for(size_t i = 0;i < entities.mEntities.size();i++) { Ogre::Entity *ent = entities.mEntities[i]; for (unsigned int i=0; i<ent->getNumSubEntities(); ++i) { Ogre::MaterialPtr mat = ent->getSubEntity(i)->getMaterial(); Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); while (techIt.hasMoreElements()) { Ogre::Technique* tech = techIt.getNext(); Ogre::Technique::PassIterator passIt = tech->getPassIterator(); while (passIt.hasMoreElements()) { Ogre::Pass* pass = passIt.getNext(); if (pass->getDepthWriteEnabled() == false) transparent = true; } } } } if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects") || transparent) { for(size_t i = 0;i < entities.mEntities.size();i++) { Ogre::Entity *ent = entities.mEntities[i]; ent->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0); ent->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc); ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); } } else { Ogre::StaticGeometry* sg = 0; if (small) { if( mStaticGeometrySmall.find(ptr.getCell()) == mStaticGeometrySmall.end()) { uniqueID = uniqueID +1; sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); mStaticGeometrySmall[ptr.getCell()] = sg; sg->setRenderingDistance(Settings::Manager::getInt("small object distance", "Viewing distance")); } else sg = mStaticGeometrySmall[ptr.getCell()]; } else { if( mStaticGeometry.find(ptr.getCell()) == mStaticGeometry.end()) { uniqueID = uniqueID +1; sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); mStaticGeometry[ptr.getCell()] = sg; } else sg = mStaticGeometry[ptr.getCell()]; } // This specifies the size of a single batch region. // If it is set too high: // - there will be problems choosing the correct lights // - the culling will be more inefficient // If it is set too low: // - there will be too many batches. sg->setRegionDimensions(Ogre::Vector3(2500,2500,2500)); sg->setVisibilityFlags(small ? RV_StaticsSmall : RV_Statics); sg->setCastShadows(true); sg->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); for(size_t i = 0;i < entities.mEntities.size();i++) { Ogre::Entity *ent = entities.mEntities[i]; insert->detachObject(ent); sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale()); mRenderer.getScene()->destroyEntity(ent); } } }
NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWorld::InventoryStore& _inv, int visibilityFlags) : Animation(), mStateID(-1), mInv(_inv), timeToChange(0), mVisibilityFlags(visibilityFlags), robe(mInv.end()), helmet(mInv.end()), shirt(mInv.end()), cuirass(mInv.end()), greaves(mInv.end()), leftpauldron(mInv.end()), rightpauldron(mInv.end()), boots(mInv.end()), leftglove(mInv.end()), rightglove(mInv.end()), skirtiter(mInv.end()), pants(mInv.end()) { MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>(); for (int init = 0; init < 27; init++) { mPartslots[init] = -1; //each slot is empty mPartPriorities[init] = 0; } const ESMS::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Race *race = store.races.find(ref->base->mRace); std::string hairID = ref->base->mHair; std::string headID = ref->base->mHead; headModel = "meshes\\" + store.bodyParts.find(headID)->mModel; hairModel = "meshes\\" + store.bodyParts.find(hairID)->mModel; npcName = ref->base->mName; isFemale = !!(ref->base->mFlags&ESM::NPC::Female); isBeast = !!(race->mData.mFlags&ESM::Race::Beast); bodyRaceID = "b_n_"+ref->base->mRace; std::transform(bodyRaceID.begin(), bodyRaceID.end(), bodyRaceID.begin(), ::tolower); mInsert = node; assert(mInsert); std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); mEntityList = NifOgre::NIFLoader::createEntities(mInsert, &mTextKeys, smodel); for(size_t i = 0;i < mEntityList.mEntities.size();i++) { Ogre::Entity *base = mEntityList.mEntities[i]; base->getUserObjectBindings ().setUserAny (Ogre::Any(-1)); base->setVisibilityFlags(mVisibilityFlags); bool transparent = false; for(unsigned int j=0;j < base->getNumSubEntities();++j) { Ogre::MaterialPtr mat = base->getSubEntity(j)->getMaterial(); Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); while (techIt.hasMoreElements()) { Ogre::Technique* tech = techIt.getNext(); Ogre::Technique::PassIterator passIt = tech->getPassIterator(); while (passIt.hasMoreElements()) { Ogre::Pass* pass = passIt.getNext(); if (pass->getDepthWriteEnabled() == false) transparent = true; } } } base->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); } if(mEntityList.mSkelBase) { Ogre::AnimationStateSet *aset = mEntityList.mSkelBase->getAllAnimationStates(); Ogre::AnimationStateIterator as = aset->getAnimationStateIterator(); while(as.hasMoreElements()) { Ogre::AnimationState *state = as.getNext(); state->setEnabled(true); state->setLoop(false); } } float scale = race->mData.mHeight.mMale; if (isFemale) { scale = race->mData.mHeight.mFemale; } mInsert->scale(scale, scale, scale); updateParts(); }
//----------------------------------------------------------------------- void TerrainLiquidObject::_prepareProjector(void) { if (mProjectorName.empty() || !mProjectorSize) return; Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().getByName(mMaterialName); if (material.isNull()) return; bool hasProjector = false; { Ogre::Material::TechniqueIterator ti = material->getTechniqueIterator(); while (ti.hasMoreElements()) { Ogre::Technique* technique = ti.getNext(); Ogre::Technique::PassIterator pi = technique->getPassIterator(); while (pi.hasMoreElements()) { Ogre::Pass* pass = pi.getNext(); Ogre::Pass::TextureUnitStateIterator tusi = pass->getTextureUnitStateIterator(); while (tusi.hasMoreElements()) { Ogre::TextureUnitState* tus = tusi.getNext(); if (Ogre::StringUtil::startsWith(tus->getName(), "Fairy/Projector", false)) { hasProjector = true; } } } } } if (!hasProjector) return; ObjectPtr object = mSystem->getSceneInfo()->findObjectByName(mProjectorName); if (!object) return; Variant directionValue = object->getProperty("direction"); if (directionValue.empty() || directionValue.type() != typeid(Ogre::Vector3)) return; Ogre::Vector3 direction = VariantCast<Ogre::Vector3>(directionValue); direction.normalise(); Ogre::String name = material->getName() + Ogre::StringConverter::toString((Ogre::ulong)this); mProjectionCamera = mTerrainLiquid->getParentSceneNode()->getCreator()->createCamera(name); mProjectionCamera->setAutoAspectRatio(false); mProjectionCamera->setAspectRatio(1.0f); mProjectionCamera->setFixedYawAxis(false); mProjectionCamera->setProjectionType(Ogre::PT_ORTHOGRAPHIC); mProjectionCamera->setFOVy(Ogre::Degree(90)); mProjectionCamera->setDirection(-direction); mProjectionCamera->setNearClipDistance(mProjectorSize / 2); mProjectionCamera->setFarClipDistance(mProjectorSize + 5000.0f); mTerrainLiquid->setProjectionCamera(mProjectionCamera); mProjectionMaterial = material->clone(name); { Ogre::Material::TechniqueIterator ti = mProjectionMaterial->getTechniqueIterator(); while (ti.hasMoreElements()) { Ogre::Technique* technique = ti.getNext(); Ogre::Technique::PassIterator pi = technique->getPassIterator(); while (pi.hasMoreElements()) { Ogre::Pass* pass = pi.getNext(); Ogre::Pass::TextureUnitStateIterator tusi = pass->getTextureUnitStateIterator(); while (tusi.hasMoreElements()) { Ogre::TextureUnitState* tus = tusi.getNext(); if (Ogre::StringUtil::startsWith(tus->getName(), "Fairy/Projector", false)) { tus->setProjectiveTexturing(true, mProjectionCamera); } } } } } mProjectionMaterial->load(); }
Ogre::MaterialPtr OgreMaterialProperties::ToOgreMaterial() { ///\todo Regression. Reimplement using the new Asset API. -jj. return Ogre::MaterialPtr(); #if 0 // Make clone from the original and uset that for creating the new material. Ogre::MaterialPtr matPtr = material_->GetMaterial(); Ogre::MaterialPtr matPtrClone = matPtr->clone(objectName().toStdString() + "Clone"); // Material if (!matPtrClone.isNull()) { // Technique Ogre::Material::TechniqueIterator tIter = matPtrClone->getTechniqueIterator(); while(tIter.hasMoreElements()) { Ogre::Technique *tech = tIter.getNext(); Ogre::Technique::PassIterator pIter = tech->getPassIterator(); while(pIter.hasMoreElements()) { // Pass Ogre::Pass *pass = pIter.getNext(); if (!pass) continue; if (pass->hasVertexProgram()) { // Vertex program const Ogre::GpuProgramPtr &verProg = pass->getVertexProgram(); if (!verProg.isNull()) { Ogre::GpuProgramParametersSharedPtr verPtr = pass->getVertexProgramParameters(); if (verPtr->hasNamedParameters()) { // Named parameters (constants) Ogre::GpuConstantDefinitionIterator mapIter = verPtr->getConstantDefinitionIterator(); //int constNum = 0; while(mapIter.hasMoreElements()) { QString paramName(mapIter.peekNextKey().c_str()); const Ogre::GpuConstantDefinition ¶mDef = mapIter.getNext(); // Filter names that end with '[0]' if (paramName.lastIndexOf("[0]") != -1) continue; if (!paramDef.isFloat()) continue; size_t size = paramDef.elementSize * paramDef.arraySize; QVector<float> newParamValue; QVector<float>::iterator it; newParamValue.resize(size); // Find the corresponding property value. QVariant val = property(paramName.append(" VP").toLatin1()); if (!val.isValid() || val.isNull()) continue; TypeValuePair typeValuePair = val.toMap(); QString newValueString(typeValuePair.begin().value().toByteArray()); newValueString = newValueString.trimmed(); // fill the float vector with new values it = newParamValue.begin(); int i = 0, j = 0; bool ok = true; while(j != -1 && ok) { j = newValueString.indexOf(' ', i); QString newValue = newValueString.mid(i, j == -1 ? j : j - i); if (!newValue.isEmpty()) { *it = newValue.toFloat(&ok); ++it; } i = j + 1; } // Set the new value. ///\todo use the exact count rather than just 4 values if needed. if (size == 16) { Ogre::Matrix4 matrix(newParamValue[0], newParamValue[1], newParamValue[2], newParamValue[3], newParamValue[4], newParamValue[5], newParamValue[6], newParamValue[7], newParamValue[8], newParamValue[9], newParamValue[10], newParamValue[11], newParamValue[12], newParamValue[13], newParamValue[14], newParamValue[15]); #if OGRE_VERSION_MINOR <= 6 && OGRE_VERSION_MAJOR <= 1 verPtr->_writeRawConstant(paramDef.physicalIndex, matrix); #else verPtr->_writeRawConstant(paramDef.physicalIndex, matrix, size); #endif } else { Ogre::Vector4 vector(newParamValue[0], newParamValue[1], newParamValue[2], newParamValue[3]); verPtr->_writeRawConstant(paramDef.physicalIndex, vector); } } } } } if (pass->hasFragmentProgram()) { // Fragment program const Ogre::GpuProgramPtr &fragProg = pass->getFragmentProgram(); if (!fragProg.isNull()) { Ogre::GpuProgramParametersSharedPtr fragPtr = pass->getFragmentProgramParameters(); if (!fragPtr.isNull()) { if (fragPtr->hasNamedParameters()) { // Named parameters (constants) Ogre::GpuConstantDefinitionIterator mapIter = fragPtr->getConstantDefinitionIterator(); while(mapIter.hasMoreElements()) { QString paramName(mapIter.peekNextKey().c_str()); const Ogre::GpuConstantDefinition ¶mDef = mapIter.getNext(); // Filter names that end with '[0]' if (paramName.lastIndexOf("[0]") != -1) continue; if (!paramDef.isFloat()) continue; size_t size = paramDef.elementSize * paramDef.arraySize; QVector<float> newParamValue; QVector<float>::iterator it; newParamValue.resize(size); // Find the corresponding property value. QVariant val = property(paramName.append(" FP").toLatin1()); if (!val.isValid() || val.isNull()) continue; TypeValuePair typeValuePair = val.toMap(); QString newValueString(typeValuePair.begin().value().toByteArray()); newValueString = newValueString.trimmed(); // Fill the float vector with new values. it = newParamValue.begin(); int i = 0, j = 0; bool ok = true; while(j != -1 && ok) { j = newValueString.indexOf(' ', i); QString newValue = newValueString.mid(i, j == -1 ? j : j - i); if (!newValue.isEmpty()) { *it = *it = newValue.toFloat(&ok); ++it; } i = j + 1; } // Set the new value. ///\todo use the exact count rather than just 4 values if needed. if (size == 16) { Ogre::Matrix4 matrix(newParamValue[0], newParamValue[1], newParamValue[2], newParamValue[3], newParamValue[4], newParamValue[5], newParamValue[6], newParamValue[7], newParamValue[8], newParamValue[9], newParamValue[10], newParamValue[11], newParamValue[12], newParamValue[13], newParamValue[14], newParamValue[15]); #if OGRE_VERSION_MINOR <= 6 && OGRE_VERSION_MAJOR <= 1 fragPtr->_writeRawConstant(paramDef.physicalIndex, matrix); #else fragPtr->_writeRawConstant(paramDef.physicalIndex, matrix, size); #endif } else { Ogre::Vector4 vector(newParamValue[0], newParamValue[1], newParamValue[2], newParamValue[3]); fragPtr->_writeRawConstant(paramDef.physicalIndex, vector); } } } } } } Ogre::Pass::TextureUnitStateIterator texIter = pass->getTextureUnitStateIterator(); while(texIter.hasMoreElements()) { // Texture units Ogre::TextureUnitState *tu = texIter.getNext(); // Replace the texture name (uuid) with the new one QString tu_name(tu->getName().c_str()); QVariant val = property(tu_name.append(" TU").toLatin1()); if (!val.isValid() || val.isNull()) continue; TypeValuePair typeValuePair = val.toMap(); QString newValueString(typeValuePair.begin().value().toByteArray()); newValueString = newValueString.trimmed(); tu->setTextureName(OgreRenderer::SanitateAssetIdForOgre(newValueString.toStdString())); /* //QString new_texture_name = iter->second; RexUUID new_name(iter->second); // If new texture is UUID-based one, make sure the corresponding RexOgreTexture gets created, // because we may not be able to load it later if load fails now if (RexUUID::IsValid(new_texture_name)) { RexUUID imageID(new_texture_name); if (!imageID.IsNull()) { image* image = imageList.getImage(imageID); if (image) { image->getOgreTexture(); } } } //tu->setTextureName(iter->second); */ } } } return matPtrClone; } matPtrClone.setNull(); return matPtrClone; #endif }
bool OgreMaterialResource::SetData(Foundation::AssetPtr source) { // Remove old material if any RemoveMaterial(); references_.clear(); original_textures_.clear(); Ogre::MaterialManager& matmgr = Ogre::MaterialManager::getSingleton(); OgreRenderingModule::LogDebug("Parsing material " + source->GetId()); if (!source) { OgreRenderingModule::LogError("Null source asset data pointer"); return false; } if (!source->GetSize()) { OgreRenderingModule::LogError("Zero sized material asset"); return false; } Ogre::DataStreamPtr data = Ogre::DataStreamPtr(new Ogre::MemoryDataStream(const_cast<u8 *>(source->GetData()), source->GetSize())); static int tempname_count = 0; tempname_count++; std::string tempname = "TempMat" + ToString<int>(tempname_count); try { int num_materials = 0; int brace_level = 0; bool skip_until_next = false; int skip_brace_level = 0; // Parsed/modified material script std::ostringstream output; while (!data->eof()) { Ogre::String line = data->getLine(); // Skip empty lines & comments if ((line.length()) && (line.substr(0, 2) != "//")) { // Process opening/closing braces if (!ResourceHandler::ProcessBraces(line, brace_level)) { // If not a brace and on level 0, it should be a new material; replace name if ((brace_level == 0) && (line.substr(0, 8) == "material")) { if (num_materials == 0) { line = "material " + tempname; ++num_materials; } else { OgreRenderingModule::LogWarning("More than one material defined in material asset " + source->GetId() + " - only first one supported"); break; } } else { // Check for textures if ((line.substr(0, 8) == "texture ") && (line.length() > 8)) { std::string tex_name = line.substr(8); // Note: we assume all texture references are asset based. ResourceHandler checks later whether this is true, // before requesting the reference references_.push_back(Foundation::ResourceReference(tex_name, OgreTextureResource::GetTypeStatic())); original_textures_.push_back(tex_name); // Replace any / with \ in the material, then change the texture names back later, so that Ogre does not go nuts ReplaceCharInplace(line, '/', '\\'); ReplaceCharInplace(line, ':', '@'); } } // Write line to the modified copy if (!skip_until_next) output << line << std::endl; } else { // Write line to the modified copy if (!skip_until_next) output << line << std::endl; if (brace_level <= skip_brace_level) skip_until_next = false; } } } std::string output_str = output.str(); Ogre::DataStreamPtr modified_data = Ogre::DataStreamPtr(new Ogre::MemoryDataStream((u8 *)(&output_str[0]), output_str.size())); matmgr.parseScript(modified_data, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); Ogre::MaterialPtr tempmat; tempmat = matmgr.getByName(tempname); if (tempmat.isNull()) { OgreRenderingModule::LogWarning(std::string("Failed to create an Ogre material from material asset ") + source->GetId()); return false; } if(!tempmat->getNumTechniques()) { OgreRenderingModule::LogWarning("Failed to create an Ogre material from material asset " + source->GetId()); return false; } ogre_material_ = tempmat->clone(id_); tempmat.setNull(); matmgr.remove(tempname); if (ogre_material_.isNull()) { OgreRenderingModule::LogWarning("Failed to create an Ogre material from material asset " + source->GetId()); return false; } // Now go through all the texturenames and restore \ back to / and @ to : Ogre::Material::TechniqueIterator iter = ogre_material_->getTechniqueIterator(); while (iter.hasMoreElements()) { Ogre::Technique *tech = iter.getNext(); Ogre::Technique::PassIterator passIter = tech->getPassIterator(); while (passIter.hasMoreElements()) { Ogre::Pass *pass = passIter.getNext(); Ogre::Pass::TextureUnitStateIterator texIter = pass->getTextureUnitStateIterator(); while (texIter.hasMoreElements()) { Ogre::TextureUnitState *texUnit = texIter.getNext(); std::string texname = texUnit->getTextureName(); if (texname.find('\\') != std::string::npos) { ReplaceCharInplace(texname, '\\', '/'); ReplaceCharInplace(texname, '@', ':'); texUnit->setTextureName(texname); } } } } //workaround: if receives shadows, check the amount of shadowmaps. If only 1 specified, add 2 more to support 3 shadowmaps if(ogre_material_->getReceiveShadows() && shadowquality_ == Shadows_High && ogre_material_->getNumTechniques() > 0) { Ogre::Technique *tech = ogre_material_->getTechnique(0); if(tech) { Ogre::Technique::PassIterator passiterator = tech->getPassIterator(); while(passiterator.hasMoreElements()) { Ogre::Pass* pass = passiterator.getNext(); Ogre::Pass::TextureUnitStateIterator texiterator = pass->getTextureUnitStateIterator(); int shadowmaps = 0; while(texiterator.hasMoreElements()) { Ogre::TextureUnitState* state = texiterator.getNext(); if(state->getContentType() == Ogre::TextureUnitState::CONTENT_SHADOW) { shadowmaps++; } } if(shadowmaps>0 && shadowmaps<3) { Ogre::TextureUnitState* sm2 = pass->createTextureUnitState(); sm2->setContentType(Ogre::TextureUnitState::CONTENT_SHADOW); Ogre::TextureUnitState* sm3 = pass->createTextureUnitState(); sm3->setContentType(Ogre::TextureUnitState::CONTENT_SHADOW); } } } } } catch (Ogre::Exception &e) { OgreRenderingModule::LogWarning(e.what()); OgreRenderingModule::LogWarning("Failed to parse Ogre material " + source->GetId() + "."); try { if (!matmgr.getByName(tempname).isNull()) Ogre::MaterialManager::getSingleton().remove(tempname); } catch (...) {} return false; } return true; }