Main Menu
Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - cnasich

#1
Support / Re: addTriangle issue
March 21, 2014, 06:34:42 PM
What I try to do is:
- Create a mesh of triangles (for now in sight) to have all Property Types calculated.
- With a VertexController, move the vertices of each triangle to trace the work done by the machine.

I do not try to keep the order of the vertices of the triangles because I assume that moving the vertices, the other properties of a triangle should not change. I also tried setting the normal (0, 1, 0) in the VertexController but nothing changes.

Here I show a sketch of what I hope will happen:
https://www.dropbox.com/s/o3md6eu9372mg54/Concept1.gif
#2
Support / Re: addTriangle issue
March 21, 2014, 12:51:23 AM
No..I called after ;)
But happen a strange behavior: the normals change.

Here create triangles in a visible position:

//Generate a track for testing propose
Log.i("Generating triangles", "Reserving space");
track = new Object3D(20000);
track.disableVertexSharing();
Log.i("Generating triangles", "Start populating");

SimpleVector v1 = new SimpleVector(), v2 = new SimpleVector(), v3 = new SimpleVector(), v4 = new SimpleVector();

for (i = 0; i < 10000; i++) {
v1.set(-working_width / 2, TRACK_FLOOR_DISTANCE, -i * 0.05f);
v2.set( working_width / 2, TRACK_FLOOR_DISTANCE, -i * 0.05f);
v3.set( working_width / 2, TRACK_FLOOR_DISTANCE, -i * 0.05f - 0.05f);
v4.set(-working_width / 2, TRACK_FLOOR_DISTANCE, -i * 0.05f - 0.05f);
track.addTriangle(v3, 1, 0, v1, 0, 1, v4, 0, 0, TextureManager.getInstance().getTextureID("track"));
track.addTriangle(v1, 0, 1, v3, 1, 0, v2, 1, 1, TextureManager.getInstance().getTextureID("track"));

if (i % 1000 == 0) {
Log.i("Generating triangles", "n = " + String.valueOf(i));
}
}
Log.i("Generating triangles", "End generation");

//setup track
track.setTransparency((int)(2^12-1));
track.setTransparencyMode(Object3D.TRANSPARENCY_MODE_DEFAULT);
track.getMesh().setVertexController(RepositionVertexes_, IVertexController.PRESERVE_SOURCE_MESH);
track.compile(true, true);
track.build();


And get this
https://www.dropbox.com/s/oqcrosjce0daotr/Screenshot_2014-03-20-19-47-11.png

The VertexController code is:

public void apply() {
SimpleVector[] dstMesh=this.getDestinationMesh();

v0.set(v1);
v1.set(v2);
if (right_triangle) {
v2.set(width / 2, 0, 0);
v2.rotateY(direction_angle);
v2.set(v2.calcAdd(t2));
dstMesh[i] = new SimpleVector(v0);
++i;
dstMesh[i] = new SimpleVector(v1);
++i;
dstMesh[i] = new SimpleVector(v2);
++i;
}
else {
v2.set(-width / 2, 0, 0);
v2.rotateY(direction_angle);
v2.set(v2.calcAdd(t2));
dstMesh[i] = new SimpleVector(v0);
++i;
dstMesh[i] = new SimpleVector(v1);
++i;
dstMesh[i] = new SimpleVector(v2);
++i;
}

right_triangle = !right_triangle;
}


Then in OnDrawFrame I call track.getMesh().applyVertexController()

track.getMesh().applyVertexController();
track.touch();


And get this
https://www.dropbox.com/s/1dz205vkcywynsb/Screenshot_2014-03-20-19-47-24.png

I not changed the normals, but seems to be changed.
#3
Support / Re: addTriangle issue
March 20, 2014, 04:25:27 PM
As you say I try calling Object3D.disableVertexSharing() when add many triangles, but I get the same results: add 998 triangles in the same place result in 4 triangles in the mesh. When add 998 in different places result in 998 triangles in the mesh.
#4
Support / Re: addTriangle issue
March 20, 2014, 03:53:23 PM
I did that and not get the expected result :(
So I will continue adding triangles to world albeit is slower.
#5
Support / Re: Dynamically addTriangles
March 19, 2014, 09:37:59 PM
Thanks Egon and AGP.
I find my problem.
I did not know the order: setVertecController, compile and build.

PD: a float is 4 bytes long in Java. A triangle have:
- 3 vectors -> 3 * 3 * 4 = 36 bytes.
- 1 normal -> 1 * 3 * 4 = 12 bytes.
- 6 texture 2D coordinates (2 each vertex) -> 6 * 4 = 24 bytes.
- 1 texture ID -> 2 bytes (I suppose).
Total for a triangle = 36 + 12 + 24 + 2 = 74
Total size in memory for 200k triangles = 200,000 * 74 = 14,800,000 bytes = 14.1 MB
Missed I some thing?
#6
Support / addTriangle issue
March 19, 2014, 09:20:20 PM
For a test case, I generated an object adding triangles with addTriangles in two ways, always before compile and build:

1- Positioning each pair of triangle in differents positions.

track = new Object3D(100000);
Log.i("Generating triangles", "Start populating");
SimpleVector v1 = new SimpleVector(), v2 = new SimpleVector(), v3 = new SimpleVector(), v4 = new SimpleVector();
v1.set(-working_width / 2, -TRACK_FLOOR_DISTANCE, 1);
v2.set( working_width / 2, -TRACK_FLOOR_DISTANCE, 1);
v3.set( working_width / 2, -TRACK_FLOOR_DISTANCE, 0);
v4.set(-working_width / 2, -TRACK_FLOOR_DISTANCE, 0);
for (i = 0; i < 499; i++) {
track.addTriangle(v1, 0, 1, v2, 1, 1, v3, 1, 0, TextureManager.getInstance().getTextureID("track"));
track.addTriangle(v1, 0, 1, v3, 1, 0, v4, 0, 0, TextureManager.getInstance().getTextureID("track"));
if (i % 1000 == 0) {
Log.i("Generating triangles", "n = " + String.valueOf(2 * i));
}
}
Log.i("Generating triangles", "End generation");


2- Positioning each pair of triangle in the same position.

track = new Object3D(100000);
Log.i("Generating triangles", "Start populating");
SimpleVector v1 = new SimpleVector(), v2 = new SimpleVector(), v3 = new SimpleVector(), v4 = new SimpleVector();
for (i = 0; i < 499; i++) {
v1.set(-working_width / 2, -TRACK_FLOOR_DISTANCE, -i * 0.0001f);
v2.set( working_width / 2, -TRACK_FLOOR_DISTANCE, -i * 0.0001f);
v3.set( working_width / 2, -TRACK_FLOOR_DISTANCE, -i * 0.0001f - 0.0001f);
v4.set(-working_width / 2, -TRACK_FLOOR_DISTANCE, -i * 0.0001f - 0.0001f);
track.addTriangle(v1, 0, 1, v3, 1, 0, v2, 1, 1, TextureManager.getInstance().getTextureID("track"));
track.addTriangle(v3, 1, 0, v1, 0, 1, v4, 0, 0, TextureManager.getInstance().getTextureID("track"));
if (i % 1000 == 0) {
Log.i("Generating triangles", "n = " + String.valueOf(2 * i));
}
}
Log.i("Generating triangles", "End generation");


When get the mesh throw a VertexController, the mesh array get different sizes depending how was positioned the triangles.
With the option 1, I get 4 elements (wrong). With option 2, I get 998 elements (which is correct size). Why? Is an issue or I are wrong?

#7
Support / Re: Dynamically addTriangles
March 18, 2014, 10:41:50 PM
Thanks Egon and AGP.
I correct you: I need 200,000 triangles, no 2,000,000. The 200,000 triangles is stored in about 8MB.
I did a test with many triangles. The refresh rate to 100,000 is ok for my application (2-4 frames per second), but is very slow loading the triangles (more than 5 minutes). I not tried more.
I´ll try to split the load to work in threads.

Egon, following your suggestion, I tried using a GenericVertexController, but the triangles are not moving.
To be safe, I first put the triangles in a visible place and then move to the position that they should be as the machine moves.
The GenericVertexController class is RepositionVertexes.


public class MainActivity extends Activity {

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

private GLView mGLView;
private TextView tv;
private ImageButton bt;
private MyRenderer renderer = null;
private FrameBuffer fb = null;
private World world = null;
private RGBColor back = new RGBColor(50, 50, 100);

private Object3D tractor = null;
private Object3D sprayer = null;
private Object3D floor = null;
private Object3D track = null;
private Object3D track2 = null;
public RepositionVertexes RepositionVertexes_ = new RepositionVertexes();
static SimpleVector t0 = new SimpleVector();
static SimpleVector t1 = new SimpleVector();
static SimpleVector t2 = new SimpleVector();
private float tractor_direction_angle = 0;
private float turn_angle_click = 0.1f;
private SimpleVector tractor_direction = new SimpleVector();
final float working_width = 10;

private Light sun = null;

enum OpMode {
ROTATE, ADD, DELETE, ZOOM
}
public OpMode currentMode = OpMode.ROTATE;

private Button btIzquierda;

private Button btDerecha;

protected void onCreate(Bundle savedInstanceState) {

Logger.log("onCreate");

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

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); //or whatever the layout you want to use
mGLView = (GLView) findViewById(R.id.graphics_glsurfaceview1);
Config.useNormalsFromOBJ = true;
Config.useRotationPivotFrom3DS = true;

tv = (TextView) findViewById(R.id.textView1);
bt = (ImageButton) findViewById(R.id.imageButton1);
btIzquierda = (Button) findViewById(R.id.btIzquierda);
btDerecha = (Button) findViewById(R.id.btDerecha);
mGLView.setEGLContextClientVersion(2);
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];
}

});
mGLView.setEGLConfigChooser(new AAConfigChooser(mGLView));

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

