forked from Experience-Monks/three-bmfont-text
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
194 lines (160 loc) · 4.67 KB
/
index.js
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
182
183
184
185
186
187
188
189
190
191
192
193
194
var createLayout = require('layout-bmfont-text')
var inherits = require('inherits')
var createIndices = require('quad-indices')
var utils = require('./lib/utils')
var Base = THREE.BufferGeometry
module.exports = function(opt) {
return new TextMesh(opt)
}
function TextMesh(opt) {
Base.call(this)
var multipage = opt && opt.multipage
this.layout = null
this._positions = new THREE.BufferAttribute(null, 2)
this._uvs = new THREE.BufferAttribute(null, 2)
if (multipage)
this._pages = new THREE.BufferAttribute(null, 1)
this._indices = new THREE.BufferAttribute(null, 1)
if (opt)
this.update(opt)
this.addAttribute('position', this._positions)
this.addAttribute('uv', this._uvs)
if (multipage)
this.addAttribute('page', this._pages)
this.addAttribute('index', this._indices)
}
inherits(TextMesh, Base)
TextMesh.prototype.update = function(opt) {
opt = opt||{}
this.layout = createLayout(opt)
//don't allow a deferred creation of multipage
//since it requires different buffer layout
if (opt.multipage && !this._pages) {
throw new Error('must specify multipage: true in constructor')
}
var font = opt.font
//determine texture size from font file
var texWidth = font.common.scaleW
var texHeight = font.common.scaleH
//get visible glyphs
var glyphs = this.layout.glyphs.filter(function(glyph) {
var bitmap = glyph.data
return bitmap.width * bitmap.height > 0
})
//get vec2 quad positions
var positions = getQuadPositions(glyphs, this.layout)
//get vec2 texcoords
var flipY = opt.flipY !== false
var uvs = getQuadUVs(glyphs, texWidth, texHeight, flipY)
if (opt.multipage) {
var pages = getQuadPages(glyphs)
this._pages.array = pages
this._pages.needsUpdate = true
}
//get indices
var quadCount = glyphs.length
var indices = createIndices({ clockwise: true, count: quadCount })
this._uvs.array = uvs
this._uvs.needsUpdate = true
this._indices.array = indices
this._indices.needsUpdate = true
this._positions.array = positions
this._positions.needsUpdate = true
}
TextMesh.prototype.computeBoundingSphere = function() {
if (this.boundingSphere === null)
this.boundingSphere = new THREE.Sphere()
var positions = this.attributes.position.array
var itemSize = this.attributes.position.itemSize
if (!positions || !itemSize || positions.length < 2) {
this.boundingSphere.radius = 0
this.boundingSphere.center.set(0, 0, 0)
return
}
utils.computeSphere(positions, this.boundingSphere)
if (isNaN(this.boundingSphere.radius))
console.error('THREE.BufferGeometry.computeBoundingSphere(): '
+ 'Computed radius is NaN. The '
+ '"position" attribute is likely to have NaN values.')
}
TextMesh.prototype.computeBoundingBox = function() {
if (this.boundingBox === null)
this.boundingBox = new THREE.Box3()
var bbox = this.boundingBox
var positions = this.attributes.position.array
var itemSize = this.attributes.position.itemSize
if (!positions || !itemSize || positions.length < 2) {
bbox.makeEmpty()
return
}
utils.computeBox(positions, bbox)
}
function getQuadPages(glyphs) {
var pages = new Float32Array(glyphs.length * 4 * 1)
var i = 0
glyphs.forEach(function(glyph) {
var id = glyph.data.page || 0
pages[i++] = id
pages[i++] = id
pages[i++] = id
pages[i++] = id
})
return pages
}
function getQuadUVs(glyphs, texWidth, texHeight, flipY) {
var uvs = new Float32Array(glyphs.length * 4 * 2)
var i = 0
glyphs.forEach(function(glyph) {
var bitmap = glyph.data
var bw = (bitmap.x+bitmap.width)
var bh = (bitmap.y+bitmap.height)
//top left position
var u0 = bitmap.x / texWidth
var v1 = bitmap.y / texHeight
var u1 = bw / texWidth
var v0 = bh / texHeight
if (flipY) {
v1 = (texHeight-bitmap.y) / texHeight
v0 = (texHeight-bh) / texHeight
}
//BL
uvs[i++] = u0
uvs[i++] = v1
//TL
uvs[i++] = u0
uvs[i++] = v0
//TR
uvs[i++] = u1
uvs[i++] = v0
//BR
uvs[i++] = u1
uvs[i++] = v1
})
return uvs
}
function getQuadPositions(glyphs, layout) {
var positions = new Float32Array(glyphs.length * 4 * 2)
var i = 0
glyphs.forEach(function(glyph) {
var bitmap = glyph.data
//bottom left position
var x = glyph.position[0] + bitmap.xoffset
var y = glyph.position[1] + bitmap.yoffset
//quad size
var w = bitmap.width
var h = bitmap.height
//BL
positions[i++] = x
positions[i++] = y
//TL
positions[i++] = x
positions[i++] = y + h
//TR
positions[i++] = x + w
positions[i++] = y + h
//BR
positions[i++] = x + w
positions[i++] = y
})
return positions
}