简体   繁体   English

用三角形绘制金字塔

[英]Drawing a Pyraminx with triangles

I'm trying to code a Pyraminx which is a tetrahedon composed with multiples triangles.我正在尝试编写一个金字塔,它是一个由多个三角形组成的四面体。 The way I do it must not be very accurate.我这样做的方式一定不是很准确。 Here is my code, also available at https://codepen.io/jeffprod/pen/XWbBZLN .这是我的代码,也可在https://codepen.io/jeffprod/pen/XWbBZLN 获得

The problem is that i'im writing the facesVectors coordinates handly.问题是我正在编写facesVectors坐标。 It seems ok for the yellow and blue side.黄色和蓝色的一面似乎没问题。 But it is going difficult to set the position of red and green triangles.但是很难设置红色和绿色三角形的位置。

Is there a simple way to do ?有没有简单的方法?

 var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100); camera.position.set(-2, 1, 3); var renderer = new THREE.WebGLRenderer(); renderer.setSize(innerWidth, innerHeight); document.body.appendChild(renderer.domElement); let controls = new THREE.OrbitControls(camera, renderer.domElement); // one triangle equilateral const sideLength = 1 const x = 0 const y = 0 const geometry = new THREE.Geometry() geometry.vertices.push(new THREE.Vector3(x, (Math.sqrt(3) / 2 * sideLength) - (sideLength / 2), 0)) geometry.vertices.push(new THREE.Vector3(x - (sideLength / 2), y - (sideLength / 2), 0)) geometry.vertices.push(new THREE.Vector3(x + (sideLength / 2), y - (sideLength / 2), 0)) geometry.faces.push(new THREE.Face3(0, 1, 2)) const facesColors = [ 0xFFFF00, // yellow 0xFF0000, // red 0x0000FF, // blue 0x008000 // green ] // 36 triangles composing the pyraminx // numbers are indexes of facesColors const pos = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3 ] // vectors of each triangle composing the tetrahedron const facesVectors = [ [0, 0, -1.5], [-0.52, 0, -0.6], [0, 0, -0.48], [0.52, 0, -0.6], [-1.04, 0, 0.3], [-0.52, 0, 0.42], [0, 0, 0.3], [0.52, 0, 0.42], [1.04, 0, 0.3], [-1.2, -0.16, 0.2], [-1.04, -0.45, 0.55], [-0.52, -0.34, 0.62], [0, -0.45, 0.55], [0.52, -0.34, 0.62], [1.04, -0.45, 0.55], [1.2, -0.16, 0.15], [-0.6, -0.16, -0.7], [-0.9, -0.3, -0.1], [-0.5, -0.5, -0.5] ] for (let i = 0; i < facesVectors.length; i++) { material = new THREE.MeshBasicMaterial({ color: facesColors[pos[i]] }) face = new THREE.Mesh(geometry, material) face.position.set(facesVectors[i][0], facesVectors[i][1], facesVectors[i][2]) // some rotations if ([0, 1, 2, 3, 4, 5, 6, 7, 8].includes(i)) { face.rotation.x = -(Math.PI / 2) } if ([2, 5, 7, 10, 12, 14].includes(i)) { // 180 face.rotation.z = Math.PI } if ([9, 16, 17, 18, 25, 26, 27, 28, 29].includes(i)) { if (i === 17) { face.rotation.x = -(1 * Math.PI) / 6 face.rotation.y = -(2 * Math.PI) / 3 face.rotation.z = -(1 * Math.PI) / 6 } else { face.rotation.x = -Math.PI / 6 face.rotation.y = -2 * Math.PI / 3 face.rotation.z = Math.PI / 6 } } if ([15, 22, 23, 24, 31, 32, 33, 34, 35].includes(i)) { face.rotation.x = -Math.PI / 6 face.rotation.y = 2 * Math.PI / 3 face.rotation.z = -Math.PI / 6 } else if ([10, 11, 12, 13, 14, 19, 20, 21, 30].includes(i)) { face.rotation.x = Math.PI / 6 } scene.add(face) } renderer.setAnimationLoop(() => { renderer.render(scene, camera); });
 <script src="https://threejs.org/build/three.min.js"></script> <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

The 4 corner points of a Tetrahedron are:四面体的 4 个角点是:

