粒子球体在 Three.js 中仅显示为直线

发布于 2025-01-10 14:54:39 字数 2670 浏览 1 评论 0原文

我正在学习通过在我的 React 应用程序中创建粒子球体来使用 THREE.js 库。引用这个项目,我已经成功获得有点开始,但有点走进了死胡同。

出于某种原因,尽管我的所有代码本质上都是相同的 - 除了一些已弃用的方法被换出之外 - THREE 每次都会呈现一条奇怪的直线。

在看了几个小时的文档并尝试学习这个组件的各个方法之后,我仍然摸不着头脑。

这就是我所拥有的(可以在此处查看实时版本 ):

let camera;
let renderer;
let scene;
const vector3D = new THREE.Vector3();

// Get constraints of the canvas.
const getConstraints = () => {
  const canvas = document.getElementById("canvas");
  const { width, height } = canvas.getBoundingClientRect();
  // Get attribute-set width and height - defaulting to computed constraints.
  return [canvas.width ?? width, canvas.height ?? height];
};
// Retrieve a random point in the sphere for a particle to be set at.
const getRandomPointInSphere = radius => {
  const x = THREE.MathUtils.randFloat(-1, 1);
  const y = THREE.MathUtils.randFloat(-1, 1);
  const z = THREE.MathUtils.randFloat(-1, 1);

  const normaliseRatio = 1 / Math.sqrt(x * x + y * y + z * z);

  vector3D.x = x * normaliseRatio * radius;
  vector3D.y = y * normaliseRatio * radius;
  vector3D.z = z * normaliseRatio * radius;

  return vector3D;
};

// Initialisation methods.
const initScene = () => {
  const [canvasWidth, canvasHeight] = getConstraints();
  // Renderer initialisation.
  renderer = new THREE.WebGLRenderer({
    canvas: document.getElementById("canvas"),
    antialias: true, alpha: true,
  });
  renderer.setSize(canvasWidth, canvasHeight);
  renderer.setPixelRatio(window.devicePixelRatio);

  // Scene initialisation.
  scene = new THREE.Scene();

  // Camera initialisation.
  camera = new THREE.PerspectiveCamera(45, canvasWidth, canvasHeight, 1, 1000);
  camera.position.set(100, 0, 100);
};
const initPoints = () => {
  const geometry = new THREE.BufferGeometry();
  const positions = [];

  const particleSize = 0.2;
  const particleColor = 0x1826e0; // Dark blue 
  const particleCount = 50000 / (particleSize * 10);

  for(let i = 0; i < particleCount; i++){
    let vertex = getRandomPointInSphere(50);
    positions.push(vertex.x, vertex.y, vertex.z);
  }

  geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3));

  const material = new THREE.PointsMaterial({ size: particleSize, color: particleColor });
  const particles = new THREE.Points(geometry, material);
  scene.add(particles);
};

initScene();
initPoints();
renderer.render(scene, camera);

我对三个(以及一般的画布)非常陌生,因此感谢所有帮助。

I'm learning to use the THREE.js library by creating a particle sphere inside my React App. Referencing this project, I've managed to get somewhat of a start, but am at a bit of a dead-end.

For some reason, despite the fact that all my code is essentially the same - except for some deprecated methods being swapped out - THREE will render a weird straight line every time.

After looking at the documentation for a few hours and trying to learn the individual methods of this component, I'm still scratching my head.

This is what I have (a live version can be viewed here):

let camera;
let renderer;
let scene;
const vector3D = new THREE.Vector3();

// Get constraints of the canvas.
const getConstraints = () => {
  const canvas = document.getElementById("canvas");
  const { width, height } = canvas.getBoundingClientRect();
  // Get attribute-set width and height - defaulting to computed constraints.
  return [canvas.width ?? width, canvas.height ?? height];
};
// Retrieve a random point in the sphere for a particle to be set at.
const getRandomPointInSphere = radius => {
  const x = THREE.MathUtils.randFloat(-1, 1);
  const y = THREE.MathUtils.randFloat(-1, 1);
  const z = THREE.MathUtils.randFloat(-1, 1);

  const normaliseRatio = 1 / Math.sqrt(x * x + y * y + z * z);

  vector3D.x = x * normaliseRatio * radius;
  vector3D.y = y * normaliseRatio * radius;
  vector3D.z = z * normaliseRatio * radius;

  return vector3D;
};

// Initialisation methods.
const initScene = () => {
  const [canvasWidth, canvasHeight] = getConstraints();
  // Renderer initialisation.
  renderer = new THREE.WebGLRenderer({
    canvas: document.getElementById("canvas"),
    antialias: true, alpha: true,
  });
  renderer.setSize(canvasWidth, canvasHeight);
  renderer.setPixelRatio(window.devicePixelRatio);

  // Scene initialisation.
  scene = new THREE.Scene();

  // Camera initialisation.
  camera = new THREE.PerspectiveCamera(45, canvasWidth, canvasHeight, 1, 1000);
  camera.position.set(100, 0, 100);
};
const initPoints = () => {
  const geometry = new THREE.BufferGeometry();
  const positions = [];

  const particleSize = 0.2;
  const particleColor = 0x1826e0; // Dark blue 
  const particleCount = 50000 / (particleSize * 10);

  for(let i = 0; i < particleCount; i++){
    let vertex = getRandomPointInSphere(50);
    positions.push(vertex.x, vertex.y, vertex.z);
  }

  geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3));

  const material = new THREE.PointsMaterial({ size: particleSize, color: particleColor });
  const particles = new THREE.Points(geometry, material);
  scene.add(particles);
};

