float ProceduralTerrainAppearance::getHeight(float x, float y) {
	ReadLocker locker(&guard);

	float affectorTransform = 1.0;

	float transformValue = 0;
	float fullTraverse = 0;

	int count = 0;
	TerrainGenerator* terrain = terrainGenerator;

	do {
		LayersGroup* layersGroup = terrain->getLayersGroup();

		Vector<Layer*>* layers = layersGroup->getLayers();

		for (int i = 0; i < layers->size(); ++i) {
			Layer* layer = layers->get(i);

			if (layer->isEnabled())
				transformValue = processTerrain(layer, x, y, fullTraverse, affectorTransform, AffectorProceduralRule::HEIGHTTYPE);
		}
	} while (count < customTerrain.size() && (terrain = customTerrain.get(count++)));

	//info("full traverse height ... is " + String::valueOf(fullTraverse) + " in mili:" + String::valueOf(start.miliDifference()), true);

	return fullTraverse;
}
void DotSceneLoader::processScene(rapidxml::xml_node<>* XMLRoot)
{
	// Process the scene parameters
	Ogre::String version = getAttrib(XMLRoot, "formatVersion", "unknown");

	Ogre::String message = "[DotSceneLoader] Parsing dotScene file with version " + version;
	if (XMLRoot->first_attribute("ID"))
		message += ", id " + Ogre::String(XMLRoot->first_attribute("ID")->value());
	if (XMLRoot->first_attribute("sceneManager"))
		message += ", scene manager " + Ogre::String(XMLRoot->first_attribute("sceneManager")->value());
	if (XMLRoot->first_attribute("minOgreVersion"))
		message += ", min. Ogre version " + Ogre::String(XMLRoot->first_attribute("minOgreVersion")->value());
	if (XMLRoot->first_attribute("author"))
		message += ", author " + Ogre::String(XMLRoot->first_attribute("author")->value());

	Ogre::LogManager::getSingleton().logMessage(message);

	rapidxml::xml_node<>* pElement;

	// Process environment (?)
	pElement = XMLRoot->first_node("environment");
	if (pElement)
		processEnvironment(pElement);

	// Process nodes (?)
	pElement = XMLRoot->first_node("nodes");
	if (pElement)
		processNodes(pElement);

	// Process externals (?)
	pElement = XMLRoot->first_node("externals");
	if (pElement)
		processExternals(pElement);

	// Process userDataReference (?)
	pElement = XMLRoot->first_node("userDataReference");
	if (pElement)
		processUserDataReference(pElement);

	// Process octree (?)
	pElement = XMLRoot->first_node("octree");
	if (pElement)
		processOctree(pElement);

	// Process light (?)
	//pElement = XMLRoot->first_node("light");
	//if(pElement)
	//    processLight(pElement);

	// Process camera (?)
	pElement = XMLRoot->first_node("camera");
	if (pElement)
		processCamera(pElement);

	// Process terrain (?)
	pElement = XMLRoot->first_node("terrain");
	if (pElement)
		processTerrain(pElement);
}
void DotSceneLoader::processScene(TiXmlElement* xmlRoot) {
	std::string version = getAttrib(xmlRoot, "formatVersion", "unknown");

	std::string message = "[DotSceneLoader] Parsing dotScene file with version " + version;

	if(xmlRoot->Attribute("ID"))
		message += ", id " + std::string(xmlRoot->Attribute("ID"));
	if(xmlRoot->Attribute("sceneManager"))
		message += ", scene manager " + std::string(xmlRoot->Attribute("sceneManager"));
	if(xmlRoot->Attribute("minOgreVersion"))
		message += ", min. Ogre version " + std::string(xmlRoot->Attribute("minOgreVersion"));
	if(xmlRoot->Attribute("author"))
		message += ", author " + std::string(xmlRoot->Attribute("author"));

	TiXmlElement *element;

	// Process nodes (?)
	element = xmlRoot->FirstChildElement("nodes");
	if(element)
		processNodes(element);

	// Process externals (?)
	element = xmlRoot->FirstChildElement("externals");
	if(element)
		processExternals(element);

	// Process environment (?)
	element = xmlRoot->FirstChildElement("environment");
	if(element)
		processEnvironment(element);

	// Process terrain (?)
	element = xmlRoot->FirstChildElement("terrain");
	if(element)
		processTerrain(element);

	// Process userDataReference (?)
	element = xmlRoot->FirstChildElement("userDataReference");
	if(element)
		processUserDataReference(element);

	// Process octree (?)
	element = xmlRoot->FirstChildElement("octree");
	if(element)
		processOctree(element);

	// Process light (?)
	element = xmlRoot->FirstChildElement("light");
	if(element)
		processLight(element);

	// Process camera (?)
	element = xmlRoot->FirstChildElement("camera");
	if(element)
		processCamera(element);
}
float ProceduralTerrainAppearance::processTerrain(Layer* layer, float x, float y, float& baseValue, float affectorTransformValue, int affectorType) {
	Vector<Boundary*>* boundaries = layer->getBoundaries();
	Vector<AffectorProceduralRule*>* affectors = layer->getAffectors();
	Vector<FilterProceduralRule*>* filters = layer->getFilters();

	float transformValue = 0;

	bool hasBoundaries = false;

	FilterRectangle rect;
	rect.minX = FLT_MAX, rect.maxX = FLT_MIN, rect.minY = FLT_MAX, rect.maxY = FLT_MIN;

	for (int i = 0; i < boundaries->size(); ++i) {
		Boundary* boundary = boundaries->get(i);

		if (!boundary->isEnabled()) {
			continue;
		} else
			hasBoundaries = true;

		float result = boundary->process(x, y);

		if (result != 0.0) {
			if (boundary->getMinX() < rect.minX)
				rect.minX = boundary->getMinX();

			if (boundary->getMaxX() > rect.maxX)
				rect.maxX = boundary->getMaxX();

			if (boundary->getMinY() < rect.minY)
				rect.minY = boundary->getMinY();

			if (boundary->getMaxY() > rect.maxY)
				rect.maxY = boundary->getMaxY();
		}

		int featheringType = boundary->getFeatheringType();

		result = calculateFeathering(result, featheringType);

		if (result > transformValue)
			transformValue = result;

		if (transformValue >= 1) {
			break;
		}
	}

	if (!hasBoundaries)
		transformValue = 1.0;

	if (layer->invertBoundaries())
		transformValue = 1.0 - transformValue;

	if (transformValue != 0) {
		for (int i = 0; i < filters->size(); ++i) {
			FilterProceduralRule* filter = filters->get(i);

			if (!filter->isEnabled())
				continue;

			/*if (!(filter->getFilterType() & affectorType))
				continue;*/

			float result = filter->process(x, y, transformValue, baseValue, terrainGenerator, &rect);

			int featheringType = filter->getFeatheringType();

			result = calculateFeathering(result, featheringType);

			if (transformValue > result)
				transformValue = result;

			if (transformValue == 0)
				break;
		}

		if (layer->invertFilters())
			transformValue = 1.0 - transformValue;

		if (transformValue != 0) {
			for (int i = 0; i < affectors->size(); ++i) {
				AffectorProceduralRule* affector = affectors->get(i);

				/*if (!affector->isEnabled()) filtered in height affectors vector
					continue;*/

				if (affector->isEnabled() && (affector->getAffectorType() & affectorType))
					affector->process(x, y, transformValue * affectorTransformValue, baseValue, terrainGenerator);
			}


			Vector<Layer*>* children = layer->getChildren();

			for (int i = 0; i < children->size(); ++i) {
				Layer* layer = children->get(i);

				if (layer->isEnabled()) {
					processTerrain(layer, x, y, baseValue, affectorTransformValue * transformValue, affectorType);
				}
			}

		}

	}

	return transformValue;
}