@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
223 lines • 18.1 kB
JavaScript
/* eslint-disable unicorn/no-useless-spread */
import { TgdDataset } from "./../../dataset/index.js";
import { TgdPainter } from "./../painter.js";
import { TgdVertexArray } from "./../../vao/index.js";
import FRAG from "./segments.frag";
import VERT from "./segments.vert";
import { TgdTexture2D } from "./../../texture/index.js";
import { TgdProgram } from "./../../program/index.js";
import { tgdCanvasCreatePalette } from "./../../utils/index.js";
import { TgdVec3 } from "./../../math/index.js";
/**
* @example
* ```
* const factory = new TgdPainterSegmentsData()
* factory.add(
* [0, 0, 0, .2],
* [1, 0, 0, .1],
* )
* factory.add(
* [0, 0, 0, .2],
* [0, 1, 0, .1],
* )
* factory.add(
* [0, 0, 0, .2],
* [0, 0, 1, .1],
* )
* const segments = new TgdPainterSegments(
* segment, factory
* )
* ```
*/
export class TgdPainterSegments extends TgdPainter {
constructor(context, options) {
super();
this.context = context;
this.minRadius = 0;
this.radiusMultiplier = 1;
this.radiusConstant = 1;
this.radiusSwitch = 0;
this.light = 1;
this.shiftZ = 0;
this.contrast = 0.3;
this.specularIntensity = 0.4;
this.specularExponent = 30;
const { roundness = 3, minRadius = 0, makeDataset } = options;
this.minRadius = minRadius;
if (roundness > 127) {
throw new Error("[TgdPainterSegments] Max roundness is 127!");
}
if (roundness < 0) {
throw new Error("[TgdPainterSegments] Min roundness is 0!");
}
this.colorTexture = new TgdTexture2D(context)
.setParams({
magFilter: "NEAREST",
minFilter: "NEAREST",
wrapR: "CLAMP_TO_EDGE",
wrapS: "CLAMP_TO_EDGE",
wrapT: "CLAMP_TO_EDGE",
})
.loadBitmap(tgdCanvasCreatePalette(["#f44", "#4f4", "#44f"]));
const prg = new TgdProgram(context.gl, {
vert: VERT,
frag: FRAG,
});
this.prg = prg;
const { capsule, elements } = makeCapsule(roundness);
const instance = makeDataset();
// instance.debug()
this.vao = new TgdVertexArray(context.gl, prg, [capsule, instance], elements);
this.vertexCount = elements.length;
this.instanceCount = instance.count;
}
delete() {
this.vao.delete();
}
paint(_time, _delay) {
const { context, prg, vao, colorTexture, vertexCount, instanceCount, light, radiusMultiplier, radiusConstant, radiusSwitch, shiftZ, contrast, specularIntensity, specularExponent, } = this;
const { gl, camera } = context;
gl.disable(gl.DITHER);
prg.use();
const minRadius = (this.minRadius * camera.spaceHeightAtTarget) /
(camera.zoom * camera.screenHeight);
prg.uniform1f("uniMinRadius", minRadius);
prg.uniform1f("uniLight", light);
prg.uniform1f("uniShiftZ", shiftZ);
prg.uniform1f("uniRadiusMultiplier", radiusMultiplier);
prg.uniform1f("uniRadiusConstant", radiusConstant);
prg.uniform1f("uniRadiusSwitch", radiusSwitch);
prg.uniform1f("uniContrast", contrast);
prg.uniform1f("uniSpecularIntensity", specularIntensity);
prg.uniform1f("uniSpecularExponent", specularExponent);
colorTexture.activate(0, prg, "uniTexture");
prg.uniformMatrix4fv("uniModelViewMatrix", camera.matrixModelView);
prg.uniformMatrix4fv("uniProjectionMatrix", camera.matrixProjection);
vao.bind();
gl.drawElementsInstanced(gl.TRIANGLES, vertexCount, gl.UNSIGNED_BYTE, 0, instanceCount);
}
}
export class TgdPainterSegmentsData {
constructor() {
this._count = 0;
this.attAxyzr = [];
this.attAuv = [];
this.attAinfluence = [];
this.attBxyzr = [];
this.attBuv = [];
this.attBinfluence = [];
this.makeDataset = () => {
const dataset = new TgdDataset({
attAxyzr: "vec4",
attAuv: "vec2",
attAinfluence: "float",
attBxyzr: "vec4",
attBuv: "vec2",
attBinfluence: "float",
}, {
divisor: 1,
});
dataset.set("attAxyzr", new Float32Array(this.attAxyzr));
dataset.set("attAuv", new Float32Array(this.attAuv));
dataset.set("attAinfluence", new Float32Array(this.attAinfluence));
dataset.set("attBxyzr", new Float32Array(this.attBxyzr));
dataset.set("attBuv", new Float32Array(this.attBuv));
dataset.set("attBinfluence", new Float32Array(this.attBinfluence));
return dataset;
};
}
get count() {
return this._count;
}
/**
* @param Axyzr (x,y,z) and radius of point A.
* @param Bxyzr (x,y,z) and radius of point B.
* @param Auv Texture coordinates for point A.
* @param Buv Texture coordinates for point B.
* @param radiusMultiplierInfluenceA If you put 0, the radius won't change regardless to the currently applied radius multiplicator.
* @param radiusMultiplierInfluenceB
*/
add(Axyzr, Bxyzr, Auv = [0, 0], Buv = [0, 0], radiusMultiplierInfluenceA = 1, radiusMultiplierInfluenceB = 1) {
this.attAxyzr.push(...Axyzr);
this.attAuv.push(...Auv);
this.attAinfluence.push(radiusMultiplierInfluenceA);
this.attBxyzr.push(...Bxyzr);
this.attBuv.push(...Buv);
this.attBinfluence.push(radiusMultiplierInfluenceB);
this._count++;
}
}
/**
* The capsule is a 2D shape (x,y) that will be used
* as a pattern for the segment.
* The segment will expand this template along Y axis.
* The tip pointing toward +Y is called A.
* The tip pointing toward -Y is called B.
* The z coodinates indicates to which tip the point
* is attached: 0 for A and 1 for B.
*/
function makeCapsule(roundness) {
// prettier-ignore
const offset = [
...[0, 0, 0], // 0
...[1, 0, 0], // 1
...[-1, 0, 0], // 2
...[0, 0, 1], // 3
...[1, 0, 1], // 4
...[-1, 0, 1], // 5
];
// prettier-ignore
const normal = [
...[0, 0, 1], // 0
...[1, 0, 0], // 1
...[-1, 0, 0], // 2
...[0, 0, 1], // 3
...[1, 0, 0], // 4
...[-1, 0, 0], // 5
];
// prettier-ignore
const elements = [
0, 3, 1,
3, 4, 1,
0, 2, 5,
3, 0, 5,
];
if (roundness > 0) {
let oldIndexA = 1;
let oldIndexB = 4;
let elementIndex = 6;
// Temporary variable to prevent multiple new() calls.
const n = new TgdVec3();
for (let roundnessStep = 0; roundnessStep < roundness; roundnessStep++) {
const ang = (Math.PI * (roundnessStep + 1)) / (roundness + 1);
const x = Math.cos(ang);
const y = Math.sin(ang);
// We set z to 0 because it's related to tip A.
offset.push(x, y, 0);
n.from([x, 0, 1 - Math.abs(x)]); //.normalize()
normal.push(n.x, n.y, n.z);
elements.push(0, oldIndexA, elementIndex);
oldIndexA = elementIndex;
elementIndex++;
// We set z to 1 because it's related to tip B.
offset.push(x, -y, 1);
n.from([x, 0, 1 - Math.abs(x)]).normalize();
normal.push(n.x, n.y, n.z);
elements.push(3, elementIndex, oldIndexB);
oldIndexB = elementIndex;
elementIndex++;
}
elements.push(0, oldIndexA, 2, 3, 5, oldIndexB);
}
const capsule = new TgdDataset({
attOffset: "vec3",
attNormal: "vec3",
});
capsule.set("attOffset", new Float32Array(offset));
capsule.set("attNormal", new Float32Array(normal));
return {
capsule,
elements: new Uint8Array(elements),
};
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VnbWVudHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcGFpbnRlci9zZWdtZW50cy5iYWNrdXAvc2VnbWVudHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsOENBQThDO0FBQzlDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxjQUFjLENBQUE7QUFDekMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFBO0FBRWpELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxVQUFVLENBQUE7QUFFekMsT0FBTyxJQUFJLE1BQU0saUJBQWlCLENBQUE7QUFDbEMsT0FBTyxJQUFJLE1BQU0saUJBQWlCLENBQUE7QUFDbEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGNBQWMsQ0FBQTtBQUMzQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sY0FBYyxDQUFBO0FBQ3pDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUVuRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFBO0FBcUJuQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFDSCxNQUFNLE9BQU8sa0JBQW1CLFNBQVEsVUFBVTtJQWlCOUMsWUFDdUIsT0FHbEIsRUFDRCxPQUVDO1FBRUQsS0FBSyxFQUFFLENBQUE7UUFSWSxZQUFPLEdBQVAsT0FBTyxDQUd6QjtRQW5CRSxjQUFTLEdBQVcsQ0FBQyxDQUFBO1FBQ3JCLHFCQUFnQixHQUFHLENBQUMsQ0FBQTtRQUNwQixtQkFBYyxHQUFHLENBQUMsQ0FBQTtRQUNsQixpQkFBWSxHQUFHLENBQUMsQ0FBQTtRQUNoQixVQUFLLEdBQUcsQ0FBQyxDQUFBO1FBQ1QsV0FBTSxHQUFHLENBQUMsQ0FBQTtRQUNWLGFBQVEsR0FBRyxHQUFHLENBQUE7UUFDZCxzQkFBaUIsR0FBRyxHQUFHLENBQUE7UUFDdkIscUJBQWdCLEdBQUcsRUFBRSxDQUFBO1FBaUJ4QixNQUFNLEVBQUUs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