Математическое моделирование эффекта Джанибекова
Здравствуйте! Захотел решить задачу об эффекте Джанибекова с визуализацией в 3D на javasrypt с помощью библиотеки Three.js. Решал дифференциальные уравнения Эйлера, итого некоторые потуги на поворот в 180 градусов присутствуют, однако что-то идет не так. Прошу помочь с проблемой. Код на html + js прилагаю
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
// Сцена и камера
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 15;
camera.position.y = 15;
camera.position.z = 25;
const renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setClearColor(0xffffff, 1);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//Оси координат
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
// Прямоугольник
var den = 1
var posx = 8
var posy = 1
var posz = 3
var m = posx * posy * posz * den
var Ix = m * (posy * posy + posz * posz)/12
var Iy = m * (posx * posx + posz * posz)/12
var Iz = m * (posy * posy + posx * posx)/12
const material = new THREE.MeshStandardMaterial({ color: 0x00aaff, roughness: 0.5, metalness: 0.5 });
material.shadowSide = THREE.DoubleSide;
const geometry = new THREE.BoxGeometry(posx, posy, posz);
const rectangle = new THREE.Mesh(geometry, material);
scene.add(rectangle);
//Плоскость
const planeGeometry = new THREE.PlaneGeometry(window.innerWidth, window.innerHeight);
const planeMaterial = new THREE.MeshStandardMaterial({ color: 0xbebebe });
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -Math.PI / 2;
plane.position.y = -20
scene.add(plane);
//свет
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(0, 10, 0);
directionalLight.castShadow = true;
scene.add(directionalLight);
renderer.shadowMap.enabled = true;
rectangle.castShadow = true;
plane.receiveShadow = true;
// камера
const controls = new THREE.OrbitControls(camera, renderer.domElement);
//движение (вокруг красной оси z )
var time = 10000
var dt = 0.001
var phinewx
var phinewy
var phinewz
var omeganewx
var omeganewy
var omeganewz
var phioldx = 0
var phioldy = 0
var phioldz = 0
var omegaoldx = 0.00000001 * 2 * Math.PI
var omegaoldy = 0.00000001 * 2 * Math.PI
var omegaoldz = 1 * 2 * Math.PI
var X = [0]
var Y = [0]
var Z = [0]
for (var i = 1; i<time; i++){
omeganewx = omegaoldx + (Iy - Iz)/Ix * omegaoldy * omegaoldz * dt
omeganewy = omegaoldy + (Iz - Ix)/Iy * omegaoldx * omegaoldz * dt
omeganewz = omegaoldz + (Ix - Iy)/Iz * omegaoldx * omegaoldy * dt
phinewx = phioldx + omeganewx * dt
phinewy = phioldy + omeganewy * dt
phinewz = phioldz + omeganewz * dt
omegaoldx = omeganewx
omegaoldy = omeganewy
omegaoldz = omeganewz
phioldx = phinewx
phioldy = phinewy
phioldz = phinewz
X[i] = phinewx
Y[i] = phinewy
Z[i] = phinewz
}
i = 1
function animate() {
rectangle.rotation.x = X[i]
rectangle.rotation.y = Y[i]
rectangle.rotation.z = Z[i]
if (i<time-1){
i++
axesHelper.rotation.copy(rectangle.rotation);
}
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
код на html
По дате
По рейтингу
Попробуй уменьшить разницу между Ix, Iy, Iz. Пусть даже оставить posx, posy, posz прежними; а скорректировать формулы для I (сделать материал неоднородным)
Кто то бесплатно возиться будет. Ага,жди...