1. 程式人生 > >在Windows平臺上編譯ElasticFusion

在Windows平臺上編譯ElasticFusion

最近在看ElasticFusion的文章,打算在Windows平臺上進行復現,由於涉及到眾多軟體,故在此記錄一下編譯過程,以備後續升級軟體使用。這篇主要記錄完整的Debug x64版編譯過程, 如果不想自己編譯,可直接從用我的百度雲分享,這裡也有編譯所需的全部檔案。
我的專案根目錄是D:\ElasticFusionDebug,其下屬的檔案目錄示例結構如下:

  • Eigen
    • blas
  • ElasticFusion
  • OpenNI2
    • OpenNI.sln
  • Pangolin
  • SuiteSparse
    • build

1. OpenNI2 Debug x64版

按照我的部落格“ElasticFusion之OpenNI2編譯”編譯OpenNI的Debug x64版本。

2. SuiteSparse Release x64版

按照我的部落格“ElasticFusion之Eigen+SuiteSparce編譯”編譯SuiteSparse的Release x64版本,不能編譯Debug x64版。

3. Pangolin Debug x64版

按照我的部落格“ElasticFusion之Pangolin編譯”編譯Pangolin的Debug x64版。

4. ElasticFusion Core Debug x64版

參考連結
將下面的程式碼儲存為static_glew_init.hpp,並放到在ElasticFusion/Core/src資料夾下。

/*
Function to get, find, or initialize Pangolin context and initialize glew
*/

#if !defined(__STATIC_GLEW_INIT_HPP__)
#define __STATIC_GLEW_INIT_HPP__
#define GLEW_STATIC
#include <pangolin/pangolin.h>
#include <pangolin/gl/gl.h>
#include <pangolin/gl/glplatform.h> #include <pangolin/display/display_internal.h> #include <string> static inline void staticGlewInit(std::string name = "Main") { // GetCurrentContext pangolin::PangolinGl* context = pangolin::GetCurrentContext(); if (context == NULL) { // Find Context context = pangolin::FindContext(name); if (context == NULL) { // Create new std::shared_ptr<pangolin::PangolinGl> newcontext(new pangolin::PangolinGl()); AddNewContext(name, newcontext); context = newcontext.get(); std::cout << "Pangolin Context" << name << "created." << std::endl; } else { std::cout << "Pangolin Context" << name << "already exists." << std::endl; } // Make Current Context context->MakeCurrent(); // Initialize GLEW glewExperimental = GL_TRUE; // GL_FALSE; GLenum error = glGetError(); if (error != GL_NO_ERROR) { std::cout << "OpenGL Error: " << error << std::endl; } GLenum glewinit = glewInit(); if (glewinit != GLEW_OK) { std::cout << "Glew Error: " << glewGetErrorString(glewinit) << std::endl; exit(EXIT_FAILURE); } } else { std::cout << "Pangolin Current Context exists." << std::endl; } } #endif /* !__STATIC_GLEW_INIT_HPP__ */

修改CMakeLists.txt檔案,新增下面兩個變數,如下所示:

set(SUITESPARSE_INCLUDE_DIR "D:/ElasticFusionDebug/SuiteSparse/build/install/include/suitesparse")
set(SUITESPARSE_LIBRARY_DIR "D:/ElasticFusionDebug/SuiteSparse/build/install/lib64")

用CMake生成VS解決方案,開啟,在efusion工程Header Files篩選器中新增static_glew_init.hpp。再開啟Shaders.h檔案,在Shader類Shader()建構函式中新增staticGlewInit()函式,修改後的檔案如下所示:

/*
 * This file is part of ElasticFusion.
 *
 * Copyright (C) 2015 Imperial College London
 * 
 * The use of the code within this file and all code within files that 
 * make up the software that is ElasticFusion is permitted for 
 * non-commercial purposes only.  The full terms and conditions that 
 * apply to the code within this file are detailed within the LICENSE.txt 
 * file and at <http://www.imperial.ac.uk/dyson-robotics-lab/downloads/elastic-fusion/elastic-fusion-license/> 
 * unless explicitly stated.  By downloading this file you agree to 
 * comply with these terms.
 *
 * If you wish to use any of this code for commercial purposes then 
 * please email [email protected]
 *
 */

#ifndef SHADERS_SHADERS_H_
#define SHADERS_SHADERS_H_

#include <pangolin/gl/glsl.h>
#include <memory>
#include "../Utils/Parse.h"
#include "../static_glew_init.hpp"
#include "Uniform.h"

class Shader : public pangolin::GlSlProgram
{
    public:
        Shader()
        {
            // glewInit
            staticGlewInit();
        }

        GLuint programId()
        {
            return prog;
        }

        void setUniform(const Uniform & v)
        {
            GLuint loc = glGetUniformLocation(prog, v.id.c_str());

            switch(v.t)
            {
                case Uniform::INT:
                    glUniform1i(loc, v.i);
                    break;
                case Uniform::FLOAT:
                    glUniform1f(loc, v.f);
                    break;
                case Uniform::VEC2:
                    glUniform2f(loc, v.v2(0), v.v2(1));
                    break;
                case Uniform::VEC3:
                    glUniform3f(loc, v.v3(0), v.v3(1), v.v3(2));
                    break;
                case Uniform::VEC4:
                    glUniform4f(loc, v.v4(0), v.v4(1), v.v4(2), v.v4(3));
                    break;
                case Uniform::MAT4:
                    glUniformMatrix4fv(loc, 1, false, v.m4.data());
                    break;
                default:
                    assert(false && "Uniform type not implemented!");
                    break;
            }
        }
};

