Пример #1
0
/**--------------------------------------------------------------------------<BR>
C2DPolyBase::Contains <BR>
\brief True if the point is contained.
<P>---------------------------------------------------------------------------*/
bool C2DPolyBase::Contains(const C2DPoint& pt) const
{
	if (!m_BoundingRect.Contains(pt))
		return false;

	C2DPointSet IntersectedPts;

	C2DLine Ray(pt, C2DVector(m_BoundingRect.Width(), 0.000001)); // Make sure to leave

	if (!this->Crosses(Ray, &IntersectedPts))
		return false;
	else
	{
		IntersectedPts.SortByDistance(Ray.point);
		if ( IntersectedPts[0] == pt)
		{
			// For integers, the pt can start On a line, meaning it's INSIDE, but the ray could cross again
			// so just return true. Because the equality test is really a test for proximity, this leads to the
			// possibility that a point could lie just outside the shape but be considered to be inside. This would
			// only be a problem with very small shapes that are a very long way from the origin. E.g. a 1m2 object
			// 1 million metres from the origin and a point 0.1mm away from the edge would give rise to a relative 
			// difference of 0.0001 / 1000000 = 0.000000001 which would just be consider to be inside.
			return true;
		}
		else
		{
			// Return true if the ray 
			return (IntersectedPts.size() & (unsigned int)1);
		}
	}
}
void CEntityGalaxy::UpdateCUDA(const C2DVector& external_force_, float dt)
{
    // instantiate some arrays to pass to the cuda kernels
    float* star_positions_x = new float[this->m_collection.size()];
    float* star_positions_y = new float[this->m_collection.size()];
    float* masses = new float[this->m_collection.size()];
    float2* grav_forces = new float2[this->m_collection.size()];

    // load the vectors
    for (size_t i = 0; i < this->m_collection.size(); ++i)
    {
        // convert C2DVectors to lighter float2s
        C2DVector cur_pos = this->m_collection[i]->GetPosition();

        star_positions_x[i] = cur_pos.x;
        star_positions_y[i] = cur_pos.y;
        masses[i] = this->m_collection[i]->GetMass();
    }

    // call cuda kernel
    compute_grav(star_positions_x,
                 star_positions_y,
                 masses,
                 grav_forces,
                 this->m_collection.size());

    for (size_t i = 0; i < this->m_collection.size(); ++i)
    {
        float mass_i = this->m_collection[i]->GetMass();
        this->m_collection[i]->Update(
            external_force_ +
                C2DVector(mass_i * grav_forces[i].x, mass_i * grav_forces[i].y),
            dt);
    }

    delete[] star_positions_x;
    delete[] star_positions_y;
    delete[] masses;
    delete[] grav_forces;
}
CPhysics::CPhysics(float mass_)
    : m_mass(mass_),
      m_inverseMass(1 / mass_),
      m_gravity_acc(C2DVector(0.0f, 9.8f))
{
}
CEntityGalaxy::CEntityGalaxy(unsigned int id_,
                             const C2DVector& initial_pos_,
                             const CEntityParticle& star_,
                             unsigned int star_number_,
                             float _bounding_box_side,
                             bool use_CUDA_)
    : CEntity(id_,
              std::unique_ptr<IMoveable>(new CMoveableParticle(initial_pos_)),
              NULL),
      m_rand_pos(),
      m_rand_mass(),
      m_using_CUDA(use_CUDA_),
      m_original_star_num(star_number_)
{
    // first check proper number of stars is given
    if (this->m_original_star_num <= 1)
    {
        this->m_original_star_num = 1;
    }

    m_rand_pos.SetRealBounds(-_bounding_box_side / 2.0f,
                             _bounding_box_side / 2.0f);
    m_rand_mass.SetRealBounds(1, 4);

    for (
        unsigned int i = 0; i < this->m_original_star_num - 1;
        ++i) //Mind the (-1), we want to add another massive star in the centre!
    {
        std::unique_ptr<CEntityParticle> new_star(new CEntityParticle(star_));

        // randomize position.
        C2DVector pos = initial_pos_ +
                        C2DVector(m_rand_pos.RandReal(), m_rand_pos.RandReal());
        C2DVector initial_vel = C2DVector(m_rand_pos.RandReal() / 200.0f,
                                          m_rand_pos.RandReal() / 200.0f);

        // randomize mass
        float mass = m_rand_mass.RandReal();
        // adjust size accordingly (assuming constant density). TODO: randomize
        // density and have britness change by it. Make them turn into black
        // holes too
        new_star->SetScale(mass);

        new_star->Reposition(pos);
        new_star->Boost(pos + initial_vel);
        new_star->SetMass(mass);

        // set id
        new_star->SetId(i);

        // add a copy of star_ to the collection
        this->m_collection.push_back(std::move(new_star));
    }

    // now add a supemassive black hole to be fixed in the center
    std::unique_ptr<CEntityParticle> super_massive_black_hole(
        new CEntityParticle(star_));

    super_massive_black_hole->SetScale(10.0f);
    super_massive_black_hole->Reposition(initial_pos_);
    float mass = 100.0f;

    super_massive_black_hole->SetMass(mass);

    // set id
    super_massive_black_hole->SetId(star_number_);

    // make super_massibe_black_hole static
    super_massive_black_hole->Block();

    // add a copy of star_ to the collection
    this->m_collection.push_back(std::move(super_massive_black_hole));
}
/**
* Update computes the total gravity acting on each single star and calls update
* on each. Scales as O(N^2)
*/
void CEntityGalaxy::UpdateCPU(const C2DVector& external_force_, float dt)
{
    std::vector<C2DVector> pairwise_forces(
        this->m_collection.size() *
        this->m_collection.size()); // We actully only need half of the matrix
                                    // (force_ij=-force_ji), with no trace (no
                                    // self interaction), however this would
                                    // lead to complicated look up

    // load the forces for each pair of star in the forces vector (N^2
    // operation)
    for (unsigned int i = 0; i < this->m_collection.size(); ++i)
    {
        for (
            unsigned int j = 0; j < i;
            ++j) //keep j < i to compute only the upper half of the matrix. The matrix is antisimmetric anyway, no need to compute it all!
        {
            float mass_i = this->m_collection[i]->GetMass();
            C2DVector pos_i = this->m_collection[i]->GetPosition();

            float mass_j = this->m_collection[j]->GetMass();
            C2DVector pos_j = this->m_collection[j]->GetPosition();

            // compute gravity
            C2DVector r = pos_j - pos_i; // vector from i to j

            float dist = r.GetLenght();
            const float min_dist = 70.0f; // to avoid infinities
            const float NEWTON_CONST =
                2.0f; //higher than in CUDA case since we surely have less stars, so let's make it more interesting!

            // force = G*m*M/ r^2
            C2DVector force_ij =
                NEWTON_CONST * mass_i * mass_j /
                (dist * dist * dist + min_dist) *
                r; // r is not normalized, therefore we divide by dist^3

            unsigned int index_ij =
                i + this->m_collection.size() * j; // col + rows_num*row
            unsigned int index_ji =
                j + this->m_collection.size() * i; // col + rows_num*row

            pairwise_forces[index_ij] = force_ij;
            pairwise_forces[index_ji] = (-1) * force_ij; // save redundant
                                                         // information for easy
                                                         // and fast look-ups
        }
    }

    // now add forces for each particle and apply it ( order N^2 )
    for (unsigned int i = 0; i < this->m_collection.size(); ++i)
    {
        C2DVector force_on_i = C2DVector(0.0f, 0.0f);
        for (unsigned int j = 0; j < this->m_collection.size();
             ++j) // sum all the column of forces
        {
            if (i != j)
            {
                unsigned int index_ij =
                    i + this->m_collection.size() * j; // col + rows_num*row
                force_on_i += pairwise_forces[index_ij];
            }
        }
        this->m_collection[i]->Update(external_force_ + force_on_i, dt);
    }
}
Пример #6
0
/**--------------------------------------------------------------------------<BR>
C2DPoint::operator-
\brief Subtraction.
<P>---------------------------------------------------------------------------*/
const C2DVector C2DPoint::operator-(const C2DPoint& Other) const
{
	return C2DVector(x - Other.x, y - Other.y);
}
Пример #7
0
/**--------------------------------------------------------------------------<BR>
C2DPoint::MakeVector
\brief Returns a vector defined by this point and a move to another point given.
<P>---------------------------------------------------------------------------*/
C2DVector C2DPoint::MakeVector(const C2DPoint&  PointTo) const 
{
	return C2DVector( *this, PointTo);
}