3ds file loading problem

Started by generalJ, February 14, 2013, 07:17:14 PM

Previous topic - Next topic

generalJ

Hello JPCT community, firstly I would like to thank you for this splendid engine.

Nevertheless, there is a problem I've been struggling with lately. When I load this particular 3ds file created in blender, consisting of multiple objects, I'm only able to see some of them. More precisely speaking, file should consist of road object, two houses, fence and lawn, while I'm not able to see second house and fence when I load this file to jPCT.

I'm pretty much out of all ideas why is this happening. When I import file back in blender, the objects are actually there so I don't think this is an exporter problem. I'm attaching the file to the topic, I hope you can figure out something.

Note: Just rename the file to index.3ds



[attachment deleted by admin]

EgonOlsen

I can't find anything wrong with that file. It loads fine and i can see the house as well as the fence. Can you post the code that loads the file and adds the objects to the world?

generalJ

#2
I cut all off all non related code. It  is based on HelloWorld example, still produces the error.

package com.threed.jpct.example;

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

import android.opengl.GLSurfaceView;

import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Light;
import com.threed.jpct.Loader;
import com.threed.jpct.Matrix;
import com.threed.jpct.Object3D;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.World;
import com.threed.jpct.util.MemoryHelper;

class MyRenderer implements GLSurfaceView.Renderer {
private FrameBuffer fb = null;
public World world = null;
public World terrainWorld = null;
private RGBColor back = new RGBColor(50, 50, 100);

private HelloWorld king;

public void setKing(HelloWorld a) {
king = a;
}

public MyRenderer() {
}

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

if (king.master == null) {
terrainWorld = new World();
terrainWorld.setAmbientLight(100, 100, 100);

Light[] lizatka = new Light[3];
for (int i = 0; i < 3; i++)
lizatka[i] = new Light(terrainWorld);
SimpleVector moveVec = new SimpleVector();
moveVec.x = -8f;
moveVec.z = 2f;
moveVec.y = -2;
lizatka[0].setPosition(moveVec);
lizatka[0].setIntensity(85, 85, 85);
moveVec.x = 8f;
lizatka[1].setPosition(moveVec);
lizatka[1].setIntensity(85, 85, 85);
moveVec = new SimpleVector(0, -5, 0);
lizatka[2].setPosition(moveVec);
lizatka[2].setIntensity(85, 85, 85);

Object3D [] terrain = Loader.load3DS(king.getAssets().open("index.3ds"), 1f);
for(Object3D obj : terrain){
obj.setVisibility(true);
obj.setAdditionalColor(RGBColor.RED);
obj.setCenter(SimpleVector.ORIGIN);
obj.rotateX((float) (-.5 * Math.PI));
obj.rotateMesh();
obj.setRotationMatrix(new Matrix());
}
terrainWorld.addObjects(terrain);
terrainWorld.renderScene(fb);

terrainWorld.getCamera().setPosition(0, -4, -10);
terrainWorld.getCamera().lookAt(terrain[6].getTransformedCenter());

MemoryHelper.compact();


}
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
}


public void onDrawFrame(GL10 gl) {
fb.clear(back);

terrainWorld.draw(fb);

fb.display();
}

}

EgonOlsen

If that's what you are doing in your actual code, it's because you don't have a proper rendering sequence. You load the model, then call renderScene(), then change the camera and the actual render method only does draw()-calls. That's not going to work, because renderScene() will create your scene with a different camera setting than you are actually using when drawing the result. Chances are that this simply clips away your objects. You should move that call to renderScene() from that location to right before the call to draw(). For reference, here's a working example:


package com.threed.jpct.example;

import java.io.IOException;
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.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;

import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Light;
import com.threed.jpct.Loader;
import com.threed.jpct.Logger;
import com.threed.jpct.Matrix;
import com.threed.jpct.Object3D;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.World;
import com.threed.jpct.util.MemoryHelper;

public class HelloWorld extends Activity {
private static HelloWorld 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 int fps = 0;

private Light sun = null;

protected void onCreate(Bundle savedInstanceState) {

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

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

Object3D[] terrain=null;
try {
terrain = Loader.load3DS(getAssets().open("testy.3ds"), 5f);
} catch (IOException e) {
e.printStackTrace();
}
for(Object3D obj : terrain){
obj.setVisibility(true);
obj.setAdditionalColor(RGBColor.RED);
obj.setCenter(SimpleVector.ORIGIN);
obj.rotateX((float) (-.5 * Math.PI));
obj.rotateMesh();
obj.setRotationMatrix(new Matrix());
}
world.addObjects(terrain);
world.buildAllObjects();

Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
cam.moveCamera(Camera.CAMERA_MOVEUP, 20);
cam.rotateX(-0.25f);

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

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

public void onDrawFrame(GL10 gl) {
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++;
}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
}
}
}


generalJ

Thank you, that pretty much solves my problem. I just didn't expect the result of not calling the render method would be random objects disappearing.

My idea was to load the terrain to separate world and since it was static and unchanging, render it once and then just draw it every frame. It actually worked, when the terrain consisted only of one object. So, am I assuming correctly that I just have to call the renderScene fuction for every frame? Is there even some recognisable performance improvement when not doing so? The world is really static and I just move its camera.

Anyway I really appreciate your help. Thanks.

EgonOlsen

Quote from: generalJ on February 15, 2013, 01:20:20 PM
I just didn't expect the result of not calling the render method would be random objects disappearing.
That's not the case. But if you call renderScene(), then transform the camera and then call draw(), your draw() call draws a scene with the new camera position but using the culling information from the renderScene() call, which isn't valid anymore. If the scene doesn't change, you may be able to omit renderScene(), but i personally wouldn't do it. You never know which side effects it might have in this or later versions.