Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions benches/apps/boids-react/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
13 changes: 13 additions & 0 deletions benches/apps/boids-react/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
31 changes: 31 additions & 0 deletions benches/apps/boids-react/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "@app/boids-react",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "oxlint",
"preview": "vite preview"
},
"dependencies": {
"@app/bench-tools": "workspace:*",
"@react-three/drei": "catalog:",
"@react-three/fiber": "catalog:",
"directed": "catalog:",
"koota": "workspace:*",
"react": "catalog:",
"react-dom": "catalog:",
"three": "catalog:"
},
"devDependencies": {
"@config/typescript": "workspace:*",
"@types/react": "catalog:",
"@types/react-dom": "catalog:",
"@types/three": "catalog:",
"@vitejs/plugin-react": "^4.2.1",
"@vitejs/plugin-react-swc": "^3.5.0",
"vite": "catalog:"
}
}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ export const schedule = new Schedule<{ world: World }>();
schedule.add(updateTime);
schedule.add(updateSpatialHashing);
schedule.add(updateNeighbors);
schedule.add(updateCoherence);
schedule.add(updateSeparation);
schedule.add(updateAlignment);
// schedule.add(updateCoherence);
// schedule.add(updateSeparation);
// schedule.add(updateAlignment);
schedule.add(avoidEdges);
schedule.add(applyForces);
schedule.add(moveBoids);
Expand Down
1 change: 1 addition & 0 deletions benches/apps/boids-react/src/vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="vite/client" />
File renamed without changes.
5 changes: 5 additions & 0 deletions benches/apps/boids-react/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"extends": "@config/typescript/react.json",
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}
4 changes: 4 additions & 0 deletions benches/apps/boids-react/tsconfig.node.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "@config/typescript/node.json",
"include": ["*.config.ts"]
}
6 changes: 3 additions & 3 deletions benches/apps/boids/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<title>Vite + TS</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
13 changes: 2 additions & 11 deletions benches/apps/boids/package.json
Original file line number Diff line number Diff line change
@@ -1,31 +1,22 @@
{
"name": "@app/boids",
"private": true,
"version": "0.0.0",
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "oxlint",
"preview": "vite preview"
},
"dependencies": {
"@app/bench-tools": "workspace:*",
"@react-three/drei": "catalog:",
"@react-three/fiber": "catalog:",
"directed": "catalog:",
"@sim/boids": "workspace:*",
"koota": "workspace:*",
"react": "catalog:",
"react-dom": "catalog:",
"three": "catalog:"
},
"devDependencies": {
"@config/typescript": "workspace:*",
"@types/react": "catalog:",
"@types/react-dom": "catalog:",
"@types/three": "catalog:",
"@vitejs/plugin-react": "^4.2.1",
"@vitejs/plugin-react-swc": "^3.5.0",
"vite": "catalog:"
}
}
67 changes: 67 additions & 0 deletions benches/apps/boids/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { initStats } from '@app/bench-tools';
import { actions, CONFIG, schedule, world } from '@sim/boids';
import { trait } from 'koota';
import * as THREE from 'three';
import { scene } from './scene';
import './styles.css';
import { init } from './systems/init';
import { render } from './systems/render';
import { syncThreeObjects } from './systems/syncThreeObjects';

// Renderer
export const renderer = new THREE.WebGLRenderer({
antialias: true,
powerPreference: 'high-performance',
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Camera
const aspect = window.innerWidth / window.innerHeight;
export const camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);

function onWindowResize() {
const aspect = window.innerWidth / window.innerHeight;
camera.aspect = aspect;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}

window.addEventListener('resize', onWindowResize);

// Camera position
camera.position.set(0, 0, 100);
camera.lookAt(0, 0, 0);

// Add view systems to the schedule
schedule.add(syncThreeObjects, { after: 'update' });
schedule.build();

// Add Three resources to the world
export const Three = trait({ renderer, camera, scene });
world.add(Three);

// Init stats
const { updateStats, measure, create } = initStats({ Boids: () => CONFIG.initialCount });
create();

// Init the scene
init({ world });

// Spawn the initial boids
const { spawnBoid } = actions(world);
for (let i = 0; i < CONFIG.initialCount; i++) {
spawnBoid();
}

// Run the simulation
const main = async () => {
measure(async () => {
schedule.run({ world });
render({ world });
updateStats();
});
requestAnimationFrame(main);
};

requestAnimationFrame(main);
4 changes: 4 additions & 0 deletions benches/apps/boids/src/scene.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import * as THREE from 'three';

export const scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000);
4 changes: 4 additions & 0 deletions benches/apps/boids/src/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
body {
margin: 0;
padding: 0;
}
30 changes: 30 additions & 0 deletions benches/apps/boids/src/systems/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { CONFIG } from '@sim/boids';
import type { World } from 'koota';
import * as THREE from 'three';
import { camera, renderer } from '../main';
import { scene } from '../scene';
import { InstancedMesh } from '../traits/InstancedMesh';

let inited = false;

const zeroScaleMatrix = new THREE.Matrix4().makeScale(0, 0, 0);

