/* * SOLID - Software Library for Interference Detection * * Copyright (C) 2001-2003 Dtecta. All rights reserved. * * This library may be distributed under the terms of the Q Public License * (QPL) as defined by Trolltech AS of Norway and appearing in the file * LICENSE.QPL included in the packaging of this file. * * This library may be distributed and/or modified under the terms of the * GNU General Public License (GPL) version 2 as published by the Free Software * Foundation and appearing in the file LICENSE.GPL included in the * packaging of this file. * * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Commercial use or any other use of this library not covered by either * the QPL or the GPL requires an additional license from Dtecta. * Please contact info@dtecta.com for enquiries about the terms of commercial * use of this library. */ #include "DT_Scene.h" #include "DT_Object.h" #include "DT_Convex.h" //#define DEBUG static void beginOverlap(void *client_data, void *object1, void *object2) { DT_Encounter e((DT_Object *)object1, (DT_Object *)object2); DT_EncounterTable *encounterTable = static_cast(client_data); #ifdef DEBUG std::cout << "Begin: " << e << std::endl; #endif encounterTable->insert(e); } static void endOverlap(void *client_data, void *object1, void *object2) { DT_Encounter e((DT_Object *)object1, (DT_Object *)object2); DT_EncounterTable *encounterTable = static_cast(client_data); #ifdef DEBUG std::cout << "End: " << e << std::endl; #endif assert(encounterTable->find(e) != encounterTable->end()); encounterTable->erase(e); } struct DT_RayCastData { DT_RayCastData(const void *ignore) : m_ignore(ignore) {} const void *m_ignore; MT_Vector3 m_normal; }; static bool objectRayCast(void *client_data, void *object, const DT_Vector3 source, const DT_Vector3 target, DT_Scalar *lambda) { DT_RayCastData *data = static_cast(client_data); if (((DT_Object *)object)->getClientObject() != data->m_ignore) { MT_Scalar param = MT_Scalar(*lambda); if (((DT_Object *)object)->ray_cast(MT_Point3(source), MT_Point3(target), param, data->m_normal)) { *lambda = param; return true; } } return false; } DT_Scene::DT_Scene() : m_broadphase(BP_CreateScene(&m_encounterTable, &beginOverlap, &endOverlap)) {} DT_Scene::~DT_Scene() { BP_DestroyScene(m_broadphase); } void DT_Scene::addObject(DT_Object &object) { const MT_BBox& bbox = object.getBBox(); DT_Vector3 min, max; bbox.getMin().getValue(min); bbox.getMax().getValue(max); BP_ProxyHandle proxy = BP_CreateProxy(m_broadphase, &object, min, max); #ifdef DEBUG DT_EncounterTable::iterator it; std::cout << "Add " << &object << ':'; for (it = m_encounterTable.begin(); it != m_encounterTable.end(); ++it) { std::cout << ' ' << (*it); } std::cout << std::endl; #endif object.addProxy(proxy); m_objectList.push_back(std::make_pair(&object, proxy)); } void DT_Scene::removeObject(DT_Object& object) { T_ObjectList::iterator it = m_objectList.begin(); while (it != m_objectList.end() && &object != (*it).first) { ++it; } if (it != m_objectList.end()) { object.removeProxy((*it).second); BP_DestroyProxy(m_broadphase, (*it).second); m_objectList.erase(it); #ifdef DEBUG std::cout << "Remove " << &object << ':'; DT_EncounterTable::iterator it; for (it = m_encounterTable.begin(); it != m_encounterTable.end(); ++it) { std::cout << ' ' << (*it); assert((*it).first() != &object && (*it).second() != &object); } std::cout << std::endl; #endif } } int DT_Scene::handleCollisions(const DT_RespTable *respTable) { int count = 0; assert(respTable); DT_EncounterTable::iterator it; for (it = m_encounterTable.begin(); it != m_encounterTable.end(); ++it) { if ((*it).exactTest(respTable, count)) { break; } } return count; } void *DT_Scene::rayCast(const void *ignore_client, const DT_Vector3 source, const DT_Vector3 target, DT_Scalar& lambda, DT_Vector3 normal) const { DT_RayCastData data(ignore_client); DT_Object *object = (DT_Object *)BP_RayCast(m_broadphase, &objectRayCast, &data, source, target, &lambda); if (object) { data.m_normal.getValue(normal); return object->getClientObject(); } return 0; }