Initial commit
This commit is contained in:
328
Torque/SDK/engine/game/physicalZone.cc
Normal file
328
Torque/SDK/engine/game/physicalZone.cc
Normal file
@@ -0,0 +1,328 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "game/physicalZone.h"
|
||||
#include "core/bitStream.h"
|
||||
#include "collision/boxConvex.h"
|
||||
#include "collision/clippedPolyList.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "math/mathIO.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "sceneGraph/sceneState.h"
|
||||
|
||||
IMPLEMENT_CO_NETOBJECT_V1(PhysicalZone);
|
||||
|
||||
ConsoleMethod(PhysicalZone, activate, void, 2, 2, "Activate the physical zone's effects.")
|
||||
{
|
||||
if (object->isClientObject())
|
||||
return;
|
||||
|
||||
object->activate();
|
||||
}
|
||||
|
||||
ConsoleMethod(PhysicalZone, deactivate, void, 2, 2, "Deactivate the physical zone's effects.")
|
||||
{
|
||||
if (object->isClientObject())
|
||||
return;
|
||||
|
||||
object->deactivate();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//--------------------------------------
|
||||
//
|
||||
PhysicalZone::PhysicalZone()
|
||||
{
|
||||
mNetFlags.set(Ghostable | ScopeAlways);
|
||||
|
||||
mTypeMask |= PhysicalZoneObjectType;
|
||||
|
||||
mVelocityMod = 1.0f;
|
||||
mGravityMod = 1.0f;
|
||||
mAppliedForce.set(0, 0, 0);
|
||||
|
||||
mConvexList = new Convex;
|
||||
mActive = true;
|
||||
}
|
||||
|
||||
PhysicalZone::~PhysicalZone()
|
||||
{
|
||||
delete mConvexList;
|
||||
mConvexList = NULL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void PhysicalZone::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
|
||||
addGroup("Misc");
|
||||
addField("velocityMod", TypeF32, Offset(mVelocityMod, PhysicalZone));
|
||||
addField("gravityMod", TypeF32, Offset(mGravityMod, PhysicalZone));
|
||||
addField("appliedForce", TypePoint3F, Offset(mAppliedForce, PhysicalZone));
|
||||
addField("polyhedron", TypeTriggerPolyhedron, Offset(mPolyhedron, PhysicalZone));
|
||||
endGroup("Misc");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool PhysicalZone::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
if (mVelocityMod < -40.0f || mVelocityMod > 40.0f) {
|
||||
Con::errorf("PhysicalZone: velocity mod out of range. [-40, 40]");
|
||||
mVelocityMod = mVelocityMod < -40.0f ? -40.0f : 40.0f;
|
||||
}
|
||||
if (mGravityMod < -40.0f || mGravityMod > 40.0f) {
|
||||
Con::errorf("PhysicalZone: GravityMod out of range. [-40, 40]");
|
||||
mGravityMod = mGravityMod < -40.0f ? -40.0f : 40.0f;
|
||||
}
|
||||
static const char* coordString[] = { "x", "y", "z" };
|
||||
F32* p = mAppliedForce;
|
||||
for (U32 i = 0; i < 3; i++) {
|
||||
if (p[i] < -40000.0f || p[i] > 40000.0f) {
|
||||
Con::errorf("PhysicalZone: applied force: %s out of range. [-40000, 40000]", coordString[i]);
|
||||
p[i] = p[i] < -40000.0f ? -40000.0f : 40000.0f;
|
||||
}
|
||||
}
|
||||
|
||||
Polyhedron temp = mPolyhedron;
|
||||
setPolyhedron(temp);
|
||||
|
||||
addToScene();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PhysicalZone::onRemove()
|
||||
{
|
||||
mConvexList->nukeList();
|
||||
|
||||
removeFromScene();
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void PhysicalZone::setTransform(const MatrixF & mat)
|
||||
{
|
||||
Parent::setTransform(mat);
|
||||
|
||||
MatrixF base(true);
|
||||
base.scale(Point3F(1.0/mObjScale.x,
|
||||
1.0/mObjScale.y,
|
||||
1.0/mObjScale.z));
|
||||
base.mul(mWorldToObj);
|
||||
mClippedList.setBaseTransform(base);
|
||||
|
||||
if (isServerObject())
|
||||
setMaskBits(InitialUpdateMask);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
U32 PhysicalZone::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
|
||||
{
|
||||
U32 i;
|
||||
U32 retMask = Parent::packUpdate(con, mask, stream);
|
||||
|
||||
if (stream->writeFlag((mask & InitialUpdateMask) != 0)) {
|
||||
// Note that we don't really care about efficiency here, since this is an
|
||||
// edit-only ghost...
|
||||
mathWrite(*stream, mObjToWorld);
|
||||
mathWrite(*stream, mObjScale);
|
||||
|
||||
// Write the polyhedron
|
||||
stream->write(mPolyhedron.pointList.size());
|
||||
for (i = 0; i < mPolyhedron.pointList.size(); i++)
|
||||
mathWrite(*stream, mPolyhedron.pointList[i]);
|
||||
|
||||
stream->write(mPolyhedron.planeList.size());
|
||||
for (i = 0; i < mPolyhedron.planeList.size(); i++)
|
||||
mathWrite(*stream, mPolyhedron.planeList[i]);
|
||||
|
||||
stream->write(mPolyhedron.edgeList.size());
|
||||
for (i = 0; i < mPolyhedron.edgeList.size(); i++) {
|
||||
const Polyhedron::Edge& rEdge = mPolyhedron.edgeList[i];
|
||||
|
||||
stream->write(rEdge.face[0]);
|
||||
stream->write(rEdge.face[1]);
|
||||
stream->write(rEdge.vertex[0]);
|
||||
stream->write(rEdge.vertex[1]);
|
||||
}
|
||||
|
||||
stream->write(mVelocityMod);
|
||||
stream->write(mGravityMod);
|
||||
mathWrite(*stream, mAppliedForce);
|
||||
stream->writeFlag(mActive);
|
||||
} else {
|
||||
stream->writeFlag(mActive);
|
||||
}
|
||||
|
||||
return retMask;
|
||||
}
|
||||
|
||||
void PhysicalZone::unpackUpdate(NetConnection* con, BitStream* stream)
|
||||
{
|
||||
Parent::unpackUpdate(con, stream);
|
||||
|
||||
if (stream->readFlag()) {
|
||||
U32 i, size;
|
||||
MatrixF temp;
|
||||
Point3F tempScale;
|
||||
Polyhedron tempPH;
|
||||
|
||||
// Transform
|
||||
mathRead(*stream, &temp);
|
||||
mathRead(*stream, &tempScale);
|
||||
|
||||
// Read the polyhedron
|
||||
stream->read(&size);
|
||||
tempPH.pointList.setSize(size);
|
||||
for (i = 0; i < tempPH.pointList.size(); i++)
|
||||
mathRead(*stream, &tempPH.pointList[i]);
|
||||
|
||||
stream->read(&size);
|
||||
tempPH.planeList.setSize(size);
|
||||
for (i = 0; i < tempPH.planeList.size(); i++)
|
||||
mathRead(*stream, &tempPH.planeList[i]);
|
||||
|
||||
stream->read(&size);
|
||||
tempPH.edgeList.setSize(size);
|
||||
for (i = 0; i < tempPH.edgeList.size(); i++) {
|
||||
Polyhedron::Edge& rEdge = tempPH.edgeList[i];
|
||||
|
||||
stream->read(&rEdge.face[0]);
|
||||
stream->read(&rEdge.face[1]);
|
||||
stream->read(&rEdge.vertex[0]);
|
||||
stream->read(&rEdge.vertex[1]);
|
||||
}
|
||||
|
||||
stream->read(&mVelocityMod);
|
||||
stream->read(&mGravityMod);
|
||||
mathRead(*stream, &mAppliedForce);
|
||||
|
||||
setPolyhedron(tempPH);
|
||||
setScale(tempScale);
|
||||
setTransform(temp);
|
||||
mActive = stream->readFlag();
|
||||
} else {
|
||||
mActive = stream->readFlag();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void PhysicalZone::setPolyhedron(const Polyhedron& rPolyhedron)
|
||||
{
|
||||
mPolyhedron = rPolyhedron;
|
||||
|
||||
if (mPolyhedron.pointList.size() != 0) {
|
||||
mObjBox.min.set(1e10, 1e10, 1e10);
|
||||
mObjBox.max.set(-1e10, -1e10, -1e10);
|
||||
for (U32 i = 0; i < mPolyhedron.pointList.size(); i++) {
|
||||
mObjBox.min.setMin(mPolyhedron.pointList[i]);
|
||||
mObjBox.max.setMax(mPolyhedron.pointList[i]);
|
||||
}
|
||||
} else {
|
||||
mObjBox.min.set(-0.5, -0.5, -0.5);
|
||||
mObjBox.max.set( 0.5, 0.5, 0.5);
|
||||
}
|
||||
|
||||
MatrixF xform = getTransform();
|
||||
setTransform(xform);
|
||||
|
||||
mClippedList.clear();
|
||||
mClippedList.mPlaneList = mPolyhedron.planeList;
|
||||
|
||||
MatrixF base(true);
|
||||
base.scale(Point3F(1.0/mObjScale.x,
|
||||
1.0/mObjScale.y,
|
||||
1.0/mObjScale.z));
|
||||
base.mul(mWorldToObj);
|
||||
|
||||
mClippedList.setBaseTransform(base);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void PhysicalZone::buildConvex(const Box3F& box, Convex* convex)
|
||||
{
|
||||
// These should really come out of a pool
|
||||
mConvexList->collectGarbage();
|
||||
|
||||
Box3F realBox = box;
|
||||
mWorldToObj.mul(realBox);
|
||||
realBox.min.convolveInverse(mObjScale);
|
||||
realBox.max.convolveInverse(mObjScale);
|
||||
|
||||
if (realBox.isOverlapped(getObjBox()) == false)
|
||||
return;
|
||||
|
||||
// Just return a box convex for the entire shape...
|
||||
Convex* cc = 0;
|
||||
CollisionWorkingList& wl = convex->getWorkingList();
|
||||
for (CollisionWorkingList* itr = wl.wLink.mNext; itr != &wl; itr = itr->wLink.mNext) {
|
||||
if (itr->mConvex->getType() == BoxConvexType &&
|
||||
itr->mConvex->getObject() == this) {
|
||||
cc = itr->mConvex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cc)
|
||||
return;
|
||||
|
||||
// Create a new convex.
|
||||
BoxConvex* cp = new BoxConvex;
|
||||
mConvexList->registerObject(cp);
|
||||
convex->addToWorkingList(cp);
|
||||
cp->init(this);
|
||||
|
||||
mObjBox.getCenter(&cp->mCenter);
|
||||
cp->mSize.x = mObjBox.len_x() / 2.0f;
|
||||
cp->mSize.y = mObjBox.len_y() / 2.0f;
|
||||
cp->mSize.z = mObjBox.len_z() / 2.0f;
|
||||
}
|
||||
|
||||
|
||||
bool PhysicalZone::testObject(SceneObject* enter)
|
||||
{
|
||||
if (mPolyhedron.pointList.size() == 0)
|
||||
return false;
|
||||
|
||||
mClippedList.clear();
|
||||
|
||||
SphereF sphere;
|
||||
sphere.center = (mWorldBox.min + mWorldBox.max) * 0.5;
|
||||
VectorF bv = mWorldBox.max - sphere.center;
|
||||
sphere.radius = bv.len();
|
||||
|
||||
enter->buildPolyList(&mClippedList, mWorldBox, sphere);
|
||||
return mClippedList.isEmpty() == false;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
void PhysicalZone::activate()
|
||||
{
|
||||
AssertFatal(isServerObject(), "Client objects not allowed in ForceFieldInstance::open()");
|
||||
|
||||
if (mActive != true)
|
||||
setMaskBits(ActiveMask);
|
||||
mActive = true;
|
||||
}
|
||||
|
||||
void PhysicalZone::deactivate()
|
||||
{
|
||||
AssertFatal(isServerObject(), "Client objects not allowed in ForceFieldInstance::close()");
|
||||
|
||||
if (mActive != false)
|
||||
setMaskBits(ActiveMask);
|
||||
mActive = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user