jPCT-AE - a 3d engine for Android > Support

How to draw a simple 2D line onto my jPCT Framebuffer?

<< < (2/4) > >>

EgonOlsen:
Use


--- Code: ---Interact2D.reproject2D3DWS(...)
--- End code ---

instead of


--- Code: ---Interact2D.reproject2D3D(...)

--- End code ---

With your code, you are calculating the coordinates in camera space, which is not what you want.

HammerNL:
Hi Egon,

Using reproject2D3DWS() does not seem to change a lot, my line is still just 3 or 4 pixels in the middle of the screen. Also, I've noticed that when I move the cam around, the reprojected lines move as well. Even though I am calling reproject2D3DWS() after every camera move. The idea is that the lines remain static on screen, like an overlay.

As the camera is passed as an argument into the reproject2D3DWS() method, I expected the method to come up with 3D coordinates that result in the exact same 2D coordinates, even when the cam is moved.

I'm still missing a vital piece. I think we need an example here to clarify things. I used your "hello world" app to demonstrate what I'm doing:


--- Code: ---package com.example.line2don3d;

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 android.view.MotionEvent;

import com.threed.jpct.*;

public class HelloWorld extends Activity {

  public final static float PI = (float)Math.PI;
  public final static SimpleVector XAXIS = new SimpleVector(1,0,0);
  public final static SimpleVector YAXIS = new SimpleVector(0,1,0);
  public final static SimpleVector ZAXIS = new SimpleVector(0,0,1);
  public final static float DEGtoRAD = PI/180;

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

  private GLSurfaceView mGLView;
  private MyRenderer renderer = null;
  private FrameBuffer fb = null;
  private World meterWorld = null;
  private RGBColor back = new RGBColor(0,0,0);

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

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

  private Camera cam = null;
  private float camX = 100;
  private float camY = 0;

  private Polyline fuelLine = 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) {
        // 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 {

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

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

        Light sun = new Light(meterWorld);
        sun.setIntensity(255,255,255);
        sun.setPosition(new SimpleVector(100,0,0));

        cam = meterWorld.getCamera();
        cam.setPosition(camX,camY,0);
        cam.setOrientation(new SimpleVector(-1,0,0),ZAXIS);

        Object3D cube = Primitives.getCube(10);
        cube.setAdditionalColor(0xff,0xff,0);
        cube.setOrigin(SimpleVector.ORIGIN);
        cube.build();
        meterWorld.addObject(cube);

        fuelLine = new Polyline(new SimpleVector[] { new SimpleVector(-20,0,20), new SimpleVector(20,20,20) }, RGBColor.RED);
        fuelLine.setWidth(3);
        meterWorld.addPolyline(fuelLine);

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

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

    private float fuel = 0;

    public void onDrawFrame(GL10 gl) {
      if (touchTurn != 0)
      {
        camY += touchTurn*10;
        cam.setPosition(camX,camY,0);
        cam.setOrientation(new SimpleVector(-1,0,0),ZAXIS);
        touchTurn = 0;
      }

      if (touchTurnUp != 0)
      {
        camX += touchTurnUp*10;
        cam.setPosition(camX,camY,0);
        cam.setOrientation(new SimpleVector(-1,0,0),ZAXIS);
        touchTurnUp = 0;
      }

      fuel += 0.01; // make the fuel line spin around and  around

      float angle = (-60+fuel*120)*DEGtoRAD;
      int x = 200;
      int y = 200;
      float r = 50;

      SimpleVector[] vectors = new SimpleVector[]
        {
          Interact2D.reproject2D3DWS(cam,fb,x,y),
          Interact2D.reproject2D3DWS(cam,fb,(int)(x+Math.sin(angle)*r+0.5),(int)(y-Math.cos(angle)*r+0.5))
        };
      fuelLine.update(vectors);

      fb.clear(back);
      meterWorld.renderScene(fb);
      meterWorld.draw(fb);
      fb.display();
    }
  }
}

--- End code ---

What I'm getting with this, is a yellow cube on the origin, and inside the cube (so zoom in A LOT by sliding down) I find my little line that is spinning around. What I want is a spinning line around the actual sceen coordinate 200,200 with a radius of 50 pixels. What to do?

EgonOlsen:
You have to keep in mind that this method returns a direction vector, not a position vector. Like the docs state, it's the direction vector from the camera's position to that given point in 3d. To make this a renderable Polyline, you have to add the position vector of the camera to both results.

HammerNL:
That's it! I missed that line in the docs, see it now.
So simple. Tanx, working perfect now!

HammerNL:
Almost there... only one tiny problem. I'm doing this in my onDrawFrame() method:


--- Code: ---      fb.clear(back);
      world.renderScene(fb);
      world.draw(fb);

      fb.blit(fuelMeter,0,0,0,0,256,256,200,200,100,false);

      meterWorld.renderScene(fb);
      meterWorld.draw(fb);
      fb.display();
--- End code ---

So first I draw my world containing the actual game objects, then I blit the static part of the fuel meter on top of it, and finally I draw the world containing nothing but my fuel indicator line on top of that. It all works great, except for 1 tiny detail:

The color of the polyline in the "meterWorld" is always white!? Even though it is defined as red:


--- Code: ---fuelLine = new Polyline(new SimpleVector[] { new SimpleVector(-20,0,20), new SimpleVector(20,20,20) }, RGBColor.RED);
--- End code ---

After some trail-and-error I found that removing the fb.blit() call fixes the issue, thus my Polyline is actually red then.

Why does this blit affect the color of the polyline? And how can I prevent that from happening?

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version