UNPKG

polygonjs-engine

Version:

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

287 lines (286 loc) 10.1 kB
import {TypedEventNode} from "./_Base"; import {NodeContext as NodeContext2} from "../../poly/NodeContext"; import {RaycastCPUController} from "./utils/raycast/CPUController"; import {CPUIntersectWith, CPU_INTERSECT_WITH_OPTIONS} from "./utils/raycast/CpuConstants"; import {RaycastGPUController} from "./utils/raycast/GPUController"; import {AttribType, ATTRIBUTE_TYPES, AttribTypeMenuEntries} from "../../../core/geometry/Constant"; import {EventConnectionPoint, EventConnectionPointType} from "../utils/io/connections/Event"; import {ParamType as ParamType2} from "../../poly/ParamType"; const TIMESTAMP = 1e3 / 60; var RaycastMode; (function(RaycastMode2) { RaycastMode2["CPU"] = "cpu"; RaycastMode2["GPU"] = "gpu"; })(RaycastMode || (RaycastMode = {})); const RAYCAST_MODES = [RaycastMode.CPU, RaycastMode.GPU]; function visible_for_cpu(options = {}) { options["mode"] = RAYCAST_MODES.indexOf(RaycastMode.CPU); return {visibleIf: options}; } function visible_for_cpu_geometry(options = {}) { options["mode"] = RAYCAST_MODES.indexOf(RaycastMode.CPU); options["intersectWith"] = CPU_INTERSECT_WITH_OPTIONS.indexOf(CPUIntersectWith.GEOMETRY); return {visibleIf: options}; } function visible_for_cpu_plane(options = {}) { options["mode"] = RAYCAST_MODES.indexOf(RaycastMode.CPU); options["intersectWith"] = CPU_INTERSECT_WITH_OPTIONS.indexOf(CPUIntersectWith.PLANE); return {visibleIf: options}; } function visible_for_gpu(options = {}) { options["mode"] = RAYCAST_MODES.indexOf(RaycastMode.GPU); return {visibleIf: options}; } export var TargetType; (function(TargetType2) { TargetType2["SCENE_GRAPH"] = "scene graph"; TargetType2["NODE"] = "node"; })(TargetType || (TargetType = {})); export const TARGET_TYPES = [TargetType.SCENE_GRAPH, TargetType.NODE]; import {NodeParamsConfig, ParamConfig} from "../utils/params/ParamsConfig"; class RaycastParamsConfig extends NodeParamsConfig { constructor() { super(...arguments); this.mode = ParamConfig.INTEGER(RAYCAST_MODES.indexOf(RaycastMode.CPU), { menu: { entries: RAYCAST_MODES.map((name, value) => { return { name, value }; }) } }); this.mouse = ParamConfig.VECTOR2([0, 0], {cook: false}); this.overrideCamera = ParamConfig.BOOLEAN(0); this.overrideRay = ParamConfig.BOOLEAN(0, { visibleIf: { mode: RAYCAST_MODES.indexOf(RaycastMode.CPU), overrideCamera: 1 } }); this.camera = ParamConfig.OPERATOR_PATH("/perspective_camera1", { nodeSelection: { context: NodeContext2.OBJ }, dependentOnFoundNode: false, visibleIf: { overrideCamera: 1, overrideRay: 0 } }); this.rayOrigin = ParamConfig.VECTOR3([0, 0, 0], { visibleIf: { overrideCamera: 1, overrideRay: 1 } }); this.rayDirection = ParamConfig.VECTOR3([0, 0, 1], { visibleIf: { overrideCamera: 1, overrideRay: 1 } }); this.material = ParamConfig.OPERATOR_PATH("/MAT/mesh_basic_builder1", { nodeSelection: { context: NodeContext2.MAT }, dependentOnFoundNode: false, callback: (node, param) => { RaycastGPUController.PARAM_CALLBACK_update_material(node); }, ...visible_for_gpu() }); this.pixelValue = ParamConfig.VECTOR4([0, 0, 0, 0], { cook: false, ...visible_for_gpu() }); this.hitThreshold = ParamConfig.FLOAT(0.5, { cook: false, ...visible_for_gpu() }); this.intersectWith = ParamConfig.INTEGER(CPU_INTERSECT_WITH_OPTIONS.indexOf(CPUIntersectWith.GEOMETRY), { menu: { entries: CPU_INTERSECT_WITH_OPTIONS.map((name, value) => { return {name, value}; }) }, ...visible_for_cpu() }); this.pointsThreshold = ParamConfig.FLOAT(1, { range: [0, 100], rangeLocked: [true, false], ...visible_for_cpu() }); this.planeDirection = ParamConfig.VECTOR3([0, 1, 0], { ...visible_for_cpu_plane() }); this.planeOffset = ParamConfig.FLOAT(0, { ...visible_for_cpu_plane() }); this.targetType = ParamConfig.INTEGER(0, { menu: { entries: TARGET_TYPES.map((name, value) => { return {name, value}; }) } }); this.targetNode = ParamConfig.NODE_PATH("/geo1", { nodeSelection: { context: NodeContext2.OBJ }, dependentOnFoundNode: false, callback: (node, param) => { RaycastCPUController.PARAM_CALLBACK_update_target(node); }, ...visible_for_cpu_geometry({targetType: TARGET_TYPES.indexOf(TargetType.NODE)}) }); this.objectMask = ParamConfig.STRING("*geo1*", { callback: (node, param) => { RaycastCPUController.PARAM_CALLBACK_update_target(node); }, ...visible_for_cpu_geometry({targetType: TARGET_TYPES.indexOf(TargetType.SCENE_GRAPH)}) }); this.printFoundObjectsFromMask = ParamConfig.BUTTON(null, { callback: (node, param) => { RaycastCPUController.PARAM_CALLBACK_print_resolve(node); }, ...visible_for_cpu_geometry({targetType: TARGET_TYPES.indexOf(TargetType.SCENE_GRAPH)}) }); this.traverseChildren = ParamConfig.BOOLEAN(0, { callback: (node, param) => { RaycastCPUController.PARAM_CALLBACK_update_target(node); }, ...visible_for_cpu_geometry() }); this.sep = ParamConfig.SEPARATOR(null, { ...visible_for_cpu_geometry() }); this.tpositionTarget = ParamConfig.BOOLEAN(0, { cook: false, ...visible_for_cpu() }); this.position = ParamConfig.VECTOR3([0, 0, 0], { cook: false, ...visible_for_cpu({tpositionTarget: 0}) }); this.positionTarget = ParamConfig.OPERATOR_PATH("", { cook: false, ...visible_for_cpu({tpositionTarget: 1}), paramSelection: ParamType2.VECTOR3, computeOnDirty: true }); this.tvelocity = ParamConfig.BOOLEAN(0, { cook: false }); this.tvelocityTarget = ParamConfig.BOOLEAN(0, { cook: false, ...visible_for_cpu({tvelocity: 1}) }); this.velocity = ParamConfig.VECTOR3([0, 0, 0], { cook: false, ...visible_for_cpu({tvelocity: 1, tvelocityTarget: 0}) }); this.velocityTarget = ParamConfig.OPERATOR_PATH("", { cook: false, ...visible_for_cpu({tvelocity: 1, tvelocityTarget: 1}), paramSelection: ParamType2.VECTOR3, computeOnDirty: true }); this.geoAttribute = ParamConfig.BOOLEAN(0, visible_for_cpu_geometry()); this.geoAttributeName = ParamConfig.STRING("id", { cook: false, ...visible_for_cpu_geometry({geoAttribute: 1}) }); this.geoAttributeType = ParamConfig.INTEGER(ATTRIBUTE_TYPES.indexOf(AttribType.NUMERIC), { menu: { entries: AttribTypeMenuEntries }, ...visible_for_cpu_geometry({geoAttribute: 1}) }); this.geoAttributeValue1 = ParamConfig.FLOAT(0, { cook: false, ...visible_for_cpu_geometry({ geoAttribute: 1, geoAttributeType: ATTRIBUTE_TYPES.indexOf(AttribType.NUMERIC) }) }); this.geoAttributeValues = ParamConfig.STRING("", { ...visible_for_cpu_geometry({ geoAttribute: 1, geoAttributeType: ATTRIBUTE_TYPES.indexOf(AttribType.STRING) }) }); } } const ParamsConfig2 = new RaycastParamsConfig(); const RaycastEventNode2 = class extends TypedEventNode { constructor() { super(...arguments); this.params_config = ParamsConfig2; this.cpu_controller = new RaycastCPUController(this); this.gpu_controller = new RaycastGPUController(this); this._last_event_processed_at = performance.now(); } static type() { return "raycast"; } initializeNode() { this.io.inputs.setNamedInputConnectionPoints([ new EventConnectionPoint("trigger", EventConnectionPointType.BASE, this._process_trigger_event_throttled.bind(this)), new EventConnectionPoint("mouse", EventConnectionPointType.MOUSE, this._process_mouse_event.bind(this)), new EventConnectionPoint("update_objects", EventConnectionPointType.BASE, this._process_trigger_update_objects.bind(this)), new EventConnectionPoint("trigger_vel_reset", EventConnectionPointType.BASE, this._process_trigger_vel_reset.bind(this)) ]); this.io.outputs.setNamedOutputConnectionPoints([ new EventConnectionPoint(RaycastEventNode2.OUTPUT_HIT, EventConnectionPointType.BASE), new EventConnectionPoint(RaycastEventNode2.OUTPUT_MISS, EventConnectionPointType.BASE) ]); } trigger_hit(context) { this.dispatch_event_to_output(RaycastEventNode2.OUTPUT_HIT, context); } trigger_miss(context) { this.dispatch_event_to_output(RaycastEventNode2.OUTPUT_MISS, context); } _process_mouse_event(context) { if (this.pv.mode == RAYCAST_MODES.indexOf(RaycastMode.CPU)) { this.cpu_controller.update_mouse(context); } else { this.gpu_controller.update_mouse(context); } } _process_trigger_event_throttled(context) { const previous = this._last_event_processed_at; const now = performance.now(); this._last_event_processed_at = now; const delta = now - previous; if (delta < TIMESTAMP) { setTimeout(() => { this._process_trigger_event(context); }, TIMESTAMP - delta); } else { this._process_trigger_event(context); } } _process_trigger_event(context) { if (this.pv.mode == RAYCAST_MODES.indexOf(RaycastMode.CPU)) { this.cpu_controller.process_event(context); } else { this.gpu_controller.process_event(context); } } _process_trigger_update_objects(context) { if (this.pv.mode == RAYCAST_MODES.indexOf(RaycastMode.CPU)) { this.cpu_controller.update_target(); } } _process_trigger_vel_reset(context) { if (this.pv.mode == RAYCAST_MODES.indexOf(RaycastMode.CPU)) { this.cpu_controller.velocity_controller.reset(); } } }; export let RaycastEventNode = RaycastEventNode2; RaycastEventNode.OUTPUT_HIT = "hit"; RaycastEventNode.OUTPUT_MISS = "miss";