Boids Simulation
{
"packages":["numpy"]
}
Parameter 01 0.0
from pyodide.ffi import create_proxy, to_js
from js import window
from js import Math
from js import THREE
from js import Object
from js import document
import asyncio
import js, pyodide
scene = THREE.Scene.new()
setcolor = "#bbbbbb"
scene.background = THREE.Color.new(setcolor)
renderer = THREE.WebGLRenderer.new()
renderer.antialias = True
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild( renderer.domElement )
camera = THREE.PerspectiveCamera.new(75, window.innerWidth / window.innerHeight, 0.1, 1000.0 )
camera.position.set(40,40,45)
controls = THREE.OrbitControls.new(camera, renderer.domElement)
controls.listenToKeyEvents(window)
def window_onsize(event):
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize( window.innerWidth, window.innerHeight )
window.onresize = window_onsize
scene.pause = True
# ================ Light setting ====================
ambientLight = THREE.AmbientLight.new(0xaaaaaa)
scene.add(ambientLight)
dirLight = THREE.DirectionalLight.new(0xffffff)
dirLight.position.set(1,1,1)
dirLight.castSHadow = True
scene.add(dirLight)
lightBack = THREE.PointLight.new(0x0FFFFF, 1)
lightBack.position.set(0, -3, -1)
scene.add(lightBack)
# ===========Creating Bound Box ============
## You can modify the size of box
boundRange = 25
bound_material = THREE.MeshStandardMaterial.new()
bound_material.color = THREE.Color.new(0x444488)
bound_material.transparent = True
bound_material.opacity = 0.1
edge_material = THREE.LineBasicMaterial.new()
edge_material.color = THREE.Color.new(0xfffffff)
bound = THREE.Mesh.new(THREE.BoxGeometry.new(boundRange * 2, boundRange * 2, boundRange * 2), bound_material)
edges = THREE.LineSegments.new(THREE.EdgesGeometry.new(THREE.BoxGeometry.new(boundRange * 2, boundRange * 2, boundRange * 2)), )
scene.add(bound)
scene.add(edges)
#===================== CORE =====================
import numpy as np
import math
boidsP = None
boidsV = None
boidsN = 0
boidsShapes = []
def create_boids(num):
global boidsN, boidsP, boidsV, boidsShapes
boidsN = num
boidsP = -np.random.rand(num, 3) * (boundRange * 2) + boundRange
boidsV = -np.random.rand(num, 3) * 3 + 1.5
for i in range(num):
geometry = THREE.CylinderGeometry.new(0.0,0.75,2.25,4,1)
material = THREE.MeshPhongMaterial.new()
material.color = THREE.Color.new(0x993333)
material.flatShading = True
boidShape = THREE.Mesh.new(geometry, material)
boidsShapes.append(boidShape)
scene.add(boidShape)
def reset_boids():
global boidsP, boidsV, boidsN, boundRange
boidsP = -np.random.rand(boidsN, 3) * (boundRange * 2) + boundRange
boidsV = -np.random.rand(boidsN, 3) * 3 + 1.5
def draw_boids(): ## Sync boidData and boidShape
global boidsV, boidsShapes
for i in range(boidsN):
boidsShapes[i].position.set(boidsP[i][0], boidsP[i][1], boidsP[i][2])
## TODO Update rotation to align the boid heading direction with its velocity
## Hint : boidsShapes[i].setRotationFromAxisAngle(THREE.Vector3.new(axis[0], axis[1], axis[2]), angle) (Find the axis and angle)
def update_boids():
global boidsP, boidsV, boidsN
## TODO Implement the velocity update rules
## vel1 = rule1()
## vel2 = rule2()
## vel3 = rule3()
## Dummy (Remove this line)
boidsV = -np.random.rand(boidsN, 3) * 2.0 + 1.0
boidsP += boidsV ## + vel1 + vel2 + vel3 ...
def run():
scene.pause = not scene.pause
def animate():
if not scene.pause:
update_boids()
draw_boids()
renderer.render(scene, camera)
## Example code for slider
def slider01_function(event):
value = int(Element("Slider01").value) * 0.01
document.getElementById("SliderValue01").innerHTML = str(round(value, 2))
document.getElementById("Slider01").oninput = slider01_function
async def main():
boid_num = 50
create_boids(boid_num)
draw_boids()
while True:
animate()
await asyncio.sleep(0.0001)
asyncio.ensure_future(main())