Created
August 19, 2025 23:21
-
-
Save Matt54/1a5066c4434e11686df1e7d48a800945 to your computer and use it in GitHub Desktop.
Revisions
-
Matt54 created this gist
Aug 19, 2025 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,20 @@ #ifndef MarchingCubesBlobParams_h #define MarchingCubesBlobParams_h #include <simd/simd.h> typedef struct { simd_float3 center; float radius; } Sphere; typedef struct { simd_uint3 cells; simd_float3 origin; simd_float3 cellSize; float isoLevel; uint32_t sphereCount; float smoothK; } MarchingCubesBlobParams; #endif /* MarchingCubesBlobParams_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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,388 @@ import Metal import RealityKit import SwiftUI struct MarchingCubesBlobView: 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 speeds: [Float] = [] @State var smoothK: Float = 0.06 @State var speed: Float = 0.25 @State var sphereCountUI: Int = 24 @State var targetRadius: Float = 0.0125 @State var radiusVariance: Float = 0.125 @State var radianceRoughness: Float = 0.12 @State var materialRoughness: Float = 0.33 @State var eta: Float = 0.2 @State var specular: Float = 0.12 @State var timer: Timer? @State var lastFrameTime = CACurrentMediaTime() // Grid sizing (similar pattern to single-shape example) 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) } // Spheres let maxSpheres = 64 struct SphereData { var center: SIMD3<Float> var radius: Float } // Metal let device: MTLDevice let commandQueue: MTLCommandQueue let computePipelineState: MTLComputePipelineState let vertexCountBuffer: MTLBuffer let spheresBuffer: MTLBuffer enum ShaderGraphParameter: String { case radianceRoughness case materialRoughness case eta case specular } init() { let device = MTLCreateSystemDefaultDevice()! self.device = device self.commandQueue = device.makeCommandQueue()! let library = device.makeDefaultLibrary()! let function = library.makeFunction(name: "generateMarchingCubesBlobMesh")! 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! VertexPositionNormal.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 await removeDefaultIBL() 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("Radiance Rough: \(radianceRoughness, specifier: "%.2f")") Spacer() Slider(value: $radianceRoughness, in: 0...0.4) .frame(width: 300) } .onChange(of: radianceRoughness) { try? setShaderGraphParameterValue(.radianceRoughness, value: radianceRoughness) } HStack { Text("Material Rough: \(materialRoughness, specifier: "%.2f")") Spacer() Slider(value: $materialRoughness, in: 0...0.4) .frame(width: 300) } .onChange(of: materialRoughness) { try? setShaderGraphParameterValue(.materialRoughness, value: materialRoughness) } HStack { Text("ETA: \(eta, specifier: "%.2f")") Spacer() Slider(value: $eta, in: 0...1) .frame(width: 300) } .onChange(of: eta) { try? setShaderGraphParameterValue(.eta, value: eta) } 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 MarchingCubesBlobView { 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 MarchingCubesBlobView { 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) } } 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]) } } } // MARK: Mesh extension MarchingCubesBlobView { 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 = MarchingCubesBlobParams( 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<MarchingCubesBlobParams>.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 // See: https://developer.apple.com/documentation/visionos/implementing-adjustable-material-in-visionos extension MarchingCubesBlobView { func getMaterial() async throws -> ShaderGraphMaterial { let baseURL = URL(string: "https://matt54.github.io/Resources/")! let fullURL = baseURL.appendingPathComponent("GlassScene.usda") let data = try Data(contentsOf: fullURL) let materialPath: String = "/Root/GlassMaterial" var material = try await ShaderGraphMaterial(named: materialPath, from: data) try! material.setParameter(name: ShaderGraphParameter.radianceRoughness.rawValue, value: .float(radianceRoughness)) try! material.setParameter(name: ShaderGraphParameter.materialRoughness.rawValue, value: .float(materialRoughness)) try! material.setParameter(name: ShaderGraphParameter.eta.rawValue, value: .float(eta)) 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] } } // MARK: Environment Lighting / IBL extension MarchingCubesBlobView { func removeDefaultIBL() async { guard let entity else { return } let cgImage = createSimpleIBLTexture(size: CGSize(width: 256, height: 128), color: CGColor(gray: 0, alpha: 0))! let greyscaleEnvironmentResource = try! await EnvironmentResource(equirectangular: cgImage) let source: ImageBasedLightComponent.Source = .single(greyscaleEnvironmentResource) let iblComponent = ImageBasedLightComponent( source: source, intensityExponent: 1 ) entity.components[ImageBasedLightComponent.self] = iblComponent entity.components.set(ImageBasedLightReceiverComponent(imageBasedLight: entity)) } func createSimpleIBLTexture(size: CGSize, color: CGColor) -> CGImage? { let colorSpace = CGColorSpaceCreateDeviceRGB() let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue) guard let context = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo.rawValue) else { return nil } context.setFillColor(color) context.fill(CGRect(origin: .zero, size: size)) return context.makeImage() } } #Preview { MarchingCubesBlobView() } 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,29 @@ import Foundation import RealityKit extension VertexPositionNormal { 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)!) ] static var vertexLayouts: [LowLevelMesh.Layout] = [ .init(bufferIndex: 0, bufferStride: MemoryLayout<Self>.stride) ] static var descriptor: LowLevelMesh.Descriptor { var desc = LowLevelMesh.Descriptor() desc.vertexAttributes = VertexPositionNormal.vertexAttributes desc.vertexLayouts = VertexPositionNormal.vertexLayouts desc.indexType = .uint32 return desc } @MainActor static func initializeMesh(vertexCapacity: Int, indexCapacity: Int) throws -> LowLevelMesh { var desc = VertexPositionNormal.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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,11 @@ #include <simd/simd.h> #ifndef VertexPositionNormal_h #define VertexPositionNormal_h struct VertexPositionNormal { simd_float3 position; simd_float3 normal; }; #endif /* VertexPositionNormal_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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,38 @@ #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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,135 @@ #include <metal_stdlib> using namespace metal; #include "VertexPositionNormal.h" #include "MarchingCubesBlobParams.h" #include "edgeTable.h" #include "triTable.h" inline float3 interpolateIsoSurfacePosition(float3 pA, float valueA, float3 pB, float valueB, float isoLevel) { float denom = (valueB - valueA); float t = (isoLevel - valueA) / (denom + 1e-6f); return mix(pA, pB, clamp(t, 0.0f, 1.0f)); } inline float sdf_sphere(float3 p, float3 c, float r) { return length(p - c) - r; } inline float smin(float a, float b, float k) { float h = clamp(0.5f + 0.5f * (b - a) / max(k, 1e-6f), 0.0f, 1.0f); return mix(b, a, h) - k * h * (1.0f - h); } inline float fieldValue(float3 worldPos, constant MarchingCubesBlobParams& P, device const Sphere* spheres) { float d = 1e9f; uint count = P.sphereCount; for (uint i = 0; i < count; ++i) { float di = sdf_sphere(worldPos, spheres[i].center, spheres[i].radius); d = smin(d, di, P.smoothK); } return d; } inline float3 estimateNormalFromField(float3 worldPos, constant MarchingCubesBlobParams& P, device const Sphere* spheres) { float h = 0.5f * min(P.cellSize.x, min(P.cellSize.y, P.cellSize.z)); float fx = fieldValue(worldPos + float3(h,0,0), P, spheres) - fieldValue(worldPos - float3(h,0,0), P, spheres); float fy = fieldValue(worldPos + float3(0,h,0), P, spheres) - fieldValue(worldPos - float3(0,h,0), P, spheres); float fz = fieldValue(worldPos + float3(0,0,h), P, spheres) - fieldValue(worldPos - float3(0,0,h), P, spheres); return normalize(float3(fx, fy, fz) / (2.0f * h)); } kernel void generateMarchingCubesBlobMesh(device VertexPositionNormal* outVertices [[buffer(0)]], device uint* outIndices [[buffer(1)]], device atomic_uint* outVertexCounter [[buffer(2)]], constant MarchingCubesBlobParams& P [[buffer(3)]], device const Sphere* spheres [[buffer(4)]], uint3 cellCoord [[thread_position_in_grid]]) { if (cellCoord.x >= P.cells.x || cellCoord.y >= P.cells.y || cellCoord.z >= P.cells.z) { return; } const int3 cornerOffsets[8] = { int3(0,0,0), int3(1,0,0), int3(1,1,0), int3(0,1,0), int3(0,0,1), int3(1,0,1), int3(1,1,1), int3(0,1,1) }; const int2 edgeCornerIndexPairs[12] = { int2(0,1), int2(1,2), int2(2,3), int2(3,0), int2(4,5), int2(5,6), int2(6,7), int2(7,4), int2(0,4), int2(1,5), int2(2,6), int2(3,7) }; const float3 cellOriginWS = P.origin + float3(cellCoord) * P.cellSize; float cornerScalar[8]; float3 cornerPositionWS[8]; for (int i = 0; i < 8; ++i) { float3 cp = cellOriginWS + float3(cornerOffsets[i]) * P.cellSize; cornerPositionWS[i] = cp; cornerScalar[i] = fieldValue(cp, P, spheres); } int cubeIndex = 0; if (cornerScalar[0] > P.isoLevel) cubeIndex |= 1; if (cornerScalar[1] > P.isoLevel) cubeIndex |= 2; if (cornerScalar[2] > P.isoLevel) cubeIndex |= 4; if (cornerScalar[3] > P.isoLevel) cubeIndex |= 8; if (cornerScalar[4] > P.isoLevel) cubeIndex |= 16; if (cornerScalar[5] > P.isoLevel) cubeIndex |= 32; if (cornerScalar[6] > P.isoLevel) cubeIndex |= 64; if (cornerScalar[7] > P.isoLevel) cubeIndex |= 128; int edgeMask = edgeTable[cubeIndex]; if (edgeMask == 0) { return; } float3 edgeIntersectionWS[12]; for (int edge = 0; edge < 12; ++edge) { if (edgeMask & (1 << edge)) { const int a = edgeCornerIndexPairs[edge].x; const int b = edgeCornerIndexPairs[edge].y; edgeIntersectionWS[edge] = interpolateIsoSurfacePosition( cornerPositionWS[a], cornerScalar[a], cornerPositionWS[b], cornerScalar[b], P.isoLevel ); } } constant int* triangleEdgesRow = &triTable[cubeIndex][0]; for (int triIdx = 0; triIdx < 16 && triangleEdgesRow[triIdx] != -1; triIdx += 3) { const int e0 = triangleEdgesRow[triIdx + 0]; const int e1 = triangleEdgesRow[triIdx + 1]; const int e2 = triangleEdgesRow[triIdx + 2]; const float3 p0 = edgeIntersectionWS[e0]; const float3 p1 = edgeIntersectionWS[e1]; const float3 p2 = edgeIntersectionWS[e2]; const float3 n0 = estimateNormalFromField(p0, P, spheres); const float3 n1 = estimateNormalFromField(p1, P, spheres); const float3 n2 = estimateNormalFromField(p2, P, spheres); const uint baseVertexIndex = atomic_fetch_add_explicit(outVertexCounter, (uint)3, memory_order_relaxed); outVertices[baseVertexIndex + 0].position = p0; outVertices[baseVertexIndex + 0].normal = n0; outVertices[baseVertexIndex + 1].position = p1; outVertices[baseVertexIndex + 1].normal = n1; outVertices[baseVertexIndex + 2].position = p2; outVertices[baseVertexIndex + 2].normal = n2; outIndices[baseVertexIndex + 0] = baseVertexIndex + 0; outIndices[baseVertexIndex + 1] = baseVertexIndex + 1; outIndices[baseVertexIndex + 2] = baseVertexIndex + 2; } } 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,262 @@ #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 */