【瞎折腾/3D】无父物体下物体的旋转与移动

2024-01-01 21:36

本文主要是介绍【瞎折腾/3D】无父物体下物体的旋转与移动,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 说在前面
  • 移动
    • World Space
    • Local Space
  • 旋转
    • World Space
    • Local Space
  • 代码

说在前面

  • 测试环境:Microsoft Edge 120.0.2210.91
  • three.js版本:0.160.0
  • 其他:本篇文章中只探讨了无父对象下的移动与旋转,有父对象的情况将在下篇文章中讨论
  • 新年快乐!

移动

World Space

  • 在世界坐标系中移动时,直接对position进行运算即可
    const translationSpeed = new THREE.Vector3(0.5, 0, 0);
    // delta 为时间间隔
    cubeB.position.x += translationSpeed.x*delta;
    cubeB.position.y += translationSpeed.y*delta;
    cubeB.position.z += translationSpeed.z*delta;
    
    在three.js中,position为局部坐标(local position)。当物体没有父物体时,局部坐标与世界坐标相等,所以此时可以直接操作position,达到在世界坐标系中移动的效果。
  • 在下面的例子中,我们让物体先让Z轴旋转60°,再沿着世界坐标轴X移动
    在这里插入图片描述

Local Space

  • 在局部坐标系中移动时,由于物体本身可能会旋转,所以需要进行一定的转换,在three.js中,我们可以使用translateX方法:

    translateOnAxis( axis, distance ) {// translate object by distance along axis in object space// axis is assumed to be normalized// 也就是应用了物体本身的旋转角度(local space)_v1.copy( axis ).applyQuaternion( this.quaternion );this.position.add( _v1.multiplyScalar( distance ) );return this;
    }translateX( distance ) {return this.translateOnAxis( _xAxis, distance );
    }
    

    所以我们可以这样写:

    const translationSpeed = new THREE.Vector3(0.5, 0, 0);cubeB.translateX(translationSpeed.x*delta);
    cubeB.translateY(translationSpeed.y*delta);
    cubeB.translateZ(translationSpeed.z*delta);
    
  • 在下面的例子中,我们让物体先让Z轴旋转60°,再沿着局部坐标轴X移动在这里插入图片描述

旋转

World Space

  • 在three.js中,旋转提供了方法供我们使用:
    rotateOnWorldAxis( axis, angle ) {// rotate object on axis in world space// axis is assumed to be normalized// method assumes no rotated parent_q1.setFromAxisAngle( axis, angle );this.quaternion.premultiply( _q1 );return this;
    }
    
    我们可以使用四元数来表示旋转,那么世界坐标系中的旋转公式为:
    Q n e w = Q d e l t a Q o l d Q_{new}=Q_{delta}Q_{old} Qnew=QdeltaQold
    注意公式里变化量在前
    故而,世界坐标系下的旋转代码如下:
    const rotationSpeed = new THREE.Vector3(0, Math.PI/3, 0);cubeB.rotateOnWorldAxis(_xAxis, rotationSpeed.x*delta);
    cubeB.rotateOnWorldAxis(_yAxis, rotationSpeed.y*delta);
    cubeB.rotateOnWorldAxis(_zAxis, rotationSpeed.z*delta);
    
  • 在下面的例子中,我们让物体先让Z轴旋转60°,再绕着世界坐标轴Y旋转
    在这里插入图片描述

Local Space

  • 在three.js中,旋转提供了方法供我们局部坐标轴旋转:

    rotateOnAxis( axis, angle ) {// rotate object on axis in object space// axis is assumed to be normalized_q1.setFromAxisAngle( axis, angle );this.quaternion.multiply( _q1 );return this;
    }
    

    同样,我们可以使用四元数来表示旋转,局部坐标系中的旋转公式为:
    Q n e w = Q o l d Q d e l t a Q_{new}=Q_{old}Q_{delta} Qnew=QoldQdelta
    注意公式里变化量在后
    因此,局部坐标系下的旋转代码可以是:

    const rotationSpeed = new THREE.Vector3(0, Math.PI/3, 0);cubeB.rotateX(rotationSpeed.x*delta);
    cubeB.rotateY(rotationSpeed.y*delta);
    cubeB.rotateZ(rotationSpeed.z*delta);
    
  • 在下面的例子中,我们让物体先让Z轴旋转60°,再绕着局部坐标轴Y旋转
    在这里插入图片描述

代码

