void SpikeGuideRenderer::addSpike(const Ray3& ray, const FloatType length, const FloatType maxLength) {
     const float mix = static_cast<float>(maxLength / length / 2.0);
     
     m_spikeVertices.push_back(SpikeVertex(ray.origin, m_color));
     m_spikeVertices.push_back(SpikeVertex(ray.pointAtDistance(length),
                               Color(m_color, m_color.a() * mix)));
 }
 Model::Hit VertexHandleManager::pickHandle(const Ray3& ray, const Renderer::Camera& camera, const Vec3& position, Model::Hit::HitType type) const {
     const FloatType distance = camera.pickPointHandle(ray, position, pref(Preferences::HandleRadius));
     if (!Math::isnan(distance)) {
         const Vec3 hitPoint = ray.pointAtDistance(distance);
         return Model::Hit::hit<Vec3>(type, distance, hitPoint, position);
     }
     
     return Model::Hit::NoHit;
 }
 void SpikeGuideRenderer::add(const Ray3& ray, const FloatType length, View::MapDocumentSPtr document) {
     Model::PickResult pickResult = Model::PickResult::byDistance(document->editorContext());
     document->pick(ray, pickResult);
     
     const Model::Hit& hit = pickResult.query().pickable().type(Model::Brush::BrushHit).occluded().minDistance(1.0).first();
     if (hit.isMatch()) {
         if (hit.distance() <= length)
             addPoint(ray.pointAtDistance(hit.distance() - 0.01));
         addSpike(ray, Math::min(length, hit.distance()), length);
     } else {
         addSpike(ray, length, length);
     }
     m_valid = false;
 }
 void CreateEntityTool::updateEntityPosition3D(const Ray3& pickRay, const Model::PickResult& pickResult) {
     assert(m_entity != NULL);
     
     MapDocumentSPtr document = lock(m_document);
     
     Vec3 delta;
     const Grid& grid = document->grid();
     const Model::Hit& hit = pickResult.query().pickable().type(Model::Brush::BrushHit).occluded().first();
     if (hit.isMatch()) {
         const Model::BrushFace* face = Model::hitToFace(hit);
         const Plane3 dragPlane = alignedOrthogonalDragPlane(hit.hitPoint(), face->boundary().normal);
         delta = grid.moveDeltaForBounds(dragPlane, m_entity->bounds(), document->worldBounds(), pickRay, hit.hitPoint());
     } else {
         const Vec3 newPosition = pickRay.pointAtDistance(Renderer::Camera::DefaultPointDistance);
         const Vec3 center = m_entity->bounds().center();
         delta = grid.moveDeltaForPoint(center, document->worldBounds(), newPosition - center);
     }
     
     if (delta.null())
         return;
     
     document->translateObjects(delta);
 }
        void CreateEntityTool::updateEntityPosition2D(const Ray3& pickRay) {
            assert(m_entity != NULL);
            
            MapDocumentSPtr document = lock(m_document);

            const Vec3 toMin = m_referenceBounds.min - pickRay.origin;
            const Vec3 toMax = m_referenceBounds.max - pickRay.origin;
            const Vec3 anchor = toMin.dot(pickRay.direction) > toMax.dot(pickRay.direction) ? m_referenceBounds.min : m_referenceBounds.max;
            const Plane3 dragPlane(anchor, -pickRay.direction);
            
            const FloatType distance = dragPlane.intersectWithRay(pickRay);
            if (Math::isnan(distance))
                return;
            
            const Vec3 hitPoint = pickRay.pointAtDistance(distance);
            
            const Grid& grid = document->grid();
            const Vec3 delta = grid.moveDeltaForBounds(dragPlane, m_entity->bounds(), document->worldBounds(), pickRay, hitPoint);
            
            if (delta.null())
                return;
            
            document->translateObjects(delta);
        }