基於Qt的Live2D模型顯示以及控制
基本說明
-
Live2D官方提供有控制Live2D模型的SDK,而且還提供了一個基於OpenGL的C++項目Example,我們可以基於該項目改成Qt的項目,做一個桌面端的Live2D桌寵程序。
- 經過改造效果如下圖所示。
官方項目配置
-
下載官方提供的SDK例程,,選擇Cubism SDK for Native。
-
下載解壓後應該是下面的樣子。
-
其中Core文件夾放的是核心庫Live2DCubismCore的動態鏈接庫,提供有各個平臺,我們只需要用windows的鏈接庫就可以了。
-
Framework提供基本的框架用於模型的讀取和配置,我們可以使用源碼也可以用它編譯成的鏈接庫。
-
Samples文件夾存放就是Example,裏面有對應的腳本,可以生成VS項目。
-
-
生成VS項目
-
進入Samples/OpenGL/Demo/proj.win.cmake/scripts目錄下,根據你們安裝的vs版本,選擇對應的腳本進行項目生成。
-
在生成項目之前還需要配置一下第三方模塊,不然無法生成。因爲用到Opengl.所以需要glew和glfw模塊。雖然官方有提供腳本一鍵配置,不過文件下載不了,我們需要手動下載配置。去github下載glfw和glew源碼。
然後來到Samples/OpenGL/thirdParty目錄下,解壓剛纔下載的兩個文件,得到兩個文件夾,文件夾名字記得修改爲glew和glfw。配置完成如下所示。
-
配置完第三方模塊後,使用項目腳本生成vs項目,打開腳本後,有一些選項可以配置,根據提示和自己需求配置即可。
-
如果之前的步驟沒有錯會在Samples/OpenGL/Demo/proj.win.cmake/目錄生成build文件夾.我們打開裏面的Demo.sln文件,即可在vs中運行項目。
點擊運行項目,即可運行官方示例。
在vs中我們看到除了Demo項目,還有glew,glfw,framework項目,它們是用來生成鏈接庫的,我們把他們設爲啓動項目然後生成一遍,得到對應鏈接庫,之後我們要用的。glew會生成glew32.lib,libglew32.lib。glfw會生成glfw3.lib。framework會生成Framework.lib。
-
至此我們就完成了第一步,跑起來官方的例程,之後想怎麼改就怎麼改。
-
準備移植Qt的文件
-
需要的鏈接庫
-
我們以Release,x64爲環境,之前的鏈接庫也按照這個模式生成。
-
首先需要我們自己生成的鏈接庫glew32.lib,libglew32.lib,glfw3.lib,Framework.lib。還有官方提供的Core鏈接庫Live2DCubismCore_MD.lib/Live2DCubismCore_MT.lib。根據我們之前配置項目時的設置,選擇MD或者MT即可。鏈接庫在下載的SDK目錄Core/lib/windows下,我們根據自己使用的vs版本選擇對應的庫,v143是Vs2022,v142是Vs2019,v141是Vs2017。
-
最後還需要主動鏈接一些系統庫,這些需要的庫我們可以在VS中查看Demo項目在屬性頁中的鏈接器看到。
pragma comment(lib, "kernel32.lib")
pragma comment(lib, "user32.lib")
pragma comment(lib, "gdi32.lib")
pragma comment(lib, "OpenGL32.lib")
pragma comment(lib, "glu32.lib")
-
-
需要的源代碼
-
我們需要在官方給出的控制代碼中一些修改一些文件,改成適合Qt程序的。所需源碼如下所示。
-
還有上面的鏈接庫glfw,glew,Framework,Live2DCubismCore_MD.lib/Live2DCubismCore_MT.lib對應的頭文件(*.h/*.hpp),以及stb_image.h文件。這些文件都可以在下載的SDK中找到。
-
移植Qt
Qt中有封裝的OpenGL類(QOpenGLWidget),我們要做的就是把模型渲染在我們自己的OpenGL窗口上。
-
準備以上文件後我們用Qt Creator新建一個帶界面UI文件的Qt程序,編譯器使用MSVC對應的版本,名字叫Live2DDemo,然後把以上鍊接庫,源文件,頭文件添加到項目中。
-
添加完成後Qt工程如下所示
我們需要在mainwindow.h中手動鏈接一下這些庫。
pragma comment(lib, "kernel32.lib")
pragma comment(lib, "user32.lib")
pragma comment(lib, "gdi32.lib")
pragma comment(lib, "OpenGL32.lib")
pragma comment(lib, "glu32.lib")
pro文件配置中加一個預定義宏,表示在WINDOWS平臺
DEFINES += CSM_TARGET_WIN_GL
Framework的頭文件直接把SDK中的Framework/src/目錄下的所有文件直接複製過來就行,不用刪除其中的cpp文件。GL和GLFW的文件夾名字不能改,因爲它們源碼就是以“GL/*.h"的方式包含的。如果更改了,需要去源碼那裏改一下頭文件的包含。
項目的工程目錄,inc目錄存放頭文件,libs存放鏈接庫,live2d存放需要修改的代碼。
配置根據各自的情況配置就行,其實就是配置一些頭文件和鏈接庫。
-
如果上面的配置都沒有錯,編譯應該是可以通過的。如果有報錯,根據報錯提示修改即可。報錯一般就是以下情況。
-
頭文件找不到。在工程文件Pro中加上缺少的即可,注意一下目錄層級。
-
鏈接庫找不到。看看是不是x64,release,MSVC的編譯環境,鏈接庫是不是x64,release環境下生成的,鏈接庫路徑有沒有寫對。
-
修改源碼
上面的配置都沒有問題後,我們就可以開始修改,把Live2D模型渲染到Qt的QOpenGLWidget窗口上。
-
新建一個類MyOpenGL然後繼承QOpenGLWidget,然後重寫下面幾個protected函數。
void initializeGL()
void resizeGL(int w, int h)
void paintGL()
下面幾個頭文件要放在cpp文件包含。
然後在mainwindow.ui界面拖拽一個QOpenGLWiget控件,提升爲我們自定義的類MyOpenGL。如果一切都沒有錯,運行後就是下面的樣子。
-
修改LAppDelegate類。
-
在LAppDelegate.hpp中包含myopengl.h頭文件,然後在public下新增兩個函數聲明。
-
註釋原來的GLFWwindow*_window,改成MyOpenGL*_window。然後修改GetWindow函數。
-
Initialize()函數修改如下
-
LAppDelegate.cpp
- 在Initialize函數中做如下修改。
- Release函數修改如下
- void LAppDelegate::Run() 函數的所有內容註釋掉,我們要把功能拆分到新增的resize()和update()函數中。兩個函數如下
-
-
修改width和height的獲取方式
原來的代碼中獲取渲染窗口的寬和高是通過glfwGetWindowSize() 函數,但我們修改爲了自己的OpenGL窗口,因此所有用到這個函數的地方都要修改。我們可以先編譯一下看看哪裏報錯,然後跳到對應地方修改就可以了。需要修改的地方比較多就不一一截出來了,修改都是類似的。
-
修改我們自己的MyOPenGL類
-
添加Resource
-
下載的SDK中有官方提供的一些live2D模型,我們把整個Resources文件夾放到exe程序的上一級目錄。因爲在Qt Creator中運行程序,運行目錄默認是exe程序的上一級目錄。
-
如果上面的步驟都沒有錯,運行出來的效果如下。如果程序閃退就是Resources文件夾放的位置不對,導致找不到文件而閃退。
-
-
加上鼠標事件和定時更新功能
鼠標事件用於和模型進行互動,可以觸發一些特定動作
到這裏就基本和官方的效果差不多了,至於更多自定義修改,比如去掉背景和一些部件,模型的自定義顯示,模型的切換等等,把那些控制代碼看看,根據的需求修改即可。
一些問題
-
Windows上Qt Creator的一些問題。
-
打開速度慢,文件跳轉慢,有時還會卡頓閃退。
-
有些配置文件修改了,但是Qt沒有加載,而是用之前的緩存,導致程序修改了,但編譯時還是用沒有修改之前的文件。
-
ui界面修改了,但是編譯的ui文件還是用之前的,導致修改了界面,程序運行後界面還是和之前一樣。
以上問題我在移植的時候都遇到過,還以爲是配置錯了,浪費了不少時間排查才知道Qt Creator沒有讀取我的最新修改,而是用之前緩存的。我重新Rebuild都沒用,需要自己去刪掉之前文件纔行。如果不是很熟悉Qt和Qt Creator,建議使用VS+Qt插件來進行配置。
-
-
如果上面的配置比較複雜或者遇到錯誤,我這有一個在MSVC2019,x64,Release配置好的Qt工程和編譯好的程序,其實就是上面的舉例的項目。
提取碼: o3vi
失效了可以聯繫我。
DesktopLive2D
基於上面的修改,我開發了一個Live2D模型桌面程序,可以把live2D模型放在桌面上,進行互動,支持自定義加載模型,幀率設置,快速切換模型,鼠標互動。後續準備加上ChatGPT和TTS。
感興趣可以去GitHub Star一下。
有任何問題可以聯繫我wx(base64) :aGVjaHVzaGluaQ==