Генерация частиц для спиральной галактики в THREE.js - PullRequest
2 голосов
/ 05 марта 2019

Я хотел бы создать простую спиральную галактику, используя THREE.Points в THEE.js.
Я не могу понять, как генерировать спиральные рукава.Есть ли какой-нибудь (не слишком сложный) способ сделать это?

Здесь я создал эту скрипку .Есть сплюснутая сфера, но без спиральных рукавов.

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>

1 Ответ

5 голосов
/ 06 марта 2019

Похоже, вы уже сделали много тяжелой работы с полярной системой координат.Имейте в виду, однако, что углы указаны в радианах, а не в градусах, поэтому вместо использования 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 в конце, как вы делали в своем примере, я просто ограничил диапазон фи до [-0.1, 0.1].Вы можете увидеть это в действии в этой скрипке

...