2012-05-15 8 views
5

Scusa se si tratta di una ripetizione, ma sto cercando di capire l'implementazione di SoRayPickAction in Open Inventor. Sto cercando di implementarlo in modo che, quando si fa clic sul mouse, selezionare un nodo particolare, quindi posso tradurre, ruotare, ecc. Ho tre nodi: scrivania, lampada e cornice (cornice). Tuttavia, non penso che il mio codice sia a posto. Ho anche vari metodi come MouseButtonCallback (che controllerà se il mouse viene cliccato e quindi usa un navigatore) e MouseMoveCallback (stessa idea). Quindi ecco il codice che ho, ma hai qualche suggerimento? In questo momento, beh, non fa niente.SoRayPickAction in Open Inventor?

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

potreste anche sapere di un'azione in OpenInventor che può "luogo" un nodo nella scena, vale a dire mettere la lampada in cima alla scrivania, cornice sul muro, ecc E 'con percorsi? Sfortunatamente non so nemmeno cosa sto cercando. Grazie mille per il vostro aiuto!!

Modifica: come appare? SoSeparator * desk2; SoSeparator * lamp2; SoSeparator * pic_frame2; SoSeparator * selezionato;

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

risposta

2

Hai il punto selezionato. Otterrai quindi un SoPath come hai indovinato. Quindi vedi se il percorso contiene un nodo con cui vuoi fare qualcosa.

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

più volte si desidera collegare il raggio di selezione per la posizione del mouse un po 'come questo:

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

Questo viene fatto prima di .apply() l'azione scelta, naturalmente.

Immagino che il mio codice sia un misto del tuo e del mio ma penso che dovrebbe darti un inizio. Inoltre, questo è seduto all'interno di una funzione per elaborare gli eventi del mouse:

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 principale o una routine di installazione a registrare l'evento del mouse (sia per azione di un click e la posizione (spostando il mouse sopra la finestra):

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

Ora che lo guardo ho scritto i pezzi in ordine inverso ;-). Scusate.

Good Luck

+1

Grande, wow, grazie mille, emsr !! Il tuo codice ha un buon senso ora. Scusa, cos'è "radomeSeparator?" E questo codice cambia se ho capito che sfortunatamente, scrivania, lampada e cornice sono Separatori piuttosto che nodi? Grazie ancora per il tuo aiuto! – m00nbeam360

+0

Scusa, radomeSeparator proviene dal mio codice ;-) Lavoro con gli aerei. Ho dimenticato di cambiarlo per sembrare il tuo codice. Ovviamente, vorrai usare i tuoi separatori. Inoltre, un SoSeparator è un SoNode - cioè SoSeparator eredita da SoNode (tramite SoGroup e forse qualcos'altro). SoNode è il genitore di un * lotto * di cose in Inventor in modo da poter scegliere un SoMaterial, SoTransform o qualsiasi altra cosa. – emsr

+0

Mi dispiace, quindi sono un po 'perso. Detesto seriamente le variabili locali! Ho già i metodi MouseMoveCallback e MouseButtonCallback. Tuttavia, come pensi che io possa eventualmente connettere tutti e tre questi a una RayPickAction? Grazie mille per il vostro aiuto! – m00nbeam360