Exemple #1
0
void LodManager::loadLod(Ogre::MeshPtr mesh, const LodDefinition& def)
{
    if (def.getUseAutomaticLod()) {
        loadAutomaticLod(mesh);
    } else if (def.getLodDistanceCount() == 0) {
        mesh->removeLodLevels();
        return;
    } else {
        Ogre::LodStrategy* strategy;
        if (def.getStrategy() == LodDefinition::LS_DISTANCE) {
            strategy = &Ogre::DistanceLodStrategy::getSingleton();
        } else {
            strategy = &Ogre::PixelCountLodStrategy::getSingleton();
        }
        mesh->setLodStrategy(strategy);

        if (def.getType() == LodDefinition::LT_AUTOMATIC_VERTEX_REDUCTION) {
            // Automatic vertex reduction
            LodConfig lodConfig;
            lodConfig.mesh = mesh;
            const LodDefinition::LodDistanceMap& data = def.getManualLodData();
            if (def.getStrategy() == LodDefinition::LS_DISTANCE) {
                // TODO: Use C++11 lambda, instead of template.
                loadAutomaticLodImpl(data.begin(), data.end(), lodConfig);
            } else {
                loadAutomaticLodImpl(data.rbegin(), data.rend(), lodConfig);
            }
            // Uncomment the ProgressiveMesh of your choice.
            // NOTE: OgreProgressiveMeshExt doesn't support collapse cost based reduction.
            // OgreProgressiveMeshExt pm;
            // ProgressiveMeshGenerator pm;
            QueuedProgressiveMeshGenerator pm;
            pm.build(lodConfig);
        } else {
            // User created Lod

            mesh->removeLodLevels();

            const LodDefinition::LodDistanceMap& data = def.getManualLodData();
            if (def.getStrategy() == LodDefinition::LS_DISTANCE) {
                // TODO: Use C++11 lambda, instead of template.
                loadUserLodImpl(data.begin(), data.end(), mesh.get());
            } else {
                loadUserLodImpl(data.rbegin(), data.rend(), mesh.get());
            }
        }
    }
}
void XMLLodDefinitionSerializer::importLodDefinition(const Ogre::DataStreamPtr& stream, LodDefinition& lodDef) const
{
	TiXmlDocument xmlDoc;
	XMLHelper xmlHelper;
	if (!xmlHelper.Load(xmlDoc, stream)) {
		return;
	}

	// <lod>...</lod>
	TiXmlElement* rootElem = xmlDoc.RootElement();
	if (rootElem) {

		// <automatic enabled="true|false" />
		TiXmlElement* autElem = rootElem->FirstChildElement("automatic");
		if (autElem) {
			const char* tmp = autElem->Attribute("enabled");
			if (tmp) {
				lodDef.setUseAutomaticLod(Ogre::StringConverter::parseBool(tmp, true));
			}
		}

		// <manual>...</manual>
		TiXmlElement* manElem = rootElem->FirstChildElement("manual");
		if (manElem) {

			// <type>user|automatic</type>
			TiXmlElement* elem = manElem->FirstChildElement("type");
			if (elem) {
				const char* tmp = elem->GetText();
				if (tmp && strcmp(tmp, "automatic") == 0) {
					lodDef.setType(LodDefinition::LT_AUTOMATIC_VERTEX_REDUCTION);
				} else {
					lodDef.setType(LodDefinition::LT_USER_CREATED_MESH);
				}
			}

			// <strategy>distance|pixelcount</strategy>
			elem = manElem->FirstChildElement("strategy");
			if (elem) {
				const char* tmp = elem->GetText();
				if (tmp && strcmp(tmp, "distance") == 0) {
					lodDef.setStrategy(LodDefinition::LS_DISTANCE);
				} else {
					lodDef.setStrategy(LodDefinition::LS_PIXEL_COUNT);
				}
			}

			// <level>...</level> <level>...</level> <level>...</level>
			for (TiXmlElement* distElem = manElem->FirstChildElement("level");
			     distElem != 0;
			     distElem = distElem->NextSiblingElement("level")) {
				LodDistance dist;

				if (lodDef.getType() == LodDefinition::LT_USER_CREATED_MESH) {
					// <meshName>.../test.mesh</meshName>
					elem = distElem->FirstChildElement("meshName");
					if (elem) {
						const char* tmp = elem->GetText();
						bool isValidMeshName = Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(tmp);
						if (tmp && isValidMeshName) {
							dist.setMeshName(tmp);
						} else {
							S_LOG_FAILURE(
							    lodDef.getName()	<<
							    " contains invalid mesh name for user created lod level. Skipping lod level for distance "
							                        << distElem->Attribute("distance"));
							continue;
						}
					}
				} else {
					// <method>constant|proportional</method>
					elem = distElem->FirstChildElement("method");
					if (elem) {
						const char* tmp = elem->GetText();
						if (tmp) {
							if (strcmp(tmp, "constant") == 0) {
								dist.setReductionMethod(Ogre::LodLevel::VRM_CONSTANT);
							} else if (strcmp(tmp, "proportional") == 0) {
								dist.setReductionMethod(Ogre::LodLevel::VRM_PROPORTIONAL);
							} else {
								dist.setReductionMethod(Ogre::LodLevel::VRM_COLLAPSE_COST);
							}
						} else {
							dist.setReductionMethod(Ogre::LodLevel::VRM_PROPORTIONAL);
						}
					}

					// <value>0.5</value>
					elem = distElem->FirstChildElement("value");
					if (elem) {
						const char* tmp = elem->GetText();
						if (tmp) {
							dist.setReductionValue(Ogre::StringConverter::parseReal(tmp));
						}
					}
				}

				// <level distance="10">...</level>
				const char* distVal = distElem->Attribute("distance");
				if (distVal) {
					lodDef.addLodDistance(Ogre::StringConverter::parseReal(distVal), dist);
				}
			}
		}
	}
}