Beispiel #1
0
// Copied from irrlicht
void recalculateTangents(scene::IMesh* mesh, bool recalculate_normals, bool smooth, bool angle_weighted)
{
    if (!mesh)
        return;

    const u32 mesh_buffer_count = mesh->getMeshBufferCount();
    for (u32 b = 0; b<mesh_buffer_count; ++b)
    {
        recalculateTangents(mesh->getMeshBuffer(b), recalculate_normals, smooth, angle_weighted);
    }
}
Beispiel #2
0
// Copied from irrlicht
scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh,
                                                bool(*predicate)(scene::IMeshBuffer*),
                                                bool recalculate_normals, bool smooth,
                                                bool angle_weighted,
                                                bool calculate_tangents)
{
    if (!mesh)
        return 0;

    // copy mesh and fill data into SMeshBufferTangents

    const u32 mesh_buffer_count = mesh->getMeshBufferCount();

    bool needs_normal_map = false;
    for (u32 b = 0; b < mesh_buffer_count; ++b)
    {
        scene::IMeshBuffer* original = mesh->getMeshBuffer(b);
        if (predicate(original))
        {
            needs_normal_map = true;
            break;
        }
    }

    if (!needs_normal_map)
    {
        return mesh;
    }
    scene::SMesh* clone = new scene::SMesh();

    for (u32 b = 0; b<mesh_buffer_count; ++b)
    {
        scene::IMeshBuffer* original = mesh->getMeshBuffer(b);
        const u32 idxCnt = original->getIndexCount();
        const u16* idx = original->getIndices();

        if (!predicate(original))
        {
            clone->addMeshBuffer(original);
            continue;
        }

        scene::SMeshBufferTangents* buffer = new scene::SMeshBufferTangents();

        buffer->Material = original->getMaterial();
        buffer->Vertices.reallocate(idxCnt);
        buffer->Indices.reallocate(idxCnt);

        core::map<video::S3DVertexTangents, int> vertMap;
        int vertLocation;

        // copy vertices

        const video::E_VERTEX_TYPE vType = original->getVertexType();
        video::S3DVertexTangents vNew;
        for (u32 i = 0; i<idxCnt; ++i)
        {
            switch (vType)
            {
                case video::EVT_STANDARD:
                {
                    const video::S3DVertex* v =
                        (const video::S3DVertex*)original->getVertices();
                    vNew = video::S3DVertexTangents(
                        v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
                }
                break;
                case video::EVT_2TCOORDS:
                {
                    const video::S3DVertex2TCoords* v =
                        (const video::S3DVertex2TCoords*)original->getVertices();
                    vNew = video::S3DVertexTangents(
                        v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
                }
                break;
                case video::EVT_TANGENTS:
                {
                        const video::S3DVertexTangents* v =
                            (const video::S3DVertexTangents*)original->getVertices();
                        vNew = v[idx[i]];
                }
                break;
            }
            core::map<video::S3DVertexTangents, int>::Node* n = vertMap.find(vNew);
            if (n)
            {
                vertLocation = n->getValue();
            }
            else
            {
                vertLocation = buffer->Vertices.size();
                buffer->Vertices.push_back(vNew);
                vertMap.insert(vNew, vertLocation);
            }

            // create new indices
            buffer->Indices.push_back(vertLocation);
        }
        buffer->recalculateBoundingBox();

        // add new buffer
        clone->addMeshBuffer(buffer);
        buffer->drop();
    }

    clone->recalculateBoundingBox();
    if (calculate_tangents)
        recalculateTangents(clone, recalculate_normals, smooth, angle_weighted);

    scene::IMeshCache* meshCache = irr_driver->getSceneManager()->getMeshCache();
    io::SNamedPath path = meshCache->getMeshName(mesh);
    if (path.getPath() == "")
    {
        // This mesh is not in irrlicht cache, drop it directly
        assert(mesh->getReferenceCount() == 1);
        mesh->drop();
        return clone;
    }
    else
    {
        // Cache the calcuated tangent mesh with path
        irr_driver->removeMeshFromCache(mesh);
        scene::SAnimatedMesh* amesh = new scene::SAnimatedMesh(clone);
        clone->drop();
        meshCache->addMesh(path, amesh);
        if (World::getWorld())
        {
            irr_driver->grabAllTextures(amesh);
            World::getWorld()->getTrack()->addCachedMesh(amesh);
            return amesh;
        }
        amesh->drop();
        return amesh;
    }

}
// Copied from irrlicht
scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh, bool(*predicate)(scene::IMeshBuffer*),
    bool recalculateNormals, bool smooth, bool angleWeighted, bool calculateTangents)
{
    if (!mesh)
        return 0;

    // copy mesh and fill data into SMeshBufferTangents

    scene::SMesh* clone = new scene::SMesh();
    const u32 meshBufferCount = mesh->getMeshBufferCount();

    bool needsNormalMap = false;
    for (u32 b = 0; b < meshBufferCount; ++b)
    {
        scene::IMeshBuffer* original = mesh->getMeshBuffer(b);
        if (predicate(original))
        {
            needsNormalMap = true;
            break;
        }
    }

    if (!needsNormalMap)
    {
        return mesh;
    }

    for (u32 b = 0; b<meshBufferCount; ++b)
    {
        scene::IMeshBuffer* original = mesh->getMeshBuffer(b);
        const u32 idxCnt = original->getIndexCount();
        const u16* idx = original->getIndices();

        if (!predicate(original))
        {
            clone->addMeshBuffer(original);
            continue;
        }

        scene::SMeshBufferTangents* buffer = new scene::SMeshBufferTangents();

        buffer->Material = original->getMaterial();
        buffer->Vertices.reallocate(idxCnt);
        buffer->Indices.reallocate(idxCnt);

        core::map<video::S3DVertexTangents, int> vertMap;
        int vertLocation;

        // copy vertices

        const video::E_VERTEX_TYPE vType = original->getVertexType();
        video::S3DVertexTangents vNew;
        for (u32 i = 0; i<idxCnt; ++i)
        {
            switch (vType)
            {
            case video::EVT_STANDARD:
            {
                                        const video::S3DVertex* v =
                                            (const video::S3DVertex*)original->getVertices();
                                        vNew = video::S3DVertexTangents(
                                            v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
            }
                break;
            case video::EVT_2TCOORDS:
            {
                                        const video::S3DVertex2TCoords* v =
                                            (const video::S3DVertex2TCoords*)original->getVertices();
                                        vNew = video::S3DVertexTangents(
                                            v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
            }
                break;
            case video::EVT_TANGENTS:
            {
                                        const video::S3DVertexTangents* v =
                                            (const video::S3DVertexTangents*)original->getVertices();
                                        vNew = v[idx[i]];
            }
                break;
            }
            core::map<video::S3DVertexTangents, int>::Node* n = vertMap.find(vNew);
            if (n)
            {
                vertLocation = n->getValue();
            }
            else
            {
                vertLocation = buffer->Vertices.size();
                buffer->Vertices.push_back(vNew);
                vertMap.insert(vNew, vertLocation);
            }

            // create new indices
            buffer->Indices.push_back(vertLocation);
        }
        buffer->recalculateBoundingBox();

        // add new buffer
        clone->addMeshBuffer(buffer);
        buffer->drop();
    }

    clone->recalculateBoundingBox();
    if (calculateTangents)
        recalculateTangents(clone, recalculateNormals, smooth, angleWeighted);
    
    irr_driver->removeMeshFromCache(mesh);

    return clone;
}