// TimeSlice Interface
void
dmz::WeaponPluginGravityBullet::update_time_slice (const Float64 TimeDelta) {

   ObjectModule *objMod (get_object_module ());

   if (objMod && _isectMod) {

      const Vector GravityVel (0.0, (-_gravity) * TimeDelta, 0.0);

      HashTableHandleIterator it;

      IsectParameters params;
      params.set_test_result_type (IsectClosestPoint);

      Float64 *speedPtr (_objectTable.get_first (it));

      while (speedPtr) {

         Handle obj (it.get_hash_key ());

         Vector pos;
         Matrix ori;
         Vector vel;
         objMod->lookup_position (obj, _defaultHandle, pos);
         objMod->lookup_orientation (obj, _defaultHandle, ori);
         objMod->lookup_velocity (obj, _defaultHandle, vel);
         vel += GravityVel;
         objMod->store_velocity (obj, _defaultHandle, vel);
         const Vector NewPos (pos + (vel * TimeDelta));

         IsectTestContainer test;
         IsectResultContainer isectResults;
         test.set_test (1, IsectSegmentTest, pos, NewPos);

         _isectMod->disable_isect (obj);

         if (_isectMod->do_isect (params, test, isectResults)) {

            if (_eventMod) {

               IsectResult value;
               isectResults.get_first (value);
               Handle target (0);
               value.get_object_handle (target);
               _eventMod->create_detonation_event (obj, target);
            }

            objMod->destroy_object (obj);
         }
         else {

            objMod->store_position (obj, _defaultHandle, NewPos);
            objMod->store_velocity (obj, _defaultHandle, vel);
         }

         _isectMod->enable_isect (obj);
         
         speedPtr = _objectTable.get_next (it);
      }
   }
}
dmz::Boolean
dmz::EntityPluginGroundSimple::_validate_isect_result (
      const Vector &Start,
      const Vector &Dir,
      const IsectResultContainer &IsectResults,
      Vector &point,
      Vector &normal) {

   Boolean result (False);

   const Vector Up (0.0, 1.0, 0.0);

   const Boolean TestingUp (Dir.get_angle (Up) < HalfPi64 ? True : False);
   
   IsectResult isResult;

   Boolean found (IsectResults.get_first (isResult));

   while (found) {

      Vector cpoint, cnormal;

      Handle handle (0);

      isResult.get_object_handle (handle);

      if (!handle && isResult.get_point (cpoint) && isResult.get_normal (cnormal)) { 

         if ((!result) ||
               ((Start - point).magnitude_squared () >
                  (Start - cpoint).magnitude_squared ())) {

            Handle cullMode (0);

            isResult.get_cull_mode (cullMode);

            if (!(cullMode & IsectPolygonBackCulledMask) &&
                  !(cullMode & IsectPolygonFrontCulledMask)) {

               if (Dir.get_angle (cnormal) < HalfPi64) {

                  cnormal = -cnormal;
               }
            }
            else if (cullMode & IsectPolygonFrontCulledMask) { cnormal = -cnormal; }

            if (TestingUp) {

               if (Dir.get_angle (cnormal) < HalfPi64) {

                  result = True;
                  point = cpoint;
                  normal = cnormal;
               }
            }
            else {

               if (Dir.get_angle (cnormal) > HalfPi64) {

                  result = True;
                  point = cpoint;
                  normal = cnormal;
               }
            }
         }
      }

      found = IsectResults.get_next (isResult);
   }

   return result;
}
void
dmz::EntityPluginGroundSimple::_validate_move (
      const Float64 TimeDelta,
      const Boolean Airborn,
      const Vector StartPos,
      Vector &pos,
      Matrix &ori,
      Vector &vel,
      Float64 &heading) {

   if (!Airborn && _isect && !(StartPos - pos).is_zero ()) {

      _isect->disable_isect (_hil);

      Vector right (1.0, 0.0, 0.0);
      Vector left (-1.0, 0.0, 0.0);
      Vector rightEnd (_move.whiskerLength, _move.whiskerHeight, 0.0);
      Vector centerOfSeg (0.0, _move.whiskerHeight, 0.0);
      Vector leftEnd (-_move.whiskerLength, _move.whiskerHeight, 0.0);

      ori.transform_vector (right);
      ori.transform_vector (left);
      ori.transform_vector (rightEnd);
      ori.transform_vector (centerOfSeg);
      ori.transform_vector (leftEnd);

      rightEnd += pos;
      centerOfSeg += pos;
      leftEnd += pos;

       _isectTestContainer.set_test (
         1, 
         IsectSegmentTest,
         rightEnd,
         leftEnd);

      IsectResultContainer isectResults;

      if (_isect->do_isect (_isectParameters, _isectTestContainer, isectResults)) {

         const Matrix TransOri (ori.transpose ());

         Boolean rightFound (False), leftFound (False);
         Float64 rightDistance (0.0), leftDistance (0.0);
         Vector rightPoint, rightNorm, leftPoint, leftNorm;
   
         IsectResult isResult;

         Boolean found (isectResults.get_first (isResult));

         while (found) {

            Handle handle (0);

            isResult.get_object_handle (handle);

            if (1) { // !handle) {

               Vector point, normal;
               Handle cullMode (0);

               isResult.get_point (point);
               isResult.get_normal (normal);
               isResult.get_cull_mode (cullMode);

               Vector transPoint (point - centerOfSeg);

               TransOri.transform_vector (transPoint);

               // Right side
               if (transPoint.get_x () > 0.0) {

                  _validate_move_isect_point (
                     cullMode,
                     rightDistance,
                     fabs (transPoint.get_x ()),
                     point,
                     right,
                     normal,
                     rightFound,
                     rightDistance,
                     rightPoint,
                     rightNorm);
               }
               else { // Left side

                  _validate_move_isect_point (
                     cullMode,
                     leftDistance,
                     fabs (transPoint.get_x ()),
                     point,
                     left,
                     normal,
                     leftFound,
                     leftDistance,
                     leftPoint,
                     leftNorm);
               }
            }
       
            found = isectResults.get_next (isResult);
         }

         Boolean calcNewOri (False);

         if (rightFound && leftFound) {

 _log.error << "Right and Left Collision." << endl;
         }
         else if (rightFound) {

            pos += rightPoint - rightEnd;
            calcNewOri = True;
         }
         else if (leftFound) {

            pos += leftPoint - leftEnd;
            calcNewOri = True;
         }

         if (calcNewOri) {

            const Float64 Speed (vel.magnitude ());
            Vector newDir ((pos - StartPos).normalize ());
            vel = newDir *  Speed;

            const Vector Forward (0.0, 0.0, -1.0);
            Vector vforward (Forward);

            ori.transform_vector (vforward);

            Matrix mat (vforward, newDir);

            ori = ori * mat;

            heading = Forward.get_signed_angle (newDir);
         }
      }

      _isect->enable_isect (_hil);
   }
}
Esempio n. 4
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;
}