javascript - 基于 Three.js 中新枢轴的对象动画旋转

标签 javascript graphics three.js

我想在 Three.JS 中这样做:

Animation

我做了螺旋和向下运动,但我没有做敲击 Action 。

var planeGeometry = new THREE.PlaneGeometry(10,10);
var planeMaterial = new THREE.MeshBasicMaterial({color: 0x828282, wireframe: false, side: THREE.DoubleSide});
var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
planeMesh.rotation.x = 1.0 * THREE.Math.degToRad(90);
scene.add(planeMesh);

var cylinderGeometry = new THREE.CylinderGeometry(0.2, 0.2, 14);
var cylinderMaterial = new THREE.MeshBasicMaterial({color: 0x00ff00, wireframe: false});
var cylinderMesh = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
cylinderMesh.position.set(0,7,0);
scene.add(cylinderMesh);


groupDown = new THREE.Group();
groupSpiral = new THREE.Group();
groupKnock = new THREE.Group();

var woodPeckerGeometry = new THREE.BoxGeometry(1,3,2);
var woodPeckerMaterial = new THREE.MeshBasicMaterial({color: 0xffffff, wireframe: false});
var woodPeckerMesh = new THREE.Mesh(woodPeckerGeometry , woodPeckerMaterial );
groupDown.add(woodPeckerMesh );
groupDown.position.set(0, 10, 2);

groupSpiral.add(groupDown)

groupKnock.add(groupSpiral)

scene.add(groupKnock);

和渲染函数:

var render = function () {
    groupDown.position.y -= 0.03;
    if(groupDown.position.y < 1.6) {
        groupDown.position.y = 13;
    }
    groupSpiral.rotation.y += 0.03;
};

那么问题来了,我怎样才能做敲门 Action 呢?

最佳答案

您可以增加 z 轴上的 groupDown 旋转,就像您对其位置所做的那样,“啄木鸟”将开始敲击圆柱体。这样做的问题是旋转的枢轴位于盒子的中心。

要解决此问题,您可以将“啄木鸟”添加到一个组(即 pivotGroup),在这个新组中将其位置相对于其高度设置并处理 pivotGroup 作为动画的新对象。这样,盒子就会从底部开始旋转。

请参阅下面的完整示例。

var camera, scene, renderer, groupSpiral, groupDown, groupKnock;

function init() {

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 10, 10000);
    camera.position.z = 30;
    camera.position.y = 24;
    camera.rotation.x = -0.55;

    scene.add(camera);

    var planeGeometry = new THREE.PlaneGeometry(10, 10);
    var planeMaterial = new THREE.MeshBasicMaterial({color: 0x828282, wireframe: false, side: THREE.DoubleSide});
    var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
    planeMesh.rotation.x = 1.0 * THREE.Math.degToRad(90);
    planeMesh.rotation.z = 1.0 * THREE.Math.degToRad(45);
    scene.add(planeMesh);

    var cylinderGeometry = new THREE.CylinderGeometry(0.3, 0.3, 14);
    var cylinderMaterial = new THREE.MeshBasicMaterial({color: 0x00ff00, wireframe: false});
    var cylinderMesh = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
    cylinderMesh.position.y = 7;
    scene.add(cylinderMesh);

    var coneGeometry = new THREE.ConeGeometry(0.3, 1, 32);
    var coneMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: false});
    var coneMesh = new THREE.Mesh(coneGeometry, coneMaterial);
    coneMesh.position.set(1, 1.8, 0);
    coneMesh.rotation.z = Math.PI / -2;

    groupDown = new THREE.Group();
    groupSpiral = new THREE.Group();
    groupKnock = new THREE.Group();

    var woodPeckerGeometry = new THREE.BoxGeometry(1, 3, 1.5);
    var woodPeckerMaterial = new THREE.MeshBasicMaterial({color: 0xffffff, wireframe: false});
    var woodPeckerMesh = new THREE.Mesh(woodPeckerGeometry, woodPeckerMaterial);

    woodPeckerMesh.position.set(0, 1, 0);
    woodPeckerMesh.rotation.set(0, 0, Math.PI);
    groupKnock.add(coneMesh);
    groupKnock.add(woodPeckerMesh);

    groupDown.add(groupKnock);
    groupDown.position.set(0, 12, 1.5);
    groupDown.rotation.y = Math.PI / 2;
    groupSpiral.add(groupDown)

    scene.add(groupSpiral);

    renderer = new THREE.WebGLRenderer({antialias: true});
    renderer.setSize(window.innerWidth, window.innerHeight);
    $(renderer.domElement).appendTo("body");

}

function animate() {

    requestAnimationFrame(animate);
    render();

}

function render() {

    groupDown.position.y -= 0.03;
    if(groupDown.position.y < 1.6) {
        groupDown.position.y = 12;
    }
    groupSpiral.rotation.y += 0.03;

    groupKnock.rotation.z += 0.035;
    if(groupKnock.rotation.z > Math.PI/6) {
        groupKnock.rotation.z = 0;
    }

    renderer.render(scene, camera);

}

$(document).ready(function() {
    init();
    animate();
});
* {
  padding: 0;
  margin: 0;
  overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

关于javascript - 基于 Three.js 中新枢轴的对象动画旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58597693/

相关文章:

c++ - 在 OpenGL 中创建不可变缓冲区

java - 调整复合(设计模式)形状的大小

three.js - Phong ShaderMaterial 参数/设置定义

javascript - three.js PointCloud 中的可点击粒子

javascript - 如何使用 canvas 和 javascript 创建运动模糊效果?

javascript - 如何让 JavaScript 等到某个事件发生?

algorithm - 将中间系统状态存储为临时文件或字符串? (用于撤消/重做)

javascript - 3D 线条未从 WebGL Globe 渲染出来(潜在的 CSS 冲突?)

javascript - CSS 变换何时真正设置?

javascript - jQuery 不适合新手