UNPKG

@polygonjs/polygonjs

Version:

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

185 lines (184 loc) 6.51 kB
"use strict"; import { TargetType, TARGET_TYPES } from "../../Raycast"; import { NodeContext } from "../../../../poly/NodeContext"; import { TypeAssert } from "../../../../poly/Assert"; import { Plane } from "three"; import { Vector3 } from "three"; import { ParamType } from "../../../../poly/ParamType"; import { AttribType, ATTRIBUTE_TYPES } from "../../../../../core/geometry/Constant"; import { RaycastCPUVelocityController } from "./VelocityController"; import { isString } from "../../../../../core/Type"; import { CPUIntersectWith, CPU_INTERSECT_WITH_OPTIONS } from "./CpuConstants"; import { isBooleanTrue } from "../../../../../core/BooleanValue"; import { IntersectDataEventNode } from "../../IntersectData"; import { BaseRaycastController } from "./BaseRaycastController"; import { resolveIntersectGeometryAttribute } from "../../../../../core/geometry/intersect/CoreIntersect"; export class RaycastCPUController extends BaseRaycastController { constructor(_node) { super(); this._node = _node; this._cursorArray = [0, 0]; this._plane = new Plane(); this._plane_intersect_target = new Vector3(); this._intersections = []; this._hitPositionArray = [0, 0, 0]; this.velocityController = new RaycastCPUVelocityController(this._node); } updateMouse(eventContext) { const viewer = eventContext.viewer; if (!viewer) { return; } const camera = viewer.camera(); if (!camera) { return; } this._cursorHelper.setCursorForCPU(eventContext, this._cursor); if (isBooleanTrue(this._node.pv.tmouse)) { this._cursor.toArray(this._cursorArray); this._node.p.mouse.set(this._cursorArray); } viewer.raycastersController.raycaster0().setFromCamera(this._cursor, camera); } processEvent(context) { this._prepareRaycaster(context); const type = CPU_INTERSECT_WITH_OPTIONS[this._node.pv.intersectWith]; switch (type) { case CPUIntersectWith.GEOMETRY: { return this._intersectGeometry(context); } case CPUIntersectWith.PLANE: { return this._intersectPlane(context); } } TypeAssert.unreachable(type); } _intersectPlane(eventContext) { const viewer = eventContext.viewer; if (!viewer) { return; } this._plane.normal.copy(this._node.pv.planeDirection); this._plane.constant = this._node.pv.planeOffset; viewer.raycastersController.raycaster0().ray.intersectPlane(this._plane, this._plane_intersect_target); this._setPositionParam(this._plane_intersect_target); this._node.triggerHit(eventContext); } _intersectGeometry(eventContext) { const viewer = eventContext.viewer; if (!viewer) { return; } if (!this._resolvedTargets) { this.updateTarget(); } if (this._resolvedTargets) { this._intersections.length = 0; const intersections = viewer.raycastersController.raycaster0().intersectObjects( this._resolvedTargets, isBooleanTrue(this._node.pv.traverseChildren), this._intersections ); const intersection = intersections[0]; if (intersection) { this._node.scene().batchUpdates(() => { if (isBooleanTrue(this._node.pv.tposition)) { this._setPositionParam(intersection.point); } if (isBooleanTrue(this._node.pv.geoAttribute)) { this._resolveIntersectAttribute(intersection); } }); eventContext.value = { intersect: intersection }; this._node.triggerHit(eventContext); } else { this._node.triggerMiss(eventContext); } } } _resolveIntersectAttribute(intersection) { const attribType = ATTRIBUTE_TYPES[this._node.pv.geoAttributeType]; let attribValue = IntersectDataEventNode.resolveObjectAttribute( intersection, this._node.pv.geoAttributeName ); if (attribValue == null) { attribValue = resolveIntersectGeometryAttribute(intersection, this._node.pv.geoAttributeName, attribType); } if (attribValue != null) { switch (attribType) { case AttribType.NUMERIC: { this._node.p.geoAttributeValue1.set(attribValue); return; } case AttribType.STRING: { if (isString(attribValue)) { this._node.p.geoAttributeValues.set(attribValue); } return; } } TypeAssert.unreachable(attribType); } } _setPositionParam(hitPosition) { var _a; hitPosition.toArray(this._hitPositionArray); if (isBooleanTrue(this._node.pv.tpositionTarget)) { const targetParam = this._node.pv.positionTarget; if (this._foundPositionTargetParam == null || isBooleanTrue(this._foundPositionTargetParam.disposed())) { this._foundPositionTargetParam = targetParam.paramWithType(ParamType.VECTOR3); } (_a = this._foundPositionTargetParam) == null ? void 0 : _a.set(this._hitPositionArray); } else { this._node.p.position.set(this._hitPositionArray); } this.velocityController.process(hitPosition); } _prepareRaycaster(eventContext) { const viewer = eventContext.viewer; if (!viewer) { return; } const pointsParam = viewer.raycastersController.raycaster0().params.Points; if (pointsParam) { pointsParam.threshold = this._node.pv.pointsThreshold; } } updateTarget() { const targetType = TARGET_TYPES[this._node.pv.targetType]; switch (targetType) { case TargetType.NODE: { return this._updateTargetFromNode(); } case TargetType.SCENE_GRAPH: { return this._updateTargetFromSceneGraph(); } } TypeAssert.unreachable(targetType); } _updateTargetFromNode() { const node = this._node.p.targetNode.value.nodeWithContext(NodeContext.OBJ); if (node) { const found_obj = isBooleanTrue(this._node.pv.traverseChildren) ? node.object : node.childrenDisplayController.sopGroup(); if (found_obj) { this._resolvedTargets = [found_obj]; } else { this._resolvedTargets = void 0; } } else { this._node.states.error.set("node is not an object"); } } _updateTargetFromSceneGraph() { const objects = this._node.scene().objectsByMask(this._node.pv.objectMask); if (objects.length > 0) { this._resolvedTargets = objects; } else { this._resolvedTargets = void 0; } } static PARAM_CALLBACK_updateTarget(node) { node.cpuController.updateTarget(); } }