Как можно изменить положение объекта, состоящего из точек, плавающих вокруг центра, за три Js?

#javascript #three.js #shader #webgl

Вопрос:

Поэтому я сделал этот объект галактики, состоящий из точек, плавающих вокруг его центра

 const parameters = {}

parameters.count = 4500
parameters.size = 0.005
parameters.radius = 0.7
parameters.branches = 4
parameters.spin = 1
parameters.randomness = 0.1
parameters.randomnessPower = 5
parameters.insideColor = '#d42b2b'
parameters.outsideColor = '#14be4c'

let galaxyGeometry = null
let galaxyMaterial = null
let galaxyPoints = null

const generateGalaxy = () => 
{   
    //DESTROY STUFF
    if(galaxyPoints !== null)
    {
        galaxyGeometry.dispose()
        galaxyMaterial.dispose()
        scene.remove(galaxyPoints)
    }

    //GALAXY GEOM AND PARTICLES
    galaxyGeometry = new THREE.BufferGeometry()

    const positions = new Float32Array(parameters.count * 3)
    const randomness = new Float32Array(parameters.count * 3)
    const galaxyColors = new Float32Array(parameters.count * 3)
    const galaxyScales = new Float32Array(parameters.count * 1)

    const colorInside = new THREE.Color(parameters.insideColor)
    const colorOutside = new THREE.Color(parameters.outsideColor)

    for(let i = 0; i < parameters.count; i  )
    {
        const i3 = i * 3
        //POSITION
        const radius = Math.random() * parameters.radius
        
        const branchAngle = (i % parameters.branches) / parameters.branches * Math.PI * 2
        
        const randomX = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1: -1) * parameters.randomness * radius
        const randomY = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1: -1) * parameters.randomness * radius
        const randomZ = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1: -1) * parameters.randomness * radius

        positions[i3    ] = Math.cos(branchAngle) * radius
        positions[i3   1] = 0
        positions[i3   2] = Math.sin(branchAngle) * radius
    
        randomness[i3    ] = randomX
        randomness[i3   1] = randomY
        randomness[i3   2] = randomZ

        //COLORS
        // Color
        const mixedColor = colorInside.clone()
        mixedColor.lerp(colorOutside, radius / parameters.radius)

        galaxyColors[i3    ] = mixedColor.r
        galaxyColors[i3   1] = mixedColor.g
        galaxyColors[i3   2] = mixedColor.b

        // Scale
        galaxyScales[i] = Math.random()
    }

    galaxyGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3))
    galaxyGeometry.setAttribute('aRandomness', new THREE.BufferAttribute(randomness, 3))
    galaxyGeometry.setAttribute('color', new THREE.BufferAttribute(galaxyColors, 3))
    galaxyGeometry.setAttribute('aScale', new THREE.BufferAttribute(galaxyColors, 3))

    //GALAXY PARTICLE MATERIALS
    galaxyMaterial = new THREE.ShaderMaterial({
        depthWrite: false,
        blending: THREE.AdditiveBlending,
        vertexColors: true,
        uniforms:
        {   
            vAlpha: { value: 1.0 },
            uTime: { value: 0 },
            uSize: { value: 40 * renderer.getPixelRatio() }
        },
        vertexShader: galaxyVertex,
        fragmentShader: galaxyFragment,
    })
    if(galaxyMaterial.uniforms.vAlpha.value !== 1.0)
    {
        galaxyGeometry.dispose()
        galaxyMaterial.dispose()
        scene.remove(galaxyPoints)
    }
    //GALAXY MESH
    galaxyPoints = new THREE.Points(galaxyGeometry, galaxyMaterial)
    console.log(galaxyPoints.position)
    scene.add(galaxyPoints)
} 
 

вместе со своей вершиной

 uniform float uTime;
 uniform float uSize;

 attribute vec3 aRandomness;
 attribute float aScale;

varying vec3 vColor;

void main()
{
    //POSITION
    vec4 modelPosition = modelMatrix * vec4(position, 1.0);
                
    // Rotate
    float angle = atan(modelPosition.x, modelPosition.z);
    float distanceToCenter = length(modelPosition.xz);
    float angleOffset = (1.0 / distanceToCenter) * uTime * 3.0;
    angle  = angleOffset;
    modelPosition.x = cos(angle) * distanceToCenter;
    modelPosition.y = sin(angle) * distanceToCenter;

    // Randomness
    modelPosition.xyz  = aRandomness;

    vec4 viewPosition = viewMatrix * modelPosition;
    vec4 projectedPosition = projectionMatrix * viewPosition;
    gl_Position = projectedPosition;

    //SIZE
    gl_PointSize = uSize * aScale;
    gl_PointSize *= (1.0 / - viewPosition.z);

    //COLOR
    vColor = color;
}
 

и шейдер фрагментов

 varying vec3 vColor;
uniform float vAlpha;

void main()
{
    //LIGHT PATTERN
    float strength = distance(gl_PointCoord, vec2(0.5));
    strength = 1.0 - strength;
    strength = pow(strength, 8.0);

    //FINAL COLOR
    vec3 color = mix(vec3(0.0), vColor, strength);
    gl_FragColor = vec4(color, vAlpha);
}
 

. Итак, мой вопрос вот в чем.Как можно перемещать объект по сцене, не меняя его первоначальный вид (например, галактика/портал). Поскольку я новичок в трех js, единственный известный мне способ перемещения объекта-это подобрать сетку и установить ее положение в соответствии с тем, что необходимо. Проблема, с которой я сейчас сталкиваюсь, заключается в том, что точки движутся вокруг центральной точки. Когда я пытаюсь переместить сетку, вся галактика распадается. Каков здесь правильный подход, чтобы переместить всю галактику , скажем, на 2,0 по оси x, y или z? Я был бы очень признателен за объяснение того, почему это также происходит. Заранее спасибо.

Комментарии:

1. Сможете ли вы преобразовать опубликованный вами код в фрагмент, пригодный для выполнения? Было бы намного легче наблюдать за тем, что происходит, если бы мы могли запустить всю систему.

2. Кодовый код Извиняюсь за опоздание с ответом. Я терял клетки мозга, пытаясь понять это, но без особого результата :/ . Я надеюсь, что кодовая панель работает. @TheJim01

3. @TheJim01 Как вы можете видеть в коде, вся эта штука с «вихрем» находится в середине экрана. Что я хочу сделать, так это попытаться переместить его вверх и вниз, влево или вправо, как обычный объект с тремя точками. С помощью простых сеток это довольно просто, я просто задаю позицию-например, mesh.position.set(3, 3, 3) — и все работает нормально. Но в связи с тем, что мой галактический объект сделан с точками, необходимо использовать другой подход. Скорее всего, это связано с математикой, в которой я, честно говоря, очень плохо разбираюсь.