polygonjs-engine
Version:
node-based webgl 3D engine https://polygonjs.com
106 lines (94 loc) • 3.31 kB
text/typescript
/**
* Creates or update uv attribute.
*
*
*/
import {Camera} from 'three/src/cameras/Camera';
import {Object3D} from 'three/src/core/Object3D';
import {Matrix4} from 'three/src/math/Matrix4';
import {Vector3} from 'three/src/math/Vector3';
import {TypedSopNode} from './_Base';
import {CoreGroup} from '../../../core/geometry/Group';
import {CameraController} from '../../../core/CameraController';
import {BaseCameraObjNodeType} from '../obj/_BaseCamera';
// const MODE = [];
const UV_NAME = 'uv';
import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig';
import {InputCloneMode} from '../../poly/InputCloneMode';
import {NodeContext} from '../../poly/NodeContext';
import {BaseObjNodeType} from '../obj/_Base';
class UvProjectSopParamsConfig extends NodeParamsConfig {
/** @param camera node to use as projection */
camera = ParamConfig.OPERATOR_PATH('/perspective_camera1', {
nodeSelection: {
context: NodeContext.OBJ,
},
});
// force_aspect = ParamConfig.BOOLEAN(0)
// aspect = ParamConfig.FLOAT(1, {
// range: [0, 2],
// visibleIf: {force_aspect: 1},
// })
}
const ParamsConfig = new UvProjectSopParamsConfig();
export class UvProjectSopNode extends TypedSopNode<UvProjectSopParamsConfig> {
params_config = ParamsConfig;
static type() {
return 'uvProject';
}
private _camera_controller: CameraController = new CameraController(this._update_uvs_from_camera.bind(this));
// private _param_camera: string
private _processed_core_group: CoreGroup | undefined;
// private _camera_node: BaseCameraObjNodeType | undefined;
private _camera_object: Camera | undefined;
initializeNode() {
this.io.inputs.setCount(1);
this.io.inputs.initInputsClonedState(InputCloneMode.FROM_NODE);
}
cook(core_groups: CoreGroup[]) {
this._processed_core_group = core_groups[0];
const camera_node = this.p.camera.found_node();
if (camera_node != null) {
this._camera_object = (camera_node as BaseCameraObjNodeType).object;
this._camera_controller.set_target(this._camera_object);
// this._add_camera_event()
} else {
this._camera_object = undefined;
//this._remove_camera_event()
this._camera_controller.remove_target();
}
this.setCoreGroup(this._processed_core_group);
}
_update_uvs_from_camera(look_at_target: Object3D) {
// let old_aspect;
// if (this.pv.force_aspect) {
// old_aspect = this._camera_object.aspect;
// this._camera_node.setup_for_aspect_ratio(this.pv.aspect);
// }
const parent = this.parent();
if (this._processed_core_group && parent) {
const points = this._processed_core_group.points();
const obj_world_matrix = (parent as BaseObjNodeType).object.matrixWorld;
points.forEach((point) => {
const position = point.position();
const uvw = this._vector_in_camera_space(position, obj_world_matrix);
if (uvw) {
const uv = {
x: 1 - (uvw[0] * 0.5 + 0.5),
y: uvw[1] * 0.5 + 0.5,
};
point.setAttribValue(UV_NAME, uv);
}
});
// if (this.pv.force_aspect) {
// this._camera_node.setup_for_aspect_ratio(old_aspect);
// }
}
}
private _vector_in_camera_space(vector: Vector3, obj_world_matrix: Matrix4) {
if (this._camera_object) {
vector.applyMatrix4(obj_world_matrix);
return vector.project(this._camera_object).toArray();
}
}
}