From c9b140bd6b28cfbb4a90fcfafac704de7a000852 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Wed, 9 Dec 2015 11:59:58 +0100 Subject: [PATCH] Semi-working entity loading from XML files! --- include/Engine/Core/EntityXMLFile.h | 3 +- resources/Schema/Entities/Test.xml | 10 +- resources/Schema/Types/Entity.xsd | 1 + src/Engine/Core/EntityXMLFile.cpp | 133 ++++++++++++++------ src/Engine/Rendering/RawModel.cpp | 32 ++--- src/Engine/Rendering/RenderQueueFactory.cpp | 5 +- 6 files changed, 121 insertions(+), 63 deletions(-) diff --git a/include/Engine/Core/EntityXMLFile.h b/include/Engine/Core/EntityXMLFile.h index d7c34e3a..6fa71dad 100644 --- a/include/Engine/Core/EntityXMLFile.h +++ b/include/Engine/Core/EntityXMLFile.h @@ -132,9 +132,10 @@ private: void parseComponentInfo(); void parseDefaults(); void predictComponentAllocation(); - void parseEntityGraph(); + void parseEntityGraph(World* world, xercesc::DOMElement* parent, EntityID parentEntity); std::size_t getTypeStride(std::string typeName); float getFloatAttribute(const xercesc::DOMElement* element, const char* attribute) const; + void writeData(const xercesc::DOMElement* element, std::string typeName, char* outData); }; #endif \ No newline at end of file diff --git a/resources/Schema/Entities/Test.xml b/resources/Schema/Entities/Test.xml index 8ca6b684..9b379495 100644 --- a/resources/Schema/Entities/Test.xml +++ b/resources/Schema/Entities/Test.xml @@ -3,10 +3,12 @@ - - - + + + + Models/Core/UnitSphere.obj + 12 11.11 @@ -14,7 +16,5 @@ - - \ No newline at end of file diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 2f0a6311..bd7de5a3 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -11,6 +11,7 @@ + diff --git a/src/Engine/Core/EntityXMLFile.cpp b/src/Engine/Core/EntityXMLFile.cpp index f64faeb6..b96e366e 100644 --- a/src/Engine/Core/EntityXMLFile.cpp +++ b/src/Engine/Core/EntityXMLFile.cpp @@ -67,7 +67,8 @@ void EntityXMLFile::PopulateWorld(World* world) } // 4. Parse entity hierarchy - //parseEntityGraph(); + auto root = m_DOMDocument->getDocumentElement(); + parseEntityGraph(world, root, 0); } @@ -261,41 +262,7 @@ void EntityXMLFile::parseDefaults() std::string fieldType = ci.second.FieldTypes.at(fieldName); unsigned int fieldOffset = ci.second.FieldOffsets.at(fieldName); - - XSValue::DataType dataType = XSValue::getDataType(XSTR(fieldType.c_str())); - if (dataType == XSValue::DataType::dt_MAXCOUNT) { - if (fieldType == "Vector") { - glm::vec3 vec; - vec.x = getFloatAttribute(fieldElement, "X"); - vec.y = getFloatAttribute(fieldElement, "Y"); - vec.z = getFloatAttribute(fieldElement, "Z"); - memcpy(ci.second.Defaults.get() + fieldOffset, reinterpret_cast(&vec), getTypeStride(fieldType)); - } else if (fieldType == "Color") { - glm::vec4 vec; - vec.r = getFloatAttribute(fieldElement, "R"); - vec.g = getFloatAttribute(fieldElement, "G"); - vec.b = getFloatAttribute(fieldElement, "B"); - vec.a = getFloatAttribute(fieldElement, "A"); - memcpy(ci.second.Defaults.get() + fieldOffset, reinterpret_cast(&vec), getTypeStride(fieldType)); - } else if (fieldType == "Quaternion") { - glm::quat q; - q.x = getFloatAttribute(fieldElement, "X"); - q.y = getFloatAttribute(fieldElement, "Y"); - q.z = getFloatAttribute(fieldElement, "Z"); - q.w = getFloatAttribute(fieldElement, "W"); - memcpy(ci.second.Defaults.get() + fieldOffset, reinterpret_cast(&q), getTypeStride(fieldType)); - } - } else if (dataType == XSValue::DataType::dt_string) { - char* str = XMLString::transcode(fieldElement->getTextContent()); - std::string standardString(str); - //new (ci.second.Defaults.get() + fieldOffset) std::string(str); - XMLString::release(&str); - memcpy(ci.second.Defaults.get() + fieldOffset, &standardString, getTypeStride(fieldType)); - } else { - XSValue::Status status; - XSValue* val = XSValue::getActualValue(fieldElement->getTextContent(), dataType, status); - memcpy(ci.second.Defaults.get() + fieldOffset, reinterpret_cast(&val->fData.fValue), getTypeStride(fieldType)); - } + writeData(fieldElement, fieldType, ci.second.Defaults.get() + fieldOffset); } } } @@ -334,11 +301,56 @@ void EntityXMLFile::predictComponentAllocation() } } -void EntityXMLFile::parseEntityGraph() +void EntityXMLFile::parseEntityGraph(World* world, xercesc::DOMElement* element, EntityID parentEntity) { - //using namespace xercesc; + using namespace xercesc; - //auto root = m_DOMDocument->getDocumentElement(); + // Create entity + EntityID entity = world->CreateEntity(parentEntity); + LOG_DEBUG("Created entity %i, parent %i", entity, parentEntity); + + // Add components + auto components = m_DOMDocument->evaluate(XSTR("Components/*"), element, nullptr, DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, nullptr); + for (int i = 0; i < components->getSnapshotLength(); i++) { + components->snapshotItem(i); + auto componentElement = dynamic_cast(components->getNodeValue()); + std::string componentName = XSTR(componentElement->getLocalName()); + auto& ci = m_ComponentInfo.at(componentName); + + // Attach the component + auto c = world->AttachComponent(entity, componentName); + LOG_DEBUG("Attached %s component", componentName.c_str()); + + // Write field data + auto fields = componentElement->getChildNodes(); + for (int j = 0; j < fields->getLength(); ++j) { + auto fieldNode = fields->item(j); + auto nodeType = fieldNode->getNodeType(); + if (nodeType != DOMNode::ELEMENT_NODE) { + continue; + } + auto field = dynamic_cast(fields->item(j)); + //const XMLCh* value = fields->item(j)->getTextContent(); + std::string fieldName(XSTR(field->getLocalName())); + if (ci.FieldTypes.find(fieldName) == ci.FieldTypes.end()) { + std::cout << "Warning: Component \"" << componentName << "\" contains invalid field \"" << fieldName << "\". Skipping." << std::endl; + continue; + } + + std::string fieldType = ci.FieldTypes.at(fieldName); + unsigned int fieldOffset = ci.FieldOffsets.at(fieldName); + std::string fieldValue(XSTR(field->getTextContent())); + LOG_DEBUG(" %s %s = %s", fieldType.c_str(), fieldName.c_str(), fieldValue.c_str()); + writeData(field, fieldType, c.Data + fieldOffset); + } + } + + // Recurse children + auto children = m_DOMDocument->evaluate(XSTR("Children/Entity"), element, nullptr, DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, nullptr); + for (int i = 0; i < children->getSnapshotLength(); i++) { + children->snapshotItem(i); + parseEntityGraph(world, dynamic_cast(children->getNodeValue()), entity); + } //auto components = m_DOMDocument->getElementsByTagNameNS(XSTR("components"), XSTR("*")); //for (int i = 0; i < components->getLength(); ++i) { @@ -425,4 +437,45 @@ float EntityXMLFile::getFloatAttribute(const xercesc::DOMElement* element, const } else { return val->fData.fValue.f_float; } -} \ No newline at end of file +} + +void EntityXMLFile::writeData(const xercesc::DOMElement* element, std::string typeName, char* outData) +{ + using namespace xercesc; + + XSValue::DataType dataType = XSValue::getDataType(XSTR(typeName.c_str())); + if (dataType == XSValue::DataType::dt_MAXCOUNT) { + if (typeName == "Vector") { + glm::vec3 vec; + vec.x = getFloatAttribute(element, "X"); + vec.y = getFloatAttribute(element, "Y"); + vec.z = getFloatAttribute(element, "Z"); + memcpy(outData, reinterpret_cast(&vec), getTypeStride(typeName)); + } else if (typeName == "Color") { + glm::vec4 vec; + vec.r = getFloatAttribute(element, "R"); + vec.g = getFloatAttribute(element, "G"); + vec.b = getFloatAttribute(element, "B"); + vec.a = getFloatAttribute(element, "A"); + memcpy(outData, reinterpret_cast(&vec), getTypeStride(typeName)); + } else if (typeName == "Quaternion") { + glm::quat q; + q.x = getFloatAttribute(element, "X"); + q.y = getFloatAttribute(element, "Y"); + q.z = getFloatAttribute(element, "Z"); + q.w = getFloatAttribute(element, "W"); + memcpy(outData, reinterpret_cast(&q), getTypeStride(typeName)); + } + } else if (dataType == XSValue::DataType::dt_string) { + char* str = XMLString::transcode(element->getTextContent()); + std::string standardString(str); + new (outData) std::string(str); + XMLString::release(&str); + //memcpy(outData, reinterpret_cast(&standardString), getTypeStride(typeName)); + } else { + XSValue::Status status; + XSValue* val = XSValue::getActualValue(element->getTextContent(), dataType, status); + memcpy(outData, reinterpret_cast(&val->fData.fValue), getTypeStride(typeName)); + } +} + diff --git a/src/Engine/Rendering/RawModel.cpp b/src/Engine/Rendering/RawModel.cpp index c14fec08..962c278f 100644 --- a/src/Engine/Rendering/RawModel.cpp +++ b/src/Engine/Rendering/RawModel.cpp @@ -34,10 +34,10 @@ RawModel::RawModel(std::string fileName) numIndices += face.mNumIndices; } } - LOG_DEBUG("Vertex count %i", numVertices); - LOG_DEBUG("Index count %i", numIndices); + //LOG_DEBUG("Vertex count %i", numVertices); + //LOG_DEBUG("Index count %i", numIndices); - LOG_DEBUG("Model has %i embedded textures", scene->mNumTextures); + //LOG_DEBUG("Model has %i embedded textures", scene->mNumTextures); std::vector> boneInfo; std::map boneNameMapping; @@ -132,35 +132,35 @@ RawModel::RawModel(std::string fileName) matGroup.EndIndex = m_Indices.size() - 1; // Material shininess material->Get(AI_MATKEY_SHININESS, matGroup.Shininess); - LOG_DEBUG("Shininess: %f", matGroup.Shininess); + //LOG_DEBUG("Shininess: %f", matGroup.Shininess); // Diffuse texture - LOG_DEBUG("%i diffuse textures found", material->GetTextureCount(aiTextureType_DIFFUSE)); + //LOG_DEBUG("%i diffuse textures found", material->GetTextureCount(aiTextureType_DIFFUSE)); if (material->GetTextureCount(aiTextureType_DIFFUSE)) { aiString path; aiTextureMapping mapping; material->GetTexture(aiTextureType_DIFFUSE, 0, &path, &mapping); std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string(); - LOG_DEBUG("Diffuse texture: %s", absolutePath.c_str()); + //LOG_DEBUG("Diffuse texture: %s", absolutePath.c_str()); matGroup.Texture = std::shared_ptr(ResourceManager::Load(absolutePath)); } // Normal map - LOG_DEBUG("%i normal maps found", material->GetTextureCount(aiTextureType_HEIGHT)); + //LOG_DEBUG("%i normal maps found", material->GetTextureCount(aiTextureType_HEIGHT)); if (material->GetTextureCount(aiTextureType_HEIGHT)) { aiString path; aiTextureMapping mapping; material->GetTexture(aiTextureType_HEIGHT, 0, &path, &mapping); std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string(); - LOG_DEBUG("Normal map: %s", absolutePath.c_str()); + //LOG_DEBUG("Normal map: %s", absolutePath.c_str()); matGroup.NormalMap = std::shared_ptr(ResourceManager::Load(absolutePath)); } // Specular map - LOG_DEBUG("%i specular maps found", material->GetTextureCount(aiTextureType_SPECULAR)); + //LOG_DEBUG("%i specular maps found", material->GetTextureCount(aiTextureType_SPECULAR)); if (material->GetTextureCount(aiTextureType_SPECULAR)) { aiString path; aiTextureMapping mapping; material->GetTexture(aiTextureType_SPECULAR, 0, &path, &mapping); std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string(); - LOG_DEBUG("Specular map: %s", absolutePath.c_str()); + //LOG_DEBUG("Specular map: %s", absolutePath.c_str()); matGroup.SpecularMap = std::shared_ptr(ResourceManager::Load(absolutePath)); } TextureGroups.push_back(matGroup); @@ -216,20 +216,20 @@ RawModel::RawModel(std::string fileName) m_Skeleton = new Skeleton(); CreateSkeleton(boneInfo, boneNameMapping, scene->mRootNode, -1); int numBones = m_Skeleton->Bones.size(); - LOG_DEBUG("Bone count: %i", numBones); + //LOG_DEBUG("Bone count: %i", numBones); if (numBones > 0) { m_Skeleton->PrintSkeleton(); } } // Animations - LOG_DEBUG("Animation count: %i", scene->mNumAnimations); + //LOG_DEBUG("Animation count: %i", scene->mNumAnimations); for (int i = 0; i < scene->mNumAnimations; ++i) { auto animation = scene->mAnimations[i]; std::string animationName = animation->mName.C_Str(); - LOG_DEBUG("Animation: %s", animationName.c_str()); - LOG_DEBUG("Duration: %f", animation->mDuration); - LOG_DEBUG("Ticks per second: %f", animation->mTicksPerSecond); + //LOG_DEBUG("Animation: %s", animationName.c_str()); + //LOG_DEBUG("Duration: %f", animation->mDuration); + //LOG_DEBUG("Ticks per second: %f", animation->mTicksPerSecond); Skeleton::Animation skelAnim; skelAnim.Name = animationName; @@ -303,7 +303,7 @@ void RawModel::CreateSkeleton(std::vector> &b // Find the bone by name in the bone info list if (boneNameMapping.find(nodeName) == boneNameMapping.end()) { - LOG_DEBUG("Node \"%s\" was not a bone", nodeName.c_str()); + //LOG_DEBUG("Node \"%s\" was not a bone", nodeName.c_str()); } else { glm::mat4 offsetMatrix; int ID = boneNameMapping[nodeName]; diff --git a/src/Engine/Rendering/RenderQueueFactory.cpp b/src/Engine/Rendering/RenderQueueFactory.cpp index 9a7d89a1..aec304ed 100644 --- a/src/Engine/Rendering/RenderQueueFactory.cpp +++ b/src/Engine/Rendering/RenderQueueFactory.cpp @@ -36,12 +36,15 @@ glm::vec3 GetAbsolutePosition(World* world, ComponentWrapper transformComponent) void RenderQueueFactory::FillModels(World* world, RenderQueue* renderQueue) { for(auto& modelC : world->GetComponents("Model")) { - ModelJob job; std::string resource = modelC["Resource"]; + if (resource.empty()) { + continue; + } glm::vec4 color = modelC["Color"]; Model* model = ResourceManager::Load(resource); for (auto texGroup : model->TextureGroups) { + ModelJob job; job.TextureID = (texGroup.Texture) ? texGroup.Texture->ResourceID : 0; job.DiffuseTexture = texGroup.Texture.get(); job.NormalTexture = texGroup.NormalMap.get();