我正在尝试使用动画在与默认轴不同的轴上旋转对象。
这实际上是我的做法。您可以单击按钮L
,Li
它实际上可以工作。但是正如您所看到的,R
按钮的旋转轴应更改。我不知道该怎么做。我是否对这种旋转动画做正确的事情?
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100);
camera.position.set(-2, 1, 3);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight - 60); // -60 to see buttons below
const divid = document.getElementById('myid');
divid.appendChild(renderer.domElement);
// show axis
scene.add(new THREE.AxesHelper(2))
let controls = new THREE.OrbitControls(camera, renderer.domElement);
// one triangle equilateral
const sideLength = 1
const x = 0
const y = 0
const geometry = new THREE.Geometry()
geometry.vertices.push(new THREE.Vector3(x, (Math.sqrt(3) / 2 * sideLength) - (sideLength / 2), 0))
geometry.vertices.push(new THREE.Vector3(x - (sideLength / 2), y - (sideLength / 2), 0))
geometry.vertices.push(new THREE.Vector3(x + (sideLength / 2), y - (sideLength / 2), 0))
geometry.faces.push(new THREE.Face3(0, 1, 2))
const facesColors = [
0xFFFF00, // yellow
0xFF0000, // red
0x0000FF, // blue
0x008000 // green
]
const pos = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3
]
const d = 0.05 // écart entre les triangles
let face
const facesVectors = [
[0, 1, 2],
[0, 2, 3],
[0, 3, 1],
[1, 3, 2]
]
// https://stackoverflow.com/questions/60774560/drawing-a-pyraminx-with-triangles
// coords des points d'un tétrahèdre
const s89 = Math.sqrt(8 / 9)
const s29 = Math.sqrt(2 / 9)
const s23 = Math.sqrt(2 / 3)
const v = [
new THREE.Vector3(0, 0, 1),
new THREE.Vector3(s89, 0, -1 / 3),
new THREE.Vector3(-s29, s23, -1 / 3),
new THREE.Vector3(-s29, -s23, -1 / 3)
]
const computeMidPts = (pts) => {
const midPts = []
for (let i = 0; i < pts.length; ++i) {
midPts.push(new THREE.Vector3().lerpVectors(pts[i], pts[(i + 1) % 3], 0.5))
}
return midPts
}
const computeInnerPts = (pts, d) => {
const innerPts = []
for (let i = 0; i < pts.length; ++i) {
const va = new THREE.Vector3().lerpVectors(pts[i], pts[(i + 1) % 3], d)
const vb = new THREE.Vector3().lerpVectors(pts[i], pts[(i + 2) % 3], d)
innerPts.push(new THREE.Vector3().lerpVectors(va, vb, 0.5))
}
return innerPts
}
let allfaces = [];
for (let i = 0; i < 4; ++i) {
const pts = [v[facesVectors[i][0]], v[facesVectors[i][1]], v[facesVectors[i][2]]]
const outerPts = computeInnerPts(pts, d)
for (let j = 0; j < 3; ++j) {
const geometry = new THREE.Geometry()
geometry.vertices.push(outerPts[j])
geometry.vertices.push(new THREE.Vector3().lerpVectors(outerPts[j], outerPts[(j + 1) % 3], 0.5 - d / 2))
geometry.vertices.push(new THREE.Vector3().lerpVectors(outerPts[j], outerPts[(j + 2) % 3], 0.5 - d / 2))
geometry.faces.push(new THREE.Face3(0, 1, 2))
const material = new THREE.MeshBasicMaterial({ color: facesColors[i] })
face = new THREE.Mesh(geometry, material)
allfaces.push(face)
scene.add(face)
}
const midPts = computeMidPts(outerPts)
const innerPts = computeInnerPts(midPts, d / 2)
const geometry = new THREE.Geometry()
geometry.vertices.push(...innerPts)
geometry.faces.push(new THREE.Face3(0, 1, 2))
const material = new THREE.MeshBasicMaterial({ color: facesColors[i] })
face = new THREE.Mesh(geometry, material)
allfaces.push(face)
scene.add(face)
}
let movingL = false
let movingLi = false
let movingR = false
let pivot = null
renderer.setAnimationLoop(() => {
if (movingL) {
pivot.rotation.z += 0.05
if (pivot.rotation.z >= (2 * Math.PI) / 3) {
movingL = false
}
} else if (movingLi) {
pivot.rotation.z -= 0.05
if (pivot.rotation.z <= -(2 * Math.PI) / 3) {
movingLi = false
}
} else if (movingR) {
pivot.rotation.x -= 0.05
if (pivot.rotation.x <= -(2 * Math.PI) / 3) {
movingR = false
}
}
renderer.render(scene, camera);
});
document.getElementById("L").addEventListener("click", function(){
pivot = new THREE.Group();
scene.add(pivot);
// faces to move
pivot.attach(allfaces[0]);
pivot.attach(allfaces[4]);
pivot.attach(allfaces[8]);
movingL = true
});
document.getElementById("Li").addEventListener("click", function(){
pivot = new THREE.Group();
scene.add(pivot);
pivot.attach(allfaces[0]);
pivot.attach(allfaces[4]);
pivot.attach(allfaces[8]);
movingLi = true
});
document.getElementById("R").addEventListener("click", function(){
pivot = new THREE.Group();
scene.add(pivot);
pivot.attach(allfaces[1]);
pivot.attach(allfaces[10]);
pivot.attach(allfaces[12]);
movingR = true
});
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div id="myid"></div>
<button id="L">L</button>
<button id="Li">Li</button>
<button id="R">R</button>
<button id="Ri">Ri</button>
...
您将必须使用Quaternions
,这是将旋转应用于对象的一种更强大的方法。
四元数有一种称为的方法.setFromAxisAngle()
,可用于设置所需的旋转轴。
在下面的示例中,每次单击按钮时,我都会设置旋转轴并使用以下方法重置旋转角度:
axisVector.set(x, y, z).normalize();
quatAngle = 0;
(归一化可确保轴总长度为1。使用轴向量(2, 0, 0)
会破坏旋转)
建立轴后,您可以使用
quatAngle += 0.05;
pivot.quaternion.setFromAxisAngle(axisVector, quatAngle);
我不确定旋转轴的位置是R
或U
,所以我只是在视觉上估计了(1, 0, -0.33)
和(-0.4, 0.7, -0.3)
,然后我.normalize()
将其长度设为1。
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100);
camera.position.set(-2, 1, 3);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight - 60); // -60 to see buttons below
const divid = document.getElementById('myid');
divid.appendChild(renderer.domElement);
// show axis
scene.add(new THREE.AxesHelper(2))
let controls = new THREE.OrbitControls(camera, renderer.domElement);
// one triangle equilateral
const sideLength = 1
const x = 0
const y = 0
const geometry = new THREE.Geometry()
geometry.vertices.push(new THREE.Vector3(x, (Math.sqrt(3) / 2 * sideLength) - (sideLength / 2), 0))
geometry.vertices.push(new THREE.Vector3(x - (sideLength / 2), y - (sideLength / 2), 0))
geometry.vertices.push(new THREE.Vector3(x + (sideLength / 2), y - (sideLength / 2), 0))
geometry.faces.push(new THREE.Face3(0, 1, 2))
const facesColors = [
0xFFFF00, // yellow
0xFF0000, // red
0x0000FF, // blue
0x008000 // green
]
const pos = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3
]
const d = 0.05 // écart entre les triangles
let face
const facesVectors = [
[0, 1, 2],
[0, 2, 3],
[0, 3, 1],
[1, 3, 2]
]
// https://stackoverflow.com/questions/60774560/drawing-a-pyraminx-with-triangles
// coords des points d'un tétrahèdre
const s89 = Math.sqrt(8 / 9)
const s29 = Math.sqrt(2 / 9)
const s23 = Math.sqrt(2 / 3)
const v = [
new THREE.Vector3(0, 0, 1),
new THREE.Vector3(s89, 0, -1 / 3),
new THREE.Vector3(-s29, s23, -1 / 3),
new THREE.Vector3(-s29, -s23, -1 / 3)
]
const computeMidPts = (pts) => {
const midPts = []
for (let i = 0; i < pts.length; ++i) {
midPts.push(new THREE.Vector3().lerpVectors(pts[i], pts[(i + 1) % 3], 0.5))
}
return midPts
}
const computeInnerPts = (pts, d) => {
const innerPts = []
for (let i = 0; i < pts.length; ++i) {
const va = new THREE.Vector3().lerpVectors(pts[i], pts[(i + 1) % 3], d)
const vb = new THREE.Vector3().lerpVectors(pts[i], pts[(i + 2) % 3], d)
innerPts.push(new THREE.Vector3().lerpVectors(va, vb, 0.5))
}
return innerPts
}
let allfaces = [];
for (let i = 0; i < 4; ++i) {
const pts = [v[facesVectors[i][0]], v[facesVectors[i][1]], v[facesVectors[i][2]]]
const outerPts = computeInnerPts(pts, d)
for (let j = 0; j < 3; ++j) {
const geometry = new THREE.Geometry()
geometry.vertices.push(outerPts[j])
geometry.vertices.push(new THREE.Vector3().lerpVectors(outerPts[j], outerPts[(j + 1) % 3], 0.5 - d / 2))
geometry.vertices.push(new THREE.Vector3().lerpVectors(outerPts[j], outerPts[(j + 2) % 3], 0.5 - d / 2))
geometry.faces.push(new THREE.Face3(0, 1, 2))
const material = new THREE.MeshBasicMaterial({ color: facesColors[i] })
face = new THREE.Mesh(geometry, material)
allfaces.push(face)
scene.add(face)
}
const midPts = computeMidPts(outerPts)
const innerPts = computeInnerPts(midPts, d / 2)
const geometry = new THREE.Geometry()
geometry.vertices.push(...innerPts)
geometry.faces.push(new THREE.Face3(0, 1, 2))
const material = new THREE.MeshBasicMaterial({ color: facesColors[i] })
face = new THREE.Mesh(geometry, material)
allfaces.push(face)
scene.add(face)
}
let movingL = false
let movingLi = false
let movingR = false
let movingU = false
let pivot = null
let quatAngle = 0;
let axisVector = new THREE.Vector3();
renderer.setAnimationLoop(() => {
if (movingL) {
quatAngle += 0.05
pivot.quaternion.setFromAxisAngle(axisVector, quatAngle);
if (quatAngle >= (2 * Math.PI) / 3) {
movingL = false
}
} else if (movingLi) {
quatAngle -= 0.05
pivot.quaternion.setFromAxisAngle(axisVector, quatAngle);
if (quatAngle <= -(2 * Math.PI) / 3) {
movingLi = false
}
} else if (movingR) {
quatAngle -= 0.05
pivot.quaternion.setFromAxisAngle(axisVector, quatAngle);
if (quatAngle <= -(2 * Math.PI) / 3) {
movingR = false
}
} else if (movingU) {
quatAngle -= 0.05
pivot.quaternion.setFromAxisAngle(axisVector, quatAngle);
if (quatAngle <= -(2 * Math.PI) / 3) {
movingU = false
}
}
renderer.render(scene, camera);
});
document.getElementById("L").addEventListener("click", function(){
pivot = new THREE.Group();
axisVector.set(0, 0, 1);
quatAngle = 0;
scene.add(pivot);
// faces to move
pivot.attach(allfaces[0]);
pivot.attach(allfaces[4]);
pivot.attach(allfaces[8]);
movingL = true
});
document.getElementById("Li").addEventListener("click", function(){
pivot = new THREE.Group();
axisVector.set(0, 0, 1);
quatAngle = 0;
scene.add(pivot);
pivot.attach(allfaces[0]);
pivot.attach(allfaces[4]);
pivot.attach(allfaces[8]);
movingLi = true
});
document.getElementById("R").addEventListener("click", function(){
pivot = new THREE.Group();
axisVector.set(1, 0, -0.33).normalize();
quatAngle = 0;
scene.add(pivot);
pivot.attach(allfaces[1]);
pivot.attach(allfaces[10]);
pivot.attach(allfaces[12]);
movingR = true
});
document.getElementById("U").addEventListener("click", function(){
pivot = new THREE.Group();
axisVector.set(-0.4, 0.7, -0.3).normalize();
quatAngle = 0;
scene.add(pivot);
pivot.attach(allfaces[2]);
pivot.attach(allfaces[5]);
pivot.attach(allfaces[14]);
movingU = true
});
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div id="myid"></div>
<button id="L">L</button>
<button id="Li">Li</button>
<button id="R">R</button>
<button id="U">U</button>
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句