VertexAttributes.update () issue

Started by mxar, September 01, 2015, 09:34:35 AM

Previous topic - Next topic

mxar

Hi,

I want to render an OBJ object3d.
Part of the initialization code is:


GroupOfModels3D = Loader.loadOBJ(objStream, mtlStream, scale);
object3D = Object3D.mergeAll(GroupOfModels3D);
object3D.build();//<----- removing this line fixes the issue


GLSLShader blendingShader = new  GLSLShader( Loader.loadTextFile(res.openRawResource(R.raw.vertexshader)),Loader.loadTextFile(res.openRawResource(R.raw.fragmentshader)));

//assign vertex colors
int  numberOfVertices = object3D.getMesh().getUniqueVertexCount();

   
float[]     offScreenColorArray = new float[numberOfVertices * 4];

for (int i = 0; i < offScreenColorArray.length; i++) {

offScreenColorArray[i] = 0.0f;

if (i > 0) {

if (i % 4 == 0)
offScreenColorArray[i] = 0; //red color

if (i % 4 == 1)
offScreenColorArray[i] = 0;//green color

if (i % 4 == 2)
offScreenColorArray[i] = 1;//blue color

if (i % 4 == 3)
offScreenColorArray[i] = 1; //transparency
// 1-> opaque 0-> total
// transparent
}
}

        vattrs = new VertexAttributes("colorinfo",offScreenColorArray,VertexAttributes.TYPE_FOUR_FLOATS);
        vattrs.setDynamic(true);
        object3D.getMesh().addVertexAttributes(vattrs);
   


At the beginning the object is rendered without using the blendingShader GLSLShader with no problem.

But later on run time i want to use the blendingShader  with a different array of color (red ) like this one:

   

int numberOfVertices = object3D.getMesh().getUniqueVertexCount();

        for(int i = 0; i < fixedColor.length; i++){
       
        fixedColor[i] = 0.0f;
           
            if(i>0){
           
              if(i%4 == 0)
              fixedColor[i] = 1;//red color
             
              if(i%4 == 1)
              fixedColor[i] = 0; //green color
             
              if(i%4 == 2)
              fixedColor[i] = 0; //blue color
             
              if(i%4 == 3)
              fixedColor[i] = 1;   //transparency
            }
           
        }
      

After i assign the new color i call the following lines:


      vattrs.update(fixedColor, 0);
       
      object3D.setShader(blendingShader);


But in this case the object3D is rendered with blue color (offScreenColorArray) instead of red color (fixedColor)


After a lot of hours i found out that if i remove the call of object3D.build() at the beginning, the object3d is rendered with red color  (fixedcolor array)



The used shaders are:


//------------------------------- vertexshader -------------------------

attribute vec4 colorinfo;
uniform mat4 modelViewProjectionMatrix;
attribute vec4 position;
varying vec4 vertexColor;





void main(void)
{
     vertexColor = colorinfo;
     gl_Position = modelViewProjectionMatrix * position;

}




//-------------------------------- fragmentshader -------------------
varying vec4 theColor;
varying vec4 vertexColor;


void main(void)
{
gl_FragColor = vertexColor;
}


What is the problem?

Thanks in Advance

EgonOlsen

That's because the object has to be compiled in dynamic mode to be aware of changes to the vertex attributes. By default, jPCT compiles an object automagically based on the information it has about the object when you are calling build() on it. In this case, if you call build() right at the beginning, it isn't aware of the presence of vertex attributes, so it compiles it in static mode. If you don't call build(), the engine does so on it's own at render time. In that case, the vertex attributes are already there, so it chooses dynamic.
You have several options to deal with this:


  • Omit build() just as you did. I don't encourage people to do this, but it's an option.
  • Delay the call to build() to after assigning the vextex attributes.
  • Leave build() where it is and add a call to Object3D.compile(true); before calling build().

mxar


Thanks for your answer.

Is it possible to create and add an object3d in the world (world.add(Object3D)) while the the renderer is active ?.

In many cases I receive exception while i try to add an Object3d to the world.

Thanks in advance


EgonOlsen

Of course it is, but not from outside the rendering thread. Have a look here: http://www.jpct.net/wiki/index.php?title=Thread_safety

