【问题标题】:Three.js animating with speed and frictionThree.js 以速度和摩擦制作动画
【发布时间】:2017-02-27 01:04:52
【问题描述】:

我试图在 three.js 中制作一个 3D 旋转轮动画,在其中我按下一个键来加速轮子,当我释放该键时,它会因摩擦而减速直到它停止。

我在这个站点上尝试了不同的示例,但我无法让它正常运行。我了解物理原理,但我很难在渲染循环中实现它。

我还想在未来实现减速曲线。 有没有人知道如何制作这样的东西?

提前致谢

编辑:

终于得到了一些我想要的东西!这是我的代码:`

var container, outputLeap;
var camera, scene, renderer;

var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;

var sceneRoot = new THREE.Group();
var wheelSpin = new THREE.Group();
var wheelMesh;

var clock = new THREE.Clock();

var speed = 0.1;
var decelRate = 100;

function onWindowResize() {
  windowHalfX = window.innerWidth / 2;
  windowHalfY = window.innerHeight / 2;

  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(window.innerWidth, window.innerHeight);
}

function onWindowResize() {
  windowHalfX = window.innerWidth / 2;
  windowHalfY = window.innerHeight / 2;

  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(window.innerWidth, window.innerHeight);
}


function init() {
  outputLeap = document.getElementById('output-leap');
  container = document.getElementById('container');


  camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 0.1, 80);

  scene = new THREE.Scene();

  var geometryWheel = new THREE.CylinderGeometry(3, 3, 0.05, 32);
  var materialWheel = new THREE.MeshBasicMaterial({
    color: 0xffff00,
    wireframe: true
  });
  var wheelMesh = new THREE.Mesh(geometryWheel, materialWheel);
  scene.add(sceneRoot);

  sceneRoot.add(wheelSpin);
  wheelSpin.add(wheelMesh);

  renderer = new THREE.WebGLRenderer();
  renderer.setClearColor(0x000000);
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  container.appendChild(renderer.domElement);

  window.addEventListener('resize', onWindowResize, false);
}

function render() {

  var time = clock.getElapsedTime();
  var delta = clock.getDelta();

  camera.position.y = 15;

  if (speed > 0)
    speed = Math.max(0, speed - decelRate * delta);
  else
    speed = Math.min(0, speed + decelRate * delta);

  camera.lookAt(scene.position);
  wheelSpin.rotation.y -= speed;

  outputLeap.innerHTML = 'Rotation: ' + speed;

  renderer.render(scene, camera);
}


function animate() {
  requestAnimationFrame(animate); 
  render();
}


init();
animate();
<!DOCTYPE html>
<html lang="en">

<head>
  <title></title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</head>

<body>
  <div id="info-top">
    <div id="output"></div>
    <div id="output-leap"><br></div>
  </div>
  <div id="container"></div>
  <script src="http://threejs.org/build/three.min.js">
  </script>
  <script src='js/THREEx.KeyboardState.js'></script>
  <script>
  </script>
</body>

</html>

似乎 delta 是制作动画的关键。但现在我想知道为什么?我还想知道您如何将速度和减速度变量转换为更“现实”的值?

【问题讨论】:

  • 发布你到目前为止所做的事情

标签: three.js game-physics


【解决方案1】:

有很多方法可以模拟摩擦和相关的加速度。

这是通过简单集成实现的。

摩擦(阻力)是与速度指数相关的力,该力作用于移动(旋转)物体的质量。

我们可以忽略我们有一个旋转物体的事实,因为摩擦的位置在中心。也有人认为轴在轴承或润滑轴上旋转,这在很大程度上可以描述为阻力。

如果我们从阻力函数中删除所有系数、面积、粘度、滚动摩擦和等等等等(它们都是线性关系)并查看核心函数。 drag = 1/2 * v*v 其中 v 是速度。将其乘以某个可调系数,我们就得到了力。

速度是车轮接触轴的部分的运动,我们从轴的半径和旋转速率中得到。

这样我们就可以设置sim了。

wheel = {
   mass : 100,  // mass
   axleRadius : 40,  // the lower the radius the less the drag
   deltaRot : 0.3,  // rate of turn per unit time.
   dragCoff : 0.1, //coefficients of drag
}

获取轴上的速度

var velocity = wheel.deltaRot * axleRadius;

从那个速度中获得阻力

var drag = 0.5 * velocity * velocity * wheel.dragCoff;

在车轮的质量 f = ma 上施加阻力(作为力)

var accel = drag / wheel.mass;

将加速度转换回接触轴的表面上的速度

wheel.deltaRot -= accel / wheel.axleRadius;

您可以很好地近似于车轮在轴上转动。

轴半径对阻力有很大影响。半径越大,阻力越大。 dragCoff 是我们没有包括的所有因素,例如接触车轴的表面积、轴承滚动阻力、润滑粘度。与速度平方相比,它们都是线性关系(因为我假设您不会在模拟期间更改轴半径),因此可以将其捆绑为一个数字以满足您的需求(当然少于一个)

还有质量,质量越大,轮子转动的时间就越长。

作为一个简单的演示,功能已经简化了一点

var wheel = {
   mass : 100,
   radius : 100,  // has no effect on the sim
   axleRadius : 30,
   deltaRot : 1.3,
   dragCoff : 0.2, //coefficients of drag
   rotation : 0,
}
function updateWheel(w){
    w.deltaRot -= ((0.5 * Math.pow(w.deltaRot * w.axleRadius,2) * w.dragCoff) / w.mass) / w.axleRadius;
    w.rotation += w.deltaRot;
}
function drawCircle(radius,x=0,y=0){
    ctx.beginPath();
    ctx.arc(0,0,radius,0,Math.PI * 2);
    ctx.fill();
}
function display() { 
    ctx.setTransform(1, 0, 0, 1, 0, 0); // reset transform
    ctx.globalAlpha = 1; // reset alpha
    ctx.clearRect(0, 0, w, h);
    updateWheel(wheel);
    ctx.setTransform(1,0,0,1,cw,ch); // draw at center of canvas
    ctx.rotate(wheel.rotation);
    ctx.fillStyle = "black";
    drawCircle(wheel.radius);
    ctx.fillStyle = "red";
    drawCircle(wheel.radius-10);
    ctx.fillStyle = "black";
    ctx.fillRect(0,-10,wheel.radius-5,20);
    ctx.fillStyle = "white";
    drawCircle(wheel.axleRadius+2);
    ctx.fillStyle = "black";
    drawCircle(wheel.axleRadius);
}

var w, h, cw, ch, canvas, ctx, globalTime = 0, firstRun = true;
;(function(){
    var  createCanvas, resizeCanvas;
    createCanvas = function () {
        var c, cs;
        cs = (c = document.createElement("canvas")).style;
        cs.position = "absolute";
        cs.top = cs.left = "0px";
        cs.zIndex = 1000;
        document.body.appendChild(c);
        return c;
    }
    resizeCanvas = function () {
        if (canvas === undefined) {
            canvas = createCanvas();
        }
        canvas.width = innerWidth;
        canvas.height = innerHeight;
        ctx = canvas.getContext("2d");
        cw = (w = canvas.width) / 2;
        ch = (h = canvas.height) / 2;
        wheel.deltaRot = 1.3;
    }
    function update() { // Main update loop
        display(); // call demo code
        requestAnimationFrame(update);
    }
    setTimeout(function(){
        resizeCanvas();
        window.addEventListener("resize", resizeCanvas);
        requestAnimationFrame(update);
    },0);
})();

【讨论】:

    猜你喜欢
    • 2019-08-05
    • 2014-03-08
    • 1970-01-01
    • 2012-01-05
    • 1970-01-01
    • 2019-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多