编译3D渲染引擎Horde3D

news2025/2/9 8:25:13

Horde3D是Github上一款开源的轻量级3D渲染引擎,同时它还支持多个平台。今天我们准备在Mac平台上交叉编译至Android平台。如果需要同时能编译Sample,那么还需要SDL2库。默认情况下,编译Horde3D时不强制下载SDL2,你可以选择强制下载,版本默认下载的是2.0.9,不过我们打算替换为2.26.5。推荐读者最好先看一下Horde3D根目录下的CMakeLists.txt脚本,可以更好地理解细节。废话不多说,现在开始编译。

在这里插入图片描述

文章目录

    • 1. 配置编译环境
    • 2. 编译Horde3D渲染引擎
      • 2.1 预编译SDL2库
      • 2.2 修改Horde3D Android Sample中样板代码
        • 2.2.1 替换BuildTools/android/app/src/main/java/org/libsdl/app下源码
        • 2.2.2 (可选)修改BuildTools/android/app/下build.gradle.in和AndroidManifest.xml
        • 2.2.3 (可选)修改BuildTools/android/gradle/wrapper下gradle-wrapper.properties文件
        • 2.2.4 (可选)修改BuildTools/android/下build.gradle文件
        • 2.2.5 修改Horde3D/Samples/Framework/SDLFramework.cpp
      • 2.3 修改Horde工程CMakeLists.txt
      • 2.4 (可选)添加BuildTools/android/gradlew的执行权限
      • 2.5 编译Horde3D库及Sample
    • 3. 吐槽在Windows上的踩坑之路
      • 3.1 给工程最好加上CMP0135政策
      • 3.2 默认下载的SDL2.0.9版本Clang14编译失败
      • 3.3 SDL2.26.5中已移除SDL_HINT_MOUSE_TOUCH_EVENTS

1. 配置编译环境

交叉编译至Android平台我们需要用到NDK,为了同时能编译Android App Sample,我们再额外准备一下Android SDK(如果你很熟悉这些,请跳过这一部分,不然的话,你最好进入Android Studio中的SDK Manager下载你需要的平台SDK)。至于CMake工具,在官网上下载即可。在Mac,Linux上编译流程类似,在Windows上稍微麻烦一点,不过是类似的,无非是环境变量的配置麻烦点,笔者都已编译过。

本次编译我们选择Mac机器进行操作示范,同时,我们通过分析Horde3D的根CMakeLists脚本,先预编译好SDL2库,然后替换一部分Horde3D的Sample的预构建样板代码,具体下面操作介绍。

2. 编译Horde3D渲染引擎

2.1 预编译SDL2库

在预编译SDL2之前,让我们先拉取一下Horde3D的源码:

  git clone https://github.com/horde3d/Horde3D.git

查看Horde3D的根CMakeLists脚本,我们看到其中逻辑会进入到find_package(SDL2),该语句会执行FindSDL2.cmake脚本。其实这里的脚本有一些逻辑错误,假如既未预编译安装SDL2库,又未强制要求Download SDL2(HORDE3D_FORCE_DOWNLOAD_SDL默认为OFF),那么会进入错误的逻辑,虽然问题不大,但是确实很讨厌。因此,出于编译单元分离的目的,我们先进行SDL2的编译。

在机器上找个合适的目录,将SDL2.26.5.zip下载下来并解压,创建一个用于存放构建内容的目录,例如:

  mkdir build-android

我们可以使用CMake-GUI工具,配置以下几个Entry(ANDROID_ABI,ANDROID_PLATFORM,ANDROID_DL_LIBRARY),Entry的值可直接参考Horde的编译指导,同时在Configure时我们选择Unix makefilesSpecify toolchain file for cross-compiling,cmake文件选择ndk中的Android NDK/build/cmake/android.toolchain.cmake文件。然后将CMAKE_INSTALL_PREFIX
设置为自定义的目录,例如build-android下再自定义一个outputConfigure完成后进行Generate以生成Makefile文件,然后在build-android目录下执行:

  make && make install

至此,SDL2.26.5版本已编译成功并安装至build-android/output下。