mxar


Hi,

thanks for the answer.

When you say rendering thread what you mean?
Do you have an example code?

It is safe to manipulate jPCT related instances (like instances of World, Object3D...)
inside the onDrawFrame() method?

In my application when I create  new Object3D model I added it in a queue (Vector) and in onDrawFrame() I read the queue .
If there is a pending Object3D model (not added in the World) then I call the method world.add(Object3D ).

The reading of queue is done before the world.draw(fb).

It is safe this way?

Thanks in advance

EgonOlsen

Yes, that's the rendering thread. It don't see how this can go wrong unless something is fishy with your queue. Which exception are you getting exactly?

mxar

Hi,

I will try to reproduce the issue again. I think happens only if the Object3dD model has texture.

A log info when the exception happens is:


D/ARRenderer(4310): world.draw() start

08-31 20:23:38.128: W/Adreno-ES20(4310): <core_glUseProgram:1525>: GL_INVALID_VALUE

08-31 20:23:38.128: I/jPCT-AE(4310): Creating buffers...

08-31 20:23:38.128: E/jPCT-AE(4310): [ 1441041818133 ] - ERROR: before: glError 1281

08-31 20:23:38.128: D/ARRenderer(4310): ################## world.draw exception ##################

08-31 20:23:38.128: D/ARRenderer(4310): world.draw() end

08-31 20:23:38.138: D/ARRenderer(4310): onSurfaceChanged start


08-31 20:23:38.138: D/ARRenderer(4310): onSurfaceChanged fb.dispose 1


The word.draw(fb) is in try/catch and when the exception happens the " ################## world.draw exception ##################" is printed.

I will  check again the source code.

Thanks in Advance


EgonOlsen

Strange. Are you fiddling around with OpenGL calls directly in your code somewhere? Or are your textures very large?

EgonOlsen

If you can reproduce it, try to der the Logger to debug and post the complete log. Please wrap the log in code-tags when posting it...it will be much more readable that way.

mxar


Hi,

one texture has side 2048x2048,two have 1024x512 and the 4 rest  have smaller.

But the same issue happens with smaller size textures.

I check carefully the code and i will try to reproduce it.

The application is built with vuforia library.

I noticed that the exception happens when the application has find the trucker (marker) at the same time the object3d model is added to the World.

If the application has not find the trucker (marker) at the time the model is added to World, but finds it after a few seconds, then there is no problem.

When an Augmented reality application finds a trucker (marker) then draws the object3d model.


Thanks for your time

I will post the complete log when i reproduce the exception again.


EgonOlsen

Maybe Vuforia causes some GL error that it doesn't catch. In that case, simply adding a new object triggers a check from jPCT when the object gets compiled, but that doesn't mean that the error actually happens there. GL will store such errors forever as long as nobody checks for them.
If you are sure that the app works fine otherwise, try to set Config.glIgnoreErrors to true. You might need the latest beta for that: jpct.de/download/beta/jpct_ae.jar

mxar

Thanks,

perhaps some direct OpenGL calls from Vuforia cause the exception.
Part of Vuforia source code in my application calls directly some OpenGL methods

I will search deeply in my source code to address the issue.

I will inform you for the results.

Thanks for your time

mxar

Hi
I finally found a way to solve the problem.

When I create a Object3D  i dont add it directly to the world calling the world.add(Object3D).

I call an AsyncTask having the following code

         @Override
         protected String doInBackground(Augmented3dModel... arg0) {
         
         
AR3dModel ar3dModel = arg0[0];
         
                    try {
                                 Thread.sleep(200);
                                 ar3dModel .shouldBeAdded = true;
                             } catch (InterruptedException e) {
                               Thread.interrupted();
                             }
                     return null;
                  }

                            In the OnDrawFrame i added the following code:


                                 if(ar3dModel .shouldBeAdded == true){
                                   world.add( ar3dModel .getObject3d());//adds the created Object3D
                                   ar3dModel .shouldBeAdded = false;
                                 }
               


AR3dModel  is a wrapper class of the Object3D.

Perhaps the delay of 200ms helps to fix the problem.


Best Regards

EgonOlsen

Sounds...hacky...but if it solves the problem (I've just no idea why...)...