Viable engine?

Started by MrAdam, May 02, 2012, 05:04:46 PM

Previous topic - Next topic

MrAdam


MrAdam

Okay, got the new version in. Only one slight problem:

model = Loader.loadSerializedObjectArray(getAssets().open("modern.png"));
world.addObjects(model);
world.compileAllObjects();

As Loader.loadSerializedObjectArray() is threaded, I am of course getting a null pointer exception due to the model not being loaded yet when it runs world.addObjects(). I have yet been able to find a way to check if the loading has finished.

EgonOlsen

Loader.loadSerializedObjectArray()  isn't threaded...nothing is threaded in the engine... ???


MrAdam

Quote from: EgonOlsen on May 25, 2012, 10:01:56 AM
Loader.loadSerializedObjectArray()  isn't threaded...nothing is threaded in the engine... ???
Well, I just did a while(model == null){}
No null pointers now ^^

EgonOlsen

Ok, but that doesn't make any sense...there are no threads involved. And even if there were...you can't change a returned instance afterwards, i.e. if it returns null, it will stay null forever. So this loop will never be entered if the loading goes fine and it will never terminate if null will be returned.

Maybe it's something else...are you trying to render the model while still loading/adding it? Can you post the null pointer exception you are getting?

MrAdam

#65
Quote from: EgonOlsen on May 25, 2012, 10:32:15 AM
Ok, but that doesn't make any sense...there are no threads involved. And even if there were...you can't change a returned instance afterwards, i.e. if it returns null, it will stay null forever. So this loop will never be entered if the loading goes fine and it will never terminate if null will be returned.

Maybe it's something else...are you trying to render the model while still loading/adding it? Can you post the null pointer exception you are getting?
This is happening at application launch and when user changes application language, way before the activity with the 3D part.
Here's the error:
05-25 10:46:42.650: E/AndroidRuntime(4411): FATAL EXCEPTION: Thread-949
05-25 10:46:42.650: E/AndroidRuntime(4411): java.lang.NullPointerException
05-25 10:46:42.650: E/AndroidRuntime(4411): at bmw.makeityours.BMWApplication$ModelLoaderThread.run(BMWApplication.java:81)

Here's the code:
private class ModelLoaderThread extends Thread {

        String modelName = "";

        public ModelLoaderThread(String modelName) {
            this.modelName = modelName;
        }

        @Override
        public void run() {
            isModelLoading = true;
            if (world != null) {
                world.removeAll();
                world.dispose();
                world = new World();
            }
            if (model != null) {
                model = null;
            }
            try {
                model = Loader.loadSerializedObjectArray(getAssets().open(modelName + ".png"));
            } catch (IOException e) {
                e.printStackTrace();
            }
            world.addObjects(model);
            world.buildAllObjects();
            world.compileAllObjects();
            isModelLoaded = true;
            isModelLoading = false;
        }
    }

The line causing the crash is the "world.addObjects(model);"

EgonOlsen

...so world is null in this case, not model. Otherwise, it would crash inside of the method and not when trying to call it.

MrAdam

#67
Quote from: EgonOlsen on May 25, 2012, 10:55:34 AM
...so world is null in this case, not model. Otherwise, it would crash inside of the method and not when trying to call it.
Well yeah, but it shouldn't reach that point without having created world. "world = new World();" doesn't fail

EDIT: Never mind, fixed it by initializing the world before starting the thread:
public World world = new World();

zammbi

QuoteRemoved. Please use this jar: http://jpct.de/download/beta/jpct_ae.jar
I've tested it and it works fine in my basic tests.

MrAdam

Quote from: EgonOlsen on May 18, 2012, 05:53:53 PM
Here's a rough port of the shader in your link:

vertex:

uniform mat4 modelViewMatrix;
uniform mat4 modelViewProjectionMatrix;

uniform vec3 lightPositions[8];
uniform vec3 diffuseColors[8];

attribute vec4 position;
attribute vec3 normal;
attribute vec2 texture0;

