UNPKG

@polygonjs/polygonjs

Version:

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

345 lines (323 loc) 9.57 kB
import {Number2} from '../../types/GlobalTypes'; import { Object3D, LineSegments, InstancedMesh, Mesh, Points, Group, Scene, MeshStandardMaterial, PointsMaterial, LineBasicMaterial, FrontSide, } from 'three'; import type { AmbientLight, // SkinnedMesh, // Bone, CubeCamera, DirectionalLight, HemisphereLight, LightProbe, Material, LOD, OrthographicCamera, PerspectiveCamera, PointLight, RectAreaLight, SpotLight, } from 'three'; import {GroupCollectionData} from './EntityGroupCollection'; import {CoreObjectType, ObjectContent} from './ObjectContent'; import type {PhysicalCamera, ShapedAreaLight, PhysicalSpotLight} from '../render/PBR/three-gpu-pathtracer'; // import {Poly} from '../../engine/Poly'; interface MaterialsByString { [propName: string]: Material; } export enum ObjectType { AMBIENT_LIGHT = 'AmbientLight', AREA_LIGHT = 'AreaLight', // BONE = 'Bone', CUBE_CAMERA = 'CubeCamera', DIRECTIONAL_LIGHT = 'DirectionalLight', GROUP = 'Group', HEMISPHERE_LIGHT = 'HemisphereLight', INSTANCED_MESH = 'InstancedMesh', LIGHT_PROBE = 'LightProbe', LINE_SEGMENTS = 'LineSegments', LOD = 'LOD', MESH = 'Mesh', OBJECT3D = 'Object3D', ORTHOGRAPHIC_CAMERA = 'OrthographicCamera', PERSPECTIVE_CAMERA = 'PerspectiveCamera', PHYSICAL_CAMERA = 'PhysicalCamera', PHYSICAL_SPOT_LIGHT = 'PhysicalSpotLight', POINT_LIGHT = 'PointLight', POINTS = 'Points', SCENE = 'Scene', SHAPED_AREA_LIGHT = 'ShapedAreaLight', // SKINNED_MESH = 'SkinnedMesh', SPOT_LIGHT = 'SpotLight', UNKNOWN = 'Unknown', QUAD = 'Quad', } export const OBJECT_TYPES: ObjectType[] = [ ObjectType.GROUP, ObjectType.LINE_SEGMENTS, ObjectType.MESH, ObjectType.OBJECT3D, ObjectType.POINTS, ObjectType.SCENE, ]; interface ObjectContentConstructor<T extends CoreObjectType> { new (arg0: any, arg1?: any, arg2?: any): ObjectContent<T>; } export type DefaultObjectContentConstructor = ObjectContentConstructor<CoreObjectType>; export interface ObjectByObjectType { [ObjectType.AMBIENT_LIGHT]: AmbientLight; [ObjectType.AREA_LIGHT]: RectAreaLight; // [ObjectType.BONE]: typeof Bone; [ObjectType.CUBE_CAMERA]: CubeCamera; [ObjectType.DIRECTIONAL_LIGHT]: DirectionalLight; [ObjectType.GROUP]: Group; [ObjectType.HEMISPHERE_LIGHT]: HemisphereLight; [ObjectType.INSTANCED_MESH]: InstancedMesh; [ObjectType.LIGHT_PROBE]: LightProbe; [ObjectType.LINE_SEGMENTS]: LineSegments; [ObjectType.LOD]: LOD; [ObjectType.MESH]: Mesh; [ObjectType.OBJECT3D]: Object3D; [ObjectType.POINT_LIGHT]: PointLight; [ObjectType.POINTS]: Points; [ObjectType.ORTHOGRAPHIC_CAMERA]: OrthographicCamera; [ObjectType.PERSPECTIVE_CAMERA]: PerspectiveCamera; [ObjectType.PHYSICAL_CAMERA]: PhysicalCamera; [ObjectType.PHYSICAL_SPOT_LIGHT]: PhysicalSpotLight; // [ObjectType.POINTS]: typeof Points; [ObjectType.SCENE]: Scene; [ObjectType.SHAPED_AREA_LIGHT]: ShapedAreaLight; // [ObjectType.SKINNED_MESH]: typeof SkinnedMesh; [ObjectType.SPOT_LIGHT]: SpotLight; [ObjectType.UNKNOWN]: null; [ObjectType.QUAD]: null; } export interface ObjectData { type: ObjectType; name: string | null; childrenCount: number; groupData: GroupCollectionData; verticesCount: number; pointsCount: number; primitivesCount: number; primitiveName: string; } const UNKNOWN_OBJECT_TYPE: ObjectTypeData = { type: ObjectType.UNKNOWN, checkFunc: (o) => ObjectType.UNKNOWN, humanName: 'Unknown', ctor: null as any, }; // type DataByConstructor = Map<DefaultObjectContentConstructor, ObjectTypeData>; type ObjectTypeCheckFunction = (object: ObjectContent<CoreObjectType>) => ObjectType | undefined; type DataByObjectType = Map<ObjectType, ObjectTypeData>; export interface ObjectTypeData { type: ObjectType; checkFunc: ObjectTypeCheckFunction; ctor: DefaultObjectContentConstructor; humanName: string; } interface ObjectTypeConstructorRegisters { objectTypeCheckFunctions: ObjectTypeCheckFunction[]; dataByObjectType: DataByObjectType; } function _initializeObjectTypeFromConstructor() { const objectTypeCheckFunctions: ObjectTypeCheckFunction[] = []; const dataByObjectType: DataByObjectType = new Map(); const maps: ObjectTypeConstructorRegisters = {objectTypeCheckFunctions, dataByObjectType}; function _register( type: ObjectType, checkFunc: ObjectTypeCheckFunction, ctor: DefaultObjectContentConstructor, humanName?: string ) { _registerObjectType_(maps, { type, checkFunc, ctor, humanName: humanName || type, }); } _register( ObjectType.OBJECT3D, (o) => ((o as Object3D).isObject3D ? ObjectType.OBJECT3D : undefined), Object3D, 'Object3D' ); _register(ObjectType.MESH, (o) => ((o as Mesh).isMesh ? ObjectType.MESH : undefined), Mesh, 'Mesh'); _register(ObjectType.GROUP, (o) => ((o as Group).isGroup ? ObjectType.GROUP : undefined), Group, 'Group'); _register( ObjectType.LINE_SEGMENTS, (o) => ((o as LineSegments).isLineSegments ? ObjectType.LINE_SEGMENTS : undefined), LineSegments, 'LineSegments' ); _register( ObjectType.INSTANCED_MESH, (o) => ((o as InstancedMesh).isInstancedMesh ? ObjectType.INSTANCED_MESH : undefined), InstancedMesh, 'InstancedMesh' ); _register(ObjectType.POINTS, (o) => ((o as Points).isPoints ? ObjectType.POINTS : undefined), Points, 'Points'); _register(ObjectType.SCENE, (o) => ((o as Scene).isScene ? ObjectType.SCENE : undefined), Scene, 'Scene'); return maps; } const {objectTypeCheckFunctions, dataByObjectType}: ObjectTypeConstructorRegisters = _initializeObjectTypeFromConstructor(); function _registerObjectType_(maps: ObjectTypeConstructorRegisters, data: ObjectTypeData) { maps.objectTypeCheckFunctions.unshift(data.checkFunc); maps.dataByObjectType.set(data.type, data); } export function registerObjectType(data: ObjectTypeData) { _registerObjectType_({objectTypeCheckFunctions, dataByObjectType}, data); } export function objectTypeFromObject(object: ObjectContent<CoreObjectType>): ObjectType { return dataFromObject(object).type; } export function dataFromObject(object: ObjectContent<CoreObjectType>): ObjectTypeData { for (const checkFunc of objectTypeCheckFunctions) { const objectType = checkFunc(object); if (objectType) { return dataByObjectType.get(objectType) as ObjectTypeData; } } return UNKNOWN_OBJECT_TYPE; } export function objectConstructorByObjectType<O extends ObjectType>(objectType: O): ObjectByObjectType[O] { const data = dataByObjectType.get(objectType); if (data) { return data.ctor as any as ObjectByObjectType[O]; } else { console.warn(`no constructor found for type '${objectType}'`); return dataByObjectType.get(ObjectType.MESH) as any as ObjectByObjectType[O]; } } export const DEFAULT_MATERIALS: MaterialsByString = { MeshStandard: new MeshStandardMaterial({ color: 0xffffff, side: FrontSide, metalness: 0.5, roughness: 0.9, }), // [ObjectType.MESH]: new MeshLambertMaterial({ // color: new Color(1, 1, 1), // side: FrontSide, // vertexColors: false, // transparent: true, // depthTest: true, // }), [ObjectType.MESH]: new MeshStandardMaterial({ color: 0xffffff, side: FrontSide, metalness: 0.0, roughness: 0.9, }), [ObjectType.POINTS]: new PointsMaterial({ color: 0xffffff, size: 0.1, //blending: AdditiveBlending depthTest: true, }), [ObjectType.LINE_SEGMENTS]: new LineBasicMaterial({ color: 0xffffff, linewidth: 1, }), }; export enum AttribClass { POINT = 'point', VERTEX = 'vertex', PRIMITIVE = 'primitive', OBJECT = 'object', CORE_GROUP = 'coreGroup', } export const ATTRIBUTE_CLASSES: Array<AttribClass> = [ AttribClass.POINT, AttribClass.VERTEX, AttribClass.PRIMITIVE, AttribClass.OBJECT, AttribClass.CORE_GROUP, ]; export const ATTRIBUTE_CLASSES_WITHOUT_CORE_GROUP: Array<AttribClass> = [ AttribClass.POINT, AttribClass.VERTEX, AttribClass.PRIMITIVE, AttribClass.OBJECT, ]; export const AttribClassMenuEntries = ATTRIBUTE_CLASSES.map((name, value) => ({name, value})); export const AttribClassMenuEntriesWithoutCoreGroup = ATTRIBUTE_CLASSES_WITHOUT_CORE_GROUP.map((name, value) => ({ name, value, })); export enum AttribType { NUMERIC = 'numeric', STRING = 'string', } export const ATTRIBUTE_TYPES: Array<AttribType> = [AttribType.NUMERIC, AttribType.STRING]; export const AttribTypeMenuEntries = ATTRIBUTE_TYPES.map((name, value) => ({name, value})); export enum AttribSize { FLOAT = 1, VECTOR2 = 2, VECTOR3 = 3, VECTOR4 = 4, } export const ATTRIBUTE_SIZES: Array<AttribSize> = [ AttribSize.FLOAT, AttribSize.VECTOR2, AttribSize.VECTOR3, AttribSize.VECTOR4, ]; export const ATTRIBUTE_SIZE_RANGE: Number2 = [AttribSize.FLOAT, AttribSize.VECTOR4]; // export const CoreConstant = { // ATTRIB_CLASS: { // VERTEX: AttribClass.POINT, // OBJECT: AttribClass.OBJECT, // }, // OBJECT_TYPES: ObjectTypes, // CONSTRUCTOR_NAMES_BY_CONSTRUCTOR_NAME: { // [Scene.name]: 'Scene', // [Group.name]: 'Group', // [Object3D.name]: 'Object3D', // [Mesh.name]: 'Mesh', // [Points.name]: 'Points', // [LineSegments.name]: 'LineSegments', // [Bone.name]: 'Bone', // [SkinnedMesh.name]: 'SkinnedMesh', // }, // CONSTRUCTORS_BY_NAME: { // [ObjectType.MESH]: Mesh, // [ObjectType.POINTS]: Points, // [ObjectType.LINE_SEGMENTS]: LineSegments, // }, // MATERIALS: materials, // }; export enum ComponentName { x = 'x', y = 'y', z = 'z', w = 'w', r = 'r', g = 'g', b = 'b', } export type ComponentIndex = 0 | 1 | 2 | 3; export const COMPONENT_INDICES: Record<ComponentName, ComponentIndex> = { x: 0, y: 1, z: 2, w: 3, r: 0, g: 1, b: 2, }; export const DOT = '.'; export type GroupString = string;