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 - Darai

#1
That worked,  :)
thank you.
#2
Hi,

I have here a strange behaviour you surely know what to do with. It looks so obvious that it must be a mistake on my side. But I am still new in this so I am asking for your help.

I created a simple object and apply to it a vertex controller. (and put lamp and ambient lighting) In the moment I applied the controller, the object get's darker and stays that way. Like the sun does not apply for the object any more. Do you know why and how to fix it? How does it look can be seen in the attached screenshots.

Thank you,
Darai.

The renderer

public void onSurfaceChanged(GL10 gl, int w, int h) {
...
world = new World();
world.setAmbientLight(20, 20, 20);

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

sqr = new MiniMonster3D();

sqr.setTexture("Tex");
sqr.setScale(10f);
sqr.build();

world.addObject(sqr);
Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
cam.lookAt(sqr.getTransformedCenter());

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

public void onDrawFrame(GL10 gl) {
...
  if (System.currentTimeMillis() - time >= 100) {
    //Logger.log(fps/10 + "fps");
    fps = 0;
    time = System.currentTimeMillis();
    sqr.pulse();
  }
  fps++;
...
}


the Object

public class MiniMonster3D extends Object3D {

public MiniMonster3D(){
super(2);
SimpleVector LU = new SimpleVector(-0.5f, -0.5f, 0f);
SimpleVector LD = new SimpleVector(-0.5f, 0.5f, 0f);
SimpleVector RU = new SimpleVector(0.5f, -0.5f, 0f);
SimpleVector RD = new SimpleVector(0.5f, 0.5f, 0f);
this.addTriangle(LU,0,0,LD,0,1,RD,1,1);
this.addTriangle(LU,0,0,RD,1,1,RU,1,0);
this.getMesh().setVertexController(new MyVertexController(), false);
}

public void pulse(){
this.getMesh().applyVertexController();
this.touch();
}
}


the Controller

public class MyVertexController extends GenericVertexController {
...
@Override
public void apply() {
nextScale();
Log.i("VC", "pulse, scale = "+myscale);
SimpleVector[]out = getDestinationMesh();
SimpleVector[]in  = getSourceMesh();
SimpleVector tgt, src;
for(int i = 0;i<3;i++){
tgt = out[i];
src = in[i];
tgt.x = src.x*myscale;
tgt.y = src.y*myscale;
tgt.z = src.z*myscale;
}
}
...

#3
Hello,

one (hopefully last) question concerning this topic...
When I stopped destroying the buffer, I also caused following problem: When I "Hide" the UI, the whole screen moves down and creates a rectengle of unused screen above of the size (roughly) of the original UI bar... Can I stretch the original screen somehow to cover also this area? or move it somehow? or how can I get rid of this problem? (Without starting destroying the buffer again since that is the only solution to the previous problem)

I am demonstrating this behaviour on attached screenshots (With / Without soft keys UI) and I am also posting the simple code example. As usual, every help will be most appreciated, thanks.
package com.threed.jpct.example;

import java.lang.reflect.Field;
import java.util.Random;

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

import android.annotation.SuppressLint;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

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;

/**
* @author Darai
*
*/
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 int fps = 0;

private Light sun = null;

private GL10 lastGl = null;

private RGBColor back = new RGBColor(50,50,10);

private static final int SWAP_UI = 1;
private boolean swapUI = false;

private Random rand = new Random();

    // Handle the message for turning on and off the immersive GUI
public static Handler handler = new Handler(Looper.getMainLooper()){
public void handleMessage(Message message) {
    // Handle the message on the thread associated to the given looper.
    if (message.what == HelloWorld.SWAP_UI) { swapSystemUIdo();}
  }
};

public static int countSquares = 0;
public Object3D obj;
public Texture texture;


protected void onCreate(Bundle savedInstanceState) {

Logger.log("onCreate");

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

super.onCreate(savedInstanceState);

mGLView = new GLSurfaceView(getApplication());
mGLView.setEGLContextClientVersion(2);
mGLView.setPreserveEGLContextOnPause(true);

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

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

    // Swap System UI Send message to the main Activity thread.
public static void swapSystemUI(){
Message message = new Message();
message.what = HelloWorld.SWAP_UI;
HelloWorld.handler.sendMessage(message);
}

    // Swap System UI - do the work (this is the right thread which can do this)
@SuppressLint("InlinedApi")
protected static void swapSystemUIdo() {
Log.i("MainActivity", "swapUI");
    // Set the IMMERSIVE flag.
    // Set the content to appear under the system bars so that the content
    // doesn't resize when the system bars hide and show.
        int uiSetting = HelloWorld.getApp().getWindow().getDecorView().getSystemUiVisibility();
        int ver = Build.VERSION.SDK_INT;
        if(ver>=14){uiSetting ^= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;}
        if(ver>=16){uiSetting ^= View.SYSTEM_UI_FLAG_FULLSCREEN;}
        if(ver>=19){uiSetting ^= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;}       
        HelloWorld.getApp().getWindow().getDecorView().setSystemUiVisibility(uiSetting);
}

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

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

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

if (me.getAction() == MotionEvent.ACTION_UP) {
swapUI = true;
return true;
}

if (me.getAction() == MotionEvent.ACTION_MOVE) {
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) {

// Renew the frame buffer
if(lastGl!=gl){
Log.i("HelloWorld","Init buffer");
if (fb != null) {
fb.dispose();
}
fb = new FrameBuffer(w, h);
fb.setVirtualDimensions(fb.getWidth(), fb.getHeight());
lastGl = gl;
}

// Create the world if not yet created
if (master == null) {
world = new World();
world.setAmbientLight(20, 20, 20);

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

// Create the texture we will use in the blitting
texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(getResources().getDrawable(R.drawable.icon)), 256, 256));
TextureManager.getInstance().addTexture("texture", texture);

// Create the object
obj = Primitives.getPlane(1, 20f);
world.addObject(obj);
obj.translate(0, 0, 0);
obj.setTexture("texture");
obj.build();

Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 15);
cam.lookAt(SimpleVector.ORIGIN);

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

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

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

public void onDrawFrame(GL10 gl) {

// If the switch is on, call the UI swap in the correct thread
if (swapUI) {
HelloWorld.swapSystemUI();
swapUI = false;
}

// Draw the main screen
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 static HelloWorld getApp(){return master;}
}


#4
In the example I wrote here (Heavy misuse of the buffer on every tick) it happend every time I called the swapUI. But I haven't yet enough time to do more test runs to be really sure. And the swapUI utility runs in different thread than the rendering so I don't know if it happend inbetween two onDraw() runs or in the middle of one of them or just randomly every time.

Ok, so since I can expect the buffer to survive and work as long as I will run the app and since there is no problem when I do the first renderring when I start / restart the app I believe it will be ok. Thanks for the clarification.
#5
Hi,

thanks for the quick reply. Actualy it is not that complex. I just hitted a real life problem and stripped it to its bare basic = cause the renderer to call the onSurfaceChange when it is doing blitting. Since this (UI swap) is the only situation I know, when I have to call the onSurfaceChange in the middle of the run, this was obvious choise. I used multiple objects for blitting to simulate the real worst case scenario.

To condition the buffer renewal (as you suggested) really helped. Now it works smoothly. But now I am little bit affraid, since I don't know, when is the gl10 variable of the renderer changing... In other words, when can I expect that it will be necessary to recreate the buffer? Can I expect the program to blow up on me in some cases?

public void onSurfaceChanged(GL10 gl, int w, int h) {

// Renew the frame buffer
if(lastGl!=gl){
Log.i("HelloWorld","Init buffer");
if (fb != null) {
fb.dispose();
}
fb = new FrameBuffer(w, h);
fb.setVirtualDimensions(fb.getWidth(), fb.getHeight());
lastGl = gl;
}


And also the example works even without the
mGLView.setPreserveEGLContextOnPause(true);
and I admit that it is my fault that I don't understand what that switch does even after reading it's doc and how is it connected to my GL surface frame buffer problem. So if you will clarify it a little bit or point me to some more information, I will be most grateful.

But even with this information I have from you now, I can continue with the work... so thank you again.
#6
Support / Re: Looking for a GPU...
February 10, 2016, 02:23:08 PM
Hmm is there a siple way to find out which GPU you have in the device? I'll probably have to search the net...
Well I have Nexus 7, which means Nvidia Tegra 3, but that is CPU, not GPU unles it ... nope, I just find that I have there probably Adreno 320. Sorry.
#7
Support / SystemUI swap & Failed to create frame buffer
February 10, 2016, 02:15:40 PM
Hello again,

here is a new issue I would like to ask about. I am testing the code with the blitting to texture you gave me (thanks again EgonOlsen so much) http://www.jpct.net/forum2/index.php/topic,4609.0.html. I implemented several performance tests and now I'm trying following situation:

  • Blit to the texture every frame
  • Have more than one object on the screen (in my example 100)
  • Try to call DecorView.setSystemUiVisibility() to show/hide the system icons of the phone. For simple, I have it here initiated by touching the screen

What is the expected problem: The program calls the main activity thread to swap the UI visibility, which initiates new onSurfaceChange run of the renderer and recreates the buffer. And in the same time use intensively the buffer by the blit function on multiple objects.

Here is the entire test activity:
package com.threed.jpct.example;

import java.lang.reflect.Field;
import java.util.Random;

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

import android.annotation.SuppressLint;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

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;

/**
* @author Darai
*
*/
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 int fps = 0;

private Light sun = null;

private RGBColor back = RGBColor.BLACK;

private static final int SWAP_UI = 1;
private boolean swapUI = false;

private Random rand = new Random();

    // Handle the message for turning on and off the immersive GUI
public static Handler handler = new Handler(Looper.getMainLooper()){
public void handleMessage(Message message) {
    // Handle the message on the thread associated to the given looper.
    if (message.what == HelloWorld.SWAP_UI) { swapSystemUIdo();}
  }
};

public static int countSquares = 0;
public Square[] squares = new Square[100];
public Texture texture;
public static Object frameBufferSync = new Object();

    // We are having 100 squares with blitting to their textures on every tick
public class Square{
private final int curID = countSquares++;
private final String texName = "squateTex/"+curID;
public static final float f = 5f;
public Object3D obj;
public Texture tex;

    // Create texture and object
public Square(){
obj = Primitives.getPlane(1, (float)rand.nextFloat()+0.5f);
tex = new Texture(64,64);
TextureManager.getInstance().addTexture(texName, tex);
world.addObject(obj);
obj.translate(2*rand.nextFloat()*f - f, 2*rand.nextFloat()*f - f, 0);
obj.setTexture(texName);
obj.build();
}

    // redo the texture on every tick (clear and blit)
public void onTick(){
fb.sync();
fb.setRenderTarget(tex);
int col = rand.nextInt(50)+200;
fb.clear(new RGBColor(col,col,col));
int x = convertX(fb, 5);
int y = convertY(fb, tex.getHeight() - 5);
int width = convertX(fb, tex.getWidth()-10);
int height = -convertY(fb, tex.getHeight()-10);
fb.blit(texture, 0, 0, x, y, 64, 64, width, height, -1, false, null);
fb.display();
fb.removeRenderTarget();
}

public int convertX(FrameBuffer buffer, int x) {
return (int) ((float) x * ((float) buffer.getWidth() / (float) tex.getWidth()));
}

public int convertY(FrameBuffer buffer, int y) {
return (int) ((float) y * ((float) buffer.getHeight() / (float) tex.getHeight()));
} }

protected void onCreate(Bundle savedInstanceState) {

Logger.log("onCreate");

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

super.onCreate(savedInstanceState);

mGLView = new GLSurfaceView(getApplication());
mGLView.setEGLContextClientVersion(2);

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

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

    // Swap System UI Send message to the main Activity thread.
public static void swapSystemUI(){
Message message = new Message();
message.what = HelloWorld.SWAP_UI;
HelloWorld.handler.sendMessage(message);
}

    // Swap System UI - do the work (this is the right thread which can do this)
@SuppressLint("InlinedApi")
protected static void swapSystemUIdo() {
Log.i("MainActivity", "swapUI");
    // Set the IMMERSIVE flag.
    // Set the content to appear under the system bars so that the content
    // doesn't resize when the system bars hide and show.
        int uiSetting = HelloWorld.getApp().getWindow().getDecorView().getSystemUiVisibility();
        int ver = Build.VERSION.SDK_INT;
        if(ver>=14){uiSetting ^= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;}
        if(ver>=16){uiSetting ^= View.SYSTEM_UI_FLAG_FULLSCREEN;}
        if(ver>=19){uiSetting ^= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;}       
        HelloWorld.getApp().getWindow().getDecorView().setSystemUiVisibility(uiSetting);
}

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

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

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

if (me.getAction() == MotionEvent.ACTION_UP) {
swapUI = true;
return true;
}

if (me.getAction() == MotionEvent.ACTION_MOVE) {
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) {

// Renew the frame buffer
synchronized(frameBufferSync){
if (fb != null) {
fb.dispose();
}
fb = new FrameBuffer(w, h);
fb.setVirtualDimensions(fb.getWidth(), fb.getHeight());
}

// Create the world if not yet created
if (master == null) {
world = new World();
world.setAmbientLight(20, 20, 20);

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

// Create the texture we will use in the blitting
texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(getResources().getDrawable(R.drawable.icon)), 64, 64));
TextureManager.getInstance().addTexture("texture", texture);

// Create the 100 objects
for(int i = 0;i<squares.length;i++){squares[i]=new Square();}

Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 15);
cam.lookAt(SimpleVector.ORIGIN);

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

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

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

public void onDrawFrame(GL10 gl) {

// If the switch is on, call the UI swap in the correct thread
if (swapUI) {
HelloWorld.swapSystemUI();
swapUI = false;
}

synchronized(frameBufferSync){
// Blit to all the objects
for(int i = 0;i<squares.length;i++){squares[i].onTick();}

// Draw the main screen
fb.clear(back);
world.renderScene(fb);
world.draw(fb);
world.getCamera().moveCamera(Camera.CAMERA_MOVEOUT, 0.1f);
world.getCamera().rotateCameraZ(0.01f);

fb.display();
}

if (System.currentTimeMillis() - time >= 1000) {
Logger.log(fps + "fps");
fps = 0;
time = System.currentTimeMillis();
}
fps++;
}
}

public static HelloWorld getApp(){return master;}
}



Well, I have got an error message and app run failure. The error is fixed on the blit function, if I don't blit, it works just fine. The synchronization I tried in this example didn't helped.
Quote
02-10 13:55:58.411: E/jPCT-AE(19599): [ 1455108958411 ] - ERROR: Failed to create frame buffer (102): glError 1282
02-10 13:55:58.470: E/AndroidRuntime(19599): FATAL EXCEPTION: GLThread 7271
02-10 13:55:58.470: E/AndroidRuntime(19599): Process: com.threed.jpct.example, PID: 19599
02-10 13:55:58.470: E/AndroidRuntime(19599): java.lang.RuntimeException: [ 1455108958411 ] - ERROR: Failed to create frame buffer (102): glError 1282
02-10 13:55:58.470: E/AndroidRuntime(19599):    at com.threed.jpct.Logger.log(Logger.java:206)
02-10 13:55:58.470: E/AndroidRuntime(19599):    at com.threed.jpct.GL20.checkError(GL20.java:158)
02-10 13:55:58.470: E/AndroidRuntime(19599):    at com.threed.jpct.GL20.setRenderTarget(GL20.java:2007)
02-10 13:55:58.470: E/AndroidRuntime(19599):    at com.threed.jpct.GLRenderer.setRenderTarget(GLRenderer.java:2111)
02-10 13:55:58.470: E/AndroidRuntime(19599):    at com.threed.jpct.FrameBuffer.setRenderTarget(FrameBuffer.java:260)
02-10 13:55:58.470: E/AndroidRuntime(19599):    at com.threed.jpct.FrameBuffer.setRenderTarget(FrameBuffer.java:222)
02-10 13:55:58.470: E/AndroidRuntime(19599):    at com.threed.jpct.example.HelloWorld$Square.onTick(HelloWorld.java:94)
02-10 13:55:58.470: E/AndroidRuntime(19599):    at com.threed.jpct.example.HelloWorld$MyRenderer.onDrawFrame(HelloWorld.java:277)
02-10 13:55:58.470: E/AndroidRuntime(19599):    at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1535)
02-10 13:55:58.470: E/AndroidRuntime(19599):    at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)

