diff --git a/README.md b/README.md
index 55df3117..e5989b8c 100644
--- a/README.md
+++ b/README.md
@@ -13,16 +13,12 @@ The application does not use any third party library.
* Collada format (DAE): https://en.wikipedia.org/wiki/COLLADA
-News (02/02/2022)
+News (25/07/2022)
=================
-* /¡\ repo moved to the3deers organization + MIT License 2020
-* New version released 3.2.0
-* Repository Explorer improved
-* Smoothing implementation fixed
-* Fixed memory leak
-
-
+* New version released 3.3.0
+* New orthographic, isometric and free camera views
+* Interactive object orientation
Demo
====
@@ -75,7 +71,7 @@ Features
- OpenGL ES 2.0 API
- Formats: OBJ (wavefront), STL (STereoLithography) & DAE (Collada-BETA)
- calculation of normals
- - transformations: scaling, rotation, translation
+ - transformations: scaling, rotation, translation, orientation
- colors
- textures
- lighting
@@ -86,6 +82,7 @@ Features
- skybox
- object pick
- camera support
+ - perspective, orthographic and isometric views
- tap to select object
- drag to move camera
- rotate with 2 fingers to rotate camera
@@ -196,6 +193,13 @@ ChangeLog
(f) fixed, (i) improved, (n) new feature
+- 3.3.0 (23/06/2022)
+ - (n) interactive object orientation
+ - (n) isometric, orthographic and free camera view
+ - (n) New gui axis + gui info
+ - (f) fixed FPS counter
+ - (i) some user options are being saved (camera settings)
+
- 3.2.0 (02/02/2022)
- (i) repository explorer improved - multiple index files
- (f) smoothing fixed
diff --git a/app/build/outputs/apk/release/app-release.apk b/app/build/outputs/apk/release/app-release.apk
index 53c49a82..b20ce1d8 100644
Binary files a/app/build/outputs/apk/release/app-release.apk and b/app/build/outputs/apk/release/app-release.apk differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e0ebbfdf..be2ac421 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,8 +2,8 @@
+ android:versionCode="32"
+ android:versionName="3.3.0">
@@ -49,6 +49,11 @@
+
+
diff --git a/app/src/main/java/org/andresoviedo/app/model3D/demo/DemoLoaderTask.java b/app/src/main/java/org/andresoviedo/app/model3D/demo/DemoLoaderTask.java
index 0e43e8b4..5056aa86 100644
--- a/app/src/main/java/org/andresoviedo/app/model3D/demo/DemoLoaderTask.java
+++ b/app/src/main/java/org/andresoviedo/app/model3D/demo/DemoLoaderTask.java
@@ -153,9 +153,9 @@ public void onLoad(Object3DData obj53) {
Object3DData obj53 = new WavefrontLoader(GLES20.GL_TRIANGLE_FAN, new LoadListenerAdapter(){
@Override
public void onLoad(Object3DData obj53) {
- obj53.setLocation(new float[] { 2f, 0f, 0f });
obj53.setColor(new float[] { 1.0f, 1.0f, 1f, 1.0f });
Rescaler.rescale(obj53, 2f);
+ obj53.setLocation(new float[] { 2f, 0f, 0f });
DemoLoaderTask.this.onLoad(obj53);
}
}).load(new URI("android://org.andresoviedo.dddmodel2/assets/models/ToyPlane.obj")).get(0);
@@ -171,10 +171,10 @@ public void onLoad(Object3DData obj53) {
Object3DData obj53 = new ColladaLoader().load(new URI("android://org.andresoviedo.dddmodel2/assets/models/cowboy.dae"), new LoadListenerAdapter(){
@Override
public void onLoad(Object3DData obj53) {
- obj53.setLocation(new float[] { 0f, -1f, 1f});
obj53.setColor(new float[] { 1.0f, 1.0f, 1f, 1.0f });
- obj53.setRotation(new float[]{-90,0,0});
Rescaler.rescale(obj53, 2f);
+ obj53.setLocation(new float[] { 0f, 0f, 2f});
+ obj53.setCentered(true);
DemoLoaderTask.this.onLoad(obj53);
}
}).get(0);
diff --git a/app/src/main/java/org/andresoviedo/app/model3D/demo/GlyphsDemoActivity.java b/app/src/main/java/org/andresoviedo/app/model3D/demo/GlyphsDemoActivity.java
new file mode 100644
index 00000000..bd2e0238
--- /dev/null
+++ b/app/src/main/java/org/andresoviedo/app/model3D/demo/GlyphsDemoActivity.java
@@ -0,0 +1,91 @@
+package org.andresoviedo.app.model3D.demo;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.Toast;
+
+import org.andresoviedo.android_3d_model_engine.gui.Text;
+import org.andresoviedo.android_3d_model_engine.gui.Widget;
+import org.andresoviedo.android_3d_model_engine.model.Camera;
+import org.andresoviedo.android_3d_model_engine.model.Constants;
+import org.andresoviedo.android_3d_model_engine.model.Projection;
+import org.andresoviedo.android_3d_model_engine.services.SceneLoader;
+import org.andresoviedo.android_3d_model_engine.view.ModelSurfaceView;
+import org.andresoviedo.android_3d_model_engine.view.ViewEvent;
+import org.andresoviedo.util.event.EventListener;
+
+import java.util.EventObject;
+
+/**
+ * This activity represents the container for our 3D viewer.
+ *
+ * @author andresoviedo
+ */
+public class GlyphsDemoActivity extends Activity implements EventListener {
+
+ private ModelSurfaceView glView;
+ private SceneLoader scene;
+ private Camera camera;
+
+ private Text abcd;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ Log.i("GlyphsDemoActivity", "onCreate: Loading activity... "+savedInstanceState);
+ super.onCreate(savedInstanceState);
+
+ try {
+ // Create our 3D scenario
+ Log.i("GlyphsDemoActivity", "Creating Scene...");
+ scene = new SceneLoader(this);
+ scene.addListener(this);
+
+ // Camera setup
+ final Camera camera = new Camera(Constants.UNIT);
+ camera.setProjection(Projection.PERSPECTIVE);
+ camera.setChanged(true);
+ scene.setCamera(camera);
+
+
+ Log.i("GlyphsDemoActivity", "Loading GLSurfaceView...");
+ glView = new ModelSurfaceView(this, Constants.COLOR_GRAY, this.scene);
+ glView.addListener(this);
+ glView.setProjection(Projection.PERSPECTIVE);
+ setContentView(glView);
+
+
+ abcd = Text.allocate(10, 6);
+ abcd.setPadding(Widget.PADDING_01);
+ abcd.update("abcdefghij\n" +
+ "klmnopqrst\n" +
+ "uvwxyz\n" +
+ "ABCDEFGHIJ\n" +
+ "KLMNOPQRST\n" +
+ "UVWXYZ");
+ abcd.setVisible(true);
+ scene.addObject(abcd);
+
+
+ } catch (Exception e) {
+ Log.e("GlyphsDemoActivity", e.getMessage(), e);
+ Toast.makeText(this, "Error loading OpenGL view:\n" + e.getMessage(), Toast.LENGTH_LONG).show();
+ }
+
+ }
+
+ @Override
+ public boolean onEvent(EventObject event) {
+ if (event instanceof ViewEvent) {
+ ViewEvent viewEvent = (ViewEvent) event;
+ if (viewEvent.getCode() == ViewEvent.Code.SURFACE_CHANGED) {
+ abcd.setScale(Constants.UNIT/5,Constants.UNIT/5,Constants.UNIT/5);
+ float ratio = (float) viewEvent.getWidth() / viewEvent.getHeight();
+ float x = -ratio * Constants.UNIT + abcd.getCurrentDimensions().getWidth() / 2 - abcd.getCurrentDimensions().getCenter()[0] + Constants.UNIT * 0.05f;
+ float y = 1 * Constants.UNIT - abcd.getCurrentDimensions().getHeight() / 2 - abcd.getCurrentDimensions().getCenter()[1] - Constants.UNIT * 0.05f;
+ abcd.setLocation( new float[]{x,y,0});
+ }
+ }
+ return false;
+ }
+}
diff --git a/app/src/main/java/org/andresoviedo/app/model3D/view/MenuActivity.java b/app/src/main/java/org/andresoviedo/app/model3D/view/MenuActivity.java
index 8c98115e..0ce305d9 100644
--- a/app/src/main/java/org/andresoviedo/app/model3D/view/MenuActivity.java
+++ b/app/src/main/java/org/andresoviedo/app/model3D/view/MenuActivity.java
@@ -18,6 +18,7 @@
import org.andresoviedo.android_3d_model_engine.services.collada.ColladaLoader;
import org.andresoviedo.android_3d_model_engine.services.wavefront.WavefrontLoader;
+import org.andresoviedo.app.model3D.demo.GlyphsDemoActivity;
import org.andresoviedo.dddmodel2.R;
import org.andresoviedo.util.android.AndroidUtils;
import org.andresoviedo.util.android.AssetUtils;
@@ -51,7 +52,7 @@ public class MenuActivity extends ListActivity {
private enum Action {
- LOAD_MODEL, CARGAR_MODELO, GITHUB, SETTINGS, HELP, AYUDA, ABOUT, ACERCA, EXIT, SALIR, UNKNOWN, DEMO
+ LOAD_MODEL, CARGAR_MODELO, GITHUB, SETTINGS, HELP, AYUDA, ABOUT, ACERCA, EXIT, SALIR, UNKNOWN, DEMO, DEMOS
}
/**
@@ -78,7 +79,9 @@ protected void onCreate(Bundle savedInstanceState) {
public void onListItemClick(ListView l, View v, int position, long id) {
String selectedItem = (String) getListView().getItemAtPosition(position);
// Toast.makeText(getApplicationContext(), "Click ListItem '" + selectedItem + "'", Toast.LENGTH_LONG).show();
- String selectedAction = selectedItem.replace(' ', '_').toUpperCase(Locale.getDefault());
+ String selectedAction = selectedItem.replace(' ', '_')
+ .replaceAll("\\.", "")
+ .toUpperCase(Locale.getDefault());
Action action = Action.UNKNOWN;
try {
action = Action.valueOf(selectedAction);
@@ -87,6 +90,21 @@ public void onListItemClick(ListView l, View v, int position, long id) {
}
try {
switch (action) {
+ case DEMOS:
+ ContentUtils.showListDialog(this, "Demos List", new String[]{"Random Objects", "GUI"}, (DialogInterface dialog, int which) -> {
+ if (which == 0) {
+ Intent demoIntent = new Intent(MenuActivity.this.getApplicationContext(), ModelActivity.class);
+ demoIntent.putExtra("immersiveMode", "false");
+ demoIntent.putExtra("backgroundColor", "0 0 0 1");
+ MenuActivity.this.startActivity(demoIntent);
+ } else if (which == 1) {
+ Intent demoIntent = new Intent(MenuActivity.this.getApplicationContext(), GlyphsDemoActivity.class);
+ MenuActivity.this.startActivity(demoIntent);
+ } else {
+ // TODO:
+ }
+ });
+ break;
case DEMO:
Intent demoIntent = new Intent(MenuActivity.this.getApplicationContext(), ModelActivity.class);
demoIntent.putExtra("immersiveMode", "false");
diff --git a/app/src/main/java/org/andresoviedo/app/model3D/view/ModelActivity.java b/app/src/main/java/org/andresoviedo/app/model3D/view/ModelActivity.java
index 2d513982..c01cb139 100644
--- a/app/src/main/java/org/andresoviedo/app/model3D/view/ModelActivity.java
+++ b/app/src/main/java/org/andresoviedo/app/model3D/view/ModelActivity.java
@@ -3,7 +3,12 @@
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ActivityNotFoundException;
+import android.content.Context;
import android.content.Intent;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -11,16 +16,25 @@
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.OrientationEventListener;
import android.view.View;
import android.widget.Toast;
+import androidx.annotation.RequiresApi;
+
import org.andresoviedo.android_3d_model_engine.camera.CameraController;
import org.andresoviedo.android_3d_model_engine.collision.CollisionController;
+import org.andresoviedo.android_3d_model_engine.collision.CollisionEvent;
import org.andresoviedo.android_3d_model_engine.controller.TouchController;
+import org.andresoviedo.android_3d_model_engine.controller.TouchEvent;
+import org.andresoviedo.android_3d_model_engine.event.SelectedObjectEvent;
+import org.andresoviedo.android_3d_model_engine.model.Projection;
import org.andresoviedo.android_3d_model_engine.services.LoaderTask;
import org.andresoviedo.android_3d_model_engine.services.SceneLoader;
-import org.andresoviedo.android_3d_model_engine.view.ModelRenderer;
+import org.andresoviedo.android_3d_model_engine.view.FPSEvent;
import org.andresoviedo.android_3d_model_engine.view.ModelSurfaceView;
+import org.andresoviedo.android_3d_model_engine.view.ViewEvent;
import org.andresoviedo.app.model3D.demo.DemoLoaderTask;
import org.andresoviedo.dddmodel2.R;
import org.andresoviedo.util.android.ContentUtils;
@@ -57,7 +71,7 @@ public class ModelActivity extends Activity implements EventListener {
*/
private float[] backgroundColor = new float[]{0.0f, 0.0f, 0.0f, 1.0f};
- private ModelSurfaceView gLView;
+ private ModelSurfaceView glView;
private TouchController touchController;
private SceneLoader scene;
private ModelViewerGUI gui;
@@ -67,9 +81,12 @@ public class ModelActivity extends Activity implements EventListener {
private Handler handler;
private CameraController cameraController;
+ private SensorManager sensorManager;
+ private Sensor sensor;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
- Log.i("ModelActivity", "Loading activity...");
+ Log.i("ModelActivity", "onCreate: Loading activity... "+savedInstanceState);
super.onCreate(savedInstanceState);
// Try to get input parameters
@@ -100,7 +117,8 @@ protected void onCreate(Bundle savedInstanceState) {
// Create our 3D scenario
Log.i("ModelActivity", "Loading Scene...");
- scene = new SceneLoader(this, paramUri, paramType, gLView);
+ scene = new SceneLoader(this, paramUri, paramType);
+ scene.addListener(this);
if (paramUri == null) {
final LoaderTask task = new DemoLoaderTask(this, null, scene);
task.execute();
@@ -115,10 +133,10 @@ protected void onCreate(Bundle savedInstanceState) {
try {
Log.i("ModelActivity", "Loading GLSurfaceView...");
- gLView = new ModelSurfaceView(this, backgroundColor, this.scene);
- gLView.addListener(this);
- setContentView(gLView);
- scene.setView(gLView);
+ glView = new ModelSurfaceView(this, backgroundColor, this.scene);
+ glView.addListener(this);
+ setContentView(glView);
+// scene.setView(glView);
} catch (Exception e) {
Log.e("ModelActivity", e.getMessage(), e);
Toast.makeText(this, "Error loading OpenGL view:\n" + e.getMessage(), Toast.LENGTH_LONG).show();
@@ -128,6 +146,7 @@ protected void onCreate(Bundle savedInstanceState) {
Log.i("ModelActivity", "Loading TouchController...");
touchController = new TouchController(this);
touchController.addListener(this);
+ //touchController.addListener(glView);
} catch (Exception e) {
Log.e("ModelActivity", e.getMessage(), e);
Toast.makeText(this, "Error loading TouchController:\n" + e.getMessage(), Toast.LENGTH_LONG).show();
@@ -135,10 +154,10 @@ protected void onCreate(Bundle savedInstanceState) {
try {
Log.i("ModelActivity", "Loading CollisionController...");
- collisionController = new CollisionController(gLView, scene);
- collisionController.addListener(scene);
- touchController.addListener(collisionController);
- touchController.addListener(scene);
+ collisionController = new CollisionController(glView, scene);
+ collisionController.addListener(this);
+ //touchController.addListener(collisionController);
+ //touchController.addListener(scene);
} catch (Exception e) {
Log.e("ModelActivity", e.getMessage(), e);
Toast.makeText(this, "Error loading CollisionController\n" + e.getMessage(), Toast.LENGTH_LONG).show();
@@ -147,8 +166,8 @@ protected void onCreate(Bundle savedInstanceState) {
try {
Log.i("ModelActivity", "Loading CameraController...");
cameraController = new CameraController(scene.getCamera());
- gLView.getModelRenderer().addListener(cameraController);
- touchController.addListener(cameraController);
+ //glView.getModelRenderer().addListener(cameraController);
+ //touchController.addListener(cameraController);
} catch (Exception e) {
Log.e("ModelActivity", e.getMessage(), e);
Toast.makeText(this, "Error loading CameraController" + e.getMessage(), Toast.LENGTH_LONG).show();
@@ -157,9 +176,9 @@ protected void onCreate(Bundle savedInstanceState) {
try {
// TODO: finish UI implementation
Log.i("ModelActivity", "Loading GUI...");
- gui = new ModelViewerGUI(gLView, scene);
+ gui = new ModelViewerGUI(glView, scene);
touchController.addListener(gui);
- gLView.addListener(gui);
+ glView.addListener(gui);
scene.addGUIObject(gui);
} catch (Exception e) {
Log.e("ModelActivity", e.getMessage(), e);
@@ -171,12 +190,84 @@ protected void onCreate(Bundle savedInstanceState) {
setupOnSystemVisibilityChangeListener();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ setupOrientationListener();
+ }
+
// load model
scene.init();
Log.i("ModelActivity", "Finished loading");
}
+ @RequiresApi(api = Build.VERSION_CODES.KITKAT)
+ private void setupOrientationListener() {
+ try {
+ //setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
+ //sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR);
+ sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);
+ if (sensor != null) {
+ sensorManager.registerListener(new SensorEventListener() {
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ /*Log.v("ModelActivity","sensor: "+ Arrays.toString(event.values));
+ Quaternion orientation = new Quaternion(event.values);
+ orientation.normalize();
+ //scene.getSelectedObject().setOrientation(orientation);
+ glView.setOrientation(orientation);*/
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+
+ }
+ }, sensor,
+ SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
+ }
+ OrientationEventListener mOrientationListener = new OrientationEventListener(
+ getApplicationContext()) {
+ @Override
+ public void onOrientationChanged(int orientation) {
+ //scene.onOrientationChanged(orientation);
+ }
+ };
+
+ if (mOrientationListener.canDetectOrientation()) {
+ mOrientationListener.enable();
+ }
+ } catch (Exception e) {
+ Log.e("ModelActivity","There is an issue setting up sensors",e);
+ }
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ outState.putFloatArray("camera.pos",scene.getCamera().getPos());
+ outState.putFloatArray("camera.view",scene.getCamera().getView());
+ outState.putFloatArray("camera.up",scene.getCamera().getUp());
+ outState.putString("renderer.projection",glView.getProjection().name());
+ outState.putInt("renderer.skybox",glView.getSkyBoxId());
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle state) {
+ if(state.containsKey("renderer.projection")) {
+ glView.setProjection(Projection.valueOf(state.getString("renderer.projection")));
+ }
+ if(state.containsKey("camera.pos") && state.containsKey("camera.view") && state.containsKey("camera.up")){
+ Log.d("ModelActivity","onRestoreInstanceState: Restoring camera settings...");
+ scene.getCamera().set(
+ state.getFloatArray("camera.pos"),
+ state.getFloatArray("camera.view"),
+ state.getFloatArray("camera.up"));
+ }
+ if(state.containsKey("renderer.skybox")){
+ glView.setSkyBox(state.getInt("renderer.skybox"));
+ }
+ }
+
+
/**
* Set up the {@link android.app.ActionBar}, if the API is available.
*/
@@ -220,6 +311,9 @@ public void onWindowFocusChanged(boolean hasFocus) {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
+ case R.id.model_toggle_projection:
+ glView.toggleProjection();
+ break;
case R.id.model_toggle_wireframe:
scene.toggleWireframe();
break;
@@ -227,7 +321,7 @@ public boolean onOptionsItemSelected(MenuItem item) {
scene.toggleBoundingBox();
break;
case R.id.model_toggle_skybox:
- gLView.toggleSkyBox();
+ glView.toggleSkyBox();
break;
case R.id.model_toggle_textures:
scene.toggleTextures();
@@ -358,17 +452,50 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
@Override
public boolean onEvent(EventObject event) {
- if (event instanceof ModelRenderer.ViewEvent) {
- ModelRenderer.ViewEvent viewEvent = (ModelRenderer.ViewEvent) event;
- if (viewEvent.getCode() == ModelRenderer.ViewEvent.Code.SURFACE_CHANGED) {
- touchController.setSize(viewEvent.getWidth(), viewEvent.getHeight());
- gLView.setTouchController(touchController);
+ if (event instanceof FPSEvent){
+ gui.onEvent(event);
+ }
+ else if (event instanceof SelectedObjectEvent){
+ gui.onEvent(event);
+ }
+ else if (event.getSource() instanceof MotionEvent){
+ // event coming from glview
+ touchController.onMotionEvent((MotionEvent) event.getSource());
+ }
+ else if (event instanceof CollisionEvent){
+ scene.onEvent(event);
+ }
+ else if (event instanceof TouchEvent){
+ TouchEvent touchEvent = (TouchEvent) event;
+ if (touchEvent.getAction() == TouchEvent.Action.CLICK){
+ if (!collisionController.onEvent(event)){
+ scene.onEvent(event);
+ }
+ } else {
+ if (scene.getSelectedObject() != null) {
+ scene.onEvent(event);
+ } else {
+ cameraController.onEvent(event);
+ scene.onEvent(event);
+ if (((TouchEvent) event).getAction() == TouchEvent.Action.PINCH) {
+ glView.onEvent(event);
+ }
+ }
+ }
+ }
+ else if (event instanceof ViewEvent) {
+ ViewEvent viewEvent = (ViewEvent) event;
+ if (viewEvent.getCode() == ViewEvent.Code.SURFACE_CHANGED) {
+ cameraController.onEvent(viewEvent);
+ touchController.onEvent(viewEvent);
// process event in GUI
if (gui != null) {
gui.setSize(viewEvent.getWidth(), viewEvent.getHeight());
gui.setVisible(true);
}
+ } else if (viewEvent.getCode() == ViewEvent.Code.PROJECTION_CHANGED){
+ cameraController.onEvent(event);
}
}
return true;
diff --git a/app/src/main/java/org/andresoviedo/app/model3D/view/ModelViewerGUI.java b/app/src/main/java/org/andresoviedo/app/model3D/view/ModelViewerGUI.java
index e0560fe6..9eef7935 100644
--- a/app/src/main/java/org/andresoviedo/app/model3D/view/ModelViewerGUI.java
+++ b/app/src/main/java/org/andresoviedo/app/model3D/view/ModelViewerGUI.java
@@ -1,7 +1,10 @@
package org.andresoviedo.app.model3D.view;
+import android.opengl.Matrix;
import android.util.Log;
+import org.andresoviedo.android_3d_model_engine.drawer.RendererFactory;
+import org.andresoviedo.android_3d_model_engine.event.SelectedObjectEvent;
import org.andresoviedo.android_3d_model_engine.gui.CheckList;
import org.andresoviedo.android_3d_model_engine.gui.GUI;
import org.andresoviedo.android_3d_model_engine.gui.Glyph;
@@ -9,13 +12,18 @@
import org.andresoviedo.android_3d_model_engine.gui.Rotator;
import org.andresoviedo.android_3d_model_engine.gui.Text;
import org.andresoviedo.android_3d_model_engine.gui.Widget;
+import org.andresoviedo.android_3d_model_engine.model.Camera;
+import org.andresoviedo.android_3d_model_engine.model.Object3DData;
+import org.andresoviedo.android_3d_model_engine.objects.Axis;
import org.andresoviedo.android_3d_model_engine.services.SceneLoader;
-import org.andresoviedo.android_3d_model_engine.view.ModelRenderer;
+import org.andresoviedo.android_3d_model_engine.view.FPSEvent;
import org.andresoviedo.android_3d_model_engine.view.ModelSurfaceView;
+import org.andresoviedo.util.math.Quaternion;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.List;
+import java.util.Locale;
final class ModelViewerGUI extends GUI {
@@ -23,6 +31,8 @@ final class ModelViewerGUI extends GUI {
private final SceneLoader scene;
private Text fps;
+ private Text info;
+ private Widget axis;
private Widget icon;
private Glyph icon2 = Glyph.build(Glyph.CHECKBOX_ON);
private Menu3D menu;
@@ -33,6 +43,7 @@ final class ModelViewerGUI extends GUI {
this.glView = glView;
this.scene = scene;
setColor(new float[]{1, 1, 1, 0f});
+ setPadding(Widget.PADDING_01);
}
/**
@@ -47,6 +58,8 @@ public void setSize(int width, int height) {
super.setSize(width, height);
try {
initFPS();
+ initInfo();
+ initAxis();
//initMenu();
//initMenu2();
}catch (Exception e){
@@ -57,6 +70,7 @@ public void setSize(int width, int height) {
private void initFPS() {
// frame-per-second
+ if (fps != null) return;
fps = Text.allocate(7, 1);
fps.setId("fps");
fps.setVisible(true);
@@ -65,10 +79,51 @@ private void initFPS() {
addWidget(fps);
- fps.setPosition(GUI.POSITION_TOP_LEFT);
+ fps.setPosition(Widget.POSITION_TOP_LEFT);
//addBackground(fps).setColor(new float[]{0.25f, 0.25f, 0.25f, 0.25f});
}
+ private void initInfo() {
+ // model info
+ if (info != null) return;
+ info = Text.allocate(15, 3, Text.PADDING_01);
+ info.setId("info");
+ info.setVisible(true);
+ info.setParent(this);
+ //info.setRelativeScale(new float[]{0.85f,0.85f,0.85f});
+ info.setRelativeScale(new float[]{0.25f,0.25f,0.25f});
+
+ addWidget(info);
+
+ info.setPosition(Widget.POSITION_BOTTOM);
+ //addBackground(fps).setColor(new float[]{0.25f, 0.25f, 0.25f, 0.25f});
+ }
+
+ private void initAxis(){
+ if (axis != null) return;
+ axis = new Widget(Axis.build()){
+ final float[] matrix = new float[16];
+ final Quaternion orientation = new Quaternion(matrix);
+ @Override
+ public void render(RendererFactory rendererFactory, Camera camera, float[] lightPosInWorldSpace, float[] colorMask) {
+ if (camera.hasChanged()){
+ Matrix.setLookAtM(matrix,0,camera.getxPos(), camera.getyPos(), camera.getzPos(),
+ 0f,0f,0f, camera.getxUp(), camera.getyUp(), camera.getzUp());
+ setOrientation(orientation);
+ }
+ super.render(rendererFactory, camera, lightPosInWorldSpace, colorMask);
+ }
+ };
+ axis.setId("gui_axis");
+ axis.setVisible(true);
+ axis.setParent(this);
+ axis.setRelativeScale(new float[]{0.1f,0.1f,0.1f});
+
+ addWidget(axis);
+
+ axis.setPosition(Widget.POSITION_TOP_RIGHT);
+ }
+
private void initMenu2() {
// checklist
CheckList.Builder menuB = new CheckList.Builder();
@@ -97,7 +152,7 @@ private void initMenu() {
icon.setParent(this);
icon.setRelativeScale(new float[]{0.1f,0.1f,0.1f});
super.addWidget(icon);
- icon.setPosition(GUI.POSITION_TOP_LEFT);
+ icon.setPosition(Widget.POSITION_TOP_LEFT);
icon.setVisible(true);
//super.addBackground(icon).setColor(new float[]{0.25f, 0.25f, 0.25f, 0.25f});
@@ -122,7 +177,7 @@ private void initMenu() {
//icon.addListener(menu);
super.addWidget(menu);
- menu.setPosition(GUI.POSITION_MIDDLE);
+ menu.setPosition(Widget.POSITION_MIDDLE);
super.addBackground(menu).setColor(new float[]{0.5f, 0f, 0f, 0.25f});
// menu rotator
@@ -138,12 +193,36 @@ private void initMenu() {
@Override
public boolean onEvent(EventObject event) {
super.onEvent(event);
- if (event instanceof ModelRenderer.FPSEvent){
+ if (event instanceof FPSEvent){
if (fps.isVisible()) {
- ModelRenderer.FPSEvent fpsEvent = (ModelRenderer.FPSEvent) event;
+ FPSEvent fpsEvent = (FPSEvent) event;
fps.update(fpsEvent.getFps() + " fps");
}
}
+ else if (event instanceof SelectedObjectEvent){
+ if (this.info.isVisible()){
+ final Object3DData selected = ((SelectedObjectEvent) event).getSelected();
+ final StringBuilder info = new StringBuilder();
+ if (selected != null) {
+ if (selected.getId().indexOf('/') == -1){
+ info.append(selected.getId());
+ } else {
+ info.append(selected.getId().substring(selected.getId().lastIndexOf('/')+1));
+ }
+ info.append('\n');
+ info.append("size: ");
+ info.append(String.format(Locale.getDefault(), "%.2f",selected.getDimensions().getLargest()));
+ info.append('\n');
+ info.append("scale: ");
+ info.append(String.format(Locale.getDefault(), "%.2f",selected.getScaleX()));
+ //final DecimalFormat df = new DecimalFormat("0.##");
+ //info.append(df.format(selected.getScaleX()));
+ info.append("x");
+ }
+ Log.v("ModelViewerGUI","Selected object info: "+info);
+ this.info.update(info.toString().toLowerCase());
+ }
+ }
else if (event instanceof Menu3D.ItemSelected) {
switch (((Menu3D.ItemSelected) event).getSelected()) {
case 0:
diff --git a/app/src/main/res/menu/model.xml b/app/src/main/res/menu/model.xml
index ba08e061..6f9bc179 100644
--- a/app/src/main/res/menu/model.xml
+++ b/app/src/main/res/menu/model.xml
@@ -1,78 +1,85 @@