📄 interiorinstance.cc
字号:
mathWrite(*stream, mObjScale);
}
stream->writeFlag(mAlarmState);
// Check the lights to see if we need to update any of their states
LightUpdateGrouper::BitIterator itr;
for (itr = mUpdateGrouper->begin(); itr.valid() && itr.getNumKeys(); itr++)
{
if (stream->writeFlag((mask & itr.getMask()) != 0))
{
LightUpdateGrouper::BitIterator::iterator kItr;
for (kItr = itr.begin(); kItr != itr.end(); kItr++)
{
U32 key = *kItr;
U32 detail = detailFromUpdateKey(key);
U32 index = indexFromUpdateKey(key);
stream->writeFlag(mLightInfo[detail].mLights[index].active);
}
}
}
if (stream->writeFlag(mask & SkinBaseMask))
stream->writeString(mSkinBase);
// audio update:
if(stream->writeFlag(mask & AudioMask))
{
// profile:
if(stream->writeFlag(mAudioProfile))
stream->writeRangedU32(mAudioProfile->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast);
// environment:
if(stream->writeFlag(mAudioEnvironment))
stream->writeRangedU32(mAudioEnvironment->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast);
}
}
return retMask;
}
//------------------------------------------------------------------------------
void InteriorInstance::unpackUpdate(NetConnection* c, BitStream* stream)
{
Parent::unpackUpdate(c, stream);
MatrixF temp;
Point3F tempScale;
if (stream->readFlag())
{
// Initial Update
// CRC
stream->read(&mCRC);
// File
mInteriorFileName = stream->readSTString();
// Terrain flag
mShowTerrainInside = stream->readFlag();
// Transform
mathRead(*stream, &temp);
mathRead(*stream, &tempScale);
setScale(tempScale);
setTransform(temp);
// Alarm state: Note that we handle this ourselves on the initial update
// so that the state is always full on or full off...
mAlarmState = stream->readFlag();
mSkinBase = stream->readSTString();
// audio profile:
if(stream->readFlag())
{
U32 profileId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
mAudioProfile = dynamic_cast<AudioProfile*>(Sim::findObject(profileId));
}
else
mAudioProfile = 0;
// audio environment:
if(stream->readFlag())
{
U32 profileId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
mAudioEnvironment = dynamic_cast<AudioEnvironment*>(Sim::findObject(profileId));
}
else
mAudioEnvironment = 0;
// Lighting behavior.
mDoSimpleDynamicRender = mUseGLLighting = stream->readFlag();
}
else
{
// Normal update
if (stream->readFlag())
{
mathRead(*stream, &temp);
mathRead(*stream, &tempScale);
setScale(tempScale);
setTransform(temp);
}
setAlarmMode(stream->readFlag());
LightUpdateGrouper::BitIterator itr;
for (itr = mUpdateGrouper->begin(); itr.valid() && itr.getNumKeys(); itr++)
{
if (stream->readFlag())
{
LightUpdateGrouper::BitIterator::iterator kItr;
for (kItr = itr.begin(); kItr != itr.end(); kItr++)
{
U32 key = *kItr;
U32 detail = detailFromUpdateKey(key);
U32 index = indexFromUpdateKey(key);
if (stream->readFlag())
activateLight(detail, index);
else
deactivateLight(detail, index);
}
}
}
if (stream->readFlag())
{
mSkinBase = stream->readSTString();
renewOverlays();
}
// audio update:
if(stream->readFlag())
{
// profile:
if(stream->readFlag())
{
U32 profileId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
mAudioProfile = dynamic_cast<AudioProfile*>(Sim::findObject(profileId));
}
else
mAudioProfile = 0;
// environment:
if(stream->readFlag())
{
U32 profileId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
mAudioEnvironment = dynamic_cast<AudioEnvironment*>(Sim::findObject(profileId));
}
else
mAudioEnvironment = 0;
}
}
}
//------------------------------------------------------------------------------
Interior* InteriorInstance::getDetailLevel(const U32 level)
{
return mInteriorRes->getDetailLevel(level);
}
U32 InteriorInstance::getNumDetailLevels()
{
return mInteriorRes->getNumDetailLevels();
}
//--------------------------------------------------------------------------
//-------------------------------------- Alarm functionality
//
void InteriorInstance::setAlarmMode(const bool alarm)
{
if (mInteriorRes->getDetailLevel(0)->mHasAlarmState == false)
return;
if (mAlarmState == alarm)
return;
mAlarmState = alarm;
if (isServerObject())
{
setMaskBits(AlarmMask);
}
else
{
// DMMTODO: Invalidate current light state
}
}
//--------------------------------------------------------------------------
void InteriorInstance::rebuildVertexColors()
{
U32 i;
for (i = 0; i < mVertexColorsNormal.size(); i++)
{
delete mVertexColorsNormal[i];
mVertexColorsNormal[i] = NULL;
}
for (i = 0; i < mVertexColorsAlarm.size(); i++)
{
delete mVertexColorsAlarm[i];
mVertexColorsAlarm[i] = NULL;
}
if (bool(mInteriorRes) == false)
return;
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]));
}
for (i = 0; i < mInteriorRes->getNumDetailLevels(); i++)
{
Interior* pInterior = mInteriorRes->getDetailLevel(i);
pInterior->rebuildVertexColors(mLMHandle,
mVertexColorsNormal[i],
mVertexColorsAlarm[i]);
}
}
//--------------------------------------------------------------------------
void InteriorInstance::updateLightMap(Interior* pInterior, LightInfo& rLightInfo, const U32 surfaceIndex)
{
AssertFatal(surfaceIndex < pInterior->mSurfaces.size(), "Error, out of range surface index");
static U8 _newLightMapBuffer[256*256*3];
const Interior::Surface& rSurface = pInterior->mSurfaces[surfaceIndex];
if (rSurface.lightCount == 0)
return;
// Get the surface's original bitmap
TextureHandle* originalLMapHandle = ((mAlarmState == false) ?
gInteriorLMManager.getHandle(pInterior->getLMHandle(), mLMHandle,
pInterior->mNormalLMapIndices[surfaceIndex]) :
gInteriorLMManager.getHandle(pInterior->getLMHandle(), mLMHandle,
pInterior->mAlarmLMapIndices[surfaceIndex]));
const GBitmap* pOriginalLMap = originalLMapHandle->getBitmap();
AssertFatal(pOriginalLMap != NULL, "error, no lightmap on the handle!");
AssertFatal(pOriginalLMap->getFormat() == GBitmap::RGB, "error, bad lightmap format!");
// First, we need to create a buffer that will receive the new lightmap
U32 dimX = rSurface.mapSizeX;
U32 dimY = rSurface.mapSizeY;
U8* pNewLightmap = _newLightMapBuffer;
// copy the original lightmap
const U8 * src = pOriginalLMap->getAddress(rSurface.mapOffsetX, rSurface.mapOffsetY);
U8 * dest = pNewLightmap;
U32 runSize = rSurface.mapSizeX * 3;
U32 srcStep = pOriginalLMap->getWidth() * 3;
for(U32 y = 0; y < rSurface.mapSizeY; y++)
{
dMemcpy(dest, src, runSize);
dest += runSize;
src += srcStep;
}
// ...now we have the original lightmap, add in the animateds...
for (U32 i = 0; i < rSurface.lightCount; i++)
{
const LightInfo::StateDataInfo& rInfo = rLightInfo.mStateDataInfo[rSurface.lightStateInfoStart + i];
// Only add in states that affect this surface...duh.
if (rInfo.curMap != NULL && rInfo.alarm == (mAlarmState != Normal))
{
intensityMapMerge(pNewLightmap, dimX, dimY,
rInfo.curMap, rInfo.curColor);
}
}
// OK, now we have the final, current lightmap. subimage it in...
glBindTexture(GL_TEXTURE_2D, originalLMapHandle->getGLName());
if (Con::getBoolVariable("$pref::OpenGL::disableSubImage", false))
{
const U8 *src = pNewLightmap;
U8 *dest = (U8 *) pOriginalLMap->getAddress(rSurface.mapOffsetX, rSurface.mapOffsetY);
U32 destStep = pOriginalLMap->getWidth() * 3;
// copy back into the original lightmap
for (U32 y = 0; y < rSurface.mapSizeY; y++)
{
dMemcpy(dest, src, runSize);
src += runSize;
dest += destStep;
}
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
pOriginalLMap->getWidth(), pOriginalLMap->getHeight(),
0,
GL_RGB, GL_UNSIGNED_BYTE,
pOriginalLMap->getBits(0));
}
else
{
glTexSubImage2D(GL_TEXTURE_2D,
0,
rSurface.mapOffsetX, rSurface.mapOffsetY,
rSurface.mapSizeX, rSurface.mapSizeY,
GL_RGB, GL_UNSIGNED_BYTE,
pNewLightmap);
}
}
//--------------------------------------------------------------------------
void InteriorInstance::downloadLightmaps(SceneState* /*state*/,
Interior* pInterior,
LightInfo& rLightInfo)
{
extern U16* sgActivePolyList;
extern U32 sgActivePolyListSize;
for (U32 i = 0; i < sgActivePolyListSize; i++)
{
if (rLightInfo.mSurfaceInvalid.test(sgActivePolyList[i]) == true)
{
updateLightMap(pInterior, rLightInfo, sgActivePolyList[i]);
rLightInfo.mSurfaceInvalid.clear(sgActivePolyList[i]);
}
}
}
//--------------------------------------------------------------------------
void InteriorInstance::addChildren()
{
if (bool(mInteriorRes) == false)
return;
char nameBuffer[256];
U32 i;
// First thing to do, add a group with our name
SimGroup* myGroup = getGroup();
// Load all the interior game objects...
for(i = 0; i < mInteriorRes->getNumGameEntities(); i++)
{
ItrGameEntity *ent = mInteriorRes->getGameEntity(i);
ConsoleObject *obj = ConsoleObject::create(ent->mGameClass);
GameBase *gb = dynamic_cast<GameBase*>(obj);
if(!gb)
{
Con::errorf("Invalid game class for entity: %s", ent->mGameClass);
delete obj;
continue;
}
gb->setField("dataBlock", ent->mDataBlock);
gb->setModStaticFields(true);
for(U32 j = 0; j < ent->mDictionary.size(); j++)
gb->setDataField(StringTable->insert(ent->mDictionary[j].name), NULL, ent->mDictionary[j].value);
gb->setModStaticFields(false);
Point3F origin = ent->mPos;
origin.convolve(mObjScale);
getTransform().mulP(origin);
MatrixF xform(true);
xform.setColumn(3, origin);
gb->setTransform(xform);
if(!gb->registerObject())
{
Con::errorf("Failed to register entity: %s: %s", ent->mGameClass, ent->mDataBlock);
delete gb;
continue;
}
myGroup->addObject(gb);
}
// Next, for each door in our resource, we'll be creating a group
for (i = 0; i < mInteriorRes->getNumInteriorPathFollowers(); i++)
{
InteriorPathFollower* pSource = mInteriorRes->getInteriorPathFollower(i);
StringTableEntry name = StringTable->insert(pSource->mName);
PathedInterior* child = new PathedInterior;
child->mName = name;
child->mInteriorResIndex = pSource->mInteriorResIndex;
child->mPathIndex = pSource->mPathI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -