Skip to content

Commit

Permalink
added support for picking queries in java
Browse files Browse the repository at this point in the history
  • Loading branch information
pixelflinger committed Sep 29, 2021
1 parent c0c0bb1 commit 0a67956
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 0 deletions.
3 changes: 3 additions & 0 deletions android/common/CallbackUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ struct JniCallback {

static void invoke(void* user);

jobject getCallbackObject() { return mCallback; }
JNIEnv* getJniEnv() { return mEnv; }

private:
JniCallback(JNIEnv* env, jobject handler, jobject runnable);
JniCallback(JniCallback const &) = delete;
Expand Down
40 changes: 40 additions & 0 deletions android/filament-android/src/main/cpp/View.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include <filament/View.h>
#include <filament/Viewport.h>

#include "common/CallbackUtils.h"

using namespace filament;

extern "C" JNIEXPORT void JNICALL
Expand Down Expand Up @@ -382,3 +384,41 @@ Java_com_google_android_filament_View_nIsScreenSpaceRefractionEnabled(JNIEnv *,
View* view = (View*) nativeView;
return (jboolean)view->isScreenSpaceRefractionEnabled();
}

extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nPick(JNIEnv* env, jclass clazz,
jlong nativeView,
jint x, jint y, jobject handler, jobject internalCallback) {

// jniState will be initialized the first time this method is called
static const struct JniState {
jclass internalOnPickCallbackClass;
jfieldID renderableFieldId;
jfieldID depthFieldId;
jfieldID fragCoordXFieldId;
jfieldID fragCoordYFieldId;
jfieldID fragCoordZFieldId;
explicit JniState(JNIEnv* env) noexcept {
internalOnPickCallbackClass = env->FindClass("com/google/android/filament/View$InternalOnPickCallback");
renderableFieldId = env->GetFieldID(internalOnPickCallbackClass, "mRenderable", "I");
depthFieldId = env->GetFieldID(internalOnPickCallbackClass, "mDepth", "F");
fragCoordXFieldId = env->GetFieldID(internalOnPickCallbackClass, "mFragCoordsX", "F");
fragCoordYFieldId = env->GetFieldID(internalOnPickCallbackClass, "mFragCoordsY", "F");
fragCoordZFieldId = env->GetFieldID(internalOnPickCallbackClass, "mFragCoordsZ", "F");
}
} jniState(env);

View* view = (View*) nativeView;
JniCallback *callback = JniCallback::make(env, handler, internalCallback);
view->pick(x, y, [callback](View::PickingQueryResult const& result) {
jobject obj = callback->getCallbackObject();
JNIEnv* const env = callback->getJniEnv();
env->SetIntField(obj, jniState.renderableFieldId, (jint)result.renderable.getId());
env->SetFloatField(obj, jniState.depthFieldId, result.depth);
env->SetFloatField(obj, jniState.fragCoordXFieldId, result.fragCoords.x);
env->SetFloatField(obj, jniState.fragCoordYFieldId, result.fragCoords.y);
env->SetFloatField(obj, jniState.fragCoordZFieldId, result.fragCoords.z);
JniCallback::invoke(callback); // this destroys JniCallback
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -1548,6 +1548,71 @@ public DepthOfFieldOptions getDepthOfFieldOptions() {
return mDepthOfFieldOptions;
}

/**
* A class containing the result of a picking query
*/
public static class PickingQueryResult {
/** The entity of the renderable at the picking query location */
@Entity public int renderable;
/** The value of the depth buffer at the picking query location */
public float depth;
/** The fragment coordinate in GL convention at the the picking query location */
@NonNull public float[] fragCoords = new float[3];
};

/**
* An interface to implement a custom class to receive results of picking queries.
*/
public interface OnPickCallback {
/**
* onPick() is called by the specified Handler in {@link View#pick} when the picking query
* result is available.
* @param result An instance of {@link PickingQueryResult}.
*/
void onPick(@NonNull PickingQueryResult result);
}

/**
* Creates a picking query. Multiple queries can be created (e.g.: multi-touch).
* Picking queries are all executed when {@link Renderer#render} is called on this View.
* The provided callback is guaranteed to be called at some point in the future.
*
* Typically it takes a couple frames to receive the result of a picking query.
*
* @param x Horizontal coordinate to query in the viewport with origin on the left.
* @param y Vertical coordinate to query on the viewport with origin at the bottom.
* @param handler An {@link java.util.concurrent.Executor Executor}.
* On Android this can also be a {@link android.os.Handler Handler}.
* @param callback User callback executed by <code>handler</code> when the picking query
* result is available.
*/
public void pick(int x, int y,
@Nullable Object handler, @Nullable OnPickCallback callback) {
InternalOnPickCallback internalCallback = new InternalOnPickCallback(callback);
nPick(getNativeObject(), x, y, handler, internalCallback);
}

private static class InternalOnPickCallback implements Runnable {
public InternalOnPickCallback(OnPickCallback mUserCallback) {
this.mUserCallback = mUserCallback;
}
@Override
public void run() {
mPickingQueryResult.renderable = mRenderable;
mPickingQueryResult.depth = mDepth;
mPickingQueryResult.fragCoords[0] = mFragCoordsX;
mPickingQueryResult.fragCoords[1] = mFragCoordsY;
mPickingQueryResult.fragCoords[2] = mFragCoordsZ;
mUserCallback.onPick(mPickingQueryResult);
}
private final OnPickCallback mUserCallback;
private final PickingQueryResult mPickingQueryResult = new PickingQueryResult();
@Entity int mRenderable;
float mDepth;
float mFragCoordsX;
float mFragCoordsY;
float mFragCoordsZ;
}

public long getNativeObject() {
if (mNativeObject == 0) {
Expand Down Expand Up @@ -1598,4 +1663,5 @@ private static native void nSetDepthOfFieldOptions(long nativeView, float cocSca
private static native boolean nIsShadowingEnabled(long nativeView);
private static native void nSetScreenSpaceRefractionEnabled(long nativeView, boolean enabled);
private static native boolean nIsScreenSpaceRefractionEnabled(long nativeView);
private static native void nPick(long nativeView, int x, int y, Object handler, InternalOnPickCallback internalCallback);
}

0 comments on commit 0a67956

Please sign in to comment.