diff --git a/application/application.pro b/application/application.pro index dbb070e0..d68cfe57 100644 --- a/application/application.pro +++ b/application/application.pro @@ -121,6 +121,11 @@ HEADERS += sources/debug.h SOURCES += sources/debug.cc HEADERS += sources/document.h SOURCES += sources/document.cc +SOURCES += sources/document_bone.cc +SOURCES += sources/document_component.cc +SOURCES += sources/document_edge.cc +SOURCES += sources/document_node.cc +SOURCES += sources/document_part.cc HEADERS += sources/document_saver.h SOURCES += sources/document_saver.cc HEADERS += sources/document_window.h diff --git a/application/sources/document.cc b/application/sources/document.cc index 99d80f2a..b84b26e9 100644 --- a/application/sources/document.cc +++ b/application/sources/document.cc @@ -20,20 +20,6 @@ unsigned long Document::m_maxSnapshot = 1000; -Document::Bone::Bone(const dust3d::Uuid& withId) -{ - id = withId.isNull() ? dust3d::Uuid::createUuid() : withId; -} - -void Document::Node::setRadius(float toRadius) -{ - if (toRadius < MeshGenerator::m_minimalRadius) - toRadius = MeshGenerator::m_minimalRadius; - else if (toRadius > 1) - toRadius = 1; - radius = toRadius; -} - Document::Document() { } diff --git a/application/sources/document.h b/application/sources/document.h index 19fe69c7..e60173c9 100644 --- a/application/sources/document.h +++ b/application/sources/document.h @@ -57,84 +57,21 @@ public: class Node { public: - Node(const dust3d::Uuid& withId = dust3d::Uuid()) - { - id = withId.isNull() ? dust3d::Uuid::createUuid() : withId; - } + Node(const dust3d::Uuid& withId = dust3d::Uuid()); void setRadius(float toRadius); - void setCutRotation(float toRotation) - { - if (toRotation < -1) - toRotation = -1; - else if (toRotation > 1) - toRotation = 1; - cutRotation = toRotation; - hasCutFaceSettings = true; - } - void setCutFace(dust3d::CutFace face) - { - cutFace = face; - cutFaceLinkedId = dust3d::Uuid(); - hasCutFaceSettings = true; - } - void setCutFaceLinkedId(const dust3d::Uuid& linkedId) - { - if (linkedId.isNull()) { - clearCutFaceSettings(); - return; - } - cutFace = dust3d::CutFace::UserDefined; - cutFaceLinkedId = linkedId; - hasCutFaceSettings = true; - } - void clearCutFaceSettings() - { - cutFace = dust3d::CutFace::Quad; - cutFaceLinkedId = dust3d::Uuid(); - cutRotation = 0; - hasCutFaceSettings = false; - } - float getX(bool rotated = false) const - { - if (rotated) - return m_y; - return m_x; - } - float getY(bool rotated = false) const - { - if (rotated) - return m_x; - return m_y; - } - float getZ(bool rotated = false) const - { - (void)rotated; - return m_z; - } - void setX(float x) - { - m_x = x; - } - void setY(float y) - { - m_y = y; - } - void setZ(float z) - { - m_z = z; - } - void addX(float x) - { - m_x += x; - } - void addY(float y) - { - m_y += y; - } - void addZ(float z) - { - m_z += z; - } + void setCutRotation(float toRotation); + void setCutFace(dust3d::CutFace face); + void setCutFaceLinkedId(const dust3d::Uuid& linkedId); + void clearCutFaceSettings(); + float getX(bool rotated = false) const; + float getY(bool rotated = false) const; + float getZ(bool rotated = false) const; + void setX(float x); + void setY(float y); + void setZ(float z); + void addX(float x); + void addY(float y); + void addZ(float z); dust3d::Uuid id; dust3d::Uuid partId; QString name; @@ -155,20 +92,12 @@ public: class Edge { public: - Edge(const dust3d::Uuid& withId = dust3d::Uuid()) - { - id = withId.isNull() ? dust3d::Uuid::createUuid() : withId; - } + Edge(const dust3d::Uuid& withId = dust3d::Uuid()); dust3d::Uuid id; dust3d::Uuid partId; QString name; std::vector nodeIds; - dust3d::Uuid neighborOf(dust3d::Uuid nodeId) const - { - if (nodeIds.size() != 2) - return dust3d::Uuid(); - return nodeIds[0] == nodeId ? nodeIds[1] : nodeIds[0]; - } + dust3d::Uuid neighborOf(dust3d::Uuid nodeId) const; }; class Part { @@ -201,201 +130,39 @@ public: bool countershaded; bool smooth; dust3d::Uuid colorImageId; - Part(const dust3d::Uuid& withId = dust3d::Uuid()) - : visible(true) - , locked(false) - , subdived(false) - , disabled(false) - , xMirrored(false) - , deformThickness(1.0) - , deformWidth(1.0) - , deformUnified(false) - , rounded(false) - , chamfered(false) - , color(Qt::white) - , hasColor(false) - , dirty(true) - , cutRotation(0.0) - , cutFace(dust3d::CutFace::Quad) - , target(dust3d::PartTarget::Model) - , colorSolubility(0.0) - , metalness(0.0) - , roughness(1.0) - , hollowThickness(0.0) - , countershaded(false) - , smooth(false) - { - id = withId.isNull() ? dust3d::Uuid::createUuid() : withId; - } - bool hasPolyFunction() const - { - return dust3d::PartTarget::Model == target; - } - bool hasSmoothFunction() const - { - return dust3d::PartTarget::Model == target; - } - bool hasSubdivFunction() const - { - return dust3d::PartTarget::Model == target; - } - bool hasRoundEndFunction() const - { - return dust3d::PartTarget::Model == target; - } - bool hasMirrorFunction() const - { - return dust3d::PartTarget::Model == target; - } - bool hasChamferFunction() const - { - return dust3d::PartTarget::Model == target; - } - bool hasRotationFunction() const - { - return dust3d::PartTarget::Model == target; - } - bool hasHollowFunction() const - { - return dust3d::PartTarget::Model == target; - } - bool hasCutFaceFunction() const - { - return dust3d::PartTarget::Model == target; - } - bool hasLayerFunction() const - { - return dust3d::PartTarget::Model == target; - } - bool hasTargetFunction() const - { - return true; - } - bool hasBaseFunction() const - { - return dust3d::PartTarget::Model == target; - } - bool hasCombineModeFunction() const - { - return dust3d::PartTarget::Model == target; - } - bool hasDeformFunction() const - { - return dust3d::PartTarget::Model == target; - } - bool hasColorFunction() const - { - return dust3d::PartTarget::Model == target; - } - void setDeformThickness(float toThickness) - { - if (toThickness < 0) - toThickness = 0; - else if (toThickness > 2) - toThickness = 2; - deformThickness = toThickness; - } - void setDeformWidth(float toWidth) - { - if (toWidth < 0) - toWidth = 0; - else if (toWidth > 2) - toWidth = 2; - deformWidth = toWidth; - } - void setCutRotation(float toRotation) - { - if (toRotation < -1) - toRotation = -1; - else if (toRotation > 1) - toRotation = 1; - cutRotation = toRotation; - } - void setCutFace(dust3d::CutFace face) - { - cutFace = face; - cutFaceLinkedId = dust3d::Uuid(); - } - void setCutFaceLinkedId(const dust3d::Uuid& linkedId) - { - if (linkedId.isNull()) { - setCutFace(dust3d::CutFace::Quad); - return; - } - cutFace = dust3d::CutFace::UserDefined; - cutFaceLinkedId = linkedId; - } - bool deformThicknessAdjusted() const - { - return fabs(deformThickness - 1.0) >= 0.01; - } - bool deformWidthAdjusted() const - { - return fabs(deformWidth - 1.0) >= 0.01; - } - bool deformAdjusted() const - { - return deformThicknessAdjusted() || deformWidthAdjusted() || deformUnified; - } - bool colorSolubilityAdjusted() const - { - return fabs(colorSolubility - 0.0) >= 0.01; - } - bool metalnessAdjusted() const - { - return fabs(metalness - 0.0) >= 0.01; - } - bool roughnessAdjusted() const - { - return fabs(roughness - 1.0) >= 0.01; - } - bool cutRotationAdjusted() const - { - return fabs(cutRotation - 0.0) >= 0.01; - } - bool hollowThicknessAdjusted() const - { - return fabs(hollowThickness - 0.0) >= 0.01; - } - bool cutFaceAdjusted() const - { - return cutFace != dust3d::CutFace::Quad; - } - bool cutAdjusted() const - { - return cutRotationAdjusted() || cutFaceAdjusted() || hollowThicknessAdjusted(); - } - bool isEditVisible() const - { - return visible && !disabled; - } - void copyAttributes(const Part& other) - { - visible = other.visible; - locked = other.locked; - subdived = other.subdived; - disabled = other.disabled; - xMirrored = other.xMirrored; - deformThickness = other.deformThickness; - deformWidth = other.deformWidth; - rounded = other.rounded; - chamfered = other.chamfered; - color = other.color; - hasColor = other.hasColor; - cutRotation = other.cutRotation; - cutFace = other.cutFace; - cutFaceLinkedId = other.cutFaceLinkedId; - componentId = other.componentId; - dirty = other.dirty; - target = other.target; - colorSolubility = other.colorSolubility; - countershaded = other.countershaded; - metalness = other.metalness; - roughness = other.roughness; - deformUnified = other.deformUnified; - smooth = other.smooth; - hollowThickness = other.hollowThickness; - } + Part(const dust3d::Uuid& withId = dust3d::Uuid()); + bool hasPolyFunction() const; + bool hasSmoothFunction() const; + bool hasSubdivFunction() const; + bool hasRoundEndFunction() const; + bool hasMirrorFunction() const; + bool hasChamferFunction() const; + bool hasRotationFunction() const; + bool hasHollowFunction() const; + bool hasCutFaceFunction() const; + bool hasLayerFunction() const; + bool hasTargetFunction() const; + bool hasBaseFunction() const; + bool hasCombineModeFunction() const; + bool hasDeformFunction() const; + bool hasColorFunction() const; + void setDeformThickness(float toThickness); + void setDeformWidth(float toWidth); + void setCutRotation(float toRotation); + void setCutFace(dust3d::CutFace face); + void setCutFaceLinkedId(const dust3d::Uuid& linkedId); + bool deformThicknessAdjusted() const; + bool deformWidthAdjusted() const; + bool deformAdjusted() const; + bool colorSolubilityAdjusted() const; + bool metalnessAdjusted() const; + bool roughnessAdjusted() const; + bool cutRotationAdjusted() const; + bool hollowThicknessAdjusted() const; + bool cutFaceAdjusted() const; + bool cutAdjusted() const; + bool isEditVisible() const; + void copyAttributes(const Part& other); private: Q_DISABLE_COPY(Part); @@ -403,18 +170,20 @@ public: class Component { public: - Component() - { - } - Component(const dust3d::Uuid& withId, const QString& linkData = QString(), const QString& linkDataType = QString()) - { - id = withId.isNull() ? dust3d::Uuid::createUuid() : withId; - if (!linkData.isEmpty()) { - if ("partId" == linkDataType) { - linkToPartId = dust3d::Uuid(linkData.toUtf8().constData()); - } - } - } + Component(); + Component(const dust3d::Uuid& withId, const QString& linkData = QString(), const QString& linkDataType = QString()); + QString linkData() const; + QString linkDataType() const; + void addChild(dust3d::Uuid childId); + void replaceChildWithOthers(const dust3d::Uuid& childId, const std::vector& others); + void removeChild(dust3d::Uuid childId); + void replaceChild(dust3d::Uuid childId, dust3d::Uuid newId); + void moveChildUp(dust3d::Uuid childId); + void moveChildDown(dust3d::Uuid childId); + void moveChildToTop(dust3d::Uuid childId); + void moveChildToBottom(dust3d::Uuid childId); + void updatePreviewMesh(std::unique_ptr mesh); + ModelMesh* takePreviewMesh() const; dust3d::Uuid id; QString name; dust3d::Uuid linkToPartId; @@ -427,131 +196,6 @@ public: std::unique_ptr previewImage; bool isPreviewImageDecorationObsolete = false; QPixmap previewPixmap; - QString linkData() const - { - return linkToPartId.isNull() ? QString() : QString(linkToPartId.toString().c_str()); - } - QString linkDataType() const - { - return linkToPartId.isNull() ? QString() : QString("partId"); - } - void addChild(dust3d::Uuid childId) - { - if (m_childrenIdSet.find(childId) != m_childrenIdSet.end()) - return; - m_childrenIdSet.insert(childId); - childrenIds.push_back(childId); - } - void replaceChildWithOthers(const dust3d::Uuid& childId, const std::vector& others) - { - if (m_childrenIdSet.find(childId) == m_childrenIdSet.end()) - return; - m_childrenIdSet.erase(childId); - std::vector candidates; - for (const auto& it : others) { - if (m_childrenIdSet.find(it) == m_childrenIdSet.end()) { - m_childrenIdSet.insert(it); - candidates.emplace_back(it); - } - } - for (size_t i = 0; i < childrenIds.size(); ++i) { - if (childId == childrenIds[i]) { - size_t newAddSize = candidates.size() - 1; - if (newAddSize > 0) { - size_t oldSize = childrenIds.size(); - childrenIds.resize(childrenIds.size() + newAddSize); - for (int j = (int)oldSize - 1; j > (int)i; --j) { - childrenIds[j + newAddSize] = childrenIds[j]; - } - } - for (size_t k = 0; k < candidates.size(); ++k) - childrenIds[i + k] = candidates[k]; - break; - } - } - } - void removeChild(dust3d::Uuid childId) - { - if (m_childrenIdSet.find(childId) == m_childrenIdSet.end()) - return; - m_childrenIdSet.erase(childId); - auto findResult = std::find(childrenIds.begin(), childrenIds.end(), childId); - if (findResult != childrenIds.end()) - childrenIds.erase(findResult); - } - void replaceChild(dust3d::Uuid childId, dust3d::Uuid newId) - { - if (m_childrenIdSet.find(childId) == m_childrenIdSet.end()) - return; - if (m_childrenIdSet.find(newId) != m_childrenIdSet.end()) - return; - m_childrenIdSet.erase(childId); - m_childrenIdSet.insert(newId); - auto findResult = std::find(childrenIds.begin(), childrenIds.end(), childId); - if (findResult != childrenIds.end()) - *findResult = newId; - } - void moveChildUp(dust3d::Uuid childId) - { - auto it = std::find(childrenIds.begin(), childrenIds.end(), childId); - if (it == childrenIds.end()) { - return; - } - - auto index = std::distance(childrenIds.begin(), it); - if (index == 0) - return; - std::swap(childrenIds[index - 1], childrenIds[index]); - } - void moveChildDown(dust3d::Uuid childId) - { - auto it = std::find(childrenIds.begin(), childrenIds.end(), childId); - if (it == childrenIds.end()) { - return; - } - - auto index = std::distance(childrenIds.begin(), it); - if (index == (int)childrenIds.size() - 1) - return; - std::swap(childrenIds[index], childrenIds[index + 1]); - } - void moveChildToTop(dust3d::Uuid childId) - { - auto it = std::find(childrenIds.begin(), childrenIds.end(), childId); - if (it == childrenIds.end()) { - return; - } - - auto index = std::distance(childrenIds.begin(), it); - if (index == 0) - return; - for (int i = index; i >= 1; i--) - std::swap(childrenIds[i - 1], childrenIds[i]); - } - void moveChildToBottom(dust3d::Uuid childId) - { - auto it = std::find(childrenIds.begin(), childrenIds.end(), childId); - if (it == childrenIds.end()) { - return; - } - - auto index = std::distance(childrenIds.begin(), it); - if (index == (int)childrenIds.size() - 1) - return; - for (int i = index; i <= (int)childrenIds.size() - 2; i++) - std::swap(childrenIds[i], childrenIds[i + 1]); - } - void updatePreviewMesh(std::unique_ptr mesh) - { - m_previewMesh = std::move(mesh); - isPreviewMeshObsolete = true; - } - ModelMesh* takePreviewMesh() const - { - if (nullptr == m_previewMesh) - return nullptr; - return new ModelMesh(*m_previewMesh); - } private: std::unique_ptr m_previewMesh; diff --git a/application/sources/document_bone.cc b/application/sources/document_bone.cc new file mode 100644 index 00000000..a4743986 --- /dev/null +++ b/application/sources/document_bone.cc @@ -0,0 +1,6 @@ +#include "document.h" + +Document::Bone::Bone(const dust3d::Uuid& withId) +{ + id = withId.isNull() ? dust3d::Uuid::createUuid() : withId; +} diff --git a/application/sources/document_component.cc b/application/sources/document_component.cc new file mode 100644 index 00000000..d0d8019b --- /dev/null +++ b/application/sources/document_component.cc @@ -0,0 +1,152 @@ +#include "document.h" + +Document::Component::Component() +{ +} + +Document::Component::Component(const dust3d::Uuid& withId, const QString& linkData, const QString& linkDataType) +{ + id = withId.isNull() ? dust3d::Uuid::createUuid() : withId; + if (!linkData.isEmpty()) { + if ("partId" == linkDataType) { + linkToPartId = dust3d::Uuid(linkData.toUtf8().constData()); + } + } +} + +QString Document::Component::linkData() const +{ + return linkToPartId.isNull() ? QString() : QString(linkToPartId.toString().c_str()); +} + +QString Document::Component::linkDataType() const +{ + return linkToPartId.isNull() ? QString() : QString("partId"); +} + +void Document::Component::addChild(dust3d::Uuid childId) +{ + if (m_childrenIdSet.find(childId) != m_childrenIdSet.end()) + return; + m_childrenIdSet.insert(childId); + childrenIds.push_back(childId); +} + +void Document::Component::replaceChildWithOthers(const dust3d::Uuid& childId, const std::vector& others) +{ + if (m_childrenIdSet.find(childId) == m_childrenIdSet.end()) + return; + m_childrenIdSet.erase(childId); + std::vector candidates; + for (const auto& it : others) { + if (m_childrenIdSet.find(it) == m_childrenIdSet.end()) { + m_childrenIdSet.insert(it); + candidates.emplace_back(it); + } + } + for (size_t i = 0; i < childrenIds.size(); ++i) { + if (childId == childrenIds[i]) { + size_t newAddSize = candidates.size() - 1; + if (newAddSize > 0) { + size_t oldSize = childrenIds.size(); + childrenIds.resize(childrenIds.size() + newAddSize); + for (int j = (int)oldSize - 1; j > (int)i; --j) { + childrenIds[j + newAddSize] = childrenIds[j]; + } + } + for (size_t k = 0; k < candidates.size(); ++k) + childrenIds[i + k] = candidates[k]; + break; + } + } +} + +void Document::Component::removeChild(dust3d::Uuid childId) +{ + if (m_childrenIdSet.find(childId) == m_childrenIdSet.end()) + return; + m_childrenIdSet.erase(childId); + auto findResult = std::find(childrenIds.begin(), childrenIds.end(), childId); + if (findResult != childrenIds.end()) + childrenIds.erase(findResult); +} + +void Document::Component::replaceChild(dust3d::Uuid childId, dust3d::Uuid newId) +{ + if (m_childrenIdSet.find(childId) == m_childrenIdSet.end()) + return; + if (m_childrenIdSet.find(newId) != m_childrenIdSet.end()) + return; + m_childrenIdSet.erase(childId); + m_childrenIdSet.insert(newId); + auto findResult = std::find(childrenIds.begin(), childrenIds.end(), childId); + if (findResult != childrenIds.end()) + *findResult = newId; +} + +void Document::Component::moveChildUp(dust3d::Uuid childId) +{ + auto it = std::find(childrenIds.begin(), childrenIds.end(), childId); + if (it == childrenIds.end()) { + return; + } + + auto index = std::distance(childrenIds.begin(), it); + if (index == 0) + return; + std::swap(childrenIds[index - 1], childrenIds[index]); +} + +void Document::Component::moveChildDown(dust3d::Uuid childId) +{ + auto it = std::find(childrenIds.begin(), childrenIds.end(), childId); + if (it == childrenIds.end()) { + return; + } + + auto index = std::distance(childrenIds.begin(), it); + if (index == (int)childrenIds.size() - 1) + return; + std::swap(childrenIds[index], childrenIds[index + 1]); +} + +void Document::Component::moveChildToTop(dust3d::Uuid childId) +{ + auto it = std::find(childrenIds.begin(), childrenIds.end(), childId); + if (it == childrenIds.end()) { + return; + } + + auto index = std::distance(childrenIds.begin(), it); + if (index == 0) + return; + for (int i = index; i >= 1; i--) + std::swap(childrenIds[i - 1], childrenIds[i]); +} + +void Document::Component::moveChildToBottom(dust3d::Uuid childId) +{ + auto it = std::find(childrenIds.begin(), childrenIds.end(), childId); + if (it == childrenIds.end()) { + return; + } + + auto index = std::distance(childrenIds.begin(), it); + if (index == (int)childrenIds.size() - 1) + return; + for (int i = index; i <= (int)childrenIds.size() - 2; i++) + std::swap(childrenIds[i], childrenIds[i + 1]); +} + +void Document::Component::updatePreviewMesh(std::unique_ptr mesh) +{ + m_previewMesh = std::move(mesh); + isPreviewMeshObsolete = true; +} + +ModelMesh* Document::Component::takePreviewMesh() const +{ + if (nullptr == m_previewMesh) + return nullptr; + return new ModelMesh(*m_previewMesh); +} diff --git a/application/sources/document_edge.cc b/application/sources/document_edge.cc new file mode 100644 index 00000000..d06beb3a --- /dev/null +++ b/application/sources/document_edge.cc @@ -0,0 +1,13 @@ +#include "document.h" + +Document::Edge::Edge(const dust3d::Uuid& withId) +{ + id = withId.isNull() ? dust3d::Uuid::createUuid() : withId; +} + +dust3d::Uuid Document::Edge::neighborOf(dust3d::Uuid nodeId) const +{ + if (nodeIds.size() != 2) + return dust3d::Uuid(); + return nodeIds[0] == nodeId ? nodeIds[1] : nodeIds[0]; +} diff --git a/application/sources/document_node.cc b/application/sources/document_node.cc new file mode 100644 index 00000000..33ef10d7 --- /dev/null +++ b/application/sources/document_node.cc @@ -0,0 +1,102 @@ +#include "document.h" +#include "mesh_generator.h" + +Document::Node::Node(const dust3d::Uuid& withId) +{ + id = withId.isNull() ? dust3d::Uuid::createUuid() : withId; +} + +void Document::Node::setRadius(float toRadius) +{ + if (toRadius < MeshGenerator::m_minimalRadius) + toRadius = MeshGenerator::m_minimalRadius; + else if (toRadius > 1) + toRadius = 1; + radius = toRadius; +} + +void Document::Node::setCutRotation(float toRotation) +{ + if (toRotation < -1) + toRotation = -1; + else if (toRotation > 1) + toRotation = 1; + cutRotation = toRotation; + hasCutFaceSettings = true; +} + +void Document::Node::setCutFace(dust3d::CutFace face) +{ + cutFace = face; + cutFaceLinkedId = dust3d::Uuid(); + hasCutFaceSettings = true; +} + +void Document::Node::setCutFaceLinkedId(const dust3d::Uuid& linkedId) +{ + if (linkedId.isNull()) { + clearCutFaceSettings(); + return; + } + cutFace = dust3d::CutFace::UserDefined; + cutFaceLinkedId = linkedId; + hasCutFaceSettings = true; +} + +void Document::Node::clearCutFaceSettings() +{ + cutFace = dust3d::CutFace::Quad; + cutFaceLinkedId = dust3d::Uuid(); + cutRotation = 0; + hasCutFaceSettings = false; +} + +float Document::Node::getX(bool rotated) const +{ + if (rotated) + return m_y; + return m_x; +} + +float Document::Node::getY(bool rotated) const +{ + if (rotated) + return m_x; + return m_y; +} + +float Document::Node::getZ(bool rotated) const +{ + (void)rotated; + return m_z; +} + +void Document::Node::setX(float x) +{ + m_x = x; +} + +void Document::Node::setY(float y) +{ + m_y = y; +} + +void Document::Node::setZ(float z) +{ + m_z = z; +} + +void Document::Node::addX(float x) +{ + m_x += x; +} + +void Document::Node::addY(float y) +{ + m_y += y; +} + +void Document::Node::addZ(float z) +{ + m_z += z; +} diff --git a/application/sources/document_part.cc b/application/sources/document_part.cc new file mode 100644 index 00000000..f49a6055 --- /dev/null +++ b/application/sources/document_part.cc @@ -0,0 +1,229 @@ +#include "document.h" + +Document::Part::Part(const dust3d::Uuid& withId) + : visible(true) + , locked(false) + , subdived(false) + , disabled(false) + , xMirrored(false) + , deformThickness(1.0) + , deformWidth(1.0) + , deformUnified(false) + , rounded(false) + , chamfered(false) + , color(Qt::white) + , hasColor(false) + , dirty(true) + , cutRotation(0.0) + , cutFace(dust3d::CutFace::Quad) + , target(dust3d::PartTarget::Model) + , colorSolubility(0.0) + , metalness(0.0) + , roughness(1.0) + , hollowThickness(0.0) + , countershaded(false) + , smooth(false) +{ + id = withId.isNull() ? dust3d::Uuid::createUuid() : withId; +} + +bool Document::Part::hasPolyFunction() const +{ + return dust3d::PartTarget::Model == target; +} + +bool Document::Part::hasSmoothFunction() const +{ + return dust3d::PartTarget::Model == target; +} + +bool Document::Part::hasSubdivFunction() const +{ + return dust3d::PartTarget::Model == target; +} + +bool Document::Part::hasRoundEndFunction() const +{ + return dust3d::PartTarget::Model == target; +} + +bool Document::Part::hasMirrorFunction() const +{ + return dust3d::PartTarget::Model == target; +} + +bool Document::Part::hasChamferFunction() const +{ + return dust3d::PartTarget::Model == target; +} + +bool Document::Part::hasRotationFunction() const +{ + return dust3d::PartTarget::Model == target; +} + +bool Document::Part::hasHollowFunction() const +{ + return dust3d::PartTarget::Model == target; +} + +bool Document::Part::hasCutFaceFunction() const +{ + return dust3d::PartTarget::Model == target; +} + +bool Document::Part::hasLayerFunction() const +{ + return dust3d::PartTarget::Model == target; +} + +bool Document::Part::hasTargetFunction() const +{ + return true; +} + +bool Document::Part::hasBaseFunction() const +{ + return dust3d::PartTarget::Model == target; +} + +bool Document::Part::hasCombineModeFunction() const +{ + return dust3d::PartTarget::Model == target; +} + +bool Document::Part::hasDeformFunction() const +{ + return dust3d::PartTarget::Model == target; +} + +bool Document::Part::hasColorFunction() const +{ + return dust3d::PartTarget::Model == target; +} + +void Document::Part::setDeformThickness(float toThickness) +{ + if (toThickness < 0) + toThickness = 0; + else if (toThickness > 2) + toThickness = 2; + deformThickness = toThickness; +} + +void Document::Part::setDeformWidth(float toWidth) +{ + if (toWidth < 0) + toWidth = 0; + else if (toWidth > 2) + toWidth = 2; + deformWidth = toWidth; +} + +void Document::Part::setCutRotation(float toRotation) +{ + if (toRotation < -1) + toRotation = -1; + else if (toRotation > 1) + toRotation = 1; + cutRotation = toRotation; +} + +void Document::Part::setCutFace(dust3d::CutFace face) +{ + cutFace = face; + cutFaceLinkedId = dust3d::Uuid(); +} + +void Document::Part::setCutFaceLinkedId(const dust3d::Uuid& linkedId) +{ + if (linkedId.isNull()) { + setCutFace(dust3d::CutFace::Quad); + return; + } + cutFace = dust3d::CutFace::UserDefined; + cutFaceLinkedId = linkedId; +} + +bool Document::Part::deformThicknessAdjusted() const +{ + return fabs(deformThickness - 1.0) >= 0.01; +} + +bool Document::Part::deformWidthAdjusted() const +{ + return fabs(deformWidth - 1.0) >= 0.01; +} + +bool Document::Part::deformAdjusted() const +{ + return deformThicknessAdjusted() || deformWidthAdjusted() || deformUnified; +} + +bool Document::Part::colorSolubilityAdjusted() const +{ + return fabs(colorSolubility - 0.0) >= 0.01; +} + +bool Document::Part::metalnessAdjusted() const +{ + return fabs(metalness - 0.0) >= 0.01; +} + +bool Document::Part::roughnessAdjusted() const +{ + return fabs(roughness - 1.0) >= 0.01; +} + +bool Document::Part::cutRotationAdjusted() const +{ + return fabs(cutRotation - 0.0) >= 0.01; +} + +bool Document::Part::hollowThicknessAdjusted() const +{ + return fabs(hollowThickness - 0.0) >= 0.01; +} + +bool Document::Part::cutFaceAdjusted() const +{ + return cutFace != dust3d::CutFace::Quad; +} + +bool Document::Part::cutAdjusted() const +{ + return cutRotationAdjusted() || cutFaceAdjusted() || hollowThicknessAdjusted(); +} + +bool Document::Part::isEditVisible() const +{ + return visible && !disabled; +} + +void Document::Part::copyAttributes(const Part& other) +{ + visible = other.visible; + locked = other.locked; + subdived = other.subdived; + disabled = other.disabled; + xMirrored = other.xMirrored; + deformThickness = other.deformThickness; + deformWidth = other.deformWidth; + rounded = other.rounded; + chamfered = other.chamfered; + color = other.color; + hasColor = other.hasColor; + cutRotation = other.cutRotation; + cutFace = other.cutFace; + cutFaceLinkedId = other.cutFaceLinkedId; + componentId = other.componentId; + dirty = other.dirty; + target = other.target; + colorSolubility = other.colorSolubility; + countershaded = other.countershaded; + metalness = other.metalness; + roughness = other.roughness; + deformUnified = other.deformUnified; + smooth = other.smooth; + hollowThickness = other.hollowThickness; +} diff --git a/dust3d/rig/skeleton_generator.cc b/dust3d/rig/skeleton_generator.cc index e7838352..7ac2abb3 100644 --- a/dust3d/rig/skeleton_generator.cc +++ b/dust3d/rig/skeleton_generator.cc @@ -48,22 +48,93 @@ void SkeletonGenerator::addBone(const Uuid& boneId, const Bone& bone) m_boneMap.emplace(std::make_pair(boneId, bone)); } -void SkeletonGenerator::addNodeBinding(const Uuid& nodeId, const NodeBinding& node) +void SkeletonGenerator::addNodeBinding(const Uuid& nodeId, const NodeBinding& nodeBinding) { - m_nodeBindingMap.emplace(std::make_pair(nodeId, node)); + m_nodeBindingMap.emplace(std::make_pair(nodeId, nodeBinding)); +} + +void SkeletonGenerator::buildEdges() +{ + for (const auto& face : m_faces) { + for (size_t i = 0; i < face.size(); ++i) { + size_t j = (i + 1) % face.size(); + m_edges[face[i]].insert(face[j]); + m_edges[face[j]].insert(face[i]); + } + } +} + +Uuid SkeletonGenerator::resolveVertexSourceByBreadthFirstSearch(size_t vertexIndex, std::unordered_set& visited) +{ + visited.insert(vertexIndex); + auto findNeighbors = m_edges.find(vertexIndex); + if (findNeighbors == m_edges.end()) + return Uuid(); + for (const auto& it : findNeighbors->second) { + if (!m_vertexSourceNodes[it].isNull()) + return m_vertexSourceNodes[it]; + } + for (const auto& it : findNeighbors->second) { + if (visited.end() != visited.find(it)) + continue; + Uuid foundId = resolveVertexSourceByBreadthFirstSearch(it, visited); + if (!foundId.isNull()) + return foundId; + } + return Uuid(); +} + +void SkeletonGenerator::resolveVertexSources() +{ + m_vertexSourceNodes.resize(m_vertices.size()); + for (size_t i = 0; i < m_vertices.size(); ++i) { + auto findNode = m_positionToNodeMap.find(m_vertices[i]); + if (findNode == m_positionToNodeMap.end()) + continue; + m_vertexSourceNodes[i] = findNode->second; + } + + for (size_t i = 0; i < m_vertexSourceNodes.size(); ++i) { + if (!m_vertexSourceNodes[i].isNull()) + continue; + std::unordered_set visited; + m_vertexSourceNodes[i] = resolveVertexSourceByBreadthFirstSearch(i, visited); + } +} + +void SkeletonGenerator::buildBoneJoints() +{ + // TODO: +} + +void SkeletonGenerator::assignBoneJointToVertices() +{ + // TODO: +} + +void SkeletonGenerator::groupBoneVertices() +{ + /* + for (size_t i = 0; i < m_vertexSourceNodes.size(); ++i) { + const Uuid& sourceNodeId = m_vertexSourceNodes[i]; + if (sourceNodeId.isNull()) + continue; + auto findBinding = m_nodeBindingMap.find(sourceNodeId); + if (findBinding == m_nodeBindingMap.end()) + continue; + // TODO: + } + */ + // TODO: } void SkeletonGenerator::bind() { - // TODO: Build vertex edge map - - // TODO: Bind unbound nodes - - // TODO: Build bone skeleton - - // TODO: Assign bone to vertex - - // TODO: finalize + buildEdges(); + resolveVertexSources(); + groupBoneVertices(); + buildBoneJoints(); + assignBoneJointToVertices(); } } diff --git a/dust3d/rig/skeleton_generator.h b/dust3d/rig/skeleton_generator.h index c91f927d..9c221d33 100644 --- a/dust3d/rig/skeleton_generator.h +++ b/dust3d/rig/skeleton_generator.h @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include namespace dust3d { @@ -40,7 +42,6 @@ public: struct Bone { std::string name; - std::string parent; }; SkeletonGenerator(); @@ -48,7 +49,7 @@ public: void setFaces(const std::vector>& faces); void setPositionToNodeMap(const std::map& positionToNodeMap); void addBone(const Uuid& boneId, const Bone& bone); - void addNodeBinding(const Uuid& nodeId, const NodeBinding& node); + void addNodeBinding(const Uuid& nodeId, const NodeBinding& nodeBinding); void bind(); private: @@ -57,6 +58,15 @@ private: std::map m_positionToNodeMap; std::map m_nodeBindingMap; std::map m_boneMap; + std::map> m_edges; + std::vector m_vertexSourceNodes; + + void buildEdges(); + void resolveVertexSources(); + Uuid resolveVertexSourceByBreadthFirstSearch(size_t vertexIndex, std::unordered_set& visited); + void groupBoneVertices(); + void buildBoneJoints(); + void assignBoneJointToVertices(); }; }