let s_8_9 = Math.sqrt(8/9), s_2_9 = Math.sqrt(2/9), s_2_3 = Math.sqrt(2/3);
let v = [
    new THREE.Vector3(0,0,1),
    new THREE.Vector3(s_8_9,0,-1/3),
    new THREE.Vector3(-s_2_9,s_2_3,-1/3),
    new THREE.Vector3(-s_2_9,-s_2_3,-1/3) 
];

UseTHREE.Vector3().lerpVectors to compute a point on an edge:使用THREE.Vector3().lerpVectors计算边上的一个点:

let pointOnEdge = (pt1, pt2, t) => new THREE.Vector3().lerpVectors(pt1, pt2, t);

and the inward offset points, of a triangular face:以及三角形面的向内偏移点:

let computeOffsetPts = (pts, d) => {
    let offsetPts = [];
    for (let i = 0; i < pts.length; ++i) {
        let va = pointOnEdge(pts[i], pts[(i+1) % 3], d);
        let vb = pointOnEdge(pts[i], pts[(i+2) % 3], d); 
        offsetPts.push(new THREE.Vector3().lerpVectors(va, vb, 0.5)); 
    }
    return offsetPts;
}

Use this points to construct the mesh.使用这些点来构建网格。 eg:例如:

 var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100); camera.position.set(-2, 1, 3); var renderer = new THREE.WebGLRenderer(); renderer.setSize(innerWidth, innerHeight); document.body.appendChild(renderer.domElement); let controls = new THREE.OrbitControls(camera, renderer.domElement); const facesColors = [ 0xFFFF00, // yellow 0xFF0000, // red 0x0000FF, // blue 0x008000 // green ] let s_8_9 = Math.sqrt(8/9), s_2_9 = Math.sqrt(2/9), s_2_3 = Math.sqrt(2/3); let v = [ new THREE.Vector3(0,0,1), new THREE.Vector3(s_8_9,0,-1/3), new THREE.Vector3(-s_2_9,s_2_3,-1/3), new THREE.Vector3(-s_2_9,-s_2_3,-1/3) ]; let faces = [[0, 1, 2], [0, 2, 3], [0, 3, 1], [1, 3, 2]] let pointOnEdge = (pt1, pt2, t) => new THREE.Vector3().lerpVectors(pt1, pt2, t); let computeOffsetPts = (pts, d) => { let offsetPts = []; for (let i = 0; i < pts.length; ++i) { let va = pointOnEdge(pts[i], pts[(i+1) % 3], d); let vb = pointOnEdge(pts[i], pts[(i+2) % 3], d); offsetPts.push(new THREE.Vector3().lerpVectors(va, vb, 0.5)); } return offsetPts; } let newTriangle = (pts, color, d) => { let innerPts = computeOffsetPts(pts, d); let material = new THREE.MeshBasicMaterial({ color: color }) let geometry = new THREE.Geometry(); geometry.vertices.push(...innerPts); geometry.faces.push(new THREE.Face3(0, 1, 2)); return new THREE.Mesh(geometry, material); } const d = 0.05; for (let i=0; i < 4; ++i ) { let color = facesColors[i]; let pts = [v[faces[i][0]], v[faces[i][1]], v[faces[i][2]]]; let centerPt = new THREE.Vector3().addVectors(pts[0], pts[1]).add(pts[2]).divideScalar(3); let hexagonPts = []; for (let j = 0; j < 3; ++j) { hexagonPts.push(pointOnEdge(pts[j], pts[(j+1) % 3], 1/3), pointOnEdge(pts[j], pts[(j+1) % 3], 2/3)); } for (let j = 0; j < 3; ++j) { let topPts = [pts[j], hexagonPts[j*2], hexagonPts[(j*2+5)%6]]; let face = newTriangle(topPts, color, d); scene.add(face); } for (let j = 0; j < hexagonPts.length; ++j) { innerPts = [centerPt, hexagonPts[j], hexagonPts[(j+1)%hexagonPts.length]]; let face = newTriangle(innerPts, color, d); scene.add(face); } } renderer.setAnimationLoop(() => { renderer.render(scene, camera); });
 <script src="https://rawcdn.githack.com/mrdoob/three.js/r113/build/three.js"></script> <script src="https://rawcdn.githack.com/mrdoob/three.js/r113/examples/js/controls/OrbitControls.js"></script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM