Android Colorovo CityTab Vision 3D Glass free 3d tablet

Started by zelo, April 22, 2014, 11:09:33 AM

Previous topic - Next topic

zelo

Hi all,

I would like to develop a simple 3d application to Colorovo CityTab Vision 3D tablet. It is a glass free 3d tablet.

This device use vertical interlaced 3d display and It must be created "manually".

I create a sample app:

public class Stencil {
/*
* this code generates the interlaced pattern to the stencil buffer for
* stereoscopic masking
*/

private float vertices[];

private FloatBuffer vertexBuffer;

public Stencil() {


}

void interlace_stencil(GL10 gl, int gliWindowWidth, int gliWindowHeight) {

vertex(gliWindowWidth, gliWindowHeight);
// seting screen-corresponding geometry
gl.glViewport(0, 0, gliWindowWidth, gliWindowHeight);
gl.glMatrixMode(gl.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glMatrixMode(gl.GL_PROJECTION);
gl.glLoadIdentity();
gl.glMatrixMode(gl.GL_MODELVIEW);
gl.glLoadIdentity();
//
// // clearing and configuring stencil drawing
gl.glEnable(gl.GL_STENCIL_TEST);
gl.glClearStencil(0);
gl.glClear(gl.GL_STENCIL_BUFFER_BIT);
gl.glStencilOp(gl.GL_REPLACE, gl.GL_REPLACE, gl.GL_REPLACE); //
// colorbuffer
// // is
// // copied to stencil
gl.glDisable(gl.GL_DEPTH_TEST);
gl.glStencilFunc(gl.GL_ALWAYS, 1, 1); // to avoid interaction with
// stencil
// content
// drawing stencil pattern
gl.glColor4f(1, 1, 1, 1);
// gl.glColor4f(1, 1, 1, 0); // alfa is 0 not to interfere with alpha
// tests
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

// Set the face rotation
gl.glFrontFace(GL10.GL_CW);

// Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);

// Draw the vertices
gl.glDrawArrays(GL10.GL_LINES, 0, vertices.length / 3);

// Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glStencilOp(gl.GL_KEEP, gl.GL_KEEP, gl.GL_KEEP); // disabling
// changes
// buffer
gl.glFlush();
}

private void vertex(int gliWindowWidth, int gliWindowHeight) {
float gliY = -1;

ArrayList<Float> ver = new ArrayList<Float>();
for (int i = 0; i < gliWindowWidth; i += 2) {
double d = (1f/Float.valueOf(gliWindowWidth))*2.0;

float f = ((float) (i*d))-1f;

ver.add(f);
ver.add(-1f);
ver.add(0f);

ver.add(f);
ver.add(1f);
ver.add(0f);

}
Float[] temp = ver.toArray(new Float[ver.size()]);

vertices = new float[temp.length];
for (int i = 0; i < temp.length; i++) {
Float float1 = temp[i];
vertices[i] = float1.floatValue();
}
// a float has 4 bytes so we allocate for each coordinate 4 bytes
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());

// allocates the memory from the byte buffer
vertexBuffer = byteBuffer.asFloatBuffer();

// fill the vertexBuffer with the vertices
vertexBuffer.put(vertices);

// set the cursor position to the beginning of the buffer
vertexBuffer.position(0);
}
}


@Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT
| GL10.GL_STENCIL_BUFFER_BIT);

stencil.interlace_stencil(gl, width, height);

gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 0.1f,
100.0f);
gl.glViewport(0, 0, width, height);

gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();


gl.glStencilFunc(gl.GL_NOTEQUAL, 1, 1); // draws if stencil <> 1
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); /* black */
gl.glClear(gl.GL_COLOR_BUFFER_BIT);

gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -10.0f);
gl.glRotatef(mCubeRotation, 1.0f, 1.0f, 1.0f);

setLeftEnv(gl);
gl.glEnable(GL10.GL_DEPTH_TEST);
mCube.draw(gl);

gl.glStencilFunc(gl.GL_EQUAL, 1, 1); // draws if stencil <> 0
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -10.0f);
gl.glRotatef(mCubeRotation, 1.0f, 1.0f, 1.0f);

setRightEnv(gl);
gl.glEnable(GL10.GL_DEPTH_TEST);
mCube.draw(gl);

gl.glLoadIdentity();

mCubeRotation -= 0.15f;
}

private void setLeftEnv(GL10 gl) {
GLU.gluLookAt(gl, 0 - (mEyeDistance), 0.0f, 0.0f, 0.0f, 0.0f, -100.0f,
0.0f, 1.0f, 0.0f);

}

private void setRightEnv(GL10 gl) {
GLU.gluLookAt(gl, 0 + (mEyeDistance), 0.0f, 0.0f, 0.0f, 0.0f, -100.0f,
0.0f, 1.0f, 0.0f);

}


It works well. But I don't know, how to implement this with JPCT-AE.
Can you help me?

Thank you in anticipation.

EgonOlsen

I'm not sure what you are after...do you want to mix jPCT's rendering with the stencil buffer settings or... ???

zelo

Hi,

I have been solved, but on post, maybe helps someone else. This code works well Colorovo and Gadmei glass free 3d tablets.


package com.threed.jpct.example;

import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;

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.opengl.GLU;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;

import com.threed.jpct.Camera;
import com.threed.jpct.Config;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Interact2D;
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.Primitives;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureInfo;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.BitmapHelper;
import com.threed.jpct.util.MemoryHelper;

/**
* A simple demo. This shows more how to use jPCT-AE than it shows how to write
* a proper application for Android. It includes basic activity management to
* handle pause and resume...
*
* @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(255, 0, 0);

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

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

private Light sun = null;
private Texture font = null;

private float move = 0;

private static final long serialVersionUID = 1L;

private Object3D cube = null;

private Camera cam = null;

protected void onCreate(Bundle savedInstanceState) {

Logger.log("onCreate");

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

super.onCreate(savedInstanceState);

mGLView = new GLSurfaceView(getApplication());
renderer = new MyRenderer();
mGLView.setEGLConfigChooser(8, 8, 8, 8, 16, 8);
mGLView.setRenderer(renderer);
setContentView(mGLView);

FileWriter localFileWriter;
try {
localFileWriter = new FileWriter("/sys/class/enable3d/enable-3d");

localFileWriter.write(49);
localFileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}

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

public boolean onKeyDown(int keyCode, KeyEvent msg) {
if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
move = 1f;
return true;
}

if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
move = -1f;
return true;
}

if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
cube.rotateY((float) Math.toRadians(-1));
return true;
}

if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
cube.rotateY((float) Math.toRadians(1));
return true;
}

return super.onKeyDown(keyCode, msg);
}

public boolean onKeyUp(int keyCode, KeyEvent msg) {
if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
move = 0;
return true;
}

if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
move = 0;
return true;
}

if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {

return true;
}

if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {

return true;
}

return super.onKeyUp(keyCode, msg);
}

protected boolean isFullscreenOpaque() {
return true;
}

class MyRenderer implements GLSurfaceView.Renderer {
private int fps = 0;
private int lfps = 0;

private long time = System.currentTimeMillis();
private boolean stop = false;
private int w;
private int h;

public MyRenderer() {

Config.maxPolysVisible = 500;
Config.farPlane = 1500;
Config.glTransparencyMul = 0.1f;
Config.glTransparencyOffset = 0.1f;
Config.useVBO = true;

Texture.defaultToMipmapping(false);
Texture.defaultTo4bpp(true);
}

public void stop() {
stop = true;
}

public void onSurfaceChanged(GL10 gl, int w, int h) {
this.w = w;
this.h = 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);

// Create a texture out of the icon...:-)
Texture texture = new Texture(BitmapHelper.rescale(
BitmapHelper.convert(getResources().getDrawable(
R.drawable.icon)), 64, 64));
TextureManager.getInstance().addTexture("texture", texture);

try {
Texture texture2 = new Texture(getResources().getAssets()
.open("alpha.png"), true);
TextureManager.getInstance().addTexture("texture2",
texture2);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

TextureInfo ti = new TextureInfo(TextureManager.getInstance()
.getTextureID("texture"));
ti.add(TextureManager.getInstance().getTextureID("texture2"),
TextureInfo.MODE_DECAL);

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

world.addObject(cube);

Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 150);
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;
}
}
}

private Object3D loadModel(InputStream filename, float scale) {
Loader.setVertexOptimization(false);

Object3D[] model = Loader.load3DS(filename, scale);
Object3D o3d = new Object3D(0);
Object3D temp = null;

for (int i = 0; i < model.length; i++) {
temp = model[i];
temp.setCenter(SimpleVector.ORIGIN);
temp.rotateX((float) (-.5 * Math.PI));
temp.rotateY((float) (-Math.PI));
temp.rotateMesh();
temp.setRotationMatrix(new Matrix());
o3d = Object3D.mergeObjects(o3d, temp);

}
o3d.build();
return o3d;
}

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

public void onDrawFrame(GL10 gl) {
try {

// selectAnyObjectAt((int) xpos, (int) ypos);

if (!stop) {
// move();

cam = world.getCamera();
cam.setPositionToCenter(cube);

cam.moveCamera(Camera.CAMERA_MOVEOUT, 100);

if (touchTurn != 0) {
cube.rotateY(touchTurn);
touchTurn = 0;
}

if (touchTurnUp != 0) {
cube.rotateX(touchTurnUp);
touchTurnUp = 0;
}

fb.clear(back);
SimpleVector position = cam.getPosition();

gl.glClear(GL10.GL_COLOR_BUFFER_BIT
| GL10.GL_DEPTH_BUFFER_BIT
| GL10.GL_STENCIL_BUFFER_BIT);
interlaceStencil(gl, w, h);

gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();

gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();

gl.glStencilFunc(gl.GL_NOTEQUAL, 1, 1); // draws if stencil
// <> 1
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); /* black */
gl.glClear(gl.GL_COLOR_BUFFER_BIT);

gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -10.0f);

gl.glEnable(GL10.GL_DEPTH_TEST);
cam.setPosition(new SimpleVector(position.x, position.y,
position.z));
world.renderScene(fb);
world.draw(fb);
gl.glStencilFunc(gl.GL_EQUAL, 1, 1); // draws if stencil <>
// 0
gl.glLoadIdentity();

gl.glEnable(GL10.GL_DEPTH_TEST);

cam.setPosition(new SimpleVector(position.x - 3,
position.y, position.z));
world.renderScene(fb);
world.draw(fb);
gl.glLoadIdentity();

blitNumber(lfps, 5, 5);

fb.display();

if (System.currentTimeMillis() - time >= 1000) {
Logger.log(fps + "fps");
lfps = fps;
fps = 0;
time = System.currentTimeMillis();
}
fps++;
} else {
if (fb != null) {
fb.dispose();
fb = null;
}
}
} catch (Exception e) {
e.printStackTrace();
Logger.log("Drawing thread terminated!", Logger.MESSAGE);
}
}

void interlaceStencil(GL10 gl, int gliWindowWidth, int gliWindowHeight) {
//
vertex(gliWindowWidth, gliWindowHeight);
// seting screen-corresponding geometry
gl.glViewport(0, 0, gliWindowWidth, gliWindowHeight);
gl.glMatrixMode(gl.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glMatrixMode(gl.GL_PROJECTION);
gl.glLoadIdentity();
gl.glMatrixMode(gl.GL_MODELVIEW);
gl.glLoadIdentity();
// clearing and configuring stencil drawing
gl.glEnable(gl.GL_STENCIL_TEST);
gl.glClearStencil(0);
gl.glClear(gl.GL_STENCIL_BUFFER_BIT);
gl.glStencilOp(gl.GL_REPLACE, gl.GL_REPLACE, gl.GL_REPLACE); //
// colorbuffer is copied to stencil
gl.glDisable(gl.GL_DEPTH_TEST);
gl.glStencilFunc(gl.GL_ALWAYS, 1, 1); // to avoid interaction
// with
// stencil
// content
// drawing stencil pattern
gl.glColor4f(1, 1, 1, 1);
// gl.glColor4f(1, 1, 1, 0); // alfa is 0 not to interfere with
// alpha
// tests
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

// Set the face rotation
// gl.glFrontFace(GL10.GL_CW);

// Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);

// Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_LINES, 0, vertices.length / 3);

// Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glStencilOp(gl.GL_KEEP, gl.GL_KEEP, gl.GL_KEEP); // disabling
// changes
// buffer
gl.glFlush();
}

private void vertex(int gliWindowWidth, int gliWindowHeight) {

ArrayList<Float> ver = new ArrayList<Float>();
for (int i = 0; i < gliWindowWidth; i += 2) {
double d = (1f / Float.valueOf(gliWindowWidth)) * 2.0;
float f = ((float) (i * d)) - 1f;

ver.add(f);
ver.add(-1f);
ver.add(0f);

ver.add(f);
ver.add(1f);
ver.add(0f);

}
Float[] temp = ver.toArray(new Float[ver.size()]);

vertices = new float[temp.length];
for (int i = 0; i < temp.length; i++) {
Float float1 = temp[i];
vertices[i] = float1.floatValue();
}
// a float has 4 bytes so we allocate for each coordinate 4 bytes
ByteBuffer byteBuffer = ByteBuffer
.allocateDirect(vertices.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());

// allocates the memory from the byte buffer
vertexBuffer = byteBuffer.asFloatBuffer();

// fill the vertexBuffer with the vertices
vertexBuffer.put(vertices);

// set the cursor position to the beginning of the buffer
vertexBuffer.position(0);
}

private float vertices[];

private FloatBuffer vertexBuffer;

private void blitNumber(int number, int x, int y) {
if (font != null) {
String sNum = Integer.toString(number);

for (int i = 0; i < sNum.length(); i++) {
char cNum = sNum.charAt(i);
int iNum = cNum - 48;
fb.blit(font, iNum * 5, 0, x, y, 5, 9,
FrameBuffer.TRANSPARENT_BLITTING);
x += 5;
}
}
}
}
}