amaze
This commit is contained in:
@@ -0,0 +1,580 @@
|
||||
import * as THREE from 'three';
|
||||
import { GLTFLoader } from 'three/examples/jsm/Addons.js';
|
||||
import { DRACOLoader } from 'three/examples/jsm/Addons.js';
|
||||
import { OrbitControls } from 'three/examples/jsm/Addons.js';
|
||||
//import { Controller as OrbitControls } from './3rd-party/phy/3TH/Controller.js';
|
||||
import { ViewportGizmo } from "three-viewport-gizmo";
|
||||
import Stats from 'three/examples/jsm/libs/stats.module';
|
||||
//import { AnaglyphEffect } from './three/AnaglyphEffect';
|
||||
import { AnaglyphEffect } from 'three/addons/effects/AnaglyphEffect.js';
|
||||
import { StereoEffect } from 'three/addons/effects/StereoEffect.js';
|
||||
import { MapControls } from 'three/addons/controls/MapControls.js';
|
||||
import { FirstPersonControls } from 'three/addons/controls/FirstPersonControls.js';
|
||||
import { TransformControls } from 'three/addons/controls/TransformControls.js';
|
||||
import { ARButton } from 'three/addons/webxr/ARButton.js';
|
||||
import { XRButton } from 'three/addons/webxr/XRButton.js';
|
||||
import { XRControllerModelFactory } from 'three/addons/webxr/XRControllerModelFactory.js';
|
||||
import { Physics } from './Physics.js';
|
||||
import { Clickable } from './Clickable.js';
|
||||
|
||||
class GameEngine {
|
||||
async init(domNode, opts = {}) {
|
||||
this.w = domNode.clientWidth || 1200, this.h = domNode.clientHeight || 800;
|
||||
this.aspect = this.w / this.h
|
||||
this.opts = opts;
|
||||
const gameEngine = this;
|
||||
|
||||
this.perspectiveCamera = new THREE.PerspectiveCamera(45, this.aspect, 0.01, 250);
|
||||
this.raycaster = new THREE.Raycaster();
|
||||
this.perspectiveCamera.position.set(0, 0, 10);
|
||||
|
||||
this.camera = this.perspectiveCamera;
|
||||
|
||||
this.frustumSize = 50;
|
||||
this.orthographicCamera = new THREE.OrthographicCamera(
|
||||
this.frustumSize * this.aspect / - 2,
|
||||
this.frustumSize * this.aspect / 2,
|
||||
this.frustumSize / 2,
|
||||
this.frustumSize / - 2,
|
||||
0.01, 1000);
|
||||
this.orthographicCamera.position.set(0, 0, 100);
|
||||
const scene = new THREE.Scene();
|
||||
this.scene = scene;
|
||||
|
||||
this.initCameraPivot()
|
||||
|
||||
// let light = new THREE.AmbientLight( 0x404040, 300 ); // soft white light
|
||||
// scene.add( this.light );
|
||||
|
||||
var hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444 );
|
||||
hemiLight.position.set(0, 33, 0);
|
||||
scene.add( hemiLight );
|
||||
|
||||
const dirLight = new THREE.DirectionalLight(0xffffff, 4);
|
||||
dirLight.color.setHSL(0.1, 1, 0.95);
|
||||
dirLight.position.set(12, 33, -37);
|
||||
// dirLight.position.multiplyScalar( 0.20 );
|
||||
// hemiLight.position.multiplyScalar( 0.20 );
|
||||
scene.add(dirLight);
|
||||
|
||||
dirLight.castShadow = true;
|
||||
|
||||
dirLight.shadow.mapSize.width = 1024;
|
||||
dirLight.shadow.mapSize.height = 1024;
|
||||
|
||||
const d = 50;
|
||||
|
||||
dirLight.shadow.camera.left = - d;
|
||||
dirLight.shadow.camera.right = d;
|
||||
dirLight.shadow.camera.top = d;
|
||||
dirLight.shadow.camera.bottom = - d;
|
||||
|
||||
dirLight.shadow.camera.far = 1000;
|
||||
dirLight.shadow.bias = - 0.001;
|
||||
|
||||
const renderer = new THREE.WebGLRenderer({
|
||||
antialias: true,
|
||||
// alpha: true,
|
||||
preserveDrawingBuffer: true, //this is important for screenshots capturing
|
||||
powerPreference: "high-performance",
|
||||
});
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
renderer.toneMapping = THREE.CineonToneMapping;
|
||||
renderer.toneMappingExposure = 1.0;
|
||||
renderer.shadowMap.enabled = true;
|
||||
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
|
||||
// renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
||||
// renderer.toneMappingExposure = 1;
|
||||
// renderer.shadowMap.enabled = true;
|
||||
// renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
||||
renderer.setSize(this.w, this.h);
|
||||
renderer.setViewport(0, 0, this.w, this.h);
|
||||
renderer.autoClear = true;
|
||||
|
||||
this.anaglyph = new AnaglyphEffect(renderer);
|
||||
this.anaglyph.setSize(this.w, this.h);
|
||||
|
||||
this.stereo = new StereoEffect(renderer);
|
||||
this.stereo.setSize(this.w, this.h);
|
||||
|
||||
this.activeObjects = new THREE.Group();
|
||||
scene.add(this.activeObjects);
|
||||
|
||||
const controls = new OrbitControls(this.camera, renderer.domElement);
|
||||
if (opts.gizmo) {
|
||||
const gizmo = new ViewportGizmo(this.camera, renderer, {
|
||||
container: '.renderer-gizmo',
|
||||
//type:'cube'
|
||||
});
|
||||
gizmo.attachControls(controls);
|
||||
this.gizmo = gizmo;
|
||||
}
|
||||
|
||||
this.orbitControls = controls;
|
||||
//controls.enableZoom = true;
|
||||
//const controls = new MapControls( camera, renderer.domElement );
|
||||
this.transformControls = new TransformControls(this.camera, renderer.domElement);
|
||||
this.transformControls.addEventListener('dragging-changed', function (event) {
|
||||
controls.enabled = !event.value;
|
||||
});
|
||||
// controls.enableDamping = true;
|
||||
// controls.screenSpacePanning = true;
|
||||
|
||||
this.renderType = 'ST';
|
||||
|
||||
function animate(time) {
|
||||
let delta = clock.getDelta();
|
||||
gameEngine.hero?.update();
|
||||
gameEngine.mixers.forEach(m => m.update(delta));
|
||||
gameEngine.handleXrAction(gameEngine, delta)
|
||||
gameEngine.render(scene, gameEngine.camera);
|
||||
if (!renderer.xr.isPresenting) {
|
||||
gameEngine.gizmo?.render();
|
||||
}
|
||||
}
|
||||
renderer.setAnimationLoop(animate);
|
||||
|
||||
const mixer = new THREE.AnimationMixer(this.scene);
|
||||
const clock = new THREE.Clock();
|
||||
|
||||
this.clock = clock;
|
||||
this.renderer = renderer;
|
||||
|
||||
this.draco = new DRACOLoader().setDecoderPath('/3rdparty/draco/');
|
||||
this.loader = new GLTFLoader();
|
||||
this.loader.setDRACOLoader(this.draco);
|
||||
this.mixers = [mixer];
|
||||
|
||||
domNode.appendChild(renderer.domElement);
|
||||
|
||||
let texture = await this.loadTexture('/static/textures/bck.webp');
|
||||
// let bck = await this.loadTexture('/static/textures/bck.webp');
|
||||
// bck.premultiplyAlpha = true;
|
||||
texture.mapping = THREE.EquirectangularReflectionMapping;
|
||||
// scene.background = bck; //new THREE.Color(0.7,0.7,0.7);
|
||||
scene.environment = texture;
|
||||
scene.background = new THREE.Color(1, 1, 1);
|
||||
console.log('GameEngine started')
|
||||
renderer.domElement.addEventListener('wheel', (event) => {
|
||||
gameEngine.camera.zoom -= event.deltaY / 1000;
|
||||
gameEngine.camera.zoom = Math.max(gameEngine.camera.zoom, .4);
|
||||
controls.rotateSpeed = 1 / gameEngine.camera.zoom;
|
||||
gameEngine.camera.updateProjectionMatrix();
|
||||
})
|
||||
|
||||
await this.initPhysics();
|
||||
|
||||
this.stats = new Stats();
|
||||
document.body.appendChild(this.stats.dom);
|
||||
|
||||
if (opts.ar) {
|
||||
renderer.xr.enabled = true;
|
||||
document.body.appendChild(ARButton.createButton(renderer, {}));
|
||||
}
|
||||
if (opts.xr) {
|
||||
renderer.xr.enabled = true;
|
||||
document.body.appendChild(XRButton.createButton(renderer, opts.depthSense ? {
|
||||
'requiredFeatures': ['depth-sensing'],
|
||||
'depthSensing': {
|
||||
usagePreference: ["gpu-optimized"],
|
||||
dataFormatPreference: ["unsigned-short"],
|
||||
matchDepthView: false
|
||||
}
|
||||
} : {}));
|
||||
this.initXrControllers();
|
||||
}
|
||||
|
||||
this.clickable = new Clickable(20);
|
||||
}
|
||||
|
||||
initXrControllers() {
|
||||
let c1 = this.renderer.xr.getController(0);
|
||||
c1.addEventListener('select', this.onSelect.bind(this));
|
||||
c1.addEventListener('selectstart', this.onControllerEvent.bind(this));
|
||||
c1.addEventListener('selectend', this.onControllerEvent.bind(this));
|
||||
c1.addEventListener('move', this.onControllerEvent.bind(this));
|
||||
c1.userData.active = false;
|
||||
c1.addEventListener('connected', e => {
|
||||
c1.gamepad = e.data.gamepad;
|
||||
// this.session = this.renderer.xr.getSession();
|
||||
// this.session.addEventListener('selectstart', this.onControllerEvent.bind(this));
|
||||
})
|
||||
this.scene.add(c1);
|
||||
|
||||
let c2 = this.renderer.xr.getController(1);
|
||||
c2.addEventListener('select', this.onSelect.bind(this));
|
||||
c2.addEventListener('selectstart', this.onControllerEvent.bind(this));
|
||||
c2.addEventListener('selectend', this.onControllerEvent.bind(this));
|
||||
c2.addEventListener('move', this.onControllerEvent.bind(this));
|
||||
c2.userData.active = true;
|
||||
c2.addEventListener('connected', e => {
|
||||
c2.gamepad = e.data.gamepad;
|
||||
})
|
||||
this.scene.add(c2);
|
||||
|
||||
const controllerModelFactory = new XRControllerModelFactory();
|
||||
|
||||
let controllerGrip1 = this.renderer.xr.getControllerGrip(0);
|
||||
controllerGrip1.add(controllerModelFactory.createControllerModel(controllerGrip1));
|
||||
this.scene.add(controllerGrip1);
|
||||
|
||||
let controllerGrip2 = this.renderer.xr.getControllerGrip(1);
|
||||
controllerGrip2.add(controllerModelFactory.createControllerModel(controllerGrip2));
|
||||
this.scene.add(controllerGrip2);
|
||||
|
||||
const geometry = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 0, - 1)]);
|
||||
|
||||
let line = new THREE.Line(geometry);
|
||||
line.name = 'line';
|
||||
line.scale.z = 5;
|
||||
|
||||
this.controllerLine = line;
|
||||
|
||||
this.xrController1 = c1
|
||||
this.xrController2 = c2
|
||||
}
|
||||
|
||||
initCameraPivot() {
|
||||
const pivot = new THREE.Object3D()
|
||||
pivot.position.set(0, 0, 0)
|
||||
|
||||
const yaw = new THREE.Object3D()
|
||||
const pitch = new THREE.Object3D()
|
||||
|
||||
this.scene.add(pivot)
|
||||
pivot.add(yaw)
|
||||
yaw.add(pitch)
|
||||
this.scene.add(this.perspectiveCamera);
|
||||
this.scene.add(this.orthographicCamera);
|
||||
this.cameraPivot = pivot;
|
||||
this.cameraYaw = yaw;
|
||||
}
|
||||
|
||||
async initPhysics() {
|
||||
//const world = new CANNON.World()
|
||||
//world.gravity.set(0, -9.82, 0)
|
||||
// let gravity = { x: 0.0, y: -9.81, z: 0.0 };
|
||||
// let world = new RAPIER.World(gravity);
|
||||
|
||||
// // Create Ground.
|
||||
// let bodyDesc = RAPIER.RigidBodyDesc.fixed();
|
||||
// let body = world.createRigidBody(bodyDesc);
|
||||
// let colliderDesc = RAPIER.ColliderDesc.cuboid(100.0, 0.1, 100.0);
|
||||
// world.createCollider(colliderDesc, body.handle);
|
||||
|
||||
// const groundMaterial = new CANNON.Material('groundMaterial')
|
||||
// const slipperyMaterial = new CANNON.Material('slipperyMaterial')
|
||||
// const slippery_ground_cm = new CANNON.ContactMaterial(
|
||||
// groundMaterial,
|
||||
// slipperyMaterial,
|
||||
// {
|
||||
// friction: 0,
|
||||
// restitution: 0.3,
|
||||
// contactEquationStiffness: 1e10,
|
||||
// contactEquationRelaxation: 30,
|
||||
// }
|
||||
// )
|
||||
// world.addContactMaterial(slippery_ground_cm)
|
||||
// const planeShape = new CANNON.Plane()
|
||||
// const planeBody = new CANNON.Body({ mass: 0, material: groundMaterial })
|
||||
// planeBody.addShape(planeShape)
|
||||
// planeBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2)
|
||||
// world.addBody(planeBody)
|
||||
|
||||
this.phy = new Physics();
|
||||
await this.phy.init();
|
||||
}
|
||||
|
||||
handleXrAction(gameEngine, delta) {
|
||||
//console.log(event.type);
|
||||
if (gameEngine.xrController1?.gamepad) {
|
||||
let gp = gameEngine.xrController1.gamepad;
|
||||
if (gp.axes[3] != 0) {
|
||||
gameEngine.activeObjects.position.z += gp.axes[3] * delta;
|
||||
}
|
||||
if (gp.axes[2] != 0) {
|
||||
gameEngine.activeObjects.position.x += gp.axes[2] * delta;
|
||||
}
|
||||
}
|
||||
if (gameEngine.xrController2?.gamepad) {
|
||||
let gp = gameEngine.xrController2.gamepad;
|
||||
let gp1 = gameEngine.xrController1.gamepad;
|
||||
// if (gp.axes[3] != 0){
|
||||
// let sc = gameEngine.scene.scale.x + gp.axes[3] * delta * 0.5;
|
||||
// gameEngine.scene.scale.set(sc, sc, sc);
|
||||
// }
|
||||
if (gp.axes[2] != 0) {
|
||||
if (gp1.buttons[4]?.pressed) {
|
||||
gameEngine.activeObjects.position.y += gp.axes[2] * delta;
|
||||
} else if (gp1.buttons[5]?.pressed) {
|
||||
let sc = gameEngine.activeObjects.scale.x * (gp.axes[2] * delta * 0.5 + 1);
|
||||
gameEngine.activeObjects.scale.set(sc, sc, sc);
|
||||
} else {
|
||||
gameEngine.activeObjects.rotation.y += gp.axes[2] * delta * 0.5;
|
||||
}
|
||||
}
|
||||
if (gp.buttons[4]?.pressed) {
|
||||
let x = performance.now() % 1000;
|
||||
if (x < 333) {
|
||||
gameEngine.transformControls.setMode('translate');
|
||||
}else if (x < 666) {
|
||||
gameEngine.transformControls.setMode('scale');
|
||||
}else{
|
||||
gameEngine.transformControls.setMode('rotate');
|
||||
}
|
||||
// let nextMode = {
|
||||
// 'translate': 'scale',
|
||||
// 'scale': 'rotate',
|
||||
// 'rotate': 'translate'
|
||||
// }
|
||||
// if(gameEngine.opts.designMode){;
|
||||
// gameEngine.transformControls.setMode(nextMode[gameEngine.transformControls.getMode()]);
|
||||
// }
|
||||
}
|
||||
// if (gp.buttons[5]?.pressed) {
|
||||
// // gameEngine.setCameraOrthographic();
|
||||
// // gameEngine.renderer.xr.updateCamera(gameEngine.orthographicCamera);
|
||||
// let session = gameEngine.renderer.xr.getFrame().session;
|
||||
// console.log(session);
|
||||
// session.resumeDepthSensing();
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
onControllerEvent(event) {
|
||||
//this.handleXrAction(event, this);
|
||||
//event.type !== 'move' && console.log(event)
|
||||
const controller = event.target;
|
||||
//console.log(event)
|
||||
|
||||
if (this.opts.designMode){
|
||||
if (!controller.userData) return
|
||||
if (controller.userData.active === false) return;
|
||||
this.transformControls.getRaycaster().setFromXRController(controller);
|
||||
switch (event.type) {
|
||||
case 'selectstart':
|
||||
this.transformControls.pointerDown(null);
|
||||
break;
|
||||
case 'selectend':
|
||||
this.transformControls.pointerUp(null);
|
||||
break;
|
||||
case 'move':
|
||||
this.transformControls.pointerHover(null);
|
||||
this.transformControls.pointerMove(null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onSelect(event) {
|
||||
const controller = event.target;
|
||||
|
||||
if (this.opts.designMode){
|
||||
this.xrController1.userData.active = false;
|
||||
this.xrController2.userData.active = false;
|
||||
|
||||
if (controller === this.xrController1) {
|
||||
this.xrController1.userData.active = true;
|
||||
this.xrController1.add(this.controllerLine);
|
||||
}
|
||||
|
||||
if (controller === this.xrController2) {
|
||||
this.xrController2.userData.active = true;
|
||||
this.xrController2.add(this.controllerLine);
|
||||
}
|
||||
|
||||
this.raycaster.setFromXRController(controller);
|
||||
const intersects = this.raycaster.intersectObjects(this.activeObjects.children, true);
|
||||
|
||||
intersects.forEach(o => {
|
||||
while (o.object && !this.activeObjects.children.includes(o.object)) {
|
||||
o.object = o.object.parent;
|
||||
}
|
||||
})
|
||||
|
||||
if (intersects.length > 0) {
|
||||
setTimeout(() => {
|
||||
this.transformControls.attach(intersects[0].object);
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ = THREE;
|
||||
|
||||
async load(url, progress) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loader.load(url, o => {
|
||||
o.scene.traverse(object => {
|
||||
if (object.name == 'environment' || object.material){
|
||||
console.log('env recomputing')
|
||||
object.material.shading = THREE.SmoothShading;
|
||||
object.geometry.computeVertexNormals(true);
|
||||
//object.material.metalness = 0;
|
||||
//if (object.material.map) object.material.map.colorSpace = THREE.SRGBColorSpace;
|
||||
}
|
||||
if ( object instanceof THREE.Mesh ) {
|
||||
//object.material.envMap = this.scene.environment;
|
||||
if (object.material.map) object.material.map.colorSpace = THREE.SRGBColorSpace;
|
||||
//object.material.metalness = 0;
|
||||
}
|
||||
object.frustumCulled = false;
|
||||
object.castShadow = true;
|
||||
object.receiveShadow = true;
|
||||
});
|
||||
resolve(o);
|
||||
}, progress, reject)
|
||||
})
|
||||
}
|
||||
|
||||
async loadTexture(url, progress) {
|
||||
return new Promise((resolve, reject) => {
|
||||
new THREE.TextureLoader().load(url, texture => {
|
||||
//texture.encoding = THREE.sRGBEncoding;
|
||||
texture.colorSpace = THREE.SRGBColorSpace;
|
||||
resolve(texture)
|
||||
}, progress, reject)
|
||||
})
|
||||
}
|
||||
|
||||
async loadPanorama(url) {
|
||||
let t = await this.loadTexture(url);
|
||||
t.mapping = THREE.EquirectangularReflectionMapping;
|
||||
this.scene.background = t;
|
||||
this.scene.environment = t;
|
||||
}
|
||||
|
||||
async captureScreenshot(type = 'image/webp', quality = 80) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.renderer.domElement.toBlob(resolve, type, quality)
|
||||
})
|
||||
}
|
||||
|
||||
playAnimation(object, clip, play = true) {
|
||||
let action = this.mixers[0].clipAction(clip, object);
|
||||
if (play) action.play();
|
||||
else action.stop();
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.renderer?.setAnimationLoop(null);
|
||||
}
|
||||
|
||||
getMouseVector(mouseEvent, domElement) {
|
||||
//console.log(mouseEvent, domElement)
|
||||
const mouse = new THREE.Vector2();
|
||||
if (this.renderType == 'VR') {
|
||||
let x;
|
||||
if (mouseEvent.offsetX > window.innerWidth / 2) {
|
||||
x = (mouseEvent.offsetX - window.innerWidth / 2) * 2
|
||||
} else {
|
||||
x = mouseEvent.offsetX * 2;
|
||||
}
|
||||
mouse.x = (x / window.innerWidth) * 2 - 1;
|
||||
mouse.y = - (mouseEvent.offsetY / window.innerHeight) * 2 + 1;
|
||||
} else {
|
||||
mouse.x = (mouseEvent.offsetX / domElement.clientWidth) * 2 - 1;
|
||||
mouse.y = - (mouseEvent.offsetY / domElement.clientHeight) * 2 + 1;
|
||||
}
|
||||
return mouse;
|
||||
}
|
||||
|
||||
intersect(mouseEvent, domElement, objects, recursive = false, returnInputObjects = true) {
|
||||
let mouse = this.getMouseVector(mouseEvent, domElement);
|
||||
this.raycaster.setFromCamera(mouse, this.camera);
|
||||
let intersects = this.raycaster.intersectObjects(objects.filter(o => o.visible), recursive);
|
||||
if (returnInputObjects && recursive) {
|
||||
intersects.forEach(o => {
|
||||
while (o.object && !objects.includes(o.object)) {
|
||||
o.object = o.object.parent;
|
||||
}
|
||||
})
|
||||
}
|
||||
//console.log('intersects', intersects);
|
||||
return intersects;
|
||||
}
|
||||
|
||||
onClick(mouseEvent, domElement){
|
||||
let mouse = this.getMouseVector(mouseEvent, domElement);
|
||||
this.raycaster.setFromCamera(mouse, this.camera);
|
||||
this.clickable.update(mouse, this.camera, mouseEvent);
|
||||
}
|
||||
|
||||
autoScale(object, mk = 1) {
|
||||
let bb = new THREE.Box3().setFromObject(object);
|
||||
let k = Math.max(bb.max.x - bb.min.x, bb.max.y - bb.min.y, bb.max.z - bb.min.z);
|
||||
object.scale.multiplyScalar(mk / k);
|
||||
}
|
||||
|
||||
setCamera(camera) {
|
||||
//camera.updateProjectionMatrix();
|
||||
this.camera = camera;
|
||||
//this.transformControls.camera = camera;
|
||||
this.orbitControls.object = camera;
|
||||
}
|
||||
|
||||
setCameraOrthographic() {
|
||||
let o = this.orthographicCamera;
|
||||
// o.position.copy(o.position);
|
||||
// const distance = o.position.distanceTo(this.orbitControls.target);
|
||||
// const halfWidth = this.frustumWidthAtDistance(o, distance) / 2;
|
||||
// const halfHeight = this.frustumHeightAtDistance(o, distance) / 2;
|
||||
// o.top = halfHeight;
|
||||
// o.bottom = -halfHeight;
|
||||
// o.left = -halfWidth;
|
||||
// o.right = halfWidth;
|
||||
// o.zoom = 1;
|
||||
// o.lookAt(this.orbitControls.target);
|
||||
// o.updateProjectionMatrix();
|
||||
this.camera = o;
|
||||
this.transformControls.camera = o;
|
||||
this.orbitControls.object = o;
|
||||
if (this.gizmo) {
|
||||
this.gizmo.camera = o;
|
||||
}
|
||||
}
|
||||
|
||||
setCameraPerspective() {
|
||||
let o = this.perspectiveCamera;
|
||||
// const oldY = o.position.y;
|
||||
// o.position.copy(o.position);
|
||||
// o.position.y = oldY / o.zoom;
|
||||
// o.updateProjectionMatrix();
|
||||
this.camera = o;
|
||||
this.transformControls.camera = o;
|
||||
this.orbitControls.object = o;
|
||||
if (this.gizmo) {
|
||||
this.gizmo.camera = o;
|
||||
}
|
||||
}
|
||||
|
||||
resize(w, h) {
|
||||
this.w = w;
|
||||
this.h = h;
|
||||
this.aspect = this.w / this.h
|
||||
this.perspectiveCamera.aspect = this.aspect;
|
||||
this.perspectiveCamera.updateProjectionMatrix();
|
||||
this.orthographicCamera.left = - this.frustumSize * this.aspect / 2;
|
||||
this.orthographicCamera.right = this.frustumSize * this.aspect / 2;
|
||||
this.orthographicCamera.top = this.frustumSize / 2;
|
||||
this.orthographicCamera.bottom = - this.frustumSize / 2;
|
||||
this.renderer.setSize(w, h);
|
||||
this.renderer.setViewport(0, 0, this.w, this.h);
|
||||
this.anaglyph.setSize(w, h);
|
||||
this.stereo.setSize(w, h);
|
||||
this.gizmo?.update();
|
||||
}
|
||||
|
||||
render(scene, camera) {
|
||||
if (this.renderType == 'VR') {
|
||||
this.stereo?.render(scene, camera);
|
||||
} else if (this.renderType == 'AG') {
|
||||
this.anaglyph?.render(scene, camera);
|
||||
} else {
|
||||
this.renderer.render(scene, camera);
|
||||
}
|
||||
this.stats?.update()
|
||||
}
|
||||
}
|
||||
|
||||
export { GameEngine }
|
||||
Reference in New Issue
Block a user