mirror of
https://github.com/mangosfour/server.git
synced 2026-01-02 01:37:05 +00:00
+ Got rid of zip lib requirement in G3D...
Still can re-enable code by defining _HAVE_ZIP...
+ Remove silly X11 lib dependency from G3D
Code doesn't seem to do anything yet anyway, and even if, we don't want it :p
+ Fix another weird G3D build problem...
+ Remove some __asm usage in g3d, which is not available on Win64
My editor also decided to remove a ton of trailing white spaces...tss...
+ Reapply G3D fixes for 64bit VC
+ not use SSE specific header when SSE not enabled in *nix
+ Updated project files
+ New vmap_assembler VC90/VC80 Project
+ vmap assembler binaries updates
NOTE: Old vmap fikes expected work (as tests show) with new library version.
But better use new generated versions. Its different in small parts to bad or good...
(based on Lynx3d's repo commit 44798d3)
Signed-off-by: VladimirMangos <vladimir@getmangos.com>
236 lines
5.8 KiB
C++
236 lines
5.8 KiB
C++
/**
|
|
@file LineSegment.cpp
|
|
|
|
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
|
|
|
@created 2003-02-08
|
|
@edited 2008-02-02
|
|
*/
|
|
|
|
#include "G3D/platform.h"
|
|
#include "G3D/LineSegment.h"
|
|
#include "G3D/Sphere.h"
|
|
#include "G3D/debug.h"
|
|
|
|
namespace G3D {
|
|
|
|
|
|
Vector3 LineSegment::closestPoint(const Vector3& p) const {
|
|
|
|
// The vector from the end of the capsule to the point in question.
|
|
Vector3 v(p - _point);
|
|
|
|
// Projection of v onto the line segment scaled by
|
|
// the length of direction.
|
|
float t = direction.dot(v);
|
|
|
|
// Avoid some square roots. Derivation:
|
|
// t/direction.length() <= direction.length()
|
|
// t <= direction.squaredLength()
|
|
|
|
if ((t >= 0) && (t <= direction.squaredMagnitude())) {
|
|
|
|
// The point falls within the segment. Normalize direction,
|
|
// divide t by the length of direction.
|
|
return _point + direction * t / direction.squaredMagnitude();
|
|
|
|
} else {
|
|
|
|
// The point does not fall within the segment; see which end is closer.
|
|
|
|
// Distance from 0, squared
|
|
float d0Squared = v.squaredMagnitude();
|
|
|
|
// Distance from 1, squared
|
|
float d1Squared = (v - direction).squaredMagnitude();
|
|
|
|
if (d0Squared < d1Squared) {
|
|
|
|
// Point 0 is closer
|
|
return _point;
|
|
|
|
} else {
|
|
|
|
// Point 1 is closer
|
|
return _point + direction;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
Vector3 LineSegment::point(int i) const {
|
|
switch (i) {
|
|
case 0:
|
|
return _point;
|
|
|
|
case 1:
|
|
return _point + direction;
|
|
|
|
default:
|
|
debugAssertM(i == 0 || i == 1, "Argument to point must be 0 or 1");
|
|
return _point;
|
|
}
|
|
}
|
|
|
|
|
|
bool LineSegment::intersectsSolidSphere(const class Sphere& s) const {
|
|
return distanceSquared(s.center) <= square(s.radius);
|
|
}
|
|
|
|
|
|
LineSegment::LineSegment(class BinaryInput& b) {
|
|
deserialize(b);
|
|
}
|
|
|
|
|
|
void LineSegment::serialize(class BinaryOutput& b) const {
|
|
_point.serialize(b);
|
|
direction.serialize(b);
|
|
}
|
|
|
|
|
|
void LineSegment::deserialize(class BinaryInput& b) {
|
|
_point.deserialize(b);
|
|
direction.deserialize(b);
|
|
}
|
|
|
|
|
|
Vector3 LineSegment::randomPoint() const {
|
|
return _point + uniformRandom(0, 1) * direction;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
LineSegment2D LineSegment2D::fromTwoPoints(const Vector2& p0, const Vector2& p1) {
|
|
LineSegment2D s;
|
|
s.m_origin = p0;
|
|
s.m_direction = p1 - p0;
|
|
s.m_length = s.m_direction.length();
|
|
return s;
|
|
}
|
|
|
|
|
|
Vector2 LineSegment2D::point(int i) const {
|
|
debugAssert(i == 0 || i == 1);
|
|
if (i == 0) {
|
|
return m_origin;
|
|
} else {
|
|
return m_direction + m_origin;
|
|
}
|
|
}
|
|
|
|
|
|
Vector2 LineSegment2D::closestPoint(const Vector2& Q) const {
|
|
// Two constants that appear in the result
|
|
const Vector2 k1(m_origin - Q);
|
|
const Vector2& k2 = m_direction;
|
|
|
|
if (fuzzyEq(m_length, 0)) {
|
|
// This line segment has no length
|
|
return m_origin;
|
|
}
|
|
|
|
// Time [0, 1] at which we hit the closest point travelling from p0 to p1.
|
|
// Derivation can be obtained by minimizing the expression
|
|
// ||P0 + (P1 - P0)t - Q||.
|
|
const float t = -k1.dot(k2) / (m_length * m_length);
|
|
|
|
if (t < 0) {
|
|
// Clipped to low end point
|
|
return m_origin;
|
|
} else if (t > 1) {
|
|
// Clipped to high end point
|
|
return m_origin + m_direction;
|
|
} else {
|
|
// Subsitute into the line equation to find
|
|
// the point on the segment.
|
|
return m_origin + k2 * t;
|
|
}
|
|
}
|
|
|
|
|
|
float LineSegment2D::distance(const Vector2& p) const {
|
|
Vector2 closest = closestPoint(p);
|
|
return (closest - p).length();
|
|
}
|
|
|
|
|
|
float LineSegment2D::length() const {
|
|
return m_length;
|
|
}
|
|
|
|
|
|
Vector2 LineSegment2D::intersection(const LineSegment2D& other) const {
|
|
|
|
if ((m_origin == other.m_origin) ||
|
|
(m_origin == other.m_origin + other.m_direction)) {
|
|
return m_origin;
|
|
}
|
|
|
|
if (m_origin + m_direction == other.m_origin) {
|
|
return other.m_origin;
|
|
}
|
|
|
|
// Note: Now that we've checked the endpoints, all other parallel lines can now be assumed
|
|
// to not intersect (within numerical precision)
|
|
|
|
Vector2 dir1 = m_direction;
|
|
Vector2 dir2 = other.m_direction;
|
|
Vector2 origin1 = m_origin;
|
|
Vector2 origin2 = other.m_origin;
|
|
|
|
if (dir1.x == 0) {
|
|
// Avoid an upcoming divide by zero
|
|
dir1 = dir1.yx();
|
|
dir2 = dir2.yx();
|
|
origin1 = origin1.yx();
|
|
origin2 = origin2.yx();
|
|
}
|
|
|
|
// t1 = ((other.m_origin.x - m_origin.x) + other.m_direction.x * t2) / m_direction.x
|
|
//
|
|
// ((other.m_origin.x - m_origin.x) + other.m_direction.x * t2) * m_direction.y / m_direction.x =
|
|
// (other.m_origin.y - m_origin.y) + other.m_direction.y * t2
|
|
//
|
|
// m = m_direction.y / m_direction.x
|
|
// d = other.m_origin - m_origin
|
|
//
|
|
// (d.x + other.m_direction.x * t2) * m = d.y + other.m_direction.y * t2
|
|
//
|
|
// d.x * m + other.m_direction.x * m * t2 = d.y + other.m_direction.y * t2
|
|
//
|
|
// d.x * m - d.y = (other.m_direction.y - other.m_direction.x * m) * t2
|
|
//
|
|
// (d.x * m - d.y) / (other.m_direction.y - other.m_direction.x * m) = t2
|
|
//
|
|
|
|
Vector2 d = origin2 - origin1;
|
|
float m = dir1.y / dir1.x;
|
|
|
|
float t2 = (d.x * m - d.y) / (dir2.y - dir2.x * m);
|
|
if (! isFinite(t2)) {
|
|
// Parallel lines: no intersection
|
|
return Vector2::inf();
|
|
}
|
|
|
|
if ((t2 < 0.0f) || (t2 > 1.0f)) {
|
|
// Intersection occurs past the end of the line segments
|
|
return Vector2::inf();
|
|
}
|
|
|
|
float t1 = (d.x + dir2.x * t2) / dir1.x;
|
|
if ((t1 < 0.0f) || (t1 > 1.0f)) {
|
|
// Intersection occurs past the end of the line segments
|
|
return Vector2::inf();
|
|
}
|
|
|
|
// Return the intersection point (computed from non-transposed
|
|
// variables even if we flipped above)
|
|
return m_origin + m_direction * t1;
|
|
|
|
}
|
|
|
|
}
|
|
|