void GeometryCollisionParticleSystemAffector::affect(ParticleSystemRefPtr System, const Time& elps) { UInt32 NumParticles(System->getNumParticles()); Line ray; IntersectAction *iAct = IntersectAction::create(); Pnt3f ParticlePos, ParticleSecPos; Real32 HitT(0.0f); for(UInt32 i(0) ; i<NumParticles ; ++i) { ParticlePos = System->getPosition(i); ParticleSecPos = System->getSecPosition(i); ray.setValue(ParticleSecPos, ParticlePos); iAct->setLine(ray); iAct->apply(getCollisionNode()); if (iAct->didHit()) { HitT = iAct->getHitT(); if(HitT > 0.0f && HitT*HitT<ParticlePos.dist2(ParticleSecPos)) { produceParticleCollision(System, i, iAct); for(UInt32 j(0) ; j<getMFCollisionAffectors()->size(); ++j) { getCollisionAffectors(i)->affect(System,i,elps); } } } } }
void CSheetSimulator::Init( int w, int h, int fixedPointCount ) { m_ControlPointOffset.Init( 0, 0, 0 ); m_HorizontalCount = w; m_VerticalCount = h; m_Particle = new Particle_t[w * h]; m_FixedPointCount = fixedPointCount; if (fixedPointCount) { m_pFixedPoint = new Vector[fixedPointCount]; m_ControlPoints = new Vector[fixedPointCount]; m_pCollisionPlanes = new cplane_t[fixedPointCount]; m_pValidCollisionPlane = new bool[fixedPointCount]; } // Initialize distances and such m_Origin = Vector(0, 0, 0); for ( int i = 0; i < NumParticles(); ++i ) { m_Particle[i].m_Mass = 1.0f; m_Particle[i].m_Collided = false; m_Particle[i].m_Position = Vector(0,0,0); m_Particle[i].m_Velocity = Vector(0,0,0); } }
void Update(Scene* scene, float dt) { Particle* particles = &scene->mParticles[0]; Triangle* triangles = &scene->mTriangles[0]; Element* elements = &scene->mElements[0]; const Vec3* planes = &scene->mPlanes[0]; uint32_t numParticles = NumParticles(scene); uint32_t numTriangles = NumTriangles(scene); uint32_t numPlanes = scene->mPlanes.size(); SceneParams params = scene->mParams; FractureEvent* fractures = &scene->mFractures[0]; uint32_t maxFractures = scene->mFractures.size(); uint32_t numFractures = UpdateForces(particles, numParticles, triangles, elements, numTriangles, params.mGravity, params.mLameLambda, params.mLameMu, params.mDamping, params.mDrag, dt, fractures, maxFractures, params.mToughness, params.mYield, params.mCreep); CollidePlanes(particles, numParticles, planes, numPlanes, params.mFriction); IntegrateForces(particles, numParticles, dt); //if (numFractures) // cout << "numFractures: " << numFractures << endl; // todo. ugh figure out a better way to manage this scene->mParticles.resize(2*numParticles); particles = &scene->mParticles[0]; /* glColor3f(1.0f, 0.0f, 0.0f); glBegin(GL_LINES); for (size_t i=0; i < numFractures; ++i) { Vec2 p = Vec2(fractures[i].mPlane)*-fractures[i].mPlane.z; Vec2 n = PerpCCW(Vec2(fractures[i].mPlane)); glVertex2fv(p+n*100.0f); glVertex2fv(p-n*100.0f); glVertex2fv(p); glVertex2fv(p + Vec2(fractures[i].mPlane)); } glEnd(); */ if (params.mToughness > 0.0f) { numParticles = Fracture(particles, numParticles, triangles, numTriangles, fractures, numFractures); numParticles = SeparateSingular(particles, numParticles, triangles, numTriangles); } scene->mParticles.resize(numParticles); particles = &scene->mParticles[0]; }
void CSheetSimulator::ClearForces() { int i; for ( i = 0; i < NumParticles(); ++i) { m_Particle[i].m_Force = Vector(0,0,0); } }
void CSheetSimulator::ComputeBounds( Vector& mins, Vector& maxs ) { VectorCopy( m_Particle[0].m_Position, mins ); VectorCopy( m_Particle[0].m_Position, maxs ); for (int i = 1; i < NumParticles(); ++i) { VectorMin( mins, m_Particle[i].m_Position, mins ); VectorMax( maxs, m_Particle[i].m_Position, maxs ); } mins -= m_Origin; maxs -= m_Origin; }
void CSheetSimulator::SetPosition( const Vector& origin, const QAngle& angles ) { // FIXME: Need a better metric for position reset if (m_Origin.DistToSqr(origin) > 1e3) { for ( int i = 0; i < NumParticles(); ++i ) { m_Particle[i].m_Position = origin; m_Particle[i].m_Velocity = Vector(0,0,0); } } m_Origin = origin; m_Angles = angles; ComputeControlPoints(); }
void CSheetSimulator::SatisfyCollisionConstraints() { // Eliminate velocity perp to a collision plane for ( int i = 0; i < NumParticles(); ++i ) { // The actual collision plane if (m_Particle[i].m_CollisionPlane >= 0) { cplane_t* pPlane = &m_pCollisionPlanes[m_Particle[i].m_CollisionPlane]; // Fix up position so it lies on the plane Vector delta = m_Particle[i].m_Position - m_Origin; m_Particle[i].m_Position = m_Origin + delta * m_Particle[i].m_CollisionDist; float perp = DotProduct( m_Particle[i].m_Velocity, pPlane->normal ); if (perp < 0) m_Particle[i].m_Velocity -= pPlane->normal * perp; } } }
// Iterative collision detection void CIterativeSheetSimulator::DetectCollisions( void ) { for ( int i = 0; i < m_CollisionCount; ++i ) { if (m_InitialPass) { InitPosition( m_CurrentCollisionPt ); } else { float flOffset = COLLISION_PLANE_OFFSET * ( (float)(m_SimulationSteps - 1) / (float)(m_TotalSteps - 1) ); DetectCollision( m_CurrentCollisionPt, flOffset ); } if (++m_CurrentCollisionPt >= NumParticles()) { m_CurrentCollisionPt = -1; m_InitialPass = false; break; } } }
void CSheetSimulator::ClampPointsToCollisionPlanes() { // Find collision planes to clamp to DetermineBestCollisionPlane( false ); // Eliminate velocity perp to a collision plane for ( int i = 0; i < NumParticles(); ++i ) { // The actual collision plane if (m_Particle[i].m_CollisionPlane >= 0) { cplane_t* pPlane = &m_pCollisionPlanes[m_Particle[i].m_CollisionPlane]; // Make sure we have a close enough perpendicular distance to the plane... float flPerpDist = fabs ( DotProduct( m_Particle[i].m_Position, pPlane->normal ) - pPlane->dist ); if (flPerpDist >= CLAMP_DIST) continue; // Drop it along the perp VectorMA( m_Particle[i].m_Position, -flPerpDist, pPlane->normal, m_Particle[i].m_Position ); } } }
void CSheetSimulator::EulerStep( float dt ) { ClearForces(); ComputeForces(); // Update positions and velocities for ( int i = 0; i < NumParticles(); ++i) { m_Particle[i].m_Position += m_Particle[i].m_Velocity * dt; m_Particle[i].m_Velocity += m_Particle[i].m_Force * dt / m_Particle[i].m_Mass; assert( _finite( m_Particle[i].m_Velocity.x ) && _finite( m_Particle[i].m_Velocity.y) && _finite( m_Particle[i].m_Velocity.z) ); // clamp for stability float lensq = m_Particle[i].m_Velocity.LengthSqr(); if (lensq > 1e6) { m_Particle[i].m_Velocity *= 1e3 / sqrt(lensq); } } SatisfyCollisionConstraints(); }
void CSheetSimulator::ComputeForces() { float springConstant; int i; for ( i = 0; i < m_Springs.Size(); ++i ) { // Hook's law for a damped spring: // got two particles, a and b with positions xa and xb and velocities va and vb // and l = xa - xb // fa = -( ks * (|l| - r) + kd * (va - vb) dot (l) / |l|) * l/|l| Vector dx, dv, force; if (m_Springs[i].m_Particle2 < 0) { // Case where we're connected to a control point dx = m_Particle[m_Springs[i].m_Particle1].m_Position - m_ControlPoints[- m_Springs[i].m_Particle2 - 1]; dv = m_Particle[m_Springs[i].m_Particle1].m_Velocity; springConstant = m_FixedSpringConstant; } else { // Case where we're connected to another part of the shield dx = m_Particle[m_Springs[i].m_Particle1].m_Position - m_Particle[m_Springs[i].m_Particle2].m_Position; dv = m_Particle[m_Springs[i].m_Particle1].m_Velocity - m_Particle[m_Springs[i].m_Particle2].m_Velocity; springConstant = m_PointSpringConstant; } float length = dx.Length(); if (length < 1e-6) continue; dx /= length; float springfactor = springConstant * ( length - m_Springs[i].m_RestLength); float dampfactor = m_DampConstant * DotProduct( dv, dx ); force = dx * -( springfactor + dampfactor ); m_Particle[m_Springs[i].m_Particle1].m_Force += force; if (m_Springs[i].m_Particle2 >= 0) m_Particle[m_Springs[i].m_Particle2].m_Force -= force; assert( _finite( m_Particle[m_Springs[i].m_Particle1].m_Force.x ) && _finite( m_Particle[m_Springs[i].m_Particle1].m_Force.y) && _finite( m_Particle[m_Springs[i].m_Particle1].m_Force.z) ); } // gravity term for (i = 0; i < m_Gravity.Count(); ++i) { m_Particle[m_Gravity[i]].m_Force.z -= m_Particle[m_Gravity[i]].m_Mass * m_GravityConstant; } // viscous drag term for (i = 0; i < NumParticles(); ++i) { // Factor out bad forces for surface contact // Do this before the drag term otherwise the drag will be too large if ((m_Particle[i].m_CollisionPlane) >= 0) { const Vector& planeNormal = m_pCollisionPlanes[m_Particle[i].m_CollisionPlane].normal; float perp = DotProduct( m_Particle[i].m_Force, planeNormal ); if (perp < 0) m_Particle[i].m_Force -= planeNormal * perp; } Vector drag = m_Particle[i].m_Velocity * m_ViscousDrag; m_Particle[i].m_Force -= drag; } }
void GetParticles(const Scene* scene, Particle* dest) { if (!scene->mParticles.empty()) memcpy(dest, &scene->mParticles[0], sizeof(Particle)*NumParticles(scene)); }
void SetParticles(Scene* scene, const Particle* src) { scene->mParticles.assign(src, src+NumParticles(scene)); }
void ParticleInstancingRenderer::Render() { glPushAttrib(GL_ALL_ATTRIB_BITS); CheckOpenGLError(); const SphereGeometryVBO& level = *sphere_geometry_vbos[quality_level]; glUseProgram(program_instancing); CheckOpenGLError(); glValidateProgram(program_instancing); CheckOpenGLError(); glUniform1i(glGetUniformLocation(program_instancing,"per_instance_data_position_radius"), 0); CheckOpenGLError(); glUniform1i(glGetUniformLocation(program_instancing,"per_instance_data_attribute"), 1); CheckOpenGLError(); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, level.GetVBOIndices()); CheckOpenGLError(); glBindBuffer(GL_ARRAY_BUFFER, level.GetVBOVertices()); CheckOpenGLError(); glVertexPointer(2, GL_FLOAT, 0, 0); CheckOpenGLError(); glEnableClientState(GL_VERTEX_ARRAY); CheckOpenGLError(); const size_t total_number_of_instances = NumParticles(); const size_t number_of_batches = 1 + (total_number_of_instances - 1) / instanced_batch_size; for(size_t batch = 0, instances_remaining = total_number_of_instances; batch < number_of_batches; ++batch, instances_remaining -= instanced_batch_size) { size_t current_buffer = batch % 2; const size_t start_instance = batch * instanced_batch_size; const size_t instance_count = std::min(instances_remaining,instanced_batch_size); CopyParticleDataToGpuBuffers(start_instance, instance_count, tbo_position_radius_batches[current_buffer], tex_position_radius_batches[current_buffer], tbo_color_batches[current_buffer], tex_color_batches[current_buffer]); glActiveTexture(GL_TEXTURE0); CheckOpenGLError(); glBindTexture(GL_TEXTURE_BUFFER_ARB, tex_position_radius_batches[current_buffer]); CheckOpenGLError(); glActiveTexture(GL_TEXTURE1); CheckOpenGLError(); glBindTexture(GL_TEXTURE_BUFFER_ARB, tex_color_batches[current_buffer]); CheckOpenGLError(); glDrawElementsInstancedARB(GL_QUAD_STRIP, GLsizei(level.GetNumIndices()), GL_UNSIGNED_SHORT, 0, GLsizei(instance_count)); CheckOpenGLError(); } glDisableClientState(GL_VERTEX_ARRAY); CheckOpenGLError(); glBindBuffer(GL_ARRAY_BUFFER, 0); CheckOpenGLError(); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); CheckOpenGLError(); glActiveTexture(GL_TEXTURE1); CheckOpenGLError(); glBindTexture(GL_TEXTURE_BUFFER_ARB, 0); CheckOpenGLError(); glActiveTexture(GL_TEXTURE0); CheckOpenGLError(); glBindTexture(GL_TEXTURE_BUFFER_ARB, 0); CheckOpenGLError(); glUseProgram(0); CheckOpenGLError(); glPopAttrib(); CheckOpenGLError(); }
Action::ResultE LineParticleSystemDrawer::draw(DrawEnv *pEnv, ParticleSystemUnrecPtr System, const MFUInt32& Sort) { UInt32 NumParticles(System->getNumParticles()); bool areEndpointsFadeSame(getEndPointFading().x() == getEndPointFading().y()); Color4f Color; if(NumParticles != 0) { bool SeparateColors(System->getNumColors() > 1); bool SeparateSizes(System->getNumSizes() > 1); bool SeparateNormals(System->getNumNormals() > 1); glBegin(GL_LINES); //Colors if(!SeparateColors && areEndpointsFadeSame) { Color = System->getColor(0); glColor4f(Color.red(), Color.green(), Color.blue(), Color.alpha() * getEndPointFading().x()); } //Sizes if(!SeparateSizes) { //glColor4fv(System->getColor(0).getValuesRGBA()); } //Normals if(!SeparateNormals) { glNormal3fv(System->getNormal(0).getValues()); } for(UInt32 i(0) ; i<NumParticles ; ++i) { //Start Color if(SeparateColors) { Color = System->getColor(i); glColor4f(Color.red(), Color.green(), Color.blue(), Color.alpha() * getEndPointFading().x()); } else if(!SeparateColors && !areEndpointsFadeSame) { Color = System->getColor(0); glColor4f(Color.red(), Color.green(), Color.blue(), Color.alpha() * getEndPointFading().x()); } //Sizes if(SeparateSizes) { //glColor4fv(System->getColor(i).getValuesRGBA()); } //Normals if(SeparateNormals) { glNormal3fv(System->getNormal(i).getValues()); } //Positions glVertex3fv(System->getPosition(i).getValues()); //End Color if(SeparateColors && !areEndpointsFadeSame) { Color = System->getColor(i); glColor4f(Color.red(), Color.green(), Color.blue(), Color.alpha() * getEndPointFading().y()); } else if(!SeparateColors && !areEndpointsFadeSame) { Color = System->getColor(0); glColor4f(Color.red(), Color.green(), Color.blue(), Color.alpha() * getEndPointFading().y()); } glVertex3fv(getLineEndpoint(System, i).getValues()); } glEnd(); } return Action::Continue; }