env tests

This commit is contained in:
2025-07-30 13:24:46 +03:00
parent 85ece672e4
commit 6d913c7d7c
14 changed files with 241 additions and 47 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

+47 -7
View File
@@ -47,15 +47,18 @@
</v-list-item>
</v-list>
</v-navigation-drawer>
<video class="d-none" src="/asset/default/44.mp4" ref="videoPlayer"></video>
</template>
<script>
import { GameEngine } from '@/lib/GameEngine';
import { Hero } from '@/lib/Hero';
import { Game1 } from '@/lib/mini-games/Game1';
import { Game2 } from '@/lib/mini-games/Game2';
import { Game4 } from '@/lib/mini-games/Game4';
import { Game1 } from '@/lib/interactive-objects/Game1';
import { Game2 } from '@/lib/interactive-objects/Game2';
import { Game4 } from '@/lib/interactive-objects/Game4';
import { Grass } from '@/lib/interactive-objects/Grass';
import { VideoPlayer } from '@/lib/interactive-objects/VideoPlayer';
import { useAppStore } from '@/stores/app';
const store = useAppStore();
@@ -154,7 +157,7 @@ export default {
}
},
async loadEnvironment(scene, target){
//await gameEngine.loadPanorama(`/asset/default/43.webp`);
await gameEngine.loadPanorama(`/asset/default/55/panorama-vaya.webp`);
await this.expandScenarioData(scene);
//gameEngine.activeObjects.scale.set(0.033, 0.033, 0.033)
gameEngine.activeObjects.clear();
@@ -166,6 +169,18 @@ export default {
let env = await gameEngine.load(`/asset/default/${this.scene.data.$environment.asset.name}`);
this.setObjectAttributes(l, this.scene.data, env, 100);
gameEngine.activeObjects.add(env.scene);
gameEngine.scene.environmentRotation.y = Math.PI / 8;
// if (env.scene.children[0]?.material?.map){
// let emap = env.scene.children[0].material.map.clone()
// emap = new gameEngine.$.Texture(emap.source.data, gameEngine.$.EquirectangularReflectionMapping)
// emap.mapping = gameEngine.$.EquirectangularReflectionMapping;
// emap.needsUpdate = true;
// emap.updateMatrix()
// emap.repeat.set(-1,-1)
// gameEngine.scene.environment = gameEngine.scene.background = emap
// console.log('env',emap)
// gameEngine.scene.environmentRotation.y = Math.PI / 2;
// }
}
for (let i of this.scene.data.items || []) {
let gltf = await gameEngine.load(`/asset/default/${i.data.$go.asset.name}`);
@@ -174,6 +189,10 @@ export default {
if (i.data.$go.type == 'player3d'){
let hero = new Hero(gltf, i.data.$go);
hero.init(gameEngine);
}else{
if (gltf.animations?.length){
gameEngine.playAnimation(gameEngine.scene, gltf.animations[0]);
}
}
//console.log(JSON.stringify(l));
//window.gameEngine = gameEngine;
@@ -187,15 +206,36 @@ export default {
let testGame1 = new Game1(gameEngine, '/static/textures/game1-test.jpg', 2, 3);
gameEngine.activeObjects.add(testGame1.game);
testGame1.game.position.set(0, 1, -5);
testGame1.game.position.set(0, 1, -15);
let testGame2 = new Game2(gameEngine, '/static/textures/game2-test.jpg', 3, 3);
gameEngine.activeObjects.add(testGame2.game);
testGame2.game.position.set(0, 1, 5);
testGame2.game.position.set(0, 1, 15);
testGame2.game.rotation.y += Math.PI;
let testGame4 = new Game4(gameEngine, '/static/feathers-game.glb', 3, 4);
gameEngine.activeObjects.add(testGame4.game);
testGame4.game.position.set(0, 1, 5);
testGame4.game.position.set(15, 1, 5);
let vp = new VideoPlayer(gameEngine, this.$refs.videoPlayer, 16, 9);
gameEngine.activeObjects.add(vp.videoPlayer);
vp.videoPlayer.position.set(37, 5.5, 15);
vp.videoPlayer.rotation.y += -Math.PI/2;
new Grass(Grass.positions(1000,50,50), '/static/textures/grass01.png', 1, .5).then(mesh=>{
console.log('adding grass')
gameEngine.scene.add(mesh);
})
new Grass(Grass.positions(250,50,50), '/static/textures/flowers01.png', 1, .75).then(mesh=>{
gameEngine.scene.add(mesh);
console.log('adding grass')
})
new Grass(Grass.positions(250,50,50), '/static/textures/flowers02.png', 1, .75).then(mesh=>{
gameEngine.scene.add(mesh);
console.log('adding grass')
})
},
async expandScenarioData(scene){
scene.data.$environment = (await this.$api.gameObject.load(scene.data.environment)).data
+67 -21
View File
@@ -9,11 +9,23 @@ class Hero{
this.object = object;
this.data = data;
this.model = object.scene
console.log(object)
//console.log(object)
}
init(gameEngine){
this.gameEngine = gameEngine;
//this.gameEngine.orbitControls.object = this.model;
//this.gameEngine.orbitControls.target = this.model.position;
this.gameEngine.orbitControls.enabled = false;
//this.model.add(gameEngine.camera)
gameEngine.camera.position.set(0,17,-30)
gameEngine.camera.lookAt(new THREE.Vector3(this.model.position.x, 5, this.model.position.z))
this.heroCamera = new THREE.Object3D()
this.model.add(this.heroCamera)
this.heroCamera.applyMatrix4(gameEngine.camera.matrix)
this.mixer = new AnimationMixer(this.model);
gameEngine.mixers.push( this.mixer );
this.actionWalk = this.mixer.clipAction( this.object.animations.find(a=>a.name=='walk') );
@@ -38,6 +50,7 @@ class Hero{
)
colliderBody.linearDamping = 0.95
colliderBody.angularFactor.set(0, 1, 0) // prevents rotation X,Z axis
//colliderBody.sleepSpeedLimit = 1.0;
gameEngine.phy.world.addBody(colliderBody)
this.characterCollider = characterCollider;
@@ -47,9 +60,9 @@ class Hero{
this.delta = 0
this.inputVelocity = new THREE.Vector3()
this.velocity = new CANNON.Vec3()
this.euler = new THREE.Euler()
this.quat = new THREE.Quaternion()
this.v = new THREE.Vector3()
this.rotation = new THREE.Euler()
this.targetQuaternion = new THREE.Quaternion()
this.distance = 0
this.canJump = true;
@@ -96,15 +109,15 @@ class Hero{
}
update(){
return
//return
if (this.gameEngine.renderer.xr.isPresenting) return;
let { inputVelocity, velocity, euler, quat, v, targetQuaternion, clock } = this;
let { inputVelocity, velocity, quat, v, targetQuaternion, clock, rotation } = this;
let pc = this.pointerControls;
pc.update();
if (this.ready) {
if (this.canJump) {
//walking
this.mixer.update(this.distance / 10)
this.mixer.update(this.distance / 100)
} else {
//were in the air
this.mixer.update(this.delta)
@@ -114,39 +127,50 @@ class Hero{
this.model.position.y = this.characterCollider.position.y
this.distance = this.model.position.distanceTo(p)
const rotationMatrix = new THREE.Matrix4()
rotationMatrix.lookAt(p, this.model.position, this.model.up)
targetQuaternion.setFromRotationMatrix(rotationMatrix)
// const rotationMatrix = new THREE.Matrix4()
// rotationMatrix.lookAt(p, this.model.position, this.model.up)
// targetQuaternion.setFromRotationMatrix(rotationMatrix)
if (!this.model.quaternion.equals(targetQuaternion)) {
this.model.quaternion.rotateTowards(targetQuaternion, this.delta * 10)
}
// if (!this.model.quaternion.equals(targetQuaternion)) {
// this.model.quaternion.rotateTowards(targetQuaternion, this.delta * 10)
// }
if (this.canJump) {
inputVelocity.set(0, 0, 0)
if (pc.moveForward) {
inputVelocity.z = -1
inputVelocity.z = 1
}
if (pc.moveBackward) {
inputVelocity.z = 1
inputVelocity.z = -1
}
if (pc.moveLeft) {
inputVelocity.x = -1
//inputVelocity.x = -1
rotation.y+=2*this.delta
}
if (pc.moveRight) {
inputVelocity.x = 1
//inputVelocity.x = 1
rotation.y-=2*this.delta
}
//let d = this.gameEngine.camera.position.distanceTo(v);
inputVelocity.setLength(this.delta * 10)
// apply camera rotation to inputVelocity
euler.y = this.gameEngine.cameraYaw.rotation.y;
//euler.y = this.gameEngine.camera.rotation.y;
euler.order = 'XYZ'
quat.setFromEuler(euler)
quat.setFromEuler(rotation)
inputVelocity.applyQuaternion(quat)
//this.gameEngine.camera.updateProjectionMatrix()
//this.gameEngine.orbitControls.update()
// if (this.gameEngine.orbitControls){
//this.gameEngine.orbitControls.target = v//this.model.position;
// //this.gameEngine.orbitControls.update()
// }
//this.gameEngine.camera.rotateOnAxis(v, rotation.y)
}
if(inputVelocity.x || inputVelocity.z){
@@ -155,7 +179,12 @@ class Hero{
this.setAction(this.actionIdle, true)
}
// this.gameEngine.camera.position.lerp(this.characterCollider.position, 1)
// this.gameEngine.camera.rotation.y = rotation.y;
this.model.position.lerp(this.characterCollider.position, 1)
this.model.rotation.y = rotation.y;
}
velocity.set(inputVelocity.x, inputVelocity.y, inputVelocity.z)
this.colliderBody.applyImpulse(velocity)
@@ -172,13 +201,30 @@ class Hero{
// })
this.characterCollider.getWorldPosition(v)
this.gameEngine.cameraPivot.position.lerp(v, 0.1)
//this.gameEngine.cameraPivot.position.lerp(v, 0.1)
// if (this.gameEngine.camera.position.distanceTo(v) > 200){
// this.gameEngine.camera.position.set(v.x+10, 3, v.z + 30);
// if (this.gameEngine.camera.position.distanceTo(v) > 2){
// this.gameEngine.camera.position.set(v.x+1, 3, v.z + 3);
// }
//this.gameEngine.camera.lookAt(v.x, 3, v.z);
//this.gameEngine.camera.rotation.y = this.model.rotation.y;
// this.gameEngine.camera.updateMatrix();
// this.model.updateMatrix();
let cam = this.gameEngine.camera;
let vv = new THREE.Vector3(), qq = new THREE.Quaternion;
this.heroCamera.getWorldPosition(vv)
//this.heroCamera.getWorldQuaternion(qq);
cam.position.copy(vv)
//cam.setRotationFromQuaternion(qq)
cam.lookAt(new THREE.Vector3(this.model.position.x, 2.8, this.model.position.z))
//console.log(vv)
// cam.matrixAutoUpdate = false;
// cam.matrix.multiplyMatrices(this.model.matrix, cam.matrix)
// //cam.matrix.decompose(cam.position, cam.quaternion, cam.scale)
// //this.gameEngine.camera.updateMatrix();
// cam.matrixAutoUpdate = true;
// this.gameEngine.orbitControls.update()
}
}
+31 -19
View File
@@ -45,16 +45,21 @@ class GameEngine {
// 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( 20 );
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 = 2048;
dirLight.shadow.mapSize.height = 2048;
dirLight.shadow.mapSize.width = 1024;
dirLight.shadow.mapSize.height = 1024;
const d = 50;
@@ -73,14 +78,14 @@ class GameEngine {
powerPreference: "high-performance",
});
renderer.setPixelRatio(window.devicePixelRatio);
// renderer.toneMapping = THREE.CineonToneMapping;
// renderer.toneMappingExposure = 1.2;
// renderer.shadowMap.enabled = true;
// renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
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.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;
@@ -235,8 +240,8 @@ class GameEngine {
this.scene.add(pivot)
pivot.add(yaw)
yaw.add(pitch)
pitch.add(this.perspectiveCamera);
pitch.add(this.orthographicCamera);
this.scene.add(this.perspectiveCamera);
this.scene.add(this.orthographicCamera);
this.cameraPivot = pivot;
this.cameraYaw = yaw;
}
@@ -252,8 +257,8 @@ class GameEngine {
{
friction: 0,
restitution: 0.3,
contactEquationStiffness: 1e8,
contactEquationRelaxation: 3,
contactEquationStiffness: 1e10,
contactEquationRelaxation: 30,
}
)
world.addContactMaterial(slippery_ground_cm)
@@ -388,11 +393,18 @@ class GameEngine {
return new Promise((resolve, reject) => {
this.loader.load(url, o => {
o.scene.traverse(object => {
// if (object.name == 'environment'){
// console.log('env recomputing')
// object.material.shading = THREE.SmoothShading;
// object.geometry.computeVertexNormals(true);
// }
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;
+65
View File
@@ -0,0 +1,65 @@
import {
Matrix4,
Mesh,
PlaneGeometry,
MeshPhongMaterial,
Vector3,
TextureLoader
} from 'three';
import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js';
class Grass {
constructor(positions, texture, x, y) {
return new Promise((resolve, reject) => {
var tLoader = new TextureLoader();
tLoader.load(texture, (t) => {
//t.encoding = sRGBEncoding;
// create the initial geometry
var geometry = new PlaneGeometry(x || 1, y || 1);
var material = new MeshPhongMaterial({
map: t,
alphaTest: .5,
});
geometry.applyMatrix4(new Matrix4().makeTranslation(0, geometry.parameters.height / 2, 0));
geometry.normalizeNormals();
var arr = [];
for (var i = 0; i < positions.length; i++) {
var position = positions[i];
var baseAngle = Math.PI * 2 * Math.random();
var nPlanes = 2;
for (var j = 0; j < nPlanes; j++) {
var angle = baseAngle + j * Math.PI / nPlanes;
var gg = geometry.clone();
gg.rotateY(angle);
gg.translate(position.x, position.y, position.z);
arr.push(gg);
var gg = geometry.clone();
gg.rotateY(angle + Math.PI);
gg.translate(position.x, position.y, position.z);
arr.push(gg);
}
}
var mesh = new Mesh(BufferGeometryUtils.mergeGeometries(arr, false), material);
resolve(mesh);
arr.forEach(g => g.dispose());
});
});
}
static positions(count, x, z) {
var positions = new Array(count);
for (var i = 0; i < count; i++) {
var position = new Vector3();
position.x = (Math.random() - 0.5) * x;
position.z = (Math.random() - 0.5) * z;
positions[i] = position;
}
return positions;
}
}
export { Grass }
@@ -0,0 +1,31 @@
import * as THREE from 'three';
class VideoPlayer {
constructor(context, video, w, h){
let geometry = new THREE.PlaneGeometry( w, h );
let map = new THREE.VideoTexture( video );
map.colorSpace = THREE.SRGBColorSpace;
let material = new THREE.MeshStandardMaterial( {
color: 0xffffff,
map,
transparent: true,
opacity: 0.5,
} );
let plane = new THREE.Mesh( geometry, material );
this.videoPlayer = plane;
context.clickable.add(plane, ()=>{
material.opacity = 0.9
if (video.paused){
video.play();
}else{
video.pause();
}
});
}
}
export {VideoPlayer}