/* * Copyright 1993-2006 NVIDIA Corporation. All rights reserved. * * NOTICE TO USER: * * This source code is subject to NVIDIA ownership rights under U.S. and * international Copyright laws. * * NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE * CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR * IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. * IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE * OR PERFORMANCE OF THIS SOURCE CODE. * * U.S. Government End Users. This source code is a "commercial item" as * that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of * "commercial computer software" and "commercial computer software * documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) * and is provided to the U.S. Government only as a commercial end item. * Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through * 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the * source code with only those rights set forth herein. */ #include #include #include #include #include #include "BMF_Api.h" #include "LinearMath/btQuickprof.h" #include "render_particles.h" #include "shaders.h" #ifndef M_PI #define M_PI 3.1415926535897932384626433832795 #endif ParticleRenderer::ParticleRenderer() : m_pos(0), m_numParticles(0), m_pointSize(1.0f), m_particleRadius(0.125f * 0.5f), m_program(0), m_vbo(0), m_colorVBO(0) { _initGL(); #ifndef BT_NO_PROFILE m_profileIterator = CProfileManager::Get_Iterator(); #endif //BT_NO_PROFILE } ParticleRenderer::~ParticleRenderer() { m_pos = 0; } void ParticleRenderer::setPositions(float *pos, int numParticles) { m_pos = pos; m_numParticles = numParticles; } void ParticleRenderer::setVertexBuffer(unsigned int vbo, int numParticles) { m_vbo = vbo; m_numParticles = numParticles; } void ParticleRenderer::_drawPoints() { if (!m_vbo) { glBegin(GL_POINTS); { int k = 0; for (int i = 0; i < m_numParticles; ++i) { glVertex3fv(&m_pos[k]); k += 4; } } glEnd(); } else { glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_vbo); glVertexPointer(4, GL_FLOAT, 0, 0); glEnableClientState(GL_VERTEX_ARRAY); if (m_colorVBO) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_colorVBO); glColorPointer(4, GL_FLOAT, 0, 0); glEnableClientState(GL_COLOR_ARRAY); } glDrawArrays(GL_POINTS, 0, m_numParticles); glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); } } void ParticleRenderer::display(DisplayMode mode /* = PARTICLE_POINTS */) { switch (mode) { case PARTICLE_POINTS: glColor3f(1, 1, 1); glPointSize(m_pointSize); _drawPoints(); break; default: case PARTICLE_SPHERES: glEnable(GL_POINT_SPRITE_ARB); glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE); glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_NV); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glUseProgram(m_program); glUniform1f( glGetUniformLocation(m_program, "pointScale"), m_window_h / tanf(m_fov*0.5f*(float)M_PI/180.0f) ); glUniform1f( glGetUniformLocation(m_program, "pointRadius"), m_particleRadius ); glColor3f(1, 1, 1); _drawPoints(); glUseProgram(0); glDisable(GL_POINT_SPRITE_ARB); break; } } GLuint ParticleRenderer::_compileProgram(const char *vsource, const char *fsource) { GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(vertexShader, 1, &vsource, 0); glShaderSource(fragmentShader, 1, &fsource, 0); glCompileShader(vertexShader); glCompileShader(fragmentShader); GLuint program = glCreateProgram(); glAttachShader(program, vertexShader); glAttachShader(program, fragmentShader); glLinkProgram(program); // check if program linked GLint success = 0; glGetProgramiv(program, GL_LINK_STATUS, &success); if (!success) { char temp[256]; glGetProgramInfoLog(program, 256, 0, temp); printf("Failed to link program:\n%s\n", temp); glDeleteProgram(program); program = 0; } return program; } void ParticleRenderer::_initGL() { m_program = _compileProgram(vertexShader, spherePixelShader); #if !defined(__APPLE__) && !defined(MACOSX) glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_FALSE); glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_FALSE); #endif } void ParticleRenderer::showProfileInfo(float& xOffset,float& yStart, float yIncr) { #ifndef BT_NO_PROFILE static double time_since_reset = 0.f; // if (!m_idle) { time_since_reset = CProfileManager::Get_Time_Since_Reset(); } beginWinCoords(); { //recompute profiling data, and store profile strings char blockTime[128]; double totalTime = 0; int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset(); m_profileIterator->First(); double parent_time = m_profileIterator->Is_Root() ? time_since_reset : m_profileIterator->Get_Current_Parent_Total_Time(); { sprintf(blockTime,"--- Profiling: %s (total running time: %.3f ms) ---", m_profileIterator->Get_Current_Parent_Name(), parent_time ); displayProfileString(xOffset,yStart,blockTime); yStart += yIncr; sprintf(blockTime,"press number (1,2...) to display child timings, or 0 to go up to parent" ); displayProfileString(xOffset,yStart,blockTime); yStart += yIncr; } double accumulated_time = 0.f; for (int i = 0; !m_profileIterator->Is_Done(); m_profileIterator->Next()) { double current_total_time = m_profileIterator->Get_Current_Total_Time(); accumulated_time += current_total_time; double fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f; sprintf(blockTime,"%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)", ++i, m_profileIterator->Get_Current_Name(), fraction, (current_total_time / (double)frames_since_reset),m_profileIterator->Get_Current_Total_Calls()); displayProfileString(xOffset,yStart,blockTime); yStart += yIncr; totalTime += current_total_time; } sprintf(blockTime,"%s (%.3f %%) :: %.3f ms", "Unaccounted", // (min(0, time_since_reset - totalTime) / time_since_reset) * 100); parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time); displayProfileString(xOffset,yStart,blockTime); yStart += yIncr; sprintf(blockTime,"-------------------------------------------------"); displayProfileString(xOffset,yStart,blockTime); yStart += yIncr; } endWinCoords(); #endif//BT_NO_PROFILE } void ParticleRenderer::displayProfileString(int xOffset,int yStart,char* message) { glRasterPos3f(xOffset,yStart,0); BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),message); }