У меня есть карта 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
Форум по Javascript
-
Anonymous
1746192875
Anonymous
У меня есть карта 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);
});
Подробнее здесь: [url]https://stackoverflow.com/questions/79603481/i-am-having-collision-problems-with-a-map-glb-file-in-three-js[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия