Geometry: Highlight Clicked Parts

../_images/tut_highlight1.png

This tutorial shows how highlight parts as a response to a mouse press event.

A highlighted part is shown with a white halo. This is useful for indicating for instance selection. Highlighting can be toggled on any number and any type of part independently.

The highlighting mechanism applies to all types of parts:

Note

This tutorial expect the application to have a correctly configured cee::vis::View in place. See demo applications on how to set up a cee::vis::View in your application.

Modify mouse event

The mouse pressed event in the viewer needs to be modified to handle picking. In this tutorial we will trigger a picking event for all mouse clicks.

The tutorial code is Qt based.

In the mouse button pressed event, find the intersect ray for the current mouse coordinates.

Emit a pick signal with the computed ray. This signal must be connected to a slot in the main application.

void TutorialRunnerViewer::mousePressEvent(QMouseEvent* event)
{
    cee::vis::View* theView = view();
    if (!theView) return;

    // Picking!
    cee::Ray ray = theView->camera().rayFromWindowCoordinates(event->pos().x(), height() - event->pos().y());
    m_mainWindow->pick(ray);

    cee::vis::CameraInputHandler* inputHandler = theView->camera().inputHandler();
    if (inputHandler)
    {
        cee::vis::MouseEvent me = cee::qt::UtilsGui::toMouseEvent(*this, *event);
        cee::vis::MouseButton buttonPressed = cee::qt::UtilsGui::toMouseButton(event->button());

        inputHandler->mousePressEvent(buttonPressed, me);
        update();
    }
}

Create the model

Create a simple geometry model with 4 boxes.

    cee::PtrRef<cee::geo::GeometryModel> geometryModel = new cee::geo::GeometryModel;
    geometryModel->addPart(new cee::geo::Part(cee::geo::DataGenerator::createBox(cee::Vec3d(1.0, 1.0, 1.0), cee::Vec3d(1.0, 1.0, 1.0)).get()));
    geometryModel->addPart(new cee::geo::Part(cee::geo::DataGenerator::createBox(cee::Vec3d(3.0, 1.0, 1.0), cee::Vec3d(1.0, 1.0, 1.0)).get()));
    geometryModel->addPart(new cee::geo::Part(cee::geo::DataGenerator::createBox(cee::Vec3d(1.0, 3.0, 1.0), cee::Vec3d(1.0, 1.0, 1.0)).get()));
    geometryModel->addPart(new cee::geo::Part(cee::geo::DataGenerator::createBox(cee::Vec3d(3.0, 3.0, 1.0), cee::Vec3d(1.0, 1.0, 1.0)).get()));

Set up the created model

The model is ready to use and can be added to the view. Exactly where the view exists depends on the platform and solution. These examples uses Qt and the view is set up in a cee::qt::ViewerWidget.

    gcView->addModel(geometryModel.get());

Respond to the pick event

The viewer need to get the pick event from the viewer. This can typically be in the mouse release event. The viewer produces a Ray based on the pick coordinates using cee::vis::Camera::rayFromWindowCoordinates() and passes this ray to the handling function.

Get the current geometry model. Since this tutorials don’t keep local pointer to all the possible models it can create, get the model from the view.

    cee::vis::View* gcView = getTutorialView();
    cee::geo::GeometryModel* geometryModel = dynamic_cast<cee::geo::GeometryModel*>(gcView->model(0));

Create a hit item from the ray object received from the viewer.

rayIntersect() returns true if any part were hit byt the ray. Check if any parts where hit. If not, leave the highlighting as it is and return.

    cee::geo::HitItem hitItem;
    if (!geometryModel->rayIntersect(ray, *gcView, &hitItem))
    {
        // No parts were hit, return without doing any changes
        return;
    }

If a part was hit, deselect all other parts and highlight the hit part.

    for (size_t i = 0; i < geometryModel->partCount(); i++)
    {
        cee::geo::Part* part = geometryModel->part(i);

        part->settings().removeAllEffectsOfType<cee::geo::EffectHalo>();

        if (part == hitItem.part())
        {
            part->settings().addEffect(new cee::geo::EffectHalo);
        }
    }

See the complete source code here:

Geometry: Highlight Clicked Parts