mirror of
https://github.com/vanitasvitae/Spherical
synced 2024-11-22 12:22:08 +01:00
Begin work on several bugfixes
This commit is contained in:
parent
5b33d05f80
commit
7932d00cdc
9 changed files with 234 additions and 170 deletions
31
app/src/main/java/de/trac/spherical/BroadcastHelper.java
Normal file
31
app/src/main/java/de/trac/spherical/BroadcastHelper.java
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package de.trac.spherical;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
|
|
||||||
|
public class BroadcastHelper {
|
||||||
|
|
||||||
|
public enum BroadcastType {
|
||||||
|
PROGRESS_START,
|
||||||
|
PROGRESS_FINISHED
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String INTENT_ACTION = "de.spherical.internal";
|
||||||
|
private static final String INTENT_KEY_NAME = "broadcast_type";
|
||||||
|
public static final IntentFilter INTENT_FILTER = new IntentFilter(INTENT_ACTION); // TODO: useful?
|
||||||
|
|
||||||
|
static public void broadcast(Context context, BroadcastType type) {
|
||||||
|
Intent intent = new Intent(INTENT_ACTION);
|
||||||
|
intent.putExtra(INTENT_KEY_NAME, type.name());
|
||||||
|
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public BroadcastType getBroadcastType(Intent intent) {
|
||||||
|
if(!INTENT_ACTION.equals(intent.getAction()))
|
||||||
|
throw new IllegalArgumentException("Not a valid intent");
|
||||||
|
|
||||||
|
return (BroadcastType) intent.getSerializableExtra(INTENT_KEY_NAME);
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,10 +52,6 @@ public class FlatFragment extends ImageFragment {
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MainActivity getMainActivity() {
|
|
||||||
return (MainActivity) getActivity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateBitmap(Bitmap bitmap) {
|
public void updateBitmap(Bitmap bitmap) {
|
||||||
if (imageView == null) {
|
if (imageView == null) {
|
||||||
|
|
|
@ -3,11 +3,11 @@ package de.trac.spherical;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by vanitas on 19.09.17.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public abstract class ImageFragment extends Fragment {
|
public abstract class ImageFragment extends Fragment {
|
||||||
|
|
||||||
public abstract void updateBitmap(Bitmap bitmap);
|
public abstract void updateBitmap(Bitmap bitmap);
|
||||||
|
|
||||||
|
public MainActivity getMainActivity() {
|
||||||
|
return (MainActivity) getActivity();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package de.trac.spherical;
|
package de.trac.spherical;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
@ -12,12 +15,13 @@ import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.design.widget.FloatingActionButton;
|
import android.support.design.widget.FloatingActionButton;
|
||||||
import android.support.v4.app.ActivityCompat;
|
import android.support.v4.app.ActivityCompat;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
import android.support.v4.view.GestureDetectorCompat;
|
import android.support.v4.view.GestureDetectorCompat;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.GestureDetector;
|
import android.view.GestureDetector;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
|
@ -30,10 +34,14 @@ import android.widget.RelativeLayout;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import de.trac.spherical.parser.PhotoSphereMetadata;
|
import de.trac.spherical.parser.PhotoSphereMetadata;
|
||||||
import de.trac.spherical.parser.PhotoSphereParser;
|
import de.trac.spherical.parser.PhotoSphereParser;
|
||||||
import de.trac.spherical.rendering.PhotoSphereSurfaceView;
|
|
||||||
|
import static de.trac.spherical.BroadcastHelper.BroadcastType.PROGRESS_FINISHED;
|
||||||
|
import static de.trac.spherical.BroadcastHelper.BroadcastType.PROGRESS_START;
|
||||||
|
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
@ -42,34 +50,73 @@ public class MainActivity extends AppCompatActivity {
|
||||||
public static final String MIME_PHOTO_SPHERE = "application/vnd.google.panorama360+jpg";
|
public static final String MIME_PHOTO_SPHERE = "application/vnd.google.panorama360+jpg";
|
||||||
private static final int PERMISSION_REQUEST_READ_EXTERNAL_STORAGE = 387;
|
private static final int PERMISSION_REQUEST_READ_EXTERNAL_STORAGE = 387;
|
||||||
|
|
||||||
private FragmentManager fm;
|
// UI
|
||||||
|
private FloatingActionButton actionButton;
|
||||||
//UI
|
|
||||||
private FloatingActionButton fab;
|
|
||||||
private Toolbar toolbar;
|
private Toolbar toolbar;
|
||||||
private GestureDetectorCompat gestureDetector;
|
private GestureDetectorCompat gestureDetector;
|
||||||
|
|
||||||
private ProgressFragment progressFragment = new ProgressFragment();
|
// Cache
|
||||||
private FlatFragment flatFragment = new FlatFragment();
|
|
||||||
private SphereFragment sphereFragment = new SphereFragment();
|
|
||||||
private ImageFragment currentlyShownImageFragment;
|
|
||||||
|
|
||||||
//Cache
|
|
||||||
private Intent cachedIntent;
|
private Intent cachedIntent;
|
||||||
private Bitmap bitmap;
|
private Bitmap bitmap;
|
||||||
private PhotoSphereMetadata metadata;
|
private PhotoSphereMetadata metadata;
|
||||||
|
|
||||||
|
// Fragments
|
||||||
|
private enum FragmentType {
|
||||||
|
PROGRESS("progress"),
|
||||||
|
SPHERE("sphere"),
|
||||||
|
FLAT("flat");
|
||||||
|
|
||||||
|
/// Optional tag.
|
||||||
|
String tag;
|
||||||
|
|
||||||
|
FragmentType(String tag) {
|
||||||
|
this.tag = tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private FragmentManager fragmentManager;
|
||||||
|
private Map<FragmentType, Fragment> fragments;
|
||||||
|
|
||||||
|
// Broadcast handling.
|
||||||
|
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
switch (BroadcastHelper.getBroadcastType(intent)) {
|
||||||
|
case PROGRESS_START:
|
||||||
|
break;
|
||||||
|
case PROGRESS_FINISHED:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
setupUI();
|
setupUI();
|
||||||
|
|
||||||
fm = getSupportFragmentManager();
|
// Init fragments.
|
||||||
|
fragmentManager = getSupportFragmentManager();
|
||||||
|
|
||||||
|
fragments = new HashMap<>();
|
||||||
|
fragments.put(FragmentType.PROGRESS, new ProgressFragment());
|
||||||
|
fragments.put(FragmentType.SPHERE, new SphereFragment());
|
||||||
|
fragments.put(FragmentType.FLAT, new FlatFragment());
|
||||||
|
|
||||||
|
// Intent handling.
|
||||||
|
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, BroadcastHelper.INTENT_FILTER);
|
||||||
handleIntent(getIntent());
|
handleIntent(getIntent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the user interface.
|
* Initialize the user interface.
|
||||||
*/
|
*/
|
||||||
|
@ -81,12 +128,12 @@ public class MainActivity extends AppCompatActivity {
|
||||||
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) toolbar.getLayoutParams();
|
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) toolbar.getLayoutParams();
|
||||||
lp.topMargin += getStatusBarHeight();
|
lp.topMargin += getStatusBarHeight();
|
||||||
toolbar.bringToFront();
|
toolbar.bringToFront();
|
||||||
fab = (FloatingActionButton) findViewById(R.id.fab);
|
actionButton = (FloatingActionButton) findViewById(R.id.fab);
|
||||||
fab.setOnClickListener(new View.OnClickListener() {
|
actionButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
sphereFragment.toggleUseTouchInput();
|
sphereFragment.toggleUseTouchInput();
|
||||||
displayUI(false);
|
setUIVisibility(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -98,7 +145,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
gestureDetector = new GestureDetectorCompat(this, new GestureDetector.SimpleOnGestureListener() {
|
gestureDetector = new GestureDetectorCompat(this, new GestureDetector.SimpleOnGestureListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onSingleTapConfirmed(MotionEvent event) {
|
public boolean onSingleTapConfirmed(MotionEvent event) {
|
||||||
displayUI(!fab.isShown());
|
setUIVisibility(!actionButton.isShown());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +160,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
switch (intent.getAction()) {
|
switch (intent.getAction()) {
|
||||||
//Image was sent into the app
|
//Image was sent into the app
|
||||||
case Intent.ACTION_SEND:
|
case Intent.ACTION_SEND:
|
||||||
showProgressFragment();
|
showFragment(FragmentType.SPHERE);
|
||||||
checkPermissionAndHandleSentImage(intent);
|
checkPermissionAndHandleSentImage(intent);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -180,73 +227,35 @@ public class MainActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
// process image asynchronous.
|
// process image asynchronous.
|
||||||
new AsyncTask<Uri, Void, Void>() {
|
new LoadImageTask(this, getContentResolver(), imageUri).execute();
|
||||||
@Override
|
|
||||||
protected Void doInBackground(Uri... params) {
|
|
||||||
Uri uri = params[0];
|
|
||||||
|
|
||||||
try {
|
|
||||||
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
|
|
||||||
metadata = PhotoSphereParser.parse(getContentResolver().openInputStream(uri));
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Void result) {
|
|
||||||
switch (type) {
|
|
||||||
case MIME_PHOTO_SPHERE:
|
|
||||||
displayPhotoSphere();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (metadata != null) {
|
|
||||||
displayPhotoSphere();
|
|
||||||
} else {
|
|
||||||
displayFlatImage();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.execute(imageUri);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show/hide the FAB and toolbar.
|
* Show/hide the FAB and toolbar.
|
||||||
* @param display show/hide
|
* @param visible show/hide
|
||||||
*/
|
*/
|
||||||
private void displayUI(boolean display) {
|
private void setUIVisibility(boolean visible) {
|
||||||
if (display) {
|
if (visible) {
|
||||||
fab.show();
|
actionButton.show();
|
||||||
toolbar.setVisibility(View.VISIBLE);
|
toolbar.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
fab.setVisibility(View.INVISIBLE);
|
actionButton.setVisibility(View.INVISIBLE);
|
||||||
toolbar.setVisibility(View.GONE);
|
toolbar.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showProgressFragment() {
|
/**
|
||||||
fm.beginTransaction().replace(R.id.container_fragment, progressFragment, "prog").commit();
|
* Will show the fragment of the given type.
|
||||||
this.currentlyShownImageFragment = null;
|
* @param type fragment to be shown
|
||||||
}
|
*/
|
||||||
|
private void showFragment(FragmentType type) {
|
||||||
private void showFlatImageFragment() {
|
fragmentManager.beginTransaction().replace(R.id.container_fragment, fragments.get(type), type.tag).commit();
|
||||||
fm.beginTransaction().replace(R.id.container_fragment, flatFragment, "flat").commit();
|
|
||||||
this.currentlyShownImageFragment = flatFragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showSphereFragment() {
|
|
||||||
fm.beginTransaction().replace(R.id.container_fragment, sphereFragment, "sphere").commit();
|
|
||||||
this.currentlyShownImageFragment = sphereFragment;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
displayUI(true);
|
setUIVisibility(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -271,7 +280,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
* Display a photo sphere.
|
* Display a photo sphere.
|
||||||
*/
|
*/
|
||||||
public void displayPhotoSphere() {
|
public void displayPhotoSphere() {
|
||||||
showSphereFragment();
|
showFragment(FragmentType.SPHERE);
|
||||||
currentlyShownImageFragment.updateBitmap(bitmap);
|
currentlyShownImageFragment.updateBitmap(bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +288,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
* Display a flat bitmap.
|
* Display a flat bitmap.
|
||||||
*/
|
*/
|
||||||
public void displayFlatImage() {
|
public void displayFlatImage() {
|
||||||
showFlatImageFragment();
|
showFragment(FragmentType.FLAT);
|
||||||
currentlyShownImageFragment.updateBitmap(bitmap);
|
currentlyShownImageFragment.updateBitmap(bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +310,59 @@ public class MainActivity extends AppCompatActivity {
|
||||||
return gestureDetector;
|
return gestureDetector;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bitmap getBitmap() {
|
/**
|
||||||
return bitmap;
|
* Dedicated async tasks to load an image.
|
||||||
|
* Takes a progress reporter and informs it about the changes.
|
||||||
|
*/
|
||||||
|
private static class LoadImageTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
private ContentResolver contentResolver;
|
||||||
|
private Uri uri;
|
||||||
|
|
||||||
|
private Bitmap bitmap;
|
||||||
|
private PhotoSphereMetadata metadata;
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
LoadImageTask(Context context, ContentResolver contentResolver, Uri uri) {
|
||||||
|
this.context = context;
|
||||||
|
this.contentResolver = contentResolver;
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPreExecute() {
|
||||||
|
BroadcastHelper.broadcast(context, PROGRESS_START);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(uri));
|
||||||
|
metadata = PhotoSphereParser.parse(contentResolver.openInputStream(uri));
|
||||||
|
} catch (IOException | OutOfMemoryError e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
BroadcastHelper.broadcast(context, PROGRESS_FINISHED);
|
||||||
|
switch (type) {
|
||||||
|
case MIME_PHOTO_SPHERE:
|
||||||
|
showFragment(FragmentType.SPHERE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (metadata != null) {
|
||||||
|
displayPhotoSphere();
|
||||||
|
} else {
|
||||||
|
displayFlatImage();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,6 @@ import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by vanitas on 18.09.17.
|
|
||||||
*/
|
|
||||||
public class ProgressFragment extends Fragment {
|
public class ProgressFragment extends Fragment {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -64,10 +64,6 @@ public class SphereFragment extends ImageFragment implements View.OnTouchListene
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MainActivity getMainActivity() {
|
|
||||||
return (MainActivity) getActivity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateBitmap(Bitmap bitmap) {
|
public void updateBitmap(Bitmap bitmap) {
|
||||||
if (surfaceView == null) {
|
if (surfaceView == null) {
|
||||||
|
@ -76,7 +72,7 @@ public class SphereFragment extends ImageFragment implements View.OnTouchListene
|
||||||
surfaceView.setBitmap(bitmap);
|
surfaceView.setBitmap(bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void toggleUseTouchInput() {
|
public PhotoSphereSurfaceView getSurfaceView() {
|
||||||
surfaceView.setUseTouchInput(!surfaceView.getUseTouchInput());
|
return surfaceView;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,58 +11,14 @@ import android.util.Log;
|
||||||
import javax.microedition.khronos.egl.EGLConfig;
|
import javax.microedition.khronos.egl.EGLConfig;
|
||||||
import javax.microedition.khronos.opengles.GL10;
|
import javax.microedition.khronos.opengles.GL10;
|
||||||
|
|
||||||
import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
|
import de.trac.spherical.BroadcastHelper;
|
||||||
import static android.opengl.GLES20.GL_COMPILE_STATUS;
|
|
||||||
import static android.opengl.GLES20.GL_CULL_FACE;
|
import static android.opengl.GLES20.*;
|
||||||
import static android.opengl.GLES20.GL_CW;
|
|
||||||
import static android.opengl.GLES20.GL_DEPTH_BUFFER_BIT;
|
|
||||||
import static android.opengl.GLES20.GL_DEPTH_TEST;
|
|
||||||
import static android.opengl.GLES20.GL_FLOAT;
|
|
||||||
import static android.opengl.GLES20.GL_FRAGMENT_SHADER;
|
|
||||||
import static android.opengl.GLES20.GL_LINEAR;
|
|
||||||
import static android.opengl.GLES20.GL_LINK_STATUS;
|
|
||||||
import static android.opengl.GLES20.GL_NEAREST;
|
|
||||||
import static android.opengl.GLES20.GL_TEXTURE0;
|
|
||||||
import static android.opengl.GLES20.GL_TEXTURE_2D;
|
|
||||||
import static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER;
|
|
||||||
import static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER;
|
|
||||||
import static android.opengl.GLES20.GL_TRIANGLES;
|
|
||||||
import static android.opengl.GLES20.GL_TRUE;
|
|
||||||
import static android.opengl.GLES20.GL_UNSIGNED_SHORT;
|
|
||||||
import static android.opengl.GLES20.GL_VERTEX_SHADER;
|
|
||||||
import static android.opengl.GLES20.glActiveTexture;
|
|
||||||
import static android.opengl.GLES20.glAttachShader;
|
|
||||||
import static android.opengl.GLES20.glBindTexture;
|
|
||||||
import static android.opengl.GLES20.glClear;
|
|
||||||
import static android.opengl.GLES20.glClearColor;
|
|
||||||
import static android.opengl.GLES20.glCompileShader;
|
|
||||||
import static android.opengl.GLES20.glCreateProgram;
|
|
||||||
import static android.opengl.GLES20.glCreateShader;
|
|
||||||
import static android.opengl.GLES20.glDeleteProgram;
|
|
||||||
import static android.opengl.GLES20.glDeleteShader;
|
|
||||||
import static android.opengl.GLES20.glDisableVertexAttribArray;
|
|
||||||
import static android.opengl.GLES20.glDrawElements;
|
|
||||||
import static android.opengl.GLES20.glEnable;
|
|
||||||
import static android.opengl.GLES20.glEnableVertexAttribArray;
|
|
||||||
import static android.opengl.GLES20.glFrontFace;
|
|
||||||
import static android.opengl.GLES20.glGenTextures;
|
|
||||||
import static android.opengl.GLES20.glGetAttribLocation;
|
|
||||||
import static android.opengl.GLES20.glGetProgramInfoLog;
|
|
||||||
import static android.opengl.GLES20.glGetProgramiv;
|
|
||||||
import static android.opengl.GLES20.glGetShaderInfoLog;
|
|
||||||
import static android.opengl.GLES20.glGetShaderiv;
|
|
||||||
import static android.opengl.GLES20.glGetUniformLocation;
|
|
||||||
import static android.opengl.GLES20.glLinkProgram;
|
|
||||||
import static android.opengl.GLES20.glShaderSource;
|
|
||||||
import static android.opengl.GLES20.glTexParameteri;
|
|
||||||
import static android.opengl.GLES20.glUniform1i;
|
|
||||||
import static android.opengl.GLES20.glUniformMatrix4fv;
|
|
||||||
import static android.opengl.GLES20.glUseProgram;
|
|
||||||
import static android.opengl.GLES20.glVertexAttribPointer;
|
|
||||||
import static android.opengl.GLES20.glViewport;
|
|
||||||
|
|
||||||
public class PhotoSphereRenderer implements GLSurfaceView.Renderer {
|
public class PhotoSphereRenderer implements GLSurfaceView.Renderer {
|
||||||
|
|
||||||
|
private static final String TAG = "PhotoSphereRenderer";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default vertex shader.
|
* Default vertex shader.
|
||||||
*
|
*
|
||||||
|
@ -97,7 +53,7 @@ public class PhotoSphereRenderer implements GLSurfaceView.Renderer {
|
||||||
// Sphere configuration.
|
// Sphere configuration.
|
||||||
public static final int SPHERE_POLY_COUNT_X = 32;
|
public static final int SPHERE_POLY_COUNT_X = 32;
|
||||||
public static final int SPHERE_POLY_COUNT_Y = 32;
|
public static final int SPHERE_POLY_COUNT_Y = 32;
|
||||||
public static final float SPHERE_RADIUS = 10.0f;
|
public static final float SPHERE_RADIUS = 1.0f;
|
||||||
|
|
||||||
// Store a photoSphereGeometry geometry as framework for the photo texture.
|
// Store a photoSphereGeometry geometry as framework for the photo texture.
|
||||||
private PhotoSphereGeometry photoSphereGeometry = null;
|
private PhotoSphereGeometry photoSphereGeometry = null;
|
||||||
|
@ -105,14 +61,14 @@ public class PhotoSphereRenderer implements GLSurfaceView.Renderer {
|
||||||
// Store projection matrix.
|
// Store projection matrix.
|
||||||
private float projectionMatrix[] = new float [16];
|
private float projectionMatrix[] = new float [16];
|
||||||
|
|
||||||
// Store modelview matrix.
|
// Store model matrix.
|
||||||
private float modelMatrix[] = new float [16];
|
private float modelMatrix[] = new float [16];
|
||||||
|
|
||||||
// Store view matrix.
|
// Store view matrix.
|
||||||
private float viewMatrix [] = new float [16];
|
private float viewMatrix [] = new float [16];
|
||||||
|
|
||||||
// Store the model view projection matrix.
|
// Store the model view projection matrix.
|
||||||
private float mvpMatrix [] = new float [16];
|
private float mvpMatrix [] = new float [32];
|
||||||
|
|
||||||
// This array contains the current view matrix {x, y, width, height).
|
// This array contains the current view matrix {x, y, width, height).
|
||||||
private int view [] = null;
|
private int view [] = null;
|
||||||
|
@ -129,8 +85,8 @@ public class PhotoSphereRenderer implements GLSurfaceView.Renderer {
|
||||||
// Store texture.
|
// Store texture.
|
||||||
private final int textureID [] = new int[1];
|
private final int textureID [] = new int[1];
|
||||||
|
|
||||||
// Store bitmap for lazy loading.
|
// Store requested bitmap for lazy loading.
|
||||||
private Bitmap bitmap = null;
|
private Bitmap requestedBitmap = null;
|
||||||
|
|
||||||
// Store input handler instance to determine transformation.
|
// Store input handler instance to determine transformation.
|
||||||
private PhotoSphereSurfaceView surfaceView;
|
private PhotoSphereSurfaceView surfaceView;
|
||||||
|
@ -155,20 +111,13 @@ public class PhotoSphereRenderer implements GLSurfaceView.Renderer {
|
||||||
public void onDrawFrame(GL10 unused) {
|
public void onDrawFrame(GL10 unused) {
|
||||||
|
|
||||||
// Upload texture, if necessary.
|
// Upload texture, if necessary.
|
||||||
if(bitmap != null) {
|
if(requestedBitmap != null)
|
||||||
glBindTexture(GL_TEXTURE_2D, textureID[0]);
|
uploadImage();
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
// Release bitmap for garbage collection.
|
|
||||||
bitmap = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update transformation matrix.
|
// Update transformation matrix.
|
||||||
Matrix.multiplyMM(mvpMatrix, 0, surfaceView.getRotationMatrix(), 0, modelMatrix, 0);
|
//Matrix.multiplyMM(mvpMatrix, 0, surfaceView.getRotationMatrix(), 0, modelMatrix, 0);
|
||||||
Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, mvpMatrix, 0);
|
//Matrix.multiplyMM(mvpMatrix, 16, viewMatrix, 0, mvpMatrix, 0);
|
||||||
|
Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, surfaceView.getRotationMatrix(), 0);
|
||||||
|
|
||||||
// Draw the frame.
|
// Draw the frame.
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
@ -218,10 +167,11 @@ public class PhotoSphereRenderer implements GLSurfaceView.Renderer {
|
||||||
photoSphereGeometry = new PhotoSphereGeometry(SPHERE_RADIUS, SPHERE_POLY_COUNT_X, SPHERE_POLY_COUNT_Y);
|
photoSphereGeometry = new PhotoSphereGeometry(SPHERE_RADIUS, SPHERE_POLY_COUNT_X, SPHERE_POLY_COUNT_Y);
|
||||||
|
|
||||||
// Set OpenGL state.
|
// Set OpenGL state.
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_CULL_FACE);
|
//glEnable(GL_CULL_FACE);
|
||||||
glFrontFace(GL_CW);
|
glDisable(GL_CULL_FACE);
|
||||||
|
//glFrontFace(GL_CW);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
// Build shader program.
|
// Build shader program.
|
||||||
|
@ -231,17 +181,51 @@ public class PhotoSphereRenderer implements GLSurfaceView.Renderer {
|
||||||
glGenTextures(1, textureID, 0);
|
glGenTextures(1, textureID, 0);
|
||||||
|
|
||||||
// Initialize matrices.
|
// Initialize matrices.
|
||||||
Matrix.setRotateM(modelMatrix, 0, 90, 1.0f, 0.0f, 0.0f);
|
//Matrix.setRotateM(modelMatrix, 0, 90, 1.0f, 0.0f, 0.0f);
|
||||||
Matrix.setLookAtM(viewMatrix, 0, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f);
|
Matrix.setLookAtM(viewMatrix, 0, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests the renderer to uploads the image data of the given bitmap as texture.
|
* Requests the renderer to uploads the image data of the given requestedBitmap as texture.
|
||||||
* May not be done immediately.
|
* May not be done immediately.
|
||||||
* @param bitmap Bitmap to be set as texture
|
* @param bitmap Bitmap to be set as texture
|
||||||
*/
|
*/
|
||||||
public void requestBitmapUpload(Bitmap bitmap) {
|
public void requestBitmapUpload(Bitmap bitmap) {
|
||||||
this.bitmap = bitmap;
|
this.requestedBitmap = bitmap;
|
||||||
|
surfaceView.requestRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uploads a requested image.
|
||||||
|
*/
|
||||||
|
private void uploadImage() {
|
||||||
|
|
||||||
|
// Tell the main activity we are going to do an expensive operation.
|
||||||
|
BroadcastHelper.broadcast(surfaceView.getContext(), BroadcastHelper.BroadcastType.PROGRESS_START);
|
||||||
|
|
||||||
|
// Check if requestedBitmap needs to be downsampled.
|
||||||
|
int [] maxTextureSize = new int[1];
|
||||||
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxTextureSize, 0);
|
||||||
|
float maxSize = Math.max(requestedBitmap.getWidth(), requestedBitmap.getHeight());
|
||||||
|
if(maxSize > maxTextureSize[0]) { // TODO: implement tiling technique
|
||||||
|
Log.w(TAG, "Image too big, exceeding " + maxTextureSize[0] + " : will be downsampled");
|
||||||
|
int newWidth = (int) (requestedBitmap.getWidth() * maxTextureSize[0] / maxSize);
|
||||||
|
int newHeight = (int) (requestedBitmap.getHeight() * maxTextureSize[0] / maxSize);
|
||||||
|
requestedBitmap = Bitmap.createScaledBitmap(requestedBitmap, newWidth, newHeight, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload texture.
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textureID[0]);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
GLUtils.texImage2D(GL_TEXTURE_2D, 0, requestedBitmap, 0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
// Release requestedBitmap for garbage collection.
|
||||||
|
requestedBitmap = null;
|
||||||
|
|
||||||
|
// Tell main activity we are done.
|
||||||
|
BroadcastHelper.broadcast(surfaceView.getContext(), BroadcastHelper.BroadcastType.PROGRESS_FINISHED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -282,8 +266,8 @@ public class PhotoSphereRenderer implements GLSurfaceView.Renderer {
|
||||||
int[] linkStatus = new int[1];
|
int[] linkStatus = new int[1];
|
||||||
glGetProgramiv(program, GL_LINK_STATUS, linkStatus, 0);
|
glGetProgramiv(program, GL_LINK_STATUS, linkStatus, 0);
|
||||||
if (linkStatus[0] != GL_TRUE) {
|
if (linkStatus[0] != GL_TRUE) {
|
||||||
Log.e("Shader", "Could not link program: ");
|
Log.e(TAG, "Could not link program: ");
|
||||||
Log.e("Shader", glGetProgramInfoLog(program));
|
Log.e(TAG, glGetProgramInfoLog(program));
|
||||||
glDeleteProgram(program);
|
glDeleteProgram(program);
|
||||||
throw new RuntimeException("Could not link program");
|
throw new RuntimeException("Could not link program");
|
||||||
}
|
}
|
||||||
|
@ -323,8 +307,8 @@ public class PhotoSphereRenderer implements GLSurfaceView.Renderer {
|
||||||
int[] compiled = new int[1];
|
int[] compiled = new int[1];
|
||||||
glGetShaderiv(shader, GL_COMPILE_STATUS, compiled, 0);
|
glGetShaderiv(shader, GL_COMPILE_STATUS, compiled, 0);
|
||||||
if (compiled[0] == 0) {
|
if (compiled[0] == 0) {
|
||||||
Log.e("Shader", "Could not compile shader " + type + ":");
|
Log.e(TAG, "Could not compile shader " + type + ":");
|
||||||
Log.e("Shader", glGetShaderInfoLog(shader));
|
Log.e(TAG, glGetShaderInfoLog(shader));
|
||||||
glDeleteShader(shader);
|
glDeleteShader(shader);
|
||||||
shader = 0;
|
shader = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ public class PhotoSphereSurfaceView extends GLSurfaceView implements SensorEvent
|
||||||
private final float rayDirection [] = new float[4];
|
private final float rayDirection [] = new float[4];
|
||||||
|
|
||||||
//
|
//
|
||||||
float oldAngleXZ, oldAngleY;
|
private float oldAngleXZ, oldAngleY;
|
||||||
|
|
||||||
// The renderer used by this view.
|
// The renderer used by this view.
|
||||||
private PhotoSphereRenderer renderer;
|
private PhotoSphereRenderer renderer;
|
||||||
|
@ -64,7 +64,7 @@ public class PhotoSphereSurfaceView extends GLSurfaceView implements SensorEvent
|
||||||
|
|
||||||
if(!useTouchInput)
|
if(!useTouchInput)
|
||||||
return true;
|
return true;
|
||||||
|
/*
|
||||||
// Retrieve ray in world space.
|
// Retrieve ray in world space.
|
||||||
renderer.getRay(event.getX(), event.getY(), rayStart, rayDirection);
|
renderer.getRay(event.getX(), event.getY(), rayStart, rayDirection);
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ public class PhotoSphereSurfaceView extends GLSurfaceView implements SensorEvent
|
||||||
synchronized (rotationMatrix) {
|
synchronized (rotationMatrix) {
|
||||||
Matrix.translateM(rotationMatrix, 0, px, py, pz);
|
Matrix.translateM(rotationMatrix, 0, px, py, pz);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
// Calculate angles.
|
// Calculate angles.
|
||||||
float angleY = (float) Math.toDegrees(Math.atan2(pz, px));
|
float angleY = (float) Math.toDegrees(Math.atan2(pz, px));
|
||||||
|
|
1
gradle/wrapper/gradle-wrapper.properties
vendored
1
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,4 +1,3 @@
|
||||||
#Tue Dec 19 17:35:15 CET 2017
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|
Loading…
Reference in a new issue