No light after world deserialization

Started by twaletz, August 26, 2013, 04:43:52 PM

Previous topic - Next topic

twaletz

Hello,

I have problem with the World Light after deserialization.
My world contains about 60 Objects3d camera and one light.

Light sun = new Light(world);
sun.setIntensity(100, 100, 100);
SimpleVector sv = new SimpleVector(100f,-100f,50f);
sun.setPosition(sv);


Everything looks good. I see shading on objects in the world.
But, when I serialize whole world and after this deserialize whole world - light disappear. World has all objects but no light.
And now even if I add a new light, objects3d stay matte (no shading).
After deserialization getSpecularLighting()==true for all objects3d.
Where is my mistake?

EgonOlsen

I can't see a reason for this ATM. Looking at the code, i would say that it should work. How exactly are you (de-)serializing the world? What happens in the log, if you add a new light source after deserializing? Is there some message about adding a new light source?

twaletz


Here is Log without repeated messages:
08-26 22:36:23.967: I/jPCT-AE(5183): Loading Texture...
08-26 22:36:23.967: I/jPCT-AE(5183): Texture loaded...16384 bytes/64*64 pixels!
...
08-26 22:36:26.697: I/jPCT-AE(5183): Loading Texture...
08-26 22:36:26.707: I/jPCT-AE(5183): Texture loaded...16384 bytes/64*64 pixels!
08-26 22:36:27.227: I/nav(5183): Loglevel:3
08-26 22:36:27.237: I/jPCT-AE(5183): Adding Lightsource: 0
08-26 22:36:27.257: I/jPCT-AE(5183): Normal vectors calculated in 9ms!
08-26 22:36:27.277: I/jPCT-AE(5183): Normal vectors calculated in 4ms!
...
08-26 22:36:27.897: I/jPCT-AE(5183): Normal vectors calculated in 1ms!
[b]08-26 22:36:27.917: I/nav(5183): World Serialization...[/b]
08-26 22:36:28.207: D/dalvikvm(5183): GC_CONCURRENT freed 1023K, 28% free 12267K/17031K, paused 2ms+5ms
08-26 22:36:28.777: D/serialize(5183): 863
[b]08-26 22:36:28.777: I/nav(5183): World deserialization ...[/b]
08-26 22:36:29.387: D/dalvikvm(5183): GC_CONCURRENT freed 1647K, 27% free 12539K/17031K, paused 2ms+4ms
08-26 22:36:29.687: I/jPCT-AE(5183): Adding Lightsource: 0
08-26 22:36:29.687: D/deserialize(5183): 913
08-26 22:36:29.707: I/ActivityManager(157): START {cmp=pl.potiopa/.activity.MapActivity} from pid 5183
08-26 22:36:29.727: I/ActivityManager(157): START {cmp=pl.potiopa/.activity.MapActivity} from pid 518308-26 22:36:29.837: I/jPCT-AE(5183): GLRenderer created with id 0 on Thread[GLThread 221,5,main]
08-26 22:36:29.837: I/jPCT-AE(5183): OpenGL vendor:     ARM
08-26 22:36:29.837: I/jPCT-AE(5183): OpenGL renderer:   Mali-400 MP
08-26 22:36:29.837: I/jPCT-AE(5183): OpenGL version:    OpenGL ES-CM 1.1
08-26 22:36:29.837: I/jPCT-AE(5183): OpenGL renderer initialized (using 2/8 texture stages)
08-26 22:36:29.837: I/jPCT-AE(5183): Memory usage before compacting: 13248 KB used out of 17031 KB. Max. memory available to the VM is 49152 KB.
08-26 22:36:30.347: I/jPCT-AE(5183): Memory usage after compacting: 12308 KB used out of 17031 KB. Max. memory available to the VM is 49152 KB.
08-26 22:36:30.347: I/jPCT-AE(5183): Subobject of object 0/object2 compiled to flat fixed point data using 48/48 vertices in 1ms!
08-26 22:36:30.347: I/jPCT-AE(5183): Processing and uploading vertices of subobject of object 0/object2 took 1ms
08-26 22:36:30.347: I/jPCT-AE(5183): Object 0/object2 compiled to 1 subobjects in 2ms!
08-26 22:36:30.347: I/jPCT-AE(5183): Object 'object2' uses one texture set!
08-26 22:36:30.347: I/jPCT-AE(5183): Subobject of object 1/object3 compiled to flat fixed point data using 36/36 vertices in 0ms!
08-26 22:36:30.347: I/jPCT-AE(5183): Processing and uploading vertices of subobject of object 1/object3 took 1ms
08-26 22:36:30.347: I/jPCT-AE(5183): Object 1/object3 compiled to 1 subobjects in 1ms!
08-26 22:36:30.347: I/jPCT-AE(5183): Object 'object3' uses one texture set!
...
08-26 22:36:30.577: I/jPCT-AE(5183): Subobject of object 67/object69 compiled to flat fixed point data using 48/48 vertices in 1ms!
08-26 22:36:30.577: I/jPCT-AE(5183): Processing and uploading vertices of subobject of object 67/object69 took 2ms
08-26 22:36:30.577: I/jPCT-AE(5183): Object 67/object69 compiled to 1 subobjects in 4ms!
08-26 22:36:30.577: I/jPCT-AE(5183): Object 'object69' uses one texture set!
08-26 22:36:30.577: I/jPCT-AE(5183): Allocating native memory for 16*16 texture(true/false/false/false/): 1024 bytes!
08-26 22:36:30.587: I/jPCT-AE(5183): New texture's id is: 1
08-26 22:36:30.587: I/jPCT-AE(5183): New texture uploaded: com.threed.jpct.Texture@410e24d0 in thread Thread[GLThread 221,5,main]
08-26 22:36:30.587: I/jPCT-AE(5183): Creating buffers...
08-26 22:36:30.587: I/jPCT-AE(5183): VBO created for object 'object2'
08-26 22:36:30.587: I/jPCT-AE(5183): Allocating native memory for 64*64 texture(true/false/false/false/): 16384 bytes!
08-26 22:36:30.587: I/jPCT-AE(5183): New texture's id is: 2
...
08-26 22:36:30.607: I/jPCT-AE(5183): Allocating native memory for 64*64 texture(true/false/false/false/): 16384 bytes!
08-26 22:36:30.607: I/jPCT-AE(5183): New texture's id is: 6
08-26 22:36:30.607: I/jPCT-AE(5183): New texture uploaded: com.threed.jpct.Texture@41073c88 in thread Thread[GLThread 221,5,main]
08-26 22:36:30.607: I/jPCT-AE(5183): Creating buffers...
08-26 22:36:30.607: I/jPCT-AE(5183): VBO created for object 'object16'


