<commit_before>/**
*  Copyright (C) 2015 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero General Public License as
*  published by the Free Software Foundation, either version 3 of the
*  License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Affero General Public License for more details.
*
*  You should have received a copy of the GNU Affero General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
* Allows geometry creation using ifcopenshell
*/

#include "repo_ifc_utils_geometry.h"
#include "../../../core/model/bson/repo_bson_factory.h"
#include <boost/filesystem.hpp>

using namespace repo::manipulator::modelconvertor;

IFCUtilsGeometry::IFCUtilsGeometry(const std::string &file, const ModelImportConfig *settings) :
file(file),
settings(settings)
{
}

IFCUtilsGeometry::~IFCUtilsGeometry()
{
}

repo_material_t IFCUtilsGeometry::createMaterial(
	const IfcGeom::Material &material)
{
	repo_material_t matProp;
	if (material.hasDiffuse())
	{
		auto diffuse = material.diffuse();
		matProp.diffuse = { (float)diffuse[0], (float)diffuse[1], (float)diffuse[2] };
	}

	if (material.hasSpecular())
	{
		auto specular = material.specular();
		matProp.specular = { (float)specular[0], (float)specular[1], (float)specular[2] };
	}

	if (material.hasSpecularity())
	{
		matProp.shininess = material.specularity();
	}
	else
	{
		matProp.shininess = NAN;
	}

	matProp.shininessStrength = NAN;

	if (material.hasTransparency())
	{
		matProp.opacity = 1. - material.transparency();
	}
	else
	{
		matProp.opacity = 1.;
	}
	return matProp;
}

IfcGeom::IteratorSettings IFCUtilsGeometry::createSettings()
{
	IfcGeom::IteratorSettings itSettings;

	itSettings.set(IfcGeom::IteratorSettings::WELD_VERTICES, settings->getWieldVertices());
	itSettings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, settings->getUseWorldCoords());
	itSettings.set(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS, settings->getConvertUnits());
	itSettings.set(IfcGeom::IteratorSettings::USE_BREP_DATA, settings->getUseBRepData());
	itSettings.set(IfcGeom::IteratorSettings::SEW_SHELLS, settings->getSewShells());
	itSettings.set(IfcGeom::IteratorSettings::FASTER_BOOLEANS, settings->getFasterBooleans());
	itSettings.set(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS, settings->getNoOpeningSubtractions());
	itSettings.set(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION, settings->getNoTriangulation());
	itSettings.set(IfcGeom::IteratorSettings::APPLY_DEFAULT_MATERIALS, settings->getUseDefaultMaterials());
	itSettings.set(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES, settings->getDisableSolidSurfaces());
	itSettings.set(IfcGeom::IteratorSettings::NO_NORMALS, settings->getNoNormals());
	itSettings.set(IfcGeom::IteratorSettings::USE_ELEMENT_NAMES, settings->getUseElementNames());
	itSettings.set(IfcGeom::IteratorSettings::USE_ELEMENT_GUIDS, settings->getUseElementGuids());
	itSettings.set(IfcGeom::IteratorSettings::USE_MATERIAL_NAMES, settings->getUseMaterialNames());
	itSettings.set(IfcGeom::IteratorSettings::CENTER_MODEL, settings->getCentreModels());
	itSettings.set(IfcGeom::IteratorSettings::GENERATE_UVS, settings->getGenerateUVs());
	itSettings.set(IfcGeom::IteratorSettings::APPLY_LAYERSETS, settings->getApplyLayerSets());

	return itSettings;
}

bool IFCUtilsGeometry::generateGeometry(std::string &errMsg)
{
	repoInfo << "Initialising Geometry....." << std::endl;

	auto itSettings = createSettings();

	IfcGeom::Iterator<double> contextIterator(itSettings, file);

	//auto filter = settings->getFilteringKeywords();
	//if (settings->getUseElementsFiltering() &&  filter.size())
	//{
	//	std::set<std::string> filterSet(filter.begin(), filter.end());

	//	if (settings->getIsExclusionFilter())
	//	{
	//		contextIterator.excludeEntities(filterSet);
	//	}
	//	else
	//	{
	//		contextIterator.includeEntities(filterSet);
	//	}
	//}
	//

	repoTrace << "Initialising Geom iterator";
	if (contextIterator.initialize())
	{
		repoTrace << "Geom Iterator initialized";
	}
	else
	{
		errMsg = "Failed to initialised Geom Iterator";
		return false;
	}

	std::vector<std::vector<repo_face_t>> allFaces;
	std::vector<std::vector<double>> allVertices;
	std::vector<std::vector<double>> allNormals;
	std::vector<std::vector<double>> allUVs;
	std::vector<std::string> allIds, allNames, allMaterials;

	retrieveGeometryFromIterator(contextIterator, itSettings.get(IfcGeom::IteratorSettings::USE_MATERIAL_NAMES),
		allVertices, allFaces, allNormals, allUVs, allIds, allNames, allMaterials);

	//now we have found all meshes, take the minimum bounding box of the scene as offset
	//and create repo meshes
	repoTrace << "Finished iterating. number of meshes found: " << allVertices.size();
	repoTrace << "Finished iterating. number of materials found: " << materials.size();

	std::map<std::string, std::vector<repo::lib::RepoUUID>> materialParent;
	for (int i = 0; i < allVertices.size(); ++i)
	{
		std::vector<repo::lib::RepoVector3D> vertices, normals;
		std::vector<repo::lib::RepoVector2D> uvs;
		std::vector<repo_face_t> faces;
		std::vector<std::vector<float>> boundingBox;
		for (int j = 0; j < allVertices[i].size(); j += 3)
		{
			vertices.push_back({ (float)(allVertices[i][j] - offset[0]), (float)(allVertices[i][j + 1] - offset[1]), (float)(allVertices[i][j + 2] - offset[2]) });
			if (allNormals[i].size())
				normals.push_back({ (float)allNormals[i][j], (float)allNormals[i][j + 1], (float)allNormals[i][j + 2] });

			auto vertex = vertices.back();
			if (j == 0)
			{
				boundingBox.push_back({ vertex.x, vertex.y, vertex.z });
				boundingBox.push_back({ vertex.x, vertex.y, vertex.z });
			}
			else
			{
				boundingBox[0][0] = boundingBox[0][0] > vertex.x ? vertex.x : boundingBox[0][0];
				boundingBox[0][1] = boundingBox[0][1] > vertex.y ? vertex.y : boundingBox[0][1];
				boundingBox[0][2] = boundingBox[0][2] > vertex.z ? vertex.z : boundingBox[0][2];

				boundingBox[1][0] = boundingBox[1][0] < vertex.x ? vertex.x : boundingBox[1][0];
				boundingBox[1][1] = boundingBox[1][1] < vertex.y ? vertex.y : boundingBox[1][1];
				boundingBox[1][2] = boundingBox[1][2] < vertex.z ? vertex.z : boundingBox[1][2];
			}
		}

		for (int j = 0; j < allUVs[i].size(); j += 2)
		{
			uvs.push_back({ (float)allUVs[i][j], (float)allUVs[i][j + 1] });
		}

		std::vector < std::vector<repo::lib::RepoVector2D>> uvChannels;
		if (uvs.size())
			uvChannels.push_back(uvs);

		auto mesh = repo::core::model::RepoBSONFactory::makeMeshNode(vertices, allFaces[i], normals, boundingBox, uvChannels,
			std::vector<repo_color4d_t>(), std::vector<std::vector<float>>());

		if (meshes.find(allIds[i]) == meshes.end())
		{
			meshes[allIds[i]] = std::vector<repo::core::model::MeshNode*>();
		}
		meshes[allIds[i]].push_back(new repo::core::model::MeshNode(mesh));

		if (allMaterials[i] != "")
		{
			if (materialParent.find(allMaterials[i]) == materialParent.end())
			{
				materialParent[allMaterials[i]] = std::vector<repo::lib::RepoUUID>();
			}

			materialParent[allMaterials[i]].push_back(mesh.getSharedID());
		}
	}

	repoTrace << "Meshes constructed. Wiring materials to parents...";

	for (const auto &pair : materialParent)
	{
		auto matIt = materials.find(pair.first);
		if (matIt != materials.end())
		{
			*(matIt->second) = matIt->second->cloneAndAddParent(pair.second);
		}
	}

	return true;
}

void IFCUtilsGeometry::retrieveGeometryFromIterator(
	IfcGeom::Iterator<double> &contextIterator,
	const bool useMaterialNames,
	std::vector < std::vector<double>> &allVertices,
	std::vector<std::vector<repo_face_t>> &allFaces,
	std::vector < std::vector<double>> &allNormals,
	std::vector < std::vector<double>> &allUVs,
	std::vector<std::string> &allIds,
	std::vector<std::string> &allNames,
	std::vector<std::string> &allMaterials)
{
	repoTrace << "Iterating through Geom Iterator.";
	do
	{
		IfcGeom::Element<double> *ob = contextIterator.get();
		auto ob_geo = static_cast<const IfcGeom::TriangulationElement<double>*>(ob);
		if (ob_geo)
		{
			auto faces = ob_geo->geometry().faces();
			auto vertices = ob_geo->geometry().verts();
			auto normals = ob_geo->geometry().normals();
			auto uvs = ob_geo->geometry().uvs();
			std::unordered_map<int, std::unordered_map<int, int>>  indexMapping;
			std::unordered_map<int, int> vertexCount;
			std::unordered_map<int, std::vector<double>> post_vertices, post_normals, post_uvs;
			std::unordered_map<int, std::string> post_materials;
			std::unordered_map<int, std::vector<repo_face_t>> post_faces;

			auto matIndIt = ob_geo->geometry().material_ids().begin();

			for (int i = 0; i < vertices.size(); i += 3)
			{
				for (int j = 0; j < 3; ++j)
				{
					int index = j + i;
					if (offset.size() < j + 1)
					{
						offset.push_back(vertices[index]);
					}
					else
					{
						offset[j] = offset[j] > vertices[index] ? vertices[index] : offset[j];
					}
				}
			}

			for (int iface = 0; iface < faces.size(); iface += 3)
			{
				auto matInd = *matIndIt;
				if (indexMapping.find(matInd) == indexMapping.end())
				{
					//new material
					indexMapping[matInd] = std::unordered_map<int, int>();
					vertexCount[matInd] = 0;

					std::unordered_map<int, std::vector<double>> post_vertices, post_normals, post_uvs;
					std::unordered_map<int, std::vector<repo_face_t>> post_faces;

					post_vertices[matInd] = std::vector<double>();
					post_normals[matInd] = std::vector<double>();
					post_uvs[matInd] = std::vector<double>();
					post_faces[matInd] = std::vector<repo_face_t>();

					auto material = ob_geo->geometry().materials()[matInd];
					std::string matName = useMaterialNames ? material.original_name() : material.name();

					post_materials[matInd] = matName;
					if (materials.find(matName) == materials.end())
					{
						//new material, add it to the vector
						repo_material_t matProp = createMaterial(material);
						materials[matName] = new repo::core::model::MaterialNode(repo::core::model::RepoBSONFactory::makeMaterialNode(matProp, matName));
					}
				}

				repo_face_t face;
				for (int j = 0; j < 3; ++j)
				{
					auto vIndex = faces[iface + j];
					if (indexMapping[matInd].find(vIndex) == indexMapping[matInd].end())
					{
						//new index. create a mapping
						indexMapping[matInd][vIndex] = vertexCount[matInd]++;
						for (int ivert = 0; ivert < 3; ++ivert)
						{
							auto bufferInd = ivert + vIndex * 3;
							post_vertices[matInd].push_back(vertices[bufferInd]);

							if (normals.size())
								post_normals[matInd].push_back(normals[bufferInd]);

							if (uvs.size() && ivert < 2)
							{
								auto uvbufferInd = ivert + vIndex * 2;
								post_uvs[matInd].push_back(uvs[uvbufferInd]);
							}
						}
					}
					face.push_back(indexMapping[matInd][vIndex]);
				}

				post_faces[matInd].push_back(face);

				++matIndIt;
			}

			auto guid = ob_geo->guid();
			auto name = ob_geo->name();
			for (const auto& pair : post_faces)
			{
				auto index = pair.first;
				allVertices.push_back(post_vertices[index]);
				allNormals.push_back(post_normals[index]);
				allFaces.push_back(pair.second);
				allUVs.push_back(post_uvs[index]);

				allIds.push_back(guid);
				allNames.push_back(name);
				allMaterials.push_back(post_materials[index]);
			}
		}
		if (allIds.size() % 100 == 0)
			repoInfo << allIds.size() << " meshes created";
	} while (contextIterator.next());
}<commit_msg>#170 catch exception on geomiterator initialisation<commit_after>/**
*  Copyright (C) 2015 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero General Public License as
*  published by the Free Software Foundation, either version 3 of the
*  License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Affero General Public License for more details.
*
*  You should have received a copy of the GNU Affero General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
* Allows geometry creation using ifcopenshell
*/

#include "repo_ifc_utils_geometry.h"
#include "../../../core/model/bson/repo_bson_factory.h"
#include <boost/filesystem.hpp>

using namespace repo::manipulator::modelconvertor;

IFCUtilsGeometry::IFCUtilsGeometry(const std::string &file, const ModelImportConfig *settings) :
file(file),
settings(settings)
{
}

IFCUtilsGeometry::~IFCUtilsGeometry()
{
}

