在 THREE.js 中为旋涡星系生成粒子
Generate particles for spiral galaxy in THREE.js
我想在 THEE.js 中使用 THREE.Points
创建一个简单的螺旋星系。
我不知道如何生成旋臂。有什么(不太难)的方法可以做到这一点吗?
这里是我创建的fiddle。有一个扁平的球体,但没有旋臂。
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight)
camera.position.z = 1500
scene.add(camera)
const renderer = new THREE.WebGLRenderer({ clearColor: 0x000000 })
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
// Random function with normal dustribution.
const normalRandom = (mean, std) => {
let n = 0
for (let i = 1; i <= 12; i++) {
n += Math.random()
}
return (n - 6) * std + mean
}
const geometry = new THREE.Geometry()
const galaxySize = 1000
// Generate particles for spiral galaxy:
for (let i = 0; i < 10000; i++) {
var theta = THREE.Math.randFloatSpread(360)
var phi = THREE.Math.randFloatSpread(360)
const distance = THREE.Math.randFloatSpread(galaxySize)
// Here I need to generate spiral arms instead of a sphere.
geometry.vertices.push(new THREE.Vector3(
distance * Math.sin(theta) * Math.cos(phi),
distance * Math.sin(theta) * Math.sin(phi),
distance * Math.cos(theta) / 10
))
}
const spiralGalaxy = new THREE.Points(geometry, new THREE.PointsMaterial({ color: 0xffffff }))
scene.add(spiralGalaxy)
function render() {
requestAnimationFrame(render)
renderer.render(scene, camera)
spiralGalaxy.rotation.x += 0.01;
spiralGalaxy.rotation.y += 0.01;
}
render()
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.min.js"></script>
看来您已经使用极坐标系完成了很多繁重的工作。但是请记住,角度以弧度为单位,而不是以度为单位,因此不应使用 360
,而应使用 PI * 2
。现在您所要做的就是同时增加 distance
和 theta
以创建螺旋,而 phi
保持接近 0 以创建银河系的黄道面。
distance
将从 0
增长到 galaxySize
theta
将从 0
增长到 Math.PI
(或 PI * 2
,如果你想要更紧密的螺旋)
phi
接近 0
// Temp variables to assign new values inside loop
var norm, theta, phi, thetaVar, distance;
// Generate particles for spiral galaxy:
for (let i = 0; i < 1000; i++) {
// Norm increments from 0 to 1
norm = i / 1000;
// Random variation to theta [-0.5, 0.5]
thetaVar = THREE.Math.randFloatSpread(0.5);
// Theta grows from 0 to Math.PI (+ random variation)
theta = norm * Math.PI + thetaVar;
// Phi stays close to 0 to create galaxy ecliptic plane
phi = THREE.Math.randFloatSpread(0.1);
// Distance grows from 0 to galaxySize
distance = norm * galaxySize;
// Here I need generate spiral arms instead of sphere.
geometry.vertices.push(new THREE.Vector3(
distance * Math.sin(theta) * Math.cos(phi),
distance * Math.sin(theta) * Math.sin(phi),
distance * Math.cos(theta)
));
}
您可以为每只手臂创建一个循环。请注意,我没有像示例中那样在最后除以 10,而是将 phi 的范围限制为 [-0.1, 0.1]
。你可以看到它的实际效果 in this fiddle
我想在 THEE.js 中使用 THREE.Points
创建一个简单的螺旋星系。
我不知道如何生成旋臂。有什么(不太难)的方法可以做到这一点吗?
这里是我创建的fiddle。有一个扁平的球体,但没有旋臂。
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight)
camera.position.z = 1500
scene.add(camera)
const renderer = new THREE.WebGLRenderer({ clearColor: 0x000000 })
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
// Random function with normal dustribution.
const normalRandom = (mean, std) => {
let n = 0
for (let i = 1; i <= 12; i++) {
n += Math.random()
}
return (n - 6) * std + mean
}
const geometry = new THREE.Geometry()
const galaxySize = 1000
// Generate particles for spiral galaxy:
for (let i = 0; i < 10000; i++) {
var theta = THREE.Math.randFloatSpread(360)
var phi = THREE.Math.randFloatSpread(360)
const distance = THREE.Math.randFloatSpread(galaxySize)
// Here I need to generate spiral arms instead of a sphere.
geometry.vertices.push(new THREE.Vector3(
distance * Math.sin(theta) * Math.cos(phi),
distance * Math.sin(theta) * Math.sin(phi),
distance * Math.cos(theta) / 10
))
}
const spiralGalaxy = new THREE.Points(geometry, new THREE.PointsMaterial({ color: 0xffffff }))
scene.add(spiralGalaxy)
function render() {
requestAnimationFrame(render)
renderer.render(scene, camera)
spiralGalaxy.rotation.x += 0.01;
spiralGalaxy.rotation.y += 0.01;
}
render()
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.min.js"></script>
看来您已经使用极坐标系完成了很多繁重的工作。但是请记住,角度以弧度为单位,而不是以度为单位,因此不应使用 360
,而应使用 PI * 2
。现在您所要做的就是同时增加 distance
和 theta
以创建螺旋,而 phi
保持接近 0 以创建银河系的黄道面。
distance
将从0
增长到galaxySize
theta
将从0
增长到Math.PI
(或PI * 2
,如果你想要更紧密的螺旋)phi
接近 0
// Temp variables to assign new values inside loop
var norm, theta, phi, thetaVar, distance;
// Generate particles for spiral galaxy:
for (let i = 0; i < 1000; i++) {
// Norm increments from 0 to 1
norm = i / 1000;
// Random variation to theta [-0.5, 0.5]
thetaVar = THREE.Math.randFloatSpread(0.5);
// Theta grows from 0 to Math.PI (+ random variation)
theta = norm * Math.PI + thetaVar;
// Phi stays close to 0 to create galaxy ecliptic plane
phi = THREE.Math.randFloatSpread(0.1);
// Distance grows from 0 to galaxySize
distance = norm * galaxySize;
// Here I need generate spiral arms instead of sphere.
geometry.vertices.push(new THREE.Vector3(
distance * Math.sin(theta) * Math.cos(phi),
distance * Math.sin(theta) * Math.sin(phi),
distance * Math.cos(theta)
));
}
您可以为每只手臂创建一个循环。请注意,我没有像示例中那样在最后除以 10,而是将 phi 的范围限制为 [-0.1, 0.1]
。你可以看到它的实际效果 in this fiddle