package edu.dhbw.andobjviewer;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.Date;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Debug;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Toast;
import edu.dhbw.andar.ARToolkit;
import edu.dhbw.andar.AndARActivity;
import edu.dhbw.andar.exceptions.AndARException;
import edu.dhbw.andarmodelviewer.R;
import edu.dhbw.andobjviewer.graphics.LightingRenderer;
import edu.dhbw.andobjviewer.graphics.Model3D;
import edu.dhbw.andobjviewer.models.Model;
import edu.dhbw.andobjviewer.parser.ObjParser;
import edu.dhbw.andobjviewer.parser.ParseException;
import edu.dhbw.andobjviewer.parser.Util;
import edu.dhbw.andobjviewer.util.AssetsFileUtil;
import edu.dhbw.andobjviewer.util.BaseFileUtil;
import edu.dhbw.andobjviewer.util.SDCardFileUtil;
/**
* Example of an application that makes use of the AndAR toolkit.
* @author Tobi
*
*/
public class AugmentedModelViewerActivity extends AndARActivity implements SurfaceHolder.Callback {
/**
* View a file in the assets folder
*/
public static final int TYPE_INTERNAL = 0;
/**
* View a file on the sd card.
*/
public static final int TYPE_EXTERNAL = 1;
public static final boolean DEBUG = false;
/* Menu Options: */
private final int MENU_SCALE = 0;
private final int MENU_ROTATE = 1;
private final int MENU_TRANSLATE = 2;
private final int MENU_SCREENSHOT = 3;
private int mode = MENU_SCALE;
private Model model;
private Model3D model3d;
private ProgressDialog waitDialog;
private Resources res;
ARToolkit artoolkit;
public AugmentedModelViewerActivity() {
super(false);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setNonARRenderer(new LightingRenderer());//or might be omited
res=getResources();
artoolkit = getArtoolkit();
getSurfaceView().setOnTouchListener(new TouchEventHandler());
getSurfaceView().getHolder().addCallback(this);
}
/**
* Inform the user about exceptions that occurred in background threads.
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
System.out.println("");
}
/* create the menu
* @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, MENU_TRANSLATE, 0, res.getText(R.string.translate))
.setIcon(R.drawable.translate);
menu.add(0, MENU_ROTATE, 0, res.getText(R.string.rotate))
.setIcon(R.drawable.rotate);
menu.add(0, MENU_SCALE, 0, res.getText(R.string.scale))
.setIcon(R.drawable.scale);
menu.add(0, MENU_SCREENSHOT, 0, res.getText(R.string.take_screenshot))
.setIcon(R.drawable.screenshoticon);
return true;
}
/* Handles item selections */
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_SCALE:
mode = MENU_SCALE;
return true;
case MENU_ROTATE:
mode = MENU_ROTATE;
return true;
case MENU_TRANSLATE:
mode = MENU_TRANSLATE;
return true;
case MENU_SCREENSHOT:
new TakeAsyncScreenshot().execute();
return true;
}
return false;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
super.surfaceCreated(holder);
//load the model
//this is done here, to assure the surface was already created, so that the preview can be started
//after loading the model
if(model == null) {
waitDialog = ProgressDialog.show(this, "",
getResources().getText(R.string.loading), true);
waitDialog.show();
new ModelLoader().execute();
}
}
/**
* Handles touch events.
* @author Tobias Domhan
*
*/
class TouchEventHandler implements OnTouchListener {
private float lastX=0;
private float lastY=0;
/* handles the touch events.
* the object will either be scaled, translated or rotated, dependen on the
* current user selected mode.
* @see android.view.View.OnTouchListener#onTouch(android.view.View, android.view.MotionEvent)
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
if(model!=null) {
switch(event.getAction()) {
//Action started
default:
case MotionEvent.ACTION_DOWN:
lastX = event.getX();
lastY = event.getY();
break;
//Action ongoing
case MotionEvent.ACTION_MOVE:
float dX = lastX - event.getX();
float dY = lastY - event.getY();
lastX = event.getX();
lastY = event.getY();
if(model != null) {
switch(mode) {
case MENU_SCALE:
model.setScale(dY/10.0f);
break;
case MENU_ROTATE:
model.setXrot(-1*dX);//dY-> Rotation um die X-Achse
model.setYrot(-1*dY);//dX-> Rotation um die Y-Achse
break;
case MENU_TRANSLATE:
model.setXpos(dY/10f);
model.setYpos(dX/10f);
break;
}
}
break;
//Action ended
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
lastX = event.getX();
lastY = event.getY();
break;
}
}
return true;
}
}
private class ModelLoader extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
Intent intent = getIntent();
Bundle data = intent.getExtras();
int type = data.getInt("type");
String modelFileName = data.getString("name");
BaseFileUtil fileUtil= null;
File modelFile=null;
switch(type) {
case TYPE_EXTERNAL:
fileUtil = new SDCardFileUtil();
modelFile = new File(URI.create(modelFileName));
modelFileName = modelFile.getName();
fileUtil.setBaseFolder(modelFile.getParentFile().getAbsolutePath());
break;
case TYPE_INTERNAL:
fileUtil = new AssetsFileUtil(getResources().getAssets());
fileUtil.setBaseFolder("models/");
break;
}
//read the model file:
if(modelFileName.endsWith(".obj")) {
ObjParser parser = new ObjParser(fileUtil);
try {
if(Config.DEBUG)
Debug.startMethodTracing("AndObjViewer");
if(type == TYPE_EXTERNAL) {
//an external file might be trimmed
BufferedReader modelFileReader = new BufferedReader(new FileReader(modelFile));
String shebang = modelFileReader.readLine();
if(!shebang.equals("#trimmed")) {
//trim the file:
File trimmedFile = new File(modelFile.getAbsolutePath()+".tmp");
BufferedWriter trimmedFileWriter = new BufferedWriter(new FileWriter(trimmedFile));
Util.trim(modelFileReader, trimmedFileWriter);
if(modelFile.delete()) {
trimmedFile.renameTo(modelFile);
}
}
}
if(fileUtil != null) {
BufferedReader fileReader = fileUtil.getReaderFromName(modelFileName);
if(fileReader != null) {
model = parser.parse("Model", fileReader);
model3d = new Model3D(model);
}
}
if(Config.DEBUG)
Debug.stopMethodTracing();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
waitDialog.dismiss();
//register model
try {
if(model3d!=null)
artoolkit.registerARObject(model3d);
} catch (AndARException e) {
e.printStackTrace();
}
startPreview();
}
}
class TakeAsyncScreenshot extends AsyncTask<Void, Void, Void> {
private String errorMsg = null;
@Override
protected Void doInBackground(Void... params) {
Bitmap bm = takeScreenshot();
FileOutputStream fos;
try {
fos = new FileOutputStream("/sdcard/AndARScreenshot"+new Date().getTime()+".png");
bm.compress(CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
errorMsg = e.getMessage();
e.printStackTrace();
} catch (IOException e) {
errorMsg = e.getMessage();
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void result) {
if(errorMsg == null)
Toast.makeText(AugmentedModelViewerActivity.this, getResources().getText(R.string.screenshotsaved), Toast.LENGTH_SHORT ).show();
else
Toast.makeText(AugmentedModelViewerActivity.this, getResources().getText(R.string.screenshotfailed)+errorMsg, Toast.LENGTH_SHORT ).show();
};
}
}