Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
nicklockwood committed Nov 26, 2023
1 parent 2a77698 commit 442ed49
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 54 deletions.
64 changes: 11 additions & 53 deletions Sources/Euclid+RealityKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,21 @@ private func defaultMaterialLookup(_ material: Polygon.Material?) -> RealityKit.

@available(macOS 12.0, iOS 15.0, *)
public extension MeshDescriptor {
private typealias SIMDVertexData = (
positions: [simd_float3],
normals: [simd_float3],
texcoords: [simd_float2]?,
indices: [UInt32],
materialIndices: [UInt32]
)

/// Creates a mesh descriptor from a ``Mesh`` using triangles.
/// - Parameters:
/// - mesh: The mesh to convert into a RealityKit mesh descriptor.
init(triangles mesh: Mesh) {
self.init()
var counts: [UInt8]?
let data = mesh.getVertexData(maxSides: 3, counts: &counts)
let data: SIMDVertexData = mesh.getVertexData(maxSides: 3, counts: &counts)
self.positions = .init(data.positions)
self.normals = .init(data.normals)
self.textureCoordinates = data.texcoords.map(MeshBuffers.TextureCoordinates.init)
Expand All @@ -105,7 +113,7 @@ public extension MeshDescriptor {
init(polygons mesh: Mesh) {
self.init()
var counts: [UInt8]? = []
let data = mesh.getVertexData(maxSides: 255, counts: &counts)
let data: SIMDVertexData = mesh.getVertexData(maxSides: 255, counts: &counts)
self.positions = .init(data.positions)
self.normals = .init(data.normals)
self.textureCoordinates = data.texcoords.map(MeshBuffers.TextureCoordinates.init)
Expand All @@ -121,7 +129,7 @@ public extension MeshDescriptor {
init(quads mesh: Mesh) {
self.init()
var counts: [UInt8]? = []
let data = mesh.getVertexData(maxSides: 4, counts: &counts)
let data: SIMDVertexData = mesh.getVertexData(maxSides: 4, counts: &counts)
self.positions = .init(data.positions)
self.normals = .init(data.normals)
self.textureCoordinates = data.texcoords.map(MeshBuffers.TextureCoordinates.init)
Expand Down Expand Up @@ -214,56 +222,6 @@ private extension Mesh {
let materialLookup = materialLookup ?? defaultMaterialLookup
return materials.map { materialLookup($0) ?? SimpleMaterial() }
}

func getVertexData(maxSides: UInt8, counts: inout [UInt8]?) -> (
positions: [SIMD3<Float>],
normals: [SIMD3<Float>],
texcoords: [SIMD2<Float>]?,
indices: [UInt32],
materialIndices: [UInt32]
) {
var positions: [SIMD3<Float>] = []
var normals: [SIMD3<Float>] = [] // looks bad with default normals
var texcoords: [SIMD2<Float>]? = hasTexcoords ? [] : nil
var indices = [UInt32]()
var materialIndices = [UInt32]()
var indicesByVertex = [Vertex: UInt32]()
let polygonsByMaterial = self.polygonsByMaterial
let perFaceMaterials = materials.count > 1
for (materialIndex, material) in materials.enumerated() {
let polygons = polygonsByMaterial[material] ?? []
for polygon in polygons.tessellate(maxSides: Int(maxSides)) {
counts?.append(UInt8(polygon.vertices.count))
for var vertex in polygon.vertices {
vertex.color = .white // Note: vertex colors are not supported
if let index = indicesByVertex[vertex] {
indices.append(index)
continue
}
let index = UInt32(indicesByVertex.count)
indicesByVertex[vertex] = index
indices.append(index)
positions.append(.init(vertex.position))
normals.append(.init(vertex.normal))
if texcoords != nil {
var texcoord = vertex.texcoord
texcoord.y = 1 - texcoord.y
texcoords?.append(.init(texcoord))
}
}
if perFaceMaterials {
materialIndices.append(UInt32(materialIndex))
}
}
}
return (
positions: positions,
normals: normals,
texcoords: texcoords,
indices: indices,
materialIndices: materialIndices
)
}
}

#endif
9 changes: 9 additions & 0 deletions Sources/Euclid+SceneKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,15 @@ extension SCNGeometrySource {
}

public extension SCNGeometry {
private typealias SCNVertexData = (
positions: [SCNVector3],
normals: [SCNVector3],
texcoords: [CGPoint]?,
colors: [SCNVector4]?,
indices: [UInt32],
materialIndices: [UInt32]
)

/// A closure that maps a Euclid material to a SceneKit material.
/// - Parameter m: A Euclid material to convert, or `nil` for the default material.
/// - Returns: An `SCNMaterial` used by SceneKit.
Expand Down
57 changes: 57 additions & 0 deletions Sources/Mesh.swift
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,63 @@ extension Mesh {
func getBSP(_ isCancelled: CancellationHandler) -> BSP {
storage.getBSP(isCancelled)
}

func getVertexData<
Position: XYZRepresentable,
Normal: XYZRepresentable,
Texcoord: XYZRepresentable
>(maxSides: UInt8, counts: inout [UInt8]?) -> (
positions: [Position],
normals: [Normal],
texcoords: [Texcoord],
indices: [UInt32],
materialIndices: [UInt32]
) {
var positions: [Position] = []
var normals: [Normal] = []
var texcoords: [Texcoord] = []
var indices = [UInt32]()
var materialIndices = [UInt32]()
let hasTexcoords = self.hasTexcoords
var indicesByVertex = [Vertex: UInt32]()
let polygonsByMaterial = self.polygonsByMaterial
let perFaceMaterials = materials.count > 1
for (materialIndex, material) in materials.enumerated() {
let polygons = polygonsByMaterial[material] ?? []
for polygon in polygons {
for polygon in polygon.tessellate(maxSides: Int(maxSides)) {
counts?.append(UInt8(polygon.vertices.count))
for vertex in polygon.vertices {
if let index = indicesByVertex[vertex] {
indices.append(index)
continue
}
let index = UInt32(indicesByVertex.count)
indicesByVertex[vertex] = index
indices.append(index)
positions.append(.init(vertex.position))
normals.append(.init(vertex.normal))
if hasTexcoords {
var texcoord = vertex.texcoord
texcoord.y = 1 - texcoord.y
texcoords.append(.init(texcoord))
}
// Note: vertex colors are not supported
}
if perFaceMaterials {
materialIndices.append(UInt32(materialIndex))
}
}
}
}
return (
positions: positions,
normals: normals,
texcoords: texcoords,
indices: indices,
materialIndices: materialIndices
)
}
}

private extension Mesh {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Polygon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1164,7 +1164,7 @@ struct CodableMaterial: Codable {
self.value = color
} else if let data = try container.decodeIfPresent(Data.self, forKey: .nscoded) {
guard let value = try NSKeyedUnarchiver.unarchivedObject(
ofClasses: Polygon.codableClasses, from: data
ofClasses: NSSet(array: Polygon.codableClasses) as! Set<AnyHashable>, from: data
) as? Polygon.Material else {
throw DecodingError.dataCorruptedError(
forKey: .nscoded,
Expand Down

0 comments on commit 442ed49

Please sign in to comment.