initScene();
initPoints();
renderer.render(scene, camera);

I'm very new to THREE (and canvases in general), so all help is appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小忆控 2025-01-17 14:54:39

首先,相机实例化的行必须是这样的:camera = new THREE.PerspectiveCamera(45, canvasWidth / canvasHeight, 1, 1000);,其中有斜杠而不是逗号。

然后,相机必须查看场景的中心,因此 camera.lookAt(scene.position);

具有固定代码的片段:

在此处输入图像描述

body{
  overflow: hidden;
  margin: 0;
}

canvas{
  border: 1px solid red;
}
<canvas id="canvas" width="400" height="400" />
<script type="module">
import * as THREE from "https://cdn.skypack.dev/[email protected]";
// THREE variables
let camera;
let renderer;
let scene;
let v3 = new THREE.Vector3();
// Get constraints of the canvas.
const getConstraints = () => {
  const canvas = document.getElementById("canvas");
  const { width, height } = canvas.getBoundingClientRect();
  // Get attribute-set width and height - defaulting to computed constraints.
  return [canvas.width ?? width, canvas.height ?? height];
};
// Retrieve a random point in the sphere for a particle to be set at.

const getRandomPointInSphere = radius => {
  v3.randomDirection();

  const normaliseRatio = 1 / Math.hypot(v3.x, v3.y, v3.z);

  v3.setLength(radius * normaliseRatio);

  return v3;
};

// Initialisation methods.
const initScene = () => {
  const [canvasWidth, canvasHeight] = getConstraints();
  // Renderer initialisation.
  renderer = new THREE.WebGLRenderer({
    canvas: document.getElementById("canvas"),
    antialias: true, alpha: true,
  });
  renderer.setSize(canvasWidth, canvasHeight);
  renderer.setPixelRatio(window.devicePixelRatio);

  // Scene initialisation.
  scene = new THREE.Scene();

  // Camera initialisation.
  camera = new THREE.PerspectiveCamera(45, canvasWidth / canvasHeight, 1, 1000);
  camera.position.set(100, 0, 100);
  camera.lookAt(scene.position);
};
const initPoints = () => {
  const geometry = new THREE.BufferGeometry();
  const positions = [];

  const particleSize = 0.2;
  const particleColor = 0x1826e0; // Dark blue 
  const particleCount = 50000 / (particleSize * 10);

  for(let i = 0; i < particleCount; i++){
    let vertex = getRandomPointInSphere(50);
    positions.push(vertex.x, vertex.y, vertex.z);
  }

  geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3));

  const material = new THREE.PointsMaterial({ size: particleSize, color: particleColor });
  const particles = new THREE.Points(geometry, material);
  scene.add(particles);
};

initScene();
initPoints();
renderer.render(scene, camera);
</script>

First of all, the line with camera instantiation has to be like this: camera = new THREE.PerspectiveCamera(45, canvasWidth / canvasHeight, 1, 1000);, there is the slash instead of comma.

And then, camera has to look at the scene's center, thus camera.lookAt(scene.position);

Snippet with fixed code:

enter image description here

body{
  overflow: hidden;
  margin: 0;
}

canvas{
  border: 1px solid red;
}
<canvas id="canvas" width="400" height="400" />
<script type="module">
import * as THREE from "https://cdn.skypack.dev/[email protected]";
// THREE variables
let camera;
let renderer;
let scene;
let v3 = new THREE.Vector3();
// Get constraints of the canvas.
const getConstraints = () => {
  const canvas = document.getElementById("canvas");
  const { width, height } = canvas.getBoundingClientRect();
  // Get attribute-set width and height - defaulting to computed constraints.
  return [canvas.width ?? width, canvas.height ?? height];
};
// Retrieve a random point in the sphere for a particle to be set at.

const getRandomPointInSphere = radius => {
  v3.randomDirection();

  const normaliseRatio = 1 / Math.hypot(v3.x, v3.y, v3.z);

  v3.setLength(radius * normaliseRatio);

  return v3;
};

// Initialisation methods.
const initScene = () => {
  const [canvasWidth, canvasHeight] = getConstraints();
  // Renderer initialisation.
  renderer = new THREE.WebGLRenderer({
    canvas: document.getElementById("canvas"),
    antialias: true, alpha: true,
  });
  renderer.setSize(canvasWidth, canvasHeight);
  renderer.setPixelRatio(window.devicePixelRatio);

  // Scene initialisation.
  scene = new THREE.Scene();

  // Camera initialisation.
  camera = new THREE.PerspectiveCamera(45, canvasWidth / canvasHeight, 1, 1000);
  camera.position.set(100, 0, 100);
  camera.lookAt(scene.position);
};
const initPoints = () => {
  const geometry = new THREE.BufferGeometry();
  const positions = [];

  const particleSize = 0.2;
  const particleColor = 0x1826e0; // Dark blue 
  const particleCount = 50000 / (particleSize * 10);

  for(let i = 0; i < particleCount; i++){
    let vertex = getRandomPointInSphere(50);
    positions.push(vertex.x, vertex.y, vertex.z);
  }

  geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3));

  const material = new THREE.PointsMaterial({ size: particleSize, color: particleColor });
  const particles = new THREE.Points(geometry, material);
  scene.add(particles);
};

initScene();
initPoints();
renderer.render(scene, camera);
</script>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文