tv.setText("Prueba");
}

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

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

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

public void OnClickDerecha(View v) {
tractor_direction_angle += -turn_angle_click;
tractor.rotateY(turn_angle_click);
tractor_direction.set((float)(0.05 * Math.cos(tractor_direction_angle + (float)Math.PI / 2)), 0,
  (float)(0.05 * Math.sin(tractor_direction_angle + (float)Math.PI / 2)));
}

public void OnClickIzquierda(View v) {
tractor_direction_angle += turn_angle_click;
tractor.rotateY(-turn_angle_click);
tractor_direction.set((float)(0.05 * Math.cos(tractor_direction_angle + (float)Math.PI / 2)), 0,
    (float)(0.05 * Math.sin(tractor_direction_angle + (float)Math.PI / 2)));
}

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

static class RepositionVertexes extends GenericVertexController {

/****************************************
* Move vertexes to it's final position *
****************************************/
private static final long serialVersionUID = 1L;
private SimpleVector v0 = new SimpleVector(), v1 = new SimpleVector(), v2 = new SimpleVector();
public float direction_angle, width;
public boolean right_triangle = false;
public static int i = 0;

@Override
public void apply() {
SimpleVector[] dstMesh=this.getDestinationMesh();


if (!t0.equals(t1) && !t1.equals(t2) && !t2.equals(t0)) {

v0.set(v1);
v1.set(v2);
if (right_triangle) {
v2.set(width / 2, 0, 0);
v2.rotateY(direction_angle);
v2.set(v2.calcAdd(t2));
}
else {
v2.set(-width / 2, 0, 0);
v2.rotateY(direction_angle);
v2.set(v2.calcAdd(t2));
}
dstMesh[i++].set(v0);
dstMesh[i++].set(v1);
dstMesh[i++].set(v2);

right_triangle = !right_triangle;
}
else {
v1.set(t2.x + width / 2, t2.y, t2.z);
v0.set(t2.x - width / 2, t2.y, t2.z);
}
}

}

class MyRenderer implements GLSurfaceView.Renderer {

private Camera cam;

public MyRenderer() {
}

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


public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Dibujar();
if (fb != null) {
fb.dispose();
}
}


