没有几何平移和枢轴的局部网格旋转(THREEJS)
local mesh rotation without geometry translate and pivot (THREEJS)
我尝试将 "local rotation" 应用于 THREEJS 中的网格。
我想围绕几何中心应用旋转,但它是围绕几何 "origin" (0, 0, 0) 应用的。
假设:
- 我无法修改几何。
我现在在做什么:
mesh3D.position.copy(worldPosition);
mesh3D.rotation.setFromRotationMatrix(localRotation);
mesh3D.updateMatrixWorld(true);
以某种方式使用枢轴是唯一的解决方案吗?我还想避免这种情况,因为它会更改对象子级层次结构...
谢谢
要围绕不是对象原点的点旋转,适用以下一般操作顺序:
- 从对象位置减去点。
- 旋转。
- 将原点添加到对象位置。
在你的例子中,原点就是几何中心。
下面的例子是一个三角形,其中对象原点和一个角在场景原点,但三角形围绕其几何中心旋转。将 matRot = new THREE.Matrix4().makeRotationX(0.01);
更改为使用 makeRotationY
/makeRotationZ
以查看它在其他方向上的工作情况。
请注意,这些变换应用于对象的局部矩阵,因此所有子对象也将跟随其父对象进行变换。
var renderer, scene, camera, controls, stats, tri;
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,
FOV = 35,
NEAR = 1,
FAR = 1000;
function createTri(){
var geo = new THREE.BufferGeometry();
geo.addAttribute("position", new THREE.BufferAttribute(new Float32Array([
-10, 20, 0,
-20, 0, 0,
0, 0, 0
]), 3));
geo.addAttribute("normal", new THREE.BufferAttribute(new Float32Array([
0, 0, 1,
0, 0, 1,
0, 0, 1
]), 3));
geo.setIndex(new THREE.BufferAttribute(new Uint32Array([
0, 1, 2
]), 1));
geo.computeBoundingBox();
tri = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({side: THREE.DoubleSide}));
scene.add(tri);
}
var matAdd = null, matSub = null, matRot = null;
function rotateTri(){
var geoCenter = tri.geometry.boundingBox.getCenter();
matAdd.makeTranslation(geoCenter.x, geoCenter.y, geoCenter.z);
matSub.getInverse(matAdd);
tri.applyMatrix(matSub);
tri.applyMatrix(matRot);
tri.applyMatrix(matAdd);
}
function init() {
matAdd = new THREE.Matrix4();
matSub = new THREE.Matrix4();
matRot = new THREE.Matrix4().makeRotationX(0.01);
document.body.style.backgroundColor = "slateGray";
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
document.body.appendChild(renderer.domElement);
document.body.style.overflow = "hidden";
document.body.style.margin = "0";
document.body.style.padding = "0";
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 100;
scene.add(camera);
controls = new THREE.TrackballControls(camera, renderer.domElement);
controls.dynamicDampingFactor = 0.5;
controls.rotateSpeed = 3;
var light = new THREE.PointLight(0xffffff, 1, Infinity);
camera.add(light);
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0';
document.body.appendChild(stats.domElement);
resize();
window.onresize = resize;
createTri();
animate();
}
function resize() {
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
if (renderer && camera && controls) {
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
controls.handleResize();
}
}
function render() {
renderer.render(scene, camera);
}
function animate() {
rotateTri(); // rotation method
requestAnimationFrame(animate);
render();
controls.update();
stats.update();
}
function threeReady() {
init();
}
(function () {
function addScript(url, callback) {
callback = callback || function () { };
var script = document.createElement("script");
script.addEventListener("load", callback);
script.setAttribute("src", url);
document.head.appendChild(script);
}
addScript("https://threejs.org/build/three.js", function () {
addScript("https://threejs.org/examples/js/controls/TrackballControls.js", function () {
addScript("https://threejs.org/examples/js/libs/stats.min.js", function () {
threeReady();
})
})
})
})();
three.jsr85
我尝试将 "local rotation" 应用于 THREEJS 中的网格。
我想围绕几何中心应用旋转,但它是围绕几何 "origin" (0, 0, 0) 应用的。
假设:
- 我无法修改几何。
我现在在做什么:
mesh3D.position.copy(worldPosition);
mesh3D.rotation.setFromRotationMatrix(localRotation);
mesh3D.updateMatrixWorld(true);
以某种方式使用枢轴是唯一的解决方案吗?我还想避免这种情况,因为它会更改对象子级层次结构...
谢谢
要围绕不是对象原点的点旋转,适用以下一般操作顺序:
- 从对象位置减去点。
- 旋转。
- 将原点添加到对象位置。
在你的例子中,原点就是几何中心。
下面的例子是一个三角形,其中对象原点和一个角在场景原点,但三角形围绕其几何中心旋转。将 matRot = new THREE.Matrix4().makeRotationX(0.01);
更改为使用 makeRotationY
/makeRotationZ
以查看它在其他方向上的工作情况。
请注意,这些变换应用于对象的局部矩阵,因此所有子对象也将跟随其父对象进行变换。
var renderer, scene, camera, controls, stats, tri;
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,
FOV = 35,
NEAR = 1,
FAR = 1000;
function createTri(){
var geo = new THREE.BufferGeometry();
geo.addAttribute("position", new THREE.BufferAttribute(new Float32Array([
-10, 20, 0,
-20, 0, 0,
0, 0, 0
]), 3));
geo.addAttribute("normal", new THREE.BufferAttribute(new Float32Array([
0, 0, 1,
0, 0, 1,
0, 0, 1
]), 3));
geo.setIndex(new THREE.BufferAttribute(new Uint32Array([
0, 1, 2
]), 1));
geo.computeBoundingBox();
tri = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({side: THREE.DoubleSide}));
scene.add(tri);
}
var matAdd = null, matSub = null, matRot = null;
function rotateTri(){
var geoCenter = tri.geometry.boundingBox.getCenter();
matAdd.makeTranslation(geoCenter.x, geoCenter.y, geoCenter.z);
matSub.getInverse(matAdd);
tri.applyMatrix(matSub);
tri.applyMatrix(matRot);
tri.applyMatrix(matAdd);
}
function init() {
matAdd = new THREE.Matrix4();
matSub = new THREE.Matrix4();
matRot = new THREE.Matrix4().makeRotationX(0.01);
document.body.style.backgroundColor = "slateGray";
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
document.body.appendChild(renderer.domElement);
document.body.style.overflow = "hidden";
document.body.style.margin = "0";
document.body.style.padding = "0";
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 100;
scene.add(camera);
controls = new THREE.TrackballControls(camera, renderer.domElement);
controls.dynamicDampingFactor = 0.5;
controls.rotateSpeed = 3;
var light = new THREE.PointLight(0xffffff, 1, Infinity);
camera.add(light);
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0';
document.body.appendChild(stats.domElement);
resize();
window.onresize = resize;
createTri();
animate();
}
function resize() {
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
if (renderer && camera && controls) {
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
controls.handleResize();
}
}
function render() {
renderer.render(scene, camera);
}
function animate() {
rotateTri(); // rotation method
requestAnimationFrame(animate);
render();
controls.update();
stats.update();
}
function threeReady() {
init();
}
(function () {
function addScript(url, callback) {
callback = callback || function () { };
var script = document.createElement("script");
script.addEventListener("load", callback);
script.setAttribute("src", url);
document.head.appendChild(script);
}
addScript("https://threejs.org/build/three.js", function () {
addScript("https://threejs.org/examples/js/controls/TrackballControls.js", function () {
addScript("https://threejs.org/examples/js/libs/stats.min.js", function () {
threeReady();
})
})
})
})();
three.jsr85