diff --git a/3rdparty/Live2D/Lib/Debug/linux_arm/framework/README.md b/3rdparty/Live2D/Lib/Debug/linux_arm/framework/README.md new file mode 100644 index 0000000..2c626b5 --- /dev/null +++ b/3rdparty/Live2D/Lib/Debug/linux_arm/framework/README.md @@ -0,0 +1,195 @@ +## Framework模块说明 + +由于嵌入式Linux的硬件差异性导致的不同嵌入式板子的sysroot不同,导致不同的板子环境差异很大, +因此对于framework这个模块,需要自行根据自己板子的sysroot或者sdk进行交叉编译。 + +#### 如何交叉编译Framework模块 +在本项目当中,有一个适用于rk3566的framework模块, +因为framework模块一般不会使用到一些特别的硬件或者是后端(音频后端之类的), +所以理论上其他rk3566的板子也可以使用我预编译的模块。 + +给出交叉编译步骤(以编译我的rk3566为例): +```shell +cmake -S ../Framework -B . \ + -DCMAKE_TOOLCHAIN_FILE=~/MisakiCodes/Env/rk3566-sdk/qt_toolchain.cmake \ + -DCMAKE_BUILD_TYPE=Debug \ + -DFRAMEWORK_SOURCE=OpenGL \ + -DRENDER_INCLUDE_PATH="${CMAKE_SOURCE_DIR}/Framework/src/Rendering/OpenGL" \ + -DFRAMEWORK_DEFINITIOINS="CSM_TARGET_HARMONYOS_ES3" +``` + +预期的配置输出: +```shell +CMake Warning (dev) in CMakeLists.txt: + No project() command is present. The top-level CMakeLists.txt file must + contain a literal, direct call to the project() command. Add a line of + code such as + + project(ProjectName) + + near the top of the file, but after cmake_minimum_required(). + + CMake is pretending there is a "project(Project)" command on the first + line. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning (dev) in CMakeLists.txt: + cmake_minimum_required() should be called prior to this top-level project() + call. Please see the cmake-commands(7) manual for usage documentation of + both commands. +This warning is for project developers. Use -Wno-dev to suppress it. + +-- The C compiler identification is GNU 12.3.0 +-- The CXX compiler identification is GNU 12.3.0 +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working C compiler: /home/misaki/MisakiCodes/Env/rk3566-sdk/toolchain/aarch64--glibc--stable-2023.08-1/bin/aarch64-linux-gcc - skipped +-- Detecting C compile features +-- Detecting C compile features - done +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Check for working CXX compiler: /home/misaki/MisakiCodes/Env/rk3566-sdk/toolchain/aarch64--glibc--stable-2023.08-1/bin/aarch64-linux-g++ - skipped +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Configuring done (0.5s) +-- Generating done (0.0s) +-- Build files have been written to: /home/misaki/Downloads/CubismSdkForNative-5-r.4.1/build_framework +``` + +观察上述命令可知,首先你肯定需要准备Live2D的SDK,这可以在官网下载,不在此过多赘述。 + +接着在与Framework的同级目录下新建一个xxx_build目录,如果你不知道这是什么,那么最好借助一下AI来帮助你。 + +之后就是cd到build目录里面。 + +Framework模块承担了Live2D的很多功能,其中唯一一个平台有关的就是Render模块, +也就是渲染功能,不过Live2D的库的渲染部分写的比较好,统一使用了OpenGL ES,同时兼容主机平台和arm移动平台。 + +你需要准备一个编译工具链,也就toolchain.cmake脚本的内容,这个编译工具链描述了编译器信息,sysroot信息等等。 +下面给出我自己的工具链作为参考。 +```cmake +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR aarch64) + +set(TOOLCHAIN_ROOT /home/misaki/MisakiCodes/Env/rk3566-sdk/toolchain/aarch64--glibc--stable-2023.08-1) +set(CMAKE_C_COMPILER ${TOOLCHAIN_ROOT}/bin/aarch64-linux-gcc) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_ROOT}/bin/aarch64-linux-g++) +set(CMAKE_AR ${TOOLCHAIN_ROOT}/bin/aarch64-linux-ar) +set(CMAKE_RANLIB ${TOOLCHAIN_ROOT}/bin/aarch64-linux-ranlib) +set(CMAKE_STRIP ${TOOLCHAIN_ROOT}/bin/aarch64-linux-strip) + +set(SYSROOT /home/misaki/MisakiCodes/Env/rk3566-sdk/host/aarch64-buildroot-linux-gnu/sysroot) +set(VPET_SDK /home/misaki/MisakiCodes/Env/rk3566-sdk/vpet-deps) +set(QT_HOST_PATH /home/misaki/Qt/6.6.3/gcc_64) + +set(CMAKE_FIND_ROOT_PATH ${SYSROOT} ${VPET_SDK}) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH) # 不使用only,否则会导致CMake找不到其他库的包,例如Qt的,会直接导致FindPackage失效,只能找sysroot里面的包 + +set(CMAKE_C_FLAGS "-march=armv8.2-a -mtune=cortex-a55 -O2 -pipe --sysroot=${SYSROOT}") +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++17") + +# === 关键:强制链接 Mali 驱动和 EGL/GLES === +set(MALI_LIBS "-lmali-hook -Wl,--whole-archive -lmali-hook-injector -Wl,--no-whole-archive -lmali -ldrm") + +set(CMAKE_EXE_LINKER_FLAGS + "-Wl,-dynamic-linker=/lib/ld-linux-aarch64.so.1 \ + -Wl,-rpath,/data/vpet/deps/lib:/usr/lib:/lib \ + --sysroot=${SYSROOT} \ + ${MALI_LIBS}" +) +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") +set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") + +# === 包含路径 === +include_directories( + ${VPET_SDK}/include + ${VPET_SDK}/include/libdrm + ${SYSROOT}/usr/include +) + +# === 库路径 === +link_directories( + ${VPET_SDK}/lib + ${SYSROOT}/usr/lib + ${SYSROOT}/lib +) + +# === pkg-config === +set(ENV{PKG_CONFIG} "/usr/bin/pkg-config") +set(ENV{PKG_CONFIG_LIBDIR} "/home/misaki/MisakiCodes/Env/rk3566-sdk/qt-pkgconfig") +set(ENV{PKG_CONFIG_SYSROOT_DIR} "${SYSROOT}") +set(ENV{PKG_CONFIG_PATH} "") + +# === 线程 === +set(CMAKE_THREAD_LIBS_INIT "-lpthread") +set(THREADS_PREFER_PTHREAD_FLAG ON) +``` + +你需要根据自己的实际情况进行调整。 + +之前的命令是配置CMake的,编译还需: +```shell +cmake --build . --target Framework -j$(nproc) +``` + + +预期的编译日志输出: +```shell +[ 7%] Building CXX object CMakeFiles/Framework.dir/src/CubismModelSettingJson.cpp.o +[ 7%] Building CXX object CMakeFiles/Framework.dir/src/CubismDefaultParameterId.cpp.o +[ 7%] Building CXX object CMakeFiles/Framework.dir/src/CubismCdiJson.cpp.o +[ 10%] Building CXX object CMakeFiles/Framework.dir/src/CubismFramework.cpp.o +[ 12%] Building CXX object CMakeFiles/Framework.dir/src/Effect/CubismEyeBlink.cpp.o +[ 15%] Building CXX object CMakeFiles/Framework.dir/src/Id/CubismId.cpp.o +[ 17%] Building CXX object CMakeFiles/Framework.dir/src/Effect/CubismPose.cpp.o +[ 20%] Building CXX object CMakeFiles/Framework.dir/src/Effect/CubismBreath.cpp.o +[ 22%] Building CXX object CMakeFiles/Framework.dir/src/Id/CubismIdManager.cpp.o +[ 25%] Building CXX object CMakeFiles/Framework.dir/src/Math/CubismMath.cpp.o +[ 27%] Building CXX object CMakeFiles/Framework.dir/src/Math/CubismMatrix44.cpp.o +[ 30%] Building CXX object CMakeFiles/Framework.dir/src/Math/CubismModelMatrix.cpp.o +[ 32%] Building CXX object CMakeFiles/Framework.dir/src/Math/CubismTargetPoint.cpp.o +[ 35%] Building CXX object CMakeFiles/Framework.dir/src/Math/CubismViewMatrix.cpp.o +[ 37%] Building CXX object CMakeFiles/Framework.dir/src/Math/CubismVector2.cpp.o +[ 40%] Building CXX object CMakeFiles/Framework.dir/src/Model/CubismMoc.cpp.o +[ 42%] Building CXX object CMakeFiles/Framework.dir/src/Model/CubismModel.cpp.o +[ 45%] Building CXX object CMakeFiles/Framework.dir/src/Model/CubismModelUserData.cpp.o +[ 47%] Building CXX object CMakeFiles/Framework.dir/src/Model/CubismModelUserDataJson.cpp.o +[ 50%] Building CXX object CMakeFiles/Framework.dir/src/Model/CubismUserModel.cpp.o +[ 52%] Building CXX object CMakeFiles/Framework.dir/src/Motion/ACubismMotion.cpp.o +[ 55%] Building CXX object CMakeFiles/Framework.dir/src/Motion/CubismExpressionMotion.cpp.o +[ 57%] Building CXX object CMakeFiles/Framework.dir/src/Motion/CubismExpressionMotionManager.cpp.o +[ 60%] Building CXX object CMakeFiles/Framework.dir/src/Motion/CubismMotion.cpp.o +[ 62%] Building CXX object CMakeFiles/Framework.dir/src/Motion/CubismMotionJson.cpp.o +[ 65%] Building CXX object CMakeFiles/Framework.dir/src/Motion/CubismMotionManager.cpp.o +[ 67%] Building CXX object CMakeFiles/Framework.dir/src/Motion/CubismMotionQueueEntry.cpp.o +[ 70%] Building CXX object CMakeFiles/Framework.dir/src/Motion/CubismMotionQueueManager.cpp.o +[ 72%] Building CXX object CMakeFiles/Framework.dir/src/Physics/CubismPhysics.cpp.o +[ 75%] Building CXX object CMakeFiles/Framework.dir/src/Rendering/CubismRenderer.cpp.o +[ 77%] Building CXX object CMakeFiles/Framework.dir/src/Physics/CubismPhysicsJson.cpp.o +[ 80%] Building CXX object CMakeFiles/Framework.dir/src/Rendering/OpenGL/CubismOffscreenSurface_OpenGLES2.cpp.o +[ 82%] Building CXX object CMakeFiles/Framework.dir/src/Rendering/OpenGL/CubismShader_OpenGLES2.cpp.o +[ 85%] Building CXX object CMakeFiles/Framework.dir/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.cpp.o +[ 87%] Building CXX object CMakeFiles/Framework.dir/src/Type/csmRectF.cpp.o +[ 90%] Building CXX object CMakeFiles/Framework.dir/src/Type/csmString.cpp.o +[ 92%] Building CXX object CMakeFiles/Framework.dir/src/Utils/CubismDebug.cpp.o +[ 95%] Building CXX object CMakeFiles/Framework.dir/src/Utils/CubismJson.cpp.o +[ 97%] Building CXX object CMakeFiles/Framework.dir/src/Utils/CubismString.cpp.o +In file included from /home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Rendering/OpenGL/../CubismClippingManager.hpp:152, + from /home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.hpp:11, + from /home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.cpp:8: +/home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Rendering/OpenGL/../CubismClippingManager.tpp: In instantiation of ‘Live2D::Cubism::Framework::Rendering::CubismClippingManager::~CubismClippingManager() [with T_ClippingContext = Live2D::Cubism::Framework::Rendering::CubismClippingContext_OpenGLES2; T_OffscreenSurface = Live2D::Cubism::Framework::Rendering::CubismOffscreenSurface_OpenGLES2]’: +/home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.hpp:61:7: required from here +/home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Rendering/OpenGL/../CubismClippingManager.tpp:66:33: warning: passing NULL to non-pointer argument 1 of ‘Live2D::Cubism::Framework::csmVector::csmVector(Live2D::Cubism::Framework::csmInt32, Live2D::Cubism::Framework::csmBool) [with T = bool; Live2D::Cubism::Framework::csmInt32 = int; Live2D::Cubism::Framework::csmBool = bool]’ [-Wconversion-null] + 66 | _clearedMaskBufferFlags = NULL; + | ^ +In file included from /home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Rendering/OpenGL/../CubismRenderer.hpp:12, + from /home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.hpp:10: +/home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Type/csmVector.hpp:559:34: note: declared here + 559 | csmVector::csmVector(csmInt32 initialCapacity, csmBool zeroClear) + | ~~~~~~~~~^~~~~~~~~~~~~~~ +[100%] Linking CXX static library libFramework.a +[100%] Built target Framework +``` \ No newline at end of file diff --git a/3rdparty/Live2D/Lib/Debug/linux_arm/framework/misaki_rk3566/libFramework.a b/3rdparty/Live2D/Lib/Debug/linux_arm/framework/misaki_rk3566/libFramework.a new file mode 100644 index 0000000..7cc25ff Binary files /dev/null and b/3rdparty/Live2D/Lib/Debug/linux_arm/framework/misaki_rk3566/libFramework.a differ diff --git a/3rdparty/Live2D/Lib/Release/linux_arm/framework/README.md b/3rdparty/Live2D/Lib/Release/linux_arm/framework/README.md new file mode 100644 index 0000000..2c626b5 --- /dev/null +++ b/3rdparty/Live2D/Lib/Release/linux_arm/framework/README.md @@ -0,0 +1,195 @@ +## Framework模块说明 + +由于嵌入式Linux的硬件差异性导致的不同嵌入式板子的sysroot不同,导致不同的板子环境差异很大, +因此对于framework这个模块,需要自行根据自己板子的sysroot或者sdk进行交叉编译。 + +#### 如何交叉编译Framework模块 +在本项目当中,有一个适用于rk3566的framework模块, +因为framework模块一般不会使用到一些特别的硬件或者是后端(音频后端之类的), +所以理论上其他rk3566的板子也可以使用我预编译的模块。 + +给出交叉编译步骤(以编译我的rk3566为例): +```shell +cmake -S ../Framework -B . \ + -DCMAKE_TOOLCHAIN_FILE=~/MisakiCodes/Env/rk3566-sdk/qt_toolchain.cmake \ + -DCMAKE_BUILD_TYPE=Debug \ + -DFRAMEWORK_SOURCE=OpenGL \ + -DRENDER_INCLUDE_PATH="${CMAKE_SOURCE_DIR}/Framework/src/Rendering/OpenGL" \ + -DFRAMEWORK_DEFINITIOINS="CSM_TARGET_HARMONYOS_ES3" +``` + +预期的配置输出: +```shell +CMake Warning (dev) in CMakeLists.txt: + No project() command is present. The top-level CMakeLists.txt file must + contain a literal, direct call to the project() command. Add a line of + code such as + + project(ProjectName) + + near the top of the file, but after cmake_minimum_required(). + + CMake is pretending there is a "project(Project)" command on the first + line. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning (dev) in CMakeLists.txt: + cmake_minimum_required() should be called prior to this top-level project() + call. Please see the cmake-commands(7) manual for usage documentation of + both commands. +This warning is for project developers. Use -Wno-dev to suppress it. + +-- The C compiler identification is GNU 12.3.0 +-- The CXX compiler identification is GNU 12.3.0 +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working C compiler: /home/misaki/MisakiCodes/Env/rk3566-sdk/toolchain/aarch64--glibc--stable-2023.08-1/bin/aarch64-linux-gcc - skipped +-- Detecting C compile features +-- Detecting C compile features - done +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Check for working CXX compiler: /home/misaki/MisakiCodes/Env/rk3566-sdk/toolchain/aarch64--glibc--stable-2023.08-1/bin/aarch64-linux-g++ - skipped +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Configuring done (0.5s) +-- Generating done (0.0s) +-- Build files have been written to: /home/misaki/Downloads/CubismSdkForNative-5-r.4.1/build_framework +``` + +观察上述命令可知,首先你肯定需要准备Live2D的SDK,这可以在官网下载,不在此过多赘述。 + +接着在与Framework的同级目录下新建一个xxx_build目录,如果你不知道这是什么,那么最好借助一下AI来帮助你。 + +之后就是cd到build目录里面。 + +Framework模块承担了Live2D的很多功能,其中唯一一个平台有关的就是Render模块, +也就是渲染功能,不过Live2D的库的渲染部分写的比较好,统一使用了OpenGL ES,同时兼容主机平台和arm移动平台。 + +你需要准备一个编译工具链,也就toolchain.cmake脚本的内容,这个编译工具链描述了编译器信息,sysroot信息等等。 +下面给出我自己的工具链作为参考。 +```cmake +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR aarch64) + +set(TOOLCHAIN_ROOT /home/misaki/MisakiCodes/Env/rk3566-sdk/toolchain/aarch64--glibc--stable-2023.08-1) +set(CMAKE_C_COMPILER ${TOOLCHAIN_ROOT}/bin/aarch64-linux-gcc) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_ROOT}/bin/aarch64-linux-g++) +set(CMAKE_AR ${TOOLCHAIN_ROOT}/bin/aarch64-linux-ar) +set(CMAKE_RANLIB ${TOOLCHAIN_ROOT}/bin/aarch64-linux-ranlib) +set(CMAKE_STRIP ${TOOLCHAIN_ROOT}/bin/aarch64-linux-strip) + +set(SYSROOT /home/misaki/MisakiCodes/Env/rk3566-sdk/host/aarch64-buildroot-linux-gnu/sysroot) +set(VPET_SDK /home/misaki/MisakiCodes/Env/rk3566-sdk/vpet-deps) +set(QT_HOST_PATH /home/misaki/Qt/6.6.3/gcc_64) + +set(CMAKE_FIND_ROOT_PATH ${SYSROOT} ${VPET_SDK}) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH) # 不使用only,否则会导致CMake找不到其他库的包,例如Qt的,会直接导致FindPackage失效,只能找sysroot里面的包 + +set(CMAKE_C_FLAGS "-march=armv8.2-a -mtune=cortex-a55 -O2 -pipe --sysroot=${SYSROOT}") +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++17") + +# === 关键:强制链接 Mali 驱动和 EGL/GLES === +set(MALI_LIBS "-lmali-hook -Wl,--whole-archive -lmali-hook-injector -Wl,--no-whole-archive -lmali -ldrm") + +set(CMAKE_EXE_LINKER_FLAGS + "-Wl,-dynamic-linker=/lib/ld-linux-aarch64.so.1 \ + -Wl,-rpath,/data/vpet/deps/lib:/usr/lib:/lib \ + --sysroot=${SYSROOT} \ + ${MALI_LIBS}" +) +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") +set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") + +# === 包含路径 === +include_directories( + ${VPET_SDK}/include + ${VPET_SDK}/include/libdrm + ${SYSROOT}/usr/include +) + +# === 库路径 === +link_directories( + ${VPET_SDK}/lib + ${SYSROOT}/usr/lib + ${SYSROOT}/lib +) + +# === pkg-config === +set(ENV{PKG_CONFIG} "/usr/bin/pkg-config") +set(ENV{PKG_CONFIG_LIBDIR} "/home/misaki/MisakiCodes/Env/rk3566-sdk/qt-pkgconfig") +set(ENV{PKG_CONFIG_SYSROOT_DIR} "${SYSROOT}") +set(ENV{PKG_CONFIG_PATH} "") + +# === 线程 === +set(CMAKE_THREAD_LIBS_INIT "-lpthread") +set(THREADS_PREFER_PTHREAD_FLAG ON) +``` + +你需要根据自己的实际情况进行调整。 + +之前的命令是配置CMake的,编译还需: +```shell +cmake --build . --target Framework -j$(nproc) +``` + + +预期的编译日志输出: +```shell +[ 7%] Building CXX object CMakeFiles/Framework.dir/src/CubismModelSettingJson.cpp.o +[ 7%] Building CXX object CMakeFiles/Framework.dir/src/CubismDefaultParameterId.cpp.o +[ 7%] Building CXX object CMakeFiles/Framework.dir/src/CubismCdiJson.cpp.o +[ 10%] Building CXX object CMakeFiles/Framework.dir/src/CubismFramework.cpp.o +[ 12%] Building CXX object CMakeFiles/Framework.dir/src/Effect/CubismEyeBlink.cpp.o +[ 15%] Building CXX object CMakeFiles/Framework.dir/src/Id/CubismId.cpp.o +[ 17%] Building CXX object CMakeFiles/Framework.dir/src/Effect/CubismPose.cpp.o +[ 20%] Building CXX object CMakeFiles/Framework.dir/src/Effect/CubismBreath.cpp.o +[ 22%] Building CXX object CMakeFiles/Framework.dir/src/Id/CubismIdManager.cpp.o +[ 25%] Building CXX object CMakeFiles/Framework.dir/src/Math/CubismMath.cpp.o +[ 27%] Building CXX object CMakeFiles/Framework.dir/src/Math/CubismMatrix44.cpp.o +[ 30%] Building CXX object CMakeFiles/Framework.dir/src/Math/CubismModelMatrix.cpp.o +[ 32%] Building CXX object CMakeFiles/Framework.dir/src/Math/CubismTargetPoint.cpp.o +[ 35%] Building CXX object CMakeFiles/Framework.dir/src/Math/CubismViewMatrix.cpp.o +[ 37%] Building CXX object CMakeFiles/Framework.dir/src/Math/CubismVector2.cpp.o +[ 40%] Building CXX object CMakeFiles/Framework.dir/src/Model/CubismMoc.cpp.o +[ 42%] Building CXX object CMakeFiles/Framework.dir/src/Model/CubismModel.cpp.o +[ 45%] Building CXX object CMakeFiles/Framework.dir/src/Model/CubismModelUserData.cpp.o +[ 47%] Building CXX object CMakeFiles/Framework.dir/src/Model/CubismModelUserDataJson.cpp.o +[ 50%] Building CXX object CMakeFiles/Framework.dir/src/Model/CubismUserModel.cpp.o +[ 52%] Building CXX object CMakeFiles/Framework.dir/src/Motion/ACubismMotion.cpp.o +[ 55%] Building CXX object CMakeFiles/Framework.dir/src/Motion/CubismExpressionMotion.cpp.o +[ 57%] Building CXX object CMakeFiles/Framework.dir/src/Motion/CubismExpressionMotionManager.cpp.o +[ 60%] Building CXX object CMakeFiles/Framework.dir/src/Motion/CubismMotion.cpp.o +[ 62%] Building CXX object CMakeFiles/Framework.dir/src/Motion/CubismMotionJson.cpp.o +[ 65%] Building CXX object CMakeFiles/Framework.dir/src/Motion/CubismMotionManager.cpp.o +[ 67%] Building CXX object CMakeFiles/Framework.dir/src/Motion/CubismMotionQueueEntry.cpp.o +[ 70%] Building CXX object CMakeFiles/Framework.dir/src/Motion/CubismMotionQueueManager.cpp.o +[ 72%] Building CXX object CMakeFiles/Framework.dir/src/Physics/CubismPhysics.cpp.o +[ 75%] Building CXX object CMakeFiles/Framework.dir/src/Rendering/CubismRenderer.cpp.o +[ 77%] Building CXX object CMakeFiles/Framework.dir/src/Physics/CubismPhysicsJson.cpp.o +[ 80%] Building CXX object CMakeFiles/Framework.dir/src/Rendering/OpenGL/CubismOffscreenSurface_OpenGLES2.cpp.o +[ 82%] Building CXX object CMakeFiles/Framework.dir/src/Rendering/OpenGL/CubismShader_OpenGLES2.cpp.o +[ 85%] Building CXX object CMakeFiles/Framework.dir/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.cpp.o +[ 87%] Building CXX object CMakeFiles/Framework.dir/src/Type/csmRectF.cpp.o +[ 90%] Building CXX object CMakeFiles/Framework.dir/src/Type/csmString.cpp.o +[ 92%] Building CXX object CMakeFiles/Framework.dir/src/Utils/CubismDebug.cpp.o +[ 95%] Building CXX object CMakeFiles/Framework.dir/src/Utils/CubismJson.cpp.o +[ 97%] Building CXX object CMakeFiles/Framework.dir/src/Utils/CubismString.cpp.o +In file included from /home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Rendering/OpenGL/../CubismClippingManager.hpp:152, + from /home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.hpp:11, + from /home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.cpp:8: +/home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Rendering/OpenGL/../CubismClippingManager.tpp: In instantiation of ‘Live2D::Cubism::Framework::Rendering::CubismClippingManager::~CubismClippingManager() [with T_ClippingContext = Live2D::Cubism::Framework::Rendering::CubismClippingContext_OpenGLES2; T_OffscreenSurface = Live2D::Cubism::Framework::Rendering::CubismOffscreenSurface_OpenGLES2]’: +/home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.hpp:61:7: required from here +/home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Rendering/OpenGL/../CubismClippingManager.tpp:66:33: warning: passing NULL to non-pointer argument 1 of ‘Live2D::Cubism::Framework::csmVector::csmVector(Live2D::Cubism::Framework::csmInt32, Live2D::Cubism::Framework::csmBool) [with T = bool; Live2D::Cubism::Framework::csmInt32 = int; Live2D::Cubism::Framework::csmBool = bool]’ [-Wconversion-null] + 66 | _clearedMaskBufferFlags = NULL; + | ^ +In file included from /home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Rendering/OpenGL/../CubismRenderer.hpp:12, + from /home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Rendering/OpenGL/CubismRenderer_OpenGLES2.hpp:10: +/home/misaki/Downloads/CubismSdkForNative-5-r.4.1/Framework/src/Type/csmVector.hpp:559:34: note: declared here + 559 | csmVector::csmVector(csmInt32 initialCapacity, csmBool zeroClear) + | ~~~~~~~~~^~~~~~~~~~~~~~~ +[100%] Linking CXX static library libFramework.a +[100%] Built target Framework +``` \ No newline at end of file diff --git a/3rdparty/Live2D/Lib/Release/linux_arm/framework/misaki_rk3566/libFramework.a b/3rdparty/Live2D/Lib/Release/linux_arm/framework/misaki_rk3566/libFramework.a new file mode 100644 index 0000000..25fb1e3 Binary files /dev/null and b/3rdparty/Live2D/Lib/Release/linux_arm/framework/misaki_rk3566/libFramework.a differ diff --git a/3rdparty/Live2D/Src/LAppLive2D/CMakeLists.txt b/3rdparty/Live2D/Src/LAppLive2D/CMakeLists.txt new file mode 100644 index 0000000..7c34a44 --- /dev/null +++ b/3rdparty/Live2D/Src/LAppLive2D/CMakeLists.txt @@ -0,0 +1,42 @@ +# LAppLive2D — Live2D SDK 示例应用层,编译为静态库 +# 依赖:Framework(libFramework.a) + Live2DCubismCore(libLive2DCubismCore.a) +# 无 Qt 依赖 — 完全解耦,仅依赖 OpenGL/GLES 头文件 + Cubism SDK + +file(GLOB_RECURSE LAppLive2D_SOURCES + CONFIGURE_DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/Src/*.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/Inc/*.hpp" +) + +add_library(lapp_live2d STATIC ${LAppLive2D_SOURCES}) + +# ============================================= +# 自身的公开头文件目录 +# ============================================= +target_include_directories(lapp_live2d + PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}/Inc" +) + +# ============================================= +# Live2D SDK 头文件(Framework + Core + stb) +# 这些是 lapp_live2d 编译时必需的,通过 PUBLIC 发布给最终链接目标 +# ============================================= +target_include_directories(lapp_live2d + PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}/../Framework/src" + "${CMAKE_CURRENT_SOURCE_DIR}/../Core/include" + "${CMAKE_CURRENT_SOURCE_DIR}/../stb" +) + +# ============================================= +# 链接依赖 — 注意链接顺序! +# lapp_live2d → Framework → Live2DCubismCore +# Framework 内部使用了 Live2DCubismCore 的符号,所以 Core 必须在 Framework 之后 +# lapp_live2d 无 Qt 依赖,开发者可自由选择 UI 后端(Qt/SDL/GLFW等) +# ============================================= +target_link_libraries(lapp_live2d + PUBLIC + Framework # Live2D Framework 静态库(IMPORTED,由父CMakeLists定义) + Live2DCubismCore # Live2D Core 静态库(IMPORTED,由父CMakeLists定义) +) diff --git a/3rdparty/Live2D/Src/LAppLive2D/Inc/GLRenderContext.hpp b/3rdparty/Live2D/Src/LAppLive2D/Inc/GLRenderContext.hpp new file mode 100644 index 0000000..3d17bcc --- /dev/null +++ b/3rdparty/Live2D/Src/LAppLive2D/Inc/GLRenderContext.hpp @@ -0,0 +1,102 @@ +// +// Created by misaki on 2026/6/23. +// + +#pragma once +#include "IRenderContext.hpp" +#include "LAppOpenGL.hpp" + +class GLRenderContext final : public IRenderContext { +public: + void Clear(float r, float g, float b, float a) override { + glClearColor(r, g, b, a); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + + void ClearDepth(float depth) override { + LAPP_GL_CLEAR_DEPTH(depth); + } + + void SetViewport(int x, int y, int w, int h) override { + glViewport(x, y, w, h); + } + + uintptr_t CreateShaderProgram() override { + return CompileShader(); + } + + uintptr_t GetShaderProgram() const override { + return _programId; + } + + void InitializeGLState() override { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + +private: + GLuint _programId = 0; + + GLuint CompileShader() { + if (_programId) return _programId; + +#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_ES_3) || defined(EMBEDDED_LINUX) + const char* vertexShader = + "#version 100\n" + "attribute vec3 position;\n" + "attribute vec2 uv;\n" + "varying vec2 vuv;\n" + "void main() {\n" + " gl_Position = vec4(position, 1.0);\n" + " vuv = uv;\n" + "}\n"; + const char* fragmentShader = + "#version 100\n" + "precision mediump float;\n" + "varying vec2 vuv;\n" + "uniform sampler2D texture;\n" + "uniform vec4 baseColor;\n" + "void main() {\n" + " gl_FragColor = texture2D(texture, vuv) * baseColor;\n" + "}\n"; +#else + const char* vertexShader = + "#version 120\n" + "attribute vec3 position;\n" + "attribute vec2 uv;\n" + "varying vec2 vuv;\n" + "void main(void) {\n" + " gl_Position = vec4(position, 1.0);\n" + " vuv = uv;\n" + "}\n"; + const char* fragmentShader = + "#version 120\n" + "varying vec2 vuv;\n" + "uniform sampler2D texture;\n" + "uniform vec4 baseColor;\n" + "void main(void) {\n" + " gl_FragColor = texture2D(texture, vuv) * baseColor;\n" + "}\n"; +#endif + + GLuint vertId = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertId, 1, &vertexShader, nullptr); + glCompileShader(vertId); + + GLuint fragId = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragId, 1, &fragmentShader, nullptr); + glCompileShader(fragId); + + _programId = glCreateProgram(); + glAttachShader(_programId, vertId); + glAttachShader(_programId, fragId); + glLinkProgram(_programId); + glUseProgram(_programId); + + glDeleteShader(vertId); + glDeleteShader(fragId); + return _programId; + } +}; \ No newline at end of file diff --git a/3rdparty/Live2D/Src/LAppLive2D/Inc/IRenderContext.hpp b/3rdparty/Live2D/Src/LAppLive2D/Inc/IRenderContext.hpp new file mode 100644 index 0000000..98f3c81 --- /dev/null +++ b/3rdparty/Live2D/Src/LAppLive2D/Inc/IRenderContext.hpp @@ -0,0 +1,17 @@ +// +// Created by misaki on 2026/6/23. +// +#pragma once +#include + +class IRenderContext { +public: + virtual ~IRenderContext() = default; + + virtual void Clear(float r, float g, float b, float a) = 0; + virtual void ClearDepth(float depth) = 0; + virtual void SetViewport(int x, int y, int w, int h) = 0; + virtual uintptr_t CreateShaderProgram() = 0; + virtual uintptr_t GetShaderProgram() const = 0; + virtual void InitializeGLState() = 0; +}; \ No newline at end of file diff --git a/3rdparty/Live2D/Src/LAppLive2D/Inc/ISpriteRenderer.hpp b/3rdparty/Live2D/Src/LAppLive2D/Inc/ISpriteRenderer.hpp new file mode 100644 index 0000000..c5cbc80 --- /dev/null +++ b/3rdparty/Live2D/Src/LAppLive2D/Inc/ISpriteRenderer.hpp @@ -0,0 +1,19 @@ +// +// Created by misaki on 2026/6/23. +// + +#pragma once +#include + +class ISpriteRenderer { +public: + virtual ~ISpriteRenderer() = default; + + virtual void SetColor(float r, float g, float b, float a) = 0; + virtual void SetWindowSize(int w, int h) = 0; + virtual void RenderImmidiate(uintptr_t textureId, + const float uvVertex[8]) const = 0; + virtual bool IsHit(float px, float py) const = 0; + virtual void ResetRect(float x, float y, float w, float h) = 0; + virtual uintptr_t GetTextureId() const = 0; +}; diff --git a/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppDelegate.hpp b/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppDelegate.hpp index 9d73d7d..b7b65de 100644 --- a/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppDelegate.hpp +++ b/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppDelegate.hpp @@ -7,10 +7,10 @@ #pragma once -#include -#include +#include "LAppOpenGL.hpp" #include "LAppAllocator.hpp" -#include "GLCore.h" +#include "IRenderContext.hpp" +#include class LAppView; class LAppTextureManager; @@ -37,17 +37,29 @@ public: static void ReleaseInstance(); // 新增 + // resize 由应用层(GLCore::resizeGL)调用,通知LApp窗口尺寸变更 void resize(int width, int height); // 新增 void update(); + IRenderContext* GetRenderContext() const { return _renderContext; } + void SetRenderContext(IRenderContext* ctx) { _renderContext = ctx; } + + // 窗口大小变更回调 解耦 AppContext/GLCore 依赖 + // 当模型加载后需要调整窗口大小时,LAppLive2DManager 通过此回调通知应用层 + using WindowResizeFunc = std::function; + void SetWindowResizeCallback(WindowResizeFunc cb) { _onResizeWindow = std::move(cb); } + void NotifyWindowResize(int width, int height) { if (_onResizeWindow) _onResizeWindow(width, height); } /** * @brief APPに必要なものを初期化する。 + * @param windowWidth 窗口宽度(像素) + * @param windowHeight 窗口高度(像素) */ - //bool Initialize(); - bool Initialize(GLCore* window); + // bool Initialize(GLCore* window); // 原 + // bool Initialize(QWidget* window); // 中间解耦版本 + bool Initialize(int windowWidth, int windowHeight); // 完全解耦Qt,仅传入尺寸 /** * @brief 解放する。 @@ -67,7 +79,8 @@ public: * @param[in] action 実行結果 * @param[in] modify */ - void OnMouseCallBack(GLFWwindow* window, int button, int action, int modify); + // void OnMouseCallBack(GLFWwindow* window, int button, int action, int modify); + void OnMouseCallBack(int button, int action, int modify); /** * @brief OpenGL用 glfwSetCursorPosCallback用関数。 @@ -76,7 +89,8 @@ public: * @param[in] x x座標 * @param[in] y x座標 */ - void OnMouseCallBack(GLFWwindow* window, double x, double y); + // void OnMouseCallBack(GLFWwindow* window, double x, double y); + void OnMouseCallBack(double x, double y); /** * @brief シェーダーを登録する。 @@ -84,9 +98,12 @@ public: GLuint CreateShader(); /** - * @brief Window情報を取得する。 + * @brief Window尺寸を取得する。 */ - GLCore* GetWindow() { return _window; } // Misaki 修改 + // GLCore* GetWindow() { return _window; } // 原 + // QWidget* GetWindow() { return _window; } // 中间版本 + int GetWindowWidth() const { return _windowWidth; } // 完全解耦Qt + int GetWindowHeight() const { return _windowHeight; } // 完全解耦Qt /** * @brief View情報を取得する。 @@ -126,10 +143,13 @@ private: */ bool CheckShader(GLuint shaderId); + IRenderContext* _renderContext = nullptr; + WindowResizeFunc _onResizeWindow; ///< 窗口大小回调 LAppAllocator _cubismAllocator; ///< Cubism SDK Allocator Csm::CubismFramework::Option _cubismOption; ///< Cubism SDK Option //GLFWwindow* _window; ///< OpenGL ウィンドウ - GLCore* _window; ///< Misaki 修改 + // GLCore* _window; ///< Misaki 修改 + // QWidget* _window; ///< 使用QWidget基类,解耦GLCore LAppView* _view; ///< View情報 bool _captured; ///< クリックしているか float _mouseX; ///< マウスX座標 @@ -141,23 +161,23 @@ private: int _windowHeight; ///< Initialize関数で設定したウィンドウ高さ }; -class EventHandler -{ -public: - /** - * @brief glfwSetMouseButtonCallback用コールバック関数。 - */ - static void OnMouseCallBack(GLFWwindow* window, int button, int action, int modify) - { - LAppDelegate::GetInstance()->OnMouseCallBack(window, button, action, modify); - } - - /** - * @brief glfwSetCursorPosCallback用コールバック関数。 - */ - static void OnMouseCallBack(GLFWwindow* window, double x, double y) - { - LAppDelegate::GetInstance()->OnMouseCallBack(window, x, y); - } - -}; +// class EventHandler +// { +// public: +// /** +// * @brief glfwSetMouseButtonCallback用コールバック関数。 +// */ +// static void OnMouseCallBack(GLFWwindow* window, int button, int action, int modify) +// { +// LAppDelegate::GetInstance()->OnMouseCallBack(window, button, action, modify); +// } +// +// /** +// * @brief glfwSetCursorPosCallback用コールバック関数。 +// */ +// static void OnMouseCallBack(GLFWwindow* window, double x, double y) +// { +// LAppDelegate::GetInstance()->OnMouseCallBack(window, x, y); +// } +// +// }; diff --git a/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppModel.hpp b/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppModel.hpp index 6e4b121..0777933 100644 --- a/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppModel.hpp +++ b/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppModel.hpp @@ -17,6 +17,7 @@ #include #include #include +#include "LAppOpenGL.hpp" /** * @brief ユーザーが実際に使用するモデルの実装クラス
* モデル生成、機能コンポーネント生成、更新処理とレンダリングの呼び出しを行う。 @@ -286,5 +287,6 @@ private: Live2D::Cubism::Framework::csmFloat32 alpha = 0.8f; // 滤波系数,范围在0到1之间,值越小,平滑效果越强 Live2D::Cubism::Framework::csmFloat32 filteredValue = 0.0f; // 滤波后的值 - Csm::Rendering::CubismOffscreenSurface_OpenGLES2 _renderBuffer; ///< フレームバッファ以外の描画先 + // Csm::Rendering::CubismOffscreenSurface_OpenGLES2 _renderBuffer; ///< フレームバッファ以外の描画先 + CUBISM_OFFSCREEN_TYPE _renderBuffer; }; diff --git a/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppOpenGL.hpp b/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppOpenGL.hpp new file mode 100644 index 0000000..aca8c8d --- /dev/null +++ b/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppOpenGL.hpp @@ -0,0 +1,46 @@ +// +// Created by misaki on 2026/5/13. +// + +// LAppOpenGL.hpp +#pragma once + +// 根据是否嵌入式选择 OpenGL 头 +#if !defined(EMBEDDED_LINUX) + // 桌面 OpenGL + #include + #include +#else + // 嵌入式 OpenGL ES + #include + #include + #include +#endif + +// 统一深度清除函数 +#if defined(EMBEDDED_LINUX) + #define LAPP_GL_CLEAR_DEPTH(d) glClearDepthf(d) +#else + #define LAPP_GL_CLEAR_DEPTH(d) glClearDepth(d) +#endif + +#define CONCAT_IMPL(a, b) a##b + +#define CONCAT(a, b) CONCAT_IMPL(a, b) + +// 渲染后端编译期类型选择 与 Cubism SDK 的 CubismRenderer::Create() 条件编译对齐 +#if defined(RENDER_BACKEND_VULKAN) + #define RENDERER_BACKEND_TAG Vulkan +#elif defined(RENDER_BACKEND_D3D11) + #define RENDERER_BACKEND_TAG D3D11 +#elif defined(RENDER_BACKEND_D3D9) + #define RENDERER_BACKEND_TAG D3D9 +#elif defined(RENDER_BACKEND_METAL) + #define RENDERER_BACKEND_TAG Metal +#else + #define RENDERER_BACKEND_TAG OpenGLES2 +#endif + +// 类型别名宏,用于 Csm 命名空间下的后端特定类型 +#define CUBISM_RENDERER_TYPE CONCAT(Csm::Rendering::CubismRenderer_, RENDERER_BACKEND_TAG) +#define CUBISM_OFFSCREEN_TYPE CONCAT(Csm::Rendering::CubismOffscreenSurface_, RENDERER_BACKEND_TAG) \ No newline at end of file diff --git a/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppSprite.hpp b/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppSprite.hpp index ef27bf1..ea26ecc 100644 --- a/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppSprite.hpp +++ b/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppSprite.hpp @@ -7,8 +7,8 @@ #pragma once -#include -#include +#include "LAppOpenGL.hpp" +#include "ISpriteRenderer.hpp" // 渲染后端抽象 /** * @brief スプライトを実装するクラス。 @@ -16,7 +16,8 @@ * テクスチャID、Rectの管理。 * */ -class LAppSprite +// class LAppSprite // 原 +class LAppSprite : public ISpriteRenderer // 继承渲染抽象接口 { public: /** @@ -41,7 +42,8 @@ public: * @param[in] textureId テクスチャID * @param[in] programId シェーダID */ - LAppSprite(float x, float y, float width, float height, GLuint textureId, GLuint programId); + // LAppSprite(float x, float y, float width, float height, GLuint textureId, GLuint programId); // 原 + LAppSprite(float x, float y, float width, float height, uintptr_t textureId, uintptr_t programId); // 抽象类型 /** * @brief デストラクタ @@ -52,7 +54,8 @@ public: * @brief Getter テクスチャID * @return テクスチャIDを返す */ - GLuint GetTextureId() { return _textureId; } + // GLuint GetTextureId() { return _textureId; } // 原 + uintptr_t GetTextureId() const override { return _textureId; } // 抽象类型 /** * @brief 描画する @@ -64,7 +67,8 @@ public: * @brief テクスチャIDを指定して描画する * */ - void RenderImmidiate(GLuint textureId, const GLfloat uvVertex[8]) const; + // void RenderImmidiate(GLuint textureId, const GLfloat uvVertex[8]) const; // 原 + void RenderImmidiate(uintptr_t textureId, const float uvVertex[8]) const override; // 抽象类型 /** * @brief コンストラクタ @@ -72,7 +76,8 @@ public: * @param[in] pointX x座標 * @param[in] pointY y座標 */ - bool IsHit(float pointX, float pointY) const; + // bool IsHit(float pointX, float pointY) const; // 原 + bool IsHit(float pointX, float pointY) const override; // 接口实现 /** * @brief 色設定 @@ -82,7 +87,8 @@ public: * @param[in] b (0.0~1.0) * @param[in] a (0.0~1.0) */ - void SetColor(float r, float g, float b, float a); + // void SetColor(float r, float g, float b, float a); // 原 + void SetColor(float r, float g, float b, float a) override; // 接口实现 /** * @brief サイズ再設定 @@ -92,7 +98,8 @@ public: * @param[in] width 横幅 * @param[in] height 高さ */ - void ResetRect(float x, float y, float width, float height); + // void ResetRect(float x, float y, float width, float height); // 原 + void ResetRect(float x, float y, float width, float height) override; // 接口实现 /** * @brief ウインドウサイズ設定 @@ -100,10 +107,12 @@ public: * @param[in] width 横幅 * @param[in] height 高さ */ - void SetWindowSize(int width, int height); + // void SetWindowSize(int width, int height); // 原 + void SetWindowSize(int width, int height) override; // 接口实现 private: - GLuint _textureId; ///< テクスチャID + // GLuint _textureId; ///< テクスチャID 原 + uintptr_t _textureId; ///< テクスチャID 抽象类型 Rect _rect; ///< 矩形 int _positionLocation; ///< 位置アトリビュート int _uvLocation; ///< UVアトリビュート diff --git a/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppTextureManager.hpp b/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppTextureManager.hpp index dc5e9b5..b5cc73c 100644 --- a/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppTextureManager.hpp +++ b/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppTextureManager.hpp @@ -8,8 +8,7 @@ #pragma once #include -#include -#include +#include "LAppOpenGL.hpp" #include /** @@ -26,7 +25,8 @@ public: */ struct TextureInfo { - GLuint id; ///< テクスチャID + // GLuint id; ///< テクスチャID + uintptr_t id; int width; ///< 横幅 int height; ///< 高さ std::string fileName; ///< ファイル名 diff --git a/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppView.hpp b/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppView.hpp index e60ddd2..9c87311 100644 --- a/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppView.hpp +++ b/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppView.hpp @@ -7,12 +7,12 @@ #pragma once -#include -#include +#include "LAppOpenGL.hpp" #include #include #include "CubismFramework.hpp" #include +#include "ISpriteRenderer.hpp" // 绘制接口抽象 class TouchManager; class LAppSprite; @@ -158,14 +158,17 @@ private: TouchManager* _touchManager; ///< タッチマネージャー Csm::CubismMatrix44* _deviceToScreen; ///< デバイスからスクリーンへの行列 Csm::CubismViewMatrix* _viewMatrix; ///< viewMatrix - GLuint _programId; ///< シェーダID + // GLuint _programId; ///< シェーダID + uintptr_t _programId; ///< 顶点着色器ID //LAppSprite* _back; ///< 背景画像 //LAppSprite* _gear; ///< ギア画像 //LAppSprite* _power; ///< 電源画像 // レンダリング先を別ターゲットにする方式の場合に使用 - LAppSprite* _renderSprite; ///< モードによっては_renderBufferのテクスチャを描画 - Csm::Rendering::CubismOffscreenSurface_OpenGLES2 _renderBuffer; ///< モードによってはCubismモデル結果をこっちにレンダリング + // LAppSprite* _renderSprite; ///< モードによっては_renderBufferのテクスチャを描画 + ISpriteRenderer* _renderSprite; ///< 绘制接口抽象 + // Csm::Rendering::CubismOffscreenSurface_OpenGLES2 _renderBuffer; ///< モードによってはCubismモデル結果をこっちにレンダリング + CUBISM_OFFSCREEN_TYPE _renderBuffer; SelectTarget _renderTarget; ///< レンダリング先の選択肢 float _clearColor[4]; ///< レンダリングターゲットのクリアカラー }; diff --git a/3rdparty/Live2D/Src/LAppLive2D/README.md b/3rdparty/Live2D/Src/LAppLive2D/README.md new file mode 100644 index 0000000..8aca7a7 --- /dev/null +++ b/3rdparty/Live2D/Src/LAppLive2D/README.md @@ -0,0 +1,283 @@ +# LAppLive2D — 独立 Live2D 渲染库 +本文档是将相关代码投喂给AI所生成的,已经过人工审阅,未发现错误。 +## 概述 + +`lapp_live2d` 是对 [Live2D Cubism SDK for Native](https://www.live2d.com/download/cubism-sdk/) 的封装层。 +它将原 SDK 示例代码中的 OpenGL 硬编码抽离为抽象接口,使库本身**不依赖任何窗口框架**(Qt / SDL / GLFW / 自研引擎均可接入)。 + +**核心设计原则**: +- 零 Qt / GLFW / SDL 依赖 — 仅依赖 C++ 标准库 + OpenGL 头文件 + Cubism SDK +- 渲染后端通过 `IRenderContext` / `ISpriteRenderer` 抽象接口注入 +- 窗口尺寸变更通过 `std::function` 回调通知,不持有窗口指针 +- 开发者可自由选择窗口框架,编写自己的 `GLCore` + +--- + +## 依赖 + +| 依赖 | 说明 | +|------|------| +| **Live2D Cubism Framework** | `libFramework.a`(静态库,Live2D 官方) | +| **Live2D Cubism Core** | `libLive2DCubismCore.a`(静态库,Live2D 官方) | +| **OpenGL / OpenGL ES 头文件** | 桌面: `GLEW` + `GLFW`头文件;嵌入式: `EGL` + `GLES2` | +| **C++ 标准库** | `std::function`, `cstdint` 等 | + +不依赖任何 Qt / SDL / GLFW 链接库。 + +--- + +## 架构 + +``` +┌───────────────────────────────────────────────────────────┐ +│ LAppDelegate (单例,应用入口) │ +│ Initialize(w, h) — 仅需传入窗口尺寸 │ +│ resize(w, h) — 窗口变更通知 │ +│ update() — 每帧渲染 │ +│ SetRenderContext() — 注入渲染后端 │ +│ SetWindowResizeCallback() — 窗口尺寸变更回调 │ +│ NotifyWindowResize() — LApp内部通知应用层调整窗口 │ +│ GetWindowWidth/Height() — 获取当前存储的窗口尺寸 │ +└──────────────┬────────────────┬────────────────────────────┘ + │ 持有 │ 持有 + ┌──────────▼──────┐ ┌─────▼──────────────────────────┐ + │ LAppView │ │ LAppLive2DManager │ + │ 渲染管理 │ │ 模型生命周期(加载/切换/更新) │ + │ - 触摸事件 │ │ - OnTap / OnDrag │ + │ - 坐标变换 │ │ - ModelSizeChange → 回调通知 │ + │ - Sprite绘制 │ │ │ + └────────┬─────────┘ └─────┬──────────────────────────┘ + │ │ 管理 + ┌────────▼───────────────────▼──────┐ + │ LAppModel : CubismUserModel │ + │ 单个Live2D模型实例 │ + │ - 加载(.moc3 / .model3.json) │ + │ - 动画、物理、口型同步 │ + │ - 命中检测 (HitTest) │ + │ - 渲染 (Draw → CubismRenderer) │ + └───────────────────────────────────┘ +``` + +### 抽象接口 + +``` +IRenderContext ISpriteRenderer + │ │ + ├─ Clear(r,g,b,a) ├─ SetColor(r,g,b,a) + ├─ ClearDepth(d) ├─ SetWindowSize(w,h) + ├─ SetViewport(x,y,w,h) ├─ RenderImmidiate(texId, uv) + ├─ CreateShaderProgram() ├─ IsHit(px, py) + ├─ GetShaderProgram() ├─ ResetRect(x,y,w,h) + ├─ InitializeGLState() └─ GetTextureId() + │ + └── GLRenderContext (OpenGL实现) + - CompileShader() 内部编译 GLSL + - Clear → glClear / glClearColor + - SetViewport → glViewport +``` + +--- + +## 接入方式(CMake) + +```cmake +# 1. 在父 CMakeLists.txt 中配置 Framework 和 Core(IMPORTED) +add_library(Framework STATIC IMPORTED GLOBAL) +set_target_properties(Framework PROPERTIES IMPORTED_LOCATION "/path/to/libFramework.a") + +add_library(Live2DCubismCore STATIC IMPORTED GLOBAL) +set_target_properties(Live2DCubismCore PROPERTIES IMPORTED_LOCATION "/path/to/libLive2DCubismCore.a") + +# 2. 导入 LAppLive2D 子项目 +add_subdirectory(3rdparty/Live2D/Src/LAppLive2D) + +# 3. 链接到你的可执行目标 +target_link_libraries(your_app PRIVATE lapp_live2d) +``` + +**注意**:LAppLive2D 内部引用 ``(桌面)或 ``(嵌入式),需确保对应的头文件路径可用。参见父项目的 `CMakeLists.txt` 中如何为 `lapp_live2d` 补充平台 GL 头文件路径。 + +--- + +## 编写自定义窗口(以 Qt 为例) + +```cpp +#include +#include "LAppDelegate.hpp" +#include "GLRenderContext.hpp" + +class MyGLCore final : public QOpenGLWidget +{ + void initializeGL() override + { + // 1. 注入 IRenderContext(OpenGL 实现) + LAppDelegate::GetInstance()->SetRenderContext(new GLRenderContext()); + + // 2. 注册窗口大小变更回调(模型加载时 LApp 通知你调整窗口) + LAppDelegate::GetInstance()->SetWindowResizeCallback([this](int w, int h) { + setFixedSize(w, h); + }); + + // 3. 初始化 LApp(传入当前窗口尺寸) + LAppDelegate::GetInstance()->Initialize(width(), height()); + } + + void resizeGL(int w, int h) override + { + LAppDelegate::GetInstance()->resize(w, h); + } + + void paintGL() override + { + LAppDelegate::GetInstance()->update(); + } + + void mousePressEvent(QMouseEvent *ev) override { + LAppDelegate::GetInstance()->GetView()->OnTouchesBegan(ev->position().x(), ev->position().y()); + } + void mouseMoveEvent(QMouseEvent *ev) override { + LAppDelegate::GetInstance()->GetView()->OnTouchesMoved(ev->position().x(), ev->position().y()); + } + void mouseReleaseEvent(QMouseEvent *ev) override { + LAppDelegate::GetInstance()->GetView()->OnTouchesEnded(ev->position().x(), ev->position().y()); + } +}; +``` + +--- + +## 切换渲染后端 + +### 当前支持 + +| 后端 | 宏定义 | 说明 | +|------|--------|------| +| OpenGL ES2 | `RENDER_BACKEND_GLES2` | 嵌入式(RK3566 等) | +| OpenGL | `RENDER_BACKEND_OPENGL` | 桌面 Windows / Linux | + +### 添加新后端 + +**第 1 步** — 在 `LAppOpenGL.hpp` 的宏分支中加一条: + +```cpp +#elif defined(RENDER_BACKEND_VULKAN) + #define RENDERER_BACKEND_TAG Vulkan +``` + +**第 2 步** — 实现 `VulkanRenderContext`(继承 `IRenderContext`),并在其中实现 `Clear` / `SetViewport` / `CreateShaderProgram` 等方法。 + +**第 3 步** — CMake 中 `add_definitions(-DRENDER_BACKEND_VULKAN)`。 + +**第 4 步** — 在你的窗口 `initializeGL()` 等价函数中创建 `VulkanRenderContext` 注入即可。 + +切换后端时 `LAppModel` 和 `LAppView` 中的 `CUBISM_RENDERER_TYPE` / `CUBISM_OFFSCREEN_TYPE` 宏会自动跟随编译宏切换对应的 Cubism SDK 后端类型。 + +--- + +## API 参考 + +### LAppDelegate(单例) + +```cpp +// 初始化(必须在 OpenGL 上下文就绪后调用) +bool Initialize(int windowWidth, int windowHeight); + +// 每帧调用 +void update(); + +// 窗口尺寸变更 +void resize(int width, int height); + +// 注入渲染后端 +void SetRenderContext(IRenderContext* ctx); +IRenderContext* GetRenderContext() const; + +// 窗口尺寸回调(模型加载时LApp通知应用层调整窗口) +using WindowResizeFunc = std::function; +void SetWindowResizeCallback(WindowResizeFunc cb); + +// 获取当前存储的窗口尺寸 +int GetWindowWidth() const; +int GetWindowHeight() const; + +// 获取 View / TextureManager +LAppView* GetView(); +LAppTextureManager* GetTextureManager(); +``` + +### IRenderContext + +```cpp +class IRenderContext { +public: + virtual ~IRenderContext() = default; + virtual void Clear(float r, float g, float b, float a) = 0; + virtual void ClearDepth(float depth) = 0; + virtual void SetViewport(int x, int y, int w, int h) = 0; + virtual uintptr_t CreateShaderProgram() = 0; + virtual uintptr_t GetShaderProgram() const = 0; + virtual void InitializeGLState() = 0; +}; +``` + +### ISpriteRenderer + +```cpp +class ISpriteRenderer { +public: + virtual ~ISpriteRenderer() = default; + virtual void SetColor(float r, float g, float b, float a) = 0; + virtual void SetWindowSize(int w, int h) = 0; + virtual void RenderImmidiate(uintptr_t textureId, const float uvVertex[8]) const = 0; + virtual bool IsHit(float px, float py) const = 0; + virtual void ResetRect(float x, float y, float w, float h) = 0; + virtual uintptr_t GetTextureId() const = 0; +}; +``` + +--- + +## 触摸事件映射 + +LApp 不依赖任何窗口事件系统,触摸由应用层主动调用: + +```cpp +// 对应 QMouseEvent / SDL_MouseButtonEvent / GLFW 回调 +LAppDelegate::GetInstance()->GetView()->OnTouchesBegan(x, y); // 按下 +LAppDelegate::GetInstance()->GetView()->OnTouchesMoved(x, y); // 移动 +LAppDelegate::GetInstance()->GetView()->OnTouchesEnded(x, y); // 释放 + +// 坐标需为窗口内像素坐标,原点在左上角 +``` + +--- + +## 项目结构 + +``` +LAppLive2D/ +├── Inc/ +│ ├── LAppDelegate.hpp ← 应用入口(单例) +│ ├── LAppView.hpp ← 渲染视图管理 +│ ├── LAppModel.hpp ← 模型实例 +│ ├── LAppSprite.hpp ← Sprite 绘制(继承 ISpriteRenderer) +│ ├── LAppLive2DManager.hpp ← 模型集管理 +│ ├── LAppTextureManager.hpp ← 纹理管理 +│ ├── LAppPal.hpp ← 平台抽象(文件IO、时间) +│ ├── LAppAllocator.hpp ← 内存分配器 +│ ├── LAppDefine.hpp ← 配置常量 +│ ├── LAppWavFileHandler.hpp ← WAV文件解析 +│ ├── TouchManager.hpp ← 触摸状态管理 +│ ├── LAppOpenGL.hpp ← OpenGL 头文件 + 后端宏 +│ │ +│ ├── IRenderContext.hpp ← 渲染上下文抽象接口 ★ +│ ├── ISpriteRenderer.hpp ← Sprite渲染抽象接口 ★ +│ └── GLRenderContext.hpp ← OpenGL IRenderContext 实现 ★ +│ +├── Src/ +│ ├── *.cpp ← 各模块实现 +│ └── ... +│ +├── CMakeLists.txt ← 子项目构建脚本 +└── README.md ← 本文件 +``` diff --git a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppDelegate.cpp b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppDelegate.cpp index 13d2c16..8a52585 100644 --- a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppDelegate.cpp +++ b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppDelegate.cpp @@ -7,8 +7,6 @@ #include "LAppDelegate.hpp" #include -#include -#include #include "LAppView.hpp" #include "LAppPal.hpp" #include "LAppDefine.hpp" @@ -43,77 +41,100 @@ void LAppDelegate::ReleaseInstance() s_instance = NULL; } -bool LAppDelegate::Initialize(GLCore* window) +// bool LAppDelegate::Initialize(GLCore* window) +// { +// if (DebugLogEnable) +// { +// LAppPal::PrintLogLn("START"); +// } +// +// // GLFWの初期化 +// if (glfwInit() == GL_FALSE) +// { +// if (DebugLogEnable) +// { +// LAppPal::PrintLogLn("Can't initilize GLFW"); +// } +// return GL_FALSE; +// } +// +// // Windowの生成_ +// //_window = glfwCreateWindow(RenderTargetWidth, RenderTargetHeight, "SAMPLE", NULL, NULL); +// _window = window; // Misaki 修改 +// if (_window == nullptr) +// { +// if (DebugLogEnable) +// { +// LAppPal::PrintLogLn("Can't create GLFW window."); +// } +// glfwTerminate(); +// return GL_FALSE; +// } +// +// // Windowのコンテキストをカレントに設定 +// //glfwMakeContextCurrent(_window); +// _window->makeCurrent(); // Misaki 修改 +// glfwSwapInterval(1); +// +// if (glewInit() != GLEW_OK) { +// if (DebugLogEnable) +// { +// LAppPal::PrintLogLn("Can't initilize glew."); +// } +// glfwTerminate(); +// return GL_FALSE; +// } +// +// //テクスチャサンプリング設定 +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +// +// //透過設定 +// glEnable(GL_BLEND); +// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +// +// +// // Misaki 修改 +// //コールバック関数の登録 +// //glfwSetMouseButtonCallback(_window, EventHandler::OnMouseCallBack); +// //glfwSetCursorPosCallback(_window, EventHandler::OnMouseCallBack); +// +// // ウィンドウサイズ記憶 +// //int width, height; +// //glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); +// _windowWidth = _window->width(); // Misaki 修改 +// _windowHeight = _window->height(); +// +// //AppViewの初期化 +// _view->Initialize(); +// +// // Cubism SDK の初期化 +// InitializeCubism(); +// +// return GL_TRUE; +// } + +// bool LAppDelegate::Initialize(GLCore* window) // 原 +// bool LAppDelegate::Initialize(QWidget* window) // 中间解耦版本 +bool LAppDelegate::Initialize(int windowWidth, int windowHeight) // 完全解耦Qt { - if (DebugLogEnable) - { - LAppPal::PrintLogLn("START"); - } + if (DebugLogEnable) LAppPal::PrintLogLn("START"); + // _window = window; // 不再持有窗口指针 + // if (!_window) return false; + _windowWidth = windowWidth; + _windowHeight = windowHeight; - // GLFWの初期化 - if (glfwInit() == GL_FALSE) - { - if (DebugLogEnable) - { - LAppPal::PrintLogLn("Can't initilize GLFW"); - } - return GL_FALSE; - } + // OpenGL 初始化(不依赖 glew) + // 原代码:原始GL调用,已抽象到IRenderContext + // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + // glEnable(GL_BLEND); + // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + _renderContext->InitializeGLState(); - // Windowの生成_ - //_window = glfwCreateWindow(RenderTargetWidth, RenderTargetHeight, "SAMPLE", NULL, NULL); - _window = window; // Misaki 修改 - if (_window == nullptr) - { - if (DebugLogEnable) - { - LAppPal::PrintLogLn("Can't create GLFW window."); - } - glfwTerminate(); - return GL_FALSE; - } - - // Windowのコンテキストをカレントに設定 - //glfwMakeContextCurrent(_window); - _window->makeCurrent(); // Misaki 修改 - glfwSwapInterval(1); - - if (glewInit() != GLEW_OK) { - if (DebugLogEnable) - { - LAppPal::PrintLogLn("Can't initilize glew."); - } - glfwTerminate(); - return GL_FALSE; - } - - //テクスチャサンプリング設定 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - //透過設定 - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - - // Misaki 修改 - //コールバック関数の登録 - //glfwSetMouseButtonCallback(_window, EventHandler::OnMouseCallBack); - //glfwSetCursorPosCallback(_window, EventHandler::OnMouseCallBack); - - // ウィンドウサイズ記憶 - //int width, height; - //glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); - _windowWidth = _window->width(); // Misaki 修改 - _windowHeight = _window->height(); - - //AppViewの初期化 _view->Initialize(); - - // Cubism SDK の初期化 InitializeCubism(); - - return GL_TRUE; + return true; } void LAppDelegate::Release() @@ -121,7 +142,7 @@ void LAppDelegate::Release() // Windowの削除 //glfwDestroyWindow(_window); // Misaki 修改 - glfwTerminate(); + // glfwTerminate(); delete _textureManager; delete _view; @@ -183,41 +204,54 @@ void LAppDelegate::resize(int width, int height) { if ((_windowWidth != width || _windowHeight != height) && width > 0 && height > 0) { + // 先更新尺寸再调_view方法,因为_view内部会通过GetWindowWidth/Height获取 + _windowWidth = width; + _windowHeight = height; //AppViewの初期化 _view->Initialize(); // スプライトサイズを再設定 _view->ResizeSprite(); - // サイズを保存しておく - _windowWidth = width; - _windowHeight = height; // ビューポート変更 - glViewport(0, 0, width, height); + // glViewport(0, 0, width, height); // 原始GL,改用IRenderContext + _renderContext->SetViewport(0, 0, width, height); } else { - glViewport(0, 0, width, height); + // glViewport(0, 0, width, height); // 原始GL,改用IRenderContext + _renderContext->SetViewport(0, 0, width, height); } } +// void LAppDelegate::update() +// { +// // 時間更新 +// LAppPal::UpdateTime(); +// +// // 画面の初期化 +// //glClearColor(0.0f, 0.0f, 0.0f, 1.0f); +// glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 渲染背景为透明 +// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +// glClearDepth(1.0); +// +// //描画更新 +// _view->Render(); +// } void LAppDelegate::update() { - // 時間更新 LAppPal::UpdateTime(); - - // 画面の初期化 - //glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 渲染背景为透明 - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glClearDepth(1.0); - - //描画更新 + // 原代码:原始GL调用,已抽象到IRenderContext + // glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + // LAPP_GL_CLEAR_DEPTH(1.0f); + _renderContext->Clear(0.0f, 0.0f, 0.0f, 0.0f); + _renderContext->ClearDepth(1.0f); _view->Render(); } LAppDelegate::LAppDelegate(): _cubismOption(), - _window(nullptr), + // _window(nullptr), // 已解耦,不再持有窗口指针 _captured(false), _mouseX(0.0f), _mouseY(0.0f), @@ -257,23 +291,139 @@ void LAppDelegate::InitializeCubism() _view->InitializeSprite(); } -void LAppDelegate::OnMouseCallBack(GLFWwindow* window, int button, int action, int modify) +// void LAppDelegate::OnMouseCallBack(GLFWwindow* window, int button, int action, int modify) +// { +// if (_view == nullptr) +// { +// return; +// } +// if (GLFW_MOUSE_BUTTON_LEFT != button) +// { +// return; +// } +// +// if (GLFW_PRESS == action) +// { +// _captured = true; +// _view->OnTouchesBegan(_mouseX, _mouseY); +// } +// else if (GLFW_RELEASE == action) +// { +// if (_captured) +// { +// _captured = false; +// _view->OnTouchesEnded(_mouseX, _mouseY); +// } +// } +// } +// +// void LAppDelegate::OnMouseCallBack(GLFWwindow* window, double x, double y) +// { +// _mouseX = static_cast(x); +// _mouseY = static_cast(y); +// +// if (!_captured) +// { +// return; +// } +// if (_view == nullptr) +// { +// return; +// } +// +// _view->OnTouchesMoved(_mouseX, _mouseY); +// } +void LAppDelegate::OnMouseCallBack(double x, double y) { - if (_view == nullptr) - { - return; - } - if (GLFW_MOUSE_BUTTON_LEFT != button) - { - return; - } + _mouseX = static_cast(x); + _mouseY = static_cast(y); + if (!_captured) return; + if (_view == nullptr) return; + _view->OnTouchesMoved(_mouseX, _mouseY); +} - if (GLFW_PRESS == action) +// GLuint LAppDelegate::CreateShader() +// { +// //バーテックスシェーダのコンパイル +// GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); +// const char* vertexShader = +// "#version 120\n" +// "attribute vec3 position;" +// "attribute vec2 uv;" +// "varying vec2 vuv;" +// "void main(void){" +// " gl_Position = vec4(position, 1.0);" +// " vuv = uv;" +// "}"; +// glShaderSource(vertexShaderId, 1, &vertexShader, nullptr); +// glCompileShader(vertexShaderId); +// if(!CheckShader(vertexShaderId)) +// { +// return 0; +// } +// +// //フラグメントシェーダのコンパイル +// GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); +// const char* fragmentShader = +// "#version 120\n" +// "varying vec2 vuv;" +// "uniform sampler2D texture;" +// "uniform vec4 baseColor;" +// "void main(void){" +// " gl_FragColor = texture2D(texture, vuv) * baseColor;" +// "}"; +// glShaderSource(fragmentShaderId, 1, &fragmentShader, nullptr); +// glCompileShader(fragmentShaderId); +// if (!CheckShader(fragmentShaderId)) +// { +// return 0; +// } +// +// //プログラムオブジェクトの作成 +// GLuint programId = glCreateProgram(); +// glAttachShader(programId, vertexShaderId); +// glAttachShader(programId, fragmentShaderId); +// +// // リンク +// glLinkProgram(programId); +// +// glUseProgram(programId); +// +// return programId; +// } +GLuint LAppDelegate::CreateShader() +{ + // Shader编译逻辑已移入GLRenderContext::CompileShader() + // 本函数保留兼容签名,内部委托给IRenderContext + return static_cast(_renderContext->GetShaderProgram()); +} +/* +// 原Shader编译代码,已迁移至GLRenderContext::CompileShader() +GLuint LAppDelegate::CreateShader() +{ +#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_ES_3) || defined(EMBEDDED_LINUX) + // OpenGL ES 2.0/3.0 着色器 + const char* vertexShader = ...; + ... +#else + ... +#endif + ... + return programId; +} +*/ + +// 鼠标回调简化(不再依赖 GLFWwindow*) +void LAppDelegate::OnMouseCallBack(int button, int action, int mods) +{ + if (_view == nullptr) return; + if (button != 0) return; // 只处理左键,0 代表左键(与 Qt 约定一致) + if (action == 1) // 按下 { _captured = true; _view->OnTouchesBegan(_mouseX, _mouseY); } - else if (GLFW_RELEASE == action) + else if (action == 0) // 释放 { if (_captured) { @@ -283,73 +433,6 @@ void LAppDelegate::OnMouseCallBack(GLFWwindow* window, int button, int action, i } } -void LAppDelegate::OnMouseCallBack(GLFWwindow* window, double x, double y) -{ - _mouseX = static_cast(x); - _mouseY = static_cast(y); - - if (!_captured) - { - return; - } - if (_view == nullptr) - { - return; - } - - _view->OnTouchesMoved(_mouseX, _mouseY); -} - -GLuint LAppDelegate::CreateShader() -{ - //バーテックスシェーダのコンパイル - GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); - const char* vertexShader = - "#version 120\n" - "attribute vec3 position;" - "attribute vec2 uv;" - "varying vec2 vuv;" - "void main(void){" - " gl_Position = vec4(position, 1.0);" - " vuv = uv;" - "}"; - glShaderSource(vertexShaderId, 1, &vertexShader, nullptr); - glCompileShader(vertexShaderId); - if(!CheckShader(vertexShaderId)) - { - return 0; - } - - //フラグメントシェーダのコンパイル - GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); - const char* fragmentShader = - "#version 120\n" - "varying vec2 vuv;" - "uniform sampler2D texture;" - "uniform vec4 baseColor;" - "void main(void){" - " gl_FragColor = texture2D(texture, vuv) * baseColor;" - "}"; - glShaderSource(fragmentShaderId, 1, &fragmentShader, nullptr); - glCompileShader(fragmentShaderId); - if (!CheckShader(fragmentShaderId)) - { - return 0; - } - - //プログラムオブジェクトの作成 - GLuint programId = glCreateProgram(); - glAttachShader(programId, vertexShaderId); - glAttachShader(programId, fragmentShaderId); - - // リンク - glLinkProgram(programId); - - glUseProgram(programId); - - return programId; -} - bool LAppDelegate::CheckShader(GLuint shaderId) { GLint status; diff --git a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppLive2DManager.cpp b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppLive2DManager.cpp index 26fb30a..b4e170a 100644 --- a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppLive2DManager.cpp +++ b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppLive2DManager.cpp @@ -15,8 +15,7 @@ #include // Linux / macOS 用 std::filesystem #include #endif -#include -#include +#include "LAppOpenGL.hpp" #include #include "LAppPal.hpp" #include "LAppDefine.hpp" @@ -222,8 +221,8 @@ void LAppLive2DManager::OnUpdate() const { //glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); - int width = LAppDelegate::GetInstance()->GetWindow()->width(); - int height = LAppDelegate::GetInstance()->GetWindow()->height(); + int width = LAppDelegate::GetInstance()->GetWindowWidth(); + int height = LAppDelegate::GetInstance()->GetWindowHeight(); csmUint32 modelCount = _models.GetSize(); for (csmUint32 i = 0; i < modelCount; ++i) @@ -264,17 +263,16 @@ void LAppLive2DManager::OnUpdate() const LAppDelegate::GetInstance()->GetView()->PostModelDraw(*model); } } -#include +// #include // 解耦,改用LAppDelegate回调 void LAppLive2DManager::ModelSizeChange(const int Sacle = 15) { - // 加载完后根据模型大小来重新设置当前窗口大小 const int width = static_cast(_models[0]->GetModel()->GetCanvasWidthPixel() / Sacle); const int height = static_cast(_models[0]->GetModel()->GetCanvasHeightPixel() / Sacle); - // 确保在主线程调用 UI 相关操作 - if(AppContext::GetGLCore()) { - AppContext::GetGLCore()->setWindowSize(width, height); - } + // if(AppContext::GetGLCore()) { // 原 + // AppContext::GetGLCore()->setWindowSize(width, height); + // } + LAppDelegate::GetInstance()->NotifyWindowResize(width, height); // 通过回调通知应用层 LAppPal::PrintLogLn("[APP]窗口尺寸重新设置为: W: %d H: %d", width, height); } void LAppLive2DManager::LoadModelFromPath(const std::string& modelPath, const std::string& fileName) @@ -289,7 +287,8 @@ void LAppLive2DManager::LoadModelFromPath(const std::string& modelPath, const st // 加载完后根据模型大小来重新设置当前窗口大小 const int width = static_cast(_models[0]->GetModel()->GetCanvasWidthPixel() / 15.0); const int height = static_cast(_models[0]->GetModel()->GetCanvasHeightPixel() / 15.0); - AppContext::GetGLCore()->setWindowSize(width, height); // 获取GLCore上下文 + // AppContext::GetGLCore()->setWindowSize(width, height); // 原 + LAppDelegate::GetInstance()->NotifyWindowResize(width, height); // 通过回调通知应用层 LAppPal::PrintLogLn("[APP]窗口尺寸重新设置为: W: %d H: %d", width, height); /* * 提供一个半透明表示模型的示例。 @@ -352,14 +351,13 @@ void LAppLive2DManager::MountLoadedModel(LAppModel* model) } // 加载完后根据模型大小来重新设置当前窗口大小 - const int width = static_cast(_models[0]->GetModel()->GetCanvasWidthPixel() / 15.0); - const int height = static_cast(_models[0]->GetModel()->GetCanvasHeightPixel() / 15.0); - - // 确保在主线程调用 UI 相关操作 - if(AppContext::GetGLCore()) { - AppContext::GetGLCore()->setWindowSize(width, height); - } - LAppPal::PrintLogLn("[APP]窗口尺寸重新设置为: W: %d H: %d", width, height); + // 原代码直接调AppContext,改为统一使用ModelSizeChange + // const int width = static_cast(_models[0]->GetModel()->GetCanvasWidthPixel() / 15.0); + // const int height = static_cast(_models[0]->GetModel()->GetCanvasHeightPixel() / 15.0); + // if(AppContext::GetGLCore()) { + // AppContext::GetGLCore()->setWindowSize(width, height); + // } + ModelSizeChange(15); // 统一入口,回调通知应用层 // 设置渲染目标等 { diff --git a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppModel.cpp b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppModel.cpp index 8dc4b5f..680ab15 100644 --- a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppModel.cpp +++ b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppModel.cpp @@ -789,7 +789,8 @@ void LAppModel::DoDraw() return; } - GetRenderer()->DrawModel(); + // GetRenderer()->DrawModel(); + GetRenderer()->DrawModel(); // 适配不同渲染器 } void LAppModel::Draw(CubismMatrix44& matrix) @@ -801,8 +802,10 @@ void LAppModel::Draw(CubismMatrix44& matrix) matrix.MultiplyByMatrix(_modelMatrix); - GetRenderer()->SetMvpMatrix(&matrix); - + // 設定MVP行列 + // GetRenderer()->SetMvpMatrix(&matrix); + GetRenderer()->SetMvpMatrix(&matrix); // 适配不同渲染器 + // 描画 DoDraw(); } @@ -892,13 +895,16 @@ void LAppModel::SetupTextures() const csmInt32 glTextueNumber = texture->id; //OpenGL - GetRenderer()->BindTexture(modelTextureNumber, glTextueNumber); + // GetRenderer()->BindTexture(modelTextureNumber, glTextueNumber); + GetRenderer()->BindTexture(modelTextureNumber, glTextueNumber); // 适配不同渲染器 } #ifdef PREMULTIPLIED_ALPHA_ENABLE - GetRenderer()->IsPremultipliedAlpha(true); + // GetRenderer()->IsPremultipliedAlpha(true); + GetRenderer()->IsPremultipliedAlpha(true); #else - GetRenderer()->IsPremultipliedAlpha(false); + // GetRenderer()->IsPremultipliedAlpha(false); + GetRenderer()->IsPremultipliedAlpha(false); #endif } diff --git a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppPal.cpp b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppPal.cpp index 1b0ea19..e6fe258 100644 --- a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppPal.cpp +++ b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppPal.cpp @@ -6,13 +6,13 @@ */ #include "LAppPal.hpp" +#include "LAppDefine.hpp" +#include #include #include #include #include #include -#include -#include #include #include "LAppDefine.hpp" #ifdef _WIN32 @@ -93,11 +93,24 @@ csmFloat32 LAppPal::GetDeltaTime() return static_cast(s_deltaTime); } +static std::chrono::steady_clock::time_point s_lastTime; +static double s_deltaTime = 0.0; void LAppPal::UpdateTime() { - s_currentFrame = glfwGetTime(); - s_deltaTime = s_currentFrame - s_lastFrame; - s_lastFrame = s_currentFrame; + // s_currentFrame = glfwGetTime(); + // s_deltaTime = s_currentFrame - s_lastFrame; + // s_lastFrame = s_currentFrame; + static bool initialized = false; + if (!initialized) + { + s_lastTime = std::chrono::steady_clock::now(); + initialized = true; + return; + } + auto now = std::chrono::steady_clock::now(); + std::chrono::duration diff = now - s_lastTime; + s_deltaTime = diff.count(); + s_lastTime = now; } void LAppPal::PrintLog(const csmChar* format, ...) diff --git a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppSprite.cpp b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppSprite.cpp index 9d449f7..d7f876f 100644 --- a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppSprite.cpp +++ b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppSprite.cpp @@ -7,7 +7,8 @@ #include "LAppSprite.hpp" -LAppSprite::LAppSprite(float x, float y, float width, float height, GLuint textureId, GLuint programId) +// LAppSprite::LAppSprite(float x, float y, float width, float height, GLuint textureId, GLuint programId) // 原 +LAppSprite::LAppSprite(float x, float y, float width, float height, uintptr_t textureId, uintptr_t programId) // 抽象类型 : _rect() { _rect.left = (x - width * 0.5f); @@ -16,11 +17,15 @@ LAppSprite::LAppSprite(float x, float y, float width, float height, GLuint textu _rect.down = (y - height * 0.5f); _textureId = textureId; - // 何番目のattribute変数か - _positionLocation = glGetAttribLocation(programId, "position"); - _uvLocation = glGetAttribLocation(programId, "uv"); - _textureLocation = glGetUniformLocation(programId, "texture"); - _colorLocation = glGetUniformLocation(programId, "baseColor"); + // 原代码:直接传GLuint,改用static_cast适配抽象类型uintptr_t + // _positionLocation = glGetAttribLocation(programId, "position"); + // _uvLocation = glGetAttribLocation(programId, "uv"); + // _textureLocation = glGetUniformLocation(programId, "texture"); + // _colorLocation = glGetUniformLocation(programId, "baseColor"); + _positionLocation = glGetAttribLocation(static_cast(programId), "position"); + _uvLocation = glGetAttribLocation(static_cast(programId), "uv"); + _textureLocation = glGetUniformLocation(static_cast(programId), "texture"); + _colorLocation = glGetUniformLocation(static_cast(programId), "baseColor"); _spriteColor[0] = 1.0f; _spriteColor[1] = 1.0f; @@ -72,11 +77,13 @@ void LAppSprite::Render() const // モデルの描画 - glBindTexture(GL_TEXTURE_2D, _textureId); + // glBindTexture(GL_TEXTURE_2D, _textureId); // 原 + glBindTexture(GL_TEXTURE_2D, static_cast(_textureId)); // 抽象类型转换 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } -void LAppSprite::RenderImmidiate(GLuint textureId, const GLfloat uvVertex[8]) const +// void LAppSprite::RenderImmidiate(GLuint textureId, const GLfloat uvVertex[8]) const // 原 +void LAppSprite::RenderImmidiate(uintptr_t textureId, const float uvVertex[8]) const // 抽象类型 { if (_maxWidth == 0 || _maxHeight == 0) { @@ -106,7 +113,8 @@ void LAppSprite::RenderImmidiate(GLuint textureId, const GLfloat uvVertex[8]) co glUniform4f(_colorLocation, _spriteColor[0], _spriteColor[1], _spriteColor[2], _spriteColor[3]); // モデルの描画 - glBindTexture(GL_TEXTURE_2D, textureId); + // glBindTexture(GL_TEXTURE_2D, textureId); // 原 + glBindTexture(GL_TEXTURE_2D, static_cast(textureId)); // 抽象类型转换 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } diff --git a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppView.cpp b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppView.cpp index b221c2c..d665495 100644 --- a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppView.cpp +++ b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppView.cpp @@ -60,8 +60,8 @@ void LAppView::Initialize() { int width, height; //glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); - width = LAppDelegate::GetInstance()->GetWindow()->width(); - height = LAppDelegate::GetInstance()->GetWindow()->height(); + width = LAppDelegate::GetInstance()->GetWindowWidth(); + height = LAppDelegate::GetInstance()->GetWindowHeight(); if(width==0 || height==0) { @@ -109,8 +109,8 @@ void LAppView::Render() // 画面サイズを取得する int maxWidth, maxHeight; //glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &maxWidth, &maxHeight); - maxWidth = LAppDelegate::GetInstance()->GetWindow()->width(); - maxHeight = LAppDelegate::GetInstance()->GetWindow()->height(); + maxWidth = LAppDelegate::GetInstance()->GetWindowWidth(); + maxHeight = LAppDelegate::GetInstance()->GetWindowHeight(); //_back->SetWindowSize(maxWidth, maxHeight); //_gear->SetWindowSize(maxWidth, maxHeight); @@ -155,12 +155,13 @@ void LAppView::Render() void LAppView::InitializeSprite() { - _programId = LAppDelegate::GetInstance()->CreateShader(); + // _programId = LAppDelegate::GetInstance()->CreateShader(); + _programId = LAppDelegate::GetInstance()->GetRenderContext()->CreateShaderProgram(); int width, height; //glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); - width = LAppDelegate::GetInstance()->GetWindow()->width(); - height = LAppDelegate::GetInstance()->GetWindow()->height(); + width = LAppDelegate::GetInstance()->GetWindowWidth(); + height = LAppDelegate::GetInstance()->GetWindowHeight(); LAppTextureManager* textureManager = LAppDelegate::GetInstance()->GetTextureManager(); const string resourcesPath = ResourcesPath; @@ -196,6 +197,13 @@ void LAppView::InitializeSprite() // x = width * 0.5f; // y = height * 0.5f; // _renderSprite = new LAppSprite(x, y, static_cast(width), static_cast(height), 0, _programId); +// _programId 类型由GLuint改为uintptr_t,构造参数匹配 +// _renderSprite = new LAppSprite(x, y, static_cast(width), +// static_cast(height), 0, +// static_cast(_programId)); + float x = width * 0.5f; + float y = height * 0.5f; + _renderSprite = new LAppSprite(x, y, static_cast(width), static_cast(height), 0, static_cast(_programId)); } void LAppView::OnTouchesBegan(float px, float py) const @@ -303,8 +311,8 @@ void LAppView::PreModelDraw(LAppModel& refModel) {// 描画ターゲット内部未作成の場合はここで作成 int width, height; /*glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height);*/ - width = LAppDelegate::GetInstance()->GetWindow()->width(); - height = LAppDelegate::GetInstance()->GetWindow()->height(); + width = LAppDelegate::GetInstance()->GetWindowWidth(); + height = LAppDelegate::GetInstance()->GetWindowHeight(); if (width != 0 && height != 0) { @@ -350,8 +358,8 @@ void LAppView::PostModelDraw(LAppModel& refModel) int maxWidth, maxHeight; /*glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &maxWidth, &maxHeight);*/ - maxWidth = LAppDelegate::GetInstance()->GetWindow()->width(); // Misaki 修改 - maxHeight = LAppDelegate::GetInstance()->GetWindow()->height(); + maxWidth = LAppDelegate::GetInstance()->GetWindowWidth(); // Misaki 修改 + maxHeight = LAppDelegate::GetInstance()->GetWindowHeight(); _renderSprite->SetWindowSize(maxWidth, maxHeight); @@ -400,8 +408,8 @@ void LAppView::ResizeSprite() // 描画領域サイズ int width, height; //glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height); - width = LAppDelegate::GetInstance()->GetWindow()->width(); - height = LAppDelegate::GetInstance()->GetWindow()->height(); + width = LAppDelegate::GetInstance()->GetWindowWidth(); + height = LAppDelegate::GetInstance()->GetWindowHeight(); float x = 0.0f; float y = 0.0f; diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f0881b..8b877c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,51 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) -set(CMAKE_PREFIX_PATH "/home/misaki/Qt/6.6.3/gcc_64") # 设置Qt6安装路径(此处请根据你的Qt6安装位置填写) +# 平台与架构检测 +if(DEFINED TARGET_ARCH AND TARGET_ARCH STREQUAL "arm64") + set(PLAT "linux_arm") + set(ARCH "arm64") + set(CMAKE_PREFIX_PATH "/home/misaki/MisakiCodes/rk3566-sdk/3rd/Qt6.6.3") + add_definitions(-DCSM_TARGET_HARMONYOS_ES3) # OpenGL ES 3.0 渲染宏 + add_definitions(-DEMBEDDED_LINUX) # 嵌入式Linux专用宏 +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|ARM64") + set(PLAT "linux_arm") + set(ARCH "arm64") + set(CMAKE_PREFIX_PATH "/home/misaki/MisakiCodes/rk3566-sdk/3rd/Qt6.6.3") + add_definitions(-DCSM_TARGET_HARMONYOS_ES3) + add_definitions(-DEMBEDDED_LINUX) +elseif(WIN32) + set(PLAT "windows") + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(ARCH "x86_64") + else() + set(ARCH "x86") + endif() + set(CMAKE_PREFIX_PATH "Qt/6.6.3/gcc_64") ## 按照自己电脑上qt6.6.3的位置来替换 + add_definitions(-DCSM_TARGET_WIN_GL) +elseif(APPLE) + set(PLAT "macos") + set(ARCH "x86_64") # 或通用二进制,可根据需要调整 + set(CMAKE_PREFIX_PATH "/home/misaki/Qt/6.6.3/gcc_64") + add_definitions(-DCSM_TARGET_MAC_GL) +elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") + set(PLAT "linux_64") + set(ARCH "x86_64") + set(CMAKE_PREFIX_PATH "/home/misaki/Qt6.3/6.6.3/gcc_64") + add_definitions(-DCSM_TARGET_LINUX_GL) +else() + message(FATAL_ERROR "Unsupported platform") +endif() + +# 渲染后端选择 +if(PLAT STREQUAL "linux_arm") + add_definitions(-DRENDER_BACKEND_GLES2) +else() + add_definitions(-DRENDER_BACKEND_OPENGL) +endif() + +message(STATUS " 当前Qt路径: ${CMAKE_PREFIX_PATH}") +message(STATUS " 当前平台: ${PLAT}, 架构: ${ARCH}") # 设置是否为debug模式 默认为Debug if(NOT CMAKE_BUILD_TYPE) @@ -16,11 +60,7 @@ endif() # 设置渲染方式,选择为OpenGL,不然默认是Cocos2d,编译会报错的,CMake也会给你警告的 set(FRAMEWORK_SOURCE OpenGL) -# 查找一些必要的src文件 -file(GLOB_RECURSE LAppLive2D - CONFIGURE_DEPENDS # CMake 3.12+:检测到新增文件自动重新生成 - "3rdparty/Live2D/Src/LAppLive2D/Src/*.cpp" -) +# 查找一些必要的src源文件 file(GLOB_RECURSE YosugaSrc CONFIGURE_DEPENDS "src/Handle/AudioHandle/Src/*.cpp" @@ -29,12 +69,8 @@ file(GLOB_RECURSE YosugaSrc "src/Handle/NetWorkHandle/Inc/*.h" "src/Handle/DataObjectHandle/Src/*.cpp" "src/Handle/DataObjectHandle/Inc/*.h" - "src/UI/Menu/Src/*.cpp" - "src/UI/Menu/Inc/*.h" "src/DAO/Inc/*.h" "src/DAO/Src/*.cpp" - "src/UI/Setting/Src/*.cpp" - "src/UI/Setting/Inc/*.h" "src/UI/Render/TextRender/Src/*.cpp" "src/UI/Render/TextRender/Inc/*.h" "src/Core/Src/*.cpp" @@ -44,6 +80,18 @@ file(GLOB_RECURSE YosugaSrc "src/Utils/Src/*.cpp" ) +# 如果是桌面平台,再额外添加 UI 相关目录 +if(NOT PLAT STREQUAL "linux_arm") + file(GLOB_RECURSE DesktopUI_Src + "src/UI/Menu/Src/*.cpp" + "src/UI/Menu/Inc/*.h" + "src/UI/Setting/Src/*.cpp" + "src/UI/Setting/Inc/*.h" + ) + message(STATUS " 被主机平台额外包含的库: ${YosugaSrc}") + list(APPEND YosugaSrc ${DesktopUI_Src}) +endif() + # 查找Qt6模块以及其他必须模块 find_package(Qt6 COMPONENTS Core @@ -57,153 +105,162 @@ find_package(Qt6 COMPONENTS OpenGLWidgets Concurrent REQUIRED) -find_package(OpenGL REQUIRED) -add_subdirectory(3rdparty/ElaWidgetTools) # 添加ElaWidgetTools UI库 -add_subdirectory(3rdparty/autogui-cpp) # 添加autogui-cpp GUI自动化库 +# 仅在非 ARM 平台查找桌面 OpenGL +if(NOT PLAT STREQUAL "linux_arm") + find_package(OpenGL REQUIRED) +else () + # 若为arm平台,对于C++采用静态链接标准库,避免环境复杂出现问题 + set(CMAKE_EXE_LINKER_FLAGS "-static-libstdc++ -static-libgcc") +endif () -add_executable(${PROJECT_NAME} main.cpp ${LAppLive2D} ${YosugaSrc}) - -# 区分平台 -if(WIN32) - set(PLAT "windows") - add_definitions(-DCSM_TARGET_WIN_GL) # 告诉 Live2D 框架,当前平台使用 OpenGL -elseif(APPLE) - set(PLAT "macos") - add_definitions(-DCSM_TARGET_MAC_GL) -elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") - if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64") - set(PLAT "linux_arm") - add_definitions(-DCSM_TARGET_LINUX_GL) - else() - set(PLAT "linux_64") - add_definitions(-DCSM_TARGET_LINUX_GL) - endif() -elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_OSX_ARCHITECTURES MATCHES "arm64") - set(PLAT "macos") # 统一按 macos 处理,后面再细分 x86_64 / arm64 +# 添加第三方子项目 +if(NOT PLAT STREQUAL "linux_arm") + ### 部分第三方子项目与嵌入式Linux不兼容(嵌入式Linux环境复杂,有的没有桌面环境,因此不一定支持窗口) + add_subdirectory(3rdparty/ElaWidgetTools) # 添加ElaWidgetTools UI库 + add_subdirectory(3rdparty/autogui-cpp) # 添加autogui-cpp GUI自动化库 +else() + message(STATUS "ARM platform: skipping ElaWidgetTools and autogui-cpp (cross‑compile them separately)") endif() -# 架构文件夹名(Windows 分 x86 / x86_64,Linux 分 x86_64 / arm64,macOS 通用二进制) -if(WIN32) - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(ARCH "x86_64") +#### 主可执行文件 +add_executable(${PROJECT_NAME} main.cpp ${YosugaSrc}) + +#### 库导入路径配置 +# Framework 静态库 +if(PLAT STREQUAL "linux_arm") + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + ### 注意此处需要根据你的framework的放置目录进行调整 + set(FRAMEWORK_LIB_PATH "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/Live2D/Lib/Debug/linux_arm/framework/misaki_rk3566/libFramework.a") else() - set(ARCH "x86") + set(FRAMEWORK_LIB_PATH "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/Live2D/Lib/Release/linux_arm/framework/misaki_rk3566/libFramework.a") endif() -elseif(PLAT STREQUAL "linux_arm") - set(ARCH "arm64") else() - set(ARCH "x86_64") + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(LIB_CONFIG "Debug") + else() + set(LIB_CONFIG "Release") + endif() + set(LIB_BASE "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/Live2D/Lib") + set(LIB_CONFIG_DIR "${LIB_BASE}/${LIB_CONFIG}/${PLAT}") + set(FRAMEWORK_LIB_PATH "${LIB_CONFIG_DIR}/framework/libFramework.a") +endif() + +add_library(Framework STATIC IMPORTED GLOBAL) +set_target_properties(Framework PROPERTIES IMPORTED_LOCATION "${FRAMEWORK_LIB_PATH}") +message(STATUS "Framework 库: ${FRAMEWORK_LIB_PATH}") + +# Core 静态库 该库由官方自行编译提供,理论上是平台无关的,但是可能和glibc版本有关,太老的glibc版本不一定能使用 +# 因为Core没有开源,也因此才叫Live2D SDK,而不是Live2D Lib。个人觉得不如开源出来,像Qt那样就挺好。 +if(PLAT STREQUAL "linux_arm") + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(CORE_LIB_PATH "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/Live2D/Lib/Debug/linux_arm/live2d/static_lib/arm64/libLive2DCubismCore.a") + else() + set(CORE_LIB_PATH "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/Live2D/Lib/Release/linux_arm/live2d/static_lib/arm64/libLive2DCubismCore.a") + endif() +else() + if(PLAT STREQUAL "windows") + set(CORE_LIB_PATH "${LIB_CONFIG_DIR}/live2d/static_lib/x86_64/Live2DCubismCore.lib") + else() + set(CORE_LIB_PATH "${LIB_CONFIG_DIR}/live2d/static_lib/x86_64/libLive2DCubismCore.a") + endif() +endif() + +add_library(Live2DCubismCore STATIC IMPORTED GLOBAL) +set_target_properties(Live2DCubismCore PROPERTIES IMPORTED_LOCATION "${CORE_LIB_PATH}") +message(STATUS "Live2D Core 库: ${CORE_LIB_PATH}") + +# 导入 LAppLive2D 子项目 Live2D 应用层,静态库 +# 依赖顺序:lapp_live2d -> Framework -> Live2DCubismCore +add_subdirectory(3rdparty/Live2D/Src/LAppLive2D) + +# LAppOpenGL.hpp 根据平台选择 GL / GLES2 头文件,为 lapp_live2d 补充对应路径 +if(NOT PLAT STREQUAL "linux_arm") + target_include_directories(lapp_live2d PUBLIC + 3rdparty/Live2D/Src/glew/include + 3rdparty/Live2D/Src/glew/include/GL + 3rdparty/Live2D/Src/glfw/include + 3rdparty/Live2D/Src/glfw/include/GLFW + ) +else() + target_include_directories(lapp_live2d PUBLIC + /home/misaki/MisakiCodes/rk3566-sdk/host/aarch64-buildroot-linux-gnu/sysroot/usr/include + /home/misaki/MisakiCodes/rk3566-sdk/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/GLES2 + ) +endif() + +# GLFW 和 GLEW(仅桌面平台需要) +if(NOT PLAT STREQUAL "linux_arm") + # glfw + add_library(glfw3 STATIC IMPORTED GLOBAL) + set_target_properties(glfw3 PROPERTIES IMPORTED_LOCATION "${LIB_CONFIG_DIR}/glfw/libglfw3.a") + message(STATUS "GLFW 库: libglfw3.a") + + # glew + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + if(PLAT STREQUAL "windows") + set(GLEW_LIB_NAME "libglew32d.dll.a") + else() + set(GLEW_LIB_NAME "libGLEWd.a") + endif() + else() + if(PLAT STREQUAL "windows") + set(GLEW_LIB_NAME "libglew32.dll.a") + else() + set(GLEW_LIB_NAME "libGLEW.a") + endif() + endif() + add_library(GLEW STATIC IMPORTED GLOBAL) + set_target_properties(GLEW PROPERTIES IMPORTED_LOCATION "${LIB_CONFIG_DIR}/glfw/${GLEW_LIB_NAME}") + message(STATUS "GLEW 库: ${GLEW_LIB_NAME}") endif() #### 以下为链接相关的内容 - -# 根据平台 + 架构生成“库搜索路径”和“库文件名” -set(LIB_BASE "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/Live2D/Lib") -# 根据当前构建类型直接确定子目录(Debug 或 Release) -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(LIB_CONFIG "Debug") +if(PLAT STREQUAL "linux_arm") ## 针对嵌入式Linux的配置,部分条目需要根据你的soc以及sysroot进行修改 + target_link_libraries(${PROJECT_NAME} PRIVATE + lapp_live2d + Framework + Live2DCubismCore + # Mali GPU 驱动完整链接(EGLFS 必需) + -lmali-hook # 注意此处,你的soc不一定是该GPU,可能需要修改 + -Wl,--whole-archive -lmali-hook-injector -Wl,--no-whole-archive + -lmali + -ldrm + -lEGL + -lGLESv2 + # Qt 模块(从交叉编译的 Qt) + Qt::Core Qt::Gui Qt::Widgets Qt::Network Qt::Svg Qt::SerialPort + Qt::WebSockets Qt::Multimedia Qt::OpenGLWidgets Qt::Concurrent + # + # ElaWidgetTools autogui-cpp + ) else() - set(LIB_CONFIG "Release") + # 桌面平台 + target_link_libraries(${PROJECT_NAME} PRIVATE + lapp_live2d + Framework + glfw3 + GLEW + Live2DCubismCore + $<$:opengl32> + $<$:glu32> + ElaWidgetTools + autogui-cpp + Qt::Core Qt::Gui Qt::Widgets Qt::Network Qt::Svg Qt::SerialPort + Qt::WebSockets Qt::Multimedia Qt::OpenGLWidgets Qt::Concurrent + ) + if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT PLAT STREQUAL "linux_arm") + find_package(X11 REQUIRED) + target_link_libraries(${PROJECT_NAME} PRIVATE X11::X11) + endif() + if(APPLE) + find_library(COREGRAPHICS_LIB CoreGraphics REQUIRED) + target_link_libraries(${PROJECT_NAME} PRIVATE ${COREGRAPHICS_LIB}) + endif() endif() -message(STATUS "当前平台与编译方式: ${PLAT} : ${ARCH} : ${LIB_CONFIG}" ) - -# 拼接完整库目录 -set(LIB_CONFIG_DIR "${LIB_BASE}/${LIB_CONFIG}/${PLAT}") -# 需要链接的库列表 -# Framework(只有 .a,且 Debug/Release 同名) -add_library(Framework STATIC IMPORTED GLOBAL) -set_target_properties(Framework PROPERTIES - IMPORTED_LOCATION "${LIB_CONFIG_DIR}/framework/libFramework.a") -message(STATUS "当前Framework库: libFramework.a") - -# glfw -add_library(glfw3 STATIC IMPORTED GLOBAL) -set_target_properties(glfw3 PROPERTIES - IMPORTED_LOCATION "${LIB_CONFIG_DIR}/glfw/libglfw3.a") -message(STATUS "当前GLEW库: libglfw3.a") - -# glew Debug/Release 同名,Debug 同时提供了 .so,此处用 .a -# Debug 带 'd' 后缀,Release 不带 -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - # GLEW Unix与Windows生成行为不一致 - if(PLAT STREQUAL "windows") - set(GLEW_LIB_NAME "libglew32d.dll.a") - else () # 其他平台 - set(GLEW_LIB_NAME "libGLEWd.a") - endif () -elseif (CMAKE_BUILD_TYPE STREQUAL "Release") - if (PLAT STREQUAL "windows") - set(GLEW_LIB_NAME "libglew32.dll.a") - else () - set(GLEW_LIB_NAME "libGLEW.a") - endif () -endif() -add_library(GLEW STATIC IMPORTED GLOBAL) -set_target_properties(GLEW PROPERTIES - IMPORTED_LOCATION "${LIB_CONFIG_DIR}/glfw/${GLEW_LIB_NAME}") -message(STATUS "当前GLEW库: ${GLEW_LIB_NAME}") - -# Live2D Cubism Core 静态 -add_library(Live2DCubismCore STATIC IMPORTED GLOBAL) -if (PLAT STREQUAL "windows") - set_target_properties(Live2DCubismCore PROPERTIES - IMPORTED_LOCATION "${LIB_CONFIG_DIR}/live2d/static_lib/x86_64/Live2DCubismCore.lib") - message(STATUS "当前Live2D库: Live2DCubismCore.lib") -else () - set_target_properties(Live2DCubismCore PROPERTIES - IMPORTED_LOCATION "${LIB_CONFIG_DIR}/live2d/static_lib/x86_64/libLive2DCubismCore.a") - message(STATUS "当前Live2D库: libLive2DCubismCore.a") -endif () - -target_link_libraries(${PROJECT_NAME} - PRIVATE - Framework - glfw3 - GLEW - Live2DCubismCore - $<$:opengl32> # WIN32 为真时才链接 - $<$:glu32> # WIN32 为真时才链接 -) -# 不论平台统一需要链接的库 -target_link_libraries(${PROJECT_NAME} - PRIVATE - ElaWidgetTools - autogui-cpp - Qt::Core - Qt::Gui - Qt::Widgets - Qt::Network - Qt::Svg - Qt::SerialPort - Qt::WebSockets - Qt::Multimedia - Qt::OpenGLWidgets - Qt::Concurrent -) - -# 全局热键 (PTT) 所需平台库 -if(APPLE) - find_library(COREGRAPHICS_LIB CoreGraphics REQUIRED) - target_link_libraries(${PROJECT_NAME} PRIVATE ${COREGRAPHICS_LIB}) -endif() -if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - find_package(X11 REQUIRED) - target_link_libraries(${PROJECT_NAME} PRIVATE X11::X11) -endif() - -# 添加头文件 -target_include_directories(${PROJECT_NAME} - PRIVATE - 3rdparty/Live2D/Src/Framework/src - 3rdparty/Live2D/Src/glew/include - 3rdparty/Live2D/Src/glew/include/GL - 3rdparty/Live2D/Src/glfw/include - 3rdparty/Live2D/Src/glfw/include/GLFW - 3rdparty/Live2D/Src/Core/include - 3rdparty/Live2D/Src/stb - 3rdparty/Live2D/Src/LAppLive2D/Inc +# 头文件路径 +target_include_directories(${PROJECT_NAME} PRIVATE 3rdparty/autogui-cpp/src src/Handle/AudioHandle/Inc src/Handle/NetWorkHandle/Inc @@ -216,19 +273,13 @@ target_include_directories(${PROJECT_NAME} src/Utils/Inc ) - - -#### 构建时额外复制一些必要的文件与运行库 - -# 将资源文件夹 'other' 复制到构建目录 +# 资源复制(所有平台) file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/other/Resources" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") -# 复制 Live2D 渲染所需的 Shader 文件 file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/other/FrameworkShaders" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") - -# 对于windows,复制一些必要的dll库 +# Windows 特有的 DLL 复制 if(PLAT STREQUAL "windows") # 自动复制Ela的DLL add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD @@ -301,6 +352,4 @@ if(PLAT STREQUAL "windows") file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/Live2D/Lib/Debug/windows/live2d/static_lib/x86_64/Live2DCubismCore.dll" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") endif () -elseif () # 其他平台 - set() -endif () +endif() diff --git a/src/Core/Inc/GLCore.h b/src/Core/Inc/GLCore.h index 17ca90e..55a5504 100644 --- a/src/Core/Inc/GLCore.h +++ b/src/Core/Inc/GLCore.h @@ -2,7 +2,13 @@ #include #include +#if !defined(EMBEDDED_LINUX) #include "menu.h" +#endif +#ifdef EMBEDDED_LINUX +#include +#endif + #ifdef Q_OS_WIN #include #endif @@ -79,7 +85,13 @@ private: double frameRate = 60.0; /// 帧率 static QMap frameRateMap; /// 帧率映射表 QTimer* frameTimer; /// 帧控制定时器 +#if !defined(EMBEDDED_LINUX) Menu *contextMenu; /// 使用 Menu 类 +#endif +#ifdef EMBEDDED_LINUX + QPushButton *pttButton; /// 嵌入式平台PTT按钮 +#endif + bool isLeftPressed; /// 鼠标左键是否按下 bool isRightPressed; /// 鼠标右键是否按下 QPoint currentPos; /// 当前鼠标位置 diff --git a/src/Core/Src/GLCore.cpp b/src/Core/Src/GLCore.cpp index 34c47e2..512258d 100644 --- a/src/Core/Src/GLCore.cpp +++ b/src/Core/Src/GLCore.cpp @@ -14,8 +14,12 @@ #include #include "TextRenderer.h" -// #include "AudioOutput.h" #include "AppContext.h" +#include "GLRenderContext.hpp" // 渲染后端抽象 +#ifdef EMBEDDED_LINUX +#include "AppCore.h" +#include +#endif QMap GLCore::frameRateMap = { {"30", 30.0}, {"60", 60.0}, @@ -49,7 +53,9 @@ GLCore::GLCore(const int width, const int height, QWidget *parent) QApplication::setFont(QFont("Microsoft YaHei", 13)); // new一些必要的对象 +#if !defined(EMBEDDED_LINUX) contextMenu = new Menu(this); +#endif // 设置窗口大小 setFixedSize(width, height); @@ -81,7 +87,38 @@ GLCore::GLCore(const int width, const int height, QWidget *parent) this->setMouseTracking(true); // 连接一些必要的信号与槽 +#ifndef EMBEDDED_LINUX // 如果不是嵌入式Linux系统(注意如果你的嵌入式Linux平台启用了桌面系统,那么可能需要去掉这个条件宏) connect(contextMenu, &Menu::closeMainWindow, this, &GLCore::closeGL); // 关闭窗口信号 +#endif + +#ifdef EMBEDDED_LINUX + AppCore::getInstance(); + + pttButton = new QPushButton(this); + pttButton->setFixedSize(64, 64); + pttButton->move(width - 80, height - 80); + pttButton->setIcon(QIcon("Resources/Pic/Others/voice.png")); + pttButton->setIconSize(QSize(56, 56)); + pttButton->setStyleSheet( + "QPushButton {" + " background-color: rgba(255, 255, 255, 60);" + " border-radius: 32px;" + " border: none;" + "}" + "QPushButton:pressed {" + " background-color: rgba(250, 80, 80, 150);" + "}" + ); + pttButton->raise(); + pttButton->show(); + + connect(pttButton, &QPushButton::pressed, this, []() { + AppCore::getInstance()->startPttRecording(); + }); + connect(pttButton, &QPushButton::released, this, []() { + AppCore::getInstance()->stopPttRecording(); + }); +#endif // 注册当前实例到中介类 AppContext::RegisterGLCore(this); @@ -191,10 +228,12 @@ void GLCore::mouseMoveEvent(QMouseEvent* event) const float y = static_cast(event->position().y()); LAppDelegate::GetInstance()->GetView()->OnTouchesMoved(x, y); // 将当前鼠标位置传递给LAppDelegate +#if !defined(EMBEDDED_LINUX) if (isLeftPressed) { // 鼠标左键按下 const QPoint newPos = event->globalPos() - currentPos; this->move(newPos); } +#endif } void GLCore::mousePressEvent(QMouseEvent* event) @@ -249,7 +288,9 @@ void GLCore::mousePressEvent(QMouseEvent* event) if (event->button() == Qt::RightButton) { // 在鼠标右键点击的位置创建菜单,显示自定义右键菜单 if (onModel) { +#if !defined(EMBEDDED_LINUX) contextMenu->showMenu(event->globalPos()); +#endif this->isRightPressed = true; } else { @@ -297,7 +338,25 @@ void GLCore::mouseReleaseEvent(QMouseEvent* event) void GLCore::initializeGL() { - LAppDelegate::GetInstance()->Initialize(this); + // 注入渲染后端抽象层,由GLCore(OpenGL)创建GLRenderContext并交给LAppDelegate管理 + if (!LAppDelegate::GetInstance()->GetRenderContext()) { + LAppDelegate::GetInstance()->SetRenderContext(new GLRenderContext()); + } + // 初始化GLEW 必须在任何Live2D渲染操作之前调用 + // Live2D预编译的libFramework.a使用GLEW函数指针(如glGenFramebuffers等), + // 未调用glewInit()会导致空指针解引用SIGSEGV + glewExperimental = GL_TRUE; + if (glewInit() != GLEW_OK) { + qFatal("Failed to initialize GLEW"); + return; + } + + // 注册窗口大小变更回调 模型加载后通过此回调通知GLCore调整窗口 + LAppDelegate::GetInstance()->SetWindowResizeCallback([this](int w, int h) { + setWindowSize(w, h); + }); + // LAppDelegate::GetInstance()->Initialize(this); // 原(QWidget*) + LAppDelegate::GetInstance()->Initialize(this->width(), this->height()); // 解耦 } void GLCore::paintGL()