【iOS ARKit】3D文字

news/2024/7/20 23:06:34 标签: ios, AR

   首先,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 Combine

struct 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 = arView
        
        let config = ARWorldTrackingConfiguration()
        config.planeDetection = .horizontal
        context.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文字的方法达到更方便使用的目的。


http://www.niftyadmin.cn/n/5449640.html

相关文章

Redis相关操作高阶篇--集群搭建

Redis相关操作大全一篇全搞定-CSDN博客 Redis集群 是一个由多个主从节点群组成的分布式服务器群,它具有复制、高可用和分片特性。Redis集群不需要seninel哨兵也能完成节点移除和故障转移的功能。需要将每个节点 设置成集群模式,这种集群模式没有中心节…

基于modbus TCP实现EPICS与西门子S7 1200系列1215C PLC的通信

PLC介绍 西门子系列PLC在国内的市场占比第一,1200系列中小型PLC,因其众多的产品序列、强大的通讯功能和丰富扩展模块,被使用在工业生产、自动化生产线、智能制造、机器人等各行各业。根据CPU的供电电源的型号和数字量输出的类型,…

中国象棋C++

题目描述 在中国象棋中正所谓新手玩车,熟手玩炮,老手玩马,由此可见象棋中炮的地位还是比较高的。 给定一个nm的棋盘,全部摆满炮,我们视所有炮都不属于同一阵营,他们之间可以相互攻击但不能不进行攻击直接移…

【Unity】UI九宫格

什么是九宫格? 顾名思义,九宫格就是指UI切成9个格子,9个格子可以任意拉伸。 1、3、7、9不拉伸。 2、8水平拉伸。 4、6垂直拉伸。 5既可以水平也可以垂直拉伸。 怎么切九宫格? 选中图片,改成Sprite模式,点…

摩洛哥公司注册

在摩洛哥注册公司需要遵循一定的程序和法规。以下是一般情况下在摩洛哥注册公司的步骤: 选择公司类型:在摩洛哥可以注册有限责任公司(Socit Responsabilit Limite,简称SARL)或股份有限公司(Socit Anonyme…

基于react native的自定义轮播图

基于react native的自定义轮播图 效果示例图示例代码 效果示例图 示例代码 import React, {useEffect, useRef, useState} from react; import {Animated,PanResponder,StyleSheet,Text,View,Dimensions, } from react-native; import {pxToPd} from ../../common/js/device;c…

力扣热门算法题 97. 交错字符串,100. 相同的树,101. 对称二叉树

97. 交错字符串,100. 相同的树,101. 对称二叉树,每题做详细思路梳理,配套Python&Java双语代码, 2024.03.245可通过leetcode所有测试用例。 目录 97. 交错字符串 解题思路 完整代码 Python Java 100. 相同的…

Linux系统安装openGauss结合内网穿透实现公网访问本地数据库管理系统——“cpolar内网穿透”

文章目录 前言1. Linux 安装 openGauss2. Linux 安装cpolar3. 创建openGauss主节点端口号公网地址4. 远程连接openGauss5. 固定连接TCP公网地址6. 固定地址连接测试 前言 openGauss是一款开源关系型数据库管理系统,采用木兰宽松许可证v2发行。openGauss内核深度融合…