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

📄 interiorinstance.cc

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

      Point3F center(0, 0, 0);
      for(U32 j = 0; j < portal->triFanCount; j++)
      {
         const Interior::TriFan & fan = interior->mWindingIndices[portal->triFanStart + j];
         const U32 numPoints = fan.windingCount;

         if(!numPoints)
            continue;

         for(U32 k = 0; k < numPoints; k++)
         {
            const Point3F & a = interior->mPoints[interior->mWindings[fan.windingStart + k]].point;
            center += a;
         }

         center /= numPoints;
         portalCenters[numPortalCenters++] = center;
      }
   }

   // 'magic' check here...
   F32 magic = Con::getFloatVariable("Interior::insideDistanceFalloff", 10.f);

   F32 val = 0.f;
   for(i = 0; i < numPortalCenters; i++)
      val += 1.f - mClampF(Point3F(portalCenters[i] - p).len() / magic, 0.f, 1.f);

   *pScale = 1.f - mClampF(val, 0.f, 1.f);

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

//--------------------------------------------------------------------------
ColorF gInteriorFogColor(1, 1, 1);

void InteriorInstance::renderObject(SceneState* state, SceneRenderImage* sceneImage)
{
   AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on entry");

   if(gEditingMission && isHidden())
      return;

   PROFILE_START(InteriorRenderObject);

   PROFILE_START(IRO_GetZones);
   U32 storedWaterMark = FrameAllocator::getWaterMark();
   dglSetRenderPrimType(2);

   InteriorRenderImage* interiorImage = static_cast<InteriorRenderImage*>(sceneImage);

   Point3F osPoint = state->getCameraPosition();
   mRenderWorldToObj.mulP(osPoint);
   osPoint.convolveInverse(mObjScale);

   // Get the object space y vector
   Point3F osCamVector;
   state->mModelview.getColumn(1, &osCamVector);
   mRenderWorldToObj.mulV(osCamVector);
   osCamVector.convolve(getScale());
   osCamVector.normalize();

   Point3F osZVec(0, 0, 1);
   mRenderWorldToObj.mulV(osZVec);
   osZVec.convolve(getScale());

   // First, we want to test the planes and setup the fog...
   U32 zoneOffset = mZoneRangeStart != 0xFFFFFFFF ? mZoneRangeStart : 0;

   Interior* pInterior = mInteriorRes->getDetailLevel(interiorImage->mDetailLevel);

   U32 baseZone = 0xFFFFFFFF;
   if (getNumCurrZones() == 1)
   {
      baseZone = getCurrZone(0);
   }
   else
   {
      for (U32 i = 0; i < getNumCurrZones(); i++)
      {
         if (state->getZoneState(getCurrZone(i)).render == true)
         {
            if (baseZone == 0xFFFFFFFF)
            {
               baseZone = getCurrZone(i);
               break;
            }
         }
      }

      if (baseZone == 0xFFFFFFFF)
         baseZone = getCurrZone(0);
   }
   PROFILE_END();


   PROFILE_START(IRO_ComputeActivePolys);
   Point3F worldOrigin;
   getRenderTransform().getColumn(3, &worldOrigin);

   ZoneVisDeterminer zoneVis;

   if (interiorImage->mDetailLevel == 0)
   {
      zoneVis.runFromState(state, zoneOffset, baseZone);
      pInterior->setupActivePolyList(zoneVis, state, osPoint, osCamVector, osZVec, worldOrigin.z, getScale());
   }
   else
   {
      // Something else...
      pInterior->prepTempRender(state,
                                getCurrZone(0),
                                0,
                                mRenderObjToWorld, mObjScale,
                                state->mFlipCull);
      zoneVis.runFromRects(state, zoneOffset, baseZone);
      pInterior->setupActivePolyList(zoneVis, state, osPoint, osCamVector, osZVec, worldOrigin.z, getScale());
   }
   PROFILE_END();

   PROFILE_START(IRO_UpdateAnimatedLights);

   // Update the animated lights...
   if (!Interior::smUseVertexLighting)
   {
      LightInfo& rLightInfo = mLightInfo[interiorImage->mDetailLevel];
      downloadLightmaps(state, pInterior, rLightInfo);
   }

   PROFILE_END();

   PROFILE_START(IRO_RenderSolids);

   if(mDoSimpleDynamicRender)
      installLights();

   // Set up the model view and the global render state...
   RectI viewport;
   dglGetViewport(&viewport);
   glMatrixMode(GL_PROJECTION);
   glPushMatrix();
   glMatrixMode(GL_MODELVIEW);
   glPushMatrix();
   dglMultMatrix(&mRenderObjToWorld);
   glScalef(mObjScale.x, mObjScale.y, mObjScale.z);

   glEnable(GL_BLEND);
   glDisable(GL_CULL_FACE);
   glEnable(GL_TEXTURE_2D);

   // We need to decide if we're going to use the low-res textures
   Point3F camPoint = state->getCameraPosition();
   Point3F closestPoint = getRenderWorldBox().getClosestPoint(camPoint);
   F32 dist = (camPoint - closestPoint).len();
   if (dist != 0.0)
   {
      F32 length = dglProjectRadius(dist, 1.0f / pInterior->mAveTexGenLength);
      if (length < (1.0 / 16.0))
      {
         TextureManager::setSmallTexturesActive(true);
      }
   }

   pInterior->setupFog(state);
   pInterior->setOSCamPosition(osPoint);
   if (interiorImage->mBaseZone != 0)
      state->setupZoneProjection(interiorImage->mBaseZone + mZoneRangeStart - 1);
   else
      state->setupObjectProjection(this);

   gInteriorFogColor = state->getFogColor();

   // make sure to build vertex color information in case interiors were
   //  added after the relight scene
   if(&((*mVertexColorsNormal[interiorImage->mDetailLevel])[0]) == NULL)
	   rebuildVertexColors();

   if(mDoSimpleDynamicRender)
   {
      pInterior->renderAsShape();
   }
   else
   {
      pInterior->render(mAlarmState, mMaterialMaps[interiorImage->mDetailLevel], mLMHandle,
                        mVertexColorsNormal[interiorImage->mDetailLevel],
                        mVertexColorsAlarm[interiorImage->mDetailLevel]);
   }

   pInterior->clearFog();

   if(mDoSimpleDynamicRender)
      uninstallLights();

   PROFILE_END();
   PROFILE_START(IRO_RenderDynamicLights);

   // Do dynamic lights if appropriate.
   if (smRenderDynamicLights == true)
   {
      // Are there any lights?
      const S32 numLights = gClientSceneGraph->getLightManager()->getNumLights();
      if (numLights > 0)
      {
         // Read out light info...
         U32 lightWaterMark = FrameAllocator::getWaterMark();
         ::LightInfo** lightArray = (::LightInfo**)FrameAllocator::alloc(sizeof(::LightInfo*) * numLights);
         gClientSceneGraph->getLightManager()->getLights(lightArray);

         for (U32 i = 0; i < numLights; i++)
         {
            // Only consider point lights.
            if (lightArray[i]->mType != ::LightInfo::Point)
               continue;

            Point3F lightPoint = lightArray[i]->mPos;
            mRenderWorldToObj.mulP(lightPoint);
            lightPoint.convolveInverse(mObjScale);

            Box3F box;
            box.min = lightPoint;
            box.max = lightPoint;
            box.min -= Point3F(lightArray[i]->mRadius, lightArray[i]->mRadius, lightArray[i]->mRadius);
            box.max += Point3F(lightArray[i]->mRadius, lightArray[i]->mRadius, lightArray[i]->mRadius);

            // TODO: Account for scale...
            if (mObjBox.isOverlapped(box) == false)
               continue;

            // The number of light surfaces cannot exceed the total number of non-null surfaces in
            //  interior...
            U32  subWaterMark = FrameAllocator::getWaterMark();
            U32* lightSurfaces    = (U32*)FrameAllocator::alloc(pInterior->mSurfaces.size() * sizeof(U32));
            U32  numLightSurfaces = 0;
            if (pInterior->buildLightPolyList(lightSurfaces, &numLightSurfaces,
                                              box, mRenderWorldToObj, getScale()) == false)
            {
               FrameAllocator::setWaterMark(subWaterMark);
               continue;
            }

            pInterior->renderLights(lightArray[i], mRenderWorldToObj, getScale(), lightSurfaces, numLightSurfaces);
            FrameAllocator::setWaterMark(subWaterMark);
         }

         FrameAllocator::setWaterMark(lightWaterMark);
      }
   }
   PROFILE_END();

   glDisable(GL_BLEND);
   if (dglDoesSupportARBMultitexture())
   {
      glActiveTextureARB(GL_TEXTURE1_ARB);
      glDisable(GL_TEXTURE_2D);
      glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
      glActiveTextureARB(GL_TEXTURE0_ARB);
      glDisable(GL_TEXTURE_2D);
      glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
   }
   else
   {
      glDisable(GL_TEXTURE_2D);
      glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
   }

   glMatrixMode(GL_PROJECTION);
   glPopMatrix();
   dglSetViewport(viewport);

   glMatrixMode(GL_MODELVIEW);
   glPopMatrix();

   AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on exit");

   FrameAllocator::setWaterMark(storedWaterMark);
   dglSetRenderPrimType(0);

   // Reset the small textures...
   TextureManager::setSmallTexturesActive(false);

   PROFILE_END();
}


//--------------------------------------------------------------------------
bool InteriorInstance::scopeObject(const Point3F&        rootPosition,
                                   const F32             /*rootDistance*/,
                                   bool*                 zoneScopeState)
{
   AssertFatal(isManagingZones(), "Error, should be a zone manager if we are called on to scope the scene!");
   if (bool(mInteriorRes) == false)
      return false;

   Interior* pInterior = getDetailLevel(0);
   AssertFatal(pInterior->mZones.size() <= csgMaxZoneSize, "Error, too many zones!  Increase max");
   bool* pInteriorScopingState = sgScopeBoolArray;
   dMemset(pInteriorScopingState, 0, sizeof(bool) * pInterior->mZones.size());

   // First, let's transform the point into the interior's space
   Point3F interiorRoot = rootPosition;
   getWorldTransform().mulP(interiorRoot);
   interiorRoot.convolveInverse(getScale());

   S32 realStartZone = getPointZone(rootPosition);
   if (realStartZone != 0)
      realStartZone = realStartZone - mZoneRangeStart + 1;

   bool continueOut = pInterior->scopeZones(realStartZone,
                                            interiorRoot,
                                            pInteriorScopingState);

   // Copy pInteriorScopingState to zoneScopeState
   for (S32 i = 1; i < pInterior->mZones.size(); i++)
      zoneScopeState[i + mZoneRangeStart - 1] = pInteriorScopingState[i];

   return continueOut;
}


