Pergunta

Eu tenho um Cone eu desenhei em Java 3D com o seguinte código:

Cone cone = new Cone(2f, 3f);

Transform3D t3d = new Transform3D();
TransformGroup coneTransform = new TransformGroup(t3d);
coneTransform.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

t3d.setTranslation(new Vector3f(0f,0f,0f);
coneTransform.setTransform(t3d);
coneTransform.addChild(cone);

this.addChild(coneTransform);

Suponha que eu tenho o cone sentado no ponto (1,1,1) e eu quero a ponta do cone para apontar para baixo uma linha imaginária que atravessa (0,0,0) e (1,1,1). .. como eu posso fazer isso?

Aqui está um exemplo do que eu tenho tentado:

Transform3D t3d = new Transform3D();  

Vector3f direction = new Vector3f(1,2,1);    

final double angleX = direction.angle(new Vector3f(1,0,0));
final double angleY = direction.angle(new Vector3f(0,1,0));
final double angleZ = direction.angle(new Vector3f(0,0,1));

t3d.rotX(angleX);
t3d.rotY(angleY);
t3d.rotZ(angleZ);

t3d.setTranslation(direction);

coneTransform.setTransform(t3d);

Agradecemos antecipadamente por toda a ajuda!

Foi útil?

Solução 3

Eu finalmente descobri o que eu queria fazer usando Quaternions, o que eu aprendi sobre aqui: http://www.cs.uic.edu/~jbell/Courses/Eng591_F1999/outline_2.html Aqui está a minha solução.

Criando o cone:

 private void attachCone(float size) {
        Cone cone = new Cone(size, size* 2);

        // The group for rotation
        arrowheadRotationGroup = new TransformGroup();
        arrowheadRotationGroup.
             setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        arrowheadRotationGroup.addChild(cone);

        // The group for positioning the cone
        arrowheadPositionGroup = new TransformGroup();
        arrowheadPositionGroup. 
              setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        arrowheadPositionGroup.addChild(arrowheadRotationGroup);

        super.addChild(arrowheadPositionGroup);
    }

Agora, quando eu quero rodar o cone de ponto em uma determinada direção especificada como o vetor do ponto (0,0,0) a (direction.x, direction.y, direction.z), eu uso:

private final Vector3f yAxis = new Vector3f(0f, 1f, 0f);
private Vector3f direction; 

private void rotateCone() {
        // Get the normalized axis perpendicular to the direction 
        Vector3f axis = new Vector3f();
        axis.cross(yAxis, direction);
        axis.normalize();

        // When the intended direction is a point on the yAxis, rotate on x
        if (Float.isNaN(axis.x) && Float.isNaN(axis.y) && Float.isNaN(axis.z)) 
        {
            axis.x = 1f;
            axis.y = 0f;
            axis.z = 0f;
        }
        // Compute the quaternion transformations
        final float angleX = yAxis.angle(direction);
        final float a = axis.x * (float) Math.sin(angleX / 2f);
        final float b = axis.y * (float) Math.sin(angleX / 2f);
        final float c = axis.z * (float) Math.sin(angleX / 2f);
        final float d = (float) Math.cos(angleX / 2f);

        Transform3D t3d = new Transform3D();
        Quat4f quat = new Quat4f(a, b, c, d);
        t3d.set(quat);
        arrowheadRotationGroup.setTransform(t3d);

        Transform3D translateToTarget = new Transform3D();
        translateToTarget.setTranslation(this.direction);
        arrowheadPositionGroup.setTransform(translateToTarget);
    }

Outras dicas

Eu estou aprendendo Java 3D mim no momento, e do meu conhecimento atual, os métodos de rotação definir a transformar a uma rotação em torno deste eixo somente. Portanto, se você deseja realizar rotações em torno de vários eixos, então você vai precisar usar um segundo Transform3D.
ou seja:

Transform3D rotation = new Transform3D();
Transform3D temp = new Transform3D();

rotation.rotX(Math.PI/2);
temp.rotZ(Math.PI/2);
rotation.mul(temp); // multiply the 2 transformation matrices together.

Quanto à razão para Math.PI, isso é porque ele utiliza radianos em vez de graus, onde Math.PI é equivalente a 180 graus.

Encontrar o ângulo entre sua orientação atual e sua orientação pretendida não é muito difícil - você poderia usar Vector3fs, com o método do ângulo (). Um vector seria criado com a orientação inicial, e uma outra no que se destina. No entanto, isso não lhe diz em que os eixos das mentiras ângulo. Isso exigiria análise dos vetores para ver quais segmentos estão definidos. [É claro, pode haver algo que eu estou atualmente desconhece na API]

Esta não é uma resposta específica JAVA3D.

De um modo geral uma matriz pode ser construída de tal modo que existem 4 vectores que o descrevem.

1) Um lado (ou lateral) vector
2) Um vetor
3) Um vector de direcção
4) A posição de um

