Procházet zdrojové kódy

Initial work on NDK sensor polling, should have all the things but might require some compile fixing and missing data.
Added set_data method to pass void* data to the driver

Joey Ferwerda před 9 roky
rodič
revize
5ea3c57ad3
4 změnil soubory, kde provedl 173 přidání a 49 odebrání
  1. 45 26
      include/openhmd.h
  2. 108 17
      src/drv_android/android.c
  3. 16 4
      src/openhmd.c
  4. 4 2
      src/openhmdi.h

+ 45 - 26
include/openhmd.h

@@ -18,7 +18,7 @@ extern "C" {
 
 #ifdef _WIN32
 #ifdef DLL_EXPORT
-#define OHMD_APIENTRY __cdecl 
+#define OHMD_APIENTRY __cdecl
 #define OHMD_APIENTRYDLL __declspec( dllexport )
 #else
 #ifdef OHMD_STATIC
@@ -55,24 +55,24 @@ typedef enum {
 	OHMD_PATH      = 2,
 } ohmd_string_value;
 
-/** A collection of float value information types used for getting and setting information with 
+/** A collection of float value information types used for getting and setting information with
  ohmd_device_getf() and ohmd_device_setf(). */
 typedef enum {
 	/** float[4], get - Absolute rotation of the device, in space, as a quaternion. */
 	OHMD_ROTATION_QUAT                    =  1,
 
-	/** float[16], get - A "ready to use" OpenGL style 4x4 matrix with a modelview matrix for the 
+	/** float[16], get - A "ready to use" OpenGL style 4x4 matrix with a modelview matrix for the
 	 left eye of the HMD. */
 	OHMD_LEFT_EYE_GL_MODELVIEW_MATRIX     =  2,
 
-	/** float[16], get - A "ready to use" OpenGL style 4x4 matrix with a modelview matrix for the 
+	/** float[16], get - A "ready to use" OpenGL style 4x4 matrix with a modelview matrix for the
 	 right eye of the HMD. */
 	OHMD_RIGHT_EYE_GL_MODELVIEW_MATRIX    =  3,
 
-	/** float[16], get - A "ready to use" OpenGL style 4x4 matrix with a projection matrix for the 
+	/** float[16], get - A "ready to use" OpenGL style 4x4 matrix with a projection matrix for the
 	 left eye of the HMD. */
 	OHMD_LEFT_EYE_GL_PROJECTION_MATRIX    =  4,
-	/** float[16], get - A "ready to use" OpenGL style 4x4 matrix with a projection matrix for the 
+	/** float[16], get - A "ready to use" OpenGL style 4x4 matrix with a projection matrix for the
 	 right eye of the HMD. */
 	OHMD_RIGHT_EYE_GL_PROJECTION_MATRIX   =  5,
 
@@ -104,13 +104,13 @@ typedef enum {
 
 	/** float[1], get/set - Z-far value for the projection matrix calculations, i.e. drawing distance. */
 	OHMD_PROJECTION_ZFAR                  = 16,
-	/** float[1], get/set - Z-near value for the projection matrix calculations, i.e. close clipping 
+	/** float[1], get/set - Z-near value for the projection matrix calculations, i.e. close clipping
 	 distance. */
 	OHMD_PROJECTION_ZNEAR                 = 17,
 
 	/** float[6], get - Device specifc distortion value. */
 	OHMD_DISTORTION_K                     = 18,
-	
+
 	/** float[10], set - Perform sensor fusion on values from external sensors. Values are: dt (time since last update, in seconds) X, Y, Z gyro, X, Y, Z accelerometer and X, Y, Z magnetometer. */
 	OHMD_EXTERNAL_SENSOR_FUSION           = 19,
 
@@ -131,6 +131,15 @@ typedef enum {
 
 } ohmd_int_value;
 
+/** A collection of data information types used for setting information with ohmd_set_data()
+*/
+typedef enum {
+    /** void*, set
+        Set void* data for use in the internal drivers. */
+    OHMD_DRIVER_DATA
+
+} ohmd_data_value;
+
 /** An opaque pointer to a context structure. */
 typedef struct ohmd_context ohmd_context;
 
@@ -145,21 +154,21 @@ typedef struct ohmd_device ohmd_device;
 OHMD_APIENTRYDLL ohmd_context* OHMD_APIENTRY ohmd_ctx_create();
 
 /**
- * Destroy an OpenHMD context. 
+ * Destroy an OpenHMD context.
  *
  * ohmd_ctx_destroy de-initializes and de-allocates an OpenHMD context allocated with ohmd_ctx_create.
  * All devices associated with the context are automatically closed.
- *  
+ *
  * @param ctx The context to destroy.
  */
 OHMD_APIENTRYDLL void OHMD_APIENTRY ohmd_ctx_destroy(ohmd_context* ctx);
 
 /**
- * Get the last error as a human readable string. 
+ * Get the last error as a human readable string.
  *
  * If a function taking a context as an argument (ohmd_context "methods") returns non-successfully,
- * a human readable error message describing what went wrong can be retreived with this function. 
- *  
+ * a human readable error message describing what went wrong can be retreived with this function.
+ *
  * @param ctx The context to retreive the error message from.
  * @return a pointer to the error message
  */
@@ -173,7 +182,7 @@ OHMD_APIENTRYDLL const char* OHMD_APIENTRY ohmd_ctx_get_error(ohmd_context* ctx)
  * Once per frame in a "game loop" should be sufficient.
  * If OpenHMD is handled in a background thread, calling ohmd_ctx_update and then sleeping for 10-20 ms
  * is recommended.
- * 
+ *
  * @param ctx The context that needs updating.
  */
 OHMD_APIENTRYDLL void OHMD_APIENTRY ohmd_ctx_update(ohmd_context* ctx);
@@ -182,7 +191,7 @@ OHMD_APIENTRYDLL void OHMD_APIENTRY ohmd_ctx_update(ohmd_context* ctx);
  * Probe for devices.
  *
  * Probes for and enumerates supported devices attached to the system.
- * 
+ *
  * @param ctx A context with no currently open devices.
  * @return number of devices found on the system
  */
@@ -191,13 +200,13 @@ OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_ctx_probe(ohmd_context* ctx);
 /**
  * Get device description from enumeration list index.
  *
- * Gets a human readable device description string from a zero indexed enumeration index 
- * between 0 and max, where max is the number ohmd_ctx_probe returned. 
+ * Gets a human readable device description string from a zero indexed enumeration index
+ * between 0 and max, where max is the number ohmd_ctx_probe returned.
  * (I.e. if ohmd_ctx_probe returns 3,valid indices are 0, 1 and 2).
  * The function can return three types of data. The vendor name, the product name and
  * a driver specific path where the device is attached.
  * ohmd_ctx_probe must be called before calling ohmd_list_gets.
- * 
+ *
  * @param ctx A (probed) context.
  * @param index An index, between 0 and the value returned from ohmd_ctx_probe.
  * @param type The type of data to fetch. One of OHMD_VENDOR, OHMD_PRODUCT and OHMD_PATH.
@@ -208,11 +217,11 @@ OHMD_APIENTRYDLL const char* OHMD_APIENTRY ohmd_list_gets(ohmd_context* ctx, int
 /**
  * Open a device.
  *
- * Opens a device from a zero indexed enumeration index between 0 and max, 
+ * Opens a device from a zero indexed enumeration index between 0 and max,
  * where max is the number ohmd_ctx_probe returned. (I.e. if ohmd_ctx_probe returns 3,
  * valid indices are 0, 1 and 2).
  * ohmd_ctx_probe must be called before calling ohmd_list_open_device.
- * 
+ *
  * @param ctx A (probed) context.
  * @param index An index, between 0 and the value returned from ohmd_ctx_probe.
  * @return a pointer to an ohmd_device, which represents a hardware device, such as an HMD.
@@ -233,7 +242,7 @@ OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_close_device(ohmd_device* device);
 /**
  * Get a floating point value from a device.
  *
- * 
+ *
  * @param device An open device to retreive the value from.
  * @param type What type of value to retreive, see ohmd_float_value section for more information.
  * @param[out] out A pointer to a float, or float array where the retreived value should be written.
@@ -252,7 +261,7 @@ OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_device_getf(ohmd_device* device, ohmd_fl
 OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_device_setf(ohmd_device* device, ohmd_float_value type, float* in);
 
 /**
- * Get an integer value from a device. 
+ * Get an integer value from a device.
  *
  * @param device An open device to retreive the value from.
  * @param type What type of value to retreive, ohmd_int_value section for more information.
@@ -262,15 +271,25 @@ OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_device_setf(ohmd_device* device, ohmd_fl
 OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_device_geti(ohmd_device* device, ohmd_int_value type, int* out);
 
 /**
- * Set an integer value from a device.
+ * Set an integer value for a device.
  *
- * @param device An open device to retreive the value from.
- * @param type What type of value to retreive, ohmd_int_value section for more information.
- * @param[out] out A pointer to an integer, or integer array where the retreived value should be written.
+ * @param device An open device to set the value in.
+ * @param type What type of value to set, see ohmd_float_value section for more information.
+ * @param in A pointer to a int, or int array where the new value is stored.
  * @return 0 on success, <0 on failure.
  */
 OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_device_seti(ohmd_device* device, ohmd_int_value type, int* in);
 
+/**
+ * Set an void* data value for a device.
+ *
+ * @param device An open device to set the value in.
+ * @param type What type of value to set, see ohmd_float_value section for more information.
+ * @param in A pointer to the void* casted object.
+ * @return 0 on success, <0 on failure.
+ */
+OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_device_set_data(ohmd_device* device, ohmd_data_value type, void* in);
+
 #ifdef __cplusplus
 }
 #endif

+ 108 - 17
src/drv_android/android.c

@@ -10,46 +10,106 @@
 
 #include "android.h"
 
+#ifdev __ANDROID__
+    #include <android/sensor.h>
+#endif // __ANDROID__
+
 typedef struct {
 	ohmd_device base;
 	fusion sensor_fusion;
+
+	//Android specific
+	#ifdev __ANDROID__
+    android_app* state;
+    ASensorManager* sensorManager;
+    const ASensor* accelerometerSensor;
+    const ASensor* gyroscopeSensor;
+    ASensorEventQueue* sensorEventQueue;
+	AAssetManager* assetMgr;
+    #endif
 } android_priv;
 
 static void update_device(ohmd_device* device)
 {
+    android_priv* priv = (android_priv*)device;
+    int ident, events;
+    struct android_poll_source* source;
+
+    while ((ident = ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0)
+    {
+        if (source != NULL)
+            source->process(state, source);
+
+		// If a sensor has data, process it now.
+		if (ident == LOOPER_ID_USER)
+		{
+			if (priv->accelerometerSensor != NULL)
+			{
+				ASensorEvent event;
+				vec3f gyro;
+				vec3f accel;
+				vec3f mag;
+				while (ASensorEventQueue_getEvents(priv->sensorEventQueue, &event, 1) > 0)
+				{
+
+					if (event.type == ASENSOR_TYPE_ACCELEROMETER)
+					{
+						accel[0] = event.acceleration.y;
+						accel[1] = -event.acceleration.x;
+						accel[2] = event.acceleration.z;
+
+						//LOGI("accelerometer: x=%f y=%f z=%f",accel[0],accel[1],accel[2]);
+					}
+					if (event.type == ASENSOR_TYPE_GYROSCOPE)
+					{
+						gyro[0] = -event.data[1];
+						gyro[1] = event.data[0];
+						gyro[2] = event.data[2];
+					}
+					//TODO: Implement mag when available
+					mag[0] = 0.0f;
+					mag[1] = 0.0f;
+					mag[2] = 0.0f;
+
+                    //apply data to the fusion
+                    ofusion_update(&priv->sensor_fusion, 100, gyro, accel, mag);
+				}
+			}
+		}
+    }
 }
 
 static void nofusion_update(fusion* me, float dt, const vec3f* accel)
-{	
+{
 	//avg raw accel data to smooth jitter, and normalise
 	ofq_add(&me->accel_fq, accel);
 	vec3f accel_mean;
 	ofq_get_mean(&me->accel_fq, &accel_mean);
 	vec3f acc_n = accel_mean;
 	ovec3f_normalize_me(&acc_n);
-	
-	
+
+
 	//reference vectors for axis-angle
-	vec3f xyzv[3] = { 
+	vec3f xyzv[3] = {
 		{1,0,0},
 		{0,1,0},
 		{0,0,1}
 	};
 	quatf roll, pitch;
-	
+
 	//pitch is rot around x, based on gravity in z and y axes
-	oquatf_init_axis(&pitch, xyzv+0, atan2f(-acc_n.z, -acc_n.y)); 
-	
+	oquatf_init_axis(&pitch, xyzv+0, atan2f(-acc_n.z, -acc_n.y));
+
 	//roll is rot around z, based on gravity in x and y axes
 	//note we need to invert the values when the device is upside down (y < 0) for proper results
-	oquatf_init_axis(&roll, xyzv+2, acc_n.y < 0 ? atan2f(-acc_n.x, -acc_n.y) : atan2f(acc_n.x, acc_n.y)); 
-	
-			
-	
+	oquatf_init_axis(&roll, xyzv+2, acc_n.y < 0 ? atan2f(-acc_n.x, -acc_n.y) : atan2f(acc_n.x, acc_n.y));
+
+
+
 	quatf or = {0,0,0,1};
 	//order of applying is yaw-pitch-roll
 	//yaw is not possible using only accel
-	oquatf_mult_me(&or, &pitch); 
+	oquatf_mult_me(&or, &pitch);
 	oquatf_mult_me(&or, &roll);
 
 	me->orient = or;
@@ -127,19 +187,38 @@ static int seti(ohmd_device* device, ohmd_int_value type, int* in)
 	switch(type){
 		case OHMD_ACCELERATION_ONLY_FALLBACK: {
 			priv->base.properties.accel_only = &in;
-			
+
 			if(priv->base.properties.accel_only = 1)
 				nofusion_init(&priv->sensor_fusion); //re-init with different smoothing
 		}
 		break;
-		
+
 		default:
 			ohmd_set_error(priv->base.ctx, "invalid type given to seti (%i)", type);
 			return -1;
 			break;
 		}
-		
-		return 0;		
+
+		return 0;
+}
+
+static int set_data(ohmd_device* device, ohmd_data_value type, void* in)
+{
+	android_priv* priv = (android_priv*)device;
+
+	switch(type){
+		case OHMD_DRIVER_DATA: {
+		    priv->state = (android_app*)in;
+		}
+		break;
+
+		default:
+			ohmd_set_error(priv->base.ctx, "invalid type given to set_data (%i)", type);
+			return -1;
+			break;
+		}
+
+		return 0;
 }
 
 static void close_device(ohmd_device* device)
@@ -178,7 +257,19 @@ static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
 	priv->base.getf = getf;
 	priv->base.setf = setf;
 	priv->base.seti = seti;
-	
+	priv->base.set_data = set_data;
+
+    //init Android sensors
+    priv->accelerometerSensor = ASensorManager_getDefaultSensor(priv->sensorManager,
+            ASENSOR_TYPE_ACCELEROMETER);
+    priv->gyroscopeSensor = ASensorManager_getDefaultSensor(priv->sensorManager,
+            ASENSOR_TYPE_GYROSCOPE);
+    priv->sensorEventQueue = ASensorManager_createEventQueue(priv->sensorManager,
+            anData->state->looper, LOOPER_ID_USER, NULL, NULL);
+
+    //if (!priv->gyroscopeSensor)
+        //set accel only
+
 	ofusion_init(&priv->sensor_fusion);
 
 	return (ohmd_device*)priv;

+ 16 - 4
src/openhmd.c

@@ -113,11 +113,11 @@ OHMD_APIENTRYDLL int OHMD_APIENTRY ohmd_close_device(ohmd_device* device)
 	ohmd_context* ctx = device->ctx;
 	int idx = device->active_device_idx;
 
-	memmove(ctx->active_devices + idx, ctx->active_devices + idx + 1, 
+	memmove(ctx->active_devices + idx, ctx->active_devices + idx + 1,
 		sizeof(ohmd_device*) * (ctx->num_active_devices - idx - 1));
-	
+
 	device->close(device);
-	
+
 	ctx->num_active_devices--;
 
 	for(int i = idx; i < ctx->num_active_devices; i++)
@@ -221,7 +221,7 @@ int OHMD_APIENTRY ohmd_device_getf(ohmd_device* device, ohmd_float_value type, f
 
 		return OHMD_S_OK;
 	}
-		
+
 	default:
 		return device->getf(device, type, out);
 	}
@@ -309,6 +309,18 @@ int OHMD_APIENTRY ohmd_device_seti(ohmd_device* device, ohmd_int_value type, int
 	}
 }
 
+int OHMD_APIENTRY ohmd_device_set_data(ohmd_device* device, ohmd_data_value type, void* in);
+{
+    switch(type){
+    case OHMD_DRIVER_DATA:{
+        return OHMD_S_OK;
+    }
+    break;
+    default:
+        return OHMD_S_INVALID_PARAMETER;
+    }
+}
+
 void* ohmd_allocfn(ohmd_context* ctx, char* e_msg, size_t size)
 {
 	void* ret = calloc(1, size);

+ 4 - 2
src/openhmdi.h

@@ -66,7 +66,7 @@ typedef struct {
 		float znear;
 
 		int accel_only; //bool-like for setting acceleration only fallback (android driver)
-		
+
 		mat4x4f proj_left; // adjusted projection matrix for left screen
 		mat4x4f proj_right; // adjusted projection matrix for right screen
 } ohmd_device_properties;
@@ -79,9 +79,11 @@ struct ohmd_device {
 
 	int (*getf)(ohmd_device* device, ohmd_float_value type, float* out);
 	int (*setf)(ohmd_device* device, ohmd_float_value type, float* in);
-	
+
 	int (*seti)(ohmd_device* device, ohmd_int_value type, int in);
 
+	int (*set_data)(ohmd_device* device, ohmd_data_value type, void* in);
+
 	void (*update)(ohmd_device* device);
 	void (*close)(ohmd_device* device);