diff --git a/src/display.c b/src/display.c index 3935dc1a0..dd9a44176 100644 --- a/src/display.c +++ b/src/display.c @@ -379,6 +379,9 @@ static void reb_display_cursor(GLFWwindow* window, double x, double y){ } } +#define history_vertex_count 100 +#define xstr(s) ystr(s) +#define ystr(s) #s static void reb_display_clear_history_data(struct reb_vec3d_opengl* history_data, int N){ if (history_data){ float n = NAN; @@ -468,7 +471,7 @@ void reb_display_keyboard(GLFWwindow* window, int key, int scancode, int action, data->wire = (data->wire+1)%2; break; case 'C': - reb_display_clear_history_data(data->history_data, data->history_shader_vertex_count*data->N_allocated); + reb_display_clear_history_data(data->history_data, history_vertex_count*data->N_allocated); break; case 'P': data->past = (data->past+1)%2; @@ -542,19 +545,23 @@ void reb_render_frame(void* p){ // prepare data (incl orbit calculation) const int N_real = r_copy->N - r_copy->N_var; + + if ((data->history_data && N_real > data->N_allocated) || (!data->history_data && data->past)){ + // Only allocate history when first enabled + data->history_data = realloc(data->history_data, history_vertex_count*N_real*sizeof(struct reb_vec3d_opengl)); + reb_display_clear_history_data(data->history_data, history_vertex_count*N_real); + glBindBuffer(GL_ARRAY_BUFFER, data->history_buffer); + glBufferData(GL_ARRAY_BUFFER, history_vertex_count*N_real*sizeof(struct reb_vec3d_opengl), NULL, GL_STATIC_DRAW); + } if (N_real > data->N_allocated){ data->N_allocated = N_real; data->particle_data = realloc(data->particle_data, data->N_allocated*sizeof(struct reb_particle_opengl)); data->orbit_data = realloc(data->orbit_data, data->N_allocated*sizeof(struct reb_orbit_opengl)); - data->history_data = realloc(data->history_data, data->history_shader_vertex_count*data->N_allocated*sizeof(struct reb_vec3d_opengl)); - reb_display_clear_history_data(data->history_data, data->history_shader_vertex_count*data->N_allocated); // Resize memory if needed glBindBuffer(GL_ARRAY_BUFFER, data->particle_buffer); glBufferData(GL_ARRAY_BUFFER, data->N_allocated*sizeof(struct reb_particle_opengl), NULL, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, data->orbit_buffer); glBufferData(GL_ARRAY_BUFFER, data->N_allocated*sizeof(struct reb_orbit_opengl), NULL, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, data->history_buffer); - glBufferData(GL_ARRAY_BUFFER, data->history_shader_vertex_count*data->N_allocated*sizeof(struct reb_vec3d_opengl), NULL, GL_STATIC_DRAW); } // this only does something for WHFAST @@ -570,18 +577,20 @@ void reb_render_frame(void* p){ data->particle_data[i].vy = (float)p.vy; data->particle_data[i].vz = (float)p.vz; data->particle_data[i].r = (float)p.r; - unsigned int k = data->history_shader_current_vertex + data->history_shader_vertex_count * i; - data->history_data[k].x = (float)p.x; - data->history_data[k].y = (float)p.y; - data->history_data[k].z = (float)p.z; + if (data->history_data){ + unsigned int k = data->history_shader_current_vertex + history_vertex_count * i; + data->history_data[k].x = (float)p.x; + data->history_data[k].y = (float)p.y; + data->history_data[k].z = (float)p.z; + } } if (r->steps_done != data->history_last_steps_done){ if (r->steps_done < data->history_last_steps_done){ // Something strange is happening. New simulation? - reb_display_clear_history_data(data->history_data, data->history_shader_vertex_count*data->N_allocated); + reb_display_clear_history_data(data->history_data, history_vertex_count*data->N_allocated); } data->history_last_steps_done = r->steps_done; - data->history_shader_current_vertex = (data->history_shader_current_vertex+1) % data->history_shader_vertex_count; + data->history_shader_current_vertex = (data->history_shader_current_vertex+1) % history_vertex_count; } if (data->wire && N_real>1){ @@ -609,9 +618,9 @@ void reb_render_frame(void* p){ glBindBuffer(GL_ARRAY_BUFFER, data->orbit_buffer); glBufferSubData(GL_ARRAY_BUFFER, 0, (N_real-1)*sizeof(struct reb_orbit_opengl), data->orbit_data); } - if (data->past){ + if (data->history_data && data->past){ glBindBuffer(GL_ARRAY_BUFFER, data->history_buffer); - glBufferSubData(GL_ARRAY_BUFFER, 0, data->history_shader_vertex_count*data->N_allocated*sizeof(struct reb_vec3d_opengl), data->history_data); + glBufferSubData(GL_ARRAY_BUFFER, 0, history_vertex_count*data->N_allocated*sizeof(struct reb_vec3d_opengl), data->history_data); } } @@ -679,13 +688,13 @@ void reb_render_frame(void* p){ reb_glDrawArraysInstanced(GL_LINE_STRIP, 0, data->orbit_shader_vertex_count, N_real-1); glBindVertexArray(0); } - if (data->past==1){ + if (data->past==1 && data->history_data){ // History glUseProgram(data->history_shader_program); glBindVertexArray(data->history_shader_particle_vao); glUniformMatrix4fv(data->history_shader_mvp_location, 1, GL_TRUE, (GLfloat*) tmp2); glUniform1i(data->history_shader_current_vertex_location, data->history_shader_current_vertex); - glDrawArrays(GL_POINTS, 0, data->history_shader_vertex_count* N_real); + glDrawArrays(GL_POINTS, 0, history_vertex_count* N_real); glBindVertexArray(0); } } @@ -1175,7 +1184,7 @@ void reb_display_init(struct reb_simulation * const r){ "void main() {\n" " gl_Position = mvp*vec4(vp, 1.0);\n" " gl_PointSize = 15.0f;\n" - " float age = float((500-current_vertex+gl_VertexID)%500)/500.0;\n" + " float age = float((" xstr(history_vertex_count) "-current_vertex+gl_VertexID)%" xstr(history_vertex_count) ")/" xstr(history_vertex_count) ".0;\n" " color = vec4(1.0,1.,1.,age*0.8);\n" "}\n"; const char* fragment_shader = @@ -1406,7 +1415,6 @@ void reb_display_init(struct reb_simulation * const r){ glEnableVertexAttribArray(hvp); data->history_shader_current_vertex = 0; - data->history_shader_vertex_count = 500; GLuint horbit_buffer; glGenBuffers(1, &horbit_buffer); @@ -1443,10 +1451,12 @@ void reb_display_init(struct reb_simulation * const r){ data->N_allocated = 0; free(data->particle_data); free(data->orbit_data); - free(data->history_data); data->particle_data = NULL; data->orbit_data = NULL; - data->history_data = NULL; + if (data->history_data){ + free(data->history_data); + data->history_data = NULL; + } } glfwTerminate(); #endif diff --git a/src/rebound.h b/src/rebound.h index d9a314b3f..6214b0c4a 100644 --- a/src/rebound.h +++ b/src/rebound.h @@ -1159,7 +1159,6 @@ struct reb_display_data { unsigned int history_shader_current_vertex_location; unsigned int history_shader_program; unsigned int history_shader_particle_vao; - unsigned int history_shader_vertex_count; unsigned int history_shader_current_vertex; uint64_t history_last_steps_done; unsigned int particle_buffer;