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>
32 #include <g3d/matrix.h>
33 #include <sys/types.h>
38 #include "hkl-geometry-private.h"
40 #include "btBulletCollisionCommon.h"
41 #include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h"
42 #include "BulletCollision/Gimpact/btGImpactShape.h"
44 #ifdef USE_PARALLEL_DISPATCHER
45 # include "BulletMultiThreaded/SpuGatheringCollisionDispatcher.h"
46 # include "BulletMultiThreaded/PlatformDefinitions.h"
47 # include "BulletMultiThreaded/PosixThreadSupport.h"
48 # include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h"
54 static float identity
[] = {1, 0, 0, 0,
59 static void *_hkl3d_malloc(int size
, const char *error
)
63 tmp
= calloc(1, size
);
65 fprintf(stderr
, "%s", error
);
72 #define HKL3D_MALLOC(type) (type *)_hkl3d_malloc(sizeof(type), "Can not allocate memory for a " #type)
78 static btTriangleMesh
*trimesh_from_g3dobject(G3DObject
*object
)
80 btTriangleMesh
*trimesh
;
84 trimesh
= new btTriangleMesh();
85 trimesh
->preallocateVertices(object
->vertex_count
);
86 faces
= object
->faces
;
87 vertex
= object
->vertex_data
;
91 face
= (G3DFace
*)faces
->data
;
92 btVector3
vertex0(vertex
[3*(face
->vertex_indices
[0])],
93 vertex
[3*(face
->vertex_indices
[0])+1],
94 vertex
[3*(face
->vertex_indices
[0])+2]);
95 btVector3
vertex1(vertex
[3*(face
->vertex_indices
[1])],
96 vertex
[3*(face
->vertex_indices
[1])+1],
97 vertex
[3*(face
->vertex_indices
[1])+2]);
98 btVector3
vertex2(vertex
[3*(face
->vertex_indices
[2])],
99 vertex
[3*(face
->vertex_indices
[2])+1],
100 vertex
[3*(face
->vertex_indices
[2])+2]);
101 trimesh
->addTriangle(vertex0
, vertex1
, vertex2
, true);
103 faces
= g_slist_next(faces
);
109 static btCollisionShape
* shape_from_trimesh(btTriangleMesh
*trimesh
, int movable
)
111 btCollisionShape
* shape
;
114 * create the bullet shape depending on the static status or not of the piece
115 * static : do not move
116 * movable : connected to a HklGeometry axis.
119 shape
= dynamic_cast<btGImpactMeshShape
*>(new btGImpactMeshShape(trimesh
));
120 shape
->setMargin(btScalar(0));
121 shape
->setLocalScaling(btVector3(1,1,1));
122 /* maybe usefull for softbodies (useless for now) */
123 (dynamic_cast<btGImpactMeshShape
*>(shape
))->postUpdate();
124 /* needed for the collision and must be call after the postUpdate (doc) */
125 (dynamic_cast<btGImpactMeshShape
*>(shape
))->updateBound();
127 shape
= dynamic_cast<btBvhTriangleMeshShape
*>(new btBvhTriangleMeshShape (trimesh
, true));
128 shape
->setMargin(btScalar(0));
129 shape
->setLocalScaling(btVector3(1,1,1));
135 static btCollisionObject
* btObject_from_shape(btCollisionShape
* shape
)
137 btCollisionObject
*btObject
;
139 /* create the Object and add the shape */
140 btObject
= new btCollisionObject();
141 btObject
->setCollisionShape(shape
);
142 btObject
->activate(true);
148 static Hkl3DObject
*hkl3d_object_new(Hkl3DModel
*model
, G3DObject
*object
, int id
)
152 G3DMaterial
* material
;
153 Hkl3DObject
*self
= NULL
;
155 self
= HKL3D_MALLOC(Hkl3DObject
);
157 /* extract the color from the first face */
158 /* this is usefull for the bullet GL draw method */
159 faces
= object
->faces
;
160 material
= ((G3DFace
*)faces
->data
)->material
;
162 /* fill the hkl3d object structure. */
165 self
->axis_name
= strdup(object
->name
);
168 self
->meshes
= trimesh_from_g3dobject(object
);
169 self
->btShape
= shape_from_trimesh(self
->meshes
, false);
170 self
->btObject
= btObject_from_shape(self
->btShape
);
171 self
->color
= new btVector3(material
->r
, material
->g
, material
->b
);
172 self
->hide
= object
->hide
;
174 self
->selected
= false;
175 self
->movable
= false;
178 * if the object already contain a transformation set the Hkl3DObject
179 * transformation with this transformation. Otherwise set it with the
182 if(object
->transformation
){
184 self
->transformation
[i
] = object
->transformation
->matrix
[i
];
186 /* create one as we requiered it to apply our transformations */
187 object
->transformation
= g_new0(G3DTransformation
, 1);
189 self
->transformation
[i
] = identity
[i
];
190 object
->transformation
->matrix
[i
] = identity
[i
];
194 self
->is_colliding
= false;
199 static void hkl3d_object_free(Hkl3DObject
*self
)
204 /* memory leak in libg3d */
205 if(self
->g3d
&& self
->g3d
->transformation
){
206 g_free(self
->g3d
->transformation
);
207 self
->g3d
->transformation
= NULL
;
214 delete self
->btObject
;
215 self
->btObject
= NULL
;
218 delete self
->btShape
;
219 self
->btShape
= NULL
;
226 free(self
->axis_name
);
227 self
->axis_name
= NULL
;
233 static void hkl3d_object_set_movable(Hkl3DObject
*self
, int movable
)
238 if(self
->movable
!= movable
){
239 self
->movable
= movable
;
240 delete self
->btObject
;
241 delete self
->btShape
;
242 self
->btShape
= shape_from_trimesh(self
->meshes
, movable
);
243 self
->btObject
= btObject_from_shape(self
->btShape
);
247 static void hkl3d_object_set_axis_name(Hkl3DObject
*self
, const char *name
)
249 if(!self
|| !name
|| self
->axis_name
== name
)
253 free(self
->axis_name
);
254 self
->axis_name
= strdup(name
);
257 static void matrix_fprintf(FILE *f
, const float matrix
[])
259 fprintf(f
, "transformation : ");
260 for(uint i
=0; i
<4; ++i
){
263 for(uint j
=0; j
<4; ++j
){
264 fprintf(f
, " %6.3f", matrix
[4 * i
+ j
]);
270 void hkl3d_object_aabb_get(const Hkl3DObject
*self
, float from
[3], float to
[3])
274 self
->btShape
->getAabb(self
->btObject
->getWorldTransform(), min
, max
);
276 from
[0] = min
.getX();
277 from
[1] = min
.getY();
278 from
[2] = min
.getZ();
284 void hkl3d_object_fprintf(FILE *f
, const Hkl3DObject
*self
)
287 G3DMaterial
* material
;
289 faces
= self
->g3d
->faces
;
290 material
= ((G3DFace
*)faces
->data
)->material
;
291 fprintf(f
, "id : %d\n", self
->id
);
292 fprintf(f
, "name : %s (%p)\n", self
->axis_name
, self
->axis_name
);
293 fprintf(f
, "axis : %p\n", self
->axis
);
294 matrix_fprintf(f
, self
->transformation
);
295 fprintf(f
, "btObject : %p\n", self
->btObject
);
296 fprintf(f
, "g3d : %p\n", self
->g3d
);
297 matrix_fprintf(f
, self
->g3d
->transformation
->matrix
);
298 fprintf(f
, "btShape : %p\n", self
->btShape
);
299 fprintf(f
, "meshes : %p\n", self
->meshes
);
300 fprintf(f
, "color : %f, %f, %f\n", material
->r
, material
->g
, material
->b
);
301 fprintf(f
, "is_colliding : %d\n", self
->is_colliding
);
302 fprintf(f
, "hide : %d\n", self
->hide
);
303 fprintf(f
, "added : %d\n", self
->added
);
304 fprintf(f
, "selected : %d\n", self
->selected
);
311 static Hkl3DModel
*hkl3d_model_new(void)
313 Hkl3DModel
*self
= NULL
;
315 self
= HKL3D_MALLOC(Hkl3DModel
);
317 self
->filename
= NULL
;
318 self
->objects
= NULL
;
325 static void hkl3d_model_free(Hkl3DModel
*self
)
332 free(self
->filename
);
333 for(i
=0; i
<self
->len
; ++i
)
334 hkl3d_object_free(self
->objects
[i
]);
336 g3d_model_free(self
->g3d
);
340 static void hkl3d_model_add_object(Hkl3DModel
*self
, Hkl3DObject
*object
)
345 self
->objects
= (typeof(self
->objects
))realloc(self
->objects
, sizeof(*self
->objects
) * (self
->len
+ 1));
346 self
->objects
[self
->len
++] = object
;
349 static void hkl3d_model_delete_object(Hkl3DModel
*self
, Hkl3DObject
*object
)
356 if(self
!= object
->model
)
359 /* find the index of the object */
360 for(i
=0; self
->objects
[i
] != object
; ++i
);
362 hkl3d_object_free(object
);
364 /* move all above objects of 1 position */
366 memmove(object
, object
+ 1, sizeof(object
) * (self
->len
- i
));
369 void hkl3d_model_fprintf(FILE *f
, const Hkl3DModel
*self
)
371 fprintf(f
, "config (%zd):\n", self
->len
);
372 for(size_t i
=0; i
<self
->len
; ++i
)
373 hkl3d_object_fprintf(f
, self
->objects
[i
]);
377 * Initialize the bullet collision environment.
378 * create the Hkl3DObjects
379 * create the Hkl3DConfig
381 static Hkl3DModel
*hkl3d_model_new_from_file(const char *filename
)
384 Hkl3DModel
*self
= NULL
;
385 GSList
*objects
; /* lets iterate from the first object. */
391 /* load the model from the file */
392 context
= g3d_context_new();
393 model
= g3d_model_load_full(context
, filename
, 0);
394 g3d_context_free(context
);
397 self
= hkl3d_model_new();
399 self
->filename
= strdup(filename
);
402 /* create all the attached Hkl3DObjects */
403 objects
= model
->objects
;
407 object
= (G3DObject
*)objects
->data
;
408 if(object
->vertex_count
){
410 Hkl3DObject
*hkl3dObject
;
412 id
= g_slist_index(model
->objects
, object
);
413 hkl3dObject
= hkl3d_object_new(self
, object
, id
);
415 /* remembers objects to avoid memory leak */
416 hkl3d_model_add_object(self
, hkl3dObject
);
418 objects
= g_slist_next(objects
);
427 static Hkl3DConfig
* hkl3d_config_new(void)
429 Hkl3DConfig
* self
= NULL
;
431 self
= (Hkl3DConfig
*)malloc(sizeof(Hkl3DConfig
));
441 static void hkl3d_config_free(Hkl3DConfig
*self
)
446 for(size_t i
=0; i
<self
->len
; ++i
)
447 hkl3d_model_free(self
->models
[i
]);
452 static void hkl3d_config_add_model(Hkl3DConfig
*self
, Hkl3DModel
*model
)
454 self
->models
= (typeof(self
->models
))realloc(self
->models
, sizeof(*self
->models
) * (self
->len
+ 1));
455 self
->models
[self
->len
++] = model
;
458 void hkl3d_config_fprintf(FILE *f
, const Hkl3DConfig
*self
)
460 fprintf(f
, "models (%zd):\n", self
->len
);
461 for(size_t i
=0; i
<self
->len
; ++i
)
462 hkl3d_model_fprintf(f
, self
->models
[i
]);
469 double hkl3d_stats_get_collision_ms(const Hkl3DStats
*self
)
471 return self
->collision
.tv_sec
*1000. + self
->collision
.tv_usec
/1000.;
474 void hkl3d_stats_fprintf(FILE *f
, const Hkl3DStats
*self
)
476 fprintf(f
, "transformation : %f ms collision : %f ms \n",
477 self
->transformation
.tv_sec
*1000. + self
->transformation
.tv_usec
/1000.,
478 hkl3d_stats_get_collision_ms(self
));
485 static Hkl3DAxis
*hkl3d_axis_new(void)
487 Hkl3DAxis
*self
= NULL
;
489 self
= HKL3D_MALLOC(Hkl3DAxis
);
491 self
->objects
= NULL
; /* do not own the objects */
497 static void hkl3d_axis_free(Hkl3DAxis
*self
)
506 /* should be optimized (useless if the Hkl3DObject had a connection with the Hkl3DAxis */
507 static void hkl3d_axis_attach_object(Hkl3DAxis
*self
, Hkl3DObject
*object
)
510 self
->objects
= (Hkl3DObject
**)realloc(self
->objects
, sizeof(*self
->objects
) * (self
->len
+ 1));
511 self
->objects
[self
->len
++] = object
;
514 /* should be optimized (useless if the Hkl3DObject had a connection with the Hkl3DAxis */
515 static void hkl3d_axis_detach_object(Hkl3DAxis
*self
, Hkl3DObject
*object
)
522 if(self
!= object
->axis
)
525 /* find the index of the object in the object list */
526 for(i
=0; self
->objects
[i
] != object
; ++i
);
529 /* move all above objects of 1 position */
532 memmove(object
, object
+1, sizeof(object
) * (self
->len
- i
));
535 static void hkl3d_axis_fprintf(FILE *f
, const Hkl3DAxis
*self
)
540 fprintf(f
, "Axis len : %zd\n", self
->len
);
541 for(size_t i
=0; i
<self
->len
; ++i
)
542 hkl3d_object_fprintf(f
, self
->objects
[i
]);
549 static Hkl3DGeometry
*hkl3d_geometry_new(HklGeometry
*geometry
)
552 Hkl3DGeometry
*self
= NULL
;
554 self
= HKL3D_MALLOC(Hkl3DGeometry
);
556 self
->geometry
= geometry
;
557 self
->axes
= (Hkl3DAxis
**)malloc(darray_size(geometry
->axes
) * sizeof(*self
->axes
));
559 for(i
=0; i
<darray_size(geometry
->axes
); ++i
)
560 self
->axes
[i
] = hkl3d_axis_new();
565 static void hkl3d_geometry_free(Hkl3DGeometry
*self
)
572 for(i
=0; i
<darray_size(self
->geometry
->axes
); ++i
)
573 hkl3d_axis_free(self
->axes
[i
]);
578 static void hkl3d_geometry_apply_transformations(Hkl3DGeometry
*self
)
582 darray_foreach(holder
, self
->geometry
->holders
){
584 btQuaternion
btQ(0, 0, 0, 1);
586 size_t len
= (*holder
)->config
->len
;
587 for(j
=0; j
<len
; j
++){
589 size_t idx
= (*holder
)->config
->idx
[j
];
590 const HklQuaternion
*q
= hkl_parameter_quaternion_get(darray_item(self
->geometry
->axes
, idx
));
593 /* conversion beetween hkl -> bullet coordinates */
594 btQ
*= btQuaternion(-q
->data
[1],
599 /* move each object connected to that hkl Axis. */
600 /* apply the quaternion transformation to the bullet object */
601 /* use the bullet library to compute the OpenGL matrix */
602 /* apply this matrix to the G3DObject for the visualisation */
603 for(k
=0; k
<self
->axes
[idx
]->len
; ++k
){
604 self
->axes
[idx
]->objects
[k
]->btObject
->getWorldTransform().setRotation(btQ
);
605 self
->axes
[idx
]->objects
[k
]->btObject
->getWorldTransform().getOpenGLMatrix( G3DM
);
606 memcpy(self
->axes
[idx
]->objects
[k
]->g3d
->transformation
->matrix
,
607 &G3DM
[0], sizeof(G3DM
));
613 static void hkl3d_geometry_fprintf(FILE *f
, const Hkl3DGeometry
*self
)
618 fprintf(f
, "Hkl3DGeometry : \n");
619 hkl_geometry_fprintf(f
, self
->geometry
);
620 for(size_t i
=0; i
<darray_size(self
->geometry
->axes
); ++i
)
621 hkl3d_axis_fprintf(f
, self
->axes
[i
]);
624 static Hkl3DAxis
*hkl3d_geometry_axis_get(Hkl3DGeometry
*self
, const char *name
)
626 for(size_t i
=0; i
<darray_size(self
->geometry
->axes
); ++i
){
627 if (!strcmp(hkl_parameter_name_get(darray_item(self
->geometry
->axes
, i
)),
629 return self
->axes
[i
];
638 static void hkl3d_apply_transformations(Hkl3D
*self
)
640 struct timeval debut
, fin
;
642 /* set the right transformation of each objects and get numbers */
643 gettimeofday(&debut
, NULL
);
644 hkl3d_geometry_apply_transformations(self
->geometry
);
645 gettimeofday(&fin
, NULL
);
646 timersub(&fin
, &debut
, &self
->stats
.transformation
);
649 void hkl3d_connect_all_axes(Hkl3D
*self
)
651 /* connect use the axes names */
652 for(size_t i
=0;i
<self
->config
->len
;i
++)
653 for(size_t j
=0;j
<self
->config
->models
[i
]->len
;j
++)
654 hkl3d_connect_object_to_axis(self
,
655 self
->config
->models
[i
]->objects
[j
],
656 self
->config
->models
[i
]->objects
[j
]->axis_name
);
668 Hkl3D
*hkl3d_new(const char *filename
, HklGeometry
*geometry
)
672 self
= HKL3D_MALLOC(Hkl3D
);
674 self
->geometry
= hkl3d_geometry_new(geometry
);
675 self
->config
= hkl3d_config_new();
676 self
->model
= g3d_model_new();
678 /* initialize the bullet part */
679 self
->_btCollisionConfiguration
= new btDefaultCollisionConfiguration();
681 #ifdef USE_PARALLEL_DISPATCHER
682 int maxNumOutstandingTasks
= 2;
683 PosixThreadSupport::ThreadConstructionInfo
constructionInfo("collision",
684 processCollisionTask
,
685 createCollisionLocalStoreMemory
,
686 maxNumOutstandingTasks
);
687 self
->_btThreadSupportInterface
= new PosixThreadSupport(constructionInfo
);
688 self
->_btDispatcher
= new SpuGatheringCollisionDispatcher(self
->_btThreadSupportInterface
,
689 maxNumOutstandingTasks
,
690 self
->_btCollisionConfiguration
);
692 self
->_btDispatcher
= new btCollisionDispatcher(self
->_btCollisionConfiguration
);
694 btGImpactCollisionAlgorithm::registerAlgorithm(self
->_btDispatcher
);
696 btVector3
worldAabbMin(-1000,-1000,-1000);
697 btVector3
worldAabbMax( 1000, 1000, 1000);
699 self
->_btBroadphase
= new btAxisSweep3(worldAabbMin
, worldAabbMax
);
701 self
->_btWorld
= new btCollisionWorld(self
->_btDispatcher
,
703 self
->_btCollisionConfiguration
);
705 self
->filename
= filename
;
707 hkl3d_load_config(self
, filename
);
712 void hkl3d_free(Hkl3D
*self
)
714 /* remove all objects from the collision world */
715 for(size_t i
=0; i
<self
->config
->len
; ++i
)
716 for(size_t j
=0; j
<self
->config
->models
[i
]->len
; ++j
)
717 if(self
->config
->models
[i
]->objects
[j
]->added
)
718 self
->_btWorld
->removeCollisionObject(self
->config
->models
[i
]->objects
[j
]->btObject
);
720 hkl3d_geometry_free(self
->geometry
);
721 hkl3d_config_free(self
->config
);
724 delete self
->_btWorld
;
725 if (self
->_btBroadphase
)
726 delete self
->_btBroadphase
;
727 if (self
->_btDispatcher
)
728 delete self
->_btDispatcher
;
729 #ifdef USE_PARALLEL_DISPATCHER
730 if (self
->_btThreadSupportInterface
){
731 /* delete _btThreadSupportInterface; */
732 /* _btThreadSupportInterface = 0; */
735 if (self
->_btCollisionConfiguration
)
736 delete self
->_btCollisionConfiguration
;
737 g_free(self
->model
); /* do not use g3d_model_free as it is juste a container for all config->model */
742 Hkl3DModel
*hkl3d_add_model_from_file(Hkl3D
*self
,
743 const char *filename
, const char *directory
)
746 Hkl3DModel
*model
= NULL
;
749 /* first set the current directory using the directory
750 * parameter. Maybe using openat should be a better solution
751 * in the hkl3d_model_new_from_file */
752 current
= open(".", O_RDONLY
);
755 res
= chdir(directory
);
759 model
= hkl3d_model_new_from_file(filename
);
761 /* we can not display two different models with the current g3dviewer code */
762 /* so concatenate this loaded model with the one of hkl3d */
763 self
->model
->objects
= g_slist_concat(self
->model
->objects
, model
->g3d
->objects
);
764 self
->model
->materials
= g_slist_concat(self
->model
->materials
, model
->g3d
->materials
);
766 /* update the Hkl3D internals from the model */
767 hkl3d_config_add_model(self
->config
, model
);
769 /* restore the current directory */
770 res
= fchdir(current
);
779 /* check that the axis name is really available in the Geometry */
780 /* if axis name not valid make the object static object->name = NULL */
781 /* ok so check if the axis was already connected or not */
782 /* if already connected check if it was a different axis do the job */
783 /* if not yet connected do the job */
784 /* fill movingCollisionObject and movingG3DObjects vectors for transformations */
785 void hkl3d_connect_object_to_axis(Hkl3D
*self
, Hkl3DObject
*object
, const char *name
)
787 Hkl3DAxis
*axis3d
= hkl3d_geometry_axis_get(self
->geometry
, name
);
788 if (!object
->movable
){
789 if(axis3d
){ /* static -> movable */
790 self
->_btWorld
->removeCollisionObject(object
->btObject
);
791 hkl3d_object_set_movable(object
, true);
792 self
->_btWorld
->addCollisionObject(object
->btObject
);
793 object
->added
= true;
794 hkl3d_axis_attach_object(axis3d
, object
);
797 if(!axis3d
){ /* movable -> static */
798 self
->_btWorld
->removeCollisionObject(object
->btObject
);
799 hkl3d_object_set_movable(object
, false);
800 self
->_btWorld
->addCollisionObject(object
->btObject
);
801 object
->added
= true;
802 }else{ /* movable -> movable */
803 if(strcmp(object
->axis_name
, name
)){ /* not the same axis */
804 hkl3d_axis_detach_object(object
->axis
, object
);
805 hkl3d_axis_attach_object(axis3d
, object
);
809 hkl3d_object_set_axis_name(object
, name
);
812 void hkl3d_load_config(Hkl3D
*self
, const char *filename
)
817 yaml_parser_t parser
;
818 yaml_event_t input_event
;
822 Hkl3DModel
*config
= NULL
;
824 /* Clear the objects. */
825 memset(&parser
, 0, sizeof(parser
));
826 memset(&input_event
, 0, sizeof(input_event
));
828 file
= fopen(filename
, "rb");
830 fprintf(stderr
, "Could not open the %s config file\n", filename
);
834 if (!yaml_parser_initialize(&parser
))
835 fprintf(stderr
, "Could not initialize the parser object\n");
836 yaml_parser_set_input_file(&parser
, file
);
838 /* compute the dirname of the config file as all model files */
839 /* will be relative to this directory */
840 dirc
= strdup(filename
);
844 /* Get the next event. */
845 yaml_parser_parse(&parser
, &input_event
);
847 /* Check if this is the stream end. */
848 if(input_event
.type
== YAML_STREAM_END_EVENT
)
850 if(input_event
.type
== YAML_DOCUMENT_START_EVENT
){
856 // SCALAR fileName key
858 yaml_event_delete(&input_event
);
859 yaml_parser_parse(&parser
, &input_event
);
862 /* the add form file method create a default Hkl3DModel and add it to the HKL3D */
863 /* we just need to update this config with the values from the configuration file */
864 config
= hkl3d_add_model_from_file(self
, (const char *)input_event
.data
.scalar
.value
, dir
);
866 // SCALAR objects key
870 yaml_event_delete(&input_event
);
871 yaml_parser_parse(&parser
, &input_event
);
875 if((input_event
.type
==YAML_MAPPING_START_EVENT
)&& config
){
881 yaml_event_delete(&input_event
);
882 yaml_parser_parse(&parser
, &input_event
);
885 /* get the object id */
886 config
->objects
[j
-1]->id
= atoi((const char *)input_event
.data
.scalar
.value
);
888 /* skip 2 more events */
892 yaml_event_delete(&input_event
);
893 yaml_parser_parse(&parser
, &input_event
);
896 /* get the name of the object from the config file */
897 hkl3d_object_set_axis_name(config
->objects
[j
-1], (const char *)input_event
.data
.scalar
.value
);
900 // SCALAR transformation key
903 yaml_event_delete(&input_event
);
904 yaml_parser_parse(&parser
, &input_event
);
907 /* get the 16 values of the transformation */
909 config
->objects
[j
-1]->transformation
[l
] = atof((const char *)input_event
.data
.scalar
.value
);
910 yaml_event_delete(&input_event
);
911 yaml_parser_parse(&parser
, &input_event
);
918 yaml_event_delete(&input_event
);
919 yaml_parser_parse(&parser
, &input_event
);
922 /* get the hide value */
923 config
->objects
[j
-1]->hide
= strcmp((const char *)input_event
.data
.scalar
.value
, "no");
924 config
->objects
[j
-1]->g3d
->hide
= config
->objects
[j
-1]->hide
;
926 yaml_event_delete(&input_event
);
930 yaml_parser_delete(&parser
);
933 /* now that everythings goes fine we can save the filename */
934 self
->filename
= filename
;
936 hkl3d_connect_all_axes(self
);
939 void hkl3d_save_config(Hkl3D
*self
, const char *filename
)
941 for(size_t i
=0; i
<self
->config
->len
; i
++){
943 int properties1
, key1
, value1
,seq0
;
946 yaml_emitter_t emitter
;
947 yaml_document_t output_document
;
948 yaml_event_t output_event
;
951 memset(&emitter
, 0, sizeof(emitter
));
952 memset(&output_document
, 0, sizeof(output_document
));
953 memset(&output_event
, 0, sizeof(output_event
));
955 if (!yaml_emitter_initialize(&emitter
))
956 fprintf(stderr
, "Could not inialize the emitter object\n");
958 /* Set the emitter parameters */
959 file
= fopen(filename
, "a+");
961 fprintf(stderr
, "Could not open the config file %s to save\n", filename
);
964 yaml_emitter_set_output_file(&emitter
, file
);
965 yaml_emitter_open(&emitter
);
967 /* Create an output_document object */
968 if (!yaml_document_initialize(&output_document
, NULL
, NULL
, NULL
, 0, 0))
969 fprintf(stderr
, "Could not create a output_document object\n");
971 /* Create the root of the config file */
973 root
= yaml_document_add_sequence(&output_document
,
974 (yaml_char_t
*)ctime(&now
),
975 YAML_BLOCK_SEQUENCE_STYLE
);
977 /* create the property of the root sequence */
978 properties1
= yaml_document_add_mapping(&output_document
,
979 (yaml_char_t
*)YAML_MAP_TAG
,
980 YAML_BLOCK_MAPPING_STYLE
);
982 yaml_document_append_sequence_item(&output_document
, root
, properties1
);
984 /* add the map key1 : value1 to the property */
985 key1
= yaml_document_add_scalar(&output_document
,
987 (yaml_char_t
*)"FileName",
989 YAML_PLAIN_SCALAR_STYLE
);
990 value1
= yaml_document_add_scalar(&output_document
,
992 (yaml_char_t
*)self
->config
->models
[i
]->filename
,
994 YAML_PLAIN_SCALAR_STYLE
);
995 yaml_document_append_mapping_pair(&output_document
, properties1
, key1
, value1
);
997 /* add the map key1 : seq0 to the first property */
998 key1
= yaml_document_add_scalar(&output_document
,
1000 (yaml_char_t
*)"Objects",
1002 YAML_PLAIN_SCALAR_STYLE
);
1003 /* create the sequence of objects */
1004 seq0
= yaml_document_add_sequence(&output_document
,
1005 (yaml_char_t
*)YAML_SEQ_TAG
,
1006 YAML_BLOCK_SEQUENCE_STYLE
);
1007 for(size_t j
=0; j
<self
->config
->models
[i
]->len
; j
++){
1014 properties
= yaml_document_add_mapping(&output_document
,
1015 (yaml_char_t
*)YAML_MAP_TAG
,
1016 YAML_BLOCK_MAPPING_STYLE
);
1017 yaml_document_append_sequence_item(&output_document
,seq0
, properties
);
1019 key
= yaml_document_add_scalar(&output_document
,
1021 (yaml_char_t
*)"Id", -1,
1022 YAML_PLAIN_SCALAR_STYLE
);
1024 sprintf(number
, "%d", self
->config
->models
[i
]->objects
[j
]->id
);
1025 value
= yaml_document_add_scalar(&output_document
,
1027 (yaml_char_t
*)number
,
1029 YAML_PLAIN_SCALAR_STYLE
);
1030 yaml_document_append_mapping_pair(&output_document
,properties
,key
,value
);
1032 key
= yaml_document_add_scalar(&output_document
,
1034 (yaml_char_t
*)"Name",
1036 YAML_PLAIN_SCALAR_STYLE
);
1037 value
= yaml_document_add_scalar(&output_document
,
1039 (yaml_char_t
*)self
->config
->models
[i
]->objects
[j
]->axis_name
,
1041 YAML_PLAIN_SCALAR_STYLE
);
1042 yaml_document_append_mapping_pair(&output_document
,properties
,key
,value
);
1044 key
= yaml_document_add_scalar(&output_document
,
1046 (yaml_char_t
*)"Transformation",
1048 YAML_PLAIN_SCALAR_STYLE
);
1049 seq1
= yaml_document_add_sequence(&output_document
,
1050 (yaml_char_t
*)YAML_SEQ_TAG
,
1051 YAML_FLOW_SEQUENCE_STYLE
);
1052 yaml_document_append_mapping_pair(&output_document
,properties
, key
, seq1
);
1053 for(k
=0; k
<16; k
++){
1054 sprintf(number
, "%f", self
->config
->models
[i
]->objects
[j
]->transformation
[k
]);
1055 value
= yaml_document_add_scalar(&output_document
,
1057 (yaml_char_t
*)number
,
1059 YAML_PLAIN_SCALAR_STYLE
);
1060 yaml_document_append_sequence_item(&output_document
,seq1
,value
);
1063 key
= yaml_document_add_scalar(&output_document
,
1065 (yaml_char_t
*)"Hide",
1067 YAML_PLAIN_SCALAR_STYLE
);
1068 if(self
->config
->models
[i
]->objects
[j
]->hide
)
1069 value
= yaml_document_add_scalar(&output_document
,
1071 (yaml_char_t
*)"yes",
1073 YAML_PLAIN_SCALAR_STYLE
);
1075 value
= yaml_document_add_scalar(&output_document
,
1077 (yaml_char_t
*)"no",
1079 YAML_PLAIN_SCALAR_STYLE
);
1080 yaml_document_append_mapping_pair(&output_document
,properties
,key
,value
);
1082 yaml_document_append_mapping_pair(&output_document
, properties1
, key1
, seq0
);
1084 /* flush the document */
1085 yaml_emitter_dump(&emitter
, &output_document
);
1088 yaml_document_delete(&output_document
);
1089 yaml_emitter_delete(&emitter
);
1094 * Hkl3D::hide_object:
1096 * update the visibility of an Hkl3DObject in the bullet world
1097 * add or remove the object from the _btWorld depending on the hide
1098 * member of the object.
1100 void hkl3d_hide_object(Hkl3D
*self
, Hkl3DObject
*object
, int hide
)
1102 /* first update the G3DObject */
1103 object
->hide
= hide
;
1104 object
->g3d
->hide
= hide
;
1107 self
->_btWorld
->removeCollisionObject(object
->btObject
);
1108 object
->added
= false;
1112 self
->_btWorld
->addCollisionObject(object
->btObject
);
1113 object
->added
= true;
1118 /* remove an object from the model */
1119 void hkl3d_remove_object(Hkl3D
*self
, Hkl3DObject
*object
)
1121 hkl3d_hide_object(self
, object
, TRUE
);
1122 hkl3d_axis_detach_object(object
->axis
, object
);
1124 /* now remove the G3DObject from the model */
1125 self
->model
->objects
= g_slist_remove(self
->model
->objects
, object
->g3d
);
1126 hkl3d_model_delete_object(object
->model
, object
);
1130 int hkl3d_is_colliding(Hkl3D
*self
)
1133 struct timeval debut
, fin
;
1135 /* apply geometry transformation */
1136 hkl3d_apply_transformations(self
);
1138 /* perform the collision detection and get numbers */
1139 gettimeofday(&debut
, NULL
);
1141 self
->_btWorld
->performDiscreteCollisionDetection();
1142 self
->_btWorld
->updateAabbs();
1144 gettimeofday(&fin
, NULL
);
1145 timersub(&fin
, &debut
, &self
->stats
.collision
);
1147 numManifolds
= self
->_btDispatcher
->getNumManifolds();
1149 /* update Hkl3DObject collision from manifolds */
1150 for(size_t i
=0; i
<self
->config
->len
; i
++){
1151 for(size_t j
=0; j
<self
->config
->models
[i
]->len
; j
++){
1152 Hkl3DObject
*object
= self
->config
->models
[i
]->objects
[j
];
1153 object
->is_colliding
= FALSE
;
1154 for(int k
=0; k
<numManifolds
; ++k
){
1155 btPersistentManifold
*manifold
= self
->_btDispatcher
->getManifoldByIndexInternal(k
);
1156 object
->is_colliding
|= object
->btObject
== manifold
->getBody0();
1157 object
->is_colliding
|= object
->btObject
== manifold
->getBody1();
1162 return numManifolds
!= 0;
1166 * Hkl3D::get_bounding_boxes:
1170 * get the bounding boxes of the current world from the bullet internals.
1172 void hkl3d_get_bounding_boxes(Hkl3D
*self
,
1173 struct btVector3
*min
, struct btVector3
*max
)
1175 self
->_btWorld
->getBroadphase()->getBroadphaseAabb(*min
, *max
);
1178 int hkl3d_get_nb_manifolds(Hkl3D
*self
)
1180 return self
->_btDispatcher
->getNumManifolds();
1183 int hkl3d_get_nb_contacts(Hkl3D
*self
, int manifold
)
1185 return self
->_btDispatcher
->getManifoldByIndexInternal(manifold
)->getNumContacts();
1188 void hkl3d_get_collision_coordinates(Hkl3D
*self
, int manifold
, int contact
,
1189 double *xa
, double *ya
, double *za
,
1190 double *xb
, double *yb
, double *zb
)
1192 btPersistentManifold
*contactManifold
;
1194 contactManifold
= self
->_btDispatcher
->getManifoldByIndexInternal(manifold
);
1195 btManifoldPoint
& pt
= contactManifold
->getContactPoint(contact
);
1196 btVector3 ptA
= pt
.getPositionWorldOnA();
1197 btVector3 ptB
= pt
.getPositionWorldOnB();
1207 void hkl3d_fprintf(FILE *f
, const Hkl3D
*self
)
1210 fprintf(f
, "filename : %s\n", self
->filename
);
1211 hkl3d_geometry_fprintf(f
, self
->geometry
);
1213 fprintf(f
, "model : %p\n", self
->model
);
1214 hkl3d_stats_fprintf(f
, &self
->stats
);
1215 hkl3d_config_fprintf(f
, self
->config
);
1217 fprintf(f
, "_btCollisionConfiguration : %p\n", self
->_btCollisionConfiguration
);
1218 fprintf(f
, "_btBroadphase : %p\n", self
->_btBroadphase
);
1219 fprintf(f
, "_btWorld : %p\n", self
->_btWorld
);
1220 fprintf(f
, "_btDispatcher : %p\n", self
->_btDispatcher
);
1221 #ifdef USE_PARALLEL_DISPATCHER
1222 fprintf(f
, "_btThreadSupportInterface : %p\n", self
->_btThreadSupportInterface
);