void _remove(Particle *p) { Particles::iterator pos = std::find(particles.begin(), particles.end(), p); if(pos != particles.end()) { particles.erase(pos); } }
void System:: init_particles( Particles<Particle_T> & particles, size_t in, size_t out, int mass) { auto it(particles.begin()); auto end(particles.end()); for (size_t i = 0; it != end && i < in; ++it, ++i) { Point p = random_insphere(0, cell_.radius); it->x = cell_.x + p.x; it->y = cell_.y + p.y; it->z = cell_.z + p.z; it->mass = mass; cell_.put_inside(*it); } for (size_t i = 0; it != end && i < out; ++it, ++i) { Point p = random_insphere(cell_.radius, outer_limit_.radius); it->x = cell_.x + p.x; it->y = cell_.y + p.y; it->z = cell_.z + p.z; it->mass = mass; cell_.put_outside(*it); } }
void CnSymmAxisDetector::init_from_protein(const atom::Hierarchies &mhs) { //create a density map Particles ps; for (atom::Hierarchies::const_iterator it = mhs.begin(); it != mhs.end(); it++) { Particles temp_ps = core::get_leaves(*it); ps.insert(ps.end(),temp_ps.begin(),temp_ps.end()); } //TODO - check the number of particles!! IMP_NEW(em::SampledDensityMap,sampled_dmap,(ps,3.,1.)); sampled_dmap->resample(); sampled_dmap->calcRMS(); dmap_=new em::DensityMap(*(sampled_dmap->get_header())); dmap_->copy_map(sampled_dmap); statistics::Histogram hist = my_get_density_histogram(dmap_,dmap_->get_header()->dmin,100); double top_20_den_val = hist.get_top(0.8); vecs_ = em::density2vectors(dmap_,top_20_den_val); //calculate pca pca_= algebra::get_principal_components(vecs_); //calculate transformation from the native axes //system to the one defined by the pca from_native_ = algebra::get_rotation_from_x_y_axes( pca_.get_principal_component(0), pca_.get_principal_component(1)); to_native_ = from_native_.get_inverse(); sampled_dmap=nullptr; }
SecondaryStructureResidue setup_coarse_secondary_structure_residue( const Particles &ssr_ps, Model *mdl, bool winner_takes_all_per_res) { Floats scores; scores.push_back(0.0); scores.push_back(0.0); scores.push_back(0.0); int count = 0; for (Particles::const_iterator p = ssr_ps.begin(); p != ssr_ps.end(); ++p) { IMP_USAGE_CHECK(SecondaryStructureResidue::get_is_setup(*p), "all particles must be SecondaryStructureResidues"); SecondaryStructureResidue ssr(*p); Floats tmp_scores; tmp_scores.push_back(ssr.get_prob_helix()); tmp_scores.push_back(ssr.get_prob_strand()); tmp_scores.push_back(ssr.get_prob_coil()); int max_i = 0; Float max = 0.0; for (int i = 0; i < 3; i++) { if (tmp_scores[i] > max) { max = tmp_scores[i]; max_i = i; } if (!winner_takes_all_per_res) scores[i] += tmp_scores[i]; } if (winner_takes_all_per_res) scores[max_i] += 1.0; count++; } IMP_NEW(Particle, coarse_p, (mdl)); SecondaryStructureResidue ssres = SecondaryStructureResidue::setup_particle( coarse_p, scores[0] / count, scores[1] / count, scores[2] / count); return ssres; }
void ClearAllParticles(){ for (ParticlesIterator pIter = g_particles.begin(); pIter != g_particles.end(); ++pIter ) { Particle* p = *(pIter); if (p) { delete p; p = NULL; } } g_particles.clear(); }
void projectPositions() { for(Particles::iterator iter = particles.begin(); iter != particles.end(); ++iter) { Particle *p = *iter; p->p = p->x + p->v * PHYSICS_DT; } }
void MapModel::initGlobal(Particles& particles, double z, double roll, double pitch, const Vector6d& initNoise, UniformGeneratorT& rngUniform, NormalGeneratorT& rngNormal, double maxHeight, double minHeight){ //maxHeight added by LC double sizeX,sizeY,sizeZ, minX, minY, minZ; //LC: get total map size m_map->getMetricSize(sizeX,sizeY,sizeZ); //LC: get minimum values of map bounding box m_map->getMetricMin(minX, minY, minZ); double weight = 1.0 / particles.size(); Particles::iterator it = particles.begin(); while (true){ if (it == particles.end()) break; // obtain a pose hypothesis: double x = minX + sizeX * rngUniform(); double y = minY + sizeY * rngUniform(); std::vector<double> z_list; getHeightlist(x, y, minHeight, maxHeight,z_list); //LC: create a pose with random yaw orientation at (x,y) for every entry in the height list for (unsigned zIdx = 0; zIdx < z_list.size(); zIdx++){ if (it == particles.end()) break; // not needed => we already know that z contains valid poses // distance map: used distance from obstacles: //std::abs(node->getLogOdds()) < 0.1){ // if (!isOccupied(octomap::point3d(x, y, z[zIdx]))){ it->pose.getOrigin().setX(x); it->pose.getOrigin().setY(y); // TODO: sample z, roll, pitch it->pose.getOrigin().setZ(z_list.at(zIdx) + z + rngNormal() * initNoise(2)); //LC: create yaw orientation from -PI to +PI double yaw = rngUniform() * 2 * M_PI -M_PI; it->pose.setRotation(tf::createQuaternionFromRPY(roll, pitch, yaw)); it->weight = weight; it++; } } }
void removeFlagged() { for(Particles::iterator iter = removeList.begin(); iter != removeList.end(); ++iter) { Particle *p = *iter; _remove(p); } removeList.clear(); }
void unprojectVelocities() { for(Particles::iterator iter = particles.begin(); iter != particles.end(); ++iter) { Particle *p = *iter; p->v = (p->p - p->x)/PHYSICS_DT; p->x = p->p; } }
void MapModel::initGlobal(Particles& particles, const Vector6d& initPose, const Vector6d& initNoise, UniformGeneratorT& rngUniform, NormalGeneratorT& rngNormal){ double sizeX,sizeY,sizeZ, minX, minY, minZ; m_map->getMetricSize(sizeX,sizeY,sizeZ); m_map->getMetricMin(minX, minY, minZ); double weight = 1.0 / particles.size(); Particles::iterator it = particles.begin(); while (true){ if (it == particles.end()) break; // obtain a pose hypothesis: double x = minX + sizeX * rngUniform(); double y = minY + sizeY * rngUniform(); std::vector<double> z; getHeightlist(x, y, 0.6,z); for (unsigned zIdx = 0; zIdx < z.size(); zIdx++){ if (it == particles.end()) break; // not needed => we already know that z contains valid poses // distance map: used distance from obstacles: //std::abs(node->getLogOdds()) < 0.1){ // if (!isOccupied(octomap::point3d(x, y, z[zIdx]))){ it->pose.getOrigin().setX(x); it->pose.getOrigin().setY(y); // TODO: sample z, roll, pitch around odom pose! it->pose.getOrigin().setZ(z.at(zIdx) + initPose(2) + rngNormal() * initNoise(2)); double yaw = rngUniform() * 2 * M_PI -M_PI; it->pose.setRotation(tf::createQuaternionFromYaw(yaw)); it->weight = weight; it++; } } }
//LC: added for local (re)localization void MapModel::distributeLocally(Particles& particles, double roll, double pitch, double yaw, double x, double y, double z, UniformGeneratorT& rngUniform, double dist_linear, double dist_angular){ //maxHeight added by LC double sizeX,sizeY,sizeZ, minX, minY, minZ; //LC: get total map size m_map->getMetricSize(sizeX,sizeY,sizeZ); //LC: get minimum values of map bounding box m_map->getMetricMin(minX, minY, minZ); double weight = 1.0 / particles.size(); Particles::iterator it = particles.begin(); while (true){ if (it == particles.end()) break; // obtain a pose hypothesis: double x_new = x + dist_linear * ((rngUniform() - 0.5) * 2); double y_new = y + dist_linear * ((rngUniform() - 0.5) * 2); double z_new = z + dist_linear * ((rngUniform() - 0.5) * 2); double roll_new = roll;// + dist_angular * ((rngUniform() - 0.5) * 2); double pitch_new = pitch;// + dist_angular * ((rngUniform() - 0.5) * 2); double yaw_new = yaw + dist_angular * ((rngUniform() - 0.5) * 2); if(it == particles.begin()) { // obtain a pose hypothesis: x_new = x; y_new = y; z_new = z; roll_new = roll; pitch_new = pitch; yaw_new = yaw; } //set new pose it->pose.getOrigin().setX(x_new); it->pose.getOrigin().setY(y_new); it->pose.getOrigin().setZ(z_new); //set orientation it->pose.setRotation(tf::createQuaternionFromRPY(roll_new, pitch_new, yaw_new)); it->weight = weight; it++; } }
void applyVoxelGridConstraint(VoxelGrid *g) { for(Particles::iterator iter = particles.begin(); iter != particles.end(); ++iter) { Particle *p = *iter; glm::ivec3 v; if(p->type == PARTICLE_PROJECTILE && g->applyConstraint(p,v)) { g->set(v, 0); remove(p); } } }
void KMLProxy::initialize(Model *m,const Particles &ps, const FloatKeys &atts,unsigned int num_centers){ for(Particles::const_iterator it = ps.begin(); it != ps.end();it++) {ps_.push_back(*it);} for(FloatKeys::const_iterator it = atts.begin(); it != atts.end();it++) {atts_.push_back(*it);} m_ = m; kcenters_=num_centers; dim_=atts.size(); centroids_ = Particles(); data_ = new KMData(dim_,ps_.size()); for(unsigned int i=0;i<ps_.size(); i++) { for(unsigned int j=0;j<atts.size();j++){ (*(*data_)[i])[j]=ps_[i]->get_value(atts[j]); } } is_init_=true; }
Particles CHARMMParameters::create_dihedrals(Particles bonds) const { IMP_OBJECT_LOG; Particles ps; BondMap particle_bonds; make_bond_map(bonds, particle_bonds); // Iterate over all bonds for (Particles::const_iterator bit1 = bonds.begin(); bit1 != bonds.end(); ++bit1) { IMP::atom::Bond bd = IMP::atom::Bond(*bit1); Particle *p2 = bd.get_bonded(0).get_particle(); Particle *p3 = bd.get_bonded(1).get_particle(); // Extend along each bond from p2 and p3 to get candidate // p1-p2-p3-p4 dihedrals for (base::Vector<IMP::atom::Bond>::const_iterator bit2 = particle_bonds[p2].begin(); bit2 != particle_bonds[p2].end(); ++bit2) { Particle *p1 = get_other_end_of_bond(p2, *bit2); if (p1 != p3) { for (base::Vector<IMP::atom::Bond>::const_iterator bit3 = particle_bonds[p3].begin(); bit3 != particle_bonds[p3].end(); ++bit3) { Particle *p4 = get_other_end_of_bond(p3, *bit3); // Avoid generating dihedrals for three-membered rings if (p1 != p4 && p2 != p4) { internal::add_dihedral_to_list(this, p1, p2, p3, p4, ps); } } } } } return ps; }
Particles CHARMMParameters::create_angles(Particles bonds) const { IMP_OBJECT_LOG; Particles ps; BondMap particle_bonds; make_bond_map(bonds, particle_bonds); // Iterate over all bonds for (Particles::const_iterator bit1 = bonds.begin(); bit1 != bonds.end(); ++bit1) { IMP::atom::Bond bd = IMP::atom::Bond(*bit1); Particle *p2 = bd.get_bonded(0).get_particle(); Particle *p3 = bd.get_bonded(1).get_particle(); // Extend along each adjoining p2 bond to get candidate p1-p2-p3 angles for (base::Vector<IMP::atom::Bond>::const_iterator bit2 = particle_bonds[p2].begin(); bit2 != particle_bonds[p2].end(); ++bit2) { Particle *p1 = get_other_end_of_bond(p2, *bit2); // Avoid making angles where p1 == p3, and avoid double-counting if (p3 > p1) { add_angle(p1, p2, p3, ps); } } // Do the same for p2-p3-p4 angles for (base::Vector<IMP::atom::Bond>::const_iterator bit2 = particle_bonds[p3].begin(); bit2 != particle_bonds[p3].end(); ++bit2) { Particle *p4 = get_other_end_of_bond(p3, *bit2); if (p4 < p2) { add_angle(p2, p3, p4, ps); } } } return ps; }
void MapModel::verifyPoses(Particles& particles){ double minX, minY, minZ, maxX, maxY, maxZ; m_map->getMetricMin(minX, minY, minZ); m_map->getMetricMax(maxX, maxY, maxZ); // find min. particle weight: double minWeight = std::numeric_limits<double>::max(); for (Particles::iterator it = particles.begin(); it != particles.end(); ++it) { if (it->weight < minWeight) minWeight = it->weight; } minWeight -= 200; unsigned numWall = 0; unsigned numOut = 0; unsigned numMotion = 0; // TODO possible speedup: cluster particles by grid voxels first? // iterate over samples, multi-threaded: #pragma omp parallel for for (unsigned i = 0; i < particles.size(); ++i){ octomap::point3d position(particles[i].pose.getOrigin().getX(), particles[i].pose.getOrigin().getY(), particles[i].pose.getOrigin().getZ()); // see if outside of map bounds: if (position(0) < minX || position(0) > maxX || position(1) < minY || position(1) > maxY || position(2) < minZ || position(2) > maxZ) { particles[i].weight = minWeight; #pragma omp atomic numOut++; } else { // see if occupied cell: if (this->isOccupied(position)){ particles[i].weight = minWeight; #pragma omp atomic numWall++; } else { // see if current pose is a valid walking pose: // TODO: need to check height over floor! if (m_motionRangeZ >= 0.0 && std::abs(particles[i].pose.getOrigin().getZ() - m_motionMeanZ) > m_motionRangeZ) { particles[i].weight = minWeight; #pragma omp atomic numMotion++; } else if (m_motionRangePitch >= 0.0 || m_motionRangeRoll >= 0.0){ double yaw, pitch, roll; particles[i].pose.getBasis().getRPY(roll, pitch, yaw); if ((m_motionRangePitch >= 0.0 && std::abs(pitch) > m_motionRangePitch) || (m_motionRangeRoll >= 0.0 && std::abs(roll) > m_motionRangeRoll)) { particles[i].weight = minWeight; #pragma omp atomic numMotion++; } } } } } // end loop over particles if (numWall > 0 || numOut > 0 || numMotion > 0){ ROS_INFO("Particle weights minimized: %d out of map, %d in obstacles, %d out of motion range", numOut, numWall, numMotion); } if (numOut + numWall >= particles.size()){ ROS_WARN("All particles are out of the valid map area or in obstacles!"); } }
ParticleIndexesAdaptor::ParticleIndexesAdaptor(const Particles &ps) : tmp_(new ParticleIndexes(ps.size())), val_(tmp_.get()) { *tmp_ = get_indexes(ParticlesTemp(ps.begin(), ps.end())); }
Particle& GetEnd(){ return *(*m_particles.end() ); }
/** @brief get the centers as intensity centroids of local maxima neighbourhood * * Local maxima are taken as the bright pixels of centersMap */ Particles Tracker::getSubPixel(bool autoThreshold) { //boost::progress_timer ptimer; //get the positions of the bright centers from flatten centersMap if(!quiet) cout<<"get positions ... "; list<size_t> flat_positions; bool* b = centersMap.origin(); for(size_t i=0; i<centersMap.num_elements(); ++i) if(*b++) flat_positions.push_back(i); //sort by increasing pixel intensity if(!quiet) cout<<flat_positions.size()<<" potential centers ... "; flat_positions.sort(compIntensities(data)); //Find the best intensity threshold if(autoThreshold) { //construct the centers intensity histogram const long double minhist = *(data+flat_positions.front()), maxhist = *(data+flat_positions.back()); const long double scale = 100.0/(maxhist-minhist); vector<size_t> hist(100, 0); for(list<size_t>::const_iterator c = flat_positions.begin(); c!= flat_positions.end(); ++c) { size_t l = (*(data + (*c)) - minhist) * scale; if(l<hist.size()) hist[l]++; } //find the population global maximum vector<size_t>::iterator peak = max_element(hist.begin(), hist.end()); if(!quiet) cout<<"peak ="<<distance(hist.begin(), peak)<<" ... "; //find the last non-null bin before the peak, and at the same time the bin with the minimum population between it and the peak vector<size_t>::iterator non_z = lower_bound(hist.begin(), peak, 1); vector<size_t>::iterator lowest = min_element(non_z, peak); //cout<<"non_z="<<distance(hist.begin(),non_z)<<"\tlowest="<<distance(hist.begin(),lowest)<<endl; while((*lowest)==0) { non_z = lowest; lowest = min_element(lowest, peak); //cout<<"non_z="<<distance(hist.begin(),non_z)<<"\tlowest="<<distance(hist.begin(),lowest)<<endl; } //lowest gives the position of the valley of the histogram, ie the best threshold if(!quiet) cout<<"best threshold = "<<distance(hist.begin(), lowest)/scale + minhist<<" ("<<distance(hist.begin(), lowest)<<"%) ... "; //We remove all centers that have lower intensity than the best threshold list<size_t>::iterator i = flat_positions.begin(); advance(i, accumulate(hist.begin(), lowest, (size_t)0)); flat_positions.erase(flat_positions.begin(), i); if(!quiet) cout<<flat_positions.size()<<" centers after auto thresholding ... "; } //centroid binning if(!quiet) cout<<"centroid ... "; list< valarray<double> > positions; boost::array<size_t,3> shape; copy(centersMap.shape(), centersMap.shape()+3, shape.begin()); transform( flat_positions.rbegin(), flat_positions.rend(), back_inserter(positions), centroid(boost::multi_array_ref<float,3>(data,shape)) ); //removing marked centers positions.remove_if(markedPositionRemover<valarray<double> >()); if(!quiet) cout<<positions.size()<<" are real local maxima ... "; Particles centers; for(size_t d=0;d<3;++d) { centers.bb.edges[d].first = 0; centers.bb.edges[d].second = centersMap.shape()[d]; } //centers.reserve(positions.size()); copy(positions.begin(), positions.end(), back_inserter(centers)); if(fortran_order) { //If the image was filled in row major ordering of the dimensions, the coordinates are given as z,y,x by the tracker. //Here we convert to the human-readable x,y,z coordinates for_each(centers.begin(), centers.end(), revert<valarray<double> >()); //don't forget the bounding box swap(centers.bb.edges[0].second, centers.bb.edges[2].second); } if(!quiet) cout << "done!" << endl; if(view) { markCenters(); display("Centers"); } return centers; }
IMPCNMULTIFIT_BEGIN_NAMESPACE Floats get_rmsd_for_models(const std::string param_filename, const std::string trans_filename, const std::string ref_filename, int start_model, int end_model) { std::string protein_filename, surface_filename; int cn_symm_deg; std::cout << "============= parameters ============" << std::endl; std::cout << "params filename : " << param_filename << std::endl; std::cout << "trans filename : " << trans_filename << std::endl; std::cout << "ref filename : " << ref_filename << std::endl; std::cout << "start index to rmsd : " << start_model << std::endl; std::cout << "end index to rmsd : " << end_model << std::endl; std::cout << "=====================================" << std::endl; internal::Parameters params(param_filename.c_str()); protein_filename = params.get_unit_pdb_fn(); cn_symm_deg = params.get_cn_symm(); IMP_NEW(Model, mdl, ()); atom::Hierarchy asmb_ref; atom::Hierarchies mhs; // read the monomer core::XYZs model_xyzs; for (int i = 0; i < cn_symm_deg; i++) { atom::Hierarchy h = atom::read_pdb(protein_filename, mdl, new atom::CAlphaPDBSelector()); atom::Chain c = atom::get_chain( atom::Residue(atom::get_residue(atom::Atom(core::get_leaves(h)[0])))); c.set_id(std::string(1, char(65 + i))); atom::add_radii(h); atom::create_rigid_body(h); mhs.push_back(h); Particles leaves = core::get_leaves(h); for (Particles::iterator it = leaves.begin(); it != leaves.end(); it++) { model_xyzs.push_back(core::XYZ(*it)); } } // read the transformations multifit::FittingSolutionRecords recs = multifit::read_fitting_solutions(trans_filename.c_str()); // read the reference structure asmb_ref = atom::read_pdb(ref_filename, mdl, new atom::CAlphaPDBSelector()); atom::Hierarchies ref_chains = atom::Hierarchies(atom::get_by_type(asmb_ref, atom::CHAIN_TYPE)); std::cout << "number of records:" << recs.size() << std::endl; Floats rmsd; std::ofstream out; out.open("rmsd.output"); if (end_model < 0 || end_model >= static_cast<int>(recs.size())) { end_model = recs.size() - 1; } for (int i = start_model; i >= 0 && i <= end_model; ++i) { algebra::Transformation3D t1 = recs[i].get_dock_transformation(); algebra::Transformation3D t2 = recs[i].get_fit_transformation(); algebra::Transformation3D t2_inv = t1.get_inverse(); transform_cn_assembly(mhs, t1); for (unsigned int j = 0; j < model_xyzs.size(); j++) { model_xyzs[j] .set_coordinates(t2.get_transformed(model_xyzs[j].get_coordinates())); } std::cout << mhs.size() << "," << ref_chains.size() << std::endl; Float cn_rmsd = get_cn_rmsd(mhs, ref_chains); out << " trans:" << i << " rmsd: " << cn_rmsd << " cc: " << 1. - recs[i].get_fitting_score() << std::endl; rmsd.push_back(cn_rmsd); for (unsigned int j = 0; j < model_xyzs.size(); j++) { model_xyzs[j].set_coordinates( t2_inv.get_transformed(model_xyzs[j].get_coordinates())); } /* std::stringstream ss; ss<<"asmb_"<<i<<".pdb"; atom::write_pdb(mhs,ss.str());*/ transform_cn_assembly(mhs, t1.get_inverse()); } out.close(); return rmsd; }
bool Particle::update() { if (!mMap) return false; if (mLifetimeLeft == 0) { mAlive = false; } if (mAlive) { //calculate particle movement if (mMomentum != 1.0f) { mVelocity *= mMomentum; } if (mTarget && mAcceleration != 0.0f) { Vector dist = mPos - mTarget->getPosition(); dist.x *= SIN45; float invHypotenuse; switch (Particle::fastPhysics) { case 1: invHypotenuse = fastInvSqrt( dist.x * dist.x + dist.y * dist.y + dist.z * dist.z); break; case 2: invHypotenuse = 2.0f / fabs(dist.x) + fabs(dist.y) + fabs(dist.z); break; default: invHypotenuse = 1.0f / sqrt( dist.x * dist.x + dist.y * dist.y + dist.z * dist.z); break; } if (invHypotenuse) { if (mInvDieDistance > 0.0f && invHypotenuse > mInvDieDistance) { mAlive = false; } float accFactor = invHypotenuse * mAcceleration; mVelocity -= dist * accFactor; } } if (mRandomnes > 0) { mVelocity.x += (rand()%mRandomnes - rand()%mRandomnes) / 1000.0f; mVelocity.y += (rand()%mRandomnes - rand()%mRandomnes) / 1000.0f; mVelocity.z += (rand()%mRandomnes - rand()%mRandomnes) / 1000.0f; } mVelocity.z -= mGravity; // Update position mPos.x += mVelocity.x; mPos.y += mVelocity.y * SIN45; mPos.z += mVelocity.z * SIN45; // Update other stuff if (mLifetimeLeft > 0) { mLifetimeLeft--; } mLifetimePast++; if (mPos.z > PARTICLE_SKY || mPos.z < 0.0f) { if (mBounce > 0.0f) { mPos.z *= -mBounce; mVelocity *= mBounce; mVelocity.z = -mVelocity.z; } else { mAlive = false; } } // Update child emitters if (mLifetimePast%Particle::emitterSkip == 0) { for ( EmitterIterator e = mChildEmitters.begin(); e != mChildEmitters.end(); e++ ) { Particles newParticles = (*e)->createParticles(); for ( ParticleIterator p = newParticles.begin(); p != newParticles.end(); p++ ) { (*p)->moveBy(mPos.x, mPos.y, mPos.z); mChildParticles.push_back (*p); } } } } // Update child particles for (ParticleIterator p = mChildParticles.begin(); p != mChildParticles.end();) { if ((*p)->update()) { p++; } else { delete (*p); p = mChildParticles.erase(p); } } if (!mAlive && mChildParticles.empty() && mAutoDelete) { return false; } return true; }
bool Particle::update() { if (!mMap) return false; if (mLifetimeLeft == 0 && mAlive == ALIVE) mAlive = DEAD_TIMEOUT; Vector oldPos = mPos; if (mAlive == ALIVE) { //calculate particle movement if (mMomentum != 1.0f) { mVelocity *= mMomentum; } if (mTarget && mAcceleration != 0.0f) { Vector dist = mPos - mTarget->getPosition(); dist.x *= SIN45; float invHypotenuse; switch (Particle::fastPhysics) { case 1: invHypotenuse = fastInvSqrt( dist.x * dist.x + dist.y * dist.y + dist.z * dist.z); break; case 2: invHypotenuse = 2.0f / fabs(dist.x) + fabs(dist.y) + fabs(dist.z); break; default: invHypotenuse = 1.0f / sqrt( dist.x * dist.x + dist.y * dist.y + dist.z * dist.z); break; } if (invHypotenuse) { if (mInvDieDistance > 0.0f && invHypotenuse > mInvDieDistance) { mAlive = DEAD_IMPACT; } float accFactor = invHypotenuse * mAcceleration; mVelocity -= dist * accFactor; } } if (mRandomness > 0) { mVelocity.x += (rand()%mRandomness - rand()%mRandomness) / 1000.0f; mVelocity.y += (rand()%mRandomness - rand()%mRandomness) / 1000.0f; mVelocity.z += (rand()%mRandomness - rand()%mRandomness) / 1000.0f; } mVelocity.z -= mGravity; // Update position mPos.x += mVelocity.x; mPos.y += mVelocity.y * SIN45; mPos.z += mVelocity.z * SIN45; // Update other stuff if (mLifetimeLeft > 0) { mLifetimeLeft--; } mLifetimePast++; if (mPos.z < 0.0f) { if (mBounce > 0.0f) { mPos.z *= -mBounce; mVelocity *= mBounce; mVelocity.z = -mVelocity.z; } else { mAlive = DEAD_FLOOR; } } else if (mPos.z > PARTICLE_SKY) { mAlive = DEAD_SKY; } // Update child emitters if ((mLifetimePast-1)%Particle::emitterSkip == 0) { for (EmitterIterator e = mChildEmitters.begin(); e != mChildEmitters.end(); e++) { Particles newParticles = (*e)->createParticles(mLifetimePast); for (ParticleIterator p = newParticles.begin(); p != newParticles.end(); p++) { (*p)->moveBy(mPos); mChildParticles.push_back (*p); } } } } // create death effect when the particle died if (mAlive != ALIVE && mAlive != DEAD_LONG_AGO) { if ((mAlive & mDeathEffectConditions) > 0x00 && !mDeathEffect.empty()) { Particle* deathEffect = particleEngine->addEffect(mDeathEffect, 0, 0); deathEffect->moveBy(mPos); } mAlive = DEAD_LONG_AGO; } Vector change = mPos - oldPos; // Update child particles for (ParticleIterator p = mChildParticles.begin(); p != mChildParticles.end();) { //move particle with its parent if desired if ((*p)->doesFollow()) { (*p)->moveBy(change); } //update particle if ((*p)->update()) { p++; } else { delete (*p); p = mChildParticles.erase(p); } } if (mAlive != ALIVE && mChildParticles.empty() && mAutoDelete) { return false; } return true; }