~nasser/lospec-2

6d8b2118c42634ea0f4535e0545ea813df072e87 — Ramsey Nasser 7 months ago 7adc2c5
Progress on sheepies
2 files changed, 65 insertions(+), 113 deletions(-)

M gizmos.js
M main.js
M gizmos.js => gizmos.js +4 -57
@@ 38,66 38,13 @@ export default class {
    line(a, b, color1 = new THREE.Color('white'), color2 = color1) {
        if (this.index >= this.size)
            return;
        if (Number.isNaN(a.x) || Number.isNaN(a.y) || Number.isNaN(a.z) ||
            Number.isNaN(b.x) || Number.isNaN(b.y) || Number.isNaN(b.z))
            throw 'nan'
        this.vertsAttribute.setXYZ(this.index, a.x, a.y, a.z)
        this.vertsAttribute.setXYZ(this.index + 1, b.x, b.y, b.z)
        this.colorsAttribute.setXYZW(this.index, color1.r, color1.g, color1.b, 1.0)
        this.colorsAttribute.setXYZW(this.index + 1, color2.r, color2.g, color2.b, 1.0)
        this.index += 2
    }
}

// export const colors = {
//     red: new THREE.Color(1, 0, 0),
//     green: new THREE.Color(0, 1, 0),
//     blue: new THREE.Color(0, 0, 1),
//     white: new THREE.Color(1, 1, 1),
//     clear: new THREE.Color(0, 0, 0)
// }

// export function init(scene, options) {
//     options = options || {}
//     const material = new THREE.LineBasicMaterial({
//         color: 0xffffff,
//         vertexColors: THREE.VertexColors
//     })
//     material.depthTest = false // hack

//     const vertCount = options.size || 2000

//     const geometry = new THREE.BufferGeometry()
//     const vertices = Float32Array.from(Array(vertCount * 3).fill(0))
//     const colors = Float32Array.from(Array(vertCount * 4).fill(1))
//     geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
//     geometry.setAttribute('color', new THREE.BufferAttribute(colors, 4));
//     vertsAttribute = geometry.getAttribute('position')
//     colorsAttribute = geometry.getAttribute('color')

//     gizmoObject = new THREE.LineSegments(geometry, material)
//     gizmoObject.renderOrder = 1 // hack
//     gizmoObject.userData.size = vertCount
//     scene.add(gizmoObject)
// }

// export function reset() {
//     index = 0
// }

// export function draw() {
//     vertsAttribute.needsUpdate = true
//     vertsAttribute.updateRange.count = index * 3
//     colorsAttribute.needsUpdate = true
//     colorsAttribute.updateRange.count = index * 4
//     gizmoObject.geometry.setDrawRange(0, index)
//     gizmoObject.geometry.computeBoundingSphere()
// }

// export function line(a, b, color) {
//     if (index >= gizmoObject.userData.size)
//         return;
//     color = color || colors.white
//     vertsAttribute.setXYZ(index, a.x, a.y, a.z)
//     vertsAttribute.setXYZ(index + 1, b.x, b.y, b.z)
//     colorsAttribute.setXYZW(index, color.r, color.g, color.b, 1.0)
//     colorsAttribute.setXYZW(index + 1, color.r, color.g, color.b, 1.0)
//     index += 2
// }
}
\ No newline at end of file

