1 /* This file is part of the hkl3d library.
3 * The hkl library is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * The hkl library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with the hkl library. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright (C) 2010 Synchrotron SOLEIL
17 * L'Orme des Merisiers Saint-Aubin
18 * BP 48 91192 GIF-sur-YVETTE CEDEX
20 * Authors: Picca Frédéric-Emmanuel <picca@synchrotron-soleil.fr>
21 * Oussama Sboui <oussama.sboui@synchrotron-soleil.fr>
27 #include "btBulletCollisionCommon.h"
28 #include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h"
30 #ifdef USE_PARALLEL_DISPATCHER
31 # include "BulletMultiThreaded/SpuGatheringCollisionDispatcher.h"
32 # include "BulletMultiThreaded/PlatformDefinitions.h"
33 # include "BulletMultiThreaded/PosixThreadSupport.h"
34 # include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h"
37 Hkl3D::Hkl3D(const char *filename
, HklGeometry
*geometry
)
40 _len
= HKL_LIST_LEN(geometry
->axes
);
42 // read the model from the file
43 _context
= g3d_context_new();
44 _model
= g3d_model_load_full(_context
, filename
,G3D_MODEL_SCALE
);
46 // load model from libg3d into bullet Hullshape.
47 if(this->isModelFileCompatibleWithGeometry() == false)
48 throw "Model not compatible with the HklGeometry\n";
49 this->loadG3dFaceInBtConvexHullShape();
50 // initialize the bullet part
51 _btCollisionConfiguration
= new btDefaultCollisionConfiguration();
53 #ifdef USE_PARALLEL_DISPATCHER
54 int maxNumOutstandingTasks
= 2;
55 PosixThreadSupport::ThreadConstructionInfo
constructionInfo("collision",
57 createCollisionLocalStoreMemory
,
58 maxNumOutstandingTasks
);
59 _btThreadSupportInterface
= new PosixThreadSupport(constructionInfo
);
60 _btDispatcher
= new SpuGatheringCollisionDispatcher(_btThreadSupportInterface
,
61 maxNumOutstandingTasks
,
62 _btCollisionConfiguration
);
64 _btDispatcher
= new btCollisionDispatcher(_btCollisionConfiguration
);
66 btGImpactCollisionAlgorithm::registerAlgorithm(_btDispatcher
);
68 btVector3
worldAabbMin(-1000,-1000,-1000);
69 btVector3
worldAabbMax( 1000, 1000, 1000);
71 _btBroadphase
= new btAxisSweep3(worldAabbMin
, worldAabbMax
);
73 _btCollisionWorld
= new btCollisionWorld(_btDispatcher
,
75 _btCollisionConfiguration
);
77 // add all objects to the world
78 for(int i
=0; i
<_btCollisionObjects
.size(); i
++)
79 _btCollisionWorld
->addCollisionObject(_btCollisionObjects
[i
]);
81 // if resp == true there is a problem in the diffractometer model.
82 bool resp
= this->is_colliding();
90 len
= _btCollisionObjects
.size();
92 // detach the objects from the collision world
93 len
= _btCollisionObjects
.size();
95 _btCollisionWorld
->removeCollisionObject(_btCollisionObjects
[i
]);
97 // delete all objects and shapes
100 delete _btCollisionShapes
[i
];
101 delete _btCollisionObjects
[i
];
104 if (_btCollisionWorld
) delete _btCollisionWorld
;
105 if (_btBroadphase
) delete _btBroadphase
;
106 if (_btDispatcher
) delete _btDispatcher
;
107 #ifdef USE_PARALLEL_DISPATCHER
108 if (_btThreadSupportInterface
){
109 //delete _btThreadSupportInterface;
110 //_btThreadSupportInterface = 0;
113 if (_btCollisionConfiguration
) delete _btCollisionConfiguration
;
115 g3d_model_free(_model
);
116 g3d_context_free(_context
);
119 bool Hkl3D::is_colliding(void)
123 struct timeval debut
, fin
, dt
;
126 // set the right transformation of each objects and get numbers
127 gettimeofday(&debut
, NULL
);
128 for(i
=0;i
<HKL_LIST_LEN(this->_geometry
->holders
);i
++){
130 btQuaternion
btQ(0, 0, 0, 1);
132 size_t len
= HKL_LIST_LEN(this->_geometry
->holders
[i
].idx
);
133 for(j
=0; j
<len
; j
++){
135 size_t idx
= this->_geometry
->holders
[i
].idx
[j
];
136 HklAxis
*axis
= &this->_geometry
->axes
[idx
];
139 // convertion beetween hkl -> bullet coordinates
140 btQ
*= btQuaternion(-axis
->q
.data
[1],
145 // move each object connected to that hkl Axis.
146 for(k
=0; k
<_movingBtCollisionObjects
[idx
].size(); ++k
){
147 _movingBtCollisionObjects
[idx
][k
]->getWorldTransform().setRotation(btQ
);
148 _movingBtCollisionObjects
[idx
][k
]->getWorldTransform().getOpenGLMatrix( G3DM
);
149 memcpy(_movingG3DObjects
[idx
][k
]->transformation
->matrix
, &G3DM
[0], sizeof(G3DM
));
153 gettimeofday(&fin
, NULL
);
154 timersub(&fin
, &debut
, &dt
);
155 fprintf(stdout
, "transformation (%f ms)", dt
.tv_sec
*1000.+dt
.tv_usec
/1000.);
157 // perform the collision detection and get numbers
158 gettimeofday(&debut
, NULL
);
159 if(_btCollisionWorld
)
160 _btCollisionWorld
->performDiscreteCollisionDetection();
161 gettimeofday(&fin
, NULL
);
162 timersub(&fin
, &debut
, &dt
);
163 fprintf(stdout
, " collision (%f ms)", dt
.tv_sec
*1000.+dt
.tv_usec
/1000.);
165 numManifolds
= _btCollisionWorld
->getDispatcher()->getNumManifolds();
166 fprintf(stdout
, " manifolds (%d)\n", numManifolds
);
168 return numManifolds
== 0;
172 * Check that for each moving part in the hkl library there is a
173 * corresponding model in the 3d model file.
174 *!!!!!!!!!!!! Missing error handling in isModelCompatiblewithGeometry method
176 bool Hkl3D::isModelFileCompatibleWithGeometry(void)
181 for(i
=0; i
<_len
; ++i
){
186 name
= ((HklParameter
*)(&_geometry
->axes
[i
]))->name
;
187 objects
= _model
->objects
;
189 while(objects
|| !found
){
192 object
= (G3DObject
*)objects
->data
;
193 if(!strcmp(object
->name
, name
)){
195 fprintf(stdout
, "%s found in the 3d model file\n", object
->name
);
197 objects
= g_slist_next(objects
);
201 resp
+= " not found in model file\n";
209 * load the model in the hkl3d structure
211 void Hkl3D::loadG3dFaceInBtConvexHullShape(void)
213 GSList
*objects
; // lets iterate from the first object.
215 // first initialize the _movingBtCollisionObjects with the right len.
216 _movingBtCollisionObjects
.resize(_len
);
217 _movingG3DObjects
.resize(_len
);
218 // for each object in the model file do the g3d -> bullet conversion
219 objects
= _model
->objects
;
222 G3DMaterial
*material
;
224 object
= (G3DObject
*)objects
->data
;
225 if(object
->vertex_count
){
227 btCollisionObject
*btObject
;
228 btTriangleMesh
*trimesh
;
230 btGImpactMeshShape
*shape
;
233 trimesh
= new btTriangleMesh();
234 trimesh
->preallocateVertices(object
->vertex_count
);
235 faces
= object
->faces
;
236 vertex
= object
->vertex_data
;
238 // extract the color from the first face
239 // usefull for the demo
240 material
= ((G3DFace
*)faces
->data
)->material
;
241 _colors
.push_back(btVector3(material
->r
, material
->g
, material
->b
));
242 fprintf(stdout
, "colors: %f %f %f\n",
243 material
->r
, material
->g
, material
->b
);
248 face
= (G3DFace
*)faces
->data
;
250 btVector3
vertex0(vertex
[3*(face
->vertex_indices
[0])],
251 vertex
[3*(face
->vertex_indices
[0])+1],
252 vertex
[3*(face
->vertex_indices
[0])+2]);
253 btVector3
vertex1(vertex
[3*(face
->vertex_indices
[1])],
254 vertex
[3*(face
->vertex_indices
[1])+1],
255 vertex
[3*(face
->vertex_indices
[1])+2]);
256 btVector3
vertex2(vertex
[3*(face
->vertex_indices
[2])],
257 vertex
[3*(face
->vertex_indices
[2])+1],
258 vertex
[3*(face
->vertex_indices
[2])+2]);
260 trimesh
->addTriangle(vertex0
, vertex1
, vertex2
, false);
261 faces
= g_slist_next(faces
);
265 shape
= new btGImpactMeshShape(trimesh
);
266 shape
->setLocalScaling(btVector3(1.f
,1.f
,1.f
));
267 shape
->setMargin(0.0f
);
268 shape
->updateBound();
270 // create the Object and add the shape
271 btObject
= new btCollisionObject();
272 btObject
->setCollisionShape(shape
);
273 btObject
->activate(true);
275 // now populate also the moving part
276 idx
= hkl_geometry_get_axis_idx_by_name(_geometry
, object
->name
);
278 _movingBtCollisionObjects
[idx
].push_back(btObject
);
279 object
->transformation
= g_new0(G3DTransformation
, 1);
280 _movingG3DObjects
[idx
].push_back(object
);
283 // remembers objects to avoid memory leak
284 _btCollisionShapes
.push_back(shape
);
285 _btMeshes
.push_back(trimesh
);
286 _btCollisionObjects
.push_back(btObject
);
288 objects
= g_slist_next(objects
);