void GravityAffector::updateParticle(const ParticlePtr& particle, float elapsedTime) { if(!m_active) return; PointF velocity = particle->getVelocity(); velocity += PointF(m_gravity * elapsedTime * cos(m_angle), m_gravity * elapsedTime * sin(m_angle)); particle->setVelocity(velocity); }
void RandomColorAffector::Update(ParticlePtr & particle, float dt) { sf::Color color = particle->GetColor(); color.r = sf::Randomizer::Random(0, 255); color.g = sf::Randomizer::Random(0, 255); color.b = sf::Randomizer::Random(0, 255); particle->SetColor(color); }
FixedDist::FixedDist(ParticlePtr pP0, ParticlePtr pP1, int matrixCol0, int matrixCol1, int NumParticles) : m_pP0(pP0), m_pP1(pP1), m_MatrixCol0(matrixCol0), m_MatrixCol1(matrixCol1), m_Dist(bnu::norm_2(pP1->GetPosition() - pP0->GetPosition())) { ResizeDJacobian(NumParticles); ResizeJacobian(NumParticles); ResizeConPos(); ResizeConVel(); }
void AttractionAffector::updateParticle(const ParticlePtr& particle, float elapsedTime) { if(!m_active) return; PointF pPosition = particle->getPosition(); PointF d = PointF(m_position.x - pPosition.x, pPosition.y - m_position.y); if(d.length() == 0) return; PointF direction = PointF(1, 1); if(m_repelish) direction = PointF(-1, -1); PointF pVelocity = particle->getVelocity() + (d / d.length() * m_acceleration * elapsedTime) * direction; particle->setVelocity(pVelocity - pVelocity * m_reduction/100.0 * elapsedTime); }
void apply(ParticlePtr p) { p->position.x = Rand::randFloat(space->min.x, space->max.x); p->position.y = Rand::randFloat(space->min.y, space->max.y); p->position.z = Rand::randFloat(space->min.z, space->max.z); p->lifeTime = Rand::randFloat(10, 100); //printf("random emit: %f %f %f\n", p->x, p->y, p->z); p->clearVelocity(); }
void CPointEmitter::InitParticle(ParticlePtr &particle) { math::vec2f ws_pos = mPos + mPositionOffset; math::vec2f dir = this->mDirection.Rotate(util::Rand::Get()->Randomf(-this->mEmisionAngle, this->mEmisionAngle)); dir.Normalize(); math::float32 speed = util::Rand::Get()->Randomf(mParticleSpeed-mParticleSpeedVariation, mParticleSpeed+mParticleSpeedVariation); math::CColorRGBA clr = RandomiseColor(); particle->Init(ws_pos, dir, speed, util::Rand::Get()->Randomf(this->mLiveTime-mLiveTimeVariation, this->mLiveTime+mLiveTimeVariation), clr, 0, mScale); }
void Emitter::Play() { if(particles.empty() && maxParticles > 0) return; for(int i = 0; i < emissionRate && (!particles.empty() || maxParticles == 0); i++) { ParticlePtr particle; if(maxParticles > 0) { particle = particles.front(); particles.pop_front(); } else { particle = ParticlePtr(new Particle()); } InitParticle(particle); emittedParticles.push_front(particle); particle->SetIsVisible(true); } }
void CLineEmitter::InitParticle(ParticlePtr &particle) { math::vec2f ws_pos = mPos + mPositionOffset; math::vec2f dir = this->mDirection.Rotate(util::Rand::Get()->Randomf(-this->mEmisionAngle, this->mEmisionAngle)); dir.Normalize(); math::vec2f ws_end_pos = ws_pos + this->mPosEnd; math::vec2f normalVec(ws_pos - ws_end_pos); math::float32 len = normalVec.Length(); normalVec.Normalize(); //len = static_cast<math::float32>(rand()%static_cast<math::int32>(len)); len = util::Rand::Get()->Randomf(len); math::float32 speed = util::Rand::Get()->Randomf(mParticleSpeed-mParticleSpeedVariation, mParticleSpeed+mParticleSpeedVariation); math::CColorRGBA clr = RandomiseColor(); particle->Init(ws_pos + (normalVec * len), dir, speed, util::Rand::Get()->Randomf(this->mLiveTime-mLiveTimeVariation, this->mLiveTime+mLiveTimeVariation), clr, 0, mScale); }
void CCircleEmitter::InitParticle(ParticlePtr &particle) { math::vec2f ws_pos = mPos + mPositionOffset; math::vec2f dir = this->mDirection.Rotate(util::Rand::Get()->Randomf(-this->mEmisionAngle, this->mEmisionAngle)); dir.Normalize(); math::vec2f spawnPos; math::float32 randomNr = util::Rand::Get()->Randomf(0.f, math::TWO_PI); spawnPos.x = mRadius * math::mathf::Sin(randomNr); spawnPos.y = mRadius * math::mathf::Cos(randomNr); spawnPos += ws_pos; math::float32 speed = util::Rand::Get()->Randomf(mParticleSpeed-mParticleSpeedVariation, mParticleSpeed+mParticleSpeedVariation); math::CColorRGBA clr = RandomiseColor(); particle->Init(spawnPos, dir, speed, util::Rand::Get()->Randomf(this->mLiveTime-mLiveTimeVariation, this->mLiveTime+mLiveTimeVariation), clr, 0, mScale); }
void ParticleSystem::collide(ParticlePtr part, PlanePtr plane) { //SimonState::exemplar()->messages << "Cloth: Kollision Kugel vs. Ebene gestartet" << SimonState::endm; float distance = dot(part->getPosition() - plane->getRigidBody()->getPosition(), plane->getNormal()); Vector3<float> n = plane->getNormal(); Vector3<float> v = part->getVelocity(); float vDotN = dot (v, n); //Vector3<float> f = getRigidBody()->getForce(); // no resting contact. check collision if ( distance <= 3.0) { if (vDotN<=0.5f) { // normal colliding contact: Vector3 <float> velPart = part->getVelocity(); Vector3 <float> normPlane = plane->getNormal(); normPlane.normalize(); float vDoN = dot(velPart, normPlane); normPlane *= vDoN; part->setVelocity(part->getVelocity() - normPlane); //cout << "Vel aus col " << part->getVelocity()<< endl; normPlane = plane->getNormal(); normPlane.normalize(); Vector3 <float> forcePart = part->getForce(); float fDotN = dot(forcePart, normPlane); normPlane *= fDotN; part->addForce((-1) * normPlane); //cout << "Acc aus Col " << part->getAcceleration() << endl; // factor in elasticity // geschummelt (eigentlich getBounciness) //vDotN *= 1 + 2.5f; // reflect veloctiy along normal //part->setVelocity( Vector3<float>(v[X] - vDotN*n[X], v[Y] - vDotN*n[Y], v[Z] - vDotN*n[Z])); SimonState::exemplar()->messages << "Cloth: Kollision Particle vs. Ebene beendet" << SimonState::endm; } } }
/** * \brief Collision Partikel mit einer Box. * \param box zu testende Box */ void ParticleSystem::collide(ParticlePtr part, BoxPtr box) { //sphere in das lokale koordinatensystem der box bringen Vector3<float> particlePos = part->getPosition() - box->getRigidBody()->getPosition(); Quaternion boxOri = box->getRigidBody()->getOrientation(); const Quaternion& boxInvOri = boxOri.inverse(); particlePos = qRotate(particlePos, boxInvOri); //test auf collision mit den 6 seiten der box unsigned int cnt = 0; float rad = 3.0f; float right = dot(particlePos, Vector3<float>(1,0,0)) + rad; float left = dot(particlePos, Vector3<float>(-1,0,0)) - rad; float front = dot(particlePos, Vector3<float>(0,0,1)) + rad; float back = dot(particlePos, Vector3<float>(0,0,-1)) - rad; float top = dot(particlePos, Vector3<float>(0,1,0)) + rad; float bottom = dot(particlePos, Vector3<float>(0,-1,0)) - rad; float dR = box->getWidth()/2 - right + rad; float dL = box->getWidth()/2 - left + rad; float dF = box->getDepth()/2 - front + rad; float dBa = box->getDepth()/2 - back + rad; float dT = box->getHeight()/2 - top + rad; float dBo = box->getHeight()/2 - bottom + rad; if (right >= 0 && dR >= 0) { cnt ++; if (right > box->getWidth()/2) particlePos[X] = box->getWidth()/2; else particlePos[X] = right ; } if (left > 0 && dL >= 0) { cnt ++; if(left > box->getWidth()/2) particlePos[X] = -box->getWidth()/2; else particlePos[X] = -left ; } if (front >= 0 && dF >= 0) { cnt ++; if (front > box->getDepth()/2) particlePos[Z] = box->getDepth()/2; else particlePos[Z] = front; } if (back > 0 && dBa >= 0) { cnt ++; if (back > box->getDepth()/2) particlePos[Z] = -box->getDepth()/2; else particlePos[Z] = -back; } if (top >= 0 && dT >= 0) { cnt ++; if (top > box->getHeight()/2) particlePos[Y] = box->getHeight()/2; else particlePos[Y] = top; } if (bottom > 0 && dBo >= 0) { cnt ++; if (bottom > box->getHeight()/2) particlePos[Y] = -box->getHeight()/2; else particlePos[Y] = -bottom ; } //test auf collision if (cnt >= 3) { //berechnung normalB und contactPoint const Vector3<float>& contactPoint = qRotate(particlePos, boxOri) + box->getRigidBody()->getPosition(); //cout << "C: " << contactPoint << endl; //cout << "P: " << part->getPosition() << endl; Vector3<float> normalB = part->getPosition() - contactPoint; //cout << normalB.length() <<"\n"; //if (normalB.length() != 0) normalB.normalize(); // folgender Abschnitt aus: // CollisionSystem::collisionResponse(part, sphere, contactPoint, normalB); //berechnung der relativen geschwindigkeit in richtung normalB const Vector3<float>& velocityA = part->getVelocity(); const Vector3<float>& velocityB = box->getRigidBody()->getVelocity(); Vector3<float> velA = part->getVelocity(); Vector3<float> forceA = part->getForce(); // const Vector3<float>& rA = contactPoint - part->getPosition(); // vorher: particlePos! // const Vector3<float>& rB = contactPoint - box->getPosition(); const Vector3<float>& vA = velocityA; const Vector3<float>& vB = velocityB; const Vector3<float>& vR = vA - vB; float vN = dot(vR, normalB); //------------------Behandlung für colliding contact--------------------------------------- if (vN <= 0.5) { //--------------------neue Behandlung aus Sphere kopiert------------------------- float vDoN = dot(velA, normalB); Vector3<float> vS = normalB * vDoN; float fDoN = dot(forceA, normalB); Vector3<float> fS = normalB * fDoN; Vector3<float> force = part->getForce(); force.normalize(); if (dot (force, normalB) > 0 ){ part->setVelocity(part->getVelocity() - vS); part->setVelocity(part->getVelocity() * 0.75); // Wert: 0.75 part->addForce((-1.0) * fS); part->setForce(part->getForce() * 0.75); // Wert: 0.75 part->setIsColliding(true); } //------------------------------------------------------------------------------ ////berechnung der impuls-kraft in richtung normalB ////float damping = (0.01f + box->getBounciness()) / 2.0f; //float damping = 0.12f; //float invMassA, invMassB = 0.0f; ////Matrix<float> invTensorA(3,3); ////Matrix<float> invTensorB = box->getInvWorldInertiaTensor(); ////test ob dynamisch //if(part->getIsDynamicFlag()) //{ // invMassA = part->getInvMass(); //} //else // invMassA = 0.0; // //if(box->getRigidBody()->getIsDynamicFlag()) //{ // invMassB = box->getInvMass(); // //invTensorB = box->getRigidBody()->getInvWorldInertiaTensor(); //} //else // invMassB = 0.0; //float fNum = -(/*1+*/damping)*(dot(normalB,(velocityA - velocityB))); //float fDenom = invMassA + invMassB;// + dot(crossA,uA)+dot(crossB,uB); //float impulseMagnitude = fNum / fDenom; //if (impulseMagnitude < 0){ //Vector3<float> impulseForce = impulseMagnitude * normalB; ///*impulseForce.normalize(); //float vDoI = dot(velA, impulseForce); //float fDoI = dot(forceA, impulseForce); //Vec3 vS = impulseForce * vDoI; //Vec3 fS = impulseForce * fDoI;*/ ////part->setVelocity(part->getVelocity()[X], 0.0f, part->getVelocity()[Z]); ////part->setVelocity(part->getVelocity() - vS); ////part->addForce(fS); ////setzen der linaren momente //if (part->getInvMass()!=0) //{ //part->setVelocity(part->getVelocity() - impulseForce/invMassA); //part->setIsColliding(true); //} ////part->setVelocity(part->getVelocity() + (impulseForce / invMassB)); // //} } } }
void ParticleSystem::collide(ParticlePtr part, CapsulePtr caps) { //part->setIsColliding(false); Vector3<float> unitV(0,1,0); Vector3<float> rV(qRotate(unitV, caps->getRigidBody()->getOrientation())); Vector3<float> A1 = caps->getRigidBody()->getPosition()+(rV*(caps->getHeight()/2)); Vector3<float> A2 = caps->getRigidBody()->getPosition()-(rV*(caps->getHeight()/2)); Vec3 nullVector = Vec3(0.0,0.0,0.0); // teile des codes Copyright 2001, softSurfer (www.softsurfer.com) // alles geschummelt. Kugelzentrum als infinitisimal kleines Segment interpretiert. Vector3<float> smallNumberVector(0.1f,0.1f,0.1f); Vector3<float> B1 = part->getPosition() + smallNumberVector; Vector3<float> B2 = part->getPosition() - smallNumberVector; Vector3<float> u = A2 - A1; Vector3<float> v = B2 - B1; Vector3<float> w = A1 - B1; float a = dot(u,u); // always >= 0 float b = dot(u,v); float c = dot(v,v); // always >= 0 float d = dot(u,w); float e = dot(v,w); float D = a*c - b*b; // always >= 0 float sc, sN, sD = D; // sc = sN / sD, default sD = D >= 0 float tc, tN, tD = D; // tc = tN / tD, default tD = D >= 0 // compute the line parameters of the two closest points if (D < 0.0000000001) { // the lines are almost parallel sN = 0.0; // force using point P0 on segment S1 sD = 1.0; // to prevent possible division by 0.0 later tN = e; tD = c; } else { // get the closest points on the infinite lines sN = (b*e - c*d); tN = (a*e - b*d); if (sN < 0.0) { // sc < 0 => the s=0 edge is visible sN = 0.0; tN = e; tD = c; } else if (sN > sD) { // sc > 1 => the s=1 edge is visible sN = sD; tN = e + b; tD = c; } } if (tN < 0.0) { // tc < 0 => the t=0 edge is visible tN = 0.0; // recompute sc for this edge if (-d < 0.0) sN = 0.0; else if (-d > a) sN = sD; else { sN = -d; sD = a; } } else if (tN > tD) { // tc > 1 => the t=1 edge is visible tN = tD; // recompute sc for this edge if ((-d + b) < 0.0) sN = 0; else if ((-d + b) > a) sN = sD; else { sN = (-d + b); sD = a; } } // finally do the division to get sc and tc if(fabs(sN) < 0.000000001) sc = 0.0; else sc = sN/sD; if(fabs(tN) < 0.0000000001) tc = 0.0; else tc = tN/tD; // get the difference of the two closest points Vector3<float> dP = w + (sc * u) - (tc * v); // = S1(sc) - S2(tc) float dist = dP.length(); // return the closest distance float radParticle = 3.0f; // 3.0f für Partikelradius //collision-behandlung if (dist < (caps->getRadius()) + radParticle) { assert(dP.length() != 0.0); if (dP.length() != 0.0) dP.normalize(); Vector3<float> normalB = dP ; Vector3<float> contactPoint = part->getPosition() + (radParticle * dP); Vector3<float> posOldToContact = contactPoint - (part->getPosition()); //überprüfung der normalen, falls die capsule weiter als radius eingedrungen ist, umdrehen if (dot(posOldToContact, normalB)<0) { //cout << "Normale " << normalB << " von B=" << caps->getId() << " zeigt in die falsche Richtung !\n"; normalB = -normalB; } else { // cout << "Normale " << normalB << " von B=" << caps->getId() << " zeigt in die richtige Richtung !\n"; } const Vector3<float>& rA = contactPoint - caps->getRigidBody()->getPosition(); const Vector3<float>& aVelocityA = caps->getRigidBody()->getAngularVelocity(); Vector3<float> velA = part->getVelocity(); Vector3<float> forceA = part->getForce(); const Vector3<float>& velocityB = part->getVelocity(); const Vector3<float>& velocityA = caps->getRigidBody()->getVelocity() + cross(aVelocityA, rA); const Vector3<float>& vR = velocityA - velocityB; float vN = dot(vR, normalB); //test auf colliding contact if (vN <= 0.03) // Wert: 0.5 { //Vector3<float> normale = -1 * part->getPosition() + caps->getPosition(); //normalB.normalize(); //-----------Marke Eigenbau-------------------------------------------------------------------------------- //float vDoN = dot(velA, normalB); //Vector3<float> vS = normalB * vDoN; //float fDoN = dot(forceA, normalB); //Vector3<float> fS = normalB * fDoN; //Vector3<float> force = part->getForce(); ////force.normalize(); //if (dot (force, normalB) >= 0.0 ){ // part->setVelocity(part->getVelocity() - vS); // part->setVelocity(part->getVelocity() * 0.75); // Wert: 0.75 // part->addForce((-1) * fS); // part->setForce(part->getForce() * 0.75); // Wert: 0.75 // part->setIsColliding(true); // } // //part->setVelocity(part->getVelocity() * vDoN); //part->setForce(part->getForce() * fDoN); //------------Kopie aus Sphere-------------------------------------------------- float vDoN = dot(velA, normalB); Vector3<float> vS = normalB * vDoN; float fDoN = dot(forceA, normalB); Vector3<float> fS = normalB * fDoN; Vector3<float> force = part->getForce(); if (force.length() != 0.0) force.normalize(); if (dot (force, normalB) > 0 ){ part->setVelocity(part->getVelocity() - vS); part->setVelocity(part->getVelocity() * 0.9f); // Wert: 0.75 part->setVelocity(part->getVelocity() + caps->getRigidBody()->getVelocity()); part->addForce((-1.f) * fS); part->setForce(part->getForce() * 0.9f); // Wert: 0.75 //part->addForce(caps->getRigidBody()->getForce()); part->setIsColliding(true); part->setIsCollidingWhere(1); } else if (dot (force, normalB) < 0){ part->setVelocity(part->getVelocity() + vS); part->setVelocity(part->getVelocity() * 0.9f); // Wert: 0.75 part->setVelocity(part->getVelocity() + caps->getRigidBody()->getVelocity()); part->addForce((1.f) * fS); part->setForce(part->getForce() * 0.9f); // Wert: 0.75 //part->addForce(caps->getRigidBody()->getForce()); part->setIsColliding(true); part->setIsCollidingWhere(-1); } //--------------------------neue Kollisionsbehandlung------------------------------------------------------------- /* float damping = 1.0f; //float damping = (0.1f + caps->getBounciness()) / 2.0f; float invMassA = caps->getInvMass(); float invMassB = part->getInvMass();//1.0f / part->getMass(); Matrix<float> invTensorA = caps->getInvWorldInertiaTensor(); const Vector3<float>& crossA = cross(rA,normalB); const Vector3<float>& uA = invTensorA * crossA; // fNum = damping *( -(1+(-0.5f)) * .... float fNum = damping*(-(1+0.0f)*(dot(normalB,(velocityA - velocityB)) + dot(aVelocityA,crossA))); float fDenom = invMassA + invMassB + dot(crossA,uA); float impulseMagnitude = fNum/fDenom; // if (impulseMagnitude > 0) { Vector3<float> impulseForce = impulseMagnitude * normalB; //impulseMagnitude * 2.0 * normalB if (part->getInvMass()!=0) // Velocity setzen part->setVelocity(part->getVelocity() - (impulseForce * invMassB)); }*/ } //--------------------keine Ahnung was ist---------------------------------------------------- /* if (vN > -1.5 && vN < 1.5){ //Vector3<float> normale = -1 * part->getPosition() + caps->getPosition(); normalB.normalize(); float vDoN = dot(velA, normalB); Vector3<float> vS = normalB * vDoN; float fDoN = dot(forceA, normalB); Vector3<float> fS = normalB * fDoN; Vector3<float> force = part->getForce(); //force.normalize(); if (dot (force, normalB) >= -0.5 ){ part->setVelocity(part->getVelocity() - (vS * 1.2)); //part->setVelocity(Vector3<float>(0.0,0.0,0.0)); //part->setForce(Vector3<float>(0.0,0.01,0.0)); part->addForce((-1.2) * fS); }*/ //--------------------------------------------------------------------------------------------------------- /*vDoN *= 50; fDoN *= 50;*/ //part->setVelocity(part->getVelocity() * vDoN); //part->setForce(part->getForce() * fDoN); } }
/** * \brief fragt ab WO ein Particle kollidiert.(unterhalb oder oberhalb des RB) */ int ParticleSystem::isCollidingWhere(ParticlePtr particle){ return particle->getIsCollidingWhere(); }
/** * \brief fragt ab ob Partikel kollidiert */ bool ParticleSystem::isColliding(ParticlePtr particle){ return particle->getIsColliding(); }
//----------------------------------------------------------------------------- //---------Test Verlet---------------- void ParticleSystem::integrateVerletBaltman (double interval) { // Iteratoren std::map<Id, ParticlePtr >::iterator particleIterator; std::map<Id, ParticlePtr >::iterator particleEnd; // aktuelle Werte ParticlePtr particle; // Partikel Vec3 position; // lineare Position (Verschiebung) Quaternion orientation; // angulaere Position (Rotation als Quat) Vec3 velocity; // lineare Geschwindigkeit Vec3 velocityAngular; // Winkelgeschwindigkeit Vec3 acceleration; // lineare Beschleunigung Vec3 accelerationAngular; // Winkelbeschleunigung Quaternion orientationDot; // Ableitung der Orientierung nach der Zeit Quaternion orientationDotDot; // 2. Ableitung der Orientierung nach der Zeit double dt = interval; // Delta time double dt2 = interval * interval; // Delta time squared particleEnd = mParticleList.end (); // for all Particles for ( particleIterator = mParticleList.begin(); particleIterator != particleEnd; ++particleIterator) { particle = particleIterator->second; // Ueberspringe den RigidBody, wenn die isDynamic Flag false ist if (!(particle->getIsDynamicFlag())) { // Setze Kraft und Drehmoment Null //particle->setForce(Vector3<float>(0, 0, 0)); //particle->setTorque(Vector3<float>(0, 0, 0)); continue; } // Werte lesen position = particle->getPosition (); //orientation = particle->getOrientation (); velocity = particle->getVelocity (); //velocityAngular = particle->getAngularVelocity (); //Winkelgeschwindigkeit nicht benötigt bei Particle acceleration = particle->getAcceleration (); //accelerationAngular = particle->getAngularAcceleration ();//nicht benötigt bei Particle // Ableitungen der Orientierung /* orientationDot = 0.5 * Quaternion (velocityAngular) * orientation; orientationDotDot = (0.5 * Quaternion(0.0, accelerationAngular [0], accelerationAngular [1], accelerationAngular [2]) * orientation + 0.5 * Quaternion (0.0, velocityAngular [0], velocityAngular [1], velocityAngular [2]) * orientationDot); */ /* // Alternative orientationDotDot = (0.5) * Quaternion (-2.0 * dot (orientationDot, orientationDot), accelerationAngular [0], accelerationAngular [1], accelerationAngular [2]) * orientation; */ // Linear Update position += ((float)dt * velocity + 0.5f * (float)dt2 * acceleration); velocity += ((float)dt * acceleration); // Angular Update //orientation += (dt * orientationDot + 0.5 * dt2 * orientationDotDot); //velocityAngular += (dt * accelerationAngular); //orientation.normalize(); if (SimonState::exemplar()->getViscosityFlag()) { velocity *= SimonState::exemplar()->getViscositySlowdownLinear(); //velocityAngular *= mViscositySlowdownAngular; } // Zurueckschreiben der Werte particle->setPosition (position); //particle->setOrientation (orientation); particle->setVelocity (velocity); //particle->setAngularVelocity (velocityAngular); // Setzen von Kraft und Drehmoment auf Null particle->setForce(Vector3<float>(0, 0, 0)); //particle->setTorque(Vector3<float>(0, 0, 0));//nicht nötig bei Particle } }
// // RenderRallyPoint // // Display a rally point // static void RenderRallyPoint() { Point<S32> srcPoint(0, 0); Point<U32> dstPoint(0, 0); Matrix src, dst; // Get the single selected unit UnitObj *unit = data.cInfo.oneUnit.GetPointer(); // Is there a rally point if (unit && unit->GetFootInstance() && unit->GetRallyPoint(dstPoint)) { // Setup destination dst.ClearData(); dst.posit.x = WorldCtrl::CellToMetresX(dstPoint.x); dst.posit.z = WorldCtrl::CellToMetresZ(dstPoint.z); dst.posit.y = TerrainData::FindFloorWithWater(dst.posit.x, dst.posit.z); // Find the source srcPoint.Set(S32(dstPoint.x), S32(dstPoint.z)); unit->GetFootInstance()->ClampToFringe(srcPoint); src.ClearData(); src.posit.x = WorldCtrl::CellToMetresX(srcPoint.x); src.posit.z = WorldCtrl::CellToMetresZ(srcPoint.z); src.posit.y = TerrainData::FindFloorWithWater(src.posit.x, src.posit.z); } else { // Act as if not selected unit = NULL; } if ( // Rally unit has been deselected (!unit && rallyUnitId) || ( // Have a rally point unit unit && ( // Different to last one (unit->Id() != rallyUnitId) || // Rally point location has changed (rallyUnitId && (dstPoint != rallyPoint)) ) ) ) { // Dispose of any current particle if (rallyParticle.Alive()) { delete rallyParticle; } // Is there a unit selected if (unit) { // Never display a trail when same point if ((srcPoint.x != S32(dstPoint.x)) || (srcPoint.z != S32(dstPoint.z))) { // Create the runner particle if (ParticleClass *p = ParticleSystem::FindType(0x94E362BD)) // "Client::Rally" { Matrix m(src); m.posit.y += 3.0F; Vector v(0.0f, 0.0f, 0.0f); rallyParticle = ParticleSystem::New(p, m, v, v, dst.posit - src.posit, 0.0F); } } // Remember this unit's info rallyUnitId = unit->Id(); rallyPoint = dstPoint; } else { rallyUnitId = 0; } } // Render the start and end points if (unit) { Common::Display::Mesh(0x693D5359, src, Color(0.0F, 0.8F, 0.0F, 0.7F)); // "Location" Common::Display::Mesh(0x693D5359, dst, Color(0.0F, 1.0F, 0.0F, 0.7F)); // "Location" } }
namespace Display { // Multiplayer markers NBinTree<PlayerMarker> markers(&PlayerMarker::node); // Selection box skin TextureSkin *selectionSkin; // FootPrint placement display static Common::Display::PlacementDeform placeDeform; // Id of unit currently displaying a rally point static U32 rallyUnitId; // Rally point runner particle static ParticlePtr rallyParticle; // Rally point location static Point<U32> rallyPoint; // // RenderSpecialized // // Display specialized unit information // static void RenderSpecialized() { // Is there a unit under the cursor UnitObj *over = data.cInfo.gameWnd.Alive() ? data.cInfo.o.unit.GetPointer() : NULL; // Can we see this units special info if (over && Team::TestDisplayRelation(over, Relation::ALLY)) { over->RenderSpecialized(); } // Now display for all selected units for (UnitObjList::Iterator i(&data.sList); *i; ++i) { if (UnitObj *u = (*i)->GetPointer()) { if (u != over) { u->RenderSpecialized(); } } } } // // RenderRallyPoint // // Display a rally point // static void RenderRallyPoint() { Point<S32> srcPoint(0, 0); Point<U32> dstPoint(0, 0); Matrix src, dst; // Get the single selected unit UnitObj *unit = data.cInfo.oneUnit.GetPointer(); // Is there a rally point if (unit && unit->GetFootInstance() && unit->GetRallyPoint(dstPoint)) { // Setup destination dst.ClearData(); dst.posit.x = WorldCtrl::CellToMetresX(dstPoint.x); dst.posit.z = WorldCtrl::CellToMetresZ(dstPoint.z); dst.posit.y = TerrainData::FindFloorWithWater(dst.posit.x, dst.posit.z); // Find the source srcPoint.Set(S32(dstPoint.x), S32(dstPoint.z)); unit->GetFootInstance()->ClampToFringe(srcPoint); src.ClearData(); src.posit.x = WorldCtrl::CellToMetresX(srcPoint.x); src.posit.z = WorldCtrl::CellToMetresZ(srcPoint.z); src.posit.y = TerrainData::FindFloorWithWater(src.posit.x, src.posit.z); } else { // Act as if not selected unit = NULL; } if ( // Rally unit has been deselected (!unit && rallyUnitId) || ( // Have a rally point unit unit && ( // Different to last one (unit->Id() != rallyUnitId) || // Rally point location has changed (rallyUnitId && (dstPoint != rallyPoint)) ) ) ) { // Dispose of any current particle if (rallyParticle.Alive()) { delete rallyParticle; } // Is there a unit selected if (unit) { // Never display a trail when same point if ((srcPoint.x != S32(dstPoint.x)) || (srcPoint.z != S32(dstPoint.z))) { // Create the runner particle if (ParticleClass *p = ParticleSystem::FindType(0x94E362BD)) // "Client::Rally" { Matrix m(src); m.posit.y += 3.0F; Vector v(0.0f, 0.0f, 0.0f); rallyParticle = ParticleSystem::New(p, m, v, v, dst.posit - src.posit, 0.0F); } } // Remember this unit's info rallyUnitId = unit->Id(); rallyPoint = dstPoint; } else { rallyUnitId = 0; } } // Render the start and end points if (unit) { Common::Display::Mesh(0x693D5359, src, Color(0.0F, 0.8F, 0.0F, 0.7F)); // "Location" Common::Display::Mesh(0x693D5359, dst, Color(0.0F, 1.0F, 0.0F, 0.7F)); // "Location" } } // // RenderCurrentRegion // // Display currently selected region // static void RenderCurrentRegion() { if (data.paintRegion.Alive()) { Common::Display::MarkAreaMetre(data.paintRegion->GetArea()); } } // // RenderFootPrint // // Render an object placement footprint // static void RenderFootPrint(Bool deform) { // Grab a shortcut CycleInfo &i = data.cInfo; // Are we placing a footprint if (i.gameWnd.Alive() && (i.pEvent == PE_CONSTRUCT || i.pEvent == PE_NOCONSTRUCT)) { ASSERT(data.constructType.Alive()) ASSERT(i.t.cell) // Does object have a footprint FootPrint::Type *foot = data.constructType->GetFootPrintType(); // Equality check because type was changed on console during dev if (foot && (foot == &data.placeFoot.GetType())) { if (deform) { Common::Display::FootPrintPlacementDeform(data.placeFoot, placeDeform, TRUE, &data.placeLocation, data.clientAlpha.GetValue()); } else { Common::Display::FootPrintPlacement(data.placeFoot, TRUE, &data.placeLocation, data.clientAlpha.GetValue()); } } if (i.pEvent == PE_CONSTRUCT) { // Is this type a wall if (WallObjType *wallType = Promote::Type<WallObjType>(data.constructType)) { wallType->DisplayAvailableLinks(i.t.pos); } } } } // // RenderFormation // // Render the formation mesh // static void RenderFormation() { // Grab a shortcut CycleInfo &i = data.cInfo; // Are we placing a formation if (i.gameWnd.Alive() && (i.pEvent == PE_FORMATION)) { Vector pos; pos.x = data.cInfo.t.pos.x; pos.z = data.cInfo.t.pos.z; pos.y = TerrainData::FindFloor(pos.x, pos.z) + 2.0f; Matrix m; WorldCtrl::SetupWorldMatrix(m, pos, data.dir); Common::Display::Mesh(0x7223612A, m); // , Color(1.0f, 1.0f, 1.0f)); // "Formation" } } // // RenderSelectionBox // static void RenderSelectionBox(const Area<S32> &rect) { if (selectionSkin) { // Setup paintinfo PaintInfo pi(selectionSkin->states[ColorGroup::NORMAL].colors); pi.client = pi.window = rect; selectionSkin->Render(pi, ColorGroup::NORMAL); } else { IFace::RenderRectangle(rect, Common::Display::GroupSelectColor()); } } // // RenderPlayerMarkers // static void RenderPlayerMarkers() { Matrix m = Matrix::I; for (NBinTree<PlayerMarker>::Iterator i(&markers); *i; i++) { PlayerMarker *p = *i; // allowed to see it if (p->canSee) { m.posit.x = WorldCtrl::CellToMetresX(p->cx); m.posit.z = WorldCtrl::CellToMetresZ(p->cz); m.posit.y = TerrainData::FindFloorWithWater(m.posit.x, m.posit.z); p->pos = m.posit; // "Location" Common::Display::Mesh(0x693D5359, m, p->player->GetTeam()->GetColor()); } } } // // PreRender // // Pre-render processing // void PreRender() { // Update the current camera Viewer::Simulate(); Viewer::Render(0xF530E366); // "Render::PreRender" /* // Get the camera matrix const Matrix &m = Vid::CurCamera().WorldMatrix(); // Update the 3D listener position Sound::Digital::UpdateListener ( m.front.x, m.front.y, m.front.z, m.up.x, m.up.y, m.up.z ); */ // Update pulsating alpha data.clientAlpha.Simulate(Main::ElapTimeFrame()); } // // PreTerrain // // Rendering before terrain is drawn // void PreTerrain() { // Render an object placement footprint if (Common::Debug::data.footDeform) { RenderFootPrint(TRUE); } } // // Render // // Client specific rendering // void Render() { // Display a region RenderCurrentRegion(); // Render an object placement footprint if (!Common::Debug::data.footDeform) { RenderFootPrint(FALSE); } // Render specialized unit information RenderSpecialized(); // Display a rally point RenderRallyPoint(); // Render formation placement RenderFormation(); // Render trails Trail::Render(); // Render player markers RenderPlayerMarkers(); // Viewer rendering Viewer::Render(0xEF30A860); // "Render::PostObject" // Display debug information #ifdef DEVELOPMENT Debug::Render(); #endif // Render interface if (!IFace::GetFlag(IFace::DISABLE_DRAW)) { IFace::InitRender(); // Display the current group selection box on top of main game window if (data.selectMode == SM_PREDRAW) { RenderSelectionBox(data.mouseRect); } // Render HUD HUD::Render(); // Render main portion of interface IFace::CallRenderProc(); // Render any other systems that require iface Viewer::Render(0xCEEF613F); // "Render::PostIFace1" Viewer::Render(0xC3AC47E6); // "Render::PostIFace2" // Display the current group selection box on top of map window if (data.selectMode == SM_POSTDRAW) { RenderSelectionBox(data.mouseRect); } // Display status icons last if (!Viewer::Action::IsPlaying()) { ClipRect screenRect = IFace::RootWindow()->GetPaintInfo().window; if (GameTime::IsFallingBehind()) { Client::HUD::RenderStatusIcon(0x267B119C, screenRect); // "FallingBehind" } if (GameTime::IsDroppingFrames()) { Client::HUD::RenderStatusIcon(0xF144EDC2, screenRect); // "DroppingFrames" } if (GameTime::IsStalled()) { Client::HUD::RenderStatusIcon(0x540B86C8, screenRect); // "NetworkLag" } } IFace::DoneRender(); } } // // PostRender // // Called after rendering is finished // void PostRender() { Common::Display::PostFootPrintPlacementDeform(placeDeform); } // // Init // // Initialize this sub-system // void Init() { // Clear the region reaper data.paintRegion = NULL; // Clear local data placeDeform.Init(); rallyUnitId = 0; rallyParticle = NULL; selectionSkin = NULL; } // // Done // // Shutdown this sub-system // void Done() { selectionSkin = NULL; markers.DisposeAll(); } // // SetPlayerMarker // void SetPlayerMarker(const Player *player, S32 cx, S32 cz) { ASSERT(player) ASSERT(WorldCtrl::CellOnMap(cx, cz)) PlayerMarker *marker; if ((marker = markers.Find(player->GetId())) == NULL) { marker = new PlayerMarker; marker->player = player; marker->canSee = Team::TestRelation(Team::GetDisplayTeam(), player->GetTeam(), Relation::ALLY) ? TRUE : FALSE; markers.Add(player->GetId(), marker); } marker->cx = cx; marker->cz = cz; } // // ClearPlayerMarker // void ClearPlayerMarker(const Player *player) { PlayerMarker *marker; if ((marker = markers.Find(player->GetId())) != NULL) { markers.Dispose(marker); } } }
void ParticleSystem::collide(ParticlePtr part, SpherePtr sphere) { Vector3<float> distance = part->getPosition() - sphere->getRigidBody()->getPosition(); float radiusSum = sphere->getRadius(); //test auf collision if (distance.length() <= radiusSum) // sonst nur radiusSum { //berechnung normalB und contactPoint distance.normalize(); const Vector3<float>& normalB = distance; //const Vector3<float>& contactPoint = part->getPosition(); //+ 0.01f * normalB; // folgender Abschnitt aus: // CollisionSystem::collisionResponse(part, sphere, contactPoint, normalB); //berechnung der relativen geschwindigkeit in richtung normalB const Vector3<float>& velocityA = part->getVelocity(); const Vector3<float>& velocityB = sphere->getRigidBody()->getVelocity(); Vector3<float> velA = part->getVelocity(); Vector3<float> forceA = part->getForce(); Vector3<float> velB = sphere->getRigidBody()->getVelocity(); Vector3<float> forceB = sphere->getRigidBody()->getForce(); const Vector3<float>& vR = velocityA - velocityB; float vN = dot(vR, normalB); //behandlung für colliding contact if (vN <= 0.5) { //Kraftberechnung für Resting Contact //Todo //--------------bisherige Behandlung---------------------------------------------- Vector3<float> normale = -1 * part->getPosition() + sphere->getRigidBody()->getPosition(); normale.normalize(); float vADoN = dot(velA, normale); Vector3<float> vS = normale * vADoN; float fADoN = dot(forceA, normale); Vector3<float> fS = normale * fADoN; float vBDoN = dot (velA, normale); Vector3<float> vS2 = normale * vBDoN; float fBDoN = dot (forceB, normale); Vector3<float> fS2 = normale * fBDoN; Vec3 nullvector = Vec3(0.0,0.0,0.0); Vector3<float> force = part->getForce(); force.normalize(); if (dot (force, normale) > 0 ){ part->setVelocity(part->getVelocity() - vS); part->setVelocity(part->getVelocity() * 0.9f); // Wert: 0.75 part->setVelocity(part->getVelocity() + sphere->getRigidBody()->getVelocity()); part->addForce((-1.f) * fS); part->setForce(part->getForce() * 0.9f); // Wert: 0.75 part->addForce(sphere->getRigidBody()->getForce()); if (!(sphere->getRigidBody()->getVelocity() == Vec3(0.0,0.0,0.0))){ sphere->getRigidBody()->addForce((-0.02f) * fS2); sphere->getRigidBody()-> setVelocity(sphere->getRigidBody()->getVelocity() - (vS2 * 0.02f)); } part->setIsColliding(true); }else if (dot (force, normale) < 0){ part->setVelocity(part->getVelocity() + vS); part->setVelocity(part->getVelocity() * 0.9f); // Wert: 0.75 part->setVelocity(part->getVelocity() + sphere->getRigidBody()->getVelocity()); part->addForce((1.0) * fS); part->setForce(part->getForce() * 0.9f); // Wert: 0.75 part->addForce(sphere->getRigidBody()->getForce()); if (!(sphere->getRigidBody()->getVelocity() == Vec3(0.0,0.0,0.0))){ sphere->getRigidBody()->addForce((-0.02f) * fS2); sphere->getRigidBody() ->setVelocity(sphere->getRigidBody()->getVelocity() - (vS2 * 0.02f)); } } //----------------alte Behandlung------------------------------------------------- //berechnung der impuls-kraft in richtung normalB /* float damping = 0.5f; //(0.6 + sphere->getBounciness()) / 2.0; float invMassA, invMassB = 0.0; Matrix<float> invTensorA(3,3); Matrix<float> invTensorB(3,3); Vec3 rA = part->getForce(); Vec3 rB = sphere->getRigidBody()->getForce(); //test ob dynamisch if(part->getIsDynamicFlag()) { invMassA = 1.0f / part->getMass(); } else invMassA = 0.0; if(sphere->getRigidBody()->getIsDynamicFlag()) { invMassB = 1.0f / sphere->getMass(); invTensorB = sphere->getRigidBody()->getInvWorldInertiaTensor(); } else invMassB = 0.0; const Vector3<float>& crossA = cross(rA,normalB); const Vector3<float>& crossB = cross(rB,normalB); const Vector3<float>& uA = invTensorA * crossA; const Vector3<float>& uB = invTensorB * crossB; float fNum = -(1+damping)*(dot(normalB,(velocityA - velocityB))); float fDenom = invMassA + invMassB + dot(crossA,uA)+dot(crossB,uB); float f = fNum / fDenom; Vector3<float> impulseForce = 9.5 * f * normalB; //jetzt: part->setVelocity(part->getVelocity() + impulseForce/part->getMass()); */ //----------neue Behandlung------------------------------------------------------- ////berechnung der impuls-kraft in richtung normalB //float damping = 0.1f; //float invMassA = part->getInvMass(); // float invMassB = sphere->getInvMass(); // // // calculate impulse //float fNum = -(/*1+*/damping)*(dot(normalB,(velocityB - velocityA))); //float fDenom = invMassA + invMassB; // //float impulseMagnitude = fNum / fDenom; //if (impulseMagnitude < 0){ //Vector3<float> impulseForce = impulseMagnitude * normalB; // //if (part->getInvMass()!=0) // part->setVelocity(part->getVelocity() - (impulseForce/invMassA)); // //if (sphere->getInvMass()!=0) // sphere->setVelocity(sphere->getVelocity() - (impulseForce * invMassB)); //} //-------------------------------------------------------------------------------- } } }