当然,如果你不喜欢使用CMake GUI,那么也可以在build-android目录下启动一个终端,并输入(供参考):

  cmake -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-24 -DANDROID_DL_LIBRARY=<path-to-your-Android-SDK>/ndk/<ndk-version>/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/libdl.so -DCMAKE_BUILD_TYPE=Release -DANDROID_SDK_ROOT_PATH=<path-to-your-Android-SDK> -DCMAKE_TOOLCHAIN_FILE=<path-to-your-Android-SDK>/ndk/<ndk-version>/build/cmake/android.toolchain.cmake -DCMAKE_INSTALL_PREFIX=<path-to-current-dir>/output -G "Unix Makefiles" --fresh ..

--fresh选项是较新的CMake上才有的,例如本文使用的3.26.4,该选项可以确保刷新CMakeCache变量。至于24,你也可以改成别的版本,配套即可。

等待构建文件生成后,再执行以下命令用以启动make

  cmake --build .

最后再make install一下。至此,与前文用CMake GUI的方式结果一致。

2.2 修改Horde3D Android Sample中样板代码

2.2.1 替换BuildTools/android/app/src/main/java/org/libsdl/app下源码

该目录下默认包含来自SDL2.0.9的代码,我们可以将SDL2.26.5解压缩的文件夹中的android-project/app/src/main/java/org/libsdl/app下的java文件拷贝至BuildTools/android/app/src/main/java/org/libsdl/app下。

2.2.2 (可选)修改BuildTools/android/app/下build.gradle.in和AndroidManifest.xml

该目录下的build.gradle.in文件是预构建Sample的app层级的build.gradle的模版文件。修改其中的compileSdkVersiontargetSdkVersion,同时删掉buildToolsVersion = '28.0.3'这句话。

若使用31及以上的SDK,则需要在AndroidManifest.xml中的<activity>中添加android:exported="true"字段。

2.2.3 (可选)修改BuildTools/android/gradle/wrapper下gradle-wrapper.properties文件

默认的Gradle版本使用的是5.1.1-all,可以自行修改至已下载的版本,例如笔者改成了6.7.1-all,缩减后续时间。

2.2.4 (可选)修改BuildTools/android/下build.gradle文件

	buildscript {
	   repositories {
	       // jcenter()
	       mavenCentral()
	       google()
	   }
	   dependencies {
	       classpath 'com.android.tools.build:gradle:4.2.2'
	   }
	}
	
	allprojects {
	   repositories {
	       // jcenter()
	       mavenCentral()
	       google()
	   }
	}

2.2.5 修改Horde3D/Samples/Framework/SDLFramework.cpp

修改以下代码(修改前):

  SDL_SetHint( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1" );
  SDL_SetHint( SDL_HINT_TOUCH_MOUSE_EVENTS, "0" );

修改后:

  // SDL_SetHint( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1" );
  SDL_SetHint( SDL_HINT_MOUSE_TOUCH_EVENTS, "0" );
  SDL_SetHint( SDL_HINT_TOUCH_MOUSE_EVENTS, "0" );

2.3 修改Horde工程CMakeLists.txt

我们不打算通过find_package的方式去查找SDL2的目录,此处直接写入以下几个值:

  # find_package(SDL2)
  set(SDL2_FOUND TRUE)
  set(SDL_LIB_PATH "<path-to-your-sdl2>/lib")
  set(SDL2_INCLUDE_DIR "<path-to-your-sdl2>/include/SDL2")
  set(SDL_LIBRARY_PATH <path-to-your-sdl2>/lib/libSDL2.so")
  set(SDL2_LIBRARY ${SDL_LIBRARY_PATH})

2.4 (可选)添加BuildTools/android/gradlew的执行权限

最好检查一下该文件的执行权限,否则在构建Sample过程中会出现Permission Denied错误。使用chmod命令,此处不赘述。

2.5 编译Horde3D库及Sample

前文所述的操作步骤完成后,即可创建自定义build文件夹来存放构建成果物,例如创建一个build-android文件夹,在该目录下打开终端,执行以下命令:

  cmake -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-24 -DHORDE3D_FORCE_DOWNLOAD_SDL=OFF -DHORDE3D_USE_GL2=OFF -DHORDE3D_USE_GL4=OFF -DHORDE3D_USE_GLES3=ON -DCMAKE_BUILD_TYPE=<Debug-or-Release> -DANDROID_SDK_ROOT_PATH=<path-to-your-Android-SDK> -DCMAKE_TOOLCHAIN_FILE=<path-to-your-Android-SDK>/ndk/<ndk-version>/build/cmake/android.toolchain.cmake -G "Unix Makefiles" --fresh ..

随后开始进行编译构建,同前文:

  cmake --build .

最后可以在build-android/Android下找到多个Android Sample Project。在Android Studio中打开并运行至手机,以Chicago为例,最后可以看到成功运行,图就不放了,读者自己去构建吧。

3. 吐槽在Windows上的踩坑之路

跟着下面的步骤,让我们一起在Windows上踩坑吧。

现在开始第一次编译,我们还没有单独编译SDL2库,因此就采用直接运行脚本来自动下载SDL2库并进行默认编译链接等动作。按照Horde3D的编译doc指导进行操作。

在Windows平台上使用CMake gui来配置路径地址时,不要使用\斜杠,一定要统一使用/斜杠,不然会导致后续的解析失败。

执行Configure,OK,不出所料,报错了。这里其实确实是一个脚本的问题,原因是我们没有强制要求下载SDL2库,它默认为SDL2已在本地是有的,因此要消除这个bug,我们本质上需要修改一下CMakeLists脚本。找到下面这句话,将OFF改为ON,或者也可以直接在CMake GUI中将HORDE3D_FORCE_DOWNLOAD_SDL这个option打上勾。

  option(HORDE3D_FORCE_DOWNLOAD_SDL "Force linking Horde3D to a downloaded version of SDL" OFF)

在CMake gui中重新Configure,再次报错,错误信息如下:

External SDL project done
CMake Error at BuildTools/CMake/Modules/FindSDL2.cmake:255 (get_filename_component):
  get_filename_component unknown component -pthread
Call Stack (most recent call first):
  CMakeLists.txt:55 (find_package)

Configuring incomplete, errors occurred!

我们找到FindSDL2.cmake文件的第255行:

	IF( ${CMAKE_SYSTEM_NAME} STREQUAL "Android" )
		get_filename_component( SDL_LIB_PATH ${SDL2_LIBRARY} DIRECTORY )
	ENDIF()

再稍作定位,找到SDL2_LIBRARY这个参数,在第245行:

    set(SDL2_LIBRARY ${SDL_LIBRARY_PATH} ${CMAKE_THREAD_LIBS_INIT})

给CMAKE_THREAD_LIBS_INIT加个打印,重新Configrure一下,可以看到,这个值就是-pthread

下一个问题,get_filename_component()函数是干嘛的(读者如果不知道的话,还是看一下CMake官方doc吧 get_filename_component),是不是移除-pthread就行。我们知道,在NDK的Native APIs这一节里,有提到这么一句话:

The standard C11 library headers such as <stdlib.h> and <stdio.h> are available as usual.

Note that on Android, unlike Linux, there are no separate `libpthread` or `librt` libraries. That functionality is included directly in libc, which does not need to be explicitly linked against.

因此,当我们的构建目标是Android时,不需要主动去链接pthread库,因为已经合入到了c库中,而c库又是NDK编译时会自动链接的。现在想必你应该已经知道了解决办法。很简单,我们将${CMAKE_THREAD_LIBS_INIT}这个值删掉。

在CMake GUI中重新configure。可喜可贺,看到了喜闻乐见的Configuring done。心情瞬间是不是好了很多。其实这后面还有坑等着你,不过到目前为止,我们似乎已经准备好了一切。接下来的工作就不手把手教了。笔者直接在此罗列一下遇到的坑。相信读者也能靠自己的耐心与能力解决它们。

3.1 给工程最好加上CMP0135政策

按照官方的提示,我们在主CMakeLists中插入以下语句:

    if(POLICY CMP0135)
        cmake_policy(SET CMP0135 NEW)
    endif(POLICY CMP0135)

3.2 默认下载的SDL2.0.9版本Clang14编译失败

Clang14在编译2.0.9版本SDL2库时,报了一个C99的错误,查看原因,似乎也很难分析出为什么,看代码似乎一切正常,摆烂,直接与时俱进,替换为SDL最新的发布版本。

查找并替换脚本中预下载的SDL版本至2.26.5。这需要接下来进行一系列的修改,主要包括将原先2.0.9的预置代码统统删掉,替换为2.26.5的新代码。

3.3 SDL2.26.5中已移除SDL_HINT_MOUSE_TOUCH_EVENTS

修改SDLFramework.cpp中的代码,替换为以下代码,同前文所述:

  // SDL_SetHint( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1" );

  SDL_SetHint( SDL_HINT_MOUSE_TOUCH_EVENTS, "0" );
  SDL_SetHint( SDL_HINT_TOUCH_MOUSE_EVENTS, "0" );

完成上述的这些修改后,需要在CMake gui中重新Configure,使其构造出默认的样板工程。然后运行Generate,创建Makefile脚本,然后运行使用NDK中Android NDK/prebuilt/windows-x86_64/bin/make.exe,参考Horde3D的doc即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/640513.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能python:Python怎么快速入门?

Python怎么快速入门&#xff1f; Python是一种易学易用的编程语言。它被广泛应用于各种领域&#xff0c;例如数据科学、自动化、Web开发、游戏开发等等。无论你是从事什么领域&#xff0c;在Python的快速入门上花费越少的时间越好。在本文中&#xff0c;我们将介绍Python的基础…

工作二--注意!!!

1、激活单元格&#xff0c;做数据回显 2、单元格退出编辑模式时&#xff0c;让 实时保存 3、获取数据时&#xff0c;用getGIUID 给数据 唯一id&#xff0c;以防数据名重复 数据结构&#xff1a;是结合接口的id 等 和 组件的数据结构 4、父子结构 下拉框中的 :value 把value值 …

网络安全如何6个月成功上岸?

学前感言: 1.这是一条坚持的道路,三分钟的热情可以放弃往下看了. 2.多练多想,不要离开了教程什么都不会了.最好看完教程自己独立完成技术方面的开发. 3.有时多 google,baidu,我们往往都遇不到好心的大神,谁会无聊天天给你做解答. 4.遇到实在搞不懂的,可以先放放,以后再来解…

Haproxy搭建Web高可用群集 【Keepalived+HAProxy 高可用 日志定义 内核优化】

Haproxy HAProxy是可提供高可用性、负载均衡以及基于TCP和HTTP应用的代理&#xff0c;是免费、快速并且可靠的一种解决方案。HAProxy非常适用于并发大&#xff08;并发达1w以上&#xff09;web站点&#xff0c;这些站点通常又需要会话保持或七层处理。HAProxy的运行模式使得它可…

Oracle 查询优化改写(第一章)

第一章 单表查询 1.查询空值 2.将空值转换为实际值 不采用nvl&#xff08;&#xff09;函数&#xff0c;而使用COALESCE函数语法为COALESCE(表达式1,表达式2,...,表达式n)&#xff0c;n>2,此表达式的功能为返回第一个不为空的表达式&#xff0c;如果都为空则返回空值。 注…

每日算法总结——回溯算法、 LeetCode 131. 分割回文串

LeetCode 131. 分割回文串 131. 分割回文串 - 力扣&#xff08;LeetCode&#xff09; 什么是回溯算法&#xff1f; 回溯算法真的是解决排列问题的一大利器&#xff0c;其实很多时候自己不经意间就写出了回溯算法&#xff0c;但是一直没有一个系统的认识&#xff0c;今天做一…

B树:数据结构中的平衡之道

目录 引言&#xff1a;一、定义&#xff1a;二、特点&#xff1a;三、应用场景&#xff1a;总结&#xff1a; 引言&#xff1a; 在计算机科学领域中&#xff0c;数据结构是构建和组织数据的重要工具。其中&#xff0c;B树&#xff08;B-tree&#xff09;作为一种自平衡的搜索树…

用RDMA重新思考有状态流处理

摘要 远程直接内存访问 (RDMA) 硬件弥合了网络和主要内存速度之间的差距&#xff0c;从而验证了网络通常是分布式数据处理系统中的瓶颈的常见假设。然而&#xff0c;高速网络并没有提供“即插即用”的性能&#xff08;例如&#xff0c;使用 IP-overInfiniBand&#xff09;&…

第二章 数据处理篇:transforms

教程参考&#xff1a; https://pytorch.org/tutorials/ https://github.com/TingsongYu/PyTorch_Tutorial https://github.com/yunjey/pytorch-tutorial 详细的transform的使用样例可以参考&#xff1a;ILLUSTRATION OF TRANSFORMS 文章目录 为什么要使用transformstransforms方…

RK3588平台开发系列讲解(以太网篇)PHY驱动

文章目录 一、PHY驱动初始化二、PHY 配置初始化三、PHY 的扫描四、PHY 的STATUS状态读取五、PHY的RESET 复位六、PHY 的注册phy_device_register七、PHY 的状态变化沉淀、分享、成长,让自己和他人都能有所收获!😄 一、PHY驱动初始化 完成了mdio总线的注册,以及对不一样厂家…

chatgpt赋能python:Python怎么截图

Python怎么截图 介绍 在日常的工作和学习中&#xff0c;截图是一项非常常见的操作。随着Python在各个领域的不断普及和应用&#xff0c;使用Python进行截图也成为了一个热门话题。Python作为一种高级编程语言&#xff0c;具备丰富的第三方库和模块&#xff0c;可以实现复杂的…

chatgpt赋能python:Python的GUI界面开发

Python的GUI界面开发 Python是目前非常流行的编程语言之一&#xff0c;其优雅的语法和强大的库使其在各个领域得到广泛应用。在GUI界面开发方面&#xff0c;Python也表现出了巨大的潜力。本文将介绍Python的GUI开发框架以及相关的工具和技术。 介绍 Python有多个GUI框架可供…

chatgpt赋能python:Python快速打括号小技巧

Python快速打括号小技巧 作为Python程序员&#xff0c;打括号无法避免。但是有没有快速打括号的方法呢&#xff1f;本文将分享一些小技巧&#xff0c;让你在编码中更加高效。 常规打括号 首先&#xff0c;我们来看看常规的打括号方法。在Python中&#xff0c;我们需要用括号…

Nacos架构与原理 - 健康检查机制

文章目录 注册中心的健康检查机制Nacos 健康检查机制临时实例健康检查机制永久实例健康检查机制集群模式下的健康检查机制 注册中心的健康检查机制 想象发生地质灾害,被掩埋在废墟下,搜救队需定位才能施救。两种方法: 大喊求救,告知位置与健康状况,让搜救队知晓搜救队使用专业…

机器学习之线性回归模型

1 线性回归模型介绍 线性回归模型是机器学习中非常基础且经典的模型&#xff0c;是利用线性拟合的方式探寻数据背后的规律&#xff0c;特征变量的个数可将线性回归模型分为一元线性回归和多元线性回归。 &#xff08;1&#xff09;一元线性回归 线性模型的原型为一元一次方程&…

多线程/WinAPI线程退出方式比较分析

文章目录 概述ExitThreadTerminateThread进程退出逼迫线程退出?线程入口函数返回验证无法执行C对象析构不同方案的比较参考或关联 概述 关于如何终止 Windows 线程&#xff0c;在 MSDN Terminating a Thread 一文中列举的很详细&#xff1a; A thread executes until one of …

python数据赋值后,修改新数据,原数据如何保证不被修改?

目录 1.deepcopy 2.实战演练 3.python中的变量实质 好文推荐&#xff1a;传送锚点 1.deepcopy python中对象&#xff0c;赋值后是同一地址&#xff0c;如果是可变对象&#xff0c;对其中一个修改会影响到另一个&#xff0c;如果要生成完全新的对象&#xff0c;应使用&#…

使用Gogs搭建自己的github服务器

文章目录 下载Gogs配置和启动让gogs保持运行 使用参考资料 Gogs官方网址&#xff1a;https://gogs.io/ 下载Gogs 在官网首页可以找到二进制运行&#xff0c;点击进去 让咱们去 github 咱们就去 github 看看好了。https://github.com/gogs/gogs/releases 找到自己需要的版本。 …

【OpenMMLab AI实战营第二期】语义分割与MMSegmentation

MMSegmentation 开源代码仓&#xff1a;https://github.com/open-mmlab/mmsegmentation 算法丰富&#xff1a;600预训练模型、40篇算法复现 模块化设计&#xff1a;配置简便、容易拓展 统一超参&#xff1a;大量消融实验、支持公平对比 使用方便&#xff1a;训练工具、调试…

Python处理办公自动化的10大场景

在编程世界里&#xff0c;Python已经是名副其实的网红了。Python最大优势在于容易学&#xff0c;门槛比Java、C低非常多&#xff0c;给非程序员群体提供了用代码干活的可能性。当然Python能成为大众编程工具&#xff0c;不紧是因为易学&#xff0c;还因为Python有成千上万的工具…