NOMAD Cardboard changes:

-Support Alcatel Flash Plus 2 with Android 6.0 (from Berlin FHI)
-Allow android api level 23
-Add icon
-Add file picker on init
-Display transparent isos using additive blending
-Make shaders gles 3.0 compatible
-Update to latest NOMAD VR Lib
parent 14a108c1
...@@ -8,7 +8,7 @@ model { ...@@ -8,7 +8,7 @@ model {
defaultConfig.with { defaultConfig.with {
applicationId = "com.google.vr.ndk.samples.treasurehunt" applicationId = "com.google.vr.ndk.samples.treasurehunt"
minSdkVersion.apiLevel = 19 minSdkVersion.apiLevel = 19
targetSdkVersion.apiLevel = 24 targetSdkVersion.apiLevel = 23
versionCode = 1 versionCode = 1
versionName = "1.0" versionName = "1.0"
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="NOMADgvrT" android:label="NOMADgvrT"
android:theme="@style/VrActivityTheme"> android:theme="@style/VrActivityTheme">
<activity <activity
......
...@@ -79,23 +79,63 @@ public static void verifyStoragePermissions(Activity activity) { ...@@ -79,23 +79,63 @@ public static void verifyStoragePermissions(Activity activity) {
} }
} }
@Override
protected void onActivityResult(int requestCode, int resultCode, android.content.Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==123 && resultCode==RESULT_OK) {
String s=data.getDataString();
android.util.Log.d("NOMADgvrT","OnActivityResult, s="+s);
String uriString="";
if (s.startsWith("file://")) {
uriString=s.substring(7);
} else if (s.startsWith("content://com.asus.filemanager.OpenFileProvider/file")) {
uriString=s.substring(52);
} else {
uriString=s;
}
android.util.Log.d("NOMADgvrT","OnActivityResult, uri="+uriString);
nativeSetConfigFile(uriString, android.os.Environment.getExternalStorageDirectory().getPath() + "/");
nativeLoadConfigFile(nativeTreasureHuntRenderer);
}
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
verifyStoragePermissions(this); verifyStoragePermissions(this);
//http://stackoverflow.com/questions/36557879/how-to-use-native-android-file-open-dialog
/////////
//setContentView(R.layout.activity_main);
///////////
String externalsd=android.os.Environment.getExternalStorageDirectory().getPath() + "/"; 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=externalsd+"material.ncfg"; String uriString=externalsd+"material.ncfg";
if (s==null) if (s==null) {
android.util.Log.d("NOMADgvrT","String intent is null"); android.util.Log.d("NOMADgvrT","String intent is null");
android.content.Intent intentSent = new android.content.Intent()
.setType("*/*")
.setAction(android.content.Intent.ACTION_GET_CONTENT);
startActivityForResult(android.content.Intent.createChooser(intentSent, "Select NOMAD VR config file (.ncfg)"), 123);
s=intentSent.getDataString();
}
else else
android.util.Log.d("NOMADgvrT","String intent is <"+ s+">"); android.util.Log.d("NOMADgvrT","String intent is <"+ s+">");
android.util.Log.d("NOMADgvrT","String intent finally is <"+s+">");
if (s!=null) { if (s!=null) {
if (s.startsWith("content://")) { if (s.startsWith("content://")) {//this only works with ncfg with no associated data
android.util.Log.d("NOMADgvrT","String intent is <"+s+">");
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];
...@@ -289,4 +329,26 @@ public static void verifyStoragePermissions(Activity activity) { ...@@ -289,4 +329,26 @@ public static void verifyStoragePermissions(Activity activity) {
private native void nativeOnResume(long nativeTreasureHuntRenderer); private native void nativeOnResume(long nativeTreasureHuntRenderer);
private native void nativeSetConfigFile(String s, String e); private native void nativeSetConfigFile(String s, String e);
private native void nativeLoadConfigFile(long nativeTreasureHuntRenderer);
public void DisplayMessage (final String s)
{
//http://stackoverflow.com/questions/3875184/cant-create-handler-inside-thread-that-has-not-called-looper-prepare
//rgh: this hangs, need to investigate
new Thread()
{
public void run()
{
MainActivity.this.runOnUiThread(new Runnable()
{
public void run()
{
android.widget.Toast toast = android.widget.Toast.makeText(MainActivity.this.getApplicationContext(), s,
android.widget.Toast.LENGTH_LONG);
}
});
}
}.start();
}
} }
//http://stackoverflow.com/questions/4875114/android-save-image-from-url-onto-sd-card
class NOMAD {
public static boolean i=false;
public static void Init ()
//we are going to block anyway until we have the datasets
{
if (android.os.Build.VERSION.SDK_INT > 9) {
android.os.StrictMode.ThreadPolicy policy = new android.os.StrictMode.ThreadPolicy.Builder().permitAll().build();
android.os.StrictMode.setThreadPolicy(policy);
}
i=true;
}
public static void GetUrl (String url, String path)
{
if (!i)
Init();
android.util.Log.d("NOMAD", "Java NOMAD.GetUrlThread(\""+url+"\",\""+path+"\") called");
try {
java.net.URL u = new java.net.URL(url);
java.net.HttpURLConnection urlConnection = (java.net.HttpURLConnection) u.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
java.io.File file = new java.io.File(path);
java.io.FileOutputStream fileOutput = new java.io.FileOutputStream(file);
int status = urlConnection.getResponseCode();
if (status != java.net.HttpURLConnection.HTTP_OK) {
return; //http error or redirect, we probably want to exit here as NOMAD encyclopedia should not do that
}
java.io.InputStream inputStream = urlConnection.getInputStream();
int totalSize = urlConnection.getContentLength();
int downloadedSize = 0;
byte[] buffer = new byte[1024];
int bufferLength = 0;
while ( (bufferLength = inputStream.read(buffer)) > 0 )
{
fileOutput.write(buffer, 0, bufferLength);
downloadedSize += bufferLength;
}
fileOutput.close();
} //try
catch (Exception e) {
e.printStackTrace();
}
} //GetUrl
} //class NOMAD
...@@ -23,10 +23,16 @@ ...@@ -23,10 +23,16 @@
#include "vr/gvr/capi/include/gvr_audio.h" #include "vr/gvr/capi/include/gvr_audio.h"
#include "NOMADVRLib/atoms.hpp" //for TMPDIR #include "NOMADVRLib/atoms.hpp" //for TMPDIR
#include "treasure_hunt_jni.h"
#define JNI_METHOD(return_type, method_name) \ #define JNI_METHOD(return_type, method_name) \
JNIEXPORT return_type JNICALL \ JNIEXPORT return_type JNICALL \
Java_com_google_vr_ndk_samples_treasurehunt_MainActivity_##method_name Java_com_google_vr_ndk_samples_treasurehunt_MainActivity_##method_name
//http://stackoverflow.com/questions/12900695/how-to-obtain-jni-interface-pointer-jnienv-for-asynchronous-calls
JavaVM* javaVM = nullptr;
jobject jo;
namespace { namespace {
inline jlong jptr(TreasureHuntRenderer *native_treasure_hunt) { inline jlong jptr(TreasureHuntRenderer *native_treasure_hunt) {
...@@ -38,6 +44,28 @@ inline TreasureHuntRenderer *native(jlong ptr) { ...@@ -38,6 +44,28 @@ inline TreasureHuntRenderer *native(jlong ptr) {
} }
} // anonymous namespace } // anonymous namespace
//http://stackoverflow.com/questions/28622036/android-ndk-calling-java-functions-from-c
/*void GetUrl (const char *url, const char *path)
{
jstring jurl = genv->NewStringUTF(url);
jstring jpath = genv->NewStringUTF(path);
jclass jc = genv->FindClass("NOMAD");
jmethodID mid = genv->GetStaticMethodID(jc, "GetUrl", "(Ljava/lang/String;Ljava/lang/String;)V");
genv->CallStaticVoidMethod(jc, mid, jurl, jpath);
}*/
void DisplayMessage (const char *s)
{
JNIEnv *env;
javaVM->AttachCurrentThread(&env, nullptr);
jstring js = env->NewStringUTF(s);
jclass cls = env->GetObjectClass(jo);
jmethodID mid = env->GetMethodID(cls, "DisplayMessage", "(Ljava/lang/String;)V");
env->CallVoidMethod(jo, mid, js);
}
extern "C" { extern "C" {
JNI_METHOD(jlong, nativeCreateRenderer) JNI_METHOD(jlong, nativeCreateRenderer)
...@@ -82,11 +110,20 @@ JNI_METHOD(void, nativeOnResume) ...@@ -82,11 +110,20 @@ JNI_METHOD(void, nativeOnResume)
native(native_treasure_hunt)->OnResume(); native(native_treasure_hunt)->OnResume();
} }
//https://library.vuforia.com/articles/Solution/How-To-Communicate-Between-Java-and-C-using-the-JNI
JNI_METHOD(void, nativeSetConfigFile) JNI_METHOD(void, nativeSetConfigFile)
(JNIEnv *env, jobject obj, jstring s, jstring e) { (JNIEnv *env, jobject obj, jstring s, jstring e) {
env->GetJavaVM(&javaVM);
jo=env->NewGlobalRef(obj);
configPath = env->GetStringUTFChars(s , NULL ) ; configPath = env->GetStringUTFChars(s , NULL ) ;
TMPDIR=env->GetStringUTFChars(e , NULL ) ; TMPDIR=env->GetStringUTFChars(e , NULL ) ;
} }
JNI_METHOD(void, nativeLoadConfigFile)
(JNIEnv *env, jobject obj, jlong native_treasure_hunt) {
native(native_treasure_hunt)->loadConfigFile();
}
} // extern "C" } // extern "C"
//void GetUrl (const char *url, const char *path);
void DisplayMessage (const char *s);
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <unistd.h> #include <unistd.h>
#include "treasure_hunt_renderer.h" // NOLINT #include "treasure_hunt_renderer.h" // NOLINT
#include "treasure_hunt_jni.h"
#include <android/log.h> #include <android/log.h>
#include <assert.h> #include <assert.h>
...@@ -33,7 +34,7 @@ ...@@ -33,7 +34,7 @@
#include "NOMADVRLib/polyhedron.h" #include "NOMADVRLib/polyhedron.h"
#include "NOMADVRLib/IsosurfacesGL.h" #include "NOMADVRLib/IsosurfacesGL.h"
#define LOG_TAG "TreasureHuntCPP" #define LOG_TAG "NOMADgvrT"
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
...@@ -59,6 +60,8 @@ void eprintf( const char *fmt, ... ) ...@@ -59,6 +60,8 @@ void eprintf( const char *fmt, ... )
if (*fmt=='\0') if (*fmt=='\0')
LOGD("Empty format"); LOGD("Empty format");
LOGD("<%s>", buffer); LOGD("<%s>", buffer);
//rgh: does not work yet
//DisplayMessage(buffer);
} }
...@@ -305,13 +308,8 @@ static float VectorInnerProduct(const std::array<float, 4>& vect1, ...@@ -305,13 +308,8 @@ static float VectorInnerProduct(const std::array<float, 4>& vect1,
} }
} // anonymous namespace } // anonymous namespace
TreasureHuntRenderer::TreasureHuntRenderer( void TreasureHuntRenderer::loadConfigFile(void)
gvr_context* gvr_context, std::unique_ptr<gvr::AudioApi> gvr_audio_api) {
: gvr_api_(gvr::GvrApi::WrapNonOwned(gvr_context)),
scratch_viewport_(gvr_api_->CreateBufferViewport()),
gvr_controller_api_(nullptr),
gvr_viewer_type_(gvr_api_->GetViewerType()) {
if (configPath!=nullptr) if (configPath!=nullptr)
eprintf ("configPath=<%s>", configPath); eprintf ("configPath=<%s>", configPath);
else else
...@@ -326,7 +324,7 @@ TreasureHuntRenderer::TreasureHuntRenderer( ...@@ -326,7 +324,7 @@ TreasureHuntRenderer::TreasureHuntRenderer(
chdir(s.substr(0, s.find_last_of("\\/")).c_str()); chdir(s.substr(0, s.find_last_of("\\/")).c_str());
if ((error=loadConfigFile(configPath))<0) { if ((error=::loadConfigFile(configPath))<0) {
if (-100<error) { if (-100<error) {
eprintf(loadConfigFileErrors[-error]); eprintf(loadConfigFileErrors[-error]);
eprintf("Config file reading error"); eprintf("Config file reading error");
...@@ -345,7 +343,17 @@ TreasureHuntRenderer::TreasureHuntRenderer( ...@@ -345,7 +343,17 @@ TreasureHuntRenderer::TreasureHuntRenderer(
LOGD("No atom glyph specified, using Icosahedron"); LOGD("No atom glyph specified, using Icosahedron");
solid=new Solid(Solid::Type::Icosahedron); solid=new Solid(Solid::Type::Icosahedron);
} }
eprintf("after config load, timesteps=%d", TIMESTEPS); }
TreasureHuntRenderer::TreasureHuntRenderer(
gvr_context* gvr_context, std::unique_ptr<gvr::AudioApi> gvr_audio_api)
: gvr_api_(gvr::GvrApi::WrapNonOwned(gvr_context)),
scratch_viewport_(gvr_api_->CreateBufferViewport()),
gvr_controller_api_(nullptr),
gvr_viewer_type_(gvr_api_->GetViewerType()) {
loadConfigFile();
//eprintf("after config load, timesteps=%d", TIMESTEPS);
ResumeControllerApiAsNeeded(); ResumeControllerApiAsNeeded();
if (gvr_viewer_type_ == GVR_VIEWER_TYPE_CARDBOARD) { if (gvr_viewer_type_ == GVR_VIEWER_TYPE_CARDBOARD) {
...@@ -374,6 +382,7 @@ void TreasureHuntRenderer::InitializeGl() { ...@@ -374,6 +382,7 @@ void TreasureHuntRenderer::InitializeGl() {
gvr_api_->InitializeGl(); gvr_api_->InitializeGl();
glGenTextures(2, textures); glGenTextures(2, textures);
glGenTextures(2+ZLAYERS, textDepthPeeling);
//white //white
unsigned char data2[4]={255,255,255,255}; //white texture for non-textured meshes unsigned char data2[4]={255,255,255,255}; //white texture for non-textured meshes
glBindTexture(GL_TEXTURE_2D, textures[0]); glBindTexture(GL_TEXTURE_2D, textures[0]);
...@@ -409,7 +418,7 @@ glGenTextures(2, textures); ...@@ -409,7 +418,7 @@ glGenTextures(2, textures);
error=-403; error=-403;
} }
e=SetupAtoms(&AtomTVAO, &AtomTBuffer); e=SetupAtoms(&AtomTVAO, &AtomTBuffer, &BondIndices);
if (e!=GL_NO_ERROR) { if (e!=GL_NO_ERROR) {
eprintf ("SetupAtoms error %d", e); eprintf ("SetupAtoms error %d", e);
error=-404; error=-404;
...@@ -428,8 +437,50 @@ glGenTextures(2, textures); ...@@ -428,8 +437,50 @@ glGenTextures(2, textures);
error=-406; error=-406;
} }
// Because we are using 2X MSAA, we can render to half as many pixels and
// achieve similar quality.
render_size_ =
HalfPixelCount(gvr_api_->GetMaximumEffectiveRenderTargetSize());
std::vector<gvr::BufferSpec> specs;
specs.push_back(gvr_api_->CreateBufferSpec());
specs[0].SetColorFormat(GVR_COLOR_FORMAT_RGBA_8888);
specs[0].SetDepthStencilFormat(GVR_DEPTH_STENCIL_FORMAT_DEPTH_16);
specs[0].SetSize(render_size_);
specs[0].SetSamples(2);
swapchain_.reset(new gvr::SwapChain(gvr_api_->CreateSwapChain(specs)));
viewport_list_.reset(
new gvr::BufferViewportList(gvr_api_->CreateEmptyBufferViewportList()));
//isosurfaces //isosurfaces
if (ISOS) { if (ISOS) {
//rgh: FIXME Additive blending for android; do not need most of these textures
//additive blending means white background makes everything white
float m=BACKGROUND[0];
m=std::max(m, BACKGROUND[1]);
m=std::max(m, BACKGROUND[2]);
if (m>0.2f) { //make background darker, preserving colour, so additive blending works
for (int i=0;i<3;i++)
BACKGROUND[i]*=0.2f / m;
}
e=SetupDepthPeeling(render_size_.width, render_size_.height, ZLAYERS,
textDepthPeeling, &peelingFramebuffer);
if (!e) {
eprintf("Error setting up DepthPeeling\n");
error=-407;
}
if (GL_NO_ERROR!=(e=PrepareISOTransShader (&TransP,
&TransMatrixLoc, &BlendP)))
{
eprintf( "Error Preparing Transparency shader, %d\n", e );
error=-408;
}
SetupBlending(&BlendVAO, &BlendBuffer, &BlendIndices);
PrepareISOShader(&ISOP, &ISOMatrixLoc); PrepareISOShader(&ISOP, &ISOMatrixLoc);
std::vector<float> vertices; std::vector<float> vertices;
...@@ -501,28 +552,13 @@ glGenTextures(2, textures); ...@@ -501,28 +552,13 @@ glGenTextures(2, textures);
indices.clear(); indices.clear();
if (p % ISOS == ISOS - 1) { if (p % ISOS == ISOS - 1) {
eprintf ("timestep %d", timestep); //eprintf ("timestep %d", timestep);
timestep++; timestep++;
} }
} }
} }
// Because we are using 2X MSAA, we can render to half as many pixels and
// achieve similar quality.
render_size_ =
HalfPixelCount(gvr_api_->GetMaximumEffectiveRenderTargetSize());
std::vector<gvr::BufferSpec> specs;
specs.push_back(gvr_api_->CreateBufferSpec());
specs[0].SetColorFormat(GVR_COLOR_FORMAT_RGBA_8888);
specs[0].SetDepthStencilFormat(GVR_DEPTH_STENCIL_FORMAT_DEPTH_16);
specs[0].SetSize(render_size_);
specs[0].SetSamples(2);
swapchain_.reset(new gvr::SwapChain(gvr_api_->CreateSwapChain(specs)));
viewport_list_.reset(
new gvr::BufferViewportList(gvr_api_->CreateEmptyBufferViewportList()));
} }
...@@ -621,6 +657,7 @@ if (animateTimesteps) { ...@@ -621,6 +657,7 @@ if (animateTimesteps) {
// Draw the world. // Draw the world.
frame.BindBuffer(0); frame.BindBuffer(0);
if (error<0) { if (error<0) {
//rgh: FIXME, add textures with messages here
if (-100<error) { if (-100<error) {
glClearColor(1.f, 0.f, 0.f, 1.f); glClearColor(1.f, 0.f, 0.f, 1.f);
} else if (-200<error){ } else if (-200<error){
...@@ -633,7 +670,7 @@ if (animateTimesteps) { ...@@ -633,7 +670,7 @@ if (animateTimesteps) {
glClearColor(1.f, 0.f, 1.f, 1.f); glClearColor(1.f, 0.f, 1.f, 1.f);
} }
} else { } else {
glClearColor(BACKGROUND[0], BACKGROUND[1], BACKGROUND[2], 0.5f); glClearColor(BACKGROUND[0], BACKGROUND[1], BACKGROUND[2], 1.f);
} }
// Dark background so text shows up. // Dark background so text shows up.
...@@ -764,10 +801,10 @@ for (int i=0;i<4;i++) ...@@ -764,10 +801,10 @@ for (int i=0;i<4;i++)
t[j*4+i]=transform.m[i][j]; t[j*4+i]=transform.m[i][j];
glUseProgram(ISOP); glUseProgram(ISOP);
if ((e = glGetError()) != GL_NO_ERROR) if ((e = glGetError()) != GL_NO_ERROR)
eprintf("1 Gl error RenderIsos timestep =%d: %d\n", currentSet, e); eprintf("1 Gl error RenderIsos timestep =%d: %d\n", currentSet, e);
glUniformMatrix4fv(ISOMatrixLoc, 1, GL_FALSE, t); glUniformMatrix4fv(ISOMatrixLoc, 1, GL_FALSE, t);
if ((e = glGetError()) != GL_NO_ERROR) if ((e = glGetError()) != GL_NO_ERROR)
eprintf("2 Gl error RenderIsos timestep =%d: %d\n", currentSet, e); eprintf("2 Gl error RenderIsos timestep =%d: %d\n", currentSet, e);
if (curDataPos!=ISOS) { if (curDataPos!=ISOS) {
...@@ -779,31 +816,58 @@ if (curDataPos!=ISOS) { ...@@ -779,31 +816,58 @@ if (curDataPos!=ISOS) {
if ((e = glGetError()) != GL_NO_ERROR) if ((e = glGetError()) != GL_NO_ERROR)
eprintf("4 Gl error RenderIsos timestep =%d: %d\n", currentSet, e); eprintf("4 Gl error RenderIsos timestep =%d: %d\n", currentSet, e);
} else { } else {
//transparency; FIXME disabled as I get 1fps, with screen in 4 columns and z-check is incorrect
/*
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
//do depth peeling
CleanDepthTexture(textDepthPeeling[0], render_size_.width, render_size_.height);
GLint dfb;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &dfb);
if ((e = glGetError()) != GL_NO_ERROR)
eprintf("Gl error RenderIsos, before zl loop: %d\n", e);
for (int zl = 0; zl < ZLAYERS; zl++) {
EnableDepthFB(zl, TransP,
peelingFramebuffer, textDepthPeeling);
glUniformMatrix4fv(TransMatrixLoc, 1, GL_FALSE, t);
for (int i=0;i<ISOS;i++) {
glBindVertexArray(ISOVAO[currentSet*ISOS+i]);
glDrawElements(GL_TRIANGLES,numISOIndices[currentSet*ISOS+i] , GL_UNSIGNED_INT, 0);
}
}
glUseProgram(BlendP);
glBindFramebuffer(GL_FRAMEBUFFER, dfb);
glBindVertexArray(BlendVAO);
if ((e = glGetError()) != GL_NO_ERROR)
eprintf("Gl error RenderIsos, after glBindVertexArray: %d\n", e);
BlendTextures(textDepthPeeling, ZLAYERS);
glBindVertexArray(0);
if ((e = glGetError()) != GL_NO_ERROR)
eprintf("Gl error RenderIsos, after BlendTextures: %d\n", e);*/
/* no transparency*/
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glDepthMask(GL_FALSE);
for (int i=0;i<ISOS;i++) { for (int i=0;i<ISOS;i++) {
glBindVertexArray(ISOVAO[currentSet*ISOS+i]); glBindVertexArray(ISOVAO[currentSet*ISOS+i]);
glBindBuffer(GL_ARRAY_BUFFER, ISOBuffer[currentSet*ISOS+i]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ISOIndices[currentSet*ISOS+i]);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 10*sizeof(float), (const void *)(0*sizeof(float)));
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 10*sizeof(float), (const void *)(3*sizeof(float)));
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 10*sizeof(float), (const void *)(6*sizeof(float)));
if ((e = glGetError()) != GL_NO_ERROR) if ((e = glGetError()) != GL_NO_ERROR)
eprintf("5 Gl error RenderIsos timestep =%d: %d\n", currentSet, e); eprintf("5 Gl error RenderIsos timestep =%d: %d\n", currentSet, e);
eprintf ("Drawing %d vertices, isos", numISOIndices[currentSet*ISOS+i]); eprintf ("Drawing %d vertices, isos", numISOIndices[currentSet*ISOS+i]);
glDrawElements(GL_TRIANGLES,numISOIndices[currentSet*ISOS+i] , GL_UNSIGNED_INT, 0); glDrawElements(GL_TRIANGLES,numISOIndices[currentSet*ISOS+i] , GL_UNSIGNED_INT, 0);
if ((e = glGetError()) != GL_NO_ERROR) if ((e = glGetError()) != GL_NO_ERROR)
eprintf("6 Gl error RenderIsos timestep =%d: %d\n", currentSet, e); eprintf("6 Gl error RenderIsos timestep =%d: %d\n", currentSet, e);
} }
} glDisable(GL_BLEND);
} //if (curDataPos!=ISOS)
//eprintf ("end of RenderIsos");
glBindVertexArray(0);
} }
void TreasureHuntRenderer::RenderAtoms(const float *m) //m[16] void TreasureHuntRenderer::RenderAtoms(const float *m) //m[16]
{ {
//return; //return;
eprintf ("RenderAtoms start numatoms %d, timestep %d", numAtoms[currentSet], currentSet); //eprintf ("RenderAtoms start numatoms %d, timestep %d", numAtoms[currentSet], currentSet);
eprintf ("solid nfaces %d", solid->nFaces); //eprintf ("solid nfaces %d", solid->nFaces);
int e; int e;
if (numAtoms==0) if (numAtoms==0)
return; return;
...@@ -977,7 +1041,7 @@ void TreasureHuntRenderer::RenderUnitCell(const gvr::Mat4f eyeViewProjection) ...@@ -977,7 +1041,7 @@ void TreasureHuntRenderer::RenderUnitCell(const gvr::Mat4f 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++)