diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2019-11-11 15:42:14 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2019-11-11 15:42:14 +0000 |
| commit | ee177d37df85b982d6c528a7b79e3cd9ca9749d6 (patch) | |
| tree | dda6c9b0c2a3f2756c08b71ebaca32644dbc9d32 /NativeApp/Android | |
| parent | Updated HLSL2GLSL converter app (diff) | |
| download | DiligentTools-ee177d37df85b982d6c528a7b79e3cd9ca9749d6.tar.gz DiligentTools-ee177d37df85b982d6c528a7b79e3cd9ca9749d6.zip | |
Moved Native App from master repository
Diffstat (limited to 'NativeApp/Android')
40 files changed, 6821 insertions, 0 deletions
diff --git a/NativeApp/Android/.gitignore b/NativeApp/Android/.gitignore new file mode 100644 index 0000000..8e7c6d9 --- /dev/null +++ b/NativeApp/Android/.gitignore @@ -0,0 +1,4 @@ +/build +/.externalNativeBuild +*.iml +.cxx diff --git a/NativeApp/Android/CMakeLists.txt b/NativeApp/Android/CMakeLists.txt new file mode 100644 index 0000000..87d8f3c --- /dev/null +++ b/NativeApp/Android/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required (VERSION 3.6) + +add_library(native_app_glue ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) +target_link_libraries(native_app_glue log) +target_include_directories(native_app_glue INTERFACE ${ANDROID_NDK}/sources/android/native_app_glue) +set_common_target_properties(native_app_glue) + +add_subdirectory(ndk_helper) diff --git a/NativeApp/Android/android_common.gradle b/NativeApp/Android/android_common.gradle new file mode 100644 index 0000000..5be7b80 --- /dev/null +++ b/NativeApp/Android/android_common.gradle @@ -0,0 +1,12 @@ +android { + compileSdkVersion=28 + + defaultConfig { + minSdkVersion 21 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } +} diff --git a/NativeApp/Android/build.gradle b/NativeApp/Android/build.gradle new file mode 100644 index 0000000..ac62940 --- /dev/null +++ b/NativeApp/Android/build.gradle @@ -0,0 +1,43 @@ +apply plugin: 'com.android.library' +apply from: "android_common.gradle" + +android { + defaultConfig { + + ndk { + abiFilters 'armeabi-v7a'//, 'armeabi', 'arm64-v8a','x86', 'x86_64' + } + externalNativeBuild { + cmake { + arguments '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=c++_static', '-DENABLE_TESTS=TRUE' + } + } + } + + externalNativeBuild { + cmake { + version '3.10.2' + path '../../../CMakeLists.txt' + } + } + + sourceSets { + main { + java.srcDirs = ['src/main/java', 'ndk_helper/src/java'] + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +buildDir './build' + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:28.0.0' +} diff --git a/NativeApp/Android/ndk_helper/CMakeLists.txt b/NativeApp/Android/ndk_helper/CMakeLists.txt new file mode 100644 index 0000000..653847d --- /dev/null +++ b/NativeApp/Android/ndk_helper/CMakeLists.txt @@ -0,0 +1,42 @@ +cmake_minimum_required (VERSION 3.6) + +project(NDKHelper CXX) + +set(SOURCE + src/gestureDetector.cpp + src/JNIHelper.cpp + src/perfMonitor.cpp + src/sensorManager.cpp + src/tapCamera.cpp + src/vecmath.cpp +) + +set(INCLUDE + include/gestureDetector.h + include/JNIHelper.h + include/perfMonitor.h + include/sensorManager.h + include/tapCamera.h +) + +add_library(NDKHelper STATIC ${SOURCE} ${INCLUDE}) +set_common_target_properties(NDKHelper) + +target_include_directories(NDKHelper +PUBLIC + include +) + +target_link_libraries(NDKHelper +PRIVATE + Diligent-BuildSettings +PUBLIC + native_app_glue +) + +source_group("src" FILES ${SOURCE}) +source_group("include" FILES ${INCLUDE}) + +set_target_properties(NDKHelper PROPERTIES + FOLDER Core/External +) diff --git a/NativeApp/Android/ndk_helper/include/GLContext.h b/NativeApp/Android/ndk_helper/include/GLContext.h new file mode 100644 index 0000000..551794f --- /dev/null +++ b/NativeApp/Android/ndk_helper/include/GLContext.h @@ -0,0 +1,115 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//-------------------------------------------------------------------------------- +// GLContext.h +//-------------------------------------------------------------------------------- +#ifndef GLCONTEXT_H_ +#define GLCONTEXT_H_ + +#include <EGL/egl.h> +#include <GLES2/gl2.h> +#include <android/log.h> + +#include "JNIHelper.h" + +namespace ndk_helper { + +//-------------------------------------------------------------------------------- +// Constants +//-------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------- +// Class +//-------------------------------------------------------------------------------- + +/****************************************************************** + * OpenGL context handler + * The class handles OpenGL and EGL context based on Android activity life cycle + * The caller needs to call corresponding methods for each activity life cycle + *events as it's done in sample codes. + * + * Also the class initializes OpenGL ES3 when the compatible driver is installed + *in the device. + * getGLVersion() returns 3.0~ when the device supports OpenGLES3.0 + * + * Thread safety: OpenGL context is expecting used within dedicated single + *thread, + * thus GLContext class is not designed as a thread-safe + */ +class GLContext { + private: + // EGL configurations + ANativeWindow* window_; + EGLDisplay display_; + EGLSurface surface_; + EGLContext context_; + EGLConfig config_; + + // Screen parameters + int32_t screen_width_; + int32_t screen_height_; + int32_t color_size_; + int32_t depth_size_; + + // Flags + bool gles_initialized_; + bool egl_context_initialized_; + bool es3_supported_; + float gl_version_; + bool context_valid_; + + void InitGLES(); + void Terminate(); + bool InitEGLSurface(); + bool InitEGLContext(); + + GLContext(GLContext const&); + void operator=(GLContext const&); + GLContext(); + virtual ~GLContext(); + + public: + static GLContext* GetInstance() { + // Singleton + static GLContext instance; + + return &instance; + } + + bool Init(ANativeWindow* window); + EGLint Swap(); + bool Invalidate(); + + void Suspend(); + EGLint Resume(ANativeWindow* window); + + ANativeWindow* GetANativeWindow(void) const { return window_; }; + int32_t GetScreenWidth() const { return screen_width_; } + int32_t GetScreenHeight() const { return screen_height_; } + + int32_t GetBufferColorSize() const { return color_size_; } + int32_t GetBufferDepthSize() const { return depth_size_; } + float GetGLVersion() const { return gl_version_; } + bool CheckExtension(const char* extension); + + EGLDisplay GetDisplay() const { return display_; } + EGLSurface GetSurface() const { return surface_; } +}; + +} // namespace ndkHelper + +#endif /* GLCONTEXT_H_ */ diff --git a/NativeApp/Android/ndk_helper/include/JNIHelper.h b/NativeApp/Android/ndk_helper/include/JNIHelper.h new file mode 100644 index 0000000..0e69905 --- /dev/null +++ b/NativeApp/Android/ndk_helper/include/JNIHelper.h @@ -0,0 +1,330 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <jni.h> +#include <vector> +#include <string> +#include <functional> +#include <assert.h> +#include <mutex> +#include <pthread.h> + +#include <android/log.h> +#include <android_native_app_glue.h> + +#define LOGI(...) \ + ((void)__android_log_print( \ + ANDROID_LOG_INFO, ndk_helper::JNIHelper::GetInstance()->GetAppName(), \ + __VA_ARGS__)) +#define LOGW(...) \ + ((void)__android_log_print( \ + ANDROID_LOG_WARN, ndk_helper::JNIHelper::GetInstance()->GetAppName(), \ + __VA_ARGS__)) +#define LOGE(...) \ + ((void)__android_log_print( \ + ANDROID_LOG_ERROR, ndk_helper::JNIHelper::GetInstance()->GetAppName(), \ + __VA_ARGS__)) + +namespace ndk_helper { + +class JUIView; + +/****************************************************************** + * Helper functions for JNI calls + * This class wraps JNI calls and provides handy interface calling commonly used + *features + * in Java SDK. + * Such as + * - loading graphics files (e.g. PNG, JPG) + * - character code conversion + * - retrieving system properties which only supported in Java SDK + * + * NOTE: To use this class, add NDKHelper.java as a corresponding helpers in + *Java code + */ +class JNIHelper { + private: + std::string app_name_; + + ANativeActivity* activity_; + jobject jni_helper_java_ref_; + jclass jni_helper_java_class_; + + jstring GetExternalFilesDirJString(JNIEnv* env); + jclass RetrieveClass(JNIEnv* jni, const char* class_name); + + JNIHelper(); + ~JNIHelper(); + JNIHelper(const JNIHelper& rhs); + JNIHelper& operator=(const JNIHelper& rhs); + + std::string app_label_; + + // mutex for synchronization + // This class uses singleton pattern and can be invoked from multiple threads, + // each methods locks the mutex for a thread safety + mutable std::mutex mutex_; + + /* + * Call method in JNIHelper class + */ + jobject CallObjectMethod(const char* strMethodName, const char* strSignature, + ...); + void CallVoidMethod(const char* strMethodName, const char* strSignature, ...); + + /* + * Unregister this thread from the VM + */ + static void DetachCurrentThreadDtor(void* p) { + LOGI("detached current thread"); + ANativeActivity* activity = (ANativeActivity*)p; + activity->vm->DetachCurrentThread(); + } + + public: + /* + * To load your own Java classes, JNIHelper requires to be initialized with a + *ANativeActivity handle. + * This methods need to be called before any call to the helper class. + * Static member of the class + * + * arguments: + * in: activity, pointer to ANativeActivity. Used internally to set up JNI + *environment + * in: helper_class_name, pointer to Java side helper class name. (e.g. + *"com/sample/helper/NDKHelper" in samples ) + */ + static void Init(ANativeActivity* activity, const char* helper_class_name); + + /* + * Init() that accept so name. + * When using a JUI helper class, Java side requires SO name to initialize JNI + * calls to invoke native callbacks. + * Use this version when using JUI helper. + * + * arguments: + * in: activity, pointer to ANativeActivity. Used internally to set up JNI + * environment + * in: helper_class_name, pointer to Java side helper class name. (e.g. + * "com/sample/helper/NDKHelper" in samples ) + * in: native_soname, pointer to soname of native library. (e.g. + * "NativeActivity" for "libNativeActivity.so" ) + */ + static void Init(ANativeActivity* activity, const char* helper_class_name, + const char* native_soname); + + /* + * Retrieve the singleton object of the helper. + * Static member of the class + + * Methods in the class are designed as thread safe. + */ + static JNIHelper* GetInstance(); + + /* + * Read a file from a strorage. + * First, the method tries to read the file from an external storage. + * If it fails to read, it falls back to use assset manager and try to read + * the file from APK asset. + * + * arguments: + * in: file_name, file name to read + * out: buffer_ref, pointer to a vector buffer to read a file. + * when the call succeeded, the buffer includes contents of specified + *file + * when the call failed, contents of the buffer remains same + * return: + * true when file read succeeded + * false when it failed to read the file + */ + bool ReadFile(const char* file_name, std::vector<uint8_t>* buffer_ref); + + /* + * Load and create OpenGL texture from given file name. + * The method invokes BitmapFactory in Java so it can read jpeg/png formatted + * files + * + * The methods creates mip-map and set texture parameters like this, + * glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + * GL_LINEAR_MIPMAP_NEAREST ); + * glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + * glGenerateMipmap( GL_TEXTURE_2D ); + * + * arguments: + * in: file_name, file name to read, PNG&JPG is supported + * outWidth(Optional) pointer to retrieve original bitmap width + * outHeight(Optional) pointer to retrieve original bitmap height + * return: + * OpenGL texture name when the call succeeded + * When it failed to load the texture, it returns -1 + */ + uint32_t LoadTexture(const char* file_name, int32_t* outWidth = nullptr, + int32_t* outHeight = nullptr, bool* hasAlpha = nullptr); + + /* + * Load and create OpenGL cubemap texture from given file name + * into specified cubemap face & miplevel + * The method invokes BitmapFactory in Java so it can read jpeg/png formatted + * files + * + * arguments: + * in: file_name, file name to read, PNG&JPG is supported + * outWidth(Optional) pointer to retrieve original bitmap width + * outHeight(Optional) pointer to retrieve original bitmap height + * return: + * OpenGL texture name when the call succeeded + * When it failed to load the texture, it returns -1 + */ + uint32_t LoadCubemapTexture(const char* file_name, const int32_t face, + const int32_t miplevel, const bool sRGB, + int32_t* outWidth = nullptr, + int32_t* outHeight = nullptr, + bool* hasAlpha = nullptr); + + /* + * Load and create image and return it as a byte array. + * The method invokes BitmapFactory in Java so it can read jpeg/png formatted + * files + * + * arguments: + * in: file_name, file name to read, PNG&JPG is supported + * outWidth(Optional) pointer to retrieve original bitmap width + * outHeight(Optional) pointer to retrieve original bitmap height + * return: + * Java ByteBuffer object containing image data converted to RGBA values. + */ + jobject LoadImage(const char* file_name, int32_t* outWidth = nullptr, + int32_t* outHeight = nullptr, bool* hasAlpha = nullptr); + + /* + * Convert string from character code other than UTF-8 + * + * arguments: + * in: str, pointer to a string which is encoded other than UTF-8 + * in: encoding, pointer to a character encoding string. + * The encoding string can be any valid java.nio.charset.Charset name + * e.g. "UTF-16", "Shift_JIS" + * return: converted input string as an UTF-8 std::string + */ + std::string ConvertString(const char* str, const char* encode); + /* + * Retrieve external file directory through JNI call + * + * return: std::string containing external file diretory + */ + std::string GetExternalFilesDir(); + + /* + * Retrieve string resource with a given name + * arguments: + * in: resourceName, name of string resource to retrieve + * return: string resource value, returns "" when there is no string resource + * with given name + */ + std::string GetStringResource(const std::string& resourceName); + + /* + * Audio helper + * Retrieves native audio buffer size which is required to achieve low latency + * audio + * + * return: Native audio buffer size which is a hint to achieve low latency + * audio + * If the API is not supported (API level < 17), it returns 0 + */ + int32_t GetNativeAudioBufferSize(); + + /* + * Audio helper + * Retrieves native audio sample rate which is required to achieve low latency + * audio + * + * return: Native audio sample rate which is a hint to achieve low latency + * audio + */ + int32_t GetNativeAudioSampleRate(); + + /* + * Retrieves application bundle name + * + * return: pointer to an app name string + * + */ + const char* GetAppName() const { return app_name_.c_str(); } + + /* + * Retrieves application label + * + * return: pointer to an app label string + * + */ + const char* GetAppLabel() const { return app_label_.c_str(); } + + /* + * Execute given function in Java UIThread. + * + * arguments: + * in: pFunction, a pointer to a function to be executed in Java UI Thread. + * Note that the helper function returns immediately without synchronizing a + * function completion. + */ + void RunOnUiThread(std::function<void()> callback); + + /* + * Attach current thread + * In Android, the thread doesn't have to be 'Detach' current thread + * as application process is only killed and VM does not shut down + */ + JNIEnv* AttachCurrentThread() { + JNIEnv* env; + if (activity_->vm->GetEnv((void**)&env, JNI_VERSION_1_4) == JNI_OK) + return env; + activity_->vm->AttachCurrentThread(&env, NULL); + pthread_key_create((int32_t*)activity_, DetachCurrentThreadDtor); + return env; + } + + void DetachCurrentThread() { + activity_->vm->DetachCurrentThread(); + return; + } + + /* + * Decrement a global reference to the object + * arguments: + * in: obj, obj to decrement a global reference + */ + void DeleteObject(jobject obj); + + /* + * Helper methods to call a method in given object + */ + jobject CreateObject(const char* class_name); + jobject CallObjectMethod(jobject object, const char* strMethodName, + const char* strSignature, ...); + void CallVoidMethod(jobject object, const char* strMethodName, + const char* strSignature, ...); + float CallFloatMethod(jobject object, const char* strMethodName, + const char* strSignature, ...); + int32_t CallIntMethod(jobject object, const char* strMethodName, + const char* strSignature, ...); + bool CallBooleanMethod(jobject object, const char* strMethodName, + const char* strSignature, ...); +}; + +} // namespace ndkHelper diff --git a/NativeApp/Android/ndk_helper/include/NDKHelper.h b/NativeApp/Android/ndk_helper/include/NDKHelper.h new file mode 100644 index 0000000..4c979e6 --- /dev/null +++ b/NativeApp/Android/ndk_helper/include/NDKHelper.h @@ -0,0 +1,43 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _NDKSUPPORT_H +#define _NDKSUPPORT_H + +#define NDK_HELPER_VERSION "0.90" + +/****************************************************************** + * NDK support helpers + * Utility module to provide misc functionalities that is used widely in native + * applications, + * such as gesture detection, jni bridge, openGL context etc. + * + * The purpose of this module is, + * - Provide best practices using NDK + * - Provide handy utility functions for NDK development + * - Make NDK samples more simpler and readable + */ +#include "gl3stub.h" // GLES3 stubs +#include "GLContext.h" // EGL & OpenGL manager +#include "shader.h" // Shader compiler support +#include "vecmath.h" // Vector math support, C++ implementation n current version +#include "tapCamera.h" // Tap/Pinch camera control +#include "JNIHelper.h" // JNI support +#include "gestureDetector.h" // Tap/Doubletap/Pinch detector +#include "perfMonitor.h" // FPS counter +#include "sensorManager.h" // SensorManager +#include "interpolator.h" // Interpolator +#endif diff --git a/NativeApp/Android/ndk_helper/include/gestureDetector.h b/NativeApp/Android/ndk_helper/include/gestureDetector.h new file mode 100644 index 0000000..87849ff --- /dev/null +++ b/NativeApp/Android/ndk_helper/include/gestureDetector.h @@ -0,0 +1,144 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//-------------------------------------------------------------------------------- +// gestureDetector.h +//-------------------------------------------------------------------------------- +#ifndef GESTUREDETECTOR_H_ +#define GESTUREDETECTOR_H_ + +#include <vector> + +#include <android/sensor.h> +#include <android/log.h> +#include <android_native_app_glue.h> +#include <android/native_window_jni.h> +#include "JNIHelper.h" +#include "vecmath.h" + +namespace ndk_helper { +//-------------------------------------------------------------------------------- +// Constants +//-------------------------------------------------------------------------------- +const int32_t DOUBLE_TAP_TIMEOUT = 300 * 1000000; +const int32_t TAP_TIMEOUT = 180 * 1000000; +const int32_t DOUBLE_TAP_SLOP = 100; +const int32_t TOUCH_SLOP = 8; + +enum { + GESTURE_STATE_NONE = 0, + GESTURE_STATE_START = 1, + GESTURE_STATE_MOVE = 2, + GESTURE_STATE_END = 4, + GESTURE_STATE_ACTION = (GESTURE_STATE_START | GESTURE_STATE_END), +}; +typedef int32_t GESTURE_STATE; + +/****************************************************************** + * Base class of Gesture Detectors + * GestureDetectors handles input events and detect gestures + * Note that different detectors may detect gestures with an event at + * same time. The caller needs to manage gesture priority accordingly + * + */ +class GestureDetector { + protected: + float dp_factor_; + + public: + GestureDetector(); + virtual ~GestureDetector() {} + virtual void SetConfiguration(AConfiguration* config); + + virtual GESTURE_STATE Detect(const AInputEvent* motion_event) = 0; +}; + +/****************************************************************** + * Tap gesture detector + * Returns GESTURE_STATE_ACTION when a tap gesture is detected + * + */ +class TapDetector : public GestureDetector { + private: + int32_t down_pointer_id_; + float down_x_; + float down_y_; + + public: + TapDetector(); + virtual ~TapDetector() {} + virtual GESTURE_STATE Detect(const AInputEvent* motion_event); +}; + +/****************************************************************** + * Pinch gesture detector + * Returns GESTURE_STATE_ACTION when a double-tap gesture is detected + * + */ +class DoubletapDetector : public GestureDetector { + private: + TapDetector tap_detector_; + int64_t last_tap_time_; + float last_tap_x_; + float last_tap_y_; + + public: + DoubletapDetector(); + virtual ~DoubletapDetector() {} + virtual GESTURE_STATE Detect(const AInputEvent* motion_event); + virtual void SetConfiguration(AConfiguration* config); +}; + +/****************************************************************** + * Double gesture detector + * Returns pinch gesture state when a pinch gesture is detected + * The class handles multiple touches more than 2 + * When the finger 1,2,3 are tapped and then finger 1 is released, + * the detector start new pinch gesture with finger 2 & 3. + */ +class PinchDetector : public GestureDetector { + private: + int32_t FindIndex(const AInputEvent* event, int32_t id); + const AInputEvent* event_; + std::vector<int32_t> vec_pointers_; + + public: + PinchDetector() {} + virtual ~PinchDetector() {} + virtual GESTURE_STATE Detect(const AInputEvent* event); + bool GetPointers(Vec2& v1, Vec2& v2); +}; + +/****************************************************************** + * Drag gesture detector + * Returns drag gesture state when a drag-tap gesture is detected + * + */ +class DragDetector : public GestureDetector { + private: + int32_t FindIndex(const AInputEvent* event, int32_t id); + const AInputEvent* event_; + std::vector<int32_t> vec_pointers_; + + public: + DragDetector() : event_(nullptr) {} + virtual ~DragDetector() {} + virtual GESTURE_STATE Detect(const AInputEvent* event); + bool GetPointer(Vec2& v); +}; + +} // namespace ndkHelper +#endif /* GESTUREDETECTOR_H_ */ diff --git a/NativeApp/Android/ndk_helper/include/gl3stub.h b/NativeApp/Android/ndk_helper/include/gl3stub.h new file mode 100644 index 0000000..4d28853 --- /dev/null +++ b/NativeApp/Android/ndk_helper/include/gl3stub.h @@ -0,0 +1,661 @@ +#ifndef __gl3_h_ +#define __gl3_h_ + +/* + * stub gl3.h for dynamic loading, based on: + * gl3.h last updated on $Date: 2013-02-12 14:37:24 -0800 (Tue, 12 Feb 2013) $ + * + * Changes: + * - Added #include <GLES2/gl2.h> + * - Removed duplicate OpenGL ES 2.0 declarations + * - Converted OpenGL ES 3.0 function prototypes to function pointer + * declarations + * - Added gl3stubInit() declaration + */ + +#include <GLES2/gl2.h> +#include <android/api-level.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + ** Copyright (c) 2007-2013 The Khronos Group Inc. + ** + ** Permission is hereby granted, free of charge, to any person obtaining a + ** copy of this software and/or associated documentation files (the + ** "Materials"), to deal in the Materials without restriction, including + ** without limitation the rights to use, copy, modify, merge, publish, + ** distribute, sublicense, and/or sell copies of the Materials, and to + ** permit persons to whom the Materials are furnished to do so, subject to + ** the following conditions: + ** + ** The above copyright notice and this permission notice shall be included + ** in all copies or substantial portions of the Materials. + ** + ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + */ + +/* + * This files is for apps that want to use ES3 if present, + * but continue to work on pre-API-18 devices. They can't just link to -lGLESv3 + *since + * that library doesn't exist on pre-API-18 devices. + * The function dynamically check if OpenGLES3.0 APIs are present and fill in if + *there are. + * Also the header defines some extra variables for OpenGLES3.0. + * + */ + +/* Call this function before calling any OpenGL ES 3.0 functions. It will + * return GL_TRUE if the OpenGL ES 3.0 was successfully initialized, GL_FALSE + * otherwise. */ +GLboolean gl3stubInit(); + +/*------------------------------------------------------------------------- + * Data type definitions + *-----------------------------------------------------------------------*/ + +/* OpenGL ES 3.0 */ + +typedef unsigned short GLhalf; +#if __ANDROID_API__ <= 19 +typedef khronos_int64_t GLint64; +typedef khronos_uint64_t GLuint64; +typedef struct __GLsync* GLsync; +#endif + +/*------------------------------------------------------------------------- + * Token definitions + *-----------------------------------------------------------------------*/ + +/* OpenGL ES core versions */ +#define GL_ES_VERSION_3_0 1 + +/* OpenGL ES 3.0 */ + +#define GL_READ_BUFFER 0x0C02 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_RED 0x1903 +#define GL_RGB8 0x8051 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_DRAW_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_HALF_FLOAT 0x140B +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_RG8 0x822B +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_COPY_READ_BUFFER_BINDING GL_COPY_READ_BUFFER +#define GL_COPY_WRITE_BUFFER_BINDING GL_COPY_WRITE_BUFFER +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFFu +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A +#define GL_SAMPLER_BINDING 0x8919 +#define GL_RGB10_A2UI 0x906F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_INT_2_10_10_10_REV 0x8D9F +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF +#define GL_COMPRESSED_R11_EAC 0x9270 +#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define GL_COMPRESSED_RG11_EAC 0x9272 +#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define GL_COMPRESSED_RGB8_ETC2 0x9274 +#define GL_COMPRESSED_SRGB8_ETC2 0x9275 +#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 +#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F +#define GL_MAX_ELEMENT_INDEX 0x8D6B +#define GL_NUM_SAMPLE_COUNTS 0x9380 +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF + +/*------------------------------------------------------------------------- + * Entrypoint definitions + *-----------------------------------------------------------------------*/ + +/* OpenGL ES 3.0 */ + +extern GL_APICALL void (*GL_APIENTRY glReadBuffer)(GLenum mode); +extern GL_APICALL void (*GL_APIENTRY glDrawRangeElements)( + GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, + const GLvoid* indices); +extern GL_APICALL void (*GL_APIENTRY glTexImage3D)( + GLenum target, GLint level, GLint internalformat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, + const GLvoid* pixels); +extern GL_APICALL void (*GL_APIENTRY glTexSubImage3D)( + GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, + const GLvoid* pixels); +extern GL_APICALL void (*GL_APIENTRY glCopyTexSubImage3D)( + GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height); +extern GL_APICALL void (*GL_APIENTRY glCompressedTexImage3D)( + GLenum target, GLint level, GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, + const GLvoid* data); +extern GL_APICALL void (*GL_APIENTRY glCompressedTexSubImage3D)( + GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const GLvoid* data); +extern GL_APICALL void (*GL_APIENTRY glGenQueries)(GLsizei n, GLuint* ids); +extern GL_APICALL void (*GL_APIENTRY glDeleteQueries)(GLsizei n, + const GLuint* ids); +extern GL_APICALL GLboolean (*GL_APIENTRY glIsQuery)(GLuint id); +extern GL_APICALL void (*GL_APIENTRY glBeginQuery)(GLenum target, GLuint id); +extern GL_APICALL void (*GL_APIENTRY glEndQuery)(GLenum target); +extern GL_APICALL void (*GL_APIENTRY glGetQueryiv)(GLenum target, GLenum pname, + GLint* params); +extern GL_APICALL void (*GL_APIENTRY glGetQueryObjectuiv)(GLuint id, + GLenum pname, + GLuint* params); +extern GL_APICALL GLboolean (*GL_APIENTRY glUnmapBuffer)(GLenum target); +extern GL_APICALL void (*GL_APIENTRY glGetBufferPointerv)(GLenum target, + GLenum pname, + GLvoid** params); +extern GL_APICALL void (*GL_APIENTRY glDrawBuffers)(GLsizei n, + const GLenum* bufs); +extern GL_APICALL void (*GL_APIENTRY glUniformMatrix2x3fv)( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (*GL_APIENTRY glUniformMatrix3x2fv)( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (*GL_APIENTRY glUniformMatrix2x4fv)( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (*GL_APIENTRY glUniformMatrix4x2fv)( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (*GL_APIENTRY glUniformMatrix3x4fv)( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (*GL_APIENTRY glUniformMatrix4x3fv)( + GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (*GL_APIENTRY glBlitFramebuffer)( + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, + GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +extern GL_APICALL void (*GL_APIENTRY glRenderbufferStorageMultisample)( + GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height); +extern GL_APICALL void (*GL_APIENTRY glFramebufferTextureLayer)( + GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +extern GL_APICALL GLvoid* (*GL_APIENTRY glMapBufferRange)(GLenum target, + GLintptr offset, + GLsizeiptr length, + GLbitfield access); +extern GL_APICALL void (*GL_APIENTRY glFlushMappedBufferRange)( + GLenum target, GLintptr offset, GLsizeiptr length); +extern GL_APICALL void (*GL_APIENTRY glBindVertexArray)(GLuint array); +extern GL_APICALL void (*GL_APIENTRY glDeleteVertexArrays)( + GLsizei n, const GLuint* arrays); +extern GL_APICALL void (*GL_APIENTRY glGenVertexArrays)(GLsizei n, + GLuint* arrays); +extern GL_APICALL GLboolean (*GL_APIENTRY glIsVertexArray)(GLuint array); +extern GL_APICALL void (*GL_APIENTRY glGetIntegeri_v)(GLenum target, + GLuint index, + GLint* data); +extern GL_APICALL void (*GL_APIENTRY glBeginTransformFeedback)( + GLenum primitiveMode); +extern GL_APICALL void (*GL_APIENTRY glEndTransformFeedback)(void); +extern GL_APICALL void (*GL_APIENTRY glBindBufferRange)(GLenum target, + GLuint index, + GLuint buffer, + GLintptr offset, + GLsizeiptr size); +extern GL_APICALL void (*GL_APIENTRY glBindBufferBase)(GLenum target, + GLuint index, + GLuint buffer); +extern GL_APICALL void (*GL_APIENTRY glTransformFeedbackVaryings)( + GLuint program, GLsizei count, const GLchar* const* varyings, + GLenum bufferMode); +extern GL_APICALL void (*GL_APIENTRY glGetTransformFeedbackVarying)( + GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, + GLsizei* size, GLenum* type, GLchar* name); +extern GL_APICALL void (*GL_APIENTRY glVertexAttribIPointer)( + GLuint index, GLint size, GLenum type, GLsizei stride, + const GLvoid* pointer); +extern GL_APICALL void (*GL_APIENTRY glGetVertexAttribIiv)(GLuint index, + GLenum pname, + GLint* params); +extern GL_APICALL void (*GL_APIENTRY glGetVertexAttribIuiv)(GLuint index, + GLenum pname, + GLuint* params); +extern GL_APICALL void (*GL_APIENTRY glVertexAttribI4i)(GLuint index, GLint x, + GLint y, GLint z, + GLint w); +extern GL_APICALL void (*GL_APIENTRY glVertexAttribI4ui)(GLuint index, GLuint x, + GLuint y, GLuint z, + GLuint w); +extern GL_APICALL void (*GL_APIENTRY glVertexAttribI4iv)(GLuint index, + const GLint* v); +extern GL_APICALL void (*GL_APIENTRY glVertexAttribI4uiv)(GLuint index, + const GLuint* v); +extern GL_APICALL void (*GL_APIENTRY glGetUniformuiv)(GLuint program, + GLint location, + GLuint* params); +extern GL_APICALL GLint (*GL_APIENTRY glGetFragDataLocation)( + GLuint program, const GLchar* name); +extern GL_APICALL void (*GL_APIENTRY glUniform1ui)(GLint location, GLuint v0); +extern GL_APICALL void (*GL_APIENTRY glUniform2ui)(GLint location, GLuint v0, + GLuint v1); +extern GL_APICALL void (*GL_APIENTRY glUniform3ui)(GLint location, GLuint v0, + GLuint v1, GLuint v2); +extern GL_APICALL void (*GL_APIENTRY glUniform4ui)(GLint location, GLuint v0, + GLuint v1, GLuint v2, + GLuint v3); +extern GL_APICALL void (*GL_APIENTRY glUniform1uiv)(GLint location, + GLsizei count, + const GLuint* value); +extern GL_APICALL void (*GL_APIENTRY glUniform2uiv)(GLint location, + GLsizei count, + const GLuint* value); +extern GL_APICALL void (*GL_APIENTRY glUniform3uiv)(GLint location, + GLsizei count, + const GLuint* value); +extern GL_APICALL void (*GL_APIENTRY glUniform4uiv)(GLint location, + GLsizei count, + const GLuint* value); +extern GL_APICALL void (*GL_APIENTRY glClearBufferiv)(GLenum buffer, + GLint drawbuffer, + const GLint* value); +extern GL_APICALL void (*GL_APIENTRY glClearBufferuiv)(GLenum buffer, + GLint drawbuffer, + const GLuint* value); +extern GL_APICALL void (*GL_APIENTRY glClearBufferfv)(GLenum buffer, + GLint drawbuffer, + const GLfloat* value); +extern GL_APICALL void (*GL_APIENTRY glClearBufferfi)(GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil); +extern GL_APICALL const GLubyte* (*GL_APIENTRY glGetStringi)(GLenum name, + GLuint index); +extern GL_APICALL void (*GL_APIENTRY glCopyBufferSubData)(GLenum readTarget, + GLenum writeTarget, + GLintptr readOffset, + GLintptr writeOffset, + GLsizeiptr size); +extern GL_APICALL void (*GL_APIENTRY glGetUniformIndices)( + GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, + GLuint* uniformIndices); +extern GL_APICALL void (*GL_APIENTRY glGetActiveUniformsiv)( + GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, + GLenum pname, GLint* params); +extern GL_APICALL GLuint (*GL_APIENTRY glGetUniformBlockIndex)( + GLuint program, const GLchar* uniformBlockName); +extern GL_APICALL void (*GL_APIENTRY glGetActiveUniformBlockiv)( + GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); +extern GL_APICALL void (*GL_APIENTRY glGetActiveUniformBlockName)( + GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, + GLchar* uniformBlockName); +extern GL_APICALL void (*GL_APIENTRY glUniformBlockBinding)( + GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +extern GL_APICALL void (*GL_APIENTRY glDrawArraysInstanced)( + GLenum mode, GLint first, GLsizei count, GLsizei instanceCount); +extern GL_APICALL void (*GL_APIENTRY glDrawElementsInstanced)( + GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, + GLsizei instanceCount); +extern GL_APICALL GLsync (*GL_APIENTRY glFenceSync)(GLenum condition, + GLbitfield flags); +extern GL_APICALL GLboolean (*GL_APIENTRY glIsSync)(GLsync sync); +extern GL_APICALL void (*GL_APIENTRY glDeleteSync)(GLsync sync); +extern GL_APICALL GLenum (*GL_APIENTRY glClientWaitSync)(GLsync sync, + GLbitfield flags, + GLuint64 timeout); +extern GL_APICALL void (*GL_APIENTRY glWaitSync)(GLsync sync, GLbitfield flags, + GLuint64 timeout); +extern GL_APICALL void (*GL_APIENTRY glGetInteger64v)(GLenum pname, + GLint64* params); +extern GL_APICALL void (*GL_APIENTRY glGetSynciv)(GLsync sync, GLenum pname, + GLsizei bufSize, + GLsizei* length, + GLint* values); +extern GL_APICALL void (*GL_APIENTRY glGetInteger64i_v)(GLenum target, + GLuint index, + GLint64* data); +extern GL_APICALL void (*GL_APIENTRY glGetBufferParameteri64v)(GLenum target, + GLenum pname, + GLint64* params); +extern GL_APICALL void (*GL_APIENTRY glGenSamplers)(GLsizei count, + GLuint* samplers); +extern GL_APICALL void (*GL_APIENTRY glDeleteSamplers)(GLsizei count, + const GLuint* samplers); +extern GL_APICALL GLboolean (*GL_APIENTRY glIsSampler)(GLuint sampler); +extern GL_APICALL void (*GL_APIENTRY glBindSampler)(GLuint unit, + GLuint sampler); +extern GL_APICALL void (*GL_APIENTRY glSamplerParameteri)(GLuint sampler, + GLenum pname, + GLint param); +extern GL_APICALL void (*GL_APIENTRY glSamplerParameteriv)(GLuint sampler, + GLenum pname, + const GLint* param); +extern GL_APICALL void (*GL_APIENTRY glSamplerParameterf)(GLuint sampler, + GLenum pname, + GLfloat param); +extern GL_APICALL void (*GL_APIENTRY glSamplerParameterfv)( + GLuint sampler, GLenum pname, const GLfloat* param); +extern GL_APICALL void (*GL_APIENTRY glGetSamplerParameteriv)(GLuint sampler, + GLenum pname, + GLint* params); +extern GL_APICALL void (*GL_APIENTRY glGetSamplerParameterfv)(GLuint sampler, + GLenum pname, + GLfloat* params); +extern GL_APICALL void (*GL_APIENTRY glVertexAttribDivisor)(GLuint index, + GLuint divisor); +extern GL_APICALL void (*GL_APIENTRY glBindTransformFeedback)(GLenum target, + GLuint id); +extern GL_APICALL void (*GL_APIENTRY glDeleteTransformFeedbacks)( + GLsizei n, const GLuint* ids); +extern GL_APICALL void (*GL_APIENTRY glGenTransformFeedbacks)(GLsizei n, + GLuint* ids); +extern GL_APICALL GLboolean (*GL_APIENTRY glIsTransformFeedback)(GLuint id); +extern GL_APICALL void (*GL_APIENTRY glPauseTransformFeedback)(void); +extern GL_APICALL void (*GL_APIENTRY glResumeTransformFeedback)(void); +extern GL_APICALL void (*GL_APIENTRY glGetProgramBinary)(GLuint program, + GLsizei bufSize, + GLsizei* length, + GLenum* binaryFormat, + GLvoid* binary); +extern GL_APICALL void (*GL_APIENTRY glProgramBinary)(GLuint program, + GLenum binaryFormat, + const GLvoid* binary, + GLsizei length); +extern GL_APICALL void (*GL_APIENTRY glProgramParameteri)(GLuint program, + GLenum pname, + GLint value); +extern GL_APICALL void (*GL_APIENTRY glInvalidateFramebuffer)( + GLenum target, GLsizei numAttachments, const GLenum* attachments); +extern GL_APICALL void (*GL_APIENTRY glInvalidateSubFramebuffer)( + GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, + GLint y, GLsizei width, GLsizei height); +extern GL_APICALL void (*GL_APIENTRY glTexStorage2D)(GLenum target, + GLsizei levels, + GLenum internalformat, + GLsizei width, + GLsizei height); +extern GL_APICALL void (*GL_APIENTRY glTexStorage3D)( + GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth); +extern GL_APICALL void (*GL_APIENTRY glGetInternalformativ)( + GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, + GLint* params); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/NativeApp/Android/ndk_helper/include/interpolator.h b/NativeApp/Android/ndk_helper/include/interpolator.h new file mode 100644 index 0000000..c198bc8 --- /dev/null +++ b/NativeApp/Android/ndk_helper/include/interpolator.h @@ -0,0 +1,80 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERPOLATOR_H_ +#define INTERPOLATOR_H_ + +#include <jni.h> +#include <errno.h> +#include <time.h> +#include "JNIHelper.h" +#include "perfMonitor.h" +#include <list> + +namespace ndk_helper { + +enum INTERPOLATOR_TYPE { + INTERPOLATOR_TYPE_LINEAR, + INTERPOLATOR_TYPE_EASEINQUAD, + INTERPOLATOR_TYPE_EASEOUTQUAD, + INTERPOLATOR_TYPE_EASEINOUTQUAD, + INTERPOLATOR_TYPE_EASEINCUBIC, + INTERPOLATOR_TYPE_EASEOUTCUBIC, + INTERPOLATOR_TYPE_EASEINOUTCUBIC, + INTERPOLATOR_TYPE_EASEINQUART, + INTERPOLATOR_TYPE_EASEINEXPO, + INTERPOLATOR_TYPE_EASEOUTEXPO, +}; + +struct InterpolatorParams { + float dest_value_; + INTERPOLATOR_TYPE type_; + double duration_; +}; + +/****************************************************************** + * Interpolates values with several interpolation methods + */ +class Interpolator { + private: + double start_time_; + double dest_time_; + INTERPOLATOR_TYPE type_; + + float start_value_; + float dest_value_; + std::list<InterpolatorParams> list_params_; + + float GetFormula(const INTERPOLATOR_TYPE type, const float t, const float b, + const float d, const float c); + + public: + Interpolator(); + ~Interpolator(); + + Interpolator& Set(const float start, const float dest, + const INTERPOLATOR_TYPE type, double duration); + + Interpolator& Add(const float dest, const INTERPOLATOR_TYPE type, + const double duration); + + bool Update(const double currentTime, float& p); + + void Clear(); +}; + +} // namespace ndkHelper +#endif /* INTERPOLATOR_H_ */ diff --git a/NativeApp/Android/ndk_helper/include/perfMonitor.h b/NativeApp/Android/ndk_helper/include/perfMonitor.h new file mode 100644 index 0000000..432569a --- /dev/null +++ b/NativeApp/Android/ndk_helper/include/perfMonitor.h @@ -0,0 +1,59 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PERFMONITOR_H_ +#define PERFMONITOR_H_ + +#include <jni.h> +#include <errno.h> +#include <time.h> +#include "JNIHelper.h" + +namespace ndk_helper { + +const int32_t kNumSamples = 100; + +/****************************************************************** + * Helper class for a performance monitoring and get current tick time + */ +class PerfMonitor { + private: + float current_FPS_; + time_t tv_last_sec_; + + double last_tick_; + int32_t tickindex_; + double ticksum_; + double ticklist_[kNumSamples]; + + double UpdateTick(double current_tick); + + public: + PerfMonitor(); + virtual ~PerfMonitor(); + + bool Update(float &fFPS); + + static double GetCurrentTime() { + struct timeval time; + gettimeofday(&time, NULL); + double ret = time.tv_sec + time.tv_usec * 1.0 / 1000000.0; + return ret; + } +}; + +} // namespace ndkHelper +#endif /* PERFMONITOR_H_ */ diff --git a/NativeApp/Android/ndk_helper/include/sensorManager.h b/NativeApp/Android/ndk_helper/include/sensorManager.h new file mode 100644 index 0000000..d0b77f8 --- /dev/null +++ b/NativeApp/Android/ndk_helper/include/sensorManager.h @@ -0,0 +1,64 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//-------------------------------------------------------------------------------- +// sensorManager.h +//-------------------------------------------------------------------------------- +#ifndef SENSORMANAGER_H_ +#define SENSORMANAGER_H_ + +#include <android/sensor.h> +#include "JNIHelper.h" + +namespace ndk_helper { +//-------------------------------------------------------------------------------- +// Constants +//-------------------------------------------------------------------------------- +enum ORIENTATION { + ORIENTATION_UNKNOWN = -1, + ORIENTATION_PORTRAIT = 0, + ORIENTATION_LANDSCAPE = 1, + ORIENTATION_REVERSE_PORTRAIT = 2, + ORIENTATION_REVERSE_LANDSCAPE = 3, +}; + +/* + * Helper to handle sensor inputs such as accelerometer. + * The helper also check for screen rotation + * + */ +class SensorManager { + ASensorManager *sensorManager_; + const ASensor *accelerometerSensor_; + ASensorEventQueue *sensorEventQueue_; + + protected: + public: + SensorManager(); + ~SensorManager(); + void Init(android_app *state); + void Suspend(); + void Resume(); +}; + +/* + * AcquireASensorManagerInstance(android_app* app) + * Workaround ASensorManager_getInstance() deprecation false alarm + * for Android-N and before, when compiling with NDK-r15 + */ +ASensorManager* AcquireASensorManagerInstance(android_app* app); +} // namespace ndkHelper +#endif /* SENSORMANAGER_H_ */ diff --git a/NativeApp/Android/ndk_helper/include/shader.h b/NativeApp/Android/ndk_helper/include/shader.h new file mode 100644 index 0000000..39a2ec9 --- /dev/null +++ b/NativeApp/Android/ndk_helper/include/shader.h @@ -0,0 +1,120 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SHADER_H_ +#define SHADER_H_ + +#include <jni.h> + +#include <vector> +#include <map> +#include <string> + +#include <EGL/egl.h> +#include <GLES/gl.h> + +#include <android/log.h> + +#include "JNIHelper.h" + +namespace ndk_helper { + +namespace shader { + +/****************************************************************** + * Shader compiler helper + * namespace: ndkHelper::shader + * + */ + +/****************************************************************** + * CompileShader() with vector + * + * arguments: + * out: shader, shader variable + * in: type, shader type (i.e. GL_VERTEX_SHADER/GL_FRAGMENT_SHADER) + * in: data, source vector + * return: true if a shader compilation succeeded, false if it failed + * + */ +bool CompileShader(GLuint *shader, const GLenum type, + std::vector<uint8_t> &data); + +/****************************************************************** + * CompileShader() with buffer + * + * arguments: + * out: shader, shader variable + * in: type, shader type (i.e. GL_VERTEX_SHADER/GL_FRAGMENT_SHADER) + * in: source, source buffer + * in: iSize, buffer size + * return: true if a shader compilation succeeded, false if it failed + * + */ +bool CompileShader(GLuint *shader, const GLenum type, const GLchar *source, + const int32_t iSize); + +/****************************************************************** + * CompileShader() with filename + * + * arguments: + * out: shader, shader variable + * in: type, shader type (i.e. GL_VERTEX_SHADER/GL_FRAGMENT_SHADER) + * in: strFilename, filename + * return: true if a shader compilation succeeded, false if it failed + * + */ +bool CompileShader(GLuint *shader, const GLenum type, const char *strFileName); + +/****************************************************************** + * CompileShader() with std::map helps patching on a shader on the fly. + * + * arguments: + * out: shader, shader variable + * in: type, shader type (i.e. GL_VERTEX_SHADER/GL_FRAGMENT_SHADER) + * in: mapParameters + * For a example, + * map : %KEY% -> %VALUE% replaces all %KEY% entries in the given shader + *code to %VALUE" + * return: true if a shader compilation succeeded, false if it failed + * + */ +bool CompileShader(GLuint *shader, const GLenum type, const char *str_file_name, + const std::map<std::string, std::string> &map_parameters); + +/****************************************************************** + * LinkProgram() + * + * arguments: + * in: program, program + * return: true if a shader linkage succeeded, false if it failed + * + */ +bool LinkProgram(const GLuint prog); + +/****************************************************************** + * validateProgram() + * + * arguments: + * in: program, program + * return: true if a shader validation succeeded, false if it failed + * + */ +bool ValidateProgram(const GLuint prog); +} // namespace shader + +} // namespace ndkHelper +#endif /* SHADER_H_ */ diff --git a/NativeApp/Android/ndk_helper/include/tapCamera.h b/NativeApp/Android/ndk_helper/include/tapCamera.h new file mode 100644 index 0000000..ea6266f --- /dev/null +++ b/NativeApp/Android/ndk_helper/include/tapCamera.h @@ -0,0 +1,110 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include <vector> +#include <string> +#include <GLES2/gl2.h> + +#include "JNIHelper.h" +#include "vecmath.h" +#include "interpolator.h" + +namespace ndk_helper { + +/****************************************************************** + * Camera control helper class with a tap gesture + * This class is mainly used for 3D space camera control in samples. + * + */ +class TapCamera { + private: + // Trackball + Vec2 vec_ball_center_; + float ball_radius_; + Quaternion quat_ball_now_; + Quaternion quat_ball_down_; + Vec2 vec_ball_now_; + Vec2 vec_ball_down_; + Quaternion quat_ball_rot_; + + bool dragging_; + bool pinching_; + + // Pinch related info + Vec2 vec_pinch_start_; + Vec2 vec_pinch_start_center_; + float pinch_start_distance_SQ_; + + // Camera shift + Vec3 vec_offset_; + Vec3 vec_offset_now_; + + // Camera Rotation + float camera_rotation_; + float camera_rotation_start_; + float camera_rotation_now_; + + // Momentum support + bool momentum_; + double time_stamp_; + Vec2 vec_drag_delta_; + Vec2 vec_last_input_; + Vec3 vec_offset_last_; + Vec3 vec_offset_delta_; + float momemtum_steps_; + + Vec2 vec_flip_; + float flip_z_; + + Mat4 mat_rotation_; + Mat4 mat_transform_; + + Vec3 vec_pinch_transform_factor_; + + Vec3 PointOnSphere(Vec2& point); + void BallUpdate(); + void InitParameters(); + + public: + TapCamera(); + virtual ~TapCamera(); + void BeginDrag(const Vec2& vec); + void EndDrag(); + void Drag(const Vec2& vec); + void Update(); + void Update(const double time); + + Mat4& GetRotationMatrix(); + Mat4& GetTransformMatrix(); + + void BeginPinch(const Vec2& v1, const Vec2& v2); + void EndPinch(); + void Pinch(const Vec2& v1, const Vec2& v2); + + void SetFlip(const float x, const float y, const float z) { + vec_flip_ = Vec2(x, y); + flip_z_ = z; + } + + void SetPinchTransformFactor(const float x, const float y, const float z) { + vec_pinch_transform_factor_ = Vec3(x, y, z); + } + + void Reset(const bool bAnimate); +}; + +} // namespace ndkHelper diff --git a/NativeApp/Android/ndk_helper/include/vecmath.h b/NativeApp/Android/ndk_helper/include/vecmath.h new file mode 100644 index 0000000..a4ba481 --- /dev/null +++ b/NativeApp/Android/ndk_helper/include/vecmath.h @@ -0,0 +1,965 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VECMATH_H_ +#define VECMATH_H_ + +#include <cmath> +#include "JNIHelper.h" + +namespace ndk_helper { + +/****************************************************************** + * Helper class for vector math operations + * Currently all implementations are in pure C++. + * Each class is an opaque class so caller does not have a direct access + * to each element. This is for an ease of future optimization to use vector + *operations. + * + */ + +class Vec2; +class Vec3; +class Vec4; +class Mat4; + +/****************************************************************** + * 2 elements vector class + * + */ +class Vec2 { + private: + float x_; + float y_; + + public: + friend class Vec3; + friend class Vec4; + friend class Mat4; + friend class Quaternion; + + Vec2() { x_ = y_ = 0.f; } + + Vec2(const float fX, const float fY) { + x_ = fX; + y_ = fY; + } + + Vec2(const Vec2& vec) { + x_ = vec.x_; + y_ = vec.y_; + } + + Vec2(const float* pVec) { + x_ = (*pVec++); + y_ = (*pVec++); + } + + // Operators + Vec2 operator*(const Vec2& rhs) const { + Vec2 ret; + ret.x_ = x_ * rhs.x_; + ret.y_ = y_ * rhs.y_; + return ret; + } + + Vec2 operator/(const Vec2& rhs) const { + Vec2 ret; + ret.x_ = x_ / rhs.x_; + ret.y_ = y_ / rhs.y_; + return ret; + } + + Vec2 operator+(const Vec2& rhs) const { + Vec2 ret; + ret.x_ = x_ + rhs.x_; + ret.y_ = y_ + rhs.y_; + return ret; + } + + Vec2 operator-(const Vec2& rhs) const { + Vec2 ret; + ret.x_ = x_ - rhs.x_; + ret.y_ = y_ - rhs.y_; + return ret; + } + + Vec2& operator+=(const Vec2& rhs) { + x_ += rhs.x_; + y_ += rhs.y_; + return *this; + } + + Vec2& operator-=(const Vec2& rhs) { + x_ -= rhs.x_; + y_ -= rhs.y_; + return *this; + } + + Vec2& operator*=(const Vec2& rhs) { + x_ *= rhs.x_; + y_ *= rhs.y_; + return *this; + } + + Vec2& operator/=(const Vec2& rhs) { + x_ /= rhs.x_; + y_ /= rhs.y_; + return *this; + } + + // External operators + friend Vec2 operator-(const Vec2& rhs) { return Vec2(rhs) *= -1; } + + friend Vec2 operator*(const float lhs, const Vec2& rhs) { + Vec2 ret; + ret.x_ = lhs * rhs.x_; + ret.y_ = lhs * rhs.y_; + return ret; + } + + friend Vec2 operator/(const float lhs, const Vec2& rhs) { + Vec2 ret; + ret.x_ = lhs / rhs.x_; + ret.y_ = lhs / rhs.y_; + return ret; + } + + // Operators with float + Vec2 operator*(const float& rhs) const { + Vec2 ret; + ret.x_ = x_ * rhs; + ret.y_ = y_ * rhs; + return ret; + } + + Vec2& operator*=(const float& rhs) { + x_ = x_ * rhs; + y_ = y_ * rhs; + return *this; + } + + Vec2 operator/(const float& rhs) const { + Vec2 ret; + ret.x_ = x_ / rhs; + ret.y_ = y_ / rhs; + return ret; + } + + Vec2& operator/=(const float& rhs) { + x_ = x_ / rhs; + y_ = y_ / rhs; + return *this; + } + + // Compare + bool operator==(const Vec2& rhs) const { + if (x_ != rhs.x_ || y_ != rhs.y_) return false; + return true; + } + + bool operator!=(const Vec2& rhs) const { + if (x_ == rhs.x_) return false; + + return true; + } + + float Length() const { return sqrtf(x_ * x_ + y_ * y_); } + + Vec2 Normalize() { + float len = Length(); + x_ = x_ / len; + y_ = y_ / len; + return *this; + } + + float Dot(const Vec2& rhs) { return x_ * rhs.x_ + y_ * rhs.y_; } + + bool Validate() { + if (std::isnan(x_) || std::isnan(y_)) return false; + return true; + } + + void Value(float& fX, float& fY) { + fX = x_; + fY = y_; + } + + void Dump() { LOGI("Vec2 %f %f", x_, y_); } +}; + +/****************************************************************** + * 3 elements vector class + * + */ +class Vec3 { + private: + float x_, y_, z_; + + public: + friend class Vec4; + friend class Mat4; + friend class Quaternion; + + Vec3() { x_ = y_ = z_ = 0.f; } + + Vec3(const float fX, const float fY, const float fZ) { + x_ = fX; + y_ = fY; + z_ = fZ; + } + + Vec3(const Vec3& vec) { + x_ = vec.x_; + y_ = vec.y_; + z_ = vec.z_; + } + + Vec3(const float* pVec) { + x_ = (*pVec++); + y_ = (*pVec++); + z_ = *pVec; + } + + Vec3(const Vec2& vec, float f) { + x_ = vec.x_; + y_ = vec.y_; + z_ = f; + } + + Vec3(const Vec4& vec); + + // Operators + Vec3 operator*(const Vec3& rhs) const { + Vec3 ret; + ret.x_ = x_ * rhs.x_; + ret.y_ = y_ * rhs.y_; + ret.z_ = z_ * rhs.z_; + return ret; + } + + Vec3 operator/(const Vec3& rhs) const { + Vec3 ret; + ret.x_ = x_ / rhs.x_; + ret.y_ = y_ / rhs.y_; + ret.z_ = z_ / rhs.z_; + return ret; + } + + Vec3 operator+(const Vec3& rhs) const { + Vec3 ret; + ret.x_ = x_ + rhs.x_; + ret.y_ = y_ + rhs.y_; + ret.z_ = z_ + rhs.z_; + return ret; + } + + Vec3 operator-(const Vec3& rhs) const { + Vec3 ret; + ret.x_ = x_ - rhs.x_; + ret.y_ = y_ - rhs.y_; + ret.z_ = z_ - rhs.z_; + return ret; + } + + Vec3& operator+=(const Vec3& rhs) { + x_ += rhs.x_; + y_ += rhs.y_; + z_ += rhs.z_; + return *this; + } + + Vec3& operator-=(const Vec3& rhs) { + x_ -= rhs.x_; + y_ -= rhs.y_; + z_ -= rhs.z_; + return *this; + } + + Vec3& operator*=(const Vec3& rhs) { + x_ *= rhs.x_; + y_ *= rhs.y_; + z_ *= rhs.z_; + return *this; + } + + Vec3& operator/=(const Vec3& rhs) { + x_ /= rhs.x_; + y_ /= rhs.y_; + z_ /= rhs.z_; + return *this; + } + + // External operators + friend Vec3 operator-(const Vec3& rhs) { return Vec3(rhs) *= -1; } + + friend Vec3 operator*(const float lhs, const Vec3& rhs) { + Vec3 ret; + ret.x_ = lhs * rhs.x_; + ret.y_ = lhs * rhs.y_; + ret.z_ = lhs * rhs.z_; + return ret; + } + + friend Vec3 operator/(const float lhs, const Vec3& rhs) { + Vec3 ret; + ret.x_ = lhs / rhs.x_; + ret.y_ = lhs / rhs.y_; + ret.z_ = lhs / rhs.z_; + return ret; + } + + // Operators with float + Vec3 operator*(const float& rhs) const { + Vec3 ret; + ret.x_ = x_ * rhs; + ret.y_ = y_ * rhs; + ret.z_ = z_ * rhs; + return ret; + } + + Vec3& operator*=(const float& rhs) { + x_ = x_ * rhs; + y_ = y_ * rhs; + z_ = z_ * rhs; + return *this; + } + + Vec3 operator/(const float& rhs) const { + Vec3 ret; + ret.x_ = x_ / rhs; + ret.y_ = y_ / rhs; + ret.z_ = z_ / rhs; + return ret; + } + + Vec3& operator/=(const float& rhs) { + x_ = x_ / rhs; + y_ = y_ / rhs; + z_ = z_ / rhs; + return *this; + } + + // Compare + bool operator==(const Vec3& rhs) const { + if (x_ != rhs.x_ || y_ != rhs.y_ || z_ != rhs.z_) return false; + return true; + } + + bool operator!=(const Vec3& rhs) const { + if (x_ == rhs.x_) return false; + + return true; + } + + float Length() const { return sqrtf(x_ * x_ + y_ * y_ + z_ * z_); } + + Vec3 Normalize() { + float len = Length(); + x_ = x_ / len; + y_ = y_ / len; + z_ = z_ / len; + return *this; + } + + float Dot(const Vec3& rhs) { return x_ * rhs.x_ + y_ * rhs.y_ + z_ * rhs.z_; } + + Vec3 Cross(const Vec3& rhs) { + Vec3 ret; + ret.x_ = y_ * rhs.z_ - z_ * rhs.y_; + ret.y_ = z_ * rhs.x_ - x_ * rhs.z_; + ret.z_ = x_ * rhs.y_ - y_ * rhs.x_; + return ret; + } + + bool Validate() { + if (std::isnan(x_) || std::isnan(y_) || std::isnan(z_)) return false; + return true; + } + + void Value(float& fX, float& fY, float& fZ) { + fX = x_; + fY = y_; + fZ = z_; + } + + void Dump() { LOGI("Vec3 %f %f %f", x_, y_, z_); } +}; + +/****************************************************************** + * 4 elements vector class + * + */ +class Vec4 { + private: + float x_, y_, z_, w_; + + public: + friend class Vec3; + friend class Mat4; + friend class Quaternion; + + Vec4() { x_ = y_ = z_ = w_ = 0.f; } + + Vec4(const float fX, const float fY, const float fZ, const float fW) { + x_ = fX; + y_ = fY; + z_ = fZ; + w_ = fW; + } + + Vec4(const Vec4& vec) { + x_ = vec.x_; + y_ = vec.y_; + z_ = vec.z_; + w_ = vec.w_; + } + + Vec4(const Vec3& vec, const float fW) { + x_ = vec.x_; + y_ = vec.y_; + z_ = vec.z_; + w_ = fW; + } + + Vec4(const float* pVec) { + x_ = (*pVec++); + y_ = (*pVec++); + z_ = *pVec; + w_ = *pVec; + } + + // Operators + Vec4 operator*(const Vec4& rhs) const { + Vec4 ret; + ret.x_ = x_ * rhs.x_; + ret.y_ = y_ * rhs.y_; + ret.z_ = z_ * rhs.z_; + ret.w_ = z_ * rhs.w_; + return ret; + } + + Vec4 operator/(const Vec4& rhs) const { + Vec4 ret; + ret.x_ = x_ / rhs.x_; + ret.y_ = y_ / rhs.y_; + ret.z_ = z_ / rhs.z_; + ret.w_ = z_ / rhs.w_; + return ret; + } + + Vec4 operator+(const Vec4& rhs) const { + Vec4 ret; + ret.x_ = x_ + rhs.x_; + ret.y_ = y_ + rhs.y_; + ret.z_ = z_ + rhs.z_; + ret.w_ = z_ + rhs.w_; + return ret; + } + + Vec4 operator-(const Vec4& rhs) const { + Vec4 ret; + ret.x_ = x_ - rhs.x_; + ret.y_ = y_ - rhs.y_; + ret.z_ = z_ - rhs.z_; + ret.w_ = z_ - rhs.w_; + return ret; + } + + Vec4& operator+=(const Vec4& rhs) { + x_ += rhs.x_; + y_ += rhs.y_; + z_ += rhs.z_; + w_ += rhs.w_; + return *this; + } + + Vec4& operator-=(const Vec4& rhs) { + x_ -= rhs.x_; + y_ -= rhs.y_; + z_ -= rhs.z_; + w_ -= rhs.w_; + return *this; + } + + Vec4& operator*=(const Vec4& rhs) { + x_ *= rhs.x_; + y_ *= rhs.y_; + z_ *= rhs.z_; + w_ *= rhs.w_; + return *this; + } + + Vec4& operator/=(const Vec4& rhs) { + x_ /= rhs.x_; + y_ /= rhs.y_; + z_ /= rhs.z_; + w_ /= rhs.w_; + return *this; + } + + // External operators + friend Vec4 operator-(const Vec4& rhs) { return Vec4(rhs) *= -1; } + + friend Vec4 operator*(const float lhs, const Vec4& rhs) { + Vec4 ret; + ret.x_ = lhs * rhs.x_; + ret.y_ = lhs * rhs.y_; + ret.z_ = lhs * rhs.z_; + ret.w_ = lhs * rhs.w_; + return ret; + } + + friend Vec4 operator/(const float lhs, const Vec4& rhs) { + Vec4 ret; + ret.x_ = lhs / rhs.x_; + ret.y_ = lhs / rhs.y_; + ret.z_ = lhs / rhs.z_; + ret.w_ = lhs / rhs.w_; + return ret; + } + + // Operators with float + Vec4 operator*(const float& rhs) const { + Vec4 ret; + ret.x_ = x_ * rhs; + ret.y_ = y_ * rhs; + ret.z_ = z_ * rhs; + ret.w_ = w_ * rhs; + return ret; + } + + Vec4& operator*=(const float& rhs) { + x_ = x_ * rhs; + y_ = y_ * rhs; + z_ = z_ * rhs; + w_ = w_ * rhs; + return *this; + } + + Vec4 operator/(const float& rhs) const { + Vec4 ret; + ret.x_ = x_ / rhs; + ret.y_ = y_ / rhs; + ret.z_ = z_ / rhs; + ret.w_ = w_ / rhs; + return ret; + } + + Vec4& operator/=(const float& rhs) { + x_ = x_ / rhs; + y_ = y_ / rhs; + z_ = z_ / rhs; + w_ = w_ / rhs; + return *this; + } + + // Compare + bool operator==(const Vec4& rhs) const { + if (x_ != rhs.x_ || y_ != rhs.y_ || z_ != rhs.z_ || w_ != rhs.w_) + return false; + return true; + } + + bool operator!=(const Vec4& rhs) const { + if (x_ == rhs.x_) return false; + + return true; + } + + Vec4 operator*(const Mat4& rhs) const; + + float Length() const { return sqrtf(x_ * x_ + y_ * y_ + z_ * z_ + w_ * w_); } + + Vec4 Normalize() { + float len = Length(); + x_ = x_ / len; + y_ = y_ / len; + z_ = z_ / len; + w_ = w_ / len; + return *this; + } + + float Dot(const Vec3& rhs) { return x_ * rhs.x_ + y_ * rhs.y_ + z_ * rhs.z_; } + + Vec3 Cross(const Vec3& rhs) { + Vec3 ret; + ret.x_ = y_ * rhs.z_ - z_ * rhs.y_; + ret.y_ = z_ * rhs.x_ - x_ * rhs.z_; + ret.z_ = x_ * rhs.y_ - y_ * rhs.x_; + return ret; + } + + bool Validate() { + if (std::isnan(x_) || std::isnan(y_) || + std::isnan(z_) || std::isnan(w_)) + return false; + + return true; + } + + void Value(float& fX, float& fY, float& fZ, float& fW) { + fX = x_; + fY = y_; + fZ = z_; + fW = w_; + } +}; + +/****************************************************************** + * 4x4 matrix + * + */ +class Mat4 { + private: + float f_[16]; + + public: + friend class Vec3; + friend class Vec4; + friend class Quaternion; + + Mat4(); + Mat4(const float*); + + Mat4 operator*(const Mat4& rhs) const; + Vec4 operator*(const Vec4& rhs) const; + + Mat4 operator+(const Mat4& rhs) const { + Mat4 ret; + for (int32_t i = 0; i < 16; ++i) { + ret.f_[i] = f_[i] + rhs.f_[i]; + } + return ret; + } + + Mat4 operator-(const Mat4& rhs) const { + Mat4 ret; + for (int32_t i = 0; i < 16; ++i) { + ret.f_[i] = f_[i] - rhs.f_[i]; + } + return ret; + } + + Mat4& operator+=(const Mat4& rhs) { + for (int32_t i = 0; i < 16; ++i) { + f_[i] += rhs.f_[i]; + } + return *this; + } + + Mat4& operator-=(const Mat4& rhs) { + for (int32_t i = 0; i < 16; ++i) { + f_[i] -= rhs.f_[i]; + } + return *this; + } + + Mat4& operator*=(const Mat4& rhs) { + Mat4 ret; + ret.f_[0] = f_[0] * rhs.f_[0] + f_[4] * rhs.f_[1] + f_[8] * rhs.f_[2] + + f_[12] * rhs.f_[3]; + ret.f_[1] = f_[1] * rhs.f_[0] + f_[5] * rhs.f_[1] + f_[9] * rhs.f_[2] + + f_[13] * rhs.f_[3]; + ret.f_[2] = f_[2] * rhs.f_[0] + f_[6] * rhs.f_[1] + f_[10] * rhs.f_[2] + + f_[14] * rhs.f_[3]; + ret.f_[3] = f_[3] * rhs.f_[0] + f_[7] * rhs.f_[1] + f_[11] * rhs.f_[2] + + f_[15] * rhs.f_[3]; + + ret.f_[4] = f_[0] * rhs.f_[4] + f_[4] * rhs.f_[5] + f_[8] * rhs.f_[6] + + f_[12] * rhs.f_[7]; + ret.f_[5] = f_[1] * rhs.f_[4] + f_[5] * rhs.f_[5] + f_[9] * rhs.f_[6] + + f_[13] * rhs.f_[7]; + ret.f_[6] = f_[2] * rhs.f_[4] + f_[6] * rhs.f_[5] + f_[10] * rhs.f_[6] + + f_[14] * rhs.f_[7]; + ret.f_[7] = f_[3] * rhs.f_[4] + f_[7] * rhs.f_[5] + f_[11] * rhs.f_[6] + + f_[15] * rhs.f_[7]; + + ret.f_[8] = f_[0] * rhs.f_[8] + f_[4] * rhs.f_[9] + f_[8] * rhs.f_[10] + + f_[12] * rhs.f_[11]; + ret.f_[9] = f_[1] * rhs.f_[8] + f_[5] * rhs.f_[9] + f_[9] * rhs.f_[10] + + f_[13] * rhs.f_[11]; + ret.f_[10] = f_[2] * rhs.f_[8] + f_[6] * rhs.f_[9] + f_[10] * rhs.f_[10] + + f_[14] * rhs.f_[11]; + ret.f_[11] = f_[3] * rhs.f_[8] + f_[7] * rhs.f_[9] + f_[11] * rhs.f_[10] + + f_[15] * rhs.f_[11]; + + ret.f_[12] = f_[0] * rhs.f_[12] + f_[4] * rhs.f_[13] + f_[8] * rhs.f_[14] + + f_[12] * rhs.f_[15]; + ret.f_[13] = f_[1] * rhs.f_[12] + f_[5] * rhs.f_[13] + f_[9] * rhs.f_[14] + + f_[13] * rhs.f_[15]; + ret.f_[14] = f_[2] * rhs.f_[12] + f_[6] * rhs.f_[13] + f_[10] * rhs.f_[14] + + f_[14] * rhs.f_[15]; + ret.f_[15] = f_[3] * rhs.f_[12] + f_[7] * rhs.f_[13] + f_[11] * rhs.f_[14] + + f_[15] * rhs.f_[15]; + + *this = ret; + return *this; + } + + Mat4 operator*(const float rhs) { + Mat4 ret; + for (int32_t i = 0; i < 16; ++i) { + ret.f_[i] = f_[i] * rhs; + } + return ret; + } + + Mat4& operator*=(const float rhs) { + for (int32_t i = 0; i < 16; ++i) { + f_[i] *= rhs; + } + return *this; + } + + Mat4& operator=(const Mat4& rhs) { + for (int32_t i = 0; i < 16; ++i) { + f_[i] = rhs.f_[i]; + } + return *this; + } + + Mat4 Inverse(); + + Mat4 Transpose() { + Mat4 ret; + ret.f_[0] = f_[0]; + ret.f_[1] = f_[4]; + ret.f_[2] = f_[8]; + ret.f_[3] = f_[12]; + ret.f_[4] = f_[1]; + ret.f_[5] = f_[5]; + ret.f_[6] = f_[9]; + ret.f_[7] = f_[13]; + ret.f_[8] = f_[2]; + ret.f_[9] = f_[6]; + ret.f_[10] = f_[10]; + ret.f_[11] = f_[14]; + ret.f_[12] = f_[3]; + ret.f_[13] = f_[7]; + ret.f_[14] = f_[11]; + ret.f_[15] = f_[15]; + *this = ret; + return *this; + } + + Mat4& PostTranslate(float tx, float ty, float tz) { + f_[12] += (tx * f_[0]) + (ty * f_[4]) + (tz * f_[8]); + f_[13] += (tx * f_[1]) + (ty * f_[5]) + (tz * f_[9]); + f_[14] += (tx * f_[2]) + (ty * f_[6]) + (tz * f_[10]); + f_[15] += (tx * f_[3]) + (ty * f_[7]) + (tz * f_[11]); + return *this; + } + + float* Ptr() { return f_; } + + //-------------------------------------------------------------------------------- + // Misc + //-------------------------------------------------------------------------------- + static Mat4 Perspective(float width, float height, float nearPlane, + float farPlane); + static Mat4 Ortho2D(float left, float top, float right, float bottom); + + static Mat4 LookAt(const Vec3& vEye, const Vec3& vAt, const Vec3& vUp); + + static Mat4 Translation(const float fX, const float fY, const float fZ); + static Mat4 Translation(const Vec3 vec); + + static Mat4 RotationX(const float angle); + + static Mat4 RotationY(const float angle); + + static Mat4 RotationZ(const float angle); + + static Mat4 Scale(const float scaleX, const float scaleY, const float scaleZ); + + static Mat4 Identity() { + Mat4 ret; + ret.f_[0] = 1.f; + ret.f_[1] = 0; + ret.f_[2] = 0; + ret.f_[3] = 0; + ret.f_[4] = 0; + ret.f_[5] = 1.f; + ret.f_[6] = 0; + ret.f_[7] = 0; + ret.f_[8] = 0; + ret.f_[9] = 0; + ret.f_[10] = 1.f; + ret.f_[11] = 0; + ret.f_[12] = 0; + ret.f_[13] = 0; + ret.f_[14] = 0; + ret.f_[15] = 1.f; + return ret; + } + + void Dump() { + LOGI("%f %f %f %f", f_[0], f_[1], f_[2], f_[3]); + LOGI("%f %f %f %f", f_[4], f_[5], f_[6], f_[7]); + LOGI("%f %f %f %f", f_[8], f_[9], f_[10], f_[11]); + LOGI("%f %f %f %f", f_[12], f_[13], f_[14], f_[15]); + } +}; + +/****************************************************************** + * Quaternion class + * + */ +class Quaternion { + private: + float x_, y_, z_, w_; + + public: + friend class Vec3; + friend class Vec4; + friend class Mat4; + + Quaternion() { + x_ = 0.f; + y_ = 0.f; + z_ = 0.f; + w_ = 1.f; + } + + Quaternion(const float fX, const float fY, const float fZ, const float fW) { + x_ = fX; + y_ = fY; + z_ = fZ; + w_ = fW; + } + + Quaternion(const Vec3 vec, const float fW) { + x_ = vec.x_; + y_ = vec.y_; + z_ = vec.z_; + w_ = fW; + } + + Quaternion(const float* p) { + x_ = *p++; + y_ = *p++; + z_ = *p++; + w_ = *p++; + } + + Quaternion operator*(const Quaternion rhs) { + Quaternion ret; + ret.x_ = x_ * rhs.w_ + y_ * rhs.z_ - z_ * rhs.y_ + w_ * rhs.x_; + ret.y_ = -x_ * rhs.z_ + y_ * rhs.w_ + z_ * rhs.x_ + w_ * rhs.y_; + ret.z_ = x_ * rhs.y_ - y_ * rhs.x_ + z_ * rhs.w_ + w_ * rhs.z_; + ret.w_ = -x_ * rhs.x_ - y_ * rhs.y_ - z_ * rhs.z_ + w_ * rhs.w_; + return ret; + } + + Quaternion& operator*=(const Quaternion rhs) { + Quaternion ret; + ret.x_ = x_ * rhs.w_ + y_ * rhs.z_ - z_ * rhs.y_ + w_ * rhs.x_; + ret.y_ = -x_ * rhs.z_ + y_ * rhs.w_ + z_ * rhs.x_ + w_ * rhs.y_; + ret.z_ = x_ * rhs.y_ - y_ * rhs.x_ + z_ * rhs.w_ + w_ * rhs.z_; + ret.w_ = -x_ * rhs.x_ - y_ * rhs.y_ - z_ * rhs.z_ + w_ * rhs.w_; + *this = ret; + return *this; + } + + Quaternion Conjugate() { + x_ = -x_; + y_ = -y_; + z_ = -z_; + return *this; + } + + // Non destuctive version + Quaternion Conjugated() { + Quaternion ret; + ret.x_ = -x_; + ret.y_ = -y_; + ret.z_ = -z_; + ret.w_ = w_; + return ret; + } + + void ToMatrix(Mat4& mat) { + float x2 = x_ * x_ * 2.0f; + float y2 = y_ * y_ * 2.0f; + float z2 = z_ * z_ * 2.0f; + float xy = x_ * y_ * 2.0f; + float yz = y_ * z_ * 2.0f; + float zx = z_ * x_ * 2.0f; + float xw = x_ * w_ * 2.0f; + float yw = y_ * w_ * 2.0f; + float zw = z_ * w_ * 2.0f; + + mat.f_[0] = 1.0f - y2 - z2; + mat.f_[1] = xy + zw; + mat.f_[2] = zx - yw; + mat.f_[4] = xy - zw; + mat.f_[5] = 1.0f - z2 - x2; + mat.f_[6] = yz + xw; + mat.f_[8] = zx + yw; + mat.f_[9] = yz - xw; + mat.f_[10] = 1.0f - x2 - y2; + + mat.f_[3] = mat.f_[7] = mat.f_[11] = mat.f_[12] = mat.f_[13] = mat.f_[14] = + 0.0f; + mat.f_[15] = 1.0f; + } + + void ToMatrixPreserveTranslate(Mat4& mat) { + float x2 = x_ * x_ * 2.0f; + float y2 = y_ * y_ * 2.0f; + float z2 = z_ * z_ * 2.0f; + float xy = x_ * y_ * 2.0f; + float yz = y_ * z_ * 2.0f; + float zx = z_ * x_ * 2.0f; + float xw = x_ * w_ * 2.0f; + float yw = y_ * w_ * 2.0f; + float zw = z_ * w_ * 2.0f; + + mat.f_[0] = 1.0f - y2 - z2; + mat.f_[1] = xy + zw; + mat.f_[2] = zx - yw; + mat.f_[4] = xy - zw; + mat.f_[5] = 1.0f - z2 - x2; + mat.f_[6] = yz + xw; + mat.f_[8] = zx + yw; + mat.f_[9] = yz - xw; + mat.f_[10] = 1.0f - x2 - y2; + + mat.f_[3] = mat.f_[7] = mat.f_[11] = 0.0f; + mat.f_[15] = 1.0f; + } + + static Quaternion RotationAxis(const Vec3 axis, const float angle) { + Quaternion ret; + float s = sinf(angle / 2); + ret.x_ = s * axis.x_; + ret.y_ = s * axis.y_; + ret.z_ = s * axis.z_; + ret.w_ = cosf(angle / 2); + return ret; + } + + void Value(float& fX, float& fY, float& fZ, float& fW) { + fX = x_; + fY = y_; + fZ = z_; + fW = w_; + } +}; + +} // namespace ndk_helper +#endif /* VECMATH_H_ */ diff --git a/NativeApp/Android/ndk_helper/src/GLContext.cpp b/NativeApp/Android/ndk_helper/src/GLContext.cpp new file mode 100644 index 0000000..53f16ff --- /dev/null +++ b/NativeApp/Android/ndk_helper/src/GLContext.cpp @@ -0,0 +1,269 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//-------------------------------------------------------------------------------- +// GLContext.cpp +//-------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------- +// includes +//-------------------------------------------------------------------------------- +#include "GLContext.h" + +#include <string.h> +#include <unistd.h> + +#include "gl3stub.h" + +namespace ndk_helper { + +//-------------------------------------------------------------------------------- +// eGLContext +//-------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------- +// Ctor +//-------------------------------------------------------------------------------- +GLContext::GLContext() + : window_(nullptr), + display_(EGL_NO_DISPLAY), + surface_(EGL_NO_SURFACE), + context_(EGL_NO_CONTEXT), + screen_width_(0), + screen_height_(0), + gles_initialized_(false), + egl_context_initialized_(false), + es3_supported_(false) {} + +void GLContext::InitGLES() { + if (gles_initialized_) return; + // + // Initialize OpenGL ES 3 if available + // + const char* versionStr = (const char*)glGetString(GL_VERSION); + if (strstr(versionStr, "OpenGL ES 3.") && gl3stubInit()) { + es3_supported_ = true; + gl_version_ = 3.0f; + } else { + gl_version_ = 2.0f; + } + + gles_initialized_ = true; +} + +//-------------------------------------------------------------------------------- +// Dtor +//-------------------------------------------------------------------------------- +GLContext::~GLContext() { Terminate(); } + +bool GLContext::Init(ANativeWindow* window) { + if (egl_context_initialized_) return true; + + // + // Initialize EGL + // + window_ = window; + InitEGLSurface(); + InitEGLContext(); + InitGLES(); + + egl_context_initialized_ = true; + + return true; +} + +bool GLContext::InitEGLSurface() { + display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); + eglInitialize(display_, 0, 0); + + /* + * Here specify the attributes of the desired configuration. + * Below, we select an EGLConfig with at least 8 bits per color + * component compatible with on-screen windows + */ + const EGLint attribs[] = {EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, // Request opengl ES2.0 + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, + EGL_BLUE_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_RED_SIZE, + 8, + EGL_DEPTH_SIZE, + 24, + EGL_NONE}; + color_size_ = 8; + depth_size_ = 24; + + EGLint num_configs; + eglChooseConfig(display_, attribs, &config_, 1, &num_configs); + + if (!num_configs) { + // Fall back to 16bit depth buffer + const EGLint attribs[] = {EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, // Request opengl ES2.0 + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, + EGL_BLUE_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_RED_SIZE, + 8, + EGL_DEPTH_SIZE, + 16, + EGL_NONE}; + eglChooseConfig(display_, attribs, &config_, 1, &num_configs); + depth_size_ = 16; + } + + if (!num_configs) { + LOGW("Unable to retrieve EGL config"); + return false; + } + + surface_ = eglCreateWindowSurface(display_, config_, window_, NULL); + eglQuerySurface(display_, surface_, EGL_WIDTH, &screen_width_); + eglQuerySurface(display_, surface_, EGL_HEIGHT, &screen_height_); + + return true; +} + +bool GLContext::InitEGLContext() { + const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, + 2, // Request opengl ES2.0 + EGL_NONE}; + context_ = eglCreateContext(display_, config_, NULL, context_attribs); + + if (eglMakeCurrent(display_, surface_, surface_, context_) == EGL_FALSE) { + LOGW("Unable to eglMakeCurrent"); + return false; + } + + context_valid_ = true; + return true; +} + +EGLint GLContext::Swap() { + bool b = eglSwapBuffers(display_, surface_); + if (!b) { + EGLint err = eglGetError(); + if (err == EGL_BAD_SURFACE) { + // Recreate surface + InitEGLSurface(); + return EGL_SUCCESS; // Still consider glContext is valid + } else if (err == EGL_CONTEXT_LOST || err == EGL_BAD_CONTEXT) { + // Context has been lost!! + context_valid_ = false; + Terminate(); + InitEGLContext(); + } + return err; + } + return EGL_SUCCESS; +} + +void GLContext::Terminate() { + if (display_ != EGL_NO_DISPLAY) { + eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (context_ != EGL_NO_CONTEXT) { + eglDestroyContext(display_, context_); + } + + if (surface_ != EGL_NO_SURFACE) { + eglDestroySurface(display_, surface_); + } + eglTerminate(display_); + } + + display_ = EGL_NO_DISPLAY; + context_ = EGL_NO_CONTEXT; + surface_ = EGL_NO_SURFACE; + window_ = nullptr; + context_valid_ = false; +} + +EGLint GLContext::Resume(ANativeWindow* window) { + if (egl_context_initialized_ == false) { + Init(window); + return EGL_SUCCESS; + } + + int32_t original_widhth = screen_width_; + int32_t original_height = screen_height_; + + // Create surface + window_ = window; + surface_ = eglCreateWindowSurface(display_, config_, window_, NULL); + eglQuerySurface(display_, surface_, EGL_WIDTH, &screen_width_); + eglQuerySurface(display_, surface_, EGL_HEIGHT, &screen_height_); + + if (screen_width_ != original_widhth || screen_height_ != original_height) { + // Screen resized + LOGI("Screen resized"); + } + + if (eglMakeCurrent(display_, surface_, surface_, context_) == EGL_TRUE) + return EGL_SUCCESS; + + EGLint err = eglGetError(); + LOGW("Unable to eglMakeCurrent %d", err); + + if (err == EGL_CONTEXT_LOST) { + // Recreate context + LOGI("Re-creating egl context"); + InitEGLContext(); + } else { + // Recreate surface + Terminate(); + InitEGLSurface(); + InitEGLContext(); + } + + return err; +} + +void GLContext::Suspend() { + if (surface_ != EGL_NO_SURFACE) { + eglDestroySurface(display_, surface_); + surface_ = EGL_NO_SURFACE; + } +} + +bool GLContext::Invalidate() { + Terminate(); + + egl_context_initialized_ = false; + return true; +} + +bool GLContext::CheckExtension(const char* extension) { + if (extension == NULL) return false; + + std::string extensions = std::string((char*)glGetString(GL_EXTENSIONS)); + std::string str = std::string(extension); + str.append(" "); + + size_t pos = 0; + if (extensions.find(extension, pos) != std::string::npos) { + return true; + } + + return false; +} + +} // namespace ndkHelper diff --git a/NativeApp/Android/ndk_helper/src/JNIHelper.cpp b/NativeApp/Android/ndk_helper/src/JNIHelper.cpp new file mode 100644 index 0000000..dfaa0bf --- /dev/null +++ b/NativeApp/Android/ndk_helper/src/JNIHelper.cpp @@ -0,0 +1,770 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "JNIHelper.h" + +#include <string.h> + +#include <fstream> +#include <iostream> + +#include <EGL/egl.h> +#include <GLES2/gl2.h> + +namespace ndk_helper { + +#define NATIVEACTIVITY_CLASS_NAME "android/app/NativeActivity" + +//--------------------------------------------------------------------------- +// JNI Helper functions +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// Singleton +//--------------------------------------------------------------------------- +JNIHelper* JNIHelper::GetInstance() { + static JNIHelper helper; + return &helper; +} + +//--------------------------------------------------------------------------- +// Ctor +//--------------------------------------------------------------------------- +JNIHelper::JNIHelper() : activity_(NULL) {} + +//--------------------------------------------------------------------------- +// Dtor +//--------------------------------------------------------------------------- +JNIHelper::~JNIHelper() { + // Lock mutex + std::lock_guard<std::mutex> lock(mutex_); + + JNIEnv* env = AttachCurrentThread(); + env->DeleteGlobalRef(jni_helper_java_ref_); + env->DeleteGlobalRef(jni_helper_java_class_); + + DetachCurrentThread(); +} + +//--------------------------------------------------------------------------- +// Init +//--------------------------------------------------------------------------- +void JNIHelper::Init(ANativeActivity* activity, const char* helper_class_name) { + JNIHelper& helper = *GetInstance(); + + helper.activity_ = activity; + + // Lock mutex + std::lock_guard<std::mutex> lock(helper.mutex_); + + JNIEnv* env = helper.AttachCurrentThread(); + + // Retrieve app bundle id + jclass android_content_Context = env->GetObjectClass(helper.activity_->clazz); + jmethodID midGetPackageName = env->GetMethodID( + android_content_Context, "getPackageName", "()Ljava/lang/String;"); + + jstring packageName = (jstring)env->CallObjectMethod(helper.activity_->clazz, + midGetPackageName); + const char* appname = env->GetStringUTFChars(packageName, NULL); + helper.app_name_ = std::string(appname); + + jclass cls = helper.RetrieveClass(env, helper_class_name); + helper.jni_helper_java_class_ = (jclass)env->NewGlobalRef(cls); + + jmethodID constructor = + env->GetMethodID(helper.jni_helper_java_class_, "<init>", + "(Landroid/app/NativeActivity;)V"); + + helper.jni_helper_java_ref_ = env->NewObject(helper.jni_helper_java_class_, + constructor, activity->clazz); + helper.jni_helper_java_ref_ = env->NewGlobalRef(helper.jni_helper_java_ref_); + + // Get app label + jstring labelName = (jstring)helper.CallObjectMethod("getApplicationName", + "()Ljava/lang/String;"); + const char* label = env->GetStringUTFChars(labelName, NULL); + helper.app_label_ = std::string(label); + + env->ReleaseStringUTFChars(packageName, appname); + env->ReleaseStringUTFChars(labelName, label); + env->DeleteLocalRef(packageName); + env->DeleteLocalRef(labelName); + env->DeleteLocalRef(cls); +} + +void JNIHelper::Init(ANativeActivity* activity, const char* helper_class_name, + const char* native_soname) { + Init(activity, helper_class_name); + if (native_soname) { + JNIHelper& helper = *GetInstance(); + // Lock mutex + std::lock_guard<std::mutex> lock(helper.mutex_); + + JNIEnv* env = helper.AttachCurrentThread(); + + // Setup soname + jstring soname = env->NewStringUTF(native_soname); + + jmethodID mid = env->GetMethodID(helper.jni_helper_java_class_, + "loadLibrary", "(Ljava/lang/String;)V"); + env->CallVoidMethod(helper.jni_helper_java_ref_, mid, soname); + + env->DeleteLocalRef(soname); + } +} + +//--------------------------------------------------------------------------- +// readFile +//--------------------------------------------------------------------------- +bool JNIHelper::ReadFile(const char* fileName, + std::vector<uint8_t>* buffer_ref) { + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized.Call init() to initialize the " + "helper"); + return false; + } + + // Lock mutex + std::lock_guard<std::mutex> lock(mutex_); + + // First, try reading from externalFileDir; + JNIEnv* env = AttachCurrentThread(); + jstring str_path = GetExternalFilesDirJString(env); + + std::string s; + if(str_path) { + const char* path = env->GetStringUTFChars(str_path, NULL); + s = std::string(path); + if (fileName[0] != '/') { + s.append("/"); + } + s.append(fileName); + env->ReleaseStringUTFChars(str_path, path); + env->DeleteLocalRef(str_path); + } + std::ifstream f(s.c_str(), std::ios::binary); + activity_->vm->DetachCurrentThread(); + if (f) { + LOGI("reading:%s", s.c_str()); + f.seekg(0, std::ifstream::end); + int32_t fileSize = f.tellg(); + f.seekg(0, std::ifstream::beg); + buffer_ref->reserve(fileSize); + buffer_ref->assign(std::istreambuf_iterator<char>(f), + std::istreambuf_iterator<char>()); + f.close(); + return true; + } else { + // Fallback to assetManager + AAssetManager* assetManager = activity_->assetManager; + AAsset* assetFile = + AAssetManager_open(assetManager, fileName, AASSET_MODE_BUFFER); + if (!assetFile) { + return false; + } + uint8_t* data = (uint8_t*)AAsset_getBuffer(assetFile); + int32_t size = AAsset_getLength(assetFile); + if (data == NULL) { + AAsset_close(assetFile); + + LOGI("Failed to load:%s", fileName); + return false; + } + + buffer_ref->reserve(size); + buffer_ref->assign(data, data + size); + + AAsset_close(assetFile); + return true; + } +} + +std::string JNIHelper::GetExternalFilesDir() { + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized. Call init() to initialize the " + "helper"); + return std::string(""); + } + + // Lock mutex + std::lock_guard<std::mutex> lock(mutex_); + + // First, try reading from externalFileDir; + JNIEnv* env = AttachCurrentThread(); + + jstring strPath = GetExternalFilesDirJString(env); + const char* path = env->GetStringUTFChars(strPath, NULL); + std::string s(path); + + env->ReleaseStringUTFChars(strPath, path); + env->DeleteLocalRef(strPath); + return s; +} + +uint32_t JNIHelper::LoadTexture(const char* file_name, int32_t* outWidth, + int32_t* outHeight, bool* hasAlpha) { + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized. Call init() to initialize the " + "helper"); + return 0; + } + + // Lock mutex + std::lock_guard<std::mutex> lock(mutex_); + + JNIEnv* env = AttachCurrentThread(); + jstring name = env->NewStringUTF(file_name); + + GLuint tex; + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + jmethodID mid = env->GetMethodID(jni_helper_java_class_, "loadTexture", + "(Ljava/lang/String;)Ljava/lang/Object;"); + + jobject out = env->CallObjectMethod(jni_helper_java_ref_, mid, name); + + jclass javaCls = + RetrieveClass(env, "com/sample/helper/NDKHelper$TextureInformation"); + jfieldID fidRet = env->GetFieldID(javaCls, "ret", "Z"); + jfieldID fidHasAlpha = env->GetFieldID(javaCls, "alphaChannel", "Z"); + jfieldID fidWidth = env->GetFieldID(javaCls, "originalWidth", "I"); + jfieldID fidHeight = env->GetFieldID(javaCls, "originalHeight", "I"); + bool ret = env->GetBooleanField(out, fidRet); + bool alpha = env->GetBooleanField(out, fidHasAlpha); + int32_t width = env->GetIntField(out, fidWidth); + int32_t height = env->GetIntField(out, fidHeight); + if (!ret) { + glDeleteTextures(1, &tex); + tex = -1; + LOGI("Texture load failed %s", file_name); + } + LOGI("Loaded texture original size:%dx%d alpha:%d", width, height, + (int32_t)alpha); + if (outWidth != NULL) { + *outWidth = width; + } + if (outHeight != NULL) { + *outHeight = height; + } + if (hasAlpha != NULL) { + *hasAlpha = alpha; + } + + // Generate mipmap + glGenerateMipmap(GL_TEXTURE_2D); + + env->DeleteLocalRef(name); + DetachCurrentThread(); + + return tex; +} + +uint32_t JNIHelper::LoadCubemapTexture(const char* file_name, + const int32_t face, + const int32_t miplevel, const bool sRGB, + int32_t* outWidth, int32_t* outHeight, + bool* hasAlpha) { + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized. Call init() to initialize the " + "helper"); + return 0; + } + + // Lock mutex + std::lock_guard<std::mutex> lock(mutex_); + + JNIEnv* env = AttachCurrentThread(); + jstring name = env->NewStringUTF(file_name); + + jmethodID mid = env->GetMethodID(jni_helper_java_class_, "loadCubemapTexture", + "(Ljava/lang/String;IIZ)Ljava/lang/Object;"); + + jobject out = + env->CallObjectMethod(jni_helper_java_ref_, mid, name, face, miplevel); + + jclass javaCls = + RetrieveClass(env, "com/sample/helper/NDKHelper$TextureInformation"); + jfieldID fidRet = env->GetFieldID(javaCls, "ret", "Z"); + jfieldID fidHasAlpha = env->GetFieldID(javaCls, "alphaChannel", "Z"); + jfieldID fidWidth = env->GetFieldID(javaCls, "originalWidth", "I"); + jfieldID fidHeight = env->GetFieldID(javaCls, "originalHeight", "I"); + bool ret = env->GetBooleanField(out, fidRet); + bool alpha = env->GetBooleanField(out, fidHasAlpha); + int32_t width = env->GetIntField(out, fidWidth); + int32_t height = env->GetIntField(out, fidHeight); + if (!ret) { + LOGI("Texture load failed %s", file_name); + } + LOGI("Loaded texture original size:%dx%d alpha:%d", width, height, + (int32_t)alpha); + if (outWidth != NULL) { + *outWidth = width; + } + if (outHeight != NULL) { + *outHeight = height; + } + if (hasAlpha != NULL) { + *hasAlpha = alpha; + } + + env->DeleteLocalRef(name); + env->DeleteLocalRef(javaCls); + + return 0; +} + +jobject JNIHelper::LoadImage(const char* file_name, int32_t* outWidth, + int32_t* outHeight, bool* hasAlpha) { + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized. Call init() to initialize the " + "helper"); + return 0; + } + + // Lock mutex + std::lock_guard<std::mutex> lock(mutex_); + + JNIEnv* env = AttachCurrentThread(); + jstring name = env->NewStringUTF(file_name); + + jmethodID mid = env->GetMethodID(jni_helper_java_class_, "loadImage", + "(Ljava/lang/String;)Ljava/lang/Object;"); + + jobject out = env->CallObjectMethod(jni_helper_java_ref_, mid, name); + + jclass javaCls = + RetrieveClass(env, "com/sample/helper/NDKHelper$TextureInformation"); + jfieldID fidRet = env->GetFieldID(javaCls, "ret", "Z"); + jfieldID fidHasAlpha = env->GetFieldID(javaCls, "alphaChannel", "Z"); + jfieldID fidWidth = env->GetFieldID(javaCls, "originalWidth", "I"); + jfieldID fidHeight = env->GetFieldID(javaCls, "originalHeight", "I"); + bool ret = env->GetBooleanField(out, fidRet); + bool alpha = env->GetBooleanField(out, fidHasAlpha); + int32_t width = env->GetIntField(out, fidWidth); + int32_t height = env->GetIntField(out, fidHeight); + if (!ret) { + LOGI("Texture load failed %s", file_name); + } + LOGI("Loaded texture original size:%dx%d alpha:%d", width, height, + (int32_t)alpha); + if (outWidth != NULL) { + *outWidth = width; + } + if (outHeight != NULL) { + *outHeight = height; + } + if (hasAlpha != NULL) { + *hasAlpha = alpha; + } + + jfieldID fidImage = env->GetFieldID(javaCls, "image", "Ljava/lang/Object;"); + jobject array = env->GetObjectField(out, fidImage); + jobject objGlobal = env->NewGlobalRef(array); + + env->DeleteLocalRef(name); + env->DeleteLocalRef(javaCls); + + return objGlobal; +} + +std::string JNIHelper::ConvertString(const char* str, const char* encode) { + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized. Call init() to initialize the " + "helper"); + return std::string(""); + } + + // Lock mutex + std::lock_guard<std::mutex> lock(mutex_); + + JNIEnv* env = AttachCurrentThread(); + env->PushLocalFrame(16); + + int32_t iLength = strlen((const char*)str); + + jbyteArray array = env->NewByteArray(iLength); + env->SetByteArrayRegion(array, 0, iLength, (const signed char*)str); + + jstring strEncode = env->NewStringUTF(encode); + + jclass cls = env->FindClass("java/lang/String"); + jmethodID ctor = env->GetMethodID(cls, "<init>", "([BLjava/lang/String;)V"); + jstring object = (jstring)env->NewObject(cls, ctor, array, strEncode); + + const char* cparam = env->GetStringUTFChars(object, NULL); + + std::string s = std::string(cparam); + + env->ReleaseStringUTFChars(object, cparam); + env->DeleteLocalRef(array); + env->DeleteLocalRef(strEncode); + env->DeleteLocalRef(object); + env->DeleteLocalRef(cls); + + env->PopLocalFrame(NULL); + + return s; +} +/* + * Retrieve string resource with a given name + * arguments: + * in: resourceName, name of string resource to retrieve + * return: string resource value, returns "" when there is no string resource + * with given name + */ +std::string JNIHelper::GetStringResource(const std::string& resourceName) { + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized. Call init() to initialize the " + "helper"); + return std::string(""); + } + + // Lock mutex + std::lock_guard<std::mutex> lock(mutex_); + + JNIEnv* env = AttachCurrentThread(); + jstring name = env->NewStringUTF(resourceName.c_str()); + + jstring ret = (jstring)CallObjectMethod( + "getStringResource", "(Ljava/lang/String;)Ljava/lang/String;", name); + + const char* resource = env->GetStringUTFChars(ret, NULL); + std::string s = std::string(resource); + + env->ReleaseStringUTFChars(ret, resource); + env->DeleteLocalRef(ret); + env->DeleteLocalRef(name); + + return s; +} +/* + * Audio helpers + */ +int32_t JNIHelper::GetNativeAudioBufferSize() { + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized. Call init() to initialize the " + "helper"); + return 0; + } + + JNIEnv* env = AttachCurrentThread(); + jmethodID mid = env->GetMethodID(jni_helper_java_class_, + "getNativeAudioBufferSize", "()I"); + int32_t i = env->CallIntMethod(jni_helper_java_ref_, mid); + return i; +} + +int32_t JNIHelper::GetNativeAudioSampleRate() { + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized. Call init() to initialize the " + "helper"); + return 0; + } + + JNIEnv* env = AttachCurrentThread(); + jmethodID mid = env->GetMethodID(jni_helper_java_class_, + "getNativeAudioSampleRate", "()I"); + int32_t i = env->CallIntMethod(jni_helper_java_ref_, mid); + return i; +} + +//--------------------------------------------------------------------------- +// Misc implementations +//--------------------------------------------------------------------------- +jclass JNIHelper::RetrieveClass(JNIEnv* jni, const char* class_name) { + jclass activity_class = jni->FindClass(NATIVEACTIVITY_CLASS_NAME); + jmethodID get_class_loader = jni->GetMethodID( + activity_class, "getClassLoader", "()Ljava/lang/ClassLoader;"); + jobject cls = jni->CallObjectMethod(activity_->clazz, get_class_loader); + jclass class_loader = jni->FindClass("java/lang/ClassLoader"); + jmethodID find_class = jni->GetMethodID( + class_loader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); + + jstring str_class_name = jni->NewStringUTF(class_name); + jclass class_retrieved = + (jclass)jni->CallObjectMethod(cls, find_class, str_class_name); + jni->DeleteLocalRef(str_class_name); + jni->DeleteLocalRef(activity_class); + jni->DeleteLocalRef(class_loader); + return class_retrieved; +} + +jstring JNIHelper::GetExternalFilesDirJString(JNIEnv* env) { + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized. Call init() to initialize the " + "helper"); + return NULL; + } + + jstring obj_Path = nullptr; + // Invoking getExternalFilesDir() java API + jclass cls_Env = env->FindClass(NATIVEACTIVITY_CLASS_NAME); + jmethodID mid = env->GetMethodID(cls_Env, "getExternalFilesDir", + "(Ljava/lang/String;)Ljava/io/File;"); + jobject obj_File = env->CallObjectMethod(activity_->clazz, mid, NULL); + if (obj_File) { + jclass cls_File = env->FindClass("java/io/File"); + jmethodID mid_getPath = + env->GetMethodID(cls_File, "getPath", "()Ljava/lang/String;"); + obj_Path = (jstring)env->CallObjectMethod(obj_File, mid_getPath); + } + return obj_Path; +} + +void JNIHelper::DeleteObject(jobject obj) { + if (obj == NULL) { + LOGI("obj can not be NULL"); + return; + } + + JNIEnv* env = AttachCurrentThread(); + env->DeleteGlobalRef(obj); +} + +jobject JNIHelper::CallObjectMethod(const char* strMethodName, + const char* strSignature, ...) { + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized. Call init() to initialize the " + "helper"); + return NULL; + } + + JNIEnv* env = AttachCurrentThread(); + jmethodID mid = + env->GetMethodID(jni_helper_java_class_, strMethodName, strSignature); + if (mid == NULL) { + LOGI("method ID %s, '%s' not found", strMethodName, strSignature); + return NULL; + } + + va_list args; + va_start(args, strSignature); + jobject obj = env->CallObjectMethodV(jni_helper_java_ref_, mid, args); + va_end(args); + + return obj; +} + +void JNIHelper::CallVoidMethod(const char* strMethodName, + const char* strSignature, ...) { + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized. Call init() to initialize the " + "helper"); + return; + } + + JNIEnv* env = AttachCurrentThread(); + jmethodID mid = + env->GetMethodID(jni_helper_java_class_, strMethodName, strSignature); + if (mid == NULL) { + LOGI("method ID %s, '%s' not found", strMethodName, strSignature); + return; + } + va_list args; + va_start(args, strSignature); + env->CallVoidMethodV(jni_helper_java_ref_, mid, args); + va_end(args); + + return; +} + +jobject JNIHelper::CallObjectMethod(jobject object, const char* strMethodName, + const char* strSignature, ...) { + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized. Call init() to initialize the " + "helper"); + return NULL; + } + + JNIEnv* env = AttachCurrentThread(); + jclass cls = env->GetObjectClass(object); + jmethodID mid = env->GetMethodID(cls, strMethodName, strSignature); + if (mid == NULL) { + LOGI("method ID %s, '%s' not found", strMethodName, strSignature); + return NULL; + } + + va_list args; + va_start(args, strSignature); + jobject obj = env->CallObjectMethodV(object, mid, args); + va_end(args); + + env->DeleteLocalRef(cls); + return obj; +} + +void JNIHelper::CallVoidMethod(jobject object, const char* strMethodName, + const char* strSignature, ...) { + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized. Call init() to initialize the " + "helper"); + return; + } + + JNIEnv* env = AttachCurrentThread(); + jclass cls = env->GetObjectClass(object); + jmethodID mid = env->GetMethodID(cls, strMethodName, strSignature); + if (mid == NULL) { + LOGI("method ID %s, '%s' not found", strMethodName, strSignature); + return; + } + + va_list args; + va_start(args, strSignature); + env->CallVoidMethodV(object, mid, args); + va_end(args); + + env->DeleteLocalRef(cls); + return; +} + +float JNIHelper::CallFloatMethod(jobject object, const char* strMethodName, + const char* strSignature, ...) { + float f = 0.f; + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized. Call init() to initialize the " + "helper"); + return f; + } + + JNIEnv* env = AttachCurrentThread(); + jclass cls = env->GetObjectClass(object); + jmethodID mid = env->GetMethodID(cls, strMethodName, strSignature); + if (mid == NULL) { + LOGI("method ID %s, '%s' not found", strMethodName, strSignature); + return f; + } + va_list args; + va_start(args, strSignature); + f = env->CallFloatMethodV(object, mid, args); + va_end(args); + + env->DeleteLocalRef(cls); + return f; +} + +int32_t JNIHelper::CallIntMethod(jobject object, const char* strMethodName, + const char* strSignature, ...) { + int32_t i = 0; + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized. Call init() to initialize the " + "helper"); + return i; + } + + JNIEnv* env = AttachCurrentThread(); + jclass cls = env->GetObjectClass(object); + jmethodID mid = env->GetMethodID(cls, strMethodName, strSignature); + if (mid == NULL) { + LOGI("method ID %s, '%s' not found", strMethodName, strSignature); + return i; + } + va_list args; + va_start(args, strSignature); + i = env->CallIntMethodV(object, mid, args); + va_end(args); + + env->DeleteLocalRef(cls); + return i; +} + +bool JNIHelper::CallBooleanMethod(jobject object, const char* strMethodName, + const char* strSignature, ...) { + bool b; + if (activity_ == NULL) { + LOGI( + "JNIHelper has not been initialized. Call init() to initialize the " + "helper"); + return false; + } + + JNIEnv* env = AttachCurrentThread(); + jclass cls = env->GetObjectClass(object); + jmethodID mid = env->GetMethodID(cls, strMethodName, strSignature); + if (mid == NULL) { + LOGI("method ID %s, '%s' not found", strMethodName, strSignature); + return false; + } + va_list args; + va_start(args, strSignature); + b = env->CallBooleanMethodV(object, mid, args); + va_end(args); + + env->DeleteLocalRef(cls); + return b; +} + +jobject JNIHelper::CreateObject(const char* class_name) { + JNIEnv* env = AttachCurrentThread(); + + jclass cls = env->FindClass(class_name); + jmethodID constructor = env->GetMethodID(cls, "<init>", "()V"); + + jobject obj = env->NewObject(cls, constructor); + jobject objGlobal = env->NewGlobalRef(obj); + env->DeleteLocalRef(obj); + env->DeleteLocalRef(cls); + return objGlobal; +} + +void JNIHelper::RunOnUiThread(std::function<void()> callback) { + // Lock mutex + std::lock_guard<std::mutex> lock(mutex_); + + JNIEnv* env = AttachCurrentThread(); + static jmethodID mid = NULL; + if (mid == NULL) + mid = env->GetMethodID(jni_helper_java_class_, "runOnUIThread", "(J)V"); + + // Allocate temporary function object to be passed around + std::function<void()>* pCallback = new std::function<void()>(callback); + env->CallVoidMethod(jni_helper_java_ref_, mid, (int64_t)pCallback); +} + +// This JNI function is invoked from UIThread asynchronously +extern "C" { +JNIEXPORT void Java_com_sample_helper_NDKHelper_RunOnUiThreadHandler( + JNIEnv* env, jobject thiz, int64_t pointer) { + std::function<void()>* pCallback = (std::function<void()>*)pointer; + (*pCallback)(); + + // Deleting temporary object + delete pCallback; +} +} + +} // namespace ndkHelper diff --git a/NativeApp/Android/ndk_helper/src/gestureDetector.cpp b/NativeApp/Android/ndk_helper/src/gestureDetector.cpp new file mode 100644 index 0000000..74e5411 --- /dev/null +++ b/NativeApp/Android/ndk_helper/src/gestureDetector.cpp @@ -0,0 +1,301 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gestureDetector.h" + +//-------------------------------------------------------------------------------- +// gestureDetector.cpp +//-------------------------------------------------------------------------------- +namespace ndk_helper { + +//-------------------------------------------------------------------------------- +// includes +//-------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------- +// GestureDetector +//-------------------------------------------------------------------------------- +GestureDetector::GestureDetector() { dp_factor_ = 1.f; } + +void GestureDetector::SetConfiguration(AConfiguration* config) { + dp_factor_ = 160.f / AConfiguration_getDensity(config); +} + +//-------------------------------------------------------------------------------- +// TapDetector +//-------------------------------------------------------------------------------- +TapDetector::TapDetector() : down_x_(0), down_y_(0) {} + +GESTURE_STATE TapDetector::Detect(const AInputEvent* motion_event) { + if (AMotionEvent_getPointerCount(motion_event) > 1) { + // Only support single touch + return false; + } + + int32_t action = AMotionEvent_getAction(motion_event); + unsigned int flags = action & AMOTION_EVENT_ACTION_MASK; + switch (flags) { + case AMOTION_EVENT_ACTION_DOWN: + down_pointer_id_ = AMotionEvent_getPointerId(motion_event, 0); + down_x_ = AMotionEvent_getX(motion_event, 0); + down_y_ = AMotionEvent_getY(motion_event, 0); + break; + case AMOTION_EVENT_ACTION_UP: { + int64_t eventTime = AMotionEvent_getEventTime(motion_event); + int64_t downTime = AMotionEvent_getDownTime(motion_event); + if (eventTime - downTime <= TAP_TIMEOUT) { + if (down_pointer_id_ == AMotionEvent_getPointerId(motion_event, 0)) { + float x = AMotionEvent_getX(motion_event, 0) - down_x_; + float y = AMotionEvent_getY(motion_event, 0) - down_y_; + if (x * x + y * y < TOUCH_SLOP * TOUCH_SLOP * dp_factor_) { + LOGI("TapDetector: Tap detected"); + return GESTURE_STATE_ACTION; + } + } + } + break; + } + } + return GESTURE_STATE_NONE; +} + +//-------------------------------------------------------------------------------- +// DoubletapDetector +//-------------------------------------------------------------------------------- +DoubletapDetector::DoubletapDetector() + : last_tap_time_(0), last_tap_x_(0), last_tap_y_(0) {} + +GESTURE_STATE DoubletapDetector::Detect(const AInputEvent* motion_event) { + if (AMotionEvent_getPointerCount(motion_event) > 1) { + // Only support single double tap + return false; + } + + bool tap_detected = tap_detector_.Detect(motion_event); + + int32_t action = AMotionEvent_getAction(motion_event); + unsigned int flags = action & AMOTION_EVENT_ACTION_MASK; + switch (flags) { + case AMOTION_EVENT_ACTION_DOWN: { + int64_t eventTime = AMotionEvent_getEventTime(motion_event); + if (eventTime - last_tap_time_ <= DOUBLE_TAP_TIMEOUT) { + float x = AMotionEvent_getX(motion_event, 0) - last_tap_x_; + float y = AMotionEvent_getY(motion_event, 0) - last_tap_y_; + if (x * x + y * y < DOUBLE_TAP_SLOP * DOUBLE_TAP_SLOP * dp_factor_) { + LOGI("DoubletapDetector: Doubletap detected"); + return GESTURE_STATE_ACTION; + } + } + break; + } + case AMOTION_EVENT_ACTION_UP: + if (tap_detected) { + last_tap_time_ = AMotionEvent_getEventTime(motion_event); + last_tap_x_ = AMotionEvent_getX(motion_event, 0); + last_tap_y_ = AMotionEvent_getY(motion_event, 0); + } + break; + } + return GESTURE_STATE_NONE; +} + +void DoubletapDetector::SetConfiguration(AConfiguration* config) { + dp_factor_ = 160.f / AConfiguration_getDensity(config); + tap_detector_.SetConfiguration(config); +} + +//-------------------------------------------------------------------------------- +// PinchDetector +//-------------------------------------------------------------------------------- + +int32_t PinchDetector::FindIndex(const AInputEvent* event, int32_t id) { + int32_t count = AMotionEvent_getPointerCount(event); + for (auto i = 0; i < count; ++i) { + if (id == AMotionEvent_getPointerId(event, i)) return i; + } + return -1; +} + +GESTURE_STATE PinchDetector::Detect(const AInputEvent* event) { + GESTURE_STATE ret = GESTURE_STATE_NONE; + int32_t action = AMotionEvent_getAction(event); + uint32_t flags = action & AMOTION_EVENT_ACTION_MASK; + event_ = event; + + int32_t count = AMotionEvent_getPointerCount(event); + switch (flags) { + case AMOTION_EVENT_ACTION_DOWN: + vec_pointers_.push_back(AMotionEvent_getPointerId(event, 0)); + break; + case AMOTION_EVENT_ACTION_POINTER_DOWN: { + int32_t iIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> + AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; + vec_pointers_.push_back(AMotionEvent_getPointerId(event, iIndex)); + if (count == 2) { + // Start new pinch + ret = GESTURE_STATE_START; + } + } break; + case AMOTION_EVENT_ACTION_UP: + vec_pointers_.pop_back(); + break; + case AMOTION_EVENT_ACTION_POINTER_UP: { + int32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> + AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; + int32_t released_pointer_id = AMotionEvent_getPointerId(event, index); + + std::vector<int32_t>::iterator it = vec_pointers_.begin(); + std::vector<int32_t>::iterator it_end = vec_pointers_.end(); + int32_t i = 0; + for (; it != it_end; ++it, ++i) { + if (*it == released_pointer_id) { + vec_pointers_.erase(it); + break; + } + } + + if (i <= 1) { + // Reset pinch or drag + if (count != 2) { + // Start new pinch + ret = GESTURE_STATE_START | GESTURE_STATE_END; + } + } + } break; + case AMOTION_EVENT_ACTION_MOVE: + switch (count) { + case 1: + break; + default: + // Multi touch + ret = GESTURE_STATE_MOVE; + break; + } + break; + case AMOTION_EVENT_ACTION_CANCEL: + break; + } + + return ret; +} + +bool PinchDetector::GetPointers(Vec2& v1, Vec2& v2) { + if (vec_pointers_.size() < 2) return false; + + int32_t index = FindIndex(event_, vec_pointers_[0]); + if (index == -1) return false; + + float x = AMotionEvent_getX(event_, index); + float y = AMotionEvent_getY(event_, index); + + index = FindIndex(event_, vec_pointers_[1]); + if (index == -1) return false; + + float x2 = AMotionEvent_getX(event_, index); + float y2 = AMotionEvent_getY(event_, index); + + v1 = Vec2(x, y); + v2 = Vec2(x2, y2); + + return true; +} + +//-------------------------------------------------------------------------------- +// DragDetector +//-------------------------------------------------------------------------------- + +int32_t DragDetector::FindIndex(const AInputEvent* event, int32_t id) { + int32_t count = AMotionEvent_getPointerCount(event); + for (auto i = 0; i < count; ++i) { + if (id == AMotionEvent_getPointerId(event, i)) return i; + } + return -1; +} + +GESTURE_STATE DragDetector::Detect(const AInputEvent* event) { + GESTURE_STATE ret = GESTURE_STATE_NONE; + int32_t action = AMotionEvent_getAction(event); + int32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> + AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; + uint32_t flags = action & AMOTION_EVENT_ACTION_MASK; + event_ = event; + + int32_t count = AMotionEvent_getPointerCount(event); + switch (flags) { + case AMOTION_EVENT_ACTION_DOWN: + vec_pointers_.push_back(AMotionEvent_getPointerId(event, 0)); + ret = GESTURE_STATE_START; + break; + case AMOTION_EVENT_ACTION_POINTER_DOWN: + vec_pointers_.push_back(AMotionEvent_getPointerId(event, index)); + break; + case AMOTION_EVENT_ACTION_UP: + vec_pointers_.pop_back(); + ret = GESTURE_STATE_END; + break; + case AMOTION_EVENT_ACTION_POINTER_UP: { + int32_t released_pointer_id = AMotionEvent_getPointerId(event, index); + + auto it = vec_pointers_.begin(); + auto it_end = vec_pointers_.end(); + int32_t i = 0; + for (; it != it_end; ++it, ++i) { + if (*it == released_pointer_id) { + vec_pointers_.erase(it); + break; + } + } + + if (i <= 1) { + // Reset pinch or drag + if (count == 2) { + ret = GESTURE_STATE_START; + } + } + break; + } + case AMOTION_EVENT_ACTION_MOVE: + switch (count) { + case 1: + // Drag + ret = GESTURE_STATE_MOVE; + break; + default: + break; + } + break; + case AMOTION_EVENT_ACTION_CANCEL: + break; + } + + return ret; +} + +bool DragDetector::GetPointer(Vec2& v) { + if (vec_pointers_.size() < 1) return false; + + int32_t iIndex = FindIndex(event_, vec_pointers_[0]); + if (iIndex == -1) return false; + + float x = AMotionEvent_getX(event_, iIndex); + float y = AMotionEvent_getY(event_, iIndex); + + v = Vec2(x, y); + + return true; +} + +} // namespace ndkHelper diff --git a/NativeApp/Android/ndk_helper/src/gl3stub.c b/NativeApp/Android/ndk_helper/src/gl3stub.c new file mode 100644 index 0000000..d918b2c --- /dev/null +++ b/NativeApp/Android/ndk_helper/src/gl3stub.c @@ -0,0 +1,421 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <EGL/egl.h> +#include "gl3stub.h" + +GLboolean gl3stubInit() { +#define FIND_PROC(s) s = (void*)eglGetProcAddress(#s); + FIND_PROC(glReadBuffer); + FIND_PROC(glDrawRangeElements); + FIND_PROC(glTexImage3D); + FIND_PROC(glTexSubImage3D); + FIND_PROC(glCopyTexSubImage3D); + FIND_PROC(glCompressedTexImage3D); + FIND_PROC(glCompressedTexSubImage3D); + FIND_PROC(glGenQueries); + FIND_PROC(glDeleteQueries); + FIND_PROC(glIsQuery); + FIND_PROC(glBeginQuery); + FIND_PROC(glEndQuery); + FIND_PROC(glGetQueryiv); + FIND_PROC(glGetQueryObjectuiv); + FIND_PROC(glUnmapBuffer); + FIND_PROC(glGetBufferPointerv); + FIND_PROC(glDrawBuffers); + FIND_PROC(glUniformMatrix2x3fv); + FIND_PROC(glUniformMatrix3x2fv); + FIND_PROC(glUniformMatrix2x4fv); + FIND_PROC(glUniformMatrix4x2fv); + FIND_PROC(glUniformMatrix3x4fv); + FIND_PROC(glUniformMatrix4x3fv); + FIND_PROC(glBlitFramebuffer); + FIND_PROC(glRenderbufferStorageMultisample); + FIND_PROC(glFramebufferTextureLayer); + FIND_PROC(glMapBufferRange); + FIND_PROC(glFlushMappedBufferRange); + FIND_PROC(glBindVertexArray); + FIND_PROC(glDeleteVertexArrays); + FIND_PROC(glGenVertexArrays); + FIND_PROC(glIsVertexArray); + FIND_PROC(glGetIntegeri_v); + FIND_PROC(glBeginTransformFeedback); + FIND_PROC(glEndTransformFeedback); + FIND_PROC(glBindBufferRange); + FIND_PROC(glBindBufferBase); + FIND_PROC(glTransformFeedbackVaryings); + FIND_PROC(glGetTransformFeedbackVarying); + FIND_PROC(glVertexAttribIPointer); + FIND_PROC(glGetVertexAttribIiv); + FIND_PROC(glGetVertexAttribIuiv); + FIND_PROC(glVertexAttribI4i); + FIND_PROC(glVertexAttribI4ui); + FIND_PROC(glVertexAttribI4iv); + FIND_PROC(glVertexAttribI4uiv); + FIND_PROC(glGetUniformuiv); + FIND_PROC(glGetFragDataLocation); + FIND_PROC(glUniform1ui); + FIND_PROC(glUniform2ui); + FIND_PROC(glUniform3ui); + FIND_PROC(glUniform4ui); + FIND_PROC(glUniform1uiv); + FIND_PROC(glUniform2uiv); + FIND_PROC(glUniform3uiv); + FIND_PROC(glUniform4uiv); + FIND_PROC(glClearBufferiv); + FIND_PROC(glClearBufferuiv); + FIND_PROC(glClearBufferfv); + FIND_PROC(glClearBufferfi); + FIND_PROC(glGetStringi); + FIND_PROC(glCopyBufferSubData); + FIND_PROC(glGetUniformIndices); + FIND_PROC(glGetActiveUniformsiv); + FIND_PROC(glGetUniformBlockIndex); + FIND_PROC(glGetActiveUniformBlockiv); + FIND_PROC(glGetActiveUniformBlockName); + FIND_PROC(glUniformBlockBinding); + FIND_PROC(glDrawArraysInstanced); + FIND_PROC(glDrawElementsInstanced); + FIND_PROC(glFenceSync); + FIND_PROC(glIsSync); + FIND_PROC(glDeleteSync); + FIND_PROC(glClientWaitSync); + FIND_PROC(glWaitSync); + FIND_PROC(glGetInteger64v); + FIND_PROC(glGetSynciv); + FIND_PROC(glGetInteger64i_v); + FIND_PROC(glGetBufferParameteri64v); + FIND_PROC(glGenSamplers); + FIND_PROC(glDeleteSamplers); + FIND_PROC(glIsSampler); + FIND_PROC(glBindSampler); + FIND_PROC(glSamplerParameteri); + FIND_PROC(glSamplerParameteriv); + FIND_PROC(glSamplerParameterf); + FIND_PROC(glSamplerParameterfv); + FIND_PROC(glGetSamplerParameteriv); + FIND_PROC(glGetSamplerParameterfv); + FIND_PROC(glVertexAttribDivisor); + FIND_PROC(glBindTransformFeedback); + FIND_PROC(glDeleteTransformFeedbacks); + FIND_PROC(glGenTransformFeedbacks); + FIND_PROC(glIsTransformFeedback); + FIND_PROC(glPauseTransformFeedback); + FIND_PROC(glResumeTransformFeedback); + FIND_PROC(glGetProgramBinary); + FIND_PROC(glProgramBinary); + FIND_PROC(glProgramParameteri); + FIND_PROC(glInvalidateFramebuffer); + FIND_PROC(glInvalidateSubFramebuffer); + FIND_PROC(glTexStorage2D); + FIND_PROC(glTexStorage3D); + FIND_PROC(glGetInternalformativ); +#undef FIND_PROC + + if (!glReadBuffer || !glDrawRangeElements || !glTexImage3D || + !glTexSubImage3D || !glCopyTexSubImage3D || !glCompressedTexImage3D || + !glCompressedTexSubImage3D || !glGenQueries || !glDeleteQueries || + !glIsQuery || !glBeginQuery || !glEndQuery || !glGetQueryiv || + !glGetQueryObjectuiv || !glUnmapBuffer || !glGetBufferPointerv || + !glDrawBuffers || !glUniformMatrix2x3fv || !glUniformMatrix3x2fv || + !glUniformMatrix2x4fv || !glUniformMatrix4x2fv || !glUniformMatrix3x4fv || + !glUniformMatrix4x3fv || !glBlitFramebuffer || + !glRenderbufferStorageMultisample || !glFramebufferTextureLayer || + !glMapBufferRange || !glFlushMappedBufferRange || !glBindVertexArray || + !glDeleteVertexArrays || !glGenVertexArrays || !glIsVertexArray || + !glGetIntegeri_v || !glBeginTransformFeedback || + !glEndTransformFeedback || !glBindBufferRange || !glBindBufferBase || + !glTransformFeedbackVaryings || !glGetTransformFeedbackVarying || + !glVertexAttribIPointer || !glGetVertexAttribIiv || + !glGetVertexAttribIuiv || !glVertexAttribI4i || !glVertexAttribI4ui || + !glVertexAttribI4iv || !glVertexAttribI4uiv || !glGetUniformuiv || + !glGetFragDataLocation || !glUniform1ui || !glUniform2ui || + !glUniform3ui || !glUniform4ui || !glUniform1uiv || !glUniform2uiv || + !glUniform3uiv || !glUniform4uiv || !glClearBufferiv || + !glClearBufferuiv || !glClearBufferfv || !glClearBufferfi || + !glGetStringi || !glCopyBufferSubData || !glGetUniformIndices || + !glGetActiveUniformsiv || !glGetUniformBlockIndex || + !glGetActiveUniformBlockiv || !glGetActiveUniformBlockName || + !glUniformBlockBinding || !glDrawArraysInstanced || + !glDrawElementsInstanced || !glFenceSync || !glIsSync || !glDeleteSync || + !glClientWaitSync || !glWaitSync || !glGetInteger64v || !glGetSynciv || + !glGetInteger64i_v || !glGetBufferParameteri64v || !glGenSamplers || + !glDeleteSamplers || !glIsSampler || !glBindSampler || + !glSamplerParameteri || !glSamplerParameteriv || !glSamplerParameterf || + !glSamplerParameterfv || !glGetSamplerParameteriv || + !glGetSamplerParameterfv || !glVertexAttribDivisor || + !glBindTransformFeedback || !glDeleteTransformFeedbacks || + !glGenTransformFeedbacks || !glIsTransformFeedback || + !glPauseTransformFeedback || !glResumeTransformFeedback || + !glGetProgramBinary || !glProgramBinary || !glProgramParameteri || + !glInvalidateFramebuffer || !glInvalidateSubFramebuffer || + !glTexStorage2D || !glTexStorage3D || !glGetInternalformativ) { + return GL_FALSE; + } + + return GL_TRUE; +} + +/* Function pointer definitions */ GL_APICALL void (*GL_APIENTRY glReadBuffer)( + GLenum mode); +GL_APICALL void (*GL_APIENTRY glDrawRangeElements)(GLenum mode, GLuint start, + GLuint end, GLsizei count, + GLenum type, + const GLvoid* indices); +GL_APICALL void (*GL_APIENTRY glTexImage3D)(GLenum target, GLint level, + GLint internalformat, GLsizei width, + GLsizei height, GLsizei depth, + GLint border, GLenum format, + GLenum type, const GLvoid* pixels); +GL_APICALL void (*GL_APIENTRY glTexSubImage3D)(GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const GLvoid* pixels); +GL_APICALL void (*GL_APIENTRY glCopyTexSubImage3D)(GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLint x, + GLint y, GLsizei width, + GLsizei height); +GL_APICALL void (*GL_APIENTRY glCompressedTexImage3D)( + GLenum target, GLint level, GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, + const GLvoid* data); +GL_APICALL void (*GL_APIENTRY glCompressedTexSubImage3D)( + GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const GLvoid* data); +GL_APICALL void (*GL_APIENTRY glGenQueries)(GLsizei n, GLuint* ids); +GL_APICALL void (*GL_APIENTRY glDeleteQueries)(GLsizei n, const GLuint* ids); +GL_APICALL GLboolean (*GL_APIENTRY glIsQuery)(GLuint id); +GL_APICALL void (*GL_APIENTRY glBeginQuery)(GLenum target, GLuint id); +GL_APICALL void (*GL_APIENTRY glEndQuery)(GLenum target); +GL_APICALL void (*GL_APIENTRY glGetQueryiv)(GLenum target, GLenum pname, + GLint* params); +GL_APICALL void (*GL_APIENTRY glGetQueryObjectuiv)(GLuint id, GLenum pname, + GLuint* params); +GL_APICALL GLboolean (*GL_APIENTRY glUnmapBuffer)(GLenum target); +GL_APICALL void (*GL_APIENTRY glGetBufferPointerv)(GLenum target, GLenum pname, + GLvoid** params); +GL_APICALL void (*GL_APIENTRY glDrawBuffers)(GLsizei n, const GLenum* bufs); +GL_APICALL void (*GL_APIENTRY glUniformMatrix2x3fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix3x2fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix2x4fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix4x2fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix3x4fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix4x3fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glBlitFramebuffer)( + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, + GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GL_APICALL void (*GL_APIENTRY glRenderbufferStorageMultisample)( + GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height); +GL_APICALL void (*GL_APIENTRY glFramebufferTextureLayer)( + GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +GL_APICALL GLvoid* (*GL_APIENTRY glMapBufferRange)(GLenum target, + GLintptr offset, + GLsizeiptr length, + GLbitfield access); +GL_APICALL void (*GL_APIENTRY glFlushMappedBufferRange)(GLenum target, + GLintptr offset, + GLsizeiptr length); +GL_APICALL void (*GL_APIENTRY glBindVertexArray)(GLuint array); +GL_APICALL void (*GL_APIENTRY glDeleteVertexArrays)(GLsizei n, + const GLuint* arrays); +GL_APICALL void (*GL_APIENTRY glGenVertexArrays)(GLsizei n, GLuint* arrays); +GL_APICALL GLboolean (*GL_APIENTRY glIsVertexArray)(GLuint array); +GL_APICALL void (*GL_APIENTRY glGetIntegeri_v)(GLenum target, GLuint index, + GLint* data); +GL_APICALL void (*GL_APIENTRY glBeginTransformFeedback)(GLenum primitiveMode); +GL_APICALL void (*GL_APIENTRY glEndTransformFeedback)(void); +GL_APICALL void (*GL_APIENTRY glBindBufferRange)(GLenum target, GLuint index, + GLuint buffer, GLintptr offset, + GLsizeiptr size); +GL_APICALL void (*GL_APIENTRY glBindBufferBase)(GLenum target, GLuint index, + GLuint buffer); +GL_APICALL void (*GL_APIENTRY glTransformFeedbackVaryings)( + GLuint program, GLsizei count, const GLchar* const* varyings, + GLenum bufferMode); +GL_APICALL void (*GL_APIENTRY glGetTransformFeedbackVarying)( + GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, + GLsizei* size, GLenum* type, GLchar* name); +GL_APICALL void (*GL_APIENTRY glVertexAttribIPointer)(GLuint index, GLint size, + GLenum type, + GLsizei stride, + const GLvoid* pointer); +GL_APICALL void (*GL_APIENTRY glGetVertexAttribIiv)(GLuint index, GLenum pname, + GLint* params); +GL_APICALL void (*GL_APIENTRY glGetVertexAttribIuiv)(GLuint index, GLenum pname, + GLuint* params); +GL_APICALL void (*GL_APIENTRY glVertexAttribI4i)(GLuint index, GLint x, GLint y, + GLint z, GLint w); +GL_APICALL void (*GL_APIENTRY glVertexAttribI4ui)(GLuint index, GLuint x, + GLuint y, GLuint z, GLuint w); +GL_APICALL void (*GL_APIENTRY glVertexAttribI4iv)(GLuint index, const GLint* v); +GL_APICALL void (*GL_APIENTRY glVertexAttribI4uiv)(GLuint index, + const GLuint* v); +GL_APICALL void (*GL_APIENTRY glGetUniformuiv)(GLuint program, GLint location, + GLuint* params); +GL_APICALL GLint (*GL_APIENTRY glGetFragDataLocation)(GLuint program, + const GLchar* name); +GL_APICALL void (*GL_APIENTRY glUniform1ui)(GLint location, GLuint v0); +GL_APICALL void (*GL_APIENTRY glUniform2ui)(GLint location, GLuint v0, + GLuint v1); +GL_APICALL void (*GL_APIENTRY glUniform3ui)(GLint location, GLuint v0, + GLuint v1, GLuint v2); +GL_APICALL void (*GL_APIENTRY glUniform4ui)(GLint location, GLuint v0, + GLuint v1, GLuint v2, GLuint v3); +GL_APICALL void (*GL_APIENTRY glUniform1uiv)(GLint location, GLsizei count, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glUniform2uiv)(GLint location, GLsizei count, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glUniform3uiv)(GLint location, GLsizei count, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glUniform4uiv)(GLint location, GLsizei count, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glClearBufferiv)(GLenum buffer, GLint drawbuffer, + const GLint* value); +GL_APICALL void (*GL_APIENTRY glClearBufferuiv)(GLenum buffer, GLint drawbuffer, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glClearBufferfv)(GLenum buffer, GLint drawbuffer, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glClearBufferfi)(GLenum buffer, GLint drawbuffer, + GLfloat depth, GLint stencil); +GL_APICALL const GLubyte* (*GL_APIENTRY glGetStringi)(GLenum name, + GLuint index); +GL_APICALL void (*GL_APIENTRY glCopyBufferSubData)(GLenum readTarget, + GLenum writeTarget, + GLintptr readOffset, + GLintptr writeOffset, + GLsizeiptr size); +GL_APICALL void (*GL_APIENTRY glGetUniformIndices)( + GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, + GLuint* uniformIndices); +GL_APICALL void (*GL_APIENTRY glGetActiveUniformsiv)( + GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, + GLenum pname, GLint* params); +GL_APICALL GLuint (*GL_APIENTRY glGetUniformBlockIndex)( + GLuint program, const GLchar* uniformBlockName); +GL_APICALL void (*GL_APIENTRY glGetActiveUniformBlockiv)( + GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); +GL_APICALL void (*GL_APIENTRY glGetActiveUniformBlockName)( + GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, + GLchar* uniformBlockName); +GL_APICALL void (*GL_APIENTRY glUniformBlockBinding)( + GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +GL_APICALL void (*GL_APIENTRY glDrawArraysInstanced)(GLenum mode, GLint first, + GLsizei count, + GLsizei instanceCount); +GL_APICALL void (*GL_APIENTRY glDrawElementsInstanced)(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid* indices, + GLsizei instanceCount); +GL_APICALL GLsync (*GL_APIENTRY glFenceSync)(GLenum condition, + GLbitfield flags); +GL_APICALL GLboolean (*GL_APIENTRY glIsSync)(GLsync sync); +GL_APICALL void (*GL_APIENTRY glDeleteSync)(GLsync sync); +GL_APICALL GLenum (*GL_APIENTRY glClientWaitSync)(GLsync sync, GLbitfield flags, + GLuint64 timeout); +GL_APICALL void (*GL_APIENTRY glWaitSync)(GLsync sync, GLbitfield flags, + GLuint64 timeout); +GL_APICALL void (*GL_APIENTRY glGetInteger64v)(GLenum pname, GLint64* params); +GL_APICALL void (*GL_APIENTRY glGetSynciv)(GLsync sync, GLenum pname, + GLsizei bufSize, GLsizei* length, + GLint* values); +GL_APICALL void (*GL_APIENTRY glGetInteger64i_v)(GLenum target, GLuint index, + GLint64* data); +GL_APICALL void (*GL_APIENTRY glGetBufferParameteri64v)(GLenum target, + GLenum pname, + GLint64* params); +GL_APICALL void (*GL_APIENTRY glGenSamplers)(GLsizei count, GLuint* samplers); +GL_APICALL void (*GL_APIENTRY glDeleteSamplers)(GLsizei count, + const GLuint* samplers); +GL_APICALL GLboolean (*GL_APIENTRY glIsSampler)(GLuint sampler); +GL_APICALL void (*GL_APIENTRY glBindSampler)(GLuint unit, GLuint sampler); +GL_APICALL void (*GL_APIENTRY glSamplerParameteri)(GLuint sampler, GLenum pname, + GLint param); +GL_APICALL void (*GL_APIENTRY glSamplerParameteriv)(GLuint sampler, + GLenum pname, + const GLint* param); +GL_APICALL void (*GL_APIENTRY glSamplerParameterf)(GLuint sampler, GLenum pname, + GLfloat param); +GL_APICALL void (*GL_APIENTRY glSamplerParameterfv)(GLuint sampler, + GLenum pname, + const GLfloat* param); +GL_APICALL void (*GL_APIENTRY glGetSamplerParameteriv)(GLuint sampler, + GLenum pname, + GLint* params); +GL_APICALL void (*GL_APIENTRY glGetSamplerParameterfv)(GLuint sampler, + GLenum pname, + GLfloat* params); +GL_APICALL void (*GL_APIENTRY glVertexAttribDivisor)(GLuint index, + GLuint divisor); +GL_APICALL void (*GL_APIENTRY glBindTransformFeedback)(GLenum target, + GLuint id); +GL_APICALL void (*GL_APIENTRY glDeleteTransformFeedbacks)(GLsizei n, + const GLuint* ids); +GL_APICALL void (*GL_APIENTRY glGenTransformFeedbacks)(GLsizei n, GLuint* ids); +GL_APICALL GLboolean (*GL_APIENTRY glIsTransformFeedback)(GLuint id); +GL_APICALL void (*GL_APIENTRY glPauseTransformFeedback)(void); +GL_APICALL void (*GL_APIENTRY glResumeTransformFeedback)(void); +GL_APICALL void (*GL_APIENTRY glGetProgramBinary)(GLuint program, + GLsizei bufSize, + GLsizei* length, + GLenum* binaryFormat, + GLvoid* binary); +GL_APICALL void (*GL_APIENTRY glProgramBinary)(GLuint program, + GLenum binaryFormat, + const GLvoid* binary, + GLsizei length); +GL_APICALL void (*GL_APIENTRY glProgramParameteri)(GLuint program, GLenum pname, + GLint value); +GL_APICALL void (*GL_APIENTRY glInvalidateFramebuffer)( + GLenum target, GLsizei numAttachments, const GLenum* attachments); +GL_APICALL void (*GL_APIENTRY glInvalidateSubFramebuffer)( + GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, + GLint y, GLsizei width, GLsizei height); +GL_APICALL void (*GL_APIENTRY glTexStorage2D)(GLenum target, GLsizei levels, + GLenum internalformat, + GLsizei width, GLsizei height); +GL_APICALL void (*GL_APIENTRY glTexStorage3D)(GLenum target, GLsizei levels, + GLenum internalformat, + GLsizei width, GLsizei height, + GLsizei depth); +GL_APICALL void (*GL_APIENTRY glGetInternalformativ)(GLenum target, + GLenum internalformat, + GLenum pname, + GLsizei bufSize, + GLint* params); diff --git a/NativeApp/Android/ndk_helper/src/gl3stub.cpp b/NativeApp/Android/ndk_helper/src/gl3stub.cpp new file mode 100644 index 0000000..cb3575b --- /dev/null +++ b/NativeApp/Android/ndk_helper/src/gl3stub.cpp @@ -0,0 +1,421 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <EGL/egl.h> +#include "gl3stub.h" + +GLboolean gl3stubInit() { +#define FIND_PROC(s) s = (decltype(s))eglGetProcAddress(#s); + FIND_PROC(glReadBuffer); + FIND_PROC(glDrawRangeElements); + FIND_PROC(glTexImage3D); + FIND_PROC(glTexSubImage3D); + FIND_PROC(glCopyTexSubImage3D); + FIND_PROC(glCompressedTexImage3D); + FIND_PROC(glCompressedTexSubImage3D); + FIND_PROC(glGenQueries); + FIND_PROC(glDeleteQueries); + FIND_PROC(glIsQuery); + FIND_PROC(glBeginQuery); + FIND_PROC(glEndQuery); + FIND_PROC(glGetQueryiv); + FIND_PROC(glGetQueryObjectuiv); + FIND_PROC(glUnmapBuffer); + FIND_PROC(glGetBufferPointerv); + FIND_PROC(glDrawBuffers); + FIND_PROC(glUniformMatrix2x3fv); + FIND_PROC(glUniformMatrix3x2fv); + FIND_PROC(glUniformMatrix2x4fv); + FIND_PROC(glUniformMatrix4x2fv); + FIND_PROC(glUniformMatrix3x4fv); + FIND_PROC(glUniformMatrix4x3fv); + FIND_PROC(glBlitFramebuffer); + FIND_PROC(glRenderbufferStorageMultisample); + FIND_PROC(glFramebufferTextureLayer); + FIND_PROC(glMapBufferRange); + FIND_PROC(glFlushMappedBufferRange); + FIND_PROC(glBindVertexArray); + FIND_PROC(glDeleteVertexArrays); + FIND_PROC(glGenVertexArrays); + FIND_PROC(glIsVertexArray); + FIND_PROC(glGetIntegeri_v); + FIND_PROC(glBeginTransformFeedback); + FIND_PROC(glEndTransformFeedback); + FIND_PROC(glBindBufferRange); + FIND_PROC(glBindBufferBase); + FIND_PROC(glTransformFeedbackVaryings); + FIND_PROC(glGetTransformFeedbackVarying); + FIND_PROC(glVertexAttribIPointer); + FIND_PROC(glGetVertexAttribIiv); + FIND_PROC(glGetVertexAttribIuiv); + FIND_PROC(glVertexAttribI4i); + FIND_PROC(glVertexAttribI4ui); + FIND_PROC(glVertexAttribI4iv); + FIND_PROC(glVertexAttribI4uiv); + FIND_PROC(glGetUniformuiv); + FIND_PROC(glGetFragDataLocation); + FIND_PROC(glUniform1ui); + FIND_PROC(glUniform2ui); + FIND_PROC(glUniform3ui); + FIND_PROC(glUniform4ui); + FIND_PROC(glUniform1uiv); + FIND_PROC(glUniform2uiv); + FIND_PROC(glUniform3uiv); + FIND_PROC(glUniform4uiv); + FIND_PROC(glClearBufferiv); + FIND_PROC(glClearBufferuiv); + FIND_PROC(glClearBufferfv); + FIND_PROC(glClearBufferfi); + FIND_PROC(glGetStringi); + FIND_PROC(glCopyBufferSubData); + FIND_PROC(glGetUniformIndices); + FIND_PROC(glGetActiveUniformsiv); + FIND_PROC(glGetUniformBlockIndex); + FIND_PROC(glGetActiveUniformBlockiv); + FIND_PROC(glGetActiveUniformBlockName); + FIND_PROC(glUniformBlockBinding); + FIND_PROC(glDrawArraysInstanced); + FIND_PROC(glDrawElementsInstanced); + FIND_PROC(glFenceSync); + FIND_PROC(glIsSync); + FIND_PROC(glDeleteSync); + FIND_PROC(glClientWaitSync); + FIND_PROC(glWaitSync); + FIND_PROC(glGetInteger64v); + FIND_PROC(glGetSynciv); + FIND_PROC(glGetInteger64i_v); + FIND_PROC(glGetBufferParameteri64v); + FIND_PROC(glGenSamplers); + FIND_PROC(glDeleteSamplers); + FIND_PROC(glIsSampler); + FIND_PROC(glBindSampler); + FIND_PROC(glSamplerParameteri); + FIND_PROC(glSamplerParameteriv); + FIND_PROC(glSamplerParameterf); + FIND_PROC(glSamplerParameterfv); + FIND_PROC(glGetSamplerParameteriv); + FIND_PROC(glGetSamplerParameterfv); + FIND_PROC(glVertexAttribDivisor); + FIND_PROC(glBindTransformFeedback); + FIND_PROC(glDeleteTransformFeedbacks); + FIND_PROC(glGenTransformFeedbacks); + FIND_PROC(glIsTransformFeedback); + FIND_PROC(glPauseTransformFeedback); + FIND_PROC(glResumeTransformFeedback); + FIND_PROC(glGetProgramBinary); + FIND_PROC(glProgramBinary); + FIND_PROC(glProgramParameteri); + FIND_PROC(glInvalidateFramebuffer); + FIND_PROC(glInvalidateSubFramebuffer); + FIND_PROC(glTexStorage2D); + FIND_PROC(glTexStorage3D); + FIND_PROC(glGetInternalformativ); +#undef FIND_PROC + + if (!glReadBuffer || !glDrawRangeElements || !glTexImage3D || + !glTexSubImage3D || !glCopyTexSubImage3D || !glCompressedTexImage3D || + !glCompressedTexSubImage3D || !glGenQueries || !glDeleteQueries || + !glIsQuery || !glBeginQuery || !glEndQuery || !glGetQueryiv || + !glGetQueryObjectuiv || !glUnmapBuffer || !glGetBufferPointerv || + !glDrawBuffers || !glUniformMatrix2x3fv || !glUniformMatrix3x2fv || + !glUniformMatrix2x4fv || !glUniformMatrix4x2fv || !glUniformMatrix3x4fv || + !glUniformMatrix4x3fv || !glBlitFramebuffer || + !glRenderbufferStorageMultisample || !glFramebufferTextureLayer || + !glMapBufferRange || !glFlushMappedBufferRange || !glBindVertexArray || + !glDeleteVertexArrays || !glGenVertexArrays || !glIsVertexArray || + !glGetIntegeri_v || !glBeginTransformFeedback || + !glEndTransformFeedback || !glBindBufferRange || !glBindBufferBase || + !glTransformFeedbackVaryings || !glGetTransformFeedbackVarying || + !glVertexAttribIPointer || !glGetVertexAttribIiv || + !glGetVertexAttribIuiv || !glVertexAttribI4i || !glVertexAttribI4ui || + !glVertexAttribI4iv || !glVertexAttribI4uiv || !glGetUniformuiv || + !glGetFragDataLocation || !glUniform1ui || !glUniform2ui || + !glUniform3ui || !glUniform4ui || !glUniform1uiv || !glUniform2uiv || + !glUniform3uiv || !glUniform4uiv || !glClearBufferiv || + !glClearBufferuiv || !glClearBufferfv || !glClearBufferfi || + !glGetStringi || !glCopyBufferSubData || !glGetUniformIndices || + !glGetActiveUniformsiv || !glGetUniformBlockIndex || + !glGetActiveUniformBlockiv || !glGetActiveUniformBlockName || + !glUniformBlockBinding || !glDrawArraysInstanced || + !glDrawElementsInstanced || !glFenceSync || !glIsSync || !glDeleteSync || + !glClientWaitSync || !glWaitSync || !glGetInteger64v || !glGetSynciv || + !glGetInteger64i_v || !glGetBufferParameteri64v || !glGenSamplers || + !glDeleteSamplers || !glIsSampler || !glBindSampler || + !glSamplerParameteri || !glSamplerParameteriv || !glSamplerParameterf || + !glSamplerParameterfv || !glGetSamplerParameteriv || + !glGetSamplerParameterfv || !glVertexAttribDivisor || + !glBindTransformFeedback || !glDeleteTransformFeedbacks || + !glGenTransformFeedbacks || !glIsTransformFeedback || + !glPauseTransformFeedback || !glResumeTransformFeedback || + !glGetProgramBinary || !glProgramBinary || !glProgramParameteri || + !glInvalidateFramebuffer || !glInvalidateSubFramebuffer || + !glTexStorage2D || !glTexStorage3D || !glGetInternalformativ) { + return GL_FALSE; + } + + return GL_TRUE; +} + +/* Function pointer definitions */ GL_APICALL void (*GL_APIENTRY glReadBuffer)( + GLenum mode); +GL_APICALL void (*GL_APIENTRY glDrawRangeElements)(GLenum mode, GLuint start, + GLuint end, GLsizei count, + GLenum type, + const GLvoid* indices); +GL_APICALL void (*GL_APIENTRY glTexImage3D)(GLenum target, GLint level, + GLint internalformat, GLsizei width, + GLsizei height, GLsizei depth, + GLint border, GLenum format, + GLenum type, const GLvoid* pixels); +GL_APICALL void (*GL_APIENTRY glTexSubImage3D)(GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const GLvoid* pixels); +GL_APICALL void (*GL_APIENTRY glCopyTexSubImage3D)(GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLint x, + GLint y, GLsizei width, + GLsizei height); +GL_APICALL void (*GL_APIENTRY glCompressedTexImage3D)( + GLenum target, GLint level, GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, + const GLvoid* data); +GL_APICALL void (*GL_APIENTRY glCompressedTexSubImage3D)( + GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const GLvoid* data); +GL_APICALL void (*GL_APIENTRY glGenQueries)(GLsizei n, GLuint* ids); +GL_APICALL void (*GL_APIENTRY glDeleteQueries)(GLsizei n, const GLuint* ids); +GL_APICALL GLboolean (*GL_APIENTRY glIsQuery)(GLuint id); +GL_APICALL void (*GL_APIENTRY glBeginQuery)(GLenum target, GLuint id); +GL_APICALL void (*GL_APIENTRY glEndQuery)(GLenum target); +GL_APICALL void (*GL_APIENTRY glGetQueryiv)(GLenum target, GLenum pname, + GLint* params); +GL_APICALL void (*GL_APIENTRY glGetQueryObjectuiv)(GLuint id, GLenum pname, + GLuint* params); +GL_APICALL GLboolean (*GL_APIENTRY glUnmapBuffer)(GLenum target); +GL_APICALL void (*GL_APIENTRY glGetBufferPointerv)(GLenum target, GLenum pname, + GLvoid** params); +GL_APICALL void (*GL_APIENTRY glDrawBuffers)(GLsizei n, const GLenum* bufs); +GL_APICALL void (*GL_APIENTRY glUniformMatrix2x3fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix3x2fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix2x4fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix4x2fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix3x4fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glUniformMatrix4x3fv)(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glBlitFramebuffer)( + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, + GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GL_APICALL void (*GL_APIENTRY glRenderbufferStorageMultisample)( + GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height); +GL_APICALL void (*GL_APIENTRY glFramebufferTextureLayer)( + GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +GL_APICALL GLvoid* (*GL_APIENTRY glMapBufferRange)(GLenum target, + GLintptr offset, + GLsizeiptr length, + GLbitfield access); +GL_APICALL void (*GL_APIENTRY glFlushMappedBufferRange)(GLenum target, + GLintptr offset, + GLsizeiptr length); +GL_APICALL void (*GL_APIENTRY glBindVertexArray)(GLuint array); +GL_APICALL void (*GL_APIENTRY glDeleteVertexArrays)(GLsizei n, + const GLuint* arrays); +GL_APICALL void (*GL_APIENTRY glGenVertexArrays)(GLsizei n, GLuint* arrays); +GL_APICALL GLboolean (*GL_APIENTRY glIsVertexArray)(GLuint array); +GL_APICALL void (*GL_APIENTRY glGetIntegeri_v)(GLenum target, GLuint index, + GLint* data); +GL_APICALL void (*GL_APIENTRY glBeginTransformFeedback)(GLenum primitiveMode); +GL_APICALL void (*GL_APIENTRY glEndTransformFeedback)(void); +GL_APICALL void (*GL_APIENTRY glBindBufferRange)(GLenum target, GLuint index, + GLuint buffer, GLintptr offset, + GLsizeiptr size); +GL_APICALL void (*GL_APIENTRY glBindBufferBase)(GLenum target, GLuint index, + GLuint buffer); +GL_APICALL void (*GL_APIENTRY glTransformFeedbackVaryings)( + GLuint program, GLsizei count, const GLchar* const* varyings, + GLenum bufferMode); +GL_APICALL void (*GL_APIENTRY glGetTransformFeedbackVarying)( + GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, + GLsizei* size, GLenum* type, GLchar* name); +GL_APICALL void (*GL_APIENTRY glVertexAttribIPointer)(GLuint index, GLint size, + GLenum type, + GLsizei stride, + const GLvoid* pointer); +GL_APICALL void (*GL_APIENTRY glGetVertexAttribIiv)(GLuint index, GLenum pname, + GLint* params); +GL_APICALL void (*GL_APIENTRY glGetVertexAttribIuiv)(GLuint index, GLenum pname, + GLuint* params); +GL_APICALL void (*GL_APIENTRY glVertexAttribI4i)(GLuint index, GLint x, GLint y, + GLint z, GLint w); +GL_APICALL void (*GL_APIENTRY glVertexAttribI4ui)(GLuint index, GLuint x, + GLuint y, GLuint z, GLuint w); +GL_APICALL void (*GL_APIENTRY glVertexAttribI4iv)(GLuint index, const GLint* v); +GL_APICALL void (*GL_APIENTRY glVertexAttribI4uiv)(GLuint index, + const GLuint* v); +GL_APICALL void (*GL_APIENTRY glGetUniformuiv)(GLuint program, GLint location, + GLuint* params); +GL_APICALL GLint (*GL_APIENTRY glGetFragDataLocation)(GLuint program, + const GLchar* name); +GL_APICALL void (*GL_APIENTRY glUniform1ui)(GLint location, GLuint v0); +GL_APICALL void (*GL_APIENTRY glUniform2ui)(GLint location, GLuint v0, + GLuint v1); +GL_APICALL void (*GL_APIENTRY glUniform3ui)(GLint location, GLuint v0, + GLuint v1, GLuint v2); +GL_APICALL void (*GL_APIENTRY glUniform4ui)(GLint location, GLuint v0, + GLuint v1, GLuint v2, GLuint v3); +GL_APICALL void (*GL_APIENTRY glUniform1uiv)(GLint location, GLsizei count, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glUniform2uiv)(GLint location, GLsizei count, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glUniform3uiv)(GLint location, GLsizei count, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glUniform4uiv)(GLint location, GLsizei count, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glClearBufferiv)(GLenum buffer, GLint drawbuffer, + const GLint* value); +GL_APICALL void (*GL_APIENTRY glClearBufferuiv)(GLenum buffer, GLint drawbuffer, + const GLuint* value); +GL_APICALL void (*GL_APIENTRY glClearBufferfv)(GLenum buffer, GLint drawbuffer, + const GLfloat* value); +GL_APICALL void (*GL_APIENTRY glClearBufferfi)(GLenum buffer, GLint drawbuffer, + GLfloat depth, GLint stencil); +GL_APICALL const GLubyte* (*GL_APIENTRY glGetStringi)(GLenum name, + GLuint index); +GL_APICALL void (*GL_APIENTRY glCopyBufferSubData)(GLenum readTarget, + GLenum writeTarget, + GLintptr readOffset, + GLintptr writeOffset, + GLsizeiptr size); +GL_APICALL void (*GL_APIENTRY glGetUniformIndices)( + GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, + GLuint* uniformIndices); +GL_APICALL void (*GL_APIENTRY glGetActiveUniformsiv)( + GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, + GLenum pname, GLint* params); +GL_APICALL GLuint (*GL_APIENTRY glGetUniformBlockIndex)( + GLuint program, const GLchar* uniformBlockName); +GL_APICALL void (*GL_APIENTRY glGetActiveUniformBlockiv)( + GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); +GL_APICALL void (*GL_APIENTRY glGetActiveUniformBlockName)( + GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, + GLchar* uniformBlockName); +GL_APICALL void (*GL_APIENTRY glUniformBlockBinding)( + GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +GL_APICALL void (*GL_APIENTRY glDrawArraysInstanced)(GLenum mode, GLint first, + GLsizei count, + GLsizei instanceCount); +GL_APICALL void (*GL_APIENTRY glDrawElementsInstanced)(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid* indices, + GLsizei instanceCount); +GL_APICALL GLsync (*GL_APIENTRY glFenceSync)(GLenum condition, + GLbitfield flags); +GL_APICALL GLboolean (*GL_APIENTRY glIsSync)(GLsync sync); +GL_APICALL void (*GL_APIENTRY glDeleteSync)(GLsync sync); +GL_APICALL GLenum (*GL_APIENTRY glClientWaitSync)(GLsync sync, GLbitfield flags, + GLuint64 timeout); +GL_APICALL void (*GL_APIENTRY glWaitSync)(GLsync sync, GLbitfield flags, + GLuint64 timeout); +GL_APICALL void (*GL_APIENTRY glGetInteger64v)(GLenum pname, GLint64* params); +GL_APICALL void (*GL_APIENTRY glGetSynciv)(GLsync sync, GLenum pname, + GLsizei bufSize, GLsizei* length, + GLint* values); +GL_APICALL void (*GL_APIENTRY glGetInteger64i_v)(GLenum target, GLuint index, + GLint64* data); +GL_APICALL void (*GL_APIENTRY glGetBufferParameteri64v)(GLenum target, + GLenum pname, + GLint64* params); +GL_APICALL void (*GL_APIENTRY glGenSamplers)(GLsizei count, GLuint* samplers); +GL_APICALL void (*GL_APIENTRY glDeleteSamplers)(GLsizei count, + const GLuint* samplers); +GL_APICALL GLboolean (*GL_APIENTRY glIsSampler)(GLuint sampler); +GL_APICALL void (*GL_APIENTRY glBindSampler)(GLuint unit, GLuint sampler); +GL_APICALL void (*GL_APIENTRY glSamplerParameteri)(GLuint sampler, GLenum pname, + GLint param); +GL_APICALL void (*GL_APIENTRY glSamplerParameteriv)(GLuint sampler, + GLenum pname, + const GLint* param); +GL_APICALL void (*GL_APIENTRY glSamplerParameterf)(GLuint sampler, GLenum pname, + GLfloat param); +GL_APICALL void (*GL_APIENTRY glSamplerParameterfv)(GLuint sampler, + GLenum pname, + const GLfloat* param); +GL_APICALL void (*GL_APIENTRY glGetSamplerParameteriv)(GLuint sampler, + GLenum pname, + GLint* params); +GL_APICALL void (*GL_APIENTRY glGetSamplerParameterfv)(GLuint sampler, + GLenum pname, + GLfloat* params); +GL_APICALL void (*GL_APIENTRY glVertexAttribDivisor)(GLuint index, + GLuint divisor); +GL_APICALL void (*GL_APIENTRY glBindTransformFeedback)(GLenum target, + GLuint id); +GL_APICALL void (*GL_APIENTRY glDeleteTransformFeedbacks)(GLsizei n, + const GLuint* ids); +GL_APICALL void (*GL_APIENTRY glGenTransformFeedbacks)(GLsizei n, GLuint* ids); +GL_APICALL GLboolean (*GL_APIENTRY glIsTransformFeedback)(GLuint id); +GL_APICALL void (*GL_APIENTRY glPauseTransformFeedback)(void); +GL_APICALL void (*GL_APIENTRY glResumeTransformFeedback)(void); +GL_APICALL void (*GL_APIENTRY glGetProgramBinary)(GLuint program, + GLsizei bufSize, + GLsizei* length, + GLenum* binaryFormat, + GLvoid* binary); +GL_APICALL void (*GL_APIENTRY glProgramBinary)(GLuint program, + GLenum binaryFormat, + const GLvoid* binary, + GLsizei length); +GL_APICALL void (*GL_APIENTRY glProgramParameteri)(GLuint program, GLenum pname, + GLint value); +GL_APICALL void (*GL_APIENTRY glInvalidateFramebuffer)( + GLenum target, GLsizei numAttachments, const GLenum* attachments); +GL_APICALL void (*GL_APIENTRY glInvalidateSubFramebuffer)( + GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, + GLint y, GLsizei width, GLsizei height); +GL_APICALL void (*GL_APIENTRY glTexStorage2D)(GLenum target, GLsizei levels, + GLenum internalformat, + GLsizei width, GLsizei height); +GL_APICALL void (*GL_APIENTRY glTexStorage3D)(GLenum target, GLsizei levels, + GLenum internalformat, + GLsizei width, GLsizei height, + GLsizei depth); +GL_APICALL void (*GL_APIENTRY glGetInternalformativ)(GLenum target, + GLenum internalformat, + GLenum pname, + GLsizei bufSize, + GLint* params); diff --git a/NativeApp/Android/ndk_helper/src/interpolator.cpp b/NativeApp/Android/ndk_helper/src/interpolator.cpp new file mode 100644 index 0000000..f729914 --- /dev/null +++ b/NativeApp/Android/ndk_helper/src/interpolator.cpp @@ -0,0 +1,153 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "interpolator.h" +#include <math.h> +#include "interpolator.h" + +namespace ndk_helper { + +//------------------------------------------------- +// Ctor +//------------------------------------------------- +Interpolator::Interpolator() { list_params_.clear(); } + +//------------------------------------------------- +// Dtor +//------------------------------------------------- +Interpolator::~Interpolator() { list_params_.clear(); } + +void Interpolator::Clear() { list_params_.clear(); } + +Interpolator& Interpolator::Set(const float start, const float dest, + const INTERPOLATOR_TYPE type, + const double duration) { + // init the parameters for the interpolation process + start_time_ = PerfMonitor::GetCurrentTime(); + dest_time_ = start_time_ + duration; + type_ = type; + + start_value_ = start; + dest_value_ = dest; + return *this; +} + +Interpolator& Interpolator::Add(const float dest, const INTERPOLATOR_TYPE type, + const double duration) { + InterpolatorParams param; + param.dest_value_ = dest; + param.type_ = type; + param.duration_ = duration; + list_params_.push_back(param); + return *this; +} + +bool Interpolator::Update(const double current_time, float& p) { + bool bContinue; + if (current_time >= dest_time_) { + p = dest_value_; + if (list_params_.size()) { + InterpolatorParams& item = list_params_.front(); + Set(dest_value_, item.dest_value_, item.type_, item.duration_); + list_params_.pop_front(); + + bContinue = true; + } else { + bContinue = false; + } + } else { + float t = (float)(current_time - start_time_); + float d = (float)(dest_time_ - start_time_); + float b = start_value_; + float c = dest_value_ - start_value_; + p = GetFormula(type_, t, b, d, c); + + bContinue = true; + } + return bContinue; +} + +float Interpolator::GetFormula(const INTERPOLATOR_TYPE type, const float t, + const float b, const float d, const float c) { + float t1; + switch (type) { + case INTERPOLATOR_TYPE_LINEAR: + // simple linear interpolation - no easing + return (c * t / d + b); + + case INTERPOLATOR_TYPE_EASEINQUAD: + // quadratic (t^2) easing in - accelerating from zero velocity + t1 = t / d; + return (c * t1 * t1 + b); + + case INTERPOLATOR_TYPE_EASEOUTQUAD: + // quadratic (t^2) easing out - decelerating to zero velocity + t1 = t / d; + return (-c * t1 * (t1 - 2) + b); + + case INTERPOLATOR_TYPE_EASEINOUTQUAD: + // quadratic easing in/out - acceleration until halfway, then deceleration + t1 = t / d / 2; + if (t1 < 1) + return (c / 2 * t1 * t1 + b); + else { + t1 = t1 - 1; + return (-c / 2 * (t1 * (t1 - 2) - 1) + b); + } + case INTERPOLATOR_TYPE_EASEINCUBIC: + // cubic easing in - accelerating from zero velocity + t1 = t / d; + return (c * t1 * t1 * t1 + b); + + case INTERPOLATOR_TYPE_EASEOUTCUBIC: + // cubic easing in - accelerating from zero velocity + t1 = t / d - 1; + return (c * (t1 * t1 * t1 + 1) + b); + + case INTERPOLATOR_TYPE_EASEINOUTCUBIC: + // cubic easing in - accelerating from zero velocity + t1 = t / d / 2; + + if (t1 < 1) + return (c / 2 * t1 * t1 * t1 + b); + else { + t1 -= 2; + return (c / 2 * (t1 * t1 * t1 + 2) + b); + } + case INTERPOLATOR_TYPE_EASEINQUART: + // quartic easing in - accelerating from zero velocity + t1 = t / d; + return (c * t1 * t1 * t1 * t1 + b); + + case INTERPOLATOR_TYPE_EASEINEXPO: + // exponential (2^t) easing in - accelerating from zero velocity + if (t == 0) + return b; + else + return (c * powf(2, (10 * (t / d - 1))) + b); + + case INTERPOLATOR_TYPE_EASEOUTEXPO: + // exponential (2^t) easing out - decelerating to zero velocity + if (t == d) + return (b + c); + else + return (c * (-powf(2, -10 * t / d) + 1) + b); + default: + return 0; + } +} + +} // namespace ndkHelper diff --git a/NativeApp/Android/ndk_helper/src/java/com/android/helper/NDKHelper.java b/NativeApp/Android/ndk_helper/src/java/com/android/helper/NDKHelper.java new file mode 100644 index 0000000..8c9055b --- /dev/null +++ b/NativeApp/Android/ndk_helper/src/java/com/android/helper/NDKHelper.java @@ -0,0 +1,360 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Must be changed with #define HELPER_CLASS_NAME "com/android/helper/NDKHelper" in AndroidMain.cpp +package com.android.helper; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.nio.ByteBuffer; + +import javax.microedition.khronos.opengles.GL10; + +import android.R.bool; +import android.opengl.GLES30; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.app.NativeActivity; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.graphics.Bitmap; +import android.graphics.Bitmap.CompressFormat; +import android.graphics.BitmapFactory; +import android.graphics.Matrix; +import android.media.AudioManager; +import android.media.AudioTrack; +import android.opengl.GLUtils; +import android.os.Build; +import android.util.Log; +import android.view.View; +import android.view.View.MeasureSpec; + +@TargetApi(Build.VERSION_CODES.GINGERBREAD) +public class NDKHelper { + + public NDKHelper(NativeActivity act) { + activity = act; + } + + public void loadLibrary(String soname) { + if (soname.isEmpty() == false) { + System.loadLibrary(soname); + loadedSO = true; + } + } + + public static Boolean checkSOLoaded() { + if (loadedSO == false) { + Log.e("NDKHelper", + "--------------------------------------------\n" + + ".so has not been loaded. To use JUI helper, please initialize with \n" + + "NDKHelper::Init( ANativeActivity* activity, const char* helper_class_name, const char* native_soname);\n" + + "--------------------------------------------\n"); + return false; + } else + return true; + } + + private static boolean loadedSO = false; + NativeActivity activity; + + + + // + // Load Bitmap + // Java helper is useful decoding PNG, TIFF etc rather than linking libPng + // etc separately + // + private int nextPOT(int i) { + int pot = 1; + while (pot < i) + pot <<= 1; + return pot; + } + + private Bitmap scaleBitmap(Bitmap bitmapToScale, float newWidth, + float newHeight) { + if (bitmapToScale == null) + return null; + // get the original width and height + int width = bitmapToScale.getWidth(); + int height = bitmapToScale.getHeight(); + // create a matrix for the manipulation + Matrix matrix = new Matrix(); + + // resize the bit map + matrix.postScale(newWidth / width, newHeight / height); + + // recreate the new Bitmap and set it back + return Bitmap.createBitmap(bitmapToScale, 0, 0, + bitmapToScale.getWidth(), bitmapToScale.getHeight(), matrix, + true); + } + + public class TextureInformation { + boolean ret; + boolean alphaChannel; + int originalWidth; + int originalHeight; + Object image; + } + + public Object loadTexture(String path) { + Bitmap bitmap = null; + TextureInformation info = new TextureInformation(); + try { + String str = path; + if (!path.startsWith("/")) { + str = "/" + path; + } + + File file = new File(activity.getExternalFilesDir(null), str); + if (file.canRead()) { + bitmap = BitmapFactory.decodeStream(new FileInputStream(file)); + } else { + bitmap = BitmapFactory.decodeStream(activity.getResources() + .getAssets().open(path)); + } + // Matrix matrix = new Matrix(); + // // resize the bit map + // matrix.postScale(-1F, 1F); + // + // // recreate the new Bitmap and set it back + // bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), + // bitmap.getHeight(), matrix, true); + + } catch (Exception e) { + Log.w("NDKHelper", "Coundn't load a file:" + path); + info.ret = false; + return info; + } + + if (bitmap != null) { + GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); + } + info.ret = true; + info.alphaChannel = bitmap.hasAlpha(); + info.originalWidth = getBitmapWidth(bitmap); + info.originalHeight = getBitmapHeight(bitmap); + + return info; + } + + public Object loadCubemapTexture(String path, int face, int miplevel, boolean sRGB) { + Bitmap bitmap = null; + TextureInformation info = new TextureInformation(); + try { + String str = path; + if (!path.startsWith("/")) { + str = "/" + path; + } + + File file = new File(activity.getExternalFilesDir(null), str); + if (file.canRead()) { + bitmap = BitmapFactory.decodeStream(new FileInputStream(file)); + } else { + bitmap = BitmapFactory.decodeStream(activity.getResources() + .getAssets().open(path)); + } + } catch (Exception e) { + Log.w("NDKHelper", "Coundn't load a file:" + path); + info.ret = false; + return info; + } + + if (bitmap != null) { + if (sRGB) + { +// GLUtils.texImage2D(face, miplevel, bitmap, 0); +// GLUtils.texImage2D(face, miplevel, +// GLUtils.getInternalFormat(bitmap), bitmap, 0); +// int i = GLUtils.getInternalFormat(bitmap); +// if( i == GL10.GL_RGBA) +// { +// GLUtils.texImage2D(face, miplevel, +// GLES30.GL_SRGB, bitmap, 0); +// } + //Leave them for now + GLUtils.texImage2D(face, miplevel, bitmap, 0); + } + else + GLUtils.texImage2D(face, miplevel, bitmap, 0); + } + info.ret = true; + info.alphaChannel = bitmap.hasAlpha(); + info.originalWidth = getBitmapWidth(bitmap); + info.originalHeight = getBitmapHeight(bitmap); + + return info; + + } + + public Object loadImage(String path) { + Bitmap bitmap = null; + TextureInformation info = new TextureInformation(); + try { + String str = path; + if (!path.startsWith("/")) { + str = "/" + path; + } + + File file = new File(activity.getExternalFilesDir(null), str); + if (file.canRead()) { + bitmap = BitmapFactory.decodeStream(new FileInputStream(file)); + } else { + bitmap = BitmapFactory.decodeStream(activity.getResources() + .getAssets().open(path)); + } + } catch (Exception e) { + Log.w("NDKHelper", "Coundn't load a file:" + path); + info.ret = false; + return info; + } + + if (bitmap != null) { + GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); + } + info.ret = true; + info.alphaChannel = bitmap.hasAlpha(); + info.originalWidth = getBitmapWidth(bitmap); + info.originalHeight = getBitmapHeight(bitmap); + + int iBytes = bitmap.getWidth() * bitmap.getHeight() * 4; + ByteBuffer buffer = ByteBuffer.allocateDirect(iBytes); + + bitmap.copyPixelsToBuffer(buffer); + info.image = buffer; + return info; + } + + public Bitmap openBitmap(String path, boolean iScalePOT) { + Bitmap bitmap = null; + try { + bitmap = BitmapFactory.decodeStream(activity.getResources() + .getAssets().open(path)); + if (iScalePOT) { + int originalWidth = getBitmapWidth(bitmap); + int originalHeight = getBitmapHeight(bitmap); + int width = nextPOT(originalWidth); + int height = nextPOT(originalHeight); + if (originalWidth != width || originalHeight != height) { + // Scale it + bitmap = scaleBitmap(bitmap, width, height); + } + } + + } catch (Exception e) { + Log.w("NDKHelper", "Coundn't load a file:" + path); + } + + return bitmap; + } + + public int getBitmapWidth(Bitmap bmp) { + return bmp.getWidth(); + } + + public int getBitmapHeight(Bitmap bmp) { + return bmp.getHeight(); + } + + public void getBitmapPixels(Bitmap bmp, int[] pixels) { + int w = bmp.getWidth(); + int h = bmp.getHeight(); + bmp.getPixels(pixels, 0, w, 0, 0, w, h); + } + + public void closeBitmap(Bitmap bmp) { + bmp.recycle(); + } + + public String getNativeLibraryDirectory(Context appContext) { + ApplicationInfo ai = activity.getApplicationInfo(); + + Log.w("NDKHelper", "ai.nativeLibraryDir:" + ai.nativeLibraryDir); + + if ((ai.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 + || (ai.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { + return ai.nativeLibraryDir; + } + return "/system/lib/"; + } + + public String getApplicationName() { + final PackageManager pm = activity.getPackageManager(); + ApplicationInfo ai; + try { + ai = pm.getApplicationInfo(activity.getPackageName(), 0); + } catch (final NameNotFoundException e) { + ai = null; + } + String applicationName = (String) (ai != null ? pm + .getApplicationLabel(ai) : "(unknown)"); + return applicationName; + } + + public String getStringResource(String resourceName) + { + int id = activity.getResources().getIdentifier(resourceName, "string", activity.getPackageName()); + String value = id == 0 ? "" : (String)activity.getResources().getText(id); + return value; + } + + // + // Audio related helpers + // + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) + public int getNativeAudioBufferSize() { + int SDK_INT = android.os.Build.VERSION.SDK_INT; + if (SDK_INT >= 17) { + AudioManager am = (AudioManager) activity + .getSystemService(Context.AUDIO_SERVICE); + String framesPerBuffer = am + .getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER); + return Integer.parseInt(framesPerBuffer); + } else { + return 0; + } + } + + public int getNativeAudioSampleRate() { + return AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM); + } + + /* + * Helper to execute function in UIThread + */ + public void runOnUIThread(final long p) { + if (checkSOLoaded()) { + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + RunOnUiThreadHandler(p); + } + }); + } + return; + } + + /* + * Native code helper for RunOnUiThread + */ + native public void RunOnUiThreadHandler(long pointer); +}
\ No newline at end of file diff --git a/NativeApp/Android/ndk_helper/src/perfMonitor.cpp b/NativeApp/Android/ndk_helper/src/perfMonitor.cpp new file mode 100644 index 0000000..b38cffd --- /dev/null +++ b/NativeApp/Android/ndk_helper/src/perfMonitor.cpp @@ -0,0 +1,61 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "perfMonitor.h" + +namespace ndk_helper { + +PerfMonitor::PerfMonitor() + : current_FPS_(0), + tv_last_sec_(0), + last_tick_(0.f), + tickindex_(0), + ticksum_(0) { + for (int32_t i = 0; i < kNumSamples; ++i) ticklist_[i] = 0; +} + +PerfMonitor::~PerfMonitor() {} + +double PerfMonitor::UpdateTick(double currentTick) { + ticksum_ -= ticklist_[tickindex_]; + ticksum_ += currentTick; + ticklist_[tickindex_] = currentTick; + tickindex_ = (tickindex_ + 1) % kNumSamples; + + return ((double)ticksum_ / kNumSamples); +} + +bool PerfMonitor::Update(float &fFPS) { + struct timeval Time; + gettimeofday(&Time, NULL); + + double time = Time.tv_sec + Time.tv_usec * 1.0 / 1000000.0; + double tick = time - last_tick_; + double d = UpdateTick(tick); + last_tick_ = time; + + if (Time.tv_sec - tv_last_sec_ >= 1) { + current_FPS_ = 1.f / d; + tv_last_sec_ = Time.tv_sec; + fFPS = current_FPS_; + return true; + } else { + fFPS = current_FPS_; + return false; + } +} + +} // namespace ndkHelper diff --git a/NativeApp/Android/ndk_helper/src/sensorManager.cpp b/NativeApp/Android/ndk_helper/src/sensorManager.cpp new file mode 100644 index 0000000..90487d0 --- /dev/null +++ b/NativeApp/Android/ndk_helper/src/sensorManager.cpp @@ -0,0 +1,106 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <math.h> +#include "sensorManager.h" + +//-------------------------------------------------------------------------------- +// sensorManager.cpp +//-------------------------------------------------------------------------------- +namespace ndk_helper { + +//-------------------------------------------------------------------------------- +// includes +//-------------------------------------------------------------------------------- + +//------------------------------------------------------------------------- +// Sensor handlers +//------------------------------------------------------------------------- +SensorManager::SensorManager() + : sensorManager_(nullptr), + accelerometerSensor_(nullptr), + sensorEventQueue_(nullptr) {} + +SensorManager::~SensorManager() {} + +void SensorManager::Init(android_app *app) { + sensorManager_ = AcquireASensorManagerInstance(app); + accelerometerSensor_ = ASensorManager_getDefaultSensor( + sensorManager_, ASENSOR_TYPE_ACCELEROMETER); + sensorEventQueue_ = ASensorManager_createEventQueue( + sensorManager_, app->looper, LOOPER_ID_USER, NULL, NULL); +} + +void SensorManager::Resume() { + // When the app gains focus, start monitoring the accelerometer. + if (accelerometerSensor_ != NULL) { + ASensorEventQueue_enableSensor(sensorEventQueue_, accelerometerSensor_); + // We'd like to get 60 events per second (in us). + ASensorEventQueue_setEventRate(sensorEventQueue_, accelerometerSensor_, + (1000L / 60) * 1000); + } +} + +void SensorManager::Suspend() { + // When the app loses focus, stop monitoring the accelerometer. + // This is to avoid consuming battery while not being used. + if (accelerometerSensor_ != NULL) { + ASensorEventQueue_disableSensor(sensorEventQueue_, accelerometerSensor_); + } +} + +#include <dlfcn.h> +ASensorManager* AcquireASensorManagerInstance(android_app* app) { + + if(!app) + return nullptr; + + typedef ASensorManager *(*PF_GETINSTANCEFORPACKAGE)(const char *name); + void* androidHandle = dlopen("libandroid.so", RTLD_NOW); + PF_GETINSTANCEFORPACKAGE getInstanceForPackageFunc = (PF_GETINSTANCEFORPACKAGE) + dlsym(androidHandle, "ASensorManager_getInstanceForPackage"); + if (getInstanceForPackageFunc) { + JNIEnv* env = nullptr; + app->activity->vm->AttachCurrentThread(&env, NULL); + + jclass android_content_Context = env->GetObjectClass(app->activity->clazz); + jmethodID midGetPackageName = env->GetMethodID(android_content_Context, + "getPackageName", + "()Ljava/lang/String;"); + jstring packageName= (jstring)env->CallObjectMethod(app->activity->clazz, + midGetPackageName); + + const char *nativePackageName = env->GetStringUTFChars(packageName, 0); + ASensorManager* mgr = getInstanceForPackageFunc(nativePackageName); + env->ReleaseStringUTFChars(packageName, nativePackageName); + app->activity->vm->DetachCurrentThread(); + if (mgr) { + dlclose(androidHandle); + return mgr; + } + } + + typedef ASensorManager *(*PF_GETINSTANCE)(); + PF_GETINSTANCE getInstanceFunc = (PF_GETINSTANCE) + dlsym(androidHandle, "ASensorManager_getInstance"); + // by all means at this point, ASensorManager_getInstance should be available + assert(getInstanceFunc); + dlclose(androidHandle); + + return getInstanceFunc(); +} + +} // namespace ndkHelper diff --git a/NativeApp/Android/ndk_helper/src/shader.cpp b/NativeApp/Android/ndk_helper/src/shader.cpp new file mode 100644 index 0000000..af7a155 --- /dev/null +++ b/NativeApp/Android/ndk_helper/src/shader.cpp @@ -0,0 +1,166 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <cstdlib> +#include <EGL/egl.h> +#include <GLES2/gl2.h> + +#include "shader.h" +#include "JNIHelper.h" + +namespace ndk_helper { + +#define DEBUG (1) + +bool shader::CompileShader( + GLuint *shader, const GLenum type, const char *str_file_name, + const std::map<std::string, std::string> &map_parameters) { + std::vector<uint8_t> data; + if (!JNIHelper::GetInstance()->ReadFile(str_file_name, &data)) { + LOGI("Can not open a file:%s", str_file_name); + return false; + } + + const char REPLACEMENT_TAG = '*'; + // Fill-in parameters + std::string str(data.begin(), data.end()); + std::string str_replacement_map(data.size(), ' '); + + std::map<std::string, std::string>::const_iterator it = + map_parameters.begin(); + std::map<std::string, std::string>::const_iterator itEnd = + map_parameters.end(); + while (it != itEnd) { + size_t pos = 0; + while ((pos = str.find(it->first, pos)) != std::string::npos) { + // Check if the sub string is already touched + + size_t replaced_pos = str_replacement_map.find(REPLACEMENT_TAG, pos); + if (replaced_pos == std::string::npos || replaced_pos > pos) { + str.replace(pos, it->first.length(), it->second); + str_replacement_map.replace(pos, it->first.length(), it->first.length(), + REPLACEMENT_TAG); + pos += it->second.length(); + } else { + // The replacement target has been touched by other tag, skipping them + pos += it->second.length(); + } + } + it++; + } + + LOGI("Patched Shdader:\n%s", str.c_str()); + + std::vector<uint8_t> v(str.begin(), str.end()); + str.clear(); + return shader::CompileShader(shader, type, v); +} + +bool shader::CompileShader(GLuint *shader, const GLenum type, + const GLchar *source, const int32_t iSize) { + if (source == NULL || iSize <= 0) return false; + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, &iSize); // Not specifying 3rd parameter + // (size) could be troublesome.. + + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + LOGI("Shader compile log:\n%s", log); + free(log); + } +#endif + + GLint status; + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return false; + } + + return true; +} + +bool shader::CompileShader(GLuint *shader, const GLenum type, + std::vector<uint8_t> &data) { + if (!data.size()) return false; + + const GLchar *source = (GLchar *)&data[0]; + int32_t iSize = data.size(); + return shader::CompileShader(shader, type, source, iSize); +} + +bool shader::CompileShader(GLuint *shader, const GLenum type, + const char *strFileName) { + std::vector<uint8_t> data; + bool b = JNIHelper::GetInstance()->ReadFile(strFileName, &data); + if (!b) { + LOGI("Can not open a file:%s", strFileName); + return false; + } + + return shader::CompileShader(shader, type, data); +} + +bool shader::LinkProgram(const GLuint prog) { + GLint status; + + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + LOGI("Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + LOGI("Program link failed\n"); + return false; + } + + return true; +} + +bool shader::ValidateProgram(const GLuint prog) { + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + LOGI("Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) return false; + + return true; +} + +} // namespace ndkHelper diff --git a/NativeApp/Android/ndk_helper/src/tapCamera.cpp b/NativeApp/Android/ndk_helper/src/tapCamera.cpp new file mode 100644 index 0000000..e753ab1 --- /dev/null +++ b/NativeApp/Android/ndk_helper/src/tapCamera.cpp @@ -0,0 +1,324 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//---------------------------------------------------------- +// tapCamera.cpp +// Camera control with tap +// +//---------------------------------------------------------- +#include <fstream> +#include "tapCamera.h" + +namespace ndk_helper { + +const float TRANSFORM_FACTOR = 15.f; +const float TRANSFORM_FACTORZ = 10.f; + +const float MOMENTUM_FACTOR_DECREASE = 0.85f; +const float MOMENTUM_FACTOR_DECREASE_SHIFT = 0.9f; +const float MOMENTUM_FACTOR = 0.8f; +const float MOMENTUM_FACTOR_THRESHOLD = 0.001f; + +//---------------------------------------------------------- +// Ctor +//---------------------------------------------------------- +TapCamera::TapCamera() + : ball_radius_(0.75f), + dragging_(false), + pinching_(false), + pinch_start_distance_SQ_(0.f), + camera_rotation_(0.f), + camera_rotation_start_(0.f), + camera_rotation_now_(0.f), + momentum_(false), + momemtum_steps_(0.f), + flip_z_(0.f) { + // Init offset + InitParameters(); + + vec_flip_ = Vec2(1.f, -1.f); + flip_z_ = -1.f; + vec_pinch_transform_factor_ = Vec3(1.f, 1.f, 1.f); + + vec_ball_center_ = Vec2(0, 0); + vec_ball_now_ = Vec2(0, 0); + vec_ball_down_ = Vec2(0, 0); + + vec_pinch_start_ = Vec2(0, 0); + vec_pinch_start_center_ = Vec2(0, 0); + + vec_flip_ = Vec2(0, 0); +} + +void TapCamera::InitParameters() { + // Init parameters + vec_offset_ = Vec3(); + vec_offset_now_ = Vec3(); + + quat_ball_rot_ = Quaternion(); + quat_ball_now_ = Quaternion(); + quat_ball_now_.ToMatrix(mat_rotation_); + camera_rotation_ = 0.f; + + vec_drag_delta_ = Vec2(); + vec_offset_delta_ = Vec3(); + + momentum_ = false; +} + +//---------------------------------------------------------- +// Dtor +//---------------------------------------------------------- +TapCamera::~TapCamera() {} + +void TapCamera::Update() { + if (momentum_) { + float momenttum_steps = momemtum_steps_; + + // Momentum rotation + Vec2 v = vec_drag_delta_; + BeginDrag(Vec2()); // NOTE:This call reset _VDragDelta + Drag(v * vec_flip_); + + // Momentum shift + vec_offset_ += vec_offset_delta_; + + BallUpdate(); + EndDrag(); + + // Decrease deltas + vec_drag_delta_ = v * MOMENTUM_FACTOR_DECREASE; + vec_offset_delta_ = vec_offset_delta_ * MOMENTUM_FACTOR_DECREASE_SHIFT; + + // Count steps + momemtum_steps_ = momenttum_steps * MOMENTUM_FACTOR_DECREASE; + if (momemtum_steps_ < MOMENTUM_FACTOR_THRESHOLD) { + momentum_ = false; + } + } else { + vec_drag_delta_ *= MOMENTUM_FACTOR; + vec_offset_delta_ = vec_offset_delta_ * MOMENTUM_FACTOR; + BallUpdate(); + } + + Vec3 vec = vec_offset_ + vec_offset_now_; + Vec3 vec_tmp(TRANSFORM_FACTOR, -TRANSFORM_FACTOR, TRANSFORM_FACTORZ); + + vec *= vec_tmp * vec_pinch_transform_factor_; + + mat_transform_ = Mat4::Translation(vec); +} + +void TapCamera::Update(const double time) { + if (momentum_) { + const float MOMENTAM_UNIT = 0.0166f; + // Activate every 16.6msec + if (time - time_stamp_ >= MOMENTAM_UNIT) { + float momenttum_steps = momemtum_steps_; + + // Momentum rotation + Vec2 v = vec_drag_delta_; + BeginDrag(Vec2()); // NOTE:This call reset _VDragDelta + Drag(v * vec_flip_); + + // Momentum shift + vec_offset_ += vec_offset_delta_; + + BallUpdate(); + EndDrag(); + + // Decrease deltas + vec_drag_delta_ = v * MOMENTUM_FACTOR_DECREASE; + vec_offset_delta_ = vec_offset_delta_ * MOMENTUM_FACTOR_DECREASE_SHIFT; + + // Count steps + momemtum_steps_ = momenttum_steps * MOMENTUM_FACTOR_DECREASE; + if (momemtum_steps_ < MOMENTUM_FACTOR_THRESHOLD) { + momentum_ = false; + } + time_stamp_ = time; + } + } else { + vec_drag_delta_ *= MOMENTUM_FACTOR; + vec_offset_delta_ = vec_offset_delta_ * MOMENTUM_FACTOR; + BallUpdate(); + time_stamp_ = time; + } + + Vec3 vec = vec_offset_ + vec_offset_now_; + Vec3 vec_tmp(TRANSFORM_FACTOR, -TRANSFORM_FACTOR, TRANSFORM_FACTORZ); + + vec *= vec_tmp * vec_pinch_transform_factor_; + + mat_transform_ = Mat4::Translation(vec); +} +Mat4& TapCamera::GetRotationMatrix() { return mat_rotation_; } + +Mat4& TapCamera::GetTransformMatrix() { return mat_transform_; } + +void TapCamera::Reset(const bool bAnimate) { + InitParameters(); + Update(); +} + +//---------------------------------------------------------- +// Drag control +//---------------------------------------------------------- +void TapCamera::BeginDrag(const Vec2& v) { + if (dragging_) EndDrag(); + + if (pinching_) EndPinch(); + + Vec2 vec = v * vec_flip_; + vec_ball_now_ = vec; + vec_ball_down_ = vec_ball_now_; + + dragging_ = true; + momentum_ = false; + vec_last_input_ = vec; + vec_drag_delta_ = Vec2(); +} + +void TapCamera::EndDrag() { + quat_ball_down_ = quat_ball_now_; + quat_ball_rot_ = Quaternion(); + + dragging_ = false; + momentum_ = true; + momemtum_steps_ = 1.0f; +} + +void TapCamera::Drag(const Vec2& v) { + if (!dragging_) return; + + Vec2 vec = v * vec_flip_; + vec_ball_now_ = vec; + + vec_drag_delta_ = vec_drag_delta_ * MOMENTUM_FACTOR + (vec - vec_last_input_); + vec_last_input_ = vec; +} + +//---------------------------------------------------------- +// Pinch controll +//---------------------------------------------------------- +void TapCamera::BeginPinch(const Vec2& v1, const Vec2& v2) { + if (dragging_) EndDrag(); + + if (pinching_) EndPinch(); + + BeginDrag(Vec2()); + + vec_pinch_start_center_ = (v1 + v2) / 2.f; + + Vec2 vec = v1 - v2; + float x_diff; + float y_diff; + vec.Value(x_diff, y_diff); + + pinch_start_distance_SQ_ = x_diff * x_diff + y_diff * y_diff; + camera_rotation_start_ = atan2f(y_diff, x_diff); + camera_rotation_now_ = 0; + + pinching_ = true; + momentum_ = false; + + // Init momentum factors + vec_offset_delta_ = Vec3(); +} + +void TapCamera::EndPinch() { + pinching_ = false; + momentum_ = true; + momemtum_steps_ = 1.f; + vec_offset_ += vec_offset_now_; + camera_rotation_ += camera_rotation_now_; + vec_offset_now_ = Vec3(); + + camera_rotation_now_ = 0; + + EndDrag(); +} + +void TapCamera::Pinch(const Vec2& v1, const Vec2& v2) { + if (!pinching_) return; + + // Update momentum factor + vec_offset_last_ = vec_offset_now_; + + float x_diff, y_diff; + Vec2 vec = v1 - v2; + vec.Value(x_diff, y_diff); + + float fDistanceSQ = x_diff * x_diff + y_diff * y_diff; + + float f = pinch_start_distance_SQ_ / fDistanceSQ; + if (f < 1.f) + f = -1.f / f + 1.0f; + else + f = f - 1.f; + if (std::isnan(f)) f = 0.f; + + vec = (v1 + v2) / 2.f - vec_pinch_start_center_; + vec_offset_now_ = Vec3(vec, flip_z_ * f); + + // Update momentum factor + vec_offset_delta_ = vec_offset_delta_ * MOMENTUM_FACTOR + + (vec_offset_now_ - vec_offset_last_); + + // + // Update ration quaternion + float fRotation = atan2f(y_diff, x_diff); + camera_rotation_now_ = fRotation - camera_rotation_start_; + + // Trackball rotation + quat_ball_rot_ = Quaternion(0.f, 0.f, sinf(-camera_rotation_now_ * 0.5f), + cosf(-camera_rotation_now_ * 0.5f)); +} + +//---------------------------------------------------------- +// Trackball controll +//---------------------------------------------------------- +void TapCamera::BallUpdate() { + if (dragging_) { + Vec3 vec_from = PointOnSphere(vec_ball_down_); + Vec3 vec_to = PointOnSphere(vec_ball_now_); + + Vec3 vec = vec_from.Cross(vec_to); + float w = vec_from.Dot(vec_to); + + Quaternion qDrag = Quaternion(vec, w); + qDrag = qDrag * quat_ball_down_; + quat_ball_now_ = quat_ball_rot_ * qDrag; + } + quat_ball_now_.ToMatrix(mat_rotation_); +} + +Vec3 TapCamera::PointOnSphere(Vec2& point) { + Vec3 ball_mouse; + float mag; + Vec2 vec = (point - vec_ball_center_) / ball_radius_; + mag = vec.Dot(vec); + if (mag > 1.f) { + float scale = 1.f / sqrtf(mag); + vec *= scale; + ball_mouse = Vec3(vec, 0.f); + } else { + ball_mouse = Vec3(vec, sqrtf(1.f - mag)); + } + return ball_mouse; +} + +} // namespace ndkHelper diff --git a/NativeApp/Android/ndk_helper/src/vecmath.cpp b/NativeApp/Android/ndk_helper/src/vecmath.cpp new file mode 100644 index 0000000..1a06432 --- /dev/null +++ b/NativeApp/Android/ndk_helper/src/vecmath.cpp @@ -0,0 +1,406 @@ +/* + * Copy_right 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * y_ou may_ not use this file ex_cept in compliance with the License. + * You may_ obtain a copy_ of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by_ applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either ex_press or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//-------------------------------------------------------------------------------- +// vecmath.cpp +//-------------------------------------------------------------------------------- +#include "vecmath.h" + +namespace ndk_helper { + +//-------------------------------------------------------------------------------- +// vec3 +//-------------------------------------------------------------------------------- +Vec3::Vec3(const Vec4& vec) { + x_ = vec.x_; + y_ = vec.y_; + z_ = vec.z_; +} + +//-------------------------------------------------------------------------------- +// vec4 +//-------------------------------------------------------------------------------- +Vec4 Vec4::operator*(const Mat4& rhs) const { + Vec4 out; + out.x_ = x_ * rhs.f_[0] + y_ * rhs.f_[1] + z_ * rhs.f_[2] + w_ * rhs.f_[3]; + out.y_ = x_ * rhs.f_[4] + y_ * rhs.f_[5] + z_ * rhs.f_[6] + w_ * rhs.f_[7]; + out.z_ = x_ * rhs.f_[8] + y_ * rhs.f_[9] + z_ * rhs.f_[10] + w_ * rhs.f_[11]; + out.w_ = + x_ * rhs.f_[12] + y_ * rhs.f_[13] + z_ * rhs.f_[14] + w_ * rhs.f_[15]; + return out; +} + +//-------------------------------------------------------------------------------- +// mat4 +//-------------------------------------------------------------------------------- +Mat4::Mat4() { + for (int32_t i = 0; i < 16; ++i) f_[i] = 0.f; + // column major identity matrix + f_[0] = f_[5] = f_[10] = f_[15] = 1.0f; +} + +Mat4::Mat4(const float* mIn) { + for (int32_t i = 0; i < 16; ++i) f_[i] = mIn[i]; +} + +Mat4 Mat4::operator*(const Mat4& rhs) const { + Mat4 ret; + ret.f_[0] = f_[0] * rhs.f_[0] + f_[4] * rhs.f_[1] + f_[8] * rhs.f_[2] + + f_[12] * rhs.f_[3]; + ret.f_[1] = f_[1] * rhs.f_[0] + f_[5] * rhs.f_[1] + f_[9] * rhs.f_[2] + + f_[13] * rhs.f_[3]; + ret.f_[2] = f_[2] * rhs.f_[0] + f_[6] * rhs.f_[1] + f_[10] * rhs.f_[2] + + f_[14] * rhs.f_[3]; + ret.f_[3] = f_[3] * rhs.f_[0] + f_[7] * rhs.f_[1] + f_[11] * rhs.f_[2] + + f_[15] * rhs.f_[3]; + + ret.f_[4] = f_[0] * rhs.f_[4] + f_[4] * rhs.f_[5] + f_[8] * rhs.f_[6] + + f_[12] * rhs.f_[7]; + ret.f_[5] = f_[1] * rhs.f_[4] + f_[5] * rhs.f_[5] + f_[9] * rhs.f_[6] + + f_[13] * rhs.f_[7]; + ret.f_[6] = f_[2] * rhs.f_[4] + f_[6] * rhs.f_[5] + f_[10] * rhs.f_[6] + + f_[14] * rhs.f_[7]; + ret.f_[7] = f_[3] * rhs.f_[4] + f_[7] * rhs.f_[5] + f_[11] * rhs.f_[6] + + f_[15] * rhs.f_[7]; + + ret.f_[8] = f_[0] * rhs.f_[8] + f_[4] * rhs.f_[9] + f_[8] * rhs.f_[10] + + f_[12] * rhs.f_[11]; + ret.f_[9] = f_[1] * rhs.f_[8] + f_[5] * rhs.f_[9] + f_[9] * rhs.f_[10] + + f_[13] * rhs.f_[11]; + ret.f_[10] = f_[2] * rhs.f_[8] + f_[6] * rhs.f_[9] + f_[10] * rhs.f_[10] + + f_[14] * rhs.f_[11]; + ret.f_[11] = f_[3] * rhs.f_[8] + f_[7] * rhs.f_[9] + f_[11] * rhs.f_[10] + + f_[15] * rhs.f_[11]; + + ret.f_[12] = f_[0] * rhs.f_[12] + f_[4] * rhs.f_[13] + f_[8] * rhs.f_[14] + + f_[12] * rhs.f_[15]; + ret.f_[13] = f_[1] * rhs.f_[12] + f_[5] * rhs.f_[13] + f_[9] * rhs.f_[14] + + f_[13] * rhs.f_[15]; + ret.f_[14] = f_[2] * rhs.f_[12] + f_[6] * rhs.f_[13] + f_[10] * rhs.f_[14] + + f_[14] * rhs.f_[15]; + ret.f_[15] = f_[3] * rhs.f_[12] + f_[7] * rhs.f_[13] + f_[11] * rhs.f_[14] + + f_[15] * rhs.f_[15]; + + return ret; +} + +Vec4 Mat4::operator*(const Vec4& rhs) const { + Vec4 ret; + ret.x_ = rhs.x_ * f_[0] + rhs.y_ * f_[4] + rhs.z_ * f_[8] + rhs.w_ * f_[12]; + ret.y_ = rhs.x_ * f_[1] + rhs.y_ * f_[5] + rhs.z_ * f_[9] + rhs.w_ * f_[13]; + ret.z_ = rhs.x_ * f_[2] + rhs.y_ * f_[6] + rhs.z_ * f_[10] + rhs.w_ * f_[14]; + ret.w_ = rhs.x_ * f_[3] + rhs.y_ * f_[7] + rhs.z_ * f_[11] + rhs.w_ * f_[15]; + return ret; +} + +Mat4 Mat4::Inverse() { + Mat4 ret; + float det_1; + float pos = 0; + float neg = 0; + float temp; + + temp = f_[0] * f_[5] * f_[10]; + if (temp >= 0) + pos += temp; + else + neg += temp; + temp = f_[4] * f_[9] * f_[2]; + if (temp >= 0) + pos += temp; + else + neg += temp; + temp = f_[8] * f_[1] * f_[6]; + if (temp >= 0) + pos += temp; + else + neg += temp; + temp = -f_[8] * f_[5] * f_[2]; + if (temp >= 0) + pos += temp; + else + neg += temp; + temp = -f_[4] * f_[1] * f_[10]; + if (temp >= 0) + pos += temp; + else + neg += temp; + temp = -f_[0] * f_[9] * f_[6]; + if (temp >= 0) + pos += temp; + else + neg += temp; + det_1 = pos + neg; + + if (det_1 == 0.0) { + // Error + } else { + det_1 = 1.0f / det_1; + ret.f_[0] = (f_[5] * f_[10] - f_[9] * f_[6]) * det_1; + ret.f_[1] = -(f_[1] * f_[10] - f_[9] * f_[2]) * det_1; + ret.f_[2] = (f_[1] * f_[6] - f_[5] * f_[2]) * det_1; + ret.f_[4] = -(f_[4] * f_[10] - f_[8] * f_[6]) * det_1; + ret.f_[5] = (f_[0] * f_[10] - f_[8] * f_[2]) * det_1; + ret.f_[6] = -(f_[0] * f_[6] - f_[4] * f_[2]) * det_1; + ret.f_[8] = (f_[4] * f_[9] - f_[8] * f_[5]) * det_1; + ret.f_[9] = -(f_[0] * f_[9] - f_[8] * f_[1]) * det_1; + ret.f_[10] = (f_[0] * f_[5] - f_[4] * f_[1]) * det_1; + + /* Calculate -C * inverse(A) */ + ret.f_[12] = + -(f_[12] * ret.f_[0] + f_[13] * ret.f_[4] + f_[14] * ret.f_[8]); + ret.f_[13] = + -(f_[12] * ret.f_[1] + f_[13] * ret.f_[5] + f_[14] * ret.f_[9]); + ret.f_[14] = + -(f_[12] * ret.f_[2] + f_[13] * ret.f_[6] + f_[14] * ret.f_[10]); + + ret.f_[3] = 0.0f; + ret.f_[7] = 0.0f; + ret.f_[11] = 0.0f; + ret.f_[15] = 1.0f; + } + + *this = ret; + return *this; +} + +//-------------------------------------------------------------------------------- +// Misc +//-------------------------------------------------------------------------------- +Mat4 Mat4::RotationX(const float fAngle) { + Mat4 ret; + float fCosine, fSine; + + fCosine = cosf(fAngle); + fSine = sinf(fAngle); + + ret.f_[0] = 1.0f; + ret.f_[4] = 0.0f; + ret.f_[8] = 0.0f; + ret.f_[12] = 0.0f; + ret.f_[1] = 0.0f; + ret.f_[5] = fCosine; + ret.f_[9] = fSine; + ret.f_[13] = 0.0f; + ret.f_[2] = 0.0f; + ret.f_[6] = -fSine; + ret.f_[10] = fCosine; + ret.f_[14] = 0.0f; + ret.f_[3] = 0.0f; + ret.f_[7] = 0.0f; + ret.f_[11] = 0.0f; + ret.f_[15] = 1.0f; + return ret; +} + +Mat4 Mat4::RotationY(const float fAngle) { + Mat4 ret; + float fCosine, fSine; + + fCosine = cosf(fAngle); + fSine = sinf(fAngle); + + ret.f_[0] = fCosine; + ret.f_[4] = 0.0f; + ret.f_[8] = -fSine; + ret.f_[12] = 0.0f; + ret.f_[1] = 0.0f; + ret.f_[5] = 1.0f; + ret.f_[9] = 0.0f; + ret.f_[13] = 0.0f; + ret.f_[2] = fSine; + ret.f_[6] = 0.0f; + ret.f_[10] = fCosine; + ret.f_[14] = 0.0f; + ret.f_[3] = 0.0f; + ret.f_[7] = 0.0f; + ret.f_[11] = 0.0f; + ret.f_[15] = 1.0f; + return ret; +} + +Mat4 Mat4::RotationZ(const float fAngle) { + Mat4 ret; + float fCosine, fSine; + + fCosine = cosf(fAngle); + fSine = sinf(fAngle); + + ret.f_[0] = fCosine; + ret.f_[4] = fSine; + ret.f_[8] = 0.0f; + ret.f_[12] = 0.0f; + ret.f_[1] = -fSine; + ret.f_[5] = fCosine; + ret.f_[9] = 0.0f; + ret.f_[13] = 0.0f; + ret.f_[2] = 0.0f; + ret.f_[6] = 0.0f; + ret.f_[10] = 1.0f; + ret.f_[14] = 0.0f; + ret.f_[3] = 0.0f; + ret.f_[7] = 0.0f; + ret.f_[11] = 0.0f; + ret.f_[15] = 1.0f; + return ret; +} + +Mat4 Mat4::Scale(const float scaleX, const float scaleY, const float scaleZ) { + Mat4 ret; + ret.f_[0] = scaleX; + ret.f_[5] = scaleY; + ret.f_[10] = scaleZ; + ret.f_[1] = ret.f_[2] = ret.f_[3] = ret.f_[4] = ret.f_[6] = ret.f_[7] = + ret.f_[8] = ret.f_[9] = ret.f_[11] = ret.f_[12] = ret.f_[13] = + ret.f_[14] = 0.f; + ret.f_[15] = 1.0f; + return ret; +} + +Mat4 Mat4::Translation(const float fX, const float fY, const float fZ) { + Mat4 ret; + ret.f_[0] = 1.0f; + ret.f_[4] = 0.0f; + ret.f_[8] = 0.0f; + ret.f_[12] = fX; + ret.f_[1] = 0.0f; + ret.f_[5] = 1.0f; + ret.f_[9] = 0.0f; + ret.f_[13] = fY; + ret.f_[2] = 0.0f; + ret.f_[6] = 0.0f; + ret.f_[10] = 1.0f; + ret.f_[14] = fZ; + ret.f_[3] = 0.0f; + ret.f_[7] = 0.0f; + ret.f_[11] = 0.0f; + ret.f_[15] = 1.0f; + return ret; +} + +Mat4 Mat4::Translation(const Vec3 vec) { + Mat4 ret; + ret.f_[0] = 1.0f; + ret.f_[4] = 0.0f; + ret.f_[8] = 0.0f; + ret.f_[12] = vec.x_; + ret.f_[1] = 0.0f; + ret.f_[5] = 1.0f; + ret.f_[9] = 0.0f; + ret.f_[13] = vec.y_; + ret.f_[2] = 0.0f; + ret.f_[6] = 0.0f; + ret.f_[10] = 1.0f; + ret.f_[14] = vec.z_; + ret.f_[3] = 0.0f; + ret.f_[7] = 0.0f; + ret.f_[11] = 0.0f; + ret.f_[15] = 1.0f; + return ret; +} + +Mat4 Mat4::Perspective(float width, float height, float nearPlane, + float farPlane) { + float n2 = 2.0f * nearPlane; + float rcpnmf = 1.f / (nearPlane - farPlane); + + Mat4 result; + result.f_[0] = n2 / width; + result.f_[4] = 0; + result.f_[8] = 0; + result.f_[12] = 0; + result.f_[1] = 0; + result.f_[5] = n2 / height; + result.f_[9] = 0; + result.f_[13] = 0; + result.f_[2] = 0; + result.f_[6] = 0; + result.f_[10] = (farPlane + nearPlane) * rcpnmf; + result.f_[14] = farPlane * rcpnmf * n2; + result.f_[3] = 0; + result.f_[7] = 0; + result.f_[11] = -1.0; + result.f_[15] = 0; + + return result; +} + +Mat4 Mat4::Ortho2D(float left, float top, float right, float bottom) { + const float zNear = -1.0f; + const float zFar = 1.0f; + const float inv_z = 1.0f / (zFar - zNear); + const float inv_y = 1.0f / (-top + bottom); + const float inv_x = 1.0f / (right - left); + + Mat4 result; + result.f_[0] = 2.0f * inv_x; + result.f_[1] = 0.0f; + result.f_[2] = 0.0f; + result.f_[3] = 0.0f; + + result.f_[4] = 0.0f; + result.f_[5] = 2.0 * inv_y; + result.f_[6] = 0.0f; + result.f_[7] = 0.0f; + + result.f_[8] = 0.0f; + result.f_[9] = 0.0f; + result.f_[10] = -2.0f * inv_z; + result.f_[11] = 0.0f; + + result.f_[12] = -(right + left) * inv_x; + result.f_[13] = (top + bottom) * inv_y; + result.f_[14] = -(zFar + zNear) * inv_z; + result.f_[15] = 1.0f; + return result; +} + +Mat4 Mat4::LookAt(const Vec3& vec_eye, const Vec3& vec_at, const Vec3& vec_up) { + Vec3 vec_forward, vec_up_norm, vec_side; + Mat4 result; + + vec_forward.x_ = vec_eye.x_ - vec_at.x_; + vec_forward.y_ = vec_eye.y_ - vec_at.y_; + vec_forward.z_ = vec_eye.z_ - vec_at.z_; + + vec_forward.Normalize(); + vec_up_norm = vec_up; + vec_up_norm.Normalize(); + vec_side = vec_up_norm.Cross(vec_forward); + vec_up_norm = vec_forward.Cross(vec_side); + + result.f_[0] = vec_side.x_; + result.f_[4] = vec_side.y_; + result.f_[8] = vec_side.z_; + result.f_[12] = 0; + result.f_[1] = vec_up_norm.x_; + result.f_[5] = vec_up_norm.y_; + result.f_[9] = vec_up_norm.z_; + result.f_[13] = 0; + result.f_[2] = vec_forward.x_; + result.f_[6] = vec_forward.y_; + result.f_[10] = vec_forward.z_; + result.f_[14] = 0; + result.f_[3] = 0; + result.f_[7] = 0; + result.f_[11] = 0; + result.f_[15] = 1.0; + + result.PostTranslate(-vec_eye.x_, -vec_eye.y_, -vec_eye.z_); + return result; +} + +} // namespace ndkHelper diff --git a/NativeApp/Android/src/main/AndroidManifest.xml b/NativeApp/Android/src/main/AndroidManifest.xml new file mode 100644 index 0000000..467f1c7 --- /dev/null +++ b/NativeApp/Android/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.diligentengine.android.common" /> diff --git a/NativeApp/Android/src/main/java/com/diligentengine/android/common/DiligentApplicationBase.java b/NativeApp/Android/src/main/java/com/diligentengine/android/common/DiligentApplicationBase.java new file mode 100644 index 0000000..2342e46 --- /dev/null +++ b/NativeApp/Android/src/main/java/com/diligentengine/android/common/DiligentApplicationBase.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.diligentengine.android.common; + +import android.app.Application; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.util.Log; +import android.widget.Toast; + +public class DiligentApplicationBase extends Application { + public void onCreate(){ + Log.w("native-activity", "onCreate"); + + final PackageManager pm = getApplicationContext().getPackageManager(); + ApplicationInfo ai; + try { + ai = pm.getApplicationInfo( this.getPackageName(), 0); + } catch (final NameNotFoundException e) { + ai = null; + } + final String applicationName = (String) (ai != null ? pm.getApplicationLabel(ai) : "(unknown)"); + Toast.makeText(this, applicationName, Toast.LENGTH_SHORT).show(); + } +} diff --git a/NativeApp/Android/src/main/java/com/diligentengine/android/common/NativeActivityBase.java b/NativeApp/Android/src/main/java/com/diligentengine/android/common/NativeActivityBase.java new file mode 100644 index 0000000..396aa7a --- /dev/null +++ b/NativeApp/Android/src/main/java/com/diligentengine/android/common/NativeActivityBase.java @@ -0,0 +1,156 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.diligentengine.android.common; + +import android.app.NativeActivity; +import android.os.Bundle; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup.MarginLayoutParams; +import android.view.WindowManager.LayoutParams; +import android.widget.LinearLayout; +import android.widget.PopupWindow; +import android.widget.TextView; +import android.util.Log; + +public class NativeActivityBase extends NativeActivity { + + static + { + try{ + System.loadLibrary("GraphicsEngineOpenGL"); + Log.i("native-activity", "Loaded GraphicsEngineOpenGL library.\n"); + } catch (UnsatisfiedLinkError e) { + Log.e("native-activity", "Failed to load GraphicsEngineOpenGL library.\n" + e); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + //Hide toolbar + int SDK_INT = android.os.Build.VERSION.SDK_INT; + if(SDK_INT >= 19) + { + setImmersiveSticky(); + + View decorView = getWindow().getDecorView(); + decorView.setOnSystemUiVisibilityChangeListener + (new View.OnSystemUiVisibilityChangeListener() { + @Override + public void onSystemUiVisibilityChange(int visibility) { + setImmersiveSticky(); + } + }); + } + + } + + protected void onResume() { + super.onResume(); + + //Hide toolbar + int SDK_INT = android.os.Build.VERSION.SDK_INT; + if(SDK_INT >= 11 && SDK_INT < 14) + { + getWindow().getDecorView().setSystemUiVisibility(View.STATUS_BAR_HIDDEN); + } + else if(SDK_INT >= 14 && SDK_INT < 19) + { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LOW_PROFILE); + } + else if(SDK_INT >= 19) + { + setImmersiveSticky(); + } + + } + // Our popup window, you will call it from your C/C++ code later + + void setImmersiveSticky() { + View decorView = getWindow().getDecorView(); + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + } + + NativeActivityBase _activity; + PopupWindow _popupWindow; + TextView _label; + + public void showUI() + { + if( _popupWindow != null ) + return; + + _activity = this; + + this.runOnUiThread(new Runnable() { + @Override + public void run() { + LayoutInflater layoutInflater + = (LayoutInflater)getBaseContext() + .getSystemService(LAYOUT_INFLATER_SERVICE); + View popupView = layoutInflater.inflate(R.layout.widgets, null); + _popupWindow = new PopupWindow( + popupView, + LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT); + + LinearLayout mainLayout = new LinearLayout(_activity); + MarginLayoutParams params = new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + params.setMargins(0, 0, 0, 0); + _activity.setContentView(mainLayout, params); + + // Show our UI over NativeActivity window + _popupWindow.showAtLocation(mainLayout, Gravity.TOP | Gravity.LEFT, 10, 10); + _popupWindow.update(); + + _label = (TextView)popupView.findViewById(R.id.textViewFPS); + + }}); + } + + protected void onPause() + { + super.onPause(); + if (_popupWindow != null) { + _popupWindow.dismiss(); + _popupWindow = null; + } + } + + public void updateFPS(final float fFPS) + { + if( _label == null ) + return; + + _activity = this; + this.runOnUiThread(new Runnable() { + @Override + public void run() { + _label.setText(String.format("%2.2f FPS", fFPS)); + + }}); + } +} + + diff --git a/NativeApp/Android/src/main/res/layout/widgets.xml b/NativeApp/Android/src/main/res/layout/widgets.xml new file mode 100644 index 0000000..b6e86e6 --- /dev/null +++ b/NativeApp/Android/src/main/res/layout/widgets.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="top" + android:orientation="vertical" > + + <TextView + android:id="@+id/textViewFPS" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="end" + android:text="@string/fps" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="@android:color/white" /> + +</LinearLayout>
\ No newline at end of file diff --git a/NativeApp/Android/src/main/res/mipmap-hdpi/ic_launcher.png b/NativeApp/Android/src/main/res/mipmap-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..5a261ea --- /dev/null +++ b/NativeApp/Android/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/NativeApp/Android/src/main/res/mipmap-mdpi/ic_launcher.png b/NativeApp/Android/src/main/res/mipmap-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..74263d9 --- /dev/null +++ b/NativeApp/Android/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/NativeApp/Android/src/main/res/mipmap-xhdpi/ic_launcher.png b/NativeApp/Android/src/main/res/mipmap-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..da6a331 --- /dev/null +++ b/NativeApp/Android/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/NativeApp/Android/src/main/res/mipmap-xxhdpi/ic_launcher.png b/NativeApp/Android/src/main/res/mipmap-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..e587387 --- /dev/null +++ b/NativeApp/Android/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/NativeApp/Android/src/main/res/values-v11/styles.xml b/NativeApp/Android/src/main/res/values-v11/styles.xml new file mode 100644 index 0000000..541752f --- /dev/null +++ b/NativeApp/Android/src/main/res/values-v11/styles.xml @@ -0,0 +1,11 @@ +<resources> + + <!-- + Base application theme for API 11+. This theme completely replaces + AppBaseTheme from res/values/styles.xml on API 11+ devices. + --> + <style name="AppBaseTheme" parent="android:Theme.Holo.Light"> + <!-- API 11 theme customizations can go here. --> + </style> + +</resources>
\ No newline at end of file diff --git a/NativeApp/Android/src/main/res/values-v14/styles.xml b/NativeApp/Android/src/main/res/values-v14/styles.xml new file mode 100644 index 0000000..f20e015 --- /dev/null +++ b/NativeApp/Android/src/main/res/values-v14/styles.xml @@ -0,0 +1,12 @@ +<resources> + + <!-- + Base application theme for API 14+. This theme completely replaces + AppBaseTheme from BOTH res/values/styles.xml and + res/values-v11/styles.xml on API 14+ devices. + --> + <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar"> + <!-- API 14 theme customizations can go here. --> + </style> + +</resources>
\ No newline at end of file diff --git a/NativeApp/Android/src/main/res/values/strings.xml b/NativeApp/Android/src/main/res/values/strings.xml new file mode 100644 index 0000000..a06980b --- /dev/null +++ b/NativeApp/Android/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ +<resources> + + <string name="fps">0.0 FPS</string> + +</resources>
\ No newline at end of file diff --git a/NativeApp/Android/src/main/res/values/styles.xml b/NativeApp/Android/src/main/res/values/styles.xml new file mode 100644 index 0000000..4a10ca4 --- /dev/null +++ b/NativeApp/Android/src/main/res/values/styles.xml @@ -0,0 +1,20 @@ +<resources> + + <!-- + Base application theme, dependent on API level. This theme is replaced + by AppBaseTheme from res/values-vXX/styles.xml on newer devices. + --> + <style name="AppBaseTheme" parent="android:Theme.Light"> + <!-- + Theme customizations available in newer API levels can go in + res/values-vXX/styles.xml, while customizations related to + backward-compatibility can go here. + --> + </style> + + <!-- Application theme. --> + <style name="AppTheme" parent="AppBaseTheme"> + <!-- All customizations that are NOT specific to a particular API-level can go here. --> + </style> + +</resources>
\ No newline at end of file |
