/* * Copyright 1993-2015 NVIDIA Corporation. All rights reserved. * * Please refer to the NVIDIA end user license agreement (EULA) associated * with this source code for terms and conditions that govern your use of * this software. Any use, reproduction, disclosure, or distribution of * this software and related documentation outside the terms of the EULA * is strictly prohibited. * */ // OpenGL Graphics includes #define HELPERGL_EXTERN_GL_FUNC_IMPLEMENTATION #include #include "particleSystem.h" #include "particleSystem.cuh" #include "particles_kernel.cuh" #include #include #include #include #include #include #include #include #include #ifndef CUDART_PI_F #define CUDART_PI_F 3.141592654f #endif ParticleSystem::ParticleSystem(uint numParticles, uint3 gridSize, bool bUseOpenGL) : m_bInitialized(false), m_bUseOpenGL(bUseOpenGL), m_numParticles(numParticles), m_hPos(0), m_hVel(0), m_dPos(0), m_dVel(0), m_gridSize(gridSize), m_timer(NULL), m_solverIterations(1) { m_numGridCells = m_gridSize.x*m_gridSize.y*m_gridSize.z; // float3 worldSize = make_float3(2.0f, 2.0f, 2.0f); m_gridSortBits = 18; // increase this for larger grids // set simulation parameters m_params.gridSize = m_gridSize; m_params.numCells = m_numGridCells; m_params.numBodies = m_numParticles; m_params.particleRadius = 1.0f / 64.0f; m_params.colliderPos = make_float3(-1.2f, -0.8f, 0.8f); m_params.colliderRadius = 0.2f; m_params.worldOrigin = make_float3(-1.0f, -1.0f, -1.0f); // m_params.cellSize = make_float3(worldSize.x / m_gridSize.x, worldSize.y / m_gridSize.y, worldSize.z / m_gridSize.z); float cellSize = m_params.particleRadius * 2.0f; // cell size equal to particle diameter m_params.cellSize = make_float3(cellSize, cellSize, cellSize); m_params.spring = 0.5f; m_params.damping = 0.02f; m_params.shear = 0.1f; m_params.attraction = 0.0f; m_params.boundaryDamping = -0.5f; m_params.gravity = make_float3(0.0f, -0.0003f, 0.0f); m_params.globalDamping = 1.0f; _initialize(numParticles); } ParticleSystem::~ParticleSystem() { _finalize(); m_numParticles = 0; } uint ParticleSystem::createVBO(uint size) { GLuint vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); return vbo; } inline float lerp(float a, float b, float t) { return a + t*(b-a); } // create a color ramp void colorRamp(float t, float *r) { const int ncolors = 7; float c[ncolors][3] = { { 1.0, 0.0, 0.0, }, { 1.0, 0.5, 0.0, }, { 1.0, 1.0, 0.0, }, { 0.0, 1.0, 0.0, }, { 0.0, 1.0, 1.0, }, { 0.0, 0.0, 1.0, }, { 1.0, 0.0, 1.0, }, }; t = t * (ncolors-1); int i = (int) t; float u = t - floorf(t); r[0] = lerp(c[i][0], c[i+1][0], u); r[1] = lerp(c[i][1], c[i+1][1], u); r[2] = lerp(c[i][2], c[i+1][2], u); } void ParticleSystem::_initialize(int numParticles) { assert(!m_bInitialized); m_numParticles = numParticles; // allocate host storage m_hPos = new float[m_numParticles*4]; m_hVel = new float[m_numParticles*4]; memset(m_hPos, 0, m_numParticles*4*sizeof(float)); memset(m_hVel, 0, m_numParticles*4*sizeof(float)); m_hCellStart = new uint[m_numGridCells]; memset(m_hCellStart, 0, m_numGridCells*sizeof(uint)); m_hCellEnd = new uint[m_numGridCells]; memset(m_hCellEnd, 0, m_numGridCells*sizeof(uint)); // allocate GPU data unsigned int memSize = sizeof(float) * 4 * m_numParticles; if (m_bUseOpenGL) { m_posVbo = createVBO(memSize); registerGLBufferObject(m_posVbo, &m_cuda_posvbo_resource); } else { checkCudaErrors(cudaMalloc((void **)&m_cudaPosVBO, memSize)) ; } allocateArray((void **)&m_dVel, memSize); allocateArray((void **)&m_dSortedPos, memSize); allocateArray((void **)&m_dSortedVel, memSize); allocateArray((void **)&m_dGridParticleHash, m_numParticles*sizeof(uint)); allocateArray((void **)&m_dGridParticleIndex, m_numParticles*sizeof(uint)); allocateArray((void **)&m_dCellStart, m_numGridCells*sizeof(uint)); allocateArray((void **)&m_dCellEnd, m_numGridCells*sizeof(uint)); if (m_bUseOpenGL) { m_colorVBO = createVBO(m_numParticles*4*sizeof(float)); registerGLBufferObject(m_colorVBO, &m_cuda_colorvbo_resource); // fill color buffer glBindBuffer(GL_ARRAY_BUFFER, m_colorVBO); float *data = (float *) glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); float *ptr = data; for (uint i=0; i maxCellSize) { maxCellSize = cellSize; } } } printf("maximum particles per cell = %d\n", maxCellSize); } void ParticleSystem::dumpParticles(uint start, uint count) { // debug copyArrayFromDevice(m_hPos, 0, &m_cuda_posvbo_resource, sizeof(float)*4*count); copyArrayFromDevice(m_hVel, m_dVel, 0, sizeof(float)*4*count); for (uint i=start; i