Divide document elements to separate file
parent
6335742b17
commit
0f77ed243d
|
@ -121,6 +121,11 @@ HEADERS += sources/debug.h
|
||||||
SOURCES += sources/debug.cc
|
SOURCES += sources/debug.cc
|
||||||
HEADERS += sources/document.h
|
HEADERS += sources/document.h
|
||||||
SOURCES += sources/document.cc
|
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
|
HEADERS += sources/document_saver.h
|
||||||
SOURCES += sources/document_saver.cc
|
SOURCES += sources/document_saver.cc
|
||||||
HEADERS += sources/document_window.h
|
HEADERS += sources/document_window.h
|
||||||
|
|
|
@ -20,20 +20,6 @@
|
||||||
|
|
||||||
unsigned long Document::m_maxSnapshot = 1000;
|
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()
|
Document::Document()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,84 +57,21 @@ public:
|
||||||
|
|
||||||
class Node {
|
class Node {
|
||||||
public:
|
public:
|
||||||
Node(const dust3d::Uuid& withId = dust3d::Uuid())
|
Node(const dust3d::Uuid& withId = dust3d::Uuid());
|
||||||
{
|
|
||||||
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
|
||||||
}
|
|
||||||
void setRadius(float toRadius);
|
void setRadius(float toRadius);
|
||||||
void setCutRotation(float toRotation)
|
void setCutRotation(float toRotation);
|
||||||
{
|
void setCutFace(dust3d::CutFace face);
|
||||||
if (toRotation < -1)
|
void setCutFaceLinkedId(const dust3d::Uuid& linkedId);
|
||||||
toRotation = -1;
|
void clearCutFaceSettings();
|
||||||
else if (toRotation > 1)
|
float getX(bool rotated = false) const;
|
||||||
toRotation = 1;
|
float getY(bool rotated = false) const;
|
||||||
cutRotation = toRotation;
|
float getZ(bool rotated = false) const;
|
||||||
hasCutFaceSettings = true;
|
void setX(float x);
|
||||||
}
|
void setY(float y);
|
||||||
void setCutFace(dust3d::CutFace face)
|
void setZ(float z);
|
||||||
{
|
void addX(float x);
|
||||||
cutFace = face;
|
void addY(float y);
|
||||||
cutFaceLinkedId = dust3d::Uuid();
|
void addZ(float z);
|
||||||
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;
|
|
||||||
}
|
|
||||||
dust3d::Uuid id;
|
dust3d::Uuid id;
|
||||||
dust3d::Uuid partId;
|
dust3d::Uuid partId;
|
||||||
QString name;
|
QString name;
|
||||||
|
@ -155,20 +92,12 @@ public:
|
||||||
|
|
||||||
class Edge {
|
class Edge {
|
||||||
public:
|
public:
|
||||||
Edge(const dust3d::Uuid& withId = dust3d::Uuid())
|
Edge(const dust3d::Uuid& withId = dust3d::Uuid());
|
||||||
{
|
|
||||||
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
|
||||||
}
|
|
||||||
dust3d::Uuid id;
|
dust3d::Uuid id;
|
||||||
dust3d::Uuid partId;
|
dust3d::Uuid partId;
|
||||||
QString name;
|
QString name;
|
||||||
std::vector<dust3d::Uuid> nodeIds;
|
std::vector<dust3d::Uuid> nodeIds;
|
||||||
dust3d::Uuid neighborOf(dust3d::Uuid nodeId) const
|
dust3d::Uuid neighborOf(dust3d::Uuid nodeId) const;
|
||||||
{
|
|
||||||
if (nodeIds.size() != 2)
|
|
||||||
return dust3d::Uuid();
|
|
||||||
return nodeIds[0] == nodeId ? nodeIds[1] : nodeIds[0];
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Part {
|
class Part {
|
||||||
|
@ -201,201 +130,39 @@ public:
|
||||||
bool countershaded;
|
bool countershaded;
|
||||||
bool smooth;
|
bool smooth;
|
||||||
dust3d::Uuid colorImageId;
|
dust3d::Uuid colorImageId;
|
||||||
Part(const dust3d::Uuid& withId = dust3d::Uuid())
|
Part(const dust3d::Uuid& withId = dust3d::Uuid());
|
||||||
: visible(true)
|
bool hasPolyFunction() const;
|
||||||
, locked(false)
|
bool hasSmoothFunction() const;
|
||||||
, subdived(false)
|
bool hasSubdivFunction() const;
|
||||||
, disabled(false)
|
bool hasRoundEndFunction() const;
|
||||||
, xMirrored(false)
|
bool hasMirrorFunction() const;
|
||||||
, deformThickness(1.0)
|
bool hasChamferFunction() const;
|
||||||
, deformWidth(1.0)
|
bool hasRotationFunction() const;
|
||||||
, deformUnified(false)
|
bool hasHollowFunction() const;
|
||||||
, rounded(false)
|
bool hasCutFaceFunction() const;
|
||||||
, chamfered(false)
|
bool hasLayerFunction() const;
|
||||||
, color(Qt::white)
|
bool hasTargetFunction() const;
|
||||||
, hasColor(false)
|
bool hasBaseFunction() const;
|
||||||
, dirty(true)
|
bool hasCombineModeFunction() const;
|
||||||
, cutRotation(0.0)
|
bool hasDeformFunction() const;
|
||||||
, cutFace(dust3d::CutFace::Quad)
|
bool hasColorFunction() const;
|
||||||
, target(dust3d::PartTarget::Model)
|
void setDeformThickness(float toThickness);
|
||||||
, colorSolubility(0.0)
|
void setDeformWidth(float toWidth);
|
||||||
, metalness(0.0)
|
void setCutRotation(float toRotation);
|
||||||
, roughness(1.0)
|
void setCutFace(dust3d::CutFace face);
|
||||||
, hollowThickness(0.0)
|
void setCutFaceLinkedId(const dust3d::Uuid& linkedId);
|
||||||
, countershaded(false)
|
bool deformThicknessAdjusted() const;
|
||||||
, smooth(false)
|
bool deformWidthAdjusted() const;
|
||||||
{
|
bool deformAdjusted() const;
|
||||||
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
bool colorSolubilityAdjusted() const;
|
||||||
}
|
bool metalnessAdjusted() const;
|
||||||
bool hasPolyFunction() const
|
bool roughnessAdjusted() const;
|
||||||
{
|
bool cutRotationAdjusted() const;
|
||||||
return dust3d::PartTarget::Model == target;
|
bool hollowThicknessAdjusted() const;
|
||||||
}
|
bool cutFaceAdjusted() const;
|
||||||
bool hasSmoothFunction() const
|
bool cutAdjusted() const;
|
||||||
{
|
bool isEditVisible() const;
|
||||||
return dust3d::PartTarget::Model == target;
|
void copyAttributes(const Part& other);
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(Part);
|
Q_DISABLE_COPY(Part);
|
||||||
|
@ -403,18 +170,20 @@ public:
|
||||||
|
|
||||||
class Component {
|
class Component {
|
||||||
public:
|
public:
|
||||||
Component()
|
Component();
|
||||||
{
|
Component(const dust3d::Uuid& withId, const QString& linkData = QString(), const QString& linkDataType = QString());
|
||||||
}
|
QString linkData() const;
|
||||||
Component(const dust3d::Uuid& withId, const QString& linkData = QString(), const QString& linkDataType = QString())
|
QString linkDataType() const;
|
||||||
{
|
void addChild(dust3d::Uuid childId);
|
||||||
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
void replaceChildWithOthers(const dust3d::Uuid& childId, const std::vector<dust3d::Uuid>& others);
|
||||||
if (!linkData.isEmpty()) {
|
void removeChild(dust3d::Uuid childId);
|
||||||
if ("partId" == linkDataType) {
|
void replaceChild(dust3d::Uuid childId, dust3d::Uuid newId);
|
||||||
linkToPartId = dust3d::Uuid(linkData.toUtf8().constData());
|
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<ModelMesh> mesh);
|
||||||
|
ModelMesh* takePreviewMesh() const;
|
||||||
dust3d::Uuid id;
|
dust3d::Uuid id;
|
||||||
QString name;
|
QString name;
|
||||||
dust3d::Uuid linkToPartId;
|
dust3d::Uuid linkToPartId;
|
||||||
|
@ -427,131 +196,6 @@ public:
|
||||||
std::unique_ptr<QImage> previewImage;
|
std::unique_ptr<QImage> previewImage;
|
||||||
bool isPreviewImageDecorationObsolete = false;
|
bool isPreviewImageDecorationObsolete = false;
|
||||||
QPixmap previewPixmap;
|
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<dust3d::Uuid>& others)
|
|
||||||
{
|
|
||||||
if (m_childrenIdSet.find(childId) == m_childrenIdSet.end())
|
|
||||||
return;
|
|
||||||
m_childrenIdSet.erase(childId);
|
|
||||||
std::vector<dust3d::Uuid> 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<ModelMesh> mesh)
|
|
||||||
{
|
|
||||||
m_previewMesh = std::move(mesh);
|
|
||||||
isPreviewMeshObsolete = true;
|
|
||||||
}
|
|
||||||
ModelMesh* takePreviewMesh() const
|
|
||||||
{
|
|
||||||
if (nullptr == m_previewMesh)
|
|
||||||
return nullptr;
|
|
||||||
return new ModelMesh(*m_previewMesh);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<ModelMesh> m_previewMesh;
|
std::unique_ptr<ModelMesh> m_previewMesh;
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include "document.h"
|
||||||
|
|
||||||
|
Document::Bone::Bone(const dust3d::Uuid& withId)
|
||||||
|
{
|
||||||
|
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
||||||
|
}
|
|
@ -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<dust3d::Uuid>& others)
|
||||||
|
{
|
||||||
|
if (m_childrenIdSet.find(childId) == m_childrenIdSet.end())
|
||||||
|
return;
|
||||||
|
m_childrenIdSet.erase(childId);
|
||||||
|
std::vector<dust3d::Uuid> 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<ModelMesh> mesh)
|
||||||
|
{
|
||||||
|
m_previewMesh = std::move(mesh);
|
||||||
|
isPreviewMeshObsolete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelMesh* Document::Component::takePreviewMesh() const
|
||||||
|
{
|
||||||
|
if (nullptr == m_previewMesh)
|
||||||
|
return nullptr;
|
||||||
|
return new ModelMesh(*m_previewMesh);
|
||||||
|
}
|
|
@ -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];
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -48,22 +48,93 @@ void SkeletonGenerator::addBone(const Uuid& boneId, const Bone& bone)
|
||||||
m_boneMap.emplace(std::make_pair(boneId, 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<size_t>& 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<size_t> 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()
|
void SkeletonGenerator::bind()
|
||||||
{
|
{
|
||||||
// TODO: Build vertex edge map
|
buildEdges();
|
||||||
|
resolveVertexSources();
|
||||||
// TODO: Bind unbound nodes
|
groupBoneVertices();
|
||||||
|
buildBoneJoints();
|
||||||
// TODO: Build bone skeleton
|
assignBoneJointToVertices();
|
||||||
|
|
||||||
// TODO: Assign bone to vertex
|
|
||||||
|
|
||||||
// TODO: finalize
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
#include <dust3d/base/uuid.h>
|
#include <dust3d/base/uuid.h>
|
||||||
#include <dust3d/base/vector3.h>
|
#include <dust3d/base/vector3.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace dust3d {
|
namespace dust3d {
|
||||||
|
@ -40,7 +42,6 @@ public:
|
||||||
|
|
||||||
struct Bone {
|
struct Bone {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string parent;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SkeletonGenerator();
|
SkeletonGenerator();
|
||||||
|
@ -48,7 +49,7 @@ public:
|
||||||
void setFaces(const std::vector<std::vector<size_t>>& faces);
|
void setFaces(const std::vector<std::vector<size_t>>& faces);
|
||||||
void setPositionToNodeMap(const std::map<PositionKey, Uuid>& positionToNodeMap);
|
void setPositionToNodeMap(const std::map<PositionKey, Uuid>& positionToNodeMap);
|
||||||
void addBone(const Uuid& boneId, const Bone& bone);
|
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();
|
void bind();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -57,6 +58,15 @@ private:
|
||||||
std::map<PositionKey, Uuid> m_positionToNodeMap;
|
std::map<PositionKey, Uuid> m_positionToNodeMap;
|
||||||
std::map<Uuid, NodeBinding> m_nodeBindingMap;
|
std::map<Uuid, NodeBinding> m_nodeBindingMap;
|
||||||
std::map<Uuid, Bone> m_boneMap;
|
std::map<Uuid, Bone> m_boneMap;
|
||||||
|
std::map<size_t, std::set<size_t>> m_edges;
|
||||||
|
std::vector<Uuid> m_vertexSourceNodes;
|
||||||
|
|
||||||
|
void buildEdges();
|
||||||
|
void resolveVertexSources();
|
||||||
|
Uuid resolveVertexSourceByBreadthFirstSearch(size_t vertexIndex, std::unordered_set<size_t>& visited);
|
||||||
|
void groupBoneVertices();
|
||||||
|
void buildBoneJoints();
|
||||||
|
void assignBoneJointToVertices();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue