I guess if you provide a copy past like test we can run, the feedback may be better. At least that worked for me the past few times I had grafic issues. @nehon normally helps with those graphic glitches or missbehaviour.
So it’s entierly up to you…
It is simple - i forgot something, someone pspeed pointed it out, i added it - problem solved - the rest was pretty unnecessary. Enough of this. Thanks to those trying to help
Hi there, sorry to bother you again. I had the chance now to try it on Android/Google Tango. As I feared,
the camera preview is occluded by a black area when switching off clearFlags in the second viewport. This time you’ll get a complete minimal code sample from me Hope someone can help. Here is again what I do:
NOTE: This doesn’t happen without glow activated!
adding a CameraPreview and rendering the Scene, GUI and Nifty GUI in front of it. I think having a look into Main, GUI and MainActivity should be sufficient, but I added the other classed as well, all reduced to a minimum.
Thanks for having a look
Main:
public class Main extends SimpleApplication {
private IJmeToAndroid androidHarness;
public static Main app;
public GUI gui;
public Node camNode;
public static void main(String[] args)
{
Main.app = new Main();
app.showSettings = false; // Don't use settings window
// Set settings
AppSettings appSettings = new AppSettings(true);
appSettings.put("Width", 800);appSettings.put("Height", 480);
appSettings.setSamples(4); // Antialiasing
appSettings.put("Title", "ARNetRayX"); // Title
app.setSettings(appSettings);
app.start();
}
@Override
public void simpleInitApp()
{
this.app = this;
// GLOW
FilterPostProcessor fpp=new FilterPostProcessor(assetManager);
BloomFilter bloom = new BloomFilter(BloomFilter.GlowMode.Objects);
fpp.addFilter(bloom);
viewPort.addProcessor(fpp);
setUpCamera();
setPlatformDependentStuff(); // Platform specific
gui = setUpGUI();
Box b = new Box(1,1,1);
Geometry g = new Geometry("box", b);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Blue);
g.setMaterial(mat);
rootNode.attachChild(g);
}
@Override
public void simpleUpdate(float tpf)
{
// TODO
}
private void setPlatformDependentStuff() {
androidHarness = getAndroidHarness(); // get android harness
// harness == null --> DESKTOP
// harness != null --> ANDROID/TANGO
if (androidHarness != null) {
// TODO
} else {
// --------------------------------------------------------- DESKTOP
cam.setLocation(new Vector3f(-6, 3, 6));
cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
}
}
private GUI setUpGUI() {
GUI gui = new GUI(assetManager, inputManager, audioRenderer,
guiViewPort, cam, this, guiNode, guiFont);
// Move GUI node behind Nifty
guiViewPort.attachScene(guiNode);
guiNode.setQueueBucket(Bucket.Gui);
Camera guiCam = new Camera(settings.getWidth(), settings.getHeight());
ViewPort guiViewPort2 = renderManager
.createPostView("Gui 2 Default", guiCam);
guiViewPort2.addProcessor(gui.getNiftyDisplay());
guiViewPort2.setClearFlags(false, false, false);
return gui;
}
private void setUpCamera() {
cam.setFrustumPerspective(
45f, (float) cam.getWidth() / cam.getHeight(), 0.01f, 100f);
flyCam.setDragToRotate(true);
}
public IJmeToAndroid getAndroidHarness()
{
return this.androidHarness;
}
public void setAndroidHarnessListener(IJmeToAndroid harness)
{
this.androidHarness = harness;
}
}
GUI:
public final class GUI {
// .............................................................. ATTRIBUTES
private final Nifty nifty;
private final Node guiNode;
private final Picture hud2;
public static final int LAYER_LABEL_BG = 0;
public static final int LAYER_LABEL = 1;
private final NiftyJmeDisplay niftyDisplay;
// ............................................................. CONSTRUCTOR
public GUI (AssetManager assets, InputManager inputs, AudioRenderer audio,
ViewPort guiViewPort, Camera cam, Main app,
Node guiNode, BitmapFont guiFont)
{
this.guiNode = guiNode;
niftyDisplay
= new NiftyJmeDisplay(assets, inputs, audio, guiViewPort);
nifty = this.niftyDisplay.getNifty();
nifty.fromXml("Interface/MainMenu.xml",
"start", new MainMenu(nifty));
guiViewPort.addProcessor(niftyDisplay);
hud2 = new Picture("hud2_bg");
hud2.setImage(assets, "Textures/hud2.png", true);
setPlatformDependentStuff();
}
private void setPlatformDependentStuff() {
if(GlobalSettings.ON_TANGO) {
hud2.setWidth(400f/800f*1920f);
hud2.setHeight(171f/480f*1080f);
hud2.setPosition(0,0);
} else {
hud2.setWidth(400f);
hud2.setHeight(171f);
hud2.setPosition(0,0);
}
guiNode.attachChild(hud2);
}
public SceneProcessor getNiftyDisplay() {
return niftyDisplay;
}
}
MainActivity:
public class MainActivity extends AndroidHarness implements IJmeToAndroid {
private static final String TAG = "ARNetRayXMainActivity";
private TangoTrackingProvider tracking; // Tracking
private Config _config; // Android Specific
private SettingsFragment _settings;
private TangoCameraPreview tangoCameraPreview;
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CONSTRUCTOR
public MainActivity() {
appClass = "de.imld.basic3d.Main";
eglBitsPerPixel = 24;
eglAlphaBits = 8;
eglDepthBits = 16;
eglSamples = 2;
eglStencilBits = 0;
frameRate = -1;
joystickEventsEnabled = false;
keyEventsEnabled = true;
mouseEventsEnabled = true;
finishOnAppStop = true;
handleExitHook = true;
exitDialogTitle = "Do you want to exit?";
exitDialogMessage = "Use your home key to bring this app into the"
+ "background or exit to terminate it.";
screenFullScreen = true;
splashPicID = 0;
}
// ################################################################# METHODS
@Override
public void onCreate(Bundle savedInstanceState) {
GlobalSettings.RES_X = 1920; // Tango Resolution
GlobalSettings.RES_Y = 1080;
GlobalSettings.ON_TANGO=true;
super.onCreate(savedInstanceState);
this._settings = new SettingsFragment();
_config = new ConfigNativeAndroid();
// Check wether app object exists, app contains main JME class instance
if(app != null) {
// Main is JME's main class and has a harness listener
// Main extends Application
Log.i(TAG, "Main Class Instance is available");
((Main) app).setAndroidHarnessListener(this);
}
// --------------------------------------------------------------- tango
try {
tracking = new TangoTrackingProvider();
((TangoTrackingProvider)tracking).layoutDisplay(tangoCameraPreview);
} catch (Exception e) {
// TODO
}
startActivityForResult(Tango.getRequestPermissionIntent(
Tango.PERMISSIONTYPE_MOTION_TRACKING),
Tango.TANGO_INTENT_ACTIVITYCODE);
}
@Override
protected void onResume() {
super.onResume();
tracking.resume();
}
@Override
protected void onPause() {
super.onPause();
tracking.pause();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
// ######################################### IJmeToAndroid INTERFACE METHODS
public TangoTrackingProvider getTrackingProvider() {
return this.tracking;
}
public Config getConfig() {
return this._config;
}
// ######################################################## Activity METHODS
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.addToBackStack(null)
.commit();
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.settings, menu);
return true;
}
/**
* Setting up the app layout. This method runs before onCreate()!
*/
@Override
public void layoutDisplay()
{
setContentView(R.layout.main); // Read from res/layout/main.xml
FrameLayout preview = (FrameLayout) findViewById(R.id.cameraPreview);
tangoCameraPreview = new TangoCameraPreview(this);
preview.addView(tangoCameraPreview);
preview.addView(view); //Add JME view which is called in Main.java
setContentView(preview);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request we're responding to
if (requestCode == Tango.TANGO_INTENT_ACTIVITYCODE) {
// Make sure the request was successful
if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "Motion Tracking Permissions Required!",
Toast.LENGTH_SHORT).show();
finish();
} else {
((TangoTrackingProvider) tracking).startCameraPreview();
((TangoTrackingProvider) tracking).mIsPermissionGranted = true;
}
}
}
}
TangoTrackingProvider:
public class TangoTrackingProvider implements ITrackingProvider {
// ############################################################## ATTRIBUTES
Handler mainHandler;
public static final float SCALE = 1;
// Tango
private TangoConfig config;
private TangoCameraPreview tangoCameraPreview;
private Tango tango;
private boolean mIsConnected;
public boolean mIsPermissionGranted;
// ############################################################# CONSTRUCTOR
public TangoTrackingProvider()
{
this.mainHandler = new Handler(App.getContext().getMainLooper());
// Instantiate Tango client
this.tango = new Tango(App.getContext());
this.config = tango.getConfig(TangoConfig.CONFIG_TYPE_CURRENT);
}
// .......................................................... PAUSE & RESUME
public void pause() {
try {
if (mIsConnected) {
tango.disconnect();
tangoCameraPreview.disconnectFromTangoCamera();
mIsConnected = false;
}
} catch (TangoErrorException e) {
Toast.makeText(App.getContext(), "Tango Error!",
Toast.LENGTH_SHORT).show();
}
}
public void resume() {
if (!mIsConnected && mIsPermissionGranted) {
try {
setTangoListeners();
} catch (TangoErrorException e) {
Toast.makeText(App.getContext(), "Tango Error! Restart the app!",
Toast.LENGTH_SHORT).show();
}
try {
tango.connect(config);
startCameraPreview();
} catch (TangoOutOfDateException e) {
Toast.makeText(App.getContext(),
"Tango Service out of date!", Toast.LENGTH_SHORT)
.show();
} catch (TangoErrorException e) {
Toast.makeText(App.getContext(),
"Tango Error! Restart the app!", Toast.LENGTH_SHORT)
.show();
}
}
}
// ################################################################# METHODS
// Camera Preview
public void startCameraPreview() {
// Connect to color camera
tangoCameraPreview.connectToTangoCamera(tango,
TangoCameraIntrinsics.TANGO_CAMERA_COLOR);
// Use default configuration for Tango Service.
tango.connect(config);
mIsConnected = true;
setTangoListeners();
}
private void setTangoListeners() {
// Select coordinate frame pairs
ArrayList<TangoCoordinateFramePair> framePairs
= new ArrayList<TangoCoordinateFramePair>();
framePairs.add(new TangoCoordinateFramePair(
TangoPoseData.COORDINATE_FRAME_AREA_DESCRIPTION,
TangoPoseData.COORDINATE_FRAME_DEVICE));
// Add a listener for Tango pose data
tango.connectListener(framePairs, new TangoUpdateListener(tangoCameraPreview));
}
public Tango getTango() {
return tango;
}
/**
* Must be called in {@link MainActivity} in onCreate()
* @param preview
*/
public void layoutDisplay(TangoCameraPreview preview) {
this.tangoCameraPreview = preview;
}
public void addListener(TrackingListener tl) {
// TODO
}
public TrackingUpdate getCurrent() {
return null;
}
}
TangoUpdateListener:
public class TangoUpdateListener implements OnTangoUpdateListener {
private final TangoCameraPreview tangoCameraPreview;
public TangoUpdateListener(TangoCameraPreview tangoCameraPreview) {
this.tangoCameraPreview = tangoCameraPreview;
}
@SuppressLint("DefaultLocale")
@Override
public void onPoseAvailable(TangoPoseData pose) {
// TODO
}
@Override
public void onXyzIjAvailable(TangoXyzIjData xyzIj) {
// TODO
}
@Override
public void onTangoEvent(TangoEvent arg0) {
// TODO
}
@Override
public void onFrameAvailable(int cameraId) {
if (cameraId == TangoCameraIntrinsics.TANGO_CAMERA_COLOR) {
tangoCameraPreview.onFrameAvailable(); // update camera preview
}
}
}
Do you need any additional information? I’m pretty desperate
Hope someone has an idea.
Cheers,
Gem
Not a good enlightened answer, but do you really need the glow filter and can’t bake the effect instead?
hi loopies,
i would really like to use it. have no idea how to “bake” it on my own.
Kind of depends what you want to see glow. If it’s only elements of the gui then you could simply use a texture that displays like a glow. Now, if we talking making “random” geometries in the scene glow, then that would be harder to bake, I guess. Sorry not really competent here, just making sure you didn’t miss a possible solution.
NB: I avoid all such effects like the pest on android because they are costly and may not be supported by some phones… at the same time I have no knowledge of the inner workings and haven’t tested the performances.
I need very complex 3d objects to glow. I guess it’s best to use the standard way. I recognized, that behind transparent gui images its not occluded, so i tried to fill the screen with a completely transparent image. and it worked.
a dirty solution, but working.
EDIT: not working - only when its not completely transparent, then it’s kinda working - but not perfect
EDIT2: works up to 50%, not further
And that work on a PC? Isn’t it possible to reproduce it in single simple app? If the answer is no then find out what is different, if the answer is yes the masters among us (sorry not me) can then maybe help better or some one with android under his belt.
Just some how you have to track down the problem to a point. Maybe a intermediate solution is: use a high alpha for your gui img?!
Already tried that image thing. It works up to 50% transparency and then it’s getting worse again.
On the PC there is no problem. It’s only on android, because there I have to place the video as an Android Surface behind the rendered scene. And somehow the glow filter draws the background black, so I can’t see the video image anymore.
Then I would write some thing very simple which fits in one class, like the beginners section, so we just can copy paste run and see. And maybe it is then not reproducable and from this point you just need to find the 10 differeces. At least I try to track down a problem that way.
And sorry I have no android knowhow so I can not help beside the general suggestions above.
Just to be clear… on the PC you also have the video? Or the video is only on Android?
I don’t think that FPP will work if you want to use video as a background because you somehow have to get the video content into the FPP. Not sure what the alteratives are on Android at this point. At first I thought maybe rendering your scene to a texture and overlaying that but I think we don’t transfer alpha through anymore like we used to (when using FPP)… that’s true on desktop also.
No, video is for android only.
unfortunately it’s not getting much simpler because of the tango stuff - but I could try making a simpler example with normal android camera overlay
Ok, I made a minimal example which should work on any android phone. The MainActivity code is long - but most of it not interesting for you - but you need it to work.
Main.java: simply adds a blue cube and the glow filter
public class Main extends SimpleApplication
{
private IJmeToAndroid _harness;
public static void main(String[] args)
{
Main app = new Main();
app.start();
}
@Override
public void simpleInitApp()
{
_harness = getHarness();
FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
BloomFilter bloom = new BloomFilter(BloomFilter.GlowMode.Objects);
fpp.addFilter(bloom);
viewPort.addProcessor(fpp);
Box b = new Box(1f, 1f, 1f);
Geometry geom = new Geometry("Box", b);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Blue);
mat.setColor("GlowColor", ColorRGBA.Blue);
geom.setMaterial(mat);
rootNode.attachChild(geom);
}
@Override
public void simpleUpdate(float tpf) {}
@Override
public void simpleRender(RenderManager rm) {}
public IJmeToAndroid getHarness() {
return this._harness;
}
public void setHarnessListener(IJmeToAndroid harness) {
this._harness = harness;
}
}
IJmeToAndroid: Interface to access android activity from Main
public interface IJmeToAndroid {
public Config getConfig();
}
MainActivity for Android: uses a second Activity with a surface to underlay the camera preview
/**
*
* @author http://hub.jmonkeyengine.org/t/augmented-reality-jmonkey/23699/6
*/
public class MainActivity extends AndroidHarness implements IJmeToAndroid {
private Camera mCamera;
private ARCameraActivity _preview;
private Config _config;
public MainActivity(){
appClass = "de.imld.basic3d.Main";
eglBitsPerPixel = 24;
eglAlphaBits = 8;
eglDepthBits = 16;
eglSamples = 2;
eglStencilBits = 0;
frameRate = -1;
joystickEventsEnabled = false;
keyEventsEnabled = true;
mouseEventsEnabled = true;
finishOnAppStop = true;
handleExitHook = true;
exitDialogTitle = "Do you want to exit?";
exitDialogMessage = "Home = Background, Exit = Terminate";
screenFullScreen = true;
splashPicID = 0;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (app != null) ((Main)app).setHarnessListener(this);
_config = new ConfigNativeAndroid();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.settings, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.addToBackStack(null).commit();
return true;
}
public Config getConfig() {
return _config;
}
public class SettingsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
Preference button = (Preference) getPreferenceManager().findPreference("exitlink");
if (button != null) {
button.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference arg0) {
if (getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
}
return true;
}
});
}
}
}
@Override
public void layoutDisplay() {
setContentView(R.layout.main);
_preview = new ARCameraActivity(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(id.cameraPreview);
preview.addView(_preview);
preview.addView(view);
}
public class ARCameraActivity extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private boolean started;
private Camera mCamera;
private List<Camera.Size> mSupportedPreviewSizes;
public ARCameraActivity(Context context, Camera camera){
super(context);
started = false;
mCamera = camera;
if (mCamera == null) mCamera = getCameraInstance();
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int suggestedWidth = getSuggestedMinimumWidth();
int suggestedHeight = getSuggestedMinimumHeight();
final int width = resolveSize(suggestedWidth, widthMeasureSpec);
final int height = resolveSize(suggestedHeight, heightMeasureSpec);
setMeasuredDimension(width, height);
}
public void surfaceCreated(SurfaceHolder holder) {
try {
if (mCamera != null) {
Camera.Parameters parameters = mCamera.getParameters();
//parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
parameters.setPreviewSize(1280, 720);
parameters.setPictureSize(1280, 720);
mCamera.setParameters(parameters);
mCamera.setPreviewDisplay(holder);
}
} catch (IOException e) {}
}
public void surfaceDestroyed(SurfaceHolder holder) {
try {
stop();
} catch (Exception e) {}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mHolder.getSurface() == null) {
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {}
try {
Camera.Parameters parameters = mCamera.getParameters();
//parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
parameters.setPreviewSize(1280, 720);
parameters.setPictureSize(1280, 720);
mCamera.setParameters(parameters);
start();
} catch (Exception e) {}
}
private Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open();
} catch (Exception e) {}
return c;
}
public void start() {
if (!started) {
mCamera.startPreview();
started = true;
}
}
public void stop() {
if (mCamera != null) {
mCamera.stopPreview();
// even though it is before
mCamera.release();
started = false;
mCamera = null;
}
}
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onPause() {
super.onPause();
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
}
And at least the layout file which goes into: /project/android/res/layout/main.xml
<?xml version="1.0" encoding="UTF-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/cameraPreview" android:layout_height="fill_parent" android:layout_width="fill_parent" android:orientation="vertical">
<!--<fragment android:id="@+id/jmeFragment" android:layout_height="match_parent" android:layout_width="match_parent" android:name="com.mycompany.mygame.MainActivity$JmeFragment"/> -->
</FrameLayout>
And again, thank you so much for your time.
right there is your first mistake …
what do you mean?