示例#1
0
double R3Distance(const R3Point& point, const R3Segment& segment)
{
  // Check if start point is closest
  R3Vector v1 = point - segment.Start();
  double dir1 = v1.Dot(segment.Vector());
  if (dir1 < 0) return v1.Length();

  // Check if end point is closest
  R3Vector v2 = point - segment.End();
  double dir2 = v2.Dot(segment.Vector());
  if (dir2 < 0) return v2.Length();

  // Return distance from point to segment line
  return R3Distance(point, segment.Line());
}
示例#2
0
double R3Distance(const R3Ray& ray, const R3Segment& segment)
{
  // There's got to be a better way ???

  // Get vectors in more convenient form
  const R3Vector v1 = ray.Vector();
  const R3Vector v2 = segment.Vector();

  // Compute useful intermediate values
  const double v1v1 = 1.0;  // v1.Dot(v1);
  const double v2v2 = 1.0;  // v2.Dot(v2);
  double v1v2 = v1.Dot(v2);
  double denom = v1v2*v1v2 - v1v1*v2v2;

  // Check if ray and segment are parallel
  if (denom == 0) {
    // Not right ???
    // Look at directions of vectors, then check relative starts and stops
    return R3Distance(segment.Line(), ray.Line());
  }
  else {
    // Find closest points
    const R3Vector p1 = ray.Start().Vector();
    const R3Vector p2 = segment.Start().Vector();
    double p1v1 = v1.Dot(p1);
    double p2v2 = v2.Dot(p2);
    double p1v2 = v2.Dot(p1);
    double p2v1 = v1.Dot(p2);
    double ray_t = (v1v2*p2v2 + v2v2*p1v1 - v1v2*p1v2 - v2v2*p2v1) / denom;
    double segment_t = (v1v2*p1v1 + v1v1*p2v2 - v1v2*p2v1 - v1v1*p1v2) / denom;
    R3Point ray_point = (ray_t <= 0.0) ? ray.Start() : ray.Point(ray_t);
    R3Point segment_point = (segment_t <= 0.0) ? segment.Start() : 
      (segment_t >= segment.Length()) ? segment.End() : segment.Ray().Point(segment_t);
    double distance = R3Distance(ray_point, segment_point);
    return distance;
  }
}
////////////////////////////////////////////////////////////
// Generating Particles
////////////////////////////////////////////////////////////
   void GenerateParticles(R3Scene *scene, double current_time, double delta_time)
   {
   // Generate new particles for every source
      R3ParticleSource* source;
      for (int i = 0; i < scene->NParticleSources(); i++)
      {
         source = scene->ParticleSource(i);
         int num_particles = source->elapsed_time * source->rate;
      	
         if ((num_particles) >= 1)
         {
            source->elapsed_time = 0;
         	
            for (int m = 0; m < num_particles; m++)
            {
               if (source->shape->type == R3_SEGMENT_SHAPE)
               {
                  R3Segment* seg = source->shape->segment;
                  R3Point pos = seg->Start() + RandomNumber() * (seg->End() - seg->Start());
                  R3Vector dir = seg->Vector();
                  dir.Cross(R3Vector(RandomNumber() - .5, RandomNumber() - .5, RandomNumber() - .5));
                  dir.Normalize();
               	
                  R3Particle* particle = new R3Particle();
                  particle->position = pos;
                  particle->velocity = source->velocity * dir;
                  particle->mass = source->mass;
                  particle->fixed = source->fixed;
                  particle->drag = source->drag;
                  particle->elasticity = source->elasticity;
                  particle->lifetime = source->lifetime;
                  particle->material = source->material; 
               
                  scene->particles.push_back(particle);
               }
            
               if (source->shape->type == R3_BOX_SHAPE)
               {
                  R3Particle* particle = generate_random_box_particle(source);
                  scene->particles.push_back(particle);
               }
               
               else if (source->shape->type == R3_MESH_SHAPE)
               {
                  R3Mesh* mesh = source->shape->mesh;
                  double area_sum = 0.0;
                  double face_prob[mesh->faces.size()];
               
                  for (unsigned int i = 0; i < mesh->faces.size(); i++)
                  {
                     face_prob[i] = mesh->faces[i]->Area();
                     area_sum += face_prob[i];
                  }
                  for (unsigned int i = 0; i < mesh->faces.size(); i++)
                     face_prob[i] /= area_sum;	
               	
                  int source_face = discrete(face_prob, mesh->faces.size());
                  int num_verts = mesh->faces[source_face]->vertices.size();
                
                	R3Point pos = R3Point(0,0,0);
                     R3Vector dir = R3Vector(0,0,0);
                  if (num_verts == 3)
                  {
                     double a = 0;
                     double b = 0;
                     double c;
                     while (a + b <= 1)
                     {
                        a = RandomNumber();
                        b = RandomNumber();  
                     }
                  
                     a = 1 - a;
                     b = 1 - b;
                     c = 1 - a - b;
                  
                     pos = a * mesh->faces[source_face]->vertices[0]->position
                        + b * mesh->faces[source_face]->vertices[1]->position
                        + c * mesh->faces[source_face]->vertices[2]->position;
                     mesh->faces[source_face]->vertices[0]->UpdateNormal();
                     mesh->faces[source_face]->vertices[1]->UpdateNormal();
                     mesh->faces[source_face]->vertices[2]->UpdateNormal();
                  
                     dir = a * mesh->faces[source_face]->vertices[0]->normal
                        + b * mesh->faces[source_face]->vertices[0]->normal
                        + c * mesh->faces[source_face]->vertices[0]->normal;
                  }
                  else
                  {
                     int num_verts = mesh->faces[source_face]->vertices.size();
                     double vert_sum = 0.0;
                     double vert_prob[num_verts];
                  
                     for (int i = 0; i < num_verts; i++)
                     {
                        vert_prob[i] = RandomNumber();
                        vert_sum += vert_prob[i];
                     }
                  
                     R3Point pos = R3Point(0,0,0);
                     R3Vector dir = R3Vector(0,0,0);
                     for (int i = 0; i < num_verts; i++)
                     {
                        vert_prob[i] /= vert_sum;
                        pos += vert_prob[i] * mesh->faces[source_face]->vertices[i]->position;
                        mesh->faces[source_face]->vertices[i]->UpdateNormal();
                        dir += vert_prob[i] * mesh->faces[source_face]->vertices[i]->normal;
                     }
                  }
               
                  dir.Normalize();
               
                  R3Particle* particle = new R3Particle();
                  particle->position = pos;
                  particle->velocity = source->velocity * dir;
                  particle->mass = source->mass;
                  particle->fixed = source->fixed;
                  particle->drag = source->drag;
                  particle->elasticity = source->elasticity;
                  particle->lifetime = source->lifetime;
                  particle->material = source->material; 
               
                  scene->particles.push_back(particle);
               	
               }
               else if (source->shape->type == R3_SPHERE_SHAPE)
               {
                  R3Sphere* sphere = source->shape->sphere;
                  double radius = sphere->Radius();
                  R3Point center = sphere->Center();
               
                  double z = (RandomNumber() * 2 - 1);
                  double t = RandomNumber() * 2 * PI;
               
                  double r = sqrt(1.0 - z*z);
                  double x = r * cos(t) * radius;
                  double y = r * sin(t) * radius;
               
                  R3Point pos = R3Point(center.X() + x, center.Y() + y, center.Z() + z*radius);
                  R3Vector dir = (pos - center);
                  dir.Normalize();
               
                  R3Particle* particle = new R3Particle();
                  particle->position = pos;
                  particle->velocity = source->velocity * dir;
                  particle->mass = source->mass;
                  particle->fixed = source->fixed;
                  particle->drag = source->drag;
                  particle->elasticity = source->elasticity;
                  particle->lifetime = source->lifetime;
                  particle->material = source->material; 
               
                  scene->particles.push_back(particle);
               }
            }
         }
         else
            source->elapsed_time += delta_time;
      }
   }