2012-05-15 15 views
5

Xin lỗi nếu đây là lần lặp lại, nhưng tôi đang cố gắng tìm hiểu cách triển khai SoRayPickAction trong Nhà phát minh mở. Tôi đang cố gắng để thực hiện nó để nó sẽ, khi con chuột được nhấp, chọn một nút cụ thể để sau đó tôi có thể dịch, xoay, vv Tôi có ba nút: bàn, đèn, và khung (khung hình). Tuy nhiên, tôi không nghĩ rằng mã của tôi là tất cả các quyền. Tôi cũng có các phương pháp khác nhau như một MouseButtonCallback (mà sẽ kiểm tra nếu con chuột được nhấp và sau đó sử dụng một navigator) và MouseMoveCallback (cùng một ý tưởng). Vì vậy, đây là mã mà tôi có, nhưng bạn có bất cứ đề nghị? Ngay bây giờ, tốt, nó không làm gì cả.Hành động SoRayPick trong Nhà phát minh mở?

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; 
    } 

Có thể bạn cũng biết của một hành động trong OpenInventor có thể "nơi" một nút trong hiện trường, ví dụ: đặt đèn trên bàn làm việc, khung trên tường, vv Có với đường dẫn? Tôi thậm chí không biết những gì tôi đang tìm kiếm, thật không may. Cám ơn rất nhiều về sự giúp đỡ của bạn!!

Chỉnh sửa: Giao diện này trông như thế nào? SoSeparator * desk2; SoSeparator * lamp2; SoSeparator * pic_frame2; SoSeparator * đã chọn;

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); 

Trả lời

2

Bạn có điểm được chọn. Sau đó bạn nhận được SoPath như bạn đã đoán. Sau đó, xem nếu đường dẫn có chứa một nút bạn muốn làm một cái gì đó với.

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)) 
      { 
      } 
     } 
    } 

Sau cùng, bạn sẽ muốn kết nối ray chọn đến vị trí chuột loại như thế này:

// Set an 2-pixel wide region around the pixel. 
SbVec2s mousePosition = event->getPosition(viewportRegion); 
pickAction.setPoint(mousePosition); 
pickAction.setPickAll(TRUE); 
pickAction.setRadius(2.0F); 

này được thực hiện trước khi bạn .apply() hành động lựa chọn tất nhiên.

Tôi đoán mã của tôi là hỗn hợp của bạn và của tôi nhưng tôi nghĩ rằng nó sẽ cung cấp cho bạn một sự khởi đầu. Ngoài ra, đây đang ngồi bên trong một hàm xử lý sự kiện chuột:

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); 

Up in chính hoặc một thói quen thiết lập tôi đăng ký sự kiện chuột (cho cả hành động nhấp chuột và vị trí (di chuyển chuột lên khung nhìn):

// 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); 

Bây giờ tôi nhìn vào nó tôi đã viết các khối theo thứ tự ngược ;-). Lấy làm tiếc.

Chúc may mắn

+1

Tuyệt vời, wow, cảm ơn rất nhiều, emsr !! Mã của bạn đã tạo ra rất nhiều ý nghĩa. Xin lỗi, "radomeSeparator là gì?" Và mã này có thay đổi không nếu tôi nhận ra rằng không may, bàn làm việc, đèn và khung hình là Dấu tách chứ không phải là nút? Một lần nữa cảm ơn sự giúp đỡ của bạn! – m00nbeam360

+0

Xin lỗi, radomeSeparator là từ mã của tôi ;-) Tôi làm việc với máy bay. Tôi quên thay đổi nó để trông giống như mã của bạn. Rõ ràng, bạn sẽ muốn sử dụng dấu phân cách của riêng bạn. Ngoài ra, một SoSeparator là một SoNode - tức là SoSeparator kế thừa từ SoNode (thông qua SoGroup và có thể một cái gì đó khác). SoNode là cha mẹ của một * rất nhiều thứ trong Inventor, do đó bạn có thể chọn SoMaterial, SoTransform hoặc bất cứ thứ gì. – emsr

+0

Tôi xin lỗi, vì vậy tôi bị mất một chút. Tôi nghiêm túc ghét các biến cục bộ! Tôi đã có các phương thức MouseMoveCallback và MouseButtonCallback. Tuy nhiên, làm thế nào để bạn nghĩ rằng tôi có thể có thể kết nối tất cả ba trong số này với một RayPickAction? Cảm ơn rất nhiều vì sự giúp đỡ của bạn! – m00nbeam360

Các vấn đề liên quan