Do you EgonOlsen or you guys know what to do with this?
Thanks for any help, Darai.
#8
Support / Re: More FrameBuffers in one program
February 04, 2016, 02:19:49 PM
And third and fourth... All but the first one are wrong...

This examle has only two objects because I wanted it to be simple, but I foud this problem on a more complex  implementation and I backtracked it here, so I can tell you also this one additional information.  :)

Interrestingly also in every onSurfaceChanged() the first texture you will blit-in will be done succesfully no matter how many times you will blit into it. But once you will try to blit to one and than switch and blit to another one... the second e.t.c. will be wrong. And no only in the first frame or second, but in every frame you will try it in.
#9
Support / Re: More FrameBuffers in one program
February 04, 2016, 02:07:54 PM
Sure, here is the screenshot (attachment):
If attachment is a bad approach, let me know and I will upload it to ImageShack
I admit, twisted is not a good description... so let's say cutted and zoomed.
#10
Support / Now for two textures
February 04, 2016, 01:49:35 PM
Hello, Egon,

I am sorry for pulling this out so many times, but I really need to solve this to know if I can use the feature or abandon this approach and do something else...

What I did:

  • I used your recalculation method to get the proper x,y,width and height
  • I made the textures to render on the second frame so I overcome the first frame issue
  • I forced the program to render to TWO textures to find out how it will behave when I will need him to render everything for the whole scene on the second frame.
And the result is strange, twisted again. I am printing here the example code... it is really only that your code with added second texture to plot to. Can you give me a hint what I did wrong? Thanks.

package com.threed.jpct.example;

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.Camera;
import com.threed.jpct.Config;
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;

/**
* @author EgonOlsen
*
*/
public class HelloWorld extends Activity {

// Used to handle pause and resume...
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 float touchTurn = 0;
private float touchTurnUp = 0;

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

private Object3D cube = null;
private int fps = 0;
private boolean gl2 = true;
private boolean first = true;

private Light sun = null;

private Texture target = null;
private Texture target2 = null;
private Texture texture = null;
private World dummyWorld = new World();

private boolean firstRun = true;

protected void onCreate(Bundle savedInstanceState) {

Logger.log("onCreate");

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

super.onCreate(savedInstanceState);
mGLView = new GLSurfaceView(getApplication());

if (gl2) {
mGLView.setEGLContextClientVersion(2);
} else {
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();
System.exit(0);
}

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

if (gl2) {
fb = new FrameBuffer(w, h); // OpenGL ES 2.0 constructor
} else {
fb = new FrameBuffer(gl, w, h); // OpenGL ES 1.x constructor
}

Config.viewportOffsetY = -0.15f;

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 = new Texture(BitmapHelper.rescale(BitmapHelper.convert(getResources().getDrawable(R.drawable.icon)), 64, 64));
TextureManager.getInstance().addTexture("texture", texture);

cube = Primitives.getCube(10);
cube.calcTextureWrapSpherical();
cube.setTexture("texture");
cube.strip();
cube.build();

target = new Texture(256, 256);
TextureManager.getInstance().addTexture("target", target);

target2 = new Texture(256, 256);
TextureManager.getInstance().addTexture("target2", target2);

world.addObject(cube);
cube.translate(15f, 0f, 0f);

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

if (master == null) {
Logger.log("Saving master Activity!");
master = HelloWorld.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;
}
if(firstRun){
if(first){
first = false;
}else{
// Snip on first
fb.setRenderTarget(target);
fb.sync();
int x = convertX(fb, target, 0);
int y = convertY(fb, target, target.getHeight() - 0);
int width = convertX(fb, target, target.getWidth());
int height = -convertY(fb, target, target.getHeight());
fb.blit(texture, 0, 0, x, y, texture.getWidth(), texture.getHeight(), width, height, -1, false, null);
dummyWorld.renderScene(fb);
dummyWorld.draw(fb);
fb.display();
fb.removeRenderTarget();
// Snip on second
fb.setRenderTarget(target2);
fb.sync();
x = convertX(fb, target2, 0);
y = convertY(fb, target2, target2.getHeight() - 0);
width = convertX(fb, target2, target2.getWidth());
height = -convertY(fb, target2, target2.getHeight());
fb.blit(texture, 0, 0, x, y, texture.getWidth(), texture.getHeight(), width, height, -1, false, null);
dummyWorld.renderScene(fb);
dummyWorld.draw(fb);
fb.display();
fb.removeRenderTarget();
firstRun = false;
}
}
// Snap

fb.clear(back);
world.renderScene(fb);
world.draw(fb);
world.getCamera().moveCamera(Camera.CAMERA_MOVEOUT, 0.1f);
world.getCamera().rotateCameraZ(0.01f);

// And blit the result
fb.blit(target, 0, 0, 10, 10, 256, 256, 400, 400, -1, false, null);
fb.blit(target2, 0, 0, 10, 510, 256, 256, 400, 400, -1, false, null);

fb.display();

if (System.currentTimeMillis() - time >= 1000) {
Logger.log(fps + "fps");
fps = 0;
time = System.currentTimeMillis();
}
fps++;
}

public int convertX(FrameBuffer buffer, Texture target, int x) {
return (int) ((float) x * ((float) buffer.getWidth() / (float) target.getWidth()));
}

public int convertY(FrameBuffer buffer, Texture target, int y) {
return (int) ((float) y * ((float) buffer.getHeight() / (float) target.getHeight()));
}
}
}
#11
Support / Re: More FrameBuffers in one program
January 29, 2016, 09:58:20 AM
I have it,

I was damaging your code up until it did the same thing I was experiencing in my code. The important difference is, that I was doing the new texture rendering only on the first onSurfaceDraw() using this code (I added the firstRun if condition). So that is the problem. On the first onDrawFrame() run, the blit is acting differently.  ;D

public void onDrawFrame(GL10 gl) {
if (touchTurn != 0) {
cube.rotateY(touchTurn);
touchTurn = 0;
}

if (touchTurnUp != 0) {
cube.rotateX(touchTurnUp);
touchTurnUp = 0;
}
if(firstRun){
// Snip
fb.setRenderTarget(target);
fb.sync();
int x = convertX(fb, target, 0);
int y = convertY(fb, target, target.getHeight() - 0);
int width = convertX(fb, target, target.getWidth());
int height = -convertY(fb, target, target.getHeight());
fb.blit(texture, 0, 0, x, y, texture.getWidth(), texture.getHeight(), width, height, -1, false, null);
dummyWorld.renderScene(fb);
dummyWorld.draw(fb);
fb.display();
fb.removeRenderTarget();
firstRun = false;
}
// Snap

fb.clear(back);
world.renderScene(fb);
world.draw(fb);
world.getCamera().moveCamera(Camera.CAMERA_MOVEOUT, 0.1f);
world.getCamera().rotateCameraZ(0.01f);

// And blit the result
fb.blit(target, 0, 0, 10, 10, 256, 256, 400, 400, -1, false, null);

fb.display();

if (System.currentTimeMillis() - time >= 1000) {
Logger.log(fps + "fps");
fps = 0;
time = System.currentTimeMillis();
}
fps++;
}
#12
Support / Re: More FrameBuffers in one program
January 28, 2016, 04:32:25 PM
One small addition, sorry :)

possibly a bug report, but first evaluate this by yourself, maybe you allready fixed this in the new beta version:
The scaling of the blitting to the texture is wrong. Even the convert function is not entirely helping. The image on the new texture was suspiciously scaled in a simmilar ratio as the screen (== the buffer) was, so I was experimenting and it turned out that if you want to blit one texture to another one using FrameBuffer fb, the variables you need are not:

int destX = 0;
int destY = -fb.getHeight();
int destWidth = fb.getWidth();
int destHeight = fb.getHeight();

as you suggested but actually:

int destX = 0;
int destY = (int)((float)(fb.getWidth()+fb.getHeight())/2f);
int destWidth = fb.getWidth();
int destHeight = -fb.getWidth();

Including the strange int destHeight = fb.getWidth();, that is not an error in my transcription I checked it and rechecked it it really works this way, check it please too if it is only my bug, and I should download your beta or if it is really still there.
#13
Support / Re: More FrameBuffers in one program
January 28, 2016, 03:29:51 PM
Finally, it is alive!!  :)

Thank you. So, to summarize it (how to blit into a texture):

  • It is doable, so if you need to change a texture dynamically, ForExample to write a text on it once in a while, go for it.
  • It doesn't work without GL2.0 http://www.jpct.net/wiki/index.php?title=OpenGL_ES_2.0_support Beware of the difference in the FrameBuffer constructor.
  • The draw to a texture has to be done in the onDraw function (well, actualy onDrawFrame() function) (Which sucks, since up until now I had all model preparation in onSurfaceChange() and now I will have to divide it, but hey that is life.)
  • The draw has to be done using the one and only FrameBuffer in the app. No other FrameBuffers allowed.
  • The best command sequence to blit into the texture is in the previous posts, combining setRenderTarget() method and a blank emptyBlitWorld World.
