src/appComponent/sceneContainer/scene/renderController.js
import * as THREE from 'three';
import * as threeOrbitControlsLib from 'three-orbit-controls'
const threeOrbitControls = threeOrbitControlsLib.default(THREE);
import MakeSpline from "./splineMaker";
/**
* Render Controller
*/
class RenderControllerClass {
/**
* initialize using three js
* @param {object} cameraControlAreaElement its the element which camera could control in it
* @param {number} width canvas width
* @param {number} height canvas height
*/
setup(cameraControlAreaElement, width, height) {
this.renderer = new THREE.WebGLRenderer();
this.renderer.setSize(width, height);
this.scene = new THREE.Scene();
this.addCamera(cameraControlAreaElement);
this.addLights();
this.buildAxes(1000);
this.repeatRendering();
return this.renderer.domElement;
}
/**
* Make lights
*/
addLights() {
let light = new THREE.PointLight(0xFF0000, 1, 100);
light.position.set(10, 0, 10);
this.scene.add(light);
light = new THREE.PointLight(0xFF0000, 1, 50);
light.position.set(-20, 15, 10);
this.scene.add(light);
this.renderer.setClearColor(0x222222, 1);
}
/**
* add 3 Axis
* @param length determine 3 axis length
*/
buildAxes(length) {
// const axes = new THREE.AxisHelper( length );
// this.scene.add( axes );
const axes = new THREE.Object3D();
this.axes = axes;
const color = 0x2c2c2c;
axes.add(this.buildAxis(new THREE.Vector3(-length, 0, 0), new THREE.Vector3(length, 0, 0), color, true)); // +X
axes.add(this.buildAxis(new THREE.Vector3(0, -length, 0), new THREE.Vector3(0, length, 0), color, true)); // +Y
axes.add(this.buildAxis(new THREE.Vector3(0, 0, -length), new THREE.Vector3(0, 0, length), color, true)); // +Z
this.scene.add(axes);
}
buildAxis(src, dst, colorHex, dashed) {
var geom = new THREE.Geometry(),
mat;
if (dashed) {
mat = new THREE.LineDashedMaterial({linewidth: 1, color: colorHex, dashSize: 1, gapSize: 1});
} else {
mat = new THREE.LineBasicMaterial({linewidth: 1, color: colorHex});
}
geom.vertices.push(src.clone());
geom.vertices.push(dst.clone());
geom.computeLineDistances(); // This one is SUPER important, otherwise dashed lines will appear as simple plain lines
return new THREE.Line(geom, mat, THREE.LinePieces);
}
/**
* add camera
* @param {object} cameraControlAreaElement its the element which camera could control in it
*/
addCamera(cameraControlAreaElement) {
this.camera = new THREE.PerspectiveCamera(
35, // FOV
800 / 640, // Aspect
0.1, // Near
10000 // Far
);
this.camera.position.set(0, 0, 0);
this.camera.position.z = 100;
this.camera.lookAt(this.scene.position);
const controls = new threeOrbitControls(this.camera, cameraControlAreaElement);
const originUpdate = controls.update;
const thisComponent = this;
controls.update = function () {//when camera state changes
originUpdate();
thisComponent.onCameraChange();
};
}
/**
* it just renders what is in the scene and won't create anything
*/
rerender() {
this.renderer.render(this.scene, this.camera);
}
/**
* it will call back on camera changes
*/
onCameraChange() {
this.cameraHasChanged = true;
return true;
}
/**
* it will call back on control changes
*/
onStateChange(newState) {
this.curState = newState;
this.stateHasChanged=true;
}
/**
* rebuild spline
*/
rebuildSpline(data) {
if (data) {
this.axes.visible = data.options.showAxes;
if (this.spline) this.scene.remove(this.spline);
this.spline = MakeSpline(data);
this.scene.add(this.spline);
}
}
/**
* control the rendering
*/
repeatRendering() {
if (this.curState) {
if (this.stateHasChanged) {
this.rebuildSpline(this.curState);
this.rerender();
this.stateHasChanged=false;
}
if (this.cameraHasChanged) {
this.rerender();
this.cameraHasChanged = false;
}
}
const thisObj = this;
requestAnimationFrame(function () {
thisObj.repeatRendering();
});
}
}
export const RenderController = new RenderControllerClass();