Пара тапок » three.js http://paratapok.ru Блог о веб-разработке Sun, 18 Dec 2022 12:14:48 +0000 ru-RU hourly 1 https://wordpress.org/?v=4.3.34 Поворот объектов вокруг глобальных и локальных осей в Three.js http://paratapok.ru/frontend/2588_povorot-obektov-vokrug-globalnyx-i-lokalnyx-osej-vo-three-js/ http://paratapok.ru/frontend/2588_povorot-obektov-vokrug-globalnyx-i-lokalnyx-osej-vo-three-js/#comments Sun, 24 Apr 2016 15:45:08 +0000 http://paratapok.ru/?p=2588 Читать далее →]]> Практически любое приложение на Three.js не обходится без необходимости повернуть тот или иной объект на произвольный угол вокруг собственной оси, либо вокруг глобальных осей сцены.

Первая задача — вращение объекта вокруг локальных осей координат — решается достаточно просто. В большинстве случает у объекта доступно свойство rotation, которое имеет три компоненты x, y и z, каждая из которых отвечает за вращение вокруг соответствующей оси, проходящей через центр объекта.

Например, поворот объекта вокруг оси Y на 180 градусов будет выглядеть следующим образом:

object.rotation.y = Math.PI;

То же самое можно выполнить, воспользовавшись функцией поворота, основанной на использовании матрицы преобразований:

var rotateAroundObjectAxis = function(object, axis, radians) {
    rotObjectMatrix = new THREE.Matrix4();
    rotObjectMatrix.makeRotationAxis(axis.normalize(), radians);                
    object.matrix.multiply(rotObjectMatrix);
    object.rotation.setFromRotationMatrix(object.matrix);
}
...
rotateAroundObjectAxis(object, new THREE.Vector3(0,1,0), Math.PI/4);

Вторая задача — поворот объекта вокруг глобальных осей координат — решается уже в два шага. В функции представленной ниже, сначала всё так же производится вращение самого объекта, а затем присвоение ему новых координат.

var rotateAroundWorldAxis = function(object, axis, radians) {
    var rotWorldMatrix = new THREE.Matrix4();
    rotWorldMatrix.makeRotationAxis(axis.normalize(), radians);

    var currentPos = new THREE.Vector4(object.position.x, object.position.y, object.position.z, 1);
    var newPos = currentPos.applyMatrix4(rotWorldMatrix);

    rotWorldMatrix.multiply(object.matrix);
    object.matrix = rotWorldMatrix;
    object.rotation.setFromRotationMatrix(object.matrix);

    object.position.x = newPos.x;
    object.position.y = newPos.y;
    object.position.z = newPos.z;
};
...
rotateAroundWorldAxis(object, new THREE.Vector3(0,1,0), Math.PI/4);

Как видите, повернуть объект во Three.js не такая уж и сложная задача. Использование обеих функций наглядно продемонстрировано в приведенном ниже примере.

]]>
http://paratapok.ru/frontend/2588_povorot-obektov-vokrug-globalnyx-i-lokalnyx-osej-vo-three-js/feed/ 0
Почему возникают артефакты при рендере сцены в Three.js? http://paratapok.ru/frontend/2578_three-js-artefakty-i-glubina-z-bufera-pri-rendere-sceny/ http://paratapok.ru/frontend/2578_three-js-artefakty-i-glubina-z-bufera-pri-rendere-sceny/#comments Sun, 10 Apr 2016 06:42:34 +0000 http://paratapok.ru/?p=2578 Читать далее →]]> Если при работе с Three.js вы столкнулись с различного рода артефактами, например, отображением частей объектов, которых видно быть не должно, появлением произвольных черных пятен или исчезанием/обрезанием частей объектов и т.д., то предлагаем несколько советов, как решить данную проблему.

Пример артефактов: появление частей объектов с заднего плана

Пример артефактов: появление частей объектов с заднего плана. Кликните для просмотра анимации

Причины появления артефактов могут быть разные, наиболее частые из них следующие:

1. Максимальное расстояние, которое рендерит камера меньше, чем расположение некоторых объектов. В этом случае объекты или их части просто напросто будут обрезаться и возможно периодически появляться и исчезать.

Например, при инициализации камеры был указан параметр far = 1000, а объект или какая-либо его часть находится за заданными пределами.

camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.001, 1000 );
...
obj = new THREE.Mesh( new THREE.BoxGeometry( 250, 250, 250 ), new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) );
obj.position.x = 900;
obj.position.y = 900;
obj.position.z = 900;

