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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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);
}