Hi,
I'm new in jPCT and I think I miss some thing and I have very strange behavior.
I made simple activity with PageViewer
https://developer.android.com/reference/android/support/v4/view/ViewPager.htmlon each page (android fragment) I put MyRenderer from HelloWord example (I only modified to load obj model).
The important feature of PageViewer is that it load 3 fragments (one main and one on left and one on right) as visible and shows only main. Reason for that is to prepare next page to show to user.
So MyRenderer is run 2 or 3 times. And I suspect that this is the problem. But how to fix/solve/workaround this?
When start of app after while (5-9 sek.) I get crash:
E/AndroidRuntime: FATAL EXCEPTION: GLThread 32054
Process: pl.example.test, PID: 15106
java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at com.threed.jpct.Object3D.render(Object3D.java:6271)
at com.threed.jpct.World.renderScene(World.java:1075)
at pl.example.test.MyRenderer.onDrawFrame(MyRenderer.java:155)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1535)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
Before crash I see the loaded model but disappearing for 200ms or so.
public class MyPageFragment extends Fragment {
int position = -1;
private GLSurfaceView mGLView;
@BindView(R.id.model_3d_frame)
FrameLayout model3dFrame;
BoatRenderer renderer;
public static MyPageFragment newInstance(int position) {
Bundle args = new Bundle();
args.putInt(ARG_POSITION, position);
MyPageFragment fragment = new MyPageFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
position = getArguments().getInt(ARG_POSITION);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.one_model3d_view_fragment, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
setupGLView(getActivity(), model3dFrame);
}
@Override
public void onResume() {
super.onResume();
mGLView.onResume();
}
@Override
public void onPause() {
super.onPause();
mGLView.onPause();
}
private void setupGLView(Context context, ViewGroup container) {
mGLView = new GLSurfaceView(context.getApplicationContext());
mGLView.setEGLContextClientVersion(2);
try {
renderer = new BoatRenderer(context);
mGLView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
mGLView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
mGLView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mGLView.setZOrderOnTop(true);
mGLView.setRenderer(renderer);
container.addView(mGLView);
} catch (IOException e) {
e.printStackTrace();
}
}
}
class MyRenderer implements GLSurfaceView.Renderer {
private static final String TAG = MyRenderer.class.getSimpleName();
private int fps = 0;
private Light sun = null;
private FrameBuffer fb = null;
private World world = null;
private long time = System.currentTimeMillis();
final Object3D m32;
boolean isSetMaster = false;
public MyRenderer(Context context) throws IOException {
m32 = loadM32(context, 20.5f);
}
Object3D loadM32(final Context context, final float scale) throws IOException {
Log.d(TAG,"loadM32 model");
final Object3D[] objs;
objs = Loader.loadOBJ(context.getAssets().open("models/m32/m32_02.obj"), context.getAssets().open("models/m32/m32_02.mtl"), scale);
if (!TextureManager.getInstance().containsTexture("K"))
TextureManager.getInstance().addTexture("K", new Texture(getBitmapFromAsset(context, "models/m32/k_tex.png")));
if (!TextureManager.getInstance().containsTexture("F"))
TextureManager.getInstance().addTexture("F", new Texture(getBitmapFromAsset(context, "models/m32/f_tex.jpg")));
if (!TextureManager.getInstance().containsTexture("G"))
TextureManager.getInstance().addTexture("G", new Texture(getBitmapFromAsset(context, "models/m32/g_tex.jpg")));
objs[0].setTexture("F");
objs[1].setTexture("G");
objs[2].setTexture("K");
return Object3D.mergeAll(objs);
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
Log.d(TAG, "onSurfaceChanged( "+w +" x " + h +")");
if (fb != null) {
fb.dispose();
}
fb = new FrameBuffer(w, h); // OpenGL ES 2.0 constructor
if (!isSetMaster) {
world = new World();
world.setAmbientLight(20, 20, 20);
sun = new Light(world);
sun.setIntensity(250, 250, 250);
world.addObjects(m32);
Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
cam.lookAt(m32.getTransformedCenter());
SimpleVector sv = new SimpleVector();
sv.set(m32.getTransformedCenter());
sv.y -= 100;
sv.z -= 100;
sun.setPosition(sv);
MemoryHelper.compact();
if (!isSetMaster) {
Logger.log("Saving master Activity!");
isSetMaster = true;
}
}
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) { }
public void onDrawFrame(GL10 gl) {
fb.clear();
world.renderScene(fb);
world.draw(fb);
fb.display();
if (System.currentTimeMillis() - time >= 10000) {
Logger.log(fps / 10 + "fps");
fps = 0;
time = System.currentTimeMillis();
}
fps++;
}
public static Bitmap getBitmapFromAsset(Context context, String filePath) {
AssetManager assetManager = context.getAssets();
InputStream istr;
Bitmap bitmap = null;
try {
istr = assetManager.open(filePath);
bitmap = BitmapFactory.decodeStream(istr);
} catch (IOException e) {
// handle exception
}
return bitmap;
}
}