У меня есть карта glb -файл. Я взял карту Skeld из нас за то, что мы ходили вкусом, и по какой -то причине я не могу справиться с ней должным образом. Например, я не могу ходить по полу, только на потолочной плоскости. Я бы рад помощи. Вот мой файл main.js: < /p>
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls.js';
import * as CANNON from 'cannon-es';
const PLAYER_RADIUS = 1;
const MOVE_SPEED = 10;
const SCALE_FACTOR = 20;
const JUMP_FORCE = 10;
let canJump = true;
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x222222);
const camera = new THREE.PerspectiveCamera(
75, window.innerWidth / window.innerHeight, 0.1, 1000
);
camera.position.set(0, PLAYER_RADIUS, 0);
const renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
scene.add(new THREE.HemisphereLight(0xffffff, 0x444444, 0.6));
const dir = new THREE.DirectionalLight(0xffffff, 0.8);
dir.position.set(5, 10, 7.5);
dir.castShadow = true;
scene.add(dir);
const world = new CANNON.World({
gravity: new CANNON.Vec3(0, -9.82, 0)
});
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 20;
world.solver.tolerance = 0.001;
const playerBody = new CANNON.Body({
mass: 1,
fixedRotation: true,
linearDamping: 0.9
});
playerBody.addShape(new CANNON.Sphere(PLAYER_RADIUS));
world.addBody(playerBody);
const controls = new PointerLockControls(camera, renderer.domElement);
scene.add(controls.getObject());
const blocker = document.getElementById('blocker');
blocker.addEventListener('click', () => controls.lock());
controls.addEventListener('lock', () => blocker.style.display = 'none');
controls.addEventListener('unlock', () => blocker.style.display = '');
const move = {
forward: 0,
back: 0,
left: 0,
right: 0
};
window.addEventListener('keydown', e => {
if (e.code === 'KeyW') move.forward = 1;
if (e.code === 'KeyS') move.back = 1;
if (e.code === 'KeyA') move.left = 1;
if (e.code === 'KeyD') move.right = 1;
if (e.code === 'Space' && canJump) {
playerBody.velocity.y = JUMP_FORCE;
canJump = false;
}
});
window.addEventListener('keyup', e => {
if (e.code === 'KeyW') move.forward = 0;
if (e.code === 'KeyS') move.back = 0;
if (e.code === 'KeyA') move.left = 0;
if (e.code === 'KeyD') move.right = 0;
});
const groundRay = new CANNON.Ray(
new CANNON.Vec3(),
new CANNON.Vec3(0, -1, 0)
);
groundRay.mode = CANNON.Ray.CLOSEST;
groundRay.skipBackfaces = true;
new GLTFLoader().load(
'amongusSkeld.glb',
({
scene: map
}) => {
map.scale.set(SCALE_FACTOR, SCALE_FACTOR, SCALE_FACTOR);
map.updateMatrixWorld(true);
scene.add(map);
const vertices = [];
const indices = [];
let vOff = 0;
map.traverse(node => {
if (!node.isMesh) return;
const geom = node.geometry.clone();
geom.applyMatrix4(node.matrixWorld);
const pa = geom.attributes.position;
for (let i = 0; i < pa.count; i++) {
vertices.push(pa.getX(i), pa.getY(i), pa.getZ(i));
}
if (geom.index) {
const ix = geom.index;
for (let i = 0; i < ix.count; i += 3) {
indices.push(
ix.getX(i) + vOff,
ix.getX(i + 1) + vOff,
ix.getX(i + 2) + vOff
);
}
} else {
for (let i = 0; i < pa.count; i += 3) {
indices.push(vOff + i, vOff + i + 1, vOff + i + 2);
}
}
vOff += pa.count;
});
console.log(`Merged collision mesh: ${vertices.length/3} verts, ${indices.length/3} tris`);
const triShape = new CANNON.Trimesh(vertices, indices);
const mapBody = new CANNON.Body({
mass: 0
});
mapBody.addShape(triShape);
world.addBody(mapBody);
const colGeom = new THREE.BufferGeometry();
colGeom.setAttribute('position',
new THREE.BufferAttribute(new Float32Array(vertices), 3)
);
colGeom.setIndex(indices);
const colMat = new THREE.MeshBasicMaterial({
color: 0xff0000,
wireframe: true,
transparent: true,
opacity: 0.5
});
const colMesh = new THREE.Mesh(colGeom, colMat);
scene.add(colMesh);
const bbox = new THREE.Box3().setFromObject(map);
const {
min,
max
} = bbox;
const center = bbox.getCenter(new THREE.Vector3());
const rayFrom = new CANNON.Vec3(center.x, max.y + SCALE_FACTOR, center.z);
const rayTo = new CANNON.Vec3(center.x, min.y - SCALE_FACTOR, center.z);
const ray = new CANNON.Ray(rayFrom, rayTo);
const result = new CANNON.RaycastResult();
ray.intersectWorld(
world, {
mode: CANNON.Ray.CLOSEST,
skipBackfaces: true
},
result
);
const spawnY = result.hasHit ?
result.hitPointWorld.y + PLAYER_RADIUS + 0.1 :
max.y + PLAYER_RADIUS + 0.1;
playerBody.position.set(center.x, spawnY, center.z);
controls.getObject().position.set(center.x, spawnY, center.z);
console.log(`Spawn at Y=${spawnY.toFixed(2)}, hit at Y=${result.hasHit ? result.hitPointWorld.y.toFixed(2) : 'none'}`);
},
xhr => console.log(`Loading map: ${(xhr.loaded/xhr.total*100).toFixed(1)}%`),
err => console.error('Map load error:', err)
);
const clock = new THREE.Clock();
const FIXED_DT = 1 / 60;
const euler = new THREE.Euler(0, 0, 0, 'YXZ');
const quat = new THREE.Quaternion();
function animate() {
requestAnimationFrame(animate);
const dt = clock.getDelta();
groundRay.from.copy(playerBody.position);
groundRay.to.copy(playerBody.position);
groundRay.to.y -= PLAYER_RADIUS + 0.1;
const result = new CANNON.RaycastResult();
groundRay.intersectWorld(world, {}, result);
canJump = result.hasHit && result.distance < PLAYER_RADIUS + 0.1;
if (controls.isLocked) {
const forward = new THREE.Vector3();
camera.getWorldDirection(forward);
forward.y = 0;
forward.normalize();
const rightDir = new THREE.Vector3();
rightDir.crossVectors(forward, new THREE.Vector3(0, 1, 0)).normalize();
const moveDir = new THREE.Vector3();
moveDir.addScaledVector(forward, move.forward - move.back);
moveDir.addScaledVector(rightDir, move.right - move.left);
if (moveDir.lengthSq() > 0) {
moveDir.normalize().multiplyScalar(MOVE_SPEED);
playerBody.velocity.x = moveDir.x;
playerBody.velocity.z = moveDir.z;
}
controls.getObject().position.copy(playerBody.position);
}
world.step(FIXED_DT, dt, 10);
renderer.render(scene, camera);
}
animate();
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
Подробнее здесь: https://stackoverflow.com/questions/796 ... n-three-js
У меня проблемы с столкновением с картой glb -файлом в Three.js ⇐ Javascript
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Есть ли способ проверить, что файл GLB является действительным или поврежденным файлом в С#?
Anonymous » » в форуме C# - 0 Ответы
- 37 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Как создать случайные и бесконечные стены с столкновением и мяч в Libgdx?
Anonymous » » в форуме JAVA - 0 Ответы
- 2 Просмотры
-
Последнее сообщение Anonymous
-