I tried to use three-to-cannon. but when implemented, all assets fly not in proper positions. what’s wrong with my code?
this link with three-to-cannon:
https://arifabas.com/sample
this link without three-to-cannon:
https://arifabas.com/
and attached, this is a sample of my code:
import { Component, OnInit } from "@angular/core";
import * as CANNON from 'cannon-es';
import * as THREE from "three";
import { threeToCannon, ShapeResult, ShapeType } from "three-to-cannon";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { UtilityService } from "src/app/core/service/utility.service";
@Component({
selector: "app-home",
templateUrl: "./home.component.html",
styleUrls: ["./home.component.scss"],
})
export class HomeComponent implements OnInit {
// Intro
intro: boolean;
constructor(private readonly utilityService: UtilityService) {}
ngOnInit(): void {
// Get Intro
this.utilityService.getIntro().subscribe((val: any) => {
this.intro = val;
});
// Call Running Park
this.runningPark();
}
runningPark(): void {
// Canvas Sizes
const canvasSizes = {
width: window.innerWidth,
height: window.innerHeight,
};
// Scene Init
const scene = new THREE.Scene();
// Camera Init
const camera = new THREE.PerspectiveCamera(75, canvasSizes.width / canvasSizes.height, 0.15, 10000);
// Light Init
const light = new THREE.PointLight(0xffffff, 0.5);
// Hemi Light Init
const hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.25);
// Direction Light Init
const dirLight = new THREE.DirectionalLight(0xffffff, 0.75);
// Cannon World
const world = new CANNON.World();
// Loading Manager
const manager = new THREE.LoadingManager();
// GLTF Loader
const loader = new GLTFLoader(manager);
const dracoLoader = new DRACOLoader();
// Update Physics Bodies
const updatePhysicsBodies: { mesh: THREE.Mesh, body: CANNON.Body }[] = [];
// Renderer Init
const renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true
});
// Controls Init
const controls = new OrbitControls(camera, renderer.domElement);
// Add Camera
scene.add(camera);
// Light Position
light.position.set(50, 50, 50);
// Add Light
scene.add(light);
// Hemi Light Position
hemiLight.color.setHSL(0.25, 0.25, 0.25);
hemiLight.groundColor.setHSL(0.5, 0.5, 0.5);
hemiLight.position.set(50, 50, 50);
// Add Hemi Light
scene.add(hemiLight);
// Direction Light Position
const d = 300;
dirLight.position.set(50, 50, 50);
dirLight.position.multiplyScalar(50);
dirLight.castShadow = true;
dirLight.shadow.mapSize.width = dirLight.shadow.mapSize.height = 1024*2;
dirLight.shadow.camera.left = -d;
dirLight.shadow.camera.right = d;
dirLight.shadow.camera.top = d;
dirLight.shadow.camera.bottom = -d;
dirLight.shadow.camera.far = 5000;
dirLight.shadow.bias = -0.5;
// Add Direction Light
scene.add(dirLight);
// Set Grafity
world.gravity.set(0, -9.82, 0)
world.broadphase = new CANNON.NaiveBroadphase();
(world.solver as CANNON.GSSolver).iterations = 10
world.allowSleep = true
// Progress Loader
manager.onProgress = (item, loaded, total) => {
const progress = Math.round((loaded / total * 100));
if(progress === 50 && progress < 100) {
this.utilityService.changeIntro(true);
}
else {
this.utilityService.changeProgress(progress.toString());
}
};
// Encoder GLTF
dracoLoader.setDecoderConfig({ type: 'js' });
dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.6/');
// Load GLTF
loader.setDRACOLoader(dracoLoader);
loader.load('../../../assets/models/playhub.glb', (gltf) => {
const model = gltf.scene;
model.castShadow = true;
model.receiveShadow = true;
// Scale Model
model.scale.set(0.005, 0.005, 0.005);
model.position.set(-80, 0, 50);
model.traverse((child) => {
if (child instanceof THREE.Mesh) {
//@ts-ignore
const shapeResult: ShapeResult = threeToCannon(child, { type: ShapeType.BOX });
if (shapeResult.shape) {
const body = new CANNON.Body({
mass: 1,
});
body.addShape(shapeResult.shape);
body.position.set(child.position.x, child.position.y, child.position.z);
world.addBody(body);
updatePhysicsBodies.push({ mesh: child, body });
}
}
});
// Add Model
scene.add(model);
});
// Renderer Set Size
renderer.setSize(canvasSizes.width, canvasSizes.height);
// Append to Body
document.body.appendChild(renderer.domElement);
// Arrow Init
let forwardValue = 0;
let backwardValue = 0;
let rightValue = 0;
let leftValue = 0;
let upVector = new THREE.Vector3(0, 1, 0);
let tempVector = new THREE.Vector3();
// Joy Manager Init
let joyManager: any;
// Controls Configuration
controls.maxDistance = 15;
controls.minDistance = 15;
controls.maxPolarAngle = Math.PI / 2.5;
controls.minPolarAngle = Math.PI / 2.5;
controls.autoRotate = true;
controls.autoRotateSpeed = 0;
controls.rotateSpeed = 0.4;
controls.enableDamping = false;
controls.dampingFactor = 0.1;
controls.enableZoom = false;
controls.enablePan = false;
controls.minAzimuthAngle = 0;
controls.maxAzimuthAngle = 0;
// Cube Init
const geometry = new THREE.BoxGeometry(1, 6, 1);
const cubeMaterial = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh(geometry, cubeMaterial);
mesh.position.set(-13, 13.25, 35);
// Add Cube
scene.add(mesh);
// Set Three.Clock
const clock = new THREE.Clock();
// Call Resize
resize();
window.addEventListener("resize", resize);
// Call Joystick
addJoystick();
// Resize Screen
function resize() {
let width = window.innerWidth;
let height = window.innerHeight;
renderer.setSize(width, height);
camera.aspect = width / height;
camera.updateProjectionMatrix();
}
// Animation
function animate() {
// Call Update Player
updatePlayer();
// Request Animation Frame
requestAnimationFrame(animate);
// Set World Delta
const delta = clock.getDelta();
world.step(delta);
// Update Physics Bodies
updatePhysicsBodies.forEach(({ mesh, body }) => {
mesh.position.copy(body.position as unknown as THREE.Vector3);
mesh.quaternion.copy(body.quaternion as unknown as THREE.Quaternion);
});
// Controls Update
controls.update();
// Renderer
renderer.render(scene, camera);
}
// Update Player
function updatePlayer() {
const angle = controls.getAzimuthalAngle();
if (forwardValue > 0) {
tempVector.set(0, 0, -forwardValue).applyAxisAngle(upVector, angle);
mesh.position.addScaledVector(tempVector, 0.15);
}
if (backwardValue > 0) {
tempVector.set(0, 0, backwardValue).applyAxisAngle(upVector, angle);
mesh.position.addScaledVector(tempVector, 0.15);
}
if (leftValue > 0) {
tempVector.set(-leftValue, 0, 0).applyAxisAngle(upVector, angle);
mesh.position.addScaledVector(tempVector, 0.15);
}
if (rightValue > 0) {
tempVector.set(rightValue, 0, 0).applyAxisAngle(upVector, angle);
mesh.position.addScaledVector(tempVector, 0.15);
}
mesh.updateMatrixWorld();
camera.position.sub(controls.target);
controls.target.copy(mesh.position);
camera.position.add(mesh.position);
}
// Keyboard Press
document.addEventListener("keypress", function(event) {
if (event.key === "w") {
console.log('w')
} else if (event.key === "s") {
console.log('s')
} else if (event.key === "a") {
console.log('a')
} else if (event.key === "d") {
console.log('d')
}
});
// Joystick
function addJoystick() {
const options = {
zone: document.getElementById("joystick-wrapper"),
size: 120,
multitouch: true,
maxNumberOfNipples: 2,
mode: "static",
restJoystick: true,
shape: "circle",
position: { top: "60px", left: "60px" },
dynamicPage: true,
};
joyManager = require("nipplejs").create(options);
joyManager["0"].on("move", function (evt: any, data: any) {
const forward = data.vector.y;
const turn = data.vector.x;
if (forward > 0) {
forwardValue = Math.abs(forward);
backwardValue = 0;
} else if (forward < 0) {
forwardValue = 0;
backwardValue = Math.abs(forward);
}
if (turn > 0) {
leftValue = 0;
rightValue = Math.abs(turn);
} else if (turn < 0) {
leftValue = Math.abs(turn);
rightValue = 0;
}
});
joyManager["0"].on("end", function (evt: any) {
backwardValue = 0;
forwardValue = 0;
leftValue = 0;
rightValue = 0;
});
}
// Call Animate
animate();
}
}