Initial commit
This commit is contained in:
784
Torque/SDK/engine/interior/interiorMap.cc
Normal file
784
Torque/SDK/engine/interior/interiorMap.cc
Normal file
@@ -0,0 +1,784 @@
|
||||
#include "interiorMap.h"
|
||||
|
||||
#include "dgl/dgl.h"
|
||||
#include "core/bitStream.h"
|
||||
#include "game/gameConnection.h"
|
||||
#include "math/mathIO.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "collision/concretePolyList.h"
|
||||
#include "dgl/gBitmap.h"
|
||||
#include "math/mPlaneTransformer.h"
|
||||
|
||||
#define FRONTEPSILON 0.00001
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
IMPLEMENT_CO_NETOBJECT_V1(InteriorMap);
|
||||
|
||||
// Return the bounding box transformed into world space
|
||||
Box3F InteriorMapConvex::getBoundingBox() const
|
||||
{
|
||||
return getBoundingBox(mObject->getTransform(), mObject->getScale());
|
||||
}
|
||||
|
||||
// Transform and scale the bounding box by the inputs
|
||||
Box3F InteriorMapConvex::getBoundingBox(const MatrixF& mat, const Point3F& scale) const
|
||||
{
|
||||
Box3F newBox = box;
|
||||
newBox.min.convolve(scale);
|
||||
newBox.max.convolve(scale);
|
||||
mat.mul(newBox);
|
||||
return newBox;
|
||||
}
|
||||
|
||||
// Return the point furthest from the input vector
|
||||
Point3F InteriorMapConvex::support(const VectorF& v) const
|
||||
{
|
||||
Point3F ret(0.0f, 0.0f, 0.0f);
|
||||
F32 dp = 0.0f;
|
||||
F32 tp = 0.0f;
|
||||
|
||||
// Loop through the points and save the furthest one
|
||||
//for (U32 i = 0; i < 8; i++)
|
||||
//{
|
||||
// tp = mDot(v, pOwner->mPoints[i]);
|
||||
|
||||
// if (tp > dp)
|
||||
// {
|
||||
// dp = tp;
|
||||
// ret = pOwner->mPoints[i];
|
||||
// }
|
||||
//}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// This function simply checks to see if the edge already exists on the edgelist
|
||||
// If it doesn't the edge gets added
|
||||
void InteriorMapConvex::addEdge(U32 zero, U32 one, U32 base, ConvexFeature* cf)
|
||||
{
|
||||
U32 newEdge0, newEdge1;
|
||||
|
||||
// Sort the vertex indexes by magnitude (lowest number first, largest second)
|
||||
newEdge0 = getMin(zero, one) + base;
|
||||
newEdge1 = getMax(zero, one) + base;
|
||||
|
||||
// Assume that it isn't found
|
||||
bool found = false;
|
||||
|
||||
// Loop through the edgelist
|
||||
// Start with base so we don't search *all* of the edges if there already are some on the list
|
||||
for (U32 k = base; k < cf->mEdgeList.size(); k++)
|
||||
{
|
||||
// If we find a match flag found and break out (no need to keep searching)
|
||||
if (cf->mEdgeList[k].vertex[0] == newEdge0 && cf->mEdgeList[k].vertex[1] == newEdge1)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't find it then add it
|
||||
// Otherwise we return without doing anything
|
||||
if (!found)
|
||||
{
|
||||
cf->mEdgeList.increment();
|
||||
cf->mEdgeList.last().vertex[0] = newEdge0;
|
||||
cf->mEdgeList.last().vertex[1] = newEdge1;
|
||||
}
|
||||
};
|
||||
|
||||
// Return the vertices, faces, and edges of the convex
|
||||
// Used by the vehicle collisions
|
||||
void InteriorMapConvex::getFeatures(const MatrixF& mat,const VectorF& n, ConvexFeature* cf)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Return list(s) of convex faces
|
||||
// Used by player collisions
|
||||
void InteriorMapConvex::getPolyList(AbstractPolyList* list)
|
||||
{
|
||||
// Be sure to transform the list into model space
|
||||
list->setTransform(&mObject->getTransform(), mObject->getScale());
|
||||
// Set the object
|
||||
list->setObject(mObject);
|
||||
|
||||
// Get the brush
|
||||
ConvexBrush* brush = pOwner->mInteriorRes->mBrushes[brushIndex];
|
||||
|
||||
brush->getPolyList(list);
|
||||
}
|
||||
|
||||
InteriorMap::InteriorMap(void)
|
||||
{
|
||||
// Setup NetObject.
|
||||
// Note that we set this as a TutorialObjectType object
|
||||
// TutorialObjectType is defined in game/objectTypes.h in the SimObjectTypes enum
|
||||
// You should also notify the scripting engine of it existance in game/main.cc in initGame()
|
||||
mTypeMask = StaticObjectType | StaticRenderedObjectType | InteriorMapObjectType;
|
||||
mNetFlags.set(Ghostable);
|
||||
|
||||
// Haven't loaded yet
|
||||
mLoaded = false;
|
||||
|
||||
// Give it a nonexistant bounding box
|
||||
mObjBox.min.set(0, 0, 0);
|
||||
mObjBox.max.set(0, 0, 0);
|
||||
|
||||
mConvexList = new Convex;
|
||||
mTexPath = NULL;
|
||||
mRenderMode = TexShaded;
|
||||
mEnableLights = true;
|
||||
mTexHandles = NULL;
|
||||
}
|
||||
|
||||
InteriorMap::~InteriorMap(void)
|
||||
{
|
||||
delete mConvexList;
|
||||
mConvexList = NULL;
|
||||
}
|
||||
|
||||
void InteriorMap::initPersistFields()
|
||||
{
|
||||
// Initialise parents' persistent fields.
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField( "File", TypeFilename, Offset( mFileName, InteriorMap ) );
|
||||
}
|
||||
|
||||
bool InteriorMap::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd()) return(false);
|
||||
|
||||
// Set our path info
|
||||
setPath(mFileName);
|
||||
|
||||
// Load resource
|
||||
mInteriorRes = ResourceManager->load(mFileName, true);
|
||||
if (bool(mInteriorRes) == false)
|
||||
{
|
||||
Con::errorf(ConsoleLogEntry::General, "Unable to load interior: %s", mFileName);
|
||||
NetConnection::setLastError("Unable to load interior: %s", mFileName);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
mLoaded = true;
|
||||
|
||||
// Scale our brushes
|
||||
if (mInteriorRes->mBrushScale != 1.0f)
|
||||
{
|
||||
for (U32 i = 0; i < mInteriorRes->mBrushes.size(); i++)
|
||||
mInteriorRes->mBrushes[i]->setScale(mInteriorRes->mBrushScale);
|
||||
}
|
||||
|
||||
loadTextures();
|
||||
|
||||
mInteriorRes->mTexGensCalced = calcTexgenDiv();
|
||||
|
||||
// Set the bounds
|
||||
mObjBox.min.set(1e10, 1e10, 1e10);
|
||||
mObjBox.max.set(-1e10, -1e10, -1e10);
|
||||
|
||||
for (U32 i = 0; i < mInteriorRes->mBrushes.size(); i++)
|
||||
{
|
||||
if (mInteriorRes->mBrushes[i]->mStatus == ConvexBrush::Good)
|
||||
{
|
||||
// Transform the bounding boxes
|
||||
MatrixF& mat = mInteriorRes->mBrushes[i]->mTransform;
|
||||
Point3F& scale = mInteriorRes->mBrushes[i]->mScale;
|
||||
|
||||
Point3F min = mInteriorRes->mBrushes[i]->mBounds.min;
|
||||
Point3F max = mInteriorRes->mBrushes[i]->mBounds.max;
|
||||
|
||||
mat.mulP(min);
|
||||
mat.mulP(max);
|
||||
|
||||
min.convolveInverse(scale);
|
||||
max.convolveInverse(scale);
|
||||
|
||||
mObjBox.min.setMin(min);
|
||||
mObjBox.max.setMax(max);
|
||||
}
|
||||
}
|
||||
|
||||
mWhite = new TextureHandle("common/lighting/whiteAlpha255", MeshTexture);
|
||||
|
||||
// Reset the World Box.
|
||||
resetWorldBox();
|
||||
// Set the Render Transform.
|
||||
setRenderTransform(mObjToWorld);
|
||||
|
||||
// Add to Scene.
|
||||
addToScene();
|
||||
|
||||
// Return OK.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InteriorMap::setPath(const char* filename)
|
||||
{
|
||||
// Save our filename just in case it hasn't already been done
|
||||
mFileName = StringTable->insert(filename);
|
||||
|
||||
// Get the directory
|
||||
char dir[4096]; // FIXME: no hardcoded lengths
|
||||
if (dStrrchr(filename, '/'))
|
||||
{
|
||||
dStrncpy(dir, filename, (int)(dStrrchr(filename, '/') - filename + 1));
|
||||
dir[(int)(dStrrchr(filename, '/') - filename + 1)] = 0;
|
||||
}
|
||||
else if (dStrrchr(filename, '\\'))
|
||||
{
|
||||
dStrncpy(dir, filename, (int)(dStrrchr(filename, '\\') - filename + 1));
|
||||
dir[(int)(dStrrchr(filename, '\\') - filename + 1)] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
dSprintf(dir, dStrlen(Platform::getWorkingDirectory()) + 1, "%s/\0", Platform::getWorkingDirectory());
|
||||
}
|
||||
|
||||
mFilePath = StringTable->insert(dir);
|
||||
if (!mTexPath)
|
||||
mTexPath = mFilePath;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InteriorMap::loadTextures()
|
||||
{
|
||||
if (mTexHandles)
|
||||
return true;
|
||||
|
||||
// Load our textures
|
||||
mTexHandles = new TextureHandle[mInteriorRes->mMaterials.size()];
|
||||
|
||||
for (int t = 0; t < mInteriorRes->mMaterials.size(); t++)
|
||||
{
|
||||
mTexHandles[t] = NULL;
|
||||
|
||||
char fullname[8192];
|
||||
|
||||
// First go for standard
|
||||
dSprintf(fullname, 8192, "%s%s\0", mTexPath, mInteriorRes->mMaterials[t]);
|
||||
|
||||
mTexHandles[t] = TextureHandle(fullname, MeshTexture);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InteriorMap::calcTexgenDiv()
|
||||
{
|
||||
// If we have already calculated our texgen scale then we don't need to do it again
|
||||
// This occurs when the client and server are on the same machine (they share Resources)
|
||||
if (mInteriorRes->mTexGensCalced)
|
||||
return true;
|
||||
|
||||
if (mInteriorRes->mBrushFormat != InteriorMapResource::QuakeOld && mInteriorRes->mBrushFormat != InteriorMapResource::Valve220)
|
||||
return false;
|
||||
|
||||
for (U32 i = 0; i < mInteriorRes->mMaterials.size(); i++)
|
||||
{
|
||||
F32 width = 16.0f;
|
||||
F32 height = 16.0f;
|
||||
|
||||
if (mTexHandles[i].getWidth() != 0UL)
|
||||
{
|
||||
width = mTexHandles[i].getWidth();
|
||||
height = mTexHandles[i].getHeight();
|
||||
}
|
||||
|
||||
for (U32 j = 0; j < mInteriorRes->mBrushes.size(); j++)
|
||||
{
|
||||
for (U32 k = 0; k < mInteriorRes->mBrushes[j]->mFaces.mPolyList.size(); k++)
|
||||
{
|
||||
if (i == mInteriorRes->mBrushes[j]->mFaces.mPolyList[k].material)
|
||||
{
|
||||
mInteriorRes->mBrushes[j]->mTexInfos[k].texDiv[0] = width;
|
||||
mInteriorRes->mBrushes[j]->mTexInfos[k].texDiv[1] = height;
|
||||
|
||||
mInteriorRes->mBrushes[j]->mTexInfos[k].texGens[0].x /= width;
|
||||
mInteriorRes->mBrushes[j]->mTexInfos[k].texGens[0].y /= width;
|
||||
mInteriorRes->mBrushes[j]->mTexInfos[k].texGens[0].z /= width;
|
||||
mInteriorRes->mBrushes[j]->mTexInfos[k].texGens[0].d /= width;
|
||||
|
||||
mInteriorRes->mBrushes[j]->mTexInfos[k].texGens[1].x /= height;
|
||||
mInteriorRes->mBrushes[j]->mTexInfos[k].texGens[1].y /= height;
|
||||
mInteriorRes->mBrushes[j]->mTexInfos[k].texGens[1].z /= height;
|
||||
mInteriorRes->mBrushes[j]->mTexInfos[k].texGens[1].d /= height;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MDFFIX: Probably should move this to its own function
|
||||
// Scale the texgens by the brushscale
|
||||
for (U32 j = 0; j < mInteriorRes->mBrushes.size(); j++)
|
||||
{
|
||||
for (U32 k = 0; k < mInteriorRes->mBrushes[j]->mFaces.mPolyList.size(); k++)
|
||||
{
|
||||
mInteriorRes->mBrushes[j]->mTexInfos[k].texGens[0] *= mInteriorRes->mBrushScale;
|
||||
mInteriorRes->mBrushes[j]->mTexInfos[k].texGens[1] *= mInteriorRes->mBrushScale;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void InteriorMap::onRemove()
|
||||
{
|
||||
mConvexList->nukeList();
|
||||
|
||||
// Remove from Scene.
|
||||
removeFromScene();
|
||||
|
||||
// Do Parent.
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
void InteriorMap::inspectPostApply()
|
||||
{
|
||||
// Set Parent.
|
||||
Parent::inspectPostApply();
|
||||
|
||||
// Set Move Mask.
|
||||
setMaskBits(MoveMask);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void InteriorMap::onEditorEnable()
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void InteriorMap::onEditorDisable()
|
||||
{
|
||||
}
|
||||
|
||||
bool InteriorMap::prepRenderImage( SceneState* state, const U32 stateKey, const U32 startZone,
|
||||
const bool modifyBaseZoneState)
|
||||
{
|
||||
// Return if last state.
|
||||
if (isLastState(state, stateKey)) return false;
|
||||
// Set Last State.
|
||||
setLastState(state, stateKey);
|
||||
|
||||
// Is Object Rendered?
|
||||
if (state->isObjectRendered(this))
|
||||
{
|
||||
// Yes, so get a SceneRenderImage.
|
||||
SceneRenderImage* image = new SceneRenderImage;
|
||||
// Populate it.
|
||||
image->obj = this;
|
||||
image->isTranslucent = false;
|
||||
image->sortType = SceneRenderImage::Normal;
|
||||
|
||||
// Insert it into the scene images.
|
||||
state->insertRenderImage(image);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void InteriorMap::renderObject(SceneState* state, SceneRenderImage*)
|
||||
{
|
||||
// Check we are in Canonical State.
|
||||
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on entry");
|
||||
|
||||
// Save state.
|
||||
RectI viewport;
|
||||
|
||||
if (mEnableLights && mRenderMode != BrushColors && mRenderMode != FaceColors && mRenderMode != BspPolys && mRenderMode != CollisionHulls)
|
||||
{
|
||||
ColorF oneColor(1,1,1,1);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, oneColor);
|
||||
installLights();
|
||||
}
|
||||
|
||||
// Save Projection Matrix so we can restore Canonical state at exit.
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
|
||||
// Save Viewport so we can restore Canonical state at exit.
|
||||
dglGetViewport(&viewport);
|
||||
|
||||
// Setup the projection to the current frustum.
|
||||
//
|
||||
// NOTE:- You should let the SceneGraph drive the frustum as it
|
||||
// determines portal clipping etc.
|
||||
// It also leaves us with the MODELVIEW current.
|
||||
//
|
||||
state->setupBaseProjection();
|
||||
|
||||
// Save ModelView Matrix so we can restore Canonical state at exit.
|
||||
glPushMatrix();
|
||||
|
||||
// Transform by the objects' transform e.g move it.
|
||||
dglMultMatrix(&getTransform());
|
||||
|
||||
glScalef(mObjScale.x, mObjScale.y, mObjScale.z);
|
||||
|
||||
// I separated out the actual render function to make this a little cleaner
|
||||
if (mRenderMode != Edges && mRenderMode != BspPolys && mRenderMode != CollisionHulls)
|
||||
render();
|
||||
|
||||
if (mEnableLights && mRenderMode != BrushColors && mRenderMode != FaceColors && mRenderMode != BspPolys && mRenderMode != CollisionHulls)
|
||||
uninstallLights();
|
||||
|
||||
// Restore our canonical matrix state.
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
// Restore our canonical viewport state.
|
||||
dglSetViewport(viewport);
|
||||
|
||||
// Check we have restored Canonical State.
|
||||
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on exit");
|
||||
}
|
||||
|
||||
bool InteriorMap::render(void)
|
||||
{
|
||||
gRandGen.setSeed(1978);
|
||||
|
||||
//glEnable(GL_CULL_FACE);
|
||||
|
||||
ColorF oneColor;
|
||||
|
||||
if (mRenderMode == TexShaded || mRenderMode == TexWireframe ||
|
||||
mRenderMode == Lighting || mRenderMode == TexLighting)
|
||||
{
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, mWhite->getGLName());
|
||||
|
||||
if(mRenderMode == Lighting || mRenderMode == TexLighting)
|
||||
{
|
||||
glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, mWhite->getGLName());
|
||||
|
||||
if(mRenderMode == TexLighting)
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
else
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
}
|
||||
else
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
}
|
||||
|
||||
S32 bound = -2;
|
||||
|
||||
for (U32 i = 0; i < mInteriorRes->mBrushes.size(); i++)
|
||||
{
|
||||
if (mInteriorRes->mBrushes[i]->mType == InteriorMapResource::Portal || mInteriorRes->mBrushes[i]->mType == InteriorMapResource::Trigger)
|
||||
continue;
|
||||
|
||||
if (mInteriorRes->mBrushes[i]->mStatus == ConvexBrush::Deleted)
|
||||
continue;
|
||||
|
||||
if (mRenderMode == BrushColors)
|
||||
{
|
||||
//oneColor = ColorF(gRandGen.randF(0.0f, 1.0f), gRandGen.randF(0.0f, 1.0f), gRandGen.randF(0.0f, 1.0f), 1.0f);
|
||||
//glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, oneColor);
|
||||
glColor4f(gRandGen.randF(0.0f, 1.0f), gRandGen.randF(0.0f, 1.0f), gRandGen.randF(0.0f, 1.0f), 1.0f);
|
||||
}
|
||||
|
||||
// Save ModelView Matrix so we can restore Canonical state at exit.
|
||||
glPushMatrix();
|
||||
|
||||
// Transform by the objects' transform e.g move it.
|
||||
dglMultMatrix(&mInteriorRes->mBrushes[i]->mTransform);
|
||||
|
||||
// Scale
|
||||
//glScalef(mInteriorRes->mBrushes[i]->mScale.x, mInteriorRes->mBrushes[i]->mScale.y, mInteriorRes->mBrushes[i]->mScale.z);
|
||||
|
||||
for (U32 j = 0; j < mInteriorRes->mBrushes[i]->mFaces.mPolyList.size(); j++)
|
||||
{
|
||||
S32 tx = mInteriorRes->mBrushes[i]->mFaces.mPolyList[j].material;
|
||||
|
||||
if (tx == -2)
|
||||
continue;
|
||||
|
||||
if (mRenderMode == TexShaded || mRenderMode == TexWireframe ||
|
||||
mRenderMode == TexLighting)
|
||||
{
|
||||
if (tx != bound)
|
||||
{
|
||||
// Really cheesy way to see if I have a TextureObject
|
||||
if (mTexHandles[tx].getWidth() != 0UL)
|
||||
{
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glBindTexture(GL_TEXTURE_2D, mTexHandles[tx].getGLName());
|
||||
bound = tx;
|
||||
}
|
||||
else
|
||||
{
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glBindTexture(GL_TEXTURE_2D, mWhite->getGLName());
|
||||
bound = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mRenderMode == FaceColors)
|
||||
{
|
||||
//oneColor = ColorF(gRandGen.randF(0.0f, 1.0f), gRandGen.randF(0.0f, 1.0f), gRandGen.randF(0.0f, 1.0f), 1.0f);
|
||||
//glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, oneColor);
|
||||
glColor4f(gRandGen.randF(0.0f, 1.0f), gRandGen.randF(0.0f, 1.0f), gRandGen.randF(0.0f, 1.0f), 1.0f);
|
||||
}
|
||||
|
||||
mInteriorRes->mBrushes[i]->renderFace(j, (mRenderMode == Lighting || mRenderMode == TexLighting));
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
if (mRenderMode == TexShaded || mRenderMode == TexWireframe ||
|
||||
mRenderMode == Lighting || mRenderMode == TexLighting)
|
||||
{
|
||||
glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
//glDisable(GL_CULL_FACE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
U32 InteriorMap::packUpdate(NetConnection * con, U32 mask, BitStream * stream)
|
||||
{
|
||||
// Pack Parent.
|
||||
U32 retMask = Parent::packUpdate(con, mask, stream);
|
||||
|
||||
// Write fxPortal Mask Flag.
|
||||
if (stream->writeFlag(mask & MoveMask))
|
||||
{
|
||||
// Write Object Transform.
|
||||
stream->writeAffineTransform(mObjToWorld);
|
||||
|
||||
// Write Object Scale.
|
||||
mathWrite(*stream, mObjScale);
|
||||
|
||||
// Write the file name
|
||||
stream->writeString(mFileName);
|
||||
}
|
||||
|
||||
if (stream->writeFlag(mask & RenderModeMask))
|
||||
stream->write(mRenderMode);
|
||||
|
||||
// Were done ...
|
||||
return(retMask);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void InteriorMap::unpackUpdate(NetConnection * con, BitStream * stream)
|
||||
{
|
||||
// Unpack Parent.
|
||||
Parent::unpackUpdate(con, stream);
|
||||
|
||||
// Read fxPortal Mask Flag.
|
||||
if (stream->readFlag())
|
||||
{
|
||||
MatrixF ObjectMatrix;
|
||||
Point3F scale;
|
||||
|
||||
// Read Object Transform.
|
||||
stream->readAffineTransform(&ObjectMatrix);
|
||||
// Set Transform.
|
||||
setTransform(ObjectMatrix);
|
||||
|
||||
// Read Object Scale
|
||||
mathRead(*stream, &scale);
|
||||
// Set Scale
|
||||
setScale(scale);
|
||||
|
||||
// Reset the World Box.
|
||||
resetWorldBox();
|
||||
// Set the Render Transform.
|
||||
setRenderTransform(mObjToWorld);
|
||||
|
||||
// Read the file name
|
||||
mFileName = stream->readSTString();
|
||||
}
|
||||
|
||||
// New RenderMode?
|
||||
if (stream->readFlag())
|
||||
stream->read(&mRenderMode);
|
||||
}
|
||||
|
||||
void InteriorMap::buildConvex(const Box3F& box, Convex* convex)
|
||||
{
|
||||
Box3F realBox = box;
|
||||
mWorldToObj.mul(realBox);
|
||||
realBox.min.convolveInverse(mObjScale);
|
||||
realBox.max.convolveInverse(mObjScale);
|
||||
|
||||
mConvexList->collectGarbage();
|
||||
|
||||
for (U32 i = 0; i < mInteriorRes->mBrushes.size(); i++)
|
||||
{
|
||||
if (mInteriorRes->mBrushes[i]->mType == InteriorMapResource::Portal || mInteriorRes->mBrushes[i]->mType == InteriorMapResource::Trigger)
|
||||
continue;
|
||||
|
||||
if (mInteriorRes->mBrushes[i]->mStatus == ConvexBrush::Deleted)
|
||||
continue;
|
||||
|
||||
ConvexBrush* brush = mInteriorRes->mBrushes[i];
|
||||
|
||||
if (realBox.isOverlapped(brush->mBounds))
|
||||
{
|
||||
// See if this brush exists in the working set already...
|
||||
Convex* cc = 0;
|
||||
CollisionWorkingList& wl = convex->getWorkingList();
|
||||
|
||||
for (CollisionWorkingList* itr = wl.wLink.mNext; itr != &wl; itr = itr->wLink.mNext)
|
||||
{
|
||||
if (itr->mConvex->getType() == InteriorMapConvexType &&
|
||||
(static_cast<InteriorMapConvex*>(itr->mConvex)->getObject() == this &&
|
||||
static_cast<InteriorMapConvex*>(itr->mConvex)->brushIndex == i))
|
||||
{
|
||||
cc = itr->mConvex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cc)
|
||||
{
|
||||
// Got ourselves a new convex
|
||||
InteriorMapConvex* cp = new InteriorMapConvex;
|
||||
mConvexList->registerObject(cp);
|
||||
convex->addToWorkingList(cp);
|
||||
cp->mObject = this;
|
||||
cp->pOwner = this;
|
||||
cp->brushIndex = i;
|
||||
cp->box = brush->mBounds;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool InteriorMap::castRay(const Point3F& s, const Point3F& e, RayInfo* info)
|
||||
{
|
||||
// This assumes that the collision hulls are convex...otherwise it can return unpredictable results
|
||||
F32 outputFraction = 1.0f;
|
||||
VectorF outputNormal;
|
||||
|
||||
// Loop through the collision hulls checking for the nearest ray collision
|
||||
// MDFFIX: Again I really should have the collision hulls sorted into a bsp
|
||||
for (U32 i = 0; i < mInteriorRes->mBrushes.size(); i++)
|
||||
{
|
||||
if (mInteriorRes->mBrushes[i]->mStatus == ConvexBrush::Deleted)
|
||||
continue;
|
||||
|
||||
RayInfo test;
|
||||
|
||||
if (mInteriorRes->mBrushes[i]->castRay(s, e, &test))
|
||||
{
|
||||
if (test.t < outputFraction)
|
||||
{
|
||||
outputFraction = test.t;
|
||||
outputNormal = test.normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we had a collision fill in the info structure and return
|
||||
if (outputFraction >= 0.0f && outputFraction < 1.0f)
|
||||
{
|
||||
info->t = outputFraction;
|
||||
info->normal = outputNormal;
|
||||
info->point.interpolate(s, e, outputFraction);
|
||||
info->face = -1;
|
||||
info->object = this;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise we didn't collide
|
||||
return false;
|
||||
}
|
||||
|
||||
void InteriorMap::removeBrush(S32 brushIndex)
|
||||
{
|
||||
if (brushIndex < 0 || brushIndex >= mInteriorRes->mBrushes.size())
|
||||
return;
|
||||
|
||||
// Grab an iterator and point it at the beginning of the VectorPtr
|
||||
VectorPtr<ConvexBrush*>::iterator cbitr = mInteriorRes->mBrushes.begin();
|
||||
|
||||
// Move the pointer up to our brush
|
||||
cbitr += brushIndex;
|
||||
|
||||
// And remove it
|
||||
delete *cbitr;
|
||||
mInteriorRes->mBrushes.erase(cbitr);
|
||||
}
|
||||
|
||||
S32 InteriorMap::getBrushIndex(U32 brushID)
|
||||
{
|
||||
for (U32 i = 0; i < mInteriorRes->mBrushes.size(); i++)
|
||||
{
|
||||
if (mInteriorRes->mBrushes[i]->mID == brushID)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//****************************************************************************
|
||||
// Map Texture Management
|
||||
//****************************************************************************
|
||||
|
||||
// Returns the number of textures used in the map
|
||||
S32 InteriorMap::getTextureCount()
|
||||
{
|
||||
if(mInteriorRes)
|
||||
return mInteriorRes->mMaterials.size();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns the name of the texture given the texture's index
|
||||
const char* InteriorMap::getTextureName(S32 index)
|
||||
{
|
||||
S32 count = getTextureCount();
|
||||
if(index >= 0 && index < count)
|
||||
{
|
||||
if(mInteriorRes)
|
||||
return ((const char*) mInteriorRes->getTextureName(index));
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
// Returns the texture for the map
|
||||
const char* InteriorMap::getTexturePathway()
|
||||
{
|
||||
return ((const char*) mTexPath);
|
||||
}
|
||||
|
||||
// Returns the requested texture's dimensions
|
||||
Point2I InteriorMap::getTextureSize(S32 index)
|
||||
{
|
||||
S32 count = getTextureCount();
|
||||
if(index >= 0 && index < count)
|
||||
{
|
||||
if(mTexHandles[index])
|
||||
return Point2I(mTexHandles[index].getWidth(), mTexHandles[index].getHeight());
|
||||
}
|
||||
|
||||
return Point2I(0,0);
|
||||
}
|
||||
Reference in New Issue
Block a user