varying vec3 vnormal;
varying vec4 pos;
varying vec4 diffuseColor;
varying vec2 texCoord;

void main() {
  vnormal = normalize(modelViewMatrix * vec4(normal, 0.0)).xyz;
  pos = modelViewMatrix * position;
  diffuseColor = vec4(diffuseColors[0], 0.0);
  texCoord = texture0.xy;
  gl_Position = modelViewProjectionMatrix * position;
}


fragment:

precision highp float;

uniform sampler2D textureUnit0;
uniform vec3 lightPositions[8];

varying vec3 vnormal;
varying vec4 pos;
varying vec4 diffuseColor;
varying vec2 texCoord;

void main() {
  vec4 color = texture2D(textureUnit0, texCoord);
 
  // Adjust this...
  vec4 matspec = vec4(0.8, 0.8, 0.8, 0.0);
  vec4 lightspec = vec4(1.0, 1.0, 1.0, 0.0);
  float shininess = 0.45;
  // ...
 
  vec4 lpos = vec4(lightPositions[0], 0.0);
  vec4 s = -normalize(pos-lpos);

  vec3 light = s.xyz;
  vec3 n = normalize(vnormal);
  vec3 r = -reflect(light, n);
  r = normalize(r);
  vec3 v = -pos.xyz;
  v = normalize(v);
   
  vec4 diffuse  = color * max(0.0, dot(n, s.xyz)) * diffuseColor;
  vec4 specular = lightspec * matspec * pow(max(0.0, dot(r, v)), shininess);

  gl_FragColor = diffuse + specular;
}


To get different specular effects, adjust the settings inside the comments...especially the shininess value. Note that you can't use this shader on transparent objects as it is. You would have to write a version that takes alpha into account if that is needed.

Hope this helps...
I noticed that this shader only works with one light at a time. Is it hard to modify it to work with several lights?

Thomas.

#70
It's just wrote in reply, I didn't test it... shader ignore specular colors of lights, that you set in application... but it isn't hard to implement, look at java doc...

fragment:

precision highp float;

uniform sampler2D textureUnit0;
uniform vec3 lightPositions[8];
uniform int lightCount;

varying vec3 vnormal;
varying vec4 pos;
varying vec4 diffuseColor;
varying vec2 texCoord;

void main() {
  vec4 color = texture2D(textureUnit0, texCoord);
 
  // Adjust this...
  vec4 matspec = vec4(0.8, 0.8, 0.8, 0.0);
  vec4 lightspec = vec4(1.0, 1.0, 1.0, 0.0);
  float shininess = 0.45;
  // ...
 
  vec4 lpos = vec4(lightPositions[0], 0.0);
  vec4 s = -normalize(pos-lpos);

  vec3 light = s.xyz;
  vec3 n = normalize(vnormal);
  vec3 r = -reflect(light, n);
  r = normalize(r);
  vec3 v = -pos.xyz;
  v = normalize(v);
   
  vec4 diffuse  = color * max(0.0, dot(n, light)) * diffuseColor;
  vec4 specular = lightspec * matspec * pow(max(0.0, dot(r, v)), shininess);

  gl_FragColor = diffuse + specular;

  if(lightCount >= 2){
     lpos = vec4(lightPositions[1], 0.0);
     s = -normalize(pos-lpos);

     light = s.xyz;
     n = normalize(vnormal);
     r = -reflect(light, n);
     r = normalize(r);
     v = -pos.xyz;
     v = normalize(v);
   
     diffuse  = color * max(0.0, dot(n, light)) * diffuseColor;
     specular = lightspec * matspec * pow(max(0.0, dot(r, v)), shininess);

     gl_FragColor += diffuse + specular;

   // if(lightCount >= 3){...}
   }
}

EgonOlsen

Just keep in mind (as you can see when looking at the source of jPCT-AE's default shaders...) that using loops for multiple lightsources isn't a good idea. because they don't compile well on Adreno GPUs. So if you want to support even more lights, do what Thomas. did and add additional if-blocks instead.