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?
			
			
			
				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?
			
			
			
				
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
			
			
			
				No idea. Can you provide a simple, compileable test case for this?
			
			
			
				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.
			
			
			
				Thanks, i'll look into it.
			
			
			
				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.
			
			
			
				This version should fix the problem: jpct.de/download/beta/jpct_ae.jar (http://jpct.de/download/beta/jpct_ae.jar)
			
			
			
				Danish: "Skide godt, Egon!" - in English: "Bloody good, Egon!" - in my county: "Klawo jak cholera".   ;)
Now works perfectly. Thank you.