matrix-engine-wgpu
Version:
Networking implemented - based on kurento openvidu server. fix arcball camera,instanced draws added also effect pipeline blend with instancing option.Normalmap added, Fixed shadows casting vs camera/video texture, webGPU powered pwa application. Crazy fas
376 lines (333 loc) • 13.5 kB
JavaScript
import {GenGeoTexture2} from "../../../src/engine/effects/gen-tex2.js";
import {GenGeo} from "../../../src/engine/effects/gen.js";
import {downloadMeshes} from "../../../src/engine/loader-obj.js";
import {uploadGLBModel} from "../../../src/engine/loaders/webgpu-gltf.js";
import {LOG_FUNNY_SMALL, LOG_MATRIX, randomFloatFromTo, randomIntFromTo} from "../../../src/engine/utils.js";
import NavMesh from "./nav-mesh.js";
import {creepPoints, startUpPositions} from "./static.js";
/**
* @description
* Map Loader controls first light
*/
export class MEMapLoader {
collectionOfTree1 = [];
collectionOfRocks = [];
async loadNavMesh(navMapPath) {
return new Promise(async (resolve, reject) => {
try {
const response = await fetch(navMapPath);
const navData = await response.json();
const nav = new NavMesh(navData, {scale: [10, 1, 10]});
resolve(nav);
} catch(err) {
reject(err);
throw err;
}
})
}
constructor(forestOfHollowBlood, navMapPath) {
this.core = forestOfHollowBlood;
this.loadNavMesh(navMapPath).then((e) => {
console.log(`%cnavMap loaded.${e}`, LOG_FUNNY_SMALL);
this.core.RPG.nav = e;
this.loadMainMap(); // <-- FIXED
});
}
async onGround(m) {
this.core.addMeshObj({
position: {x: 0, y: -5, z: -10},
rotation: {x: 0, y: 0, z: 0},
rotationSpeed: {x: 0, y: 0, z: 0},
texturesPaths: ['./res/meshes/maps-objs/textures/map-bg.png'],
name: 'ground',
mesh: m.cube,
physics: {
enabled: false,
mass: 0,
geometry: "Cube"
},
raycast: {enabled: true, radius: 1.5}
});
//https://sketchfab.com/search?features=downloadable&licenses=7c23a1ba438d4306920229c12afcb5f9&licenses=322a749bcfa841b29dff1e8a1bb74b0b&q=rock&type=models
var glbFile01 = await fetch('./res/meshes/env/rocks/rock1.glb').then(res => res.arrayBuffer().then(buf => uploadGLBModel(buf, this.core.device)));
this.core.addGlbObjInctance({
material: {type: 'standard', useTextureFromGlb: true},
scale: [14, 13, 14],
position: {
x: -780,
y: -10,
z: 950
},
name: 'rocks1',
texturesPaths: ['./res/meshes/glb/textures/mutant_origin.png'],
raycast: {enabled: false, radius: 1.5},
pointerEffect: {
enabled: true
}
}, null, glbFile01);
// on engine level must be upgraded "add rotation for instanced objs... on meshObjInstanced class..."
// FOr now i will use another scene obj but same loaded data - that ok
this.core.addGlbObjInctance({
material: {type: 'standard', useTextureFromGlb: true},
scale: [14, 13, 14],
rotation: {x: 0, y: 90, z: 0},
position: {
x: -1040,
y: -10,
z: 850
},
name: 'rocks2',
texturesPaths: ['./res/meshes/glb/textures/mutant_origin.png'],
raycast: {enabled: false, radius: 1.5},
pointerEffect: {
enabled: true,
flameEffect: false
}
}, null, glbFile01);
// Tron enemy
var glbFile02 = await fetch('./res/meshes/env/rocks/home.glb').then(res => res.arrayBuffer().then(buf => uploadGLBModel(buf, this.core.device)));
let getEnemyName__ = '';
if(this.core.player.data.team == "south") {
getEnemyName__ = 'north';
} else {
getEnemyName__ = 'south';
}
this.core.addGlbObjInctance({
material: {type: 'standard', useTextureFromGlb: true},
scale: [15, 15, 15],
rotation: {x: 0, y: 90, z: 0},
position: {
x: creepPoints[app.player.data.team].finalPoint[0],
y: creepPoints[app.player.data.team].finalPoint[1],
z: creepPoints[app.player.data.team].finalPoint[2]
},
name: 'enemytron',
texturesPaths: ['./res/meshes/glb/textures/mutant_origin.png'],
raycast: {enabled: false, radius: 1.5},
pointerEffect: {
enabled: true,
energyBar: true
}
}, null, glbFile02);
var glbFile03 = await fetch('./res/meshes/env/rocks/home.glb').then(res => res.arrayBuffer().then(buf => uploadGLBModel(buf, this.core.device)));
this.core.addGlbObjInctance({
material: {type: 'standard', useTextureFromGlb: true},
scale: [15, 15, 15],
rotation: {x: 0, y: 90, z: 0},
position: {
x: creepPoints[getEnemyName__].finalPoint[0],
y: creepPoints[getEnemyName__].finalPoint[1],
z: creepPoints[getEnemyName__].finalPoint[2]
},
name: 'friendlytron',
texturesPaths: ['./res/textures/star1.png'],
raycast: {enabled: false, radius: 1.5},
pointerEffect: {
enabled: true,
energyBar: true,
}
}, null, glbFile03);
setTimeout(() => {
this.collectionOfRocks = this.core.mainRenderBundle.filter((item) => item.name.indexOf('rocks1') != -1);
this.collectionOfRocks.forEach((item) => {
item.globalAmbient = [10, 10, 10];
// this.core.collisionSystem.register(`rock1`, item.position, 15.0, 'rock');
});
this.collectionOfRocks2 = this.core.mainRenderBundle.filter((item) => item.name.indexOf('rocks2') != -1);
this.collectionOfRocks2.forEach((item) => {
item.globalAmbient = [10, 10, 10];
// this.core.collisionSystem.register(`rock1`, item.position, 15.0, 'rock');
})
this.addInstancingRock();
// trons
app.enemytron = this.core.mainRenderBundle.filter((item) => item.name.indexOf('enemytron') != -1)[0];
app.tron = this.core.mainRenderBundle.filter((item) => item.name.indexOf('friendlytron') != -1)[0];
app.tron.globalAmbient = [2, 2, 2];
// no need to extend whole Hero class
// Fiktive
app.tron.currentLevel = 10;
app.tron.hp = 400;
app.tron.armor = 0.1;
app.enemytron.currentLevel = 10;
app.enemytron.hp = 400;
app.enemytron.armor = 0.1;
addEventListener(`onDamage-${app.enemytron.name}`, (e) => {
console.info(`%c ON damage TRON send [damage-tron] ! ${e.detail}`, LOG_MATRIX)
app.enemytron.effects.energyBar.setProgress(e.detail.progress);
this.core.net.sendOnlyData({
type: "damage-tron",
defenderTeam: app.player.data.enemyTeam,
defenderName: e.detail.defender,
attackerName: e.detail.attacker,
hp: e.detail.hp,
progress: e.detail.progress
});
})
// this.pointerEffect.circlePlaneTexPath
app.tron.effects.circle = new GenGeoTexture2(app.device, app.tron.presentationFormat, 'circle2', './res/textures/star1.png');
app.tron.effects.circle.rotateEffectSpeed = 0.01;
app.enemytron.effects.circle = new GenGeoTexture2(app.device, app.enemytron.presentationFormat, 'circle2', './res/textures/star1.png');
app.enemytron.effects.circle.rotateEffectSpeed = 0.01;
// emit pos
app.tron.position.teams[0] = app.player.remoteByTeam[app.player.data.team];
app.tron.position.teams[1] = app.player.remoteByTeam[app.player.data.enemyTeam];
app.tron.position.netObject = app.tron.name;
let t = app.tron.name.replace('friendlytron', 'enemytron');
app.tron.position.remoteName = t;
this.core.collisionSystem.register(app.tron.name, app.tron.position, 25.0, 'friendly');
this.core.collisionSystem.register(app.enemytron.name, app.enemytron.position, 25.0, 'enemy');
setTimeout(() => {
app.tron.effects.circle.instanceTargets[0].position = [0, 6, 0];
app.tron.effects.circle.instanceTargets[1].position = [0, 6, 0];
app.tron.effects.circle.instanceTargets[0].color = [2, 0.1, 0, 0.5];
app.tron.effects.circle.instanceTargets[1].color = [1, 1, 1, 0.11];
app.enemytron.effects.circle.instanceTargets[0].position = [0, 6, 0];
app.enemytron.effects.circle.instanceTargets[1].position = [0, 6, 0];
app.enemytron.effects.circle.instanceTargets[0].color = [2, 0.1, 0, 0.5];
app.enemytron.effects.circle.instanceTargets[1].color = [1, 1, 1, 0.11];
}, 1000);
}, 6500);
this.core.lightContainer[0].position[1] = 175;
this.core.lightContainer[0].intesity = 1;
}
onTree(m) {
this.core.addMeshObj({
position: {x: 0, y: -5, z: -10},
rotation: {x: 0, y: 0, z: 0},
rotationSpeed: {x: 0, y: 0, z: 0},
texturesPaths: ['./res/meshes/maps-objs/textures/stablo.jpg'],
name: 'tree11',
mesh: m.tree11,
physics: {
enabled: false,
mass: 0,
geometry: "Cube"
},
raycast: {enabled: false, radius: 1.5}
});
this.core.addMeshObj({
position: {x: 0, y: -5, z: -10},
rotation: {x: 0, y: 0, z: 0},
rotationSpeed: {x: 0, y: 0, z: 0},
texturesPaths: ['./res/meshes/maps-objs/textures/green.png'],
name: 'tree12',
mesh: m.tree12,
physics: {
enabled: false,
mass: 0,
geometry: "Cube"
},
raycast: {enabled: false, radius: 1.5}
});
setTimeout(() => {
app.getSceneObjectByName('tree1-leaf2.001-0').position.y = 50
}, 200)
}
async loadMainMap() {
downloadMeshes({
cube: "./res/meshes/maps-objs/map-1.obj",
tower: "./res/meshes/env/tower.obj"
}, this.onGround.bind(this), {scale: [10, 10, 10]});
var glbFile01 = await fetch('./res/meshes/maps-objs/tree.glb').then(res => res.arrayBuffer().then(buf => uploadGLBModel(buf, this.core.device)));
this.core.addGlbObjInctance({
material: {type: 'standard', useTextureFromGlb: true},
scale: [randomIntFromTo(10, 15), randomIntFromTo(10, 15), randomIntFromTo(10, 15)],
position: {x: -500, y: -35, z: -500},
name: 'tree1',
texturesPaths: ['./res/meshes/maps-objs/textures/green.png'],
raycast: {enabled: true, radius: 1.5},
pointerEffect: {
enabled: true,
}
}, null, glbFile01);
setTimeout(() => {
this.collectionOfTree1 = this.core.mainRenderBundle.filter((o => o.name.indexOf('tree') != -1));
this.addInstancing();
}, 4000);
}
addInstancing() {
const spacing = 150;
const clusterOffsets = [
[0, 0],
[700, 0],
[0, 700],
[700, 700]
];
this.collectionOfTree1.forEach((partOftree) => {
partOftree.globalAmbient = [randomIntFromTo(5, 15), randomIntFromTo(5, 15), randomIntFromTo(5, 15)];
const treesPerCluster = 9;
const gridSize = Math.ceil(Math.sqrt(treesPerCluster));
const totalInstances = treesPerCluster * clusterOffsets.length;
partOftree.updateMaxInstances(totalInstances);
partOftree.updateInstances(totalInstances);
let instanceIndex = 0;
for(const [offsetX, offsetZ] of clusterOffsets) {
for(let i = 0;i < treesPerCluster;i++) {
const row = Math.floor(i / gridSize);
const col = i % gridSize;
const instance = partOftree.instanceTargets[instanceIndex++];
instance.position[0] = offsetX + col * spacing + randomIntFromTo(0, 20);
instance.position[2] = offsetZ + row * spacing + randomIntFromTo(0, 20);
instance.position[1] = 0;
instance.color[3] = 1;
instance.color[0] = randomFloatFromTo(0.5, 2.0);
instance.color[1] = randomFloatFromTo(0.7, 1.0);
instance.color[2] = randomFloatFromTo(0.5, 0.9);
}
}
});
}
addInstancingRock() {
const NUM = 16;
this.collectionOfRocks.forEach((rock) => {
rock.updateMaxInstances(NUM);
rock.updateInstances(NUM);
for(var x = 0;x < NUM;x++) {
let instance;
if(x == 0) {
instance = rock.instanceTargets[x];
instance.position[0] = 200;
instance.position[2] = 0;
instance.position[1] = 0;
} else if(x < 8) {
instance = rock.instanceTargets[x];
instance.position[0] = x * 250;
instance.position[2] = 0;
instance.position[1] = 0;
} else if(x < 16) {
instance = rock.instanceTargets[x];
instance.position[0] = (x - 8) * 250;
instance.position[2] = -2000;
instance.position[1] = 0;
}
instance.color[3] = 1;
instance.color[0] = 1;
instance.color[1] = 1;
instance.color[2] = randomIntFromTo(1, 1.5);
}
});
const NUM2 = 16;
this.collectionOfRocks2.forEach((rock) => {
rock.updateMaxInstances(NUM2);
rock.updateInstances(NUM2);
for(var x = 0;x < NUM2;x++) {
let instance;
if(x < 8) {
instance = rock.instanceTargets[x];
instance.position[0] = -50;
instance.position[2] = -2000 + x * 250;
instance.position[1] = 0;
} else if(x < 16) {
instance = rock.instanceTargets[x];
instance.position[0] = 1950;
instance.position[2] = -1800 + (x - 8) * 250;
instance.position[1] = 0;
}
instance.color[3] = 1;
instance.color[0] = 1;
instance.color[1] = 1;
instance.color[2] = 1;
}
});
}
}