пушка. js объект переворачивается от начала до конца - PullRequest
1 голос
/ 01 февраля 2020

Я работаю над небольшой три. js сценой , в которой я хочу вести машину по дороге. Беда в том, что моя машина переворачивает каждый кадр, вместо того, чтобы кататься на шинах:

enter image description here

Кто-нибудь знает, как я могу сделать свою машину? катиться с пушкой. js? Любые указатели были бы чрезвычайно полезны. Ради сохранения вот моя грубая сцена:

var carBody,
    floorBody,
    pressed = {},
    rotation = 0,
    clock = new THREE.Clock(),
    loader = new THREE.TextureLoader(),
    container = document.querySelector('body'),
    w = container.clientWidth,
    h = container.clientHeight,
    scene = new THREE.Scene(),
    camera = new THREE.PerspectiveCamera(75, w/h, 0.1, 100000),
    controls = new THREE.TrackballControls(camera, container),
    renderConfig = {antialias: true, alpha: true},
    renderer = new THREE.WebGLRenderer(renderConfig);
controls.target = new THREE.Vector3(0, 0, 0.75);
controls.panSpeed = 0.4;
camera.position.set(0,80,-4900);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(w, h);
container.appendChild(renderer.domElement);

window.addEventListener('resize', function() {
  w = container.clientWidth;
  h = container.clientHeight;
  camera.aspect = w/h;
  camera.updateProjectionMatrix();
  renderer.setSize(w, h);
})

function render() {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
  if (car && carBody && carBody.position) {
    moveCar();
    updatePhysics();
    moveCamera();
    //controls.update();
  }
}

function getPlane(img, w, h, wrap) {
  var texture = loader.load(img);
  if (wrap) {
    texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
    texture.repeat.set(10, 10);
  }
  var material = new THREE.MeshBasicMaterial({
    map: texture,
    side: THREE.DoubleSide,
  });
  var geometry = new THREE.PlaneGeometry(w, h, 10, 10);
  return new THREE.Mesh(geometry, material);
}

function getSides() {
  var d = 300;
  var group = new THREE.Group();
  for (var i=0; i<2; i++) {
    var plane = getPlane('asphalt.jpg', 10000, 200, true);
    plane.position.y = 100;
    plane.rotation.set(Math.PI/2, -Math.PI/2, Math.PI/2);
    plane.position.x = i == 0 ? -d : d;
    group.add(plane);
  }
  return group;
}

function getSky() {
  var directions  = ['right', 'left', 'top', 'bottom', 'front', 'back'];
  var geometry = new THREE.BoxGeometry(50000, 50000, 50000);
  var materialArray = [];
  for (var i=0; i<6; i++)
    materialArray.push( new THREE.MeshBasicMaterial({
      map: loader.load(directions[i] + '.bmp'),
      side: THREE.BackSide
    }));
  return new THREE.Mesh( geometry, materialArray );
}

function getCar() {
  var mtlLoader = new THREE.MTLLoader();
  mtlLoader.load('car.mtl', function(mat) {
    mat.preload();
    var objLoader = new THREE.OBJLoader();
    objLoader.setMaterials(mat);
    objLoader.load('car.obj', function(obj) {
      window.car = obj;
      car.scale.set(0.1, 0.1, 0.1);
      obj.position.set(0, 0, -4800);
      scene.add(obj);
    })
  })
}

function getPhysics() {
  world = new CANNON.World();
  world.gravity.set(0, -100, 0); // earth = -9.82 m/s
  world.broadphase = new CANNON.NaiveBroadphase();
  world.broadphase.useBoundingBoxes = true;
  var solver = new CANNON.GSSolver();
  solver.iterations = 7;
  solver.tolerance = 0.1;
  world.solver = solver;
  world.quatNormalizeSkip = 0;
  world.quatNormalizeFast = false;
  world.defaultContactMaterial.contactEquationStiffness = 1e9;
  world.defaultContactMaterial.contactEquationRelaxation = 4;
  return world;
}

