⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sceneobject.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 5 页
字号:

   // Polylist bounding box & sphere
   Point3F min(1e10, 1e10, 1e10);
   Point3F max(-1e10, -1e10, -1e10);
   for (U32 i = 0; i < polyhedron.pointList.size(); i++)
   {
      min.setMin(polyhedron.pointList[i]);
      max.setMax(polyhedron.pointList[i]);
   }

   info.boundingBox.min = info.boundingBox.max = Point3F(0, 0, 0);
   info.boundingBox.min.setMin(vector);
   info.boundingBox.max.setMax(vector);
   info.boundingBox.min += min;
   info.boundingBox.max += max;
   info.boundingSphere.center = (info.boundingBox.min + info.boundingBox.max) * 0.5;
   VectorF bv = info.boundingBox.max - info.boundingSphere.center;
   info.boundingSphere.radius = bv.len();

   // Extruded
   sExtrudedPolyList.extrude(polyhedron, vector);
   sExtrudedPolyList.setVelocity(velocity);
   if (velocity.isZero())
   {
      sExtrudedPolyList.clearInterestNormal();
   }
   else
   {
      Point3F normVec = velocity;
      normVec.normalize();
      sExtrudedPolyList.setInterestNormal(normVec);
   }
   sExtrudedPolyList.setCollisionList(collisionList);
   info.polyList = &sExtrudedPolyList;

   Box3F queryBox = info.boundingBox;

   // Query main database
   findObjects(queryBox, mask, callback ? callback : buildCallback, &info);
   sExtrudedPolyList.adjustCollisionTime();
   return collisionList->count != 0;
}


void Container::cleanupSearchVectors()
{
   for (U32 i = 0; i < mSearchList.size(); i++)
      delete mSearchList[i];
   mSearchList.clear();
   mCurrSearchPos = -1;
}


static Point3F sgSortReferencePoint;
int QSORT_CALLBACK cmpSearchPointers(const void* inP1, const void* inP2)
{
   SimObjectPtr<SceneObject>** p1 = (SimObjectPtr<SceneObject>**)inP1;
   SimObjectPtr<SceneObject>** p2 = (SimObjectPtr<SceneObject>**)inP2;

   Point3F temp;
   F32 d1, d2;

   if (bool(**p1))
   {
      (**p1)->getWorldBox().getCenter(&temp);
      d1 = (temp - sgSortReferencePoint).len();
   }
   else
   {
      d1 = 0;
   }
   if (bool(**p2))
   {
      (**p2)->getWorldBox().getCenter(&temp);
      d2 = (temp - sgSortReferencePoint).len();
   }
   else
   {
      d2 = 0;
   }

   if (d1 > d2)
      return 1;
   else if (d1 < d2)
      return -1;
   else
      return 0;
}

void Container::initRadiusSearch(const Point3F& searchPoint,
                                 const F32      searchRadius,
                                 const U32      searchMask)
{
   AssertFatal(this == &gServerContainer, "Abort.  Searches only allowed on server container");
   cleanupSearchVectors();

   mSearchReferencePoint = searchPoint;

   Box3F queryBox(searchPoint, searchPoint);
   queryBox.min -= Point3F(searchRadius, searchRadius, searchRadius);
   queryBox.max += Point3F(searchRadius, searchRadius, searchRadius);

   SimpleQueryList queryList;
   findObjects(queryBox, searchMask, SimpleQueryList::insertionCallback, &queryList);

   F32 radiusSquared = searchRadius * searchRadius;

   const F32* pPoint = &searchPoint.x;
   for (U32 i = 0; i < queryList.mList.size(); i++)
   {
      const F32* bMins;
      const F32* bMaxs;
      bMins = &queryList.mList[i]->getWorldBox().min.x;
      bMaxs = &queryList.mList[i]->getWorldBox().max.x;
      F32 sum = 0;
      for (U32 j = 0; j < 3; j++)
      {
         if (pPoint[j] < bMins[j])
            sum += (pPoint[j] - bMins[j])*(pPoint[j] - bMins[j]);
         else if (pPoint[j] > bMaxs[j])
            sum += (pPoint[j] - bMaxs[j])*(pPoint[j] - bMaxs[j]);
      }
      if (sum < radiusSquared || queryList.mList[i]->isGlobalBounds())
      {
         mSearchList.push_back(new SimObjectPtr<SceneObject>);
         *(mSearchList.last()) = queryList.mList[i];
      }
   }
   if (mSearchList.size() != 0)
   {
      sgSortReferencePoint = mSearchReferencePoint;
      dQsort(mSearchList.address(), mSearchList.size(),
             sizeof(SimObjectPtr<SceneObject>*), cmpSearchPointers);
   }
}

U32 Container::containerSearchNext()
{
   AssertFatal(this == &gServerContainer, "Abort.  Searches only allowed on server container");

   if (mCurrSearchPos >= mSearchList.size())
      return 0;

   mCurrSearchPos++;
   while (mCurrSearchPos < mSearchList.size() && bool(*mSearchList[mCurrSearchPos]) == false)
      mCurrSearchPos++;

   if (mCurrSearchPos == mSearchList.size())
      return 0;

   return (*mSearchList[mCurrSearchPos])->getId();
}


F32 Container::containerSearchCurrDist()
{
   AssertFatal(this == &gServerContainer, "Abort.  Searches only allowed on server container");
   AssertFatal(mCurrSearchPos != -1, "Error, must call containerSearchNext before containerSearchCurrDist");

   if (mCurrSearchPos == -1 || mCurrSearchPos >= mSearchList.size() ||
       bool(*mSearchList[mCurrSearchPos]) == false)
      return 0.0;

   Point3F pos;
   (*mSearchList[mCurrSearchPos])->getWorldBox().getCenter(&pos);
   return (pos - mSearchReferencePoint).len();
}

F32 Container::containerSearchCurrRadiusDist()
{
   AssertFatal(this == &gServerContainer, "Abort.  Searches only allowed on server container");
   AssertFatal(mCurrSearchPos != -1, "Error, must call containerSearchNext before containerSearchCurrDist");

   if (mCurrSearchPos == -1 || mCurrSearchPos >= mSearchList.size() ||
       bool(*mSearchList[mCurrSearchPos]) == false)
      return 0.0;

   Point3F pos;
   (*mSearchList[mCurrSearchPos])->getWorldBox().getCenter(&pos);

   F32 dist = (pos - mSearchReferencePoint).len();

   F32 min = (*mSearchList[mCurrSearchPos])->getWorldBox().len_x();
   if ((*mSearchList[mCurrSearchPos])->getWorldBox().len_y() < min)
      min = (*mSearchList[mCurrSearchPos])->getWorldBox().len_y();
   if ((*mSearchList[mCurrSearchPos])->getWorldBox().len_z() < min)
      min = (*mSearchList[mCurrSearchPos])->getWorldBox().len_z();

   dist -= min;
   if (dist < 0)
      dist = 0;

   return dist;
}

//----------------------------------------------------------------------------
void SimpleQueryList::insertionCallback(SceneObject* obj, void *key)
{
   SimpleQueryList* pList = (SimpleQueryList*)key;
   pList->insertObject(obj);
}

Point3F SceneObject::getPosition() const
{
   Point3F pos;
   mObjToWorld.getColumn(3, &pos);
   return pos;
}

Point3F SceneObject::getRenderPosition() const
{
   Point3F pos;
   mRenderObjToWorld.getColumn(3, &pos);
   return pos;
}

void SceneObject::setPosition(const Point3F &pos)
{
   MatrixF xform = mObjToWorld;
   xform.setColumn(3, pos);
   setTransform(xform);
}

//--------------------------------------------------------------------------
SceneObject::LightingInfo::LightingInfo()
{
   mUseInfo = false;
   mDirty = false;
   mHasLastColor = false;

   // set the colors to half white for invalid surfaces and all...
   mDefaultColor.set(0.5f, 0.5f, 0.5f);
   mAlarmColor.set(0.5f, 0.5f, 0.5f);
   mLastColor.set(0.5f, 0.5f, 0.5f);

   mLastTime = 0;
}

//--------------------------------------------------------------------------
void SceneObject::installLights()
{
   // install the lights:
   LightManager * lightManager = gClientSceneGraph->getLightManager();
   AssertFatal(lightManager!=NULL, "SceneObject::installLights: LightManager not found");

   ColorF ambientColor;
   if(getLightingAmbientColor(&ambientColor))
   {
      switch(mLightingInfo.mLightSource)
      {
         case LightingInfo::Interior:
         {
            // ambient/directional contributions
            const F32 directionalFactor = 0.3f;
            const F32 ambientFactor = 0.7f;

            LightInfo & light = mLightingInfo.smAmbientLight;

            light.mType = LightInfo::Ambient;
      		light.mDirection = VectorF(0.57735f, 0.57735f, -0.57735f);
            light.mColor = ambientColor * directionalFactor;
            light.mAmbient = ambientColor * ambientFactor;

            lightManager->addLight(&mLightingInfo.smAmbientLight);
            lightManager->setVectorLightsEnabled(false);

            break;
         }

         case LightingInfo::Terrain:
         {
            F32 factor = mClampF((ambientColor.red + ambientColor.green + ambientColor.blue) / 3.f, 0.f, 1.f);
            lightManager->setVectorLightsAttenuation(factor);
            break;
         }
      }
   }
   lightManager->installGLLights(getRenderWorldBox());
}

void SceneObject::uninstallLights()
{
   LightManager * lightManager = gClientSceneGraph->getLightManager();
   AssertFatal(lightManager!=NULL, "SceneObject::uninstallLights: LightManager not found");

   lightManager->removeLight(&mLightingInfo.smAmbientLight);

   // resets all ambient/vector settings
   lightManager->uninstallGLLights();
}

//--------------------------------------------------------------------------
// Lighting update: not used directly by sceneobject...
// - if an interior, which contains this object, moves then this value will be incorrect
bool SceneObject::getLightingAmbientColor(ColorF * col)
{
   AssertFatal(col!=NULL, "SceneObject::getLightingAmbientColor: invalid color ptr");

   const F32 cRayLength = 100.f;             // down/up
   const F32 cTerrainRayLength = 10.f;       // height above terrain for no ambient
   const F32 cColorStep = 0.2f;              // amount to add per 100ms

   PROFILE_START(GetLightingAmbientColor);

   // query a new value?
   if(mLightingInfo.mDirty)
   {
      mLightingInfo.mDirty = false;

      Point3F pos;
      getRenderWorldBox().getCenter(&pos);

      // check if shadowed:
      disableCollision();

      mLightingInfo.mUseInfo = false;
      mLightingInfo.mInterior = 0;

      // Ambient light is determined by the surface we are standing on.
      RayInfo collision;
      if (gClientContainer.castRay(pos, Point3F(pos.x, pos.y, pos.z - cRayLength),
            InteriorObjectType | TerrainObjectType, &collision))
      {
         // Standing on an interior object
         if (InteriorInstance * instance = dynamic_cast<InteriorInstance*>(collision.object))
         {
            if (collision.face != -1)
            {
               // determine the color of this point...
               Interior * interior = instance->getDetailLevel(0);
               AssertFatal(interior!=NULL, "SceneObject::getLightingAmbientColor: invalid interior");
               AssertFatal(collision.face < interior->getSurfaceCount(), "SceneObject::getLightingAmbientColor: invalid surface");

               const Interior::Surface & surface = interior->getSurface(collision.face);

               // get the render order
               U32 currIndex = 0;
               U32 last = 2;

               static U32 renderIndices[512];

               while(last < surface.windingCount)
               {
                  // first
                  renderIndices[currIndex++] = last - 2;
                  renderIndices[currIndex++] = last - 1;
                  renderIndices[currIndex++] = last - 0;
                  last++;

                  if(last == surface.windingCount)
                     break;

                  // second
                  renderIndices[currIndex++] = last - 1;
                  renderIndices[currIndex++] = last - 2;
                  renderIndices[currIndex++] = last - 0;
                  last++;
               }

               // get the winding indices, the src indices and the points
               static Point3F points[512];
               static U32 srcIndices[512];
               for(U32 i = 0; i < currIndex; i++)
               {
                  srcIndices[i] = surface.windingStart + renderIndices[i];
                  renderIndices[i] = interior->getWinding(srcIndices[i]);
                  points[i] = interior->getPoint(renderIndices[i]);
               }

               // project the collision point into object space
               instance->getWorldTransform().mulP(collision.point);

               PlaneF plane = interior->getFlippedPlane(surface.planeIndex);

               // walk the tri's to find the one under collision point
               S32 insideOffset = -1;
               for(U32 offset = 0; offset < currIndex; offset += 3)
               {
                  bool inside = true;
                  for(U32 j = 0; (j < 3) && inside; j++)
                  {
                     U32 k = (j+1) % 3;

                     VectorF vec1 = points[offset + k] - points[offset + j];
                     VectorF vec2 = collision.point - points[offset + j];

                     Point3F cross;
                     mCross(vec2, vec1, &cross);

                     if(mDot(plane, cross) < 0.f)
                        inside = false;
                  }

                  if(inside)
                  {
                     insideOffset = offset;
                     break;
                  }
               }

               if(insideOffset != -1)
               {
                  // box map the surface:
                  F32 max = 0.f;
                  S32 index = -1;
                  F32

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -