@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
218 lines • 16.3 kB
JavaScript
import { TgdDataset } from "./../../dataset/index.js";
import { TgdPainter } from "./../painter.js";
import { TgdVertexArray } from "./../../vao/index.js";
import { TgdTexture2D } from "./../../texture/index.js";
import { TgdProgram } from "./../../program/index.js";
import { tgdCanvasCreatePalette } from "./../../utils/index.js";
import { TgdMaterialFaceOrientation } from "./../../material/index.js";
import { makeCapsule } from "./capsule.js";
import { TgdShaderFragment, TgdShaderVertex } from "./../../shader/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 {
// private readonly painter: TgdPainter
constructor(context, options) {
var _a, _b, _c, _d;
super();
this.context = context;
this.minRadius = 1;
this.radiusMultiplier = 1;
this.radiusConstant = 1;
this.radiusSwitch = 0;
const { roundness = 3, minRadius = 1, makeDataset } = options;
const geometry = makeCapsule(roundness);
const material = (_a = options.material) !== null && _a !== void 0 ? _a : new TgdMaterialFaceOrientation();
this.material = material;
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", "#ff4", "#4f4", "#4ff", "#44f"]));
const vert = new TgdShaderVertex({
uniforms: Object.assign({ uniTransfoMatrix: "mat4", uniModelViewMatrix: "mat4", uniProjectionMatrix: "mat4", uniMinRadius: "float" }, material.uniforms),
attributes: {
[geometry.attPosition]: "vec3",
[geometry.attNormal]: "vec3",
attTip: "float",
attXYZR0: "vec4",
attXYZR1: "vec4",
attUV0: "vec2",
attUV1: "vec2",
},
varying: material.varyings,
functions: {
applyMaterial: [
"void applyMaterial() {",
[material.vertexShaderCode],
"}",
],
getPosition: [
"vec4 getPosition(vec4 pos) {",
[(_b = material.vertexShaderCodeForGetPosition) !== null && _b !== void 0 ? _b : "return pos;"],
"}",
],
},
mainCode: [
`vec3 normal = NORMAL;`,
`vec3 pos = POSITION;`,
`vec4 xyzr = mix(attXYZR0, attXYZR1, attTip);`,
`vec3 center = xyzr.xyz;`,
`float radius = max(`,
[
`xyzr.w,`,
`uniMinRadius * (uniProjectionMatrix * uniModelViewMatrix * vec4(center, 1)).w`,
],
`);`,
`vec3 dir = attXYZR1.xyz - attXYZR0.xyz;`,
`float len = length(dir);`,
`if (len == 0.0) {`,
[`// Just a sphere`, `pos *= radius;`, `pos += center.xyz;`],
`} else {`,
[
`// Full capsule`,
`vec3 Z = dir / len;`,
`vec3 v = abs(Z.z) > 0.7 ? vec3(1,0,0) : vec3(0,0,1);`,
`vec3 Y = cross(v, Z);`,
`vec3 X = cross(Y, Z);`,
`mat3 mat = mat3(X, Y, Z);`,
`pos *= radius;`,
`pos = mat * pos + center.xyz;`,
`normal = mat * normal;`,
],
`}`,
`gl_Position = uniProjectionMatrix * uniModelViewMatrix * vec4(pos, 1);`,
"applyMaterial();",
"varNormal = normal;",
],
}).code;
const frag = new TgdShaderFragment({
uniforms: material.uniforms,
outputs: { FragColor: "vec4" },
varying: material.varyings,
functions: {
applyMaterial: [
"vec4 applyMaterial() {",
[material.fragmentShaderCode],
"}",
],
},
mainCode: [`FragColor = applyMaterial();`],
}).code;
const prg = new TgdProgram(context.gl, {
vert,
frag,
});
prg.debug();
this.prg = prg;
// this.painter = new TgdPainterMesh(context, {
// geometry,
// material: new TgdMaterialFaceOrientation(),
// })
const instance = makeDataset();
this.vao = new TgdVertexArray(context.gl, prg, [geometry.dataset, instance], geometry.elements);
this.vertexCount = (_d = (_c = geometry.elements) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0;
this.instanceCount = instance.count;
}
delete() {
this.vao.delete();
this.prg.delete();
// this.painter.delete()
}
paint(time, delay) {
// this.painter.paint(_time, _delay)
const { context, prg, vao, vertexCount, instanceCount, material } = this;
const { gl, camera } = context;
gl.disable(gl.DITHER);
prg.use();
this.material.setUniforms(prg, time, delay);
prg.uniform1f("uniMinRadius", (this.minRadius * 2) / gl.drawingBufferHeight);
prg.uniformMatrix4fv("uniModelViewMatrix", camera.matrixModelView);
prg.uniformMatrix4fv("uniProjectionMatrix", camera.matrixProjection);
material.applyState(gl, () => {
vao.bind();
gl.drawElementsInstanced(gl.TRIANGLES, vertexCount, gl.UNSIGNED_SHORT, 0, instanceCount);
vao.unbind();
});
}
}
export class TgdPainterSegmentsData {
constructor() {
this._count = 0;
this.attXYZR0 = [];
this.attUV0 = [];
this.attInfluence0 = [];
this.attXYZR1 = [];
this.attUV1 = [];
this.attInfluence1 = [];
this.makeDataset = () => {
const dataset = new TgdDataset({
attXYZR0: "vec4",
attUV0: "vec2",
attInfluence0: "float",
attXYZR1: "vec4",
attUV1: "vec2",
attInfluence1: "float",
}, {
divisor: 1,
});
dataset.set("attXYZR0", new Float32Array(this.attXYZR0));
dataset.set("attUV0", new Float32Array(this.attUV0));
dataset.set("attInfluence0", new Float32Array(this.attInfluence0));
dataset.set("attXYZR1", new Float32Array(this.attXYZR1));
dataset.set("attUV1", new Float32Array(this.attUV1));
dataset.set("attInfluence1", new Float32Array(this.attInfluence1));
return dataset;
};
}
get count() {
return this._count;
}
/**
* @param XYZR0 (x,y,z) and radius of point A.
* @param XYZR1 (x,y,z) and radius of point B.
* @param UV0 Texture coordinates for point A.
* @param UV1 Texture coordinates for point B.
* @param radiusMultiplierInfluence0 If you put 0, the radius won't change regardless to the currently applied radius multiplicator.
* @param radiusMultiplierInfluence1
*/
add(XYZR0, XYZR1, UV0 = [0, 0], UV1 = [0, 0], radiusMultiplierInfluence0 = 1, radiusMultiplierInfluence1 = 1) {
this.attXYZR0.push(...XYZR0);
this.attUV0.push(...UV0);
this.attInfluence0.push(radiusMultiplierInfluence0);
this.attXYZR1.push(...XYZR1);
this.attUV1.push(...UV1);
this.attInfluence1.push(radiusMultiplierInfluence1);
this._count++;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VnbWVudHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcGFpbnRlci9zZWdtZW50cy9zZWdtZW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sY0FBYyxDQUFBO0FBQ3pDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQTtBQUVqRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBR3pDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxjQUFjLENBQUE7QUFDM0MsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGNBQWMsQ0FBQTtBQUN6QyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFLbkQsT0FBTyxFQUFlLDBCQUEwQixFQUFFLE1BQU0sZUFBZSxDQUFBO0FBQ3ZFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFDdkMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGVBQWUsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQW1CaEU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBQ0gsTUFBTSxPQUFPLGtCQUFtQixTQUFRLFVBQVU7SUFhOUMsdUNBQXVDO0lBRXZDLFlBQ3VCLE9BR2xCLEVBQ0QsT0FFQzs7UUFFRCxLQUFLLEVBQUUsQ0FBQTtRQVJZLFlBQU8sR0FBUCxPQUFPLENBR3pCO1FBakJFLGNBQVMsR0FBVyxDQUFDLENBQUE7UUFDckIscUJBQWdCLEdBQUcsQ0FBQyxDQUFBO1FBQ3BCLG1CQUFjLEdBQUcsQ0FBQyxDQUFBO1FBQ2xCLGlCQUFZLEdBQUcsQ0FBQyxDQUFBO1FBb0JuQixNQUFNLEVBQUUsU0FBUyxHQUFHLENBQUMsRUFBRSxTQUFTLEdBQUcsQ0FBQyxFQUFFLFdBQVcsRUFBRSxHQUFHLE9BQU8sQ0FBQTtRQUM3RCxNQUFNLFFBQVEsR0FBRyxXQUFXLENBQUMsU0FBUyxDQUFDLENB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