Проблема проиллюстрирована на картинках, представленных ниже.

Неверно задан параметр камеры far

Неверно задан параметр камеры far

2. Объекты находятся далеко от камеры, но относительно близко к друг к другу. В таком случае некоторые части объекта, расположенного на заднем плане могут в некоторые моменты времени оказаться спереди и наложиться на другой объект.

Артефакт: наложение кубов друг на друга

Артефакт: наложение кубов друг на друга

Наглядный пример такой проблемы и ее решение представлены в одном из примеров, опубликованных в разделе примеров на официальном сайте Three.js.

Проблема объясняется точностью буфера глубины — depth buffer, которой не хватает в данной ситуации. Общий эффект представляет собой попеременное отображение частей то одного объекта, то другого — происходит своеобразная «борьба» за пиксели. Устраняются такие артефакты путем увеличения глубины z-buffer.

Стандартное создание рендерера выглядит так:

renderer = new THREE.WebGLRenderer();

Чтобы увеличить точность следует указать при инициализации свойство logarithmicDepthBuffer со значением true:

renderer = new THREE.WebGLRenderer({ antialias: true, logarithmicDepthBuffer: true });

Однако следует отметить, что при этом снижается производительность рендера сцены, и потому не всегда такое решение может быть пригодным. Поэтому такие артефакты теоретически могут быть отчасти решены следующими методами:

  1. более удаленное размещение объектов между друг другом;
  2. если все объекты находятся в рамках единого диапазона координат, то как вариант попробовать уменьшить модель в несколько раз, переведя координаты объектов, например, из тысяч в десятки.
]]>
http://paratapok.ru/frontend/2578_three-js-artefakty-i-glubina-z-bufera-pri-rendere-sceny/feed/ 0
Как получить размеры 3d-объекта с произвольным набором mesh-ей в Three.js? http://paratapok.ru/frontend/2568_kak-poluchit-razmery-3d-obekta-s-proizvolnym-naborom-mesh-ej-v-three-js/ http://paratapok.ru/frontend/2568_kak-poluchit-razmery-3d-obekta-s-proizvolnym-naborom-mesh-ej-v-three-js/#comments Thu, 31 Mar 2016 20:24:22 +0000 http://paratapok.ru/?p=2568 Читать далее →]]> При разработке приложений на Three.js зачастую возникает ситуация, когда на сцену помещается 3d object с набором потомков. Особенностью 3d-объекта является то, что у него отсутствует свойство геометрии с методом computeBoundingBox(), который позволяет получить границы параллелепипеда (координаты max и min), в которые заключен объект. Тех, кто только начинает работать с Three.js, может заинтересовать вопрос, каким образом вычислить размеры такого объекта?

Есть простой способ. Для этого следует всего лишь создать объект с помощью конструктора THREE.Box3() и воспользоваться методом setFromObject(), в который передать наш 3d-объект, напичканный разнообразными мешами. Теперь у нас есть граничные координаты max и min, соответственно вычисление размеров уже дело арифметики.

var getBoundaryGeometry = function(obj) {
    var modelBoundingBox;

    modelBoundingBox = new THREE.Box3().setFromObject(obj);
    modelBoundingBox.size = {};
    modelBoundingBox.size.x = modelBoundingBox.max.x - modelBoundingBox.min.x;
    modelBoundingBox.size.y = modelBoundingBox.max.y - modelBoundingBox.min.y;
    modelBoundingBox.size.z = modelBoundingBox.max.z - modelBoundingBox.min.z;

    return modelBoundingBox;
};

Как видите данный способ занимает всего пару строк. Хотя справедливости ради следует заметить, что можно и вручную сделать все те же самые действия, перебрав в цикле всех потомков 3d-объекта. При этом необходимо последовательно вызывать метод computeBoundingBox() свойства geometry каждого потомка и сравнением вычислять наиболее отдаленные вершины max и min.

В приведенном ниже примере на сцену добавлен 3d-объект с 10 рандомно спозиционированными кубами. При инициализации вычисляются размеры объекта, которые пишутся в блок в правом верхнем углу. При этом также происходит вращение вокруг оси y, поэтому размеры параллелепипеда, расположенного вдоль координатных осей и включающего в себя все кубы, изменяются. С помощью кнопки «Обновить» можно обновить размеры.

]]>
http://paratapok.ru/frontend/2568_kak-poluchit-razmery-3d-obekta-s-proizvolnym-naborom-mesh-ej-v-three-js/feed/ 0