private void Dibujar() {
if (master == null) {

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

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

Texture tx_worked_area = new Texture(2, 2, new RGBColor(200, 10, 10));
TextureManager.getInstance().addTexture("track", tx_worked_area);
Texture tx_worked_area2 = new Texture(2, 2, new RGBColor(10, 200, 200));
TextureManager.getInstance().addTexture("track2", tx_worked_area2);
Texture tx_floor = new Texture(2, 2, new RGBColor(6, 120, 58));
TextureManager.getInstance().addTexture("floor", tx_floor);

tractor = Object3D.mergeAll(Loader.loadOBJ(getResources().openRawResource(R.raw.tractor_obj),
getResources().openRawResource(R.raw.tractor_mtl), 1.0f));
sprayer = Object3D.mergeAll(Loader.loadOBJ(getResources().openRawResource(R.raw.fumigadora_de_arrastre_obj),
getResources().openRawResource(R.raw.fumigadora_de_arrastre_mtl),1.0f));

floor = Primitives.getPlane(1, 10000);
floor.rotateX((float) (90 * Math.PI / 180));
floor.setTexture("floor");

//Generate a track for testing propose
Log.i("Generating triangles", "Reserving space");
track = new Object3D(1000);
SimpleVector v1 = new SimpleVector(), v2 = new SimpleVector(), v3 = new SimpleVector(), v4 = new SimpleVector();
Log.i("Generating triangles", "Start populating");
for (i = 0; i < 499; i++) {
v1.set(-working_width / 2, 0, -i * 0.001f);
v2.set( working_width / 2, 0, -i * 0.001f);
v3.set( working_width / 2, 0, -i * 0.001f - 0.001f);
v4.set(-working_width / 2, 0, -i * 0.001f - 0.001f);
track.addTriangle(v2, 1, 0, v1, 1, 0, v3, 1, -1, TextureManager.getInstance().getTextureID("track"));
track.addTriangle(v1, 0, 0, v4, 0, -1, v3, 1, -1, TextureManager.getInstance().getTextureID("track"));
if (i % 100 == 0) {
//MemoryHelper.compact();
Log.i("Generating triangles", "n = " + String.valueOf(2 * i));
}
}
Log.i("Generating triangles", "End generation");

//setup track
track.setTransparency((int)(2^12-1));
track.setTransparencyMode(Object3D.TRANSPARENCY_MODE_DEFAULT);
track.strip();
track.build();
track.translate(0, -0.5f, 0);
track.getMesh().setVertexController(RepositionVertexes_, IVertexController.PRESERVE_SOURCE_MESH);
track.compile(true);
RepositionVertexes_.width = working_width;

/*track2 = new Object3D(200000);
track2.setTransparency((int)(2^12-1));
track2.setTransparencyMode(Object3D.TRANSPARENCY_MODE_DEFAULT);
track2.build();
track2.compile(true, true);
world.addObject(track2);*/
tractor.strip();
tractor.build();
tractor.rotateZ((float) (180 * Math.PI / 180));
tractor.translate(0, -tractor.getCenter().y * 2, 0);
sprayer.build();
sprayer.strip();
sprayer.rotateZ((float) (180 * Math.PI / 180));
sprayer.translate(0, -tractor.getCenter().y * 2, 0);
floor.strip();
floor.build();
floor.translate(0,0,0);

world.addObject(tractor);
world.addObject(sprayer);
world.addObject(floor);
world.addObject(track);

cam = world.getCamera();
cam.setPosition(0, 0, 0);
cam.moveCamera(Camera.CAMERA_MOVEOUT, 10);
cam.moveCamera(Camera.CAMERA_MOVEUP, 3);
cam.lookAt(tractor.getTransformedCenter());

SimpleVector sv = new SimpleVector();

sv.x = 4000;
sv.y = -4000;
sv.z = 4000;
sun.setPosition(sv);
t0 = tractor.getTransformedCenter();
t1 = tractor.getTransformedCenter();

MemoryHelper.compact();

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


Matrix rotationmatrix, transformMatrix;
SimpleVector camera_axis = new SimpleVector();
//SimpleVector v0 = new SimpleVector(), v1 = new SimpleVector(), v2 = new SimpleVector();
int i = 0;
boolean right_triangle = false;

public void onDrawFrame(GL10 gl) {
camera_axis.set(0, 0, mGLView.touchTurnUp);

if (mGLView.touchTurn != 0) {
mGLView.touchTurn = 0;
}
if (mGLView.touchTurnUp != 0) {
mGLView.touchTurnUp = 0;
}
tractor.translate(tractor_direction);


t2 = tractor.getTransformedCenter();
RepositionVertexes_.direction_angle = tractor_direction_angle;

track.getMesh().applyVertexController();
track.touch();
t0.set(t1);
t1.set(t2);

cam.setPositionToCenter(tractor);
cam.align(tractor);
cam.moveCamera(Camera.CAMERA_MOVEOUT, 10);
cam.moveCamera(Camera.CAMERA_MOVEUP, -4);

cam.lookAt(tractor.getTransformedCenter());

fb.clear(back);
world.renderScene(fb);
world.draw(fb);
fb.display();
tv.post(new Runnable() {

@Override
public void run() {
tv.setText("x=" + String.valueOf(t0.x) +
"; y=" + String.valueOf(t0.z) +
"; thita=" + String.valueOf(Math.toDegrees(tractor_direction_angle)));
MemoryHelper.printMemory();
}
});
}
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}


I think I'm misusing the GenericVertexController, but not know how to use it properly.

Can you post a complete code for using GenericVertexController?
#8
Support / Dynamically addTriangles
March 17, 2014, 08:23:28 PM
Hi. I write a software for satellital guidance for farm equipment. The software must record and display the track of the machine (with GPS data).
The software is in the start yet.
The issue is the slower refresh when add 1000 or more triangles. But I need add 200000 triangles at least.


import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;

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.opengl.GLSurfaceView;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;

import com.threed.jpct.*;
import com.threed.jpct.util.*;


public class MainActivity extends Activity {
   
   // Used to handle pause and resume...
   private static MainActivity master = null;

   private GLView mGLView;
   private TextView tv;
   private ImageButton bt;
   private MyRenderer renderer = null;
   private FrameBuffer fb = null;
   private World world = null;
   private RGBColor back = new RGBColor(50, 50, 100);

   private Object3D tractor = null;
   private Object3D sprayer = null;
   private Object3D floor = null;
   private Object3D track = null;
   private Object3D track2 = null;
   SimpleVector t0 = new SimpleVector(), t1 = new SimpleVector();   
   private float tractor_direction_angle = 0;
   private float turn_angle_click = 0.1f;
   private SimpleVector tractor_direction = new SimpleVector();
   final float working_width = 10;

   private Light sun = null;
   
   enum OpMode {
      ROTATE, ADD, DELETE, ZOOM
   }
   public OpMode currentMode = OpMode.ROTATE;

   private Button btIzquierda;

   private Button btDerecha;

   protected void onCreate(Bundle savedInstanceState) {

      Logger.log("onCreate");

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

      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main); //or whatever the layout you want to use
      mGLView = (GLView) findViewById(R.id.graphics_glsurfaceview1);
      Config.useNormalsFromOBJ = true;
      Config.useRotationPivotFrom3DS = true;
     
      tv = (TextView) findViewById(R.id.textView1);
      bt = (ImageButton) findViewById(R.id.imageButton1);
      btIzquierda = (Button) findViewById(R.id.btIzquierda);
      btDerecha = (Button) findViewById(R.id.btDerecha);
      mGLView.setEGLContextClientVersion(2);
      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];
         }
         
      });
      mGLView.setEGLConfigChooser(new AAConfigChooser(mGLView));

      renderer = new MyRenderer();
      mGLView.setRenderer(renderer);
     
      tv.setText("Prueba");
   }

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

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

   @Override
   protected void onStop() {
      super.onStop();
   }
   
   public void OnClickDerecha(View v) {
      tractor_direction_angle += -turn_angle_click;
      tractor.rotateY(turn_angle_click);
      tractor_direction.set((float)(0.05 * Math.cos(tractor_direction_angle + (float)Math.PI / 2)), 0,
                       (float)(0.05 * Math.sin(tractor_direction_angle + (float)Math.PI / 2)));
   }

   public void OnClickIzquierda(View v) {
      tractor_direction_angle += turn_angle_click;
      tractor.rotateY(-turn_angle_click);
      tractor_direction.set((float)(0.05 * Math.cos(tractor_direction_angle + (float)Math.PI / 2)), 0,
                         (float)(0.05 * Math.sin(tractor_direction_angle + (float)Math.PI / 2)));
   }
   
   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 Camera cam;

      public MyRenderer() {
      }

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

     
      public void onSurfaceCreated(GL10 gl, EGLConfig config) {
         Dibujar();
         if (fb != null) {
            fb.dispose();
         }
      }

     
      private void Dibujar() {
         if (master == null) {

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

            sun = new Light(world);           
            sun.setIntensity(1500, 1500, 1500);
           
            Texture tx_worked_area = new Texture(2, 2, new RGBColor(200, 10, 10));
            TextureManager.getInstance().addTexture("track", tx_worked_area);
            Texture tx_worked_area2 = new Texture(2, 2, new RGBColor(10, 200, 200));
            TextureManager.getInstance().addTexture("track2", tx_worked_area2);
            Texture tx_floor = new Texture(2, 2, new RGBColor(6, 120, 58));
            TextureManager.getInstance().addTexture("floor", tx_floor);

            tractor = Object3D.mergeAll(Loader.loadOBJ(getResources().openRawResource(R.raw.tractor_obj),
                  getResources().openRawResource(R.raw.tractor_mtl), 1.0f));
            sprayer = Object3D.mergeAll(Loader.loadOBJ(getResources().openRawResource(R.raw.fumigadora_de_arrastre_obj),
                  getResources().openRawResource(R.raw.fumigadora_de_arrastre_mtl),1.0f));
           
            floor = Primitives.getPlane(1, 10000);
            floor.rotateX((float) (90 * Math.PI / 180));
            floor.setTexture("floor");
           
            //Generate a track for testing propose
            track = new Object3D(2);
            SimpleVector v1 = new SimpleVector(), v2 = new SimpleVector(), v3 = new SimpleVector(), v4 = new SimpleVector();
            v1.set(-working_width / 2, 0, 0);
            v2.set( working_width / 2, 0, 0);
            v3.set( working_width / 2, 0, -1000);
            v4.set(-working_width / 2, 0, -1000);
            track.addTriangle(v2, 1, 0, v1, 1, 0, v3, 1, -1, TextureManager.getInstance().getTextureID("track"));
            track.addTriangle(v1, 0, 0, v4, 0, -1, v3, 1, -1, TextureManager.getInstance().getTextureID("track"));
           
            /*track2 = new Object3D(200000);
            track2.setTransparency((int)(2^12-1));
            track2.setTransparencyMode(Object3D.TRANSPARENCY_MODE_DEFAULT);
            track2.build();
            track2.compile(true, true);
            world.addObject(track2);*/
            tractor.strip();
            tractor.build();
            tractor.rotateZ((float) (180 * Math.PI / 180));
            tractor.translate(0, -tractor.getCenter().y * 2, 0);
            sprayer.build();
            sprayer.strip();
            sprayer.rotateZ((float) (180 * Math.PI / 180));
            sprayer.translate(0, -tractor.getCenter().y * 2, 0);
            floor.strip();
            floor.build();
            floor.translate(0,0,0);
            track.setTransparency((int)(2^12-1));
            track.setTransparencyMode(Object3D.TRANSPARENCY_MODE_DEFAULT);
            track.strip();
            track.build();
            track.translate(0, -0.5f, 0);
            world.addObject(tractor);
            world.addObject(sprayer);
            world.addObject(floor);
            world.addObject(track);

            cam = world.getCamera();
            cam.setPosition(0, 0, 0);
            cam.moveCamera(Camera.CAMERA_MOVEOUT, 10);
            cam.moveCamera(Camera.CAMERA_MOVEUP, 3);
            cam.lookAt(tractor.getTransformedCenter());

            SimpleVector sv = new SimpleVector();

            sv.x = 4000;
            sv.y = -4000;
            sv.z = 4000;
            sun.setPosition(sv);
            t0 = tractor.getTransformedCenter();
            t1 = tractor.getTransformedCenter();
           
            MemoryHelper.compact();

            if (master == null) {
               Logger.log("Saving master Activity!");
               master = MainActivity.this;
            }
         }
      }
     
     
      Matrix rotationmatrix, transformMatrix;
      SimpleVector camera_axis = new SimpleVector();
      SimpleVector v0 = new SimpleVector(), v1 = new SimpleVector(), v2 = new SimpleVector();
      int i = 0;
      boolean right_triangle = false;
     
      public void onDrawFrame(GL10 gl) {   
         camera_axis.set(0, 0, mGLView.touchTurnUp);
         
         if (mGLView.touchTurn != 0) {
            mGLView.touchTurn = 0;
         }
         if (mGLView.touchTurnUp != 0) {
            mGLView.touchTurnUp = 0;
         }
         tractor.translate(tractor_direction);
         
         
         SimpleVector t2 = tractor.getTransformedCenter();
         if (!t0.equals(t1) && !t1.equals(t2) && !t2.equals(t0)) {
            Object3D g = new Object3D(1);
            v0.set(v1);
            v1.set(v2);
            if (right_triangle) {
               v2.set(working_width / 2, 0, 0);
               v2.rotateY(tractor_direction_angle);
               v2.set(v2.calcAdd(t2));
            }
            else {
               v2.set(-working_width / 2, 0, 0);
               v2.rotateY(tractor_direction_angle);
               v2.set(v2.calcAdd(t2));
            }
            g.addTriangle(v0, 0, 0, v1, 1, 0, v2, 1, 1, TextureManager.getInstance().getTextureID("track2"));
            if (right_triangle) g.invert();
            /*track2.addChild(g);
            track2.touch();*/
            g.build();
            g.setTransparency((int)(2^12-1));
            g.setTransparencyMode(Object3D.TRANSPARENCY_MODE_DEFAULT);
            world.addObject(g);
            right_triangle = !right_triangle;

         }
         else {
            v1.set(t2.x + working_width / 2, t2.y, t2.z);
            v0.set(t2.x - working_width / 2, t2.y, t2.z);
         }
         t0.set(t1);
         t1.set(t2);

         cam.setPositionToCenter(tractor);
         cam.align(tractor);
         cam.moveCamera(Camera.CAMERA_MOVEOUT, 10);
         cam.moveCamera(Camera.CAMERA_MOVEUP, -4);

         cam.lookAt(tractor.getTransformedCenter());
         
         fb.clear(back);
         world.renderScene(fb);
         world.draw(fb);
         fb.display();
         tv.post(new Runnable() {
           
            @Override
            public void run() {
               tv.setText("x=" + String.valueOf(t0.x) +
                  "; y=" + String.valueOf(t0.z) +
                  "; thita=" + String.valueOf(Math.toDegrees(tractor_direction_angle)) + "; Nº=" +  String.valueOf(world.getSize()));
               MemoryHelper.printMemory();
            }
         });
      }
   }

   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.main, menu);
      return true;
   }
   
   /**
    * Obtiene las cotas maximas y minimas
    * @param obj
    * @return  float[0] = x.min;
    *          float[2] = y.min;
    *          float[4] = z.min;
    *        float[1] = x.max;
    *        float[3] = y.max;
    *        float[5] = z.max
    */
   public float[] getWorldSpaceBounds(Object3D obj) {
      float[] objectSpaceBounds = obj.getMesh().getBoundingBox();
      SimpleVector mins = new SimpleVector(objectSpaceBounds[0], objectSpaceBounds[2], objectSpaceBounds[4]);
      SimpleVector maxs = new SimpleVector(objectSpaceBounds[1], objectSpaceBounds[3], objectSpaceBounds[5]);
      SimpleVector[] p = new SimpleVector[8];
      p[0] = new SimpleVector(mins.x, mins.y, maxs.z); p[1] = new SimpleVector(mins.x, mins.y, mins.z); p[2] = new SimpleVector(maxs.x, mins.y, mins.z);
      p[3] = new SimpleVector(maxs.x, mins.y, maxs.z); p[4] = new SimpleVector(maxs.x, maxs.y, mins.z);
      p[5] = new SimpleVector(maxs.x, maxs.y, maxs.z); p[6] = new SimpleVector(mins.x, maxs.y, mins.z); p[7] = new SimpleVector(mins.x, maxs.y, maxs.z);
      float minX = Float.MAX_VALUE, minY = Float.MAX_VALUE, minZ = Float.MAX_VALUE, maxX = -Float.MAX_VALUE, maxY = -Float.MAX_VALUE, maxZ = -Float.MAX_VALUE;
      for (int i = 0; i < 8; i++) {
           p[i].matMul(obj.getWorldTransformation());
           if (p[i].x < minX)
         minX = p[i].x;
           if (p[i].y < minY)
         minY = p[i].y;
           if (p[i].z < minZ)
         minZ = p[i].z;
           if (p[i].x > maxX)
         maxX = p[i].x;
           if (p[i].y > maxY)
         maxY = p[i].y;
           if (p[i].z > maxZ)
         maxZ = p[i].z;
      }
      float[] worldSpaceBounds = new float[6];
      worldSpaceBounds[0] = minX;
      worldSpaceBounds[2] = minY;
      worldSpaceBounds[4] = minZ;
      worldSpaceBounds[1] = maxX;
      worldSpaceBounds[3] = maxY;
      worldSpaceBounds[5] = maxZ;
      return worldSpaceBounds;
   }

}


How can improve the refresh?
Is a VertexController a solution to the slow refresh? How I must use it?

Thanks in advance.
Claudio Nasich