polygonjs-engine
Version:
node-based webgl 3D engine https://polygonjs.com
98 lines (81 loc) • 3.16 kB
text/typescript
/**
* Projects points from the left input geometry onto the faces of the right input geometry.
*
*/
import {Vector3} from 'three/src/math/Vector3';
import {Raycaster, Intersection} from 'three/src/core/Raycaster';
import {Object3D} from 'three/src/core/Object3D';
import {MeshBasicMaterial} from 'three/src/materials/MeshBasicMaterial';
import {Mesh} from 'three/src/objects/Mesh';
import {DoubleSide} from 'three/src/constants';
import {TypedSopNode} from './_Base';
import {CoreGroup} from '../../../core/geometry/Group';
import {InputCloneMode} from '../../poly/InputCloneMode';
const MAT_DOUBLE_SIDED = new MeshBasicMaterial({
side: DoubleSide,
});
import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig';
class RaySopParamsConfig extends NodeParamsConfig {
/** @param toggle on to use the normals as the ray direction */
useNormals = ParamConfig.BOOLEAN(1);
/** @param if the normals are not used as the ray direction, this define the direction used */
direction = ParamConfig.VECTOR3([0, -1, 0], {
visibleIf: {useNormals: 0},
});
/** @param copies the normals from the right geometry to the left one */
transferFaceNormals = ParamConfig.BOOLEAN(1);
}
const ParamsConfig = new RaySopParamsConfig();
export class RaySopNode extends TypedSopNode<RaySopParamsConfig> {
params_config = ParamsConfig;
static type() {
return 'ray';
}
// _material_by_object_uuid: MaterialByString
private _bound_assign_mat = this._assign_double_sided_material_to_object.bind(this); //(Object3D)=>void;
private _raycaster = new Raycaster();
static double_sided_material() {
return MAT_DOUBLE_SIDED;
}
static displayedInputNames(): string[] {
return ['geometry to move', 'geometry to ray onto'];
}
initializeNode() {
this.io.inputs.setCount(2);
this.io.inputs.initInputsClonedState([
InputCloneMode.FROM_NODE,
InputCloneMode.ALWAYS, // to assign double sided mat
]);
}
create_params() {}
cook(input_contents: CoreGroup[]) {
const core_group = input_contents[0];
const core_group_collision = input_contents[1];
this.ray(core_group, core_group_collision);
}
ray(core_group: CoreGroup, core_group_collision: CoreGroup) {
// this._material_by_object_uuid = {}
this._assign_double_sided_material_to_core_group(core_group_collision);
let direction: Vector3, first_intersect: Intersection;
for (let point of core_group.points()) {
direction = this.pv.useNormals ? point.normal() : this.pv.direction;
this._raycaster.set(point.position(), direction);
first_intersect = this._raycaster.intersectObjects(core_group_collision.objects(), true)[0];
if (first_intersect) {
point.setPosition(first_intersect.point);
if (this.pv.transferFaceNormals && first_intersect.face) {
point.setNormal(first_intersect.face.normal);
}
}
}
this.setCoreGroup(core_group);
}
_assign_double_sided_material_to_core_group(core_group: CoreGroup) {
for (let object of core_group.objects()) {
object.traverse(this._bound_assign_mat);
}
}
_assign_double_sided_material_to_object(object: Object3D) {
(object as Mesh).material = RaySopNode.double_sided_material();
}
}