M main.js => main.js +61 -56
@@ 22,13 22,13 @@ const INPUT = new Input([
const scene = new THREE.Scene()

const camera = new THREE.OrthographicCamera()
camera.position.set(10, 10, 10);
camera.position.setFromSphericalCoords(
    10,
    1000,
    Math.PI / 3,
    Math.PI / 4
)
camera.lookAt(scene.position);
camera.scale.y = -1

const renderer = new THREE.WebGLRenderer()
document.body.appendChild(renderer.domElement)


@@ 38,11 38,13 @@ renderer.domElement.style.imageRendering = "pixelated"
function resize() {
    const aspect = ls16.width / ls16.height
    const smallest = Math.min(ls16.width, ls16.height)
    const d = 2
    const d = 200
    camera.left = -d
    camera.right = d
    camera.top = -d
    camera.bottom = d
    camera.near = 1
    camera.far = 10000
    camera.updateProjectionMatrix()
    renderer.setSize(smallest, smallest, false)
    const scale = Math.floor(Math.min(window.innerWidth / ls16.width, window.innerHeight / ls16.height))


@@ 52,7 54,7 @@ function resize() {
window.addEventListener('resize', resize)
resize()

scene.add(new THREE.GridHelper(10, 5))
scene.add(new THREE.GridHelper(500, 8))
// new OrbitControls(camera, renderer.domElement)

const GIZMOS = new Gizmos()


@@ 67,73 69,76 @@ new THREE.TextureLoader().load(ls16.palette, palette => {
    composer.addPass(pass)
})

const paletteColors = [
    new THREE.Color(0xff032b),
    new THREE.Color(0x800034),
    new THREE.Color(0xffff0d),
    new THREE.Color(0xff8f00),
    new THREE.Color(0x0aff0a),
    new THREE.Color(0x007062),
    new THREE.Color(0x0dffff),
    new THREE.Color(0x3c80db),
    new THREE.Color(0x2929ff),
    new THREE.Color(0x2d006e),
    new THREE.Color(0xff08ff),
    new THREE.Color(0x6e0085),
    new THREE.Color(0x260a34),
    new THREE.Color(0x000000),
    new THREE.Color(0xffffff),
    new THREE.Color(0x7d7da3),
]

scene.add(new THREE.DirectionalLight())
scene.add(new THREE.AmbientLight())

function drawSheep(position, color = 'white', size = 8) {
    const v = new THREE.Vector3(Math.floor(position.x), 0, Math.floor(position.y))
    GIZMOS.line(v, v.clone().add(new THREE.Vector3(0, size, 0)), new THREE.Color(color))
}

function line2d(a, b, color) {
    GIZMOS.line(new THREE.Vector3(a.x, 0, a.y), new THREE.Vector3(b.x, 0, b.y), color)
}

SCHED.add(function* () {
    const geometry = new THREE.BoxGeometry(0.5, 0.5, 0.5);
    const material = new THREE.MeshStandardMaterial({ color: paletteColors[1], wireframe: true });
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);

    function getColor(t, colors = paletteColors) {
        const l = colors.length - 1
        const tt = t * l
        const a = tt - Math.floor(tt)
        const i = Math.floor(tt)
        const j = Math.ceil(tt) == i ? i + 1 : Math.ceil(tt)
        return new THREE.Color().lerpColors(colors[i], colors[j], a)
    const sheepies = []
    for (let i = 0; i < 200; i++) {
        sheepies.push({
            position: new THREE.Vector2(Math.random() * 80, Math.random() * 80),
            velocity: new THREE.Vector2()
        })
    }

    function getSheepNear(p, except = null, threshold = 10) {
        const near = []
        for (const sheep of sheepies)
            if (sheep !== except && sheep.position.distanceTo(p) < threshold)
                near.push(sheep)
        return near
    }

    let t = 0
    const cohesionFactor = 0.005

    while (true) {
        GIZMOS.line(new THREE.Vector3(3, 0, 1.1), new THREE.Vector3(1, 0, 2), new THREE.Color('blue'))
        GIZMOS.line(new THREE.Vector3(3, 0, 1.1), new THREE.Vector3(3, -.2, 1.1), new THREE.Color('white'))
        GIZMOS.line(new THREE.Vector3(1, 0, 2), new THREE.Vector3(-1, 0, 1), new THREE.Color('red'))
        GIZMOS.line(new THREE.Vector3(1, 0, 2), new THREE.Vector3(1, -.2, 2), new THREE.Color('white'))
        GIZMOS.line(new THREE.Vector3(-1, 0, 1), new THREE.Vector3(-1.5, 0, -2), new THREE.Color('blue'))
        GIZMOS.line(new THREE.Vector3(-1, 0, 1), new THREE.Vector3(-1,-.2, 1), new THREE.Color('white'))
        GIZMOS.line(new THREE.Vector3(-1.5, 0, -2), new THREE.Vector3(3, 0, 1.1), new THREE.Color('yellow'))
        GIZMOS.line(new THREE.Vector3(-1.5, 0, -2), new THREE.Vector3(-1.5, -.2, -2), new THREE.Color('white'))
        // cube.rotateX(INPUT.now.time.delta)
        // cube.rotateY(INPUT.now.time.delta * 0.25)
        cube.material.color = getColor(t)
        t = (t + INPUT.now.time.delta * 0.1) % 1

        camera.position.setFromSphericalCoords(
            10,
            Math.PI / 3,
            Math.PI / 4 + INPUT.now.time.now * 0.5
        )
        camera.lookAt(scene.position);
        
        for (const sheep of sheepies) {
            const neighborhood = getSheepNear(sheep.position, sheep, 20)
            if (neighborhood.length > 0) {
                const centroid = new THREE.Vector2()
                const avoidMovement = new THREE.Vector2()
                const averageVelocity = new THREE.Vector2()
                for (const neighbor of neighborhood) {
                    centroid.add(neighbor.position)
                    avoidMovement.add(sheep.position.clone().sub(neighbor.position).multiplyScalar(2 / sheep.position.distanceTo(neighbor.position)))
                    averageVelocity.add(neighbor.velocity)
                }
                averageVelocity.divideScalar(neighborhood.length)
                centroid.divideScalar(neighborhood.length)
                sheep.velocity.add(centroid.clone().sub(sheep.position).multiplyScalar(1))
                sheep.velocity.add(avoidMovement.multiplyScalar(2))
                sheep.velocity.add(averageVelocity.addScaledVector(sheep.velocity, 4))

                sheep.velocity.normalize()
                sheep.position.addScaledVector(sheep.velocity, 0.1)
                drawSheep(sheep.position)
                // line2d(sheep.position, centroid, 'yellow')
            } else {
                sheep.position.add(sheep.velocity.clone().multiplyScalar(0.1))
                drawSheep(sheep.position, 'gray')

            }

        }
        yield
    }
})

function tick() {
    requestAnimationFrame(tick)
    GIZMOS.reset()
    INPUT.collect()
    SCHED.tick()
    GIZMOS.draw()
    composer.render()
}
tick()
\ No newline at end of file