-
Notifications
You must be signed in to change notification settings - Fork 1
/
SDTextPlane.swift
181 lines (144 loc) · 7.2 KB
/
SDTextPlane.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
import Foundation
import MetalKit
import SDFont
class SDTextPlane {
static let TextureMargin : CGFloat = 0.001 // margin from the real glyph box to include the spread part
let device : MTLDevice
var dimension : CGSize
var sdHelper : SDFontRuntimeHelper
var scaleForTypeSetting : CGFloat
var vertexBuffer : MTLBuffer?
var numVertices : Int
var indexBuffer : MTLBuffer?
var numIndices : Int
var localTransform : float4x4
var globalTransform : float4x4
var uniformPerInstance : UniformPerInstance
var perInstanceBuffer : MTLBuffer?
var uniformSDFont : UniformSDFont
var sdFontUniformBuffer : MTLBuffer?
var sdFontTexture : MTLTexture?
var animationSequencer : AnimationSequencer?
init(
device : MTLDevice,
dimension : CGSize,
sdHelper : SDFontRuntimeHelper,
scaleForTypeSetting : CGFloat,
uniformSDFont : UniformSDFont
) {
self.device = device
self.dimension = dimension
self.sdHelper = sdHelper
self.scaleForTypeSetting = scaleForTypeSetting
self.numVertices = 0
self.numIndices = 0
self.localTransform = float4x4.identity()
self.globalTransform = float4x4.identity()
self.uniformPerInstance = UniformPerInstance( modelMatrix : self.globalTransform * self.localTransform )
self.uniformSDFont = uniformSDFont
self.perInstanceBuffer = UniformPerInstance.generateMTLBuffer( device : device, instances : [uniformPerInstance] )
self.sdFontUniformBuffer = UniformSDFont.generateMTLBuffer( device : device, v : &self.uniformSDFont )
self.sdFontTexture = sdHelper.texture()
}
func setLocalTransform( translation : SIMD3<Float> ) {
localTransform.columns.3.x = translation.x
localTransform.columns.3.y = translation.y
localTransform.columns.3.z = translation.z
self.uniformPerInstance = UniformPerInstance( modelMatrix : self.globalTransform * self.localTransform )
UniformPerInstance.updateMTLBuffer( buffer : perInstanceBuffer!, instances : [uniformPerInstance] )
}
func setGlobalTransform( transform : float4x4 ) {
self.globalTransform = transform
self.uniformPerInstance = UniformPerInstance( modelMatrix : self.globalTransform * self.localTransform )
UniformPerInstance.updateMTLBuffer( buffer : perInstanceBuffer!, instances : [uniformPerInstance] )
}
func rotate90AroundX() {
localTransform.columns.0 = SIMD4<Float>( 1.0, 0.0, 0.0, 0.0 )
localTransform.columns.1 = SIMD4<Float>( 0.0, 0.0, -1.0, 0.0 )
localTransform.columns.2 = SIMD4<Float>( 0.0, 1.0, 0.0, 0.0 )
self.uniformPerInstance = UniformPerInstance( modelMatrix : self.globalTransform * self.localTransform )
UniformPerInstance.updateMTLBuffer( buffer : perInstanceBuffer!, instances : [uniformPerInstance] )
}
func setAnimation(
temporalPoints : [TimeInterval],
spacialPoints : [SIMD3<Float>],
colors : [SIMD4<Float>]
) {
animationSequencer = AnimationSequencer(
temporalPoints : temporalPoints,
spacialPoints : spacialPoints,
colors : colors
)
}
func startAnimation() {
animationSequencer!.startAnimation()
}
func animationActive()-> Bool {
animationSequencer!.animationActive
}
func step() {
animationSequencer!.step()
let s = animationSequencer!.spacialPointNow
setLocalTransform( translation : s )
uniformSDFont.foregroundColor = animationSequencer!.colorNow
UniformSDFont.updateMTLBuffer( buffer : sdFontUniformBuffer!, v : &uniformSDFont )
}
func setText( textPlain: String, lineAlignment: CTTextAlignment ) {
let rectForTypeSetting = CGRect(
x : -0.5 * dimension.width * scaleForTypeSetting,
y : -0.5 * dimension.height * scaleForTypeSetting,
width : dimension.width * scaleForTypeSetting,
height : dimension.height * scaleForTypeSetting
)
let scaledBounds = sdHelper.typeset( frameRect: rectForTypeSetting, textPlain: textPlain, lineAlignment: lineAlignment )
generateVerticesAndIndices( bounds : scaledBounds )
}
func generateVerticesAndIndices( bounds : [SDFontRuntimeHelper.GlyphBound] )
{
var indexBegin : Int32 = 0
var positions : [ SIMD4<Float> ] = []
var uvs : [ SIMD2<Float> ] = []
var indices : [ Int32 ] = []
for bound in bounds {
var factor : CGFloat
if bound.textureBound.size.width > bound.textureBound.size.height {
factor = bound.frameBound.size.width / bound.textureBound.size.width
}
else {
factor = bound.frameBound.size.height / bound.textureBound.size.height
}
let frameMargin = factor * Self.TextureMargin
let xLeft = Float( ( bound.frameBound.origin.x - frameMargin ) / scaleForTypeSetting )
let xRight = Float( ( bound.frameBound.origin.x + bound.frameBound.size.width + frameMargin ) / scaleForTypeSetting )
let yLower = Float( ( bound.frameBound.origin.y - frameMargin ) / scaleForTypeSetting )
let yUpper = Float( ( bound.frameBound.origin.y + bound.frameBound.size.height + frameMargin ) / scaleForTypeSetting )
positions.append( SIMD4<Float>( xLeft, yLower, 0.0, 1.0 ) )
positions.append( SIMD4<Float>( xRight, yLower, 0.0, 1.0 ) )
positions.append( SIMD4<Float>( xRight, yUpper, 0.0, 1.0 ) )
positions.append( SIMD4<Float>( xLeft, yUpper, 0.0, 1.0 ) )
let uLeft = Float( bound.textureBound.origin.x - Self.TextureMargin )
let uRight = Float( bound.textureBound.origin.x + bound.textureBound.size.width + Self.TextureMargin )
let vLower = Float( bound.textureBound.origin.y - Self.TextureMargin )
let vUpper = Float( bound.textureBound.origin.y + bound.textureBound.size.height + Self.TextureMargin )
uvs.append( SIMD2<Float>( uLeft, vLower ) )
uvs.append( SIMD2<Float>( uRight, vLower ) )
uvs.append( SIMD2<Float>( uRight, vUpper ) )
uvs.append( SIMD2<Float>( uLeft, vUpper ) )
indices.append( indexBegin )
indices.append( indexBegin + 1 )
indices.append( indexBegin + 2 )
indices.append( indexBegin )
indices.append( indexBegin + 2 )
indices.append( indexBegin + 3 )
indexBegin += 4
}
vertexBuffer = VertexInPositionUV.generateMTLBuffer(
device : device,
positions : positions,
uvs : uvs
)
numVertices = positions.count
numIndices = indices.count
indexBuffer = VertexInIndex.generateMTLBuffer( device: device, indices : indices )
}
}