@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
161 lines (144 loc) • 5.15 kB
text/typescript
import {
Vector2,
Vector3,
Vector4,
BufferGeometry,
BufferAttribute,
RGBAFormat,
FloatType,
DataTexture,
NearestFilter,
RepeatWrapping,
Mesh,
} from 'three';
import {nearestPower2} from '../../math/_Module';
import {CoreAttribute} from '../Attribute';
import {pointsCountFromObject} from '../entities/point/CorePointUtils';
const _textureSize = new Vector2();
const _v2 = new Vector2();
const _v3 = new Vector3();
const _v4 = new Vector4();
function _vectorFromAttribSize(attribSize: number) {
switch (attribSize) {
case 2:
return _v2;
case 3:
return _v3;
case 4:
return _v4;
}
}
export enum AttribLookup {
ID = 'attribLookupId',
UV = 'attribLookupUv',
}
const dummyMesh = new Mesh();
export function textureFromAttributePointsCount(geometry: BufferGeometry): number {
dummyMesh.geometry = geometry;
return pointsCountFromObject(dummyMesh);
}
export function textureSizeFromPointsCount(geometry: BufferGeometry, target: Vector2): void {
// const position = geometry.attributes.position;
// if (!(position instanceof BufferAttribute)) {
// console.warn('position is not a BufferAttribute');
// return;
// }
// const pointsCount = position.count;
const pointsCount = textureFromAttributePointsCount(geometry);
// const autoTexturesSize = CoreParticlesAttribute.getAutoTextureSize(object);
// CoreParticlesAttribute.getMaxTextureSize(object, _maxTexturesSize);
// CoreParticlesAttribute.getTextureSize(object, _texturesSize);
// // get texture size
// if (isBooleanTrue(autoTexturesSize)) {
const nearestPowerOfTwo = nearestPower2(Math.sqrt(pointsCount));
target.x = nearestPowerOfTwo; //Math.min(nearestPowerOfTwo, _maxTexturesSize.x);
target.y = nearestPowerOfTwo; //Math.min(nearestPowerOfTwo, _maxTexturesSize.y);
// const pointsCount = position.count;
// return nearestPower2(Math.sqrt(pointsCount));
// return Math.ceil(Math.sqrt(pointsCount));
}
export function textureFromAttributesMissingAttributes(geometry: BufferGeometry, attribNames: string[]): string[] {
const missingAttributes: string[] = [];
for (const attribName of attribNames) {
const attributeName = CoreAttribute.remapName(attribName);
const attribute = geometry.getAttribute(attributeName) as BufferAttribute;
if (!attribute) {
missingAttributes.push(attribName);
}
}
return missingAttributes;
}
export function textureFromAttributesTotalAttribSizes(geometry: BufferGeometry, attribNames: string[]) {
let currentSize = 0;
for (const attribName of attribNames) {
const attributeName = CoreAttribute.remapName(attribName);
const attribute = geometry.getAttribute(attributeName) as BufferAttribute;
if (attribute) {
currentSize += attribute.itemSize;
}
}
return currentSize;
}
export function textureFromAttributes(geometry: BufferGeometry, attribNames: string[]) {
textureSizeFromPointsCount(geometry, _textureSize);
const pointsCount = textureFromAttributePointsCount(geometry);
const width = _textureSize.x;
const height = _textureSize.y;
const size = width * height * 4;
const pixelBuffer = new Float32Array(size);
let currentIndex = 0;
for (let attribName of attribNames) {
attribName = CoreAttribute.remapName(attribName);
const attribute = geometry.getAttribute(attribName) as BufferAttribute;
if (attribute) {
const attribSize = attribute.itemSize;
const attribArray = attribute.array;
if (attribSize == 1) {
for (let i = 0; i < pointsCount; i++) {
pixelBuffer[i * 4 + currentIndex] = attribArray[i];
}
} else {
const vector = _vectorFromAttribSize(attribSize);
if (!vector) {
return;
}
for (let i = 0; i < pointsCount; i++) {
vector.fromArray(attribArray, i * attribSize);
vector.toArray(pixelBuffer, i * 4 + currentIndex);
}
}
currentIndex += attribSize;
}
}
const texture = new DataTexture(pixelBuffer, width, height, RGBAFormat, FloatType);
texture.minFilter = texture.magFilter = NearestFilter;
texture.wrapS = texture.wrapT = RepeatWrapping;
texture.needsUpdate = true;
return texture;
}
export function textureFromAttribLookupUv(geometry: BufferGeometry) {
const attribSize = 2;
const pointsCount = textureFromAttributePointsCount(geometry);
textureSizeFromPointsCount(geometry, _textureSize);
const uvSize = 2;
const values = new Array(pointsCount * uvSize);
for (let pointIndex = 0; pointIndex < pointsCount; pointIndex++) {
_v2.x = pointIndex % _textureSize.x;
_v2.y = Math.floor(pointIndex / _textureSize.x);
_v2.addScalar(0.5);
_v2.divide(_textureSize);
_v2.toArray(values, pointIndex * uvSize);
}
const uvArray = new Float32Array(values);
geometry.setAttribute(AttribLookup.UV, new BufferAttribute(uvArray, attribSize));
}
export function textureFromAttribLookupId(geometry: BufferGeometry) {
const pointsCount = textureFromAttributePointsCount(geometry);
const idSize = 1;
const values = new Array(pointsCount * idSize);
for (let pointIndex = 0; pointIndex < pointsCount; pointIndex++) {
values[pointIndex] = pointIndex;
}
const idArray = new Float32Array(values);
geometry.setAttribute(AttribLookup.ID, new BufferAttribute(idArray, idSize));
}