Поворот вокруг определенной точки в Java3D

У меня есть приложение, в котором все объекты сцены загружаются из .obj файлов (они экспортируются из Blender). И мне нужно повернуть один из этих объектов вокруг определенной точки. В настоящее время у меня есть следующий код:

public void rotateTo() {
    // translate to origin, rotate, translate back

    Vector3f origin = new Vector3f();
    Vector3f pivot = new Vector3f(.0f, .5f, .0f);

    this.getTransform(this.transform);
    this.transform.get(origin);

    double angle = -Math.PI / 2;
    double newX = origin.getX() + Math.cos(angle) * (pivot.getX() - origin.getX()) - Math.sin(angle) * (pivot.getY() - origin.getY());
    double newY = origin.getY() + Math.sin(angle) * (pivot.getX() - origin.getX()) + Math.cos(angle) * (pivot.getY() - origin.getY());

    this.transform.set(new Vector3f((float)newX, (float)newY, .0f), 0.15f);
    this.setTransform(this.transform);

    this.transform.set(origin, 0.15f);
    this.setTransform(this.transform);

}

Где this относится к TransformGroup объекту, который мне нужно повернуть, а this.transform относится к объекту Transform3D.

Но этот метод работает не так, как я ожидал. Я также пробовал this и это решения, но они также не сработали для меня.

Думаю, может, попробовать проделать эту манипуляцию с помощью GeometryArray, но не понимаю, как это сделать. Кроме того, я могу попытаться экспортировать свои объекты с разными исходными точками, но я думаю, что это не чистое решение, потому что тогда мне нужно было бы переместить их в правильные позиции с помощью кода.

Вот мой объект:

объект

Я пытаюсь повернуть его вокруг зеленой точки, но во всех случаях он вращается вокруг красной точки, или вообще не вращается, или переводится в какую-то точку без вращения.

P.S. Я знаю, что Java3D - старая библиотека и может использовать более мощные инструменты, но это требование профессора моего университета, и я не могу отказаться от ее использования.


person vanelizarov    schedule 29.10.2016    source источник


Ответы (1)


Композиция преобразований может быть достигнута с помощью умножения матриц. Ниже приведен пример поворота куба на 180 ° вокруг оси X с точкой поворота в центре его верхней грани.

Как упоминалось в вопросе, есть три шага: переместить так, чтобы точка поворота находилась в исходной точке, повернуть и переместить обратно. Прокомментируйте шаги, чтобы увидеть, что происходит.

  • Когда все шаги закомментированы, прямоугольник появляется в центре красной стороной вперед.

  • Раскомментируйте первый шаг. Коробка сдвигается вниз, так что ее верхняя часть оказывается в центре экрана.

  • Раскомментируйте второй шаг. Блок вращается вокруг оси X (ось влево-вправо через верхнюю часть блока). Зеленая сторона теперь обращена вперед, а нижняя часть поля теперь находится в центре экрана.

  • Раскомментируйте третий шаг. Коробка сдвигается вверх, и общий эффект заключается в том, что она вращается вокруг оси влево-вправо через его верхнюю грань.

Применение преобразования T к вектору v определяется как T * v в Java 3D, поэтому композиция двух преобразований T и U, где T должен быть выполнен первым, а U должен быть выполнен вторым, это U * T < / em>. Обратите внимание на обратный порядок. Как правило, сначала выполняется композиция преобразований T1, T2, ..., Tn, где T1 и Tn выполняется последним - Tn * ... * T2 * T1.

Это можно выразить в Java 3D с помощью следующего шаблона:

Transform3D t1 = ..., t2 = ..., t3 = ...;
// first do t1, then t2, then t3
Transform3D all = new Transform3D(); // all = identity
all.mul(t1, all); // all = t1 * all
all.mul(t2, all); // all = t2 * all
all.mul(t3, all); // all = t3 * all
// now all == t3 * t2 * t1

Такие методы, как Transform3D.set(Vector3d,double) и TransformGroup.setTransform(), перезаписывают существующее преобразование, а не сочетаются с ним, что является одной из причин, по которой ваш код не работает.

Я нашел статью http://www.developer.com/java/other/article.php/3717101/Understanding-Transforms-in-Java-3D.htm полезно.

// based on http://www.java3d.org/starting.html
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.SimpleUniverse;
import javax.media.j3d.*;
import javax.vecmath.*;

public class Demo
{
  public Demo() {
    SimpleUniverse universe = new SimpleUniverse();
    BranchGroup group = new BranchGroup();
    group.addChild(createModel());
    universe.getViewingPlatform().setNominalViewingTransform();
    universe.addBranchGraph(group);
  }

  Node createModel() {
    double radius = 0.3;
    ColorCube cube = new ColorCube(radius);
    // rotation of cube about the center of the top face
    // i.e. the point (x=0, y=radius, z=0)
    Transform3D transform = new Transform3D();
    // step 1: translate cube down so that (0, radius, 0) is at the origin
    Transform3D translate1 = new Transform3D();
    translate1.setTranslation(new Vector3d(0.0, -radius, 0.0));
    transform.mul(translate1, transform);
    // step 2: rotate cube about X axis by 180 degrees
    Transform3D rotate = new Transform3D();
    rotate.rotX(Math.PI);
    transform.mul(rotate, transform);
    // step 3: translate cube back up
    Transform3D translate2 = new Transform3D();
    translate2.setTranslation(new Vector3d(0.0, +radius, 0.0));
    transform.mul(translate2, transform);
    // create a TransformGroup
    TransformGroup tg = new TransformGroup();
    tg.setTransform(transform);
    tg.addChild(cube);
    return tg;
  }

  public static void main(String[] args) {
    new Demo();
  }
}
person tom    schedule 29.10.2016
comment
Теперь все ясно, спасибо большое! Я упустил, что set... методы переопределяют существующее преобразование. - person vanelizarov; 29.10.2016