export function init({ world }: { world: World }) {
if (inited) return;

// I'm not sure why it matters, but you can't set iniitial radius to 1 or everything is invisible.
const geometry = new THREE.SphereGeometry(1, 12, 12);
const material = new THREE.MeshBasicMaterial({ color: new THREE.Color().setRGB(1, 1, 1) });
const instancedMesh = new THREE.InstancedMesh(geometry, material, CONFIG.initialCount + 200);

// Set initial scale to zero
for (let i = 0; i < instancedMesh.count; i++) instancedMesh.setMatrixAt(i, zeroScaleMatrix);

scene.add(instancedMesh);
world.spawn(InstancedMesh({ object: instancedMesh }));

// Compile Three shaders.
renderer.compile(scene, camera);

inited = true;
}
7 changes: 7 additions & 0 deletions benches/apps/boids/src/systems/render.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { World } from 'koota';
import { Three } from '../main';

export const render = ({ world }: { world: World }) => {
const { renderer, scene, camera } = world.get(Three)!;
renderer.render(scene, camera);
};
28 changes: 28 additions & 0 deletions benches/apps/boids/src/systems/syncThreeObjects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Position } from '@sim/boids';
import type { World } from 'koota';
import * as THREE from 'three';
import { InstancedMesh } from '../traits/InstancedMesh';

const dummy = new THREE.Object3D();
const dummyColor = new THREE.Color();

export const syncThreeObjects = ({ world }: { world: World }) => {
const instanceEnt = world.queryFirst(InstancedMesh);
if (instanceEnt === undefined) return;

const instancedMesh = instanceEnt.get(InstancedMesh)!.object;

world.query(Position).updateEach(([position], entity) => {
dummy.position.set(position.x, position.y, 0);
dummy.scale.set(1, 1, 1);

dummy.updateMatrix();
instancedMesh.setMatrixAt(entity.id(), dummy.matrix);

dummyColor.setRGB(0.5, 0.5, 0.5);
instancedMesh.setColorAt(entity.id(), dummyColor);
});

instancedMesh.instanceMatrix.needsUpdate = true;
instancedMesh.instanceColor!.needsUpdate = true;
};
4 changes: 4 additions & 0 deletions benches/apps/boids/src/traits/InstancedMesh.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { trait } from 'koota';
import type * as THREE from 'three';

export const InstancedMesh = trait({ object: null! as THREE.InstancedMesh });
2 changes: 1 addition & 1 deletion benches/apps/boids/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"extends": "@config/typescript/react.json",
"extends": "@config/typescript/base.json",
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}
10 changes: 10 additions & 0 deletions benches/apps/boids/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { defineConfig } from 'vite';

export default defineConfig({
server: {
headers: {
'Cross-Origin-Embedder-Policy': 'require-corp',
'Cross-Origin-Opener-Policy': 'same-origin',
},
},
});
3 changes: 3 additions & 0 deletions benches/sims/boids/.oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["node_modules/@config/oxlint/base.json"]
}
17 changes: 17 additions & 0 deletions benches/sims/boids/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "@sim/boids",
"private": true,
"version": "0.0.1",
"description": "Boids simulation using Koota",
"type": "module",
"main": "./src/index.ts",
"dependencies": {
"@sim/bench-tools": "workspace:*",
"koota": "workspace:*",
"directed": "catalog:"
},
"devDependencies": {
"@config/oxlint": "workspace:*",
"@config/typescript": "workspace:*"
}
}
22 changes: 22 additions & 0 deletions benches/sims/boids/src/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { createActions, TraitInstance } from 'koota';
import { Forces, Position, Velocity } from './traits';
import { randomSphericalDirection } from './utils/random-direction';
import { between } from './utils/between';

export const actions = createActions((world) => ({
spawnBoid: (
position: TraitInstance<typeof Position> = randomSphericalDirection(between(0, 100)),
velocity: TraitInstance<typeof Velocity> = randomSphericalDirection()
) => {
world.spawn(Position(position), Velocity(velocity), Forces);
},
destroyRandomBoid: () => {
const entities = world.query(Position, Velocity);
if (entities.length) entities[Math.floor(Math.random() * entities.length)].destroy();
},
destroyAllBoids: () => {
world.query(Position, Velocity).forEach((entity) => {
entity.destroy();
});
},
}));
7 changes: 7 additions & 0 deletions benches/sims/boids/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const CONFIG = {
initialCount: 500,
maxVelocity: 6,
avoidEdgesFactor: 5,
avoidEdgesMaxDistance: 100,
coherenceFactor: 0.5,
};
7 changes: 7 additions & 0 deletions benches/sims/boids/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export * from './traits';
export { world } from './world';
export { CONFIG } from './config';
export { schedule } from './systems/schedule';
export { actions } from './actions';
export { randomSphericalDirection } from './utils/random-direction';
export { between } from './utils/between';
21 changes: 21 additions & 0 deletions benches/sims/boids/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { measure, requestAnimationFrame } from '@sim/bench-tools';
import { actions } from './actions';
import { CONFIG } from './config';
import { schedule } from './systems/schedule';
import { world } from './world';

// Start the simulation.
const main = async () => {
const { initialCount } = CONFIG;
const { spawnBoid } = actions(world);

// Spawn the initial boids.
for (let i = 0; i < initialCount; i++) {
spawnBoid();
}

await measure(() => schedule.run({ world }));
requestAnimationFrame(main);
};

requestAnimationFrame(main);
Loading