2016-10-29 3 views
1

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

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 и this, но они также не работали для меня.

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

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

object

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

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

ответ

1

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

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

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

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

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

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

Применение преобразования T к вектору v определяется как T * V в Java 3D, так что композиция двух преобразований Т и U, где Т должен быть сделан первым, и U должно быть сделано вторым является U * T. Обратите внимание, как порядок отменяется.В целом, композиция преобразований T1, Т2, ..., Тп, где Т1 выполняется первым и Тп делается последнее Тп * ... * Т2 * Т1.

Это может быть выражено в 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(); 
    } 
} 
+0

Теперь все ясно, спасибо большое! Я пропустил, что методы 'set ...' переопределяют существующее преобразование. – vanelizarov