diff --git a/core/src/ve/ucv/ciens/icaro/ardemo/EviDemo.java b/core/src/ve/ucv/ciens/icaro/ardemo/EviDemo.java index 1238a86..6cf59e5 100644 --- a/core/src/ve/ucv/ciens/icaro/ardemo/EviDemo.java +++ b/core/src/ve/ucv/ciens/icaro/ardemo/EviDemo.java @@ -5,34 +5,49 @@ import ve.ucv.ciens.icaro.ardemo.ImageProcessor.MarkerData; import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.assets.AssetManager; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.g3d.Model; +import com.badlogic.gdx.graphics.g3d.ModelBatch; public class EviDemo extends ApplicationAdapter { - private static final String TAG = "NXTAR_ANDROID_MAIN"; + private static final String TAG = "EVI DEMO - CORE"; private static final String CLASS_NAME = EviDemo.class.getSimpleName(); - private ImageProcessor cvProc; - private Texture tex; - private Pixmap frame; - private SpriteBatch batch; - private MarkerData data; - private CalibrationData calib; + private static final int W = 640; + private static final int H = 360; + private static final float NEAR = 0.01f; + private static final float FAR = 10.0f; + private static final int CODE = 213; + + private ImageProcessor cvProc; + private Texture tex; + private Pixmap frame; + private SpriteBatch batch; + private ModelBatch mBatch; + private MarkerData data; + private CalibrationData calib; + private AssetManager manager; + private boolean doneLoading; + private CustomPerspectiveCamera camera; + private Monkey monkey; private float[][] calibrationSamples; private int lastSampleTaken; public EviDemo(ImageProcessor proc) { super(); - tex = null; - cvProc = proc; - frame = null; - - lastSampleTaken = 0; - + tex = null; + cvProc = proc; + frame = null; + doneLoading = false; + lastSampleTaken = 0; calibrationSamples = new float[ProjectConstants.CALIBRATION_SAMPLES][]; + monkey = new Monkey(); + for(int i = 0; i < calibrationSamples.length; i++){ calibrationSamples[i] = new float[ProjectConstants.CALIBRATION_PATTERN_POINTS * 2]; } @@ -40,63 +55,118 @@ public class EviDemo extends ApplicationAdapter { @Override public void create () { - batch = new SpriteBatch(); + batch = new SpriteBatch(); + mBatch = new ModelBatch(); + + manager = new AssetManager(); + manager.load("monkey.g3db", Model.class); + + camera = new CustomPerspectiveCamera(67, W, H); + camera.near = NEAR; + camera.far = FAR; + camera.translate(0.0f, 0.0f, 0.0f); + camera.lookAt(0.0f, 0.0f, -1.0f); + camera.update(); + } + + @Override + public void dispose() { + if(tex != null) tex.dispose(); + manager.dispose(); + batch.dispose(); + mBatch.dispose(); } @Override public void render () { + float focalPointX, focalPointY, cameraCenterX, cameraCenterY; + Gdx.gl.glClearColor(1, 0, 0, 1); - Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT); - if(cvProc.isCameraCalibrated()) { - data = cvProc.findMarkersInFrame(); - if(data != null) { - frame = new Pixmap(data.outFrame, 0, data.outFrame.length); - tex = new Texture(frame); + if(doneLoading) { - batch.begin(); - batch.draw(tex, 0, 0); - batch.end(); + if(cvProc.isCameraCalibrated()) { + data = cvProc.findMarkersInFrame(); - frame.dispose(); - tex.dispose(); - } - } else { - calib = cvProc.findCalibrationPattern(); + if(data != null) { - if(calib != null){ - - if(!cvProc.isCameraCalibrated() && calib.calibrationPoints != null){ - Gdx.app.log(TAG, CLASS_NAME + ".render(): Sample taken."); - - // Save the calibration points to the samples array. - for(int i = 0; i < calib.calibrationPoints.length; i += 2){ - Gdx.app.log(TAG, CLASS_NAME + ".render(): Value " + Integer.toString(i) + " = (" + Float.toString(calib.calibrationPoints[i]) + ", " + Float.toString(calib.calibrationPoints[i + 1]) + ")"); - calibrationSamples[lastSampleTaken][i] = calib.calibrationPoints[i]; - calibrationSamples[lastSampleTaken][i + 1] = calib.calibrationPoints[i + 1]; + for(int i = 0; i < ProjectConstants.MAXIMUM_NUMBER_OF_MARKERS; i++) { + if(data.markerCodes[i] == CODE) { + monkey.position.set(data.translationVectors[i]); + monkey.rotation.set(data.rotationMatrices[i]); + monkey.applyWorldTransform(); + monkey.setVisible(true); + } } - // Move to the next sample. - lastSampleTaken++; + focalPointX = cvProc.getFocalPointX(); + focalPointY = cvProc.getFocalPointY(); + cameraCenterX = cvProc.getCameraCenterX(); + cameraCenterY = cvProc.getCameraCenterY(); + camera.setCustomARProjectionMatrix(focalPointX, focalPointY, cameraCenterX, cameraCenterY, NEAR, FAR, W, H); + camera.update(camera.projection); - // If enough samples has been taken then calibrate the camera. - if(lastSampleTaken == ProjectConstants.CALIBRATION_SAMPLES){ - Gdx.app.log(TAG, CLASS_NAME + "render(): Last sample taken."); + frame = new Pixmap(data.outFrame, 0, data.outFrame.length); + tex = new Texture(frame); - cvProc.calibrateCamera(calibrationSamples); + batch.begin(); { + batch.draw(tex, 0, 0); + } batch.end(); + + if(monkey.isVisible()) { + mBatch.begin(camera); { + mBatch.render(monkey.instance); + } mBatch.end(); + monkey.setVisible(false); } + + frame.dispose(); + tex.dispose(); } - frame = new Pixmap(calib.outFrame, 0, calib.outFrame.length); - tex = new Texture(frame); + } else { + calib = cvProc.findCalibrationPattern(); - batch.begin(); - batch.draw(tex, 0, 0); - batch.end(); + if(calib != null){ - frame.dispose(); - tex.dispose(); + if(!cvProc.isCameraCalibrated() && calib.calibrationPoints != null){ + Gdx.app.log(TAG, CLASS_NAME + ".render(): Sample taken."); + + // Save the calibration points to the samples array. + for(int i = 0; i < calib.calibrationPoints.length; i += 2){ + Gdx.app.log(TAG, CLASS_NAME + ".render(): Value " + Integer.toString(i) + " = (" + Float.toString(calib.calibrationPoints[i]) + ", " + Float.toString(calib.calibrationPoints[i + 1]) + ")"); + calibrationSamples[lastSampleTaken][i] = calib.calibrationPoints[i]; + calibrationSamples[lastSampleTaken][i + 1] = calib.calibrationPoints[i + 1]; + } + + // Move to the next sample. + lastSampleTaken++; + + // If enough samples has been taken then calibrate the camera. + if(lastSampleTaken == ProjectConstants.CALIBRATION_SAMPLES){ + Gdx.app.log(TAG, CLASS_NAME + "render(): Last sample taken."); + + cvProc.calibrateCamera(calibrationSamples); + } + } + + frame = new Pixmap(calib.outFrame, 0, calib.outFrame.length); + tex = new Texture(frame); + + batch.begin(); + batch.draw(tex, 0, 0); + batch.end(); + + frame.dispose(); + tex.dispose(); + } } + + } else { + doneLoading = manager.update(); + if(doneLoading) + monkey.setModel(manager.get("monkey.g3db", Model.class)); } } } diff --git a/core/src/ve/ucv/ciens/icaro/ardemo/Monkey.java b/core/src/ve/ucv/ciens/icaro/ardemo/Monkey.java new file mode 100644 index 0000000..3235669 --- /dev/null +++ b/core/src/ve/ucv/ciens/icaro/ardemo/Monkey.java @@ -0,0 +1,75 @@ +package ve.ucv.ciens.icaro.ardemo; + +import com.badlogic.gdx.graphics.g3d.Model; +import com.badlogic.gdx.graphics.g3d.ModelInstance; +import com.badlogic.gdx.math.Matrix3; +import com.badlogic.gdx.math.Matrix4; +import com.badlogic.gdx.math.Vector3; + +class Monkey { + private Model model; + public ModelInstance instance; + public Vector3 position; + public Matrix3 rotation; + public Vector3 scaling; + private boolean visible; + + public Monkey() { + this.position = new Vector3(); + this.rotation = new Matrix3(); + this.scaling = new Vector3(1.0f, 1.0f, 1.0f); + this.visible = false; + this.instance = null; + this.model = null; + } + + public boolean isVisible() { + return visible; + } + + public void setVisible(boolean visible) { + this.visible = visible; + } + + public Model getModel() { + return model; + } + + public void setModel(Model model) { + this.model = model; + this.instance = new ModelInstance(this.model); + } + + public void applyWorldTransform(){ + Matrix4 translationMatrix = new Matrix4().setToTranslation(0.0f, 0.0f, 0.0f);; + Matrix4 rotationMatrix = new Matrix4().idt();; + Matrix4 scalingMatrix = new Matrix4().setToScaling(0.0f, 0.0f, 0.0f);; + + translationMatrix.setToTranslation(this.position); + + rotationMatrix.val[Matrix4.M00] = this.rotation.val[0]; + rotationMatrix.val[Matrix4.M10] = this.rotation.val[1]; + rotationMatrix.val[Matrix4.M20] = this.rotation.val[2]; + rotationMatrix.val[Matrix4.M30] = 0; + + rotationMatrix.val[Matrix4.M01] = this.rotation.val[3]; + rotationMatrix.val[Matrix4.M11] = this.rotation.val[4]; + rotationMatrix.val[Matrix4.M21] = this.rotation.val[5]; + rotationMatrix.val[Matrix4.M31] = 0; + + rotationMatrix.val[Matrix4.M02] = this.rotation.val[6]; + rotationMatrix.val[Matrix4.M12] = this.rotation.val[7]; + rotationMatrix.val[Matrix4.M22] = this.rotation.val[8]; + rotationMatrix.val[Matrix4.M32] = 0; + + rotationMatrix.val[Matrix4.M03] = 0; + rotationMatrix.val[Matrix4.M13] = 0; + rotationMatrix.val[Matrix4.M23] = 0; + rotationMatrix.val[Matrix4.M33] = 1; + + scalingMatrix.setToScaling(this.scaling); + + instance.transform.idt().mul(translationMatrix).mul(rotationMatrix).mul(scalingMatrix); + instance.calculateTransforms(); + } +} diff --git a/desktop/src/ve/ucv/ciens/icaro/ardemo/desktop/CVProcessor.java b/desktop/src/ve/ucv/ciens/icaro/ardemo/desktop/CVProcessor.java index 4d71103..2764c7d 100644 --- a/desktop/src/ve/ucv/ciens/icaro/ardemo/desktop/CVProcessor.java +++ b/desktop/src/ve/ucv/ciens/icaro/ardemo/desktop/CVProcessor.java @@ -28,9 +28,28 @@ public class CVProcessor implements ImageProcessor { private boolean cameraCalibrated; - private native void getMarkerCodesAndLocations(long inMat, long outMat, int[] codes, long camMat, long distMat, float[] translations, float[] rotations); - private native boolean findCalibrationPattern(long inMat, long outMat, float[] points); - private native double calibrateCameraParameters(long camMat, long distMat, long frame, float[] calibrationPoints); + private native void getMarkerCodesAndLocations( + long inMat, + long outMat, + int[] codes, + long camMat, + long distMat, + float[] translations, + float[] rotations + ); + + private native boolean findCalibrationPattern( + long inMat, + long outMat, + float[] points + ); + + private native double calibrateCameraParameters( + long camMat, + long distMat, + long frame, + float[] calibrationPoints + ); static{ try{ diff --git a/desktop/src/ve/ucv/ciens/icaro/ardemo/desktop/DesktopLauncher.java b/desktop/src/ve/ucv/ciens/icaro/ardemo/desktop/DesktopLauncher.java index c0875ec..4928779 100644 --- a/desktop/src/ve/ucv/ciens/icaro/ardemo/desktop/DesktopLauncher.java +++ b/desktop/src/ve/ucv/ciens/icaro/ardemo/desktop/DesktopLauncher.java @@ -8,7 +8,7 @@ import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; public class DesktopLauncher{ private static final String TAG = "NXTAR_ANDROID_MAIN"; private static final String CLASS_NAME = DesktopLauncher.class.getSimpleName(); - + public static void main (String[] arg) { if(!CVProcessor.isOcvOn()){ throw new RuntimeException(TAG + " : " + CLASS_NAME + ": OpenCV failed to load.");