repo_material_t IFCUtilsGeometry::createMaterial(
	const IfcGeom::Material &material)
{
	repo_material_t matProp;
	if (material.hasDiffuse())
	{
		auto diffuse = material.diffuse();
		matProp.diffuse = { (float)diffuse[0], (float)diffuse[1], (float)diffuse[2] };
	}

	if (material.hasSpecular())
	{
		auto specular = material.specular();
		matProp.specular = { (float)specular[0], (float)specular[1], (float)specular[2] };
	}

	if (material.hasSpecularity())
	{
		matProp.shininess = material.specularity();
	}
	else
	{
		matProp.shininess = NAN;
	}

	matProp.shininessStrength = NAN;

	if (material.hasTransparency())
	{
		matProp.opacity = 1. - material.transparency();
	}
	else
	{
		matProp.opacity = 1.;
	}
	return matProp;
}

IfcGeom::IteratorSettings IFCUtilsGeometry::createSettings()
{
	IfcGeom::IteratorSettings itSettings;

	itSettings.set(IfcGeom::IteratorSettings::WELD_VERTICES, settings->getWieldVertices());
	itSettings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, settings->getUseWorldCoords());
	itSettings.set(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS, settings->getConvertUnits());
	itSettings.set(IfcGeom::IteratorSettings::USE_BREP_DATA, settings->getUseBRepData());
	itSettings.set(IfcGeom::IteratorSettings::SEW_SHELLS, settings->getSewShells());
	itSettings.set(IfcGeom::IteratorSettings::FASTER_BOOLEANS, settings->getFasterBooleans());
	itSettings.set(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS, settings->getNoOpeningSubtractions());
	itSettings.set(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION, settings->getNoTriangulation());
	itSettings.set(IfcGeom::IteratorSettings::APPLY_DEFAULT_MATERIALS, settings->getUseDefaultMaterials());
	itSettings.set(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES, settings->getDisableSolidSurfaces());
	itSettings.set(IfcGeom::IteratorSettings::NO_NORMALS, settings->getNoNormals());
	itSettings.set(IfcGeom::IteratorSettings::USE_ELEMENT_NAMES, settings->getUseElementNames());
	itSettings.set(IfcGeom::IteratorSettings::USE_ELEMENT_GUIDS, settings->getUseElementGuids());
	itSettings.set(IfcGeom::IteratorSettings::USE_MATERIAL_NAMES, settings->getUseMaterialNames());
	itSettings.set(IfcGeom::IteratorSettings::CENTER_MODEL, settings->getCentreModels());
	itSettings.set(IfcGeom::IteratorSettings::GENERATE_UVS, settings->getGenerateUVs());
	itSettings.set(IfcGeom::IteratorSettings::APPLY_LAYERSETS, settings->getApplyLayerSets());

	return itSettings;
}

bool IFCUtilsGeometry::generateGeometry(std::string &errMsg)
{
	repoInfo << "Initialising Geometry....." << std::endl;

	auto itSettings = createSettings();

	IfcGeom::Iterator<double> contextIterator(itSettings, file);

	//auto filter = settings->getFilteringKeywords();
	//if (settings->getUseElementsFiltering() &&  filter.size())
	//{
	//	std::set<std::string> filterSet(filter.begin(), filter.end());

	//	if (settings->getIsExclusionFilter())
	//	{
	//		contextIterator.excludeEntities(filterSet);
	//	}
	//	else
	//	{
	//		contextIterator.includeEntities(filterSet);
	//	}
	//}
	//

	repoTrace << "Initialising Geom iterator";
	bool res = false;
	try{
		res = contextIterator.initialize();
	}
	catch (const std::exception &e)
	{
		repoError << "Failed to initialise Geom iterator: " << e.what();
	}

	if (res)
	{
		repoTrace << "Geom Iterator initialized";
	}
	else
	{
		errMsg = "Failed to initialised Geom Iterator";
		return false;
	}

	std::vector<std::vector<repo_face_t>> allFaces;
	std::vector<std::vector<double>> allVertices;
	std::vector<std::vector<double>> allNormals;
	std::vector<std::vector<double>> allUVs;
	std::vector<std::string> allIds, allNames, allMaterials;

	retrieveGeometryFromIterator(contextIterator, itSettings.get(IfcGeom::IteratorSettings::USE_MATERIAL_NAMES),
		allVertices, allFaces, allNormals, allUVs, allIds, allNames, allMaterials);

	//now we have found all meshes, take the minimum bounding box of the scene as offset
	//and create repo meshes
	repoTrace << "Finished iterating. number of meshes found: " << allVertices.size();
	repoTrace << "Finished iterating. number of materials found: " << materials.size();

	std::map<std::string, std::vector<repo::lib::RepoUUID>> materialParent;
	for (int i = 0; i < allVertices.size(); ++i)
	{
		std::vector<repo::lib::RepoVector3D> vertices, normals;
		std::vector<repo::lib::RepoVector2D> uvs;
		std::vector<repo_face_t> faces;
		std::vector<std::vector<float>> boundingBox;
		for (int j = 0; j < allVertices[i].size(); j += 3)
		{
			vertices.push_back({ (float)(allVertices[i][j] - offset[0]), (float)(allVertices[i][j + 1] - offset[1]), (float)(allVertices[i][j + 2] - offset[2]) });
			if (allNormals[i].size())
				normals.push_back({ (float)allNormals[i][j], (float)allNormals[i][j + 1], (float)allNormals[i][j + 2] });

			auto vertex = vertices.back();
			if (j == 0)
			{
				boundingBox.push_back({ vertex.x, vertex.y, vertex.z });
				boundingBox.push_back({ vertex.x, vertex.y, vertex.z });
			}
			else
			{
				boundingBox[0][0] = boundingBox[0][0] > vertex.x ? vertex.x : boundingBox[0][0];
				boundingBox[0][1] = boundingBox[0][1] > vertex.y ? vertex.y : boundingBox[0][1];
				boundingBox[0][2] = boundingBox[0][2] > vertex.z ? vertex.z : boundingBox[0][2];

				boundingBox[1][0] = boundingBox[1][0] < vertex.x ? vertex.x : boundingBox[1][0];
				boundingBox[1][1] = boundingBox[1][1] < vertex.y ? vertex.y : boundingBox[1][1];
				boundingBox[1][2] = boundingBox[1][2] < vertex.z ? vertex.z : boundingBox[1][2];
			}
		}

		for (int j = 0; j < allUVs[i].size(); j += 2)
		{
			uvs.push_back({ (float)allUVs[i][j], (float)allUVs[i][j + 1] });
		}

		std::vector < std::vector<repo::lib::RepoVector2D>> uvChannels;
		if (uvs.size())
			uvChannels.push_back(uvs);

		auto mesh = repo::core::model::RepoBSONFactory::makeMeshNode(vertices, allFaces[i], normals, boundingBox, uvChannels,
			std::vector<repo_color4d_t>(), std::vector<std::vector<float>>());

		if (meshes.find(allIds[i]) == meshes.end())
		{
			meshes[allIds[i]] = std::vector<repo::core::model::MeshNode*>();
		}
		meshes[allIds[i]].push_back(new repo::core::model::MeshNode(mesh));

		if (allMaterials[i] != "")
		{
			if (materialParent.find(allMaterials[i]) == materialParent.end())
			{
				materialParent[allMaterials[i]] = std::vector<repo::lib::RepoUUID>();
			}

			materialParent[allMaterials[i]].push_back(mesh.getSharedID());
		}
	}

	repoTrace << "Meshes constructed. Wiring materials to parents...";

	for (const auto &pair : materialParent)
	{
		auto matIt = materials.find(pair.first);
		if (matIt != materials.end())
		{
			*(matIt->second) = matIt->second->cloneAndAddParent(pair.second);
		}
	}

	return true;
}

void IFCUtilsGeometry::retrieveGeometryFromIterator(
	IfcGeom::Iterator<double> &contextIterator,
	const bool useMaterialNames,
	std::vector < std::vector<double>> &allVertices,
	std::vector<std::vector<repo_face_t>> &allFaces,
	std::vector < std::vector<double>> &allNormals,
	std::vector < std::vector<double>> &allUVs,
	std::vector<std::string> &allIds,
	std::vector<std::string> &allNames,
	std::vector<std::string> &allMaterials)
{
	repoTrace << "Iterating through Geom Iterator.";
	do
	{
		IfcGeom::Element<double> *ob = contextIterator.get();
		auto ob_geo = static_cast<const IfcGeom::TriangulationElement<double>*>(ob);
		if (ob_geo)
		{
			auto faces = ob_geo->geometry().faces();
			auto vertices = ob_geo->geometry().verts();
			auto normals = ob_geo->geometry().normals();
			auto uvs = ob_geo->geometry().uvs();
			std::unordered_map<int, std::unordered_map<int, int>>  indexMapping;
			std::unordered_map<int, int> vertexCount;
			std::unordered_map<int, std::vector<double>> post_vertices, post_normals, post_uvs;
			std::unordered_map<int, std::string> post_materials;
			std::unordered_map<int, std::vector<repo_face_t>> post_faces;

			auto matIndIt = ob_geo->geometry().material_ids().begin();

			for (int i = 0; i < vertices.size(); i += 3)
			{
				for (int j = 0; j < 3; ++j)
				{
					int index = j + i;
					if (offset.size() < j + 1)
					{
						offset.push_back(vertices[index]);
					}
					else
					{
						offset[j] = offset[j] > vertices[index] ? vertices[index] : offset[j];
					}
				}
			}

			for (int iface = 0; iface < faces.size(); iface += 3)
			{
				auto matInd = *matIndIt;
				if (indexMapping.find(matInd) == indexMapping.end())
				{
					//new material
					indexMapping[matInd] = std::unordered_map<int, int>();
					vertexCount[matInd] = 0;

					std::unordered_map<int, std::vector<double>> post_vertices, post_normals, post_uvs;
					std::unordered_map<int, std::vector<repo_face_t>> post_faces;

					post_vertices[matInd] = std::vector<double>();
					post_normals[matInd] = std::vector<double>();
					post_uvs[matInd] = std::vector<double>();
					post_faces[matInd] = std::vector<repo_face_t>();

					auto material = ob_geo->geometry().materials()[matInd];
					std::string matName = useMaterialNames ? material.original_name() : material.name();

					post_materials[matInd] = matName;
					if (materials.find(matName) == materials.end())
					{
						//new material, add it to the vector
						repo_material_t matProp = createMaterial(material);
						materials[matName] = new repo::core::model::MaterialNode(repo::core::model::RepoBSONFactory::makeMaterialNode(matProp, matName));
					}
				}

				repo_face_t face;
				for (int j = 0; j < 3; ++j)
				{
					auto vIndex = faces[iface + j];
					if (indexMapping[matInd].find(vIndex) == indexMapping[matInd].end())
					{
						//new index. create a mapping
						indexMapping[matInd][vIndex] = vertexCount[matInd]++;
						for (int ivert = 0; ivert < 3; ++ivert)
						{
							auto bufferInd = ivert + vIndex * 3;
							post_vertices[matInd].push_back(vertices[bufferInd]);

							if (normals.size())
								post_normals[matInd].push_back(normals[bufferInd]);

							if (uvs.size() && ivert < 2)
							{
								auto uvbufferInd = ivert + vIndex * 2;
								post_uvs[matInd].push_back(uvs[uvbufferInd]);
							}
						}
					}
					face.push_back(indexMapping[matInd][vIndex]);
				}

				post_faces[matInd].push_back(face);

				++matIndIt;
			}

			auto guid = ob_geo->guid();
			auto name = ob_geo->name();
			for (const auto& pair : post_faces)
			{
				auto index = pair.first;
				allVertices.push_back(post_vertices[index]);
				allNormals.push_back(post_normals[index]);
				allFaces.push_back(pair.second);
				allUVs.push_back(post_uvs[index]);

				allIds.push_back(guid);
				allNames.push_back(name);
				allMaterials.push_back(post_materials[index]);
			}
		}
		if (allIds.size() % 100 == 0)
			repoInfo << allIds.size() << " meshes created";
	} while (contextIterator.next());
}<|endoftext|>


<commit_before>
/**************************************************************************
 * Copyright(c) 1998-2010, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/////////////////////////////////////////////////////////////
//
// Base class for cuts on AOD reconstructed heavy-flavour decay
//
// Author: A.Dainese, andrea.dainese@pd.infn.it
/////////////////////////////////////////////////////////////
#include <Riostream.h>

#include "AliVEvent.h"
#include "AliESDEvent.h"
#include "AliAODEvent.h"
#include "AliVVertex.h"
#include "AliESDVertex.h"
#include "AliAODVertex.h"
#include "AliESDtrack.h"
#include "AliAODTrack.h"
#include "AliESDtrackCuts.h"
#include "AliAODRecoDecayHF.h"
#include "AliRDHFCuts.h"

ClassImp(AliRDHFCuts)

//--------------------------------------------------------------------------
AliRDHFCuts::AliRDHFCuts(const Char_t* name, const Char_t* title) :
AliAnalysisCuts(name,title),
fMinVtxType(3),
fMinVtxContr(1),
fMaxVtxRedChi2(1e6),
fMinSPDMultiplicity(0),
fTriggerMask(0),
fTrackCuts(0),
fnPtBins(1),
fnPtBinLimits(1),
fPtBinLimits(0),
fnVars(1),
fVarNames(0),
fnVarsForOpt(0),
fVarsForOpt(0),
fGlobalIndex(1),
fCutsRD(0),
fIsUpperCut(0)
{
  //
  // Default Constructor
  //
}
//--------------------------------------------------------------------------
AliRDHFCuts::AliRDHFCuts(const AliRDHFCuts &source) :
  AliAnalysisCuts(source),
  fMinVtxType(source.fMinVtxType),
  fMinVtxContr(source.fMinVtxContr),
  fMaxVtxRedChi2(source.fMaxVtxRedChi2),
  fMinSPDMultiplicity(source.fMinSPDMultiplicity),
  fTriggerMask(source.fTriggerMask),
  fTrackCuts(0),
  fnPtBins(source.fnPtBins),
  fnPtBinLimits(source.fnPtBinLimits),
  fPtBinLimits(0),
  fnVars(source.fnVars),
  fVarNames(0),
  fnVarsForOpt(source.fnVarsForOpt),
  fVarsForOpt(0),
  fGlobalIndex(source.fGlobalIndex),
  fCutsRD(0),
  fIsUpperCut(0)
{
  //
  // Copy constructor
  //
  cout<<"Copy constructor"<<endl;
  if(source.GetTrackCuts()) AddTrackCuts(source.GetTrackCuts());
  if(source.fPtBinLimits) SetPtBins(source.fnPtBinLimits,source.fPtBinLimits);
  if(source.fVarNames) SetVarNames(source.fnVars,source.fVarNames,source.fIsUpperCut);
  if(source.fCutsRD) SetCuts(source.fGlobalIndex,source.fCutsRD);
  if(source.fVarsForOpt) SetVarsForOpt(source.fnVarsForOpt,source.fVarsForOpt);
  PrintAll();

}
//--------------------------------------------------------------------------
AliRDHFCuts &AliRDHFCuts::operator=(const AliRDHFCuts &source)
{
  //
  // assignment operator
  //
  if(&source == this) return *this;

  AliAnalysisCuts::operator=(source);

  fMinVtxType=source.fMinVtxType;
  fMinVtxContr=source.fMinVtxContr;
  fMaxVtxRedChi2=source.fMaxVtxRedChi2;
  fMinSPDMultiplicity=source.fMinSPDMultiplicity;
  fTriggerMask=source.fTriggerMask;
  fnPtBins=source.fnPtBins;
  fnVars=source.fnVars;
  fGlobalIndex=source.fGlobalIndex;
  fnVarsForOpt=source.fnVarsForOpt;

  if(source.fPtBinLimits) SetPtBins(source.fnPtBinLimits,source.fPtBinLimits);
  if(source.fVarNames) SetVarNames(source.fnVars,source.fVarNames,source.fIsUpperCut);
  if(source.fCutsRD) SetCuts(source.fGlobalIndex,source.fCutsRD);
  if(source.fVarsForOpt) SetVarsForOpt(source.fnVarsForOpt,source.fVarsForOpt);
  PrintAll();

  return *this;
}
//--------------------------------------------------------------------------
AliRDHFCuts::~AliRDHFCuts() {
  //
  // Default Destructor
  //
  if(fPtBinLimits) {delete [] fPtBinLimits; fPtBinLimits=0;}
  if(fVarNames) {delete [] fVarNames; fVarNames=0;}
  if(fVarsForOpt) {delete [] fVarsForOpt; fVarsForOpt=0;}
  if(fCutsRD) {
    delete [] fCutsRD;
    fCutsRD=0;
  }
  if(fIsUpperCut) {delete [] fIsUpperCut; fIsUpperCut=0;}

}
//---------------------------------------------------------------------------
Bool_t AliRDHFCuts::IsEventSelected(AliVEvent *event) const {
  //
  // Event selection
  //
  //if(fTriggerMask && event->GetTriggerMask()!=fTriggerMask) return kFALSE;

  // multiplicity cuts no implemented yet

  const AliVVertex *vertex = event->GetPrimaryVertex();

  if(!vertex) return kFALSE;

  TString title=vertex->GetTitle();
  if(title.Contains("Z") && fMinVtxType>1) return kFALSE;
  if(title.Contains("3D") && fMinVtxType>2) return kFALSE;

  if(vertex->GetNContributors()<fMinVtxContr) return kFALSE;

  return kTRUE;
}
//---------------------------------------------------------------------------
Bool_t AliRDHFCuts::AreDaughtersSelected(AliAODRecoDecayHF *d) const {
  //
  // Daughter tracks selection
  //
  if(!fTrackCuts) return kTRUE;

  Int_t ndaughters = d->GetNDaughters();
  AliESDtrack* esdTrack=0;
  AliAODVertex *vAOD = d->GetPrimaryVtx();
  Double_t pos[3],cov[6];
  vAOD->GetXYZ(pos);
  vAOD->GetCovarianceMatrix(cov);
  const AliESDVertex *vESD = new AliESDVertex(pos,cov,100.,100);

  Bool_t retval=kTRUE;

  for(Int_t idg=0; idg<ndaughters; idg++) {
    AliAODTrack *dgTrack = (AliAODTrack*)d->GetDaughter(idg);
    if(!dgTrack) retval = kFALSE;
    //printf("charge %d\n",dgTrack->Charge());
    if(dgTrack->Charge()==0) continue; // it's not a track, but a V0
    // convert to ESD track here
    esdTrack=new AliESDtrack(dgTrack);
    // needed to calculate the impact parameters
    esdTrack->RelateToVertex(vESD,0.,3.);
    if(!fTrackCuts->IsSelected(esdTrack)) retval = kFALSE;
    delete esdTrack; esdTrack=0;
  }

  delete vESD; vESD=0;

  return retval;
}
//---------------------------------------------------------------------------
void AliRDHFCuts::SetPtBins(Int_t nPtBinLimits,Float_t *ptBinLimits) {
  // Set the pt bins

  if(fPtBinLimits) {
    delete [] fPtBinLimits;
    fPtBinLimits = NULL;
    printf("Changing the pt bins\n");
  }

  if(nPtBinLimits != fnPtBins+1){
    cout<<"Warning: ptBinLimits dimention "<<nPtBinLimits<<" != nPtBins+1 ("<<fnPtBins+1<<")\nSetting nPtBins to "<<nPtBinLimits-1<<endl;
    SetNPtBins(nPtBinLimits-1);
  }

  fnPtBinLimits = nPtBinLimits;
  SetGlobalIndex();
  cout<<"Changing also Global Index -> "<<fGlobalIndex<<endl;
  fPtBinLimits = new Float_t[fnPtBinLimits];
  for(Int_t ib=0; ib<nPtBinLimits; ib++) fPtBinLimits[ib]=ptBinLimits[ib];

  return;
}
//---------------------------------------------------------------------------
void AliRDHFCuts::SetVarNames(Int_t nVars,TString *varNames,Bool_t *isUpperCut){
  // Set the variable names

  if(fVarNames) {
    delete [] fVarNames;
    fVarNames = NULL;
    printf("Changing the variable names\n");
  }
  if(nVars!=fnVars){
    printf("Wrong number of variables: it has to be %d\n",fnVars);
    return;
  }
  //fnVars=nVars;
  fVarNames = new TString[nVars];
  fIsUpperCut = new Bool_t[nVars];
  for(Int_t iv=0; iv<nVars; iv++) {
    fVarNames[iv] = varNames[iv];
    fIsUpperCut[iv] = isUpperCut[iv];
  }

  return;
}
//---------------------------------------------------------------------------
void AliRDHFCuts::SetVarsForOpt(Int_t nVars,Bool_t *forOpt) {
  // Set the variables to be used for cuts optimization

  if(fVarsForOpt) {
    delete [] fVarsForOpt;
    fVarsForOpt = NULL;
    printf("Changing the variables for cut optimization\n");
  }

  if(nVars==0){//!=fnVars) {
    printf("%d not accepted as number of variables: it has to be %d\n",nVars,fnVars);
    return;
  }

  fnVarsForOpt = 0;
  fVarsForOpt = new Bool_t[fnVars];
  for(Int_t iv=0; iv<fnVars; iv++) {
    fVarsForOpt[iv]=forOpt[iv];
    if(fVarsForOpt[iv]) fnVarsForOpt++;
  }

  return;
}
//---------------------------------------------------------------------------
void AliRDHFCuts::SetCuts(Int_t nVars,Int_t nPtBins,Float_t **cutsRD) {
  //
  // store the cuts
  //
  if(nVars!=fnVars) {
    printf("Wrong number of variables: it has to be %d\n",fnVars);
    return;
  }
  if(nPtBins!=fnPtBins) {
    printf("Wrong number of pt bins: it has to be %d\n",fnPtBins);
    return;
  }

  if(!fCutsRD)  fCutsRD = new Float_t[fGlobalIndex];

  for(Int_t iv=0; iv<fnVars; iv++) {

    for(Int_t ib=0; ib<fnPtBins; ib++) {

      //check
      if(GetGlobalIndex(iv,ib)>=fGlobalIndex) {
	cout<<"Overflow, exit..."<<endl;
	return;
      }

      fCutsRD[GetGlobalIndex(iv,ib)] = cutsRD[iv][ib];

    }
  }
  return;
}
//---------------------------------------------------------------------------
void AliRDHFCuts::SetCuts(Int_t glIndex,Float_t* cutsRDGlob){
  //
  // store the cuts
  //
  if(glIndex != fGlobalIndex){
    cout<<"Wrong array size: it has to be "<<fGlobalIndex<<endl;
    return;
  }
  if(!fCutsRD)  fCutsRD = new Float_t[fGlobalIndex];

  for(Int_t iGl=0;iGl<fGlobalIndex;iGl++){
    fCutsRD[iGl] = cutsRDGlob[iGl];
  }
  return;
}
//---------------------------------------------------------------------------
void AliRDHFCuts::PrintAll() const {
  //
  // print all cuts values
  //
  if(fVarNames){
    cout<<"Array of variables"<<endl;
    for(Int_t iv=0;iv<fnVars;iv++){
      cout<<fVarNames[iv]<<"\t";
    }
    cout<<endl;
  }
  if(fVarsForOpt){
    cout<<"Array of optimization"<<endl;
    for(Int_t iv=0;iv<fnVars;iv++){
      cout<<fVarsForOpt[iv]<<"\t";
    }
    cout<<endl;
  }
  if(fIsUpperCut){
    cout<<"Array of upper/lower cut"<<endl;
   for(Int_t iv=0;iv<fnVars;iv++){
     cout<<fIsUpperCut[iv]<<"\t";
   }
   cout<<endl;
  }
  if(fPtBinLimits){
    cout<<"Array of ptbin limits"<<endl;
    for(Int_t ib=0;ib<fnPtBinLimits;ib++){
      cout<<fPtBinLimits[ib]<<"\t";
    }
    cout<<endl;
  }
  if(fCutsRD){
    cout<<"Matrix of cuts"<<endl;
   for(Int_t iv=0;iv<fnVars;iv++){
     for(Int_t ib=0;ib<fnPtBins;ib++){
       cout<<"fCutsRD["<<iv<<"]["<<ib<<"] = "<<fCutsRD[GetGlobalIndex(iv,ib)]<<"\t";
     }
     cout<<endl;
   }
   cout<<endl;
  }
  return;
}
//---------------------------------------------------------------------------
void AliRDHFCuts::GetCuts(Float_t**& cutsRD) const{
  //
  // get the cuts
  //

  //cout<<"Give back a "<<fnVars<<"x"<<fnPtBins<<" matrix."<<endl;

  Int_t iv,ib;
  if(!cutsRD) {
    //cout<<"Initialization..."<<endl;
    cutsRD=new Float_t*[fnVars];
    for(iv=0; iv<fnVars; iv++) {
      cutsRD[iv] = new Float_t[fnPtBins];
    }
  }

  for(Int_t iGlobal=0; iGlobal<fGlobalIndex; iGlobal++) {
    GetVarPtIndex(iGlobal,iv,ib);
    cutsRD[iv][ib] = fCutsRD[iGlobal];
  }

  return;
}

//---------------------------------------------------------------------------
Int_t AliRDHFCuts::GetGlobalIndex(Int_t iVar,Int_t iPtBin) const{
  //
  // give the global index from variable and pt bin
  //
  return iPtBin*fnVars+iVar;
}

//---------------------------------------------------------------------------
void AliRDHFCuts::GetVarPtIndex(Int_t iGlob, Int_t& iVar, Int_t& iPtBin) const {
  //
  //give the index of the variable and of the pt bin from the global index
  //
  iPtBin=(Int_t)iGlob/fnVars;
  iVar=iGlob%fnVars;

  return;
}

//---------------------------------------------------------------------------
Int_t AliRDHFCuts::PtBin(Double_t pt) const {
  //
  //give the pt bin where the pt lies.
  //
  Int_t ptbin=0;
  for (Int_t i=0;i<fnPtBins;i++){
    if(pt<fPtBinLimits[i+1]) {
      ptbin=i;
      break;
    }
  }
  return ptbin;
}
<commit_msg>Fix in operator=<commit_after>
/**************************************************************************
 * Copyright(c) 1998-2010, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/////////////////////////////////////////////////////////////
//
// Base class for cuts on AOD reconstructed heavy-flavour decay
//
// Author: A.Dainese, andrea.dainese@pd.infn.it
/////////////////////////////////////////////////////////////
#include <Riostream.h>

#include "AliVEvent.h"
#include "AliESDEvent.h"
#include "AliAODEvent.h"
#include "AliVVertex.h"
#include "AliESDVertex.h"
#include "AliAODVertex.h"
#include "AliESDtrack.h"
#include "AliAODTrack.h"
#include "AliESDtrackCuts.h"
#include "AliAODRecoDecayHF.h"
#include "AliRDHFCuts.h"

ClassImp(AliRDHFCuts)

//--------------------------------------------------------------------------
AliRDHFCuts::AliRDHFCuts(const Char_t* name, const Char_t* title) :
AliAnalysisCuts(name,title),
fMinVtxType(3),
fMinVtxContr(1),
fMaxVtxRedChi2(1e6),
fMinSPDMultiplicity(0),
fTriggerMask(0),
fTrackCuts(0),
fnPtBins(1),
fnPtBinLimits(1),
fPtBinLimits(0),
fnVars(1),
fVarNames(0),
fnVarsForOpt(0),
fVarsForOpt(0),
fGlobalIndex(1),
fCutsRD(0),
fIsUpperCut(0)
{
  //
  // Default Constructor
  //
}
//--------------------------------------------------------------------------
AliRDHFCuts::AliRDHFCuts(const AliRDHFCuts &source) :
  AliAnalysisCuts(source),
  fMinVtxType(source.fMinVtxType),
  fMinVtxContr(source.fMinVtxContr),
  fMaxVtxRedChi2(source.fMaxVtxRedChi2),
  fMinSPDMultiplicity(source.fMinSPDMultiplicity),
  fTriggerMask(source.fTriggerMask),
  fTrackCuts(0),
  fnPtBins(source.fnPtBins),
  fnPtBinLimits(source.fnPtBinLimits),
  fPtBinLimits(0),
  fnVars(source.fnVars),
  fVarNames(0),
  fnVarsForOpt(source.fnVarsForOpt),
  fVarsForOpt(0),
  fGlobalIndex(source.fGlobalIndex),
  fCutsRD(0),
  fIsUpperCut(0)
{
  //
  // Copy constructor
  //
  cout<<"Copy constructor"<<endl;
  if(source.GetTrackCuts()) AddTrackCuts(source.GetTrackCuts());
  if(source.fPtBinLimits) SetPtBins(source.fnPtBinLimits,source.fPtBinLimits);
  if(source.fVarNames) SetVarNames(source.fnVars,source.fVarNames,source.fIsUpperCut);
  if(source.fCutsRD) SetCuts(source.fGlobalIndex,source.fCutsRD);
  if(source.fVarsForOpt) SetVarsForOpt(source.fnVarsForOpt,source.fVarsForOpt);
  PrintAll();

}
//--------------------------------------------------------------------------
AliRDHFCuts &AliRDHFCuts::operator=(const AliRDHFCuts &source)
{
  //
  // assignment operator
  //
  if(&source == this) return *this;

  AliAnalysisCuts::operator=(source);

  fMinVtxType=source.fMinVtxType;
  fMinVtxContr=source.fMinVtxContr;
  fMaxVtxRedChi2=source.fMaxVtxRedChi2;
  fMinSPDMultiplicity=source.fMinSPDMultiplicity;
  fTriggerMask=source.fTriggerMask;
  fnPtBins=source.fnPtBins;
  fnVars=source.fnVars;
  fGlobalIndex=source.fGlobalIndex;
  fnVarsForOpt=source.fnVarsForOpt;

  if(source.GetTrackCuts()) AddTrackCuts(source.GetTrackCuts());
  if(source.fPtBinLimits) SetPtBins(source.fnPtBinLimits,source.fPtBinLimits);
  if(source.fVarNames) SetVarNames(source.fnVars,source.fVarNames,source.fIsUpperCut);
  if(source.fCutsRD) SetCuts(source.fGlobalIndex,source.fCutsRD);
  if(source.fVarsForOpt) SetVarsForOpt(source.fnVarsForOpt,source.fVarsForOpt);
  PrintAll();

  return *this;
}
//--------------------------------------------------------------------------
AliRDHFCuts::~AliRDHFCuts() {
  //
  // Default Destructor
  //
  if(fPtBinLimits) {delete [] fPtBinLimits; fPtBinLimits=0;}
  if(fVarNames) {delete [] fVarNames; fVarNames=0;}
  if(fVarsForOpt) {delete [] fVarsForOpt; fVarsForOpt=0;}
  if(fCutsRD) {
    delete [] fCutsRD;
    fCutsRD=0;
  }
  if(fIsUpperCut) {delete [] fIsUpperCut; fIsUpperCut=0;}

}
//---------------------------------------------------------------------------
Bool_t AliRDHFCuts::IsEventSelected(AliVEvent *event) const {
  //
  // Event selection
  //
  //if(fTriggerMask && event->GetTriggerMask()!=fTriggerMask) return kFALSE;

  // multiplicity cuts no implemented yet

  const AliVVertex *vertex = event->GetPrimaryVertex();

  if(!vertex) return kFALSE;

  TString title=vertex->GetTitle();
  if(title.Contains("Z") && fMinVtxType>1) return kFALSE;
  if(title.Contains("3D") && fMinVtxType>2) return kFALSE;

  if(vertex->GetNContributors()<fMinVtxContr) return kFALSE;

  return kTRUE;
}
//---------------------------------------------------------------------------
Bool_t AliRDHFCuts::AreDaughtersSelected(AliAODRecoDecayHF *d) const {
  //
  // Daughter tracks selection
  //
  if(!fTrackCuts) return kTRUE;

  Int_t ndaughters = d->GetNDaughters();
  AliESDtrack* esdTrack=0;
  AliAODVertex *vAOD = d->GetPrimaryVtx();
  Double_t pos[3],cov[6];
  vAOD->GetXYZ(pos);
  vAOD->GetCovarianceMatrix(cov);
  const AliESDVertex *vESD = new AliESDVertex(pos,cov,100.,100);

  Bool_t retval=kTRUE;

  for(Int_t idg=0; idg<ndaughters; idg++) {
    AliAODTrack *dgTrack = (AliAODTrack*)d->GetDaughter(idg);
    if(!dgTrack) retval = kFALSE;
    //printf("charge %d\n",dgTrack->Charge());
    if(dgTrack->Charge()==0) continue; // it's not a track, but a V0
    // convert to ESD track here
    esdTrack=new AliESDtrack(dgTrack);
    // needed to calculate the impact parameters
    esdTrack->RelateToVertex(vESD,0.,3.);
    if(!fTrackCuts->IsSelected(esdTrack)) retval = kFALSE;
    delete esdTrack; esdTrack=0;
  }

  delete vESD; vESD=0;

  return retval;
}
//---------------------------------------------------------------------------
void AliRDHFCuts::SetPtBins(Int_t nPtBinLimits,Float_t *ptBinLimits) {
  // Set the pt bins

  if(fPtBinLimits) {
    delete [] fPtBinLimits;
    fPtBinLimits = NULL;
    printf("Changing the pt bins\n");
  }

  if(nPtBinLimits != fnPtBins+1){
    cout<<"Warning: ptBinLimits dimention "<<nPtBinLimits<<" != nPtBins+1 ("<<fnPtBins+1<<")\nSetting nPtBins to "<<nPtBinLimits-1<<endl;
    SetNPtBins(nPtBinLimits-1);
  }

  fnPtBinLimits = nPtBinLimits;
  SetGlobalIndex();
  cout<<"Changing also Global Index -> "<<fGlobalIndex<<endl;
  fPtBinLimits = new Float_t[fnPtBinLimits];
  for(Int_t ib=0; ib<nPtBinLimits; ib++) fPtBinLimits[ib]=ptBinLimits[ib];

  return;
}
//---------------------------------------------------------------------------
void AliRDHFCuts::SetVarNames(Int_t nVars,TString *varNames,Bool_t *isUpperCut){
  // Set the variable names

  if(fVarNames) {
    delete [] fVarNames;
    fVarNames = NULL;
    printf("Changing the variable names\n");
  }
  if(nVars!=fnVars){
    printf("Wrong number of variables: it has to be %d\n",fnVars);
    return;
  }
  //fnVars=nVars;
  fVarNames = new TString[nVars];
  fIsUpperCut = new Bool_t[nVars];
  for(Int_t iv=0; iv<nVars; iv++) {
    fVarNames[iv] = varNames[iv];
    fIsUpperCut[iv] = isUpperCut[iv];
  }

  return;
}
//---------------------------------------------------------------------------
void AliRDHFCuts::SetVarsForOpt(Int_t nVars,Bool_t *forOpt) {
  // Set the variables to be used for cuts optimization

  if(fVarsForOpt) {
    delete [] fVarsForOpt;
    fVarsForOpt = NULL;
    printf("Changing the variables for cut optimization\n");
  }

  if(nVars==0){//!=fnVars) {
    printf("%d not accepted as number of variables: it has to be %d\n",nVars,fnVars);
    return;
  }

  fnVarsForOpt = 0;
  fVarsForOpt = new Bool_t[fnVars];
  for(Int_t iv=0; iv<fnVars; iv++) {
    fVarsForOpt[iv]=forOpt[iv];
    if(fVarsForOpt[iv]) fnVarsForOpt++;
  }

  return;
}
//---------------------------------------------------------------------------
void AliRDHFCuts::SetCuts(Int_t nVars,Int_t nPtBins,Float_t **cutsRD) {
  //
  // store the cuts
  //
  if(nVars!=fnVars) {
    printf("Wrong number of variables: it has to be %d\n",fnVars);
    return;
  }
  if(nPtBins!=fnPtBins) {
    printf("Wrong number of pt bins: it has to be %d\n",fnPtBins);
    return;
  }

  if(!fCutsRD)  fCutsRD = new Float_t[fGlobalIndex];

  for(Int_t iv=0; iv<fnVars; iv++) {

    for(Int_t ib=0; ib<fnPtBins; ib++) {

      //check
      if(GetGlobalIndex(iv,ib)>=fGlobalIndex) {
	cout<<"Overflow, exit..."<<endl;
	return;
      }

      fCutsRD[GetGlobalIndex(iv,ib)] = cutsRD[iv][ib];

    }
  }
  return;
}
//---------------------------------------------------------------------------
void AliRDHFCuts::SetCuts(Int_t glIndex,Float_t* cutsRDGlob){
  //
  // store the cuts
  //
  if(glIndex != fGlobalIndex){
    cout<<"Wrong array size: it has to be "<<fGlobalIndex<<endl;
    return;
  }
  if(!fCutsRD)  fCutsRD = new Float_t[fGlobalIndex];

  for(Int_t iGl=0;iGl<fGlobalIndex;iGl++){
    fCutsRD[iGl] = cutsRDGlob[iGl];
  }
  return;
}
//---------------------------------------------------------------------------
void AliRDHFCuts::PrintAll() const {
  //
  // print all cuts values
  //
  if(fVarNames){
    cout<<"Array of variables"<<endl;
    for(Int_t iv=0;iv<fnVars;iv++){
      cout<<fVarNames[iv]<<"\t";
    }
    cout<<endl;
  }
  if(fVarsForOpt){
    cout<<"Array of optimization"<<endl;
    for(Int_t iv=0;iv<fnVars;iv++){
      cout<<fVarsForOpt[iv]<<"\t";
    }
    cout<<endl;
  }
  if(fIsUpperCut){
    cout<<"Array of upper/lower cut"<<endl;
   for(Int_t iv=0;iv<fnVars;iv++){
     cout<<fIsUpperCut[iv]<<"\t";
   }
   cout<<endl;
  }
  if(fPtBinLimits){
    cout<<"Array of ptbin limits"<<endl;
    for(Int_t ib=0;ib<fnPtBinLimits;ib++){
      cout<<fPtBinLimits[ib]<<"\t";
    }
    cout<<endl;
  }
  if(fCutsRD){
    cout<<"Matrix of cuts"<<endl;
   for(Int_t iv=0;iv<fnVars;iv++){
     for(Int_t ib=0;ib<fnPtBins;ib++){
       cout<<"fCutsRD["<<iv<<"]["<<ib<<"] = "<<fCutsRD[GetGlobalIndex(iv,ib)]<<"\t";
     }
     cout<<endl;
   }
   cout<<endl;
  }
  return;
}
//---------------------------------------------------------------------------
void AliRDHFCuts::GetCuts(Float_t**& cutsRD) const{
  //
  // get the cuts
  //

  //cout<<"Give back a "<<fnVars<<"x"<<fnPtBins<<" matrix."<<endl;

  Int_t iv,ib;
  if(!cutsRD) {
    //cout<<"Initialization..."<<endl;
    cutsRD=new Float_t*[fnVars];
    for(iv=0; iv<fnVars; iv++) {
      cutsRD[iv] = new Float_t[fnPtBins];
    }
  }

  for(Int_t iGlobal=0; iGlobal<fGlobalIndex; iGlobal++) {
    GetVarPtIndex(iGlobal,iv,ib);
    cutsRD[iv][ib] = fCutsRD[iGlobal];
  }

  return;
}

//---------------------------------------------------------------------------
Int_t AliRDHFCuts::GetGlobalIndex(Int_t iVar,Int_t iPtBin) const{
  //
  // give the global index from variable and pt bin
  //
  return iPtBin*fnVars+iVar;
}

//---------------------------------------------------------------------------
void AliRDHFCuts::GetVarPtIndex(Int_t iGlob, Int_t& iVar, Int_t& iPtBin) const {
  //
  //give the index of the variable and of the pt bin from the global index
  //
  iPtBin=(Int_t)iGlob/fnVars;
  iVar=iGlob%fnVars;

  return;
}

//---------------------------------------------------------------------------
Int_t AliRDHFCuts::PtBin(Double_t pt) const {
  //
  //give the pt bin where the pt lies.
  //
  Int_t ptbin=0;
  for (Int_t i=0;i<fnPtBins;i++){
    if(pt<fPtBinLimits[i+1]) {
      ptbin=i;
      break;
    }
  }
  return ptbin;
}
<|endoftext|>


<commit_before>

#include "stdafx.h"
#include "GStreamerCore.h"

#include "UnityHelpers.h"
#include <IThreadManager.h>

#include <gst/app/gstappsink.h>
#include <gst/video/video.h>

#include <glib-object.h>
#include <glib.h>
#include <algorithm>

#if false
#include "CMySrc.h"
#include "CMySink.h"
#endif

#ifdef USE_UNITY_NETWORK
#include "CMyUDPSrc.h"
#include "CMyUDPSink.h"
#include "CMyListener.h"
#endif

#ifdef __ANDROID__

void
gst_android_register_static_plugins(void);
/* Call this function to load GIO modules */
void
gst_android_load_gio_modules(void);
#endif

namespace mray
{
namespace video
{

GStreamerCore* GStreamerCore::m_instance=0;
uint GStreamerCore::m_refCount = 0;

static gboolean appsink_plugin_init(GstPlugin * plugin)
{
	gst_element_register(plugin, "appsink", GST_RANK_NONE, GST_TYPE_APP_SINK);

	return TRUE;
}

class GstMainLoopThread : public OS::IThreadFunction{
public:
	GMainLoop *main_loop;
	GstMainLoopThread()
		:main_loop(NULL)
	{

	}

	void setup(){
		//			startThread();
	}
	void execute(OS::IThread*caller, void*arg){
		main_loop = g_main_loop_new(NULL, FALSE);
		g_main_loop_run(main_loop);
		LogMessage("GST Thread shutdown",ELL_INFO);
	}
};

GStreamerCore::GStreamerCore()
{
	gub_main_loop_thread = 0;
	gub_main_loop = 0;
	_Init();
}

GStreamerCore::~GStreamerCore()
{
	_StopLoop();
	gst_deinit();
}

void g_logFunction(const gchar   *log_domain,
	GLogLevelFlags log_level,
	const gchar   *message,
	gpointer       user_data)
{
    if(log_level==G_LOG_LEVEL_INFO || log_level==G_LOG_LEVEL_DEBUG)
        LogMessage(message, ELL_INFO);
    else if(log_level==G_LOG_LEVEL_WARNING)
        LogMessage(message, ELL_WARNING);
    else if(log_level==G_LOG_LEVEL_CRITICAL || log_level==G_LOG_FLAG_FATAL)
        LogMessage(message, ELL_ERROR);
    else
        LogMessage(message, ELL_INFO);
}

gpointer gst_main_loop_func(gpointer data)
{
	GStreamerCore* core = (GStreamerCore*)data;
	core->_loopFunction();

	return NULL;
}

void GStreamerCore::_Init()
{

	GError *err = 0;
	_gst_debug_enabled = false;
	if (!gst_init_check(0,0, &err))
	{
		LogManager::Instance()->LogMessage("GStreamerCore - Failed to init GStreamer!");
	}
	else
    {
        g_log_set_handler(0,  G_LOG_LEVEL_WARNING, g_logFunction, 0);
        g_log_set_handler(0,  G_LOG_LEVEL_MESSAGE, g_logFunction, 0);
        g_log_set_handler(0,  G_LOG_LEVEL_INFO, g_logFunction, 0);
        g_log_set_handler(0,  G_LOG_LEVEL_DEBUG, g_logFunction, 0);
        g_log_set_handler(0,  G_LOG_LEVEL_CRITICAL, g_logFunction, 0);
		g_log_set_handler(0, G_LOG_FLAG_FATAL , g_logFunction, 0);
		g_log_set_default_handler(g_logFunction, 0);

#if defined (__ANDROID__)
		//gst_android_register_static_plugins();
		//gst_android_load_gio_modules();
#endif

        LogManager::Instance()->LogMessage("GStreamerCore - Registering Elements!");
		//fclose(stderr);

		//register plugin path

		//std::string gst_path = g_getenv("GSTREAMER_1_0_ROOT_X86_64");
		//putenv(("GST_PLUGIN_PATH_1_0=" + gst_path + "lib\\gstreamer-1.0" + ";.").c_str());
        //add our custom src/sink elements
#ifdef USE_UNITY_NETWORK
		gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
			"appsink", (char*)"Element application sink",
			appsink_plugin_init, "0.1", "LGPL", "ofVideoPlayer", "openFrameworks",
                                   "http://openframeworks.cc/");
	/*	gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
			"mysrc", (char*)"Element application src",
			_GstMySrcClass::plugin_init, "0.1", "LGPL", "GstVideoProvider", "mray",
			"");
		gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
			"mysink", (char*)"Element application sink",
			_GstMySinkClass::plugin_init, "0.1", "LGPL", "GstVideoProvider", "mray",
                                   "");*/
		gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
			"myudpsrc", (char*)"Element udp src",
			_GstMyUDPSrcClass::plugin_init, "0.1", "LGPL", "GstVideoProvider", "mray",
			"");
		gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
			"myudpsink", (char*)"Element udp sink",
			_GstMyUDPSinkClass::plugin_init, "0.1", "LGPL", "GstVideoProvider", "mray",
			"");

		gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
			"mylistener", (char*)"Custom listener element",
			_GstMyListenerClass::plugin_init, "0.1", "LGPL", "GstVideoProvider", "mray",
			"");
#endif
		LogManager::Instance()->LogMessage("GStreamerCore - GStreamer inited");
	}

#if GLIB_MINOR_VERSION<32
	if (!g_thread_supported()){
		g_thread_init(NULL);
	}
#endif

	gub_main_loop_thread = g_thread_new("GstUnityBridge Main Thread", gst_main_loop_func, this);
	if (!gub_main_loop_thread) {
		LogManager::Instance()->LogMessage(std::string("Failed to create GLib main thread: ") + std::string(err ? err->message : "<No error message>"));
		return;
	}

	_StartLoop();
}

void GStreamerCore::_loopFunction() {
	LogManager::Instance()->LogMessage("Entering main loop");
	gub_main_loop = g_main_loop_new(NULL, FALSE);
	g_main_loop_run(gub_main_loop);
	LogManager::Instance()->LogMessage("Quitting main loop");
}

void GStreamerCore::_StartLoop()
{
	/*m_threadFunc = new GstMainLoopThread();
	m_mainLoopThread = OS::IThreadManager::getInstance().createThread(m_threadFunc);
	m_mainLoopThread->start(0);*/
}

void GStreamerCore::_StopLoop()
{
	/*
	if (!m_threadFunc)
		return;
	GstMainLoopThread* mainLoop = (GstMainLoopThread*)m_threadFunc;
	g_main_loop_quit(mainLoop->main_loop);
	bool running = g_main_loop_is_running(mainLoop->main_loop);
	g_main_loop_unref(mainLoop->main_loop);
	delete m_threadFunc;
	OS::IThreadManager::getInstance().killThread(m_mainLoopThread);
	delete m_mainLoopThread;
	m_threadFunc = 0;
	m_mainLoopThread = 0;
	*/

	if (!gub_main_loop) {
		return;
	}
	g_main_loop_quit(gub_main_loop);
	gub_main_loop = NULL;
	g_thread_join(gub_main_loop_thread);
	gub_main_loop_thread = NULL;
}

void GStreamerCore::Ref()
{
	m_refCount++;
	if (m_refCount==1)
	{
		LogManager::Instance()->LogMessage("Initializing GStreamer");
		m_instance = new GStreamerCore();
		LogManager::Instance()->LogMessage("Initializing GStreamer - Done");
	}

}

void GStreamerCore::Unref()
{
	if (m_refCount == 0)
	{
		LogMessage("GStreamerCore::Unref() - unreferencing GStreamer with no reference! ", ELL_ERROR);
		return;
	}
	//m_refCount--;
	if (m_refCount == 0)
	{
		delete m_instance;
		m_instance = 0;
	}
}

GStreamerCore* GStreamerCore::Instance()
{
	return m_instance;
}

}
}

<commit_msg>Fix errors during GStreamer init not being logged<commit_after>

#include "stdafx.h"
#include "GStreamerCore.h"

#include "UnityHelpers.h"
#include <IThreadManager.h>

#include <gst/app/gstappsink.h>
#include <gst/video/video.h>

#include <glib-object.h>
#include <glib.h>
#include <algorithm>

#if false
#include "CMySrc.h"
#include "CMySink.h"
#endif

#ifdef USE_UNITY_NETWORK
#include "CMyUDPSrc.h"
#include "CMyUDPSink.h"
#include "CMyListener.h"
#endif

#ifdef __ANDROID__

void
gst_android_register_static_plugins(void);
/* Call this function to load GIO modules */
void
gst_android_load_gio_modules(void);
#endif

namespace mray
{
namespace video
{

GStreamerCore* GStreamerCore::m_instance=0;
uint GStreamerCore::m_refCount = 0;

static gboolean appsink_plugin_init(GstPlugin * plugin)
{
	gst_element_register(plugin, "appsink", GST_RANK_NONE, GST_TYPE_APP_SINK);

	return TRUE;
}

class GstMainLoopThread : public OS::IThreadFunction{
public:
	GMainLoop *main_loop;
	GstMainLoopThread()
		:main_loop(NULL)
	{

	}

	void setup(){
		//			startThread();
	}
	void execute(OS::IThread*caller, void*arg){
		main_loop = g_main_loop_new(NULL, FALSE);
		g_main_loop_run(main_loop);
		LogMessage("GST Thread shutdown",ELL_INFO);
	}
};

GStreamerCore::GStreamerCore()
{
	gub_main_loop_thread = 0;
	gub_main_loop = 0;
	_Init();
}

GStreamerCore::~GStreamerCore()
{
	_StopLoop();
	gst_deinit();
}

void g_logFunction(const gchar   *log_domain,
	GLogLevelFlags log_level,
	const gchar   *message,
	gpointer       user_data)
{
    if(log_level==G_LOG_LEVEL_INFO || log_level==G_LOG_LEVEL_DEBUG)
        LogMessage(message, ELL_INFO);
    else if(log_level==G_LOG_LEVEL_WARNING)
        LogMessage(message, ELL_WARNING);
    else if(log_level==G_LOG_LEVEL_CRITICAL || log_level==G_LOG_FLAG_FATAL)
        LogMessage(message, ELL_ERROR);
    else
        LogMessage(message, ELL_INFO);
}

gpointer gst_main_loop_func(gpointer data)
{
	GStreamerCore* core = (GStreamerCore*)data;
	core->_loopFunction();

	return NULL;
}

void GStreamerCore::_Init()
{
	g_log_set_handler(0,  G_LOG_LEVEL_WARNING, g_logFunction, 0);
	g_log_set_handler(0,  G_LOG_LEVEL_MESSAGE, g_logFunction, 0);
	g_log_set_handler(0,  G_LOG_LEVEL_INFO, g_logFunction, 0);
	g_log_set_handler(0,  G_LOG_LEVEL_DEBUG, g_logFunction, 0);
	g_log_set_handler(0,  G_LOG_LEVEL_CRITICAL, g_logFunction, 0);
	g_log_set_handler(0, G_LOG_FLAG_FATAL , g_logFunction, 0);
	g_log_set_default_handler(g_logFunction, 0);

	GError *err = 0;
	_gst_debug_enabled = false;
	if (!gst_init_check(0,0, &err))
	{
		LogManager::Instance()->LogMessage("GStreamerCore - Failed to init GStreamer!");
	}
	else
    {
#if defined (__ANDROID__)
		//gst_android_register_static_plugins();
		//gst_android_load_gio_modules();
#endif

        LogManager::Instance()->LogMessage("GStreamerCore - Registering Elements!");
		//fclose(stderr);

		//register plugin path

		//std::string gst_path = g_getenv("GSTREAMER_1_0_ROOT_X86_64");
		//putenv(("GST_PLUGIN_PATH_1_0=" + gst_path + "lib\\gstreamer-1.0" + ";.").c_str());
        //add our custom src/sink elements
#ifdef USE_UNITY_NETWORK
		gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
			"appsink", (char*)"Element application sink",
			appsink_plugin_init, "0.1", "LGPL", "ofVideoPlayer", "openFrameworks",
                                   "http://openframeworks.cc/");
	/*	gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
			"mysrc", (char*)"Element application src",
			_GstMySrcClass::plugin_init, "0.1", "LGPL", "GstVideoProvider", "mray",
			"");
		gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
			"mysink", (char*)"Element application sink",
			_GstMySinkClass::plugin_init, "0.1", "LGPL", "GstVideoProvider", "mray",
                                   "");*/
		gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
			"myudpsrc", (char*)"Element udp src",
			_GstMyUDPSrcClass::plugin_init, "0.1", "LGPL", "GstVideoProvider", "mray",
			"");
		gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
			"myudpsink", (char*)"Element udp sink",
			_GstMyUDPSinkClass::plugin_init, "0.1", "LGPL", "GstVideoProvider", "mray",
			"");

		gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
			"mylistener", (char*)"Custom listener element",
			_GstMyListenerClass::plugin_init, "0.1", "LGPL", "GstVideoProvider", "mray",
			"");
#endif
		LogManager::Instance()->LogMessage("GStreamerCore - GStreamer inited");
	}

#if GLIB_MINOR_VERSION<32
	if (!g_thread_supported()){
		g_thread_init(NULL);
	}