import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';let camera, scene, renderer;scene = new THREE.Scene();renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);// camera
camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(15, 20, 30);
scene.add(camera);// controls
const controls = new OrbitControls(camera, renderer.domElement);
controls.minDistance = 20;
controls.maxDistance = 50;
controls.maxPolarAngle = Math.PI / 2;// ambient light
scene.add(new THREE.AmbientLight(0x666666));// point light
const light = new THREE.PointLight(0xffffff, 3, 0, 0);
camera.add(light);// helper
scene.add(new THREE.AxesHelper(20));// textures
const loader = new THREE.TextureLoader();
const texture = loader.load('textures/sprites/disc.png');
texture.colorSpace = THREE.SRGBColorSpace;// CubeA
const meshA = new THREE.BoxGeometry(1, 1, 1);
const mateA = new THREE.MeshNormalMaterial();
const cubeA = new THREE.Mesh(meshA, mateA);
scene.add(cubeA);// CubeB
const meshB = new THREE.BoxGeometry(1, 1, 1);
const mateB = new THREE.MeshNormalMaterial();
const cubeB = new THREE.Mesh(meshA, mateA);
scene.add(cubeB);cubeB.position.x = 2;
cubeB.rotateZ(Math.PI/3);
cubeB.add(new THREE.AxesHelper(4));window.addEventListener('resize', onWindowResize);const translationSpeed = new THREE.Vector3(0.5, 0, 0);
const rotationSpeed = new THREE.Vector3(0, Math.PI/3, 0);let preTime = Date.now();
let curTime = preTime;
let delta;const _xAxis = /*@__PURE__*/ new THREE.Vector3( 1, 0, 0 );
const _yAxis = /*@__PURE__*/ new THREE.Vector3( 0, 1, 0 );
const _zAxis = /*@__PURE__*/ new THREE.Vector3( 0, 0, 1 );animate();function onWindowResize() {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);}function animate() {requestAnimationFrame(animate);curTime = Date.now();delta = (curTime - preTime)/1000;preTime = curTime;// cubeB.position.x += translationSpeed.x*delta;// cubeB.position.y += translationSpeed.y*delta;// cubeB.position.z += translationSpeed.z*delta;cubeB.translateX(translationSpeed.x*delta);cubeB.translateY(translationSpeed.y*delta);cubeB.translateZ(translationSpeed.z*delta);// cubeB.rotateX(rotationSpeed.x*delta);// cubeB.rotateY(rotationSpeed.y*delta);// cubeB.rotateZ(rotationSpeed.z*delta);cubeB.rotateOnWorldAxis(_xAxis, rotationSpeed.x*delta);cubeB.rotateOnWorldAxis(_yAxis, rotationSpeed.y*delta);cubeB.rotateOnWorldAxis(_zAxis, rotationSpeed.z*delta);render();}function render() {renderer.render(scene, camera);}

这篇关于【瞎折腾/3D】无父物体下物体的旋转与移动的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/560576

相关文章

Python使用Matplotlib绘制3D曲面图详解

《Python使用Matplotlib绘制3D曲面图详解》:本文主要介绍Python使用Matplotlib绘制3D曲面图,在Python中,使用Matplotlib库绘制3D曲面图可以通过mpl... 目录准备工作绘制简单的 3D 曲面图绘制 3D 曲面图添加线框和透明度控制图形视角Matplotlib

Qt把文件夹从A移动到B的实现示例

《Qt把文件夹从A移动到B的实现示例》本文主要介绍了Qt把文件夹从A移动到B的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录如何移动一个文件? 如何移动文件夹(包含里面的全部内容):如何删除文件夹:QT 文件复制,移动(

Python重命名文件并移动到对应文件夹

《Python重命名文件并移动到对应文件夹》在日常的文件管理和处理过程中,我们可能会遇到需要将文件整理到不同文件夹中的需求,下面我们就来看看如何使用Python实现重命名文件并移动到对应文件夹吧... 目录检查并删除空文件夹1. 基本需求2. 实现代码解析3. 代码解释4. 代码执行结果5. 总结方法补充在

css实现图片旋转功能

《css实现图片旋转功能》:本文主要介绍了四种CSS变换效果:图片旋转90度、水平翻转、垂直翻转,并附带了相应的代码示例,详细内容请阅读本文,希望能对你有所帮助... 一 css实现图片旋转90度.icon{ -moz-transform:rotate(-90deg); -webkit-transfo

使用C#如何创建人名或其他物体随机分组

《使用C#如何创建人名或其他物体随机分组》文章描述了一个随机分配人员到多个团队的代码示例,包括将人员列表随机化并根据组数分配到不同组,最后按组号排序显示结果... 目录C#创建人名或其他物体随机分组此示例使用以下代码将人员分配到组代码首先将lstPeople ListBox总结C#创建人名或其他物体随机分组

Qt QWidget实现图片旋转动画

《QtQWidget实现图片旋转动画》这篇文章主要为大家详细介绍了如何使用了Qt和QWidget实现图片旋转动画效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 一、效果展示二、源码分享本例程通过QGraphicsView实现svg格式图片旋转。.hpjavascript

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

poj 2187 凸包or旋转qia壳法

题意: 给n(50000)个点,求这些点与点之间距离最大的距离。 解析: 先求凸包然后暴力。 或者旋转卡壳大法。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <s

我在移动打工的日志

客户:给我搞一下录音 我:不会。不在服务范围。 客户:是不想吧 我:笑嘻嘻(气笑) 客户:小姑娘明明会,却欺负老人 我:笑嘻嘻 客户:那我交话费 我:手机号 客户:给我搞录音 我:不会。不懂。没搞过。 客户:那我交话费 我:手机号。这是电信的啊!!我这是中国移动!! 客户:我不管,我要充话费,充话费是你们的 我:可是这是移动!!中国移动!! 客户:我这是手机号 我:那又如何,这是移动!你是电信!!

MiniGPT-3D, 首个高效的3D点云大语言模型,仅需一张RTX3090显卡,训练一天时间,已开源

项目主页:https://tangyuan96.github.io/minigpt_3d_project_page/ 代码:https://github.com/TangYuan96/MiniGPT-3D 论文:https://arxiv.org/pdf/2405.01413 MiniGPT-3D在多个任务上取得了SoTA,被ACM MM2024接收,只拥有47.8M的可训练参数,在一张RTX