Pregunta

Estoy haciendo algo como una aplicación de realidad aumentada, en la que tengo una escena de OpenGL que quiero mantenerme alineada con la gravedad sin importar cómo se mueva el dispositivo iOS. Pensé que lo había configurado bien con un cmdevicemotion.attitude.pitch, hasta que descubrí que inclinar un iPhone Sidewards se mete con ese número. Así que tomé algún código del ejemplo del parque* y ahora estoy tratando de aislar la rotación alrededor del acceso vertical. A la escena que estoy dibujando no le importa a qué encabezado se enfrenta al usuario, las cifras siempre se extraerán una distancia establecida del espectador. Creo que cuando descubro el componente de rotación del eje vertical, puedo revertirlo y multiplicarlo de la matriz de rotación, así que mantenga las figuras OpenGL quieto cuando el usuario cambie.

Aquí está mi código:

CMDeviceMotion *d = motionManager.deviceMotion;
if (d != nil) {

    CMRotationMatrix r = d.attitude.rotationMatrix;
    transformFromCMRotationMatrix(cameraTransform, &r);


    mat4f_t projectionCameraTransform;
    multiplyMatrixAndMatrix(projectionCameraTransform, projectionTransform, cameraTransform);

    GLKMatrix4 rotMatrix = GLKMatrix4Make(projectionCameraTransform[0], 
                                          projectionCameraTransform[1], 
                                          projectionCameraTransform[2], 
                                          projectionCameraTransform[3], 
                                          projectionCameraTransform[4], 
                                          projectionCameraTransform[5], 
                                          projectionCameraTransform[6], 
                                          projectionCameraTransform[7], 
                                          projectionCameraTransform[8], 
                                          projectionCameraTransform[9], 
                                          projectionCameraTransform[10], 
                                          projectionCameraTransform[11], 
                                          projectionCameraTransform[12], 
                                          projectionCameraTransform[13], 
                                          projectionCameraTransform[14], 
                                          projectionCameraTransform[15]);

    }

Luego uso la Rotmatrix como de costumbre en OpenGL.

¿Pensamientos, sugerencias? Gracias por adelantado.

*El código de muestra del parque establece algunos puntos en el espacio real, elabora la ubicación del usuario y la dirección relativa de esos puntos y los atrae en la pantalla para que parezcan flotar en el horizonte apuntando hacia su ubicación.

¿Fue útil?

Solución 3

He tomado algunas pistas de esta respuesta y presenta una solución:

https://stackoverflow.com/questions/5328848/simulating-an-image-floating-efect-using-coremotion-devicemotion-on-the-iphone/5442962#5442962

if (d != nil) {

    GLKMatrix4 rotMatrix = GLKMatrix4MakeRotation(0, 0, 1, 0);
    float pitch = d.attitude.pitch;

    if (d.gravity.z > 0)
        pitch = -pitch;

    rotMatrix = GLKMatrix4Rotate(rotMatrix, pitch, -1, 0, 0);
    rotMatrix = GLKMatrix4Rotate(rotMatrix, d.attitude.roll, 0, -1, 0);
    rotMatrix = GLKMatrix4Rotate(rotMatrix, d.attitude.yaw, 0, 0, -1);
    rotMatrix = GLKMatrix4Multiply(rotMatrix, GLKMatrix4MakeRotation(M_PI/2, 1, 0, 0));
}

Sin embargo, este Haywire cuando el teléfono está casi vertical. Así que sigo buscando.

Otros consejos

Simplemente gire la orientación alrededor del eje Z dependiendo de la orientación de la pantalla del dispositivo. Este no es lo más bonito, pero parece hacer exactamente lo que necesito, sin ir a Euler y de regreso (y por lo tanto, evitando los problemas de bloqueo de Gymbal)

GLKMatrix4 deviceMotionAttitudeMatrix;
if (_cmMotionmanager.deviceMotionActive) {
    CMDeviceMotion *deviceMotion = _cmMotionmanager.deviceMotion;

    // Correct for the rotation matrix not including the screen orientation:
    // TODO: Let the device notify me when the orientation changes instead of querying on each update.
    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
    float deviceOrientationRadians = 0.0f;
    if (orientation == UIDeviceOrientationLandscapeLeft) {
        deviceOrientationRadians = M_PI_2;
    }
    if (orientation == UIDeviceOrientationLandscapeRight) {
        deviceOrientationRadians = -M_PI_2;
    }
    if (orientation == UIDeviceOrientationPortraitUpsideDown) {
        deviceOrientationRadians = M_PI;
    }
    GLKMatrix4 baseRotation = GLKMatrix4MakeRotation(deviceOrientationRadians, 0.0f, 0.0f, 1.0f);

    CMRotationMatrix a = deviceMotion.attitude.rotationMatrix;
    deviceMotionAttitudeMatrix
        = GLKMatrix4Make(a.m11, a.m21, a.m31, 0.0f,
                         a.m12, a.m22, a.m32, 0.0f,
                         a.m13, a.m23, a.m33, 0.0f,
                         0.0f, 0.0f, 0.0f, 1.0f);
    deviceMotionAttitudeMatrix = GLKMatrix4Multiply(baseRotation, deviceMotionAttitudeMatrix);
}
else
{
    // Look straight forward (we're probably in the simulator, or a device without a gyro)
    deviceMotionAttitudeMatrix = GLKMatrix4MakeRotation(-M_PI_2, 1.0f, 0.0f, 0.0f);
}

Aquí hay algún código para aclarar cómo usar la actitud. RotationMatrix

// initial model view matrix
GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -5.f);

// convert CMRotationMatrix to GLKMatrix4
CMRotationMatrix r = motion.attitude.rotationMatrix;
GLKMatrix4 = GLKMatrix4Make(r.m11, r.m21, r.m31, 0.0f,
                            r.m12, r.m22, r.m32, 0.0f,
                            r.m13, r.m23, r.m33, 0.0f,
                             0.0f,  0.0f,  0.0f, 1.0f);

// apply motion rotation matrix
modelViewMatrix = GLKMatrix4Multiply(modelViewMatrix, _motionRotationMatrix);

// apply matrix to effect
self.effect.transform.modelviewMatrix = modelViewMatrix;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top