Fix some issues, add the mesh rendering. General code improvements
This commit is contained in:
parent
e4217d3f4d
commit
0410e3d709
20
src/main.mjs
20
src/main.mjs
|
|
@ -1,9 +1,11 @@
|
||||||
import { Thread, supportThreads } from "./utils/workerUtils.mjs";
|
import { Thread, supportThreads } from "./utils/workerUtils.mjs";
|
||||||
import Renderer from "./modules/renderer/renderer.mjs";
|
import Renderer from "./modules/renderer/renderer.mjs";
|
||||||
|
import Noise from '../libs/alea.mjs'
|
||||||
|
import Delaunator from 'https://cdn.skypack.dev/delaunator@5.0.0';
|
||||||
|
|
||||||
(async function()
|
(async function()
|
||||||
{
|
{
|
||||||
globalThis.DEBUG = localStorage.getItem("debug");
|
globalThis.DEBUG = !!localStorage.getItem("debug");
|
||||||
globalThis.VERBOSE = DEBUG && localStorage.getItem("verbose");
|
globalThis.VERBOSE = DEBUG && localStorage.getItem("verbose");
|
||||||
globalThis.TIMINGS = DEBUG && localStorage.getItem("timings");
|
globalThis.TIMINGS = DEBUG && localStorage.getItem("timings");
|
||||||
globalThis.RELEASE = !DEBUG;
|
globalThis.RELEASE = !DEBUG;
|
||||||
|
|
@ -11,15 +13,17 @@ import Renderer from "./modules/renderer/renderer.mjs";
|
||||||
const thread = new Thread("./workers/base.mjs", "model", true);
|
const thread = new Thread("./workers/base.mjs", "model", true);
|
||||||
await thread.setup();
|
await thread.setup();
|
||||||
|
|
||||||
const settings = { x: 200, y: 200, seed: 0, jitter: 0.5, width: window.innerWidth, height: window.innerHeight };
|
//await new Promise(r => setTimeout(r, 3000));
|
||||||
await thread.model.generatePoints(settings);
|
|
||||||
await thread.model.generateTriangles(settings);
|
|
||||||
|
|
||||||
const delaunay = await thread.debug.getDelaunay();
|
const settings = { model: { x: 50, y: 25, seed: 0, jitter: 0.2, }, view: { width: window.innerWidth, height: window.innerHeight, }, };
|
||||||
console.log(delaunay);
|
await thread.global.updateSettings(settings);
|
||||||
|
|
||||||
const view = new Float32Array(await thread.view.lerpToViewport(settings));
|
await thread.model.generateTriangles();
|
||||||
|
|
||||||
|
const view = await thread.view.lerpToViewport();
|
||||||
|
|
||||||
|
const debug = await thread.debug.getAll();
|
||||||
|
|
||||||
Renderer.init();
|
Renderer.init();
|
||||||
Renderer.initGrid(view, settings);
|
Renderer.initGrid(view.position, view.vertices);
|
||||||
})();
|
})();
|
||||||
|
|
@ -23,8 +23,11 @@ class Renderer
|
||||||
this._width = window.innerWidth;
|
this._width = window.innerWidth;
|
||||||
this._height = window.innerHeight;
|
this._height = window.innerHeight;
|
||||||
|
|
||||||
|
this._clock = new Three.Clock();
|
||||||
this._scene = new Three.Scene();
|
this._scene = new Three.Scene();
|
||||||
this._camera = new Three.OrthographicCamera(this._width / - 2, this._width / 2, this._height / 2, this._height / - 2, 0.1, 1000);
|
this._camera = new Three.OrthographicCamera(0, this._width, 0, this._height, 0.1, 1000);
|
||||||
|
this._camera.zoom = 0.98;
|
||||||
|
this._camera.updateProjectionMatrix();
|
||||||
|
|
||||||
Renderer.render();
|
Renderer.render();
|
||||||
}
|
}
|
||||||
|
|
@ -36,22 +39,30 @@ class Renderer
|
||||||
|
|
||||||
this._rAF = requestAnimationFrame(Renderer.render.bind(Renderer));
|
this._rAF = requestAnimationFrame(Renderer.render.bind(Renderer));
|
||||||
|
|
||||||
|
/*this._camera.zoom = 1 + (0.5 + Math.sin(this._clock.getElapsedTime()) / 2) * 5;
|
||||||
|
this._camera.updateProjectionMatrix();*/
|
||||||
|
|
||||||
this._renderer.render(this._scene, this._camera);
|
this._renderer.render(this._scene, this._camera);
|
||||||
}
|
}
|
||||||
static async initGrid(grid, settings) //Share the list of cell and the resolution in the model with the view
|
static async initGrid(position, vertices) //Share the list of cell and the resolution in the model with the view
|
||||||
{
|
{
|
||||||
if(this._threaded)
|
if(this._threaded)
|
||||||
{
|
{
|
||||||
//We can share the cells with the rendering thread because it will only be used as read-only to create the point data
|
//We can share the cells with the rendering thread because it will only be used as read-only to create the point data
|
||||||
await this._renderer_thread.view.lerpToView(grid, settings);
|
await this._renderer_thread.view.lerpToView(position, settings);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const geometry = new Three.BufferGeometry();
|
const geometry = new Three.BufferGeometry();
|
||||||
geometry.setAttribute('position', new Three.Float32BufferAttribute(grid, 3));
|
geometry.setIndex( new Three.Uint32BufferAttribute( vertices, 1 ) );
|
||||||
|
geometry.setAttribute('position', new Three.Float32BufferAttribute( position, 3));
|
||||||
|
|
||||||
const points = new Three.Points(geometry);
|
const material = new Three.MeshBasicMaterial( { color: 0xff0000, wireframe: true, } );
|
||||||
this._scene.add(points);
|
const mesh = new Three.Mesh( geometry, material );
|
||||||
|
this._scene.add( mesh );
|
||||||
|
|
||||||
|
/*const points = new Three.Points( geometry, new Three.PointsMaterial( { size: 3.0 } ) );
|
||||||
|
this._scene.add( points );*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,13 @@ const Constants = {
|
||||||
WAITING: 1,
|
WAITING: 1,
|
||||||
OK: 2,
|
OK: 2,
|
||||||
ERROR: 3,
|
ERROR: 3,
|
||||||
|
LOG: 4,
|
||||||
},
|
},
|
||||||
REQUEST: {
|
REQUEST: {
|
||||||
WAKEUP: 1,
|
WAKEUP: 1,
|
||||||
SETUP: 2,
|
SETUP: 2,
|
||||||
CALL: 3,
|
CALL: 3,
|
||||||
TERMINATE: 4,
|
TERMINATE: 4
|
||||||
},
|
},
|
||||||
TRANSFERABLE: [
|
TRANSFERABLE: [
|
||||||
ArrayBuffer,
|
ArrayBuffer,
|
||||||
|
|
@ -101,6 +102,17 @@ function wrapper(thread, mod, fn)
|
||||||
function onmessage(thread)
|
function onmessage(thread)
|
||||||
{
|
{
|
||||||
return function(e) {
|
return function(e) {
|
||||||
|
if(e.data[0] === Constants.STATE.LOG)
|
||||||
|
{
|
||||||
|
globalThis.VERBOSE && console.debug(ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(e.data[0] === Constants.STATE.ERROR)
|
||||||
|
{
|
||||||
|
console.error(e.data[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const ret = parseReturns(e.data);
|
const ret = parseReturns(e.data);
|
||||||
globalThis.VERBOSE && console.debug(`Received message from ${thread._name} containing `, ret);
|
globalThis.VERBOSE && console.debug(`Received message from ${thread._name} containing `, ret);
|
||||||
globalThis.TIMINGS && thread._calledFn !== "" && console.timeEnd("Measuring " + thread._calledMod + "." + thread._calledFn);
|
globalThis.TIMINGS && thread._calledFn !== "" && console.timeEnd("Measuring " + thread._calledMod + "." + thread._calledFn);
|
||||||
|
|
@ -178,6 +190,16 @@ function send(ret)
|
||||||
postMessage([Constants.STATE.OK, ret], getTransferables(ret));
|
postMessage([Constants.STATE.OK, ret], getTransferables(ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function error(err)
|
||||||
|
{
|
||||||
|
postMessage([Constants.STATE.ERROR, err]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function log(msg)
|
||||||
|
{
|
||||||
|
postMessage([Constants.STATE.LOG, msg]);
|
||||||
|
}
|
||||||
|
|
||||||
class Process
|
class Process
|
||||||
{
|
{
|
||||||
static _isSetup = false;
|
static _isSetup = false;
|
||||||
|
|
@ -187,10 +209,11 @@ class Process
|
||||||
Process._isSetup = true;
|
Process._isSetup = true;
|
||||||
Process._customFn = {};
|
Process._customFn = {};
|
||||||
globalThis.onmessage = Process.onmessage;
|
globalThis.onmessage = Process.onmessage;
|
||||||
|
globalThis.onerror = Process.onerror;
|
||||||
}
|
}
|
||||||
static onmessage(e)
|
static onmessage(e)
|
||||||
{
|
{
|
||||||
globalThis.VERBOSE && console.debug(`Received `, e.data);
|
globalThis.VERBOSE && log(`Received `, e.data);
|
||||||
if(e && e.data)
|
if(e && e.data)
|
||||||
{
|
{
|
||||||
switch(e.data[0])
|
switch(e.data[0])
|
||||||
|
|
@ -210,7 +233,14 @@ class Process
|
||||||
|
|
||||||
case Constants.REQUEST.CALL:
|
case Constants.REQUEST.CALL:
|
||||||
const args = e.data[3];
|
const args = e.data[3];
|
||||||
|
try
|
||||||
|
{
|
||||||
send(Process._customFn[e.data[1]][e.data[2]](...args));
|
send(Process._customFn[e.data[1]][e.data[2]](...args));
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
error(e);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Constants.REQUEST.TERMINATE:
|
case Constants.REQUEST.TERMINATE:
|
||||||
|
|
|
||||||
|
|
@ -4,33 +4,37 @@ import Delaunator from 'https://cdn.skypack.dev/delaunator@5.0.0';
|
||||||
|
|
||||||
let settings = {};
|
let settings = {};
|
||||||
const model = {};
|
const model = {};
|
||||||
|
const view = {};
|
||||||
|
|
||||||
//Settings contains x, y, seed, jitter
|
function lerp(a, b, x)
|
||||||
function generatePoints(settings)
|
|
||||||
{
|
{
|
||||||
const noise = Noise(settings.seed);
|
return a + (b - a) * x;
|
||||||
const grid = new Float32Array(settings.x * settings.y * 2);
|
}
|
||||||
|
function inverse_lerp(a, b, x)
|
||||||
|
{
|
||||||
|
return (x - a) / (b - a);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Settings model contains x, y, seed, jitter
|
||||||
|
function generateTriangles()
|
||||||
|
{
|
||||||
|
const rand = Noise(settings.model.seed);
|
||||||
|
const grid = new Float32Array(settings.model.x * settings.model.y * 2);
|
||||||
for(let i = grid.length * 2 - 2; i > 0; i -= 2)
|
for(let i = grid.length * 2 - 2; i > 0; i -= 2)
|
||||||
{
|
{
|
||||||
const _x = i / 2 % settings.x;
|
const _x = i / 2 % settings.model.x;
|
||||||
const _y = (i / 2 - _x) / settings.x;
|
const _y = (i / 2 - _x) / settings.model.x;
|
||||||
|
|
||||||
grid[i] = _x + (noise() - 0.5) * settings.jitter;
|
const angle = lerp(0, Math.PI * 2, rand());
|
||||||
grid[i + 1] = _y + (noise() - 0.5) * settings.jitter;
|
const magnitude = lerp(0, settings.model.jitter, rand());
|
||||||
|
|
||||||
|
grid[i ] = _x + Math.sin(angle) * magnitude;
|
||||||
|
grid[i + 1] = _y + Math.cos(angle) * magnitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
model.grid = grid;
|
model.delaunay = new Delaunator(grid);
|
||||||
}
|
}
|
||||||
function generateTriangles(settings)
|
function generateVoronoi()
|
||||||
{
|
|
||||||
if(!model.hasOwnProperty("grid"))
|
|
||||||
generatePoints(settings);
|
|
||||||
|
|
||||||
const delaunay = new Delaunator(model.grid);
|
|
||||||
|
|
||||||
model.delaunay = delaunay;
|
|
||||||
}
|
|
||||||
function generateVoronoi(settings)
|
|
||||||
{
|
{
|
||||||
function circumcenter(a, b, c)
|
function circumcenter(a, b, c)
|
||||||
{
|
{
|
||||||
|
|
@ -44,30 +48,52 @@ function generateVoronoi(settings)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const coords = model.delaunay.coords;
|
||||||
|
const tri = model.delaunay.triangles;
|
||||||
|
|
||||||
|
for(let i = model.delaunay.trianglesLen - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
tri[]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDelaunay()
|
function getDelaunay()
|
||||||
{
|
{
|
||||||
return model.delaunay;
|
return model.delaunay;
|
||||||
}
|
}
|
||||||
|
function getAll()
|
||||||
function lerpToViewport(settings)
|
|
||||||
{
|
{
|
||||||
const size = settings.x * settings.y;
|
return { model: model, view: view };
|
||||||
const grid = model.grid;
|
}
|
||||||
const view = new Float32Array(size * 3);
|
|
||||||
|
//Settings view contains width & height
|
||||||
|
function lerpToViewport()
|
||||||
|
{
|
||||||
|
const size = settings.model.x * settings.model.y;
|
||||||
|
const grid = model.delaunay.coords;
|
||||||
|
view.grid = new Float32Array(size * 3);
|
||||||
for(let i = size - 1; i >= 0; --i)
|
for(let i = size - 1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
view[i * 3] = settings.width * grid[i * 2] / settings.x - settings.width / 2;
|
view.grid[i * 3 ] = lerp(0, settings.view.width , inverse_lerp(0, settings.model.x - 1, grid[i * 2 ]));
|
||||||
view[i * 3 + 1] = settings.height * grid[i * 2 + 1] / settings.y - settings.height / 2;
|
view.grid[i * 3 + 1] = lerp(0, settings.view.height, inverse_lerp(0, settings.model.y - 1, grid[i * 2 + 1]));
|
||||||
view[i * 3 + 2] = -3;
|
view.grid[i * 3 + 2] = -3;
|
||||||
}
|
}
|
||||||
return view.buffer;
|
|
||||||
|
return { position: view.grid, vertices: model.delaunay.triangles };
|
||||||
}
|
}
|
||||||
|
|
||||||
//Process.register is the equivalent of export
|
//Process.register is the equivalent of export
|
||||||
Process.register("model", [generatePoints, generateTriangles]);
|
Process.register("model", [generateTriangles]);
|
||||||
Process.register("view", [lerpToViewport]);
|
Process.register("view", [lerpToViewport]);
|
||||||
|
|
||||||
Process.register("debug", [getDelaunay]);
|
function updateSettings(s)
|
||||||
|
{
|
||||||
|
const old_settings = settings;
|
||||||
|
settings = s;
|
||||||
|
|
||||||
|
//Check which property has change and regenerate the appropriate objects.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Process.register("global", [updateSettings]);
|
||||||
|
Process.register("debug", [getDelaunay, getAll]);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue