3
« on: October 02, 2015, 06:48:14 pm »
hi all !
So I've bee trying to integrate Vuforia with jPCT for the last couple of days and I have seen a couple of tutorials and answers(including the official wikipedia).
However I am not able to do it on my own.
Integration is on Vuforia User Defined Target sample which basically displays a teapot on the screen when the user takes a picture of something and remembering the picture later so it can track it.
When I follow the tutorial of integrating these two(vuforia+jpct) I can't make the primitive(basic cube) to render onto the screen.
Here is my current code
/*===============================================================================
Copyright (c) 2012-2014 Qualcomm Connected Experiences, Inc. All Rights Reserved.
Vuforia is a trademark of QUALCOMM Incorporated, registered in the United States
and other countries. Trademarks of QUALCOMM Incorporated are used with permission.
===============================================================================*/
package com.marked.vifo.UserDefinedTargets;
import android.annotation.SuppressLint;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.Log;
import com.marked.vifo.VuforiaApplication.ApplicationSession;
import com.marked.vifo.VuforiaApplication.utils.CubeShaders;
import com.marked.vifo.VuforiaApplication.utils.MeshObject;
import com.marked.vifo.VuforiaApplication.utils.SampleUtils;
import com.marked.vifo.VuforiaApplication.utils.Texture;
import com.qualcomm.vuforia.Matrix44F;
import com.qualcomm.vuforia.Renderer;
import com.qualcomm.vuforia.State;
import com.qualcomm.vuforia.Tool;
import com.qualcomm.vuforia.TrackableResult;
import com.qualcomm.vuforia.VIDEO_BACKGROUND_REFLECTION;
import com.qualcomm.vuforia.Vuforia;
import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Light;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.World;
import com.threed.jpct.util.MemoryHelper;
import java.util.Vector;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
// The renderer class for the ImageTargetsBuilder sample.
public class ImageTargetRenderer implements GLSurfaceView.Renderer {
// Constants:
static final float kObjectScale = 3.f;
private static final String LOGTAG = "ImageTargetRenderer";
public boolean mIsActive = false;
Object3D box;
private ApplicationSession vuforiaAppSession;
private Vector<Texture> mTextures;
private int shaderProgramID;
private int vertexHandle;
private int normalHandle;
private int textureCoordHandle;
private int mvpMatrixHandle;
private int texSampler2DHandle;
private MeshObject mTeapot;
// Reference to main activity
private ImageTargets mActivity;
private FrameBuffer fb;
private World world;
private float[] modelViewMat;
private Light sun;
private Object3D cube;
private Camera cam;
private float fov;
private float fovy;
private float[] modelViewMatrix;
private SimpleVector mCameraPosition;
private SimpleVector mCameraDirection;
private SimpleVector mCameraUp;
public ImageTargetRenderer(ImageTargets activity, ApplicationSession session, MeshObject meshObject) {
this.mActivity = activity;
this.vuforiaAppSession = session;
this.mTeapot = meshObject;
this.world = new World();
world.setAmbientLight(25, 25, 25);
this.sun = new Light(world);
sun.setIntensity(250, 250, 250);
// Create a texture out of the icon...:-)
// TextureManager txtMgr = TextureManager.getInstance();
// if (!txtMgr.containsTexture("texture")) {
// com.threed.jpct.Texture texture = new com.threed.jpct.Texture(64, 64, RGBColor.BLUE);
// txtMgr.addTexture("texture", texture);
// }
box = Primitives.getCube(10.0f);
box.setEnvmapped(Object3D.ENVMAP_ENABLED);
box.translate(5, 0, 12);
// box.setTexture("texture");
// box.calcTextureWrapSpherical();
box.strip();
box.build();
world.addObject(box);
cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
cam.lookAt(box.getTransformedCenter());
SimpleVector sv = new SimpleVector();
sv.set(box.getTransformedCenter());
sv.y -= 100;
sv.z -= 100;
sun.setPosition(sv);
MemoryHelper.compact();
}
// Called when the surface is created or recreated.
@SuppressLint("LongLogTag")
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Log.d(LOGTAG, "GLRenderer.onSurfaceCreated");
// Call function to initialize rendering:
initRendering();
// Call Vuforia function to (re)initialize rendering after first use
// or after OpenGL ES context was lost (e.g. after onPause/onResume):
vuforiaAppSession.onSurfaceCreated();
}
// Called when the surface changed size.
@SuppressLint("LongLogTag")
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// Call function to update rendering when render surface
// parameters have changed:
mActivity.updateRendering();
// Call Vuforia function to handle render surface size changes:
vuforiaAppSession.onSurfaceChanged(width, height);
if (fb != null) {
fb.dispose();
}
fb = new com.threed.jpct.FrameBuffer(width, height);
}
// Called to draw the current frame.
@Override
public void onDrawFrame(GL10 gl) {
if (!mIsActive) {
return;
}
// Call our function to render content
renderFrame();
updateCamera();
drawWorld();
}
public void drawWorld() {
try {
// if (fb==null)
world.renderScene(fb);
world.draw(fb);
fb.display();
} catch (Exception e) {
e.printStackTrace();
}
}
private void renderFrame() {
// Clear color and depth buffer
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// Get the state from Vuforia and mark the beginning of a rendering
// section
State state = Renderer.getInstance().begin();
// Explicitly render the Video Background
Renderer.getInstance().drawVideoBackground();
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_CULL_FACE);
if (Renderer.getInstance().getVideoBackgroundConfig().getReflection() ==
VIDEO_BACKGROUND_REFLECTION.VIDEO_BACKGROUND_REFLECTION_ON)
GLES20.glFrontFace(GLES20.GL_CW); // Front camera
else
GLES20.glFrontFace(GLES20.GL_CCW); // Back camera
// Render the RefFree UI elements depending on the current state
mActivity.refFreeFrame.render();
// Did we find any trackables this frame?
for (int tIdx = 0; tIdx < state.getNumTrackableResults(); tIdx++) {
// Get the trackable:
TrackableResult trackableResult = state.getTrackableResult(tIdx);
Matrix44F modelViewMatrix_Vuforia = Tool.convertPose2GLMatrix(trackableResult.getPose());
modelViewMatrix = modelViewMatrix_Vuforia.getData();
float[] modelViewProjection = new float[16];
Matrix.translateM(modelViewMatrix, 0, 0.0f, 0.0f, kObjectScale);
Matrix.scaleM(modelViewMatrix, 0, kObjectScale, kObjectScale, kObjectScale);
Matrix.multiplyMM(modelViewProjection, 0, vuforiaAppSession.getProjectionMatrix().getData(), 0, modelViewMatrix,
0);
GLES20.glUseProgram(shaderProgramID);
mCameraPosition = new SimpleVector(modelViewMatrix[12], modelViewMatrix[13], modelViewMatrix[14]);
mCameraDirection = new SimpleVector(modelViewMatrix[8], modelViewMatrix[9], modelViewMatrix[10]);
//LANDSCAPE: 0, 1, 2
//PORTRAIT: 4, 5, 6
mCameraUp = new SimpleVector(-modelViewMatrix[0], -modelViewMatrix[1], -modelViewMatrix[2]);
com.threed.jpct.Matrix mat = new com.threed.jpct.Matrix();
mat.setDump(modelViewProjection);
//If I comment this out, picking works flawless:
cam.setBack(mat);
GLES20.glVertexAttribPointer(vertexHandle, 3, GLES20.GL_FLOAT, false, 0, mTeapot.getVertices());
GLES20.glVertexAttribPointer(normalHandle, 3, GLES20.GL_FLOAT, false, 0, mTeapot.getNormals());
GLES20.glVertexAttribPointer(textureCoordHandle, 2, GLES20.GL_FLOAT, false, 0, mTeapot.getTexCoords());
GLES20.glEnableVertexAttribArray(vertexHandle);
GLES20.glEnableVertexAttribArray(normalHandle);
GLES20.glEnableVertexAttribArray(textureCoordHandle);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures.get(0).mTextureID[0]);
GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, modelViewProjection, 0);
GLES20.glUniform1i(texSampler2DHandle, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, mTeapot.getNumObjectIndex(), GLES20.GL_UNSIGNED_SHORT,
mTeapot.getIndices());
GLES20.glDisableVertexAttribArray(vertexHandle);
GLES20.glDisableVertexAttribArray(normalHandle);
GLES20.glDisableVertexAttribArray(textureCoordHandle);
drawWorld();
SampleUtils.checkGLError("UserDefinedTargets renderFrame");
}
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
Renderer.getInstance().end();
}
public void updateCamera() {
if (modelViewMatrix != null) {
com.threed.jpct.Matrix m = new com.threed.jpct.Matrix();
m.setDump(modelViewMatrix);
cam.setBack(m);
// cam.setOrientation(mCameraDirection, mCameraUp);
// cam.setPosition(mCameraPosition);
}
}
@SuppressLint("LongLogTag")
private void initRendering() {
Log.d(LOGTAG, "initRendering");
// Define clear color
GLES20.glClearColor(0.0f, 0.0f, 0.0f, Vuforia.requiresAlpha() ? 0.0f : 1.0f);
// Now generate the OpenGL texture objects and add settings
for (Texture t : mTextures) {
GLES20.glGenTextures(1, t.mTextureID, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, t.mTextureID[0]);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, t.mWidth, t.mHeight, 0, GLES20.GL_RGBA,
GLES20.GL_UNSIGNED_BYTE, t.mData);
}
shaderProgramID = SampleUtils.createProgramFromShaderSrc(CubeShaders.CUBE_MESH_VERTEX_SHADER,
CubeShaders.CUBE_MESH_FRAGMENT_SHADER);
vertexHandle = GLES20.glGetAttribLocation(shaderProgramID, "vertexPosition");
normalHandle = GLES20.glGetAttribLocation(shaderProgramID, "vertexNormal");
textureCoordHandle = GLES20.glGetAttribLocation(shaderProgramID, "vertexTexCoord");
mvpMatrixHandle = GLES20.glGetUniformLocation(shaderProgramID, "modelViewProjectionMatrix");
texSampler2DHandle = GLES20.glGetUniformLocation(shaderProgramID, "texSampler2D");
}
public void setTextures(Vector<Texture> textures) {
mTextures = textures;
}
}
When I run the app I see the cube on the screen for 0.5 sec, then disappears and I'm getting an infinite loop of thrown exception
10-02 19:40:11.257 21975-22043/com.marked.vifo I/jPCT-AE: Additional visibility list (43) created with size: 512
10-02 19:40:11.257 21975-22043/com.marked.vifo W/System.err: java.lang.NullPointerException: Attempt to read from field 'int com.threed.jpct.Texture.glTarget' on a null object reference
10-02 19:40:11.257 21975-22043/com.marked.vifo W/System.err: at com.threed.jpct.CompiledInstance.render(CompiledInstance.java:692)
10-02 19:40:11.257 21975-22043/com.marked.vifo W/System.err: at com.threed.jpct.GLRenderer.drawVertexArray(GLRenderer.java:2308)
10-02 19:40:11.257 21975-22043/com.marked.vifo W/System.err: at com.threed.jpct.World.draw(World.java:1417)
10-02 19:40:11.257 21975-22043/com.marked.vifo W/System.err: at com.threed.jpct.World.draw(World.java:1100)
10-02 19:40:11.257 21975-22043/com.marked.vifo W/System.err: at com.marked.vifo.UserDefinedTargets.ImageTargetRenderer.drawWorld(ImageTargetRenderer.java:157)
10-02 19:40:11.257 21975-22043/com.marked.vifo W/System.err: at com.marked.vifo.UserDefinedTargets.ImageTargetRenderer.onDrawFrame(ImageTargetRenderer.java:150)
10-02 19:40:11.257 21975-22043/com.marked.vifo W/System.err: at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1522)
10-02 19:40:11.258 21975-22043/com.marked.vifo W/System.err: at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1239)
The exception is thrown from this code
public void drawWorld() {
try {
world.renderScene(fb);
world.draw(fb);
fb.display();
} catch (Exception e) {
e.printStackTrace();
}
}
And I get an infinite number of thrown exception because I call this method in renderFrame() and for each frame throws an exception.
To me it seems that somewhere fb == null but I don't know how to fix this because I'm quite new to graphics/opengl/vuforia/jpct .
Also I don't know if I need/should link somehow the framebuffer(fb) to Vuforia's image/buffer/something
I would love some help if anyone knows what's going on.
Thank you very much!