Added correct 3D model rendering.
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
75
core/src/ve/ucv/ciens/icaro/ardemo/Monkey.java
Normal file
75
core/src/ve/ucv/ciens/icaro/ardemo/Monkey.java
Normal file
@@ -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();
|
||||
}
|
||||
}
|
@@ -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{
|
||||
|
@@ -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.");
|
||||
|
Reference in New Issue
Block a user