Reverted incorrect merge (missing files)
[blender.git] / extern / solid / src / DT_C-api.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
25 #include "SOLID.h"
26
27 #include "DT_Box.h"
28 #include "DT_Cone.h"
29 #include "DT_Cylinder.h"
30 #include "DT_Sphere.h"
31 #include "DT_Complex.h"
32 #include "DT_Polytope.h"
33 #include "DT_Polyhedron.h"
34 #include "DT_Point.h"
35 #include "DT_LineSegment.h"
36 #include "DT_Triangle.h"
37 #include "DT_Minkowski.h"
38 #include "DT_Hull.h"
39
40 #include "DT_Response.h"
41 #include "DT_RespTable.h"
42
43 #include "DT_Scene.h"
44 #include "DT_Object.h"
45
46 #include "DT_VertexBase.h"
47
48 #include "DT_Accuracy.h"
49
50 typedef MT::Tuple3<DT_Scalar> T_Vertex;
51 typedef std::vector<T_Vertex> T_VertexBuf;
52 typedef std::vector<DT_Index> T_IndexBuf;
53 typedef std::vector<const DT_Convex *> T_PolyList;
54
55 static T_VertexBuf vertexBuf;
56 static T_IndexBuf indexBuf;
57 static T_PolyList polyList; 
58
59 static DT_Complex       *currentComplex    = 0;
60 static DT_Polyhedron    *currentPolyhedron = 0;
61 static DT_VertexBase    *currentBase = 0;
62
63
64
65
66
67                 
68 DT_VertexBaseHandle DT_NewVertexBase(const void *pointer, DT_Size stride) 
69 {
70     return (DT_VertexBaseHandle)new DT_VertexBase(pointer, stride);
71 }
72
73 void DT_DeleteVertexBase(DT_VertexBaseHandle vertexBase) 
74
75     delete (DT_VertexBase *)vertexBase; 
76 }
77
78 void DT_ChangeVertexBase(DT_VertexBaseHandle vertexBase, const void *pointer) 
79
80         DT_VertexBase *base = (DT_VertexBase *)vertexBase;
81         base->setPointer(pointer);
82         const DT_ComplexList& complexList = base->getComplexList();
83         DT_ComplexList::const_iterator it;
84         for (it = complexList.begin(); it != complexList.end(); ++it)
85         {
86                 (*it)->refit();
87         }
88 }
89
90
91 DT_ShapeHandle DT_NewBox(DT_Scalar x, DT_Scalar y, DT_Scalar z) 
92 {
93     return (DT_ShapeHandle)new DT_Box(MT_Scalar(x) * MT_Scalar(0.5), 
94                                                                           MT_Scalar(y) * MT_Scalar(0.5), 
95                                                                           MT_Scalar(z) * MT_Scalar(0.5));
96 }
97
98 DT_ShapeHandle DT_NewCone(DT_Scalar radius, DT_Scalar height)
99 {
100     return (DT_ShapeHandle)new DT_Cone(MT_Scalar(radius), MT_Scalar(height));
101 }
102
103 DT_ShapeHandle DT_NewCylinder(DT_Scalar radius, DT_Scalar height) 
104 {
105     return (DT_ShapeHandle)new DT_Cylinder(MT_Scalar(radius), MT_Scalar(height));
106 }
107
108 DT_ShapeHandle DT_NewSphere(DT_Scalar radius) 
109 {
110     return (DT_ShapeHandle)new DT_Sphere(MT_Scalar(radius));
111 }
112
113 DT_ShapeHandle DT_NewPoint(const DT_Vector3 point) 
114 {
115         return (DT_ShapeHandle)new DT_Point(MT_Point3(point));
116 }
117
118 DT_ShapeHandle DT_NewLineSegment(const DT_Vector3 source, const DT_Vector3 target) 
119 {
120         return (DT_ShapeHandle)new DT_LineSegment(MT_Point3(source), MT_Point3(target));
121 }
122
123 DT_ShapeHandle DT_NewMinkowski(DT_ShapeHandle shape1, DT_ShapeHandle shape2) 
124 {
125         if (((DT_Shape *)shape1)->getType() != CONVEX ||
126                 ((DT_Shape *)shape2)->getType() != CONVEX) 
127         {
128                 return 0;
129         }
130
131         return (DT_ShapeHandle)new DT_Minkowski(*(DT_Convex *)shape1, *(DT_Convex *)shape2);
132 }
133         
134 DT_ShapeHandle DT_NewHull(DT_ShapeHandle shape1, DT_ShapeHandle shape2)
135 {
136         if (((DT_Shape *)shape1)->getType() != CONVEX ||
137                 ((DT_Shape *)shape2)->getType() != CONVEX) 
138         {
139                 return 0;
140         }
141
142         return (DT_ShapeHandle)new DT_Hull(*(DT_Convex *)shape1, *(DT_Convex *)shape2);
143 }
144
145 DT_ShapeHandle DT_NewComplexShape(const DT_VertexBaseHandle vertexBase) 
146 {
147     if (!currentComplex) 
148         {
149                 currentBase = vertexBase ? (DT_VertexBase *)vertexBase : new DT_VertexBase;
150                 currentComplex = new DT_Complex(currentBase);
151         }
152     return (DT_ShapeHandle)currentComplex;
153 }
154
155 void DT_EndComplexShape() 
156 {
157     if (currentComplex) 
158         {
159         if (currentBase->getPointer() == 0) 
160                 {
161             T_Vertex *vertexArray = new T_Vertex[vertexBuf.size()];   
162                         assert(vertexArray);    
163             std::copy(vertexBuf.begin(), vertexBuf.end(), &vertexArray[0]);
164             currentBase->setPointer(vertexArray, true);         
165         }
166                 
167                 vertexBuf.clear();
168         
169         currentComplex->finish(polyList.size(), &polyList[0]);
170         polyList.clear();
171         currentComplex = 0;
172         currentBase = 0; 
173     }
174 }
175
176 DT_ShapeHandle DT_NewPolytope(const DT_VertexBaseHandle vertexBase) 
177 {
178     if (!currentPolyhedron) 
179         {
180                 currentBase = vertexBase ? (DT_VertexBase *)vertexBase : new DT_VertexBase;
181         currentPolyhedron = new DT_Polyhedron;
182                 
183     }
184     return (DT_ShapeHandle)currentPolyhedron;
185 }
186
187 void DT_EndPolytope() 
188 {
189     if (currentPolyhedron) 
190         {
191         if (currentBase->getPointer() == 0) 
192                 {
193                         currentBase->setPointer(&vertexBuf[0]);         
194                         new (currentPolyhedron) DT_Polyhedron(currentBase, indexBuf.size(), &indexBuf[0]);
195                         
196                         delete currentBase;
197                 }
198                 else
199                 {
200                         new (currentPolyhedron) DT_Polyhedron(currentBase, indexBuf.size(), &indexBuf[0]);
201                 }
202                 vertexBuf.clear();
203         indexBuf.clear();
204         currentPolyhedron = 0;
205         currentBase = 0;
206     }
207 }
208
209 void DT_Begin() 
210 {}
211
212 void DT_End() 
213
214         if (currentComplex) 
215         {
216                 DT_VertexIndices(indexBuf.size(), &indexBuf[0]);
217                 indexBuf.clear();
218         }
219 }
220
221 void DT_Vertex(const DT_Vector3 vertex)
222 {
223     MT::Vector3<DT_Scalar> p(vertex);
224     int i = GEN_max((int)vertexBuf.size() - 20, 0);
225         int n = static_cast<int>(vertexBuf.size());
226         
227     while (i != n  && !(vertexBuf[i] == p)) 
228         {
229                 ++i;
230         }
231
232     if (i == n) 
233         {
234                 vertexBuf.push_back(p);
235         }
236     indexBuf.push_back(i);
237 }
238
239
240 void DT_VertexIndex(DT_Index index) { indexBuf.push_back(index); }
241
242 void DT_VertexIndices(DT_Count count, const DT_Index *indices) 
243 {
244     if (currentComplex) 
245         {
246                 DT_Convex *poly = count == 3 ? 
247                                       static_cast<DT_Convex *>(new DT_Triangle(currentBase, indices[0], indices[1], indices[2])) :
248                                                   static_cast<DT_Convex *>(new DT_Polytope(currentBase, count, indices));  
249                 polyList.push_back(poly);
250       
251     }
252
253     if (currentPolyhedron) 
254         {
255                 int i;
256                 for (i = 0; i < count; ++i) 
257                 {
258             indexBuf.push_back(indices[i]);
259         }
260     }   
261 }
262
263 void DT_VertexRange(DT_Index first, DT_Count count) 
264 {
265     DT_Index *indices = new DT_Index[count];
266     
267         DT_Index i;
268     for (i = 0; i != count; ++i) 
269         {
270         indices[i] = first + i;
271     }
272     DT_VertexIndices(count, indices);
273
274     delete [] indices;  
275 }
276
277 void DT_DeleteShape(DT_ShapeHandle shape) 
278
279     delete (DT_Shape *)shape; 
280 }
281
282
283
284
285 // Scene
286
287
288 DT_SceneHandle DT_CreateScene() 
289 {
290     return (DT_SceneHandle)new DT_Scene; 
291 }
292
293 void DT_DestroyScene(DT_SceneHandle scene) 
294 {
295     delete (DT_Scene *)scene;
296 }
297
298 void DT_AddObject(DT_SceneHandle scene, DT_ObjectHandle object) 
299 {
300     assert(scene);
301     assert(object);
302     ((DT_Scene *)scene)->addObject(*(DT_Object *)object);
303 }
304
305 void DT_RemoveObject(DT_SceneHandle scene, DT_ObjectHandle object) 
306 {
307     assert(scene);
308     assert(object);
309     ((DT_Scene *)scene)->removeObject(*(DT_Object *)object);
310 }
311
312
313 // Object instantiation
314
315
316 DT_ObjectHandle DT_CreateObject(void *client_object,
317                                 DT_ShapeHandle shape)
318 {
319         return (DT_ObjectHandle)new DT_Object(client_object, *(DT_Shape *)shape);
320 }
321
322 void DT_DestroyObject(DT_ObjectHandle object) 
323 {
324     delete (DT_Object *)object;
325 }
326
327 void DT_SetMargin(DT_ObjectHandle object, DT_Scalar margin) 
328 {
329     ((DT_Object *)object)->setMargin(MT_Scalar(margin));
330 }
331
332
333 void DT_SetScaling(DT_ObjectHandle object, const DT_Vector3 scaling) 
334 {
335     ((DT_Object *)object)->setScaling(MT_Vector3(scaling));
336 }
337
338 void DT_SetPosition(DT_ObjectHandle object, const DT_Vector3 position) 
339 {
340     ((DT_Object *)object)->setPosition(MT_Point3(position));
341 }
342
343 void DT_SetOrientation(DT_ObjectHandle object, const DT_Quaternion orientation) 
344 {
345     ((DT_Object *)object)->setOrientation(MT_Quaternion(orientation));   
346 }
347
348
349 void DT_SetMatrixf(DT_ObjectHandle object, const float *m) 
350 {
351     ((DT_Object *)object)->setMatrix(m);
352 }
353
354 void DT_GetMatrixf(DT_ObjectHandle object, float *m) 
355 {
356     ((DT_Object *)object)->getMatrix(m);
357 }
358
359 void DT_SetMatrixd(DT_ObjectHandle object, const double *m) 
360 {
361     ((DT_Object *)object)->setMatrix(m);
362 }
363 void DT_GetMatrixd(DT_ObjectHandle object, double *m) 
364 {
365     ((DT_Object *)object)->getMatrix(m);
366 }
367
368 void DT_GetBBox(DT_ObjectHandle object, DT_Vector3 min, DT_Vector3 max) 
369 {
370         const MT_BBox& bbox = ((DT_Object *)object)->getBBox();
371         bbox.getMin().getValue(min);
372         bbox.getMax().getValue(max);
373 }
374
375 DT_Bool DT_GetIntersect(DT_ObjectHandle object1, DT_ObjectHandle object2, DT_Vector3 vec)
376 {
377         MT_Vector3 v;
378         DT_Bool result = intersect(*(DT_Object*)object1, *(DT_Object*)object2, v);
379         v.getValue(vec);
380         return result;
381 }
382
383 DT_Scalar DT_GetClosestPair(DT_ObjectHandle object1, DT_ObjectHandle object2,
384                                                         DT_Vector3 point1, DT_Vector3 point2) 
385 {
386     MT_Point3 p1, p2;
387     
388     MT_Scalar result = closest_points(*(DT_Object *)object1, 
389                                                                           *(DT_Object *)object2,
390                                                                           p1, p2);
391         p1.getValue(point1);
392         p2.getValue(point2);
393
394     return MT_sqrt(result);
395 }
396
397 DT_Bool DT_GetCommonPoint(DT_ObjectHandle object1, DT_ObjectHandle object2,
398                                                   DT_Vector3 point) 
399 {
400     MT_Point3   p1, p2;
401         MT_Vector3  v(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0)); 
402     
403     bool result = common_point(*(DT_Object *)object1, *(DT_Object *)object2, v, p1, p2);
404
405         if (result) 
406         {
407                 p1.getValue(point);
408         }
409
410     return result;
411 }
412
413 DT_Bool DT_GetPenDepth(DT_ObjectHandle object1, DT_ObjectHandle object2,
414                                     DT_Vector3 point1, DT_Vector3 point2) 
415 {
416     MT_Point3   p1, p2;
417         MT_Vector3  v(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0)); 
418     
419     bool result = penetration_depth(*(DT_Object *)object1, *(DT_Object *)object2, v, p1, p2);
420
421         if (result) 
422         {
423                 p1.getValue(point1);
424                 p2.getValue(point2);
425         }
426
427     return result;
428 }
429
430 // Response
431
432 DT_RespTableHandle DT_CreateRespTable() 
433 {
434     return (DT_RespTableHandle)new DT_RespTable;
435 }    
436
437 void DT_DestroyRespTable(DT_RespTableHandle respTable) 
438 {
439     delete (DT_RespTable *)respTable;
440 }
441
442 DT_ResponseClass DT_GenResponseClass(DT_RespTableHandle respTable) 
443 {
444         return ((DT_RespTable *)respTable)->genResponseClass();
445 }
446
447 void DT_SetResponseClass(DT_RespTableHandle respTable, DT_ObjectHandle object,
448                                                  DT_ResponseClass responseClass)
449 {
450         ((DT_RespTable *)respTable)->setResponseClass(object, responseClass);
451 }
452
453 void DT_ClearResponseClass(DT_RespTableHandle respTable, 
454                                                    DT_ObjectHandle object)
455 {
456         ((DT_RespTable *)respTable)->clearResponseClass(object);
457 }
458
459 void DT_CallResponse(DT_RespTableHandle respTable,
460                                          DT_ObjectHandle object1,
461                                          DT_ObjectHandle object2,
462                                          const DT_CollData *coll_data)
463 {
464         const DT_ResponseList& responseList =
465                 ((DT_RespTable *)respTable)->find(object1, object2);
466         
467         if (responseList.getType() != DT_NO_RESPONSE) 
468         {
469                 responseList(((DT_Object *)object1)->getClientObject(), 
470                                          ((DT_Object *)object2)->getClientObject(),
471                                          coll_data);
472         }
473 }
474
475
476 void DT_AddDefaultResponse(DT_RespTableHandle respTable,
477                            DT_ResponseCallback response, 
478                                                    DT_ResponseType type, void *client_data)
479 {
480     ((DT_RespTable *)respTable)->addDefault(DT_Response(response, type, client_data));
481 }
482
483 void DT_RemoveDefaultResponse(DT_RespTableHandle respTable,
484                                                           DT_ResponseCallback response)
485 {
486       ((DT_RespTable *)respTable)->removeDefault(DT_Response(response));
487 }
488
489 void DT_AddClassResponse(DT_RespTableHandle respTable,
490                                                  DT_ResponseClass responseClass, 
491                                                  DT_ResponseCallback response, 
492                                                  DT_ResponseType type, void *client_data)
493 {
494     ((DT_RespTable *)respTable)->addSingle(responseClass, 
495                                                                                    DT_Response(response, type, client_data));
496 }
497
498 void DT_RemoveClassResponse(DT_RespTableHandle respTable,
499                                                         DT_ResponseClass responseClass, 
500                                                         DT_ResponseCallback response) 
501 {
502     ((DT_RespTable *)respTable)->removeSingle(responseClass, 
503                                                                                           DT_Response(response));
504 }
505
506 void DT_AddPairResponse(DT_RespTableHandle respTable,
507                         DT_ResponseClass responseClass1, 
508                                                 DT_ResponseClass responseClass2, 
509                         DT_ResponseCallback response,
510                                                 DT_ResponseType type, void *client_data)
511 {
512     ((DT_RespTable *)respTable)->addPair(responseClass1, responseClass2, 
513                                                                                  DT_Response(response, type, client_data));
514 }
515
516 void DT_RemovePairResponse(DT_RespTableHandle respTable,
517                                                    DT_ResponseClass responseClass1, 
518                                                    DT_ResponseClass responseClass2, 
519                                                    DT_ResponseCallback response)
520 {
521     ((DT_RespTable *)respTable)->removePair(responseClass1, responseClass2, 
522                                                                                         DT_Response(response));
523 }
524
525
526 // Runtime
527
528 void DT_SetAccuracy(DT_Scalar max_error) 
529
530         if (max_error > MT_Scalar(0.0)) 
531         {
532                 DT_Accuracy::setAccuracy(MT_Scalar(max_error)); 
533         }
534 }
535
536 void DT_SetTolerance(DT_Scalar tol_error) 
537
538         if (tol_error > MT_Scalar(0.0)) 
539         {
540                 DT_Accuracy::setTolerance(MT_Scalar(tol_error)); 
541         }
542 }
543
544 DT_Count DT_Test(DT_SceneHandle scene, DT_RespTableHandle respTable) 
545
546     return ((DT_Scene *)scene)->handleCollisions((DT_RespTable *)respTable);
547 }
548
549 void *DT_RayCast(DT_SceneHandle scene, void *ignore_client,
550                                  const DT_Vector3 source, const DT_Vector3 target,
551                                  DT_Scalar max_param, DT_Scalar *param, DT_Vector3 normal) 
552 {
553         DT_Scalar  lambda = max_param;
554
555         void *client_object = ((DT_Scene *)scene)->rayCast(ignore_client, source, target, 
556                                                                                                            lambda, normal);
557    if (client_object)
558    {
559       *param = lambda;
560    }
561         return client_object;
562 }
563
564 DT_Bool DT_ObjectRayCast(DT_ObjectHandle object,
565                                              const DT_Vector3 source, const DT_Vector3 target,
566                                              DT_Scalar max_param, DT_Scalar *param, DT_Vector3 hit_normal) 
567 {
568         MT_Scalar lambda = MT_Scalar(max_param);
569         MT_Vector3 normal;  
570
571         bool result = ((DT_Object *)object)->ray_cast(MT_Point3(source), MT_Point3(target), 
572                                                                                                   lambda, normal);
573
574         if (result) 
575         {
576                 *param = lambda;
577                 normal.getValue(hit_normal);
578         }
579         return result;
580 }
581