首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Open Inventor中使用SoRayPickAction?

在Open Inventor中使用SoRayPickAction?
EN

Stack Overflow用户
提问于 2012-05-16 03:49:59
回答 1查看 946关注 0票数 5

如果这是重复的,很抱歉,但我正在尝试弄清楚SoRayPickAction在Open Inventor中的实现。我正在尝试实现它,这样当鼠标单击时,它将选择一个特定的节点,这样我就可以平移、旋转等。我有三个节点:桌子、灯和框架(图片框架)。然而,我不认为我的代码是完全正确的。我还有各种方法,比如MouseButtonCallback (它将检查鼠标是否被单击,然后使用导航器)和MouseMoveCallback (相同的想法)。这是我的代码,但是你有什么建议吗?现在,嗯,它什么也做不了。

代码语言:javascript
复制
SbViewportRegion viewport(400,300); 
    SoRayPickAction m(viewport); 
    m.setRay(SbVec3f(0.0,0.0,0.0), SbVec3f(0.0,0.0,-1.0));
    m.apply(callback_node);
    const SoPickedPoint *mpp = m.getPickedPoint(); 
    if(mpp != NULL) {
        std::cout << "test" << std::endl;
    }

你可能也知道OpenInventor中的一个动作,它可以在场景中“放置”一个节点,比如把灯放在桌子上,把框架放在墙上等等。它是有路径的吗?不幸的是,我甚至不知道我在找什么。非常感谢你的帮助!!

编辑:这看起来怎么样?SoSeparator *桌面2;SoSeparator *灯2;SoSeparator *pic_frame2;SoSeparator *picked;

代码语言:javascript
复制
void MouseButtonCallback(void* data, SoEventCallback* node)
{
   SoHandleEventAction* action = node->getAction();
   const SoMouseButtonEvent* event = static_cast<const SoMouseButtonEvent*>(action-          >getEvent());
   Navigator* nav = static_cast<Navigator*>(data);

   if (SoMouseButtonEvent::isButtonPressEvent(event, event->getButton())) 
       nav->OnMouseDown(event, action);
   else
         nav->OnMouseUp(event, action);

   const SbViewportRegion & viewportRegion = action->getViewportRegion();
   SoRayPickAction pickAction(viewportRegion); 

   SbVec2s mousePos = event->getPosition(viewportRegion); 
   pickAction.setPoint(mousePos); 
   pickAction.setPickAll(TRUE); 
   pickAction.setRadius(2.0F); 
   pickAction.setRay(SbVec3f(0.0,0.0,0.0), SbVec3f(0.0,0.0,-1.0));
   pickAction.apply(node);
   const SoPickedPoint *mpp = pickAction.getPickedPoint(); 
   if(mpp != NULL) {
  SoPath *path = mpp->getPath(); 

 if(desk2 != NULL && path->containsNode(desk2))
  {             //but this doesn't respond with cout when I try to test it :(
      if (SoMouseButtonEvent::isButtonPressEvent(event, event->getButton()))
      *picked = *desk2; 
  }
  else if(lamp2 != NULL && path->containsNode(lamp2))
  {
      if (SoMouseButtonEvent::isButtonPressEvent(event, event->getButton()))
      *picked = *lamp2;
  }
  else if(pic_frame2 != NULL && path->containsNode(pic_frame2))
  {
      if (SoMouseButtonEvent::isButtonPressEvent(event, event->getButton())) 
      *picked = *pic_frame2;
  }

           action->setHandled();
   }
 void MouseMoveCallback(void* data, SoEventCallback* node)
{
    SoHandleEventAction* action = node->getAction();
    const SoLocation2Event* event = static_cast<const SoLocation2Event*>(action->getEvent());
    Navigator* nav = static_cast<Navigator*>(data);

    nav->OnMouseMove(event, action);

     const SbViewportRegion & viewportRegion = action->getViewportRegion();
    SoRayPickAction pickAction(viewportRegion); 

    SbVec2s mousePos = event->getPosition(viewportRegion); 
    pickAction.setPoint(mousePos); 
    pickAction.setPickAll(TRUE); 
    pickAction.setRadius(2.0F); 
    pickAction.setRay(SbVec3f(0.0,0.0,0.0), SbVec3f(0.0,0.0,-1.0));
    pickAction.apply(node);
    const SoPickedPoint *mpp = pickAction.getPickedPoint(); 
    if(mpp != NULL) {
  SoPath *path = mpp->getPath(); 
  if(desk2 != NULL && path->containsNode(desk2))
  {
      *picked = *desk2; //can't remember how to set pointers, will figure that out
  }
  else if(lamp2 != NULL && path->containsNode(lamp2))
  {
      *picked = *lamp2;
  }
  else if(pic_frame2 != NULL && path->containsNode(pic_frame2))
  {
       *picked = *pic_frame2;
  }
   }  
        action->setHandled();
    }

  (part of main method) 

 //desk 
SoTransform *desk_transform = new SoTransform; 
desk_transform->translation.setValue(SbVec3f(380,340,330)); 
SoSeparator* desk2 = new SoSeparator(); 
desk2->addChild(desk_transform);
desk2->addChild(desk); 
root->addChild(desk2);

  SoTransformerManip* picked_transform = new SoTransformerManip(); 
   picked_transform->translation.setValue(SbVec3f(200,340,330));
  SoSeparator* pick2 = new SoSeparator(); 
  pick2->addChild(picked_transform); 
  pick2->addChild(picked); 
  root->addChild(pick2); 

 std::auto_ptr<btCollisionShape> picked_shape(new btBoxShape(btVector3(10.0f, 10.0f,  10.0f)));
  CollisionEngine* picked_collision = new CollisionEngine(collision_world.get(),      picked_shape.get());
  picked_collision->translation_in.connectFrom(&picked_transform->translation);
  picked_collision->rotation_in.connectFrom(&picked_transform->rotation);
  picked_transform->translation.connectFrom(&picked_collision->translation_out);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-05-16 11:45:02

您已拾取点。然后,如您所料,您将获得一个SoPath。然后查看路径中是否包含您想要使用的节点。

代码语言:javascript
复制
SbViewportRegion viewport(400,300); 
    SoRayPickAction m(viewport); 
    m.setRay(SbVec3f(0.0,0.0,0.0), SbVec3f(0.0,0.0,-1.0));
    m.apply(callback_node);
    const SoPickedPoint *mpp = m.getPickedPoint(); 
    if(mpp != NULL) {
        std::cout << "test" << std::endl;
        SoPath * path = pickedPoint->getPath();

        if (deskSeparator != NULL && path->containsNode(deskSeparator)
        {
        }
        else if (lampSeparator != NULL && path->containsNode(lampSeparator)
        {
        }
        else if (radomeSeparator != NULL && path->containsNode(radomeSeparator)
        {
            if (    SoMouseButtonEvent::isButtonPressEvent( event, SoMouseButtonEvent::BUTTON2 )
                 || ( SoMouseButtonEvent::isButtonPressEvent( event, SoMouseButtonEvent::BUTTON1 ) && event->wasShiftDown() ) )
            {
                modelPointMoving = true;
                const SoDetail * detail = modelPickedPoint->getDetail( 0 );
                int face = -1;
                if ( detail && detail->isOfType( SoFaceDetail::getClassTypeId() ) )
                {
                    const SoFaceDetail * faceDetail = static_cast<const SoFaceDetail *>( detail );
                    face = faceDetail->getFaceIndex();
                }
                updateStatusBar( face, point.getValue(), normal.getValue() );
                graphicModel.postNote( pickedPoint );
                break;
            }
            else if ( SoMouseButtonEvent::isButtonPressEvent( event, SoMouseButtonEvent::BUTTON1 ) )
            {
            }
            else if ( SoMouseButtonEvent::isButtonReleaseEvent( event, SoMouseButtonEvent::BUTTON1 ) )
            {
            }
        }
    }

最终,您需要将拾取光线连接到鼠标位置,如下所示:

代码语言:javascript
复制
//  Set an 2-pixel wide region around the pixel.
SbVec2s mousePosition = event->getPosition( viewportRegion );
pickAction.setPoint( mousePosition );
pickAction.setPickAll( TRUE );
pickAction.setRadius( 2.0F );

当然,这是在您选择.apply()操作之前完成的。

我猜我的代码是你和我的代码的混合体,但我认为它应该给你一个开始。此外,它位于一个处理鼠标事件的函数中:

代码语言:javascript
复制
void
RenderWindow::mouseEvent( void *, SoEventCallback * eventCallback )
{
    const SoEvent *event = eventCallback->getEvent();

    if ( ! event )
    {
        qDebug() << "  **  Error in mousePressCallback: Event not found.";
        return;
    }

    //SoType eventType = event->getTypeId();   
    //SbName eventTypeName = eventType.getName();
    //const char * eventTypeString = eventTypeName.getString();
    SoHandleEventAction * action = eventCallback->getAction();
    const SbViewportRegion & viewportRegion = action->getViewportRegion();
    SoRayPickAction pickAction( viewportRegion );

在main或设置例程中,我注册鼠标事件(对于单击动作和位置(将鼠标移动到视口上):

代码语言:javascript
复制
//  Add a mouse event callback to catch mouse button presses.
SoEventCallback * mouseEventCallback = new SoEventCallback();
mouseEventCallback->setName( "MOUSE_EVENT_CALLBACK" );
mouseEventCallback->addEventCallback( SoMouseButtonEvent::getClassTypeId(), &::mouseEvent, static_cast<void *>( this ) );
//  Add a mouse event callback to catch mouse motion.
mouseEventCallback->addEventCallback( SoLocation2Event::getClassTypeId(), &::mouseEvent, static_cast<void *>( this ) );
rootSeparator->addChild( mouseEventCallback );

现在我看了一下,我以相反的顺序写了块;-)。抱歉的。

祝好运

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10607792

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档