Skip to content

Commit 0dd669a

Browse files
committed
Improve caching for repeated path fill/extrude (e.g. text)
1 parent 16847b4 commit 0dd669a

File tree

3 files changed

+16
-17
lines changed

3 files changed

+16
-17
lines changed

ShapeScript/Geometry.swift

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,12 @@ public final class Geometry: Hashable {
159159
case (_, 0):
160160
type = .extrude([], .default)
161161
children = paths.map { path in
162-
let (path, material) = path.vertexColorsToMaterial(material: material)
162+
let (temp, material) = path.vertexColorsToMaterial(material: material)
163+
let (path, offset) = temp.withNormalizedPosition()
163164
return Geometry(
164165
type: .extrude([path], options),
165166
name: nil,
166-
transform: .identity,
167+
transform: .translation(offset),
167168
material: material,
168169
smoothing: smoothing,
169170
children: [],
@@ -177,13 +178,14 @@ public final class Geometry: Hashable {
177178
type = .extrude([], .default)
178179
children = paths.flatMap { path in
179180
options.along.map { along in
181+
let (along, offset) = along.withNormalizedPosition()
180182
let (pair, material) = [path, along].vertexColorsToMaterial(material: material)
181183
var options = options
182184
options.along = [pair[1]]
183185
return Geometry(
184186
type: .extrude([pair[0]], options),
185187
name: nil,
186-
transform: .identity,
188+
transform: .translation(offset),
187189
material: material,
188190
smoothing: smoothing,
189191
children: [],
@@ -205,6 +207,7 @@ public final class Geometry: Hashable {
205207
// separate child geometry so they can be renderered individually
206208
type = .lathe([], segments: 0)
207209
children = paths.map { path in
210+
// TODO: normalize path y-position for better caching
208211
let (path, material) = path.vertexColorsToMaterial(material: material)
209212
return Geometry(
210213
type: .lathe([path], segments: segments),
@@ -230,11 +233,12 @@ public final class Geometry: Hashable {
230233
// separate child geometry so they can be renderered individually
231234
type = .fill([])
232235
children = paths.map { path in
233-
let (path, material) = path.vertexColorsToMaterial(material: material)
236+
let (temp, material) = path.vertexColorsToMaterial(material: material)
237+
let (path, offset) = temp.withNormalizedPosition()
234238
return Geometry(
235239
type: .fill([path]),
236240
name: nil,
237-
transform: .identity,
241+
transform: .translation(offset),
238242
material: material,
239243
smoothing: smoothing,
240244
children: [],
@@ -244,6 +248,7 @@ public final class Geometry: Hashable {
244248
material = children.first?.material ?? .default
245249
}
246250
case var .loft(paths):
251+
// TODO: normalize all paths by their collective offset for better caching
247252
(paths, material) = paths.vertexColorsToMaterial(material: material)
248253
type = .loft(paths)
249254
case var .path(path):

ShapeScript/StandardLibrary.swift

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -183,29 +183,23 @@ extension Symbols {
183183
} ?? .default
184184
if let along = context.value(for: "along")?.tupleValue as? [Path] {
185185
// shapes follow a common path
186-
// TODO: modify this to reuse meshes where possible
187186
return .mesh(Geometry(type: .extrude(context.paths, .init(
188-
along: along.map {
189-
$0.withDetail(context.detail, twist: twist)
190-
},
187+
along: along.map { $0.withDetail(context.detail, twist: twist) },
191188
twist: twist,
192189
align: align
193190
)), in: context))
194191
}
195192
if twist == .zero {
196193
// Fast path - can reuse meshes (good for text)
197-
// TODO: modify to return separate meshes rather than union
198194
return .mesh(Geometry(
199195
type: .extrude(context.paths, .default),
200196
in: context
201197
))
202198
}
203199
// Slow path, each calculated separately, no reuse
204-
// TODO: modify this to reuse meshes where possible
205200
return .tuple(context.paths.map {
206201
let vector = $0.faceNormal / 2
207-
let along = Path.line(-vector, vector)
208-
.withDetail(context.detail, twist: twist)
202+
let along = Path.line(-vector, vector).withDetail(context.detail, twist: twist)
209203
return .mesh(Geometry(type: .extrude([$0], .init(
210204
along: [along],
211205
twist: twist,

ShapeScriptTests/GeometryTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,8 @@ final class GeometryTests: XCTestCase {
220220
"""), delegate: nil, cache: cache)
221221
_ = scene.build { true }
222222
#if canImport(CoreText)
223-
// TODO: Ideally cache should have only 8 entries as the 'o' and 'l' are repeated
224-
XCTAssertEqual(cache.count, 11)
223+
// Cache should have only 8 entries as the 'o' and 'l' are repeated
224+
XCTAssertEqual(cache.count, 8)
225225
let meshes = scene.children.compactMap(\.mesh)
226226
XCTAssertEqual(meshes.count, 1)
227227
#endif
@@ -234,8 +234,8 @@ final class GeometryTests: XCTestCase {
234234
"""), delegate: nil, cache: cache)
235235
_ = scene.build { true }
236236
#if canImport(CoreText)
237-
// TODO: Ideally cache should have only 8 entries as the 'o' and 'l' are repeated
238-
XCTAssertEqual(cache.count, 11)
237+
// Cache should have only 8 entries as the 'o' and 'l' are repeated
238+
XCTAssertEqual(cache.count, 8)
239239
let meshes = scene.children.compactMap(\.mesh)
240240
XCTAssertEqual(meshes.count, 1)
241241
#endif

0 commit comments

Comments
 (0)