Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.
Posted 22 April 2010 - 08:06 AM
Posted 01 May 2010 - 05:24 PM
Posted 02 May 2010 - 12:29 AM
Vector vxd = v.cross_product(b - a);
Vector pxd = (p - c).cross_product(b - a);
float a = vxd.dot_product(vxd);
float b = 2.0f * vxd.dot_product(pxd);
float c = pxd.dot_product(pxd) - (r*r) * (b - a).dot_product(b - a);
float d2 = b*b - (4.0f * a * c);
if(d2 < 0.0f) return false;
float d = sqrt(d2);
float t0 = (-b - d) / (2.0f * a);
float t1 = (-b + d) / (2.0f * a);
if(t0 > t1) swap(t0, t1);
p_enter = p + v * t0;
float t = (p_enter - a).dot_product(b - a) / (b - a).dot_product(b - a);
if(t < 0.0f)
{
// you've hit the cylinder in front of 'a'.
// test against vertex 'a'.
}
else if(t > 1.of)
{
// you've hit the cylinder behind of 'b'.
// test against vertex 'b'.
}
else
{
// you've hit the cylinder between 'a' and 'b'.
t_collision = t0;
}
Everything is better with Metal.
Posted 04 May 2010 - 08:04 PM
Posted 04 May 2010 - 11:18 PM
Everything is better with Metal.
Posted 05 May 2010 - 03:38 AM
Posted 05 May 2010 - 04:32 AM
Everything is better with Metal.
Posted 05 May 2010 - 05:39 AM
class Vector
{
public:
float x, y, z;
Vector(){}
Vector(float a, float b, float c) : x(a), y(b), z©{}
Vector(const Vector& other) : x(other.x), y(other.y), z(other.z){}
Vector& operator += (const Vector& other) { x += other.x; y += other.y; z += other.z; return *this; }
Vector& operator -= (const Vector& other) { x -= other.x; y -= other.y; z -= other.z; return *this; }
Vector& operator *= (const float scalar) { x *= scalar; y *= scalar; z *= scalar; return *this; }
Vector& operator /= (const float scalar) { float inv = (1.0f / scalar); return (*this) *= inv; }
Vector operator + (const Vector& other) const { Vector temp(*this); return temp += other; }
Vector operator - (const Vector& other) const { Vector temp(*this); return temp -= other; }
Vector operator * (const float scalar) const { Vector temp(*this); return temp *= scalar; }
Vector operator / (const float scalar) const { Vector temp(*this); return temp /= scalar; }
Vector cross_product(const Vector& other) const { Vector temp(y*other.z-z*other.y, z*other.x-x*other.z, x*other.y-y*other.x); return temp; }
float dot_product(const Vector& other) const { return x*other.x + y*other.y + z*other.z; }
float length_squared() const { return (*this).dot_product(*this); }
float length() const { return sqrt(length_squared()); }
float normalise() { float l = length(); if(l > 1.0E-8f) (*this) /= l; return l; }
friend Vector operator * (float scalar, const Vector& v) { return v * scalar; }
};
// quadratic : a* t^2 + b*t + c = 0.
// d = b^2 - 4*a*c
// t0 = (-b - sqrt(d)) / (2 * a)
// t1 = (-b + sqrt(d)) / (2 * a)
bool solveQuadratic(float a, float b, float c, float& t0, float& t1)
{
float d2 = b*b - 4 * a * c;
if(d2 < 0.0f) return false;
float d = sqrt(d2);
t0 = (-b - d) / (2 * a);
t1 = (-b + d) / (2 * a);
if(t0 > t1) { float temp(t0); t0 = t1; t1 = temp; }
if(t1 < 0.0f || t0 > 1.0f) return false;
return true;
}
// ray (p, v)
// sphere (c, r)
// quadratic : ((p - c) + v * t)^2 = r^2
bool intersectRaySphere(const Vector& ray_origin,
const Vector& ray_direction,
const Vector& sphere_origin,
const float sphere_radius,
float& t_enter,
float& t_exit)
{
Vector p(ray_origin - sphere_origin);
float r2 = (sphere_radius * sphere_radius);
float v2 = ray_direction.dot_product(ray_direction);
float p2 = p.dot_product(p);
float pv = p.dot_product(ray_direction);
float a = v2;
float b = pv * 2.0f;
float c = p2 - r2;
// ray direction very small.
if(a < 1.0E-8f)
{
// no intersection
if (c > 0.0f) return false;
// intersection
t_enter = t_exit = 0.0f;
return true;
}
return solveQuadratic(a, b, c, t_enter, t_exit);
}
// ray (p, v)
// cylinder (c, d, r)
// quadratic : ((p - c) x d + (v x d) * t)^2 = r^2 * (d.d)
bool intersectRayCylinder( const Vector& ray_origin,
const Vector& ray_direction,
const Vector& cylinder_origin,
const Vector& cylinder_direction,
const float cylinder_radius,
float& t_enter,
float& t_exit)
{
Vector pxd = (ray_origin - cylinder_origin).cross_product(cylinder_direction);
Vector vxd = ray_direction.cross_product(cylinder_direction);
float r2 = (cylinder_radius * cylinder_radius);
float d2 = cylinder_direction.dot_product(cylinder_direction);
float v2 = vxd.dot_product(vxd);
float p2 = pxd.dot_product(pxd);
float pv = pxd.dot_product(vxd);
float a = v2;
float b = pv * 2.0f;
float c = p2 - (r2 * d2);
// ray direction parallel to cylinder.
if(a < 1.0E-8f)
{
// no intersection
if (c > 0.0f) return false;
// intersection
t_enter = t_exit = 0.0f;
return true;
}
return solveQuadratic(a, b, c, t_enter, t_exit);
}
bool CollideSphereEdge( const Vector& sphere_centre,
const Vector& sphere_velocity,
const float sphere_radius,
const Vector& edge_start,
const Vector& edge_end,
Vector& collision_point, // point of collision on edge
Vector& collision_normal, // normal of collision
float& collision_depth, // depth of intersection in case the sphere is embedded in edge
float& collision_time) // time of collisoin. 0.0f if sphere intersects edge already.
{
// edge dir (not normalised)
Vector edge_dir(edge_end - edge_start);
// chech against infinite cylinder.
float t_enter, t_exit;
if(!intersectRayCylinder( sphere_centre,
sphere_velocity,
edge_start,
edge_dir,
sphere_radius,
t_enter,
t_exit))
{
// missed cylinder -> missed edge
return false;
}
// time of collision (the time we first hit the edge).
float t_collision = t_enter;
// intersecting. reset to 0.0f.
if(t_collision < 0.0f) t_collision = 0.0f;
// sphere centre position at time of collision.
Vector sphere_collision = sphere_centre + sphere_velocity * t_collision;
// which side of the edge the sphere is.
float u = (sphere_collision - edge_start).dot_product(edge_dir) / edge_dir.dot_product(edge_dir);
// point on the edge collided by the sphere
Vector edge_collision;
// sphere position before edge start. test against edge start vertex.
if(u < 0.0f)
{
// test against start vertex.
if(!intersectRaySphere( sphere_centre,
sphere_velocity,
edge_start,
sphere_radius,
t_enter,
t_exit))
{
// missed vertex -> missed edge.
return false;
}
// new time of collision
t_collision = t_enter;
if(t_collision < 0.0f) t_collision = 0.0f;
// re-compute the sphere position at new time of collision.
sphere_collision = sphere_centre + sphere_velocity * t_collision;
// point on edge is start point.
edge_collision = edge_start;
}
// sphere position after edge end. test against edge end vertex.
else if (u > 1.0f)
{
if(!intersectRaySphere( sphere_centre,
sphere_velocity,
edge_end,
sphere_radius,
t_enter,
t_exit))
{
// missed vertex -> missed edge.
return false;
}
// new time of collision
t_collision = t_enter;
if(t_collision < 0.0f) t_collision = 0.0f;
// re-compute the sphere position at new time of collision.
sphere_collision = sphere_centre + sphere_velocity * t_collision;
// point on edge is end point.
edge_collision = edge_end;
}
else
{
// point of collision on the edge.
edge_collision = edge_start + edge_dir * u;
}
collision_point = edge_collision; // collision point on edge.
collision_time = t_collision; // time of collision.
collision_normal = (sphere_collision - edge_collision); // normal of collision.
float d = collision_normal.normalise(); // disatnce of the sphere position and point of collision
collision_depth = (d < sphere_radius)? (sphere_radius- d) : 0.0f; // intersection depth, if intersecting.
return true;
}
Everything is better with Metal.
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.
GameDev.net™, the GameDev.net logo, and GDNet™ are trademarks of GameDev.net, LLC.