我在THREEJS中绘制一个带有粒子的球体。这很好。
然而,我将这些点循环到动画(重新定位它们)。当我使用50以下的widthSegments(WidthSegement是第二个参数)时工作得很好。超过50的任何东西都将停止被吸引。
供参考:
SphereGeometry(radius, widthSegments, heightSegments)
这样可以正常工作:
let geometry = new THREE.SphereGeometry(30, 50, 20);
然而,这只发生在我通过点循环以改变它们的位置时。
它仍然激发了现有的观点。但不是任何其他人。
//Related to the audio api
let AudioContext = window.AudioContext || window.webkitAudioContext,
ctxAudio = new AudioContext(),
sampleRate = ctxAudio.sampleRate,
audio = document.getElementById("sound"),
audioSrc = ctxAudio.createMediaElementSource(audio),
analyser = ctxAudio.createAnalyser(),
bufferLength = analyser.frequencyBinCount,
dataArray = new Uint8Array(bufferLength);
analyser.fftSize = 2048 * 2;
analyser.smoothingTimeConstant = 0.75;
audioSrc.connect(analyser);
audioSrc.connect(ctxAudio.destination);
//Setting up the renderer
let renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//Defining the objects in the scene
let geometry = new THREE.SphereGeometry(30, 100, 20);
let loader = new THREE.TextureLoader();
loader.crossOrigin = true;
let particleTexture = loader.load('https://threejs.org/examples/textures/particle2.png');
let material = new THREE.PointsMaterial({
color: 0x20C9BD,
size: 1,
transparent: true,
blending: THREE.AdditiveBlending,
map: particleTexture,
depthWrite: false
});
let points = new THREE.Points(geometry, material);
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
//Setting the scene
scene.add(points);
camera.position.z = 100;
//Copy the default sphere into a vector
const def = new THREE.Vector3;
for (let i = 0; i < geometry.vertices.length; i++) {
def[i] = {
x: geometry.vertices[i].x,
y: geometry.vertices[i].y,
z: geometry.vertices[i].z
};
}
//Render the scene(looping through it 60 times a second)
//This is where the issue is
function render() {
requestAnimationFrame(render);
analyser.getByteFrequencyData(dataArray);
camera.lookAt(points.position);
for (let i = 0; i < geometry.vertices.length; i++) {
let particle = geometry.vertices[i];
let dx = def[i].x * (dataArray[i] / 255.0) + def[i].x;
let dy = def[i].y * (dataArray[i] / 255.0) + def[i].y;
let dz = def[i].z * (dataArray[i] / 255.0) + def[i].z;
particle.set(dx, dy, dz); //<--this is where the issue is.
}
geometry.verticesNeedUpdate = true;
renderer.render(scene, camera);
}
render();
&#13;
<script src="https://rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/three.js"></script>
</head>
<body>
<audio id="sound" controls src="http://tackj.happyvisocoders.be/audio/DieForYou-Starset.mp3"></audio>
</body>
</html>
&#13;
如果你注释掉了particle.set(dx,dy,dz),它会完美地绘制。 然而,这会使粒子与音乐一起移动。因此保持这一部分非常重要。
为什么球体没有完全绘制,我该如何解决这个问题呢?
答案 0 :(得分:2)
这实际上与three.js关系不大,但与webaudio-API有关。
当您创建FFT大小为2048的分析仪时,您将获得1024个频率区间(请参阅analyzer.frequencyBinCount
),但您的几何体有1902个顶点。因此,对于索引为1024到1901的顶点,dataArray[i]
未定义,计算全部解析为NaN
。现在你将向量设置为vector.set(NaN, NaN, NaN)
并且三个.js不知道该怎么做,所以这些点不会被渲染。
因此,如果用
替换循环的那部分let fftValue = (dataArray[i] / 255.0) || 0;
let dx = def[i].x * fftValue + def[i].x;
let dy = def[i].y * fftValue + def[i].y;
let dz = def[i].z * fftValue + def[i].z;
particle.set(dx, dy, dz);
甚至更简单:
let fftValue = (dataArray[i] / 255.0) || 0;
geometry.vertices[i]
.copy(def)
.multiplyScalar(1 + fftValue)
你应该没事。