function addPhysics() {
  var m = getPhysicsMaterial();
  carBody = new CANNON.Body({
    mass: 10,
    material: m,
    shape: new CANNON.Sphere(30),
    linearDamping: 0.6,
    angularDamping: 0.8,
    position: new CANNON.Vec3(0, 30, -4900)
  });
  world.addBody(carBody);
  // floor
  var q = floor.quaternion;
  var floorBody = new CANNON.Body({
    mass: 0, // mass = 0 makes the body static
    material: m,
    shape: new CANNON.Plane(),
    quaternion: new CANNON.Quaternion(-q._x, q._y, q._z, q._w)
  });
  world.addBody(floorBody);
}

function getPhysicsMaterial() {
  var m = new CANNON.Material('slipperyMaterial');
  var c = new CANNON.ContactMaterial(m, m, {
    friction: 0.3,
    restitution: 0.3,
  })
  world.addContactMaterial(c);
  return m;
}

function moveCar() {
  var delta = clock.getDelta(); // seconds
  var moveDistance = 2000 * delta; // n pixels per second
  // set roll sensitivity
  var sensitivity = 1.5;
  var rotateAngle = Math.PI / 2 * delta * sensitivity;
  // determine the direction to travel
  var p = carBody.position;
  var dir = new THREE.Vector3(p.x, p.y, p.z);
  dir.sub(camera.position).normalize(); // vector b/w camera and car
  if (pressed['W'] || pressed['ARROWUP']) {
    carBody.velocity.x += moveDistance * dir.x;
    carBody.velocity.z += moveDistance * dir.z;
  }
  if (pressed['S'] || pressed['ARROWDOWN']) {
    carBody.velocity.x -= moveDistance * dir.x;
    carBody.velocity.z -= moveDistance * dir.z;
  }
  if (pressed['A'] || pressed['ARROWLEFT']) {
    rotation += rotateAngle;
  }
  if (pressed['D'] || pressed['ARROWRIGHT']) {
    rotation -= rotateAngle;
  }
  if (pressed[' ']) {
    carBody.velocity.y = 10;
  }
}

function updatePhysics() {
  world.step(1/60);
  car.position.copy(carBody.position);
  car.quaternion.copy(carBody.quaternion);
}

function moveCamera() {
  var rotZ = Math.cos(rotation);
  var rotX = Math.sin(rotation);
  var distance = 100;
  camera.position.x = carBody.position.x - (distance * rotX);
  camera.position.y = carBody.position.y + 20;
  camera.position.z = carBody.position.z - (distance * rotZ);
  camera.lookAt(car.position);
}

window.addEventListener('keydown', function(e) {
  pressed[e.key.toUpperCase()] = true;
})
window.addEventListener('keyup', function(e) {
  pressed[e.key.toUpperCase()] = false;
})

/**
* Add elems
**/

var light = new THREE.HemisphereLight(0xffffbb, 0x080820, 1);
scene.add(light);

var geometry = new THREE.PlaneGeometry(10000, 10000);
var material = new THREE.MeshBasicMaterial();
var floor = new THREE.Mesh(geometry, material);
floor.rotation.x = Math.PI / 2;
scene.add(floor);

var street = getPlane('asphalt.jpg', 10000, 1000, true);
street.rotation.x = Math.PI/2;
street.rotation.z = Math.PI/2;
scene.add(street);

var sides = getSides();
scene.add(sides);

var sky = getSky();
scene.add(sky);

var car = getCar();

var world = getPhysics();
addPhysics();
render();
html,
body {
  width: 100%;
  height: 100%;
  background: #aaa;
}
body {
  margin: 0;
  overflow: hidden;
}
canvas {
  width: 100%;
  height: 100%;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/cannon.js/0.6.2/cannon.js'></script>
<script src='https://raw.githack.com/mrdoob/three.js/master/examples/js/loaders/ObjLoader.js'></script>
<script src='https://raw.githack.com/mrdoob/three.js/master/examples/js/loaders/MTLLoader.js'></script>
<script src='https://raw.githack.com/mrdoob/three.js/master/examples/js/controls/TrackballControls.js'></script>
...