Cada linha de uma matriz 4x4.

Assim, para uma matriz de identidade simples, temos a seguinte matriz (vou definir uma grande matriz de coluna, para uma grande matriz de linha tudo o que você precisa fazer é trocar os índices de matriz em torno de tal forma que a linha 2 col 3 torna-se linha 3 col 2 em toda a matriz).

1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

nesta primeira coluna é o vector de lado. A segunda coluna o vector acima. A terceira direcção e a quarta posição.

Logicamente, podemos ver que o vector de (1, 0, 0, 0) pontos ao longo do eixo x (e, portanto, é o vector de lado). O vector de (0, 1, 0, 0) pontos ao longo do eixo y (e, portanto, é o vector acima). O terceiro (0, 0, 1, 0) pontos ao longo do eixo Z (e, portanto, é o vector de direcção). A quarta (0, 0, 0, 1) indica que os objectos não se move de todo.

Agora, vamos dizer que queríamos rosto ao longo do eixo-X.

Obviamente, isso significaria que temos um vector de (1, 0, 0, 0) para o nosso vetor de direção. -Se ainda seria (0, 1, 0, 0) e posição ainda 0, 0, 0 1. Então, o que seria o nosso vector lado ser? Bem, logicamente seria apontar ao longo do eixo z. Mas de que maneira? Bem segurar os dedos de tal forma que um dedo aponta para a frente, um para o lado e uma para cima. Agora gire de modo que o dedo para a frente está virada na mesma direcção que o dedo lado apontador. Que maneira é o lado Apontando o dedo Apontando agora? A direção oposta ao dedo originais direção apontador. Assim, a matriz é

 0 0 1 0
 0 1 0 0
-1 0 0 0
 0 0 0 1

Neste ponto coisas aparentemente se um pouco mais complicado. É bastante simples de tomar uma posição arbitrária e um ponto arbitrário olhada (vou chamá-los vPos e vFocus). É bastante fácil para formar um vector de vPos para vFocus subtraindo vPos de vFocus (vFocus.x - vPos.x, vFocus.y - vPos.y, vFocus.z - vPos.z, vFocus.w - vPos.w) . Tenha em mente todas as posições devem ser definidos com um '1' na posição w, onde todas as direções deve ter um '0'. Esta é tirada automaticamente cuidado de quando você faz a subtração acima como 1 em ambos os ws vai anular e deixar 0. De qualquer forma, agora temos um vetor apontando a partir da posição em direção vFocus vamos chamá-lo VDIR. Infelizmente, tem o comprimento da diferença entre vPos e vFocus. No entanto, se dividirmos o vetor VDIR pelo seu comprimento (vDir.x / comprimento, vDir.y / comprimento, vDir.z / comprimento, vDir.w / comprimento) então nós normalize isso e temos um o sentido com um comprimento total de 1.

Neste ponit agora temos a nossa 3ª e 4ª colunas de nossa matriz. Agora, vamos assuem up ainda é (0, 1, 0, 0) ou VUP. Podemos assumir que o CrossProduct da direcção e VUP irá produzir um vector que é perpendicular (e também da unidade de comprimento) para o plano formado pela VDIR e VUP. Isso nos dá o nosso vector lado ou VLAT. Agora .. fizemos tipo de assumir o vector de modo que não é estritamente correto. Agora podemos calcular exatamente tomando o produto cruzado de VLAT e VDIR e temos todos os 4 vetores.

A matriz final é, assim, definida como se segue

vLat.x vUp.x vDir.x vPos.x
vLat.y vUp.y vDir.y vPos.y
vLat.z vUp.z vDir.z vPos.z
vLat.w vUp.w vDir.w vPos.w

Isto não é estritamente a resposta completa como você vai ter problemas como você olhar para um ponto perto de sua (0, 1, 0, 0) vector mas que deve trabalhar para a maioria casos.

Eu acho que isso deve fazê-lo:

coneTransform.rotX(Math.PI / 4);
coneTransform.rotY(Math.PI / 4);

Você pode dar o seu Transform3D uma matriz de rotação. você pode obter uma matriz de rotação usando a calculadora matriz de rotação on-line: http://toolserver.org/~dschwen /tools/rotationmatrix.html aqui está o meu exemplo:

    Matrix3f mat = new Matrix3f(0.492403876506104f, 0.586824088833465f,
            -0.642787609686539f, 0.413175911166535f, 0.492403876506104f,
            0.766044443118978f, 0.766044443118978f, -0.642787609686539f, 0f);

    Transform3D trans = new Transform3D();

    trans.set(mat);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top