And that is that... thanks again for all your help.
#14
Support / Re: More FrameBuffers in one program
January 28, 2016, 02:47:08 PM
Still no success,

The renderer requires the onDrawFrame(GL10 gl) method, so I am using this for the normal onDraw stuff. I tried to add the texture alternating code to the beginning of this onDrawFrame() and also to the isolated onDraw() method, but without success. So again, I expect that I am something missing, but what? obj2.build(false)? obj2.touch()? I tried those with the same result.


public void onDrawFrame(GL10 gl) {
if(!textureChanged){
textureChanged = true;

int destX = convertX(fb, 0);
int destY = convertY(fb, tx2.getHeight() - 0);
int destWidth = convertX(fb, 256);
int destHeight = -convertY(fb, 256);

fb.setRenderTarget(tx2);
fb.sync();
fb.clear(RGBColor.BLUE);
fb.blit(tx1, 0, 0, destX, destY, 512, 512, destWidth, destHeight, 255, false);
fb.display();
fb.removeRenderTarget();
}
fb.clear(RGBColor.BLUE);
world.renderScene(fb);
world.draw(fb);
fb.display();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

#15
Support / Re: More FrameBuffers in one program
January 28, 2016, 02:01:27 PM
Hmm,

ok, I am still doing something wrong... I know, that now I moved to the wider topic (blitting to a texture) but I hope you don't mind to finish it.

I rewrote the problem into the following simple example. It is all inside the onSurfaceChanged() method. I have 2 squares, the left one with the original texture and the right one, where I would expect a BLUE texture, or copy of the right-square texture. But no, I have still the dull black empty texture, so what am I missing? And what is more, during the fb.display() it anounces a warning: "<core_glCopyTexSubImage2D:318>: GL_INVALID_OPERATION"

Thanks again for your help.


public void onSurfaceChanged(GL10 gl, int w, int h) {
if(master != null){return;}
master = HelloWorld.this;

if (fb != null) {
fb.dispose();
}

fb = new FrameBuffer(gl, w, h);
world = new World();
world.setAmbientLight(150, 150, 150);
sun = new Light(world);
sun.setIntensity(100, 100, 100);
SimpleVector sv = new SimpleVector(0, -50, -80);
sun.setPosition(sv);
try {
tx1 = new Texture(HelloWorld.getApp().getAssets().open("Texture.png"), true);
TextureManager.getInstance().addTexture("tx1", tx1);
} catch (IOException e) {
e.printStackTrace();
}
tx2 = new Texture(256,256);
TextureManager.getInstance().addTexture("tx2", tx2);
int tx1ID = TextureManager.getInstance().getTextureID("tx1");
int tx2ID = TextureManager.getInstance().getTextureID("tx2");

int destX = convertX(fb, 0);
int destY = convertY(fb, tx2.getHeight() - 0);
int destWidth = convertX(fb, 256);
int destHeight = -convertY(fb, 256);

fb.setRenderTarget(tx2);
fb.sync();
fb.clear(RGBColor.BLUE);
fb.blit(tx1, 0, 0, destX, destY, 512, 512, destWidth, destHeight, 255, false);
fb.display();
fb.removeRenderTarget();

camera = world.getCamera();
camera.setPosition(0, 0, -50);
camera.lookAt(SimpleVector.ORIGIN);

try {
obj1 = new Object3D(2);
obj1.addTriangle(new SimpleVector(-1f,-1f,0), 0, 0, new SimpleVector(-1f,1f,0), 0, 1f, new SimpleVector(1f,1f,0), 1f, 1f, tx1ID);
obj1.addTriangle(new SimpleVector(-1f,-1f,0), 0, 0, new SimpleVector(1f,1f,0), 1f, 1f, new SimpleVector(1f,-1f,0), 1f, 0, tx1ID);
obj1.scale(10f);
world.addObject(obj1);

obj1.translate(-15f, 0f, 0f);

obj2 = new Object3D(2);
obj2.addTriangle(new SimpleVector(-1f,-1f,0), 0, 0, new SimpleVector(-1f,1f,0), 0, 1f, new SimpleVector(1f,1f,0), 1f, 1f, tx2ID);
obj2.addTriangle(new SimpleVector(-1f,-1f,0), 0, 0, new SimpleVector(1f,1f,0), 1f, 1f, new SimpleVector(1f,-1f,0), 1f, 0, tx2ID);
obj2.scale(10f);
world.addObject(obj2);

obj2.translate(15f, 0f, 0f);
} catch (Exception e) {
e.printStackTrace();
}
MemoryHelper.compact();
}