📄 interiorinstance.cc
字号:
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 + -