void JelloMesh::ComputeForces(ParticleGrid& grid) { // Add external froces to all points for (int i = 0; i < m_rows+1; i++) { for (int j = 0; j < m_cols+1; j++) { for (int k = 0; k < m_stacks+1; k++) { Particle& p = GetParticle(grid, i,j,k); p.force = m_externalForces * p.mass; } } } // Update springs for(unsigned int i = 0; i < m_vsprings.size(); i++) { Spring& spring = m_vsprings[i]; Particle& a = GetParticle(grid, spring.m_p1); Particle& b = GetParticle(grid, spring.m_p2); // TODO vec3 xab = a.position - b.position; vec3 vab = a.velocity - b.velocity; vec3 force_change = - spring.m_Ks*(sqrt(xab*xab)-spring.m_restLen)*xab/(sqrt(xab*xab)) - spring.m_Kd*(vab*xab)*xab/(xab*xab); a.force += force_change; b.force -= force_change; } }
int SpringSystem::CreateSpring(int particleId1, int particleId2) { Spring* spr = GetSpring(particleId1, particleId2); if (spr) { std::cout << "CreateSpring: found duplicate spring.\n"; return spr->GetId(); } int n = m_springs.size(); spr = new Spring(n, GetParticle(particleId1), GetParticle(particleId2)); m_springs.push_back(spr); // Add this spring to the map of springs connected to each particle m_springMap[particleId1].insert(spr); m_springMap[particleId2].insert(spr); // We have just set the natural length of the spring. // Set the min and max lengths based on this. // TODO This is a property of the squishy thing float natLen = spr->GetNaturalLength(); // TODO TEMP TEST spr->SetMaxLength(natLen * 1.5f); spr->SetMinLength(natLen * 0.7f); return n; }
void Physics_Cloth::CreateHooks() { // Move the particles closer together make it look more like a curtain for (int i = 0; i < (m_particlesWidthCount - 1) / 2; i++) { // Determine the ratio of movement float ratio = 1.0f - ((float)i / ((float)(m_particlesWidthCount - 1) / 2.0f)); GetParticle(i, 0)->Move({ ratio, 0.0f, 0.0f }); GetParticle((m_particlesWidthCount - i - 1), 0)->Move({ -ratio, 0.0f, 0.0f }); } // Calculate the exact distance apart the hooks should be float hookDist = (float)m_width / (float)(m_hooks - 1); int increment = 0; for (int i = 0; i < m_hooks; i++) { // Calculate a rounded distance so the hook points line up with particle points int roundedDist = (int)round(increment * hookDist); if (i % 2 == 0) // Hook particle on the left { HookParticle(GetParticle(roundedDist, 0)); } else // Hook particle on the right { HookParticle(GetParticle((m_width - roundedDist), 0)); // Increment the distance every odd/second hook increment++; } } }
//------------------------------------------------------------------ // collide joints with each other. Skip particles too close //------------------------------------------------------------------ bool CChain::SelfCollide() { bool bCollided = false; for(int i = 0; i < GetNumParticles(); i ++) { for (int j = i + m_iSelfCollisionStep; j < GetNumParticles(); j ++) { bCollided |= GetParticle(i).Collide(GetParticle(j)); } } return bCollided; }
bool ECHARM_multiple_scattering::DoScatteringAxial(ECHARM_distribution *vDistribution, unsigned int vCrystalComponent) { double vEnergyTotal = GetParticle()->GetMomentumVector()->GetModule(); double vEnergyVariation = vDistribution->GenerateNumber(); vEnergyTotal += vEnergyVariation; if(vEnergyTotal>0.){ double vRandomAngle = 2 * M_PI * drand48(); GetParticle()->GetMomentumVector()->AddX( vEnergyVariation * cos(vRandomAngle) ); GetParticle()->GetMomentumVector()->AddY( vEnergyVariation * sin(vRandomAngle) ); GetParticle()->GetMomentumVector()->ScaleModuleTo(vEnergyTotal); } else return false; return true; }
void SpringSys::SetInitialVelocity (Point3 p, int index) { if (index < 0 || index > parts.length() ) return; GetParticle(index)->SetVel(p); return; }
//------------------------------------------------------------------------------ // void gosFX::CardCloud::CreateNewParticle(uint32_t index, Stuff::Point3D* translation) { // Check_Object(this); // //------------------------------------------------------------------- // Let our parent do creation, then turn on the particle in the cloud //------------------------------------------------------------------- // SpinningCloud::CreateNewParticle(index, translation); m_cloudImplementation->TurnOn(index); _ASSERT(m_cloudImplementation->IsOn(index)); // //----------------------------- // Figure out the particle size //----------------------------- // Specification* spec = GetSpecification(); Check_Object(spec); Particle* particle = GetParticle(index); Check_Object(particle); particle->m_halfY = spec->m_halfHeight.ComputeValue(m_age, particle->m_seed); particle->m_halfX = particle->m_halfY * spec->m_aspectRatio.ComputeValue(m_age, particle->m_seed); particle->m_radius = Stuff::Sqrt(particle->m_halfX * particle->m_halfX + particle->m_halfY * particle->m_halfY); }
//------------------------------------------------------------------------------ // bool gosFX::ShapeCloud::AnimateParticle( unsigned index, const Stuff::LinearMatrix4D *world_to_new_local, Stuff::Time till ) { Check_Object(this); // //----------------------------------------- // Animate the parent then get our pointers //----------------------------------------- // if (!SpinningCloud::AnimateParticle(index, world_to_new_local, till)) return false; Set_Statistic(Shape_Count, Shape_Count+1); Specification *spec = GetSpecification(); Check_Object(spec); Particle *particle = GetParticle(index); Check_Object(particle); Stuff::Scalar seed = particle->m_seed; Stuff::Scalar age = particle->m_age; // //------------------ // Animate the color //------------------ // particle->m_color.red = spec->m_pRed.ComputeValue(age, seed); particle->m_color.green = spec->m_pGreen.ComputeValue(age, seed); particle->m_color.blue = spec->m_pBlue.ComputeValue(age, seed); particle->m_color.alpha = spec->m_pAlpha.ComputeValue(age, seed); return true; }
void SpringSys::SetInitialBoneStates(Tab<Matrix3> boneTMs) { for (int x = 0; x< GetParticles()->length(); x++) { SSParticle *p = GetParticle(x); for (int tmId = 0; tmId< boneTMs.Count(); tmId++) { for (int i=0;i<p->GetSprings()->length();i++) { if (tmId == p->GetSpring(i)->GetPointConstraint()->GetIndex()) { if (tmId == 0) p->GetSpring(i)->SetLength(Point3::Origin); else p->GetSpring(i)->SetLength( initPosTab[x] * Inverse(boneTMs[tmId]) ); p->GetSpring(i)->GetPointConstraint()->SetPos(initPosTab[x]); p->GetSpring(i)->GetPointConstraint()->SetVel(Point3::Origin); } } if (frameCache.bone.length() <= tmId) { SSConstraintPoint contBone = SSConstraintPoint(tmId); frameCache.bone.append(contBone); } } //frameCache.bone.SetCount(tmId+1); } }
void SpringSys::SetInitialPosition (Point3 p, int index) { if (index < 0 || index > parts.length() ) return; initPosTab[index] = p; GetParticle(index)->SetPos(p); return; }
double ECHARM_multiple_scattering_functions::EvaluateSingleScatteringEnergyVariationConstantBiryukov() //!< Biryukov book INTEGRATED OVER T [I,T_max]!! { double EnergyLoss = (4.0 * M_PI * pow(cElectronRadius,2.0) * cElectronMass); EnergyLoss *= (pow(fabs(fParticle->GetZ()),2.0)*fCrystal->GetZ()); EnergyLoss /= ( 2.0 * pow(GetParticle()->GetBeta(),2.0) ); EnergyLoss *= fCrossedMaterialLength; EnergyLoss *= fCrystal->GetNucleiDensity(); return EnergyLoss; }
//_____________________________________________________________________________ TParticle* amsvmc_MCStack::GetCurrentTrack() const { /// \return The current track particle TParticle* current = GetParticle(fCurrentTrack); if (!current) Warning("GetCurrentTrack", "Current track not found in the stack"); return current; }
//_____________________________________________________________________________ void amsvmc_MCStack::Print(Option_t* /*option*/) const { /// Print info for all particles. // cout << "amsvmc_MCStack Info " << endl; // cout << "Total number of particles: " << GetNtrack() << endl; // cout << "Number of primary particles: " << GetNprimary() << endl; for (Int_t i=0; i<GetNtrack(); i++) GetParticle(i)->Print(); }
void CChain::SetChain(const Vector& P0, const Vector& P1, int iNumParticles, int iRigidity, float fParticleRadius, float fParticleMass) { Free(); Allocate(iNumParticles, iNumParticles-1); if (iNumParticles < 2) return; if (iRigidity <= 0) iRigidity = 1; SetRigidity(iRigidity); //----------------------------------------------------------- // copy particles //----------------------------------------------------------- Vector P = P0; Vector D = (P0 - P1) / ((float) iNumParticles); for(int i = 0; i < iNumParticles; i ++) { AddParticle(CParticle(P, fParticleRadius, (i != 0)? fParticleMass : 0.0f)); P += D; } //------------------------------------------------------------------ // link particles together //------------------------------------------------------------------ for(int i = 0; i < iNumParticles-1; i ++) { AddConstraint(CLinConstraint(&GetParticle(i), &GetParticle(i+1))); P += D; } ComputeBoundingSphere(); m_iSelfCollisionStep = 2; }
void Physics_Cloth::AddForce(v3float _force, eForceType _forceType, bool _selected) { switch (_forceType) { case FT_GENERIC: // Adds the same generic force to each particle { for (int i = 0; i < m_particleCount; i++) { if (m_pParticles[i].GetSelectedState() == _selected) { m_pParticles[i].AddForce(_force); } } } break; case FT_WIND: // Add a wind force that bases the strength of the force on the normal of triangles { // Multiply the force direction by the current wind speed _force = _force.Normalise() * m_windSpeed; // Cycle through the particles based on the rows and columns (Due to using a triangle strip topology) for (int x = 0; x < m_particlesWidthCount - 1; x++) { for (int y = 0; y < m_particlesHeightCount - 1; y++) { // Add wind force to both triangles in the current grid selection AddWindForceForTri(GetParticle(x + 1, y + 1), GetParticle(x, y + 1), GetParticle(x, y), _force); AddWindForceForTri(GetParticle(x, y), GetParticle(x + 1, y), GetParticle(x + 1, y + 1), _force); } } } break; default:break; } }
void JelloMesh::DrawSprings(double a) { const ParticleGrid& g = m_vparticles; glBegin(GL_LINES); for (unsigned int i = 0; i < m_vsprings.size(); i++) { if (!(m_vsprings[i].m_type & m_drawflags)) continue; if (isInterior(m_vsprings[i])) continue; switch (m_vsprings[i].m_type) { case BEND: glColor4f(1.0, 1.0, 0.0, a); break; case STRUCTURAL: glColor4f(1.0, 1.0, 0.0, a); break; case SHEAR: glColor4f(0.0, 1.0, 1.0, a); break; }; vec3 p1 = GetParticle(g, m_vsprings[i].m_p1).position; vec3 p2 = GetParticle(g, m_vsprings[i].m_p2).position; glVertex3f(p1[0], p1[1], p1[2]); glVertex3f(p2[0], p2[1], p2[2]); } glEnd(); }
void JelloMesh::ResolveCollisions(ParticleGrid& grid) { for(unsigned int i = 0; i < m_vcollisions.size(); i++) { Intersection& result = m_vcollisions[i]; Particle& pt = GetParticle(grid, result.m_p); vec3 normal = result.m_normal; float dist = result.m_distance; // TODO if(pt.velocity*normal<0) pt.force += g_penaltyKs*normal*dist + g_penaltyKd*(pt.velocity*normal)*normal; } }
void JelloMesh::ResolveContacts(ParticleGrid& grid) { for (unsigned int i = 0; i < m_vcontacts.size(); i++) { // const Intersection& contact = m_vcontacts[i]; Intersection& contact = m_vcontacts[i]; Particle& p = GetParticle(grid, contact.m_p); vec3 normal = contact.m_normal; float dist = contact.m_distance; // TODO p.position += normal*dist; p.velocity += 2*(-p.velocity*normal)*normal; } }
void ECHARM_simulation_integration_averaged::PreInitializeEnergyToDechannel() { double vTempEnergy; double vX; fPlanarEnergyToDechannel.clear(); double vPotentialBarrier = GetStrip()->GetCrystal()->GetPlanarElectricCharacteristic(0.0,0); #ifdef ROOT_ std::string vHistoName = "hEnergyToDechannel_prf" + GetStrip()->GetRadiusValueAsStringText() + "_" + GetStrip()->GetLengthValueAsStringText(); TH1F *hEnergyToDechannel = new TH1F( vHistoName.c_str(),"hEnergyToDechannel;Interplanar Distance [#AA]",GetIntegrationStepNumberPlanar(),0.,GetStrip()->GetCrystal()->GetDirectPeriodPlanar() ); #endif for(unsigned int i = 0; i < GetIntegrationStepNumberPlanar(); i++) { vX = double(i) / double(GetIntegrationStepNumberPlanar()) * GetStrip()->GetCrystal()->GetDirectPeriodPlanar(); vTempEnergy = GetStrip()->GetCrystal()->GetPlanarElectricCharacteristic( vX , 0); //std::cout << vTempEnergy << " "; if( StripIsBentX() ) vTempEnergy += ( GetParticle()->GetMomentumVector()->GetZ() * GetParticle()->GetBeta() * vX / GetStrip()->GetCurvatureRadius()->GetX() ); //std::cout << GetParticle()->GetMomentumVector()->GetZ() << " " << GetParticle()->GetBeta() << " " << GetStrip()->GetCurvatureRadius()->GetX() << " " << vX << " "; vTempEnergy -= vPotentialBarrier; vTempEnergy += ( GetParticle()->GetBeta() * fSquare(GetParticle()->GetMomentumVector()->GetX()) / GetParticle()->GetMomentumVector()->GetZ()); //std::cout << vTempEnergy << " "; if(vTempEnergy > 0.0) vTempEnergy = -0.; vTempEnergy *= (-1.); fPlanarEnergyToDechannel.push_back(vTempEnergy); //std::cout << vTempEnergy << std::endl; // DA TOGLIERE #ifdef ROOT_ hEnergyToDechannel->SetBinContent(i+1,vTempEnergy); #endif } }
void JelloMesh::EulerIntegrate(double dt) { //TODO for (int i = 0; i < m_rows+1; i++) { for (int j = 0; j < m_cols+1; j++) { for (int k = 0; k < m_stacks+1; k++) { Particle& p = GetParticle(m_vparticles, i,j,k); p.velocity = p.velocity + dt*p.force/p.mass; p.position = p.position + dt*p.velocity; } } } }
void JelloMesh::CheckForCollisions(ParticleGrid& grid, const World& world) { m_vcontacts.clear(); m_vcollisions.clear(); for (int i = 0; i < m_rows+1; i++) { for (int j = 0; j < m_cols+1; j++) { for (int k = 0; k < m_stacks+1; k++) { Particle& p = GetParticle(grid, i,j,k); // 1. Check collisions with world objects for (unsigned int l = 0; l < world.m_shapes.size(); l++) { Intersection intersection; if (world.m_shapes[l]->GetType() == World::CYLINDER && CylinderIntersection(p, (World::Cylinder*) world.m_shapes[l], intersection)) { if(intersection.m_type == CONTACT) m_vcontacts.push_back(intersection); else m_vcollisions.push_back(intersection); } else if (world.m_shapes[l]->GetType() == World::GROUND && FloorIntersection(p, intersection)) { if(intersection.m_type == CONTACT) m_vcontacts.push_back(intersection); else m_vcollisions.push_back(intersection); } else if (world.m_shapes[l]->GetType() == World::SPHERE && SphereIntersection(p, (World::Sphere*) world.m_shapes[l], intersection)) { if(intersection.m_type == CONTACT) m_vcontacts.push_back(intersection); else m_vcollisions.push_back(intersection); } if (world.m_shapes[l]->GetType() == World::CUBE && CubeIntersection(p, (World::Cube*) world.m_shapes[l], intersection)) { if(intersection.m_type == CONTACT) m_vcontacts.push_back(intersection); else m_vcollisions.push_back(intersection); } } } } } }
void JelloMesh::DrawCollisionNormals() { const ParticleGrid& g = m_vparticles; glBegin(GL_LINES); glColor3f(0.0, 1.0, 0.0); for(unsigned int i = 0; i < m_vcollisions.size(); i++) { Intersection intersection = m_vcollisions[i]; if (isInterior(intersection.m_p)) continue; const Particle& pt = GetParticle(g, intersection.m_p); vec3 normal = intersection.m_normal; vec3 end = pt.position + 0.2 * normal; glVertex3f(pt.position[0], pt.position[1], pt.position[2]); glVertex3f(end[0], end[1], end[2]); } glEnd(); }
//------------------------------------------------------------------------------ // void gosFX::ShapeCloud::CreateNewParticle( unsigned index, Stuff::Point3D *translation ) { Check_Object(this); // //------------------------------------------------------------------- // Let our parent do creation, then turn on the particle in the cloud //------------------------------------------------------------------- // SpinningCloud::CreateNewParticle(index, translation); Specification *spec = GetSpecification(); Check_Object(spec); Particle *particle = GetParticle(index); Check_Object(particle); particle->m_radius = spec->m_radius; }
AxisAlignedBox MeteorProjectile::GetBoundingBox() { return ParticleSystem::GetBoundingBox(); // Uses one random particles distance from the center. GLib::Particle* particle = GetParticle(1); if(particle == nullptr) return XNA::AxisAlignedBox(); XMFLOAT3 pos = particle->GetPosition(); XMFLOAT3 diff = pos - GetPosition(); float dist = sqrt(diff.x*diff.x + diff.y * diff.y + diff.z*diff.z); XNA::AxisAlignedBox box; box.Center = GetPosition(); box.Extents = XMFLOAT3(dist, dist, dist); char buffer[244]; sprintf(buffer, "DIST MFER: %f\n", dist); OutputDebugString(buffer); return box; }
double ECHARM_simulation_integration_averaged::GetElectricalCharactericticPlanarAveragedOverOnePeriod(unsigned int vType) { ECHARM_threevector *vPositionStart = new ECHARM_threevector(); ECHARM_threevector *vMomentumStart = new ECHARM_threevector(); vPositionStart->CopyFrom(GetParticle()->GetPositionVector()); vMomentumStart->CopyFrom(GetParticle()->GetMomentumVector()); double vDensity = 0.0; do { UpdateStepLengthPlanar(); DoIntegrationStepPlanarVelocityVerlet(); vDensity += GetStrip()->GetCrystal()->GetPlanarElectricCharacteristic(GetParticle()->GetPositionVector()->GetX(),vType) * GetStepLength(); } while ( GetParticle()->GetPositionVector()->GetZ() < GetStrip()->GetDimension()->GetZ()); GetParticle()->GetPositionVector()->CopyFrom(vPositionStart); GetParticle()->GetMomentumVector()->CopyFrom(vMomentumStart); return vDensity; }
//------------------------------------------------------------------------------ // bool gosFX::PointCloud::AnimateParticle( uint32_t index, const Stuff::LinearMatrix4D* world_to_new_local, Stuff::Time till ) { Check_Object(this); // //----------------------------------------------------------------------- // If this cloud is unparented, we need to transform the point from local // space into world space and set the internal position/velocity pointers // to these temporary values //----------------------------------------------------------------------- // Particle* particle = GetParticle(index); Check_Object(particle); float age = particle->m_age; if(age >= 1.0f) return false; Set_Statistic(Point_Count, Point_Count + 1); Stuff::Vector3D* velocity = &particle->m_localLinearVelocity; Stuff::Point3D* translation = &m_P_localTranslation[index]; int32_t sim_mode = GetSimulationMode(); if(sim_mode == DynamicWorldSpaceSimulationMode) { Check_Object(translation); Check_Object(velocity); particle->m_worldLinearVelocity.Multiply(*velocity, m_localToWorld); particle->m_worldTranslation.Multiply(*translation, m_localToWorld); translation = &particle->m_worldTranslation; velocity = &particle->m_worldLinearVelocity; } Check_Object(translation); Check_Object(velocity); // //------------------------------------------------------------------ // First, calculate the drag on the particle. Drag can never assist // velocity //------------------------------------------------------------------ // float seed = particle->m_seed; Specification* spec = GetSpecification(); Check_Object(spec); Stuff::Vector3D ether; ether.x = spec->m_pEtherVelocityX.ComputeValue(age, seed); ether.y = spec->m_pEtherVelocityY.ComputeValue(age, seed); ether.z = spec->m_pEtherVelocityZ.ComputeValue(age, seed); Stuff::Vector3D accel(Stuff::Vector3D::Identity); // //------------------------------------------------------------------- // Deal with pseudo-world simulation. In this mode, we interpret the // forces as if they are already in worldspace, and we transform them // back to local space //------------------------------------------------------------------- // float drag = -spec->m_pDrag.ComputeValue(age, seed); Max_Clamp(drag, 0.0f); if(sim_mode == StaticWorldSpaceSimulationMode) { Stuff::LinearMatrix4D world_to_effect; world_to_effect.Invert(m_localToWorld); Stuff::Vector3D local_ether; local_ether.MultiplyByInverse(ether, world_to_effect); Stuff::Vector3D rel_vel; rel_vel.Subtract(*velocity, local_ether); accel.Multiply(rel_vel, drag); // //----------------------------------------- // Now, add in acceleration of the particle //----------------------------------------- // Stuff::Vector3D world_accel; world_accel.x = spec->m_pAccelerationX.ComputeValue(age, seed); world_accel.y = spec->m_pAccelerationY.ComputeValue(age, seed); world_accel.z = spec->m_pAccelerationZ.ComputeValue(age, seed); Stuff::Vector3D local_accel; local_accel.Multiply(world_accel, world_to_effect); accel += local_accel; } // //---------------------------------------------------------------------- // Otherwise, just add the forces in the same space the particles are in //---------------------------------------------------------------------- // else { Stuff::Vector3D rel_vel; rel_vel.Subtract(*velocity, ether); accel.Multiply(rel_vel, drag); // //----------------------------------------- // Now, add in acceleration of the particle //----------------------------------------- // accel.x += spec->m_pAccelerationX.ComputeValue(age, seed); accel.y += spec->m_pAccelerationY.ComputeValue(age, seed); accel.z += spec->m_pAccelerationZ.ComputeValue(age, seed); } // //------------------------------------------------- // Compute the particle's new velocity and position //------------------------------------------------- // float time_slice = static_cast<float>(till - m_lastRan); velocity->AddScaled(*velocity, accel, time_slice); translation->AddScaled(*translation, *velocity, time_slice); // //--------------------------------------------------------------------- // If we are unparented, we need to transform the velocity and position // data back into the NEW local space //--------------------------------------------------------------------- // if(sim_mode == DynamicWorldSpaceSimulationMode) { Check_Object(world_to_new_local); particle->m_localLinearVelocity.Multiply( particle->m_worldLinearVelocity, *world_to_new_local ); m_P_localTranslation[index].Multiply( particle->m_worldTranslation, *world_to_new_local ); } // //------------------ // Animate the color //------------------ // Check_Pointer(m_P_color); m_P_color[index].red = spec->m_pRed.ComputeValue(age, seed); m_P_color[index].green = spec->m_pGreen.ComputeValue(age, seed); m_P_color[index].blue = spec->m_pBlue.ComputeValue(age, seed); m_P_color[index].alpha = spec->m_pAlpha.ComputeValue(age, seed); return true; }
bool Physics_Cloth::ResetCloth() { // Clear Memory ReleaseCloth(); ReleaseSelected(); m_contraints.clear(); m_nextIndex = 0; if (m_initialisedParticles == false) { ReleasePtr(m_pMesh); ReleasePtrArray(m_pParticles); // Create memory for all the particles m_particleCount = m_particlesWidthCount * m_particlesHeightCount; m_pParticles = new Physics_Particle[m_particleCount]; m_pVertices = new TVertexColor[m_particleCount]; // Calculate how many indices there are with be based on how many particles there are using line list int immediateConstraintCount = (m_particlesWidthCount - 1) * (m_particlesHeightCount - 1) * 4 + (m_particlesWidthCount - 1) + (m_particlesHeightCount - 1); int secondaryConstraintCount = 0; if (m_complexWeave == true) { // Calculate the secondary indices count only if the weave is set to complex secondaryConstraintCount = (m_particlesWidthCount - 2) * (m_particlesHeightCount - 2) * 4 + ((m_particlesWidthCount - 2) * 2) + ((m_particlesHeightCount - 2) * 2); } // Create the indices buffer with the amount of calculated constraints m_indexCount = (immediateConstraintCount + secondaryConstraintCount) * 2; m_pIndices = new DWORD[m_indexCount]; } // Cycle through all the particles for (int col = 0; col < m_particlesWidthCount; col++) { for (int row = 0; row < m_particlesHeightCount; row++) { // Calculate the position based on the particles row and column v3float pos; pos.x = m_width * (col / (float)m_width) - ((float)m_width / 2.0f); pos.y = -m_height * (row / (float)m_height) + ((float)m_height / 2.0f); pos.z = 0.0f; int index = row * m_particlesWidthCount + col; if (m_initialisedParticles == false) { // First time. Initialise m_pVertices[index] = { { pos.x, pos.y, pos.z }, d3dxColors::White }; VALIDATE(m_pParticles[index].Initialise(index, &m_pVertices[index], pos, m_timeStep, m_damping)); } else { // Particle has already been initialized so just reset the position m_pParticles[index].Reset(); m_pParticles[index].SetPosition(pos, true); m_pVertices[index].color = d3dxColors::White; } } } // Connect Particles that are immediately to the right and below (include diagonals) for (int col = 0; col < m_particlesWidthCount; col++) { for (int row = 0; row < m_particlesHeightCount; row++) { // Particle to the Right exists if (col < m_particlesWidthCount - 1) { VALIDATE(MakeConstraint(GetParticleIndex(col, row), GetParticleIndex(col + 1, row), true)); // Add the constraint index to each attached particle GetParticle(col, row)->AddContraintIndex(m_contraints.size() - 1); GetParticle(col + 1, row)->AddContraintIndex(m_contraints.size() - 1); } // Particle below exists if (row < m_particlesHeightCount - 1) { VALIDATE(MakeConstraint(GetParticleIndex(col, row), GetParticleIndex(col, row + 1), true)); // Add the constraint index to each attached particle GetParticle(col, row)->AddContraintIndex(m_contraints.size() - 1); GetParticle(col, row + 1)->AddContraintIndex(m_contraints.size() - 1); } // Particle to the right and below exists if ((col < m_particlesWidthCount - 1) && (row < m_particlesHeightCount - 1)) { VALIDATE(MakeConstraint(GetParticleIndex(col, row), GetParticleIndex(col + 1, row + 1), true)); // Add the constraint index to each attached particle GetParticle(col, row)->AddContraintIndex(m_contraints.size() - 1); GetParticle(col + 1, row + 1)->AddContraintIndex(m_contraints.size() - 1); VALIDATE(MakeConstraint(GetParticleIndex(col + 1, row), GetParticleIndex(col, row + 1), true)); // Add the constraint index to each attached particle GetParticle(col + 1, row)->AddContraintIndex(m_contraints.size() - 1); GetParticle(col, row + 1)->AddContraintIndex(m_contraints.size() - 1); } } } if (m_complexWeave == true) { // Connect Particles the are one step further away than previous loop for (int col = 0; col < m_particlesWidthCount; col++) { for (int row = 0; row < m_particlesHeightCount; row++) { // Particle to the Right exists if (col < m_particlesWidthCount - 2) { VALIDATE(MakeConstraint(GetParticleIndex(col, row), GetParticleIndex(col + 2, row), false)); // Add the constraint index to each attached particle GetParticle(col, row)->AddContraintIndex(m_contraints.size() - 1); GetParticle(col + 2, row)->AddContraintIndex(m_contraints.size() - 1); } // Particle below exists if (row < m_particlesHeightCount - 2) { VALIDATE(MakeConstraint(GetParticleIndex(col, row), GetParticleIndex(col, row + 2), false)); // Add the constraint index to each attached particle GetParticle(col, row)->AddContraintIndex(m_contraints.size() - 1); GetParticle(col, row + 2)->AddContraintIndex(m_contraints.size() - 1); } // Particle to the right and below exists if ((col < m_particlesWidthCount - 2) && (row < m_particlesHeightCount - 2)) { VALIDATE(MakeConstraint(GetParticleIndex(col, row), GetParticleIndex(col + 2, row + 2), false)); // Add the constraint index to each attached particle GetParticle(col, row)->AddContraintIndex(m_contraints.size() - 1); GetParticle(col + 2, row + 2)->AddContraintIndex(m_contraints.size() - 1); VALIDATE(MakeConstraint(GetParticleIndex(col + 2, row), GetParticleIndex(col, row + 2), false)); // Add the constraint index to each attached particle GetParticle(col + 2, row)->AddContraintIndex(m_contraints.size() - 1); GetParticle(col, row + 2)->AddContraintIndex(m_contraints.size() - 1); } } } } if (m_initialisedParticles == false) { // Create a new Cloth Mesh m_pMesh = new DX10_Mesh(); VALIDATE(m_pMesh->InitialiseCloth(m_pRenderer, m_pVertices, m_pIndices, m_particleCount, m_indexCount, sizeof(TVertexColor), D3D10_PRIMITIVE_TOPOLOGY_LINELIST, D3D10_USAGE_DYNAMIC, D3D10_USAGE_DYNAMIC)); } // Create the hooks and pin the cloth CreateHooks(); // Add a wind force of 1 down the Z axis to settle the cloth AddForce({ 0.0f, 0.0f, 1.0f }, FT_GENERIC, false); Process(CT_NONE); m_initialisedParticles = true; return true; }
//------------------------------------------------------------------------------ // void gosFX::CardCloud::Draw(DrawInfo* info) { // Check_Object(this); Check_Object(info); // //--------------------------------------------------------- // If we have active particles, set up the draw information //--------------------------------------------------------- // if (m_activeParticleCount) { MidLevelRenderer::DrawEffectInformation dInfo; dInfo.effect = m_cloudImplementation; Specification* spec = GetSpecification(); Check_Object(spec); dInfo.state.Combine(info->m_state, spec->m_state); dInfo.clippingFlags = info->m_clippingFlags; Stuff::LinearMatrix4D local_to_world; local_to_world.Multiply(m_localToParent, *info->m_parentToWorld); dInfo.effectToWorld = &local_to_world; // //-------------------------------------------------------------- // Check the orientation mode. The first case is XY orientation //-------------------------------------------------------------- // uint32_t i; uint32_t vert = 0; if (spec->m_alignZUsingX) { if (spec->m_alignZUsingY) { // //----------------------------------------- // Get the camera location into local space //----------------------------------------- // Stuff::Point3D camera_in_world(info->m_clipper->GetCameraToWorldMatrix()); Stuff::Point3D camera_in_cloud; camera_in_cloud.MultiplyByInverse(camera_in_world, local_to_world); // //-------------------------------------- // Spin through all the active particles //-------------------------------------- // for (i = 0; i < m_activeParticleCount; i++) { Particle* particle = GetParticle(i); Check_Object(particle); if (particle->m_age < 1.0f) { // //-------------------------------- // Build the local to cloud matrix //-------------------------------- // Stuff::Vector3D direction_in_cloud; direction_in_cloud.Subtract(camera_in_cloud, particle->m_localTranslation); Stuff::LinearMatrix4D card_to_cloud; card_to_cloud.BuildRotation(particle->m_localRotation); card_to_cloud.AlignLocalAxisToWorldVector( direction_in_cloud, Stuff::Z_Axis, Stuff::Y_Axis, Stuff::X_Axis); card_to_cloud.BuildTranslation(particle->m_localTranslation); // //------------------------------------------------- // Figure out the scale, then build the four points //------------------------------------------------- // float scale = particle->m_scale; m_P_vertices[vert++].Multiply(Stuff::Point3D(scale * particle->m_halfX, -scale * particle->m_halfY, 0.0f), card_to_cloud); m_P_vertices[vert++].Multiply(Stuff::Point3D(-scale * particle->m_halfX, -scale * particle->m_halfY, 0.0f), card_to_cloud); m_P_vertices[vert++].Multiply(Stuff::Point3D(-scale * particle->m_halfX, scale * particle->m_halfY, 0.0f), card_to_cloud); m_P_vertices[vert++].Multiply(Stuff::Point3D(scale * particle->m_halfX, scale * particle->m_halfY, 0.0f), card_to_cloud); } else vert += 4; } } // //----------------------- // Handle X-only rotation //----------------------- // else { // //----------------------------------------- // Get the camera location into local space //----------------------------------------- // Stuff::Point3D camera_in_world(info->m_clipper->GetCameraToWorldMatrix()); Stuff::Point3D camera_in_cloud; camera_in_cloud.MultiplyByInverse(camera_in_world, local_to_world); // //-------------------------------------- // Spin through all the active particles //-------------------------------------- // for (i = 0; i < m_activeParticleCount; i++) { Particle* particle = GetParticle(i); Check_Object(particle); if (particle->m_age < 1.0f) { // //-------------------------------- // Build the local to cloud matrix //-------------------------------- // Stuff::Vector3D direction_in_cloud; direction_in_cloud.Subtract(camera_in_cloud, particle->m_localTranslation); Stuff::LinearMatrix4D card_to_cloud; card_to_cloud.BuildRotation(particle->m_localRotation); card_to_cloud.AlignLocalAxisToWorldVector( direction_in_cloud, Stuff::Z_Axis, Stuff::X_Axis, -1); card_to_cloud.BuildTranslation(particle->m_localTranslation); // //------------------------------------------------- // Figure out the scale, then build the four points //------------------------------------------------- // float scale = particle->m_scale; m_P_vertices[vert++].Multiply(Stuff::Point3D(scale * particle->m_halfX, -scale * particle->m_halfY, 0.0f), card_to_cloud); m_P_vertices[vert++].Multiply(Stuff::Point3D(-scale * particle->m_halfX, -scale * particle->m_halfY, 0.0f), card_to_cloud); m_P_vertices[vert++].Multiply(Stuff::Point3D(-scale * particle->m_halfX, scale * particle->m_halfY, 0.0f), card_to_cloud); m_P_vertices[vert++].Multiply(Stuff::Point3D(scale * particle->m_halfX, scale * particle->m_halfY, 0.0f), card_to_cloud); } else vert += 4; } } } // //------------------------------------------------------- // Each matrix needs to be aligned to the camera around Y //------------------------------------------------------- // else if (spec->m_alignZUsingY) { // //----------------------------------------- // Get the camera location into local space //----------------------------------------- // Stuff::Point3D camera_in_world(info->m_clipper->GetCameraToWorldMatrix()); Stuff::Point3D camera_in_cloud; camera_in_cloud.MultiplyByInverse(camera_in_world, local_to_world); // //-------------------------------------- // Spin through all the active particles //-------------------------------------- // for (i = 0; i < m_activeParticleCount; i++) { Particle* particle = GetParticle(i); Check_Object(particle); if (particle->m_age < 1.0f) { // //-------------------------------- // Build the local to cloud matrix //-------------------------------- // Stuff::Vector3D direction_in_cloud; direction_in_cloud.Subtract(camera_in_cloud, particle->m_localTranslation); Stuff::LinearMatrix4D card_to_cloud; card_to_cloud.BuildRotation(particle->m_localRotation); card_to_cloud.AlignLocalAxisToWorldVector( direction_in_cloud, Stuff::Z_Axis, Stuff::Y_Axis, -1); card_to_cloud.BuildTranslation(particle->m_localTranslation); // //------------------------------------------------- // Figure out the scale, then build the four points //------------------------------------------------- // float scale = particle->m_scale; m_P_vertices[vert++].Multiply( Stuff::Point3D(scale * particle->m_halfX, -scale * particle->m_halfY, 0.0f), card_to_cloud); m_P_vertices[vert++].Multiply(Stuff::Point3D(-scale * particle->m_halfX, -scale * particle->m_halfY, 0.0f), card_to_cloud); m_P_vertices[vert++].Multiply( Stuff::Point3D(-scale * particle->m_halfX, scale * particle->m_halfY, 0.0f), card_to_cloud); m_P_vertices[vert++].Multiply( Stuff::Point3D(scale * particle->m_halfX, scale * particle->m_halfY, 0.0f), card_to_cloud); } else vert += 4; } } // //--------------------------------------------------------------- // No alignment is necessary, so just multiply out all the active // particles //--------------------------------------------------------------- // else { for (i = 0; i < m_activeParticleCount; i++) { Particle* particle = GetParticle(i); Check_Object(particle); if (particle->m_age < 1.0f) { // //-------------------------------- // Build the local to cloud matrix //-------------------------------- // Stuff::LinearMatrix4D card_to_cloud; card_to_cloud.BuildRotation(particle->m_localRotation); card_to_cloud.BuildTranslation(particle->m_localTranslation); // //------------------------------------------------- // Figure out the scale, then build the four points //------------------------------------------------- // float scale = particle->m_scale; m_P_vertices[vert++].Multiply( Stuff::Point3D(scale * particle->m_halfX, -scale * particle->m_halfY, 0.0f), card_to_cloud); m_P_vertices[vert++].Multiply(Stuff::Point3D(-scale * particle->m_halfX, -scale * particle->m_halfY, 0.0f), card_to_cloud); m_P_vertices[vert++].Multiply( Stuff::Point3D(-scale * particle->m_halfX, scale * particle->m_halfY, 0.0f), card_to_cloud); m_P_vertices[vert++].Multiply( Stuff::Point3D(scale * particle->m_halfX, scale * particle->m_halfY, 0.0f), card_to_cloud); } else vert += 4; } } // //--------------------- // Now just do the draw //--------------------- // info->m_clipper->DrawEffect(&dInfo); } SpinningCloud::Draw(info); }
//------------------------------------------------------------------------------ // void gosFX::ShapeCloud::Draw(DrawInfo *info) { Check_Object(this); Check_Object(info); Check_Object(info->m_parentToWorld); // //---------------------------- // Set up the common draw info //---------------------------- // if (m_activeParticleCount) { MidLevelRenderer::DrawScalableShapeInformation dinfo; MidLevelRenderer::MLRShape *shape = GetSpecification()->m_shape; dinfo.clippingFlags.SetClippingState(0x3f); dinfo.worldToShape = NULL; Specification *spec = GetSpecification(); Check_Object(spec); dinfo.state.Combine(info->m_state, spec->m_state); dinfo.activeLights = NULL; dinfo.nrOfActiveLights = 0; dinfo.shape = shape; Stuff::LinearMatrix4D local_to_world; local_to_world.Multiply(m_localToParent, *info->m_parentToWorld); // //-------------------------------------------------------------- // Check the orientation mode. The first case is XY orientation //-------------------------------------------------------------- // unsigned i; if (spec->m_alignZUsingX) { if (spec->m_alignZUsingY) { // //----------------------------------------- // Get the camera location into local space //----------------------------------------- // Stuff::Point3D camera_in_world(info->m_clipper->GetCameraToWorldMatrix()); Stuff::Point3D camera_in_cloud; camera_in_cloud.MultiplyByInverse( camera_in_world, local_to_world ); for (unsigned i = 0; i < m_activeParticleCount; i++) { Particle *particle = GetParticle(i); Check_Object(particle); // //----------------------------------------------------------------- // If the particle is still alive, concatenate into world space and // issue the draw command //----------------------------------------------------------------- // if (particle->m_age < 1.0f) { Stuff::Vector3D direction_in_cloud; direction_in_cloud.Subtract( camera_in_cloud, particle->m_localTranslation ); Stuff::LinearMatrix4D shape_to_cloud; shape_to_cloud.BuildRotation(particle->m_localRotation); shape_to_cloud.AlignLocalAxisToWorldVector( direction_in_cloud, Stuff::Z_Axis, Stuff::Y_Axis, Stuff::X_Axis ); shape_to_cloud.BuildTranslation(particle->m_localTranslation); Stuff::LinearMatrix4D shape_to_world; shape_to_world.Multiply( shape_to_cloud, local_to_world ); dinfo.shapeToWorld = &shape_to_world; Stuff::Vector3D scale( particle->m_scale, particle->m_scale, particle->m_scale ); dinfo.scaling = &scale; dinfo.paintMe = &particle->m_color; info->m_clipper->DrawScalableShape(&dinfo); //magic 28112011 begin dinfo.shapeToWorld = NULL; dinfo.scaling = NULL; //magic 28112011 end } } } // //----------------------- // Handle X-only rotation //----------------------- // else { // //----------------------------------------- // Get the camera location into local space //----------------------------------------- // Stuff::Point3D camera_in_world(info->m_clipper->GetCameraToWorldMatrix()); Stuff::Point3D camera_in_cloud; camera_in_cloud.MultiplyByInverse( camera_in_world, local_to_world ); for (unsigned i = 0; i < m_activeParticleCount; i++) { Particle *particle = GetParticle(i); Check_Object(particle); // //----------------------------------------------------------------- // If the particle is still alive, concatenate into world space and // issue the draw command //----------------------------------------------------------------- // if (particle->m_age < 1.0f) { Stuff::Vector3D direction_in_cloud; direction_in_cloud.Subtract( camera_in_cloud, particle->m_localTranslation ); Stuff::LinearMatrix4D shape_to_cloud; shape_to_cloud.BuildRotation(particle->m_localRotation); shape_to_cloud.AlignLocalAxisToWorldVector( direction_in_cloud, Stuff::Z_Axis, Stuff::X_Axis, -1 ); shape_to_cloud.BuildTranslation(particle->m_localTranslation); Stuff::LinearMatrix4D shape_to_world; shape_to_world.Multiply( shape_to_cloud, local_to_world ); dinfo.shapeToWorld = &shape_to_world; Stuff::Vector3D scale( particle->m_scale, particle->m_scale, particle->m_scale ); dinfo.scaling = &scale; dinfo.paintMe = &particle->m_color; info->m_clipper->DrawScalableShape(&dinfo); //magic 28112011 begin dinfo.shapeToWorld = NULL; dinfo.scaling = NULL; //magic 28112011 end } } } } // //------------------------------------------------------- // Each matrix needs to be aligned to the camera around Y //------------------------------------------------------- // else if (spec->m_alignZUsingY) { // //----------------------------------------- // Get the camera location into local space //----------------------------------------- // Stuff::Point3D camera_in_world(info->m_clipper->GetCameraToWorldMatrix()); Stuff::Point3D camera_in_cloud; camera_in_cloud.MultiplyByInverse( camera_in_world, local_to_world ); for (unsigned i = 0; i < m_activeParticleCount; i++) { Particle *particle = GetParticle(i); Check_Object(particle); // //----------------------------------------------------------------- // If the particle is still alive, concatenate into world space and // issue the draw command //----------------------------------------------------------------- // if (particle->m_age < 1.0f) { Stuff::Vector3D direction_in_cloud; direction_in_cloud.Subtract( camera_in_cloud, particle->m_localTranslation ); Stuff::LinearMatrix4D shape_to_cloud; shape_to_cloud.BuildRotation(particle->m_localRotation); shape_to_cloud.AlignLocalAxisToWorldVector( direction_in_cloud, Stuff::Z_Axis, Stuff::Y_Axis, -1 ); shape_to_cloud.BuildTranslation(particle->m_localTranslation); Stuff::LinearMatrix4D shape_to_world; shape_to_world.Multiply( shape_to_cloud, local_to_world ); dinfo.shapeToWorld = &shape_to_world; Stuff::Vector3D scale( particle->m_scale, particle->m_scale, particle->m_scale ); dinfo.scaling = &scale; dinfo.paintMe = &particle->m_color; info->m_clipper->DrawScalableShape(&dinfo); //magic 28112011 begin dinfo.shapeToWorld = NULL; dinfo.scaling = NULL; //magic 28112011 end } } } // //--------------------------------------------------------------- // No alignment is necessary, so just multiply out all the active // particles //--------------------------------------------------------------- // else { for (i=0; i < m_activeParticleCount; i++) { Particle *particle = GetParticle(i); Check_Object(particle); // //----------------------------------------------------------------- // If the particle is still alive, concatenate into world space and // issue the draw command //----------------------------------------------------------------- // if (particle->m_age < 1.0f) { Stuff::LinearMatrix4D shape_to_cloud; shape_to_cloud.BuildTranslation(particle->m_localTranslation); shape_to_cloud.BuildRotation(particle->m_localRotation); Stuff::LinearMatrix4D shape_to_world; shape_to_world.Multiply( shape_to_cloud, local_to_world ); dinfo.shapeToWorld = &shape_to_world; Stuff::Vector3D scale( particle->m_scale, particle->m_scale, particle->m_scale ); dinfo.scaling = &scale; dinfo.paintMe = &particle->m_color; info->m_clipper->DrawScalableShape(&dinfo); //magic 28112011 begin dinfo.shapeToWorld = NULL; dinfo.scaling = NULL; //magic 28112011 end } } } } // //---------------------------- // Let our parent do its thing //---------------------------- // SpinningCloud::Draw(info); }
//------------------------------------------------------------------------------ // bool gosFX::PointCloud::Execute(ExecuteInfo* info) { Check_Object(this); Check_Object(info); // //---------------------------------------- // If we aren't supposed to execute, don't //---------------------------------------- // if(!IsExecuted()) return false; // //------------------------------------------------------------------ // Animate the particles. If it is time for us to die, return false //------------------------------------------------------------------ // if(!ParticleCloud::Execute(info)) return false; // //----------------------------------------------------------------------- // If there are active particles to animate, get the current center point // of the bounds //----------------------------------------------------------------------- // if(m_activeParticleCount > 0) { Stuff::ExtentBox box(Stuff::Point3D::Identity, Stuff::Point3D::Identity); Stuff::Point3D* vertex = &m_P_localTranslation[0]; uint32_t i = 0; // //------------------------------------------------------------------- // If there is no bounds yet, we need to create our extent box around // the first legal point we find //------------------------------------------------------------------- // while(i < m_activeParticleCount) { Particle* particle = GetParticle(i); Check_Object(particle); if(particle->m_age < 1.0f) { Check_Object(vertex); box.maxX = vertex->x; box.minX = vertex->x; box.maxY = vertex->y; box.minY = vertex->y; box.maxZ = vertex->z; box.minZ = vertex->z; ++vertex; ++i; break; } ++vertex; ++i; } // //----------------------------- // Look for the other particles //----------------------------- // while(i < m_activeParticleCount) { Particle* particle = GetParticle(i); Check_Object(particle); if(particle->m_age < 1.0f) { Check_Object(vertex); if(vertex->x > box.maxX) box.maxX = vertex->x; else if(vertex->x < box.minX) box.minX = vertex->x; if(vertex->y > box.maxY) box.maxY = vertex->y; else if(vertex->y < box.minY) box.minY = vertex->y; if(vertex->z > box.maxZ) box.maxZ = vertex->z; else if(vertex->z < box.minZ) box.minZ = vertex->z; } ++vertex; ++i; } // //------------------------------------ // Now, build a info->m_bounds around this box //------------------------------------ // Verify(box.maxX >= box.minX); Verify(box.maxY >= box.minY); Verify(box.maxZ >= box.minZ); Stuff::OBB local_bounds = Stuff::OBB::Identity; local_bounds.axisExtents.x = 0.5f * (box.maxX - box.minX); local_bounds.axisExtents.y = 0.5f * (box.maxY - box.minY); local_bounds.axisExtents.z = 0.5f * (box.maxZ - box.minZ); local_bounds.localToParent(3, 0) = box.minX + local_bounds.axisExtents.x; local_bounds.localToParent(3, 1) = box.minY + local_bounds.axisExtents.y; local_bounds.localToParent(3, 2) = box.minZ + local_bounds.axisExtents.z; local_bounds.sphereRadius = local_bounds.axisExtents.GetLength(); if(local_bounds.sphereRadius < Stuff::SMALL) local_bounds.sphereRadius = 0.01f; Stuff::OBB parent_bounds; parent_bounds.Multiply(local_bounds, m_localToParent); info->m_bounds->Union(*info->m_bounds, parent_bounds); } // //---------------------------------------------- // Tell our caller that we get to keep executing //---------------------------------------------- // return true; }