Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 23 additions & 11 deletions lib/render-elements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,6 @@ export async function buildRenderElements(
}
}
}

// BSP sort faces before merging with other elements
function sortFacesBSP(
polys: Face[],
Expand All @@ -392,19 +391,32 @@ export async function buildRenderElements(
const EPS = 1e-6
type Node = {
face: Face
normal: Point3
point: Point3
normal: Point3 // splitter plane normal (need not be unit length)
planeD: number // plane constant: n·x + d = 0 (d = –n·p0)
front: Node | null
back: Node | null
}

function build(list: Face[]): Node | null {
if (!list.length) return null
const face = list[0]!
const p0 = face.cam[0]!
const p1 = face.cam[1]!
const p2 = face.cam[2]!
const normal = cross(sub(p1, p0), sub(p2, p0))
const [p0, p1, p2] = face.cam as [Point3, Point3, Point3]

// --- inline cross( p1-p0 , p2-p0 ) --------------------------
const ax = p1.x - p0.x,
ay = p1.y - p0.y,
az = p1.z - p0.z
const bx = p2.x - p0.x,
by = p2.y - p0.y,
bz = p2.z - p0.z
const normal = {
x: ay * bz - az * by,
y: az * bx - ax * bz,
z: ax * by - ay * bx,
}
// plane constant d = –n·p0
const planeD = -(normal.x * p0.x + normal.y * p0.y + normal.z * p0.z)

const front: Face[] = []
const back: Face[] = []

Expand All @@ -415,7 +427,7 @@ export async function buildRenderElements(
neg = 0
const d: number[] = []
for (const v of f.cam) {
const dist = dot(normal, sub(v!, p0))
const dist = normal.x * v.x + normal.y * v.y + normal.z * v.z + planeD
d.push(dist)
if (dist > EPS) pos++
else if (dist < -EPS) neg++
Expand Down Expand Up @@ -483,16 +495,16 @@ export async function buildRenderElements(
return {
face,
normal,
point: p0,
planeD,
front: build(front),
back: build(back),
}
}

function traverse(node: Node | null, out: Face[]) {
if (!node) return
const cameraSide = dot(node.normal, scale(node.point, -1))
if (cameraSide >= 0) {
if (node.planeD >= 0) {
// camera (origin) is on the “front” side
traverse(node.back, out)
out.push(node.face)
traverse(node.front, out)
Expand Down
246 changes: 123 additions & 123 deletions tests/__snapshots__/obj1.snap.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
148 changes: 74 additions & 74 deletions tests/__snapshots__/obj2.snap.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 1 addition & 3 deletions tests/__snapshots__/scene1.snap.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 4 additions & 6 deletions tests/__snapshots__/scene2.snap.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 8 additions & 8 deletions tests/__snapshots__/stl2.snap.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion tests/__snapshots__/topimage2.snap.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading