【iOS ARKit】3D文字
首先,3D场景中渲染的任何虚拟元素都必须具有网格(顶点及顶点间的拓扑关系),没有网格的元素无法利用GPU 进行渲染,因此,在3D 场景申渲染 3D文字时,文字也必须具有网格。在计算机系统中,文字以平面点阵的形式存储和表示,所以进行3D文字渲染,需要将平面点阵转换为3D网格。
在 RealityKit 中,开发人员可以程序化地生成立方体、球体、圆柱体等3D虚拟对象,这个过程其实就是利用算法生成立方体、球体、圆柱体的网格信息、法线信息、UV坐标信息的过程,有了这些基础信息,CPU与 GPU 就知道如何将虚拟对象渲染出来。
RealityKit 也提供了根据指定文字自动生成文字网格、法线信息、UV坐标信息的方法 generateText(),该方法返回 MeshResource 类型对象,利用这个对象就可以对文字进行3D 渲染。在 RealityKit 中,生成3D文字的典型代码如代码如下所示。
//
// Text3DView.swift
// ARKitDeamo
//
// Created by zhaoquan du on 2024/3/21.
//import SwiftUI
import ARKit
import RealityKit
import Combinestruct Text3DView: View {@State var change: String = "中文汉字"var body: some View {Text3DViewContainer(change: change).overlay(VStack{Spacer()TextField( LocalizedStringKey(""), text: $change).foregroundColor(.black).background(Color.white).frame(width:300,height:50).cornerRadius(5).opacity(0.6).offset(y:-330).padding(.bottom, 300)}).navigationTitle("3D文字").edgesIgnoringSafeArea(.all)}
}struct Text3DViewContainer:UIViewRepresentable {var change:String = ""func makeUIView(context: Context) -> some ARView {let arView = ARView(frame: .zero)context.coordinator.arView = arViewlet config = ARWorldTrackingConfiguration()config.planeDetection = .horizontalcontext.coordinator.createPlane()arView.session.run(config)return arView}func updateUIView(_ uiView: UIViewType, context: Context) {if !change.isEmpty {context.coordinator.chengeText(text: change)}}func makeCoordinator() -> Coordinator {Coordinator()}class Coordinator: NSObject {var arView: ARView!var text: String = ""var textEntity: ModelEntity!func createPlane() {let planeAnchor = AnchorEntity(plane: .horizontal)let textr = MeshResource.generateText("中文汉字",extrusionDepth: 0.05,font: .systemFont(ofSize: 15),containerFrame: .zero,alignment: .left,lineBreakMode: .byWordWrapping)let textMetiral = SimpleMaterial(color: .red, isMetallic: true)textEntity = ModelEntity(mesh: textr, materials: [textMetiral])textEntity.generateCollisionShapes(recursive: false)planeAnchor.addChild(textEntity)arView.scene.addAnchor(planeAnchor)arView.installGestures(.all, for: textEntity)}func chengeText(text: String) {let planeAnchor = AnchorEntity(plane: .horizontal)let textr = MeshResource.generateText(text,extrusionDepth: 0.05,font: .systemFont(ofSize: 2),containerFrame: .zero,alignment: .left,lineBreakMode: .byWordWrapping)let textMetiral = SimpleMaterial(color: .red, isMetallic: true)textEntity.removeFromParent()textEntity = ModelEntity(mesh: textr, materials: [textMetiral])textEntity.generateCollisionShapes(recursive: false)planeAnchor.addChild(textEntity)arView.scene.addAnchor(planeAnchor)arView.installGestures(.all, for: textEntity)}}
}
#Preview {Text3DView()
}
从代码可以看到,生成3D文字的过程与生成其他程序化虚拟模型对象的过程完全一致,唯一区别是生成 3D 文字网格的方法要求设置的参数更多,generateText()方法原型
static func generateText (_ string: String, extrusionDepth: Float = 0. 25, font: MeshResource. Font = .systemPont(ofSize: MeshResource. Font. systemFontSize), containerFrame: CGRect = CGRect. zero, alignment: CTTextAlignment =. left, lineBreakMode: CTLineBreakMode = byTruncatingTail) - > MeshResource
generateText()方法参数众多,但实际除了 string 其余参数都可以使用默认值,各参数的意义如下表所示。
表11-1 生成3D文字网格的参数属性
| 参数名 | 描述 |
| string | 需要3D渲染的文字,使用内置的systemFont 可以渲染中文汉字与英文字符,如果使用其他字体渲染中文汉字需要确保字体支持 |
| extrusionDepth | 渲染的文字厚度,即在Z轴上的长度,以米为单位 |
| font | 渲染所用字体,渲染中文汉字需要字体支持,使用该属性可以指定字体大小。默认使用系统字体 |
| containerFrame | 该属性指定文字所占空间尺寸,类似于 Word文字排版软件中的文本框指定文字所占尺寸,当指定该值时,如果文字渲染超出该尺寸则会以 lineBreakMode 属性指定的方式截断。默认为(0,0),会以最合适的大小包裹所有文字 |
| alignment | 文字在 containerFrame 中的对齐方式,可以为 center(居中对齐)、justified(分散对齐)、left(左对齐)、natural(两端对齐)、right(右对齐)之一,该属性会影响缩放、旋转3D文字时的定位点 |
| lineBreakMode | 文字超出 containerFrame 范围时的截断方式,可以 byWordWrapping(以单词/汉字为单位显示,超出部分不显示)、byCharWrapping(以字符/汉字单位显示,超出部分不显示)、byClipping(剪切与containerFrame 尺寸一致的内容长度,后半部分被截断)、byTruncatingHead(前面文字被截断,用省略号显示)、byTruncatingTail(后面文字被截断,用省略号显示)、byTruncatingMiddle(两端文字保留,中间文字被省略,用省略号显示)之一 |
generateText()方法生成的文字 3D网格可以与其他程序化虚拟模型对象一样被赋子材质,包括纹理,也可以使用 ARAnchor 将其固定到场景中。
在 RealityKit 中生成的文字 3D网格不可修改,因此,无法通过网格修改的方式更新谊染的3D文字,果需要更新已生成的3D文字,则只能重新生成新的文字3D网格。
上述代码我们直接使用 changeText()方法重新生成新的文字3D网格,然后重新生成 textEntity 实体更新渲染的3D文字。在实际开发中,也可以通过扩展(extension) Entity 或者 ModelEntity 类,添加更新 3D文字的方法达到更方便使用的目的。
相关文章:
【iOS ARKit】3D文字
首先,3D场景中渲染的任何虚拟元素都必须具有网格(顶点及顶点间的拓扑关系),没有网格的元素无法利用GPU 进行渲染,因此,在3D 场景申渲染 3D文字时,文字也必须具有网格。在计算机系统中࿰…...
第二百二十八回
文章目录 1. 概念介绍2. 修改方法2.1 修改形状2.2 修改颜色2.3 修改位置 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何创建以图片为背景的页面"相关的内容,本章回中将介绍如何修改按钮的形状.闲话休提,让我们一起Talk Flutter吧。 1. …...
Java设计模式之单例模式(多种实现方式)
虽然写了很多年代码,但是说真的对设计模式不是很熟练,虽然平时也会用到一些,但是都没有深入研究过,所以趁现在有空练下手 这章主要讲单例模式,也是最简单的一种模式,但是因为spring中bean的广泛应用&#…...
Miracast投屏探索
Miracast是一种Wi-Fi Alliance推出的无线显示技术,允许在支持Miracast标准的设备之间进行屏幕镜像和内容共享。在Miracast技术中,通常会涉及到两种角色:Source(发送端)和Sink(接收端)。 Source&…...
2024年幻兽帕鲁服务器优惠价格表手动整理,最全报价
2024年全网最全的幻兽帕鲁服务器租用价格表,阿里云幻兽帕鲁游戏服务器26元1个月、腾讯云32元一个月、京东云26元一个月、华为云24元1个月,阿腾云atengyun.com整理最新幻兽帕鲁专用4核16G、8核16G、8核32G游戏服务器租用价格表大全: 阿里云幻…...
使用Python自动备份重要文件:一步一步的教程
目录 1 重要性说明1.1 数据丢失的风险1.2 自动化备份的好处1.3 提高数据安全性和恢复力 2 工具和技术简介2.1 os库2.2 shutil库2.3 glob库2.4 pathlib库 3 备份策略设计3.1 全备份3.2 增量备份3.3 差异备份3.4 根据需求选择备份策略 4 编写备份脚本4.1 步骤拆解步骤 1: 选择源文…...
python学习
Python面试题大全 - 50道经典面试题 - 掘金 yoloV5:yolov5: YOLOv5 汉化版,保持官方同步更新 yoloV8使用案例:用YOLOv8一站式解决图像分类、检测、分割…… - 掘金 yoloV8使用案例douyin:https://www.douyin.com/user/self?modal_id7276287878194285…...
【使用redisson完成延迟队列的功能】使用redisson配合线程池完成异步执行功能,延迟队列和不需要延迟的队列
1. 使用redisson完成延迟队列的功能 引入依赖 spring-boot-starter-actuator是Spring Boot提供的一个用于监控和管理应用程序的模块 用于查看应用程序的健康状况、审计信息、指标和其他有用的信息。这些端点可以帮助你监控应用程序的运行状态、性能指标和健康状况。 已经有了…...
Linux 性能分析工具 perf 的使用指南
什么是perf,可以用来干什么 perf 是 Linux 内核的性能分析工具集,它可以用来监控和分析系统和应用程序的性能。perf 提供了一系列功能强大的子命令,可以帮助开发者和系统管理员: 监控 CPU 使用率:识别最消耗 CPU 的代…...
【QT入门】 Qt代码创建布局之水平布局、竖直布局详解
往期回顾: 【QT入门】 Qt实现自定义信号-CSDN博客 【QT入门】 Qt自定义信号后跨线程发送信号-CSDN博客 【QT入门】 Qt内存管理机制详解-CSDN博客 【QT入门】 Qt代码创建布局之水平布局、竖直布局详解 先看两个问题: 1、ui设计器设计界面很方便…...
C 传递数组给函数
如果您想要在函数中传递一个一维数组作为参数,您必须以下面三种方式来声明函数形式参数,这三种声明方式的结果是一样的,因为每种方式都会告诉编译器将要接收一个整型指针。同样地,您也可以传递一个多维数组作为形式参数。 方式 1…...
二次开发Flink-coGroup算子支持迟到数据通过测输出流提取
目录 1.背景 2.coGroup算子源码分析 2.1完整的coGroup算子调用流程 2.2coGroup方法入口 2.3 CoGroupedStreams对象分析 2.4WithWindow内部类分析 2.5CoGroupWindowFunction函数分析 3.修改源码支持获取迟到数据测输出流 3.1复制CoGroupedStreams 3.2新增WithWindow.si…...
【容器源码篇】Set容器(HashSet,LinkedHashSet,TreeSet的特点)
文章目录 ⭐容器继承关系🌹Set容器🗒️HashSet源码解析构造方法public HashSet()public HashSet(Collection<? extends E> c)public HashSet(int initialCapacity, float loadFactor)HashSet(int initialCapacity, float loadFactor, boolean dum…...
网络工程师实验命令(华为数通HCIA)
VRP系统的基本操作 dis version #查看设备版本信息 sys #进入系统视图 system-name R1 #改设备名字为R1进入接口配置IP地址 int g0/0/0 ip address 192.168.1.1 255.255.255.0 #配置接口地址为192.168.1.1/255.255.255.0 ip address 192.168.1.2 24 sub #此…...
AI大模型学习:AI大模型在特定领域的应用
1. 引言 随着人工智能技术的飞速发展,AI大模型已成为推动科技创新的重要力量。从自然语言处理到图像识别,再到复杂决策支持系统,AI大模型在多个领域展现出了前所未有的潜力和应用广度。本文旨在深入探讨AI大模型在特定领域中的应用࿰…...
Channel 结合 Select 使用
在Go语言中,channel和select结合使用是一种强大的并发模式。channel允许在不同的goroutine之间安全地传递消息,而select使得goroutine可以同时等待多个通信操作(channel操作)。 select语句等待多个channel操作中的任意一个完成。…...
LeetCode-1669题:合并两个链表(原创)
【题目描述】 给你两个链表 list1 和 list2 ,它们包含的元素分别为 n 个和 m 个。请你将 list1 中下标从 a 到 b 的全部节点都删除,并将list2 接在被删除节点的位置。下图中蓝色边和节点展示了操作后的结果: 请你返回结果链表的头指针。 【…...
微服务高级篇(三):分布式缓存+Redis集群
文章目录 一、单点Redis的问题及解决方案二、Redis持久化2.1 单机安装Redis2.2 RDB持久化2.3 AOF持久化2.4 RDB和AOF对比 三、Redis主从3.1 搭建Redis主从架构3.1.1 集群结构3.1.2 准备实例和配置3.1.3 启动3.1.4 开启主从关系3.1.5 测试 3.2 数据同步3.2.1 全量同步【建立连接…...
机器学习——元学习
元学习(Meta Learning)是一种机器学习方法,旨在使模型能够学习如何学习。它涉及到在学习过程中自动化地学习和优化学习算法或模型的能力。元学习的目标是使模型能够从有限的训练样本中快速适应新任务或新环境。 在传统的机器学习中ÿ…...
day56 动态规划part13
300. 最长递增子序列 中等 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
协议转换利器,profinet转ethercat网关的两大派系,各有千秋
随着工业以太网的发展,其高效、便捷、协议开放、易于冗余等诸多优点,被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口,具有实时性、开放性,使用TCP/IP和IT标准,符合基于工业以太网的…...
Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合
无论是python,或者java 的大型项目中,都会涉及到 自身平台微服务之间的相互调用,以及和第三发平台的 接口对接,那在python 中是怎么实现的呢? 在 Python Web 开发中,FastAPI 和 Django 是两个重要但定位不…...
leetcode73-矩阵置零
leetcode 73 思路 记录 0 元素的位置:遍历整个矩阵,找出所有值为 0 的元素,并将它们的坐标记录在数组zeroPosition中置零操作:遍历记录的所有 0 元素位置,将每个位置对应的行和列的所有元素置为 0 具体步骤 初始化…...
Linux基础开发工具——vim工具
文章目录 vim工具什么是vimvim的多模式和使用vim的基础模式vim的三种基础模式三种模式的初步了解 常用模式的详细讲解插入模式命令模式模式转化光标的移动文本的编辑 底行模式替换模式视图模式总结 使用vim的小技巧vim的配置(了解) vim工具 本文章仍然是继续讲解Linux系统下的…...
MeanFlow:何凯明新作,单步去噪图像生成新SOTA
1.简介 这篇文章介绍了一种名为MeanFlow的新型生成模型框架,旨在通过单步生成过程高效地将先验分布转换为数据分布。文章的核心创新在于引入了平均速度的概念,这一概念的引入使得模型能够通过单次函数评估完成从先验分布到数据分布的转换,显…...