//--------------------------------------------------------------------------
U32 InteriorInstance::calcDetailLevel(SceneState* state, const Point3F& wsPoint)
{
   AssertFatal(mInteriorRes, "Error, should not try to calculate the deatil level without a resource to work with!");
   AssertFatal(getNumCurrZones() > 0, "Error, must belong to a zone for this to work");

   if (smDetailModification < 0.3)
      smDetailModification = 0.3;
   if (smDetailModification > 1.0)
      smDetailModification = 1.0;

   // Early out for simple interiors
   if (mInteriorRes->getNumDetailLevels() == 1)
      return 0;

   if((mForcedDetailLevel >= 0) && (mForcedDetailLevel < mInteriorRes->getNumDetailLevels()))
      return(mForcedDetailLevel);

   Point3F osPoint = wsPoint;
   mRenderWorldToObj.mulP(osPoint);
   osPoint.convolveInverse(mObjScale);

   // First, see if the point is in the object space bounding box of the highest detail
   //  If it is, then the detail level is zero.
   if (mObjBox.isContained(osPoint))
      return 0;

   // Otherwise, we're going to have to do some ugly trickery to get the projection.
   //  I've stolen the worldToScreenScale from dglMatrix, we'll have to calculate the
   //  projection of the bounding sphere of the lowest detail level.
   //  worldToScreenScale = (near * view.extent.x) / (right - left)
   RectI viewport;
   F64   frustum[4] = { 1e10, -1e10, 1e10, -1e10 };

   bool init = false;
   SceneObjectRef* pWalk = mZoneRefHead;
   AssertFatal(pWalk != NULL, "Error, object must exist in at least one zone to call this!");
   while (pWalk)
   {
      const SceneState::ZoneState& rState = state->getZoneState(pWalk->zone);
      if (rState.render == true)
      {
         // frustum
         if (rState.frustum[0] < frustum[0]) frustum[0] = rState.frustum[0];
         if (rState.frustum[1] > frustum[1]) frustum[1] = rState.frustum[1];
         if (rState.frustum[2] < frustum[2]) frustum[2] = rState.frustum[2];
         if (rState.frustum[3] > frustum[3]) frustum[3] = rState.frustum[3];

         // viewport
         if (init == false)
            viewport = rState.viewport;
         else
            viewport.unionRects(rState.viewport);

         init = true;
      }
      pWalk = pWalk->nextInObj;
   }

   AssertFatal(init, "InteriorInstance::calcDetailLevel - Error, at least one zone must be rendered here!");

   const F32 worldToScreenScale  = (state->getNearPlane() * viewport.extent.x) / (frustum[1] - frustum[0]);
   const SphereF& lowSphere      = mInteriorRes->getDetailLevel(mInteriorRes->getNumDetailLevels() - 1)->mBoundingSphere;
   const F32 dist                = (lowSphere.center - osPoint).len();
   F32 projRadius                = (lowSphere.radius / dist) * worldToScreenScale;

   // Scale the projRadius based on the objects maximum scale axis
   projRadius *= getMax(mFabs(mObjScale.x), getMax(mFabs(mObjScale.y), mFabs(mObjScale.z)));

   // Multiply based on detail preference...
   projRadius *= smDetailModification;

   // Ok, now we have the projected radius, we need to search through the interiors to
   //  find the largest interior that will support this projection.
   U32 final = mInteriorRes->getNumDetailLevels() - 1;
   for (U32 i = 0; i< mInteriorRes->getNumDetailLevels() - 1; i++)
   {
      Interior* pDetail = mInteriorRes->getDetailLevel(i);

⌨️ 快捷键说明

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