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 4e0b8b0
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
28 changes: 28 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,29 @@ 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) {
View* view = (View*) nativeView;
JniCallback *callback = JniCallback::make(env, handler, internalCallback);
view->pick(x, y, [callback, env, internalCallback](View::PickingQueryResult const& result) {

auto internalOnPickCallbackClass = env->FindClass("com/google/android/filament/View$InternalOnPickCallback");
auto renderableFieldId = env->GetFieldID(internalOnPickCallbackClass, "mRenderable", "I");
auto depthFieldId = env->GetFieldID(internalOnPickCallbackClass, "mDepth", "F");
auto fragCoordXFieldId = env->GetFieldID(internalOnPickCallbackClass, "mFragCoordsX", "F");
auto fragCoordYFieldId = env->GetFieldID(internalOnPickCallbackClass, "mFragCoordsY", "F");
auto fragCoordZFieldId = env->GetFieldID(internalOnPickCallbackClass, "mFragCoordsZ", "F");

env->SetIntField(internalCallback, renderableFieldId, (jint)result.renderable.getId());
env->SetFloatField(internalCallback, depthFieldId, result.depth);
env->SetFloatField(internalCallback, fragCoordXFieldId, result.fragCoords.x);
env->SetFloatField(internalCallback, fragCoordYFieldId, result.fragCoords.y);
env->SetFloatField(internalCallback, 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,63 @@ public DepthOfFieldOptions getDepthOfFieldOptions() {
return mDepthOfFieldOptions;
}

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

public interface OnPickCallback {
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 public int mRenderable;
public float mDepth;
public float mFragCoordsX;
public float mFragCoordsY;
public float mFragCoordsZ;
}

public long getNativeObject() {
if (mNativeObject == 0) {
Expand Down Expand Up @@ -1598,4 +1655,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 4e0b8b0

Please sign in to comment.