cyphesis/physics/Collision.cpp

439 lines
16 KiB
C++
Raw Permalink Normal View History

2006-01-19 Al Riddoch <alriddoch@zepler.org> * aiclient/ClientAccount.cpp, aiclient/ClientAccount.h, aiclient/ClientConnection.cpp, aiclient/ClientConnection.h, aiclient/client.cpp, aiclient/client.h, client/BaseClient.cpp, client/BaseClient.h, client/CharacterClient.cpp, client/CharacterClient.h, client/ClientConnection.cpp, client/ClientConnection.h, client/CreatorClient.cpp, client/CreatorClient.h, client/ObserverClient.cpp, client/ObserverClient.h, client/Py_CreatorClient.cpp, client/Py_CreatorClient.h, client/client.cpp, client/define_world.cpp, client/define_world.h, common/Add.h, common/Affect.h, common/AtlasFileLoader.cpp, common/AtlasFileLoader.h, common/Attack.h, common/BaseEntity.cpp, common/BaseEntity.h, common/BaseWorld.cpp, common/BaseWorld.h, common/Burn.h, common/Chop.h, common/Connect.h, common/CustomOp.cpp, common/CustomOp.h, common/CustomOp_impl.h, common/Cut.h, common/Database.cpp, common/Database.h, common/Delve.h, common/Dig.h, common/Eat.h, common/FormattedXMLWriter.cpp, common/FormattedXMLWriter.h, common/Generic.h, common/Load.h, common/Monitor.h, common/Mow.h, common/Nourish.h, common/OOGThing.cpp, common/OOGThing.h, common/Property.cpp, common/Property.h, common/Property_impl.h, common/Save.h, common/Setup.h, common/Tick.h, common/Unseen.h, common/Update.h, common/Use.h, common/Wield.h, common/accountbase.cpp, common/accountbase.h, common/const.cpp, common/const.h, common/custom.cpp, common/debug.h, common/globals.cpp, common/globals.h, common/id.cpp, common/id.h, common/inheritance.cpp, common/inheritance.h, common/inheritance_impl.h, common/log.cpp, common/log.h, common/newid.cpp, common/nls.h, common/op_switch.h, common/operations.cpp, common/operations.h, common/random.h, common/refno.h, common/serialno.cpp, common/serialno.h, common/system.cpp, common/system.h, common/terrain_utils.cpp, common/terrain_utils.h, common/type_utils.h, common/types.h, common/utility.cpp, common/utility.h, modules/DateTime.cpp, modules/DateTime.h, modules/Location.cpp, modules/Location.h, modules/WorldTime.cpp, modules/WorldTime.h, physics/BBox.cpp, physics/BBox.h, physics/Collision.cpp, physics/Collision.h, physics/Quaternion.cpp, physics/Quaternion.h, physics/Vector3D.cpp, physics/Vector3D.h, physics/VectorPol.h, rulesets/Area.cpp, rulesets/Area.h, rulesets/AreaProperty.cpp, rulesets/AreaProperty.h, rulesets/ArithmeticScript.cpp, rulesets/ArithmeticScript.h, rulesets/BaseMind.cpp, rulesets/BaseMind.h, rulesets/CalendarProperty.cpp, rulesets/CalendarProperty.h, rulesets/Character.cpp, rulesets/Character.h, rulesets/Combat.cpp, rulesets/Combat.h, rulesets/Container.cpp, rulesets/Container.h, rulesets/Creator.cpp, rulesets/Creator.h, rulesets/Entity.cpp, rulesets/Entity.h, rulesets/EntityProperties.cpp, rulesets/Entity_getLocation.h, rulesets/Fell.cpp, rulesets/Fell.h, rulesets/Food.cpp, rulesets/Food.h, rulesets/Line.cpp, rulesets/Line.h, rulesets/LineProperty.cpp, rulesets/LineProperty.h, rulesets/MemEntity.cpp, rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/MemMap.h, rulesets/MemMap_methods.h, rulesets/MindFactory.cpp, rulesets/MindFactory.h, rulesets/Missile.h, rulesets/Motion.cpp, rulesets/Motion.h, rulesets/Movement.cpp, rulesets/Movement.h, rulesets/Pedestrian.cpp, rulesets/Pedestrian.h, rulesets/Plant.cpp, rulesets/Plant.h, rulesets/Py_BBox.cpp, rulesets/Py_BBox.h, rulesets/Py_EntityWrapper.h, rulesets/Py_Location.cpp, rulesets/Py_Location.h, rulesets/Py_Map.cpp, rulesets/Py_Map.h, rulesets/Py_Mind.cpp, rulesets/Py_Mind.h, rulesets/Py_Object.cpp, rulesets/Py_Object.h, rulesets/Py_Operation.cpp, rulesets/Py_Operation.h, rulesets/Py_Oplist.cpp, rulesets/Py_Oplist.h, rulesets/Py_Optime.cpp, rulesets/Py_Optime.h, rulesets/Py_Point3D.cpp, rulesets/Py_Point3D.h, rulesets/Py_Property.cpp, rulesets/Py_Property.h, rulesets/Py_Quaternion.cpp, rulesets/Py_Quaternion.h, rulesets/Py_RootEntity.cpp, rulesets/Py_RootEntity.h, rulesets/Py_Statistics.cpp, rulesets/Py_Statistics.h, rulesets/Py_Task.cpp, rulesets/Py_Task.h, rulesets/Py_Thing.cpp, rulesets/Py_Thing.h, rulesets/Py_Vector3D.cpp, rulesets/Py_Vector3D.h, rulesets/Py_World.cpp, rulesets/Py_World.h, rulesets/Py_WorldTime.cpp, rulesets/Py_WorldTime.h, rulesets/PythonArithmeticScript.cpp, rulesets/PythonArithmeticScript.h, rulesets/PythonMindScript.cpp, rulesets/PythonMindScript.h, rulesets/PythonScript.cpp, rulesets/PythonScript.h, rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h, rulesets/PythonWrapper.cpp, rulesets/PythonWrapper.h, rulesets/Python_API.cpp, rulesets/Python_API.h, rulesets/Python_Script_Utils.h, rulesets/Script.cpp, rulesets/Script.h, rulesets/Stackable.cpp, rulesets/Stackable.h, rulesets/Statistics.cpp, rulesets/Statistics.h, rulesets/StatisticsProperty.cpp, rulesets/StatisticsProperty.h, rulesets/Structure.cpp, rulesets/Structure.h, rulesets/Task.cpp, rulesets/Task.h, rulesets/TaskScript.cpp, rulesets/TaskScript.h, rulesets/TerrainProperty.cpp, rulesets/TerrainProperty.h, rulesets/Thing.cpp, rulesets/Thing.h, rulesets/ThingFactory.cpp, rulesets/ThingFactory.h, rulesets/World.cpp, rulesets/World.h, rulesets/attributes.h, server/Account.cpp, server/Account.h, server/Admin.cpp, server/Admin.h, server/ArithmeticFactory.cpp, server/ArithmeticFactory.h, server/CommClient.cpp, server/CommClient.h, server/CommIdleSocket.cpp, server/CommIdleSocket.h, server/CommListener.cpp, server/CommListener.h, server/CommLocalClient.cpp, server/CommLocalClient.h, server/CommMDNSPublisher.cpp, server/CommMDNSPublisher.h, server/CommMaster.cpp, server/CommMaster.h, server/CommMetaClient.cpp, server/CommMetaClient.h, server/CommPSQLSocket.cpp, server/CommPSQLSocket.h, server/CommPeer.cpp, server/CommPeer.h, server/CommPeerListener.cpp, server/CommPeerListener.h, server/CommRemoteClient.cpp, server/CommRemoteClient.h, server/CommServer.cpp, server/CommServer.h, server/CommSlaveClient.cpp, server/CommSlaveClient.h, server/CommSlaveListener.cpp, server/CommSlaveListener.h, server/CommSocket.cpp, server/CommSocket.h, server/CommUnixListener.cpp, server/CommUnixListener.h, server/Connection.cpp, server/Connection.h, server/Connection_methods.h, server/EntityFactory.cpp, server/EntityFactory.h, server/ExternalMind.cpp, server/ExternalMind.h, server/Idle.cpp, server/Idle.h, server/Lobby.cpp, server/Lobby.h, server/Master.cpp, server/Master.h, server/Peer.cpp, server/Peer.h, server/Persistance.cpp, server/Persistance.h, server/PersistantThingFactory.cpp, server/PersistantThingFactory.h, server/PersistantThingFactory_impl.h, server/Persistor.cpp, server/Persistor.h, server/Persistor_impl.h, server/Player.cpp, server/Player.h, server/Restoration.cpp, server/Restoration.h, server/Restorer.cpp, server/Restorer.h, server/Restorer_impl.h, server/ScriptFactory.cpp, server/ScriptFactory.h, server/ServerRouting.cpp, server/ServerRouting.h, server/ServerRouting_methods.h, server/SlaveClientConnection.cpp, server/SlaveClientConnection.h, server/TaskFactory.cpp, server/TaskFactory.h, server/TrustedConnection.cpp, server/TrustedConnection.h, server/WorldRouter.cpp, server/WorldRouter.h, server/server.cpp, server/server.h, server/slave.cpp, tests/Areatest.cpp, tests/BaseEntitytest.cpp, tests/Charactertest.cpp, tests/Containertest.cpp, tests/Creatortest.cpp, tests/EntityExerciser.h, tests/EntityFactorytest.cpp, tests/Entitytest.cpp, tests/Foodtest.cpp, tests/IGEntityExerciser.h, tests/Linetest.cpp, tests/Locationtest.cpp, tests/OOGThingtest.cpp, tests/Planttest.cpp, tests/Propertytest.cpp, tests/Stackabletest.cpp, tests/Structuretest.cpp, tests/Tasktest.cpp, tests/TestWorld.h, tests/Thingtest.cpp, tests/WorldTimetest.cpp, tests/Worldtest.cpp, tests/allOperations.h, tests/collisiontest.cpp, tests/consttest.cpp, tests/distancetest.cpp, tests/emergencetest.cpp, tests/inheritancetest.cpp, tests/logtest.cpp, tests/randomtest.cpp, tests/systemtest.cpp, tests/transformtest.cpp, tests/type_utilstest.cpp, tests/utilitytest.cpp, tools/AdminClient.cpp, tools/AdminClient.h, tools/cyaddrules.cpp, tools/cycmd.cpp, tools/cyconfig.cpp, tools/cyconvertrules.cpp, tools/cyctrl.cpp, tools/cydbload.cpp, tools/cydumprules.cpp, tools/cyisoload.cpp, tools/cyloadrules.cpp, tools/cypasswd.cpp, tools/cywatchdog.cpp: Replace the copyright and license statements with new versions that include disclaimer of warranty, and permit distribution under later versions of the GPL.
2006-01-19 02:17:06 +00:00
// Cyphesis Online RPG Server and AI Engine
// Copyright (C) 2003 Alistair Riddoch
2006-01-19 Al Riddoch <alriddoch@zepler.org> * aiclient/ClientAccount.cpp, aiclient/ClientAccount.h, aiclient/ClientConnection.cpp, aiclient/ClientConnection.h, aiclient/client.cpp, aiclient/client.h, client/BaseClient.cpp, client/BaseClient.h, client/CharacterClient.cpp, client/CharacterClient.h, client/ClientConnection.cpp, client/ClientConnection.h, client/CreatorClient.cpp, client/CreatorClient.h, client/ObserverClient.cpp, client/ObserverClient.h, client/Py_CreatorClient.cpp, client/Py_CreatorClient.h, client/client.cpp, client/define_world.cpp, client/define_world.h, common/Add.h, common/Affect.h, common/AtlasFileLoader.cpp, common/AtlasFileLoader.h, common/Attack.h, common/BaseEntity.cpp, common/BaseEntity.h, common/BaseWorld.cpp, common/BaseWorld.h, common/Burn.h, common/Chop.h, common/Connect.h, common/CustomOp.cpp, common/CustomOp.h, common/CustomOp_impl.h, common/Cut.h, common/Database.cpp, common/Database.h, common/Delve.h, common/Dig.h, common/Eat.h, common/FormattedXMLWriter.cpp, common/FormattedXMLWriter.h, common/Generic.h, common/Load.h, common/Monitor.h, common/Mow.h, common/Nourish.h, common/OOGThing.cpp, common/OOGThing.h, common/Property.cpp, common/Property.h, common/Property_impl.h, common/Save.h, common/Setup.h, common/Tick.h, common/Unseen.h, common/Update.h, common/Use.h, common/Wield.h, common/accountbase.cpp, common/accountbase.h, common/const.cpp, common/const.h, common/custom.cpp, common/debug.h, common/globals.cpp, common/globals.h, common/id.cpp, common/id.h, common/inheritance.cpp, common/inheritance.h, common/inheritance_impl.h, common/log.cpp, common/log.h, common/newid.cpp, common/nls.h, common/op_switch.h, common/operations.cpp, common/operations.h, common/random.h, common/refno.h, common/serialno.cpp, common/serialno.h, common/system.cpp, common/system.h, common/terrain_utils.cpp, common/terrain_utils.h, common/type_utils.h, common/types.h, common/utility.cpp, common/utility.h, modules/DateTime.cpp, modules/DateTime.h, modules/Location.cpp, modules/Location.h, modules/WorldTime.cpp, modules/WorldTime.h, physics/BBox.cpp, physics/BBox.h, physics/Collision.cpp, physics/Collision.h, physics/Quaternion.cpp, physics/Quaternion.h, physics/Vector3D.cpp, physics/Vector3D.h, physics/VectorPol.h, rulesets/Area.cpp, rulesets/Area.h, rulesets/AreaProperty.cpp, rulesets/AreaProperty.h, rulesets/ArithmeticScript.cpp, rulesets/ArithmeticScript.h, rulesets/BaseMind.cpp, rulesets/BaseMind.h, rulesets/CalendarProperty.cpp, rulesets/CalendarProperty.h, rulesets/Character.cpp, rulesets/Character.h, rulesets/Combat.cpp, rulesets/Combat.h, rulesets/Container.cpp, rulesets/Container.h, rulesets/Creator.cpp, rulesets/Creator.h, rulesets/Entity.cpp, rulesets/Entity.h, rulesets/EntityProperties.cpp, rulesets/Entity_getLocation.h, rulesets/Fell.cpp, rulesets/Fell.h, rulesets/Food.cpp, rulesets/Food.h, rulesets/Line.cpp, rulesets/Line.h, rulesets/LineProperty.cpp, rulesets/LineProperty.h, rulesets/MemEntity.cpp, rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/MemMap.h, rulesets/MemMap_methods.h, rulesets/MindFactory.cpp, rulesets/MindFactory.h, rulesets/Missile.h, rulesets/Motion.cpp, rulesets/Motion.h, rulesets/Movement.cpp, rulesets/Movement.h, rulesets/Pedestrian.cpp, rulesets/Pedestrian.h, rulesets/Plant.cpp, rulesets/Plant.h, rulesets/Py_BBox.cpp, rulesets/Py_BBox.h, rulesets/Py_EntityWrapper.h, rulesets/Py_Location.cpp, rulesets/Py_Location.h, rulesets/Py_Map.cpp, rulesets/Py_Map.h, rulesets/Py_Mind.cpp, rulesets/Py_Mind.h, rulesets/Py_Object.cpp, rulesets/Py_Object.h, rulesets/Py_Operation.cpp, rulesets/Py_Operation.h, rulesets/Py_Oplist.cpp, rulesets/Py_Oplist.h, rulesets/Py_Optime.cpp, rulesets/Py_Optime.h, rulesets/Py_Point3D.cpp, rulesets/Py_Point3D.h, rulesets/Py_Property.cpp, rulesets/Py_Property.h, rulesets/Py_Quaternion.cpp, rulesets/Py_Quaternion.h, rulesets/Py_RootEntity.cpp, rulesets/Py_RootEntity.h, rulesets/Py_Statistics.cpp, rulesets/Py_Statistics.h, rulesets/Py_Task.cpp, rulesets/Py_Task.h, rulesets/Py_Thing.cpp, rulesets/Py_Thing.h, rulesets/Py_Vector3D.cpp, rulesets/Py_Vector3D.h, rulesets/Py_World.cpp, rulesets/Py_World.h, rulesets/Py_WorldTime.cpp, rulesets/Py_WorldTime.h, rulesets/PythonArithmeticScript.cpp, rulesets/PythonArithmeticScript.h, rulesets/PythonMindScript.cpp, rulesets/PythonMindScript.h, rulesets/PythonScript.cpp, rulesets/PythonScript.h, rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h, rulesets/PythonWrapper.cpp, rulesets/PythonWrapper.h, rulesets/Python_API.cpp, rulesets/Python_API.h, rulesets/Python_Script_Utils.h, rulesets/Script.cpp, rulesets/Script.h, rulesets/Stackable.cpp, rulesets/Stackable.h, rulesets/Statistics.cpp, rulesets/Statistics.h, rulesets/StatisticsProperty.cpp, rulesets/StatisticsProperty.h, rulesets/Structure.cpp, rulesets/Structure.h, rulesets/Task.cpp, rulesets/Task.h, rulesets/TaskScript.cpp, rulesets/TaskScript.h, rulesets/TerrainProperty.cpp, rulesets/TerrainProperty.h, rulesets/Thing.cpp, rulesets/Thing.h, rulesets/ThingFactory.cpp, rulesets/ThingFactory.h, rulesets/World.cpp, rulesets/World.h, rulesets/attributes.h, server/Account.cpp, server/Account.h, server/Admin.cpp, server/Admin.h, server/ArithmeticFactory.cpp, server/ArithmeticFactory.h, server/CommClient.cpp, server/CommClient.h, server/CommIdleSocket.cpp, server/CommIdleSocket.h, server/CommListener.cpp, server/CommListener.h, server/CommLocalClient.cpp, server/CommLocalClient.h, server/CommMDNSPublisher.cpp, server/CommMDNSPublisher.h, server/CommMaster.cpp, server/CommMaster.h, server/CommMetaClient.cpp, server/CommMetaClient.h, server/CommPSQLSocket.cpp, server/CommPSQLSocket.h, server/CommPeer.cpp, server/CommPeer.h, server/CommPeerListener.cpp, server/CommPeerListener.h, server/CommRemoteClient.cpp, server/CommRemoteClient.h, server/CommServer.cpp, server/CommServer.h, server/CommSlaveClient.cpp, server/CommSlaveClient.h, server/CommSlaveListener.cpp, server/CommSlaveListener.h, server/CommSocket.cpp, server/CommSocket.h, server/CommUnixListener.cpp, server/CommUnixListener.h, server/Connection.cpp, server/Connection.h, server/Connection_methods.h, server/EntityFactory.cpp, server/EntityFactory.h, server/ExternalMind.cpp, server/ExternalMind.h, server/Idle.cpp, server/Idle.h, server/Lobby.cpp, server/Lobby.h, server/Master.cpp, server/Master.h, server/Peer.cpp, server/Peer.h, server/Persistance.cpp, server/Persistance.h, server/PersistantThingFactory.cpp, server/PersistantThingFactory.h, server/PersistantThingFactory_impl.h, server/Persistor.cpp, server/Persistor.h, server/Persistor_impl.h, server/Player.cpp, server/Player.h, server/Restoration.cpp, server/Restoration.h, server/Restorer.cpp, server/Restorer.h, server/Restorer_impl.h, server/ScriptFactory.cpp, server/ScriptFactory.h, server/ServerRouting.cpp, server/ServerRouting.h, server/ServerRouting_methods.h, server/SlaveClientConnection.cpp, server/SlaveClientConnection.h, server/TaskFactory.cpp, server/TaskFactory.h, server/TrustedConnection.cpp, server/TrustedConnection.h, server/WorldRouter.cpp, server/WorldRouter.h, server/server.cpp, server/server.h, server/slave.cpp, tests/Areatest.cpp, tests/BaseEntitytest.cpp, tests/Charactertest.cpp, tests/Containertest.cpp, tests/Creatortest.cpp, tests/EntityExerciser.h, tests/EntityFactorytest.cpp, tests/Entitytest.cpp, tests/Foodtest.cpp, tests/IGEntityExerciser.h, tests/Linetest.cpp, tests/Locationtest.cpp, tests/OOGThingtest.cpp, tests/Planttest.cpp, tests/Propertytest.cpp, tests/Stackabletest.cpp, tests/Structuretest.cpp, tests/Tasktest.cpp, tests/TestWorld.h, tests/Thingtest.cpp, tests/WorldTimetest.cpp, tests/Worldtest.cpp, tests/allOperations.h, tests/collisiontest.cpp, tests/consttest.cpp, tests/distancetest.cpp, tests/emergencetest.cpp, tests/inheritancetest.cpp, tests/logtest.cpp, tests/randomtest.cpp, tests/systemtest.cpp, tests/transformtest.cpp, tests/type_utilstest.cpp, tests/utilitytest.cpp, tools/AdminClient.cpp, tools/AdminClient.h, tools/cyaddrules.cpp, tools/cycmd.cpp, tools/cyconfig.cpp, tools/cyconvertrules.cpp, tools/cyctrl.cpp, tools/cydbload.cpp, tools/cydumprules.cpp, tools/cyisoload.cpp, tools/cyloadrules.cpp, tools/cypasswd.cpp, tools/cywatchdog.cpp: Replace the copyright and license statements with new versions that include disclaimer of warranty, and permit distribution under later versions of the GPL.
2006-01-19 02:17:06 +00:00
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2009-04-09 12:42:44 +01:00
// $Id$
#include "Collision.h"
#include "modules/Location.h"
#include "common/debug.h"
#include "common/log.h"
#include <iostream>
2011-02-02 23:29:21 -08:00
#include <cassert>
static const bool debug_flag = false;
////////////////////////// COLLISION //////////////////////////
bool getCollisionTime(const Point3D & p, // Position of point
const Vector3D & u, // Velocity of point
// float point_time, // Time since position set
const Point3D & l, // Position on plane
const Vector3D & n, // Plane normal
const Vector3D & v, // Velocity of plane
// float plane_time, // Time since position set
float & time) // Collision time return
//
//
// | \ n
// p ___ u | v __\ l
// \ | /
// \ | /
// \ | /
// \ | /
// \ | /
// \ | /
// _________________________\|/___________________________
//
// The time when point hits plane is as follows:
//
// ( (p + u * t) - (l + v * t) ) . n = 0
//
// dot product ( . ) is x*x + y*y + z*z
//
// (p.x + u.x * t - l.x - v.x * t) * n.x +
// (p.y + u.y * t - l.y - v.y * t) * n.y +
// (p.z + u.z * t - l.z - v.z * t) * n.z = 0
//
// p.x * n.x + u.x * n.x * t - l.x * n.x - v.x * n.x * t +
// p.y * n.y + u.y * n.y * t - l.y * n.y - v.y * n.y * t +
// p.z * n.z + u.z * n.z * t - l.z * n.z - v.z * n.z * t = 0
//
//
// ( v.x * n.x + v.y * n.y + v.z * n.z - u.x * n.x - u.y * n.y - u.z * n.z ) * t
// = ( p.x * n.x - l.x * n.x + p.y * n.y - l.y * n.y + p.z * n.z - l.z * n.z )
//
// t =
// ( p.x * n.x - l.x * n.x + p.y * n.y - l.y * n.y + p.z * n.z - l.z * n.z ) /
// ( v.x * n.x + v.y * n.y + v.z * n.z - u.x * n.x - u.y * n.y - u.z * n.z )
//
// return value should indicate whether the point was infront of the plane
// before the collision.
//
{
time = ( p.x() * n.x() - l.x() * n.x()
+ p.y() * n.y() - l.y() * n.y()
+ p.z() * n.z() - l.z() * n.z() ) /
( v.x() * n.x() + v.y() * n.y()
+ v.z() * n.z() - u.x() * n.x()
- u.y() * n.y() - u.z() * n.z() );
// Set now_infront to true if point is currently in front of the plane
bool now_infront = (Dot(p - l, n) > 0.);
// Set collided to true if the collision has alread occured
bool collided = (time < 0.);
// Return true if the collision direction is from infront,
// whether it has already happened on not
// We require logical EOR, which for bools is equivalent to !=
// return ((now_infront && !collided) || (!now_infront && collided));
return now_infront != collided;
}
// Returns true if first_collision has been updated
static
bool predictEntryExit(const CoordList & c, // Vertices of this mesh
const Vector3D & u, // Velocity of this mesh
const CoordList & o, // Vertices of other mesh
const NormalSet & n, // Normals of other mesh
const Vector3D & v, // Velocity of other mesh
float & first_collision, // Time first vertex enters
Vector3D & normal) // Returned collision normal
{
// Check l vertices against o surfaces
Vector3D entry_normal;
bool ret = false, already = false;
// Iterate over vertices
CoordList::const_iterator Iend = c.end();
for (CoordList::const_iterator I = c.begin(); I != Iend; ++I) {
debug(std::cout << "outer loop" << std::endl << std::flush;);
float last_vertex_entry = -100, first_vertex_exit = 100, time;
// Iterate over surfaces
NormalSet::const_iterator Jend = n.end();
for (NormalSet::const_iterator J = n.begin(); J != Jend; ++J) {
const Point3D & s_pos = o[J->first];
const Vector3D & s_norm = J->second;
debug(std::cout << "Testing vertex " << *I << " to surface "
<< s_pos << ": " << s_norm;);
if (getCollisionTime(*I, u, s_pos, s_norm, v, time)) {
debug(std::cout << " Collision at " << time;);
// We are colliding from infront ie entering
if (time > last_vertex_entry) {
debug(std::cout << " new";);
last_vertex_entry = time;
entry_normal = s_norm;
}
} else {
debug(std::cout << " Emergence at " << time;);
// We are colliding fron behind ie exitint
if (time < first_vertex_exit) {
first_vertex_exit = time;
}
}
debug(std::cout << std::endl << std::flush;);
}
debug(std::cout << last_vertex_entry << ":"
<< first_vertex_exit << ":"
<< first_collision << std::endl << std::flush;);
if ((last_vertex_entry < first_vertex_exit) &&
(last_vertex_entry < first_collision)) {
if (last_vertex_entry >= 0.) {
first_collision = last_vertex_entry;
debug(std::cout << "hit" << std::endl << std::flush;);
ret = true;
normal = entry_normal;
} else {
// Indicate that one or more vertices is already in collision
already = true;
}
}
}
// If one or more vertices are already in collision, and some are yet to
// collide, then we consider that the collision is immediate.
if (ret && already) {
first_collision = 0.f;
// It is possible that we need to modify the normal here, perhaps
// to cancel out velocity completely.
}
return ret;
}
bool predictCollision(const CoordList & l, // Vertices of this mesh
const NormalSet & ln, // Normals of this mesh
const Vector3D & u, // Velocity of this mesh
const CoordList & o, // Vertices of other mesh
const NormalSet & on, // Normals of other mesh
const Vector3D & v, // Velocity of other mesh
float & time, // Returned time to collision
Vector3D & n) // Returned collision normal
{
debug(std::cout << u << ", " << v << std::endl << std::flush; );
debug(std::cout << "l with o normals" << std::endl << std::flush; );
bool lo = predictEntryExit(l, u, o, on, v, time, n);
debug(std::cout << "o with l normals" << std::endl << std::flush; );
bool ol = predictEntryExit(o, v, l, ln, u, time, n);
if (ol) {
// If ol is true then the collision is in the opposite direction,
// and the normal reaction needs to be reversed.
n = -n;
}
return (lo || ol);
}
//
// This is the vertex layout used by the 3Dbox functions.
//
//
// 6
//
//
// 7 5
//
//
// 4
//
//
//
// 2
//
//
// 3 1
// z
// |
// y\ | /x 0
// \|/
bool predictCollision(const Location & l, // This location
const Location & o, // Other location
float & time, // Returned time to collision
Vector3D & normal) // Returned normal acting on l
// Predict collision between 2 entity locations
// Returns whether the collision will occur
{
// FIXME Handle entities which have no box - just one vertex I think
// FIXME THe mesh conversion process below should probably be eliminated
// by generating the data when bBox or orienation are changed.
// This would also allow us to have other mesh shapes
assert(l.bBox().isValid());
assert(o.bBox().isValid());
assert(l.velocity().isValid());
Vector3D notMoving(0., 0., 0.);
bool oMoving = o.velocity().isValid();
const Vector3D & o_velocity = oMoving ? o.velocity() : notMoving;
assert(o_velocity.isValid());
Vector3D dist = o.pos() - l.pos();
if ((dist.mag() - l.velocity().mag() * time - o_velocity.mag() * time) >
(boxBoundingRadius(l.bBox()) + boxBoundingRadius(o.bBox()))) {
return false;
}
const WFMath::Point<3> & ln = l.bBox().lowCorner();
const WFMath::Point<3> & lf = l.bBox().highCorner();
const WFMath::Point<3> & on = o.bBox().lowCorner();
const WFMath::Point<3> & of = o.bBox().highCorner();
// Create a set of vertices representing the box corners
CoordList lbox(8), obox(8);
lbox[0] = WFMath::Point<3>(ln.x(), ln.y(), ln.z());
lbox[1] = WFMath::Point<3>(lf.x(), ln.y(), ln.z());
lbox[2] = WFMath::Point<3>(lf.x(), lf.y(), ln.z());
lbox[3] = WFMath::Point<3>(ln.x(), lf.y(), ln.z());
lbox[4] = WFMath::Point<3>(ln.x(), ln.y(), lf.z());
lbox[5] = WFMath::Point<3>(lf.x(), ln.y(), lf.z());
lbox[6] = WFMath::Point<3>(lf.x(), lf.y(), lf.z());
lbox[7] = WFMath::Point<3>(ln.x(), lf.y(), lf.z());
obox[0] = WFMath::Point<3>(on.x(), on.y(), on.z());
obox[1] = WFMath::Point<3>(of.x(), on.y(), on.z());
obox[2] = WFMath::Point<3>(of.x(), of.y(), on.z());
obox[3] = WFMath::Point<3>(on.x(), of.y(), on.z());
obox[4] = WFMath::Point<3>(on.x(), on.y(), of.z());
obox[5] = WFMath::Point<3>(of.x(), on.y(), of.z());
obox[6] = WFMath::Point<3>(of.x(), of.y(), of.z());
obox[7] = WFMath::Point<3>(on.x(), of.y(), of.z());
// Set up a set of surface normals, each with an assoicated corner
NormalSet lnormals;
lnormals.insert(std::make_pair(0, Vector3D( 0., 0., -1.))); // Bottom face
lnormals.insert(std::make_pair(1, Vector3D( 0., -1., 0.))); // South face
lnormals.insert(std::make_pair(3, Vector3D(-1., 0., 0.))); // West face
lnormals.insert(std::make_pair(2, Vector3D( 1., 0., 0.))); // East face
lnormals.insert(std::make_pair(6, Vector3D( 0., 1., 0.))); // North face
lnormals.insert(std::make_pair(4, Vector3D( 0., 0., 1.))); // Top face
NormalSet onormals(lnormals);
static const Quaternion identity(1, 0, 0, 0);
// Orient the surface normals and box corners
if (l.orientation().isValid()) {
NormalSet::iterator Iend = lnormals.end();
for (NormalSet::iterator I = lnormals.begin(); I != Iend; ++I) {
I->second.rotate(l.orientation());
}
for (int i = 0; i < 8; ++i) {
lbox[i] = lbox[i].toParentCoords(l.pos(), l.orientation());
}
} else {
for (int i = 0; i < 8; ++i) {
lbox[i] = lbox[i].toParentCoords(l.pos(), identity);
}
}
if (o.orientation().isValid()) {
NormalSet::iterator Iend = onormals.end();
for (NormalSet::iterator I = onormals.begin(); I != Iend; ++I) {
I->second.rotate(o.orientation());
}
for (int i = 0; i < 8; ++i) {
obox[i] = obox[i].toParentCoords(o.pos(), o.orientation());
}
} else {
for (int i = 0; i < 8; ++i) {
obox[i] = obox[i].toParentCoords(o.pos(), identity);
}
}
#if 0
// This must be done whether orientation is valid or not
// Translate the box corners
for(int i = 0; i < 8; ++i) {
lbox[i] += l.pos();
obox[i] += o.pos();
}
#endif
// Predict the collision using the generic mesh function
return predictCollision(lbox, lnormals, l.velocity(),
obox, onormals, o_velocity,
time, normal);
}
////////////////////////// EMERGENCE //////////////////////////
bool getEmergenceTime(const Point3D & p, // Position of point
const Vector3D & u, // Velocity of point
// float point_time, // Time since position set
const Point3D & l, // Position on plane
const Vector3D & n, // Plane normal
const Vector3D & v, // Velocity of plane
// float plane_time, // Time since position set
float & time) // Emergence time return
{
return !getCollisionTime(p, u, l, n, v, time);
}
static float min(float a, float b, float c)
{
if (a < b) {
if (a < c) {
return a;
} else {
return c;
}
} else if (b < c) {
return b;
} else {
return c;
}
}
bool predictEmergence(const CoordList & l, // Vertices of this mesh
const Vector3D & u, // Velocity of this mesh
const WFMath::AxisBox<3> & o,// Bounding box of container
float & time) // Returned time to emergence
{
const WFMath::Point<3> & on = o.lowCorner();
const WFMath::Point<3> & of = o.highCorner();
float maxtime = -1;
CoordList::const_iterator Iend = l.end();
for (CoordList::const_iterator I = l.begin(); I != Iend; ++I) {
float xtime = (u.x() >= 0.f) ? ((of.x() - I->x()) / u.x())
: ((on.x() - I->x()) / u.x());
float ytime = (u.y() >= 0.f) ? ((of.y() - I->y()) / u.y())
: ((on.y() - I->y()) / u.y());
float ztime = (u.z() >= 0.f) ? ((of.z() - I->z()) / u.z())
: ((on.z() - I->z()) / u.z());
// Determine the time taken for the box corner to reach the nearest
// edge.
float ctime = min(xtime, ytime, ztime);
debug(std::cout << xtime << ":" << ytime << ":" << ztime << ":" << ctime
<< std::endl << std::flush;);
// maxtime is the time for the last corner to make contact with the
// edge
if (ctime > maxtime) {
maxtime = ctime;
}
}
if (maxtime > 0) {
time = maxtime;
} else {
time = 0;
}
return true;
}
bool predictEmergence(const Location & l, // This location
const Location & o, // Other location
float & time) // Returned time to collision
{
// We are predicting emergence of l from its parent o
// Orientation of o is irrelevant, as children and their relative
// position are also oriented, so o's bbox is axis aligned.
// In fact the only feature of o we are interested is its bbox, so
// we could drop the Location, and take the bbox instead.
// So all we need to do is get oriented points for l, and check
// when they will first leave the axis aligned bounding values
const WFMath::Point<3> & ln = l.bBox().lowCorner();
const WFMath::Point<3> & lf = l.bBox().highCorner();
CoordList lbox(8);
lbox[0] = WFMath::Point<3>(ln.x(), ln.y(), ln.z());
lbox[1] = WFMath::Point<3>(lf.x(), ln.y(), ln.z());
lbox[2] = WFMath::Point<3>(lf.x(), lf.y(), ln.z());
lbox[3] = WFMath::Point<3>(ln.x(), lf.y(), ln.z());
lbox[4] = WFMath::Point<3>(ln.x(), ln.y(), lf.z());
lbox[5] = WFMath::Point<3>(lf.x(), ln.y(), lf.z());
lbox[6] = WFMath::Point<3>(lf.x(), lf.y(), lf.z());
lbox[7] = WFMath::Point<3>(ln.x(), lf.y(), lf.z());
// Orient the box corners
if (l.orientation().isValid()) {
for(int i = 0; i < 8; ++i) {
lbox[i] = lbox[i].toParentCoords(l.pos(), l.orientation());
}
} else {
log(WARNING, "predictEmergence(): Entity has non-valid orientation.");
}
#if 0
// Translate the box corners
for(int i = 0; i < 8; ++i) {
lbox[i] += l.pos();
}
#endif
assert(l.velocity().isValid());
// We are now ready to carry out the next step
return predictEmergence(lbox, l.velocity(), o.bBox(), time);
}