代码之家  ›  专栏  ›  技术社区  ›  Chet

3J多面体几何并不是绘制所有的面

  •  0
  • Chet  · 技术社区  · 7 年前

    我正在做我的第一个Three.js项目,遇到了一些奇怪的问题。我在看书 this paper

    我已经弄清楚了如何渲染一个二十面体,以及如何将它划分成一个n度的测地线穹顶。然而,当我渲染测地圆顶时,似乎有一些面没有填充(见图)。我在用 THREE.PolyhedronGeometry 看起来所有的面都被定义了,否则没有面的线框的边不应该出现,但是它们确实出现了。。。

    这是我生成测地圆顶三角形的代码

    // 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))
    

    下面是我绘制多面体的3.js代码:

    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()
    

    你知道为什么那些脸没有出现吗?我甚至找不到脸的颜色是在哪里定义的,或者我会给它一个颜色让它更明显。

    如果克隆my repo,则可以自己运行代码:

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

    enter image description here

    0 回复  |  直到 7 年前