Commit 4692c8ca authored by Ruben Jesus Garcia Hernandez's avatar Ruben Jesus Garcia Hernandez
Browse files

Support Nexus in google cardboard. Small bugfix in oculus mobile

parent 46e1c559
...@@ -84,18 +84,22 @@ public static void verifyStoragePermissions(Activity activity) { ...@@ -84,18 +84,22 @@ public static void verifyStoragePermissions(Activity activity) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
verifyStoragePermissions(this); verifyStoragePermissions(this);
String externalsd=android.os.Environment.getExternalStorageDirectory().getPath() + "/";
//intents //intents
android.content.Intent intent = getIntent(); android.content.Intent intent = getIntent();
String s=intent.getDataString(); String s=intent.getDataString();
String uriString="/data/local/tmp/material.ncfg"; String uriString=externalsd+"material.ncfg";
if (s==null)
android.util.Log.d("NOMADgvrT","String intent is null");
else
android.util.Log.d("NOMADgvrT","String intent is <"+ s+">");
if (s!=null) { if (s!=null) {
if (s.startsWith("content://")) { if (s.startsWith("content://")) {
try { try {
java.io.InputStream input = getContentResolver().openInputStream(intent.getData()); java.io.InputStream input = getContentResolver().openInputStream(intent.getData());
byte[] buffer = new byte[8 * 1024]; byte[] buffer = new byte[8 * 1024];
java.io.FileOutputStream output = new java.io.FileOutputStream("/data/local/tmp/material.ncfg"); java.io.FileOutputStream output = new java.io.FileOutputStream(uriString);
try{ try{
int bytesRead; int bytesRead;
while((bytesRead = input.read()) != -1){ while((bytesRead = input.read()) != -1){
...@@ -106,24 +110,29 @@ public static void verifyStoragePermissions(Activity activity) { ...@@ -106,24 +110,29 @@ public static void verifyStoragePermissions(Activity activity) {
output.close(); output.close();
} catch (Exception e) { } catch (Exception e) {
uriString=null; uriString=null;
android.util.Log.d("NOMADgvrT","Exception closing output stream");
} }
try { try {
input.close(); input.close();
} catch (java.io.IOException e) { } catch (java.io.IOException e) {
uriString=null; uriString=null;
android.util.Log.d("NOMADgvrT","Exception closing input stream");
} }
} }
} catch (java.io.IOException e) { } catch (java.io.IOException e) {
uriString=null; uriString=null;
android.util.Log.d("NOMADgvrT","Exception saving intent to disk");
} }
if (uriString!=null) if (uriString!=null)
nativeSetConfigFile(uriString); nativeSetConfigFile(uriString, externalsd);
} else if (s.startsWith("file://")) { } else if (s.startsWith("file://")) {
uriString=s.substring(7); uriString=s.substring(7);
nativeSetConfigFile(uriString); nativeSetConfigFile(uriString, externalsd);
} else { } else {
android.util.Log.d("NOMADgvrT","Unknown protocol in intent:"+ s); android.util.Log.d("NOMADgvrT","Unknown protocol in intent:"+ s);
} }
} else { //use default
nativeSetConfigFile(externalsd+"Default.ncfg", externalsd);
} }
// Ensure fullscreen immersion. // Ensure fullscreen immersion.
...@@ -277,5 +286,5 @@ public static void verifyStoragePermissions(Activity activity) { ...@@ -277,5 +286,5 @@ public static void verifyStoragePermissions(Activity activity) {
private native void nativeOnResume(long nativeTreasureHuntRenderer); private native void nativeOnResume(long nativeTreasureHuntRenderer);
private native void nativeSetConfigFile(String s); private native void nativeSetConfigFile(String s, String e);
} }
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "treasure_hunt_renderer.h" // NOLINT #include "treasure_hunt_renderer.h" // NOLINT
#include "vr/gvr/capi/include/gvr.h" #include "vr/gvr/capi/include/gvr.h"
#include "vr/gvr/capi/include/gvr_audio.h" #include "vr/gvr/capi/include/gvr_audio.h"
#include "NOMADVRLib/atoms.hpp" //for TMPDIR
#define JNI_METHOD(return_type, method_name) \ #define JNI_METHOD(return_type, method_name) \
JNIEXPORT return_type JNICALL \ JNIEXPORT return_type JNICALL \
...@@ -82,8 +83,9 @@ JNI_METHOD(void, nativeOnResume) ...@@ -82,8 +83,9 @@ JNI_METHOD(void, nativeOnResume)
} }
JNI_METHOD(void, nativeSetConfigFile) JNI_METHOD(void, nativeSetConfigFile)
(JNIEnv *env, jobject obj, jstring s) { (JNIEnv *env, jobject obj, jstring s, jstring e) {
configPath = env->GetStringUTFChars(s , NULL ) ; configPath = env->GetStringUTFChars(s , NULL ) ;
TMPDIR=env->GetStringUTFChars(e , NULL ) ;
} }
......
...@@ -312,31 +312,32 @@ TreasureHuntRenderer::TreasureHuntRenderer( ...@@ -312,31 +312,32 @@ TreasureHuntRenderer::TreasureHuntRenderer(
gvr_controller_api_(nullptr), gvr_controller_api_(nullptr),
gvr_viewer_type_(gvr_api_->GetViewerType()) { gvr_viewer_type_(gvr_api_->GetViewerType()) {
eprintf ("configPath=%d", configPath);
if (configPath!=nullptr) if (configPath!=nullptr)
eprintf ("configPath=<%s>", configPath); eprintf ("configPath=<%s>", configPath);
else
eprintf ("configPath is null");
const char *configfile="/storage/emulated/0/Oculus/NOMAD/ViveTDefault.ncfg"; if (TMPDIR!=nullptr)
//change cwd so that relative paths work eprintf ("TMPDIR=<%s>", TMPDIR);
if (configPath!=nullptr) else
configfile=configPath; eprintf ("TMPDIR is null");
std::string s(configfile);
std::string s(configPath);
chdir(s.substr(0, s.find_last_of("\\/")).c_str()); chdir(s.substr(0, s.find_last_of("\\/")).c_str());
int r;
if ((r=loadConfigFile(configfile))<0) { if ((error=loadConfigFile(configPath))<0) {
if (-100<r) { if (-100<error) {
eprintf(loadConfigFileErrors[-r]); eprintf(loadConfigFileErrors[-error]);
eprintf("Config file reading error"); eprintf("Config file reading error");
} else if (-200<r){ } else if (-200<error){
eprintf(readAtomsXYZErrors[-r-100]); eprintf(readAtomsXYZErrors[-error-100]);
eprintf("XYZ file reading error"); eprintf("XYZ file reading error");
} else if (-300<r) { } else if (-300<error) {
eprintf(readAtomsCubeErrors[-r-200]); eprintf(readAtomsCubeErrors[-error-200]);
eprintf("Cube file reading error"); eprintf("Cube file reading error");
} else { } else {
eprintf(readAtomsJsonErrors[-r-300]); eprintf(readAtomsJsonErrors[-error-300]);
eprintf("Json reading error"); eprintf("Json reading error");
} }
} }
...@@ -365,6 +366,12 @@ TreasureHuntRenderer::~TreasureHuntRenderer() { ...@@ -365,6 +366,12 @@ TreasureHuntRenderer::~TreasureHuntRenderer() {
glDeleteTextures(2, textures); glDeleteTextures(2, textures);
} }
const char * ErrorsGL[] = {
"Failure compiling Unit Cell Shader", //-401
"Failure compiling Atom Shader NoTess", //-402;
};
void TreasureHuntRenderer::InitializeGl() { void TreasureHuntRenderer::InitializeGl() {
gvr_api_->InitializeGl(); gvr_api_->InitializeGl();
...@@ -382,35 +389,46 @@ glGenTextures(2, textures); ...@@ -382,35 +389,46 @@ glGenTextures(2, textures);
//Leave atoms until we check if android 7 has gles 3.2 or if we use the old icosahedron method with no tesselation //Leave atoms until we check if android 7 has gles 3.2 or if we use the old icosahedron method with no tesselation
if (!PrepareUnitCellShader (&UnitCellP, &UnitCellMatrixLoc, &UnitCellColourLoc)) { if (!PrepareUnitCellShader (&UnitCellP, &UnitCellMatrixLoc, &UnitCellColourLoc)) {
eprintf("OneTimeInit, failure compiling Unit Cell Shader"); eprintf("OneTimeInit, failure compiling Unit Cell Shader");
error=-401;
return ; return ;
} }
//rgh: for now, we don't have any tess-ready phones //rgh: for now, we don't have any tess-ready phones
//if (!PrepareAtomShader(&AtomsP, &AtomMatrixLoc)) { //if (!PrepareAtomShader(&AtomsP, &AtomMatrixLoc)) {
hasTess=false; hasTess=false;
if (!PrepareAtomShaderNoTess(&AtomsP, &AtomMatrixLoc)) if (!PrepareAtomShaderNoTess(&AtomsP, &AtomMatrixLoc)) {
error=-402;
eprintf ("PrepareAtomShaderNoTess failed"); eprintf ("PrepareAtomShaderNoTess failed");
}
//}; //};
//atom texture //atom texture
int e; int e;
e=atomTexture(textures[1]); e=atomTexture(textures[1]);
if (e!=GL_NO_ERROR) if (e!=GL_NO_ERROR) {
eprintf ("atomTexture error %d", e); eprintf ("atomTexture error %d", e);
error=-403;
}
e=SetupAtoms(&AtomTVAO, &AtomTBuffer); e=SetupAtoms(&AtomTVAO, &AtomTBuffer);
if (e!=GL_NO_ERROR) if (e!=GL_NO_ERROR) {
eprintf ("SetupAtoms error %d", e); eprintf ("SetupAtoms error %d", e);
error=-404;
}
if (!hasTess) if (!hasTess)
e=SetupAtomsNoTess(&AtomVAO, &AtomBuffer, &AtomIndices); e=SetupAtomsNoTess(&AtomVAO, &AtomBuffer, &AtomIndices);
if (e!=GL_NO_ERROR) if (e!=GL_NO_ERROR) {
eprintf ("SetupAtomsNoTess error %d, tess=%d", e, hasTess); eprintf ("SetupAtomsNoTess error %d, tess=%d", e, hasTess);
error=-405;
}
e=SetupUnitCell(&UnitCellVAO, &UnitCellBuffer, &UnitCellIndexBuffer); e=SetupUnitCell(&UnitCellVAO, &UnitCellBuffer, &UnitCellIndexBuffer);
if (e!=GL_NO_ERROR) if (e!=GL_NO_ERROR) {
eprintf ("SetupUnitCell error %d", e); eprintf ("SetupUnitCell error %d", e);
error=-406;
}
// Because we are using 2X MSAA, we can render to half as many pixels and // Because we are using 2X MSAA, we can render to half as many pixels and
// achieve similar quality. // achieve similar quality.
...@@ -525,7 +543,23 @@ if (animateTimesteps) { ...@@ -525,7 +543,23 @@ if (animateTimesteps) {
// Draw the world. // Draw the world.
frame.BindBuffer(0); frame.BindBuffer(0);
glClearColor(0.1f, 0.1f, 0.1f, 0.5f); // Dark background so text shows up. if (error<0) {
if (-100<error) {
glClearColor(1.f, 0.f, 0.f, 1.f);
} else if (-200<error){
glClearColor(0.f, 1.f, 0.f, 1.f);
} else if (-300<error) {
glClearColor(0.f, 0.f, 1.f, 1.f);
} else if (-400<error) {
glClearColor(0.f, 1.f, 1.f, 1.f);
} else {
glClearColor(1.f, 0.f, 1.f, 1.f);
}
} else {
glClearColor(BACKGROUND[0], BACKGROUND[1], BACKGROUND[2], 0.5f);
}
// Dark background so text shows up.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
viewport_list_->GetBufferViewport(0, &scratch_viewport_); viewport_list_->GetBufferViewport(0, &scratch_viewport_);
DrawWorld(left_eye_view, scratch_viewport_); DrawWorld(left_eye_view, scratch_viewport_);
...@@ -623,7 +657,14 @@ void TreasureHuntRenderer::DrawWorld(const gvr::Mat4f& view_matrix, ...@@ -623,7 +657,14 @@ void TreasureHuntRenderer::DrawWorld(const gvr::Mat4f& view_matrix,
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
modelview_=view_matrix; modelview_=view_matrix;
modelview_projection_cube_ = MatrixMul(perspective, modelview_); modelview_projection_cube_ = MatrixMul(perspective, modelview_);
RenderUnitCell(modelview_projection_cube_); if(error)
return;
if (has_abc) {
RenderUnitCell(modelview_projection_cube_);
} else {
//atom trajectories
RenderAtomTrajectories(modelview_projection_cube_);
}
} }
...@@ -724,6 +765,31 @@ void TreasureHuntRenderer::RenderAtoms(const float *m) //m[16] ...@@ -724,6 +765,31 @@ void TreasureHuntRenderer::RenderAtoms(const float *m) //m[16]
} // no tess } // no tess
} }
void TreasureHuntRenderer::RenderAtomTrajectories(const gvr::Mat4f eyeViewProjection)
{
int e;
if (!numAtoms)
return;
gvr::Mat4f trans={1,0,0,UserTranslation[0],
0,1,0,UserTranslation[1],
0,0,1,UserTranslation[2],
0,0,0,1};
//trans.translate(iPos).rotateX(-90).translate(UserPosition);
gvr::Mat4f transform = MatrixMul(eyeViewProjection,trans);
//gvr::Mat4f transform=eyeViewProjection;
float t[16];
for (int i=0;i<4;i++)
for (int j=0;j<4;j++)
t[j*4+i]=transform.m[i][j];
glUseProgram(UnitCellP);
glUniformMatrix4fv(UnitCellMatrixLoc, 1, GL_FALSE, t);
if ((e = glGetError()) != GL_NO_ERROR)
eprintf("Gl error after glUniform4fv 1 RenderAtomTrajectories: %d\n", e);
RenderAtomTrajectoriesUnitCell();
RenderAtoms(t);
}
void TreasureHuntRenderer::RenderAtomTrajectoriesUnitCell() void TreasureHuntRenderer::RenderAtomTrajectoriesUnitCell()
{ {
//now trajectories //now trajectories
...@@ -743,7 +809,7 @@ glBindVertexArray(AtomTVAO[0]); ...@@ -743,7 +809,7 @@ glBindVertexArray(AtomTVAO[0]);
float color[4]={1,0,0,1}; float color[4]={1,0,0,1};
glUniform4fv(UnitCellColourLoc, 1, color); glUniform4fv(UnitCellColourLoc, 1, color);
if ((e = glGetError()) != GL_NO_ERROR) if ((e = glGetError()) != GL_NO_ERROR)
eprintf("Gl error after glUniform4fv 2 RenderUnitCell: %d\n", e); eprintf("Gl error after glUniform4fv 2 RenderAtomTrajectoriesUnitCell: %d\n", e);
//glEnableVertexAttribArray(0); //glEnableVertexAttribArray(0);
//glDisableVertexAttribArray(1); //glDisableVertexAttribArray(1);
...@@ -776,13 +842,10 @@ for (unsigned int i=0;i<atomtrajectories.size();i++) { ...@@ -776,13 +842,10 @@ for (unsigned int i=0;i<atomtrajectories.size();i++) {
void TreasureHuntRenderer::RenderUnitCell(const gvr::Mat4f eyeViewProjection) void TreasureHuntRenderer::RenderUnitCell(const gvr::Mat4f eyeViewProjection)
{ {
eprintf ("eyeViewProjection"); //eprintf ("eyeViewProjection");
for (int i=0;i<4;i++) //for (int i=0;i<4;i++)
for (int j=0;j<4;j++) // for (int j=0;j<4;j++)
eprintf ("%d %d = %f", i, j, eyeViewProjection.m[i][j]); // eprintf ("%d %d = %f", i, j, eyeViewProjection.m[i][j]);
//repetitions[0]=10;
//repetitions[1]=10;
//repetitions[2]=10;
eprintf ("RenderUnitCell, has_abc=%d", has_abc); eprintf ("RenderUnitCell, has_abc=%d", has_abc);
if (!has_abc) if (!has_abc)
return; return;
......
...@@ -162,9 +162,10 @@ bool animateTimesteps=false; ...@@ -162,9 +162,10 @@ bool animateTimesteps=false;
void RenderAtoms(const float *m); void RenderAtoms(const float *m);
void RenderUnitCell(const gvr::Mat4f eyeViewProjection); void RenderUnitCell(const gvr::Mat4f eyeViewProjection);
void RenderAtomTrajectoriesUnitCell(); void RenderAtomTrajectoriesUnitCell();
void RenderAtomTrajectories(const gvr::Mat4f eyeViewProjection);
float UserTranslation[3]={10,0,0}; float UserTranslation[3]={10,0,0};
int error=0;
}; };
#endif // TREASUREHUNT_APP_SRC_MAIN_JNI_TREASUREHUNTRENDERER_H_ // NOLINT #endif // TREASUREHUNT_APP_SRC_MAIN_JNI_TREASUREHUNTRENDERER_H_ // NOLINT
This repository contains the demos for Google cardboard using GVR Android SDK v1.20.0
https://github.com/googlevr/gvr-android-sdk
Clone that repository and add the content of this one inside the Samples directory.
Copy the content of the ../libs directory (happyhttp, rapidjson) and NOMADVRLib into
NOMADgvrT/src/main/jni
Enable support for ndk (tested: android-ndk-r10d) in settings.gradle:
include ':samples:NOMADgvrT'
List of directories
NOMADgvrT:
This program can load prepared molecular dynamics simulations, and is
compatible with the TimestepData OpenVR demo.
Ply support is not yet implemented
\ No newline at end of file
...@@ -128,6 +128,7 @@ int loadConfigFile(const char * f) ...@@ -128,6 +128,7 @@ int loadConfigFile(const char * f)
showTrajectories = false; showTrajectories = false;
basisvectorreps=0; basisvectorreps=0;
numClonedAtoms=0; numClonedAtoms=0;
has_abc=false;
for (int i=0;i<3;i++) for (int i=0;i<3;i++)
repetitions[i]=1; repetitions[i]=1;
for (int i=0;i<3;i++) for (int i=0;i<3;i++)
...@@ -249,6 +250,7 @@ int loadConfigFile(const char * f) ...@@ -249,6 +250,7 @@ int loadConfigFile(const char * f)
if (e<0) if (e<0)
return e-100; return e-100;
updateTIMESTEPS (timesteps); updateTIMESTEPS (timesteps);
//eprintf ("After read of xyzfile, numatoms 0 =%d", numAtoms[0]);
} }
else if (!strcmp(s, "cubefile")) { else if (!strcmp(s, "cubefile")) {
r=readString(F, s); r=readString(F, s);
...@@ -345,9 +347,12 @@ int loadConfigFile(const char * f) ...@@ -345,9 +347,12 @@ int loadConfigFile(const char * f)
solid=new Solid(Solid::Type::Tetrahedron); solid=new Solid(Solid::Type::Tetrahedron);
else else
return -15; return -15;
} } else if (!strcmp (s, "\x0d")) { //discard windows newline (problem in Sebastian Kokott's phone (?!)
else { continue;
} else {
eprintf( "Unrecognized parameter %s\n", s); eprintf( "Unrecognized parameter %s\n", s);
for (int i=0;i<strlen(s);i++)
eprintf ("<%d>", s[i]);
fclose(F); fclose(F);
return -2; return -2;
} }
...@@ -381,6 +386,6 @@ int loadConfigFile(const char * f) ...@@ -381,6 +386,6 @@ int loadConfigFile(const char * f)
for (int i=0;i<*numAtoms;i++) for (int i=0;i<*numAtoms;i++)
atomtrajectories.push_back(i); atomtrajectories.push_back(i);
} }
//eprintf ("Before returning, numatoms 0 =%d", numAtoms[0]);
return 0; return 0;
} }
\ No newline at end of file
...@@ -5,7 +5,7 @@ const char * const UnitCellShaders [] = {"Unit Cell Renderer", ...@@ -5,7 +5,7 @@ const char * const UnitCellShaders [] = {"Unit Cell Renderer",
#ifdef WIN32 #ifdef WIN32
"#version 410\n" "#version 410\n"
#else #else
"#version 310 es\n" "#version 300 es\n"
#endif #endif
"uniform mat4 matrix;\n" "uniform mat4 matrix;\n"
"layout(location = 0) in vec3 pos;\n" "layout(location = 0) in vec3 pos;\n"
...@@ -18,7 +18,7 @@ const char * const UnitCellShaders [] = {"Unit Cell Renderer", ...@@ -18,7 +18,7 @@ const char * const UnitCellShaders [] = {"Unit Cell Renderer",
#ifdef WIN32 #ifdef WIN32
"#version 410\n" "#version 410\n"
#else #else
"#version 310 es\n" "#version 300 es\n"
#endif #endif
"uniform lowp vec4 color;\n" "uniform lowp vec4 color;\n"
"out lowp vec4 outputColor;\n" "out lowp vec4 outputColor;\n"
......
...@@ -18,7 +18,9 @@ ...@@ -18,7 +18,9 @@
#ifdef WIN32 #ifdef WIN32
const char * TMPDIR=""; const char * TMPDIR="";
#else #else
const char * TMPDIR="/sdcard/Oculus/NOMAD/"; //const char * TMPDIR="/sdcard/Oculus/NOMAD/";
const char * TMPDIR;//filled by main
//="/storage/540E-1AE2/";
#endif #endif
const char * const atomNames[] = const char * const atomNames[] =
...@@ -204,6 +206,7 @@ int readAtomsXYZ(const char *const file, int **numatoms, int *timesteps, float * ...@@ -204,6 +206,7 @@ int readAtomsXYZ(const char *const file, int **numatoms, int *timesteps, float *
continue; //there may be a blank line at the end of the file continue; //there may be a blank line at the end of the file
(*timesteps)++; (*timesteps)++;
discardline (f); discardline (f);
//eprintf ("Getting atoms, mynumatoms=%d",mynumatoms);
mypos.push_back(new float[mynumatoms*4]); mypos.push_back(new float[mynumatoms*4]);
mynum.push_back(mynumatoms); mynum.push_back(mynumatoms);
discardline (f); //comment discardline (f); //comment
...@@ -223,6 +226,7 @@ int readAtomsXYZ(const char *const file, int **numatoms, int *timesteps, float * ...@@ -223,6 +226,7 @@ int readAtomsXYZ(const char *const file, int **numatoms, int *timesteps, float *
for (int i=0;i<*timesteps;i++) { for (int i=0;i<*timesteps;i++) {
(*pos)[i]=mypos[i]; (*pos)[i]=mypos[i];
(*numatoms)[i]=mynum[i]; (*numatoms)[i]=mynum[i];
//eprintf ("Getting atoms, numatoms=%d",(*numatoms)[i]);
} }
return 0; return 0;
......
...@@ -13,20 +13,26 @@ GLenum atomTexture(GLuint t) ...@@ -13,20 +13,26 @@ GLenum atomTexture(GLuint t)
{ {
GLenum e; GLenum e;
//rgh: scale atoms here //rgh: scale atoms here
for (int i = 0; i < 118; i++) //in google cardboard, this is called again if the program is running, so leave original or atoms get progresivelly smaller!
atomColours[i][3] *= atomScaling; float *a=new float[118*4];
for (int i = 0; i < 118; i++) {
a[i*4+0]=atomColours[i][0];
a[i*4+1]=atomColours[i][1];
a[i*4+2]=atomColours[i][2];
a[i*4+3]=atomColours[i][3] * atomScaling;
}
glBindTexture(GL_TEXTURE_2D, t); //atom texture glBindTexture(GL_TEXTURE_2D, t); //atom texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);