2012-05-15 4 views
5

Eğer bu bir tekrar olsaydı özür dilerim, ama Açık Inventor'da SoRayPickAction uygulamasını anlamaya çalışıyorum. Ben, fare tıklandığında, belirli bir düğümü seçin, böylece çevirebilir, döndürmek, vb. Ben üç düğümler: masa, lamba ve çerçeve (resim çerçevesi) var, böylece uygulamak için çalışıyorum. Ancak, kodumun doğru olmadığını düşünüyorum. Ben de MouseButtonCallback (fare tıklatılıp, sonra bir navigator kullanıp kullanmadığını kontrol edecek) ve MouseMoveCallback (aynı fikir) gibi çeşitli yöntemlerim var. İşte sahip olduğum kod, ama herhangi bir öneriniz var mı? Şu an, hiçbir şey yapmıyor. Açık Inventor'da SoRayPickAction?

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

ayrıca vs. "yer" sahnede bir düğüm, yani duvara masanın üstüne, çerçeve üzerinde lamba yerleştirebilirsiniz Open Inventor bir eylem, bu yolları mı biliyor olabilir mi? Ne aradığımı bile bilmiyorum maalesef. Yardımın için çok teşekkürler!!

Düzenleme: Bu nasıl görünüyor? SoSeparator * desk2; SoSeparator * lamp2; SoSeparator * pic_frame2; SoSeparator * seçildi;

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

cevap

2

Toplama noktanız var. Daha sonra tahmin ettiğiniz gibi bir SoPath olsun. Ardından, yolun bir şey yapmak istediğiniz bir düğüm içerip içermediğini görün.

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

Sonunda böyle bir çeşit fare pozisyonuna seçim ray bağlamak istersiniz:

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

Bu sizin .apply() önce elbette seçim eylemi yapılıyor.

Sanırım benim kodum sizin ve benimkilerin bir karışımıdır ama bence size bir başlangıç ​​yapmalı.

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

ana bölgesi Yukarı veya() portu üzerine fareyi hareket Ben tıklama eylem ve konumu hem de fare olay (kayıt bir kurulum rutini:: Ayrıca, bu fare olayları işlemek için bir işlev içinde oturuyor

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

Şimdi baktığımda, parçaları ters sırada yazdım ;-). Afedersiniz.

İyi Şanslar

+1

Harika, vay, çok teşekkürler, emsr! Kodun şimdi bir tonluk his veriyor. Üzgünüz, "radomeSeparator" nedir? Ve maalesef, masa, lamba ve çerçevenin düğümlerden ziyade Ayırıcı olduğunu fark ettiğimde bu kod değişiyor mu? Yine, yardımlarınız için teşekkürler! – m00nbeam360

+0

Üzgünüz, radomeSeparator benim kodumdan ;-) Uçakla çalışıyorum. Koduna benzemek için değiştirmeyi unuttum. Açıkçası, kendi ayırıcılarınızı kullanmak isteyeceksiniz. Ayrıca, bir SoSeparatör bir SoNodur - yani SoSeparatör SoNode'dan (SoGroup ve belki başka bir şeyden) miras alır. SoNode, Inventor'daki şeylerin bir * lotunun ebeveynidir, böylece bir SoMaterial, SoTransform ya da herneyse. – emsr

+0

Üzgünüm, bu yüzden biraz kayboldum. Yerel değişkenlerden ciddi olarak nefret ediyorum! MouseMoveCallback ve MouseButtonCallback yöntemleri zaten var. Ancak, bunlardan üçünü de RayPickAction'a bağlayabileceğimi düşünüyorsunuz? Yardımın için çok teşekkür ederim! – m00nbeam360