nicklockwood/Euclid

Crash when trying to create a Mesh from an SCNCylinder geometry

lutes1 opened this issue · 2 comments

First of all thank you for an amazing framework, awesome job!

I have a node with a cylinder geometry.
let cylinderNode = SCNNode(geometry: SCNCylinder(radius: 3, height: 5))

I need to find out the intersection polygon of this node with a plane that cuts through it.
let plane = Plane(points: [.zero, Vector.unitX, Vector.unitY])!

I'm trying to create a Mesh using the existing cylinderNode and compute the intersection with the plane.
let cylinderMesh = Mesh(cylinderNode, ignoringTransforms: false)
let intersection = cylinderMesh.edges(intersecting: plane)

But Mesh(cylinderNode, ignoringTransforms: false) crashes at init(polygons: [Polygon], bounds: Bounds?, isConvex: Bool, isWatertight: Bool?, submeshes: [Mesh]?) (line 436 in the Mesh.swift file).

The line that crashes is assert(isWatertight == nil || isWatertight == polygons.areWatertight)
isWatertight is true but polygons.areWatertight is false

Looking at polygons.holeEdges, it's indeed not empty and has 37 segments.

Assuming that the polygons represent the cylinder and the knowing that SCNCylinder geometry is in fact watertight, it looks to me that there is a problem with the Mesh initialiser.

Framework version - 0.6.9

I'll see if I can reproduce this. In general it's caused due to floating point imprecision. Apple's SCN primitives for some reason have very poor precision with their vertex placement, causing Euclid to think there are gaps between the polygons. To account for this I have to either reduce the precision of Euclid equality checks or modify the SCN mesh geometry.

The good news is that these assertions only run at debug time, so if you run in release mode it's probably fine. I suggest building the Euclid module in release mode anyway for performance reasons, and only using a debug build if you are trying to track down bugs in the framework.

@lutes1 fixed in 0.6.10