diff --git a/src/modelingwidget.cpp b/src/modelingwidget.cpp index 794e0437..6dc4a96d 100644 --- a/src/modelingwidget.cpp +++ b/src/modelingwidget.cpp @@ -179,7 +179,7 @@ void ModelingWidget::initializeGL() // Our camera never changes in this example. m_camera.setToIdentity(); - m_camera.translate(0, 0, -4.5); + m_camera.translate(0, 0, -2.5); // Light position is fixed. m_program->setUniformValue(m_lightPosLoc, QVector3D(0, 0, 70)); diff --git a/src/skeletoneditgraphicsview.cpp b/src/skeletoneditgraphicsview.cpp index 7c02636d..9dd6bdf2 100644 --- a/src/skeletoneditgraphicsview.cpp +++ b/src/skeletoneditgraphicsview.cpp @@ -151,6 +151,13 @@ void SkeletonEditGraphicsView::mouseReleaseEvent(QMouseEvent *event) SkeletonEditEdgeItem *newEdge = new SkeletonEditEdgeItem(); newEdge->setNodes(masterNode, m_nextStartNodeItem); scene()->addItem(newEdge); + masterNode->setGroup(m_nextStartNodeItem->group()); + slaveNode->setGroup(masterNode->group()); + } else { + QGraphicsItemGroup *group = new QGraphicsItemGroup(); + scene()->addItem(group); + masterNode->setGroup(group); + slaveNode->setGroup(masterNode->group()); } setNextStartNodeItem(masterNode); emit nodesChanged(); diff --git a/src/skeletoneditnodeitem.h b/src/skeletoneditnodeitem.h index 80f5b1c4..22c496be 100644 --- a/src/skeletoneditnodeitem.h +++ b/src/skeletoneditnodeitem.h @@ -26,6 +26,7 @@ private: bool m_isNextStartNode; SkeletonEditNodeItem *m_master; SkeletonEditNodeItem *m_slave; +private: void updateBorder(); }; diff --git a/src/skeletontomesh.cpp b/src/skeletontomesh.cpp index 15b2d58f..3490ef20 100644 --- a/src/skeletontomesh.cpp +++ b/src/skeletontomesh.cpp @@ -12,21 +12,34 @@ struct NodeItemInfo }; SkeletonToMesh::SkeletonToMesh(SkeletonEditGraphicsView *graphicsView) : - m_mesh(NULL), m_rootNodeId(0) + m_mesh(NULL) { QList::iterator it; QList list = graphicsView->scene()->items(); std::map nodeItemsMap; + std::map groupIdsMap; int maxNeighborCount = 0; for (it = list.begin(); it != list.end(); ++it) { if ((*it)->data(0).toString() == "edge") { SkeletonEditEdgeItem *edgeItem = static_cast(*it); SkeletonEditNodeItem *nodeItems[] = {edgeItem->firstNode(), edgeItem->secondNode()}; int nodeIndices[] = {0, 0}; + SkeletonGroup *skeletonGroup = NULL; for (int i = 0; i < 2; i++) { SkeletonEditNodeItem *nodeItem = nodeItems[i]; - std::map::iterator findResult = nodeItemsMap.find(nodeItem); - if (findResult == nodeItemsMap.end()) { + std::map::iterator findGroupId = groupIdsMap.find(nodeItem->group()); + if (findGroupId == groupIdsMap.end()) { + SkeletonGroup group; + group.maxNeighborCount = 0; + group.rootNode = 0; + group.bmeshId = -1; + group.meshId = -1; + groupIdsMap[nodeItem->group()] = m_groups.size(); + m_groups.push_back(group); + } + skeletonGroup = &m_groups[groupIdsMap[nodeItem->group()]]; + std::map::iterator findNode = nodeItemsMap.find(nodeItem); + if (findNode == nodeItemsMap.end()) { SkeletonNode node; NodeItemInfo info; QPointF origin = nodeItem->origin(); @@ -34,29 +47,28 @@ SkeletonToMesh::SkeletonToMesh(SkeletonEditGraphicsView *graphicsView) : node.originX = origin.x(); node.originY = origin.y(); node.originZ = nodeItem->slave()->origin().x(); - node.processed = false; node.bmeshNodeId = -1; node.radius = nodeItem->radius(); - info.index = m_nodes.size(); + info.index = skeletonGroup->nodes.size(); info.neighborCount = 1; nodeIndices[i] = info.index; nodeItemsMap[nodeItem] = info; - m_nodes.push_back(node); + skeletonGroup->nodes.push_back(node); } else { - nodeIndices[i] = findResult->second.index; - findResult->second.neighborCount++; - if (findResult->second.neighborCount > maxNeighborCount) { - m_rootNodeId = findResult->second.index; - maxNeighborCount = findResult->second.neighborCount; + nodeIndices[i] = findNode->second.index; + findNode->second.neighborCount++; + if (findNode->second.neighborCount > skeletonGroup->maxNeighborCount) { + skeletonGroup->rootNode = findNode->second.index; + maxNeighborCount = findNode->second.neighborCount; } } } SkeletonEdge edge; edge.firstNode = nodeIndices[0]; edge.secondNode = nodeIndices[1]; - m_edges.push_back(edge); + skeletonGroup->edges.push_back(edge); } } } @@ -75,7 +87,7 @@ Mesh *SkeletonToMesh::takeResultMesh() void SkeletonToMesh::process() { - if (m_nodes.size() <= 1) { + if (m_groups.size() <= 0) { emit finished(); return; } @@ -85,25 +97,28 @@ void SkeletonToMesh::process() float bottom = -1; float zLeft = -1; float zRight = -1; - for (size_t i = 0; i < m_nodes.size(); i++) { - SkeletonNode *node = &m_nodes[i]; - if (left < 0 || node->originX < left) { - left = node->originX; - } - if (top < 0 || node->originY < top) { - top = node->originY; - } - if (node->originX > right) { - right = node->originX; - } - if (node->originY > bottom) { - bottom = node->originY; - } - if (zLeft < 0 || node->originZ < zLeft) { - zLeft = node->originZ; - } - if (node->originZ > zRight) { - zRight = node->originZ; + for (size_t i = 0; i < m_groups.size(); i++) { + SkeletonGroup *group = &m_groups[i]; + for (size_t j = 0; j < group->nodes.size(); j++) { + SkeletonNode *node = &group->nodes[j]; + if (left < 0 || node->originX < left) { + left = node->originX; + } + if (top < 0 || node->originY < top) { + top = node->originY; + } + if (node->originX > right) { + right = node->originX; + } + if (node->originY > bottom) { + bottom = node->originY; + } + if (zLeft < 0 || node->originZ < zLeft) { + zLeft = node->originZ; + } + if (node->originZ > zRight) { + zRight = node->originZ; + } } } float height = bottom - top; @@ -113,23 +128,39 @@ void SkeletonToMesh::process() } float zWidth = right - left; void *context = meshlite_create_context(); - int bmesh = meshlite_bmesh_create(context); - for (size_t i = 0; i < m_nodes.size(); i++) { - SkeletonNode *node = &m_nodes[i]; - float x = (node->originX - left - height / 2) / height; - float y = (node->originY - top - height / 2) / height; - float z = (node->originZ - zLeft - zWidth / 2) / height; - float r = node->radius / height; - node->bmeshNodeId = meshlite_bmesh_add_node(context, bmesh, x, y, z, r); + + for (size_t i = 0; i < m_groups.size(); i++) { + SkeletonGroup *group = &m_groups[i]; + group->bmeshId = meshlite_bmesh_create(context); + for (size_t j = 0; j < group->nodes.size(); j++) { + SkeletonNode *node = &group->nodes[j]; + float x = (node->originX - left - height / 2) / height; + float y = (node->originY - top - height / 2) / height; + float z = (node->originZ - zLeft - zWidth / 2) / height; + float r = node->radius / height; + node->bmeshNodeId = meshlite_bmesh_add_node(context, group->bmeshId, x, y, z, r); + } + for (size_t j = 0; j < group->edges.size(); j++) { + SkeletonNode *firstNode = &group->nodes[group->edges[j].firstNode]; + SkeletonNode *secondNode = &group->nodes[group->edges[j].secondNode]; + meshlite_bmesh_add_edge(context, group->bmeshId, firstNode->bmeshNodeId, secondNode->bmeshNodeId); + } + group->meshId = meshlite_bmesh_generate_mesh(context, group->bmeshId, group->nodes[group->rootNode].bmeshNodeId); } - for (size_t i = 0; i < m_edges.size(); i++) { - SkeletonNode *firstNode = &m_nodes[m_edges[i].firstNode]; - SkeletonNode *secondNode = &m_nodes[m_edges[i].secondNode]; - meshlite_bmesh_add_edge(context, bmesh, firstNode->bmeshNodeId, secondNode->bmeshNodeId); + + int unionMeshId = m_groups[0].meshId; + for (size_t i = 1; i < m_groups.size(); i++) { + int newUnionMeshId = meshlite_union(context, m_groups[i].meshId, unionMeshId); + // TODO: destroy last unionMeshId + // ... ... + unionMeshId = newUnionMeshId; } - int mesh = meshlite_bmesh_generate_mesh(context, bmesh, m_nodes[m_rootNodeId].bmeshNodeId); - meshlite_bmesh_destroy(context, bmesh); - int triangulate = meshlite_triangulate(context, mesh); + + for (size_t i = 1; i < m_groups.size(); i++) { + meshlite_bmesh_destroy(context, m_groups[i].bmeshId); + } + + int triangulate = meshlite_triangulate(context, unionMeshId); meshlite_export(context, triangulate, "/Users/jeremy/testlib.obj"); m_mesh = new Mesh(context, triangulate); meshlite_destroy_context(context); diff --git a/src/skeletontomesh.h b/src/skeletontomesh.h index 036290a8..de83815c 100644 --- a/src/skeletontomesh.h +++ b/src/skeletontomesh.h @@ -13,7 +13,6 @@ struct SkeletonNode float originY; float originZ; float radius; - bool processed; int bmeshNodeId; }; @@ -23,6 +22,16 @@ struct SkeletonEdge int secondNode; }; +struct SkeletonGroup +{ + std::vector nodes; + std::vector edges; + int rootNode; + int maxNeighborCount; + int bmeshId; + int meshId; +}; + class SkeletonToMesh : public QObject { Q_OBJECT @@ -36,9 +45,7 @@ public slots: void process(); private: Mesh *m_mesh; - std::vector m_nodes; - std::vector m_edges; - int m_rootNodeId; + std::vector m_groups; }; #endif