コード例 #1
0
RepoUser RepoBSONFactory::makeRepoUser(
	const std::string                           &userName,
	const std::string                           &password,
	const std::string                           &firstName,
	const std::string                           &lastName,
	const std::string                           &email,
	const std::list<std::pair<std::string, std::string>>   &roles,
	const std::list<std::pair<std::string, std::string>>   &apiKeys,
	const std::vector<char>                     &avatar)
{
	RepoBSONBuilder builder;
	RepoBSONBuilder customDataBuilder;

	builder.append(REPO_LABEL_ID, generateUUID());
	if (!userName.empty())
		builder << REPO_USER_LABEL_USER << userName;

	if (!password.empty())
	{
		RepoBSONBuilder credentialsBuilder;
		credentialsBuilder << REPO_USER_LABEL_CLEARTEXT << password;
		builder << REPO_USER_LABEL_CREDENTIALS << credentialsBuilder.obj();
	}

	if (!firstName.empty())
		customDataBuilder << REPO_USER_LABEL_FIRST_NAME << firstName;

	if (!lastName.empty())
		customDataBuilder << REPO_USER_LABEL_LAST_NAME << lastName;

	if (!email.empty())
		customDataBuilder << REPO_USER_LABEL_EMAIL << email;

	if (!apiKeys.empty())
		customDataBuilder.appendArrayPair(REPO_USER_LABEL_API_KEYS, apiKeys, REPO_USER_LABEL_LABEL, REPO_USER_LABEL_KEY);

	if (avatar.size())
	{
		RepoBSONBuilder avatarBuilder;
		avatarBuilder.appendBinary(REPO_LABEL_DATA, &avatar.at(0), sizeof(avatar.at(0))*avatar.size());
		customDataBuilder << REPO_LABEL_AVATAR << avatarBuilder.obj();
	}

	builder << REPO_USER_LABEL_CUSTOM_DATA << customDataBuilder.obj();

	if (roles.size())
		builder.appendArrayPair(REPO_USER_LABEL_ROLES, roles, REPO_USER_LABEL_DB, REPO_USER_LABEL_ROLE);

	return RepoUser(builder.obj());
}
コード例 #2
0
TextureNode RepoBSONFactory::makeTextureNode(
	const std::string &name,
	const char        *data,
	const uint32_t    &byteCount,
	const uint32_t    &width,
	const uint32_t    &height,
	const int         &apiLevel)
{
	RepoBSONBuilder builder;
	auto defaults = appendDefaults(REPO_NODE_TYPE_TEXTURE, apiLevel, generateUUID(), name);
	builder.appendElements(defaults);
	//
	// Width
	//
	builder << REPO_LABEL_WIDTH << width;

	//
	// Height
	//
	builder << REPO_LABEL_HEIGHT << height;

	//
	// Format TODO: replace format with MIME Type?
	//
	if (!name.empty())
	{
		boost::filesystem::path file{ name };
		std::string ext = file.extension().string();
		if (!ext.empty())
			builder << REPO_NODE_LABEL_EXTENSION << ext.substr(1, ext.size());
	}
	//
	// Data
	//

	if (data && byteCount)
		builder.appendBinary(
		REPO_LABEL_DATA,
		data,
		byteCount);
	else
	{
		repoWarning << " Creating a texture node with no texture!";
	}

	return TextureNode(builder.obj());
}
コード例 #3
0
MeshNode RepoBSONFactory::makeMeshNode(
	const std::vector<repo_vector_t>                  &vertices,
	const std::vector<repo_face_t>                    &faces,
	const std::vector<repo_vector_t>                  &normals,
	const std::vector<std::vector<float>>             &boundingBox,
	const std::vector<std::vector<repo_vector2d_t>>   &uvChannels,
	const std::vector<repo_color4d_t>                 &colors,
	const std::vector<std::vector<float>>             &outline,
	const std::string                           &name,
	const int                                   &apiLevel)
{
	RepoBSONBuilder builder;
	uint64_t bytesize = 0; //track the (approximate) size to know when we need to offload to gridFS
	repoUUID uniqueID = generateUUID();
	auto defaults = appendDefaults(REPO_NODE_TYPE_MESH, apiLevel, generateUUID(), name, std::vector<repoUUID>(), uniqueID);
	bytesize += defaults.objsize();
	builder.appendElements(defaults);

	if (!vertices.size() || !faces.size())
	{
		repoWarning << "Creating a mesh (" << defaults.getUUIDField(REPO_NODE_LABEL_ID) << ") with no vertices/faces!";
	}
	std::unordered_map<std::string, std::pair<std::string, std::vector<uint8_t>>> binMapping;

	if (boundingBox.size() > 0)
	{
		RepoBSONBuilder arrayBuilder;

		for (int i = 0; i < boundingBox.size(); i++)
		{
			arrayBuilder.appendArray(std::to_string(i), boundingBox[i]);
			bytesize += boundingBox[i].size() * sizeof(boundingBox[i][0]);
		}

		builder.appendArray(REPO_NODE_MESH_LABEL_BOUNDING_BOX, arrayBuilder.obj());
	}

	if (outline.size() > 0)
	{
		RepoBSONBuilder arrayBuilder;

		for (int i = 0; i < outline.size(); i++)
		{
			arrayBuilder.appendArray(boost::lexical_cast<std::string>(i), outline[i]);
			bytesize += outline[i].size() * sizeof(outline[i][0]);
		}

		builder.appendArray(REPO_NODE_MESH_LABEL_OUTLINE, arrayBuilder.obj());
	}

	/*
		* TODO: because mongo has a stupid internal limit of 64MB, we can't store everything in a BSON
		* There are 2 options
		* 1. store binaries in memory outside of the bson and put it into GRIDFS at the point of commit
		* 2. leave mongo's bson, use our own/exteral library that doesn't have this limit and database handle this at the point of commit
		* below uses option 1, but ideally we should be doing option 2.
		*/

	if (vertices.size() > 0)
	{
		uint64_t verticesByteCount = vertices.size() * sizeof(vertices[0]);

		if (verticesByteCount + bytesize >= REPO_BSON_MAX_BYTE_SIZE)
		{
			std::string bName = UUIDtoString(uniqueID) + "_vertices";
			//inclusion of this binary exceeds the maximum, store separately
			binMapping[REPO_NODE_MESH_LABEL_VERTICES] =
				std::pair<std::string, std::vector<uint8_t>>(bName, std::vector<uint8_t>());
			binMapping[REPO_NODE_MESH_LABEL_VERTICES].second.resize(verticesByteCount); //uint8_t will ensure it is a byte addrressing
			memcpy(binMapping[REPO_NODE_MESH_LABEL_VERTICES].second.data(), &vertices[0], verticesByteCount);
			bytesize += sizeof(bName);
		}
		else
		{
			builder.appendBinary(
				REPO_NODE_MESH_LABEL_VERTICES,
				&vertices[0],
				vertices.size() * sizeof(vertices[0])
				);
			bytesize += verticesByteCount;
		}
	}

	if (faces.size() > 0)
	{
		builder << REPO_NODE_MESH_LABEL_FACES_COUNT << (uint32_t)(faces.size());

		// In API LEVEL 1, faces are stored as
		// [n1, v1, v2, ..., n2, v1, v2...]
		std::vector<repo_face_t>::iterator faceIt;

		std::vector<uint32_t> facesLevel1;
		for (auto &face : faces){
			auto nIndices = face.size();
			if (!nIndices)
			{
				repoWarning << "number of indices in this face is 0!";
			}
			facesLevel1.push_back(nIndices);
			for (uint32_t ind = 0; ind < nIndices; ind++)
			{
				facesLevel1.push_back(face[ind]);
			}
		}

		uint64_t facesByteCount = facesLevel1.size() * sizeof(facesLevel1[0]);

		if (facesByteCount + bytesize >= REPO_BSON_MAX_BYTE_SIZE)
		{
			std::string bName = UUIDtoString(uniqueID) + "_faces";
			//inclusion of this binary exceeds the maximum, store separately
			binMapping[REPO_NODE_MESH_LABEL_FACES] =
				std::pair<std::string, std::vector<uint8_t>>(bName, std::vector<uint8_t>());
			binMapping[REPO_NODE_MESH_LABEL_FACES].second.resize(facesByteCount); //uint8_t will ensure it is a byte addrressing
			memcpy(binMapping[REPO_NODE_MESH_LABEL_FACES].second.data(), &facesLevel1[0], facesByteCount);

			bytesize += sizeof(bName);
		}
		else
		{
			builder.appendBinary(
				REPO_NODE_MESH_LABEL_FACES,
				&facesLevel1[0],
				facesLevel1.size() * sizeof(facesLevel1[0])
				);

			bytesize += facesByteCount;
		}
	}

	if (normals.size() > 0)
	{
		uint64_t normalsByteCount = normals.size() * sizeof(normals[0]);

		if (normalsByteCount + bytesize >= REPO_BSON_MAX_BYTE_SIZE)
		{
			std::string bName = UUIDtoString(uniqueID) + "_normals";
			//inclusion of this binary exceeds the maximum, store separately
			binMapping[REPO_NODE_MESH_LABEL_NORMALS] =
				std::pair<std::string, std::vector<uint8_t>>(bName, std::vector<uint8_t>());
			binMapping[REPO_NODE_MESH_LABEL_NORMALS].second.resize(normalsByteCount); //uint8_t will ensure it is a byte addrressing
			memcpy(binMapping[REPO_NODE_MESH_LABEL_NORMALS].second.data(), &normals[0], normalsByteCount);

			bytesize += sizeof(bName);
		}
		else
		{
			builder.appendBinary(
				REPO_NODE_MESH_LABEL_NORMALS,
				&normals[0],
				normals.size() * sizeof(normals[0]));

			bytesize += normalsByteCount;
		}
	}

	//if (!vertexHash.empty())
	//{
	//	// TODO: Fix this call - needs to be fixed as int conversion is overloaded
	//	//builder << REPO_NODE_LABEL_SHA256 << (long unsigned int)(vertexHash);
	//}

	//--------------------------------------------------------------------------
	// Vertex colors
	if (colors.size())
	{
		uint64_t colorsByteCount = colors.size() * sizeof(colors[0]);

		if (colorsByteCount + bytesize >= REPO_BSON_MAX_BYTE_SIZE)
		{
			std::string bName = UUIDtoString(uniqueID) + "_colors";
			//inclusion of this binary exceeds the maximum, store separately
			binMapping[REPO_NODE_MESH_LABEL_COLORS] =
				std::pair<std::string, std::vector<uint8_t>>(bName, std::vector<uint8_t>());
			binMapping[REPO_NODE_MESH_LABEL_COLORS].second.resize(colorsByteCount); //uint8_t will ensure it is a byte addrressing
			memcpy(binMapping[REPO_NODE_MESH_LABEL_COLORS].second.data(), &colors[0], colorsByteCount);

			bytesize += sizeof(bName);
		}
		else
		{
			builder.appendBinary(
				REPO_NODE_MESH_LABEL_COLORS,
				&colors[0],
				colors.size() * sizeof(colors[0]));
			bytesize += colorsByteCount;
		}
	}

	//--------------------------------------------------------------------------
	// UV channels
	if (uvChannels.size() > 0)
	{
		// Could be unsigned __int64 if BSON had such construct (the closest is only __int64)
		builder << REPO_NODE_MESH_LABEL_UV_CHANNELS_COUNT << (uint32_t)(uvChannels.size());

		std::vector<repo_vector2d_t> concatenated;

		for (auto it = uvChannels.begin(); it != uvChannels.end(); ++it)
		{
			std::vector<repo_vector2d_t> channel = *it;

			std::vector<repo_vector2d_t>::iterator cit;
			for (cit = channel.begin(); cit != channel.end(); ++cit)
			{
				concatenated.push_back(*cit);
			}
		}

		uint64_t uvByteCount = concatenated.size() * sizeof(concatenated[0]);

		if (uvByteCount + bytesize >= REPO_BSON_MAX_BYTE_SIZE)
		{
			std::string bName = UUIDtoString(uniqueID) + "_uv";
			//inclusion of this binary exceeds the maximum, store separately
			binMapping[REPO_NODE_MESH_LABEL_UV_CHANNELS] =
				std::pair<std::string, std::vector<uint8_t>>(bName, std::vector<uint8_t>());
			binMapping[REPO_NODE_MESH_LABEL_UV_CHANNELS].second.resize(uvByteCount); //uint8_t will ensure it is a byte addrressing
			memcpy(binMapping[REPO_NODE_MESH_LABEL_UV_CHANNELS].second.data(), &concatenated[0], uvByteCount);

			bytesize += sizeof(bName);
		}
		else
		{
			builder.appendBinary(
				REPO_NODE_MESH_LABEL_UV_CHANNELS,
				&concatenated[0],
				concatenated.size() * sizeof(concatenated[0]));

			bytesize += uvByteCount;
		}
	}

	return MeshNode(builder.obj(), binMapping);
}
コード例 #4
0
RepoNode MeshNode::cloneAndApplyTransformation(
	const std::vector<float> &matrix) const
{
	std::vector<repo_vector_t> vertices = getVertices();
	std::vector<repo_vector_t> normals = getNormals();

	auto newBigFiles = bigFiles;

	RepoBSONBuilder builder;
	std::vector<repo_vector_t> resultVertice;
	std::vector<repo_vector_t> newBbox;
	if (vertices.size())
	{
		resultVertice.reserve(vertices.size());
		for (const repo_vector_t &v : vertices)
		{
			resultVertice.push_back(multiplyMatVec(matrix, v));
			if (newBbox.size())
			{
				if (resultVertice.back().x < newBbox[0].x)
					newBbox[0].x = resultVertice.back().x;

				if (resultVertice.back().y < newBbox[0].y)
					newBbox[0].y = resultVertice.back().y;

				if (resultVertice.back().z < newBbox[0].z)
					newBbox[0].z = resultVertice.back().z;

				if (resultVertice.back().x > newBbox[1].x)
					newBbox[1].x = resultVertice.back().x;

				if (resultVertice.back().y > newBbox[1].y)
					newBbox[1].y = resultVertice.back().y;

				if (resultVertice.back().z > newBbox[1].z)
					newBbox[1].z = resultVertice.back().z;
			}
			else
			{
				newBbox.push_back(resultVertice.back());
				newBbox.push_back(resultVertice.back());
			}
		}
		if (newBigFiles.find(REPO_NODE_MESH_LABEL_VERTICES) != newBigFiles.end())
		{
			const uint64_t verticesByteCount = resultVertice.size() * sizeof(repo_vector_t);
			newBigFiles[REPO_NODE_MESH_LABEL_VERTICES].second.resize(verticesByteCount);
			memcpy(newBigFiles[REPO_NODE_MESH_LABEL_VERTICES].second.data(), resultVertice.data(), verticesByteCount);
		}
		else
			builder.appendBinary(REPO_NODE_MESH_LABEL_VERTICES, resultVertice.data(), resultVertice.size() * sizeof(repo_vector_t));

		if (normals.size())
		{
			auto matInverse = invertMat(matrix);
			auto worldMat = transposeMat(matInverse);

			std::vector<repo_vector_t> resultNormals;
			resultNormals.reserve(normals.size());
			for (const repo_vector_t &v : normals)
			{
				auto transformedNormal = multiplyMatVecFake3x3(worldMat, v);
				normalize(transformedNormal);
				resultNormals.push_back(transformedNormal);
			}

			if (newBigFiles.find(REPO_NODE_MESH_LABEL_NORMALS) != newBigFiles.end())
			{
				const uint64_t byteCount = resultNormals.size() * sizeof(repo_vector_t);
				newBigFiles[REPO_NODE_MESH_LABEL_NORMALS].second.resize(byteCount);
				memcpy(newBigFiles[REPO_NODE_MESH_LABEL_NORMALS].second.data(), resultNormals.data(), byteCount);
			}
			else
				builder.appendBinary(REPO_NODE_MESH_LABEL_NORMALS, resultNormals.data(), resultNormals.size() * sizeof(repo_vector_t));
		}

		RepoBSONBuilder arrayBuilder, outlineBuilder;
		for (size_t i = 0; i < newBbox.size(); ++i)
		{
			std::vector<float> boundVec = { newBbox[i].x, newBbox[i].y, newBbox[i].z };
			arrayBuilder.appendArray(std::to_string(i), boundVec);
		}

		if (newBbox[0].x > newBbox[1].x || newBbox[0].z > newBbox[1].z || newBbox[0].y > newBbox[1].y)
		{
			repoError << "New bounding box is incorrect!!!";
		}
		builder.appendArray(REPO_NODE_MESH_LABEL_BOUNDING_BOX, arrayBuilder.obj());

		std::vector<float> outline0 = { newBbox[0].x, newBbox[0].y };
		std::vector<float> outline1 = { newBbox[1].x, newBbox[0].y };
		std::vector<float> outline2 = { newBbox[1].x, newBbox[1].y };
		std::vector<float> outline3 = { newBbox[0].x, newBbox[1].y };
		outlineBuilder.appendArray("0", outline0);
		outlineBuilder.appendArray("1", outline1);
		outlineBuilder.appendArray("2", outline2);
		outlineBuilder.appendArray("3", outline3);
		builder.appendArray(REPO_NODE_MESH_LABEL_OUTLINE, outlineBuilder.obj());

		return MeshNode(builder.appendElementsUnique(*this), newBigFiles);
	}
	else
	{
		repoError << "Unable to apply transformation: Cannot find vertices within a mesh!";
		return  RepoNode(this->copy(), bigFiles);
	}
}