mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-21 23:53:51 +00:00
Adds Component, the various main component classes and their interfaces.
This commit is contained in:
parent
2e339bafba
commit
fa78a2f354
37 changed files with 9736 additions and 0 deletions
258
Engine/source/T3D/components/Collision/collisionInterfaces.cpp
Normal file
258
Engine/source/T3D/components/Collision/collisionInterfaces.cpp
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "T3D/Components/collision/collisionInterfaces.h"
|
||||
#include "scene/sceneObject.h"
|
||||
#include "T3D/Entity.h"
|
||||
#include "console/engineAPI.h"
|
||||
#include "T3D/trigger.h"
|
||||
#include "materials/baseMatInstance.h"
|
||||
|
||||
void CollisionInterface::handleCollisionList( CollisionList &collisionList, VectorF velocity )
|
||||
{
|
||||
Collision bestCol;
|
||||
|
||||
mCollisionList = collisionList;
|
||||
|
||||
for (U32 i=0; i < collisionList.getCount(); ++i)
|
||||
{
|
||||
Collision& colCheck = collisionList[i];
|
||||
|
||||
if (colCheck.object)
|
||||
{
|
||||
if (colCheck.object->getTypeMask() & PlayerObjectType)
|
||||
{
|
||||
handleCollision( colCheck, velocity );
|
||||
}
|
||||
else if (colCheck.object->getTypeMask() & TriggerObjectType)
|
||||
{
|
||||
// We've hit it's bounding box, that's close enough for triggers
|
||||
Trigger* pTrigger = static_cast<Trigger*>(colCheck.object);
|
||||
|
||||
Component *comp = dynamic_cast<Component*>(this);
|
||||
pTrigger->potentialEnterObject(comp->getOwner());
|
||||
}
|
||||
else if (colCheck.object->getTypeMask() & DynamicShapeObjectType)
|
||||
{
|
||||
Con::printf("HIT A GENERICALLY DYNAMIC OBJECT");
|
||||
handleCollision(colCheck, velocity);
|
||||
}
|
||||
else if(colCheck.object->getTypeMask() & EntityObjectType)
|
||||
{
|
||||
Entity* ent = dynamic_cast<Entity*>(colCheck.object);
|
||||
if (ent)
|
||||
{
|
||||
CollisionInterface *colObjectInterface = ent->getComponent<CollisionInterface>();
|
||||
if (colObjectInterface)
|
||||
{
|
||||
//convert us to our component
|
||||
Component *thisComp = dynamic_cast<Component*>(this);
|
||||
if (thisComp)
|
||||
{
|
||||
colObjectInterface->onCollisionSignal.trigger(thisComp->getOwner());
|
||||
|
||||
//TODO: properly do this
|
||||
Collision oppositeCol = colCheck;
|
||||
oppositeCol.object = thisComp->getOwner();
|
||||
|
||||
colObjectInterface->handleCollision(oppositeCol, velocity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
handleCollision(colCheck, velocity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionInterface::handleCollision( Collision &col, VectorF velocity )
|
||||
{
|
||||
if (col.object && (mContactInfo.contactObject == NULL ||
|
||||
col.object->getId() != mContactInfo.contactObject->getId()))
|
||||
{
|
||||
queueCollision(col.object, velocity - col.object->getVelocity());
|
||||
|
||||
//do the callbacks to script for this collision
|
||||
Component *comp = dynamic_cast<Component*>(this);
|
||||
if (comp->isMethod("onCollision"))
|
||||
{
|
||||
S32 matId = col.material != NULL ? col.material->getMaterial()->getId() : 0;
|
||||
Con::executef(comp, "onCollision", col.object, col.normal, col.point, matId, velocity);
|
||||
}
|
||||
|
||||
if (comp->getOwner()->isMethod("onCollisionEvent"))
|
||||
{
|
||||
S32 matId = col.material != NULL ? col.material->getMaterial()->getId() : 0;
|
||||
Con::executef(comp->getOwner(), "onCollisionEvent", col.object, col.normal, col.point, matId, velocity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionInterface::handleCollisionNotifyList()
|
||||
{
|
||||
//special handling for any collision components we should notify that a collision happened.
|
||||
for (U32 i = 0; i < mCollisionNotifyList.size(); ++i)
|
||||
{
|
||||
//convert us to our component
|
||||
Component *thisComp = dynamic_cast<Component*>(this);
|
||||
if (thisComp)
|
||||
{
|
||||
mCollisionNotifyList[i]->onCollisionSignal.trigger(thisComp->getOwner());
|
||||
}
|
||||
}
|
||||
|
||||
mCollisionNotifyList.clear();
|
||||
}
|
||||
|
||||
Chunker<CollisionInterface::CollisionTimeout> sTimeoutChunker;
|
||||
CollisionInterface::CollisionTimeout* CollisionInterface::sFreeTimeoutList = 0;
|
||||
|
||||
void CollisionInterface::queueCollision( SceneObject *obj, const VectorF &vec)
|
||||
{
|
||||
// Add object to list of collisions.
|
||||
SimTime time = Sim::getCurrentTime();
|
||||
S32 num = obj->getId();
|
||||
|
||||
CollisionTimeout** adr = &mTimeoutList;
|
||||
CollisionTimeout* ptr = mTimeoutList;
|
||||
while (ptr)
|
||||
{
|
||||
if (ptr->objectNumber == num)
|
||||
{
|
||||
if (ptr->expireTime < time)
|
||||
{
|
||||
ptr->expireTime = time + CollisionTimeoutValue;
|
||||
ptr->object = obj;
|
||||
ptr->vector = vec;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Recover expired entries
|
||||
if (ptr->expireTime < time)
|
||||
{
|
||||
CollisionTimeout* cur = ptr;
|
||||
*adr = ptr->next;
|
||||
ptr = ptr->next;
|
||||
cur->next = sFreeTimeoutList;
|
||||
sFreeTimeoutList = cur;
|
||||
}
|
||||
else
|
||||
{
|
||||
adr = &ptr->next;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
}
|
||||
|
||||
// New entry for the object
|
||||
if (sFreeTimeoutList != NULL)
|
||||
{
|
||||
ptr = sFreeTimeoutList;
|
||||
sFreeTimeoutList = ptr->next;
|
||||
ptr->next = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = sTimeoutChunker.alloc();
|
||||
}
|
||||
|
||||
ptr->object = obj;
|
||||
ptr->objectNumber = obj->getId();
|
||||
ptr->vector = vec;
|
||||
ptr->expireTime = time + CollisionTimeoutValue;
|
||||
ptr->next = mTimeoutList;
|
||||
|
||||
mTimeoutList = ptr;
|
||||
}
|
||||
|
||||
bool CollisionInterface::checkEarlyOut(Point3F start, VectorF velocity, F32 time, Box3F objectBox, Point3F objectScale,
|
||||
Box3F collisionBox, U32 collisionMask, CollisionWorkingList &colWorkingList)
|
||||
{
|
||||
Point3F end = start + velocity * time;
|
||||
Point3F distance = end - start;
|
||||
|
||||
Box3F scaledBox = objectBox;
|
||||
scaledBox.minExtents.convolve(objectScale);
|
||||
scaledBox.maxExtents.convolve(objectScale);
|
||||
|
||||
if (mFabs(distance.x) < objectBox.len_x() &&
|
||||
mFabs(distance.y) < objectBox.len_y() &&
|
||||
mFabs(distance.z) < objectBox.len_z())
|
||||
{
|
||||
// We can potentially early out of this. If there are no polys in the clipped polylist at our
|
||||
// end position, then we can bail, and just set start = end;
|
||||
Box3F wBox = scaledBox;
|
||||
wBox.minExtents += end;
|
||||
wBox.maxExtents += end;
|
||||
|
||||
static EarlyOutPolyList eaPolyList;
|
||||
eaPolyList.clear();
|
||||
eaPolyList.mNormal.set(0.0f, 0.0f, 0.0f);
|
||||
eaPolyList.mPlaneList.clear();
|
||||
eaPolyList.mPlaneList.setSize(6);
|
||||
eaPolyList.mPlaneList[0].set(wBox.minExtents,VectorF(-1.0f, 0.0f, 0.0f));
|
||||
eaPolyList.mPlaneList[1].set(wBox.maxExtents,VectorF(0.0f, 1.0f, 0.0f));
|
||||
eaPolyList.mPlaneList[2].set(wBox.maxExtents,VectorF(1.0f, 0.0f, 0.0f));
|
||||
eaPolyList.mPlaneList[3].set(wBox.minExtents,VectorF(0.0f, -1.0f, 0.0f));
|
||||
eaPolyList.mPlaneList[4].set(wBox.minExtents,VectorF(0.0f, 0.0f, -1.0f));
|
||||
eaPolyList.mPlaneList[5].set(wBox.maxExtents,VectorF(0.0f, 0.0f, 1.0f));
|
||||
|
||||
// Build list from convex states here...
|
||||
CollisionWorkingList& rList = colWorkingList;
|
||||
CollisionWorkingList* pList = rList.wLink.mNext;
|
||||
while (pList != &rList)
|
||||
{
|
||||
Convex* pConvex = pList->mConvex;
|
||||
|
||||
if (pConvex->getObject()->getTypeMask() & collisionMask)
|
||||
{
|
||||
Box3F convexBox = pConvex->getBoundingBox();
|
||||
|
||||
if (wBox.isOverlapped(convexBox))
|
||||
{
|
||||
// No need to separate out the physical zones here, we want those
|
||||
// to cause a fallthrough as well...
|
||||
pConvex->getPolyList(&eaPolyList);
|
||||
}
|
||||
}
|
||||
pList = pList->wLink.mNext;
|
||||
}
|
||||
|
||||
if (eaPolyList.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Collision* CollisionInterface::getCollision(S32 col)
|
||||
{
|
||||
if(col < mCollisionList.getCount() && col >= 0)
|
||||
return &mCollisionList[col];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue