strange render behavior

Started by kelmer, January 20, 2013, 03:37:38 PM

Previous topic - Next topic

kelmer

I have this obj model of a building, which I tried both on the jpct and jpct-ae helloworld demos, with good results:



Now if I try this same model in my vuforia - jpct-ae integration it shows up like this, with some meshes overlapping others:



I tried another obj model in the vuforia+jpct-ae and it rendered without this problem.

The piece of code used to load and render the model is the same in both cases:


                     torre = Loader.loadOBJ(mActivity.getResources().openRawResource(R.raw.torresola), mActivity.getResources().openRawResource(R.raw.torremat), 10.0f);
torreSingle = Object3D.mergeAll(torre);
world.addObject(torreSingle);


Also, i'm posting Vuiforia's demo own config chooser, maybe that's were the problem is. Or maybe its because the use of OpenGL ES 2.0?

/*==============================================================================
            Copyright (c) 2010-2012 QUALCOMM Austria Research Center GmbH.
            All Rights Reserved.
            Qualcomm Confidential and Proprietary
==============================================================================*/

package com.qualcomm.QCARSamples.ImageTargets;

import com.qualcomm.QCAR.QCAR;

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 android.content.Context;
import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView;

/**
* QCARSampleGLView is a support class for the QCAR samples applications.
* Responsible for setting up and configuring the OpenGL surface view.
*/
public class QCARSampleGLView extends GLSurfaceView {
private static boolean mUseOpenGLES2 = true;

/** Constructor. */
public QCARSampleGLView(Context context) {
super(context);
}

/** Initialization. */
public void init(int flags, boolean translucent, int depth, int stencil) {
// By default GLSurfaceView tries to find a surface that is as close
// as possible to a 16-bit RGB frame buffer with a 16-bit depth buffer.
// This function can override the default values and set custom values.

// Extract OpenGL ES version from flags
mUseOpenGLES2 = (flags & QCAR.GL_20) != 0;

// 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.

DebugLog.LOGI("Using OpenGL ES " + (mUseOpenGLES2 ? "2.0" : "1.x"));
DebugLog.LOGI("Using " + (translucent ? "translucent" : "opaque") + " GLView, depth buffer size: " + depth + ", stencil size: " + stencil);

// If required set translucent format to allow camera image to
// show through in the background
if (translucent) {
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
}
// Setup the context factory for 1.x / 2.0 rendering
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));


}

/** Creates OpenGL contexts. */
private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;

public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
EGLContext context;
if (mUseOpenGLES2) {
DebugLog.LOGI("Creating OpenGL ES 2.0 context");
checkEglError("Before eglCreateContext", egl);
int[] attrib_list_gl20 = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list_gl20);
} else {
DebugLog.LOGI("Creating OpenGL ES 1.x context");
checkEglError("Before eglCreateContext", egl);
int[] attrib_list_gl1x = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL10.EGL_NONE };
context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list_gl1x);
}

checkEglError("After eglCreateContext", egl);
return context;
}

public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
egl.eglDestroyContext(display, context);
}
}

/** Checks the OpenGL error. */
private static void checkEglError(String prompt, EGL10 egl) {
int error;
while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
DebugLog.LOGE(String.format("%s: EGL error: 0x%x", prompt, error));
}
}

/** The config chooser. */
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;
}

private EGLConfig getMatchingConfig(EGL10 egl, EGLDisplay display, int[] configAttribs) {
// Get the number of minimally matching EGL configurations
int[] num_config = new int[1];
egl.eglChooseConfig(display, configAttribs, null, 0, num_config);

int numConfigs = num_config[0];
if (numConfigs <= 0)
throw new IllegalArgumentException("No matching EGL configs");

// Allocate then read the array of minimally matching EGL configs
EGLConfig[] configs = new EGLConfig[numConfigs];
egl.eglChooseConfig(display, configAttribs, configs, numConfigs, num_config);

// Now return the "best" one
return chooseConfig(egl, display, configs);
}

public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
if (mUseOpenGLES2) {
// This EGL config specification is used to specify 2.0
// rendering. We use a minimum size of 4 bits for
// red/green/blue, but will perform actual matching in
// chooseConfig() below.
final int EGL_OPENGL_ES2_BIT = 0x0004;
final int[] s_configAttribs_gl20 = { EGL10.EGL_RED_SIZE, 4, EGL10.EGL_GREEN_SIZE, 4, EGL10.EGL_BLUE_SIZE, 4, EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL10.EGL_NONE };

return getMatchingConfig(egl, display, s_configAttribs_gl20);
} else {
final int EGL_OPENGL_ES1X_BIT = 0x0001;
final int[] s_configAttribs_gl1x = { EGL10.EGL_RED_SIZE, 5, EGL10.EGL_GREEN_SIZE, 6, EGL10.EGL_BLUE_SIZE, 5, EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES1X_BIT, EGL10.EGL_NONE };

return getMatchingConfig(egl, display, s_configAttribs_gl1x);
}
}

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;
}

// 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];
}
}


EDIT: correction: it does happen with other models as well.

EgonOlsen

Is some transparency enabled on this object (this can be part of the file, try to set it to -1 explicitly)? Either that, or the config that your config chooser creates has no depth buffer enabled.

kelmer

The Config chooser is saying my depth buffer size is 16 so I guess it's activated.

The objects themselves shouldn't have any transparency, they load nicely in the helloworld demo. Anyway I tried setting it to -1 as you said, but it changed nothing...

EgonOlsen

But there obviously is no depth buffering present... ??? Have you verified that your returned config really uses a depth of anything but 0?

kelmer

I just checked... after calling init() my depthBuffer is still 16... I used Eclipse's debug mode to check. Don't know if there's a better/more reliable way to check this.

[attachment deleted by admin]

EgonOlsen

Just check which value 'd' has right before the return in this line:


if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize)  {
   //check for d here
   return config;
}

kelmer


EgonOlsen

Have you tried without that ConfigChooser?

kelmer

I tried to use this one:
setEGLConfigChooser(5,6,5,0,16,0);

but I get a crash on the ContextFactory:

01-21 15:04:31.037: I/QCAR(8209): Creating OpenGL ES 2.0 context
01-21 15:04:31.045: W/dalvikvm(8209): threadid=14: thread exiting with uncaught exception (group=0x41cef930)
01-21 15:04:31.045: E/AndroidRuntime(8209): FATAL EXCEPTION: GLThread 760
01-21 15:04:31.045: E/AndroidRuntime(8209): java.lang.RuntimeException: createContext failed: EGL_SUCCESS
01-21 15:04:31.045: E/AndroidRuntime(8209): at android.opengl.GLSurfaceView$EglHelper.throwEglException(GLSurfaceView.java:1193)
01-21 15:04:31.045: E/AndroidRuntime(8209): at android.opengl.GLSurfaceView$EglHelper.throwEglException(GLSurfaceView.java:1184)
01-21 15:04:31.045: E/AndroidRuntime(8209): at android.opengl.GLSurfaceView$EglHelper.start(GLSurfaceView.java:1034)
01-21 15:04:31.045: E/AndroidRuntime(8209): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1401)
01-21 15:04:31.045: E/AndroidRuntime(8209): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)


I'm not sure I follow understand how this initialization process works.  :-\

EgonOlsen

Just omit that whole setConfigChooser-stuff. The alpha background might not work then, but at least it should be possible to see if the problem is caused by the chooser.

EgonOlsen

Another interesting thing to know would be if this happens on all devices and if not, on which devices it does.

kelmer

#11
I tried removing that line but I get the same crash...

I get this problem both on my Galaxy Nexus and on my tablet (with 4.0.3).

The tablet throws this error to LogCat constantly (although it seems to be working exactly the same as the nexus):

01-21 17:29:29.409: E/SurfaceTexture(2074): [unnamed-2074-3] dequeueBuffer: no available buffer slots

EgonOlsen

Then maybe it's not the depth buffer but the culling? It's hard to tell from that screen shot...maybe the matrix you are using inverts the culling...you might want to try to set invertCulling(true) on the object. 

kelmer

Okay this is now getting weird. I tried this config:

mGlView = new GLSurfaceView(this.getApplication());

//mGlView.init(mQCARFlags, translucent, depthSize, stencilSize);
mGlView.setEGLContextClientVersion(2);
mGlView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);

mRenderer = new ImageTargetsRenderer(this);
mGlView.setRenderer(mRenderer);


Both in HelloWorld demo and this app. The HelloWorld demo still showed the model perfectly, and the latter one still showed the same problem.

EDIT: while I was posting you replied, so I tried inverting Culling, and disabling/enabling it, to no avail.

kelmer

Here are a couple more screenshots.



The second one is a ship, that's supposed to be seen from below. Here's the proper model: