dmz::Boolean
dmz::RenderPluginPickOSG::source_to_world (
      const Int32 SourcePosX,
      const Int32 SourcePosY,
      Vector &worldPosition,
      Vector &normal,
      Handle &objectHandle) {

   Boolean result (False);

   if (_core && _view.valid () && _viewport.valid ()) {

      const float Height = _viewport->height ();

      osgUtil::LineSegmentIntersector::Intersections isect;

      if (_view->computeIntersections (
            (float)SourcePosX,
            Height - (float)SourcePosY,
            isect,
            _isectMask)) {

         osgUtil::LineSegmentIntersector::Intersections::iterator it = isect.begin ();

         while (!result && (it != isect.end ())) {

            Boolean disabled (False);

            osg::NodePath path = it->nodePath;

            for (osg::NodePath::iterator node = path.begin ();
                  (node != path.end ()) && !disabled;
                  node++) {

               if (*node) {

                  osg::Referenced *ref ((*node)->getUserData ());

                  if (ref) {

                     RenderObjectDataOSG *data (
                        dynamic_cast<RenderObjectDataOSG *> (ref));

                     if (data) {

                        if (!data->do_isect ()) { disabled = True; }
                        else { objectHandle = data->get_handle (); }
                     }
                  }
               }
            }

            if (!disabled) {

               worldPosition = to_dmz_vector (it->getWorldIntersectPoint ());
               normal = to_dmz_vector (it->getWorldIntersectNormal ());
               result = True;
            }
            else { it++; }
         }
      }
   }

   return result;
}
Beispiel #2
0
dmz::Boolean
dmz::RenderModuleIsectOSG::do_isect (
    const IsectParameters &Parameters,
    const IsectTestContainer &TestValues,
    IsectResultContainer &resultContainer) {

    if (_core) {

        osg::ref_ptr<osg::Group> scene = _core->get_isect ();
//      osg::ref_ptr<osg::Group> scene = _core->get_static_objects ();

        osg::BoundingSphere bs = scene->getBound();

        std::vector<osg::LineSegment*> lsList;// = new osg::LineSegment[TestValues];

        osgUtil::IntersectVisitor visitor;
        visitor.setTraversalMask (_isectMask);

        UInt32 testHandle;
        IsectTestTypeEnum testType;
        Vector vec1, vec2;

        std::vector<UInt32> handleArray;
        std::vector<Vector> sourceArray;

        TestValues.get_first_test (testHandle, testType, vec1, vec2);

        do {

            if (testType == IsectRayTest) {

                vec2 = (vec1 + (vec2 * (bs.radius () * 2)));
            }

            osg::LineSegment *ls = new osg::LineSegment;
            ls->set (to_osg_vector (vec1), to_osg_vector (vec2));
            visitor.addLineSegment (ls);
            lsList.push_back (ls);
            handleArray.push_back (testHandle);
            sourceArray.push_back (vec1);

        } while (TestValues.get_next_test (testHandle, testType, vec1, vec2));

        scene->accept (visitor);

        IsectTestResultTypeEnum param = Parameters.get_test_result_type ();
        bool closestPoint = (param == IsectClosestPoint);
        bool firstPoint = (param == IsectFirstPoint);

        if (closestPoint && !Parameters.get_calculate_distance ()) {

            firstPoint = true;
            closestPoint = false;
        }

        Boolean result (False);

        for (unsigned int ix = 0; ix < lsList.size () && !result; ix++) {

            osgUtil::IntersectVisitor::HitList resultHits;
            resultHits = visitor.getHitList (lsList[ix]);

            if (!resultHits.empty ()) {

                for (unsigned int jy = 0; jy < resultHits.size (); jy++) {

                    Handle objHandle (0);

                    osgUtil::Hit currentHit = resultHits[jy];

                    Boolean disabled (False);
                    osg::CullFace *cf (0);

                    osg::NodePath path = currentHit.getNodePath ();

                    for (
                        osg::NodePath::iterator it = path.begin ();
                        (it != path.end ()) && !disabled;
                        it++) {

                        osg::Node *node (*it);

                        if (node) {


                            osg::StateSet *sSet = (node->getStateSet ());

                            if (sSet) {

                                osg::CullFace *cfTmp (
                                    (osg::CullFace*)(sSet->getAttribute (
                                                         osg::StateAttribute::CULLFACE)));

                                if (cfTmp) {
                                    cf = cfTmp;
                                }
                            }

                            osg::Referenced *r (node->getUserData ());

                            if (r) {

                                RenderObjectDataOSG *data (
                                    dynamic_cast<RenderObjectDataOSG *> (r));

                                if (data) {

                                    if (!data->do_isect ()) {

                                        // Should never reach here now
                                        disabled = True;
                                    }
                                    else {
                                        objHandle = data->get_handle ();
                                    }
                                }
                            }
                        }
                    }

                    if (!disabled) {

                        Vector lsPoint = to_dmz_vector (currentHit.getWorldIntersectPoint ());
                        IsectResult lsResult;

                        lsResult.set_isect_test_id (handleArray[ix]);

                        lsResult.set_point (lsPoint);

                        if (Parameters.get_calculate_object_handle ()) {

                            lsResult.set_object_handle (objHandle);
                        }

                        if (Parameters.get_calculate_normal ()) {

                            lsResult.set_normal (
                                to_dmz_vector (currentHit.getWorldIntersectNormal ()));
                        }

                        if (Parameters.get_calculate_distance ()) {

                            lsResult.set_distance ((lsPoint - sourceArray[ix]).magnitude ());
                        }

                        if (Parameters.get_calculate_cull_mode ()) {

                            UInt32 cullMask = 0;

                            if (cf) {

                                if (cf->getMode () == osg::CullFace::FRONT ||
                                        cf->getMode () == osg::CullFace::FRONT_AND_BACK)  {

                                    cullMask |= IsectPolygonFrontCulledMask;
                                }

                                if (cf->getMode () == osg::CullFace::BACK ||
                                        cf->getMode () == osg::CullFace::FRONT_AND_BACK) {

                                    cullMask |= IsectPolygonBackCulledMask;
                                }
                            }
                            else {
                                cullMask |= IsectPolygonBackCulledMask;
                            }


                            lsResult.set_cull_mode (cullMask);
                        }

                        if (Parameters.get_calculate_object_handle ()) {

                            osg::Geode *hitObject = currentHit.getGeode ();
                        }

                        resultContainer.add_result (lsResult);

                        if (firstPoint) {

                            result = true;
                        }
                    }
                }
            }
        }

        if (closestPoint && resultContainer.get_result_count () > 1) {

            IsectResult current;
            resultContainer.get_first (current);
            IsectResult closest (current);

            double closestDist;
            current.get_distance (closestDist);

            while (resultContainer.get_next (current)) {

                double testDist;
                if (current.get_distance (testDist)) {

                    if (testDist < closestDist) {

                        closest = current;
                    }
                }
            }

            IsectResultContainer closestContainer;
            closestContainer.add_result (closest);
            resultContainer = closestContainer;
        }
    }

    return resultContainer.get_result_count () > 0;
}