#endif

	gub_main_loop_thread = g_thread_new("GstUnityBridge Main Thread", gst_main_loop_func, this);
	if (!gub_main_loop_thread) {
		LogManager::Instance()->LogMessage(std::string("Failed to create GLib main thread: ") + std::string(err ? err->message : "<No error message>"));
		return;
	}

	_StartLoop();
}

void GStreamerCore::_loopFunction() {
	LogManager::Instance()->LogMessage("Entering main loop");
	gub_main_loop = g_main_loop_new(NULL, FALSE);
	g_main_loop_run(gub_main_loop);
	LogManager::Instance()->LogMessage("Quitting main loop");
}

void GStreamerCore::_StartLoop()
{
	/*m_threadFunc = new GstMainLoopThread();
	m_mainLoopThread = OS::IThreadManager::getInstance().createThread(m_threadFunc);
	m_mainLoopThread->start(0);*/
}

void GStreamerCore::_StopLoop()
{
	/*
	if (!m_threadFunc)
		return;
	GstMainLoopThread* mainLoop = (GstMainLoopThread*)m_threadFunc;
	g_main_loop_quit(mainLoop->main_loop);
	bool running = g_main_loop_is_running(mainLoop->main_loop);
	g_main_loop_unref(mainLoop->main_loop);
	delete m_threadFunc;
	OS::IThreadManager::getInstance().killThread(m_mainLoopThread);
	delete m_mainLoopThread;
	m_threadFunc = 0;
	m_mainLoopThread = 0;
	*/

	if (!gub_main_loop) {
		return;
	}
	g_main_loop_quit(gub_main_loop);
	gub_main_loop = NULL;
	g_thread_join(gub_main_loop_thread);
	gub_main_loop_thread = NULL;
}

void GStreamerCore::Ref()
{
	m_refCount++;
	if (m_refCount==1)
	{
		LogManager::Instance()->LogMessage("Initializing GStreamer");
		m_instance = new GStreamerCore();
		LogManager::Instance()->LogMessage("Initializing GStreamer - Done");
	}

}

void GStreamerCore::Unref()
{
	if (m_refCount == 0)
	{
		LogMessage("GStreamerCore::Unref() - unreferencing GStreamer with no reference! ", ELL_ERROR);
		return;
	}
	//m_refCount--;
	if (m_refCount == 0)
	{
		delete m_instance;
		m_instance = 0;
	}
}

GStreamerCore* GStreamerCore::Instance()
{
	return m_instance;
}

}
}

<|endoftext|>


<commit_before>
<commit_msg>Removed useless file<commit_after><|endoftext|>


<commit_before>#include "PAK.hpp"
#include "DNAMP3.hpp"

namespace DataSpec::DNAMP3 {

const hecl::FourCC CMPD("CMPD");

template <>
void PAK::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) {
  m_header.read(reader);
  if (m_header.version != 2)
    Log.report(logvisor::Fatal, fmt("unexpected PAK magic"));

  reader.seek(8, athena::SeekOrigin::Current);
  atUint32 strgSz = reader.readUint32Big();
  reader.seek(4, athena::SeekOrigin::Current);
  atUint32 rshdSz = reader.readUint32Big();
  reader.seek(44, athena::SeekOrigin::Current);
  atUint32 dataOffset = 128 + strgSz + rshdSz;

  atUint64 strgBase = reader.position();
  atUint32 nameCount = reader.readUint32Big();
  m_nameEntries.clear();
  m_nameEntries.reserve(nameCount);
  for (atUint32 n = 0; n < nameCount; ++n) {
    m_nameEntries.emplace_back();
    m_nameEntries.back().read(reader);
  }
  reader.seek(strgBase + strgSz, athena::SeekOrigin::Begin);

  atUint32 count = reader.readUint32Big();
  m_entries.clear();
  m_entries.reserve(count);
  m_firstEntries.clear();
  m_firstEntries.reserve(count);
  std::vector<Entry> entries;
  entries.reserve(count);
  for (atUint32 e = 0; e < count; ++e) {
    entries.emplace_back();
    entries.back().read(reader);
  }
  for (atUint32 e = 0; e < count; ++e) {
    Entry& entry = entries[e];
    entry.offset += dataOffset;

    auto search = m_entries.find(entry.id);
    if (search == m_entries.end()) {
      m_firstEntries.push_back(entry.id);
      m_entries[entry.id] = std::move(entry);
    } else {
      /* Find next MREA to record which area has dupes */
      for (atUint32 e2 = e + 1; e2 < count; ++e2) {
        Entry& entry2 = entries[e2];
        if (entry2.type != FOURCC('MREA'))
          continue;
        m_dupeMREAs.insert(entry2.id);
        break;
      }
    }
  }

  m_nameMap.clear();
  m_nameMap.reserve(nameCount);
  for (NameEntry& entry : m_nameEntries)
    m_nameMap[entry.name] = entry.id;
}

template <>
void PAK::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer) {
  m_header.write(writer);

  DNAFourCC("STRG").write(writer);
  atUint32 strgSz = 4;
  for (const NameEntry& entry : m_nameEntries)
    strgSz += (atUint32)entry.name.size() + 13;
  atUint32 strgPad = ((strgSz + 63) & ~63) - strgSz;
  strgSz += strgPad;
  writer.writeUint32Big(strgSz);

  DNAFourCC("RSHD").write(writer);
  atUint32 rshdSz = 4 + 24 * m_entries.size();
  atUint32 rshdPad = ((rshdSz + 63) & ~63) - rshdSz;
  rshdSz += rshdPad;
  writer.writeUint32Big(rshdSz);
  atUint32 dataOffset = 128 + strgSz + rshdSz;

  DNAFourCC("DATA").write(writer);
  atUint32 dataSz = 0;
  for (const auto& entry : m_entries)
    dataSz += (entry.second.size + 63) & ~63;
  atUint32 dataPad = ((dataSz + 63) & ~63) - dataSz;
  dataSz += dataPad;
  writer.writeUint32Big(dataSz);
  writer.seek(36, athena::SeekOrigin::Current);

  writer.writeUint32Big((atUint32)m_nameEntries.size());
  for (const NameEntry& entry : m_nameEntries)
    entry.write(writer);
  writer.seek(strgPad, athena::SeekOrigin::Current);

  writer.writeUint32Big((atUint32)m_entries.size());
  for (const auto& entry : m_entries) {
    Entry copy = entry.second;
    copy.offset -= dataOffset;
    copy.write(writer);
  }
  writer.seek(rshdPad, athena::SeekOrigin::Current);
}

template <>
void PAK::Enumerate<BigDNA::BinarySize>(size_t& __isz) {
  m_header.binarySize(__isz);

  size_t strgSz = 4;
  for (const NameEntry& entry : m_nameEntries)
    strgSz += entry.name.size() + 13;
  size_t strgPad = ((strgSz + 63) & ~63) - strgSz;

  size_t rshdSz = 4 + 24 * m_entries.size();
  size_t rshdPad = ((rshdSz + 63) & ~63) - rshdSz;

  __isz += 60;

  __isz += 4;
  for (const NameEntry& entry : m_nameEntries)
    entry.binarySize(__isz);
  __isz += strgPad;

  __isz += 4;
  for (const auto& entry : m_entries)
    entry.second.binarySize(__isz);
  __isz += rshdPad;
}

std::unique_ptr<atUint8[]> PAK::Entry::getBuffer(const nod::Node& pak, atUint64& szOut) const {
  if (compressed) {
    std::unique_ptr<nod::IPartReadStream> strm = pak.beginReadStream(offset);
    struct {
      hecl::FourCC magic;
      atUint32 blockCount;
    } head;
    strm->read(&head, 8);
    if (head.magic != CMPD) {
      Log.report(logvisor::Error, fmt("invalid CMPD block"));
      return std::unique_ptr<atUint8[]>();
    }
    head.blockCount = hecl::SBig(head.blockCount);

    struct Block {
      atUint32 compSz;
      atUint32 decompSz;
    };
    std::unique_ptr<Block[]> blocks(new Block[head.blockCount]);
    strm->read(blocks.get(), 8 * head.blockCount);

    atUint64 maxBlockSz = 0;
    atUint64 totalDecompSz = 0;
    for (atUint32 b = 0; b < head.blockCount; ++b) {
      Block& block = blocks[b];
      block.compSz = hecl::SBig(block.compSz) & 0xffffff;
      block.decompSz = hecl::SBig(block.decompSz);
      if (block.compSz > maxBlockSz)
        maxBlockSz = block.compSz;
      totalDecompSz += block.decompSz;
    }

    std::unique_ptr<atUint8[]> compBuf(new atUint8[maxBlockSz]);
    atUint8* buf = new atUint8[totalDecompSz];
    atUint8* bufCur = buf;
    for (atUint32 b = 0; b < head.blockCount; ++b) {
      Block& block = blocks[b];
      atUint8* compBufCur = compBuf.get();
      strm->read(compBufCur, block.compSz);
      if (block.compSz == block.decompSz) {
        memcpy(bufCur, compBufCur, block.decompSz);
        bufCur += block.decompSz;
      } else {
        atUint32 rem = block.decompSz;
        while (rem) {
          atUint16 chunkSz = hecl::SBig(*(atUint16*)compBufCur);
          compBufCur += 2;
          size_t dsz;
          lzokay::decompress(compBufCur, chunkSz, bufCur, rem, dsz);
          compBufCur += chunkSz;
          bufCur += dsz;
          rem -= dsz;
        }
      }
    }

    szOut = totalDecompSz;
    return std::unique_ptr<atUint8[]>(buf);
  } else {
    atUint8* buf = new atUint8[size];
    pak.beginReadStream(offset)->read(buf, size);
    szOut = size;
    return std::unique_ptr<atUint8[]>(buf);
  }
}

const PAK::Entry* PAK::lookupEntry(const UniqueID64& id) const {
  auto result = m_entries.find(id);
  if (result != m_entries.end())
    return &result->second;
  return nullptr;
}

const PAK::Entry* PAK::lookupEntry(std::string_view name) const {
  auto result = m_nameMap.find(name.data());
  if (result != m_nameMap.end()) {
    auto result1 = m_entries.find(result->second);
    if (result1 != m_entries.end())
      return &result1->second;
  }
  return nullptr;
}

std::string PAK::bestEntryName(const nod::Node& pakNode, const Entry& entry, std::string& catalogueName) const {
  /* Prefer named entries first */
  for (const NameEntry& nentry : m_nameEntries)
    if (nentry.id == entry.id) {
      catalogueName = nentry.name;
      return fmt::format(fmt("{}_{}"), nentry.name, entry.id);
    }

  /* Otherwise return ID format string */
  return fmt::format(fmt("{}_{}"), entry.type, entry.id);
}

} // namespace DataSpec::DNAMP3
<commit_msg>DNAMP3/PAK: Make use of unique_ptr in getBuffer()<commit_after>#include "PAK.hpp"
#include "DNAMP3.hpp"

namespace DataSpec::DNAMP3 {

const hecl::FourCC CMPD("CMPD");

template <>
void PAK::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) {
  m_header.read(reader);
  if (m_header.version != 2)
    Log.report(logvisor::Fatal, fmt("unexpected PAK magic"));

  reader.seek(8, athena::SeekOrigin::Current);
  atUint32 strgSz = reader.readUint32Big();
  reader.seek(4, athena::SeekOrigin::Current);
  atUint32 rshdSz = reader.readUint32Big();
  reader.seek(44, athena::SeekOrigin::Current);
  atUint32 dataOffset = 128 + strgSz + rshdSz;

  atUint64 strgBase = reader.position();
  atUint32 nameCount = reader.readUint32Big();
  m_nameEntries.clear();
  m_nameEntries.reserve(nameCount);
  for (atUint32 n = 0; n < nameCount; ++n) {
    m_nameEntries.emplace_back();
    m_nameEntries.back().read(reader);
  }
  reader.seek(strgBase + strgSz, athena::SeekOrigin::Begin);

  atUint32 count = reader.readUint32Big();
  m_entries.clear();
  m_entries.reserve(count);
  m_firstEntries.clear();
  m_firstEntries.reserve(count);
  std::vector<Entry> entries;
  entries.reserve(count);
  for (atUint32 e = 0; e < count; ++e) {
    entries.emplace_back();
    entries.back().read(reader);
  }
  for (atUint32 e = 0; e < count; ++e) {
    Entry& entry = entries[e];
    entry.offset += dataOffset;

    auto search = m_entries.find(entry.id);
    if (search == m_entries.end()) {
      m_firstEntries.push_back(entry.id);
      m_entries[entry.id] = std::move(entry);
    } else {
      /* Find next MREA to record which area has dupes */
      for (atUint32 e2 = e + 1; e2 < count; ++e2) {
        Entry& entry2 = entries[e2];
        if (entry2.type != FOURCC('MREA'))
          continue;
        m_dupeMREAs.insert(entry2.id);
        break;
      }
    }
  }

  m_nameMap.clear();
  m_nameMap.reserve(nameCount);
  for (NameEntry& entry : m_nameEntries)
    m_nameMap[entry.name] = entry.id;
}

template <>
void PAK::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer) {
  m_header.write(writer);

  DNAFourCC("STRG").write(writer);
  atUint32 strgSz = 4;
  for (const NameEntry& entry : m_nameEntries)
    strgSz += (atUint32)entry.name.size() + 13;
  atUint32 strgPad = ((strgSz + 63) & ~63) - strgSz;
  strgSz += strgPad;
  writer.writeUint32Big(strgSz);

  DNAFourCC("RSHD").write(writer);
  atUint32 rshdSz = 4 + 24 * m_entries.size();
  atUint32 rshdPad = ((rshdSz + 63) & ~63) - rshdSz;
  rshdSz += rshdPad;
  writer.writeUint32Big(rshdSz);
  atUint32 dataOffset = 128 + strgSz + rshdSz;

  DNAFourCC("DATA").write(writer);
  atUint32 dataSz = 0;
  for (const auto& entry : m_entries)
    dataSz += (entry.second.size + 63) & ~63;
  atUint32 dataPad = ((dataSz + 63) & ~63) - dataSz;
  dataSz += dataPad;
  writer.writeUint32Big(dataSz);
  writer.seek(36, athena::SeekOrigin::Current);

  writer.writeUint32Big((atUint32)m_nameEntries.size());
  for (const NameEntry& entry : m_nameEntries)
    entry.write(writer);
  writer.seek(strgPad, athena::SeekOrigin::Current);

  writer.writeUint32Big((atUint32)m_entries.size());
  for (const auto& entry : m_entries) {
    Entry copy = entry.second;
    copy.offset -= dataOffset;
    copy.write(writer);
  }
  writer.seek(rshdPad, athena::SeekOrigin::Current);
}

template <>
void PAK::Enumerate<BigDNA::BinarySize>(size_t& __isz) {
  m_header.binarySize(__isz);

  size_t strgSz = 4;
  for (const NameEntry& entry : m_nameEntries)
    strgSz += entry.name.size() + 13;
  size_t strgPad = ((strgSz + 63) & ~63) - strgSz;

  size_t rshdSz = 4 + 24 * m_entries.size();
  size_t rshdPad = ((rshdSz + 63) & ~63) - rshdSz;

  __isz += 60;

  __isz += 4;
  for (const NameEntry& entry : m_nameEntries)
    entry.binarySize(__isz);
  __isz += strgPad;

  __isz += 4;
  for (const auto& entry : m_entries)
    entry.second.binarySize(__isz);
  __isz += rshdPad;
}

std::unique_ptr<atUint8[]> PAK::Entry::getBuffer(const nod::Node& pak, atUint64& szOut) const {
  if (compressed) {
    std::unique_ptr<nod::IPartReadStream> strm = pak.beginReadStream(offset);
    struct {
      hecl::FourCC magic;
      atUint32 blockCount;
    } head;
    strm->read(&head, 8);
    if (head.magic != CMPD) {
      Log.report(logvisor::Error, fmt("invalid CMPD block"));
      return nullptr;
    }
    head.blockCount = hecl::SBig(head.blockCount);

    struct Block {
      atUint32 compSz;
      atUint32 decompSz;
    };
    std::unique_ptr<Block[]> blocks(new Block[head.blockCount]);
    strm->read(blocks.get(), 8 * head.blockCount);

    atUint64 maxBlockSz = 0;
    atUint64 totalDecompSz = 0;
    for (atUint32 b = 0; b < head.blockCount; ++b) {
      Block& block = blocks[b];
      block.compSz = hecl::SBig(block.compSz) & 0xffffff;
      block.decompSz = hecl::SBig(block.decompSz);
      if (block.compSz > maxBlockSz)
        maxBlockSz = block.compSz;
      totalDecompSz += block.decompSz;
    }

    std::unique_ptr<atUint8[]> compBuf(new atUint8[maxBlockSz]);
    std::unique_ptr<atUint8[]> buf{new atUint8[totalDecompSz]};
    atUint8* bufCur = buf.get();
    for (atUint32 b = 0; b < head.blockCount; ++b) {
      Block& block = blocks[b];
      atUint8* compBufCur = compBuf.get();
      strm->read(compBufCur, block.compSz);
      if (block.compSz == block.decompSz) {
        memcpy(bufCur, compBufCur, block.decompSz);
        bufCur += block.decompSz;
      } else {
        atUint32 rem = block.decompSz;
        while (rem) {
          atUint16 chunkSz = hecl::SBig(*(atUint16*)compBufCur);
          compBufCur += 2;
          size_t dsz;
          lzokay::decompress(compBufCur, chunkSz, bufCur, rem, dsz);
          compBufCur += chunkSz;
          bufCur += dsz;
          rem -= dsz;
        }
      }
    }

    szOut = totalDecompSz;
    return buf;
  } else {
    std::unique_ptr<atUint8[]> buf{new atUint8[size]};
    pak.beginReadStream(offset)->read(buf.get(), size);
    szOut = size;
    return buf;
  }
}

const PAK::Entry* PAK::lookupEntry(const UniqueID64& id) const {
  auto result = m_entries.find(id);
  if (result != m_entries.end())
    return &result->second;
  return nullptr;
}

const PAK::Entry* PAK::lookupEntry(std::string_view name) const {
  auto result = m_nameMap.find(name.data());
  if (result != m_nameMap.end()) {
    auto result1 = m_entries.find(result->second);
    if (result1 != m_entries.end())
      return &result1->second;
  }
  return nullptr;
}

std::string PAK::bestEntryName(const nod::Node& pakNode, const Entry& entry, std::string& catalogueName) const {
  /* Prefer named entries first */
  for (const NameEntry& nentry : m_nameEntries)
    if (nentry.id == entry.id) {
      catalogueName = nentry.name;
      return fmt::format(fmt("{}_{}"), nentry.name, entry.id);
    }

  /* Otherwise return ID format string */
  return fmt::format(fmt("{}_{}"), entry.type, entry.id);
}

} // namespace DataSpec::DNAMP3
<|endoftext|>


<commit_before>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkCanvas.h"
#include "SkGradientShader.h"

#define W   SkIntToScalar(80)
#define H   SkIntToScalar(60)

typedef void (*PaintProc)(SkPaint*);

static void identity_paintproc(SkPaint* paint) {}
static void gradient_paintproc(SkPaint* paint) {
    const SkColor colors[] = { SK_ColorGREEN, SK_ColorBLUE };
    const SkPoint pts[] = { { 0, 0 }, { W, H } };
    SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL,
                                                 SK_ARRAY_COUNT(colors),
                                                 SkShader::kClamp_TileMode);
    paint->setShader(s)->unref();
}

typedef void (*Proc)(SkCanvas*, const SkPaint&);

static void draw_hair(SkCanvas* canvas, const SkPaint& paint) {
    SkPaint p(paint);
    p.setStrokeWidth(0);
    canvas->drawLine(0, 0, W, H, p);
}

static void draw_thick(SkCanvas* canvas, const SkPaint& paint) {
    SkPaint p(paint);
    p.setStrokeWidth(H/5);
    canvas->drawLine(0, 0, W, H, p);
}

static void draw_rect(SkCanvas* canvas, const SkPaint& paint) {
    canvas->drawRect(SkRect::MakeWH(W, H), paint);
}

static void draw_oval(SkCanvas* canvas, const SkPaint& paint) {
    canvas->drawOval(SkRect::MakeWH(W, H), paint);
}

static void draw_text(SkCanvas* canvas, const SkPaint& paint) {
    SkPaint p(paint);
    p.setTextSize(H/4);
    canvas->drawText("Hamburge", 8, 0, H*2/3, p);
}

class SrcModeGM : public skiagm::GM {
    SkPath fPath;
public:
    SrcModeGM() {
        this->setBGColor(0xFFDDDDDD);
    }

protected:
    virtual SkString onShortName() {
        return SkString("srcmode");
    }

    virtual SkISize onISize() {
        return SkISize::Make(640, 760);
    }

    virtual void onDraw(SkCanvas* canvas) {
        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));

        SkPaint paint;
        paint.setColor(0x80FF0000);

        const Proc procs[] = {
            draw_hair, draw_thick, draw_rect, draw_oval, draw_text
        };

        const SkXfermode::Mode modes[] = {
            SkXfermode::kSrcOver_Mode, SkXfermode::kSrc_Mode, SkXfermode::kClear_Mode
        };

        const PaintProc paintProcs[] = {
            identity_paintproc, gradient_paintproc
        };

        for (int aa = 0; aa <= 1; ++aa) {
            paint.setAntiAlias(SkToBool(aa));
            canvas->save();
            for (size_t i = 0; i < SK_ARRAY_COUNT(paintProcs); ++i) {
                paintProcs[i](&paint);
                for (size_t x = 0; x < SK_ARRAY_COUNT(modes); ++x) {
                    paint.setXfermodeMode(modes[x]);
                    canvas->save();
                    for (size_t y = 0; y < SK_ARRAY_COUNT(procs); ++y) {
                        procs[y](canvas, paint);
                        canvas->translate(0, H * 5 / 4);
                    }
                    canvas->restore();
                    canvas->translate(W * 5 / 4, 0);
                }
            }
            canvas->restore();
            canvas->translate(0, (H * 5 / 4) * SK_ARRAY_COUNT(procs));
        }
    }

private:
    typedef skiagm::GM INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

DEF_GM(return new SrcModeGM;)

<commit_msg>draw offscreen so we can see the alpha-channel we are writing todo: know when to use a gpu-surface<commit_after>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkCanvas.h"
#include "SkGradientShader.h"
#include "SkSurface.h"

#define W   SkIntToScalar(80)
#define H   SkIntToScalar(60)

typedef void (*PaintProc)(SkPaint*);

static void identity_paintproc(SkPaint* paint) {}
static void gradient_paintproc(SkPaint* paint) {
    const SkColor colors[] = { SK_ColorGREEN, SK_ColorBLUE };
    const SkPoint pts[] = { { 0, 0 }, { W, H } };
    SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL,
                                                 SK_ARRAY_COUNT(colors),
                                                 SkShader::kClamp_TileMode);
    paint->setShader(s)->unref();
}

typedef void (*Proc)(SkCanvas*, const SkPaint&);

static void draw_hair(SkCanvas* canvas, const SkPaint& paint) {
    SkPaint p(paint);
    p.setStrokeWidth(0);
    canvas->drawLine(0, 0, W, H, p);
}

static void draw_thick(SkCanvas* canvas, const SkPaint& paint) {
    SkPaint p(paint);
    p.setStrokeWidth(H/5);
    canvas->drawLine(0, 0, W, H, p);
}

static void draw_rect(SkCanvas* canvas, const SkPaint& paint) {
    canvas->drawRect(SkRect::MakeWH(W, H), paint);
}

static void draw_oval(SkCanvas* canvas, const SkPaint& paint) {
    canvas->drawOval(SkRect::MakeWH(W, H), paint);
}

static void draw_text(SkCanvas* canvas, const SkPaint& paint) {
    SkPaint p(paint);
    p.setTextSize(H/4);
    canvas->drawText("Hamburge", 8, 0, H*2/3, p);
}

class SrcModeGM : public skiagm::GM {
    SkPath fPath;
public:
    SrcModeGM() {
        this->setBGColor(SK_ColorBLACK);
    }

protected:
    virtual SkString onShortName() {
        return SkString("srcmode");
    }

    virtual SkISize onISize() {
        return SkISize::Make(640, 760);
    }

    void drawContent(SkCanvas* canvas) {
        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));

        SkPaint paint;
        paint.setColor(0x80FF0000);

        const Proc procs[] = {
            draw_hair, draw_thick, draw_rect, draw_oval, draw_text
        };

        const SkXfermode::Mode modes[] = {
            SkXfermode::kSrcOver_Mode, SkXfermode::kSrc_Mode, SkXfermode::kClear_Mode
        };

        const PaintProc paintProcs[] = {
            identity_paintproc, gradient_paintproc
        };

        for (int aa = 0; aa <= 1; ++aa) {
            paint.setAntiAlias(SkToBool(aa));
            canvas->save();
            for (size_t i = 0; i < SK_ARRAY_COUNT(paintProcs); ++i) {
                paintProcs[i](&paint);
                for (size_t x = 0; x < SK_ARRAY_COUNT(modes); ++x) {
                    paint.setXfermodeMode(modes[x]);
                    canvas->save();
                    for (size_t y = 0; y < SK_ARRAY_COUNT(procs); ++y) {
                        procs[y](canvas, paint);
                        canvas->translate(0, H * 5 / 4);
                    }
                    canvas->restore();
                    canvas->translate(W * 5 / 4, 0);
                }
            }
            canvas->restore();
            canvas->translate(0, (H * 5 / 4) * SK_ARRAY_COUNT(procs));
        }
    }

    static SkSurface* compat_surface(SkCanvas* canvas, const SkISize& size) {
        SkImage::Info info = {
            size.width(),
            size.height(),
            SkImage::kPMColor_ColorType,
            SkImage::kPremul_AlphaType
        };
        return SkSurface::NewRaster(info);
    }

    virtual void onDraw(SkCanvas* canvas) {
        SkAutoTUnref<SkSurface> surf(compat_surface(canvas, this->getISize()));
        surf->getCanvas()->drawColor(SK_ColorWHITE);
        this->drawContent(surf->getCanvas());
        surf->draw(canvas, 0, 0, NULL);

    }

private:
    typedef skiagm::GM INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

DEF_GM(return new SrcModeGM;)

<|endoftext|>


<commit_before>#include "ofApp.h"

void ofApp::setup()
{
    femurBone.load("femur.png");

    images = { femurBone, femurBone, femurBone, femurBone, femurBone, femurBone, femurBone, femurBone };
    angles = { 0, 0, 0, 0, 0, 0, 0, 0 };
    anglesMinimum = { -360, -270, -180, -90, -80, -70, -60, -45 };
    anglesMaximum = { 360, 270, 180, 90, 80, 70, 60, 45 };
    anglesNoiseIncrement = { 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01  };
    anglesNoiseOffsets = { ofRandom(100), ofRandom(100), ofRandom(100), ofRandom(100), ofRandom(100), ofRandom(100), ofRandom(100), ofRandom(100) };
    anglesNoiseScales = { 2, 2, 2, 2, 2, 2, 2, 2 };
    isNewSegment = { false, false, false, false, false, false, false, false };
}

void ofApp::update()
{
    // Loop through all of the images!
    for (std::size_t i = 0; i < images.size(); ++i)
    {
        // This is how we move through the Perlin noise. We adjust the offset
        // just a tiny bit to get the next value in the neighborhood of noise.
        anglesNoiseOffsets[i] += anglesNoiseIncrement[i];

        // ... next we ask for the noise at the current offset. It will be a
        // value between -1 and 1 for ofSignedNoise.
        float noiseAtOffset = ofSignedNoise(anglesNoiseOffsets[i]);

        // ... next we scale the noise by multiplying it by a scaler.
        noiseAtOffset *= anglesNoiseScales[i];

        // Now add some noise to the angle.
        angles[i] = angles[i] + noiseAtOffset;

        // Now clamp the angle values to keep them in a reasonable range.
        angles[i] = ofClamp(angles[i], anglesMinimum[i], anglesMaximum[i]);
    }
}

void ofApp::draw()
{
    ofBackground(0);
    ofSetColor(ofColor::white);

    ofDrawBitmapString("Press spacebar for debug mode", 20, 20);

    // Move our canvas (translate)

    ofPushMatrix();

    int x = ofGetMouseX();
    int y = ofGetMouseY();

    ofTranslate(x, y);

    // Loop through all o fthe images.
    for (std::size_t i = 0; i < images.size(); ++i)
    {
        // If we want to have different attachment points, we must push (or not
        // push) a new transoformation matrix.
        if (isNewSegment[i])
        {
            ofPushMatrix();
        }

        ofRotateZDeg(angles[i]);

        images[i].draw(-images[i].getWidth() / 2,
                       -images[i].getWidth() / 2);

        // We draw the debugging here so that it is on top of our image.
        if (showGrid)
        {
            drawGrid(80, 80, 10);
            ofDrawBitmapString(ofToString("Transform: " + ofToString(i)), 14, 14);
        }

        ofTranslate(0, images[i].getHeight());

        // If we pushed a new matrix, go ahead and pop it off again.
        if (isNewSegment[i])
        {
            ofPopMatrix();
        }
    }

    ofPopMatrix();

}

void ofApp::keyPressed(int key)
{
    if (key == ' ')
    {
        showGrid = !showGrid;
    }
}

void ofApp::drawGrid(float width, float height, float size)
{
    ofPushStyle();
    ofNoFill();
    ofSetColor(255, 60);

    for (int x = 0; x < width; x += size)
    {
        ofDrawLine(x, 0, x, height);
    }

    for (int y = 0; y < height; y += size)
    {
        ofDrawLine(0, y, width, y);
    }

    ofDrawRectangle(0, 0, width, height);

    ofSetColor(ofColor::green);
    ofDrawLine(0, 0, width / 2, 0);

    ofSetColor(ofColor::red);
    ofDrawLine(0, 0, 0, height / 2);

    ofPopStyle();
}

<commit_msg>Update flailer.<commit_after>#include "ofApp.h"

void ofApp::setup()
{
    femurBone.load("femur.png");

    images = { femurBone, femurBone, femurBone, femurBone, femurBone, femurBone, femurBone, femurBone };
    angles = { 0, 0, 0, 0, 0, 0, 0, 0 };
    anglesMinimum = { -360, -270, -180, -90, -80, -70, -60, -45 };
    anglesMaximum = { 360, 270, 180, 90, 80, 70, 60, 45 };
    anglesNoiseIncrement = { 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01  };
    anglesNoiseOffsets = { ofRandom(100), ofRandom(100), ofRandom(100), ofRandom(100), ofRandom(100), ofRandom(100), ofRandom(100), ofRandom(100) };
    anglesNoiseScales = { 2, 2, 2, 2, 2, 2, 2, 2 };
    isNewSegment = { false, false, true, false, false, false, true, true };
}

void ofApp::update()
{
    // Loop through all of the images!
    for (std::size_t i = 0; i < images.size(); ++i)
    {
        // This is how we move through the Perlin noise. We adjust the offset
        // just a tiny bit to get the next value in the neighborhood of noise.
        anglesNoiseOffsets[i] += anglesNoiseIncrement[i];

        // ... next we ask for the noise at the current offset. It will be a
        // value between -1 and 1 for ofSignedNoise.
        float noiseAtOffset = ofSignedNoise(anglesNoiseOffsets[i]);

        // ... next we scale the noise by multiplying it by a scaler.
        noiseAtOffset *= anglesNoiseScales[i];

        // Now add some noise to the angle.
        angles[i] = angles[i] + noiseAtOffset;

        // Now clamp the angle values to keep them in a reasonable range.
        angles[i] = ofClamp(angles[i], anglesMinimum[i], anglesMaximum[i]);
    }
}

void ofApp::draw()
{
    ofBackground(0);
    ofSetColor(ofColor::white);

    ofDrawBitmapString("Press spacebar for debug mode", 20, 20);

    // Move our canvas (translate)

    ofPushMatrix();

    int x = ofGetMouseX();
    int y = ofGetMouseY();

    ofTranslate(x, y);

    // Loop through all o fthe images.
    for (std::size_t i = 0; i < images.size(); ++i)
    {
        // If we want to have different attachment points, we must push (or not
        // push) a new transoformation matrix.
        if (isNewSegment[i])
        {
            ofPushMatrix();
        }

        ofRotateZDeg(angles[i]);

        images[i].draw(-images[i].getWidth() / 2,
                       -images[i].getWidth() / 2);

        // We draw the debugging here so that it is on top of our image.
        if (showGrid)
        {
            drawGrid(80, 80, 10);
            ofDrawBitmapString(ofToString("Transform: " + ofToString(i)), 14, 14);
        }

        ofTranslate(0, images[i].getHeight());

        // If we pushed a new matrix, go ahead and pop it off again.
        if (isNewSegment[i])
        {
            ofPopMatrix();
        }
    }

    ofPopMatrix();

}

void ofApp::keyPressed(int key)
{
    if (key == ' ')
    {
        showGrid = !showGrid;
    }
}

void ofApp::drawGrid(float width, float height, float size)
{
    ofPushStyle();
    ofNoFill();
    ofSetColor(255, 60);

    for (int x = 0; x < width; x += size)
    {
        ofDrawLine(x, 0, x, height);
    }

    for (int y = 0; y < height; y += size)
    {
        ofDrawLine(0, y, width, y);
    }

    ofDrawRectangle(0, 0, width, height);

    ofSetColor(ofColor::green);
    ofDrawLine(0, 0, width / 2, 0);

    ofSetColor(ofColor::red);
    ofDrawLine(0, 0, 0, height / 2);

    ofPopStyle();
}

<|endoftext|>


<commit_before>//include the engine code
#include "../RTEngine/RTEngine.hpp"
#include "../RTEngine/PhongMaterial.hpp"
#include "../RTEngine/Sphere.hpp"
#include "../RTEngine/Plane.hpp"
#include "../RTEngine/SphericalLight.hpp"
#include <cstdio>
#include <png.h>

using namespace RealRT;

void writeBufferAsPng(std::string fileName, unsigned char *buffer, int width, int height)
{
	std::FILE *fh = std::fopen(fileName.c_str(), "wb");

	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	png_infop info_ptr = png_create_info_struct(png_ptr);

	png_init_io(png_ptr, fh);

	png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
	png_write_info(png_ptr, info_ptr);

	png_bytepp rowPointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
	for(int i = 0; i < height; i++)
		rowPointers[i] = buffer + (width * i);

	png_write_image(png_ptr, rowPointers);

	png_write_end(png_ptr, NULL);

	std::fclose(fh);
}

int main(int argc, char **argv)
{
	std::shared_ptr<RTEngine> engine = RTEngine::Instantiate(1280, 1024);

	Sphere s1(DiffuseRed,{-5.0,0.0,2.0});
	Sphere s2(DiffuseGreen,{0.0,4.0,0.0},0.5);
	Sphere s3(DiffuseGreen,{0.0,2.0,0.0},0.5);
	Sphere s4(DiffuseGreen,{0.0,0.0,0.0},0.5);
	Sphere s5(ReflectiveBlue,{5.0,0.0,0.0},1.5);

	Plane floorobj(Mirror,{0.0,1.0,0.0},3.0);

	SphericalLight l1(WhiteLight,{-9.5,6.0,0.0},0.1);
	SphericalLight l2(WhiteLight,{0.0,6.0,-2.0},0.1);
	SphericalLight l3(WhiteLight,{9.5,6.0,0.0},0.1);

	engine->AddWorldObject(std::shared_ptr<Shape>(&floorobj));

	engine->AddWorldObject(std::shared_ptr<Shape>(&s1));
	engine->AddWorldObject(std::shared_ptr<Shape>(&s2));
	engine->AddWorldObject(std::shared_ptr<Shape>(&s3));
	engine->AddWorldObject(std::shared_ptr<Shape>(&s4));
	engine->AddWorldObject(std::shared_ptr<Shape>(&s5));

	engine->AddWorldObject(std::shared_ptr<Shape>(&l1));
	engine->AddWorldObject(std::shared_ptr<Shape>(&l2));
	engine->AddWorldObject(std::shared_ptr<Shape>(&l3));

	engine->CalculateScene();

	unsigned char *rendered = engine->Screen();

	std::string output = "out.png";
	if(argc > 1)
		output = argv[1];

	writeBufferAsPng(output, rendered, 1280, 1024);

	return 0;
}
<commit_msg>Fixed memory errors and added raw image output<commit_after>//include the engine code
#include "../RTEngine/RTEngine.hpp"
#include "../RTEngine/PhongMaterial.hpp"
#include "../RTEngine/Sphere.hpp"
#include "../RTEngine/Plane.hpp"
#include "../RTEngine/SphericalLight.hpp"
#include <cstdio>
#include <fstream>
#include <png.h>
#include <opencv2/opencv.hpp>

using namespace RealRT;

const int Width = 2560;
const int Height = 1600;

void writeBufferAsPng(std::string fileName, unsigned char *buffer, int width, int height)
{
	std::FILE *fh = std::fopen(fileName.c_str(), "wb");

	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	png_infop info_ptr = png_create_info_struct(png_ptr);

	png_init_io(png_ptr, fh);

	png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
	png_write_info(png_ptr, info_ptr);

	png_bytepp rowPointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
	for(int i = 0; i < height; i++)
		rowPointers[i] = buffer + (width * i * 3);

	png_write_image(png_ptr, rowPointers);

	png_write_end(png_ptr, NULL);

	std::fclose(fh);
}

void writeBufferAsRaw(std::string fileName, unsigned char *buffer, int width, int height)
{
	std::ofstream img(fileName + ".raw", std::ios::binary);

	for(int j = 0; j < height; j++)
	{
		for(int i = 0; i < width; i++)
		{
			img << buffer[((j * width) + i) * 3 + 0] << buffer[((j * width) + i) * 3 + 1] << buffer[((j * width) + i) * 3 + 2];
		}
	}
}

int main(int argc, char **argv)
{
	std::shared_ptr<RTEngine> engine = RTEngine::Instantiate(Width, Height);

	std::shared_ptr<Sphere> s1 = std::make_shared<Sphere>(DiffuseRed,Vector3D(-5.0,0.0,2.0));
	std::shared_ptr<Sphere> s2 = std::make_shared<Sphere>(DiffuseGreen,Vector3D(0.0,4.0,0.0),0.5);
	std::shared_ptr<Sphere> s3 = std::make_shared<Sphere>(DiffuseGreen,Vector3D(0.0,2.0,0.0),0.5);
	std::shared_ptr<Sphere> s4 = std::make_shared<Sphere>(DiffuseGreen,Vector3D(0.0,0.0,0.0),0.5);
	std::shared_ptr<Sphere> s5 = std::make_shared<Sphere>(ReflectiveBlue,Vector3D(5.0,0.0,0.0),1.5);

	std::shared_ptr<Plane> floorobj = std::make_shared<Plane>(Mirror,Vector3D(0.0,1.0,0.0),3.0);

	std::shared_ptr<SphericalLight> l1 = std::make_shared<SphericalLight>(WhiteLight,Vector3D(-9.5,6.0,0.0),0.1);
	std::shared_ptr<SphericalLight> l2 = std::make_shared<SphericalLight>(WhiteLight,Vector3D(0.0,6.0,-2.0),0.1);
	std::shared_ptr<SphericalLight> l3 = std::make_shared<SphericalLight>(WhiteLight,Vector3D(9.5,6.0,0.0),0.1);

	engine->AddWorldObject(floorobj);

	engine->AddWorldObject(s1);
	engine->AddWorldObject(s2);
	engine->AddWorldObject(s3);
	engine->AddWorldObject(s4);
	engine->AddWorldObject(s5);

	engine->AddWorldObject(l1);
	engine->AddWorldObject(l2);
	engine->AddWorldObject(l3);

	engine->CalculateScene();

	unsigned char *rendered = engine->Screen();

	std::string output = "out.png";
	if(argc > 1)
		output = argv[1];

	writeBufferAsPng(output, rendered, Width, Height);

	return 0;
}
<|endoftext|>