diff --git a/examples/14_pose/assets/sample.png b/examples/14_pose/assets/sample.png new file mode 100644 index 0000000..9aa4f31 Binary files /dev/null and b/examples/14_pose/assets/sample.png differ diff --git a/examples/14_pose/main.qml b/examples/14_pose/main.qml index e4a9d26..180ad59 100644 --- a/examples/14_pose/main.qml +++ b/examples/14_pose/main.qml @@ -9,6 +9,7 @@ import QtQuick.Window 2.2 import QtQuick 2.6 +import Qt3D.Core 2.0 import ch.epfl.chili.qmlar 1.0 /** @brief This project renders a cube at (0, 0, 0) using qml-ar. @@ -28,16 +29,123 @@ Window { // setting width width: 500 + + init_type: AR.INIT_IMAGE } // showing a text in the middle with matrix components Text { anchors.centerIn: parent font.pixelSize: 30 - text: pretty_print_matrix4(arComponent.mvp_matrix) + text: pretty_print_matrix4(get_mv(arComponent.mvp_matrix)) + pretty_print_transform() color: "red" } + function get_camera_matrix() { + // Get the calibrated camera matrix. + // TODO: read the asset instead of using the hardcoded matrix + + var C = [ + 7.3321993364036177e+02, 0., 2.9429448615773646e+02, + 0., 7.3321993364036177e+02, 6.8074088355361582e+01, + 0., 0., 1. + ]; + + return C; + } + + function get_projection_matrix_manual(H, W) { + var Hcalib = 480; + var Wcalib = 640; + var n = 1; + var f = 10000; + + // Get the projection matrix manually. + + // translate (-1, 1, 0) + var translate_m1 = Qt.matrix4x4(1, 0, 0, -1, + 0, 1, 0, 1, + 0, 0, 1, 0, + 0, 0, 0, 1); + + var scaler = Qt.matrix4x4(2. / W, 0, 0, 0, + 0, -2. / H, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1) + + var C = get_camera_matrix(); + + var project = Qt.matrix4x4( + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0); + + project.m11 = C[0]; + project.m12 = C[1]; + project.m13 = C[2]; + + project.m21 = C[3]; + project.m22 = C[4]; + project.m23 = C[5]; + + project.m31 = C[6]; + project.m32 = C[7]; + project.m33 = C[8]; + + project.m33 = 0; + project.m43 = 1; + + project.m33 = (f + n) / (f - n); + project.m34 = -2 * n * f / (f - n); + + return translate_m1.times(scaler.times(project)); + } + + function get_mv(mvp) { + var p = get_projection_matrix_manual(arComponent.height, arComponent.width); + var mv = p.inverted().times(mvp); + return mv; + } + + Matrix4x4 { + id: mv_transform + matrix: get_mv() + } + + // print the transform as rotation and translation + function pretty_print_transform() { + var res = ""; + + console.log(mv_transform.rotationX) + + var mv = get_mv(arComponent.mvp_matrix); + + // translation + var t = Qt.vector3d(mv.m14, mv.m24, mv.m34); + + res += "x=" + Math.round(t.x * 1) / 1 + '\t'; + res += "y=" + Math.round(t.y * 1) / 1 + '\t'; + res += "tz=" + Math.round(t.z * 1) / 1 + '\t'; + res += '\n'; + + + // adapted from https://stackoverflow.com/questions/54616049/converting-a-rotation-matrix-to-euler-angles-and-back-special-case + var beta = -Math.asin(mv.m31); + var alpha = Math.atan2(mv.m32 / Math.cos(beta), mv.m33 / Math.cos(beta)); + var gamma = Math.atan2(mv.m21 / Math.cos(beta), mv.m11 / Math.cos(beta)); + + beta = beta * 180 / Math.PI; + alpha = alpha * 180 / Math.PI; + gamma = gamma * 180 / Math.PI; + + res += 'b=' + Math.round(beta * 1) / 1 + '\t'; + res += 'a=' + Math.round(alpha * 1) / 1 + '\t'; + res += 'g=' + Math.round(gamma * 1) / 1 + '\t'; + + return res; + } + /** Print matrix 4x4 in a nice way */ function pretty_print_matrix4(mat) { var res = ""; diff --git a/examples/14_pose/qml.qrc b/examples/14_pose/qml.qrc index b05633c..72d1113 100644 --- a/examples/14_pose/qml.qrc +++ b/examples/14_pose/qml.qrc @@ -4,5 +4,6 @@ Activity.qml assets/markers.json assets/camera_matrix.json + assets/sample.png