refactoring meshUtils, added sceneScale, #74
This commit is contained in:
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { GameEngine } from '@/lib/GameEngine.js';
|
import { GameEngine } from '@/lib/GameEngine.js';
|
||||||
import { autoScale } from '@/lib/MeshUtils';
|
|
||||||
let engine = null;
|
let engine = null;
|
||||||
|
|
||||||
export default{
|
export default{
|
||||||
@@ -81,7 +80,7 @@ export default{
|
|||||||
this.animations = gltf.animations.map(a => ({
|
this.animations = gltf.animations.map(a => ({
|
||||||
name: a.name, id: a.uuid
|
name: a.name, id: a.uuid
|
||||||
}));
|
}));
|
||||||
autoScale(gltf.scene);
|
engine.meshUtils.autoScale(gltf.scene);
|
||||||
let bb = new engine.$.Box3().setFromObject(gltf.scene);
|
let bb = new engine.$.Box3().setFromObject(gltf.scene);
|
||||||
engine.camera.position.set(bb.max.x, bb.max.y, bb.max.z*3);
|
engine.camera.position.set(bb.max.x, bb.max.y, bb.max.z*3);
|
||||||
engine.orbitControls.target.set((bb.max.x + bb.min.x) / 2, (bb.max.y + bb.min.y) / 2, (bb.max.z + bb.min.z) / 2)
|
engine.orbitControls.target.set((bb.max.x + bb.min.x) / 2, (bb.max.y + bb.min.y) / 2, (bb.max.z + bb.min.z) / 2)
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { bottomOrigin } from "@/lib/MeshUtils";
|
|
||||||
class CharacterObject{
|
class CharacterObject{
|
||||||
constructor(engine, data){
|
constructor(engine, data){
|
||||||
return new Promise(async(resolve, reject)=>{
|
return new Promise(async(resolve, reject)=>{
|
||||||
this.source = await engine.load(data.$go.asset.name);
|
this.source = await engine.load(data.$go.asset.name);
|
||||||
this.object = bottomOrigin(this.source.scene);
|
this.object = engine.meshUtils.bottomOrigin(this.source.scene);
|
||||||
resolve(this);
|
resolve(this);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Color, Group, DoubleSide, RepeatWrapping, MeshStandardMaterial, VideoTexture } from "three"
|
import { Color, Group, DoubleSide, RepeatWrapping, MeshStandardMaterial, VideoTexture } from "three"
|
||||||
import { EventManager } from '@/lib/EventManager';
|
import { EventManager } from '@/lib/EventManager';
|
||||||
import { centerOrigin, clearMaterial, clearObject } from "@/lib/MeshUtils";
|
|
||||||
import Utils from "#/app/Utils";
|
import Utils from "#/app/Utils";
|
||||||
|
|
||||||
class ClassicPuzzle extends EventManager {
|
class ClassicPuzzle extends EventManager {
|
||||||
@@ -100,11 +99,11 @@ class ClassicPuzzle extends EventManager {
|
|||||||
done0.position.set(0,0,0);
|
done0.position.set(0,0,0);
|
||||||
engine.draggable.remove(done0)
|
engine.draggable.remove(done0)
|
||||||
container.add(dragZone);
|
container.add(dragZone);
|
||||||
this.object = centerOrigin(container);
|
this.object = engine.meshUtils.centerOrigin(container);
|
||||||
this.dispose = () => {
|
this.dispose = () => {
|
||||||
//console.log('disposing!!!!!!!')
|
//console.log('disposing!!!!!!!')
|
||||||
clearMaterial(defaultMaterial);
|
engine.meshUtils.clearMaterial(defaultMaterial);
|
||||||
clearObject(gltf.scene);
|
engine.meshUtils.clearObject(gltf.scene);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
resolve(this);
|
resolve(this);
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getBoundingBox, getBoundingBoxCenterPoint, getBoundingBoxMaxLength, centerOrigin } from "@/lib/MeshUtils";
|
|
||||||
import { EventManager } from '@/lib/EventManager';
|
import { EventManager } from '@/lib/EventManager';
|
||||||
|
|
||||||
class GenericObject extends EventManager{
|
class GenericObject extends EventManager{
|
||||||
@@ -7,7 +6,7 @@ class GenericObject extends EventManager{
|
|||||||
super();
|
super();
|
||||||
return new Promise(async(resolve, reject)=>{
|
return new Promise(async(resolve, reject)=>{
|
||||||
this.source = await engine.load(data.$go.asset.name);
|
this.source = await engine.load(data.$go.asset.name);
|
||||||
this.object = centerOrigin(this.source.scene)
|
this.object = engine.meshUtils.bottomOrigin(this.source.scene)
|
||||||
|
|
||||||
if (!data.exclude){
|
if (!data.exclude){
|
||||||
engine.clickable.add(this.object, async e=>{
|
engine.clickable.add(this.object, async e=>{
|
||||||
@@ -17,9 +16,9 @@ class GenericObject extends EventManager{
|
|||||||
if (this.object._hud ){
|
if (this.object._hud ){
|
||||||
engine.dashboard.detach(this.object);
|
engine.dashboard.detach(this.object);
|
||||||
}else{
|
}else{
|
||||||
let bb = getBoundingBox(this.object);
|
let bb = engine.meshUtils.getBoundingBox(this.object);
|
||||||
let scale = 0.5 * engine.dashboard.height/getBoundingBoxMaxLength(bb);
|
let scale = 0.5 * engine.dashboard.height/engine.meshUtils.getBoundingBoxMaxLength(bb);
|
||||||
let position = getBoundingBoxCenterPoint(bb, this.object.position).multiplyScalar(scale).negate()
|
let position = engine.meshUtils.getBoundingBoxCenterPoint(bb, this.object.position).multiplyScalar(scale).negate()
|
||||||
|
|
||||||
let placement = {
|
let placement = {
|
||||||
quaternion: { x:0, y:0, z:0, w:0 },
|
quaternion: { x:0, y:0, z:0, w:0 },
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Vector3, AnimationMixer } from "three";
|
import { AnimationMixer } from "three";
|
||||||
import { assignMaterial } from "@/lib/MeshUtils";
|
|
||||||
|
|
||||||
class GltfObject {
|
class GltfObject {
|
||||||
constructor(engine, obj) {
|
constructor(engine, obj) {
|
||||||
@@ -13,7 +12,7 @@ class GltfObject {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
assignMaterial(gltfObj, obj);
|
engine.meshUtils.assignMaterial(gltfObj, obj);
|
||||||
if (gltf.animations && gltf.animations.length) {
|
if (gltf.animations && gltf.animations.length) {
|
||||||
let mixer = new AnimationMixer(gltfObj);
|
let mixer = new AnimationMixer(gltfObj);
|
||||||
engine.mixers.push(mixer);
|
engine.mixers.push(mixer);
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import { SingleQuestion } from "./SingleQuestion";
|
|||||||
import { MazeQuizGame } from "./MazeQuizGame/MazeQuizGame";
|
import { MazeQuizGame } from "./MazeQuizGame/MazeQuizGame";
|
||||||
import { Particles } from "./Particles";
|
import { Particles } from "./Particles";
|
||||||
import { SceneSwitcher } from "./SceneSwitcher";
|
import { SceneSwitcher } from "./SceneSwitcher";
|
||||||
import { assignParams, wrapInGroup, getBoundingBoxMaxLength } from "@/lib/MeshUtils";
|
|
||||||
import { GameEngine } from "@/lib/GameEngine";
|
import { GameEngine } from "@/lib/GameEngine";
|
||||||
|
|
||||||
const InteractiveObjectsImports = {
|
const InteractiveObjectsImports = {
|
||||||
@@ -79,11 +78,11 @@ class InteractiveObject extends EventManager{
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (obj.shouldBeLocked){
|
if (obj.shouldBeLocked){
|
||||||
this.object = wrapInGroup(this.object)
|
this.object = engine.meshUtils.wrapInGroup(this.object)
|
||||||
this.activator = new (obj.activationType == 'unlock' ? LockActivator : VisibilityActivator)(engine, this.object);
|
this.activator = new (obj.activationType == 'unlock' ? LockActivator : VisibilityActivator)(engine, this.object);
|
||||||
this.activator.deactivate();
|
this.activator.deactivate();
|
||||||
}
|
}
|
||||||
assignParams(this.object, obj);
|
engine.meshUtils.assignParams(this.object, obj);
|
||||||
if (obj.motion){
|
if (obj.motion){
|
||||||
engine.motionQueue.add({
|
engine.motionQueue.add({
|
||||||
o: this.object, ...obj.motion
|
o: this.object, ...obj.motion
|
||||||
@@ -124,7 +123,7 @@ class LockActivator{
|
|||||||
transparent: true, opacity:1, color: 0xaaaaaa
|
transparent: true, opacity:1, color: 0xaaaaaa
|
||||||
})
|
})
|
||||||
constructor(engine, group){
|
constructor(engine, group){
|
||||||
const bckGeometry = new SphereGeometry(getBoundingBoxMaxLength(group.userData.bbox)/2,8,8)
|
const bckGeometry = new SphereGeometry(engine.meshUtils.getBoundingBoxMaxLength(group.userData.bbox)/2,8,8)
|
||||||
const bckMesh = new Mesh(bckGeometry, LockActivator.materialLocked);
|
const bckMesh = new Mesh(bckGeometry, LockActivator.materialLocked);
|
||||||
bckMesh.visible = false;
|
bckMesh.visible = false;
|
||||||
group.add(bckMesh)
|
group.add(bckMesh)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Group, Vector3, Matrix4, Quaternion, RepeatWrapping, Vector2} from 'three';
|
import { Group, Vector3, Matrix4, Quaternion, RepeatWrapping, Vector2} from 'three';
|
||||||
import { InteractiveObject } from '../InteractiveObject';
|
import { InteractiveObject } from '../InteractiveObject';
|
||||||
import { getBoundingBox, getBoundingBoxSize } from '@/lib/MeshUtils';
|
|
||||||
|
|
||||||
class MazeObject {
|
class MazeObject {
|
||||||
constructor(engine, def, params){
|
constructor(engine, def, params){
|
||||||
@@ -157,8 +156,8 @@ class MazeObject {
|
|||||||
o[e] = mazeAsset.scene.getObjectByName(e);
|
o[e] = mazeAsset.scene.getObjectByName(e);
|
||||||
if (o[e]){
|
if (o[e]){
|
||||||
o[e].scale.setScalar(scale);
|
o[e].scale.setScalar(scale);
|
||||||
let bb = getBoundingBox(o[e]);
|
let bb = engine.meshUtils.getBoundingBox(o[e]);
|
||||||
o[e].userData.size = getBoundingBoxSize(bb);
|
o[e].userData.size = engine.meshUtils.getBoundingBoxSize(bb);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.mazeObject(def, room);
|
this.mazeObject(def, room);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { BoxGeometry, Mesh, MeshStandardMaterial, Group, Vector3, CatmullRomCurve3, Color } from 'three';
|
import { BoxGeometry, Mesh, MeshStandardMaterial, Group, Vector3, CatmullRomCurve3} from 'three';
|
||||||
import { LineMaterial, LineGeometry, Line2 } from 'three/examples/jsm/Addons.js';
|
import { LineMaterial, LineGeometry, Line2 } from 'three/examples/jsm/Addons.js';
|
||||||
import { centerOrigin, clearMaterial } from '@/lib/MeshUtils';
|
|
||||||
import { EventManager } from '@/lib/EventManager';
|
import { EventManager } from '@/lib/EventManager';
|
||||||
import Utils from '#/app/Utils';
|
import Utils from '#/app/Utils';
|
||||||
|
|
||||||
@@ -109,10 +108,10 @@ class PairMatchingGame extends EventManager {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.object = centerOrigin(container);
|
this.object = engine.meshUtils.centerOrigin(container);
|
||||||
|
|
||||||
this.dispose = () => {
|
this.dispose = () => {
|
||||||
clearMaterial(material);
|
engine.meshUtils.clearMaterial(material);
|
||||||
bm.dispose();
|
bm.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { BoxGeometry, Mesh, MeshBasicMaterial, Group, VideoTexture } from 'three';
|
import { BoxGeometry, Mesh, MeshBasicMaterial, Group, VideoTexture } from 'three';
|
||||||
import { centerOrigin, clearMaterial } from '@/lib/MeshUtils';
|
|
||||||
import { EventManager } from '@/lib/EventManager';
|
import { EventManager } from '@/lib/EventManager';
|
||||||
|
|
||||||
class PuzzleGame1 extends EventManager {
|
class PuzzleGame1 extends EventManager {
|
||||||
@@ -123,11 +122,11 @@ class PuzzleGame1 extends EventManager {
|
|||||||
|
|
||||||
engine.addEventListener('beforeRender', this.update)
|
engine.addEventListener('beforeRender', this.update)
|
||||||
|
|
||||||
this.object = centerOrigin(container);
|
this.object = engine.meshUtils.centerOrigin(container);
|
||||||
|
|
||||||
this.dispose = () => {
|
this.dispose = () => {
|
||||||
//console.log('disposing PG1')
|
//console.log('disposing PG1')
|
||||||
clearMaterial(material);
|
engine.meshUtils.clearMaterial(material);
|
||||||
bm.dispose();
|
bm.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { BoxGeometry, Mesh, MeshBasicMaterial, Group, VideoTexture } from 'three';
|
import { BoxGeometry, Mesh, MeshBasicMaterial, Group, VideoTexture } from 'three';
|
||||||
import { centerOrigin } from '@/lib/MeshUtils';
|
|
||||||
import { EventManager } from '@/lib/EventManager';
|
import { EventManager } from '@/lib/EventManager';
|
||||||
|
|
||||||
class PuzzleGame2 extends EventManager {
|
class PuzzleGame2 extends EventManager {
|
||||||
@@ -166,7 +165,7 @@ class PuzzleGame2 extends EventManager {
|
|||||||
};
|
};
|
||||||
engine.addEventListener('beforeRender', this.update)
|
engine.addEventListener('beforeRender', this.update)
|
||||||
|
|
||||||
this.object = centerOrigin(container)
|
this.object = engine.meshUtils.centerOrigin(container)
|
||||||
resolve(this)
|
resolve(this)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Group, Color } from 'three';
|
import { Group, Color } from 'three';
|
||||||
import { centerOrigin } from '@/lib/MeshUtils';
|
|
||||||
import { EventManager } from '@/lib/EventManager';
|
import { EventManager } from '@/lib/EventManager';
|
||||||
import { TextObject } from './TextObject';
|
import { TextObject } from './TextObject';
|
||||||
import Utils from '#/app/Utils';
|
import Utils from '#/app/Utils';
|
||||||
@@ -38,7 +37,7 @@ class SingleQuestion extends EventManager {
|
|||||||
}
|
}
|
||||||
container.add(question.object);
|
container.add(question.object);
|
||||||
container.add(answers);
|
container.add(answers);
|
||||||
this.object = centerOrigin(container);
|
this.object = engine.meshUtils.centerOrigin(container);
|
||||||
resolve(this);
|
resolve(this);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { MeshBasicMaterial, Color, DoubleSide } from "three";
|
import { MeshBasicMaterial, Color, DoubleSide } from "three";
|
||||||
import { Text } from "troika-three-text";
|
import { Text } from "troika-three-text";
|
||||||
import { assignParams } from "@/lib/MeshUtils";
|
|
||||||
|
|
||||||
class TextObject {
|
class TextObject {
|
||||||
constructor(engine, obj) {
|
constructor(engine, obj) {
|
||||||
@@ -21,7 +20,7 @@ class TextObject {
|
|||||||
txt.depthOffset = 0.1;
|
txt.depthOffset = 0.1;
|
||||||
//txt.outlineBlur = '50%';
|
//txt.outlineBlur = '50%';
|
||||||
txt.color = new Color(0x0);
|
txt.color = new Color(0x0);
|
||||||
assignParams(txt, obj)
|
engine.meshUtils.assignParams(txt, obj)
|
||||||
let m = new MeshBasicMaterial({
|
let m = new MeshBasicMaterial({
|
||||||
// roughness: .73,
|
// roughness: .73,
|
||||||
// metalness: .37,
|
// metalness: .37,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ class Clickable {
|
|||||||
constructor(engine, defaultDistance) {
|
constructor(engine, defaultDistance) {
|
||||||
const objects = [];
|
const objects = [];
|
||||||
const raycaster = new Raycaster();
|
const raycaster = new Raycaster();
|
||||||
let v = new Vector3;
|
let v = new Vector3(), cv = new Vector3();
|
||||||
|
|
||||||
this.add = function (object, fn, distance) {
|
this.add = function (object, fn, distance) {
|
||||||
objects.push(object);
|
objects.push(object);
|
||||||
@@ -33,6 +33,7 @@ class Clickable {
|
|||||||
|
|
||||||
this.handle = function(){
|
this.handle = function(){
|
||||||
let forExecute = [];
|
let forExecute = [];
|
||||||
|
engine.cameraWorld.getWorldPosition(cv);
|
||||||
objects.filter(o=>{
|
objects.filter(o=>{
|
||||||
do {
|
do {
|
||||||
if (o.__active === false || o.visible === false) return false;
|
if (o.__active === false || o.visible === false) return false;
|
||||||
@@ -41,7 +42,7 @@ class Clickable {
|
|||||||
return true;
|
return true;
|
||||||
}).forEach(o => {
|
}).forEach(o => {
|
||||||
o.getWorldPosition(v);
|
o.getWorldPosition(v);
|
||||||
if (engine.cameraWorld.position.distanceTo(v) <= o._clickable.distance) {
|
if (cv.distanceTo(v) <= o._clickable.distance / engine.scale) {
|
||||||
const intersects = raycaster.intersectObject(o);
|
const intersects = raycaster.intersectObject(o);
|
||||||
if (intersects[0]) {
|
if (intersects[0]) {
|
||||||
forExecute.push({ o, i: intersects[0] });
|
forExecute.push({ o, i: intersects[0] });
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ class DashBoard extends EventManager {
|
|||||||
this.object = dash;
|
this.object = dash;
|
||||||
hud.visible = false;
|
hud.visible = false;
|
||||||
let hudAnimation, hudPlane, textPlane, sceneHeader;
|
let hudAnimation, hudPlane, textPlane, sceneHeader;
|
||||||
this.group = dash;
|
|
||||||
dash.add(hud);
|
dash.add(hud);
|
||||||
hud.add(hudTarget)
|
hud.add(hudTarget)
|
||||||
hudTarget.position.set(0,0,0.52);
|
hudTarget.position.set(0,0,0.52);
|
||||||
@@ -285,11 +284,11 @@ class DashBoard extends EventManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get active(){
|
get active(){
|
||||||
return this.group.visible;
|
return this.object.visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
set active(v){
|
set active(v){
|
||||||
this.group.visible = v;
|
this.object.visible = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
get points(){
|
get points(){
|
||||||
|
|||||||
+10
-3
@@ -4,7 +4,7 @@ class Draggable{
|
|||||||
constructor(engine, defaultDistance){
|
constructor(engine, defaultDistance){
|
||||||
const objects = [];
|
const objects = [];
|
||||||
const raycaster = new Raycaster();
|
const raycaster = new Raycaster();
|
||||||
let v = new Vector3;
|
let v = new Vector3(), cv = new Vector3();
|
||||||
let dragging = null;
|
let dragging = null;
|
||||||
this.add = function(object, dragZone, fn, distance){
|
this.add = function(object, dragZone, fn, distance){
|
||||||
objects.push(object);
|
objects.push(object);
|
||||||
@@ -29,9 +29,16 @@ class Draggable{
|
|||||||
this.handle = function(action){
|
this.handle = function(action){
|
||||||
if (['start', 'selectstart'].includes(action)){
|
if (['start', 'selectstart'].includes(action)){
|
||||||
let forExecute = [];
|
let forExecute = [];
|
||||||
objects.forEach(o=>{
|
engine.cameraWorld.getWorldPosition(cv);
|
||||||
|
objects.filter(o=>{
|
||||||
|
do {
|
||||||
|
if (o.__active === false || o.visible === false) return false;
|
||||||
|
o = o.parent;
|
||||||
|
} while (o);
|
||||||
|
return true;
|
||||||
|
}).forEach(o=>{
|
||||||
o.getWorldPosition(v);
|
o.getWorldPosition(v);
|
||||||
if (engine.cameraWorld.position.distanceTo(v) <= o._draggable.distance && o.visible){
|
if (cv.distanceTo(v) <= o._draggable.distance / engine.scale){
|
||||||
const intersects = raycaster.intersectObject(o);
|
const intersects = raycaster.intersectObject(o);
|
||||||
if (intersects[0]) forExecute.push({o, i:intersects[0]})
|
if (intersects[0]) forExecute.push({o, i:intersects[0]})
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-8
@@ -20,12 +20,13 @@ import { MotionEngine } from './MotionEngine.js';
|
|||||||
import { Draggable } from './Draggable.js';
|
import { Draggable } from './Draggable.js';
|
||||||
import { EventManager } from "./EventManager";
|
import { EventManager } from "./EventManager";
|
||||||
import { Telemetry } from './Telemetry.js';
|
import { Telemetry } from './Telemetry.js';
|
||||||
import { clearObject } from './MeshUtils.js';
|
import { MeshUtils } from './MeshUtils.js';
|
||||||
|
|
||||||
THREE.Cache.enabled = true
|
THREE.Cache.enabled = true
|
||||||
|
|
||||||
const assetPath = '/asset/default/';
|
const assetPath = '/asset/default/';
|
||||||
const defaultLightIntensity = 11;
|
const defaultLightIntensity = 11;
|
||||||
|
const sceneScale = 1//.33;
|
||||||
|
|
||||||
class GameEngine extends EventManager{
|
class GameEngine extends EventManager{
|
||||||
|
|
||||||
@@ -45,6 +46,11 @@ class GameEngine extends EventManager{
|
|||||||
);
|
);
|
||||||
|
|
||||||
const scene = new THREE.Scene();
|
const scene = new THREE.Scene();
|
||||||
|
|
||||||
|
this.sceneWrapper = new THREE.Group();
|
||||||
|
this.sceneWrapper.scale.setScalar(this.scale);
|
||||||
|
scene.add(this.sceneWrapper);
|
||||||
|
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
|
|
||||||
this.initCameraPivot()
|
this.initCameraPivot()
|
||||||
@@ -84,7 +90,7 @@ class GameEngine extends EventManager{
|
|||||||
this.ambientSound = new THREE.Audio(this.listener);
|
this.ambientSound = new THREE.Audio(this.listener);
|
||||||
|
|
||||||
this.activeObjects = new THREE.Group();
|
this.activeObjects = new THREE.Group();
|
||||||
scene.add(this.activeObjects);
|
this.sceneWrapper.add(this.activeObjects);
|
||||||
|
|
||||||
if (this.opts.gizmo) {
|
if (this.opts.gizmo) {
|
||||||
this.orbitControls = new OrbitControls(this.camera, this.renderer.domElement);
|
this.orbitControls = new OrbitControls(this.camera, this.renderer.domElement);
|
||||||
@@ -99,6 +105,7 @@ class GameEngine extends EventManager{
|
|||||||
this.orthographicCamera.position.set(0, 0, 100);
|
this.orthographicCamera.position.set(0, 0, 100);
|
||||||
this.cameraRig.rotation.y = 0;
|
this.cameraRig.rotation.y = 0;
|
||||||
}
|
}
|
||||||
|
//this.scene.scale.setScalar(1.25);
|
||||||
|
|
||||||
//const controls = new MapControls( camera, renderer.domElement );
|
//const controls = new MapControls( camera, renderer.domElement );
|
||||||
|
|
||||||
@@ -145,11 +152,12 @@ class GameEngine extends EventManager{
|
|||||||
}
|
}
|
||||||
|
|
||||||
async init(domNode, opts = {}) {
|
async init(domNode, opts = {}) {
|
||||||
|
this.scale = sceneScale;
|
||||||
this.w = domNode.clientWidth || 1200, this.h = domNode.clientHeight || 800;
|
this.w = domNode.clientWidth || 1200, this.h = domNode.clientHeight || 800;
|
||||||
this.aspect = this.w / this.h
|
this.aspect = this.w / this.h
|
||||||
this.opts = opts;
|
this.opts = opts;
|
||||||
const gameEngine = this;
|
|
||||||
this.raycaster = new THREE.Raycaster();
|
this.raycaster = new THREE.Raycaster();
|
||||||
|
this.meshUtils = new MeshUtils(this);
|
||||||
|
|
||||||
const renderer = new THREE.WebGLRenderer({
|
const renderer = new THREE.WebGLRenderer({
|
||||||
antialias: true,
|
antialias: true,
|
||||||
@@ -378,7 +386,7 @@ class GameEngine extends EventManager{
|
|||||||
this.cameraRig.add(this.orthographicCamera);
|
this.cameraRig.add(this.orthographicCamera);
|
||||||
this.cameraRig.rotation.y = Math.PI;
|
this.cameraRig.rotation.y = Math.PI;
|
||||||
this.cameraWorld.add(this.cameraRig);
|
this.cameraWorld.add(this.cameraRig);
|
||||||
this.scene.add(this.cameraWorld);
|
this.sceneWrapper.add(this.cameraWorld);
|
||||||
}
|
}
|
||||||
|
|
||||||
async initPhysics() {
|
async initPhysics() {
|
||||||
@@ -626,10 +634,11 @@ class GameEngine extends EventManager{
|
|||||||
}
|
}
|
||||||
|
|
||||||
processHideIfFar(){
|
processHideIfFar(){
|
||||||
let v = new THREE.Vector3();
|
let v = new THREE.Vector3(), cv = new THREE.Vector3();
|
||||||
|
this.cameraWorld.getWorldPosition(cv);
|
||||||
this.farArray.forEach(e=>{
|
this.farArray.forEach(e=>{
|
||||||
e.object.getWorldPosition(v);
|
e.object.getWorldPosition(v);
|
||||||
let dst = this.cameraWorld.position.distanceTo(v);
|
let dst = v.distanceTo(cv) / this.scale;
|
||||||
if (dst <= e.distance && !e.object.visible) {
|
if (dst <= e.distance && !e.object.visible) {
|
||||||
e.object.visible = true;
|
e.object.visible = true;
|
||||||
}else if (dst > e.distance && e.object.visible){
|
}else if (dst > e.distance && e.object.visible){
|
||||||
@@ -672,14 +681,14 @@ class GameEngine extends EventManager{
|
|||||||
this.gizmo?.dispose();
|
this.gizmo?.dispose();
|
||||||
this.motionQueue.clearAll();
|
this.motionQueue.clearAll();
|
||||||
this.ambientSound.stop();
|
this.ambientSound.stop();
|
||||||
this.loadedObjects.forEach(o=>clearObject(o.scene))
|
this.loadedObjects.forEach(o=>this.meshUtils.clearObject(o.scene))
|
||||||
GameEngine.loadedTextures.forEach(t=>{
|
GameEngine.loadedTextures.forEach(t=>{
|
||||||
t.dispose();
|
t.dispose();
|
||||||
});
|
});
|
||||||
GameEngine.loadedTextures.splice(0, GameEngine.loadedTextures.length);
|
GameEngine.loadedTextures.splice(0, GameEngine.loadedTextures.length);
|
||||||
this.scene.background?.dispose?.();
|
this.scene.background?.dispose?.();
|
||||||
this.scene.environment?.dispose?.();
|
this.scene.environment?.dispose?.();
|
||||||
clearObject(this.scene);
|
this.meshUtils.clearObject(this.scene);
|
||||||
this.scene = null;
|
this.scene = null;
|
||||||
this.tm?.setScene(null);
|
this.tm?.setScene(null);
|
||||||
this.removeAllListenersOfType('beforeRender');
|
this.removeAllListenersOfType('beforeRender');
|
||||||
@@ -739,6 +748,8 @@ class GameEngine extends EventManager{
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static scale = 1.33;
|
||||||
|
|
||||||
loadTexture = GameEngine.loadTexture
|
loadTexture = GameEngine.loadTexture
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { InteractiveObject } from "@/components/InteractiveObjects/InteractiveObject";
|
import { InteractiveObject } from "@/components/InteractiveObjects/InteractiveObject";
|
||||||
import { VideoPlayer } from '@/components/InteractiveObjects/VideoPlayer';
|
import { VideoPlayer } from '@/components/InteractiveObjects/VideoPlayer';
|
||||||
import { Hero } from "./Hero";
|
import { Hero } from "./Hero";
|
||||||
import { getBoundingBox, getBoundingBoxSize, autoScale } from "./MeshUtils";
|
|
||||||
import { api } from "./Api";
|
import { api } from "./Api";
|
||||||
|
|
||||||
class GameManager{
|
class GameManager{
|
||||||
constructor(engine, gameData, scenarioData, opts = {}){
|
constructor(engine, gameData, scenarioData, opts = {}){
|
||||||
|
this.engine = engine
|
||||||
return new Promise(async (resolve, reject)=>{
|
return new Promise(async (resolve, reject)=>{
|
||||||
if (typeof gameData != 'object'){
|
if (typeof gameData != 'object'){
|
||||||
gameData = (await api.game.load(gameData)).data;
|
gameData = (await api.game.load(gameData)).data;
|
||||||
@@ -85,8 +85,8 @@ class GameManager{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!i.data.noPhysics){
|
if (!i.data.noPhysics){
|
||||||
let bb = getBoundingBox(io.object);
|
let bb = engine.meshUtils.getBoundingBox(io.object);
|
||||||
let bbs = getBoundingBoxSize(bb);
|
let bbs = engine.meshUtils.getBoundingBoxSize(bb);
|
||||||
engine.physics.add(io.object, 'fixed', false, undefined, 'capsule', {
|
engine.physics.add(io.object, 'fixed', false, undefined, 'capsule', {
|
||||||
radius: Math.max(bbs.x, bbs.z)/2, halfHeight: bbs.y/2
|
radius: Math.max(bbs.x, bbs.z)/2, halfHeight: bbs.y/2
|
||||||
})
|
})
|
||||||
@@ -145,7 +145,7 @@ class GameManager{
|
|||||||
|
|
||||||
engine.dashboard?.loading(1)
|
engine.dashboard?.loading(1)
|
||||||
engine.physics.start();
|
engine.physics.start();
|
||||||
//this.debug('Scene loaded', engine.renderer.info.memory)
|
//console.log('Scene loaded', engine.renderer.info.memory)
|
||||||
}
|
}
|
||||||
resolve(this);
|
resolve(this);
|
||||||
})
|
})
|
||||||
@@ -173,7 +173,8 @@ class GameManager{
|
|||||||
object3d[p].copy(sceneObjects[data.id][p])
|
object3d[p].copy(sceneObjects[data.id][p])
|
||||||
})
|
})
|
||||||
}else if (!data.type || data.type == 'GenericObject'){
|
}else if (!data.type || data.type == 'GenericObject'){
|
||||||
autoScale(object3d, autoScaleFactor);
|
console.log('autoscaling', data.id, autoScaleFactor);
|
||||||
|
this.engine.meshUtils.autoScale(object3d, autoScaleFactor);
|
||||||
}
|
}
|
||||||
sceneObjects[data.id] = sceneObjects[data.id] || {};
|
sceneObjects[data.id] = sceneObjects[data.id] || {};
|
||||||
if (this.opts.onObjectLoad){
|
if (this.opts.onObjectLoad){
|
||||||
|
|||||||
+6
-6
@@ -1,5 +1,4 @@
|
|||||||
import { AnimationMixer, Vector3, Vector2 } from 'three';
|
import { AnimationMixer, Vector3, Vector2 } from 'three';
|
||||||
import { getBoundingBox, getBoundingBoxSize } from './MeshUtils';
|
|
||||||
import { QueryFilterFlags } from '@dimforge/rapier3d';
|
import { QueryFilterFlags } from '@dimforge/rapier3d';
|
||||||
|
|
||||||
const zero2 = new Vector2(0,0);
|
const zero2 = new Vector2(0,0);
|
||||||
@@ -66,8 +65,9 @@ class Hero{
|
|||||||
// let bb = this.model.userData.bbox;
|
// let bb = this.model.userData.bbox;
|
||||||
// let size = getBoundingBoxSize(bb);
|
// let size = getBoundingBoxSize(bb);
|
||||||
// let center = getBoundingBoxCenterPoint(bb, this.model.userData.object.position)
|
// let center = getBoundingBoxCenterPoint(bb, this.model.userData.object.position)
|
||||||
let bb = getBoundingBox(io.object);
|
let bb = engine.meshUtils.getBoundingBox(io.object);
|
||||||
this.size = getBoundingBoxSize(bb);
|
this.size = engine.meshUtils.getBoundingBoxSize(bb);
|
||||||
|
console.log('Hero size is', this.size);
|
||||||
// let center = getBoundingBoxCenterPoint(bb, io.object.position)
|
// let center = getBoundingBoxCenterPoint(bb, io.object.position)
|
||||||
|
|
||||||
// console.log('hero', size, center, size.y - 2*this.characterGapOffset)
|
// console.log('hero', size, center, size.y - 2*this.characterGapOffset)
|
||||||
@@ -307,9 +307,9 @@ class Hero{
|
|||||||
this.camera.position.copy(cameraPosition)
|
this.camera.position.copy(cameraPosition)
|
||||||
if (!this.fpv){
|
if (!this.fpv){
|
||||||
this.camera.lookAt(
|
this.camera.lookAt(
|
||||||
this.model.position.x,
|
this.engine.scale * this.model.position.x,
|
||||||
this.cameraY -this.size.y * 0.5 + this.model.position.y,
|
this.engine.scale * (this.cameraY -this.size.y * 0.5 + this.model.position.y),
|
||||||
this.model.position.z
|
this.engine.scale * this.model.position.z
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+127
-124
@@ -1,134 +1,137 @@
|
|||||||
import { Box3, Vector3, Group } from "three";
|
import { Box3, Vector3, Group } from "three";
|
||||||
import { GameEngine } from "./GameEngine";
|
class MeshUtils {
|
||||||
|
constructor(engine) {
|
||||||
function assignParams(mesh, params){
|
this.engine = engine;
|
||||||
['scale', 'rotation', 'position'].forEach(p=>params[p] && mesh[p].fromArray(params[p]));
|
|
||||||
[
|
|
||||||
'visible', 'name', 'fontSize', 'color', 'lineHeight',
|
|
||||||
'maxWidth', 'anchorX', 'anchorY', 'outlineColor', 'outlineWidth', 'textAlign'
|
|
||||||
].forEach(p=>{
|
|
||||||
if (params[p]!==undefined) mesh[p] = params[p];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function assignMaterial(mesh, params){
|
|
||||||
if (params.name && params.material){
|
|
||||||
//let mp = params.material.metalness ? new MeshStandardMaterial(params.material) : new MeshBasicMaterial(params.material)
|
|
||||||
Object.assign(mesh.material, params.material)
|
|
||||||
if (params.dm){
|
|
||||||
GameEngine.loadTexture(params.dm, params.path, undefined, [mesh.material, 'map'])
|
|
||||||
// var dm = new TextureLoader().setPath(params.path).load(params.dm);
|
|
||||||
// mesh.material.map = dm;
|
|
||||||
}
|
|
||||||
if (params.nm){
|
|
||||||
GameEngine.loadTexture(params.nm, params.path, undefined, [mesh.material, 'normalMap'])
|
|
||||||
//mesh.material.normalMap = new TextureLoader().setPath(params.path).load(params.nm);
|
|
||||||
}
|
|
||||||
if (params.em) {
|
|
||||||
GameEngine.loadTexture(params.em, params.path, undefined, [mesh.material, 'emissiveMap'])
|
|
||||||
//mesh.material.emissiveMap = new TextureLoader().setPath(params.path).load(params.em);
|
|
||||||
}
|
|
||||||
//mesh.material = mp;
|
|
||||||
mesh.material.needsUpdate = true;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function getBoundingBox(object){
|
assignParams(mesh, params){
|
||||||
return new Box3().setFromObject(object);
|
['scale', 'rotation', 'position'].forEach(p=>params[p] && mesh[p].fromArray(params[p]));
|
||||||
}
|
[
|
||||||
|
'visible', 'name', 'fontSize', 'color', 'lineHeight',
|
||||||
|
'maxWidth', 'anchorX', 'anchorY', 'outlineColor', 'outlineWidth', 'textAlign'
|
||||||
|
].forEach(p=>{
|
||||||
|
if (params[p]!==undefined) mesh[p] = params[p];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function getBoundingBoxSize(bb){
|
assignMaterial(mesh, params){
|
||||||
return new Vector3(bb.max.x - bb.min.x, bb.max.y - bb.min.y, bb.max.z - bb.min.z);
|
if (params.name && params.material){
|
||||||
}
|
//let mp = params.material.metalness ? new MeshStandardMaterial(params.material) : new MeshBasicMaterial(params.material)
|
||||||
|
Object.assign(mesh.material, params.material)
|
||||||
function getBoundingBoxMaxLength(bb){
|
if (params.dm){
|
||||||
let size = getBoundingBoxSize(bb)
|
this.engine.loadTexture(params.dm, params.path, undefined, [mesh.material, 'map'])
|
||||||
return Math.max(size.x, size.y, size.z)
|
// var dm = new TextureLoader().setPath(params.path).load(params.dm);
|
||||||
}
|
// mesh.material.map = dm;
|
||||||
|
}
|
||||||
function getBoundingBoxCenterPoint(bb, relativeTo){
|
if (params.nm){
|
||||||
relativeTo = relativeTo || new Vector3(0,0,0)
|
this.engine.loadTexture(params.nm, params.path, undefined, [mesh.material, 'normalMap'])
|
||||||
let size = getBoundingBoxSize(bb)
|
//mesh.material.normalMap = new TextureLoader().setPath(params.path).load(params.nm);
|
||||||
return new Vector3(
|
}
|
||||||
bb.min.x + (size.x)/2 - relativeTo.x,
|
if (params.em) {
|
||||||
bb.min.y + (size.y)/2 - relativeTo.y,
|
this.engine.loadTexture(params.em, params.path, undefined, [mesh.material, 'emissiveMap'])
|
||||||
bb.min.z + (size.z)/2 - relativeTo.z
|
//mesh.material.emissiveMap = new TextureLoader().setPath(params.path).load(params.em);
|
||||||
)
|
}
|
||||||
}
|
//mesh.material = mp;
|
||||||
|
mesh.material.needsUpdate = true;
|
||||||
function autoScale(object, mk = 1) {
|
|
||||||
if (mk === null) return;
|
|
||||||
let bb = getBoundingBox(object);
|
|
||||||
let k = getBoundingBoxMaxLength(bb);
|
|
||||||
object.scale.multiplyScalar(mk / k);
|
|
||||||
}
|
|
||||||
|
|
||||||
function wrapInGroup(object){
|
|
||||||
if (object.isWrapper) return object;
|
|
||||||
let group = new Group();
|
|
||||||
group.userData.bbox = getBoundingBox(object);
|
|
||||||
group.add(object);
|
|
||||||
group.userData.object = object;
|
|
||||||
group.isWrapper = true;
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
function centerOrigin(object){
|
|
||||||
let group = wrapInGroup(object);
|
|
||||||
let position = getBoundingBoxCenterPoint(group.userData.bbox, object.position).negate();
|
|
||||||
object.position.copy(position)
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
function bottomOrigin(object){
|
|
||||||
let group = centerOrigin(object);
|
|
||||||
group.userData.object.position.y = -group.userData.bbox.min.y
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearObject(o){
|
|
||||||
let disposables = []
|
|
||||||
o.traverse(object => {
|
|
||||||
if (object.isMesh) {
|
|
||||||
disposables.push(object);
|
|
||||||
}
|
}
|
||||||
if (object.isLight){
|
}
|
||||||
//console.log('Disposeing light', object)
|
|
||||||
object.dispose();
|
|
||||||
object.shadow?.dispose();
|
|
||||||
object.shadow?.map?.dispose();
|
|
||||||
}
|
|
||||||
if (object.userData?._io){
|
|
||||||
object.userData._io.dispose?.();
|
|
||||||
delete object.userData._io;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
disposables.forEach(object=>{
|
|
||||||
object.removeFromParent();
|
|
||||||
object.geometry.dispose();
|
|
||||||
if (object.material.isMaterial) {
|
|
||||||
clearMaterial(object.material)
|
|
||||||
} else {
|
|
||||||
for (const material of object.material) clearMaterial(material)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
o.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearMaterial(material) {
|
getBoundingBox(object){
|
||||||
material.dispose();
|
let bb = new Box3().setFromObject(object);
|
||||||
for (const key of Object.keys(material)) {
|
bb.min.multiplyScalar(1 / this.engine.scale);
|
||||||
const value = material[key]
|
bb.max.multiplyScalar(1 / this.engine.scale);
|
||||||
if (value && typeof value == 'object' && 'minFilter' in value) {
|
return bb;
|
||||||
//console.log('Disposing', value.name, this.renderer.info.memory.textures );
|
}
|
||||||
value.dispose();
|
|
||||||
//console.log('Disposed', value.name, this.renderer.info.memory.textures );
|
getBoundingBoxSize(bb){
|
||||||
|
return new Vector3(bb.max.x - bb.min.x, bb.max.y - bb.min.y, bb.max.z - bb.min.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
getBoundingBoxMaxLength(bb){
|
||||||
|
let size = this.getBoundingBoxSize(bb)
|
||||||
|
return Math.max(size.x, size.y, size.z)
|
||||||
|
}
|
||||||
|
|
||||||
|
getBoundingBoxCenterPoint(bb, relativeTo){
|
||||||
|
relativeTo = relativeTo || new Vector3(0,0,0)
|
||||||
|
let size = this.getBoundingBoxSize(bb)
|
||||||
|
return new Vector3(
|
||||||
|
bb.min.x + (size.x)/2 - relativeTo.x,
|
||||||
|
bb.min.y + (size.y)/2 - relativeTo.y,
|
||||||
|
bb.min.z + (size.z)/2 - relativeTo.z
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
autoScale(object, mk = 1) {
|
||||||
|
if (mk === null) return;
|
||||||
|
let bb = this.getBoundingBox(object);
|
||||||
|
let k = this.getBoundingBoxMaxLength(bb);
|
||||||
|
object.scale.multiplyScalar(mk / k);
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapInGroup(object){
|
||||||
|
if (object.isWrapper) return object;
|
||||||
|
let group = new Group();
|
||||||
|
group.userData.bbox = this.getBoundingBox(object);
|
||||||
|
group.add(object);
|
||||||
|
group.userData.object = object;
|
||||||
|
group.isWrapper = true;
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
centerOrigin(object){
|
||||||
|
let group = this.wrapInGroup(object);
|
||||||
|
let position = this.getBoundingBoxCenterPoint(group.userData.bbox, object.position).negate();
|
||||||
|
object.position.copy(position)
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
bottomOrigin(object){
|
||||||
|
let group = this.centerOrigin(object);
|
||||||
|
group.userData.object.position.y = -group.userData.bbox.min.y
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearObject(o){
|
||||||
|
let disposables = []
|
||||||
|
o.traverse(object => {
|
||||||
|
if (object.isMesh) {
|
||||||
|
disposables.push(object);
|
||||||
|
}
|
||||||
|
if (object.isLight){
|
||||||
|
//console.log('Disposeing light', object)
|
||||||
|
object.dispose();
|
||||||
|
object.shadow?.dispose();
|
||||||
|
object.shadow?.map?.dispose();
|
||||||
|
}
|
||||||
|
if (object.userData?._io){
|
||||||
|
object.userData._io.dispose?.();
|
||||||
|
delete object.userData._io;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
disposables.forEach(object=>{
|
||||||
|
object.removeFromParent();
|
||||||
|
object.geometry.dispose();
|
||||||
|
if (object.material.isMaterial) {
|
||||||
|
this.clearMaterial(object.material)
|
||||||
|
} else {
|
||||||
|
for (const material of object.material) this.clearMaterial(material)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
o.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
clearMaterial(material) {
|
||||||
|
material.dispose();
|
||||||
|
for (const key of Object.keys(material)) {
|
||||||
|
const value = material[key]
|
||||||
|
if (value && typeof value == 'object' && 'minFilter' in value) {
|
||||||
|
//console.log('Disposing', value.name, this.renderer.info.memory.textures );
|
||||||
|
value.dispose();
|
||||||
|
//console.log('Disposed', value.name, this.renderer.info.memory.textures );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { MeshUtils }
|
||||||
assignParams, assignMaterial, autoScale, centerOrigin, wrapInGroup, bottomOrigin,
|
|
||||||
getBoundingBox, getBoundingBoxSize, getBoundingBoxMaxLength, getBoundingBoxCenterPoint,
|
|
||||||
clearObject, clearMaterial
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user