gpu-curtains
Version:
gpu-curtains is a 3D WebGPU rendering engine. It can be used as a standalone 3D engine, but also includes extra classes focused on mapping 3d objects to DOM elements; It allows users to synchronize values such as position, sizing, or scale between them.
102 lines (99 loc) • 3.85 kB
JavaScript
import { IndexedGeometry } from './IndexedGeometry.mjs';
class PlaneGeometry extends IndexedGeometry {
/**
* PlaneGeometry constructor
* @param parameters - {@link PlaneGeometryParams | parameters} used to create our PlaneGeometry
*/
constructor({
widthSegments = 1,
heightSegments = 1,
instancesCount = 1,
vertexBuffers = [],
topology
} = {}) {
super({ verticesOrder: "ccw", topology, instancesCount, vertexBuffers, mapBuffersAtCreation: true });
this.type = "PlaneGeometry";
widthSegments = Math.floor(widthSegments);
heightSegments = Math.floor(heightSegments);
this.definition = {
id: widthSegments * heightSegments + widthSegments,
width: widthSegments,
height: heightSegments,
count: widthSegments * heightSegments
};
const verticesCount = (this.definition.width + 1) * (this.definition.height + 1);
const attributes = this.getIndexedVerticesAndUVs(verticesCount);
for (const attribute of Object.values(attributes)) {
this.setAttribute(attribute);
}
this.setIndexArray();
}
/**
* Set our PlaneGeometry index array
*/
setIndexArray() {
const indexArray = this.useUint16IndexArray ? new Uint16Array(this.definition.count * 6) : new Uint32Array(this.definition.count * 6);
let index = 0;
for (let y = 0; y < this.definition.height; y++) {
for (let x = 0; x < this.definition.width; x++) {
indexArray[index++] = x + y * (this.definition.width + 1);
indexArray[index++] = this.definition.width + x + 1 + y * (this.definition.width + 1);
indexArray[index++] = x + 1 + y * (this.definition.width + 1);
indexArray[index++] = x + 1 + y * (this.definition.width + 1);
indexArray[index++] = this.definition.width + x + 1 + y * (this.definition.width + 1);
indexArray[index++] = this.definition.width + x + 2 + y * (this.definition.width + 1);
}
}
this.setIndexBuffer({
array: indexArray,
bufferFormat: this.useUint16IndexArray ? "uint16" : "uint32"
});
}
/**
* Compute the UV and position arrays based on our plane widthSegments and heightSegments values and return the corresponding attributes
* @param verticesCount - {@link Geometry#verticesCount | number of vertices} of our {@link PlaneGeometry}
* @returns - our position and uv {@link VertexBufferAttributeParams | attributes}
*/
getIndexedVerticesAndUVs(verticesCount) {
const uv = {
name: "uv",
type: "vec2f",
bufferFormat: "float32x2",
size: 2,
array: new Float32Array(verticesCount * 2)
};
const position = {
name: "position",
type: "vec3f",
bufferFormat: "float32x3",
// nb of triangles * 3 vertices per triangle * 3 coordinates per triangle
size: 3,
array: new Float32Array(verticesCount * 3)
};
const normal = {
name: "normal",
type: "vec3f",
bufferFormat: "float32x3",
// nb of triangles * 3 vertices per triangle * 3 coordinates per triangle
size: 3,
array: new Float32Array(verticesCount * 3)
};
let positionOffset = 0;
let normalOffset = 0;
let uvOffset = 0;
for (let y = 0; y <= this.definition.height; y++) {
for (let x = 0; x <= this.definition.width; x++) {
uv.array[uvOffset++] = 1 - x / this.definition.width;
uv.array[uvOffset++] = 1 - y / this.definition.height;
position.array[positionOffset++] = 1 - x * 2 / this.definition.width;
position.array[positionOffset++] = y * 2 / this.definition.height - 1;
position.array[positionOffset++] = 0;
normal.array[normalOffset++] = 0;
normal.array[normalOffset++] = 0;
normal.array[normalOffset++] = 1;
}
}
return { position, uv, normal };
}
}
export { PlaneGeometry };