Ejemplo n.º 1
0
std::pair<float, int> Layer::calculateOptimalLayerParms(const RodTemplate& rodTemplate) {
                                                              
  // CUIDADO fix placeRadiusHint!!!!!
  double maxDsDistance = (*std::max_element(rodTemplate.begin(), 
                                            rodTemplate.end(), 
                                            [](const unique_ptr<BarrelModule>& m1, const unique_ptr<BarrelModule>& m2) { return m1->dsDistance() > m2->dsDistance(); } ))->dsDistance();
  float moduleWidth = (*rodTemplate.rbegin())->minWidth();
  float f = moduleWidth/2 - phiOverlap()/2;
  float gamma = atan(f/(placeRadiusHint() + bigDelta() + smallDelta() + maxDsDistance/2)) + atan(f/(placeRadiusHint() - bigDelta() + smallDelta() + maxDsDistance/2));
  float tentativeModsPerSegment = 2*M_PI/(gamma * phiSegments());

  float optimalRadius;
  int optimalModsPerSegment;

  switch (radiusMode()) {
  case SHRINK:
    optimalModsPerSegment = floor(tentativeModsPerSegment);
    optimalRadius = calculatePlaceRadius(optimalModsPerSegment*phiSegments(), bigDelta(), smallDelta(), maxDsDistance, moduleWidth, phiOverlap());
    break;
  case ENLARGE:
    optimalModsPerSegment = ceil(tentativeModsPerSegment);
    optimalRadius = calculatePlaceRadius(optimalModsPerSegment*phiSegments(), bigDelta(), smallDelta(), maxDsDistance, moduleWidth, phiOverlap());
    break;
  case FIXED:
    optimalModsPerSegment = ceil(tentativeModsPerSegment);
    optimalRadius = placeRadiusHint();
    break;
  case AUTO: {
    int modsPerSegLo = floor(tentativeModsPerSegment);
    int modsPerSegHi = ceil(tentativeModsPerSegment);
    float radiusLo = calculatePlaceRadius(modsPerSegLo*phiSegments(), bigDelta(), smallDelta(), maxDsDistance, moduleWidth, phiOverlap());
    float radiusHi = calculatePlaceRadius(modsPerSegHi*phiSegments(), bigDelta(), smallDelta(), maxDsDistance, moduleWidth, phiOverlap());

    if (fabs(radiusHi - placeRadiusHint()) < fabs(radiusLo - placeRadiusHint())) {
      optimalRadius = radiusHi;
      optimalModsPerSegment = modsPerSegHi;
    } else {
      optimalRadius = radiusLo;
      optimalModsPerSegment = modsPerSegLo;
    }
    break;
             }
  default:
    throw PathfulException("Invalid value for enum radiusMode");
  }

  return std::make_pair(optimalRadius, optimalModsPerSegment*phiSegments());
}
Ejemplo n.º 2
0
void Layer::buildStraight() {

  RodTemplate rodTemplate = makeRodTemplate();

  std::pair<double, int> optimalLayerParms = calculateOptimalLayerParms(rodTemplate);
  placeRadius_ = optimalLayerParms.first; 
  numRods_ = optimalLayerParms.second;
  if (!minBuildRadius.state() || !maxBuildRadius.state()) {
    minBuildRadius(placeRadius_);
    maxBuildRadius(placeRadius_);
  }

  float rodPhiRotation = 2*M_PI/numRods_;

  StraightRodPair* first = GeometryFactory::make<StraightRodPair>();
  first->myid(1);
  first->minBuildRadius(minBuildRadius()-bigDelta());
  first->maxBuildRadius(maxBuildRadius()+bigDelta());
  if (buildNumModules() > 0) first->buildNumModules(buildNumModules());
  else if (maxZ.state()) first->maxZ(maxZ());
  first->smallDelta(smallDelta());
  //first->ringNode = ringNode; // we need to pass on the contents of the ringNode to allow the RodPair to build the module decorators
  first->store(propertyTree());
  first->build(rodTemplate);

  logINFO(Form("Copying rod %s", fullid(*this).c_str()));
  StraightRodPair* second = GeometryFactory::clone(*first);
  second->myid(2);
  if (!sameParityRods()) second->zPlusParity(first->zPlusParity()*-1);

  first->translateR(placeRadius_ + (bigParity() > 0 ? bigDelta() : -bigDelta()));
  //first->translate(XYZVector(placeRadius_+bigDelta(), 0, 0));
  rods_.push_back(first);

  second->translateR(placeRadius_ + (bigParity() > 0 ? -bigDelta() : bigDelta()));
  //second->translate(XYZVector(placeRadius_-bigDelta(), 0, 0));
  second->rotateZ(rodPhiRotation);
  rods_.push_back(second);

  for (int i = 2; i < numRods_; i++) {
    RodPair* rod = i%2 ? GeometryFactory::clone(*second) : GeometryFactory::clone(*first); // clone rods
    rod->myid(i+1);
    rod->rotateZ(rodPhiRotation*(i%2 ? i-1 : i));
    rods_.push_back(rod);
  }
}
Ejemplo n.º 3
0
void HifiClientProcessList::clientCatchup(GameConnection * connection)
{
#ifdef TORQUE_DEBUG_NET_MOVES
   Con::printf("client catching up... (%i)%s", mCatchup, mForceHifiReset ? " reset" : "");
#endif

   if (connection->getControlObject() && connection->getControlObject()->isGhostUpdated())
      // if control object is reset, make sure moves are reset too
      connection->mMoveList->resetCatchup();

   const F32 maxVel = mSqrt(gMaxHiFiVelSq) * 1.25f;
   F32 dt = F32(mCatchup+1) * TickSec;
   Point3F bigDelta(maxVel*dt,maxVel*dt,maxVel*dt);

   // walk through all process objects looking for ones which were updated
   // -- during first pass merely collect neighbors which need to be reset and updated in unison
   ProcessObject * pobj;
   if (mCatchup && !mForceHifiReset)
   {
      for (pobj = mHead.mProcessLink.next; pobj != &mHead; pobj = pobj->mProcessLink.next)
      {
         GameBase *obj = getGameBase( pobj );
         static SimpleQueryList nearby;
         nearby.mList.clear();
         // check for nearby objects which need to be reset and then caught up
         // note the funky loop logic -- first time through obj is us, then
         // we start iterating through nearby list (to look for objects nearby
         // the nearby objects), which is why index starts at -1
         // [objects nearby the nearby objects also get added to the nearby list]
         for (S32 i=-1; obj; obj = ++i<nearby.mList.size() ? (GameBase*)nearby.mList[i] : NULL)
         {
            if (obj->isGhostUpdated() && (obj->getTypeMask() & GameBaseHiFiObjectType) && !obj->isNetNearbyAdded())
            {
               Point3F start = obj->getWorldSphere().center;
               Point3F end = start + 1.1f * dt * obj->getVelocity();
               F32 rad = 1.5f * obj->getWorldSphere().radius;

               // find nearby items not updated but are hi fi, mark them as updated (and restore old loc)
               // check to see if added items have neighbors that need updating
               Box3F box;
               Point3F rads(rad,rad,rad);
               box.minExtents = box.maxExtents = start;
               box.minExtents -= bigDelta + rads;
               box.maxExtents += bigDelta + rads;

               // CodeReview - this is left in for MBU, but also so we can deal with the issue later.
               // add marble blast hack so hifi networking can see hidden objects
               // (since hidden is under control of hifi networking)
               //  gForceNotHidden = true;

               S32 j = nearby.mList.size();
               gClientContainer.findObjects(box, GameBaseHiFiObjectType, SimpleQueryList::insertionCallback, &nearby);

               // CodeReview - this is left in for MBU, but also so we can deal with the issue later.
               // disable above hack
               //  gForceNotHidden = false;

               // drop anyone not heading toward us or already checked
               for (; j<nearby.mList.size(); j++)
               {
                  GameBase * obj2 = (GameBase*)nearby.mList[j];
                  // if both passive, these guys don't interact with each other
                  bool passive = obj->isHifiPassive() && obj2->isHifiPassive();
                  if (!obj2->isGhostUpdated() && !passive)
                  {
                     // compare swept spheres of obj and obj2
                     // if collide, reset obj2, setGhostUpdated(true), and continue
                     Point3F end2 = obj2->getWorldSphere().center;
                     Point3F start2 = end2 - 1.1f * dt * obj2->getVelocity();
                     F32 rad2 = 1.5f * obj->getWorldSphere().radius;
                     if (MathUtils::capsuleCapsuleOverlap(start,end,rad,start2,end2,rad2))
                     {
                        // better add obj2
                        obj2->getTickCache().beginCacheList();
                        TickCacheEntry * tce = obj2->getTickCache().incCacheList();
                        BitStream bs(tce->packetData,TickCacheEntry::MaxPacketSize);
                        obj2->readPacketData(connection,&bs);
                        obj2->setGhostUpdated(true);

                        // continue so we later add the neighbors too
                        continue;
                     }

                  }

                  // didn't pass above test...so don't add it or nearby objects
                  nearby.mList[j] = nearby.mList.last();
                  nearby.mList.decrement();
                  j--;
               }
               obj->setNetNearbyAdded(true);
            }
         }
      }
   }

   // save water mark -- for game base list
   FrameAllocatorMarker mark;

   // build ordered list of client objects which need to be caught up
   GameBaseListNode list;
   for (pobj = mHead.mProcessLink.next; pobj != &mHead; pobj = pobj->mProcessLink.next)
   {
      GameBase *obj = getGameBase( pobj );
      //GameBase *obj = dynamic_cast<GameBase*>( pobj );
      //GameBase *obj = (GameBase*)pobj;

      // Not a GameBase object so nothing to do.
      if ( !obj )
         continue;

      if (obj->isGhostUpdated() && (obj->getTypeMask() & GameBaseHiFiObjectType))
      {
         // construct process object and add it to the list
         // hold pointer to our object in mAfterObject
         GameBaseListNode * po = (GameBaseListNode*)FrameAllocator::alloc(sizeof(GameBaseListNode));
         po->mObject = obj;
         po->linkBefore(&list);

         // begin iterating through tick list (skip first tick since that is the state we've been reset to)
         obj->getTickCache().beginCacheList();
         obj->getTickCache().incCacheList();
      }
      else if (mForceHifiReset && (obj->getTypeMask() & GameBaseHiFiObjectType))
      {
         // add all hifi objects
         obj->getTickCache().beginCacheList();
         TickCacheEntry * tce = obj->getTickCache().incCacheList();
         BitStream bs(tce->packetData,TickCacheEntry::MaxPacketSize);
         obj->readPacketData(connection,&bs);
         obj->setGhostUpdated(true);

         // construct process object and add it to the list
         // hold pointer to our object in mAfterObject
         GameBaseListNode * po = (GameBaseListNode*)FrameAllocator::alloc(sizeof(GameBaseListNode));
         po->mObject = obj;
         po->linkBefore(&list);
      }
      else if (obj == connection->getControlObject() && obj->isGhostUpdated())
      {
         // construct process object and add it to the list
         // hold pointer to our object in mAfterObject
         // .. but this is not a hi fi object, so don't mess with tick cache
         GameBaseListNode * po = (GameBaseListNode*)FrameAllocator::alloc(sizeof(GameBaseListNode));
         po->mObject = obj;
         po->linkBefore(&list);
      }
      else if (obj->isGhostUpdated())
      {
         // not hifi but we were updated, so perform net smooth now
         obj->computeNetSmooth(mLastDelta);
      }

      // clear out work flags
      obj->setNetNearbyAdded(false);
      obj->setGhostUpdated(false);
   }

   // run through all the moves in the move list so we can play them with our control object
   Move* movePtr;
   U32 numMoves;
   connection->mMoveList->resetClientMoves();
   connection->mMoveList->getMoves(&movePtr, &numMoves);
   AssertFatal(mCatchup<=numMoves,"doh");

   // tick catchup time
   for (U32 m=0; m<mCatchup; m++)
   {
      for (GameBaseListNode * walk = list.mNext; walk != &list; walk = walk->mNext)
      {
         // note that we get object from after object not getGameBase function
         // this is because we are an on the fly linked list which uses mAfterObject
         // rather than the linked list embedded in GameBase (clean this up?)
         GameBase * obj = walk->mObject;

         // it's possible for a non-hifi object to get in here, but
         // only if it is a control object...make sure we don't do any
         // of the tick cache stuff if we are not hifi.
         bool hifi = obj->getTypeMask() & GameBaseHiFiObjectType;
         TickCacheEntry * tce = hifi ? obj->getTickCache().incCacheList() : NULL;

         // tick object
         if (obj==connection->getControlObject())
         {
            obj->processTick(movePtr);
            movePtr->checksum = obj->getPacketDataChecksum(connection);
            movePtr++;
         }
         else
         {
            AssertFatal(tce && hifi,"Should not get in here unless a hi fi object!!!");
            obj->processTick(tce->move);
         }

         if (hifi)
         {
            BitStream bs(tce->packetData,TickCacheEntry::MaxPacketSize);
            obj->writePacketData(connection,&bs);
         }
      }
      if (connection->getControlObject() == NULL)
         movePtr++;
   }
   connection->mMoveList->clearMoves(mCatchup);

   // Handle network error smoothing here...but only for control object
   GameBase * control = connection->getControlObject();
   if (control && !control->isNewGhost())
   {
      control->computeNetSmooth(mLastDelta);
      control->setNewGhost(false);
   }

   if (moveSync.doAction() && moveSync.moveDiff>0)
   {
      S32 moveDiff = moveSync.moveDiff;
#ifdef TORQUE_DEBUG_NET_MOVES
      Con::printf("client timewarping to catchup %i moves",moveDiff);
#endif
      while (moveDiff--)
         advanceObjects();
      moveSync.reset();
   }

#ifdef TORQUE_DEBUG_NET_MOVES
   Con::printf("---------");
#endif

   // all caught up
   mCatchup = 0;
}