std::vector<repoUUID> RepoBSON::getUUIDFieldArray(const std::string &label) const{ std::vector<repoUUID> results; if (hasField(label)) { RepoBSON array = getObjectField(label); if (!array.isEmpty()) { std::set<std::string> fields; array.getFieldNames(fields); std::set<std::string>::iterator it; for (it = fields.begin(); it != fields.end(); ++it) results.push_back(array.getUUIDField(*it)); } else { repoError << "getUUIDFieldArray: field " << label << " is an empty bson or wrong type!"; } } return results; }
TEST(RepoBSONTest, GetFloatArray) { std::vector<float> floatArrIn; size_t size = 10; mongo::BSONObjBuilder builder, arrbuilder; floatArrIn.reserve(size); for (size_t i = 0; i < size; ++i) { floatArrIn.push_back((float)rand()/100.); arrbuilder << std::to_string(i) << floatArrIn[i]; } builder.appendArray("floatarr", arrbuilder.obj()); RepoBSON bson = builder.obj(); std::vector<float> floatArrOut = bson.getFloatArray("floatarr"); EXPECT_EQ(floatArrIn.size(), floatArrOut.size()); for (size_t i = 0; i < size; i++) { EXPECT_EQ(floatArrIn[i], floatArrOut[i]); } //Shouldn't fail if trying to get a uuid field that doesn't exist EXPECT_EQ(0, bson.getFloatArray("hello").size()); EXPECT_EQ(0, testBson.getFloatArray("ice").size()); EXPECT_EQ(0, emptyBson.getFloatArray("ice").size()); }
MeshNode MeshNode::cloneAndUpdateMeshMapping( const std::vector<repo_mesh_mapping_t> &vec, const bool &overwrite) { RepoBSONBuilder builder, mapbuilder; uint32_t index = 0; std::vector<repo_mesh_mapping_t> mappings; RepoBSON mapArray = getObjectField(REPO_NODE_MESH_LABEL_MERGE_MAP); if (!overwrite && !mapArray.isEmpty()) { //if map array isn't empty, find the next index it needs to slot in std::set<std::string> fields; mapArray.getFieldNames(fields); index = fields.size(); } for (uint32_t i = 0; i < vec.size(); ++i) { mapbuilder << std::to_string(index + i) << meshMappingAsBSON(vec[i]); } //append the rest of the array onto this new map bson if (!overwrite) mapbuilder.appendElementsUnique(mapArray); builder.appendArray(REPO_NODE_MESH_LABEL_MERGE_MAP, mapbuilder.obj()); //append the rest of the mesh onto this new bson builder.appendElementsUnique(*this); return MeshNode(builder.obj(), bigFiles); }
bool RepoScene::commitProjectSettings( repo::core::handler::AbstractDatabaseHandler *handler, std::string &errMsg, const std::string &userName) { RepoProjectSettings projectSettings = RepoBSONFactory::makeRepoProjectSettings(projectName, userName); bool success = handler->insertDocument( databaseName, REPO_COLLECTION_SETTINGS, projectSettings, errMsg); if (!success) { //check that the error occurred because of duplicated index (i.e. there's already an entry for projects) RepoBSON criteria = BSON(REPO_LABEL_ID << projectName); RepoBSON doc = handler->findOneByCriteria(databaseName, REPO_COLLECTION_SETTINGS, criteria); //If it already exist, that's fine. success = !doc.isEmpty(); if (success) { repoTrace << "This project already has a project settings entry, skipping project settings commit..."; errMsg.clear(); } } return success; }
TEST(RepoBSONTest, GetUUIDFieldArray) { std::vector<repoUUID> uuids; size_t size = 10; mongo::BSONObjBuilder builder, arrbuilder; uuids.reserve(size); for (size_t i = 0; i < size; ++i) { uuids.push_back(generateUUID()); arrbuilder.appendBinData(std::to_string(i), uuids[i].size(), mongo::bdtUUID, (char*)uuids[i].data); } builder.appendArray("uuid", arrbuilder.obj()); RepoBSON bson = builder.obj(); std::vector<repoUUID> outUUIDS = bson.getUUIDFieldArray("uuid"); EXPECT_EQ(outUUIDS.size(), uuids.size()); for (size_t i = 0; i < size; i++) { EXPECT_EQ(uuids[i], outUUIDS[i]); } //Shouldn't fail if trying to get a uuid field that doesn't exist EXPECT_EQ(0, bson.getUUIDFieldArray("hello").size()); EXPECT_EQ(0, testBson.getUUIDFieldArray("ice").size()); EXPECT_EQ(0, emptyBson.getUUIDFieldArray("ice").size()); }
RepoProjectSettings RepoBSONFactory::makeRepoProjectSettings( const std::string &uniqueProjectName, const std::string &owner, const std::string &type, const std::string &description, const double pinSize, const double avatarHeight, const double visibilityLimit, const double speed, const double zNear, const double zFar) { RepoBSONBuilder builder; //-------------------------------------------------------------------------- // Project name if (!uniqueProjectName.empty()) builder << REPO_LABEL_ID << uniqueProjectName; //-------------------------------------------------------------------------- // Owner if (!owner.empty()) builder << REPO_LABEL_OWNER << owner; //-------------------------------------------------------------------------- // Description if (!description.empty()) builder << REPO_LABEL_DESCRIPTION << description; //-------------------------------------------------------------------------- // Type if (!type.empty()) builder << REPO_LABEL_TYPE << type; //-------------------------------------------------------------------------- // Properties (embedded sub-bson) RepoBSONBuilder propertiesBuilder; if (pinSize != REPO_DEFAULT_PROJECT_PIN_SIZE) propertiesBuilder << REPO_LABEL_PIN_SIZE << pinSize; if (avatarHeight != REPO_DEFAULT_PROJECT_AVATAR_HEIGHT) propertiesBuilder << REPO_LABEL_AVATAR_HEIGHT << avatarHeight; if (visibilityLimit != REPO_DEFAULT_PROJECT_VISIBILITY_LIMIT) propertiesBuilder << REPO_LABEL_VISIBILITY_LIMIT << visibilityLimit; if (speed != REPO_DEFAULT_PROJECT_SPEED) propertiesBuilder << REPO_LABEL_SPEED << speed; if (zNear != REPO_DEFAULT_PROJECT_ZNEAR) propertiesBuilder << REPO_LABEL_ZNEAR << zNear; if (zFar != REPO_DEFAULT_PROJECT_ZFAR) propertiesBuilder << REPO_LABEL_ZFAR << zFar; RepoBSON propertiesBSON = propertiesBuilder.obj(); if (propertiesBSON.isValid() && !propertiesBSON.isEmpty()) builder << REPO_LABEL_PROPERTIES << propertiesBSON; //-------------------------------------------------------------------------- // Add to the parent object return RepoProjectSettings(builder.obj()); }
MetadataNode RepoBSONFactory::makeMetaDataNode( RepoBSON &metadata, const std::string &mimeType, const std::string &name, const std::vector<repoUUID> &parents, const int &apiLevel) { RepoBSONBuilder builder; // Compulsory fields such as _id, type, api as well as path // and optional name auto defaults = appendDefaults(REPO_NODE_TYPE_METADATA, apiLevel, generateUUID(), name, parents); builder.appendElements(defaults); //-------------------------------------------------------------------------- // Media type if (!mimeType.empty()) builder << REPO_LABEL_MEDIA_TYPE << mimeType; //-------------------------------------------------------------------------- // Add metadata subobject if (!metadata.isEmpty()) builder << REPO_NODE_LABEL_METADATA << metadata; return MetadataNode(builder.obj()); }
TEST(RepoBSONFactoryTest, MakeMetaDataNodeTest) { RepoBSON data = BSON("something" << "Something else" << "something2" << "somethingelse2"); std::string mimeType = "application/x-mswrite"; std::string name = "MetaTest"; MetadataNode metaNode = RepoBSONFactory::makeMetaDataNode(data, mimeType, name); EXPECT_FALSE(metaNode.isEmpty()); EXPECT_EQ(name, metaNode.getName()); EXPECT_EQ(metaNode.getTypeAsEnum(), NodeType::METADATA); EXPECT_EQ(mimeType, metaNode.getStringField(REPO_LABEL_MEDIA_TYPE)); EXPECT_EQ(data.toString(), metaNode.getObjectField(REPO_NODE_LABEL_METADATA).toString()); }
TEST(RepoBSONTest, GetTimeStampField) { mongo::BSONObjBuilder builder; mongo::Date_t date = mongo::Date_t(time(NULL) * 1000); builder.append("ts", date); RepoBSON tsBson = builder.obj(); EXPECT_EQ(date.asInt64(), tsBson.getTimeStampField("ts")); //Shouldn't fail if trying to get a uuid field that doesn't exist EXPECT_EQ(-1, tsBson.getTimeStampField("hello")); EXPECT_EQ(-1, testBson.getTimeStampField("ice")); EXPECT_EQ(-1, emptyBson.getTimeStampField("ice")); }
TEST(RepoBSONTest, GetUUIDField) { repoUUID uuid = generateUUID(); mongo::BSONObjBuilder builder; builder.appendBinData("uuid", uuid.size(), mongo::bdtUUID, (char*)uuid.data); RepoBSON test = RepoBSON(builder.obj()); EXPECT_EQ(uuid, test.getUUIDField("uuid")); //Shouldn't fail if trying to get a uuid field that doesn't exist EXPECT_NE(uuid, test.getUUIDField("hello")); EXPECT_NE(uuid, testBson.getUUIDField("ice")); EXPECT_NE(uuid, emptyBson.getUUIDField("ice")); }
std::vector<std::pair<std::string, std::string>> RepoBSON::getFileList() const { std::vector<std::pair<std::string, std::string>> fileList; if (hasField(REPO_LABEL_OVERSIZED_FILES)) { RepoBSON extRefbson = getObjectField(REPO_LABEL_OVERSIZED_FILES); std::set<std::string> fieldNames; extRefbson.getFieldNames(fieldNames); for (const auto &name : fieldNames) { fileList.push_back(std::pair<std::string, std::string>(name, extRefbson.getStringField(name))); } } return fileList; }
TEST(RepoBSONTest, HasOversizeFiles) { std::vector < uint8_t > in; size_t size = 100; in.resize(size); std::unordered_map < std::string, std::pair<std::string, std::vector<uint8_t>>> mapping; mapping["orgRef"] = std::pair<std::string, std::vector<uint8_t>>("blah", in); RepoBSON binBson(testBson, mapping); EXPECT_TRUE(binBson.hasOversizeFiles()); EXPECT_FALSE(testBson.hasOversizeFiles()); EXPECT_FALSE(emptyBson.hasOversizeFiles()); }
std::vector<std::string> RevisionNode::getOrgFiles() const { std::vector<std::string> fileList; if (hasField(REPO_NODE_REVISION_LABEL_REF_FILE)) { RepoBSON arraybson = getObjectField(REPO_NODE_REVISION_LABEL_REF_FILE); std::set<std::string> fields; arraybson.getFieldNames(fields); for (const auto &field : fields) { fileList.push_back(arraybson.getStringField(field)); } } return fileList; }
TEST(RepoBSONTest, GetFileList) { std::vector < uint8_t > in; size_t size = 100; in.resize(size); std::unordered_map < std::string, std::pair<std::string, std::vector<uint8_t>>> mapping; mapping["orgRef"] = std::pair<std::string, std::vector<uint8_t>>("blah", in); RepoBSON binBson(testBson, mapping); auto fileList = binBson.getFileList(); EXPECT_EQ(1, fileList.size()); EXPECT_TRUE(fileList[0].first == "orgRef"); EXPECT_EQ(0, testBson.getFileList().size()); EXPECT_EQ(0, emptyBson.getFileList().size()); }
TEST(RepoBSONTest, HasEmbeddedFieldTest) { EXPECT_FALSE(emptyBson.hasEmbeddedField("hi", "bye")); RepoBSON hasFieldWrongTypeBson(BSON("field" << 1)); EXPECT_FALSE(hasFieldWrongTypeBson.hasEmbeddedField("field", "bye")); RepoBSON expectTrue(BSON("field" << testBson)); EXPECT_TRUE(expectTrue.hasEmbeddedField("field", "ice")); EXPECT_FALSE(expectTrue.hasEmbeddedField("field", "NonExistent")); }
std::vector<repo_vector_t> MeshNode::getBoundingBox(RepoBSON &bbArr) { std::vector<repo_vector_t> bbox; if (!bbArr.isEmpty() && bbArr.couldBeArray()) { size_t nVec = bbArr.nFields(); bbox.reserve(nVec); for (uint32_t i = 0; i < nVec; ++i) { auto bbVectorBson = bbArr.getObjectField(std::to_string(i)); if (!bbVectorBson.isEmpty() && bbVectorBson.couldBeArray()) { int32_t nFields = bbVectorBson.nFields(); if (nFields >= 3) { repo_vector_t vector; vector.x = bbVectorBson.getField("0").Double(); vector.y = bbVectorBson.getField("1").Double(); vector.z = bbVectorBson.getField("2").Double(); bbox.push_back(vector); } else { repoError << "Insufficient amount of elements within bounding box! #fields: " << nFields; } } else { repoError << "Failed to get a vector for bounding box!"; } } } else { repoError << "Failed to fetch bounding box from Mesh Node!"; } return bbox; }
TEST(RepoBSONTest, GetFilesMapping) { std::vector < uint8_t > in; size_t size = 100; in.resize(size); std::unordered_map < std::string, std::pair<std::string, std::vector<uint8_t>>> mapping, outMapping; mapping["orgRef"] = std::pair<std::string, std::vector<uint8_t>>("blah", in); RepoBSON binBson(testBson, mapping); outMapping = binBson.getFilesMapping(); EXPECT_EQ(1, outMapping.size()); EXPECT_FALSE(outMapping.find("orgRef") == outMapping.end()); EXPECT_EQ(0, testBson.getFilesMapping().size()); EXPECT_EQ(0, emptyBson.getFilesMapping().size()); }
bool RepoScene::loadRevision( repo::core::handler::AbstractDatabaseHandler *handler, std::string &errMsg){ bool success = true; if (!handler) { errMsg = "Cannot load revision with an empty database handler"; return false; } RepoBSON bson; repoTrace << "loading revision : " << databaseName << "." << projectName << " head Revision: " << headRevision; if (headRevision){ RepoBSONBuilder critBuilder; critBuilder.append(REPO_NODE_LABEL_SHARED_ID, branch); critBuilder << REPO_NODE_REVISION_LABEL_INCOMPLETE << BSON("$exists" << false); bson = handler->findOneByCriteria(databaseName, projectName + "." + revExt, critBuilder.obj(), REPO_NODE_REVISION_LABEL_TIMESTAMP); repoTrace << "Fetching head of revision from branch " << UUIDtoString(branch); } else{ bson = handler->findOneByUniqueID(databaseName, projectName + "." + revExt, revision); repoTrace << "Fetching revision using unique ID: " << UUIDtoString(revision); } if (bson.isEmpty()){ errMsg = "Failed: cannot find revision document from " + databaseName + "." + projectName + "." + revExt; success = false; } else{ revNode = new RevisionNode(bson); worldOffset = revNode->getCoordOffset(); } return success; }
TEST(RepoBSONTest, CloneAndShrink) { //shrinking a bson without any binary fields should yield an identical bson RepoBSON shrunkBson = testBson.cloneAndShrink(); EXPECT_EQ(testBson, shrunkBson); EXPECT_EQ(testBson.getFilesMapping().size(), shrunkBson.getFilesMapping().size()); mongo::BSONObjBuilder builder; std::vector < uint8_t > in, out, ref; size_t size = 100; in.resize(size); ref.resize(size); builder << "stringTest" << "hello"; builder << "numTest" << 1.35; builder.appendBinData("binDataTest", in.size(), mongo::BinDataGeneral, in.data()); std::unordered_map < std::string, std::pair<std::string, std::vector<uint8_t>>> mapping, outMapping; mapping["orgRef"] = std::pair<std::string, std::vector<uint8_t>>("blah", ref); RepoBSON binBson(builder.obj(), mapping); shrunkBson = binBson.cloneAndShrink(); outMapping = shrunkBson.getFilesMapping(); EXPECT_NE(shrunkBson, binBson); EXPECT_FALSE(shrunkBson.hasField("binDataTest")); EXPECT_EQ(2, outMapping.size()); EXPECT_TRUE(outMapping.find("orgRef") != outMapping.end()); //Check the binary still obtainable EXPECT_TRUE(shrunkBson.getBinaryFieldAsVector("binDataTest", out)); ASSERT_EQ(in.size(), out.size()); for (size_t i = 0; i < out.size(); ++i) { EXPECT_EQ(in[i], out[i]); } //Check the out referenced bigfile is still sane EXPECT_EQ(ref.size(), outMapping["orgRef"].second.size()); for (size_t i = 0; i < ref.size(); ++i) { EXPECT_EQ(ref[i], outMapping["orgRef"].second[i]); } }
TEST(RepoBSONTest, GetField) { EXPECT_EQ(testBson.getField("ice"), testBson.getField("ice")); EXPECT_NE(testBson.getField("ice"), testBson.getField("amount")); EXPECT_EQ("lolly", testBson.getField("ice").str()); EXPECT_EQ(100, testBson.getField("amount").Int()); EXPECT_TRUE(emptyBson.getField("hello").eoo()); }
TEST(RepoBSONTest, AssignOperator) { RepoBSON test = testBson; EXPECT_TRUE(test.toString() == testBson.toString()); EXPECT_EQ(test.getFilesMapping().size(), testBson.getFilesMapping().size()); //Test with bigfile mapping std::vector < uint8_t > in; in.resize(100); std::unordered_map<std::string, std::pair<std::string, std::vector<uint8_t>>> map, mapout; map["testingfile"] = std::pair<std::string, std::vector<uint8_t>>( "field", in); RepoBSON test2(testBson, map); mapout = test2.getFilesMapping(); ASSERT_EQ(mapout.size(), map.size()); auto mapIt = map.begin(); auto mapoutIt = mapout.begin(); for (; mapIt != map.end(); ++mapIt, ++mapoutIt) { EXPECT_EQ(mapIt->first, mapIt->first); EXPECT_EQ(mapIt->second.first, mapIt->second.first); std::vector<uint8_t> dataOut = mapoutIt->second.second; std::vector<uint8_t> dataIn = mapIt->second.second; EXPECT_EQ(dataOut.size(), dataIn.size()); if (dataIn.size()>0) EXPECT_EQ(0, strncmp((char*)&dataOut[0], (char*)&dataIn[0], dataIn.size())); } }
RepoBSON RepoBSON::cloneAndShrink() const { std::set<std::string> fields; std::unordered_map< std::string, std::pair<std::string, std::vector<uint8_t>>> rawFiles(bigFiles.begin(), bigFiles.end()); std::string uniqueIDStr = hasField(REPO_LABEL_ID) ? UUIDtoString(getUUIDField(REPO_LABEL_ID)) : UUIDtoString(generateUUID()); getFieldNames(fields); RepoBSON resultBson = *this; for (const std::string &field : fields) { if (getField(field).type() == ElementType::BINARY) { std::string fileName = uniqueIDStr + "_" + field; rawFiles[field] = std::pair<std::string, std::vector<uint8_t>>(fileName, std::vector<uint8_t>()); getBinaryFieldAsVector(field, &rawFiles[field].second); resultBson = resultBson.removeField(field); } } return RepoBSON(resultBson, rawFiles); }
std::vector<float> RepoBSON::getFloatArray(const std::string &label) const { std::vector<float> results; if (hasField(label)) { RepoBSON array = getObjectField(label); if (!array.isEmpty()) { std::set<std::string> fields; array.getFieldNames(fields); // Pre allocate memory to speed up copying results.reserve(fields.size()); for (auto field : fields) results.push_back(array.getField(field).numberDouble()); } else { repoError << "getFloatArray: field " << label << " is an empty bson or wrong type!"; } } return results; }
TEST(RepoBSONTest, GetEmbeddedDoubleTest) { RepoBSON empty; //Shouldn't fail. EXPECT_EQ(empty.getEmbeddedDouble("something", "somethingElse"), 0); EXPECT_EQ(empty.getEmbeddedDouble("something", "somethingElse", 10), 10); RepoBSON hasFieldWrongTypeBson(BSON("field" << 1)); EXPECT_EQ(hasFieldWrongTypeBson.getEmbeddedDouble("field", "somethingElse"), 0); RepoBSON hasFieldNoEmbeddedField(BSON("field" << testBson)); EXPECT_EQ(hasFieldNoEmbeddedField.getEmbeddedDouble("field", "somethingElse"), 0); RepoBSON hasEmbeddedFieldWrongType(BSON("field" << testBson)); EXPECT_EQ(hasEmbeddedFieldWrongType.getEmbeddedDouble("field", "ice"), 0); RepoBSON expectNumber(BSON("field" << testBson)); EXPECT_EQ(expectNumber.getEmbeddedDouble("field", "amount"), 100); auto innerBson = BSON("amount" << 1.10101); RepoBSON expectNumber2(BSON("field" << innerBson )); EXPECT_EQ(expectNumber2.getEmbeddedDouble("field", "amount"), 1.10101); }
TEST(RepoBSONTest, GetListStringPairField) { std::vector<std::vector<std::string>> vecIn; size_t size = 10; mongo::BSONObjBuilder builder, arrbuilder; vecIn.reserve(size); for (size_t i = 0; i < size; ++i) { int n1 = rand(); int n2 = rand(); vecIn.push_back({ std::to_string(n1), std::to_string(n2) }); arrbuilder << std::to_string(i) << BSON("first" << std::to_string(n1) << "second" << std::to_string(n2) << "third" << 1); } builder.appendArray("bsonArr", arrbuilder.obj()); RepoBSON bson = builder.obj(); std::list<std::pair<std::string, std::string>> vecOut = bson.getListStringPairField("bsonArr", "first", "second"); EXPECT_EQ(vecIn.size(), vecOut.size()); auto listIt = vecOut.begin(); for (size_t i = 0; i < size; i++) { EXPECT_EQ(vecIn[i][0], listIt->first); EXPECT_EQ(vecIn[i][1], listIt->second); ++listIt; } //Shouldn't fail if trying to get a uuid field that doesn't exist EXPECT_EQ(0, bson.getListStringPairField("hello", "first", "third").size()); EXPECT_EQ(0, bson.getListStringPairField("hello", "hi", "bye").size()); EXPECT_EQ(0, bson.getListStringPairField("hello", "first", "second").size()); EXPECT_EQ(0, testBson.getListStringPairField("ice", "first", "second").size()); EXPECT_EQ(0, emptyBson.getListStringPairField("ice", "first", "second").size()); }
TEST(RepoBSONTest, Swap) { RepoBSON test = testBson; //Test with bigfile mapping std::vector < uint8_t > in; in.resize(100); std::unordered_map<std::string, std::pair<std::string, std::vector<uint8_t>>> map, mapout; map["testingfile"] = std::pair<std::string, std::vector<uint8_t>>("blah", in); RepoBSON testDiff_org(BSON("entirely" << "different"), map); RepoBSON testDiff = testDiff_org; EXPECT_TRUE(testDiff_org.toString() == testDiff.toString()); EXPECT_TRUE(testDiff_org.getFilesMapping().size() == testDiff.getFilesMapping().size()); test.swap(testDiff); EXPECT_EQ(testDiff_org.toString(), test.toString()); mapout = test.getFilesMapping(); ASSERT_EQ(map.size(), mapout.size()); auto mapIt = map.begin(); auto mapoutIt = mapout.begin(); for (; mapIt != map.end(); ++mapIt, ++mapoutIt) { EXPECT_EQ(mapIt->first, mapIt->first); EXPECT_EQ(mapIt->second.first, mapIt->second.first); std::vector<uint8_t> dataOut = mapoutIt->second.second; std::vector<uint8_t> dataIn = mapIt->second.second; EXPECT_EQ(dataIn.size(), dataOut.size()); if (dataIn.size()>0) EXPECT_EQ(0, strncmp((char*)dataOut.data(), (char*)dataIn.data(), dataIn.size())); } }
TEST(RepoBSONTest, GetBigBinary) { std::vector < uint8_t > in, out; size_t size = 100; in.resize(size); std::unordered_map < std::string, std::pair<std::string, std::vector<uint8_t>>> mapping; mapping["blah"] = std::pair<std::string, std::vector<uint8_t>>("orgRef", in); RepoBSON binBson(testBson, mapping); out = binBson.getBigBinary("blah"); EXPECT_EQ(in.size(), out.size()); for (size_t i = 0; i < out.size(); ++i) { EXPECT_EQ(in[i], out[i]); } EXPECT_EQ(0, binBson.getBigBinary("hello").size()); EXPECT_EQ(0, binBson.getBigBinary("ice").size()); EXPECT_EQ(0, emptyBson.getBigBinary("ice").size()); }
std::vector<repo_mesh_mapping_t> MeshNode::getMeshMapping() const { std::vector<repo_mesh_mapping_t> mappings; RepoBSON mapArray = getObjectField(REPO_NODE_MESH_LABEL_MERGE_MAP); if (!mapArray.isEmpty()) { std::set<std::string> fields; mapArray.getFieldNames(fields); mappings.resize(fields.size()); for (const auto &name : fields) { repo_mesh_mapping_t mapping; RepoBSON mappingObj = mapArray.getObjectField(name); mapping.mesh_id = mappingObj.getUUIDField(REPO_NODE_MESH_LABEL_MAP_ID); mapping.material_id = mappingObj.getUUIDField(REPO_NODE_MESH_LABEL_MATERIAL_ID); mapping.vertFrom = mappingObj.getField(REPO_NODE_MESH_LABEL_VERTEX_FROM).Int(); mapping.vertTo = mappingObj.getField(REPO_NODE_MESH_LABEL_VERTEX_TO).Int(); mapping.triFrom = mappingObj.getField(REPO_NODE_MESH_LABEL_TRIANGLE_FROM).Int(); mapping.triTo = mappingObj.getField(REPO_NODE_MESH_LABEL_TRIANGLE_TO).Int(); RepoBSON boundingBox = mappingObj.getObjectField(REPO_NODE_MESH_LABEL_BOUNDING_BOX); std::vector<repo_vector_t> bboxVec = getBoundingBox(boundingBox); mapping.min.x = bboxVec[0].x; mapping.min.y = bboxVec[0].y; mapping.min.z = bboxVec[0].z; mapping.max.x = bboxVec[1].x; mapping.max.y = bboxVec[1].y; mapping.max.z = bboxVec[1].z; mappings[std::stoi(name)] = mapping; } } return mappings; }
RepoNode::RepoNode(RepoBSON bson, const std::unordered_map<std::string, std::pair<std::string, std::vector<uint8_t>>> &binMapping) : RepoBSON(bson, binMapping){ if (binMapping.size() == 0) bigFiles = bson.getFilesMapping(); }
bool RepoScene::populate( const GraphType >ype, repo::core::handler::AbstractDatabaseHandler *handler, std::vector<RepoBSON> nodes, std::string &errMsg) { bool success = true; repoGraphInstance &g = gtype == GraphType::OPTIMIZED ? stashGraph : graph; std::unordered_map<repoUUID, RepoNode *, RepoUUIDHasher> nodesBySharedID; for (std::vector<RepoBSON>::const_iterator it = nodes.begin(); it != nodes.end(); ++it) { RepoBSON obj = *it; RepoNode *node = NULL; std::string nodeType = obj.getField(REPO_NODE_LABEL_TYPE).str(); if (REPO_NODE_TYPE_TRANSFORMATION == nodeType) { node = new TransformationNode(obj); g.transformations.insert(node); } else if (REPO_NODE_TYPE_MESH == nodeType) { node = new MeshNode(obj); g.meshes.insert(node); } else if (REPO_NODE_TYPE_MATERIAL == nodeType) { node = new MaterialNode(obj); g.materials.insert(node); } else if (REPO_NODE_TYPE_TEXTURE == nodeType) { node = new TextureNode(obj); g.textures.insert(node); } else if (REPO_NODE_TYPE_CAMERA == nodeType) { node = new CameraNode(obj); g.cameras.insert(node); } else if (REPO_NODE_TYPE_REFERENCE == nodeType) { node = new ReferenceNode(obj); g.references.insert(node); } else if (REPO_NODE_TYPE_METADATA == nodeType) { node = new MetadataNode(obj); g.metadata.insert(node); } else{ //UNKNOWN TYPE - instantiate it with generic RepoNode node = new RepoNode(obj); g.unknowns.insert(node); } success &= addNodeToMaps(gtype, node, errMsg); } //Node Iteration //deal with References RepoNodeSet::iterator refIt; //Make sure it is propagated into the repoScene if it exists in revision node if (g.references.size()) worldOffset.clear(); for (const auto &node : g.references) { ReferenceNode* reference = (ReferenceNode*)node; //construct a new RepoScene with the information from reference node and append this g to the Scene std::string spDbName = reference->getDatabaseName(); if (spDbName.empty()) spDbName = databaseName; RepoScene *refg = new RepoScene(spDbName, reference->getProjectName(), sceneExt, revExt); if (reference->useSpecificRevision()) refg->setRevision(reference->getRevisionID()); else refg->setBranch(reference->getRevisionID()); //Try to load the stash first, if fail, try scene. if (refg->loadStash(handler, errMsg) || refg->loadScene(handler, errMsg)) { g.referenceToScene[reference->getSharedID()] = refg; auto refOffset = refg->getWorldOffset(); if (!worldOffset.size()) { worldOffset = refOffset; } } else{ repoWarning << "Failed to load reference node for ref ID" << reference->getUniqueID() << ": " << errMsg; } } repoTrace << "World Offset = [" << worldOffset[0] << " , " << worldOffset[1] << ", " << worldOffset[2] << " ]"; //Now that we know the world Offset, make sure the referenced scenes are shifted accordingly for (const auto &node : g.references) { ReferenceNode* reference = (ReferenceNode*)node; auto parent = reference->getParentIDs().at(0); auto refScene = g.referenceToScene[reference->getSharedID()]; auto refOffset = refScene->getWorldOffset(); //Back to world coord of subProject std::vector<std::vector<float>> backToSubWorld = { { 1., 0., 0., (float)refOffset[0] }, { 0., 1., 0., (float)refOffset[1] }, { 0., 0., 1., (float)refOffset[2] }, { 0., 0., 0., 1 } }; std::vector<std::vector<float>> toFedWorldTrans = { { 1., 0., 0., (float)-worldOffset[0] }, { 0., 1., 0., (float)-worldOffset[1] }, { 0., 0., 1., (float)-worldOffset[2] }, { 0., 0., 0., 1. } }; //parent - ref //Becomes: toFedWorld - parent - toSubWorld - ref auto parentNode = getNodeBySharedID(GraphType::DEFAULT, parent); auto grandParent = parentNode->getParentIDs().at(0); auto grandParentNode = getNodeBySharedID(GraphType::DEFAULT, grandParent); auto toFedWorld = new TransformationNode(RepoBSONFactory::makeTransformationNode(toFedWorldTrans, "trans", { grandParent })); auto toSubWorld = new TransformationNode(RepoBSONFactory::makeTransformationNode(backToSubWorld, "trans", { parent })); std::vector<RepoNode*> newNodes; newNodes.push_back(toFedWorld); newNodes.push_back(toSubWorld); addNodes(newNodes); addInheritance(GraphType::DEFAULT, toSubWorld, reference); addInheritance(GraphType::DEFAULT, toFedWorld, parentNode); abandonChild(GraphType::DEFAULT, grandParent, parentNode); abandonChild(GraphType::DEFAULT, parent, reference); newModified.clear(); //We're still loading the scene, there shouldn't be anything here anyway. } return success; }