static inline std::shared_ptr<Shader> loadProgramGeomFromFile(const std::string& vertex_shader_file, const std::string& geometry_shader_file)
{
    std::shared_ptr<Shader> program = std::make_shared<Shader>();

    program->AddShaderFromFile(pangolin::GlSlVertexShader, Parse::get().shaderDir() + "/" + vertex_shader_file, {}, {Parse::get().shaderDir()});
    program->AddShaderFromFile(pangolin::GlSlGeometryShader, Parse::get().shaderDir() + "/" + geometry_shader_file, {}, {Parse::get().shaderDir()});
    program->Link();

    return program;
}

static inline std::shared_ptr<Shader> loadProgramFromFile(const std::string& vertex_shader_file)
{
    std::shared_ptr<Shader> program = std::make_shared<Shader>();

    program->AddShaderFromFile(pangolin::GlSlVertexShader, Parse::get().shaderDir() + "/" + vertex_shader_file, {}, {Parse::get().shaderDir()});
    program->Link();

    return program;
}

static inline std::shared_ptr<Shader> loadProgramFromFile(const std::string& vertex_shader_file, const std::string& fragment_shader_file)
{
    std::shared_ptr<Shader> program = std::make_shared<Shader>();

    program->AddShaderFromFile(pangolin::GlSlVertexShader, Parse::get().shaderDir() + "/" + vertex_shader_file, {}, {Parse::get().shaderDir()});
    program->AddShaderFromFile(pangolin::GlSlFragmentShader, Parse::get().shaderDir() + "/" + fragment_shader_file, {}, {Parse::get().shaderDir()});
    program->Link();

    return program;
}

static inline std::shared_ptr<Shader> loadProgramFromFile(const std::string& vertex_shader_file, const std::string& fragment_shader_file, const std::string& geometry_shader_file)
{
    std::shared_ptr<Shader> program = std::make_shared<Shader>();

    program->AddShaderFromFile(pangolin::GlSlVertexShader, Parse::get().shaderDir() + "/" + vertex_shader_file, {}, {Parse::get().shaderDir()});
    program->AddShaderFromFile(pangolin::GlSlGeometryShader, Parse::get().shaderDir() + "/" + geometry_shader_file, {}, {Parse::get().shaderDir()});
    program->AddShaderFromFile(pangolin::GlSlFragmentShader, Parse::get().shaderDir() + "/" + fragment_shader_file, {}, {Parse::get().shaderDir()});
    program->Link();

    return program;
}

#endif /* SHADERS_SHADERS_H_ */

儲存,編譯。

5. ElasticFusion GUI Debug x64版

修改CMakeLists.txt檔案,新增幾個路徑變數,如下所示:

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}")
set(JPEG_LIBRARY "D:/ElasticFusionDebug/Pangolin/build/external/libjpeg/lib/jpeg.lib")
set(JPEG_INCLUDE_DIR "D:/ElasticFusionDebug/Pangolin/build/external/libjpeg/include")
set(ZLIB_LIBRARY "D:/ElasticFusionDebug/Pangolin/build/external/zlib/lib/zlibd.lib")
set(ZLIB_INCLUDE_DIR "D:/ElasticFusionDebug/Pangolin/build/external/zlib/include")
set(OPENNI2_LIBRARY "D:/ElasticFusionDebug/OpenNI2/Bin/x64-Debug/OpenNI2.lib")
set(SUITESPARSE_INCLUDE_DIR "D:/ElasticFusionDebug/SuiteSparse/build/install/include/suitesparse")
set(SUITESPARSE_LIBRARY_DIR "D:/ElasticFusionDebug/SuiteSparse/build/install/lib64")
set(EFUSION_LIBRARY "D:/ElasticFusionDebug/ElasticFusion/Core/src/build/Debug/efusion.lib")
set(BLAS_LIBRARIES_DIR "D:/ElasticFusionDebug/SuiteSparse/build/install/lib64/lapack_blas_windows")
set(LAPACK_LIBRARIES_DIR  "D:/ElasticFusionDebug/SuiteSparse/build/install/lib64/lapack_blas_windows")

需要根據實際路徑進行修改
用CMake生成VS解決方案,編譯。

6. 測試

將D:\ElasticFusionDebug\OpenNI2\Bin\x64-Debug下OpenNI2資料夾和OpenNI2.dll,將D:\ElasticFusionDebug\SuiteSparse\build\install\lib64\lapack_blas_windows下五個dll檔案,將D:\ElasticFusionDebug\Pangolin\build\external\zlib\bin下zlibd.dll,將D:\ElasticFusionDebug\ElasticFusion\Core\src\build\Debug下efusion.dll,拷貝到D:\ElasticFusionDebug\ElasticFusion\GUI\src\build\Debug下。

開啟命令列視窗,cd到D:\ElasticFusionDebug\ElasticFusion\GUI\src\build\Debug,插上Kinect一代,執行ElasticFusion.exe命令,即可。