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

📄 interiorinstance.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 5 页
字号:
            char newName[256];
            AssertFatal(len < 200, "InteriorInstance::renewOverlays: Error, len exceeds allowed name length");

            dStrncpy(newName, pName, possible - pName);
            newName[possible - pName] = '\0';
            dStrcat(newName, ".");
            dStrcat(newName, baseName);

            TextureHandle test = TextureHandle(newName, MeshTexture, false);
            if (test.getGLName() != 0)
            {
               pMatList->mMaterials[j] = test;
            }
            else
            {
               pMatList->mMaterials[j] = TextureHandle(pName, MeshTexture, false);
            }
         }
      }
   }
}


//--------------------------------------------------------------------------
void InteriorInstance::setSkinBase(const char* newBase)
{
   if (dStricmp(mSkinBase, newBase) == 0)
      return;

   mSkinBase = StringTable->insert(newBase);

   if (isServerObject())
	{
      setMaskBits(SkinBaseMask);
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsServerObject
	}
   else
	{
#endif
      renewOverlays();
	}
}


//--------------------------------------------------------------------------
// from resManager.cc
extern U32 calculateCRC(void * buffer, S32 len, U32 crcVal );

bool InteriorInstance::onAdd()
{
   U32 i;

   // Load resource
   mInteriorRes = ResourceManager->load(mInteriorFileName, true);

   if (bool(mInteriorRes) == false)
   {
      Con::errorf(ConsoleLogEntry::General, "Unable to load interior: %s", mInteriorFileName);
      NetConnection::setLastError("Unable to load interior: %s", mInteriorFileName);
      return false;
   }

#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
   if(isClientObject())
   {
      if(mCRC != mInteriorRes.getCRC())
      {
         NetConnection::setLastError("Local interior file '%s' does not match version on server.", mInteriorFileName);
         return false;
      }
#endif

      for (i = 0; i < mInteriorRes->getNumDetailLevels(); i++)
      {
         // ok, if the material list load failed...
         // if this is a local connection, we'll assume that's ok
         // and just have white textures...
         // otherwise we want to return false.
         Interior* pInterior = mInteriorRes->getDetailLevel(i);
         if(!pInterior->prepForRendering(mInteriorRes.getFilePath()) )
               return false;
      }
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
   }
   else
      mCRC = mInteriorRes.getCRC();
#endif

   if(!Parent::onAdd())
      return false;

   // Set up vertex lighting.
   mVertexColorsNormal.setSize(mInteriorRes->getNumDetailLevels());
   mVertexColorsAlarm.setSize(mInteriorRes->getNumDetailLevels());
   for (i = 0; i < mInteriorRes->getNumDetailLevels(); i++)
   {
      mVertexColorsNormal[i] = new Vector<ColorI>;
      mVertexColorsAlarm[i]  = new Vector<ColorI>;
      VECTOR_SET_ASSOCIATION((*mVertexColorsNormal[i]));
      VECTOR_SET_ASSOCIATION((*mVertexColorsAlarm[i]));
   }

   // Ok, everything's groovy!  Let's cache our hashed filename for renderimage sorting...
   mInteriorFileHash = _StringTable::hashString(mInteriorFileName);

   // Setup bounding information
   mObjBox = mInteriorRes->getDetailLevel(0)->getBoundingBox();
   resetWorldBox();
   setRenderTransform(mObjToWorld);

   // Setup mLightInfo structure
   mLightInfo.setSize(mInteriorRes->getNumDetailLevels());

   for (i = 0; i < mInteriorRes->getNumDetailLevels(); i++)
   {
      Interior* pInterior = mInteriorRes->getDetailLevel(i);
      constructInPlace(&mLightInfo[i]);
      LightInfo& rInfo = mLightInfo[i];

      rInfo.mSurfaceInvalid.setSize(pInterior->mSurfaces.size());
      rInfo.mSurfaceInvalid.clear();

      rInfo.mStateDataInfo.setSize(pInterior->mNumLightStateEntries);
      dMemset(rInfo.mStateDataInfo.address(), 0x00,
              sizeof(LightInfo::StateDataInfo) * rInfo.mStateDataInfo.size());

      rInfo.mLights.setSize(pInterior->mAnimatedLights.size());
      for (U32 j = 0; j < rInfo.mLights.size(); j++)
      {
         LightInfo::Light& rLight = rInfo.mLights[j];
         rLight.curState = 0;
         rLight.curTime  = 0;

         Interior::LightState& rState = pInterior->mLightStates[pInterior->mAnimatedLights[j].stateIndex];
         rLight.curColor.set(rState.red, rState.green, rState.blue);
         rLight.active   = false;
         rLight.alarm    = (pInterior->mAnimatedLights[j].flags & Interior::AlarmLight) != 0;

         installLight(i, j);
      }
   }

   // Setup lightgrouper
   mUpdateGrouper = new LightUpdateGrouper(LightUpdateBitStart, LightUpdateBitEnd);
   for (U32 d = 0; d < mInteriorRes->getNumDetailLevels(); d++)
   {
      Interior* pInterior = mInteriorRes->getDetailLevel(d);

      for (U32 j = 0; j < pInterior->mNumTriggerableLights; j++)
         mUpdateGrouper->addKey(makeUpdateKey(d, j));
   }


#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
	if (isClientObject())
#endif
   {
      // create all the subObjects
      mInteriorSubObjects.setSize(mInteriorRes->getNumDetailLevels());
      for (i = 0; i < mInteriorRes->getNumDetailLevels(); i++)
      {
         constructInPlace(&mInteriorSubObjects[i]);

         Interior* pInterior = mInteriorRes->getDetailLevel(i);
         for (U32 j = 0; j < pInterior->mSubObjects.size(); j++)
            mInteriorSubObjects[i].push_back(pInterior->mSubObjects[j]->clone(this));
      }
   }
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
   else
   {
      // creates all subobjects
      mInteriorSubObjects.setSize(mInteriorRes->getNumDetailLevels());
      for (i = 0; i < mInteriorRes->getNumDetailLevels(); i++)
      {
         constructInPlace(&mInteriorSubObjects[i]);

         Interior* pInterior = mInteriorRes->getDetailLevel(i);

         for (U32 j = 0; j < pInterior->mSubObjects.size(); j++)
            mInteriorSubObjects[i].push_back(pInterior->mSubObjects[j]->clone(this));
      }
   }
#endif

   // Do any handle loading, etc. required.

   if (isClientObject())
   {
      setLightUpdatedTime(Platform::getVirtualMilliseconds());

      for (i = 0; i < mInteriorRes->getNumDetailLevels(); i++)
      {
         Interior* pInterior = mInteriorRes->getDetailLevel(i);

         // Force the lightmap manager to download textures if we're
         // running the mission editor.  Normally they are only
         // downloaded after the whole scene is lit.
         gInteriorLMManager.addInstance(pInterior->getLMHandle(), mLMHandle, this);
         if (gEditingMission)
         {
            gInteriorLMManager.useBaseTextures(pInterior->getLMHandle(), mLMHandle);
            gInteriorLMManager.downloadGLTextures(pInterior->getLMHandle());
         }

         // Install material list
         mMaterialMaps.push_back(new MaterialList(pInterior->mMaterialList));

         // A client interior starts up it's ambient animations on add.  Ambients
         //  are just past the triggerables.
         for (U32 j = pInterior->mNumTriggerableLights; j < pInterior->mAnimatedLights.size(); j++)
            activateLight(i, j);
      }

      renewOverlays();
   }
   else
   {
      // WTF goes here? -- BJG
   }

   addToScene();
   return true;
}


void InteriorInstance::onRemove()
{
   // Kill our convexes.
   mConvexList->nukeList();

   // Clean up our lightmaps.
   if(isClientObject())
   {
      if(bool(mInteriorRes) && mLMHandle != 0xFFFFFFFF)
      {
         for(U32 i = 0; i < mInteriorRes->getNumDetailLevels(); i++)
         {
            Interior * pInterior = mInteriorRes->getDetailLevel(i);
            if (pInterior->getLMHandle() != 0xFFFFFFFF)
               gInteriorLMManager.removeInstance(pInterior->getLMHandle(), mLMHandle);
         }
      }
   }

   removeFromScene();
   Parent::onRemove();
}


//--------------------------------------------------------------------------
bool InteriorInstance::onSceneAdd(SceneGraph* pGraph)
{
   AssertFatal(mInteriorRes, "Error, should not have been added to the scene if there's no interior!");

   if (Parent::onSceneAdd(pGraph) == false)
      return false;

   if (mInteriorRes->getDetailLevel(0)->mZones.size() > 1)
   {
      AssertWarn(getNumCurrZones() == 1, "There should be one and only one zone for an interior that manages zones");
      mSceneManager->registerZones(this, (mInteriorRes->getDetailLevel(0)->mZones.size() - 1));
   }

   return true;
}


//--------------------------------------------------------------------------
void InteriorInstance::onSceneRemove()
{
   AssertFatal(mInteriorRes, "Error, should not have been added to the scene if there's no interior!");

   if (isManagingZones())
      mSceneManager->unregisterZones(this);

   Parent::onSceneRemove();
}


//--------------------------------------------------------------------------
bool InteriorInstance::getOverlappingZones(SceneObject* obj,
                                           U32*         zones,
                                           U32*         numZones)
{
   MatrixF xForm(true);
   Point3F invScale(1.0f / getScale().x,
                    1.0f / getScale().y,
                    1.0f / getScale().z);
   xForm.scale(invScale);
   xForm.mul(getWorldTransform());
   xForm.mul(obj->getTransform());
   xForm.scale(obj->getScale());

   U32 waterMark = FrameAllocator::getWaterMark();

   U16* zoneVector = (U16*)FrameAllocator::alloc(mInteriorRes->getDetailLevel(0)->mZones.size() * sizeof(U16));
   U32 numRetZones = 0;

   bool outsideToo = mInteriorRes->getDetailLevel(0)->scanZones(obj->getObjBox(),
                                                                xForm,
                                                                zoneVector,
                                                                &numRetZones);
   if (numRetZones > SceneObject::MaxObjectZones)
   {
      Con::warnf(ConsoleLogEntry::General, "Too many zones returned for query on %s.  Returning first %d",
                 mInteriorFileName, SceneObject::MaxObjectZones);
   }

   for (U32 i = 0; i < getMin(numRetZones, U32(SceneObject::MaxObjectZones)); i++)
      zones[i] = zoneVector[i] + mZoneRangeStart - 1;
   *numZones = numRetZones;

   FrameAllocator::setWaterMark(waterMark);

   return outsideToo;
}


//--------------------------------------------------------------------------
U32 InteriorInstance::getPointZone(const Point3F& p)
{
   AssertFatal(mInteriorRes, "Error, no interior!");

   Point3F osPoint = p;
   mWorldToObj.mulP(osPoint);
   osPoint.convolveInverse(mObjScale);

   const S32 zone = mInteriorRes->getDetailLevel(0)->getZoneForPoint(osPoint);

   // If we're in solid (-1) or outside, we need to return 0
   if (zone == -1 || zone == 0)
      return 0;

   return (zone-1) + mZoneRangeStart;
}

// does a hack check to determine how much a point is 'inside'.. should have
// portals prebuilt with the transfer energy to each other portal in the zone
// from the neighboring zone.. these values can be used to determine the factor
// from within an individual zone.. also, each zone could be marked with
// average material property for eax environment audio
// ~0: outside -> 1: inside
bool InteriorInstance::getPointInsideScale(const Point3F & pos, F32 * pScale)
{
   AssertFatal(mInteriorRes, "InteriorInstance::getPointInsideScale: no interior");

   Interior * interior = mInteriorRes->getDetailLevel(0);

   Point3F p = pos;
   mWorldToObj.mulP(p);
   p.convolveInverse(mObjScale);

   U32 zoneIndex = interior->getZoneForPoint(p);
   if(zoneIndex == -1)  // solid?
   {
      *pScale = 1.f;
      return(true);
   }
   else if(zoneIndex == 0) // outside?
   {
      *pScale = 0.f;
      return(true);
   }

   U32 waterMark = FrameAllocator::getWaterMark();
   const Interior::Portal** portals = (const Interior::Portal**)FrameAllocator::alloc(256 * sizeof(const Interior::Portal*));
   U32 numPortals = 0;

   Interior::Zone & zone = interior->mZones[zoneIndex];

   U32 i;
   for(i = 0; i < zone.portalCount; i++)
   {
      const Interior::Portal & portal = interior->mPortals[interior->mZonePortalList[zone.portalStart + i]];
      if(portal.zoneBack == 0 || portal.zoneFront == 0)
      {
         AssertFatal(numPortals < 256, "Error, overflow in temporary portal buffer!");
         portals[numPortals++] = &portal;
      }
   }

   // inside?
   if(numPortals == 0)
   {
      *pScale = 1.f;

      FrameAllocator::setWaterMark(waterMark);
      return(true);
   }

   Point3F* portalCenters = (Point3F*)FrameAllocator::alloc(numPortals * sizeof(Point3F));
   U32 numPortalCenters = 0;

   // scale using the distances to the portals in this zone...
   for(i = 0; i < numPortals; i++)
   {
      const Interior::Portal * portal = portals[i];
      if(!portal->triFanCount)

⌨️ 快捷键说明

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