Skip to content

Commit

Permalink
Implement RotateFree::transform()
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Jan 14, 2017
1 parent b7a49b2 commit e8e7d53
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 8 deletions.
26 changes: 26 additions & 0 deletions libs/math/Ray.h
Expand Up @@ -251,4 +251,30 @@ class Ray

return POINT; // I is in T
}

/**
* Tries to find the intersection point of this Ray with the sphere given by its
* origin and radius. The intersection will be written to the given Vector3.
* Returns false if the Ray misses the sphere, in which case the intersection will
* be returned as the Ray's nearest point to the sphere.
* Taken from GtkRadiant's sphere_intersect_ray() function.
*/
bool intersectSphere(const Vector3& sphereOrigin, double radius, Vector3& intersection) const
{
intersection = sphereOrigin - origin;

const double a = intersection.dot(direction);
const double d = radius * radius - (intersection.dot(intersection) - a * a);

if (d > 0)
{
intersection = origin + direction * (a - sqrt(d));
return true;
}
else
{
intersection = origin + direction*a;
return false;
}
}
};
39 changes: 32 additions & 7 deletions radiant/selection/manipulators/ManipulatorComponents.cpp
Expand Up @@ -38,23 +38,48 @@ Vector3 ManipulatorComponentBase::getPlaneProjectedPoint(const Matrix4& pivot2wo
return device2pivot.transform(point).getProjected();
}

Vector3 ManipulatorComponentBase::getSphereIntersection(const Matrix4& pivot2world, const VolumeTest& view, const Vector2& devicePoint)
{
// Construct a ray to intersect with a defined sphere

// The device coords x,y generated by the mouse click already defines a ray in 3D space,
// we just need to pick a z coordinate for start and end. For simplicity we use z=-1 and z=+1
// which resolves to the near and far plane in device space.
Vector4 deviceOrigin(devicePoint.x(), devicePoint.y(), -1, 1); // point on near plane
Vector4 deviceEnd(devicePoint.x(), devicePoint.y(), +1, 1); // point on far plane

// Run these points through the device2pivot matrix and construct the ray
Matrix4 device2pivot = constructDevice2Pivot(pivot2world, view);

Vector3 rayOrigin = device2pivot.transform(deviceOrigin).getProjected();
Vector3 rayDirection = (device2pivot.transform(deviceEnd).getProjected() - rayOrigin).getNormalised();

// Construct the ray and return the intersection or the Ray's nearest point to the sphere
Ray ray(rayOrigin, rayDirection);

Vector3 intersectionPoint;
ray.intersectSphere(Vector3(0, 0, 0), 64.0, intersectionPoint);

return intersectionPoint;
}

// ===============================================================================================

void RotateFree::beginTransformation(const Matrix4& pivot2world, const VolumeTest& view, const Vector2& devicePoint)
{
//point_on_sphere(_start, device2manip, x, y);
//_start.normalise();
_start = getSphereIntersection(pivot2world, view, devicePoint);
_start.normalise();
}

void RotateFree::transform(const Matrix4& pivot2world, const VolumeTest& view, const Vector2& devicePoint)
{
// Vector3 current;
Vector3 current = getSphereIntersection(pivot2world, view, devicePoint);
current.normalise();

// point_on_sphere(current, device2manip, x, y);
// current.normalise();
// call the Rotatable with its transform method
Quaternion rotation = Quaternion::createForUnitVectors(_start, current);

//// call the Rotatable with its transform method
// _rotatable.rotate(Quaternion::createForUnitVectors(_start, current));
_rotatable.rotate(rotation);
}

// ===============================================================================================
Expand Down
9 changes: 8 additions & 1 deletion radiant/selection/manipulators/ManipulatorComponents.h
Expand Up @@ -30,6 +30,12 @@ class ManipulatorComponentBase :
* located on the plane going through pivot space origin, orthogonal to the view direction
*/
Vector3 getPlaneProjectedPoint(const Matrix4& pivot2world, const VolumeTest& view, const Vector2& devicePoint);

/**
* Returns the intersection point of the Ray defined by the given devicepoint with a sphere
* located at the pivot space origin. If the Ray misses the sphere, its nearest point will be returned.
*/
Vector3 getSphereIntersection(const Matrix4& pivot2world, const VolumeTest& view, const Vector2& devicePoint);
};

/* greebo: The following are specialised manipulatables that provide the methods as described in the ABC.
Expand All @@ -40,8 +46,9 @@ class ManipulatorComponentBase :
*/

class RotateFree :
public Manipulator::Component
public ManipulatorComponentBase
{
private:
Vector3 _start;
Rotatable& _rotatable;
public:
Expand Down

0 comments on commit e8e7d53

Please sign in to comment.