0

I'm working on my first Three.js project and running into some weird issues. I'm reading this paper about geodesic domes and trying to render them.

I have figured out how to render an icosahedron and how to divide it into a nth degree geodesic dome. However, when I render the geodesic dome, there appear to be faces that aren't filled in (see picture). I'm using THREE.PolyhedronGeometry and it appears all the faces are defined, otherwise the edges of the wireframe where there are no faces shouldn't appear, but they do...

Here's my code for generating the geodesic dome triangles

// http://www.geometer.org/mathcircles/geodesic.pdf
// Golden Ratio
const g = (1 + Math.sqrt(5)) / 2

type Point = [number, number, number]
type Triangle = [Point, Point, Point]

// Points
const A: Point = [0, 1, g]
const B: Point = [0, -1, g]
const C: Point = [0, -1, -g]
const D: Point = [0, 1, -g]
const E: Point = [g, 0, 1]
const F: Point = [-g, 0, 1]
const G: Point = [-g, 0, -1]
const H: Point = [g, 0, -1]
const I: Point = [1, g, 0]
const J: Point = [-1, g, 0]
const K: Point = [-1, -g, 0]
const L: Point = [1, -g, 0]

// Triangles
const icosahedron: Triangle[] = [
    [A, I, J],
    [A, J, F],
    [A, F, B],
    [A, B, E],
    [A, E, I],
    [B, F, K],
    [B, K, L],
    [B, L, E],
    [C, D, H],
    [C, H, L],
    [C, L, K],
    [C, K, G],
    [C, G, D],
    [D, G, J],
    [D, J, I],
    [D, I, H],
    [E, L, H],
    [E, H, I],
    [F, J, G],
    [F, G, K],
]

const edge = 2
const radius = Math.sqrt(1 + g * g)

function sub(p1: Point, p2: Point): Point {
    return [p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2]]
}

function mult(n: number, p1: Point): Point {
    return [p1[0] * n, p1[1] * n, p1[2] * n]
}

function add(p1: Point, p2: Point): Point {
    return [p1[0] + p2[0], p1[1] + p2[1], p1[2] + p2[2]]
}

function distance(p1: Point, p2: Point): number {
    const x = sub(p1, p2)
    return Math.sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2])
}

function split(tri: Triangle): Array<Triangle> {
    const midpoint01 = add(mult(0.5, tri[0]), mult(0.5, tri[1]))
    const midpoint02 = add(mult(0.5, tri[0]), mult(0.5, tri[2]))
    const midpoint12 = add(mult(0.5, tri[1]), mult(0.5, tri[2]))
    const scale = radius / distance(midpoint01, [0, 0, 0])
    const m01 = mult(scale, midpoint01)
    const m02 = mult(scale, midpoint02)
    const m12 = mult(scale, midpoint12)
    return [
        [m01, m02, m12],
        [tri[0], m01, m02],
        [tri[1], m01, m12],
        [tri[2], m02, m12],
    ]
}

const geodome1 = _.flatten(icosahedron.map(split))
const geodome2 = _.flatten(geodome1.map(split))

And here's my Three.js code for rendering the Polyhedron:

function trianglesToPoly(triangles: Triangle[]) {
    const points: Point[] = _.uniqWith(_.flatten(triangles), _.isEqual)
    const vertices = _.flatten(points)
    const faces = _.flatten(
        _.flatten(
            triangles.map(triangle => {
                return triangle.map(point => {
                    return points.findIndex(p => _.isEqual(p, point))
                })
            })
        )
    )
    const geometry = new THREE.PolyhedronGeometry(vertices, faces, 10, 0)
    return geometry
}

const scene = new THREE.Scene()
const width = window.innerWidth * 0.8
const height = window.innerHeight * 0.8

const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000)

const renderer = new THREE.WebGLRenderer()
renderer.setSize(width, height)
renderer.domElement.style.height = `${height}px`
renderer.domElement.style.width = `${width}px`
document.body.appendChild(renderer.domElement)

// const geometry = trianglesToPoly(icosahedron)
const geometry = trianglesToPoly(geodome1)
// const geometry = trianglesToPoly(geodome2)

var material = new THREE.MeshPhongMaterial({
    color: 0x0000ff,
    polygonOffset: true,
    polygonOffsetFactor: 1, // positive value pushes polygon further away
    polygonOffsetUnits: 1,
})

const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)

// https://stackoverflow.com/questions/31539130/display-wireframe-and-solid-color
var geo = new THREE.EdgesGeometry(mesh.geometry) // or WireframeGeometry
var mat = new THREE.LineBasicMaterial({ color: 0xffffff, linewidth: 4 })
var wireframe = new THREE.LineSegments(geo, mat)
mesh.add(wireframe)

camera.position.z = 50

const animate = () => {
    requestAnimationFrame(animate)

    mesh.rotation.x += 0.01
    mesh.rotation.y += 0.01

    renderer.render(scene, camera)
}

animate()

Any ideas why those faces aren't showing up? I can't even find where the color of the faces are defined or I would give it a color to make it more obvious.

You can run the code yourself if you clone my repo:

git clone https://github.com/ccorcos/geodome.git
cd geodome
npm install
npm start

enter image description here

Chet
  • 18,421
  • 15
  • 69
  • 113

0 Answers0