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