├── .idea
├── .name
├── copyright
│ └── profiles_settings.xml
├── dictionaries
│ └── matthieu.xml
├── scopes
│ └── scope_settings.xml
├── encodings.xml
├── vcs.xml
├── libraries
│ ├── android_support_v4.xml
│ └── tango_native_service_client_helperlib1.xml
├── modules.xml
├── compiler.xml
└── misc.xml
├── TangoUtils
├── ic_launcher-web.png
├── libs
│ └── android-support-v4.jar
├── res
│ ├── drawable-hdpi
│ │ └── ic_launcher.png
│ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ │ └── ic_launcher.png
│ ├── values
│ │ ├── strings.xml
│ │ └── styles.xml
│ ├── values-v11
│ │ └── styles.xml
│ └── values-v14
│ │ └── styles.xml
├── .settings
│ └── org.eclipse.jdt.core.prefs
├── .classpath
├── project.properties
├── proguard-project.txt
├── .project
├── TangoUtils.iml
├── AndroidManifest.xml
└── src
│ └── com
│ └── kitware
│ └── tangoutils
│ ├── renderables
│ ├── RenderUtils.java
│ ├── Renderable.java
│ ├── Grid.java
│ ├── PointCloud.java
│ ├── CameraFrustum.java
│ ├── CameraFrustumAndAxis.java
│ └── Trajectory.java
│ ├── ModelMatCalculator.java
│ └── Renderer.java
├── ParaViewTangoRecorder
├── ic_launcher-web.png
├── res
│ ├── drawable-xxhdpi
│ │ ├── paraview.png
│ │ └── ic_launcher.png
│ ├── xml
│ │ └── filepaths.xml
│ ├── values
│ │ ├── dimens.xml
│ │ ├── styles.xml
│ │ └── strings.xml
│ ├── values-v11
│ │ └── styles.xml
│ ├── values-w820dp
│ │ └── dimens.xml
│ ├── values-v14
│ │ └── styles.xml
│ └── layout
│ │ └── activity_jpoint_cloud.xml
├── libs
│ └── tango_native_service_client_helperlib.jar
├── .settings
│ └── org.eclipse.jdt.core.prefs
├── .classpath
├── project.properties
├── .project
├── src
│ └── com
│ │ └── kitware
│ │ └── tangoproject
│ │ └── paraviewtangorecorder
│ │ ├── package-info.java
│ │ ├── ZipWriter.java
│ │ ├── PCRenderer.java
│ │ └── PointCloudActivity.java
├── ParaViewTangoRecorder.iml
└── AndroidManifest.xml
├── ParaViewPlugins
├── make.sh
├── AccumulatePointClouds.py
├── QuaternionToOrientationFrame.py
├── ApplyPoseTransformToPointCloud.py
└── python_filter_generator.py
├── .gitignore
├── README.md
└── LICENSE
/.idea/.name:
--------------------------------------------------------------------------------
1 | kitware-tango-demo
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/dictionaries/matthieu.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/TangoUtils/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kitware/ParaViewTangoRecorder/HEAD/TangoUtils/ic_launcher-web.png
--------------------------------------------------------------------------------
/TangoUtils/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kitware/ParaViewTangoRecorder/HEAD/TangoUtils/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kitware/ParaViewTangoRecorder/HEAD/ParaViewTangoRecorder/ic_launcher-web.png
--------------------------------------------------------------------------------
/TangoUtils/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kitware/ParaViewTangoRecorder/HEAD/TangoUtils/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/TangoUtils/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kitware/ParaViewTangoRecorder/HEAD/TangoUtils/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/TangoUtils/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kitware/ParaViewTangoRecorder/HEAD/TangoUtils/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/TangoUtils/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kitware/ParaViewTangoRecorder/HEAD/TangoUtils/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/res/drawable-xxhdpi/paraview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kitware/ParaViewTangoRecorder/HEAD/ParaViewTangoRecorder/res/drawable-xxhdpi/paraview.png
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kitware/ParaViewTangoRecorder/HEAD/ParaViewTangoRecorder/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/.idea/scopes/scope_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/res/xml/filepaths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/libs/tango_native_service_client_helperlib.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kitware/ParaViewTangoRecorder/HEAD/ParaViewTangoRecorder/libs/tango_native_service_client_helperlib.jar
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/TangoUtils/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
3 | org.eclipse.jdt.core.compiler.compliance=1.6
4 | org.eclipse.jdt.core.compiler.source=1.6
5 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
3 | org.eclipse.jdt.core.compiler.compliance=1.6
4 | org.eclipse.jdt.core.compiler.source=1.6
5 |
--------------------------------------------------------------------------------
/.idea/libraries/android_support_v4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ParaViewPlugins/make.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | python python_filter_generator.py ApplyPoseTransformToPointCloud.py ApplyPoseTransformToPointCloud.xml
4 | python python_filter_generator.py QuaternionToOrientationFrame.py QuaternionToOrientationFrame.xml
5 | python python_filter_generator.py AccumulatePointClouds.py AccumulatePointClouds.xml
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Proguard folder generated by Eclipse
16 | proguard/
17 |
18 | # Log Files
19 | *.log
20 |
21 | # IntelliJ files
22 | .idea/workspace.xml
23 |
--------------------------------------------------------------------------------
/.idea/libraries/tango_native_service_client_helperlib1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Kitware Demo application for Google Tango project
2 | =================================================
3 |
4 | For more information on how to use this app please see our blog post describing loading data from the Project Tango development kit into ParaView: http://kitware.com/blog/home/post/838
5 |
6 | Acknowledgements
7 | ----------------
8 |
9 | This project is based on the PointCloudJava sample, from the Google Tango API.
10 | You can find it at http://github.com/googlesamples/tango-examples-java
11 |
--------------------------------------------------------------------------------
/TangoUtils/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/TangoUtils/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-19
15 | android.library=true
16 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-19
15 | android.library.reference.1=../TangoUtils
16 |
--------------------------------------------------------------------------------
/TangoUtils/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | TangoUtils
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/TangoUtils/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | Abstraction issues
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 | 16dp
20 | 16dp
21 |
22 |
23 |
--------------------------------------------------------------------------------
/TangoUtils/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | TangoUtils
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/TangoUtils/TangoUtils.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | file:///usr/lib/jvm/jdk1.7.0_67/tools/proguard/proguard-android.txt
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | PointCloudJava
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/src/com/kitware/tangoproject/paraviewtangorecorder/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | /**
17 | * A sample application to show hwo to get Point Cloud Data from Project Tango API
18 | * and display in world coordinates of Opengl ES2.0.
19 | */
20 | package com.kitware.tangoproject.paraviewtangorecorder;
21 |
--------------------------------------------------------------------------------
/TangoUtils/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
22 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
22 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
23 | 64dp
24 |
25 |
26 |
--------------------------------------------------------------------------------
/TangoUtils/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
23 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
23 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/TangoUtils/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
16 |
20 |
21 |
24 |
25 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/ParaViewTangoRecorder.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | file:///usr/lib/jvm/jdk1.7.0_67/tools/proguard/proguard-android.txt
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/TangoUtils/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
22 |
29 |
30 |
31 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
22 |
29 |
30 |
31 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/TangoUtils/src/com/kitware/tangoutils/renderables/RenderUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.kitware.tangoutils.renderables;
18 |
19 | import android.opengl.GLES20;
20 |
21 | /**
22 | * Static functions used by Renderer classes in Tango Java samples.
23 | */
24 | public class RenderUtils {
25 |
26 | /**
27 | * Creates a vertex or fragment shader.
28 | *
29 | * @param type
30 | * one of GLES20.GL_VERTEX_SHADER or GLES20.GL_FRAGMENT_SHADER
31 | * @param shaderCode
32 | * GLSL code for the shader as a String
33 | * @return a compiled shader.
34 | */
35 | public static int loadShader(int type, String shaderCode) {
36 | // Create a shader of the correct type
37 | int shader = GLES20.glCreateShader(type);
38 |
39 | // Compile the shader from source code
40 | GLES20.glShaderSource(shader, shaderCode);
41 | GLES20.glCompileShader(shader);
42 |
43 | return shader;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/TangoUtils/src/com/kitware/tangoutils/renderables/Renderable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.kitware.tangoutils.renderables;
18 |
19 | import android.opengl.Matrix;
20 |
21 | /**
22 | * Base class for all self-drawing OpenGL objects used in Tango Java examples.
23 | * Contains common logic for handling the MVP matrices.
24 | */
25 | public abstract class Renderable {
26 |
27 | private float[] mModelMatrix = new float[16];
28 | private float[] mMvMatrix = new float[16];
29 | private float[] mMvpMatrix = new float[16];
30 |
31 | /**
32 | * Applies the view and projection matrices and draws the Renderable.
33 | *
34 | * @param viewMatrix
35 | * the view matrix to map from world space to camera space.
36 | * @param projectionMatrix
37 | * the projection matrix to map from camera space to screen
38 | * space.
39 | */
40 | public abstract void draw(float[] viewMatrix, float[] projectionMatrix);
41 |
42 | public synchronized void updateMvpMatrix(float[] viewMatrix,
43 | float[] projectionMatrix) {
44 | // Compose the model, view, and projection matrices into a single mvp
45 | // matrix
46 | Matrix.setIdentityM(mMvMatrix, 0);
47 | Matrix.setIdentityM(mMvpMatrix, 0);
48 | Matrix.multiplyMM(mMvMatrix, 0, viewMatrix, 0, mModelMatrix, 0);
49 | Matrix.multiplyMM(mMvpMatrix, 0, projectionMatrix, 0, mMvMatrix, 0);
50 | }
51 |
52 | public float[] getModelMatrix() {
53 | return mModelMatrix;
54 | }
55 |
56 | public void setModelMatrix(float[] modelMatrix) {
57 | mModelMatrix = modelMatrix;
58 | }
59 |
60 | public float[] getMvMatrix() {
61 | return mMvMatrix;
62 | }
63 |
64 | public float[] getMvpMatrix() {
65 | return mMvpMatrix;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/src/com/kitware/tangoproject/paraviewtangorecorder/ZipWriter.java:
--------------------------------------------------------------------------------
1 | package com.kitware.tangoproject.paraviewtangorecorder;
2 |
3 | /*
4 | * Copyright 2015 Kitware Inc. All Rights Reserved.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | *
18 | */
19 | /*
20 | * Based on example provided by:
21 | * http://www.jondev.net/articles/Zipping_Files_with_Android_%28Programmatically%29
22 | */
23 |
24 |
25 | import android.util.Log;
26 | import java.io.BufferedInputStream;
27 | import java.io.BufferedOutputStream;
28 | import java.io.FileInputStream;
29 | import java.io.FileOutputStream;
30 | import java.util.zip.ZipEntry;
31 | import java.util.zip.ZipOutputStream;
32 |
33 |
34 | public class ZipWriter {
35 |
36 | private static final int BUFFER = 2048;
37 | private String[] _files;
38 | private String _zipFile;
39 |
40 | public ZipWriter(String[] files, String zipFile) {
41 | _files = files;
42 | _zipFile = zipFile;
43 | }
44 |
45 | public void zip() {
46 | try {
47 | BufferedInputStream origin = null;
48 | FileOutputStream dest = new FileOutputStream(_zipFile);
49 |
50 | ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
51 |
52 | byte data[] = new byte[BUFFER];
53 |
54 | for (String _file : _files) {
55 | // Log.i("Compress", "Adding: " + _file.substring(_file.lastIndexOf("/") + 1));
56 | FileInputStream fi = new FileInputStream(_file);
57 | origin = new BufferedInputStream(fi, BUFFER);
58 | ZipEntry entry = new ZipEntry(_file.substring(_file.lastIndexOf("/") + 1));
59 | out.putNextEntry(entry);
60 | int count;
61 | while ((count = origin.read(data, 0, BUFFER)) != -1) {
62 | out.write(data, 0, count);
63 | }
64 | origin.close();
65 | }
66 |
67 | out.close();
68 | } catch(Exception e) {
69 | e.printStackTrace();
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
23 |
24 |
28 |
29 |
32 |
33 |
34 |
35 |
36 |
41 |
44 |
45 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
61 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/ParaViewPlugins/AccumulatePointClouds.py:
--------------------------------------------------------------------------------
1 | ###################################################
2 | ######## Programmable filter script ########
3 | ###################################################
4 |
5 | # Author: Casey Goodlett
6 |
7 | # Output DataSet Type = Same as Input
8 |
9 |
10 | ############# Properties for auto-generated XML #############
11 |
12 | Name = 'AccumulatePointClouds'
13 | Label = 'Accumulate Point Clouds over time'
14 | Help = 'This accumulates all the point clouds into a single dataset'
15 |
16 |
17 | # Still don't know if these lines are actually necessary
18 | NumberOfInputs = 1
19 | InputDataType1 = 'vtkPolyData'
20 | # OutputDataType = 'vtkPolyData' # omit this line to use 'same as input'
21 |
22 | Properties = {}
23 |
24 | def RequestData():
25 | import numpy as np
26 | import vtk.util.numpy_support as vnp
27 |
28 | try:
29 | x = self.UpdateTimeIndex
30 | except AttributeError:
31 | self.UpdateTimeIndex = 0
32 |
33 | inp = inputs[0]
34 | if self.UpdateTimeIndex < len(self.TimeValues) - 1:
35 | #print self.UpdateTimeIndex
36 |
37 | # If we are not done, ask the pipeline to re-execute us.
38 | self.UpdateTimeIndex += 1
39 | request.Set(
40 | vtk.vtkStreamingDemandDrivenPipeline.CONTINUE_EXECUTING(), 1)
41 | pts = inp.Points.copy()
42 | try:
43 | self.Cache.append(pts)
44 | except AttributeError:
45 | self.Cache = []
46 | self.Cache.append(pts)
47 | else:
48 | request.Remove(
49 | vtk.vtkStreamingDemandDrivenPipeline.CONTINUE_EXECUTING())
50 | self.UpdateTimeIndex = 0
51 |
52 | pts = np.concatenate(self.Cache)
53 | self.Cache = []
54 |
55 | pd = vtk.vtkPolyData()
56 | vpts = vtk.vtkPoints()
57 | vpts.SetData(vnp.numpy_to_vtk(pts, deep=True))
58 | pd.SetPoints(vpts)
59 |
60 | m = vtk.vtkMaskPoints()
61 | m.SetOnRatio(1)
62 | m.SetGenerateVertices(True)
63 | m.SetInputData(pd)
64 | m.Update()
65 |
66 | output.DeepCopy(m.GetOutput())
67 |
68 | def RequestInformation():
69 | import vtk
70 |
71 | executive = self.GetExecutive()
72 | info = executive.GetInputInformation(0,0)
73 | outInfo = executive.GetOutputInformation(0)
74 |
75 | # Reset values.
76 | self.TimeValues = info.Get(
77 | vtk.vtkStreamingDemandDrivenPipeline.TIME_STEPS())
78 |
79 | # We accumulate all particles to one dataset so we don't really
80 | # produce temporal data that can be separately requested.
81 | outInfo.Remove(
82 | vtk.vtkStreamingDemandDrivenPipeline.TIME_STEPS())
83 | outInfo.Remove(
84 | vtk.vtkStreamingDemandDrivenPipeline.TIME_RANGE())
85 |
86 | return 1
87 |
88 | def RequestUpdateExtent():
89 | try:
90 | x = self.UpdateTimeIndex
91 | except AttributeError:
92 | self.UpdateTimeIndex = 0
93 |
94 | info = self.GetExecutive().GetInputInformation(0,0)
95 | info.Set(vtk.vtkStreamingDemandDrivenPipeline.UPDATE_TIME_STEP(),
96 | self.TimeValues[self.UpdateTimeIndex])
97 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
23 |
24 |
25 |
26 | ParaView Tango Recorder
27 | ParaView Tango Recorder
28 | Number of points:
29 | Tango service version:
30 | "App version: "
31 | "Tango system event: "
32 | Target->Device, Base->Start:
33 | ", count: "
34 | "status: "
35 | ", delta time (ms): "
36 | ", position (m): "
37 | ", orientation: "
38 | First
39 | Third
40 | Top
41 | Start
42 | Auto Reset On
43 | Auto Reset Off
44 | "Average depth (m): "
45 | "Point count: "
46 | "Frame delta time (ms): "
47 | "Tango Exception! Try again!"
48 | "Tango Service outdated!"
49 | "Motion Tracking permission needed!"
50 | "N/A"
51 | "initializing"
52 | "valid"
53 | "invalid"
54 | "unknown"
55 | ", Latest ADF is: "
56 |
57 | "File written to SD card :"
58 | "Auto Mode"
59 | "Take Snapshot"
60 | "Record"
61 | "Saving scan…"
62 | "Initializing…"
63 |
64 |
65 |
--------------------------------------------------------------------------------
/ParaViewPlugins/QuaternionToOrientationFrame.py:
--------------------------------------------------------------------------------
1 | ###################################################
2 | ######## Programmable filter script ########
3 | ###################################################
4 |
5 | Name = 'QuaternionToOrientation'
6 | Label = 'Convert Quaternion to Orientation Frame'
7 | Help = 'This converts the orientation from a quaternion to an orientation matrix'
8 |
9 | # Author: Matthieu Heitz
10 |
11 | # Output DataSet Type = Same as Input
12 |
13 | NumberOfInputs = 1
14 | InputDataType1 = 'vtkPolyData'
15 |
16 | Properties = {}
17 |
18 | def RequestData():
19 | import vtk
20 | import numpy as np
21 | from numpy import linalg as LA
22 |
23 | # print "\n\n"
24 | # print "****************************************************\n" \
25 | # "Programmable Filter: Quaternion to Orientation Frame\n" \
26 | # "****************************************************\n"
27 |
28 | # Get I/O
29 | pdi = self.GetPolyDataInput()
30 | pdo = self.GetPolyDataOutput()
31 |
32 |
33 | pointData = pdi.GetPointData()
34 | # print pointData
35 |
36 | if pointData is None:
37 | print "ERROR: vtkPolyData has no dataArray"
38 |
39 |
40 | orientationArray = pointData.GetArray("orientation")
41 | # print orientationArray
42 |
43 | if orientationArray is None:
44 | print "ERROR: vtkPolyData has no dataArray called \"orientation\""
45 |
46 |
47 | numTuples = orientationArray.GetNumberOfTuples()
48 |
49 | # Right = X
50 | # Up = Y
51 | # Backward = Z
52 |
53 | rightArray = vtk.vtkFloatArray()
54 | rightArray.SetNumberOfComponents(3)
55 | rightArray.SetNumberOfTuples(numTuples)
56 | rightArray.SetName('right')
57 |
58 | upArray = vtk.vtkFloatArray()
59 | upArray.SetNumberOfComponents(3)
60 | upArray.SetNumberOfTuples(numTuples)
61 | upArray.SetName('up')
62 |
63 | backwardArray = vtk.vtkFloatArray()
64 | backwardArray.SetNumberOfComponents(3)
65 | backwardArray.SetNumberOfTuples(numTuples)
66 | backwardArray.SetName('backward')
67 |
68 | forwardArray = vtk.vtkFloatArray()
69 | forwardArray.SetNumberOfComponents(3)
70 | forwardArray.SetNumberOfTuples(numTuples)
71 | forwardArray.SetName('forward')
72 |
73 | for i in range(0, numTuples):
74 | orientation = orientationArray.GetTuple(i)
75 | x = orientation[0]
76 | y = orientation[1]
77 | z = orientation[2]
78 | w = orientation[3]
79 |
80 | a = 1.0 - 2.0 * (y*y + z*z)
81 | b = 2.0 * (x*y + w*z)
82 | c = 2.0 * (x*z - w*y)
83 | rightArray.SetTuple3(i, a, b, c)
84 |
85 | a = 2.0 * (x*y - w*z)
86 | b = 1.0 - 2.0 * (x*x + z*z)
87 | c = 2.0 * (y*z + w*x)
88 | upArray.SetTuple3(i, a, b, c)
89 |
90 | a = 2.0 * (x*z + w*y)
91 | b = 2.0 * (y*z - w*x)
92 | c = 1.0 - 2.0 *(x*x + y*y)
93 | backwardArray.SetTuple3(i, a, b, c)
94 | forwardArray.SetTuple3(i, -a, -b, -c)
95 |
96 |
97 | pdo.GetPointData().AddArray(orientationArray)
98 | pdo.GetPointData().AddArray(rightArray)
99 | pdo.GetPointData().AddArray(upArray)
100 | pdo.GetPointData().AddArray(backwardArray)
101 | pdo.GetPointData().AddArray(forwardArray)
102 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/src/com/kitware/tangoproject/paraviewtangorecorder/PCRenderer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.kitware.tangoproject.paraviewtangorecorder;
18 |
19 | import android.opengl.GLES20;
20 | import android.opengl.GLSurfaceView;
21 | import android.opengl.Matrix;
22 |
23 | import javax.microedition.khronos.egl.EGLConfig;
24 | import javax.microedition.khronos.opengles.GL10;
25 |
26 | import com.kitware.tangoutils.Renderer;
27 | import com.kitware.tangoutils.renderables.CameraFrustum;
28 | import com.kitware.tangoutils.renderables.CameraFrustumAndAxis;
29 | import com.kitware.tangoutils.renderables.Grid;
30 | import com.kitware.tangoutils.renderables.PointCloud;
31 |
32 | /**
33 | * OpenGL rendering class for the Motion Tracking API sample. This class
34 | * managers the objects visible in the OpenGL view which are the
35 | * {@link CameraFrustum}, {@link PointCloud} and the {@link Grid}. These objects
36 | * are implemented in the TangoUtils library in the package
37 | * {@link com.kitware.tangoutils.renderables}.
38 | *
39 | * This class receives {@link TangoPose} data from the {@link MotionTracking}
40 | * class and updates the model and view matrices of the {@link Renderable}
41 | * objects appropriately. It also handles the user-selected camera view, which
42 | * can be 1st person, 3rd person, or top-down.
43 | *
44 | */
45 | public class PCRenderer extends Renderer implements GLSurfaceView.Renderer {
46 |
47 | private PointCloud mPointCloud;
48 | private Grid mGrid;
49 | private CameraFrustumAndAxis mCameraFrustumAndAxis;
50 | private int mMaxDepthPoints;
51 |
52 | public PCRenderer(int maxDepthPoints) {
53 | mMaxDepthPoints = maxDepthPoints;
54 | }
55 |
56 | @Override
57 | public void onSurfaceCreated(GL10 gl, EGLConfig config) {
58 | GLES20.glClearColor(1f, 1f, 1f, 1.0f);
59 | GLES20.glEnable(GLES20.GL_DEPTH_TEST);
60 | mPointCloud = new PointCloud(mMaxDepthPoints);
61 | mGrid = new Grid();
62 | mCameraFrustumAndAxis = new CameraFrustumAndAxis();
63 | Matrix.setIdentityM(mViewMatrix, 0);
64 | Matrix.setLookAtM(mViewMatrix, 0, 5f, 5f, 5f, 0f, 0f, 0f, 0f, 1f, 0f);
65 | mCameraFrustumAndAxis.setModelMatrix(getModelMatCalculator()
66 | .getModelMatrix());
67 | }
68 |
69 | @Override
70 | public void onSurfaceChanged(GL10 gl, int width, int height) {
71 | GLES20.glViewport(0, 0, width, height);
72 | mCameraAspect = (float) width / height;
73 | Matrix.perspectiveM(mProjectionMatrix, 0, CAMERA_FOV, mCameraAspect,
74 | CAMERA_NEAR, CAMERA_FAR);
75 | }
76 |
77 | @Override
78 | public void onDrawFrame(GL10 gl) {
79 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
80 | mGrid.draw(mViewMatrix, mProjectionMatrix);
81 | mPointCloud.draw(mViewMatrix, mProjectionMatrix);
82 | mCameraFrustumAndAxis.draw(mViewMatrix, mProjectionMatrix);
83 | }
84 |
85 | public PointCloud getPointCloud() {
86 | return mPointCloud;
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/TangoUtils/src/com/kitware/tangoutils/renderables/Grid.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.kitware.tangoutils.renderables;
18 |
19 | import java.nio.ByteBuffer;
20 | import java.nio.ByteOrder;
21 | import java.nio.FloatBuffer;
22 |
23 | import android.opengl.GLES20;
24 | import android.opengl.Matrix;
25 |
26 | /**
27 | * {@link Renderable} OpenGL object showing the 'floor' of the current scene.
28 | * This is a static grid placed in the scene to provide perspective in the
29 | * various views.
30 | */
31 | public class Grid extends Renderable {
32 |
33 | private static final int COORDS_PER_VERTEX = 3;
34 | private static final int GRID_RANGE_M = 100;
35 | private static final int BYTES_PER_FLOAT = 4;
36 |
37 | private static final String sVertexShaderCode = "uniform mat4 uMVPMatrix;"
38 | + "attribute vec4 vPosition;" + "void main() {"
39 | + "gl_Position = uMVPMatrix * vPosition;" + "}";
40 | private static final String sFragmentShaderCode = "precision mediump float;"
41 | + "uniform vec4 vColor;"
42 | + "void main() {"
43 | + " gl_FragColor = vec4(0.8,0.8,0.8,1.0);" + "}";
44 |
45 | private FloatBuffer mVertexBuffer;
46 | private final int mProgram;
47 | private int mPosHandle;
48 | private int mMVPMatrixHandle;
49 |
50 | public Grid() {
51 | // Reset the model matrix to the identity
52 | Matrix.setIdentityM(getModelMatrix(), 0);
53 |
54 | // Allocate a vertex buffer
55 | ByteBuffer vertexByteBuffer = ByteBuffer
56 | .allocateDirect((GRID_RANGE_M * 2 + 1) * 4 * 3
57 | * BYTES_PER_FLOAT);
58 | vertexByteBuffer.order(ByteOrder.nativeOrder());
59 | mVertexBuffer = vertexByteBuffer.asFloatBuffer();
60 |
61 | // Load the vertices for the z-axis grid lines into the vertex buffer
62 | for (int x = -GRID_RANGE_M; x <= GRID_RANGE_M; x++) {
63 | mVertexBuffer.put(new float[] { x, -1.3f, (float) -GRID_RANGE_M });
64 | mVertexBuffer.put(new float[] { x, -1.3f, (float) GRID_RANGE_M });
65 | }
66 |
67 | // Load the vertices for the x-axis grid lines into the vertex buffer
68 | for (int z = -GRID_RANGE_M; z <= GRID_RANGE_M; z++) {
69 | mVertexBuffer.put(new float[] { (float) -GRID_RANGE_M, -1.3f, z });
70 | mVertexBuffer.put(new float[] { (float) GRID_RANGE_M, -1.3f, z });
71 | }
72 |
73 | // Load the vertex and fragment shaders, then link the program
74 | int vertexShader = RenderUtils.loadShader(GLES20.GL_VERTEX_SHADER,
75 | sVertexShaderCode);
76 | int fragShader = RenderUtils.loadShader(GLES20.GL_FRAGMENT_SHADER,
77 | sFragmentShaderCode);
78 | mProgram = GLES20.glCreateProgram();
79 | GLES20.glAttachShader(mProgram, vertexShader);
80 | GLES20.glAttachShader(mProgram, fragShader);
81 | GLES20.glLinkProgram(mProgram);
82 | }
83 |
84 | @Override
85 | public void draw(float[] viewMatrix, float[] projectionMatrix) {
86 | GLES20.glUseProgram(mProgram);
87 | mVertexBuffer.position(0);
88 |
89 | // Compose the model, view, and projection matrices into a single m-v-p
90 | // matrix
91 | updateMvpMatrix(viewMatrix, projectionMatrix);
92 |
93 | // Load vertex attribute data
94 | mPosHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
95 | GLES20.glVertexAttribPointer(mPosHandle, COORDS_PER_VERTEX,
96 | GLES20.GL_FLOAT, false, 0, mVertexBuffer);
97 | GLES20.glEnableVertexAttribArray(mPosHandle);
98 |
99 | // Draw the Grid
100 | mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
101 | GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, getMvpMatrix(), 0);
102 | GLES20.glLineWidth(1);
103 | GLES20.glDrawArrays(GLES20.GL_LINES, 0, (GRID_RANGE_M * 2 + 1) * 4);
104 | }
105 |
106 | }
--------------------------------------------------------------------------------
/TangoUtils/src/com/kitware/tangoutils/renderables/PointCloud.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.kitware.tangoutils.renderables;
18 |
19 | import java.nio.ByteBuffer;
20 | import java.nio.ByteOrder;
21 | import java.nio.FloatBuffer;
22 |
23 | import android.opengl.GLES20;
24 | import android.opengl.Matrix;
25 |
26 | /**
27 | * {@link Renderable} OpenGL showing a PointCloud obtained from Tango XyzIj
28 | * data. The point count can vary over as the information is updated.
29 | */
30 | public class PointCloud extends Renderable {
31 |
32 | private static final int COORDS_PER_VERTEX = 3;
33 |
34 | private static final String sVertexShaderCode = "uniform mat4 uMVPMatrix;"
35 | + "attribute vec4 vPosition;" + "varying vec4 vColor;"
36 | + "void main() {" + "gl_PointSize = 5.0;"
37 | + " gl_Position = uMVPMatrix * vPosition;"
38 | + " vColor = vPosition;" + "}";
39 | private static final String sFragmentShaderCode = "precision mediump float;"
40 | + "varying vec4 vColor;"
41 | + "void main() {"
42 | + " gl_FragColor = vec4(vColor);" + "}";
43 |
44 | private static final int BYTES_PER_FLOAT = 4;
45 | private static final int POINT_TO_XYZ = 3;
46 | private FloatBuffer mVertexBuffer;
47 | private final int mProgram;
48 | private int mPosHandle;
49 | private int mMVPMatrixHandle;
50 | private int mPointCount;
51 | private float mAverageZ;
52 |
53 | public PointCloud(int maxDepthPoints) {
54 | mAverageZ = 0;
55 | int vertexShader = RenderUtils.loadShader(GLES20.GL_VERTEX_SHADER,
56 | sVertexShaderCode);
57 | int fragShader = RenderUtils.loadShader(GLES20.GL_FRAGMENT_SHADER,
58 | sFragmentShaderCode);
59 | mProgram = GLES20.glCreateProgram();
60 | GLES20.glAttachShader(mProgram, vertexShader);
61 | GLES20.glAttachShader(mProgram, fragShader);
62 | GLES20.glLinkProgram(mProgram);
63 | Matrix.setIdentityM(getModelMatrix(), 0);
64 | mVertexBuffer = ByteBuffer
65 | .allocateDirect(maxDepthPoints * BYTES_PER_FLOAT * POINT_TO_XYZ)
66 | .order(ByteOrder.nativeOrder()).asFloatBuffer();
67 | }
68 |
69 | public synchronized void UpdatePoints(byte[] byteArray, int pointCount) {
70 | FloatBuffer mPointCloudFloatBuffer;
71 | mPointCloudFloatBuffer = ByteBuffer.wrap(byteArray)
72 | .order(ByteOrder.nativeOrder()).asFloatBuffer();
73 | mPointCount = pointCount;
74 | mVertexBuffer.clear();
75 | mVertexBuffer.position(0);
76 | mVertexBuffer.put(mPointCloudFloatBuffer);
77 | float totalZ = 0;
78 | for (int i = 0; i < mPointCloudFloatBuffer.capacity() - 3; i = i + 3) {
79 | totalZ = totalZ + mPointCloudFloatBuffer.get(i + 2);
80 | }
81 | mAverageZ = totalZ / mPointCount;
82 | }
83 |
84 | @Override
85 | public synchronized void draw(float[] viewMatrix, float[] projectionMatrix) {
86 | if (mPointCount > 0) {
87 | mVertexBuffer.position(0);
88 | GLES20.glUseProgram(mProgram);
89 | updateMvpMatrix(viewMatrix, projectionMatrix);
90 | mPosHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
91 | GLES20.glVertexAttribPointer(mPosHandle, COORDS_PER_VERTEX,
92 | GLES20.GL_FLOAT, false, 0, mVertexBuffer);
93 | GLES20.glEnableVertexAttribArray(mPosHandle);
94 | mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram,
95 | "uMVPMatrix");
96 | GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false,
97 | getMvpMatrix(), 0);
98 | GLES20.glDrawArrays(GLES20.GL_POINTS, 0, mPointCount);
99 | }
100 | }
101 |
102 | public float getAverageZ() {
103 | return mAverageZ;
104 | }
105 |
106 | public int getPointCount() {
107 | return mPointCount;
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/TangoUtils/src/com/kitware/tangoutils/renderables/CameraFrustum.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.kitware.tangoutils.renderables;
18 |
19 | import java.nio.ByteBuffer;
20 | import java.nio.ByteOrder;
21 | import java.nio.FloatBuffer;
22 |
23 | import android.opengl.GLES20;
24 | import android.opengl.Matrix;
25 |
26 | /**
27 | * {@link Renderable} OpenGL object showing the Camera Frustum in 3D. This shows
28 | * the view of the Tango camera at the current translation and rotation.
29 | */
30 | public class CameraFrustum extends Renderable {
31 |
32 | private static final int COORDS_PER_VERTEX = 3;
33 |
34 | private static final String sVertexShaderCode = "uniform mat4 uMVPMatrix;"
35 | + "attribute vec4 vPosition;" + "attribute vec4 aColor;"
36 | + "varying vec4 vColor;" + "void main() {" + " vColor=aColor;"
37 | + "gl_Position = uMVPMatrix * vPosition;" + "}";
38 |
39 | private static final String sFragmentShaderCode = "precision mediump float;"
40 | + "varying vec4 vColor;"
41 | + "void main() {"
42 | + "gl_FragColor = vec4(0.8,0.5,0.8,1);" + "}";
43 |
44 | private FloatBuffer mVertexBuffer, mColorBuffer;
45 |
46 | private float mVertices[] = { 0.0f, 0.0f, 0.0f, -0.4f, 0.3f, -0.5f,
47 |
48 | 0.0f, 0.0f, 0.0f, 0.4f, 0.3f, -0.5f,
49 |
50 | 0.0f, 0.0f, 0.0f, -0.4f, -0.3f, -0.5f,
51 |
52 | 0.0f, 0.0f, 0.0f, 0.4f, -0.3f, -0.5f,
53 |
54 | -0.4f, 0.3f, -0.5f, 0.4f, 0.3f, -0.5f,
55 |
56 | 0.4f, 0.3f, -0.5f, 0.4f, -0.3f, -0.5f,
57 |
58 | 0.4f, -0.3f, -0.5f, -0.4f, -0.3f, -0.5f,
59 |
60 | -0.4f, -0.3f, -0.5f, -0.4f, 0.3f, -0.5f };
61 |
62 | private float mColors[] = { 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
63 |
64 | 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
65 |
66 | 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
67 |
68 | 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
69 |
70 | 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
71 |
72 | 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
73 |
74 | 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
75 |
76 | 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f };
77 |
78 | private final int mProgram;
79 | private int mPosHandle, mColorHandle;
80 | private int mMVPMatrixHandle;
81 |
82 | public CameraFrustum() {
83 | // Reset the model matrix to the identity
84 | Matrix.setIdentityM(getModelMatrix(), 0);
85 |
86 | // Load the vertices into a vertex buffer
87 | ByteBuffer byteBuf = ByteBuffer.allocateDirect(mVertices.length * 4);
88 | byteBuf.order(ByteOrder.nativeOrder());
89 | mVertexBuffer = byteBuf.asFloatBuffer();
90 | mVertexBuffer.put(mVertices);
91 | mVertexBuffer.position(0);
92 |
93 | // Load the colors into a color buffer
94 | ByteBuffer cByteBuff = ByteBuffer.allocateDirect(mColors.length * 4);
95 | cByteBuff.order(ByteOrder.nativeOrder());
96 | mColorBuffer = cByteBuff.asFloatBuffer();
97 | mColorBuffer.put(mColors);
98 | mColorBuffer.position(0);
99 |
100 | // Load the vertex and fragment shaders, then link the program
101 | int vertexShader = RenderUtils.loadShader(GLES20.GL_VERTEX_SHADER,
102 | sVertexShaderCode);
103 | int fragShader = RenderUtils.loadShader(GLES20.GL_FRAGMENT_SHADER,
104 | sFragmentShaderCode);
105 | mProgram = GLES20.glCreateProgram();
106 | GLES20.glAttachShader(mProgram, vertexShader);
107 | GLES20.glAttachShader(mProgram, fragShader);
108 | GLES20.glLinkProgram(mProgram);
109 | }
110 |
111 | @Override
112 | public void draw(float[] viewMatrix, float[] projectionMatrix) {
113 | GLES20.glUseProgram(mProgram);
114 | // updateViewMatrix(viewMatrix);
115 |
116 | // Compose the model, view, and projection matrices into a single mvp
117 | // matrix
118 | updateMvpMatrix(viewMatrix, projectionMatrix);
119 |
120 | // Load vertex attribute data
121 | mPosHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
122 | GLES20.glVertexAttribPointer(mPosHandle, COORDS_PER_VERTEX,
123 | GLES20.GL_FLOAT, false, 0, mVertexBuffer);
124 | GLES20.glEnableVertexAttribArray(mPosHandle);
125 |
126 | // Load color attribute data
127 | mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
128 | GLES20.glVertexAttribPointer(mColorHandle, 4, GLES20.GL_FLOAT, false,
129 | 0, mColorBuffer);
130 | GLES20.glEnableVertexAttribArray(mColorHandle);
131 |
132 | // Draw the CameraFrustum
133 | mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
134 | GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, getMvpMatrix(), 0);
135 | GLES20.glLineWidth(1);
136 | GLES20.glDrawArrays(GLES20.GL_LINES, 0, 16);
137 | }
138 | }
--------------------------------------------------------------------------------
/TangoUtils/src/com/kitware/tangoutils/renderables/CameraFrustumAndAxis.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.kitware.tangoutils.renderables;
18 |
19 | import java.nio.ByteBuffer;
20 | import java.nio.ByteOrder;
21 | import java.nio.FloatBuffer;
22 |
23 | import android.opengl.GLES20;
24 | import android.opengl.Matrix;
25 |
26 | /**
27 | * {@link Renderable} OpenGL object representing XYZ axes in 3D space. X is Red,
28 | * Y is Green, and Z is Blue.
29 | */
30 | public class CameraFrustumAndAxis extends Renderable {
31 |
32 | private static final int COORDS_PER_VERTEX = 3;
33 |
34 | private static final String sVertexShaderCode = "uniform mat4 uMVPMatrix;"
35 | + "attribute vec4 vPosition;" + "attribute vec4 aColor;"
36 | + "varying vec4 vColor;" + "void main() {" + " vColor=aColor;"
37 | + "gl_Position = uMVPMatrix * vPosition;" + "}";
38 |
39 | private static final String sFragmentShaderCode = "precision mediump float;"
40 | + "varying vec4 vColor;"
41 | + "void main() {"
42 | + "gl_FragColor = vColor;" + "}";
43 | private FloatBuffer mVertexBuffer, mColorBuffer;
44 |
45 | private float mVertices[] = { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
46 |
47 | 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
48 |
49 | 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
50 |
51 | 0.0f, 0.0f, 0.0f, -0.4f, 0.3f, -0.5f,
52 |
53 | 0.0f, 0.0f, 0.0f, 0.4f, 0.3f, -0.5f,
54 |
55 | 0.0f, 0.0f, 0.0f, -0.4f, -0.3f, -0.5f,
56 |
57 | 0.0f, 0.0f, 0.0f, 0.4f, -0.3f, -0.5f,
58 |
59 | -0.4f, 0.3f, -0.5f, 0.4f, 0.3f, -0.5f,
60 |
61 | 0.4f, 0.3f, -0.5f, 0.4f, -0.3f, -0.5f,
62 |
63 | 0.4f, -0.3f, -0.5f, -0.4f, -0.3f, -0.5f,
64 |
65 | -0.4f, -0.3f, -0.5f, -0.4f, 0.3f, -0.5f };
66 |
67 | private float mColors[] = { 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
68 |
69 | 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
70 |
71 | 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
72 |
73 | 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
74 |
75 | 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
76 |
77 | 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
78 |
79 | 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
80 |
81 | 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
82 |
83 | 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
84 |
85 | 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
86 |
87 | 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, };
88 |
89 | private final int mProgram;
90 | private int mPosHandle, mColorHandle;
91 | private int mMVPMatrixHandle;
92 |
93 | public CameraFrustumAndAxis() {
94 | // Set model matrix to the identity
95 | Matrix.setIdentityM(getModelMatrix(), 0);
96 |
97 | // Put vertices into a vertex buffer
98 | ByteBuffer byteBuf = ByteBuffer.allocateDirect(mVertices.length * 4);
99 | byteBuf.order(ByteOrder.nativeOrder());
100 | mVertexBuffer = byteBuf.asFloatBuffer();
101 | mVertexBuffer.put(mVertices);
102 | mVertexBuffer.position(0);
103 |
104 | // Put colors into a color buffer
105 | ByteBuffer cByteBuff = ByteBuffer.allocateDirect(mColors.length * 4);
106 | cByteBuff.order(ByteOrder.nativeOrder());
107 | mColorBuffer = cByteBuff.asFloatBuffer();
108 | mColorBuffer.put(mColors);
109 | mColorBuffer.position(0);
110 |
111 | // Load the vertex and fragment shaders, then link the program
112 | int vertexShader = RenderUtils.loadShader(GLES20.GL_VERTEX_SHADER,
113 | sVertexShaderCode);
114 | int fragShader = RenderUtils.loadShader(GLES20.GL_FRAGMENT_SHADER,
115 | sFragmentShaderCode);
116 | mProgram = GLES20.glCreateProgram();
117 | GLES20.glAttachShader(mProgram, vertexShader);
118 | GLES20.glAttachShader(mProgram, fragShader);
119 | GLES20.glLinkProgram(mProgram);
120 | }
121 |
122 | @Override
123 | public synchronized void draw(float[] viewMatrix, float[] projectionMatrix) {
124 | GLES20.glUseProgram(mProgram);
125 |
126 | // Compose the model, view, and projection matrices into a single m-v-p
127 | // matrix
128 | updateMvpMatrix(viewMatrix, projectionMatrix);
129 |
130 | // Load vertex attribute data
131 | mPosHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
132 | GLES20.glVertexAttribPointer(mPosHandle, COORDS_PER_VERTEX,
133 | GLES20.GL_FLOAT, false, 0, mVertexBuffer);
134 | GLES20.glEnableVertexAttribArray(mPosHandle);
135 |
136 | // Load color attribute data
137 | mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
138 | GLES20.glVertexAttribPointer(mColorHandle, 4, GLES20.GL_FLOAT, false,
139 | 0, mColorBuffer);
140 | GLES20.glEnableVertexAttribArray(mColorHandle);
141 |
142 | // Draw the CameraFrustumAndAxis
143 | mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
144 | GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, getMvpMatrix(), 0);
145 | GLES20.glLineWidth(3);
146 | GLES20.glDrawArrays(GLES20.GL_LINES, 0, mVertices.length / 3);
147 |
148 | }
149 |
150 | }
--------------------------------------------------------------------------------
/TangoUtils/src/com/kitware/tangoutils/renderables/Trajectory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.kitware.tangoutils.renderables;
18 |
19 | import java.nio.ByteBuffer;
20 | import java.nio.ByteOrder;
21 | import java.nio.FloatBuffer;
22 |
23 | import android.opengl.GLES20;
24 | import android.opengl.Matrix;
25 | import android.util.Log;
26 |
27 | /**
28 | * {@link Renderable} OpenGL object showing the Trajectory of the Project Tango
29 | * device in 3D space. Points are added when the trajectory is updated by
30 | * passing translation data obtained from Tango Pose Data.
31 | */
32 | public class Trajectory extends Renderable {
33 |
34 | private static final int COORDS_PER_VERTEX = 3;
35 | private static final float MIN_DISTANCE_CHECK = 0.025f;
36 |
37 | /** Note: due to resetPath() logic, keep this as a multiple of 9 **/
38 | private static final int MAX_VERTICES = 9000;
39 | private static final int BYTES_PER_FLOAT = 4;
40 | private static int mTrajectoryCount = 0;
41 |
42 | private static final String TAG = Trajectory.class.getSimpleName();
43 | private String mVertexShaderCode = "uniform mat4 uMVPMatrix;"
44 | + "attribute vec4 vPosition;" + "uniform vec4 aColor;"
45 | + "varying vec4 vColor;" + "void main() {" + "gl_PointSize = 5.0;"
46 | + "vColor=aColor;" + "gl_Position = uMVPMatrix * vPosition;" + "}";
47 | private String mFragmentShaderCode = "precision mediump float;"
48 | + "varying vec4 vColor;" + "void main() {"
49 | + "gl_FragColor = vColor;" + "}";
50 | private FloatBuffer mVertexBuffer;
51 | private float[] mColor = { 0.22f, 0.28f, 0.67f, 1.0f };
52 | private final int mProgram;
53 | private int mPosHandle;
54 | private int mMVPMatrixHandle;
55 | private int mColorHandle;
56 | private int mLineWidth;
57 |
58 | public Trajectory(int lineWidth) {
59 | mLineWidth = lineWidth;
60 | // Reset the model matrix to the identity
61 | Matrix.setIdentityM(getModelMatrix(), 0);
62 |
63 | // Allocate a vertex buffer
64 | ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(MAX_VERTICES
65 | * BYTES_PER_FLOAT);
66 | vertexByteBuffer.order(ByteOrder.nativeOrder());
67 | mVertexBuffer = vertexByteBuffer.asFloatBuffer();
68 |
69 | // Load the vertex and fragment shaders, then link the program
70 | int vertexShader = RenderUtils.loadShader(GLES20.GL_VERTEX_SHADER,
71 | mVertexShaderCode);
72 | int fragShader = RenderUtils.loadShader(GLES20.GL_FRAGMENT_SHADER,
73 | mFragmentShaderCode);
74 | mProgram = GLES20.glCreateProgram();
75 | GLES20.glAttachShader(mProgram, vertexShader);
76 | GLES20.glAttachShader(mProgram, fragShader);
77 | GLES20.glLinkProgram(mProgram);
78 | }
79 |
80 | // float[] color should contain only 4 elements.
81 | public Trajectory(int lineWidth, float[] color) {
82 | mLineWidth = lineWidth;
83 | mColor = color;
84 | // Reset the model matrix to the identity
85 | Matrix.setIdentityM(getModelMatrix(), 0);
86 |
87 | // Allocate a vertex buffer
88 | ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(MAX_VERTICES
89 | * BYTES_PER_FLOAT);
90 | vertexByteBuffer.order(ByteOrder.nativeOrder());
91 | mVertexBuffer = vertexByteBuffer.asFloatBuffer();
92 |
93 | // Load the vertex and fragment shaders, then link the program
94 | int vertexShader = RenderUtils.loadShader(GLES20.GL_VERTEX_SHADER,
95 | mVertexShaderCode);
96 | int fragShader = RenderUtils.loadShader(GLES20.GL_FRAGMENT_SHADER,
97 | mFragmentShaderCode);
98 | mProgram = GLES20.glCreateProgram();
99 | GLES20.glAttachShader(mProgram, vertexShader);
100 | GLES20.glAttachShader(mProgram, fragShader);
101 | GLES20.glLinkProgram(mProgram);
102 | }
103 |
104 | public void updateTrajectory(float[] translation) {
105 | mVertexBuffer.position(mTrajectoryCount * 3);
106 | if (((mTrajectoryCount + 1) * 3) >= MAX_VERTICES) {
107 | Log.w(TAG, "Clearing float buffer");
108 | resetPath();
109 | }
110 | float dx = 0, dy = 0, dz = 0;
111 | try {
112 | dx = mVertexBuffer.get(mVertexBuffer.position() - 3)
113 | - translation[0];
114 | dy = mVertexBuffer.get(mVertexBuffer.position() - 2)
115 | - translation[2];
116 | dz = mVertexBuffer.get(mVertexBuffer.position() - 1)
117 | - (-translation[1]);
118 | } catch (IndexOutOfBoundsException e) {
119 | mVertexBuffer.put(new float[] { translation[0], translation[2],
120 | -translation[1] });
121 | mTrajectoryCount++;
122 | }
123 | float distance = (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
124 | if (distance > MIN_DISTANCE_CHECK) {
125 | mVertexBuffer.put(new float[] { translation[0], translation[2],
126 | -translation[1] });
127 | mTrajectoryCount++;
128 | }
129 | }
130 |
131 | public void resetPath() {
132 | int currentPosition = mVertexBuffer.position();
133 | int pointsToGet = (MAX_VERTICES / 3);
134 | mVertexBuffer.position(currentPosition - pointsToGet);
135 |
136 | float[] tail = new float[pointsToGet];
137 | mVertexBuffer.get(tail, 0, pointsToGet);
138 |
139 | mVertexBuffer.clear();
140 | mVertexBuffer.put(tail);
141 |
142 | mTrajectoryCount = pointsToGet / 3;
143 | }
144 |
145 | public void clearPath() {
146 | ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(MAX_VERTICES
147 | * BYTES_PER_FLOAT);
148 | vertexByteBuffer.order(ByteOrder.nativeOrder());
149 | mVertexBuffer = vertexByteBuffer.asFloatBuffer();
150 | }
151 |
152 | @Override
153 | public void draw(float[] viewMatrix, float[] projectionMatrix) {
154 | GLES20.glUseProgram(mProgram);
155 | mVertexBuffer.position(0);
156 |
157 | // Compose the model, view, and projection matrices into a single m-v-p
158 | // matrix
159 | updateMvpMatrix(viewMatrix, projectionMatrix);
160 |
161 | // Load vertex attribute data
162 | mPosHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
163 | GLES20.glVertexAttribPointer(mPosHandle, COORDS_PER_VERTEX,
164 | GLES20.GL_FLOAT, false, 0, mVertexBuffer);
165 | GLES20.glEnableVertexAttribArray(mPosHandle);
166 |
167 | mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
168 | GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, getMvpMatrix(), 0);
169 |
170 | mColorHandle = GLES20.glGetUniformLocation(mProgram, "aColor");
171 | GLES20.glUniform4f(mColorHandle, mColor[0], mColor[1], mColor[2],
172 | mColor[3]);
173 | GLES20.glLineWidth(mLineWidth);
174 | GLES20.glDrawArrays(GLES20.GL_LINE_STRIP, 0, mTrajectoryCount);
175 | }
176 |
177 | public void setColor(float[] color) {
178 | mColor = color;
179 | }
180 | }
--------------------------------------------------------------------------------
/ParaViewPlugins/ApplyPoseTransformToPointCloud.py:
--------------------------------------------------------------------------------
1 | ###################################################
2 | ######## Programmable filter script ########
3 | ###################################################
4 |
5 | # Author: Matthieu Heitz
6 |
7 | # Output DataSet Type = Same as Input
8 |
9 |
10 | ############# Properties for auto-generated XML #############
11 |
12 | Name = 'ApplyPoseTransformToPointCloud'
13 | Label = 'Apply Pose To PointCloud'
14 | Help = 'This applies the device pose point cloud at each timestep'
15 |
16 |
17 | # Still don't know if these lines are actually necessary
18 | NumberOfInputs = 2
19 | InputDataType1 = 'vtkPolyData'
20 | InputDataType2 = 'vtkPolyData'
21 | # OutputDataType = 'vtkPolyData' # omit this line to use 'same as input'
22 |
23 | Properties = {}
24 |
25 | def RequestData():
26 |
27 | ############# Initialize the filter #############
28 |
29 | import vtk
30 | import numpy as np
31 | from numpy import linalg as LA
32 |
33 | # print "\n\n"
34 | # print "********************************************************\n" \
35 | # "Programmable Filter: Apply Pose Transform to Point Cloud\n" \
36 | # "********************************************************\n"
37 |
38 |
39 | ############# Get I/O #############
40 |
41 | # Get the two inputs, and the output
42 | polyDataA = self.GetInputDataObject(0, 0)
43 | polyDataB = self.GetInputDataObject(0, 1)
44 | pdo = self.GetPolyDataOutput()
45 |
46 | # If only one input is given, raise an exception
47 | if polyDataA is None or polyDataB is None:
48 | raise Exception("\nThis filter takes 2 inputs:\n"
49 | "Point Cloud Data files: pc_HHMMSSDD_NNN.vtk\n"
50 | "Pose Data file: pc_HHMMSSDD_poses.vtk\n"
51 | "Note that ParaView groups all the Point Cloud Data files in one\n")
52 |
53 | # Initialize vtkPolyData for point cloud data (PC) and pose data (P)
54 | polyData_PC = vtk.vtkPolyData()
55 | polyData_P = vtk.vtkPolyData()
56 |
57 | # Figure out which PolyData is which
58 | if polyDataA.GetFieldData().GetArray("timestamp") is not None and \
59 | polyDataB.GetPointData().GetArray("timestamp") is not None:
60 | polyData_PC = polyDataA
61 | polyData_P = polyDataB
62 | else:
63 | if polyDataB.GetFieldData().GetArray("timestamp") is not None and \
64 | polyDataA.GetPointData().GetArray("timestamp") is not None:
65 | polyData_PC = polyDataB
66 | polyData_P = polyDataA
67 | else: # If none of the configuration above is met, raise an exception
68 | raise Exception("\nOne or both of the inputs don't have a \"timestamp\" Point/Field Data\n"
69 | "Is this data coming from the \"Paraview Tango Recorder\" app ?\n"
70 | "The input that ends with \'_poses.vtk\" must have a \"timestamp\" PointData\n"
71 | "The input that ends with \'*.vtk\" must have a \"timestamp\" FieldData\n")
72 |
73 | # If the pose data doesn't contain an "orientation" PointData array, raise an exception
74 | if polyData_P.GetPointData().GetArray("orientation") is None:
75 | raise Exception("\nThe Pose file (that ends with \"_poses.vtk\") has no dataArray called \"orientation\"\n")
76 |
77 |
78 | ############# Find the point cloud timestamp #############
79 |
80 | timestamp_PC = polyData_PC.GetFieldData().GetArray("timestamp").GetTuple(0)[0]
81 | #print "Point cloud timestamp: " + str(timestamp_PC)
82 |
83 |
84 | ############# Find the closest timestamp in the poses #############
85 |
86 | timestampArray_P = polyData_P.GetPointData().GetArray("timestamp")
87 |
88 | minDiff = 1e10
89 | closestIndex = 0
90 | for i in range(0, timestampArray_P.GetNumberOfTuples()):
91 | diff = abs(timestampArray_P.GetTuple(i)[0]-timestamp_PC)
92 | if diff < minDiff:
93 | closestIndex = i
94 | minDiff = diff
95 |
96 | #print "Closest Pose timestamp: " + str(timestampArray_P.GetTuple(closestIndex)[0])
97 | #print "Index: " + str(closestIndex)
98 |
99 |
100 | ############# Calculate the pose transform #############
101 |
102 | q = polyData_P.GetPointData().GetArray("orientation").GetTuple(closestIndex)
103 |
104 | # Add the orientation
105 | # Warning: orientation gives (x, y, z, w) but vtkQuaternion takes (w, x, y, z)
106 | myQuaternion = vtk.vtkQuaternionf(q[3], q[0], q[1], q[2])
107 | rotMatrix = np.zeros((4, 4))
108 | rotMatrix[3, 3] = 1
109 | myQuaternion.ToMatrix3x3(rotMatrix[0:3, 0:3])
110 |
111 | # Add the translation components
112 | pointArray_P = polyData_P.GetPoints()
113 | translation = pointArray_P.GetPoint(closestIndex)
114 | rotMatrix[0:3, 3] = translation
115 |
116 | ############# Read the Camera2Device transform #############
117 |
118 | # Array of 16 values
119 | raw_Cam2Dev_TFM = polyData_P.GetFieldData().GetArray("Cam2Dev_transform").GetTuple(0)
120 |
121 | # Reshape the matrix
122 | Camera2DeviceTFM = np.array(raw_Cam2Dev_TFM).reshape((4,4), order='F')
123 | #print "Cam2DevTFM_read_np_reshaped =\n" + str(Camera2DeviceTFM)
124 |
125 |
126 | ############# Apply the transforms to the point cloud #############
127 |
128 | vtkTFM = vtk.vtkTransform()
129 | vtkTFM.PostMultiply()
130 | vtkTFM.Identity()
131 | vtkTFM.Concatenate(Camera2DeviceTFM.flatten())
132 | vtkTFM.Concatenate(rotMatrix.flatten())
133 |
134 | vtkTFMFilter = vtk.vtkTransformPolyDataFilter()
135 | vtkTFMFilter.SetTransform(vtkTFM)
136 | vtkTFMFilter.SetInputData(polyData_PC)
137 | vtkTFMFilter.Update()
138 |
139 | pdo.ShallowCopy(vtkTFMFilter.GetOutput())
140 |
141 |
142 | def RequestInformation():
143 | import vtk
144 |
145 | ############# Get I/O #############
146 |
147 | # Get the two inputs, and the output
148 | polyDataA = self.GetInputDataObject(0, 0)
149 | polyDataB = self.GetInputDataObject(0, 1)
150 | pdo = self.GetPolyDataOutput()
151 |
152 | # If only one input is given, raise an exception
153 | if polyDataA is None or polyDataB is None:
154 | raise Exception("\nThis filter takes 2 inputs:\n"
155 | "Point Cloud Data files: pc_HHMMSSDD_NNN.vtk\n"
156 | "Pose Data file: pc_HHMMSSDD_poses.vtk\n"
157 | "Note that ParaView groups all the Point Cloud Data files in one\n")
158 |
159 | # Initialize vtkPolyData for point cloud data (PC) and pose data (P)
160 | polyData_PC = vtk.vtkPolyData()
161 | polyData_P = vtk.vtkPolyData()
162 |
163 | if polyDataA.GetFieldData().GetArray("timestamp") is not None and \
164 | polyDataB.GetPointData().GetArray("timestamp") is not None:
165 | pointCloudPortIndex = 0
166 | else:
167 | if polyDataB.GetFieldData().GetArray("timestamp") is not None and \
168 | polyDataA.GetPointData().GetArray("timestamp") is not None:
169 | pointCloudPortIndex = 1
170 | else: # If none of the configuration above is met, raise an exception
171 | raise Exception("\nOne or both of the inputs don't have a \"timestamp\" Point/Field Data\n"
172 | "Is this data coming from the \"Paraview Tango Recorder\" app ?\n"
173 | "The input that ends with \'_poses.vtk\" must have a \"timestamp\" PointData\n"
174 | "The input that ends with \'*.vtk\" must have a \"timestamp\" FieldData\n")
175 |
176 | def setOutputTimesteps ( algorithm , timesteps ):
177 | "helper routine to set timestep information"
178 | executive = algorithm . GetExecutive ()
179 | outInfo = executive . GetOutputInformation (0)
180 | outInfo.Remove ( executive.TIME_STEPS () )
181 | for timestep in timesteps :
182 | outInfo . Append ( executive . TIME_STEPS () , timestep )
183 |
184 | outInfo . Remove ( executive . TIME_RANGE () )
185 | outInfo . Append ( executive . TIME_RANGE () , timesteps [0])
186 | outInfo . Append ( executive . TIME_RANGE () , timesteps [ -1])
187 |
188 | def getInputTimesteps( algorithm, portindex):
189 | "helper routine to set timestep information"
190 | executive = algorithm . GetExecutive ()
191 | inInfo = executive . GetInputInformation (0, portindex)
192 | return inInfo.Get(executive.TIME_STEPS())
193 |
194 | myrange = getInputTimesteps(self, pointCloudPortIndex)
195 | setOutputTimesteps(self, myrange)
196 |
--------------------------------------------------------------------------------
/TangoUtils/src/com/kitware/tangoutils/ModelMatCalculator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.kitware.tangoutils;
18 |
19 | import android.opengl.Matrix;
20 |
21 | /**
22 | * Utility class to manage the calculation of a Model Matrix from the
23 | * translation and quaternion arrays obtained from an {@link TangoPose} object.
24 | * Delegates some mathematical computations to the {@link MathUtils}.
25 | */
26 | public class ModelMatCalculator {
27 |
28 | private static float[] mConversionMatrix = new float[] { 1.0f, 0.0f, 0.0f,
29 | 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
30 | 0.0f, 1.0f };
31 |
32 | private float[] mModelMatrix = new float[16];
33 | private float[] mPointCloudModelMatrix = new float[16];
34 | private float[] mDevice2IMUMatrix = new float[] { 1.0f, 0.0f, 0.0f, 0.0f,
35 | 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
36 | 1.0f };
37 | private float[] mColorCamera2IMUMatrix = new float[] { 1.0f, 0.0f, 0.0f,
38 | 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
39 | 0.0f, 1.0f };
40 | private float[] mOpengl2ColorCameraMatrix = new float[] { 1.0f, 0.0f, 0.0f,
41 | 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
42 | 0.0f, 1.0f };
43 |
44 | public ModelMatCalculator() {
45 | Matrix.setIdentityM(mModelMatrix, 0);
46 | Matrix.setIdentityM(mPointCloudModelMatrix, 0);
47 | }
48 |
49 | /**
50 | * Updates the model matrix (rotation and translation).
51 | *
52 | * @param translation
53 | * a three-element array of translation data.
54 | * @param quaternion
55 | * a four-element array of rotation data.
56 | */
57 | public void updatePointCloudModelMatrix(float[] translation,
58 | float[] quaternion) {
59 |
60 | float[] tempMultMatrix = new float[16];
61 | Matrix.setIdentityM(tempMultMatrix, 0);
62 | Matrix.multiplyMM(tempMultMatrix, 0, mColorCamera2IMUMatrix, 0,
63 | mOpengl2ColorCameraMatrix, 0);
64 | float[] tempInvertMatrix = new float[16];
65 | Matrix.setIdentityM(tempInvertMatrix, 0);
66 | Matrix.invertM(tempInvertMatrix, 0, mDevice2IMUMatrix, 0);
67 | float[] tempMultMatrix2 = new float[16];
68 | Matrix.setIdentityM(tempMultMatrix2, 0);
69 | Matrix.multiplyMM(tempMultMatrix2, 0, tempInvertMatrix, 0,
70 | tempMultMatrix, 0);
71 |
72 | float[] quaternionMatrix = new float[16];
73 | Matrix.setIdentityM(quaternionMatrix, 0);
74 | quaternionMatrix = quaternionMatrixOpenGL(quaternion);
75 | float[] tempMultMatrix3 = new float[16];
76 | Matrix.setIdentityM(tempMultMatrix3, 0);
77 | Matrix.setIdentityM(mPointCloudModelMatrix, 0);
78 | Matrix.multiplyMM(tempMultMatrix3, 0, quaternionMatrix, 0,
79 | tempMultMatrix2, 0);
80 | Matrix.multiplyMM(mPointCloudModelMatrix, 0, mConversionMatrix, 0,
81 | tempMultMatrix3, 0);
82 | mPointCloudModelMatrix[12] += translation[0];
83 | mPointCloudModelMatrix[13] += translation[2];
84 | mPointCloudModelMatrix[14] += -1f * translation[1];
85 | }
86 |
87 | /**
88 | * Updates the model matrix (rotation and translation).
89 | *
90 | * @param translation
91 | * a three-element array of translation data.
92 | * @param quaternion
93 | * a four-element array of rotation data.
94 | */
95 | public void updateModelMatrix(float[] translation, float[] quaternion) {
96 |
97 | float[] tempMultMatrix = new float[16];
98 | Matrix.setIdentityM(tempMultMatrix, 0);
99 | Matrix.multiplyMM(tempMultMatrix, 0, mColorCamera2IMUMatrix, 0,
100 | mOpengl2ColorCameraMatrix, 0);
101 | float[] tempInvertMatrix = new float[16];
102 | Matrix.setIdentityM(tempInvertMatrix, 0);
103 | Matrix.invertM(tempInvertMatrix, 0, mDevice2IMUMatrix, 0);
104 | float[] tempMultMatrix2 = new float[16];
105 | Matrix.setIdentityM(tempMultMatrix2, 0);
106 | Matrix.multiplyMM(tempMultMatrix2, 0, tempInvertMatrix, 0,
107 | tempMultMatrix, 0);
108 |
109 | float[] quaternionMatrix = new float[16];
110 | Matrix.setIdentityM(quaternionMatrix, 0);
111 | quaternionMatrix = quaternionMatrixOpenGL(quaternion);
112 | float[] tempMultMatrix3 = new float[16];
113 | Matrix.setIdentityM(tempMultMatrix3, 0);
114 | Matrix.setIdentityM(mModelMatrix, 0);
115 | Matrix.multiplyMM(tempMultMatrix3, 0, quaternionMatrix, 0,
116 | tempMultMatrix2, 0);
117 | Matrix.multiplyMM(mModelMatrix, 0, mConversionMatrix, 0,
118 | tempMultMatrix3, 0);
119 | mModelMatrix[12] += translation[0];
120 | mModelMatrix[13] += translation[2];
121 | mModelMatrix[14] += -1f * translation[1];
122 | }
123 |
124 | public void SetDevice2IMUMatrix(float[] translation, float[] quaternion) {
125 | mDevice2IMUMatrix = quaternionMatrixOpenGL(quaternion);
126 | mDevice2IMUMatrix[12] = translation[0];
127 | mDevice2IMUMatrix[13] = translation[1];
128 | mDevice2IMUMatrix[14] = translation[2];
129 | }
130 |
131 | public void SetColorCamera2IMUMatrix(float[] translation, float[] quaternion) {
132 | mOpengl2ColorCameraMatrix = new float[] { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
133 | -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
134 | 1.0f };
135 | mColorCamera2IMUMatrix = quaternionMatrixOpenGL(quaternion);
136 | mColorCamera2IMUMatrix[12] = translation[0];
137 | mColorCamera2IMUMatrix[13] = translation[1];
138 | mColorCamera2IMUMatrix[14] = translation[2];
139 | }
140 |
141 | public float[] getModelMatrix() {
142 | return mModelMatrix;
143 | }
144 |
145 | public float[] getModelMatrixCopy() {
146 | float[] modelMatCopy = new float[16];
147 | System.arraycopy(mModelMatrix, 0, modelMatCopy, 0, 16);
148 | return modelMatCopy;
149 | }
150 |
151 | public float[] getPointCloudModelMatrixCopy() {
152 | float[] modelMatCopy = new float[16];
153 | float[] tempMultMat = new float[16];
154 | Matrix.setIdentityM(tempMultMat, 0);
155 | float[] invertYandZMatrix = new float[] { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
156 | -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
157 | 1.0f };
158 | Matrix.multiplyMM(tempMultMat, 0, mPointCloudModelMatrix, 0,
159 | invertYandZMatrix, 0);
160 | System.arraycopy(tempMultMat, 0, modelMatCopy, 0, 16);
161 | return modelMatCopy;
162 | }
163 |
164 | public float[] getTranslation() {
165 | return new float[] { mModelMatrix[12], mModelMatrix[13],
166 | mModelMatrix[14] };
167 | }
168 |
169 | /**
170 | * A function to convert a quaternion to quaternion Matrix. Please note that
171 | * Opengl.Matrix is Column Major and so we construct the matrix in Column
172 | * Major Format. - - - - | 0 4 8 12 | | 1 5 9 13 | | 2 6 10 14 | | 3 7 11 15
173 | * | - - - -
174 | *
175 | * @param quaternion
176 | * Input quaternion with float[4]
177 | * @return Quaternion Matrix of float[16]
178 | */
179 | public static float[] quaternionMatrixOpenGL(float[] quaternion) {
180 | float[] matrix = new float[16];
181 | normalizeVector(quaternion);
182 |
183 | float x = quaternion[0];
184 | float y = quaternion[1];
185 | float z = quaternion[2];
186 | float w = quaternion[3];
187 |
188 | float x2 = x * x;
189 | float y2 = y * y;
190 | float z2 = z * z;
191 | float xy = x * y;
192 | float xz = x * z;
193 | float yz = y * z;
194 | float wx = w * x;
195 | float wy = w * y;
196 | float wz = w * z;
197 |
198 | matrix[0] = 1f - 2f * (y2 + z2);
199 | matrix[4] = 2f * (xy - wz);
200 | matrix[8] = 2f * (xz + wy);
201 | matrix[12] = 0f;
202 |
203 | matrix[1] = 2f * (xy + wz);
204 | matrix[5] = 1f - 2f * (x2 + z2);
205 | matrix[9] = 2f * (yz - wx);
206 | matrix[13] = 0f;
207 |
208 | matrix[2] = 2f * (xz - wy);
209 | matrix[6] = 2f * (yz + wx);
210 | matrix[10] = 1f - 2f * (x2 + y2);
211 | matrix[14] = 0f;
212 |
213 | matrix[3] = 0f;
214 | matrix[7] = 0f;
215 | matrix[11] = 0f;
216 | matrix[15] = 1f;
217 |
218 | return matrix;
219 | }
220 |
221 | /**
222 | * Creates a unit vector in the direction of an arbitrary vector. The
223 | * original vector is modified in place.
224 | *
225 | * @param v
226 | * the vector to normalize
227 | */
228 | public static void normalizeVector(float[] v) {
229 | float mag2 = v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3];
230 | if (Math.abs(mag2) > 0.00001f && Math.abs(mag2 - 1.0f) > 0.00001f) {
231 | float mag = (float) Math.sqrt(mag2);
232 | v[0] = v[0] / mag;
233 | v[1] = v[1] / mag;
234 | v[2] = v[2] / mag;
235 | v[3] = v[3] / mag;
236 | }
237 | }
238 | }
239 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/res/layout/activity_jpoint_cloud.xml:
--------------------------------------------------------------------------------
1 |
16 |
22 |
23 |
26 |
27 |
32 |
33 |
41 |
42 |
46 |
47 |
51 |
52 |
57 |
58 |
59 |
63 |
64 |
68 |
69 |
74 |
75 |
79 |
80 |
84 |
85 |
90 |
91 |
92 |
96 |
97 |
101 |
102 |
103 |
104 |
108 |
109 |
114 |
115 |
120 |
121 |
125 |
126 |
131 |
132 |
136 |
137 |
142 |
143 |
147 |
148 |
153 |
157 |
158 |
163 |
164 |
165 |
166 |
170 |
171 |
175 |
176 |
181 |
182 |
183 |
187 |
188 |
192 |
193 |
198 |
199 |
200 |
204 |
205 |
209 |
210 |
215 |
216 |
217 |
221 |
222 |
226 |
227 |
232 |
233 |
234 |
235 |
236 |
247 |
248 |
257 |
258 |
268 |
269 |
276 |
277 |
289 |
290 |
299 |
300 |
307 |
308 |
314 |
315 |
323 |
324 |
325 |
--------------------------------------------------------------------------------
/TangoUtils/src/com/kitware/tangoutils/Renderer.java:
--------------------------------------------------------------------------------
1 | package com.kitware.tangoutils;
2 |
3 | import android.opengl.Matrix;
4 | import android.util.Log;
5 | import android.view.MotionEvent;
6 |
7 | public class Renderer {
8 |
9 | protected static final int FIRST_PERSON = 0;
10 | protected static final int TOP_DOWN = 1;
11 | protected static final int THIRD_PERSON = 2;
12 | protected static final int THIRD_PERSON_FOV = 65;
13 | protected static final int TOPDOWN_FOV = 65;
14 | protected static final int MATRIX_4X4 = 16;
15 |
16 | protected static final float CAMERA_FOV = 37.8f;
17 | protected static final float CAMERA_NEAR = 0.01f;
18 | protected static final float CAMERA_FAR = 200f;
19 | protected float mCameraAspect;
20 | protected float[] mProjectionMatrix = new float[MATRIX_4X4];
21 | private ModelMatCalculator mModelMatCalculator;
22 | private int viewId = 2;
23 | protected float[] mViewMatrix = new float[MATRIX_4X4];
24 | protected float[] mCameraPosition;
25 | protected float[] mLookAtPosition;
26 | protected float[] mCameraUpVector;
27 | private float[] mDevicePosition;
28 | private float mCameraOrbitRadius;
29 | private float mRotationX;
30 | private float mRotationY;
31 | private float mPreviousRotationX;
32 | private float mPreviousRotationY;
33 | private float mPreviousTouchX;
34 | private float mPreviousTouchY;
35 | private float mTouch1X, mTouch2X, mTouch1Y, mTouch2Y, mTouchStartDistance,
36 | mTouchMoveDistance, mStartCameraRadius;
37 |
38 | public Renderer() {
39 | mModelMatCalculator = new ModelMatCalculator();
40 | mRotationX = (float) Math.PI / 4;
41 | mRotationY = 0;
42 | mCameraOrbitRadius = 5.0f;
43 | mCameraPosition = new float[3];
44 | mCameraPosition[0] = 5f;
45 | mCameraPosition[1] = 5f;
46 | mCameraPosition[2] = 5f;
47 | mDevicePosition = new float[3];
48 | mDevicePosition[0] = 0;
49 | mDevicePosition[1] = 0;
50 | mDevicePosition[2] = 0;
51 | }
52 |
53 | /**
54 | * Update the view matrix of the Renderer to follow the position of the
55 | * device in the current perspective.
56 | */
57 | public void updateViewMatrix() {
58 | mDevicePosition = mModelMatCalculator.getTranslation();
59 |
60 | switch (viewId) {
61 | case FIRST_PERSON:
62 | float[] invertModelMat = new float[MATRIX_4X4];
63 | Matrix.setIdentityM(invertModelMat, 0);
64 |
65 | float[] temporaryMatrix = new float[MATRIX_4X4];
66 | Matrix.setIdentityM(temporaryMatrix, 0);
67 |
68 | Matrix.setIdentityM(mViewMatrix, 0);
69 | Matrix.invertM(invertModelMat, 0,
70 | mModelMatCalculator.getModelMatrix(), 0);
71 | Matrix.multiplyMM(temporaryMatrix, 0, mViewMatrix, 0,
72 | invertModelMat, 0);
73 | System.arraycopy(temporaryMatrix, 0, mViewMatrix, 0, 16);
74 | break;
75 | case THIRD_PERSON:
76 |
77 | Matrix.setLookAtM(mViewMatrix, 0, mDevicePosition[0]
78 | + mCameraPosition[0], mCameraPosition[1]
79 | + mDevicePosition[1], mCameraPosition[2]
80 | + mDevicePosition[2], mDevicePosition[0],
81 | mDevicePosition[1], mDevicePosition[2], 0f, 1f, 0f);
82 | break;
83 | case TOP_DOWN:
84 | // Matrix.setIdentityM(mViewMatrix, 0);
85 | Matrix.setLookAtM(mViewMatrix, 0, mDevicePosition[0]
86 | + mCameraPosition[0], mCameraPosition[1],
87 | mCameraPosition[2] + mDevicePosition[2], mDevicePosition[0]
88 | + mCameraPosition[0], mCameraPosition[1] - 5,
89 | mCameraPosition[2] + mDevicePosition[2], 0f, 0f, -1f);
90 | break;
91 | default:
92 | viewId = THIRD_PERSON;
93 | return;
94 | }
95 | }
96 |
97 | public boolean onTouchEvent(MotionEvent event) {
98 | if (viewId == THIRD_PERSON) {
99 | int pointCount = event.getPointerCount();
100 | if (pointCount == 1) {
101 | switch (event.getAction()) {
102 | case MotionEvent.ACTION_DOWN: {
103 | final float x = event.getX();
104 | final float y = event.getY();
105 | // Remember where we started
106 | mPreviousTouchX = x;
107 | mPreviousTouchY = y;
108 | mPreviousRotationX = mRotationX;
109 | mPreviousRotationY = mRotationY;
110 | break;
111 | }
112 | case MotionEvent.ACTION_MOVE: {
113 | final float x = event.getX();
114 | final float y = event.getY();
115 | // Calculate the distance moved
116 | final float dx = mPreviousTouchX - x;
117 | final float dy = mPreviousTouchY - y;
118 | mRotationX = mPreviousRotationX
119 | + (float) (Math.PI * dx / 1900); // ScreenWidth
120 | mRotationY = mPreviousRotationY
121 | + (float) (Math.PI * dy / 1200); // Screen height
122 | if (mRotationY > (float) Math.PI)
123 | mRotationY = (float) Math.PI;
124 | if (mRotationY < 0)
125 | mRotationY = 0.0f;
126 | mCameraPosition[0] = (float) (mCameraOrbitRadius * Math
127 | .sin(mRotationX));
128 | mCameraPosition[1] = (float) (mCameraOrbitRadius * Math
129 | .cos(mRotationY));
130 | mCameraPosition[2] = (float) (mCameraOrbitRadius * Math
131 | .cos(mRotationX));
132 | break;
133 | }
134 | }
135 | }
136 | if (pointCount == 2) {
137 | switch (event.getActionMasked()) {
138 | case MotionEvent.ACTION_DOWN:
139 | case MotionEvent.ACTION_POINTER_DOWN: {
140 | mTouch1X = event.getX(0);
141 | mTouch1Y = event.getY(0);
142 | mTouch2X = event.getX(1);
143 | mTouch2Y = event.getY(1);
144 | mTouchStartDistance = (float) Math.sqrt(Math.pow(mTouch1X
145 | - mTouch2X, 2)
146 | + Math.pow(mTouch1Y - mTouch2Y, 2));
147 | mStartCameraRadius = mCameraOrbitRadius;
148 | break;
149 | }
150 | case MotionEvent.ACTION_MOVE: {
151 | mTouch1X = event.getX(0);
152 | mTouch1Y = event.getY(0);
153 | mTouch2X = event.getX(1);
154 | mTouch2Y = event.getY(1);
155 | mTouchMoveDistance = (float) Math.sqrt(Math.pow(mTouch1X
156 | - mTouch2X, 2)
157 | + Math.pow(mTouch1Y - mTouch2Y, 2));
158 | float tmp = 0.05f * (mTouchMoveDistance - mTouchStartDistance);
159 | mCameraOrbitRadius = mStartCameraRadius - tmp;
160 | if (mCameraOrbitRadius < 1)
161 | mCameraOrbitRadius = 1;
162 | mCameraPosition[0] = (float) (mCameraOrbitRadius * Math
163 | .sin(mRotationX));
164 | mCameraPosition[1] = (float) (mCameraOrbitRadius * Math
165 | .cos(mRotationY));
166 | mCameraPosition[2] = (float) (mCameraOrbitRadius * Math
167 | .cos(mRotationX));
168 | break;
169 | }
170 | case MotionEvent.ACTION_POINTER_UP: {
171 | int index = event.getActionIndex() == 0 ? 1 : 0;
172 | final float x = event.getX(index);
173 | final float y = event.getY(index);
174 | // Remember where we started
175 | mPreviousTouchX = x;
176 | mPreviousTouchY = y;
177 | mPreviousRotationX = mRotationX;
178 | mPreviousRotationY = mRotationY;
179 | }
180 | }
181 | }
182 | } else if (viewId == TOP_DOWN) {
183 | int pointCount = event.getPointerCount();
184 | if (pointCount == 1) {
185 | switch (event.getAction()) {
186 | case MotionEvent.ACTION_DOWN: {
187 | final float x = event.getX();
188 | final float y = event.getY();
189 | // Remember where we started
190 | mPreviousTouchX = x;
191 | mPreviousTouchY = y;
192 | mPreviousRotationX = mCameraPosition[0];
193 | mPreviousRotationY = mCameraPosition[2];
194 | break;
195 | }
196 | case MotionEvent.ACTION_MOVE: {
197 | final float x = event.getX();
198 | final float y = event.getY();
199 | // Calculate the distance moved
200 | final float dx = mPreviousTouchX - x;
201 | final float dy = mPreviousTouchY - y;
202 | mCameraPosition[0] = mPreviousRotationX + dx / 190;
203 | mCameraPosition[2] = mPreviousRotationY + dy / 120;
204 | break;
205 | }
206 | }
207 | }
208 | if (pointCount == 2) {
209 | switch (event.getActionMasked()) {
210 | case MotionEvent.ACTION_DOWN:
211 | case MotionEvent.ACTION_POINTER_DOWN: {
212 | mTouch1X = event.getX(0);
213 | mTouch1Y = event.getY(0);
214 | mTouch2X = event.getX(1);
215 | mTouch2Y = event.getY(1);
216 | mTouchStartDistance = (float) Math.sqrt(Math.pow(mTouch1X
217 | - mTouch2X, 2)
218 | + Math.pow(mTouch1Y - mTouch2Y, 2));
219 | mStartCameraRadius = mCameraPosition[1];
220 | Log.i("Start Radius is :", "" + mStartCameraRadius);
221 | break;
222 | }
223 | case MotionEvent.ACTION_MOVE: {
224 | mTouch1X = event.getX(0);
225 | mTouch1Y = event.getY(0);
226 | mTouch2X = event.getX(1);
227 | mTouch2Y = event.getY(1);
228 | mTouchMoveDistance = (float) Math.sqrt(Math.pow(mTouch1X
229 | - mTouch2X, 2)
230 | + Math.pow(mTouch1Y - mTouch2Y, 2));
231 | float tmp = 0.05f * (mTouchMoveDistance - mTouchStartDistance);
232 | mCameraPosition[1] = mStartCameraRadius - tmp;
233 | break;
234 | }
235 | case MotionEvent.ACTION_POINTER_UP: {
236 | int index = event.getActionIndex() == 0 ? 1 : 0;
237 | final float x = event.getX(index);
238 | final float y = event.getY(index);
239 | // Remember where we started
240 | mPreviousTouchX = x;
241 | mPreviousTouchY = y;
242 | mPreviousRotationX = mCameraPosition[0];
243 | mPreviousRotationY = mCameraPosition[2];
244 | }
245 | }
246 | }
247 | }
248 | return true;
249 | }
250 |
251 | public void setFirstPersonView() {
252 | viewId = FIRST_PERSON;
253 | Matrix.perspectiveM(mProjectionMatrix, 0, CAMERA_FOV, mCameraAspect,
254 | CAMERA_NEAR, CAMERA_FAR);
255 | }
256 |
257 | public void setThirdPersonView() {
258 | viewId = THIRD_PERSON;
259 | mCameraPosition[0] = 5;
260 | mCameraPosition[1] = 5;
261 | mCameraPosition[2] = 5;
262 | mRotationX = mRotationY = (float) (Math.PI / 4);
263 | mCameraOrbitRadius = 5.0f;
264 | Matrix.perspectiveM(mProjectionMatrix, 0, THIRD_PERSON_FOV,
265 | mCameraAspect, CAMERA_NEAR, CAMERA_FAR);
266 | }
267 |
268 | public void setTopDownView() {
269 | viewId = TOP_DOWN;
270 | mCameraPosition[0] = 0;
271 | mCameraPosition[1] = 5;
272 | mCameraPosition[2] = 0;
273 | Matrix.perspectiveM(mProjectionMatrix, 0, TOPDOWN_FOV, mCameraAspect,
274 | CAMERA_NEAR, CAMERA_FAR);
275 | }
276 |
277 | public void resetModelMatCalculator() {
278 | mModelMatCalculator = new ModelMatCalculator();
279 | }
280 |
281 | public ModelMatCalculator getModelMatCalculator() {
282 | return mModelMatCalculator;
283 | }
284 |
285 | public float[] getViewMatrix() {
286 | return mViewMatrix;
287 | }
288 |
289 | public float[] getProjectionMatrix() {
290 | return mProjectionMatrix;
291 | }
292 |
293 | }
294 |
--------------------------------------------------------------------------------
/ParaViewPlugins/python_filter_generator.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | import inspect
4 | import textwrap
5 |
6 |
7 | def escapeForXmlAttribute(s):
8 |
9 | # http://www.w3.org/TR/2000/WD-xml-c14n-20000119.html#charescaping
10 | # In character data and attribute values, the character information items "<" and "&" are represented by "<" and "&" respectively.
11 | # In attribute values, the double-quote character information item (") is represented by """.
12 | # In attribute values, the character information items TAB (#x9), newline (#xA), and carriage-return (#xD) are represented by " ", "
", and "
" respectively.
13 |
14 | s = s.replace('&', '&') # Must be done first!
15 | s = s.replace('<', '<')
16 | s = s.replace('>', '>')
17 | s = s.replace('"', '"')
18 | s = s.replace('\r', '
')
19 | s = s.replace('\n', '
')
20 | s = s.replace('\t', ' ')
21 | return s
22 |
23 |
24 |
25 | def getScriptPropertiesXml(info):
26 |
27 | e = escapeForXmlAttribute
28 |
29 | requestData = e(info['RequestData'])
30 | requestInformation = e(info['RequestInformation'])
31 | requestUpdateExtent = e(info['RequestUpdateExtent'])
32 |
33 | if requestData:
34 | requestData = '''
35 |
41 |
42 |
43 |
44 | This property contains the text of a python program that
45 | the programmable source runs.
46 | ''' % requestData
47 |
48 | if requestInformation:
49 | requestInformation = '''
50 |
57 |
58 |
59 |
60 | This property is a python script that is executed during
61 | the RequestInformation pipeline pass. Use this to provide information
62 | such as WHOLE_EXTENT to the pipeline downstream.
63 | ''' % requestInformation
64 |
65 | if requestUpdateExtent:
66 | requestUpdateExtent = '''
67 |
74 |
75 |
76 |
77 | This property is a python script that is executed during
78 | the RequestUpdateExtent pipeline pass. Use this to modify the update
79 | extent that your filter ask up stream for.
80 | ''' % requestUpdateExtent
81 |
82 | return '\n'.join([requestData, requestInformation, requestUpdateExtent])
83 |
84 |
85 |
86 | def getPythonPathProperty():
87 | return '''
88 |
92 | A semi-colon (;) separated list of directories to add to
93 | the python library search path.
94 | '''
95 |
96 |
97 |
98 | def getFilterPropertyXml(propertyInfo, propertyName):
99 |
100 | e = escapeForXmlAttribute
101 |
102 | propertyValue = propertyInfo[propertyName]
103 | propertyLabel = propertyName.replace('_', ' ')
104 |
105 | if isinstance(propertyValue, dict):
106 | # A dictionary that contains 'type' and 'default' keys overrides
107 | # any inferred propertyType with 'type'
108 | if propertyValue.has_key('type') and propertyValue.has_key('default'):
109 | numberOfElements = propertyValue['length'] if propertyValue.has_key('length') else 1
110 | propertyDoc = propertyValue['doc'] if propertyValue.has_key('doc') else ''
111 | if propertyValue['type'] == 'file':
112 | propertyType = file
113 | elif propertyValue['type'] == 'float':
114 | propertyType = float
115 | rangeSpec = ''
116 | if propertyValue.has_key('min'):
117 | rangeSpec += ' min="%s"' % str(propertyValue['min'])
118 | if propertyValue.has_key('max'):
119 | rangeSpec += ' max="%s"' % str(propertyValue['max'])
120 | propertyDomain = """""" % rangeSpec
121 | elif propertyValue['type'] == 'int':
122 | propertyType = int
123 | rangeSpec = ''
124 | if propertyValue.has_key('min'):
125 | rangeSpec += ' min="%s"' % str(propertyValue['min'])
126 | if propertyValue.has_key('max'):
127 | rangeSpec += ' max="%s"' % str(propertyValue['max'])
128 | propertyDomain = """""" % rangeSpec
129 | elif propertyValue['type'] == 'bool':
130 | propertyType = bool
131 | elif propertyValue['type'] == 'string':
132 | propertyType = str
133 | if propertyValue.has_key('enums'):
134 | propertyDomain = """\n%s""" % (propertyName.lower(), '\n'.join(['' % x for x in propertyValue['enums']]))
135 | else:
136 | propertyDomain = ''
137 | elif propertyValue['type'] == 'list':
138 | propertyType = list
139 | defaultValues = propertyValue['default']
140 | elif isinstance(propertyValue, list):
141 | numberOfElements = len(propertyValue)
142 | assert numberOfElements > 0
143 | propertyType = type(propertyValue[0])
144 | propertyDoc = ''
145 | defaultValues = ' '.join([str(v) for v in propertyValue])
146 | else:
147 | numberOfElements = 1
148 | propertyType = type(propertyValue)
149 | propertyDoc = ''
150 | propertyDomain = ''
151 | defaultValues = str(propertyValue)
152 |
153 | if 'propertyType' not in locals():
154 | print 'Failed to find type for %s' % propertyName
155 |
156 | if propertyType is bool:
157 |
158 | defaultValues = defaultValues.replace('True', '1').replace('False', '0')
159 |
160 | return '''
161 |
169 |
170 | %s
171 | ''' % (propertyName, propertyLabel, propertyName, defaultValues, numberOfElements, propertyDoc)
172 |
173 |
174 | if propertyType is int:
175 | return '''
176 |
184 | %s
185 | %s
186 | ''' % (propertyName, propertyLabel, propertyName, defaultValues, numberOfElements, propertyDomain, propertyDoc)
187 |
188 | if propertyType is float:
189 | return '''
190 |
198 | %s
199 | %s
200 | ''' % (propertyName, propertyLabel, propertyName, defaultValues, numberOfElements, propertyDomain, propertyDoc)
201 |
202 | if propertyType is str:
203 | return '''
204 |
212 | %s
213 | %s
214 | ''' % (propertyName, propertyLabel, propertyName, defaultValues, numberOfElements, propertyDomain, propertyDoc)
215 |
216 | if propertyType is file:
217 | return '''
218 |
226 | %s
227 |
228 | ''' % (propertyName, propertyLabel, propertyName, defaultValues, numberOfElements, propertyDoc)
229 |
230 | raise Exception('Unknown property type: %r' % propertyType)
231 |
232 |
233 | def getFilterPropertiesXml(info):
234 |
235 | propertyInfo = info['Properties']
236 | if type(propertyInfo) == tuple or type(propertyInfo) == list:
237 | propertyDict = {x['name']:x for x in propertyInfo}
238 | order = [x['name'] for x in propertyInfo]
239 | else: # Must be a dictionary; make UI order alphabetical
240 | propertyDict = propertyInfo
241 | order = sorted(propertyDict.keys())
242 |
243 | xml = [getFilterPropertyXml(propertyDict, name) for name in order]
244 | return '\n\n'.join(xml)
245 |
246 |
247 | def getNumberOfInputs(info):
248 | return info.get('NumberOfInputs', 1)
249 |
250 |
251 | def getInputPropertyXml(info):
252 |
253 | numberOfInputs = getNumberOfInputs(info)
254 | if not numberOfInputs:
255 | return ''
256 |
257 |
258 | inputDataType = info.get('InputDataType', 'vtkDataObject')
259 |
260 | inputDataTypeDomain = ''
261 | if inputDataType:
262 | inputDataTypeDomain = '''
263 |
264 |
265 | ''' % inputDataType
266 |
267 | inputPropertyAttributes = 'command="SetInputConnection"'
268 | if numberOfInputs > 1:
269 | inputPropertyAttributes = '''\
270 | clean_command="RemoveAllInputs"
271 | command="AddInputConnection"
272 | multiple_input="1"'''
273 |
274 | inputPropertyXml = '''
275 |
278 |
279 |
280 |
281 |
282 | %s
283 | ''' % (inputPropertyAttributes, inputDataTypeDomain)
284 |
285 | return inputPropertyXml
286 |
287 |
288 | def getOutputDataSetTypeXml(info):
289 |
290 |
291 | outputDataType = info.get('OutputDataType', '')
292 |
293 | typeMap = {
294 |
295 | '' : 8, # same as input
296 | 'vtkPolyData' : 0,
297 | 'vtkStructuredGrid' : 2,
298 | 'vtkRectilinearGrid' : 3,
299 | 'vtkUnstructuredGrid' : 4,
300 | 'vtkImageData' : 6,
301 | 'vtkUniformGrid' : 10,
302 | 'vtkMultiblockDataSet' : 13,
303 | 'vtkHierarchicalBoxDataSet' : 15,
304 | 'vtkTable' : 19
305 | }
306 |
307 | typeValue = typeMap[outputDataType]
308 |
309 | return '''
310 |
311 |
316 | The value of this property determines the dataset type
317 | for the output of the programmable filter.
318 | ''' % (outputDataType or 'Same as input', typeValue)
319 |
320 |
321 | def getProxyGroup(info):
322 | return 'sources' if getNumberOfInputs(info) == 0 else 'filters'
323 |
324 |
325 | def generatePythonFilter(info):
326 |
327 |
328 | e = escapeForXmlAttribute
329 |
330 | proxyName = info['Name']
331 | proxyLabel = info['Label']
332 | shortHelp = e(info['Help'])
333 | longHelp = e(info['Help'])
334 | extraXml = info.get('ExtraXml', '')
335 |
336 | proxyGroup = getProxyGroup(info)
337 | inputPropertyXml = getInputPropertyXml(info)
338 | outputDataSetType = getOutputDataSetTypeXml(info)
339 | scriptProperties = getScriptPropertiesXml(info)
340 | filterProperties = getFilterPropertiesXml(info)
341 |
342 |
343 | outputXml = '''\
344 |
345 |
346 |
347 |
348 |
351 |
352 |
353 | %s
354 |
355 | %s
356 |
357 | %s
358 |
359 | %s
360 |
361 | %s
362 |
363 |
364 |
365 |
366 | ''' % (proxyGroup, proxyName, proxyLabel, longHelp, shortHelp, inputPropertyXml,
367 | filterProperties, extraXml, outputDataSetType, scriptProperties)
368 |
369 | return textwrap.dedent(outputXml)
370 |
371 |
372 |
373 |
374 | def replaceFunctionWithSourceString(namespace, functionName, allowEmpty=False):
375 |
376 | func = namespace.get(functionName)
377 | if not func:
378 | if allowEmpty:
379 | namespace[functionName] = ''
380 | return
381 | else:
382 | raise Exception('Function %s not found in input source code.' % functionName)
383 |
384 | if not inspect.isfunction(func):
385 | raise Exception('Object %s is not a function object.' % functionName)
386 |
387 | lines = inspect.getsourcelines(func)[0]
388 |
389 | if len(lines) <= 1:
390 | raise Exception('Function %s must not be a single line of code.' % functionName)
391 |
392 | # skip first line (the declaration) and then dedent the source code
393 | sourceCode = textwrap.dedent(''.join(lines[1:]))
394 |
395 | namespace[functionName] = sourceCode
396 |
397 |
398 | def generatePythonFilterFromFiles(scriptFile, outputFile):
399 |
400 | namespace = {}
401 | execfile(scriptFile, namespace)
402 |
403 | replaceFunctionWithSourceString(namespace, 'RequestData')
404 | replaceFunctionWithSourceString(namespace, 'RequestInformation', allowEmpty=True)
405 | replaceFunctionWithSourceString(namespace, 'RequestUpdateExtent', allowEmpty=True)
406 |
407 | xmlOutput = generatePythonFilter(namespace)
408 |
409 | open(outputFile, 'w').write(xmlOutput)
410 |
411 |
412 | def main():
413 |
414 | if len(sys.argv) != 3:
415 | print 'Usage: %s ' % sys.argv[0]
416 | sys.exit(1)
417 |
418 | inputScript = sys.argv[1]
419 | outputFile = sys.argv[2]
420 |
421 | generatePythonFilterFromFiles(inputScript, outputFile)
422 |
423 |
424 | if __name__ == '__main__':
425 | main()
426 |
427 |
428 |
--------------------------------------------------------------------------------
/ParaViewTangoRecorder/src/com/kitware/tangoproject/paraviewtangorecorder/PointCloudActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | /*
19 | * Additional changes are made by Kitware Inc. and are also licensed under
20 | * the Apache License, Version 2.0 (the "License"):
21 | *
22 | * http://www.apache.org/licenses/LICENSE-2.0
23 | *
24 | */
25 |
26 | package com.kitware.tangoproject.paraviewtangorecorder;
27 |
28 | import com.google.atap.tangoservice.Tango;
29 | import com.google.atap.tangoservice.Tango.OnTangoUpdateListener;
30 | import com.google.atap.tangoservice.TangoConfig;
31 | import com.google.atap.tangoservice.TangoCoordinateFramePair;
32 | import com.google.atap.tangoservice.TangoErrorException;
33 | import com.google.atap.tangoservice.TangoEvent;
34 | import com.google.atap.tangoservice.TangoInvalidException;
35 | import com.google.atap.tangoservice.TangoOutOfDateException;
36 | import com.google.atap.tangoservice.TangoPoseData;
37 | import com.google.atap.tangoservice.TangoXyzIjData;
38 | import com.kitware.tangoutils.ModelMatCalculator;
39 |
40 | import android.app.Activity;
41 | import android.content.Context;
42 | import android.content.Intent;
43 | import android.content.pm.PackageInfo;
44 | import android.content.pm.PackageManager.NameNotFoundException;
45 | import android.net.Uri;
46 | import android.opengl.GLSurfaceView;
47 | import android.opengl.Matrix;
48 | import android.os.AsyncTask;
49 | import android.os.Bundle;
50 | import android.os.Environment;
51 | import android.support.v4.content.FileProvider;
52 | import android.util.Log;
53 | import android.view.MotionEvent;
54 | import android.view.View;
55 | import android.view.View.OnClickListener;
56 | import android.widget.Button;
57 | import android.widget.CompoundButton;
58 | import android.widget.LinearLayout;
59 | import android.widget.ProgressBar;
60 | import android.widget.Switch;
61 | import android.widget.TextView;
62 | import android.widget.Toast;
63 |
64 | import java.io.BufferedOutputStream;
65 | import java.io.DataOutputStream;
66 | import java.io.File;
67 | import java.io.FileInputStream;
68 | import java.io.FileOutputStream;
69 | import java.io.FileWriter;
70 | import java.io.IOException;
71 | import java.nio.ByteBuffer;
72 | import java.nio.ByteOrder;
73 | import java.text.DecimalFormat;
74 | import java.util.ArrayList;
75 | import java.util.Calendar;
76 | import java.util.concurrent.Semaphore;
77 |
78 | /**
79 | * Main Activity class for the Point Cloud Sample. Handles the connection to the
80 | * {@link Tango} service and propagation of Tango XyzIj data to OpenGL and
81 | * Layout views. OpenGL rendering logic is delegated to the {@link PCrenderer}
82 | * class.
83 | */
84 | public class PointCloudActivity extends Activity implements OnClickListener {
85 |
86 | private static final String TAG = PointCloudActivity.class.getSimpleName();
87 | private static final int SECS_TO_MILLISECS = 1000;
88 | private Tango mTango;
89 | private TangoConfig mConfig;
90 |
91 | private PCRenderer mRenderer;
92 | private GLSurfaceView mGLView;
93 |
94 | private TextView mDeltaTextView;
95 | private TextView mPoseCountTextView;
96 | private TextView mPoseTextView;
97 | private TextView mQuatTextView;
98 | private TextView mPoseStatusTextView;
99 | private TextView mTangoEventTextView;
100 | private TextView mPointCountTextView;
101 | private TextView mTangoServiceVersionTextView;
102 | private TextView mApplicationVersionTextView;
103 | private TextView mAverageZTextView;
104 | private TextView mFrequencyTextView;
105 |
106 | private Button mFirstPersonButton;
107 | private Button mThirdPersonButton;
108 | private Button mTopDownButton;
109 |
110 | private int mValidPoseCallbackCount;
111 | private int mPreviousPoseStatus;
112 | private float mDeltaTime;
113 | private float mPosePreviousTimeStamp;
114 | private float mXyIjPreviousTimeStamp;
115 | private float mCurrentTimeStamp;
116 | private String mServiceVersion;
117 | private boolean mIsTangoServiceConnected;
118 |
119 | // My variables
120 | private Button mTakeSnapButton;
121 | private TextView mFilesWrittenToSDCardTextView;
122 | private Switch mAutoModeSwitch;
123 | private Switch mRecordSwitch;
124 | private ProgressBar mWaitingProgressBar;
125 | private TextView mWaitingTextView;
126 | private LinearLayout mWaitingLinearLayout;
127 |
128 | private static final String mMainDirPath = Environment.getExternalStorageDirectory()
129 | .getAbsolutePath() + "/Tango/";
130 | private static final String mSaveDirAbsPath = Environment.getExternalStorageDirectory()
131 | .getAbsolutePath() + "/Tango/MyPointCloudData/";
132 | private String mFilename;
133 | private int mNumberOfFilesWritten;
134 | private Boolean mTimeToTakeSnap;
135 | private Boolean mAutoMode;
136 | private String mNowTimeString;
137 | private ArrayList mPosePositionBuffer;
138 | private ArrayList mPoseOrientationBuffer;
139 | private ArrayList mPoseTimestampBuffer;
140 | private ArrayList mFilenameBuffer;
141 | private float[] cam2dev_Transform;
142 | private int mNumPoseInSequence;
143 | boolean mIsRecording;
144 | private int mXyzIjCallbackCount;
145 | private Semaphore mutex_on_mIsRecording;
146 | private boolean mAppIsStarting;
147 | // End of My variables
148 |
149 | @Override
150 | protected void onCreate(Bundle savedInstanceState) {
151 | super.onCreate(savedInstanceState);
152 | setContentView(R.layout.activity_jpoint_cloud);
153 | setTitle(R.string.app_name);
154 |
155 | mPoseTextView = (TextView) findViewById(R.id.pose);
156 | mQuatTextView = (TextView) findViewById(R.id.quat);
157 | mPoseCountTextView = (TextView) findViewById(R.id.posecount);
158 | mDeltaTextView = (TextView) findViewById(R.id.deltatime);
159 | mTangoEventTextView = (TextView) findViewById(R.id.tangoevent);
160 | mPoseStatusTextView = (TextView) findViewById(R.id.status);
161 | mPointCountTextView = (TextView) findViewById(R.id.pointCount);
162 | mTangoServiceVersionTextView = (TextView) findViewById(R.id.version);
163 | mApplicationVersionTextView = (TextView) findViewById(R.id.appversion);
164 | mAverageZTextView = (TextView) findViewById(R.id.averageZ);
165 | mFrequencyTextView = (TextView) findViewById(R.id.frameDelta);
166 |
167 | mFirstPersonButton = (Button) findViewById(R.id.first_person_button);
168 | mFirstPersonButton.setOnClickListener(this);
169 | mThirdPersonButton = (Button) findViewById(R.id.third_person_button);
170 | mThirdPersonButton.setOnClickListener(this);
171 | mTopDownButton = (Button) findViewById(R.id.top_down_button);
172 | mTopDownButton.setOnClickListener(this);
173 |
174 | mTango = new Tango(this);
175 | mConfig = mTango.getConfig(TangoConfig.CONFIG_TYPE_CURRENT);
176 | mConfig.putBoolean(TangoConfig.KEY_BOOLEAN_DEPTH, true);
177 |
178 | int maxDepthPoints = mConfig.getInt("max_point_cloud_elements");
179 | mRenderer = new PCRenderer(maxDepthPoints);
180 | mGLView = (GLSurfaceView) findViewById(R.id.gl_surface_view);
181 | mGLView.setEGLContextClientVersion(2);
182 | mGLView.setRenderer(mRenderer);
183 | mGLView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
184 |
185 | PackageInfo packageInfo;
186 | try {
187 | packageInfo = this.getPackageManager().getPackageInfo(
188 | this.getPackageName(), 0);
189 | mApplicationVersionTextView.setText(packageInfo.versionName);
190 | } catch (NameNotFoundException e) {
191 | e.printStackTrace();
192 | }
193 |
194 | // Display the version of Tango Service
195 | mServiceVersion = mConfig.getString("tango_service_library_version");
196 | mTangoServiceVersionTextView.setText(mServiceVersion);
197 | mIsTangoServiceConnected = false;
198 |
199 | // My initializations
200 | mTakeSnapButton = (Button) findViewById(R.id.take_snap_button);
201 | mTakeSnapButton.setOnClickListener(this);
202 | mFilesWrittenToSDCardTextView = (TextView) findViewById(R.id.fileWritten);
203 | mAutoModeSwitch = (Switch) findViewById(R.id.auto_mode_switch);
204 | mAutoModeSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
205 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
206 | autoMode_SwitchChanged(isChecked);
207 | }
208 | });
209 | mRecordSwitch = (Switch) findViewById(R.id.record_switch);
210 | mRecordSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
211 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
212 | record_SwitchChanged(isChecked);
213 | }
214 | });
215 | mWaitingProgressBar = (ProgressBar) findViewById(R.id.progressBar);
216 | mWaitingProgressBar.setVisibility(View.VISIBLE);
217 | mWaitingTextView = (TextView) findViewById(R.id.waitingTextView);
218 | mWaitingTextView.setVisibility(View.VISIBLE);
219 | mWaitingTextView.setText(R.string.waitInitialize);
220 | mWaitingLinearLayout = (LinearLayout) findViewById(R.id.waitingBarLayout);
221 | mWaitingLinearLayout.setVisibility(View.VISIBLE);
222 |
223 | mFilename = "";
224 | mNumberOfFilesWritten = 0;
225 | mTimeToTakeSnap = false;
226 | mTakeSnapButton.setEnabled(false);
227 | mAutoMode = false;
228 | mAutoModeSwitch.setChecked(false);
229 | mIsRecording = false;
230 | mRecordSwitch.setChecked(false);
231 | mPosePositionBuffer = new ArrayList();
232 | mPoseOrientationBuffer = new ArrayList();
233 | mPoseTimestampBuffer = new ArrayList();
234 | mFilenameBuffer = new ArrayList();
235 | mNumPoseInSequence = 0;
236 | mXyzIjCallbackCount = 0;
237 | mutex_on_mIsRecording = new Semaphore(1,true);
238 | mAppIsStarting = true;
239 | // End of My initializations
240 | }
241 |
242 | @Override
243 | protected void onPause() {
244 | super.onPause();
245 | try {
246 | mTango.disconnect();
247 | mIsTangoServiceConnected = false;
248 | } catch (TangoErrorException e) {
249 | Toast.makeText(getApplicationContext(), R.string.TangoError,
250 | Toast.LENGTH_SHORT).show();
251 | }
252 | }
253 |
254 | @Override
255 | protected void onResume() {
256 | super.onResume();
257 | if (!mIsTangoServiceConnected) {
258 | startActivityForResult(
259 | Tango.getRequestPermissionIntent(Tango.PERMISSIONTYPE_MOTION_TRACKING),
260 | Tango.TANGO_INTENT_ACTIVITYCODE);
261 | }
262 | Log.i(TAG, "onResumed");
263 | }
264 |
265 | @Override
266 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
267 | // Check which request we're responding to
268 | if (requestCode == Tango.TANGO_INTENT_ACTIVITYCODE) {
269 | Log.i(TAG, "Triggered");
270 | // Make sure the request was successful
271 | if (resultCode == RESULT_CANCELED) {
272 | Toast.makeText(this, R.string.motiontrackingpermission,
273 | Toast.LENGTH_LONG).show();
274 | finish();
275 | return;
276 | }
277 | try {
278 | setTangoListeners();
279 | } catch (TangoErrorException e) {
280 | Toast.makeText(this, R.string.TangoError, Toast.LENGTH_SHORT)
281 | .show();
282 | } catch (SecurityException e) {
283 | Toast.makeText(getApplicationContext(),
284 | R.string.motiontrackingpermission, Toast.LENGTH_SHORT)
285 | .show();
286 | }
287 | try {
288 | mTango.connect(mConfig);
289 | mIsTangoServiceConnected = true;
290 | } catch (TangoOutOfDateException e) {
291 | Toast.makeText(getApplicationContext(),
292 | R.string.TangoOutOfDateException, Toast.LENGTH_SHORT)
293 | .show();
294 | } catch (TangoErrorException e) {
295 | Toast.makeText(getApplicationContext(), R.string.TangoError,
296 | Toast.LENGTH_SHORT).show();
297 | }
298 | setUpExtrinsics();
299 | }
300 | }
301 |
302 | @Override
303 | protected void onDestroy() {
304 | super.onDestroy();
305 | }
306 |
307 | @Override
308 | public void onClick(View v) {
309 | switch (v.getId()) {
310 | case R.id.first_person_button:
311 | mRenderer.setFirstPersonView();
312 | break;
313 | case R.id.third_person_button:
314 | mRenderer.setThirdPersonView();
315 | break;
316 | case R.id.top_down_button:
317 | mRenderer.setTopDownView();
318 | break;
319 | case R.id.take_snap_button:
320 | takeSnapshot_ButtonClicked();
321 | break;
322 | default:
323 | Log.w(TAG, "Unrecognized button click.");
324 | break;
325 | }
326 | }
327 |
328 | @Override
329 | public boolean onTouchEvent(MotionEvent event) {
330 | return mRenderer.onTouchEvent(event);
331 | }
332 |
333 | private void setUpExtrinsics() {
334 | // Set device to imu matrix in Model Matrix Calculator.
335 | TangoPoseData device2IMUPose = new TangoPoseData();
336 | TangoCoordinateFramePair framePair = new TangoCoordinateFramePair();
337 | framePair.baseFrame = TangoPoseData.COORDINATE_FRAME_IMU;
338 | framePair.targetFrame = TangoPoseData.COORDINATE_FRAME_DEVICE;
339 | try {
340 | device2IMUPose = mTango.getPoseAtTime(0.0, framePair);
341 | } catch (TangoErrorException e) {
342 | Toast.makeText(getApplicationContext(), R.string.TangoError,
343 | Toast.LENGTH_SHORT).show();
344 | }
345 | mRenderer.getModelMatCalculator().SetDevice2IMUMatrix(
346 | device2IMUPose.getTranslationAsFloats(),
347 | device2IMUPose.getRotationAsFloats());
348 |
349 | // Set color camera to imu matrix in Model Matrix Calculator.
350 | TangoPoseData color2IMUPose = new TangoPoseData();
351 |
352 | framePair.baseFrame = TangoPoseData.COORDINATE_FRAME_IMU;
353 | framePair.targetFrame = TangoPoseData.COORDINATE_FRAME_CAMERA_COLOR;
354 | try {
355 | color2IMUPose = mTango.getPoseAtTime(0.0, framePair);
356 | } catch (TangoErrorException e) {
357 | Toast.makeText(getApplicationContext(), R.string.TangoError,
358 | Toast.LENGTH_SHORT).show();
359 | }
360 | mRenderer.getModelMatCalculator().SetColorCamera2IMUMatrix(
361 | color2IMUPose.getTranslationAsFloats(),
362 | color2IMUPose.getRotationAsFloats());
363 |
364 | // Get the Camera2Device transform
365 | float[] rot_Dev2IMU = device2IMUPose.getRotationAsFloats();
366 | float[] trans_Dev2IMU = device2IMUPose.getTranslationAsFloats();
367 | float[] rot_Cam2IMU = color2IMUPose.getRotationAsFloats();
368 | float[] trans_Cam2IMU = color2IMUPose.getTranslationAsFloats();
369 |
370 | float[] dev2IMU = new float[16];
371 | Matrix.setIdentityM(dev2IMU, 0);
372 | dev2IMU = ModelMatCalculator.quaternionMatrixOpenGL(rot_Dev2IMU);
373 | dev2IMU[12] += trans_Dev2IMU[0];
374 | dev2IMU[13] += trans_Dev2IMU[1];
375 | dev2IMU[14] += trans_Dev2IMU[2];
376 |
377 | float[] IMU2dev = new float[16];
378 | Matrix.setIdentityM(IMU2dev, 0);
379 | Matrix.invertM(IMU2dev, 0, dev2IMU, 0);
380 |
381 | float[] cam2IMU = new float[16];
382 | Matrix.setIdentityM(cam2IMU, 0);
383 | cam2IMU = ModelMatCalculator.quaternionMatrixOpenGL(rot_Cam2IMU);
384 | cam2IMU[12] += trans_Cam2IMU[0];
385 | cam2IMU[13] += trans_Cam2IMU[1];
386 | cam2IMU[14] += trans_Cam2IMU[2];
387 |
388 | cam2dev_Transform = new float[16];
389 | Matrix.setIdentityM(cam2dev_Transform, 0);
390 | Matrix.multiplyMM(cam2dev_Transform, 0, IMU2dev, 0, cam2IMU, 0);
391 | }
392 |
393 | private void setTangoListeners() {
394 | // Configure the Tango coordinate frame pair
395 | final ArrayList framePairs =
396 | new ArrayList();
397 | framePairs.add(new TangoCoordinateFramePair(
398 | TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE,
399 | TangoPoseData.COORDINATE_FRAME_DEVICE));
400 | // Listen for new Tango data
401 | mTango.connectListener(framePairs, new OnTangoUpdateListener() {
402 |
403 | @Override
404 | public void onPoseAvailable(final TangoPoseData pose) {
405 | mDeltaTime = (float) (pose.timestamp - mPosePreviousTimeStamp)
406 | * SECS_TO_MILLISECS;
407 | mPosePreviousTimeStamp = (float) pose.timestamp;
408 | if (mPreviousPoseStatus != pose.statusCode) {
409 | mValidPoseCallbackCount = 0;
410 | }
411 | mValidPoseCallbackCount++;
412 | mPreviousPoseStatus = pose.statusCode;
413 |
414 | // My pose buffering
415 | if (mIsRecording && pose.statusCode == TangoPoseData.POSE_VALID) {
416 | mPosePositionBuffer.add(mNumPoseInSequence, pose.getTranslationAsFloats());
417 | mPoseOrientationBuffer.add(mNumPoseInSequence, pose.getRotationAsFloats());
418 | mPoseTimestampBuffer.add((float)pose.timestamp);
419 | mNumPoseInSequence++;
420 | }
421 | //End of My pose buffering
422 |
423 | mRenderer.getModelMatCalculator().updateModelMatrix(
424 | pose.getTranslationAsFloats(),
425 | pose.getRotationAsFloats());
426 | mRenderer.updateViewMatrix();
427 | mGLView.requestRender();
428 | // Update the UI with TangoPose information
429 | runOnUiThread(new Runnable() {
430 | @Override
431 | public void run() {
432 | DecimalFormat threeDec = new DecimalFormat("0.000");
433 | String translationString = "["
434 | + threeDec.format(pose.translation[0]) + ", "
435 | + threeDec.format(pose.translation[1]) + ", "
436 | + threeDec.format(pose.translation[2]) + "] ";
437 | String quaternionString = "["
438 | + threeDec.format(pose.rotation[0]) + ", "
439 | + threeDec.format(pose.rotation[1]) + ", "
440 | + threeDec.format(pose.rotation[2]) + ", "
441 | + threeDec.format(pose.rotation[3]) + "] ";
442 |
443 | // Display pose data on screen in TextViews
444 | mPoseTextView.setText(translationString);
445 | mQuatTextView.setText(quaternionString);
446 | mPoseCountTextView.setText(Integer.toString(mValidPoseCallbackCount));
447 | mDeltaTextView.setText(threeDec.format(mDeltaTime));
448 | if (pose.statusCode == TangoPoseData.POSE_VALID) {
449 | mPoseStatusTextView.setText(R.string.pose_valid);
450 | } else if (pose.statusCode == TangoPoseData.POSE_INVALID) {
451 | mPoseStatusTextView.setText(R.string.pose_invalid);
452 | } else if (pose.statusCode == TangoPoseData.POSE_INITIALIZING) {
453 | mPoseStatusTextView.setText(R.string.pose_initializing);
454 | } else if (pose.statusCode == TangoPoseData.POSE_UNKNOWN) {
455 | mPoseStatusTextView.setText(R.string.pose_unknown);
456 | }
457 | }
458 | });
459 | }
460 |
461 | @Override
462 | public void onXyzIjAvailable(final TangoXyzIjData xyzIj) {
463 | mCurrentTimeStamp = (float) xyzIj.timestamp;
464 | final float frameDelta = (mCurrentTimeStamp - mXyIjPreviousTimeStamp)
465 | * SECS_TO_MILLISECS;
466 | mXyIjPreviousTimeStamp = mCurrentTimeStamp;
467 | mXyzIjCallbackCount++;
468 | final byte[] buffer = new byte[xyzIj.xyzCount * 3 * 4];
469 | FileInputStream fileStream = new FileInputStream(
470 | xyzIj.xyzParcelFileDescriptor.getFileDescriptor());
471 | try {
472 | fileStream.read(buffer, xyzIj.xyzParcelFileDescriptorOffset, buffer.length);
473 | fileStream.close();
474 | } catch (IOException e) {
475 | e.printStackTrace();
476 | }
477 |
478 | // My writing to file function
479 |
480 | // Background task for writing to file
481 | class SendCommandTask extends AsyncTask {
482 | /** The system calls this to perform work in a worker thread and
483 | * delivers it the parameters given to AsyncTask.execute() */
484 | @Override
485 | protected Boolean doInBackground(Void... params) {
486 |
487 | try {
488 | mutex_on_mIsRecording.acquire();
489 | } catch (InterruptedException e) {
490 | e.printStackTrace();
491 | }
492 | // Saving the frame or not, depending on the current mode.
493 | if ( mTimeToTakeSnap || ( mIsRecording && mAutoMode && mXyzIjCallbackCount % 3 == 0 ) ) {
494 | writePointCloudToFile(xyzIj, buffer, framePairs);
495 | }
496 | mutex_on_mIsRecording.release();
497 | return true;
498 | }
499 |
500 | /** The system calls this to perform work in the UI thread and delivers
501 | * the result from doInBackground() */
502 | @Override
503 | protected void onPostExecute(Boolean done) {
504 |
505 | }
506 | }
507 | new SendCommandTask().execute();
508 |
509 |
510 |
511 | // End of My writing to file function
512 |
513 | try {
514 | TangoPoseData pointCloudPose = mTango.getPoseAtTime(
515 | mCurrentTimeStamp, framePairs.get(0));
516 |
517 | mRenderer.getPointCloud().UpdatePoints(buffer,
518 | xyzIj.xyzCount);
519 | mRenderer.getModelMatCalculator()
520 | .updatePointCloudModelMatrix(
521 | pointCloudPose.getTranslationAsFloats(),
522 | pointCloudPose.getRotationAsFloats());
523 | mRenderer.getPointCloud().setModelMatrix(
524 | mRenderer.getModelMatCalculator()
525 | .getPointCloudModelMatrixCopy());
526 | } catch (TangoErrorException e) {
527 | Toast.makeText(getApplicationContext(),
528 | R.string.TangoError, Toast.LENGTH_SHORT).show();
529 | } catch (TangoInvalidException e) {
530 | Toast.makeText(getApplicationContext(),
531 | R.string.TangoError, Toast.LENGTH_SHORT).show();
532 | }
533 |
534 | // Must run UI changes on the UI thread. Running in the Tango
535 | // service thread will result in an error.
536 | runOnUiThread(new Runnable() {
537 | DecimalFormat threeDec = new DecimalFormat("0.000");
538 |
539 | @Override
540 | public void run() {
541 | // Display a waiting progress bar
542 | if(mAppIsStarting) {
543 | mWaitingLinearLayout.setVisibility(View.GONE);
544 | mAppIsStarting = false;
545 | }
546 | // Display number of points in the point cloud
547 | mPointCountTextView.setText(Integer
548 | .toString(xyzIj.xyzCount));
549 | mFrequencyTextView.setText(""
550 | + threeDec.format(frameDelta));
551 | mAverageZTextView.setText(""
552 | + threeDec.format(mRenderer.getPointCloud()
553 | .getAverageZ()));
554 | // My GUI updates
555 | mFilesWrittenToSDCardTextView.setText("" +
556 | String.valueOf(mNumberOfFilesWritten) + "\n" + mFilename);
557 | // End of My GUI updates
558 | }
559 | });
560 | }
561 |
562 | @Override
563 | public void onTangoEvent(final TangoEvent event) {
564 | runOnUiThread(new Runnable() {
565 | @Override
566 | public void run() {
567 | mTangoEventTextView.setText(event.eventKey + ": "
568 | + event.eventValue);
569 | }
570 | });
571 | }
572 | });
573 | }
574 |
575 |
576 | // My functions
577 |
578 | // This function is called when the Take Snapshot button is clicked
579 | private void takeSnapshot_ButtonClicked() {
580 | mTimeToTakeSnap=true;
581 | }
582 |
583 | // This function is called when the Auto Mode Switch is changed
584 | private void autoMode_SwitchChanged(boolean isChecked) {
585 | mAutoMode = isChecked;
586 | }
587 |
588 | // This function is called when the Record Switch is changed
589 | private void record_SwitchChanged(boolean isChecked) {
590 | try {
591 | mutex_on_mIsRecording.acquire();
592 | } catch (InterruptedException e) {
593 | e.printStackTrace();
594 | }
595 | mIsRecording = isChecked;
596 | // Start Recording
597 | if (mIsRecording) {
598 | // Generate a new date number to create a new group of files
599 | Calendar rightNow = Calendar.getInstance();
600 | int hour = rightNow.get(Calendar.HOUR_OF_DAY);
601 | int minute = rightNow.get(Calendar.MINUTE);
602 | int sec = rightNow.get(Calendar.SECOND);
603 | int milliSec = rightNow.get(Calendar.MILLISECOND);
604 | mNowTimeString = "" + (int)(1000000 * hour + 10000 * minute + 100 * sec +
605 | (float)milliSec / 10.0);
606 | mNumberOfFilesWritten = 0;
607 | // Enable snapshot button
608 | mTakeSnapButton.setEnabled(true);
609 | }
610 | // Finish Recording
611 | else {
612 | // Disable snapshot button
613 | mTakeSnapButton.setEnabled(false);
614 | // Display a waiting progress bar
615 | mWaitingTextView.setText(R.string.waitSavingScan);
616 | mWaitingLinearLayout.setVisibility(View.VISIBLE);
617 | // Background task for writing poses to file
618 | class SendCommandTask extends AsyncTask {
619 | /** The system calls this to perform work in a worker thread and
620 | * delivers it the parameters given to AsyncTask.execute() */
621 | @Override
622 | protected Uri doInBackground(Context... myAppContext) {
623 |
624 | // Stop the Pose Recording, and write them to a file.
625 | writePoseToFile(mNumPoseInSequence);
626 | // If a snap has been asked just before, but not saved, ignore it, otherwise,
627 | // it will be saved at the end dof this function, and the 2nd archive will override
628 | // the first.
629 | mTimeToTakeSnap = false;
630 | mNumPoseInSequence = 0;
631 | mPoseOrientationBuffer.clear();
632 | mPoseOrientationBuffer.clear();
633 | mPoseTimestampBuffer.clear();
634 |
635 | // Zip all the files from this sequence
636 | String zipFilename = mSaveDirAbsPath + "TangoData_" + mNowTimeString +
637 | "_" + mFilenameBuffer.size() + "files.zip";
638 | String[] fileList = mFilenameBuffer.toArray(new String[mFilenameBuffer.size()]);
639 | ZipWriter zipper = new ZipWriter(fileList, zipFilename);
640 | zipper.zip();
641 |
642 | // Delete the data files now that they are archived
643 | for (String s : mFilenameBuffer) {
644 | File file = new File(s);
645 | boolean deleted = file.delete();
646 | if (!deleted) {
647 | Log.w(TAG, "File \"" + s + "\" not deleted\n");
648 | }
649 | }
650 | mFilenameBuffer.clear();
651 |
652 | // Send the zip file to another app
653 | File myZipFile = new File(zipFilename);
654 |
655 | return FileProvider.getUriForFile(myAppContext[0], "com.kitware." +
656 | "tangoproject.paraviewtangorecorder.fileprovider", myZipFile);
657 | }
658 |
659 | /** The system calls this to perform work in the UI thread and delivers
660 | * the result from doInBackground() */
661 | @Override
662 | protected void onPostExecute(Uri fileURI) {
663 | Intent shareIntent = new Intent();
664 | shareIntent.setAction(Intent.ACTION_SEND);
665 | shareIntent.putExtra(Intent.EXTRA_STREAM, fileURI);
666 | shareIntent.setType("application/zip");
667 | startActivity(Intent.createChooser(shareIntent, "Send Scan To..."));
668 | mWaitingLinearLayout.setVisibility(View.GONE);
669 | }
670 | }
671 | new SendCommandTask().execute(this);
672 |
673 | }
674 | mutex_on_mIsRecording.release();
675 |
676 | }
677 |
678 | // This function writes the XYZ points to .vtk files in binary
679 | private void writePointCloudToFile(TangoXyzIjData xyzIj, byte[] buffer,
680 | ArrayList framePairs) {
681 |
682 | ByteBuffer myBuffer = ByteBuffer.allocate(xyzIj.xyzCount * 3 * 4);
683 | myBuffer.order(ByteOrder.LITTLE_ENDIAN);
684 | myBuffer.put(buffer, xyzIj.xyzParcelFileDescriptorOffset, myBuffer.capacity());
685 |
686 |
687 | File mainDir = new File(mMainDirPath);
688 | if(!mainDir.exists()) {
689 | boolean created = mainDir.mkdir();
690 | if (created) {
691 | Log.i(TAG, "Folder: \"" + mMainDirPath + "\" created\n");
692 | }
693 | }
694 |
695 | File dir = new File(mSaveDirAbsPath);
696 | if(!dir.exists()) {
697 | boolean created = dir.mkdir();
698 | if (created) {
699 | Log.i(TAG, "Folder: \"" + mSaveDirAbsPath + "\" created\n");
700 | }
701 | }
702 |
703 | mFilename = "pc_" + mNowTimeString + "_" + String.format("%03d", mNumberOfFilesWritten) +
704 | ".vtk";
705 | mFilenameBuffer.add(mSaveDirAbsPath + mFilename);
706 | File file = new File(dir, mFilename);
707 |
708 |
709 | try {
710 |
711 | DataOutputStream out = new DataOutputStream(new BufferedOutputStream(
712 | new FileOutputStream(file)));
713 |
714 | out.write(("# vtk DataFile Version 3.0\n" +
715 | "vtk output\n" +
716 | "BINARY\n" +
717 | "DATASET POLYDATA\n" +
718 | "POINTS " + xyzIj.xyzCount + " float\n").getBytes());
719 |
720 | for (int i = 0; i < xyzIj.xyzCount; i++) {
721 |
722 | out.writeFloat(myBuffer.getFloat(3 * i * 4));
723 | out.writeFloat(myBuffer.getFloat((3 * i + 1) * 4));
724 | out.writeFloat(myBuffer.getFloat((3 * i + 2) * 4));
725 | }
726 |
727 | out.write(("\nVERTICES 1 " + String.valueOf(xyzIj.xyzCount + 1) + "\n").getBytes());
728 | out.writeInt(xyzIj.xyzCount);
729 | for (int i = 0; i < xyzIj.xyzCount; i++) {
730 | out.writeInt(i);
731 | }
732 |
733 | out.write(("\nFIELD FieldData 1\n" + "timestamp 1 1 float\n").getBytes());
734 | out.writeFloat((float) xyzIj.timestamp);
735 |
736 | out.close();
737 | mNumberOfFilesWritten++;
738 | mTimeToTakeSnap = false;
739 |
740 | } catch (IOException e) {
741 | e.printStackTrace();
742 | }
743 | }
744 |
745 | // This function writes the pose data and timestamps to .vtk files in binary
746 | private void writePoseToFile(int numPoints) {
747 |
748 | File mainDir = new File(mMainDirPath);
749 | if(!mainDir.exists()) {
750 | boolean created = mainDir.mkdir();
751 | if (created) {
752 | Log.i(TAG, "Folder: \"" + mMainDirPath + "\" created\n");
753 | }
754 | }
755 |
756 | File dir = new File(mSaveDirAbsPath);
757 | if(!dir.exists()) {
758 | boolean created = dir.mkdir();
759 | if (created) {
760 | Log.i(TAG, "Folder: \"" + mSaveDirAbsPath + "\" created\n");
761 | }
762 | }
763 | String poseFileName = "pc_" + mNowTimeString + "_poses.vtk";
764 | mFilenameBuffer.add(mSaveDirAbsPath + poseFileName);
765 | File file = new File(dir, poseFileName);
766 |
767 | try {
768 | DataOutputStream out = new DataOutputStream(new BufferedOutputStream(
769 | new FileOutputStream(file)));
770 |
771 | out.write(("# vtk DataFile Version 3.0\n" +
772 | "vtk output\n" +
773 | "BINARY\n" +
774 | "DATASET POLYDATA\n" +
775 | "POINTS " + numPoints + " float\n").getBytes());
776 |
777 | for (int i = 0; i < numPoints; i++) {
778 | out.writeFloat(mPosePositionBuffer.get(i)[0]);
779 | out.writeFloat(mPosePositionBuffer.get(i)[1]);
780 | out.writeFloat(mPosePositionBuffer.get(i)[2]);
781 | }
782 |
783 | out.write(("\nLINES 1 " + String.valueOf(numPoints + 1) + "\n").getBytes());
784 | out.writeInt(numPoints);
785 | for (int i = 0; i < numPoints; i++) {
786 | out.writeInt(i);
787 | }
788 |
789 | out.write(("\nFIELD FieldData 1\n" +
790 | "Cam2Dev_transform 16 1 float\n").getBytes());
791 | for (int i = 0; i < cam2dev_Transform.length; i++) {
792 | out.writeFloat(cam2dev_Transform[i]);
793 | }
794 |
795 | out.write(("\nPOINT_DATA " + String.valueOf(numPoints) + "\n" +
796 | "FIELD FieldData 2\n" +
797 | "orientation 4 " + String.valueOf(numPoints) + " float\n").getBytes());
798 |
799 | for (int i = 0; i < numPoints; i++) {
800 | out.writeFloat(mPoseOrientationBuffer.get(i)[0]);
801 | out.writeFloat(mPoseOrientationBuffer.get(i)[1]);
802 | out.writeFloat(mPoseOrientationBuffer.get(i)[2]);
803 | out.writeFloat(mPoseOrientationBuffer.get(i)[3]);
804 | }
805 |
806 | out.write(("\ntimestamp 1 " + String.valueOf(numPoints) + " float\n").getBytes());
807 | for (int i = 0; i < numPoints; i++) {
808 | out.writeFloat(mPoseTimestampBuffer.get(i));
809 | }
810 |
811 | out.close();
812 | } catch (IOException e) {
813 | e.printStackTrace();
814 | }
815 | }
816 |
817 | // End of My functions
818 | }
819 |
--------------------------------------------------------------------------------