Node *AbsoluteTransformator::toAbsolute(Node *relativeRoot, glm::mat4 transform) { if (relativeRoot == nullptr) new Group(); glm::mat4 newTransform = relativeRoot->transform() * transform; Node *absoluteRoot; if (relativeRoot->children().size() > 0) { Group *absoluteGroup = new Group(); for (auto child : relativeRoot->children()) { Node *absoluteChild = toAbsolute(static_cast<Node *>(child), newTransform); if (absoluteChild != nullptr) { absoluteGroup->append(absoluteChild); } } absoluteRoot = absoluteGroup; } else { PolygonalDrawable *poly = dynamic_cast<PolygonalDrawable *>(relativeRoot); if (poly == nullptr) { absoluteRoot = new Group(); } else { auto relativeGeometry = poly->geometry(); auto vertices = relativeGeometry->copyVertices(); auto absoluteGeometry = new TriangleObject(); p_TriangleList triangles = absoluteGeometry->triangles(); for (auto index : relativeGeometry->indices()) { glm::vec4 homogenous = newTransform * glm::vec4(vertices.at(index), 1.0f); triangles->push_back(homogenous.xyz * (1 / homogenous.w)); } absoluteRoot = absoluteGeometry; } } absoluteRoot->setName(relativeRoot->name()); absoluteRoot->setReferenceFrame(Node::RF_Absolute); return absoluteRoot; }
PolygonalDrawable * AssimpLoader::parseMesh(const aiMesh & mesh) const { auto geometry = std::make_shared<PolygonalGeometry>(m_registry); const bool usesNormalIndices(mesh.mNormals != NULL); for (unsigned int i = 0; i < mesh.mNumVertices; i++) { glm::vec3 vector( mesh.mVertices[i].x, mesh.mVertices[i].y, mesh.mVertices[i].z ); geometry->setVertex(i, vector); } if (usesNormalIndices) { for (unsigned int i = 0; i < mesh.mNumVertices; i++) { glm::vec3 vector( mesh.mNormals[i].x, mesh.mNormals[i].y, mesh.mNormals[i].z ); geometry->setNormal(i, vector); } } unsigned int currentIndex = 0; for (unsigned int i = 0; i < mesh.mNumFaces; i++) { if (mesh.mFaces[i].mNumIndices != 3) qCritical("Ignore polygon with num vertices != 3 (only triangles are supported)."); else for (unsigned int j = 0; j < mesh.mFaces[i].mNumIndices; j++) geometry->setIndex(currentIndex++, mesh.mFaces[i].mIndices[j]); } if (!usesNormalIndices) geometry->retrieveNormals(); PolygonalDrawable * drawable = new PolygonalDrawable(mesh.mName.C_Str()); drawable->setGeometry(geometry); drawable->setMode(GL_TRIANGLES); return drawable; }
PolygonalDrawable * ObjIO::createPolygonalDrawable( const ObjObject & object , const ObjGroup & group) { if(group.vis.empty()) return NULL; // TODO: this should test if all consecutive offsets are equal 3. // The current expression could return false positives. if(group.vis.size() / 3 != group.foffs.size()) { qCritical("Ignore polygon with num vertices != 3 (only triangles are supported)."); return NULL; } const bool usesTexCoordIndices(!group.vtis.empty()); const bool usesNormalIndices(!group.vnis.empty()); PolygonalDrawable * drawable = new PolygonalDrawable(); const GLuint size(static_cast<GLuint>(group.vis.size())); for(GLuint i = 0; i < size; ++i) { // add vertex and its new index based on obj index // TODO: make use of vertex reuse! drawable->indices().push_back(i); drawable->vertices().push_back(object.vs[group.vis[i]]); if(usesTexCoordIndices) drawable->texcs().push_back(object.vts[group.vtis[i]]); if(usesNormalIndices) drawable->normals().push_back(object.vns[group.vnis[i]]); } // TODO: support other modes here! drawable->setMode(GL_TRIANGLES); if(!usesNormalIndices) drawable->retrieveNormals(); return drawable; }
void HalfEdgeStructure::setup(PolygonalDrawable & drawable) { if(drawable.indices().isEmpty()) return; const int nTriangles(drawable.indices().size() / 3); m_faces.resize(nTriangles); // TODO: there is strict triangle support only... assert(drawable.indices().size() % 3 == 0); // Map of edges (given by two indices) -> opposite half-edge typedef std::map<std::pair<QVector3D const *, QVector3D const *>, HalfEdge*> t_opp_map; t_opp_map opp; const int he_count = nTriangles * 3; m_halfEdges.resize(he_count); for(int k = 0; k < nTriangles; k++) { m_faces[k].he = &m_halfEdges[k * 3]; for (int i = 0; i < 3; ++i) { const int j(k * 3 + i); m_halfEdges[j].prev = &m_halfEdges[(i == 0) ? j + 2 : j - 1]; m_halfEdges[j].next = &m_halfEdges[(i == 2) ? j - 2 : j + 1]; m_halfEdges[j].opp = NULL; m_halfEdges[j].face = &m_faces[k]; const int l(drawable.indices()[j]); m_halfEdges[j].vertex = &(drawable.vertices()[l]); m_halfEdges[j].normal = drawable.normals()[l]; } // set opposite-pointers for (int i = 0; i < 3; ++i) { const int j(k * 3 + i); QVector3D const * v0 = m_halfEdges[j].vertex; QVector3D const * v1 = m_halfEdges[j].next->vertex; // Check if opposite half-edge is already stored t_opp_map::iterator p = opp.find(t_opp_map::key_type(v0, v1)); if(p == opp.end()) { // no: Add half-edge in opposite direction opp[t_opp_map::key_type(v1, v0)] = &m_halfEdges[j]; } else { // yes: Set opposite-pointers of both half-edges p->second->opp = &m_halfEdges[j]; m_halfEdges[j].opp = p->second; opp.erase(p); } } } calculatePerFaceNormals(); calculatePerVertexNormals(0.f); }