Forked from Matt54/MarchingCubesColorBlobParams.h
Created
September 22, 2025 15:37
-
-
Save SergeiMeza/5ef8648db6d1f8957907b318a050ee0a to your computer and use it in GitHub Desktop.
RealityKit Color-Blending Metaballs (Metal + LowLevelMesh + Marching Cubes)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef edgeTable_h | |
#define edgeTable_h | |
constant int edgeTable[256]={ | |
0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, | |
0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, | |
0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, | |
0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, | |
0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, | |
0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, | |
0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, | |
0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, | |
0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, | |
0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, | |
0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, | |
0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, | |
0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, | |
0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, | |
0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , | |
0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, | |
0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, | |
0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, | |
0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, | |
0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, | |
0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, | |
0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, | |
0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, | |
0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, | |
0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, | |
0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, | |
0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, | |
0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, | |
0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, | |
0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, | |
0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, | |
0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 }; | |
#endif /* edgeTable_h */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef MarchingCubesColorBlobParams_h | |
#define MarchingCubesColorBlobParams_h | |
#include <simd/simd.h> | |
typedef struct { | |
simd_float3 center; | |
float radius; | |
simd_float3 color; | |
float _pad; | |
} ColorSphere; | |
typedef struct { | |
simd_uint3 cells; | |
simd_float3 origin; | |
simd_float3 cellSize; | |
float isoLevel; | |
uint32_t sphereCount; | |
float smoothK; | |
} MarchingCubesColorBlobParams; | |
#endif /* MarchingCubesColorBlobParams_h */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Metal | |
import RealityKit | |
import SwiftUI | |
struct MarchingCubesColorBlobView: View { | |
@State var entity: Entity? | |
@State var mesh: LowLevelMesh? | |
@State var positions: [SIMD3<Float>] = [] | |
@State var targets: [SIMD3<Float>] = [] | |
@State var radii: [Float] = [] | |
@State var colors: [SIMD3<Float>] = [] | |
@State var speeds: [Float] = [] | |
@State var timer: Timer? | |
@State var lastFrameTime = CACurrentMediaTime() | |
@State var sphereCountUI: Int = 24 | |
@State var smoothK: Float = 0.055 | |
@State var targetRadius: Float = 0.0125 | |
@State var radiusVariance: Float = 0.3 | |
@State var speed: Float = 0.25 | |
@State var roughness: Float = 0.5 | |
@State var metallic: Float = 0.0 | |
@State var specular: Float = 0.5 | |
// Grid sizing | |
let volumeRadius: Float = 0.175 | |
var cellsPerAxis: UInt32 = 80 | |
var cells: SIMD3<UInt32> { SIMD3<UInt32>(cellsPerAxis, cellsPerAxis, cellsPerAxis) } | |
var cellSize: SIMD3<Float> { | |
let ratio = volumeRadius / Float(cellsPerAxis) * 2 | |
return SIMD3<Float>(ratio, ratio, ratio) | |
} | |
let device: MTLDevice | |
let commandQueue: MTLCommandQueue | |
let computePipelineState: MTLComputePipelineState | |
let vertexCountBuffer: MTLBuffer | |
let spheresBuffer: MTLBuffer | |
let maxSpheres = 64 | |
struct SphereData { | |
var center: SIMD3<Float> | |
var radius: Float | |
var color: SIMD3<Float> | |
var pad: Float = 0 | |
} | |
enum ShaderGraphParameter: String { | |
case roughness | |
case metallic | |
case specular | |
} | |
init() { | |
let device = MTLCreateSystemDefaultDevice()! | |
self.device = device | |
self.commandQueue = device.makeCommandQueue()! | |
let library = device.makeDefaultLibrary()! | |
let function = library.makeFunction(name: "generateMarchingCubesColorBlobMesh")! | |
self.computePipelineState = try! device.makeComputePipelineState(function: function) | |
self.vertexCountBuffer = device.makeBuffer(length: MemoryLayout<UInt32>.stride, options: .storageModeShared)! | |
self.spheresBuffer = device.makeBuffer(length: maxSpheres * MemoryLayout<SphereData>.stride, options: .storageModeShared)! | |
} | |
var body: some View { | |
VStack(spacing: 40) { | |
RealityView { content in | |
let maxCellCount = Int(cells.x * cells.y * cells.z) | |
let vertexCapacity = 15 * maxCellCount | |
let indexCapacity = vertexCapacity | |
let lowLevelMesh = try! VertexPositionNormalColor.initializeMesh(vertexCapacity: vertexCapacity, | |
indexCapacity: indexCapacity) | |
let meshResource = try! await MeshResource(from: lowLevelMesh) | |
let material = try! await getMaterial() | |
let entity = ModelEntity(mesh: meshResource, materials: [material]) | |
content.add(entity) | |
self.mesh = lowLevelMesh | |
self.entity = entity | |
reseedSpheres(count: sphereCountUI) | |
startTimer() | |
} | |
.onDisappear { stopTimer() } | |
VStack { | |
HStack { | |
Text("Spheres: \(sphereCountUI)") | |
Spacer() | |
Slider(value: Binding(get: { Double(sphereCountUI) }, | |
set: { newVal in | |
sphereCountUI = Int(newVal) | |
reseedSpheres(count: sphereCountUI) | |
}), | |
in: 1...Double(maxSpheres), step: 1) | |
.frame(width: 300) | |
} | |
HStack { | |
Text("Target Radius: \(targetRadius, specifier: "%.4f")") | |
Spacer() | |
Slider(value: Binding(get: { Double(targetRadius) }, | |
set: { newVal in | |
targetRadius = Float(newVal) | |
reseedSpheres(count: sphereCountUI) | |
}), | |
in: 0.005...0.05) | |
.frame(width: 300) | |
} | |
HStack { | |
Text("Radius Variance: \(radiusVariance*100, specifier: "%.1f")%") | |
Spacer() | |
Slider(value: Binding(get: { Double(radiusVariance) }, | |
set: { newVal in | |
radiusVariance = Float(newVal) | |
reseedSpheres(count: sphereCountUI) | |
}), | |
in: 0.0...1.0) | |
.frame(width: 300) | |
} | |
HStack { | |
Text("Smooth K: \(smoothK, specifier: "%.3f")") | |
Spacer() | |
Slider(value: $smoothK, in: 0.0...0.12) | |
.frame(width: 300) | |
} | |
HStack { | |
Text("Speed: \(speed, specifier: "%.2f")") | |
Spacer() | |
Slider(value: $speed, in: 0.0...1.0) | |
.frame(width: 300) | |
} | |
HStack { | |
Text("Roughness: \(roughness, specifier: "%.2f")") | |
Spacer() | |
Slider(value: $roughness, in: 0...1.0) | |
.frame(width: 300) | |
} | |
.onChange(of: roughness) { | |
try? setShaderGraphParameterValue(.roughness, value: roughness) | |
} | |
HStack { | |
Text("Metallic: \(metallic, specifier: "%.2f")") | |
Spacer() | |
Slider(value: $metallic, in: 0...1) | |
.frame(width: 300) | |
} | |
.onChange(of: metallic) { | |
try? setShaderGraphParameterValue(.metallic, value: metallic) | |
} | |
HStack { | |
Text("Specular: \(specular, specifier: "%.2f")") | |
Spacer() | |
Slider(value: $specular, in: 0...1) | |
.frame(width: 300) | |
} | |
.onChange(of: specular) { | |
try? setShaderGraphParameterValue(.specular, value: specular) | |
} | |
} | |
.frame(width: 500) | |
.padding() | |
.glassBackgroundEffect() | |
} | |
} | |
} | |
// MARK: Timer / Animation | |
extension MarchingCubesColorBlobView { | |
func startTimer() { | |
stopTimer() | |
lastFrameTime = CACurrentMediaTime() | |
timer = Timer.scheduledTimer(withTimeInterval: 1.0 / 60.0, repeats: true) { _ in | |
let now = CACurrentMediaTime() | |
let deltaTime = max(0.0, now - lastFrameTime) | |
lastFrameTime = now | |
updateSpheres(deltaTime: Float(deltaTime)) | |
updateMesh() | |
} | |
} | |
func stopTimer() { | |
timer?.invalidate() | |
timer = nil | |
} | |
} | |
// MARK: Sphere Size and Position | |
extension MarchingCubesColorBlobView { | |
private func randomPositionWithPadding() -> SIMD3<Float> { | |
let gridSizeWorldSpace = SIMD3<Float>(Float(cells.x), Float(cells.y), Float(cells.z)) * cellSize | |
let minWorldSpace = -0.5 * gridSizeWorldSpace | |
let maxWorldSpace = minWorldSpace + gridSizeWorldSpace | |
// Add padding to prevent spheres from going too close to edges | |
// smoothK increases size so we increase padding to compensate | |
let padding: Float = volumeRadius * (0.3+smoothK*3) | |
let paddedMin = minWorldSpace + padding | |
let paddedMax = maxWorldSpace - padding | |
return SIMD3<Float>( | |
Float.random(in: paddedMin.x...paddedMax.x), | |
Float.random(in: paddedMin.y...paddedMax.y), | |
Float.random(in: paddedMin.z...paddedMax.z) | |
) | |
} | |
func reseedSpheres(count: Int) { | |
// Calculate min/max radius based on target and variance | |
let varianceAmount = targetRadius * radiusVariance | |
let minR = targetRadius - varianceAmount | |
let maxR = targetRadius + varianceAmount | |
positions = (0..<count).map { _ in randomPositionWithPadding() } | |
targets = (0..<count).map { _ in randomPositionWithPadding() } | |
radii = (0..<count).map { _ in Float.random(in: minR...maxR) } | |
speeds = (0..<count).map { _ in Float.random(in: 0.5...1.5) } | |
colors = (0..<count).map { i in | |
let r: Float = i % 2 == 0 ? 1.0 : 0 | |
let g: Float = i % 2 == 0 ? 1.0 : 0 | |
let b: Float = i % 2 == 0 ? 1.0 : 0 | |
return SIMD3<Float>(r, g, b) | |
} | |
} | |
func updateSpheres(deltaTime: Float) { | |
guard positions.count == sphereCountUI else { return } | |
for sphereIndex in 0..<sphereCountUI { | |
let currentPosition = positions[sphereIndex] | |
let targetPosition = targets[sphereIndex] | |
var direction = targetPosition - currentPosition | |
let distance = simd_length(direction) | |
if distance < 1e-5 { | |
targets[sphereIndex] = randomPositionWithPadding() | |
continue | |
} | |
direction /= distance | |
let movementStep = speed * speeds[sphereIndex] * deltaTime * volumeRadius * 1.5 | |
if movementStep >= distance { | |
positions[sphereIndex] = targetPosition | |
targets[sphereIndex] = randomPositionWithPadding() | |
} else { | |
positions[sphereIndex] = currentPosition + direction * movementStep | |
} | |
} | |
// Write spheres to buffer | |
let sphereDataPointer = spheresBuffer.contents().bindMemory(to: SphereData.self, capacity: maxSpheres) | |
for sphereIndex in 0..<sphereCountUI { | |
sphereDataPointer[sphereIndex] = SphereData(center: positions[sphereIndex], radius: radii[sphereIndex], color: colors[sphereIndex]) | |
} | |
} | |
} | |
// MARK: Mesh | |
extension MarchingCubesColorBlobView { | |
func updateMesh() { | |
guard let mesh = mesh, | |
let commandBuffer = commandQueue.makeCommandBuffer(), | |
let computeEncoder = commandBuffer.makeComputeCommandEncoder() | |
else { return } | |
let gridSizeWorldSpace = SIMD3<Float>(Float(cells.x), Float(cells.y), Float(cells.z)) * cellSize | |
let gridMinCornerWorldSpace = -0.5 * gridSizeWorldSpace | |
let gridMaxCornerWorldSpace = gridMinCornerWorldSpace + gridSizeWorldSpace | |
var params = MarchingCubesColorBlobParams( | |
cells: cells, | |
origin: gridMinCornerWorldSpace, | |
cellSize: cellSize, | |
isoLevel: 0.0, | |
sphereCount: UInt32(sphereCountUI), | |
smoothK: smoothK | |
) | |
// Reset vertex counter | |
vertexCountBuffer.contents().bindMemory(to: UInt32.self, capacity: 1).pointee = 0 | |
// Acquire GPU-backed mesh buffers | |
let vertexBuffer = mesh.replace(bufferIndex: 0, using: commandBuffer) | |
let indexBuffer = mesh.replaceIndices(using: commandBuffer) | |
// Encode compute | |
computeEncoder.setComputePipelineState(computePipelineState) | |
computeEncoder.setBuffer(vertexBuffer, offset: 0, index: 0) | |
computeEncoder.setBuffer(indexBuffer, offset: 0, index: 1) | |
computeEncoder.setBuffer(vertexCountBuffer, offset: 0, index: 2) | |
computeEncoder.setBytes(¶ms, length: MemoryLayout<MarchingCubesColorBlobParams>.stride, index: 3) | |
computeEncoder.setBuffer(spheresBuffer, offset: 0, index: 4) | |
let threadsPerThreadgroup = MTLSize(width: 8, height: 8, depth: 4) | |
let threadgroups = MTLSize( | |
width: (Int(cells.x) + threadsPerThreadgroup.width - 1) / threadsPerThreadgroup.width, | |
height: (Int(cells.y) + threadsPerThreadgroup.height - 1) / threadsPerThreadgroup.height, | |
depth: (Int(cells.z) + threadsPerThreadgroup.depth - 1) / threadsPerThreadgroup.depth | |
) | |
computeEncoder.dispatchThreadgroups(threadgroups, threadsPerThreadgroup: threadsPerThreadgroup) | |
computeEncoder.endEncoding() | |
commandBuffer.commit() | |
commandBuffer.waitUntilCompleted() | |
let vertexCount = Int(vertexCountBuffer.contents().bindMemory(to: UInt32.self, capacity: 1).pointee) | |
mesh.parts.replaceAll([ | |
LowLevelMesh.Part(indexCount: vertexCount, | |
topology: .triangle, | |
bounds: BoundingBox(min: gridMinCornerWorldSpace, max: gridMaxCornerWorldSpace)) | |
]) | |
} | |
} | |
// MARK: Material | |
extension MarchingCubesColorBlobView { | |
func getMaterial() async throws -> ShaderGraphMaterial { | |
let baseURL = URL(string: "https://matt54.github.io/Resources/")! | |
let fullURL = baseURL.appendingPathComponent("GeometryColorPBR.usda") | |
let data = try Data(contentsOf: fullURL) | |
let materialPath: String = "/Root/GeometryColorPBRMaterial" | |
var material = try await ShaderGraphMaterial(named: materialPath, from: data) | |
try! material.setParameter(name: ShaderGraphParameter.roughness.rawValue, value: .float(roughness)) | |
try! material.setParameter(name: ShaderGraphParameter.metallic.rawValue, value: .float(metallic)) | |
try! material.setParameter(name: ShaderGraphParameter.specular.rawValue, value: .float(specular)) | |
return material | |
} | |
func setShaderGraphParameterValue(_ parameter: ShaderGraphParameter, value: Float) throws { | |
guard let entity = entity else { return } | |
guard let modelComponent = entity.components[ModelComponent.self] else { return } | |
guard var material = modelComponent.materials.first as? ShaderGraphMaterial else { return } | |
try material.setParameter(name: parameter.rawValue, value: .float(value)) | |
entity.components[ModelComponent.self]?.materials = [material] | |
} | |
} | |
#Preview { MarchingCubesColorBlobView() } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef triTable_h | |
#define triTable_h | |
constant int triTable[256][16] = | |
{{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1}, | |
{3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1}, | |
{3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1}, | |
{3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, | |
{2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1}, | |
{8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}, | |
{4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1}, | |
{3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1}, | |
{4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1}, | |
{4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}, | |
{5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1}, | |
{2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1}, | |
{9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}, | |
{2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1}, | |
{10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1}, | |
{4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1}, | |
{5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1}, | |
{5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1}, | |
{10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1}, | |
{8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1}, | |
{2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1}, | |
{7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1}, | |
{2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1}, | |
{11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1}, | |
{5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1}, | |
{11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1}, | |
{11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1}, | |
{5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1}, | |
{2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1}, | |
{5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1}, | |
{6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1}, | |
{3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1}, | |
{6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1}, | |
{5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, | |
{10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1}, | |
{6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1}, | |
{8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1}, | |
{7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1}, | |
{3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1}, | |
{5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1}, | |
{0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1}, | |
{9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1}, | |
{8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1}, | |
{5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1}, | |
{0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1}, | |
{6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1}, | |
{10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1}, | |
{10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1}, | |
{8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1}, | |
{1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1}, | |
{3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1}, | |
{0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1}, | |
{10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1}, | |
{3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1}, | |
{6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1}, | |
{9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1}, | |
{8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1}, | |
{3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1}, | |
{6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1}, | |
{10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1}, | |
{10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1}, | |
{2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1}, | |
{7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1}, | |
{7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1}, | |
{2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1}, | |
{1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1}, | |
{11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1}, | |
{8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1}, | |
{0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1}, | |
{7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1}, | |
{10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1}, | |
{2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1}, | |
{6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1}, | |
{7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1}, | |
{2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1}, | |
{10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1}, | |
{10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1}, | |
{0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1}, | |
{7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1}, | |
{6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1}, | |
{8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1}, | |
{6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1}, | |
{4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1}, | |
{10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1}, | |
{8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1}, | |
{1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1}, | |
{8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1}, | |
{10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1}, | |
{4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1}, | |
{10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1}, | |
{5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}, | |
{11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1}, | |
{9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}, | |
{6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1}, | |
{7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1}, | |
{3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1}, | |
{7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1}, | |
{3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1}, | |
{6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1}, | |
{9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1}, | |
{1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1}, | |
{4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1}, | |
{7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1}, | |
{6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1}, | |
{3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1}, | |
{0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1}, | |
{6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1}, | |
{0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1}, | |
{11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1}, | |
{6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1}, | |
{5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1}, | |
{9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1}, | |
{1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1}, | |
{10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1}, | |
{0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1}, | |
{5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1}, | |
{10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1}, | |
{11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1}, | |
{9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1}, | |
{7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1}, | |
{2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1}, | |
{8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1}, | |
{9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1}, | |
{9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1}, | |
{1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1}, | |
{5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1}, | |
{0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1}, | |
{10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1}, | |
{2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1}, | |
{0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1}, | |
{0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1}, | |
{9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1}, | |
{5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1}, | |
{3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1}, | |
{5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1}, | |
{8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1}, | |
{9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1}, | |
{1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1}, | |
{3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1}, | |
{4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1}, | |
{9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1}, | |
{11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1}, | |
{11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1}, | |
{2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1}, | |
{9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1}, | |
{3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1}, | |
{1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1}, | |
{4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1}, | |
{4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1}, | |
{3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1}, | |
{3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1}, | |
{0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1}, | |
{9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1}, | |
{1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, | |
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}; | |
#endif /* triTable_h */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import RealityKit | |
extension VertexPositionNormalColor { | |
static var vertexAttributes: [LowLevelMesh.Attribute] = [ | |
.init(semantic: .position, format: .float3, offset: MemoryLayout<Self>.offset(of: \.position)!), | |
.init(semantic: .normal, format: .float3, offset: MemoryLayout<Self>.offset(of: \.normal)!), | |
.init(semantic: .color, format: .float3, offset: MemoryLayout<Self>.offset(of: \.color)!) | |
] | |
static var vertexLayouts: [LowLevelMesh.Layout] = [ | |
.init(bufferIndex: 0, bufferStride: MemoryLayout<Self>.stride) | |
] | |
static var descriptor: LowLevelMesh.Descriptor { | |
var desc = LowLevelMesh.Descriptor() | |
desc.vertexAttributes = VertexPositionNormalColor.vertexAttributes | |
desc.vertexLayouts = VertexPositionNormalColor.vertexLayouts | |
desc.indexType = .uint32 | |
return desc | |
} | |
@MainActor static func initializeMesh(vertexCapacity: Int, | |
indexCapacity: Int) throws -> LowLevelMesh { | |
var desc = VertexPositionNormalColor.descriptor | |
desc.vertexCapacity = vertexCapacity | |
desc.indexCapacity = indexCapacity | |
return try LowLevelMesh(descriptor: desc) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <simd/simd.h> | |
#ifndef VertexPositionNormalColor_h | |
#define VertexPositionNormalColor_h | |
struct VertexPositionNormalColor { | |
simd_float3 position; | |
simd_float3 normal; | |
simd_float3 color; | |
}; | |
#endif /* VertexPositionNormalColor_h */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment