make voronoi go really fast
This commit is contained in:
parent
68a58e24d7
commit
720520f4b7
5 changed files with 144 additions and 50 deletions
|
@ -9,6 +9,7 @@ import { Texture } from "./webgl/texture";
|
||||||
import { callbackify } from "util";
|
import { callbackify } from "util";
|
||||||
import { defaultLabelFactory, LabelFactory, Align, Label } from "./webgl/text";
|
import { defaultLabelFactory, LabelFactory, Align, Label } from "./webgl/text";
|
||||||
import Voronoi = require("./voronoi/voronoi-core");
|
import Voronoi = require("./voronoi/voronoi-core");
|
||||||
|
import { VoronoiBuilder } from "./voronoi/voronoi";
|
||||||
|
|
||||||
function f32v(ptr: number, size: number): Float32Array {
|
function f32v(ptr: number, size: number): Float32Array {
|
||||||
return new Float32Array(memory.buffer, ptr, size);
|
return new Float32Array(memory.buffer, ptr, size);
|
||||||
|
@ -91,6 +92,8 @@ class GameInstance {
|
||||||
renderer: Renderer;
|
renderer: Renderer;
|
||||||
planet_count: number;
|
planet_count: number;
|
||||||
|
|
||||||
|
vor_builder: VoronoiBuilder;
|
||||||
|
|
||||||
vor_counter = 3;
|
vor_counter = 3;
|
||||||
use_vor = true;
|
use_vor = true;
|
||||||
playing = true; // 0 is paused, 1 is playing but not rerendered, 2 is playing and rerendered
|
playing = true; // 0 is paused, 1 is playing but not rerendered, 2 is playing and rerendered
|
||||||
|
@ -120,25 +123,25 @@ class GameInstance {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const indexBuffer = new IndexBuffer(GL, [
|
// const indexBuffer = new IndexBuffer(GL, [
|
||||||
0, 1, 2,
|
// 0, 1, 2,
|
||||||
1, 2, 3,
|
// 1, 2, 3,
|
||||||
]);
|
// ]);
|
||||||
|
|
||||||
const positionBuffer = new VertexBuffer(GL, [
|
// const positionBuffer = new VertexBuffer(GL, [
|
||||||
-1, -1,
|
// -1, -1,
|
||||||
-1, 1,
|
// -1, 1,
|
||||||
1, -1,
|
// 1, -1,
|
||||||
1, 1,
|
// 1, 1,
|
||||||
]);
|
// ]);
|
||||||
|
|
||||||
const layout = new VertexBufferLayout();
|
// const layout = new VertexBufferLayout();
|
||||||
layout.push(GL.FLOAT, 2, 4, "a_pos");
|
// layout.push(GL.FLOAT, 2, 4, "a_pos");
|
||||||
|
|
||||||
const vao = new VertexArray();
|
// const vao = new VertexArray();
|
||||||
vao.addBuffer(positionBuffer, layout);
|
// vao.addBuffer(positionBuffer, layout);
|
||||||
|
|
||||||
this.renderer.addToDraw(indexBuffer, vao, this.vor_shader);
|
// this.renderer.addToDraw(indexBuffer, vao, this.vor_shader);
|
||||||
|
|
||||||
// Setup key handling
|
// Setup key handling
|
||||||
document.addEventListener('keydown', this.handleKey.bind(this));
|
document.addEventListener('keydown', this.handleKey.bind(this));
|
||||||
|
@ -146,6 +149,22 @@ class GameInstance {
|
||||||
// List of [(x, y, r)] for all planets
|
// List of [(x, y, r)] for all planets
|
||||||
const planets = f32v(game.get_planets(), this.planet_count * 3);
|
const planets = f32v(game.get_planets(), this.planet_count * 3);
|
||||||
|
|
||||||
|
const planet_points = [];
|
||||||
|
for(let i = 0; i < planets.length; i += 3) {
|
||||||
|
planet_points.push({'x': planets[i], 'y': planets[i+1]});
|
||||||
|
}
|
||||||
|
const _bbox = f32v(game.get_viewbox(), 4);
|
||||||
|
const bbox = {
|
||||||
|
'xl': _bbox[0], 'xr': _bbox[0] + _bbox[2],
|
||||||
|
'yt': _bbox[1], 'yb': _bbox[1] + _bbox[3]
|
||||||
|
};
|
||||||
|
|
||||||
|
this.vor_builder = new VoronoiBuilder(GL, this.vor_shader, planet_points, bbox);
|
||||||
|
this.renderer.addRenderable(this.vor_builder.getRenderable());
|
||||||
|
const players= new Array(this.planet_count).fill(undefined).map((_, i) => i);
|
||||||
|
console.log(players);
|
||||||
|
this.vor_builder.updateOwners(GL, players);
|
||||||
|
|
||||||
for (let i = 0; i < this.planet_count; i++) {
|
for (let i = 0; i < this.planet_count; i++) {
|
||||||
{
|
{
|
||||||
const transform = new UniformMatrix3fv([
|
const transform = new UniformMatrix3fv([
|
||||||
|
@ -211,7 +230,7 @@ class GameInstance {
|
||||||
this.renderer.addRenderable(label.getRenderable())
|
this.renderer.addRenderable(label.getRenderable())
|
||||||
}
|
}
|
||||||
|
|
||||||
this.vor_shader.uniform(GL, "u_planets", new Uniform3fv(planets));
|
// this.vor_shader.uniform(GL, "u_planets", new Uniform3fv(planets));
|
||||||
|
|
||||||
// Set slider correctly
|
// Set slider correctly
|
||||||
SLIDER.max = this.turn_count - 1 + '';
|
SLIDER.max = this.turn_count - 1 + '';
|
||||||
|
|
68
frontend/www/src/voronoi/voronoi.ts
Normal file
68
frontend/www/src/voronoi/voronoi.ts
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import { Shader } from "../webgl/shader";
|
||||||
|
import { BBox, Point, VoronoiDiagram } from "./voronoi-core";
|
||||||
|
import Voronoi = require("./voronoi-core");
|
||||||
|
import { DefaultRenderable } from "../webgl/renderer";
|
||||||
|
import { IndexBuffer, VertexBuffer } from "../webgl/buffer";
|
||||||
|
import { VertexBufferLayout, VertexArray } from "../webgl/vertexBufferLayout";
|
||||||
|
|
||||||
|
function to_key(p: Point): string {
|
||||||
|
return [p.x, p.y] + "";
|
||||||
|
}
|
||||||
|
|
||||||
|
export class VoronoiBuilder {
|
||||||
|
inner: DefaultRenderable;
|
||||||
|
|
||||||
|
vor: VoronoiDiagram;
|
||||||
|
a_own: number[];
|
||||||
|
|
||||||
|
constructor(gl: WebGLRenderingContext, shader: Shader, planets: Point[], bbox: BBox) {
|
||||||
|
const voronoi = new Voronoi();
|
||||||
|
this.vor = voronoi.compute(planets, bbox);
|
||||||
|
|
||||||
|
const a_pos = planets.concat(this.vor.vertices).reduce((a, b) => a.concat([-b.x, -b.y]), []);
|
||||||
|
const a_own = new Array(planets.length + this.vor.vertices.length).fill(-1);
|
||||||
|
|
||||||
|
const vert_indcs = {};
|
||||||
|
planets.concat(this.vor.vertices).forEach((p, i) => vert_indcs[to_key(p)] = i);
|
||||||
|
|
||||||
|
const ids = [];
|
||||||
|
|
||||||
|
for (let cell of this.vor.cells) {
|
||||||
|
const baseIndx = vert_indcs[to_key(cell.site)];
|
||||||
|
console.log(baseIndx);
|
||||||
|
for (let edge of cell.halfedges) {
|
||||||
|
ids.push(baseIndx);
|
||||||
|
|
||||||
|
ids.push(vert_indcs[to_key(edge.getStartpoint())]);
|
||||||
|
ids.push(vert_indcs[to_key(edge.getEndpoint())])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ib = new IndexBuffer(gl, ids);
|
||||||
|
const vb_pos = new VertexBuffer(gl, a_pos);
|
||||||
|
const vb_own = new VertexBuffer(gl, a_own);
|
||||||
|
|
||||||
|
const layout_pos = new VertexBufferLayout();
|
||||||
|
layout_pos.push(gl.FLOAT, 2, 4, "a_pos");
|
||||||
|
|
||||||
|
const layout_own = new VertexBufferLayout();
|
||||||
|
layout_own.push(gl.FLOAT, 1, 4, "a_own");
|
||||||
|
|
||||||
|
const vao = new VertexArray();
|
||||||
|
vao.addBuffer(vb_pos, layout_pos);
|
||||||
|
vao.addBuffer(vb_own, layout_own);
|
||||||
|
|
||||||
|
this.inner = new DefaultRenderable(ib, vao, shader, [], {});
|
||||||
|
|
||||||
|
this.a_own = a_own;
|
||||||
|
}
|
||||||
|
|
||||||
|
getRenderable(): DefaultRenderable {
|
||||||
|
return this.inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateOwners(gl: WebGLRenderingContext, planets_owners: number[]) {
|
||||||
|
planets_owners.forEach((own, i) => this.a_own[i] = own);
|
||||||
|
this.inner.updateVAOBuffer(gl, 1, this.a_own);
|
||||||
|
}
|
||||||
|
}
|
|
@ -53,14 +53,18 @@ export class Label {
|
||||||
|
|
||||||
const uniforms = transform ? { "u_trans": transform, "u_trans_next": transform, } : {};
|
const uniforms = transform ? { "u_trans": transform, "u_trans_next": transform, } : {};
|
||||||
const ib = new IndexBuffer(gl, []);
|
const ib = new IndexBuffer(gl, []);
|
||||||
const vb = new VertexBuffer(gl, []);
|
const vb_pos = new VertexBuffer(gl, []);
|
||||||
|
const vb_tex = new VertexBuffer(gl, []);
|
||||||
|
|
||||||
const layout = new VertexBufferLayout();
|
const layout_pos = new VertexBufferLayout();
|
||||||
layout.push(gl.FLOAT, 2, 4, "a_position");
|
layout_pos.push(gl.FLOAT, 2, 4, "a_position");
|
||||||
layout.push(gl.FLOAT, 2, 4, "a_texCoord");
|
|
||||||
|
const layout_tex = new VertexBufferLayout();
|
||||||
|
layout_tex.push(gl.FLOAT, 2, 4, "a_texCoord");
|
||||||
|
|
||||||
const vao = new VertexArray();
|
const vao = new VertexArray();
|
||||||
vao.addBuffer(vb, layout);
|
vao.addBuffer(vb_pos, layout_pos);
|
||||||
|
vao.addBuffer(vb_tex, layout_tex);
|
||||||
|
|
||||||
this.inner = new DefaultRenderable(ib, vao, shader, [tex], uniforms);
|
this.inner = new DefaultRenderable(ib, vao, shader, [tex], uniforms);
|
||||||
}
|
}
|
||||||
|
@ -71,7 +75,8 @@ export class Label {
|
||||||
|
|
||||||
setText(gl: WebGLRenderingContext, text: string, h_align = Align.Begin, v_align = Align.Begin) {
|
setText(gl: WebGLRenderingContext, text: string, h_align = Align.Begin, v_align = Align.Begin) {
|
||||||
const idxs = [];
|
const idxs = [];
|
||||||
const verts = [];
|
const verts_pos = [];
|
||||||
|
const verts_tex = [];
|
||||||
|
|
||||||
const letterHeight = this.font.letterHeight / this.font.textureHeight;
|
const letterHeight = this.font.letterHeight / this.font.textureHeight;
|
||||||
let xPos = 0;
|
let xPos = 0;
|
||||||
|
@ -106,10 +111,16 @@ export class Label {
|
||||||
const letterWidth = info.width / this.font.textureWidth;
|
const letterWidth = info.width / this.font.textureWidth;
|
||||||
const x0 = info.x / this.font.textureWidth;
|
const x0 = info.x / this.font.textureWidth;
|
||||||
const y0 = info.y / this.font.textureHeight;
|
const y0 = info.y / this.font.textureHeight;
|
||||||
verts.push(xPos, yStart, x0, y0);
|
verts_pos.push(xPos, yStart);
|
||||||
verts.push(xPos + dx, yStart, x0 + letterWidth, y0);
|
verts_pos.push(xPos + dx, yStart);
|
||||||
verts.push(xPos, yStart-1, x0, y0 + letterHeight);
|
verts_pos.push(xPos, yStart-1);
|
||||||
verts.push(xPos + dx, yStart-1, x0 + letterWidth, y0 + letterHeight);
|
verts_pos.push(xPos + dx, yStart-1);
|
||||||
|
|
||||||
|
verts_tex.push(x0, y0);
|
||||||
|
verts_tex.push(x0 + letterWidth, y0);
|
||||||
|
verts_tex.push(x0, y0 + letterHeight);
|
||||||
|
verts_tex.push(x0 + letterWidth, y0 + letterHeight);
|
||||||
|
|
||||||
xPos += dx;
|
xPos += dx;
|
||||||
|
|
||||||
idxs.push(j+0, j+1, j+2, j+1, j+2, j+3);
|
idxs.push(j+0, j+1, j+2, j+1, j+2, j+3);
|
||||||
|
@ -121,7 +132,8 @@ export class Label {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.inner.updateIndexBuffer(gl, idxs);
|
this.inner.updateIndexBuffer(gl, idxs);
|
||||||
this.inner.updateVAOBuffer(gl, 0, verts);
|
this.inner.updateVAOBuffer(gl, 0, verts_pos);
|
||||||
|
this.inner.updateVAOBuffer(gl, 1, verts_tex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,29 +2,15 @@
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uniform vec3 u_planets[$PLANETS];
|
|
||||||
uniform vec3 u_planet_colours[$PLANETS * 2];
|
uniform vec3 u_planet_colours[$PLANETS * 2];
|
||||||
|
|
||||||
uniform float u_step_interval;
|
uniform float u_step_interval;
|
||||||
uniform float u_time;
|
uniform float u_time;
|
||||||
uniform bool u_vor;
|
uniform bool u_vor;
|
||||||
|
|
||||||
|
varying vec3 v_color;
|
||||||
varying vec2 v_pos;
|
varying vec2 v_pos;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec3 color = vec3(0.2);
|
gl_FragColor = vec4(v_color, 0.8);
|
||||||
|
|
||||||
if (u_vor) {
|
|
||||||
float dis = 1000000.0;
|
|
||||||
|
|
||||||
for(int i = 0; i < $PLANETS; i++) {
|
|
||||||
float d = distance(v_pos, u_planets[i].xy);
|
|
||||||
if (d < dis) {
|
|
||||||
dis = d;
|
|
||||||
color = u_planet_colours[2 * i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_FragColor = vec4(color, 0.2);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,24 +3,33 @@ precision mediump float;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
attribute vec2 a_pos;
|
attribute vec2 a_pos;
|
||||||
|
attribute float a_own;
|
||||||
|
|
||||||
|
uniform vec3 u_planet_colours[$PLANETS * 2];
|
||||||
uniform vec4 u_viewbox; // [x, y, width, height]
|
uniform vec4 u_viewbox; // [x, y, width, height]
|
||||||
uniform vec2 u_resolution;
|
uniform vec2 u_resolution;
|
||||||
|
|
||||||
varying vec2 v_pos;
|
varying vec2 v_pos;
|
||||||
|
varying vec3 v_color;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
int own = int(a_own);
|
||||||
|
|
||||||
vec2 uv = (a_pos.xy + 1.0) * 0.5;
|
vec2 uv = a_pos;
|
||||||
uv = 1.0 - uv;
|
|
||||||
// uv *= -1.0;
|
|
||||||
|
|
||||||
// Viewbox's center is top left, a_position's is in the center to the screen
|
// Viewbox's center is top left, a_position's is in the center to the screen
|
||||||
// So translate and scale the viewbox**
|
// So translate and scale the viewbox**
|
||||||
uv *= u_viewbox.zw;
|
uv -= u_viewbox.xy + (u_viewbox.zw * 0.5);
|
||||||
uv -= u_viewbox.xy + u_viewbox.zw;
|
uv /= u_viewbox.zw * 0.5;
|
||||||
|
|
||||||
v_pos = uv.xy;
|
|
||||||
|
|
||||||
gl_Position = vec4(a_pos, 0.0, 1.0);
|
v_pos = (uv.xy + 1.0) * 0.5;
|
||||||
|
|
||||||
|
if (own < 0) {
|
||||||
|
v_color = vec3(0., 0., 0.);
|
||||||
|
} else {
|
||||||
|
v_color = u_planet_colours[own * 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_Position = vec4(uv.xy, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue