我试图在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>
&#13;
似乎delta是使动画工作的关键。但现在我想知道为什么?我也想知道你如何将速度和减速变量转化为更多现实的&#34;值?
答案 0 :(得分:1)
有许多方法可以模拟摩擦和相关的加速度。
这是一个简单的整合。
摩擦力(阻力)是与速度指数相关的力,该力作用于移动(旋转)物体的质量。
我们可以忽略这样一个事实:我们有一个旋转物体,因为摩擦的位置在中心。还有人希望轴在轴承或润滑轴上旋转,这在很大程度上可以描述为阻力。
如果我们从拖曳函数中删除所有系数,面积,粘度,滚动摩擦和blah blah(它们都是线性关系)并查看核心函数。 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);
})();
&#13;