diff --git a/examples/osgAndroidExampleGLES1/AndroidManifest.xml b/examples/osgAndroidExampleGLES1/AndroidManifest.xml
new file mode 100644
index 000000000..eac0d374a
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/AndroidManifest.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/osgAndroidExampleGLES1/default.properties b/examples/osgAndroidExampleGLES1/default.properties
new file mode 100644
index 000000000..e2e8061f2
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/default.properties
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-8
diff --git a/examples/osgAndroidExampleGLES1/jni/Android.mk b/examples/osgAndroidExampleGLES1/jni/Android.mk
new file mode 100644
index 000000000..1a4d3efc0
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/jni/Android.mk
@@ -0,0 +1,67 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := osgNativeLib
+### Main Install dir
+OSG_ANDROID_DIR := < type your install directory >
+LIBDIR := $(OSG_ANDROID_DIR)/obj/local/armeabi
+
+ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
+ LOCAL_ARM_NEON := true
+ LIBDIR := $(OSG_ANDROID_DIR)/obj/local/armeabi-v7a
+endif
+
+### Add all source file names to be included in lib separated by a whitespace
+
+LOCAL_C_INCLUDES:= $(OSG_ANDROID_DIR)/include
+LOCAL_CFLAGS := -Werror -fno-short-enums
+LOCAL_CPPFLAGS := -DOSG_LIBRARY_STATIC
+
+LOCAL_LDLIBS := -llog -lGLESv1_CM -ldl -lz
+LOCAL_SRC_FILES := osgNativeLib.cpp OsgMainApp.cpp OsgAndroidNotifyHandler.cpp
+LOCAL_LDFLAGS := -L $(LIBDIR) \
+-losgdb_dds \
+-losgdb_openflight \
+-losgdb_tga \
+-losgdb_rgb \
+-losgdb_osgterrain \
+-losgdb_osg \
+-losgdb_ive \
+-losgdb_deprecated_osgviewer \
+-losgdb_deprecated_osgvolume \
+-losgdb_deprecated_osgtext \
+-losgdb_deprecated_osgterrain \
+-losgdb_deprecated_osgsim \
+-losgdb_deprecated_osgshadow \
+-losgdb_deprecated_osgparticle \
+-losgdb_deprecated_osgfx \
+-losgdb_deprecated_osganimation \
+-losgdb_deprecated_osg \
+-losgdb_serializers_osgvolume \
+-losgdb_serializers_osgtext \
+-losgdb_serializers_osgterrain \
+-losgdb_serializers_osgsim \
+-losgdb_serializers_osgshadow \
+-losgdb_serializers_osgparticle \
+-losgdb_serializers_osgmanipulator \
+-losgdb_serializers_osgfx \
+-losgdb_serializers_osganimation \
+-losgdb_serializers_osg \
+-losgViewer \
+-losgVolume \
+-losgTerrain \
+-losgText \
+-losgShadow \
+-losgSim \
+-losgParticle \
+-losgManipulator \
+-losgGA \
+-losgFX \
+-losgDB \
+-losgAnimation \
+-losgUtil \
+-losg \
+-lOpenThreads
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/examples/osgAndroidExampleGLES1/jni/Application.mk b/examples/osgAndroidExampleGLES1/jni/Application.mk
new file mode 100644
index 000000000..20040dc94
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/jni/Application.mk
@@ -0,0 +1,11 @@
+#ANDROID APPLICATION MAKEFILE
+APP_BUILD_SCRIPT := $(call my-dir)/Android.mk
+#APP_PROJECT_PATH := $(call my-dir)
+
+APP_OPTIM := release
+
+APP_PLATFORM := android-7
+APP_STL := gnustl_static
+APP_CPPFLAGS := -fexceptions -frtti
+APP_ABI := armeabi armeabi-v7a
+APP_MODULES := osgNativeLib
\ No newline at end of file
diff --git a/examples/osgAndroidExampleGLES1/jni/OsgAndroidNotifyHandler.cpp b/examples/osgAndroidExampleGLES1/jni/OsgAndroidNotifyHandler.cpp
new file mode 100644
index 000000000..2e4f38c15
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/jni/OsgAndroidNotifyHandler.cpp
@@ -0,0 +1,38 @@
+/*
+ * OsgAndroidNotifyHandler.cpp
+ *
+ * Created on: 31/05/2011
+ * Author: Jorge Izquierdo Ciges
+ */
+
+#include "OsgAndroidNotifyHandler.hpp"
+#include
+
+void OsgAndroidNotifyHandler::setTag(std::string tag){
+ _tag = tag;
+}
+void OsgAndroidNotifyHandler::notify(osg::NotifySeverity severity, const char *message){
+
+ switch ( severity ) {
+ case osg::DEBUG_FP:
+ __android_log_write(ANDROID_LOG_VERBOSE,_tag.c_str(),message);
+ break;
+ case osg::DEBUG_INFO:
+ __android_log_write(ANDROID_LOG_DEBUG,_tag.c_str(),message);
+ break;
+ case osg::NOTICE:
+ case osg::INFO:
+ __android_log_write(ANDROID_LOG_INFO,_tag.c_str(),message);
+ break;
+ case osg::WARN:
+ __android_log_write(ANDROID_LOG_WARN,_tag.c_str(),message);
+ break;
+ case osg::FATAL:
+ case osg::ALWAYS:
+ __android_log_write(ANDROID_LOG_ERROR,_tag.c_str(),message);
+ break;
+ default:
+ __android_log_write(ANDROID_LOG_DEBUG,_tag.c_str(),message);
+ break;
+ }
+}
diff --git a/examples/osgAndroidExampleGLES1/jni/OsgAndroidNotifyHandler.hpp b/examples/osgAndroidExampleGLES1/jni/OsgAndroidNotifyHandler.hpp
new file mode 100644
index 000000000..114a369aa
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/jni/OsgAndroidNotifyHandler.hpp
@@ -0,0 +1,26 @@
+/*
+ * OsgAndroidNotifyHandler.hpp
+ *
+ * Created on: 31/05/2011
+ * Author: Jorge Izquierdo Ciges
+ */
+
+#ifndef OSGANDROIDNOTIFYHANDLER_HPP_
+#define OSGANDROIDNOTIFYHANDLER_HPP_
+
+#include
+
+#include
+
+#include
+
+class OSG_EXPORT OsgAndroidNotifyHandler : public osg::NotifyHandler
+{
+private:
+ std::string _tag;
+public:
+ void setTag(std::string tag);
+ void notify(osg::NotifySeverity severity, const char *message);
+};
+
+#endif /* OSGANDROIDNOTIFYHANDLER_HPP_ */
diff --git a/examples/osgAndroidExampleGLES1/jni/OsgMainApp.cpp b/examples/osgAndroidExampleGLES1/jni/OsgMainApp.cpp
new file mode 100644
index 000000000..c1d930c55
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/jni/OsgMainApp.cpp
@@ -0,0 +1,205 @@
+#include "OsgMainApp.hpp"
+
+
+OsgMainApp::OsgMainApp(){
+
+ _lodScale = 1.0f;
+ _prevFrame = 0;
+
+ _initialized = false;
+ _clean_scene = false;
+
+}
+OsgMainApp::~OsgMainApp(){
+
+}
+void OsgMainApp::loadModels(){
+ if(_vModelsToLoad.size()==0) return;
+
+ osg::notify(osg::ALWAYS)<<"There are "<<_vModelsToLoad.size()<<" models to load"< loadedModel = osgDB::readNodeFile(newModel.filename);
+ if (loadedModel == 0) {
+ osg::notify(osg::ALWAYS)<<"Model not loaded"<setName(newModel.name);
+ _root->addChild(loadedModel);
+ }
+ }
+
+ _viewer->setSceneData(NULL);
+ _viewer->setSceneData(_root.get());
+ _manipulator->getNode();
+ _viewer->home();
+
+ _viewer->getDatabasePager()->clear();
+ _viewer->getDatabasePager()->registerPagedLODs(_root.get());
+ _viewer->getDatabasePager()->setUpThreads(3, 1);
+ _viewer->getDatabasePager()->setTargetMaximumNumberOfPageLOD(2);
+ _viewer->getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true, true);
+
+ _vModelsToLoad.clear();
+
+}
+void OsgMainApp::deleteModels(){
+ if(_vModelsToDelete.size()==0) return;
+
+ osg::notify(osg::ALWAYS)<<"There are "<<_vModelsToDelete.size()<<" models to delete"<getNumChildren(); j>0; j--){
+ osg::ref_ptr children = _root->getChild(j-1);
+ if(children->getName() == modelToDelete.name){
+ _root->removeChild(children);
+ }
+ }
+
+ }
+
+ _vModelsToDelete.clear();
+ osg::notify(osg::ALWAYS)<<"finished"<setTag("Osg Viewer");
+ osg::setNotifyHandler(_notifyHandler);
+
+ osg::notify(osg::ALWAYS)<<"Testing"<setUpViewerAsEmbeddedInWindow(x, y, width, height);
+
+ _root = new osg::Group();
+
+ _viewer->realize();
+
+ _state = _root->getOrCreateStateSet();
+ _state->setMode(GL_LIGHTING, osg::StateAttribute::ON);
+ _state->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
+ _state->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
+
+ _viewer->setSceneData(_root.get());
+
+ _viewer->addEventHandler(new osgViewer::StatsHandler);
+ _viewer->addEventHandler(new osgGA::StateSetManipulator(_viewer->getCamera()->getOrCreateStateSet()));
+ _viewer->addEventHandler(new osgViewer::ThreadingHandler);
+ _viewer->addEventHandler(new osgViewer::LODScaleHandler);
+
+ _manipulator = new osgGA::KeySwitchMatrixManipulator;
+
+ _manipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
+ _manipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
+ _manipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
+ _manipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
+ _manipulator->addMatrixManipulator( '5', "Orbit", new osgGA::OrbitManipulator() );
+ _manipulator->addMatrixManipulator( '6', "FirstPerson", new osgGA::FirstPersonManipulator() );
+ _manipulator->addMatrixManipulator( '7', "Spherical", new osgGA::SphericalManipulator() );
+
+ _viewer->setCameraManipulator( _manipulator.get() );
+
+ _viewer->getViewerStats()->collectStats("scene", true);
+
+ _initialized = true;
+
+}
+//Draw
+void OsgMainApp::draw(){
+ //Every load o remove has to be done before any drawing
+ loadModels();
+ deleteModels();
+
+ _viewer->frame();
+}
+//Events
+void OsgMainApp::mouseButtonPressEvent(float x,float y,int button){
+ _viewer->getEventQueue()->mouseButtonPress(x, y, button);
+}
+void OsgMainApp::mouseButtonReleaseEvent(float x,float y,int button){
+ _viewer->getEventQueue()->mouseButtonRelease(x, y, button);
+}
+void OsgMainApp::mouseMoveEvent(float x,float y){
+ _viewer->getEventQueue()->mouseMotion(x, y);
+}
+void OsgMainApp::keyboardDown(int key){
+ _viewer->getEventQueue()->keyPress(key);
+}
+void OsgMainApp::keyboardUp(int key){
+ _viewer->getEventQueue()->keyRelease(key);
+}
+//Loading and unloading
+void OsgMainApp::loadObject(std::string filePath){
+ Model newModel;
+ newModel.filename = filePath;
+ newModel.name = filePath;
+
+ int num = 0;
+ for(unsigned int i=0;i<_vModels.size();i++){
+ if(_vModels[i].name==newModel.name)
+ return;
+ }
+
+ _vModelsToLoad.push_back(newModel);
+
+}
+void OsgMainApp::loadObject(std::string name,std::string filePath){
+
+ Model newModel;
+ newModel.filename = filePath;
+ newModel.name = name;
+
+ for(unsigned int i=0;i<_vModels.size();i++){
+ if(_vModels[i].name==newModel.name){
+ osg::notify(osg::ALWAYS)<<"Name already used"<getCamera()->setClearColor(color);
+}
+osg::Vec4f OsgMainApp::getClearColor(){
+ osg::notify(osg::ALWAYS)<<"Getting Clear Color"<getCamera()->getClearColor();
+}
diff --git a/examples/osgAndroidExampleGLES1/jni/OsgMainApp.hpp b/examples/osgAndroidExampleGLES1/jni/OsgMainApp.hpp
new file mode 100644
index 000000000..95f18b286
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/jni/OsgMainApp.hpp
@@ -0,0 +1,138 @@
+/*
+ * OsgMainApp.hpp
+ *
+ * Created on: 29/05/2011
+ * Author: Jorge Izquierdo Ciges
+ */
+
+#ifndef OSGMAINAPP_HPP_
+#define OSGMAINAPP_HPP_
+
+//Android log
+#include
+#include
+#include
+#include
+
+//Standard libraries
+#include
+
+//osg
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+//osgText
+#include
+//osgDB
+#include
+#include
+#include
+#include
+//osg_viewer
+#include
+#include
+#include
+//osgGA
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+//Self headers
+#include "OsgAndroidNotifyHandler.hpp"
+
+//Static plugins Macro
+USE_OSGPLUGIN(ive)
+USE_OSGPLUGIN(osg)
+USE_OSGPLUGIN(osg2)
+USE_OSGPLUGIN(terrain)
+USE_OSGPLUGIN(rgb)
+USE_OSGPLUGIN(OpenFlight)
+USE_OSGPLUGIN(dds)
+//Static DOTOSG
+USE_DOTOSGWRAPPER_LIBRARY(osg)
+USE_DOTOSGWRAPPER_LIBRARY(osgFX)
+USE_DOTOSGWRAPPER_LIBRARY(osgParticle)
+USE_DOTOSGWRAPPER_LIBRARY(osgTerrain)
+USE_DOTOSGWRAPPER_LIBRARY(osgText)
+USE_DOTOSGWRAPPER_LIBRARY(osgViewer)
+USE_DOTOSGWRAPPER_LIBRARY(osgVolume)
+//Static serializer
+USE_SERIALIZER_WRAPPER_LIBRARY(osg)
+USE_SERIALIZER_WRAPPER_LIBRARY(osgAnimation)
+USE_SERIALIZER_WRAPPER_LIBRARY(osgFX)
+USE_SERIALIZER_WRAPPER_LIBRARY(osgManipulator)
+USE_SERIALIZER_WRAPPER_LIBRARY(osgParticle)
+USE_SERIALIZER_WRAPPER_LIBRARY(osgTerrain)
+USE_SERIALIZER_WRAPPER_LIBRARY(osgText)
+USE_SERIALIZER_WRAPPER_LIBRARY(osgVolume)
+
+#define LOG_TAG "osgNativeLib"
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
+
+struct Model{
+ std::string filename;
+ std::string name;
+};
+
+class OsgMainApp{
+private:
+ osg::ref_ptr _viewer;
+ osg::ref_ptr _root;
+ osg::ref_ptr _state;
+ osg::ref_ptr _manipulator;
+
+ float _lodScale;
+ unsigned int _prevFrame;
+
+ bool _initialized;
+ bool _clean_scene;
+
+ OsgAndroidNotifyHandler *_notifyHandler;
+
+ std::vector _vModels;
+ std::vector _vModelsToLoad;
+ std::vector _vModelsToDelete;
+
+ void loadModels();
+ void deleteModels();
+
+public:
+ OsgMainApp();
+ ~OsgMainApp();
+
+ //Initialization function
+ void initOsgWindow(int x,int y,int width,int height);
+ //Draw
+ void draw();
+ //Events
+ void mouseButtonPressEvent(float x,float y,int button);
+ void mouseButtonReleaseEvent(float x,float y,int button);
+ void mouseMoveEvent(float x,float y);
+ void keyboardDown(int key);
+ void keyboardUp(int key);
+ //Loading and unloading
+ void loadObject(std::string filePath);
+ void loadObject(std::string name,std::string filePath);
+ void unLoadObject(int number);
+ void clearScene();
+ //Other functions
+ int getNumberObjects();
+ std::string getObjectName(int nunmber);
+
+ void setClearColor(osg::Vec4f color);
+ osg::Vec4f getClearColor();
+};
+
+
+#endif /* OSGMAINAPP_HPP_ */
diff --git a/examples/osgAndroidExampleGLES1/jni/osgNativeLib.cpp b/examples/osgAndroidExampleGLES1/jni/osgNativeLib.cpp
new file mode 100644
index 000000000..4c8efc3f2
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/jni/osgNativeLib.cpp
@@ -0,0 +1,113 @@
+#include
+#include
+#include
+
+#include
+
+#include "OsgMainApp.hpp"
+
+OsgMainApp mainApp;
+
+extern "C" {
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_init(JNIEnv * env, jobject obj, jint width, jint height);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_step(JNIEnv * env, jobject obj);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_clearContents(JNIEnv * env, jobject obj);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_mouseButtonPressEvent(JNIEnv * env, jobject obj, jfloat x, jfloat y, jint button);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_mouseButtonReleaseEvent(JNIEnv * env, jobject obj, jfloat x, jfloat y, jint button);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_mouseMoveEvent(JNIEnv * env, jobject obj, jfloat x, jfloat y);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_keyboardDown(JNIEnv * env, jobject obj, jint key);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_keyboardUp(JNIEnv * env, jobject obj, jint key);
+ JNIEXPORT jintArray JNICALL Java_osg_AndroidExample_osgNativeLib_getClearColor(JNIEnv * env, jobject obj);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_setClearColor(JNIEnv * env, jobject obj, jint red, jint green, jint blue);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_loadObject(JNIEnv * env, jobject obj, jstring address);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_unLoadObject(JNIEnv * env, jobject obj, jint number);
+ JNIEXPORT jobjectArray JNICALL Java_osg_AndroidExample_osgNativeLib_getObjectNames(JNIEnv * env, jobject obj);
+};
+
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_init(JNIEnv * env, jobject obj, jint width, jint height){
+ mainApp.initOsgWindow(0,0,width,height);
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_step(JNIEnv * env, jobject obj){
+ mainApp.draw();
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_clearContents(JNIEnv * env, jobject obj){
+ mainApp.clearScene();
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_mouseButtonPressEvent(JNIEnv * env, jobject obj, jfloat x, jfloat y, jint button){
+ mainApp.mouseButtonPressEvent(x,y,button);
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_mouseButtonReleaseEvent(JNIEnv * env, jobject obj, jfloat x, jfloat y, jint button){
+ mainApp.mouseButtonReleaseEvent(x,y,button);
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_mouseMoveEvent(JNIEnv * env, jobject obj, jfloat x, jfloat y){
+ mainApp.mouseMoveEvent(x,y);
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_keyboardDown(JNIEnv * env, jobject obj, jint key){
+ mainApp.keyboardDown(key);
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_keyboardUp(JNIEnv * env, jobject obj, jint key){
+ mainApp.keyboardUp(key);
+}
+JNIEXPORT jintArray JNICALL Java_osg_AndroidExample_osgNativeLib_getClearColor(JNIEnv * env, jobject obj){
+
+ jintArray color;
+ color = env->NewIntArray(3);
+ if (color == NULL) {
+ return NULL;
+ }
+ osg::Vec4 vTemp1 = mainApp.getClearColor();
+
+ jint vTemp2[3];
+
+ vTemp2[0] = (int) (vTemp1.r() * 255);
+ vTemp2[1] = (int) (vTemp1.g() * 255);
+ vTemp2[2] = (int) (vTemp1.b() * 255);
+
+ std::cout<SetIntArrayRegion(color, 0, 3, vTemp2);
+
+ return color;
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_setClearColor(JNIEnv * env, jobject obj, jint red, jint green, jint blue){
+ osg::Vec4 tVec((float) red / 255.0f, (float) green / 255.0f, (float) blue / 255.0f, 0.0f);
+ mainApp.setClearColor(tVec);
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_loadObject(JNIEnv * env, jobject obj, jstring address){
+ //Import Strings from JNI
+ const char *nativeAddress = env->GetStringUTFChars(address, false);
+
+ mainApp.loadObject(std::string(nativeAddress));
+
+ //Release Strings to JNI
+ env->ReleaseStringUTFChars(address, nativeAddress);
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_loadObject(JNIEnv * env, jobject obj, jstring address, jstring name){
+ //Import Strings from JNI
+ const char *nativeAddress = env->GetStringUTFChars(address, false);
+ const char *nativeName = env->GetStringUTFChars(name, false);
+
+ mainApp.loadObject(std::string(nativeName),std::string(nativeAddress));
+
+ //Release Strings to JNI
+ env->ReleaseStringUTFChars(address, nativeAddress);
+ env->ReleaseStringUTFChars(address, nativeName);
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_unLoadObject(JNIEnv * env, jobject obj, jint number){
+
+ mainApp.unLoadObject(number);
+
+}
+JNIEXPORT jobjectArray JNICALL Java_osg_AndroidExample_osgNativeLib_getObjectNames(JNIEnv * env, jobject obj){
+
+ jobjectArray fileNames;
+ unsigned int numModels = mainApp.getNumberObjects();
+ fileNames = (jobjectArray)env->NewObjectArray(numModels,env->FindClass("java/lang/String"),env->NewStringUTF(""));
+
+ for(unsigned int i=0;i < numModels;i++){
+ std::string name = mainApp.getObjectName(i);
+ env->SetObjectArrayElement(fileNames,i,env->NewStringUTF(name.c_str()));
+ }
+
+ return fileNames;
+}
diff --git a/examples/osgAndroidExampleGLES1/proguard.cfg b/examples/osgAndroidExampleGLES1/proguard.cfg
new file mode 100644
index 000000000..12dd0392c
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/proguard.cfg
@@ -0,0 +1,36 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/examples/osgAndroidExampleGLES1/res/drawable-hdpi/osg.png b/examples/osgAndroidExampleGLES1/res/drawable-hdpi/osg.png
new file mode 100644
index 000000000..e9377f500
Binary files /dev/null and b/examples/osgAndroidExampleGLES1/res/drawable-hdpi/osg.png differ
diff --git a/examples/osgAndroidExampleGLES1/res/drawable-hdpi/web_browser.png b/examples/osgAndroidExampleGLES1/res/drawable-hdpi/web_browser.png
new file mode 100644
index 000000000..ed13e46bd
Binary files /dev/null and b/examples/osgAndroidExampleGLES1/res/drawable-hdpi/web_browser.png differ
diff --git a/examples/osgAndroidExampleGLES1/res/drawable-ldpi/osg.png b/examples/osgAndroidExampleGLES1/res/drawable-ldpi/osg.png
new file mode 100644
index 000000000..0b8cce36b
Binary files /dev/null and b/examples/osgAndroidExampleGLES1/res/drawable-ldpi/osg.png differ
diff --git a/examples/osgAndroidExampleGLES1/res/drawable-mdpi/osg.png b/examples/osgAndroidExampleGLES1/res/drawable-mdpi/osg.png
new file mode 100644
index 000000000..f8275b46b
Binary files /dev/null and b/examples/osgAndroidExampleGLES1/res/drawable-mdpi/osg.png differ
diff --git a/examples/osgAndroidExampleGLES1/res/layout/dialog_text_entry.xml b/examples/osgAndroidExampleGLES1/res/layout/dialog_text_entry.xml
new file mode 100644
index 000000000..767021164
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/res/layout/dialog_text_entry.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
diff --git a/examples/osgAndroidExampleGLES1/res/layout/main.xml b/examples/osgAndroidExampleGLES1/res/layout/main.xml
new file mode 100644
index 000000000..3a5f117d3
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/res/layout/main.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/examples/osgAndroidExampleGLES1/res/layout/ui_layout_gles.xml b/examples/osgAndroidExampleGLES1/res/layout/ui_layout_gles.xml
new file mode 100644
index 000000000..1d10283f5
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/res/layout/ui_layout_gles.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/osgAndroidExampleGLES1/res/menu/appmenu.xml b/examples/osgAndroidExampleGLES1/res/menu/appmenu.xml
new file mode 100644
index 000000000..94cbfad3a
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/res/menu/appmenu.xml
@@ -0,0 +1,9 @@
+
+
diff --git a/examples/osgAndroidExampleGLES1/res/values/strings.xml b/examples/osgAndroidExampleGLES1/res/values/strings.xml
new file mode 100644
index 000000000..e242634ea
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/res/values/strings.xml
@@ -0,0 +1,28 @@
+
+
+ Hello World, osgViewer!
+ osgAndroidExample
+ #BBBBBB
+ Light (ON/OFF)
+ Center View
+ Change Navigation
+ Write address
+ Main navigation
+ Second Navigation
+ Light ON
+ Light OFF
+ Load Object
+ L. Object
+ Delete Object
+ D. Object
+ Clean Scene
+ Clean
+ Change Background
+ C.Background
+ Show Keyboard
+ S.Keyboard
+ Select Object
+ Write file address
+ Accept
+ Cancel
+
diff --git a/examples/osgAndroidExampleGLES1/src/osg/AndroidExample/ColorPickerDialog.java b/examples/osgAndroidExampleGLES1/src/osg/AndroidExample/ColorPickerDialog.java
new file mode 100644
index 000000000..b24e853f1
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/src/osg/AndroidExample/ColorPickerDialog.java
@@ -0,0 +1,250 @@
+package osg.AndroidExample;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.Shader;
+import android.os.Bundle;
+import android.view.MotionEvent;
+import android.view.View;
+
+public class ColorPickerDialog extends Dialog{
+
+ public interface OnColorChangeListener{
+ void colorChange(int color);
+ }
+
+ private OnColorChangeListener tListener;
+ private int tInitialColor;
+
+ private static class ColorPickerView extends View{
+
+ private Paint tPaint;
+ private float tCurrentHue = 0;
+ private int tCurrentX = 0;
+ private int tCurrentY = 0;
+ private int tCurrentColor;
+ private final int[] tHueGradientColors = new int [258];
+ private int [] tGradientColors = new int[65536]; //256X256 colors
+ private OnColorChangeListener tListener;
+ private boolean tQSelected = false;
+
+ public ColorPickerView(Context context, OnColorChangeListener listener, int color) {
+ super(context);
+ // TODO Auto-generated constructor stub
+ tListener = listener;
+
+ //Get Hue from tCurrentColor and update the Gradient of Color
+ float[] newHSV = new float[3];
+ Color.colorToHSV(color, newHSV);
+ tCurrentHue = newHSV[0];
+ updateGradientColors();
+ tCurrentColor = color;
+
+ //Initialize of colors in Hue slider
+
+ int index = 0;
+ for(float i=0; i<256; i += 256/42 , index++){
+ tHueGradientColors[index] = Color.rgb(255, 0, (int)i);
+ }
+ for(float i=0; i<256; i += 256/42 , index++){
+ tHueGradientColors[index] = Color.rgb(255-(int)i, 0, 255);
+ }
+ for(float i=0; i<256; i += 256/42 , index++){
+ tHueGradientColors[index] = Color.rgb(0, (int) i, 255);
+ }
+ for(float i=0; i<256; i += 256/42 , index++){
+ tHueGradientColors[index] = Color.rgb(0, 255, 255-(int)i);
+ }
+ for(float i=0; i<256; i += 256/42 , index++){
+ tHueGradientColors[index] = Color.rgb((int)i, 255, 0);
+ }
+ for(float i=0; i<256; i += 256/42 , index++){
+ tHueGradientColors[index] = Color.rgb(255, 255-(int)i, 0);
+ }
+
+ // Paint initialized
+ tPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ tPaint.setTextAlign(Paint.Align.CENTER);
+ tPaint.setTextSize(12);
+ }
+
+ // Get the Color from Hue Bar
+ private int getCurrentGradientColor(){
+
+ int currentHue = 255 - (int)(tCurrentHue*255/360);
+ int index = 0;
+ for (float i=0; i<256; i += 256/42, index++){
+ if (index == currentHue) return Color.rgb(255, 0, (int) i );
+ }
+ for (float i=0; i<256; i += 256/42, index++){
+ if (index == currentHue) return Color.rgb(255-(int)i, 0, 255 );
+ }
+ for (float i=0; i<256; i += 256/42, index++){
+ if (index == currentHue) return Color.rgb(0, (int) i, 255 );
+ }
+ for (float i=0; i<256; i += 256/42, index++){
+ if (index == currentHue) return Color.rgb(0, 255, 255-(int) i );
+ }
+ for (float i=0; i<256; i += 256/42, index++){
+ if (index == currentHue) return Color.rgb((int) i, 255, 0 );
+ }
+ for (float i=0; i<256; i += 256/42, index++){
+ if (index == currentHue) return Color.rgb(255, 255-(int) i, 0);
+ }
+ return Color.RED;
+ }
+
+ private void updateGradientColors(){
+
+ int actualColor = getCurrentGradientColor();
+ int index = 0;
+ int[] colColors = new int[256];
+ for(int y=0; y<256; y++){
+ for(int x=0; x<256; x++ , index++){
+ if(y==0){
+ tGradientColors[index] = Color.rgb(255-(255-Color.red(actualColor))*x/255, 255-(255-Color.green(actualColor))*x/255, 255-(255-Color.blue(actualColor))*x/255);
+ colColors[x] = tGradientColors[index];
+ }
+ else{
+ tGradientColors[index] = Color.rgb((255-y)*Color.red(colColors[x])/255, (255-y)*Color.green(colColors[x])/255, (255-y)*Color.blue(colColors[x])/255);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas){
+ int translatedHue = 255 - (int)(tCurrentHue*255/360);
+ //Display HUE with bar lines
+
+ for(int x=0; x<256; x++){
+ //We display the color or a big white bar
+ if(translatedHue != x){
+ tPaint.setColor(tHueGradientColors[x]);
+ tPaint.setStrokeWidth(1);
+ }
+ else{
+ tPaint.setColor(Color.WHITE);
+ tPaint.setStrokeWidth(3);
+ }
+ canvas.drawLine(x+10, 0, x+10, 40, tPaint);
+ }
+
+ // Display Gradient Box
+ for(int x=0; x<256;x++){
+ int[] colors = new int[2];
+ colors[0] = tGradientColors[x];
+ colors[1] = Color.BLACK;
+ Shader shader = new LinearGradient(0,50,0,306,colors,null, Shader.TileMode.REPEAT);
+ tPaint.setShader(shader);
+ canvas.drawLine(x+10, 50, x+10, 306, tPaint);
+ }
+ tPaint.setShader(null);
+
+ //Display the circle around the currently selected color in the main field
+ if(tCurrentX !=0 && tCurrentY != 0){
+ tPaint.setStyle(Paint.Style.STROKE);
+ tPaint.setColor(Color.BLACK);
+ canvas.drawCircle(tCurrentX, tCurrentY, 10, tPaint);
+ }
+
+ //Draw a button
+
+ tPaint.setStyle(Paint.Style.FILL);
+ if(tQSelected){
+ tPaint.setColor(Color.WHITE);
+ canvas.drawCircle(138, 336, 30, tPaint);
+ }
+ tPaint.setColor(tCurrentColor);
+ canvas.drawCircle(138, 336, 20, tPaint);
+
+ }
+
+ @Override
+ protected void onMeasure(int width,int height){
+ setMeasuredDimension(276, 366);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event){
+ if(event.getAction() != MotionEvent.ACTION_DOWN && event.getAction() != MotionEvent.ACTION_MOVE && event.getAction() != MotionEvent.ACTION_UP) return true;
+ float x = event.getX();
+ float y = event.getY();
+
+ tQSelected=false;
+
+ // if in Hue Bar
+ if(x >10 && x <266 && y>0 && y<40){
+ //Update gradient
+ tCurrentHue = (255-x)*360/255;
+ updateGradientColors();
+
+ //Update current Selected Color
+ int nX = tCurrentX-10;
+ int nY = tCurrentY-60;
+ int index = 256 * (nY-1)+nX;
+
+ if(index>0 && index < tGradientColors.length)
+ tCurrentColor = tGradientColors[256*(nY-1)+nX];
+
+ invalidate(); //By invalidating we are forcing a redraw;
+ }
+
+ // If Main gradient
+
+ if ( x >10 && x< 266 && y>50 && y <306){
+ tCurrentX = (int) x;
+ tCurrentY = (int) y;
+ int nX = tCurrentX - 10;
+ int nY = tCurrentY - 60;
+ int index = 256*(nY-1)+nX;
+ if (index >0 && index < tGradientColors.length){
+ tCurrentColor = tGradientColors[index];
+
+ invalidate(); //By invalidating we are forcing a redraw;
+ }
+ }
+ if( x>118 && x<158 && y > 316 && y <356){
+ if(event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE){
+ tQSelected=true;
+ }
+ if(event.getAction() == MotionEvent.ACTION_UP){
+ tQSelected=false;
+ tListener.colorChange(tCurrentColor);
+ }
+ invalidate();
+ }
+
+
+
+ return true;
+ }
+
+
+ }
+
+ public ColorPickerDialog(Context context, OnColorChangeListener listener, int initialColor){
+ super(context);
+
+ tListener = listener;
+ tInitialColor = initialColor;
+ }
+
+ @Override
+ protected void onCreate( Bundle savedInstanceState){
+ super.onCreate(savedInstanceState);
+ OnColorChangeListener l = new OnColorChangeListener(){
+ public void colorChange(int color){
+ tListener.colorChange(color);
+ dismiss();
+ }
+ };
+
+ setContentView(new ColorPickerView(getContext(),l,tInitialColor));
+ }
+
+}
diff --git a/examples/osgAndroidExampleGLES1/src/osg/AndroidExample/EGLview.java b/examples/osgAndroidExampleGLES1/src/osg/AndroidExample/EGLview.java
new file mode 100644
index 000000000..44cecaf71
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/src/osg/AndroidExample/EGLview.java
@@ -0,0 +1,329 @@
+
+package osg.AndroidExample;
+/*
+ * Copyright (C) 2008 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.
+ */
+import android.app.Dialog;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.*;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.opengles.GL10;
+/**
+ * A simple GLSurfaceView sub-class that demonstrate how to perform
+ * OpenGL ES 1.0 rendering into a GL Surface. Note the following important
+ * details:
+ *
+ * - The class must use a custom context factory to enable 1.0 rendering.
+ * See ContextFactory class definition below.
+ *
+ * - The class must use a custom EGLConfigChooser to be able to select
+ * an EGLConfig that supports 1.0. This is done by providing a config
+ * specification to eglChooseConfig() that has the attribute
+ * EGL10.ELG_RENDERABLE_TYPE containing the EGL_OPENGL_ES_BIT flag
+ * set. See ConfigChooser class definition below.
+ *
+ * - The class must select the surface's format, then choose an EGLConfig
+ * that matches it exactly (with regards to red/green/blue/alpha channels
+ * bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
+ */
+public class EGLview extends GLSurfaceView {
+ private static String TAG = "EGLview";
+ private static final boolean DEBUG = false;
+
+ public EGLview(Context context) {
+ super(context);
+ init(false, 16, 8);
+ }
+ public EGLview(Context context, AttributeSet attrs) {
+ super(context,attrs);
+ init(false, 16, 8);
+ }
+
+
+ public EGLview(Context context, boolean translucent, int depth, int stencil) {
+ super(context);
+ init(translucent, depth, stencil);
+ }
+
+ private void init(boolean translucent, int depth, int stencil) {
+
+ /* By default, GLSurfaceView() creates a RGB_565 opaque surface.
+ * If we want a translucent one, we should change the surface's
+ * format here, using PixelFormat.TRANSLUCENT for GL Surfaces
+ * is interpreted as any 32-bit surface with alpha by SurfaceFlinger.
+ */
+ if (translucent) {
+ this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
+ }
+
+ /* Setup the context factory for 1.0 rendering.
+ * See ContextFactory class definition below
+ */
+ setEGLContextFactory(new ContextFactory());
+
+ /* We need to choose an EGLConfig that matches the format of
+ * our surface exactly. This is going to be done in our
+ * custom config chooser. See ConfigChooser class definition
+ * below.
+ */
+ setEGLConfigChooser( translucent ?
+ new ConfigChooser(8, 8, 8, 8, depth, stencil) :
+ new ConfigChooser(5, 6, 5, 0, depth, stencil) );
+
+ /* Set the renderer responsible for frame rendering */
+ setRenderer(new Renderer());
+ }
+
+ private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
+ private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+ public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
+ Log.w(TAG, "creating OpenGL ES 1 context");
+ checkEglError("Before eglCreateContext", egl);
+ int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 1, EGL10.EGL_NONE };
+ EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
+ checkEglError("After eglCreateContext", egl);
+ return context;
+ }
+
+ public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
+ egl.eglDestroyContext(display, context);
+ }
+ }
+
+ private static void checkEglError(String prompt, EGL10 egl) {
+ int error;
+ while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
+ Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
+ }
+ }
+
+ private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
+
+ public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) {
+ mRedSize = r;
+ mGreenSize = g;
+ mBlueSize = b;
+ mAlphaSize = a;
+ mDepthSize = depth;
+ mStencilSize = stencil;
+ }
+
+ /* This EGL config specification is used to specify 1.x rendering.
+ * We use a minimum size of 4 bits for red/green/blue, but will
+ * perform actual matching in chooseConfig() below.
+ */
+ private static int EGL_OPENGL_ES_BIT = 1;
+ private static int[] s_configAttribs2 =
+ {
+ EGL10.EGL_RED_SIZE, 4,
+ EGL10.EGL_GREEN_SIZE, 4,
+ EGL10.EGL_BLUE_SIZE, 4,
+ EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
+ EGL10.EGL_NONE
+ };
+
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
+
+ /* Get the number of minimally matching EGL configurations
+ */
+ int[] num_config = new int[1];
+ egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config);
+
+ int numConfigs = num_config[0];
+
+ if (numConfigs <= 0) {
+ throw new IllegalArgumentException("No configs match configSpec");
+ }
+
+ /* Allocate then read the array of minimally matching EGL configs
+ */
+ EGLConfig[] configs = new EGLConfig[numConfigs];
+ egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);
+
+ if (DEBUG) {
+ printConfigs(egl, display, configs);
+ }
+ /* Now return the "best" one
+ */
+ return chooseConfig(egl, display, configs);
+ }
+
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
+ EGLConfig[] configs) {
+ for(EGLConfig config : configs) {
+ int d = findConfigAttrib(egl, display, config,
+ EGL10.EGL_DEPTH_SIZE, 0);
+ int s = findConfigAttrib(egl, display, config,
+ EGL10.EGL_STENCIL_SIZE, 0);
+
+ // We need at least mDepthSize and mStencilSize bits
+ if (d < mDepthSize || s < mStencilSize)
+ continue;
+
+ // We want an *exact* match for red/green/blue/alpha
+ int r = findConfigAttrib(egl, display, config,
+ EGL10.EGL_RED_SIZE, 0);
+ int g = findConfigAttrib(egl, display, config,
+ EGL10.EGL_GREEN_SIZE, 0);
+ int b = findConfigAttrib(egl, display, config,
+ EGL10.EGL_BLUE_SIZE, 0);
+ int a = findConfigAttrib(egl, display, config,
+ EGL10.EGL_ALPHA_SIZE, 0);
+
+ if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize)
+ return config;
+ }
+ return null;
+ }
+
+ private int findConfigAttrib(EGL10 egl, EGLDisplay display,
+ EGLConfig config, int attribute, int defaultValue) {
+
+ if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
+ return mValue[0];
+ }
+ return defaultValue;
+ }
+
+ private void printConfigs(EGL10 egl, EGLDisplay display,
+ EGLConfig[] configs) {
+ int numConfigs = configs.length;
+ Log.w(TAG, String.format("%d configurations", numConfigs));
+ for (int i = 0; i < numConfigs; i++) {
+ Log.w(TAG, String.format("Configuration %d:\n", i));
+ printConfig(egl, display, configs[i]);
+ }
+ }
+
+ private void printConfig(EGL10 egl, EGLDisplay display,
+ EGLConfig config) {
+ int[] attributes = {
+ EGL10.EGL_BUFFER_SIZE,
+ EGL10.EGL_ALPHA_SIZE,
+ EGL10.EGL_BLUE_SIZE,
+ EGL10.EGL_GREEN_SIZE,
+ EGL10.EGL_RED_SIZE,
+ EGL10.EGL_DEPTH_SIZE,
+ EGL10.EGL_STENCIL_SIZE,
+ EGL10.EGL_CONFIG_CAVEAT,
+ EGL10.EGL_CONFIG_ID,
+ EGL10.EGL_LEVEL,
+ EGL10.EGL_MAX_PBUFFER_HEIGHT,
+ EGL10.EGL_MAX_PBUFFER_PIXELS,
+ EGL10.EGL_MAX_PBUFFER_WIDTH,
+ EGL10.EGL_NATIVE_RENDERABLE,
+ EGL10.EGL_NATIVE_VISUAL_ID,
+ EGL10.EGL_NATIVE_VISUAL_TYPE,
+ 0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
+ EGL10.EGL_SAMPLES,
+ EGL10.EGL_SAMPLE_BUFFERS,
+ EGL10.EGL_SURFACE_TYPE,
+ EGL10.EGL_TRANSPARENT_TYPE,
+ EGL10.EGL_TRANSPARENT_RED_VALUE,
+ EGL10.EGL_TRANSPARENT_GREEN_VALUE,
+ EGL10.EGL_TRANSPARENT_BLUE_VALUE,
+ 0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB,
+ 0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA,
+ 0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL,
+ 0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL,
+ EGL10.EGL_LUMINANCE_SIZE,
+ EGL10.EGL_ALPHA_MASK_SIZE,
+ EGL10.EGL_COLOR_BUFFER_TYPE,
+ EGL10.EGL_RENDERABLE_TYPE,
+ 0x3042 // EGL10.EGL_CONFORMANT
+ };
+ String[] names = {
+ "EGL_BUFFER_SIZE",
+ "EGL_ALPHA_SIZE",
+ "EGL_BLUE_SIZE",
+ "EGL_GREEN_SIZE",
+ "EGL_RED_SIZE",
+ "EGL_DEPTH_SIZE",
+ "EGL_STENCIL_SIZE",
+ "EGL_CONFIG_CAVEAT",
+ "EGL_CONFIG_ID",
+ "EGL_LEVEL",
+ "EGL_MAX_PBUFFER_HEIGHT",
+ "EGL_MAX_PBUFFER_PIXELS",
+ "EGL_MAX_PBUFFER_WIDTH",
+ "EGL_NATIVE_RENDERABLE",
+ "EGL_NATIVE_VISUAL_ID",
+ "EGL_NATIVE_VISUAL_TYPE",
+ "EGL_PRESERVED_RESOURCES",
+ "EGL_SAMPLES",
+ "EGL_SAMPLE_BUFFERS",
+ "EGL_SURFACE_TYPE",
+ "EGL_TRANSPARENT_TYPE",
+ "EGL_TRANSPARENT_RED_VALUE",
+ "EGL_TRANSPARENT_GREEN_VALUE",
+ "EGL_TRANSPARENT_BLUE_VALUE",
+ "EGL_BIND_TO_TEXTURE_RGB",
+ "EGL_BIND_TO_TEXTURE_RGBA",
+ "EGL_MIN_SWAP_INTERVAL",
+ "EGL_MAX_SWAP_INTERVAL",
+ "EGL_LUMINANCE_SIZE",
+ "EGL_ALPHA_MASK_SIZE",
+ "EGL_COLOR_BUFFER_TYPE",
+ "EGL_RENDERABLE_TYPE",
+ "EGL_CONFORMANT"
+ };
+ int[] value = new int[1];
+ for (int i = 0; i < attributes.length; i++) {
+ int attribute = attributes[i];
+ String name = names[i];
+ if ( egl.eglGetConfigAttrib(display, config, attribute, value)) {
+ Log.w(TAG, String.format(" %s: %d\n", name, value[0]));
+ } else {
+ // Log.w(TAG, String.format(" %s: failed\n", name));
+ while (egl.eglGetError() != EGL10.EGL_SUCCESS);
+ }
+ }
+ }
+
+ // Subclasses can adjust these values:
+ protected int mRedSize;
+ protected int mGreenSize;
+ protected int mBlueSize;
+ protected int mAlphaSize;
+ protected int mDepthSize;
+ protected int mStencilSize;
+ private int[] mValue = new int[1];
+ }
+
+ private static class Renderer implements GLSurfaceView.Renderer {
+ public void onDrawFrame(GL10 gl) {
+ osgNativeLib.step();
+ }
+
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ osgNativeLib.init(width, height);
+ }
+
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ // Do nothing
+ gl.glEnable(GL10.GL_DEPTH_TEST);
+ }
+ }
+
+}
+
diff --git a/examples/osgAndroidExampleGLES1/src/osg/AndroidExample/osgNativeLib.java b/examples/osgAndroidExampleGLES1/src/osg/AndroidExample/osgNativeLib.java
new file mode 100644
index 000000000..52e946a4e
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/src/osg/AndroidExample/osgNativeLib.java
@@ -0,0 +1,28 @@
+package osg.AndroidExample;
+
+public class osgNativeLib {
+
+ static {
+ System.loadLibrary("osgNativeLib");
+ }
+
+ /**
+ * @param width the current view width
+ * @param height the current view height
+ */
+ public static native void init(int width, int height);
+ public static native void step();
+ public static native void clearContents();
+ public static native void mouseButtonPressEvent(float x,float y, int button);
+ public static native void mouseButtonReleaseEvent(float x,float y, int button);
+ public static native void mouseMoveEvent(float x,float y);
+ public static native void keyboardDown(int key);
+ public static native void keyboardUp(int key);
+ public static native void setClearColor(int red,int green, int blue);
+ public static native int[] getClearColor();
+ public static native void loadObject(String address);
+ public static native void loadObject(String address,String name);
+ public static native void unLoadObject(int number);
+ public static native String[] getObjectNames();
+
+}
diff --git a/examples/osgAndroidExampleGLES1/src/osg/AndroidExample/osgViewer.java b/examples/osgAndroidExampleGLES1/src/osg/AndroidExample/osgViewer.java
new file mode 100644
index 000000000..d3cfdb962
--- /dev/null
+++ b/examples/osgAndroidExampleGLES1/src/osg/AndroidExample/osgViewer.java
@@ -0,0 +1,417 @@
+package osg.AndroidExample;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.PointF;
+import android.os.Bundle;
+import android.util.FloatMath;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.WindowManager;
+import android.view.View.OnClickListener;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.widget.ImageButton;
+
+import java.io.File;
+
+public class osgViewer extends Activity implements View.OnTouchListener, View.OnKeyListener, ColorPickerDialog.OnColorChangeListener {
+ enum moveTypes { NONE , DRAG, MDRAG, ZOOM ,ACTUALIZE}
+ enum navType { PRINCIPAL , SECONDARY }
+ enum lightType { ON , OFF }
+
+ moveTypes mode=moveTypes.NONE;
+ navType navMode = navType.PRINCIPAL;
+ lightType lightMode = lightType.ON;
+
+ PointF oneFingerOrigin = new PointF(0,0);
+ long timeOneFinger=0;
+ PointF twoFingerOrigin = new PointF(0,0);
+ long timeTwoFinger=0;
+ float distanceOrigin;
+
+ int backgroundColor;
+
+ private static final String TAG = "OSG Activity";
+ //Ui elements
+ EGLview mView;
+ Button uiCenterViewButton;
+ Button uiNavigationChangeButton;
+ ImageButton uiNavigationLeft;
+ ImageButton uiNavigationRight;
+ Button uiLightChangeButton;
+
+ //Toasts
+ Toast msgUiNavPrincipal;
+ Toast msgUiNavSecondary;
+ Toast msgUiLightOn;
+ Toast msgUiLightOff;
+
+ //Dialogs
+ AlertDialog removeLayerDialog;
+ AlertDialog loadLayerAddress;
+
+ //Main Android Activity life cycle
+ @Override protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.ui_layout_gles);
+ //Obtain every Ui element
+ mView= (EGLview) findViewById(R.id.surfaceGLES);
+ mView.setOnTouchListener(this);
+ mView.setOnKeyListener(this);
+
+ uiCenterViewButton = (Button) findViewById(R.id.uiButtonCenter);
+ uiCenterViewButton.setOnClickListener(uiListenerCenterView);
+ uiNavigationChangeButton = (Button) findViewById(R.id.uiButtonChangeNavigation);
+ uiNavigationChangeButton.setOnClickListener(uiListenerChangeNavigation);
+ uiLightChangeButton = (Button) findViewById(R.id.uiButtonLight);
+ uiLightChangeButton.setOnClickListener(uiListenerChangeLight);
+
+ //Creating Toasts
+ msgUiNavPrincipal = Toast.makeText(getApplicationContext(), R.string.uiToastNavPrincipal, Toast.LENGTH_SHORT);
+ msgUiNavSecondary = Toast.makeText(getApplicationContext(), R.string.uiToastNavSecond, Toast.LENGTH_SHORT);
+ msgUiLightOn = Toast.makeText(getApplicationContext(), R.string.uiToastLightOn, Toast.LENGTH_SHORT);
+ msgUiLightOff = Toast.makeText(getApplicationContext(), R.string.uiToastLightOff, Toast.LENGTH_SHORT);
+
+ //Creating Dialogs
+
+ LayoutInflater factory = LayoutInflater.from(getApplicationContext());
+ final View textEntryView = factory.inflate(R.layout.dialog_text_entry, null);
+ AlertDialog.Builder loadLayerDialogBuilder = new AlertDialog.Builder(this);
+ loadLayerDialogBuilder.setIcon(R.drawable.web_browser);
+ loadLayerDialogBuilder.setTitle(R.string.uiDialogTextAddress);
+ loadLayerDialogBuilder.setView(textEntryView);
+ loadLayerDialogBuilder.setPositiveButton(R.string.uiDialogOk, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // TODO Auto-generated method stub
+ EditText address;
+ address = (EditText) textEntryView.findViewById(R.id.uiEditTextInput);
+ osgNativeLib.loadObject(address.getText().toString());
+ }
+ });
+ loadLayerDialogBuilder.setNegativeButton(R.string.uiDialogCancel, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // TODO Auto-generated method stub
+
+ }
+ });
+
+ loadLayerAddress = loadLayerDialogBuilder.create();
+ }
+ @Override protected void onPause() {
+ super.onPause();
+ mView.onPause();
+ }
+ @Override protected void onResume() {
+ super.onResume();
+ mView.onResume();
+ }
+
+ //Main view event processing
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+
+ return true;
+ }
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event){
+ //DO NOTHING this will render useless every menu key except Home
+ int keyChar= event.getUnicodeChar();
+ osgNativeLib.keyboardDown(keyChar);
+ return true;
+ }
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event){
+ switch (keyCode){
+ case KeyEvent.KEYCODE_BACK:
+ super.onDestroy();
+ this.finish();
+ break;
+ case KeyEvent.KEYCODE_SEARCH:
+ break;
+ case KeyEvent.KEYCODE_MENU:
+ this.openOptionsMenu();
+ break;
+ default:
+ int keyChar= event.getUnicodeChar();
+ osgNativeLib.keyboardUp(keyChar);
+ }
+
+ return true;
+ }
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+
+ //dumpEvent(event);
+
+ long time_arrival = event.getEventTime();
+ int n_points = event.getPointerCount();
+ int action = event.getAction() & MotionEvent.ACTION_MASK;
+
+ switch(n_points){
+ case 1:
+ switch(action){
+ case MotionEvent.ACTION_DOWN:
+ mode = moveTypes.DRAG;
+
+ osgNativeLib.mouseMoveEvent(event.getX(0), event.getY(0));
+ if(navMode==navType.PRINCIPAL)
+ osgNativeLib.mouseButtonPressEvent(event.getX(0), event.getY(0), 2);
+ else
+ osgNativeLib.mouseButtonPressEvent(event.getX(0), event.getY(0), 1);
+
+ oneFingerOrigin.x=event.getX(0);
+ oneFingerOrigin.y=event.getY(0);
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ switch(mode){
+ case DRAG:
+ osgNativeLib.mouseMoveEvent(event.getX(0), event.getY(0));
+ if(navMode==navType.PRINCIPAL)
+ osgNativeLib.mouseButtonReleaseEvent(event.getX(0), event.getY(0), 2);
+ else
+ osgNativeLib.mouseButtonReleaseEvent(event.getX(0), event.getY(0), 1);
+ break;
+ default :
+ Log.e(TAG,"There has been an anomaly in touch input 1point/action");
+ }
+ mode = moveTypes.NONE;
+ break;
+ case MotionEvent.ACTION_MOVE:
+
+ osgNativeLib.mouseMoveEvent(event.getX(0), event.getY(0));
+
+ oneFingerOrigin.x=event.getX(0);
+ oneFingerOrigin.y=event.getY(0);
+
+ break;
+ case MotionEvent.ACTION_UP:
+ switch(mode){
+ case DRAG:
+ if(navMode==navType.PRINCIPAL)
+ osgNativeLib.mouseButtonReleaseEvent(event.getX(0), event.getY(0), 2);
+ else
+ osgNativeLib.mouseButtonReleaseEvent(event.getX(0), event.getY(0), 1);
+ break;
+ default :
+ Log.e(TAG,"There has been an anomaly in touch input 1 point/action");
+ }
+ mode = moveTypes.NONE;
+ break;
+ default :
+ Log.e(TAG,"1 point Action not captured");
+ }
+ break;
+ case 2:
+ switch (action){
+ case MotionEvent.ACTION_POINTER_DOWN:
+ //Free previous Action
+ switch(mode){
+ case DRAG:
+ if(navMode==navType.PRINCIPAL)
+ osgNativeLib.mouseButtonReleaseEvent(event.getX(0), event.getY(0), 2);
+ else
+ osgNativeLib.mouseButtonReleaseEvent(event.getX(0), event.getY(0), 1);
+ break;
+ }
+ mode = moveTypes.ZOOM;
+ distanceOrigin = sqrDistance(event);
+ twoFingerOrigin.x=event.getX(1);
+ twoFingerOrigin.y=event.getY(1);
+ oneFingerOrigin.x=event.getX(0);
+ oneFingerOrigin.y=event.getY(0);
+
+ osgNativeLib.mouseMoveEvent(oneFingerOrigin.x,oneFingerOrigin.y);
+ osgNativeLib.mouseButtonPressEvent(oneFingerOrigin.x,oneFingerOrigin.y, 3);
+ osgNativeLib.mouseMoveEvent(oneFingerOrigin.x,oneFingerOrigin.y);
+
+ case MotionEvent.ACTION_MOVE:
+ float distance = sqrDistance(event);
+ float result = distance-distanceOrigin;
+ distanceOrigin=distance;
+
+ if(result>1||result<-1){
+ oneFingerOrigin.y=oneFingerOrigin.y+result;
+ osgNativeLib.mouseMoveEvent(oneFingerOrigin.x,oneFingerOrigin.y);
+ }
+
+ break;
+ case MotionEvent.ACTION_POINTER_UP:
+ mode =moveTypes.NONE;
+ osgNativeLib.mouseButtonReleaseEvent(oneFingerOrigin.x,oneFingerOrigin.y, 3);
+ break;
+ case MotionEvent.ACTION_UP:
+ mode =moveTypes.NONE;
+ osgNativeLib.mouseButtonReleaseEvent(oneFingerOrigin.x,oneFingerOrigin.y, 3);
+ break;
+ default :
+ Log.e(TAG,"2 point Action not captured");
+ }
+ break;
+ }
+
+ return true;
+ }
+
+ //Ui Listeners
+ OnClickListener uiListenerCenterView = new OnClickListener() {
+ public void onClick(View v) {
+ //Log.d(TAG, "Center View");
+ osgNativeLib.keyboardDown(32);
+ osgNativeLib.keyboardUp(32);
+ }
+ };
+ OnClickListener uiListenerChangeNavigation = new OnClickListener() {
+ public void onClick(View v) {
+ //Log.d(TAG, "Change Navigation");
+ if(navMode==navType.PRINCIPAL){
+ msgUiNavSecondary.show();
+ navMode=navType.SECONDARY;
+ }
+ else{
+ msgUiNavPrincipal.show();
+ navMode=navType.PRINCIPAL;
+ }
+ }
+ };
+ OnClickListener uiListenerChangeLight = new OnClickListener() {
+ public void onClick(View v) {
+ //Log.d(TAG, "Change Light");
+ if(lightMode==lightType.ON){
+ msgUiLightOff.show();
+ lightMode=lightType.OFF;
+ osgNativeLib.keyboardDown(108);
+ osgNativeLib.keyboardUp(108);
+ }
+ else{
+ msgUiLightOn.show();
+ lightMode=lightType.ON;
+ osgNativeLib.keyboardDown(108);
+ osgNativeLib.keyboardUp(108);
+ }
+ }
+ };
+
+ //Menu
+
+ @Override
+ public void colorChange(int color) {
+ // TODO Auto-generated method stub
+ // Do nothing
+ int red = Color.red(color);
+ int green = Color.green(color);
+ int blue = Color.blue(color);
+ //Log.d(TAG,"BACK color "+red+" "+green+" "+blue+" ");
+ osgNativeLib.setClearColor(red,green,blue);
+ }
+
+ //Android Life Cycle Menu
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.appmenu, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle item selection
+ switch (item.getItemId()) {
+ case R.id.menuLoadObject:
+ Log.d(TAG,"Load Object");
+ loadLayerAddress.show();
+ return true;
+ case R.id.menuCleanScene:
+ Log.d(TAG,"Clean Scene");
+ osgNativeLib.clearContents();
+ return true;
+ case R.id.menuDeleteObject:
+ Log.d(TAG,"Delete a object");
+ String vNames[] = osgNativeLib.getObjectNames();
+
+ //Remove Layer Dialog
+ AlertDialog.Builder removeLayerDialogBuilder = new AlertDialog.Builder(this);
+ removeLayerDialogBuilder.setTitle(R.string.uiDialogTextChoseRemove);
+ removeLayerDialogBuilder.setItems(vNames, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int witch) {
+ // TODO Auto-generated method stub
+ osgNativeLib.unLoadObject(witch);
+ }
+ });
+ removeLayerDialog = removeLayerDialogBuilder.create();
+
+ if(vNames.length > 0)
+ removeLayerDialog.show();
+
+ return true;
+ case R.id.menuChangeBackground:
+ Log.d(TAG,"Change background color");
+ int[] test = new int [3];
+ test = osgNativeLib.getClearColor();
+ backgroundColor = Color.rgb(test[0], test[1], test[2]);
+
+ ColorPickerDialog colorDialog;
+ new ColorPickerDialog(this, this, backgroundColor).show();
+ return true;
+ case R.id.menuShowKeyboard:
+ Log.d(TAG,"Keyboard");
+ InputMethodManager mgr= (InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
+ mgr.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ //Utilities
+ /** Show an event in the LogCat view, for debugging */
+ private void dumpEvent(MotionEvent event) {
+ String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE",
+ "POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
+ StringBuilder sb = new StringBuilder();
+ int action = event.getAction();
+ int actionCode = action & MotionEvent.ACTION_MASK;
+ sb.append("event ACTION_").append(names[actionCode]);
+ if (actionCode == MotionEvent.ACTION_POINTER_DOWN
+ || actionCode == MotionEvent.ACTION_POINTER_UP) {
+ sb.append("(pid ").append(
+ action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
+ sb.append(")");
+ }
+ sb.append("[");
+ for (int i = 0; i < event.getPointerCount(); i++) {
+ sb.append("#").append(i);
+ sb.append("(pid ").append(event.getPointerId(i));
+ sb.append(")=").append((int) event.getX(i));
+ sb.append(",").append((int) event.getY(i));
+ if (i + 1 < event.getPointerCount())
+ sb.append(";");
+ }
+ sb.append("]");
+ //Log.d(TAG, sb.toString());
+ }
+ private float sqrDistance(MotionEvent event) {
+ float x = event.getX(0) - event.getX(1);
+ float y = event.getY(0) - event.getY(1);
+ return (float)(Math.sqrt(x * x + y * y));
+ }
+
+}
\ No newline at end of file
diff --git a/examples/osgAndroidExampleGLES2/AndroidManifest.xml b/examples/osgAndroidExampleGLES2/AndroidManifest.xml
new file mode 100644
index 000000000..7c6c68209
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/AndroidManifest.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/osgAndroidExampleGLES2/default.properties b/examples/osgAndroidExampleGLES2/default.properties
new file mode 100644
index 000000000..e2e8061f2
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/default.properties
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-8
diff --git a/examples/osgAndroidExampleGLES2/jni/Android.mk b/examples/osgAndroidExampleGLES2/jni/Android.mk
new file mode 100644
index 000000000..582a47f5b
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/jni/Android.mk
@@ -0,0 +1,67 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := osgNativeLib
+### Main Install dir
+OSG_ANDROID_DIR := < type your install directory >
+LIBDIR := $(OSG_ANDROID_DIR)/obj/local/armeabi
+
+ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
+ LOCAL_ARM_NEON := true
+ LIBDIR := $(OSG_ANDROID_DIR)/obj/local/armeabi-v7a
+endif
+
+### Add all source file names to be included in lib separated by a whitespace
+
+LOCAL_C_INCLUDES:= $(OSG_ANDROID_DIR)/include
+LOCAL_CFLAGS := -Werror -fno-short-enums
+LOCAL_CPPFLAGS := -DOSG_LIBRARY_STATIC
+
+LOCAL_LDLIBS := -llog -lGLESv2 -lz
+LOCAL_SRC_FILES := osgNativeLib.cpp OsgMainApp.cpp OsgAndroidNotifyHandler.cpp
+LOCAL_LDFLAGS := -L $(LIBDIR) \
+-losgdb_dds \
+-losgdb_openflight \
+-losgdb_tga \
+-losgdb_rgb \
+-losgdb_osgterrain \
+-losgdb_osg \
+-losgdb_ive \
+-losgdb_deprecated_osgviewer \
+-losgdb_deprecated_osgvolume \
+-losgdb_deprecated_osgtext \
+-losgdb_deprecated_osgterrain \
+-losgdb_deprecated_osgsim \
+-losgdb_deprecated_osgshadow \
+-losgdb_deprecated_osgparticle \
+-losgdb_deprecated_osgfx \
+-losgdb_deprecated_osganimation \
+-losgdb_deprecated_osg \
+-losgdb_serializers_osgvolume \
+-losgdb_serializers_osgtext \
+-losgdb_serializers_osgterrain \
+-losgdb_serializers_osgsim \
+-losgdb_serializers_osgshadow \
+-losgdb_serializers_osgparticle \
+-losgdb_serializers_osgmanipulator \
+-losgdb_serializers_osgfx \
+-losgdb_serializers_osganimation \
+-losgdb_serializers_osg \
+-losgViewer \
+-losgVolume \
+-losgTerrain \
+-losgText \
+-losgShadow \
+-losgSim \
+-losgParticle \
+-losgManipulator \
+-losgGA \
+-losgFX \
+-losgDB \
+-losgAnimation \
+-losgUtil \
+-losg \
+-lOpenThreads
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/examples/osgAndroidExampleGLES2/jni/Application.mk b/examples/osgAndroidExampleGLES2/jni/Application.mk
new file mode 100644
index 000000000..0387c4daa
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/jni/Application.mk
@@ -0,0 +1,11 @@
+#ANDROID APPLICATION MAKEFILE
+APP_BUILD_SCRIPT := $(call my-dir)/Android.mk
+#APP_PROJECT_PATH := $(call my-dir)
+
+APP_OPTIM := release
+
+APP_PLATFORM := android-7
+APP_STL := gnustl_static
+APP_CPPFLAGS := -fexceptions -frtti
+APP_ABI := armeabi armeabi-v7a
+APP_MODULES := osgNativeLib
diff --git a/examples/osgAndroidExampleGLES2/jni/OsgAndroidNotifyHandler.cpp b/examples/osgAndroidExampleGLES2/jni/OsgAndroidNotifyHandler.cpp
new file mode 100644
index 000000000..2e4f38c15
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/jni/OsgAndroidNotifyHandler.cpp
@@ -0,0 +1,38 @@
+/*
+ * OsgAndroidNotifyHandler.cpp
+ *
+ * Created on: 31/05/2011
+ * Author: Jorge Izquierdo Ciges
+ */
+
+#include "OsgAndroidNotifyHandler.hpp"
+#include
+
+void OsgAndroidNotifyHandler::setTag(std::string tag){
+ _tag = tag;
+}
+void OsgAndroidNotifyHandler::notify(osg::NotifySeverity severity, const char *message){
+
+ switch ( severity ) {
+ case osg::DEBUG_FP:
+ __android_log_write(ANDROID_LOG_VERBOSE,_tag.c_str(),message);
+ break;
+ case osg::DEBUG_INFO:
+ __android_log_write(ANDROID_LOG_DEBUG,_tag.c_str(),message);
+ break;
+ case osg::NOTICE:
+ case osg::INFO:
+ __android_log_write(ANDROID_LOG_INFO,_tag.c_str(),message);
+ break;
+ case osg::WARN:
+ __android_log_write(ANDROID_LOG_WARN,_tag.c_str(),message);
+ break;
+ case osg::FATAL:
+ case osg::ALWAYS:
+ __android_log_write(ANDROID_LOG_ERROR,_tag.c_str(),message);
+ break;
+ default:
+ __android_log_write(ANDROID_LOG_DEBUG,_tag.c_str(),message);
+ break;
+ }
+}
diff --git a/examples/osgAndroidExampleGLES2/jni/OsgAndroidNotifyHandler.hpp b/examples/osgAndroidExampleGLES2/jni/OsgAndroidNotifyHandler.hpp
new file mode 100644
index 000000000..114a369aa
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/jni/OsgAndroidNotifyHandler.hpp
@@ -0,0 +1,26 @@
+/*
+ * OsgAndroidNotifyHandler.hpp
+ *
+ * Created on: 31/05/2011
+ * Author: Jorge Izquierdo Ciges
+ */
+
+#ifndef OSGANDROIDNOTIFYHANDLER_HPP_
+#define OSGANDROIDNOTIFYHANDLER_HPP_
+
+#include
+
+#include
+
+#include
+
+class OSG_EXPORT OsgAndroidNotifyHandler : public osg::NotifyHandler
+{
+private:
+ std::string _tag;
+public:
+ void setTag(std::string tag);
+ void notify(osg::NotifySeverity severity, const char *message);
+};
+
+#endif /* OSGANDROIDNOTIFYHANDLER_HPP_ */
diff --git a/examples/osgAndroidExampleGLES2/jni/OsgMainApp.cpp b/examples/osgAndroidExampleGLES2/jni/OsgMainApp.cpp
new file mode 100644
index 000000000..45bdec4d6
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/jni/OsgMainApp.cpp
@@ -0,0 +1,217 @@
+#include "OsgMainApp.hpp"
+
+
+OsgMainApp::OsgMainApp(){
+
+ _lodScale = 1.0f;
+ _prevFrame = 0;
+
+ _initialized = false;
+ _clean_scene = false;
+
+}
+OsgMainApp::~OsgMainApp(){
+
+}
+void OsgMainApp::loadModels(){
+ if(_vModelsToLoad.size()==0) return;
+
+ osg::notify(osg::ALWAYS)<<"There are "<<_vModelsToLoad.size()<<" models to load"< loadedModel = osgDB::readNodeFile(newModel.filename);
+ if (loadedModel == 0) {
+ osg::notify(osg::ALWAYS)<<"Model not loaded"<setName(newModel.name);
+
+ osg::Shader * vshader = new osg::Shader(osg::Shader::VERTEX, gVertexShader );
+ osg::Shader * fshader = new osg::Shader(osg::Shader::FRAGMENT, gFragmentShader );
+
+ osg::Program * prog = new osg::Program;
+ prog->addShader ( vshader );
+ prog->addShader ( fshader );
+
+ loadedModel->getOrCreateStateSet()->setAttribute ( prog );
+
+ _root->addChild(loadedModel);
+ }
+ }
+
+ osgViewer::Viewer::Windows windows;
+ _viewer->getWindows(windows);
+ for(osgViewer::Viewer::Windows::iterator itr = windows.begin();itr != windows.end();++itr)
+ {
+ (*itr)->getState()->setUseModelViewAndProjectionUniforms(true);
+ (*itr)->getState()->setUseVertexAttributeAliasing(true);
+ }
+
+ _viewer->setSceneData(NULL);
+ _viewer->setSceneData(_root.get());
+ _manipulator->getNode();
+ _viewer->home();
+
+ _viewer->getDatabasePager()->clear();
+ _viewer->getDatabasePager()->registerPagedLODs(_root.get());
+ _viewer->getDatabasePager()->setUpThreads(3, 1);
+ _viewer->getDatabasePager()->setTargetMaximumNumberOfPageLOD(2);
+ _viewer->getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true, true);
+
+ _vModelsToLoad.clear();
+
+}
+void OsgMainApp::deleteModels(){
+ if(_vModelsToDelete.size()==0) return;
+
+ osg::notify(osg::ALWAYS)<<"There are "<<_vModelsToDelete.size()<<" models to delete"<getNumChildren(); j>0; j--){
+ osg::ref_ptr children = _root->getChild(j-1);
+ if(children->getName() == modelToDelete.name){
+ _root->removeChild(children);
+ }
+ }
+
+ }
+
+ _vModelsToDelete.clear();
+ osg::notify(osg::ALWAYS)<<"finished"<setTag("Osg Viewer");
+ osg::setNotifyHandler(_notifyHandler);
+
+ osg::notify(osg::ALWAYS)<<"Testing"<setUpViewerAsEmbeddedInWindow(x, y, width, height);
+ _viewer->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
+
+ _root = new osg::Group();
+
+ _viewer->realize();
+
+ _viewer->addEventHandler(new osgViewer::StatsHandler);
+ _viewer->addEventHandler(new osgGA::StateSetManipulator(_viewer->getCamera()->getOrCreateStateSet()));
+ _viewer->addEventHandler(new osgViewer::ThreadingHandler);
+ _viewer->addEventHandler(new osgViewer::LODScaleHandler);
+
+ _manipulator = new osgGA::KeySwitchMatrixManipulator;
+
+ _manipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
+ _manipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
+ _manipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
+ _manipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
+ _manipulator->addMatrixManipulator( '5', "Orbit", new osgGA::OrbitManipulator() );
+ _manipulator->addMatrixManipulator( '6', "FirstPerson", new osgGA::FirstPersonManipulator() );
+ _manipulator->addMatrixManipulator( '7', "Spherical", new osgGA::SphericalManipulator() );
+
+ _viewer->setCameraManipulator( _manipulator.get() );
+
+ _viewer->getViewerStats()->collectStats("scene", true);
+
+ _initialized = true;
+
+}
+//Draw
+void OsgMainApp::draw(){
+ //Every load o remove has to be done before any drawing
+ loadModels();
+ deleteModels();
+
+ _viewer->frame();
+}
+//Events
+void OsgMainApp::mouseButtonPressEvent(float x,float y,int button){
+ _viewer->getEventQueue()->mouseButtonPress(x, y, button);
+}
+void OsgMainApp::mouseButtonReleaseEvent(float x,float y,int button){
+ _viewer->getEventQueue()->mouseButtonRelease(x, y, button);
+}
+void OsgMainApp::mouseMoveEvent(float x,float y){
+ _viewer->getEventQueue()->mouseMotion(x, y);
+}
+void OsgMainApp::keyboardDown(int key){
+ _viewer->getEventQueue()->keyPress(key);
+}
+void OsgMainApp::keyboardUp(int key){
+ _viewer->getEventQueue()->keyRelease(key);
+}
+//Loading and unloading
+void OsgMainApp::loadObject(std::string filePath){
+ Model newModel;
+ newModel.filename = filePath;
+ newModel.name = filePath;
+
+ int num = 0;
+ for(unsigned int i=0;i<_vModels.size();i++){
+ if(_vModels[i].name==newModel.name)
+ return;
+ }
+
+ _vModelsToLoad.push_back(newModel);
+
+}
+void OsgMainApp::loadObject(std::string name,std::string filePath){
+
+ Model newModel;
+ newModel.filename = filePath;
+ newModel.name = name;
+
+ for(unsigned int i=0;i<_vModels.size();i++){
+ if(_vModels[i].name==newModel.name){
+ osg::notify(osg::ALWAYS)<<"Name already used"<getCamera()->setClearColor(color);
+}
+osg::Vec4f OsgMainApp::getClearColor(){
+ osg::notify(osg::ALWAYS)<<"Getting Clear Color"<getCamera()->getClearColor();
+}
diff --git a/examples/osgAndroidExampleGLES2/jni/OsgMainApp.hpp b/examples/osgAndroidExampleGLES2/jni/OsgMainApp.hpp
new file mode 100644
index 000000000..cc3b02b89
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/jni/OsgMainApp.hpp
@@ -0,0 +1,182 @@
+/*
+ * OsgMainApp.hpp
+ *
+ * Created on: 29/05/2011
+ * Author: Jorge Izquierdo Ciges
+ */
+
+#ifndef OSGMAINAPP_HPP_
+#define OSGMAINAPP_HPP_
+
+//Android log
+#include
+#include
+#include
+#include
+
+//Standard libraries
+#include
+
+//osg
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+//osgText
+#include
+//osgDB
+#include
+#include
+#include
+#include
+//osg_viewer
+#include
+#include
+#include
+//osgGA
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+//Self headers
+#include "OsgAndroidNotifyHandler.hpp"
+
+//Static plugins Macro
+USE_OSGPLUGIN(ive)
+USE_OSGPLUGIN(osg)
+USE_OSGPLUGIN(osg2)
+USE_OSGPLUGIN(terrain)
+USE_OSGPLUGIN(rgb)
+USE_OSGPLUGIN(OpenFlight)
+USE_OSGPLUGIN(dds)
+//Static DOTOSG
+USE_DOTOSGWRAPPER_LIBRARY(osg)
+USE_DOTOSGWRAPPER_LIBRARY(osgFX)
+USE_DOTOSGWRAPPER_LIBRARY(osgParticle)
+USE_DOTOSGWRAPPER_LIBRARY(osgTerrain)
+USE_DOTOSGWRAPPER_LIBRARY(osgText)
+USE_DOTOSGWRAPPER_LIBRARY(osgViewer)
+USE_DOTOSGWRAPPER_LIBRARY(osgVolume)
+//Static serializer
+USE_SERIALIZER_WRAPPER_LIBRARY(osg)
+USE_SERIALIZER_WRAPPER_LIBRARY(osgAnimation)
+USE_SERIALIZER_WRAPPER_LIBRARY(osgFX)
+USE_SERIALIZER_WRAPPER_LIBRARY(osgManipulator)
+USE_SERIALIZER_WRAPPER_LIBRARY(osgParticle)
+USE_SERIALIZER_WRAPPER_LIBRARY(osgTerrain)
+USE_SERIALIZER_WRAPPER_LIBRARY(osgText)
+USE_SERIALIZER_WRAPPER_LIBRARY(osgVolume)
+
+#define LOG_TAG "osgNativeLib"
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
+
+struct Model{
+ std::string filename;
+ std::string name;
+};
+
+static const char gVertexShader[] =
+ "varying vec4 color; \n"
+ "const vec3 lightPos =vec3(0.0, 0.0, 10.0); \n"
+ "const vec4 cessnaColor =vec4(0.8, 0.8, 0.8, 1.0); \n"
+ "const vec4 lightAmbient =vec4(0.1, 0.1, 0.1, 1.0); \n"
+ "const vec4 lightDiffuse =vec4(0.4, 0.4, 0.4, 1.0); \n"
+ "const vec4 lightSpecular =vec4(0.8, 0.8, 0.8, 1.0); \n"
+ "void DirectionalLight(in vec3 normal, \n"
+ " in vec3 ecPos, \n"
+ " inout vec4 ambient, \n"
+ " inout vec4 diffuse, \n"
+ " inout vec4 specular) \n"
+ "{ \n"
+ " float nDotVP; \n"
+ " vec3 L = normalize(gl_ModelViewMatrix*vec4(lightPos, 0.0)).xyz; \n"
+ " nDotVP = max(0.0, dot(normal, L)); \n"
+ " \n"
+ " if (nDotVP > 0.0) { \n"
+ " vec3 E = normalize(-ecPos); \n"
+ " vec3 R = normalize(reflect( L, normal )); \n"
+ " specular = pow(max(dot(R, E), 0.0), 16.0) * lightSpecular; \n"
+ " } \n"
+ " ambient = lightAmbient; \n"
+ " diffuse = lightDiffuse * nDotVP; \n"
+ "} \n"
+ "void main() { \n"
+ " vec4 ambiCol = vec4(0.0); \n"
+ " vec4 diffCol = vec4(0.0); \n"
+ " vec4 specCol = vec4(0.0); \n"
+ " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n"
+ " vec3 normal = normalize(gl_NormalMatrix * gl_Normal); \n"
+ " vec4 ecPos = gl_ModelViewMatrix * gl_Vertex; \n"
+ " DirectionalLight(normal, ecPos.xyz, ambiCol, diffCol, specCol); \n"
+ " color = cessnaColor * (ambiCol + diffCol + specCol); \n"
+ "} \n";
+
+static const char gFragmentShader[] =
+ "precision mediump float; \n"
+ "varying mediump vec4 color; \n"
+ "void main() { \n"
+ " gl_FragColor = color; \n"
+ "} \n";
+
+
+class OsgMainApp{
+private:
+ osg::ref_ptr _viewer;
+ osg::ref_ptr _root;
+ osg::ref_ptr _state;
+ osg::ref_ptr _manipulator;
+
+ float _lodScale;
+ unsigned int _prevFrame;
+
+ bool _initialized;
+ bool _clean_scene;
+
+ OsgAndroidNotifyHandler *_notifyHandler;
+
+ std::vector _vModels;
+ std::vector _vModelsToLoad;
+ std::vector _vModelsToDelete;
+
+ void loadModels();
+ void deleteModels();
+
+public:
+ OsgMainApp();
+ ~OsgMainApp();
+
+ //Initialization function
+ void initOsgWindow(int x,int y,int width,int height);
+ //Draw
+ void draw();
+ //Events
+ void mouseButtonPressEvent(float x,float y,int button);
+ void mouseButtonReleaseEvent(float x,float y,int button);
+ void mouseMoveEvent(float x,float y);
+ void keyboardDown(int key);
+ void keyboardUp(int key);
+ //Loading and unloading
+ void loadObject(std::string filePath);
+ void loadObject(std::string name,std::string filePath);
+ void unLoadObject(int number);
+ void clearScene();
+ //Other functions
+ int getNumberObjects();
+ std::string getObjectName(int nunmber);
+
+ void setClearColor(osg::Vec4f color);
+ osg::Vec4f getClearColor();
+};
+
+
+#endif /* OSGMAINAPP_HPP_ */
diff --git a/examples/osgAndroidExampleGLES2/jni/osgNativeLib.cpp b/examples/osgAndroidExampleGLES2/jni/osgNativeLib.cpp
new file mode 100644
index 000000000..4c8efc3f2
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/jni/osgNativeLib.cpp
@@ -0,0 +1,113 @@
+#include
+#include
+#include
+
+#include
+
+#include "OsgMainApp.hpp"
+
+OsgMainApp mainApp;
+
+extern "C" {
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_init(JNIEnv * env, jobject obj, jint width, jint height);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_step(JNIEnv * env, jobject obj);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_clearContents(JNIEnv * env, jobject obj);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_mouseButtonPressEvent(JNIEnv * env, jobject obj, jfloat x, jfloat y, jint button);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_mouseButtonReleaseEvent(JNIEnv * env, jobject obj, jfloat x, jfloat y, jint button);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_mouseMoveEvent(JNIEnv * env, jobject obj, jfloat x, jfloat y);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_keyboardDown(JNIEnv * env, jobject obj, jint key);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_keyboardUp(JNIEnv * env, jobject obj, jint key);
+ JNIEXPORT jintArray JNICALL Java_osg_AndroidExample_osgNativeLib_getClearColor(JNIEnv * env, jobject obj);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_setClearColor(JNIEnv * env, jobject obj, jint red, jint green, jint blue);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_loadObject(JNIEnv * env, jobject obj, jstring address);
+ JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_unLoadObject(JNIEnv * env, jobject obj, jint number);
+ JNIEXPORT jobjectArray JNICALL Java_osg_AndroidExample_osgNativeLib_getObjectNames(JNIEnv * env, jobject obj);
+};
+
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_init(JNIEnv * env, jobject obj, jint width, jint height){
+ mainApp.initOsgWindow(0,0,width,height);
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_step(JNIEnv * env, jobject obj){
+ mainApp.draw();
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_clearContents(JNIEnv * env, jobject obj){
+ mainApp.clearScene();
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_mouseButtonPressEvent(JNIEnv * env, jobject obj, jfloat x, jfloat y, jint button){
+ mainApp.mouseButtonPressEvent(x,y,button);
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_mouseButtonReleaseEvent(JNIEnv * env, jobject obj, jfloat x, jfloat y, jint button){
+ mainApp.mouseButtonReleaseEvent(x,y,button);
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_mouseMoveEvent(JNIEnv * env, jobject obj, jfloat x, jfloat y){
+ mainApp.mouseMoveEvent(x,y);
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_keyboardDown(JNIEnv * env, jobject obj, jint key){
+ mainApp.keyboardDown(key);
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_keyboardUp(JNIEnv * env, jobject obj, jint key){
+ mainApp.keyboardUp(key);
+}
+JNIEXPORT jintArray JNICALL Java_osg_AndroidExample_osgNativeLib_getClearColor(JNIEnv * env, jobject obj){
+
+ jintArray color;
+ color = env->NewIntArray(3);
+ if (color == NULL) {
+ return NULL;
+ }
+ osg::Vec4 vTemp1 = mainApp.getClearColor();
+
+ jint vTemp2[3];
+
+ vTemp2[0] = (int) (vTemp1.r() * 255);
+ vTemp2[1] = (int) (vTemp1.g() * 255);
+ vTemp2[2] = (int) (vTemp1.b() * 255);
+
+ std::cout<SetIntArrayRegion(color, 0, 3, vTemp2);
+
+ return color;
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_setClearColor(JNIEnv * env, jobject obj, jint red, jint green, jint blue){
+ osg::Vec4 tVec((float) red / 255.0f, (float) green / 255.0f, (float) blue / 255.0f, 0.0f);
+ mainApp.setClearColor(tVec);
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_loadObject(JNIEnv * env, jobject obj, jstring address){
+ //Import Strings from JNI
+ const char *nativeAddress = env->GetStringUTFChars(address, false);
+
+ mainApp.loadObject(std::string(nativeAddress));
+
+ //Release Strings to JNI
+ env->ReleaseStringUTFChars(address, nativeAddress);
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_loadObject(JNIEnv * env, jobject obj, jstring address, jstring name){
+ //Import Strings from JNI
+ const char *nativeAddress = env->GetStringUTFChars(address, false);
+ const char *nativeName = env->GetStringUTFChars(name, false);
+
+ mainApp.loadObject(std::string(nativeName),std::string(nativeAddress));
+
+ //Release Strings to JNI
+ env->ReleaseStringUTFChars(address, nativeAddress);
+ env->ReleaseStringUTFChars(address, nativeName);
+}
+JNIEXPORT void JNICALL Java_osg_AndroidExample_osgNativeLib_unLoadObject(JNIEnv * env, jobject obj, jint number){
+
+ mainApp.unLoadObject(number);
+
+}
+JNIEXPORT jobjectArray JNICALL Java_osg_AndroidExample_osgNativeLib_getObjectNames(JNIEnv * env, jobject obj){
+
+ jobjectArray fileNames;
+ unsigned int numModels = mainApp.getNumberObjects();
+ fileNames = (jobjectArray)env->NewObjectArray(numModels,env->FindClass("java/lang/String"),env->NewStringUTF(""));
+
+ for(unsigned int i=0;i < numModels;i++){
+ std::string name = mainApp.getObjectName(i);
+ env->SetObjectArrayElement(fileNames,i,env->NewStringUTF(name.c_str()));
+ }
+
+ return fileNames;
+}
diff --git a/examples/osgAndroidExampleGLES2/proguard.cfg b/examples/osgAndroidExampleGLES2/proguard.cfg
new file mode 100644
index 000000000..12dd0392c
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/proguard.cfg
@@ -0,0 +1,36 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembernames class * {
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
diff --git a/examples/osgAndroidExampleGLES2/res/drawable-hdpi/osg.png b/examples/osgAndroidExampleGLES2/res/drawable-hdpi/osg.png
new file mode 100644
index 000000000..e9377f500
Binary files /dev/null and b/examples/osgAndroidExampleGLES2/res/drawable-hdpi/osg.png differ
diff --git a/examples/osgAndroidExampleGLES2/res/drawable-hdpi/web_browser.png b/examples/osgAndroidExampleGLES2/res/drawable-hdpi/web_browser.png
new file mode 100644
index 000000000..ed13e46bd
Binary files /dev/null and b/examples/osgAndroidExampleGLES2/res/drawable-hdpi/web_browser.png differ
diff --git a/examples/osgAndroidExampleGLES2/res/drawable-ldpi/osg.png b/examples/osgAndroidExampleGLES2/res/drawable-ldpi/osg.png
new file mode 100644
index 000000000..0b8cce36b
Binary files /dev/null and b/examples/osgAndroidExampleGLES2/res/drawable-ldpi/osg.png differ
diff --git a/examples/osgAndroidExampleGLES2/res/drawable-mdpi/osg.png b/examples/osgAndroidExampleGLES2/res/drawable-mdpi/osg.png
new file mode 100644
index 000000000..f8275b46b
Binary files /dev/null and b/examples/osgAndroidExampleGLES2/res/drawable-mdpi/osg.png differ
diff --git a/examples/osgAndroidExampleGLES2/res/layout/dialog_text_entry.xml b/examples/osgAndroidExampleGLES2/res/layout/dialog_text_entry.xml
new file mode 100644
index 000000000..767021164
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/res/layout/dialog_text_entry.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
diff --git a/examples/osgAndroidExampleGLES2/res/layout/main.xml b/examples/osgAndroidExampleGLES2/res/layout/main.xml
new file mode 100644
index 000000000..3a5f117d3
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/res/layout/main.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/examples/osgAndroidExampleGLES2/res/layout/ui_layout_gles.xml b/examples/osgAndroidExampleGLES2/res/layout/ui_layout_gles.xml
new file mode 100644
index 000000000..1d10283f5
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/res/layout/ui_layout_gles.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/osgAndroidExampleGLES2/res/menu/appmenu.xml b/examples/osgAndroidExampleGLES2/res/menu/appmenu.xml
new file mode 100644
index 000000000..94cbfad3a
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/res/menu/appmenu.xml
@@ -0,0 +1,9 @@
+
+
diff --git a/examples/osgAndroidExampleGLES2/res/values/strings.xml b/examples/osgAndroidExampleGLES2/res/values/strings.xml
new file mode 100644
index 000000000..e242634ea
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/res/values/strings.xml
@@ -0,0 +1,28 @@
+
+
+ Hello World, osgViewer!
+ osgAndroidExample
+ #BBBBBB
+ Light (ON/OFF)
+ Center View
+ Change Navigation
+ Write address
+ Main navigation
+ Second Navigation
+ Light ON
+ Light OFF
+ Load Object
+ L. Object
+ Delete Object
+ D. Object
+ Clean Scene
+ Clean
+ Change Background
+ C.Background
+ Show Keyboard
+ S.Keyboard
+ Select Object
+ Write file address
+ Accept
+ Cancel
+
diff --git a/examples/osgAndroidExampleGLES2/src/osg/AndroidExample/ColorPickerDialog.java b/examples/osgAndroidExampleGLES2/src/osg/AndroidExample/ColorPickerDialog.java
new file mode 100644
index 000000000..b24e853f1
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/src/osg/AndroidExample/ColorPickerDialog.java
@@ -0,0 +1,250 @@
+package osg.AndroidExample;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.Shader;
+import android.os.Bundle;
+import android.view.MotionEvent;
+import android.view.View;
+
+public class ColorPickerDialog extends Dialog{
+
+ public interface OnColorChangeListener{
+ void colorChange(int color);
+ }
+
+ private OnColorChangeListener tListener;
+ private int tInitialColor;
+
+ private static class ColorPickerView extends View{
+
+ private Paint tPaint;
+ private float tCurrentHue = 0;
+ private int tCurrentX = 0;
+ private int tCurrentY = 0;
+ private int tCurrentColor;
+ private final int[] tHueGradientColors = new int [258];
+ private int [] tGradientColors = new int[65536]; //256X256 colors
+ private OnColorChangeListener tListener;
+ private boolean tQSelected = false;
+
+ public ColorPickerView(Context context, OnColorChangeListener listener, int color) {
+ super(context);
+ // TODO Auto-generated constructor stub
+ tListener = listener;
+
+ //Get Hue from tCurrentColor and update the Gradient of Color
+ float[] newHSV = new float[3];
+ Color.colorToHSV(color, newHSV);
+ tCurrentHue = newHSV[0];
+ updateGradientColors();
+ tCurrentColor = color;
+
+ //Initialize of colors in Hue slider
+
+ int index = 0;
+ for(float i=0; i<256; i += 256/42 , index++){
+ tHueGradientColors[index] = Color.rgb(255, 0, (int)i);
+ }
+ for(float i=0; i<256; i += 256/42 , index++){
+ tHueGradientColors[index] = Color.rgb(255-(int)i, 0, 255);
+ }
+ for(float i=0; i<256; i += 256/42 , index++){
+ tHueGradientColors[index] = Color.rgb(0, (int) i, 255);
+ }
+ for(float i=0; i<256; i += 256/42 , index++){
+ tHueGradientColors[index] = Color.rgb(0, 255, 255-(int)i);
+ }
+ for(float i=0; i<256; i += 256/42 , index++){
+ tHueGradientColors[index] = Color.rgb((int)i, 255, 0);
+ }
+ for(float i=0; i<256; i += 256/42 , index++){
+ tHueGradientColors[index] = Color.rgb(255, 255-(int)i, 0);
+ }
+
+ // Paint initialized
+ tPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ tPaint.setTextAlign(Paint.Align.CENTER);
+ tPaint.setTextSize(12);
+ }
+
+ // Get the Color from Hue Bar
+ private int getCurrentGradientColor(){
+
+ int currentHue = 255 - (int)(tCurrentHue*255/360);
+ int index = 0;
+ for (float i=0; i<256; i += 256/42, index++){
+ if (index == currentHue) return Color.rgb(255, 0, (int) i );
+ }
+ for (float i=0; i<256; i += 256/42, index++){
+ if (index == currentHue) return Color.rgb(255-(int)i, 0, 255 );
+ }
+ for (float i=0; i<256; i += 256/42, index++){
+ if (index == currentHue) return Color.rgb(0, (int) i, 255 );
+ }
+ for (float i=0; i<256; i += 256/42, index++){
+ if (index == currentHue) return Color.rgb(0, 255, 255-(int) i );
+ }
+ for (float i=0; i<256; i += 256/42, index++){
+ if (index == currentHue) return Color.rgb((int) i, 255, 0 );
+ }
+ for (float i=0; i<256; i += 256/42, index++){
+ if (index == currentHue) return Color.rgb(255, 255-(int) i, 0);
+ }
+ return Color.RED;
+ }
+
+ private void updateGradientColors(){
+
+ int actualColor = getCurrentGradientColor();
+ int index = 0;
+ int[] colColors = new int[256];
+ for(int y=0; y<256; y++){
+ for(int x=0; x<256; x++ , index++){
+ if(y==0){
+ tGradientColors[index] = Color.rgb(255-(255-Color.red(actualColor))*x/255, 255-(255-Color.green(actualColor))*x/255, 255-(255-Color.blue(actualColor))*x/255);
+ colColors[x] = tGradientColors[index];
+ }
+ else{
+ tGradientColors[index] = Color.rgb((255-y)*Color.red(colColors[x])/255, (255-y)*Color.green(colColors[x])/255, (255-y)*Color.blue(colColors[x])/255);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas){
+ int translatedHue = 255 - (int)(tCurrentHue*255/360);
+ //Display HUE with bar lines
+
+ for(int x=0; x<256; x++){
+ //We display the color or a big white bar
+ if(translatedHue != x){
+ tPaint.setColor(tHueGradientColors[x]);
+ tPaint.setStrokeWidth(1);
+ }
+ else{
+ tPaint.setColor(Color.WHITE);
+ tPaint.setStrokeWidth(3);
+ }
+ canvas.drawLine(x+10, 0, x+10, 40, tPaint);
+ }
+
+ // Display Gradient Box
+ for(int x=0; x<256;x++){
+ int[] colors = new int[2];
+ colors[0] = tGradientColors[x];
+ colors[1] = Color.BLACK;
+ Shader shader = new LinearGradient(0,50,0,306,colors,null, Shader.TileMode.REPEAT);
+ tPaint.setShader(shader);
+ canvas.drawLine(x+10, 50, x+10, 306, tPaint);
+ }
+ tPaint.setShader(null);
+
+ //Display the circle around the currently selected color in the main field
+ if(tCurrentX !=0 && tCurrentY != 0){
+ tPaint.setStyle(Paint.Style.STROKE);
+ tPaint.setColor(Color.BLACK);
+ canvas.drawCircle(tCurrentX, tCurrentY, 10, tPaint);
+ }
+
+ //Draw a button
+
+ tPaint.setStyle(Paint.Style.FILL);
+ if(tQSelected){
+ tPaint.setColor(Color.WHITE);
+ canvas.drawCircle(138, 336, 30, tPaint);
+ }
+ tPaint.setColor(tCurrentColor);
+ canvas.drawCircle(138, 336, 20, tPaint);
+
+ }
+
+ @Override
+ protected void onMeasure(int width,int height){
+ setMeasuredDimension(276, 366);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event){
+ if(event.getAction() != MotionEvent.ACTION_DOWN && event.getAction() != MotionEvent.ACTION_MOVE && event.getAction() != MotionEvent.ACTION_UP) return true;
+ float x = event.getX();
+ float y = event.getY();
+
+ tQSelected=false;
+
+ // if in Hue Bar
+ if(x >10 && x <266 && y>0 && y<40){
+ //Update gradient
+ tCurrentHue = (255-x)*360/255;
+ updateGradientColors();
+
+ //Update current Selected Color
+ int nX = tCurrentX-10;
+ int nY = tCurrentY-60;
+ int index = 256 * (nY-1)+nX;
+
+ if(index>0 && index < tGradientColors.length)
+ tCurrentColor = tGradientColors[256*(nY-1)+nX];
+
+ invalidate(); //By invalidating we are forcing a redraw;
+ }
+
+ // If Main gradient
+
+ if ( x >10 && x< 266 && y>50 && y <306){
+ tCurrentX = (int) x;
+ tCurrentY = (int) y;
+ int nX = tCurrentX - 10;
+ int nY = tCurrentY - 60;
+ int index = 256*(nY-1)+nX;
+ if (index >0 && index < tGradientColors.length){
+ tCurrentColor = tGradientColors[index];
+
+ invalidate(); //By invalidating we are forcing a redraw;
+ }
+ }
+ if( x>118 && x<158 && y > 316 && y <356){
+ if(event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE){
+ tQSelected=true;
+ }
+ if(event.getAction() == MotionEvent.ACTION_UP){
+ tQSelected=false;
+ tListener.colorChange(tCurrentColor);
+ }
+ invalidate();
+ }
+
+
+
+ return true;
+ }
+
+
+ }
+
+ public ColorPickerDialog(Context context, OnColorChangeListener listener, int initialColor){
+ super(context);
+
+ tListener = listener;
+ tInitialColor = initialColor;
+ }
+
+ @Override
+ protected void onCreate( Bundle savedInstanceState){
+ super.onCreate(savedInstanceState);
+ OnColorChangeListener l = new OnColorChangeListener(){
+ public void colorChange(int color){
+ tListener.colorChange(color);
+ dismiss();
+ }
+ };
+
+ setContentView(new ColorPickerView(getContext(),l,tInitialColor));
+ }
+
+}
diff --git a/examples/osgAndroidExampleGLES2/src/osg/AndroidExample/EGLview.java b/examples/osgAndroidExampleGLES2/src/osg/AndroidExample/EGLview.java
new file mode 100644
index 000000000..29295053b
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/src/osg/AndroidExample/EGLview.java
@@ -0,0 +1,329 @@
+
+package osg.AndroidExample;
+/*
+ * Copyright (C) 2008 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.
+ */
+import android.app.Dialog;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.*;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.opengles.GL10;
+/**
+ * A simple GLSurfaceView sub-class that demonstrate how to perform
+ * OpenGL ES 1.0 rendering into a GL Surface. Note the following important
+ * details:
+ *
+ * - The class must use a custom context factory to enable 1.0 rendering.
+ * See ContextFactory class definition below.
+ *
+ * - The class must use a custom EGLConfigChooser to be able to select
+ * an EGLConfig that supports 1.0. This is done by providing a config
+ * specification to eglChooseConfig() that has the attribute
+ * EGL10.ELG_RENDERABLE_TYPE containing the EGL_OPENGL_ES_BIT flag
+ * set. See ConfigChooser class definition below.
+ *
+ * - The class must select the surface's format, then choose an EGLConfig
+ * that matches it exactly (with regards to red/green/blue/alpha channels
+ * bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
+ */
+public class EGLview extends GLSurfaceView {
+ private static String TAG = "EGLview";
+ private static final boolean DEBUG = false;
+
+ public EGLview(Context context) {
+ super(context);
+ init(false, 16, 8);
+ }
+ public EGLview(Context context, AttributeSet attrs) {
+ super(context,attrs);
+ init(false, 16, 8);
+ }
+
+
+ public EGLview(Context context, boolean translucent, int depth, int stencil) {
+ super(context);
+ init(translucent, depth, stencil);
+ }
+
+ private void init(boolean translucent, int depth, int stencil) {
+
+ /* By default, GLSurfaceView() creates a RGB_565 opaque surface.
+ * If we want a translucent one, we should change the surface's
+ * format here, using PixelFormat.TRANSLUCENT for GL Surfaces
+ * is interpreted as any 32-bit surface with alpha by SurfaceFlinger.
+ */
+ if (translucent) {
+ this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
+ }
+
+ /* Setup the context factory for 2.0 rendering.
+ * See ContextFactory class definition below
+ */
+ setEGLContextFactory(new ContextFactory());
+
+ /* We need to choose an EGLConfig that matches the format of
+ * our surface exactly. This is going to be done in our
+ * custom config chooser. See ConfigChooser class definition
+ * below.
+ */
+ setEGLConfigChooser( translucent ?
+ new ConfigChooser(8, 8, 8, 8, depth, stencil) :
+ new ConfigChooser(5, 6, 5, 0, depth, stencil) );
+
+ /* Set the renderer responsible for frame rendering */
+ setRenderer(new Renderer());
+ }
+
+ private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
+ private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+ public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
+ Log.w(TAG, "creating OpenGL ES 2.0 context");
+ checkEglError("Before eglCreateContext", egl);
+ int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
+ EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
+ checkEglError("After eglCreateContext", egl);
+ return context;
+ }
+
+ public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
+ egl.eglDestroyContext(display, context);
+ }
+ }
+
+ private static void checkEglError(String prompt, EGL10 egl) {
+ int error;
+ while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
+ Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
+ }
+ }
+
+ private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
+
+ public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) {
+ mRedSize = r;
+ mGreenSize = g;
+ mBlueSize = b;
+ mAlphaSize = a;
+ mDepthSize = depth;
+ mStencilSize = stencil;
+ }
+
+ /* This EGL config specification is used to specify 1.x rendering.
+ * We use a minimum size of 4 bits for red/green/blue, but will
+ * perform actual matching in chooseConfig() below.
+ */
+ private static int EGL_OPENGL_ES_BIT = 4;
+ private static int[] s_configAttribs2 =
+ {
+ EGL10.EGL_RED_SIZE, 4,
+ EGL10.EGL_GREEN_SIZE, 4,
+ EGL10.EGL_BLUE_SIZE, 4,
+ EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
+ EGL10.EGL_NONE
+ };
+
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
+
+ /* Get the number of minimally matching EGL configurations
+ */
+ int[] num_config = new int[1];
+ egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config);
+
+ int numConfigs = num_config[0];
+
+ if (numConfigs <= 0) {
+ throw new IllegalArgumentException("No configs match configSpec");
+ }
+
+ /* Allocate then read the array of minimally matching EGL configs
+ */
+ EGLConfig[] configs = new EGLConfig[numConfigs];
+ egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);
+
+ if (DEBUG) {
+ printConfigs(egl, display, configs);
+ }
+ /* Now return the "best" one
+ */
+ return chooseConfig(egl, display, configs);
+ }
+
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
+ EGLConfig[] configs) {
+ for(EGLConfig config : configs) {
+ int d = findConfigAttrib(egl, display, config,
+ EGL10.EGL_DEPTH_SIZE, 0);
+ int s = findConfigAttrib(egl, display, config,
+ EGL10.EGL_STENCIL_SIZE, 0);
+
+ // We need at least mDepthSize and mStencilSize bits
+ if (d < mDepthSize || s < mStencilSize)
+ continue;
+
+ // We want an *exact* match for red/green/blue/alpha
+ int r = findConfigAttrib(egl, display, config,
+ EGL10.EGL_RED_SIZE, 0);
+ int g = findConfigAttrib(egl, display, config,
+ EGL10.EGL_GREEN_SIZE, 0);
+ int b = findConfigAttrib(egl, display, config,
+ EGL10.EGL_BLUE_SIZE, 0);
+ int a = findConfigAttrib(egl, display, config,
+ EGL10.EGL_ALPHA_SIZE, 0);
+
+ if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize)
+ return config;
+ }
+ return null;
+ }
+
+ private int findConfigAttrib(EGL10 egl, EGLDisplay display,
+ EGLConfig config, int attribute, int defaultValue) {
+
+ if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
+ return mValue[0];
+ }
+ return defaultValue;
+ }
+
+ private void printConfigs(EGL10 egl, EGLDisplay display,
+ EGLConfig[] configs) {
+ int numConfigs = configs.length;
+ Log.w(TAG, String.format("%d configurations", numConfigs));
+ for (int i = 0; i < numConfigs; i++) {
+ Log.w(TAG, String.format("Configuration %d:\n", i));
+ printConfig(egl, display, configs[i]);
+ }
+ }
+
+ private void printConfig(EGL10 egl, EGLDisplay display,
+ EGLConfig config) {
+ int[] attributes = {
+ EGL10.EGL_BUFFER_SIZE,
+ EGL10.EGL_ALPHA_SIZE,
+ EGL10.EGL_BLUE_SIZE,
+ EGL10.EGL_GREEN_SIZE,
+ EGL10.EGL_RED_SIZE,
+ EGL10.EGL_DEPTH_SIZE,
+ EGL10.EGL_STENCIL_SIZE,
+ EGL10.EGL_CONFIG_CAVEAT,
+ EGL10.EGL_CONFIG_ID,
+ EGL10.EGL_LEVEL,
+ EGL10.EGL_MAX_PBUFFER_HEIGHT,
+ EGL10.EGL_MAX_PBUFFER_PIXELS,
+ EGL10.EGL_MAX_PBUFFER_WIDTH,
+ EGL10.EGL_NATIVE_RENDERABLE,
+ EGL10.EGL_NATIVE_VISUAL_ID,
+ EGL10.EGL_NATIVE_VISUAL_TYPE,
+ 0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
+ EGL10.EGL_SAMPLES,
+ EGL10.EGL_SAMPLE_BUFFERS,
+ EGL10.EGL_SURFACE_TYPE,
+ EGL10.EGL_TRANSPARENT_TYPE,
+ EGL10.EGL_TRANSPARENT_RED_VALUE,
+ EGL10.EGL_TRANSPARENT_GREEN_VALUE,
+ EGL10.EGL_TRANSPARENT_BLUE_VALUE,
+ 0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB,
+ 0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA,
+ 0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL,
+ 0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL,
+ EGL10.EGL_LUMINANCE_SIZE,
+ EGL10.EGL_ALPHA_MASK_SIZE,
+ EGL10.EGL_COLOR_BUFFER_TYPE,
+ EGL10.EGL_RENDERABLE_TYPE,
+ 0x3042 // EGL10.EGL_CONFORMANT
+ };
+ String[] names = {
+ "EGL_BUFFER_SIZE",
+ "EGL_ALPHA_SIZE",
+ "EGL_BLUE_SIZE",
+ "EGL_GREEN_SIZE",
+ "EGL_RED_SIZE",
+ "EGL_DEPTH_SIZE",
+ "EGL_STENCIL_SIZE",
+ "EGL_CONFIG_CAVEAT",
+ "EGL_CONFIG_ID",
+ "EGL_LEVEL",
+ "EGL_MAX_PBUFFER_HEIGHT",
+ "EGL_MAX_PBUFFER_PIXELS",
+ "EGL_MAX_PBUFFER_WIDTH",
+ "EGL_NATIVE_RENDERABLE",
+ "EGL_NATIVE_VISUAL_ID",
+ "EGL_NATIVE_VISUAL_TYPE",
+ "EGL_PRESERVED_RESOURCES",
+ "EGL_SAMPLES",
+ "EGL_SAMPLE_BUFFERS",
+ "EGL_SURFACE_TYPE",
+ "EGL_TRANSPARENT_TYPE",
+ "EGL_TRANSPARENT_RED_VALUE",
+ "EGL_TRANSPARENT_GREEN_VALUE",
+ "EGL_TRANSPARENT_BLUE_VALUE",
+ "EGL_BIND_TO_TEXTURE_RGB",
+ "EGL_BIND_TO_TEXTURE_RGBA",
+ "EGL_MIN_SWAP_INTERVAL",
+ "EGL_MAX_SWAP_INTERVAL",
+ "EGL_LUMINANCE_SIZE",
+ "EGL_ALPHA_MASK_SIZE",
+ "EGL_COLOR_BUFFER_TYPE",
+ "EGL_RENDERABLE_TYPE",
+ "EGL_CONFORMANT"
+ };
+ int[] value = new int[1];
+ for (int i = 0; i < attributes.length; i++) {
+ int attribute = attributes[i];
+ String name = names[i];
+ if ( egl.eglGetConfigAttrib(display, config, attribute, value)) {
+ Log.w(TAG, String.format(" %s: %d\n", name, value[0]));
+ } else {
+ // Log.w(TAG, String.format(" %s: failed\n", name));
+ while (egl.eglGetError() != EGL10.EGL_SUCCESS);
+ }
+ }
+ }
+
+ // Subclasses can adjust these values:
+ protected int mRedSize;
+ protected int mGreenSize;
+ protected int mBlueSize;
+ protected int mAlphaSize;
+ protected int mDepthSize;
+ protected int mStencilSize;
+ private int[] mValue = new int[1];
+ }
+
+ private static class Renderer implements GLSurfaceView.Renderer {
+ public void onDrawFrame(GL10 gl) {
+ osgNativeLib.step();
+ }
+
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ osgNativeLib.init(width, height);
+ }
+
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ // Do nothing
+ gl.glEnable(GL10.GL_DEPTH_TEST);
+ }
+ }
+
+}
+
diff --git a/examples/osgAndroidExampleGLES2/src/osg/AndroidExample/osgNativeLib.java b/examples/osgAndroidExampleGLES2/src/osg/AndroidExample/osgNativeLib.java
new file mode 100644
index 000000000..52e946a4e
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/src/osg/AndroidExample/osgNativeLib.java
@@ -0,0 +1,28 @@
+package osg.AndroidExample;
+
+public class osgNativeLib {
+
+ static {
+ System.loadLibrary("osgNativeLib");
+ }
+
+ /**
+ * @param width the current view width
+ * @param height the current view height
+ */
+ public static native void init(int width, int height);
+ public static native void step();
+ public static native void clearContents();
+ public static native void mouseButtonPressEvent(float x,float y, int button);
+ public static native void mouseButtonReleaseEvent(float x,float y, int button);
+ public static native void mouseMoveEvent(float x,float y);
+ public static native void keyboardDown(int key);
+ public static native void keyboardUp(int key);
+ public static native void setClearColor(int red,int green, int blue);
+ public static native int[] getClearColor();
+ public static native void loadObject(String address);
+ public static native void loadObject(String address,String name);
+ public static native void unLoadObject(int number);
+ public static native String[] getObjectNames();
+
+}
diff --git a/examples/osgAndroidExampleGLES2/src/osg/AndroidExample/osgViewer.java b/examples/osgAndroidExampleGLES2/src/osg/AndroidExample/osgViewer.java
new file mode 100644
index 000000000..d3cfdb962
--- /dev/null
+++ b/examples/osgAndroidExampleGLES2/src/osg/AndroidExample/osgViewer.java
@@ -0,0 +1,417 @@
+package osg.AndroidExample;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.PointF;
+import android.os.Bundle;
+import android.util.FloatMath;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.WindowManager;
+import android.view.View.OnClickListener;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.widget.ImageButton;
+
+import java.io.File;
+
+public class osgViewer extends Activity implements View.OnTouchListener, View.OnKeyListener, ColorPickerDialog.OnColorChangeListener {
+ enum moveTypes { NONE , DRAG, MDRAG, ZOOM ,ACTUALIZE}
+ enum navType { PRINCIPAL , SECONDARY }
+ enum lightType { ON , OFF }
+
+ moveTypes mode=moveTypes.NONE;
+ navType navMode = navType.PRINCIPAL;
+ lightType lightMode = lightType.ON;
+
+ PointF oneFingerOrigin = new PointF(0,0);
+ long timeOneFinger=0;
+ PointF twoFingerOrigin = new PointF(0,0);
+ long timeTwoFinger=0;
+ float distanceOrigin;
+
+ int backgroundColor;
+
+ private static final String TAG = "OSG Activity";
+ //Ui elements
+ EGLview mView;
+ Button uiCenterViewButton;
+ Button uiNavigationChangeButton;
+ ImageButton uiNavigationLeft;
+ ImageButton uiNavigationRight;
+ Button uiLightChangeButton;
+
+ //Toasts
+ Toast msgUiNavPrincipal;
+ Toast msgUiNavSecondary;
+ Toast msgUiLightOn;
+ Toast msgUiLightOff;
+
+ //Dialogs
+ AlertDialog removeLayerDialog;
+ AlertDialog loadLayerAddress;
+
+ //Main Android Activity life cycle
+ @Override protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.ui_layout_gles);
+ //Obtain every Ui element
+ mView= (EGLview) findViewById(R.id.surfaceGLES);
+ mView.setOnTouchListener(this);
+ mView.setOnKeyListener(this);
+
+ uiCenterViewButton = (Button) findViewById(R.id.uiButtonCenter);
+ uiCenterViewButton.setOnClickListener(uiListenerCenterView);
+ uiNavigationChangeButton = (Button) findViewById(R.id.uiButtonChangeNavigation);
+ uiNavigationChangeButton.setOnClickListener(uiListenerChangeNavigation);
+ uiLightChangeButton = (Button) findViewById(R.id.uiButtonLight);
+ uiLightChangeButton.setOnClickListener(uiListenerChangeLight);
+
+ //Creating Toasts
+ msgUiNavPrincipal = Toast.makeText(getApplicationContext(), R.string.uiToastNavPrincipal, Toast.LENGTH_SHORT);
+ msgUiNavSecondary = Toast.makeText(getApplicationContext(), R.string.uiToastNavSecond, Toast.LENGTH_SHORT);
+ msgUiLightOn = Toast.makeText(getApplicationContext(), R.string.uiToastLightOn, Toast.LENGTH_SHORT);
+ msgUiLightOff = Toast.makeText(getApplicationContext(), R.string.uiToastLightOff, Toast.LENGTH_SHORT);
+
+ //Creating Dialogs
+
+ LayoutInflater factory = LayoutInflater.from(getApplicationContext());
+ final View textEntryView = factory.inflate(R.layout.dialog_text_entry, null);
+ AlertDialog.Builder loadLayerDialogBuilder = new AlertDialog.Builder(this);
+ loadLayerDialogBuilder.setIcon(R.drawable.web_browser);
+ loadLayerDialogBuilder.setTitle(R.string.uiDialogTextAddress);
+ loadLayerDialogBuilder.setView(textEntryView);
+ loadLayerDialogBuilder.setPositiveButton(R.string.uiDialogOk, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // TODO Auto-generated method stub
+ EditText address;
+ address = (EditText) textEntryView.findViewById(R.id.uiEditTextInput);
+ osgNativeLib.loadObject(address.getText().toString());
+ }
+ });
+ loadLayerDialogBuilder.setNegativeButton(R.string.uiDialogCancel, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // TODO Auto-generated method stub
+
+ }
+ });
+
+ loadLayerAddress = loadLayerDialogBuilder.create();
+ }
+ @Override protected void onPause() {
+ super.onPause();
+ mView.onPause();
+ }
+ @Override protected void onResume() {
+ super.onResume();
+ mView.onResume();
+ }
+
+ //Main view event processing
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+
+ return true;
+ }
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event){
+ //DO NOTHING this will render useless every menu key except Home
+ int keyChar= event.getUnicodeChar();
+ osgNativeLib.keyboardDown(keyChar);
+ return true;
+ }
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event){
+ switch (keyCode){
+ case KeyEvent.KEYCODE_BACK:
+ super.onDestroy();
+ this.finish();
+ break;
+ case KeyEvent.KEYCODE_SEARCH:
+ break;
+ case KeyEvent.KEYCODE_MENU:
+ this.openOptionsMenu();
+ break;
+ default:
+ int keyChar= event.getUnicodeChar();
+ osgNativeLib.keyboardUp(keyChar);
+ }
+
+ return true;
+ }
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+
+ //dumpEvent(event);
+
+ long time_arrival = event.getEventTime();
+ int n_points = event.getPointerCount();
+ int action = event.getAction() & MotionEvent.ACTION_MASK;
+
+ switch(n_points){
+ case 1:
+ switch(action){
+ case MotionEvent.ACTION_DOWN:
+ mode = moveTypes.DRAG;
+
+ osgNativeLib.mouseMoveEvent(event.getX(0), event.getY(0));
+ if(navMode==navType.PRINCIPAL)
+ osgNativeLib.mouseButtonPressEvent(event.getX(0), event.getY(0), 2);
+ else
+ osgNativeLib.mouseButtonPressEvent(event.getX(0), event.getY(0), 1);
+
+ oneFingerOrigin.x=event.getX(0);
+ oneFingerOrigin.y=event.getY(0);
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ switch(mode){
+ case DRAG:
+ osgNativeLib.mouseMoveEvent(event.getX(0), event.getY(0));
+ if(navMode==navType.PRINCIPAL)
+ osgNativeLib.mouseButtonReleaseEvent(event.getX(0), event.getY(0), 2);
+ else
+ osgNativeLib.mouseButtonReleaseEvent(event.getX(0), event.getY(0), 1);
+ break;
+ default :
+ Log.e(TAG,"There has been an anomaly in touch input 1point/action");
+ }
+ mode = moveTypes.NONE;
+ break;
+ case MotionEvent.ACTION_MOVE:
+
+ osgNativeLib.mouseMoveEvent(event.getX(0), event.getY(0));
+
+ oneFingerOrigin.x=event.getX(0);
+ oneFingerOrigin.y=event.getY(0);
+
+ break;
+ case MotionEvent.ACTION_UP:
+ switch(mode){
+ case DRAG:
+ if(navMode==navType.PRINCIPAL)
+ osgNativeLib.mouseButtonReleaseEvent(event.getX(0), event.getY(0), 2);
+ else
+ osgNativeLib.mouseButtonReleaseEvent(event.getX(0), event.getY(0), 1);
+ break;
+ default :
+ Log.e(TAG,"There has been an anomaly in touch input 1 point/action");
+ }
+ mode = moveTypes.NONE;
+ break;
+ default :
+ Log.e(TAG,"1 point Action not captured");
+ }
+ break;
+ case 2:
+ switch (action){
+ case MotionEvent.ACTION_POINTER_DOWN:
+ //Free previous Action
+ switch(mode){
+ case DRAG:
+ if(navMode==navType.PRINCIPAL)
+ osgNativeLib.mouseButtonReleaseEvent(event.getX(0), event.getY(0), 2);
+ else
+ osgNativeLib.mouseButtonReleaseEvent(event.getX(0), event.getY(0), 1);
+ break;
+ }
+ mode = moveTypes.ZOOM;
+ distanceOrigin = sqrDistance(event);
+ twoFingerOrigin.x=event.getX(1);
+ twoFingerOrigin.y=event.getY(1);
+ oneFingerOrigin.x=event.getX(0);
+ oneFingerOrigin.y=event.getY(0);
+
+ osgNativeLib.mouseMoveEvent(oneFingerOrigin.x,oneFingerOrigin.y);
+ osgNativeLib.mouseButtonPressEvent(oneFingerOrigin.x,oneFingerOrigin.y, 3);
+ osgNativeLib.mouseMoveEvent(oneFingerOrigin.x,oneFingerOrigin.y);
+
+ case MotionEvent.ACTION_MOVE:
+ float distance = sqrDistance(event);
+ float result = distance-distanceOrigin;
+ distanceOrigin=distance;
+
+ if(result>1||result<-1){
+ oneFingerOrigin.y=oneFingerOrigin.y+result;
+ osgNativeLib.mouseMoveEvent(oneFingerOrigin.x,oneFingerOrigin.y);
+ }
+
+ break;
+ case MotionEvent.ACTION_POINTER_UP:
+ mode =moveTypes.NONE;
+ osgNativeLib.mouseButtonReleaseEvent(oneFingerOrigin.x,oneFingerOrigin.y, 3);
+ break;
+ case MotionEvent.ACTION_UP:
+ mode =moveTypes.NONE;
+ osgNativeLib.mouseButtonReleaseEvent(oneFingerOrigin.x,oneFingerOrigin.y, 3);
+ break;
+ default :
+ Log.e(TAG,"2 point Action not captured");
+ }
+ break;
+ }
+
+ return true;
+ }
+
+ //Ui Listeners
+ OnClickListener uiListenerCenterView = new OnClickListener() {
+ public void onClick(View v) {
+ //Log.d(TAG, "Center View");
+ osgNativeLib.keyboardDown(32);
+ osgNativeLib.keyboardUp(32);
+ }
+ };
+ OnClickListener uiListenerChangeNavigation = new OnClickListener() {
+ public void onClick(View v) {
+ //Log.d(TAG, "Change Navigation");
+ if(navMode==navType.PRINCIPAL){
+ msgUiNavSecondary.show();
+ navMode=navType.SECONDARY;
+ }
+ else{
+ msgUiNavPrincipal.show();
+ navMode=navType.PRINCIPAL;
+ }
+ }
+ };
+ OnClickListener uiListenerChangeLight = new OnClickListener() {
+ public void onClick(View v) {
+ //Log.d(TAG, "Change Light");
+ if(lightMode==lightType.ON){
+ msgUiLightOff.show();
+ lightMode=lightType.OFF;
+ osgNativeLib.keyboardDown(108);
+ osgNativeLib.keyboardUp(108);
+ }
+ else{
+ msgUiLightOn.show();
+ lightMode=lightType.ON;
+ osgNativeLib.keyboardDown(108);
+ osgNativeLib.keyboardUp(108);
+ }
+ }
+ };
+
+ //Menu
+
+ @Override
+ public void colorChange(int color) {
+ // TODO Auto-generated method stub
+ // Do nothing
+ int red = Color.red(color);
+ int green = Color.green(color);
+ int blue = Color.blue(color);
+ //Log.d(TAG,"BACK color "+red+" "+green+" "+blue+" ");
+ osgNativeLib.setClearColor(red,green,blue);
+ }
+
+ //Android Life Cycle Menu
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.appmenu, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle item selection
+ switch (item.getItemId()) {
+ case R.id.menuLoadObject:
+ Log.d(TAG,"Load Object");
+ loadLayerAddress.show();
+ return true;
+ case R.id.menuCleanScene:
+ Log.d(TAG,"Clean Scene");
+ osgNativeLib.clearContents();
+ return true;
+ case R.id.menuDeleteObject:
+ Log.d(TAG,"Delete a object");
+ String vNames[] = osgNativeLib.getObjectNames();
+
+ //Remove Layer Dialog
+ AlertDialog.Builder removeLayerDialogBuilder = new AlertDialog.Builder(this);
+ removeLayerDialogBuilder.setTitle(R.string.uiDialogTextChoseRemove);
+ removeLayerDialogBuilder.setItems(vNames, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int witch) {
+ // TODO Auto-generated method stub
+ osgNativeLib.unLoadObject(witch);
+ }
+ });
+ removeLayerDialog = removeLayerDialogBuilder.create();
+
+ if(vNames.length > 0)
+ removeLayerDialog.show();
+
+ return true;
+ case R.id.menuChangeBackground:
+ Log.d(TAG,"Change background color");
+ int[] test = new int [3];
+ test = osgNativeLib.getClearColor();
+ backgroundColor = Color.rgb(test[0], test[1], test[2]);
+
+ ColorPickerDialog colorDialog;
+ new ColorPickerDialog(this, this, backgroundColor).show();
+ return true;
+ case R.id.menuShowKeyboard:
+ Log.d(TAG,"Keyboard");
+ InputMethodManager mgr= (InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
+ mgr.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ //Utilities
+ /** Show an event in the LogCat view, for debugging */
+ private void dumpEvent(MotionEvent event) {
+ String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE",
+ "POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
+ StringBuilder sb = new StringBuilder();
+ int action = event.getAction();
+ int actionCode = action & MotionEvent.ACTION_MASK;
+ sb.append("event ACTION_").append(names[actionCode]);
+ if (actionCode == MotionEvent.ACTION_POINTER_DOWN
+ || actionCode == MotionEvent.ACTION_POINTER_UP) {
+ sb.append("(pid ").append(
+ action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
+ sb.append(")");
+ }
+ sb.append("[");
+ for (int i = 0; i < event.getPointerCount(); i++) {
+ sb.append("#").append(i);
+ sb.append("(pid ").append(event.getPointerId(i));
+ sb.append(")=").append((int) event.getX(i));
+ sb.append(",").append((int) event.getY(i));
+ if (i + 1 < event.getPointerCount())
+ sb.append(";");
+ }
+ sb.append("]");
+ //Log.d(TAG, sb.toString());
+ }
+ private float sqrDistance(MotionEvent event) {
+ float x = event.getX(0) - event.getX(1);
+ float y = event.getY(0) - event.getY(1);
+ return (float)(Math.sqrt(x * x + y * y));
+ }
+
+}
\ No newline at end of file