Serialization code:
public boolean serialize(World world, File file) {
try {
Log.i("nav", "World Serialization...");
file.createNewFile();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(world);
byte[] array = baos.toByteArray();
oos.close();
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
bos.write(array, 0, array.length);
bos.close();

return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}


Deserialization code:
public World deserialize(File file) {
try {
Log.i("nav", "World deserialization ...");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
ObjectInputStream ois = new ObjectInputStream(bis);
World world = (World) ois.readObject();
ois.close();
return world;
} catch (Exception x) {
x.printStackTrace();
throw new RuntimeException(x);
}
// return null;
}


Here is a metod adding lights to the world:
public void setLights(World world) {
world.removeAllLights();
world.setAmbientLight(50, 50, 50);
Light sun = new Light(world);
sun.setIntensity(100, 100, 100);

SimpleVector sv = new SimpleVector(100f,-100f,50f);
sun.setPosition(sv);
}


Normally I run this method only once before serialization. But now I don't know what's going on,  therefore in the example this method I run before serialization and after deserialization. There isn't  differences between it.

What do you think about it?

Thanks

EgonOlsen

No idea. Can you provide a simple, compileable test case for this?

twaletz

Thanks so much for your time,

Code bellow it is a simple example I get from: http://www.jpct.net/wiki/index.php/Hello_World_for_Android.
I add only method serialize and method deserialize an.

If you turn off deserializarion by comment line: world=this.deserialize(worldFile); everything looks good. But if line is uncommented the box is gray and without light.

package com.example.jpcthello;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;

import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Light;
import com.threed.jpct.Logger;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.BitmapHelper;
import com.threed.jpct.util.MemoryHelper;

public class MainActivity extends Activity {

// Used to handle pause and resume...
private static MainActivity master = null;

private GLSurfaceView mGLView;
private MyRenderer renderer = null;
private FrameBuffer fb = null;
private World world = null;
private RGBColor back = new RGBColor(50, 50, 100);

private float touchTurn = 0;
private float touchTurnUp = 0;

private float xpos = -1;
private float ypos = -1;

private Object3D cube = null;
private int fps = 0;

private Light sun = null;

private Context ctx;

protected void onCreate(Bundle savedInstanceState) {

ctx=this.getApplicationContext();
Logger.log("onCreate");

if (master != null) {
copy(master);
}

super.onCreate(savedInstanceState);
mGLView = new GLSurfaceView(getApplication());

mGLView.setEGLConfigChooser(new GLSurfaceView.EGLConfigChooser() {
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
// Ensure that we get a 16bit framebuffer. Otherwise, we'll fall
// back to Pixelflinger on some device (read: Samsung I7500)
int[] attributes = new int[] { EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE };
EGLConfig[] configs = new EGLConfig[1];
int[] result = new int[1];
egl.eglChooseConfig(display, attributes, configs, 1, result);
return configs[0];
}
});

renderer = new MyRenderer();
mGLView.setRenderer(renderer);
setContentView(mGLView);
}

@Override
protected void onPause() {
super.onPause();
mGLView.onPause();
}

@Override
protected void onResume() {
super.onResume();
mGLView.onResume();
}

@Override
protected void onStop() {
super.onStop();
}

private void copy(Object src) {
try {
Logger.log("Copying data from master Activity!");
Field[] fs = src.getClass().getDeclaredFields();
for (Field f : fs) {
f.setAccessible(true);
f.set(this, f.get(src));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public boolean onTouchEvent(MotionEvent me) {

if (me.getAction() == MotionEvent.ACTION_DOWN) {
xpos = me.getX();
ypos = me.getY();
return true;
}

if (me.getAction() == MotionEvent.ACTION_UP) {
xpos = -1;
ypos = -1;
touchTurn = 0;
touchTurnUp = 0;
return true;
}

if (me.getAction() == MotionEvent.ACTION_MOVE) {
float xd = me.getX() - xpos;
float yd = me.getY() - ypos;

xpos = me.getX();
ypos = me.getY();

touchTurn = xd / -100f;
touchTurnUp = yd / -100f;
return true;
}

try {
Thread.sleep(15);
} catch (Exception e) {
// No need for this...
}

return super.onTouchEvent(me);
}

protected boolean isFullscreenOpaque() {
return true;
}

class MyRenderer implements GLSurfaceView.Renderer {

private long time = System.currentTimeMillis();

public MyRenderer() {
}

public void onSurfaceChanged(GL10 gl, int w, int h) {
if (fb != null) {
fb.dispose();
}
fb = new FrameBuffer(gl, w, h);

if (master == null) {

world = new World();
world.setAmbientLight(20, 20, 20);

sun = new Light(world);
sun.setIntensity(250, 250, 250);

// Create a texture out of the icon...:-)
Texture texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(getResources().getDrawable(R.drawable.ic_launcher)), 64, 64));
TextureManager.getInstance().addTexture("texture", texture);

cube = Primitives.getBox(1, 1);
cube.calcTextureWrapSpherical();
cube.setTexture("texture");
cube.scale(5);
cube.strip();
cube.build();

int CubeId=world.addObject(cube);
Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
cam.lookAt(cube.getTransformedCenter());

SimpleVector sv = new SimpleVector();
sv.set(cube.getTransformedCenter());
sv.y -= 100;
sv.z -= 100;
sun.setPosition(sv);
MemoryHelper.compact();

/**** serialize - deserialize ****/
//set directory and file
File directory = ctx.getFilesDir();
File worldFile = new File(directory, "world.ser");
//serialize
this.serialize(world, worldFile);
//deserialize
world=this.deserialize(worldFile);
world.buildAllObjects();
//retrive cube again
cube=world.getObject(CubeId);
/**** serialize - deserialize FINISH ****/

if (master == null) {
Logger.log("Saving master Activity!");
master = MainActivity.this;
}
}
}

public void onSurfaceCreated(GL10 gl, EGLConfig config) {
}

public void onDrawFrame(GL10 gl) {
if (touchTurn != 0) {
cube.rotateY(touchTurn);
touchTurn = 0;
}

if (touchTurnUp != 0) {
cube.rotateX(touchTurnUp);
touchTurnUp = 0;
}

fb.clear(back);
world.renderScene(fb);
world.draw(fb);
fb.display();

if (System.currentTimeMillis() - time >= 1000) {
Logger.log(fps + "fps");
fps = 0;
time = System.currentTimeMillis();
}
fps++;
}


public boolean serialize(World world, File file) {
try {
Log.i("ser", "World Serialization...");
file.createNewFile();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(world);
byte[] array = baos.toByteArray();
oos.close();
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
bos.write(array, 0, array.length);
bos.close();

return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}

public World deserialize(File file) {
try {
Log.i("ser", "World deserialization ...");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
ObjectInputStream ois = new ObjectInputStream(bis);
World world = (World) ois.readObject();
ois.close();
return world;
} catch (Exception x) {
x.printStackTrace();
throw new RuntimeException(x);
}
// return null;
}


}
}


I rely don't know what's going on. Even if I add a new Light after deserialization exactly like in the top of this code box stay gray.

EgonOlsen


EgonOlsen

I think that i found the reason, i'm just not sure how to deal with it...i'll try to fix it later today.

EgonOlsen


twaletz

Danish: "Skide godt, Egon!" - in English: "Bloody good, Egon!" - in my county: "Klawo jak cholera".   ;)

Now works perfectly. Thank you.