polygonjs-engine
Version:
node-based webgl 3D engine https://polygonjs.com
287 lines (286 loc) • 10.1 kB
JavaScript
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";