pepel_xD Asked:2020-07-07 14:33:35 +0800 CST2020-07-07 14:33:35 +0800 CST 2020-07-07 14:33:35 +0800 CST 如何使用three.js中的粒子制作带有外观动画的文本? 772 这可以通过什么方式实现?是否需要先在一些3D编辑器中实现,然后导出为三个,还是可以使用标准库工具来完成? 我是 3D 图形的新手。 javascript 1 个回答 Voted Best Answer prisoner849 2020-07-07T20:10:12+08:002020-07-07T20:10:12+08:00 UPD:如果您需要用点填充封闭的缓冲区几何体(不是通过点和三角形的投影,而是通过全 3D 的方式),那么有一个功能可以做到这一点。 您可能可以在 3D 编辑器中实现它,在一些简单的情况下您可以不用它。我们将一个点投影到一个平面上xy,看看它是否落入几何体的任何三角形到同一平面上的投影: var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000); camera.position.set(0, 10, 20); var renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); var controls = new THREE.OrbitControls(camera, renderer.domElement); var light = new THREE.DirectionalLight(0xffffff, 2); light.position.setScalar(100); scene.add(light); var textGeo = null; var newGeo = null; var textPoints = null; var loader = new THREE.FontLoader(); loader.load('https://threejs.org/examples/fonts/droid/droid_serif_bold.typeface.json', function(response) { var font = response; setText(font); render(); }); function setText(font) { textGeo = new THREE.TextGeometry("ABC", { font: font, size: 4, height: 0.25, curveSegments: 1, bevelEnabled: false }); textGeo.computeBoundingBox(); textGeo.computeVertexNormals(); textGeo.center(); fillWithPoints(textGeo, 1000); textGeo.vertices.forEach(function(vertex) { vertex.startPoint = vertex.clone(); vertex.direction = vertex.clone().normalize(); }) textPoints = new THREE.Points(textGeo, new THREE.PointsMaterial({ color: 0x00ff00, size: 0.1 })); scene.add(textPoints); } function fillWithPoints(geometry, pointNumber) { geometry.computeBoundingBox(); for (var i = 0; i < pointNumber; i++) { setRandomPoint(geometry); } } function setRandomPoint(geometry) { var point = new THREE.Vector3( THREE.Math.randFloat(geometry.boundingBox.min.x, geometry.boundingBox.max.x), THREE.Math.randFloat(geometry.boundingBox.min.y, geometry.boundingBox.max.y), THREE.Math.randFloat(geometry.boundingBox.min.z, geometry.boundingBox.max.z) ); //console.log(point); if (isPointInside(point, geometry)) { geometry.vertices.push(point); } else { setRandomPoint(geometry); } } var a = new THREE.Vector3(); var b = new THREE.Vector3(); var c = new THREE.Vector3(); var face = new THREE.Face3(); function isPointInside(point, geometry) { var retVal = false; for (var i = 0; i < geometry.faces.length; i++) { face = geometry.faces[i]; a = geometry.vertices[face.a]; b = geometry.vertices[face.b]; c = geometry.vertices[face.c]; //console.log(face, a, b, c); if (ptInTriangle(point, a, b, c)) { var retVal = true; break; } } return retVal; } function ptInTriangle(p, p0, p1, p2) { // credits: http://jsfiddle.net/PerroAZUL/zdaY8/1/ var A = 1 / 2 * (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y); var sign = A < 0 ? -1 : 1; var s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y) * sign; var t = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y) * sign; return s > 0 && t > 0 && (s + t) < 2 * A * sign; } function render() { requestAnimationFrame(render); textGeo.vertices.forEach(function(vertex) { vertex.copy(vertex.startPoint).addScaledVector(vertex.direction, 5 + Math.sin(Date.now() * 0.001) * 5); }); textGeo.verticesNeedUpdate = true; renderer.render(scene, camera); } body { overflow: hidden; margin: 0 } <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/94/three.min.js"></script> <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
UPD:如果您需要用点填充封闭的缓冲区几何体(不是通过点和三角形的投影,而是通过全 3D 的方式),那么有一个功能可以做到这一点。
您可能可以在 3D 编辑器中实现它,在一些简单的情况下您可以不用它。我们将一个点投影到一个平面上
xy
,看看它是否落入几何体的任何三角形到同一平面上的投影: