UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

673 lines (663 loc) 22.3 kB
import { Box3, Color, Vector2, Vector3, Vector4, Plane, Ray, Sphere, Quaternion, Matrix4, Euler, EulerOrder, } from 'three'; import {isBoolean, isNumber, isString} from '../../../../../core/Type'; import {Number2, Number3, Number4, Number16} from '../../../../../types/GlobalTypes'; import {TypeAssert} from '../../../../poly/Assert'; import { JsConnectionPointType, PrimitiveArrayElement, VectorArrayElement, JsConnectionPointTypeFromArrayTypeMap, } from '../../../utils/io/connections/Js'; export type RegisterableVariable = | Box3 | Color | Euler | Plane | Quaternion | Matrix4 | Ray | Sphere | Vector2 | Vector3 | Vector4 | PrimitiveArray<PrimitiveArrayElement> | VectorArray<VectorArrayElement>; // | PrimitiveArray<PrimitiveArrayElement> // | VectorArray<Color> // | VectorArray<Matrix4> // | VectorArray<Quaternion> // | VectorArray<Vector2> // | VectorArray<Vector3> // | VectorArray<Vector4>; export class PrimitiveArray<V extends PrimitiveArrayElement> { public readonly isPrimitiveArray = true; constructor(protected _elements: V[]) {} elements() { return this._elements; } clone(): V[] { return this._elements.map((v) => v as V); } } export class VectorArray<V extends VectorArrayElement> { public readonly isVectorArray = true; constructor(protected _elements: V[]) {} elements() { return this._elements; } clone(): V[] { return this._elements.map((v) => v.clone() as V); } } // Color | Vector2 | Vector3 | Vector4 | Matrix4 | Quaternion export function createVariable(type: JsConnectionPointType) { switch (type) { case JsConnectionPointType.BOOLEAN: case JsConnectionPointType.INT: case JsConnectionPointType.FLOAT: case JsConnectionPointType.STRING: { return null; } case JsConnectionPointType.COLOR: { return new Color(); } case JsConnectionPointType.EULER: { return new Euler(); } case JsConnectionPointType.MATRIX4: { return new Matrix4(); } case JsConnectionPointType.QUATERNION: { return new Quaternion(); } case JsConnectionPointType.VECTOR2: { return new Vector2(); } case JsConnectionPointType.VECTOR3: { return new Vector3(); } case JsConnectionPointType.VECTOR4: { return new Vector4(); } case JsConnectionPointType.BOX3: { return new Box3(); } case JsConnectionPointType.PLANE: { return new Plane(); } case JsConnectionPointType.RAY: { return new Ray(); } case JsConnectionPointType.SPHERE: { return new Sphere(); } case JsConnectionPointType.BOOLEAN_ARRAY: case JsConnectionPointType.FLOAT_ARRAY: case JsConnectionPointType.INT_ARRAY: case JsConnectionPointType.STRING_ARRAY: { return createPrimitiveArray(type); } case JsConnectionPointType.MATRIX4_ARRAY: case JsConnectionPointType.QUATERNION_ARRAY: case JsConnectionPointType.TEXTURE_ARRAY: case JsConnectionPointType.COLOR_ARRAY: case JsConnectionPointType.EULER_ARRAY: case JsConnectionPointType.OBJECT_3D_ARRAY: case JsConnectionPointType.VECTOR2_ARRAY: case JsConnectionPointType.VECTOR3_ARRAY: case JsConnectionPointType.VECTOR4_ARRAY: { return createVectorArray(type); } case JsConnectionPointType.ANIMATION_MIXER: case JsConnectionPointType.ANIMATION_ACTION: case JsConnectionPointType.CAMERA: case JsConnectionPointType.CATMULL_ROM_CURVE3: case JsConnectionPointType.INTERSECTION: case JsConnectionPointType.INTERSECTION_ARRAY: case JsConnectionPointType.MATERIAL: case JsConnectionPointType.NODE: case JsConnectionPointType.OBJECT_3D: case JsConnectionPointType.PARAM: case JsConnectionPointType.TEXTURE: case JsConnectionPointType.TEXTURE_ARRAY: case JsConnectionPointType.TRIGGER: { // console.warn('no variable can be created for type', type); return null; } } console.warn('createVariable not implemented with type', type); TypeAssert.unreachable(type); } export function createPrimitiveArray<V extends PrimitiveArrayElement>(type: JsConnectionPointType): PrimitiveArray<V> { type = JsConnectionPointTypeFromArrayTypeMap[type]; switch (type) { case JsConnectionPointType.BOOLEAN: { return new PrimitiveArray([false]) as PrimitiveArray<V>; } case JsConnectionPointType.INT: { return new PrimitiveArray([0]) as PrimitiveArray<V>; } case JsConnectionPointType.FLOAT: { return new PrimitiveArray([0]) as PrimitiveArray<V>; } case JsConnectionPointType.STRING: { return new PrimitiveArray(['']) as PrimitiveArray<V>; } } console.warn('createPrimitiveArray not implemented for type:', type); return new PrimitiveArray([0]) as PrimitiveArray<V>; } export function createVectorArray<V extends VectorArrayElement>(type: JsConnectionPointType): VectorArray<V> { type = JsConnectionPointTypeFromArrayTypeMap[type]; switch (type) { case JsConnectionPointType.COLOR: { return new VectorArray([new Color()]) as VectorArray<V>; } case JsConnectionPointType.EULER: { return new VectorArray([new Euler()]) as VectorArray<V>; } case JsConnectionPointType.MATRIX4: { return new VectorArray([new Matrix4()]) as VectorArray<V>; } case JsConnectionPointType.QUATERNION: { return new VectorArray([new Quaternion()]) as VectorArray<V>; } case JsConnectionPointType.VECTOR2: { return new VectorArray([new Vector2()]) as VectorArray<V>; } case JsConnectionPointType.VECTOR3: { return new VectorArray([new Vector3()]) as VectorArray<V>; } case JsConnectionPointType.VECTOR4: { return new VectorArray([new Vector4()]) as VectorArray<V>; } } console.warn('createVectorArray not implemented for type:', type); return new VectorArray([new Vector4()]) as VectorArray<V>; } export enum SerializedVariableType { Box3 = 'Box3', Color = 'Color', Euler = 'Euler', Matrix4 = 'Matrix4', Plane = 'Plane', Quaternion = 'Quaternion', Ray = 'Ray', Sphere = 'Sphere', Vector2 = 'Vector2', Vector3 = 'Vector3', Vector4 = 'Vector4', // prim array boolean_Array = 'boolean[]', number_Array = 'number[]', string_Array = 'string[]', // vector array Color_Array = 'Color[]', Euler_Array = 'Euler[]', // Intersection_Array = 'Intersection[]', Matrix4_Array = 'Matrix4[]', Quaternion_Array = 'Quaternion[]', // Texture_Array = 'Texture[]', Vector2_Array = 'Vector2[]', Vector3_Array = 'Vector3[]', Vector4_Array = 'Vector4[]', } interface EulerSerialized { rotation: Number3; rotationOrder: EulerOrder; } interface SerializedDataByType { [SerializedVariableType.Box3]: {min: Number3; max: Number3}; [SerializedVariableType.Color]: Number3; [SerializedVariableType.Euler]: EulerSerialized; [SerializedVariableType.Matrix4]: Number16; [SerializedVariableType.Plane]: {normal: Number3; constant: number}; [SerializedVariableType.Quaternion]: Number4; [SerializedVariableType.Ray]: {origin: Number3; direction: Number3}; [SerializedVariableType.Sphere]: {center: Number3; radius: number}; [SerializedVariableType.Vector2]: Number2; [SerializedVariableType.Vector3]: Number3; [SerializedVariableType.Vector4]: Number4; // prim array [SerializedVariableType.boolean_Array]: boolean[]; [SerializedVariableType.number_Array]: number[]; [SerializedVariableType.string_Array]: string[]; // vector array [SerializedVariableType.Color_Array]: Number3[]; [SerializedVariableType.Euler_Array]: EulerSerialized[]; [SerializedVariableType.Matrix4_Array]: Number16[]; [SerializedVariableType.Quaternion_Array]: Number4[]; [SerializedVariableType.Vector2_Array]: Number2[]; [SerializedVariableType.Vector3_Array]: Number3[]; [SerializedVariableType.Vector4_Array]: Number4[]; } interface VariableByType { [SerializedVariableType.Box3]: Box3; [SerializedVariableType.Color]: Color; [SerializedVariableType.Euler]: Euler; [SerializedVariableType.Matrix4]: Matrix4; [SerializedVariableType.Plane]: Plane; [SerializedVariableType.Quaternion]: Quaternion; [SerializedVariableType.Ray]: Ray; [SerializedVariableType.Sphere]: Sphere; [SerializedVariableType.Vector2]: Vector2; [SerializedVariableType.Vector3]: Vector3; [SerializedVariableType.Vector4]: Vector4; // prim array [SerializedVariableType.boolean_Array]: PrimitiveArray<boolean>; [SerializedVariableType.number_Array]: PrimitiveArray<number>; [SerializedVariableType.string_Array]: PrimitiveArray<string>; // vector array [SerializedVariableType.Color_Array]: VectorArray<Color>; [SerializedVariableType.Euler_Array]: VectorArray<Euler>; [SerializedVariableType.Matrix4_Array]: VectorArray<Matrix4>; [SerializedVariableType.Quaternion_Array]: VectorArray<Quaternion>; [SerializedVariableType.Vector2_Array]: VectorArray<Vector2>; [SerializedVariableType.Vector3_Array]: VectorArray<Vector3>; [SerializedVariableType.Vector4_Array]: VectorArray<Vector4>; } type SerializableVariable = | Box3 | Color | Euler | Matrix4 | Plane | Quaternion | Ray | Sphere | Vector2 | Vector3 | Vector4; export interface SerializedVariable<T extends SerializedVariableType> { type: SerializedVariableType; data: SerializedDataByType[T]; } export function isVariableSerializable(variable: any): variable is SerializableVariable { if ( variable instanceof Box3 || variable instanceof Color || variable instanceof Euler || variable instanceof Matrix4 || variable instanceof Plane || variable instanceof Quaternion || variable instanceof Ray || variable instanceof Sphere || variable instanceof Vector2 || variable instanceof Vector3 || variable instanceof Vector4 || variable instanceof PrimitiveArray || variable instanceof VectorArray ) { return true; } else { console.warn('not serializable', variable); return false; } } export function serializeVariable<T extends SerializedVariableType>( variable: VariableByType[T] ): SerializedVariable<T> { if (variable instanceof Box3) { const data: SerializedVariable<SerializedVariableType.Box3> = { type: SerializedVariableType.Box3, data: { min: variable.min.toArray() as Number3, max: variable.min.toArray() as Number3, }, }; return data as SerializedVariable<T>; } if (variable instanceof Color) { const data: SerializedVariable<SerializedVariableType.Color> = { type: SerializedVariableType.Color, data: variable.toArray() as Number3, }; return data as SerializedVariable<T>; } if (variable instanceof Euler) { const data: SerializedVariable<SerializedVariableType.Euler> = { type: SerializedVariableType.Euler, data: { rotation: variable.toArray() as Number3, rotationOrder: variable.order, }, }; return data as SerializedVariable<T>; } if (variable instanceof Matrix4) { const data: SerializedVariable<SerializedVariableType.Matrix4> = { type: SerializedVariableType.Matrix4, data: variable.toArray() as Number16, }; return data as SerializedVariable<T>; } if (variable instanceof Plane) { const data: SerializedVariable<SerializedVariableType.Plane> = { type: SerializedVariableType.Plane, data: { normal: variable.normal.toArray() as Number3, constant: variable.constant, }, }; return data as SerializedVariable<T>; } if (variable instanceof Quaternion) { const data: SerializedVariable<SerializedVariableType.Quaternion> = { type: SerializedVariableType.Quaternion, data: variable.toArray() as Number4, }; return data as SerializedVariable<T>; } if (variable instanceof Ray) { const data: SerializedVariable<SerializedVariableType.Ray> = { type: SerializedVariableType.Ray, data: { origin: variable.origin.toArray() as Number3, direction: variable.direction.toArray() as Number3, }, }; return data as SerializedVariable<T>; } if (variable instanceof Sphere) { const data: SerializedVariable<SerializedVariableType.Sphere> = { type: SerializedVariableType.Sphere, data: { center: variable.center.toArray() as Number3, radius: variable.radius, }, }; return data as SerializedVariable<T>; } if (variable instanceof Vector2) { const data: SerializedVariable<SerializedVariableType.Vector2> = { type: SerializedVariableType.Vector2, data: variable.toArray() as Number2, }; return data as SerializedVariable<T>; } if (variable instanceof Vector3) { const data: SerializedVariable<SerializedVariableType.Vector3> = { type: SerializedVariableType.Vector3, data: variable.toArray() as Number3, }; return data as SerializedVariable<T>; } if (variable instanceof Vector4) { const data: SerializedVariable<SerializedVariableType.Vector4> = { type: SerializedVariableType.Vector4, data: variable.toArray() as Number4, }; return data as SerializedVariable<T>; } if ((variable as PrimitiveArray<any>).isPrimitiveArray) { const elements = variable.elements(); const firstElement = elements[0]; if (isBoolean(firstElement)) { const data: SerializedVariable<SerializedVariableType.boolean_Array> = { type: SerializedVariableType.boolean_Array, data: elements.map((v) => v as boolean), }; return data as SerializedVariable<T>; } if (isNumber(firstElement)) { const data: SerializedVariable<SerializedVariableType.number_Array> = { type: SerializedVariableType.number_Array, data: elements.map((v) => v as number), }; return data as SerializedVariable<T>; } if (isString(firstElement)) { const data: SerializedVariable<SerializedVariableType.string_Array> = { type: SerializedVariableType.string_Array, data: elements.map((v) => v as string), }; return data as SerializedVariable<T>; } } if ((variable as VectorArray<any>).isVectorArray) { const elements = (variable as VectorArray<any>).elements(); const firstElement = elements[0]; if (firstElement instanceof Color) { const data: SerializedVariable<SerializedVariableType.Color_Array> = { type: SerializedVariableType.Color_Array, data: elements.map((v) => v.toArray() as Number3), }; return data as SerializedVariable<T>; } if (firstElement instanceof Euler) { const data: SerializedVariable<SerializedVariableType.Euler_Array> = { type: SerializedVariableType.Euler_Array, data: elements.map((v) => ({ rotation: v.toArray() as Number3, rotationOrder: (v as Euler).order, })), }; return data as SerializedVariable<T>; } if (firstElement instanceof Matrix4) { const data: SerializedVariable<SerializedVariableType.Matrix4_Array> = { type: SerializedVariableType.Matrix4_Array, data: elements.map((v) => v.toArray() as Number16), }; return data as SerializedVariable<T>; } if (firstElement instanceof Quaternion) { const data: SerializedVariable<SerializedVariableType.Quaternion_Array> = { type: SerializedVariableType.Quaternion_Array, data: elements.map((v) => v.toArray() as Number4), }; return data as SerializedVariable<T>; } if (firstElement instanceof Vector2) { const data: SerializedVariable<SerializedVariableType.Vector2_Array> = { type: SerializedVariableType.Vector2_Array, data: elements.map((v) => v.toArray() as Number2), }; return data as SerializedVariable<T>; } if (firstElement instanceof Vector3) { const data: SerializedVariable<SerializedVariableType.Vector3_Array> = { type: SerializedVariableType.Vector3_Array, data: elements.map((v) => v.toArray() as Number3), }; return data as SerializedVariable<T>; } if (firstElement instanceof Vector4) { const data: SerializedVariable<SerializedVariableType.Vector4_Array> = { type: SerializedVariableType.Vector4_Array, data: elements.map((v) => v.toArray() as Number4), }; return data as SerializedVariable<T>; } console.log('array variable serialization not implemeted', variable, firstElement); } console.log('variable serialization not implemeted', variable); const data: SerializedVariable<SerializedVariableType.Vector3> = { type: SerializedVariableType.Vector3, data: new Vector3().toArray() as Number3, }; return data as SerializedVariable<T>; } export function deserializeVariable<T extends SerializedVariableType>( serialized: SerializedVariable<T> ): VariableByType[T] { const type = serialized.type; switch (type) { case SerializedVariableType.Box3: { const data = (serialized as SerializedVariable<SerializedVariableType.Box3>).data; const box3 = new Box3(); box3.min.set(data.min[0], data.min[1], data.min[2]); box3.max.set(data.max[0], data.max[1], data.max[2]); return box3 as VariableByType[T]; } case SerializedVariableType.Color: { const data = (serialized as SerializedVariable<SerializedVariableType.Color>).data; const color = new Color(); color.r = data[0]; color.g = data[1]; color.b = data[2]; return color as VariableByType[T]; } case SerializedVariableType.Euler: { const data = (serialized as SerializedVariable<SerializedVariableType.Euler>).data; const euler = new Euler(data.rotation[0], data.rotation[1], data.rotation[2], data.rotationOrder); return euler as VariableByType[T]; } case SerializedVariableType.Matrix4: { const data = (serialized as SerializedVariable<SerializedVariableType.Matrix4>).data; const matrix = new Matrix4(); matrix.set(...data); return matrix as VariableByType[T]; } case SerializedVariableType.Plane: { const data = (serialized as SerializedVariable<SerializedVariableType.Plane>).data; const plane = new Plane(); plane.normal.set(...data.normal); plane.constant = data.constant; return plane as VariableByType[T]; } case SerializedVariableType.Quaternion: { const data = (serialized as SerializedVariable<SerializedVariableType.Quaternion>).data; const vector = new Quaternion(); vector.set(...data); return vector as VariableByType[T]; } case SerializedVariableType.Ray: { const data = (serialized as SerializedVariable<SerializedVariableType.Ray>).data; const ray = new Ray(); ray.origin.set(...data.origin); ray.direction.set(...data.direction); return ray as VariableByType[T]; } case SerializedVariableType.Sphere: { const data = (serialized as SerializedVariable<SerializedVariableType.Sphere>).data; const sphere = new Sphere(); sphere.center.set(...data.center); sphere.radius = data.radius; return sphere as VariableByType[T]; } case SerializedVariableType.Vector2: { const data = (serialized as SerializedVariable<SerializedVariableType.Vector2>).data; const vector = new Vector2(); vector.set(...data); return vector as VariableByType[T]; } case SerializedVariableType.Vector3: { const data = (serialized as SerializedVariable<SerializedVariableType.Vector3>).data; const vector = new Vector3(); vector.set(...data); return vector as VariableByType[T]; } case SerializedVariableType.Vector4: { const data = (serialized as SerializedVariable<SerializedVariableType.Vector4>).data; const vector = new Vector4(); vector.set(...data); return vector as VariableByType[T]; } // prim array case SerializedVariableType.boolean_Array: { const data = (serialized as SerializedVariable<SerializedVariableType.boolean_Array>).data; const values = [...data]; const numberArray = new PrimitiveArray(values); return numberArray as VariableByType[T]; } case SerializedVariableType.number_Array: { const data = (serialized as SerializedVariable<SerializedVariableType.number_Array>).data; const values = [...data]; const numberArray = new PrimitiveArray(values); return numberArray as VariableByType[T]; } case SerializedVariableType.string_Array: { const data = (serialized as SerializedVariable<SerializedVariableType.string_Array>).data; const values = [...data]; const numberArray = new PrimitiveArray(values); return numberArray as VariableByType[T]; } // vector array case SerializedVariableType.Color_Array: { const data = (serialized as SerializedVariable<SerializedVariableType.Color_Array>).data; const vectors = data.map((d) => { const color = new Color(); color.r = d[0]; color.g = d[1]; color.b = d[2]; return color; }); const vectorArray = new VectorArray(vectors); return vectorArray as VariableByType[T]; } case SerializedVariableType.Euler_Array: { const data = (serialized as SerializedVariable<SerializedVariableType.Euler_Array>).data; const eulers = data.map((d) => { const euler = new Euler(d.rotation[0], d.rotation[1], d.rotation[2], d.rotationOrder); return euler; }); const vectorArray = new VectorArray(eulers); return vectorArray as VariableByType[T]; } case SerializedVariableType.Matrix4_Array: { const data = (serialized as SerializedVariable<SerializedVariableType.Matrix4_Array>).data; const vectors = data.map((d) => { const v = new Matrix4(); v.set(...d); return v; }); const vectorArray = new VectorArray(vectors); return vectorArray as VariableByType[T]; } case SerializedVariableType.Quaternion_Array: { const data = (serialized as SerializedVariable<SerializedVariableType.Quaternion_Array>).data; const vectors = data.map((d) => { const v = new Quaternion(); v.set(...d); return v; }); const vectorArray = new VectorArray(vectors); return vectorArray as VariableByType[T]; } case SerializedVariableType.Vector2_Array: { const data = (serialized as SerializedVariable<SerializedVariableType.Vector2_Array>).data; const vectors = data.map((d) => { const v = new Vector2(); v.set(...d); return v; }); const vectorArray = new VectorArray(vectors); return vectorArray as VariableByType[T]; } case SerializedVariableType.Vector3_Array: { const data = (serialized as SerializedVariable<SerializedVariableType.Vector3_Array>).data; const vectors = data.map((d) => { const v = new Vector3(); v.set(...d); return v; }); const vectorArray = new VectorArray(vectors); return vectorArray as VariableByType[T]; } case SerializedVariableType.Vector4_Array: { const data = (serialized as SerializedVariable<SerializedVariableType.Vector4_Array>).data; const vectors = data.map((d) => { const v = new Vector4(); v.set(...d); return v; }); const vectorArray = new VectorArray(vectors); return vectorArray as VariableByType[T]; } } TypeAssert.unreachable(type); }