Reverted incorrect merge (missing files)
[blender.git] / extern / solid / src / DT_Scene.cpp
1 /*
2  * SOLID - Software Library for Interference Detection
3  * 
4  * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
5  *
6  * This library may be distributed under the terms of the Q Public License
7  * (QPL) as defined by Trolltech AS of Norway and appearing in the file
8  * LICENSE.QPL included in the packaging of this file.
9  *
10  * This library may be distributed and/or modified under the terms of the
11  * GNU General Public License (GPL) version 2 as published by the Free Software
12  * Foundation and appearing in the file LICENSE.GPL included in the
13  * packaging of this file.
14  *
15  * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17  *
18  * Commercial use or any other use of this library not covered by either 
19  * the QPL or the GPL requires an additional license from Dtecta. 
20  * Please contact info@dtecta.com for enquiries about the terms of commercial
21  * use of this library.
22  */
23
24 #include "DT_Scene.h"
25 #include "DT_Object.h"
26 #include "DT_Convex.h"
27
28 //#define DEBUG
29
30 static void beginOverlap(void *client_data, void *object1, void *object2) 
31 {
32         DT_Encounter e((DT_Object *)object1, (DT_Object *)object2);
33         DT_EncounterTable *encounterTable = static_cast<DT_EncounterTable *>(client_data);
34
35 #ifdef DEBUG    
36         std::cout << "Begin: " << e << std::endl; 
37 #endif
38
39         encounterTable->insert(e);
40 }
41
42
43 static void endOverlap(void *client_data, void *object1, void *object2) 
44 {
45         DT_Encounter e((DT_Object *)object1, (DT_Object *)object2);
46         DT_EncounterTable *encounterTable = static_cast<DT_EncounterTable *>(client_data);
47
48 #ifdef DEBUG
49         std::cout << "End:   " << e << std::endl; 
50 #endif
51         
52         assert(encounterTable->find(e) != encounterTable->end()); 
53         encounterTable->erase(e);
54 }
55
56 struct DT_RayCastData {
57         DT_RayCastData(const void *ignore) 
58           : m_ignore(ignore) 
59         {}
60
61         const void  *m_ignore;
62         MT_Vector3  m_normal;
63 };
64
65 static bool objectRayCast(void *client_data, 
66                                                   void *object,  
67                                                   const DT_Vector3 source,
68                                                   const DT_Vector3 target,
69                                                   DT_Scalar *lambda) 
70 {
71         DT_RayCastData *data = static_cast<DT_RayCastData *>(client_data); 
72         if (((DT_Object *)object)->getClientObject() != data->m_ignore)
73         {
74                 MT_Scalar param = MT_Scalar(*lambda);
75                 
76                 if (((DT_Object *)object)->ray_cast(MT_Point3(source), MT_Point3(target),
77                                                                                         param, data->m_normal))
78                 {
79                         *lambda = param;
80                         return true;
81                 }
82         }
83         return false;
84 }
85
86 DT_Scene::DT_Scene() 
87   : m_broadphase(BP_CreateScene(&m_encounterTable, &beginOverlap, &endOverlap))
88 {}
89
90 DT_Scene::~DT_Scene()
91 {
92         BP_DestroyScene(m_broadphase);
93 }
94
95 void DT_Scene::addObject(DT_Object &object)
96 {
97         const MT_BBox& bbox = object.getBBox();
98         DT_Vector3 min, max;
99         bbox.getMin().getValue(min);
100         bbox.getMax().getValue(max);
101     BP_ProxyHandle proxy = BP_CreateProxy(m_broadphase, &object, min, max);
102         
103 #ifdef DEBUG
104         DT_EncounterTable::iterator it; 
105         std::cout << "Add " << &object << ':';
106         for (it = m_encounterTable.begin(); it != m_encounterTable.end(); ++it) {
107                 std::cout << ' ' << (*it);
108         }
109         std::cout << std::endl;
110 #endif
111         object.addProxy(proxy);
112     m_objectList.push_back(std::make_pair(&object, proxy));
113 }
114
115
116
117 void DT_Scene::removeObject(DT_Object& object)
118 {
119     T_ObjectList::iterator it = m_objectList.begin();
120
121     while (it != m_objectList.end() && &object != (*it).first)
122         {
123         ++it;
124     }
125
126     if (it != m_objectList.end())
127         {
128                 object.removeProxy((*it).second);
129         BP_DestroyProxy(m_broadphase, (*it).second);
130                 m_objectList.erase(it);
131
132 #ifdef DEBUG
133                 std::cout << "Remove " << &object << ':';
134                 DT_EncounterTable::iterator it; 
135                 for (it = m_encounterTable.begin(); it != m_encounterTable.end(); ++it)
136                 {
137                         std::cout << ' ' << (*it);
138                         assert((*it).first() != &object &&
139                                    (*it).second() != &object);
140                 }
141                 std::cout << std::endl;
142 #endif
143     }
144 }
145
146
147
148 int DT_Scene::handleCollisions(const DT_RespTable *respTable)
149 {
150     int count = 0;
151
152     assert(respTable);
153
154         DT_EncounterTable::iterator it; 
155         for (it = m_encounterTable.begin(); it != m_encounterTable.end(); ++it)
156         {
157                 if ((*it).exactTest(respTable, count))
158                 {
159                         break;
160         }
161         
162     }
163     return count;
164 }
165
166 void *DT_Scene::rayCast(const void *ignore_client,
167                                                 const DT_Vector3 source, const DT_Vector3 target, 
168                                                 DT_Scalar& lambda, DT_Vector3 normal) const 
169 {
170         DT_RayCastData data(ignore_client);
171         DT_Object *object = (DT_Object *)BP_RayCast(m_broadphase, 
172                                                                                                 &objectRayCast, 
173                                                                                                 &data, 
174                                                                                                 source, target,
175                                                                                                 &lambda);
176         if (object)
177         {
178                 data.m_normal.getValue(normal);
179                 return object->getClientObject();
180         }
181         
182         return 0;
183 }