@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
115 lines (104 loc) • 3.63 kB
text/typescript
import {BaseSopOperation} from './_Base';
import {CoreGroup, Object3DWithGeometry} from '../../../core/geometry/Group';
import {InputCloneMode} from '../../poly/InputCloneMode';
import {BufferAttribute, Color} from 'three';
import {DefaultOperationParams} from '../../../core/operations/_Base';
import {SORTED_PALETTE_NAMES} from '../../../core/color/chromotomeWrapper';
import {AttribClass, ATTRIBUTE_CLASSES} from '../../../core/geometry/Constant';
import {TypeAssert} from '../../poly/Assert';
import {coreObjectClassFactory, corePointClassFactory} from '../../../core/geometry/CoreObjectFactory';
interface PaletteSopParams extends DefaultOperationParams {
class: number;
paletteName: string;
colorsCount: number;
color1: Color;
color2: Color;
color3: Color;
color4: Color;
color5: Color;
}
export class PaletteSopOperation extends BaseSopOperation {
static override readonly DEFAULT_PARAMS: PaletteSopParams = {
class: ATTRIBUTE_CLASSES.indexOf(AttribClass.POINT),
paletteName: SORTED_PALETTE_NAMES[0],
colorsCount: 0,
color1: new Color(1, 1, 1),
color2: new Color(1, 1, 1),
color3: new Color(1, 1, 1),
color4: new Color(1, 1, 1),
color5: new Color(1, 1, 1),
};
static override readonly INPUT_CLONED_STATE = InputCloneMode.FROM_NODE;
static override type(): Readonly<'palette'> {
return 'palette';
}
override cook(inputCoreGroups: CoreGroup[], params: PaletteSopParams) {
const coreGroup = inputCoreGroups[0];
const colors = [params.color1, params.color2, params.color3, params.color4, params.color5];
this._addAttribute(ATTRIBUTE_CLASSES[params.class], coreGroup, params, colors);
return coreGroup;
}
private async _addAttribute(
attribClass: AttribClass,
coreGroup: CoreGroup,
params: PaletteSopParams,
colors: Color[]
) {
switch (attribClass) {
case AttribClass.POINT:
return await this._setVertexColor(coreGroup, params, colors);
case AttribClass.VERTEX:
this.states?.error.set('vertex not supported yet');
return;
case AttribClass.PRIMITIVE:
this.states?.error.set('primitive not supported yet');
return;
case AttribClass.OBJECT:
return await this._setObjectColor(coreGroup, params, colors);
case AttribClass.CORE_GROUP:
return;
}
TypeAssert.unreachable(attribClass);
}
private _setObjectColor(coreGroup: CoreGroup, params: PaletteSopParams, colors: Color[]) {
const objects = coreGroup.allObjects();
let i = 0;
for (let object of objects) {
const color = colors[i % params.colorsCount];
coreObjectClassFactory(object).addAttribute(object, 'color', color.clone());
i++;
}
return coreGroup;
}
private _setVertexColor(coreGroup: CoreGroup, params: PaletteSopParams, colors: Color[]) {
const objects = coreGroup.threejsObjectsWithGeo();
for (let object of objects) {
this._setVertexColorToObject(object, params, colors);
}
}
private _setVertexColorToObject(object: Object3DWithGeometry, params: PaletteSopParams, colors: Color[]) {
if (params.colorsCount <= 0) {
return;
}
const corePointClass = corePointClassFactory(object);
const geometry = object.geometry;
if (!geometry) {
return;
}
let colorAttrib = geometry.getAttribute('color') as BufferAttribute;
if (!colorAttrib) {
corePointClass.addNumericAttribute(object, 'color', 3, [0, 0, 0]);
colorAttrib = geometry.getAttribute('color') as BufferAttribute;
}
if (!colorAttrib) {
return;
}
const array = colorAttrib.array;
let ptIndex = 0;
for (let i = 0; i < array.length; i += 3) {
const color = colors[ptIndex % params.colorsCount];
color.toArray(array, i);
ptIndex++;
}
}
}