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"
55 static float identity
[] = {1, 0, 0, 0,
60 static void *_hkl3d_malloc(int size
, const char *error
)
64 tmp
= calloc(1, size
);
66 fprintf(stderr
, "%s", error
);
73 #define HKL3D_MALLOC(type) (type *)_hkl3d_malloc(sizeof(type), "Can not allocate memory for a " #type)
79 static btTriangleMesh
*trimesh_from_g3dobject(G3DObject
*object
)
81 btTriangleMesh
*trimesh
;
85 trimesh
= new btTriangleMesh();
86 trimesh
->preallocateVertices(object
->vertex_count
);
87 faces
= object
->faces
;
88 vertex
= object
->vertex_data
;
92 face
= (G3DFace
*)faces
->data
;
93 btVector3
vertex0(vertex
[3*(face
->vertex_indices
[0])],
94 vertex
[3*(face
->vertex_indices
[0])+1],
95 vertex
[3*(face
->vertex_indices
[0])+2]);
96 btVector3
vertex1(vertex
[3*(face
->vertex_indices
[1])],
97 vertex
[3*(face
->vertex_indices
[1])+1],
98 vertex
[3*(face
->vertex_indices
[1])+2]);
99 btVector3
vertex2(vertex
[3*(face
->vertex_indices
[2])],
100 vertex
[3*(face
->vertex_indices
[2])+1],
101 vertex
[3*(face
->vertex_indices
[2])+2]);
102 trimesh
->addTriangle(vertex0
, vertex1
, vertex2
, true);
104 faces
= g_slist_next(faces
);
110 static btCollisionShape
* shape_from_trimesh(btTriangleMesh
*trimesh
, int movable
)
112 btCollisionShape
* shape
;
115 * create the bullet shape depending on the static status or not of the piece
116 * static : do not move
117 * movable : connected to a HklGeometry axis.
120 shape
= dynamic_cast<btGImpactMeshShape
*>(new btGImpactMeshShape(trimesh
));
121 shape
->setMargin(btScalar(0));
122 shape
->setLocalScaling(btVector3(1,1,1));
123 /* maybe usefull for softbodies (useless for now) */
124 (dynamic_cast<btGImpactMeshShape
*>(shape
))->postUpdate();
125 /* needed for the collision and must be call after the postUpdate (doc) */
126 (dynamic_cast<btGImpactMeshShape
*>(shape
))->updateBound();
128 shape
= dynamic_cast<btBvhTriangleMeshShape
*>(new btBvhTriangleMeshShape (trimesh
, true));
129 shape
->setMargin(btScalar(0));
130 shape
->setLocalScaling(btVector3(1,1,1));
136 static btCollisionObject
* btObject_from_shape(btCollisionShape
* shape
)
138 btCollisionObject
*btObject
;
140 /* create the Object and add the shape */
141 btObject
= new btCollisionObject();
142 btObject
->setCollisionShape(shape
);
143 btObject
->activate(true);
149 static Hkl3DObject
*hkl3d_object_new(Hkl3DModel
*model
, G3DObject
*object
, int id
)
153 G3DMaterial
* material
;
154 Hkl3DObject
*self
= NULL
;
156 self
= HKL3D_MALLOC(Hkl3DObject
);
158 /* extract the color from the first face */
159 /* this is usefull for the bullet GL draw method */
160 faces
= object
->faces
;
161 material
= ((G3DFace
*)faces
->data
)->material
;
163 /* fill the hkl3d object structure. */
166 self
->axis_name
= strdup(object
->name
);
169 self
->meshes
= trimesh_from_g3dobject(object
);
170 self
->btShape
= shape_from_trimesh(self
->meshes
, false);
171 self
->btObject
= btObject_from_shape(self
->btShape
);
172 self
->color
= new btVector3(material
->r
, material
->g
, material
->b
);
173 self
->hide
= object
->hide
;
175 self
->selected
= false;
176 self
->movable
= false;
179 * if the object already contain a transformation set the Hkl3DObject
180 * transformation with this transformation. Otherwise set it with the
183 if(object
->transformation
){
185 self
->transformation
[i
] = object
->transformation
->matrix
[i
];
187 /* create one as we requiered it to apply our transformations */
188 object
->transformation
= g_new0(G3DTransformation
, 1);
190 self
->transformation
[i
] = identity
[i
];
191 object
->transformation
->matrix
[i
] = identity
[i
];
195 self
->is_colliding
= false;
200 static void hkl3d_object_free(Hkl3DObject
*self
)
205 /* memory leak in libg3d */
206 if(self
->g3d
&& self
->g3d
->transformation
){
207 g_free(self
->g3d
->transformation
);
208 self
->g3d
->transformation
= NULL
;
215 delete self
->btObject
;
216 self
->btObject
= NULL
;
219 delete self
->btShape
;
220 self
->btShape
= NULL
;
227 free(self
->axis_name
);
228 self
->axis_name
= NULL
;
234 static void hkl3d_object_set_movable(Hkl3DObject
*self
, int movable
)
239 if(self
->movable
!= movable
){
240 self
->movable
= movable
;
241 delete self
->btObject
;
242 delete self
->btShape
;
243 self
->btShape
= shape_from_trimesh(self
->meshes
, movable
);
244 self
->btObject
= btObject_from_shape(self
->btShape
);
248 static void hkl3d_object_set_axis_name(Hkl3DObject
*self
, const char *name
)
250 if(!self
|| !name
|| self
->axis_name
== name
)
254 free(self
->axis_name
);
255 self
->axis_name
= strdup(name
);
258 static void matrix_fprintf(FILE *f
, const float matrix
[])
260 fprintf(f
, "transformation : ");
261 for(uint i
=0; i
<4; ++i
){
264 for(uint j
=0; j
<4; ++j
){
265 fprintf(f
, " %6.3f", matrix
[4 * i
+ j
]);
271 void hkl3d_object_aabb_get(const Hkl3DObject
*self
, float from
[3], float to
[3])
275 self
->btShape
->getAabb(self
->btObject
->getWorldTransform(), min
, max
);
277 from
[0] = min
.getX();
278 from
[1] = min
.getY();
279 from
[2] = min
.getZ();
285 void hkl3d_object_fprintf(FILE *f
, const Hkl3DObject
*self
)
288 G3DMaterial
* material
;
290 faces
= self
->g3d
->faces
;
291 material
= ((G3DFace
*)faces
->data
)->material
;
292 fprintf(f
, "id : %d\n", self
->id
);
293 fprintf(f
, "name : %s (%p)\n", self
->axis_name
, self
->axis_name
);
294 fprintf(f
, "axis : %p\n", self
->axis
);
295 matrix_fprintf(f
, self
->transformation
);
296 fprintf(f
, "btObject : %p\n", self
->btObject
);
297 fprintf(f
, "g3d : %p\n", self
->g3d
);
298 matrix_fprintf(f
, self
->g3d
->transformation
->matrix
);
299 fprintf(f
, "btShape : %p\n", self
->btShape
);
300 fprintf(f
, "meshes : %p\n", self
->meshes
);
301 fprintf(f
, "color : %f, %f, %f\n", material
->r
, material
->g
, material
->b
);
302 fprintf(f
, "is_colliding : %d\n", self
->is_colliding
);
303 fprintf(f
, "hide : %d\n", self
->hide
);
304 fprintf(f
, "added : %d\n", self
->added
);
305 fprintf(f
, "selected : %d\n", self
->selected
);
312 static Hkl3DModel
*hkl3d_model_new(void)
314 Hkl3DModel
*self
= NULL
;
316 self
= HKL3D_MALLOC(Hkl3DModel
);
318 self
->filename
= NULL
;
319 self
->objects
= NULL
;
326 static void hkl3d_model_free(Hkl3DModel
*self
)
333 free(self
->filename
);
334 for(i
=0; i
<self
->len
; ++i
)
335 hkl3d_object_free(self
->objects
[i
]);
337 g3d_model_free(self
->g3d
);
341 static void hkl3d_model_add_object(Hkl3DModel
*self
, Hkl3DObject
*object
)
346 self
->objects
= (typeof(self
->objects
))realloc(self
->objects
, sizeof(*self
->objects
) * (self
->len
+ 1));
347 self
->objects
[self
->len
++] = object
;
350 static void hkl3d_model_delete_object(Hkl3DModel
*self
, Hkl3DObject
*object
)
357 if(self
!= object
->model
)
360 /* find the index of the object */
361 for(i
=0; self
->objects
[i
] != object
; ++i
);
363 hkl3d_object_free(object
);
365 /* move all above objects of 1 position */
367 memmove(object
, object
+ 1, sizeof(object
) * (self
->len
- i
));
370 void hkl3d_model_fprintf(FILE *f
, const Hkl3DModel
*self
)
372 fprintf(f
, "config (%d):\n", self
->len
);
373 for(size_t i
=0; i
<self
->len
; ++i
)
374 hkl3d_object_fprintf(f
, self
->objects
[i
]);
378 * Initialize the bullet collision environment.
379 * create the Hkl3DObjects
380 * create the Hkl3DConfig
382 static Hkl3DModel
*hkl3d_model_new_from_file(const char *filename
)
385 Hkl3DModel
*self
= NULL
;
386 GSList
*objects
; /* lets iterate from the first object. */
392 /* load the model from the file */
393 context
= g3d_context_new();
394 model
= g3d_model_load_full(context
, filename
, 0);
395 g3d_context_free(context
);
398 self
= hkl3d_model_new();
400 self
->filename
= strdup(filename
);
403 /* create all the attached Hkl3DObjects */
404 objects
= model
->objects
;
408 object
= (G3DObject
*)objects
->data
;
409 if(object
->vertex_count
){
411 Hkl3DObject
*hkl3dObject
;
413 id
= g_slist_index(model
->objects
, object
);
414 hkl3dObject
= hkl3d_object_new(self
, object
, id
);
416 /* remembers objects to avoid memory leak */
417 hkl3d_model_add_object(self
, hkl3dObject
);
419 objects
= g_slist_next(objects
);
428 static Hkl3DConfig
* hkl3d_config_new(void)
430 Hkl3DConfig
* self
= NULL
;
432 self
= (Hkl3DConfig
*)malloc(sizeof(Hkl3DConfig
));
442 static void hkl3d_config_free(Hkl3DConfig
*self
)
447 for(size_t i
=0; i
<self
->len
; ++i
)
448 hkl3d_model_free(self
->models
[i
]);
453 static void hkl3d_config_add_model(Hkl3DConfig
*self
, Hkl3DModel
*model
)
455 self
->models
= (typeof(self
->models
))realloc(self
->models
, sizeof(*self
->models
) * (self
->len
+ 1));
456 self
->models
[self
->len
++] = model
;
459 void hkl3d_config_fprintf(FILE *f
, const Hkl3DConfig
*self
)
461 fprintf(f
, "models (%d):\n", self
->len
);
462 for(size_t i
=0; i
<self
->len
; ++i
)
463 hkl3d_model_fprintf(f
, self
->models
[i
]);
470 double hkl3d_stats_get_collision_ms(const Hkl3DStats
*self
)
472 return self
->collision
.tv_sec
*1000. + self
->collision
.tv_usec
/1000.;
475 void hkl3d_stats_fprintf(FILE *f
, const Hkl3DStats
*self
)
477 fprintf(f
, "transformation : %f ms collision : %f ms \n",
478 self
->transformation
.tv_sec
*1000. + self
->transformation
.tv_usec
/1000.,
479 hkl3d_stats_get_collision_ms(self
));
486 static Hkl3DAxis
*hkl3d_axis_new(void)
488 Hkl3DAxis
*self
= NULL
;
490 self
= HKL3D_MALLOC(Hkl3DAxis
);
492 self
->objects
= NULL
; /* do not own the objects */
498 static void hkl3d_axis_free(Hkl3DAxis
*self
)
507 /* should be optimized (useless if the Hkl3DObject had a connection with the Hkl3DAxis */
508 static void hkl3d_axis_attach_object(Hkl3DAxis
*self
, Hkl3DObject
*object
)
511 self
->objects
= (Hkl3DObject
**)realloc(self
->objects
, sizeof(*self
->objects
) * (self
->len
+ 1));
512 self
->objects
[self
->len
++] = object
;
515 /* should be optimized (useless if the Hkl3DObject had a connection with the Hkl3DAxis */
516 static void hkl3d_axis_detach_object(Hkl3DAxis
*self
, Hkl3DObject
*object
)
523 if(self
!= object
->axis
)
526 /* find the index of the object in the object list */
527 for(i
=0; self
->objects
[i
] != object
; ++i
);
530 /* move all above objects of 1 position */
533 memmove(object
, object
+1, sizeof(object
) * (self
->len
- i
));
536 static void hkl3d_axis_fprintf(FILE *f
, const Hkl3DAxis
*self
)
541 fprintf(f
, "Axis len : %d\n", self
->len
);
542 for(size_t i
=0; i
<self
->len
; ++i
)
543 hkl3d_object_fprintf(f
, self
->objects
[i
]);
550 static Hkl3DGeometry
*hkl3d_geometry_new(HklGeometry
*geometry
)
553 Hkl3DGeometry
*self
= NULL
;
555 self
= HKL3D_MALLOC(Hkl3DGeometry
);
557 self
->geometry
= geometry
;
558 self
->axes
= (Hkl3DAxis
**)malloc(darray_size(geometry
->axes
) * sizeof(*self
->axes
));
560 for(i
=0; i
<darray_size(geometry
->axes
); ++i
)
561 self
->axes
[i
] = hkl3d_axis_new();
566 static void hkl3d_geometry_free(Hkl3DGeometry
*self
)
573 for(i
=0; i
<darray_size(self
->geometry
->axes
); ++i
)
574 hkl3d_axis_free(self
->axes
[i
]);
579 static void hkl3d_geometry_apply_transformations(Hkl3DGeometry
*self
)
583 darray_foreach(holder
, self
->geometry
->holders
){
585 btQuaternion
btQ(0, 0, 0, 1);
587 size_t len
= (*holder
)->config
->len
;
588 for(j
=0; j
<len
; j
++){
590 size_t idx
= (*holder
)->config
->idx
[j
];
591 const HklQuaternion
*q
= hkl_parameter_quaternion_get(darray_item(self
->geometry
->axes
, idx
));
594 /* conversion beetween hkl -> bullet coordinates */
595 btQ
*= btQuaternion(-q
->data
[1],
600 /* move each object connected to that hkl Axis. */
601 /* apply the quaternion transformation to the bullet object */
602 /* use the bullet library to compute the OpenGL matrix */
603 /* apply this matrix to the G3DObject for the visualisation */
604 for(k
=0; k
<self
->axes
[idx
]->len
; ++k
){
605 self
->axes
[idx
]->objects
[k
]->btObject
->getWorldTransform().setRotation(btQ
);
606 self
->axes
[idx
]->objects
[k
]->btObject
->getWorldTransform().getOpenGLMatrix( G3DM
);
607 memcpy(self
->axes
[idx
]->objects
[k
]->g3d
->transformation
->matrix
,
608 &G3DM
[0], sizeof(G3DM
));
614 static void hkl3d_geometry_fprintf(FILE *f
, const Hkl3DGeometry
*self
)
619 fprintf(f
, "Hkl3DGeometry : \n");
620 hkl_geometry_fprintf(f
, self
->geometry
);
621 for(size_t i
=0; i
<darray_size(self
->geometry
->axes
); ++i
)
622 hkl3d_axis_fprintf(f
, self
->axes
[i
]);
625 static Hkl3DAxis
*hkl3d_geometry_axis_get(Hkl3DGeometry
*self
, const char *name
)
627 for(size_t i
=0; i
<darray_size(self
->geometry
->axes
); ++i
){
628 if (!strcmp(hkl_parameter_name_get(darray_item(self
->geometry
->axes
, i
)),
630 return self
->axes
[i
];
639 static void hkl3d_apply_transformations(Hkl3D
*self
)
641 struct timeval debut
, fin
;
643 /* set the right transformation of each objects and get numbers */
644 gettimeofday(&debut
, NULL
);
645 hkl3d_geometry_apply_transformations(self
->geometry
);
646 gettimeofday(&fin
, NULL
);
647 timersub(&fin
, &debut
, &self
->stats
.transformation
);
650 void hkl3d_connect_all_axes(Hkl3D
*self
)
652 /* connect use the axes names */
653 for(size_t i
=0;i
<self
->config
->len
;i
++)
654 for(size_t j
=0;j
<self
->config
->models
[i
]->len
;j
++)
655 hkl3d_connect_object_to_axis(self
,
656 self
->config
->models
[i
]->objects
[j
],
657 self
->config
->models
[i
]->objects
[j
]->axis_name
);
669 Hkl3D
*hkl3d_new(const char *filename
, HklGeometry
*geometry
)
673 self
= HKL3D_MALLOC(Hkl3D
);
675 self
->geometry
= hkl3d_geometry_new(geometry
);
676 self
->config
= hkl3d_config_new();
677 self
->model
= g3d_model_new();
679 /* initialize the bullet part */
680 self
->_btCollisionConfiguration
= new btDefaultCollisionConfiguration();
682 #ifdef USE_PARALLEL_DISPATCHER
683 int maxNumOutstandingTasks
= 2;
684 PosixThreadSupport::ThreadConstructionInfo
constructionInfo("collision",
685 processCollisionTask
,
686 createCollisionLocalStoreMemory
,
687 maxNumOutstandingTasks
);
688 self
->_btThreadSupportInterface
= new PosixThreadSupport(constructionInfo
);
689 self
->_btDispatcher
= new SpuGatheringCollisionDispatcher(self
->_btThreadSupportInterface
,
690 maxNumOutstandingTasks
,
691 self
->_btCollisionConfiguration
);
693 self
->_btDispatcher
= new btCollisionDispatcher(self
->_btCollisionConfiguration
);
695 btGImpactCollisionAlgorithm::registerAlgorithm(self
->_btDispatcher
);
697 btVector3
worldAabbMin(-1000,-1000,-1000);
698 btVector3
worldAabbMax( 1000, 1000, 1000);
700 self
->_btBroadphase
= new btAxisSweep3(worldAabbMin
, worldAabbMax
);
702 self
->_btWorld
= new btCollisionWorld(self
->_btDispatcher
,
704 self
->_btCollisionConfiguration
);
706 self
->filename
= filename
;
708 hkl3d_load_config(self
, filename
);
713 void hkl3d_free(Hkl3D
*self
)
718 /* remove all objects from the collision world */
719 for(size_t i
=0; i
<self
->config
->len
; ++i
)
720 for(size_t j
=0; j
<self
->config
->models
[i
]->len
; ++j
)
721 if(self
->config
->models
[i
]->objects
[j
]->added
)
722 self
->_btWorld
->removeCollisionObject(self
->config
->models
[i
]->objects
[j
]->btObject
);
724 hkl3d_geometry_free(self
->geometry
);
725 hkl3d_config_free(self
->config
);
728 delete self
->_btWorld
;
729 if (self
->_btBroadphase
)
730 delete self
->_btBroadphase
;
731 if (self
->_btDispatcher
)
732 delete self
->_btDispatcher
;
733 #ifdef USE_PARALLEL_DISPATCHER
734 if (self
->_btThreadSupportInterface
){
735 /* delete _btThreadSupportInterface; */
736 /* _btThreadSupportInterface = 0; */
739 if (self
->_btCollisionConfiguration
)
740 delete self
->_btCollisionConfiguration
;
741 g_free(self
->model
); /* do not use g3d_model_free as it is juste a container for all config->model */
746 Hkl3DModel
*hkl3d_add_model_from_file(Hkl3D
*self
,
747 const char *filename
, const char *directory
)
750 Hkl3DModel
*model
= NULL
;
753 /* first set the current directory using the directory
754 * parameter. Maybe using openat should be a better solution
755 * in the hkl3d_model_new_from_file */
756 current
= open(".", O_RDONLY
);
759 res
= chdir(directory
);
763 model
= hkl3d_model_new_from_file(filename
);
765 /* we can not display two different models with the current g3dviewer code */
766 /* so concatenate this loaded model with the one of hkl3d */
767 self
->model
->objects
= g_slist_concat(self
->model
->objects
, model
->g3d
->objects
);
768 self
->model
->materials
= g_slist_concat(self
->model
->materials
, model
->g3d
->materials
);
770 /* update the Hkl3D internals from the model */
771 hkl3d_config_add_model(self
->config
, model
);
773 /* restore the current directory */
774 res
= fchdir(current
);
783 /* check that the axis name is really available in the Geometry */
784 /* if axis name not valid make the object static object->name = NULL */
785 /* ok so check if the axis was already connected or not */
786 /* if already connected check if it was a different axis do the job */
787 /* if not yet connected do the job */
788 /* fill movingCollisionObject and movingG3DObjects vectors for transformations */
789 void hkl3d_connect_object_to_axis(Hkl3D
*self
, Hkl3DObject
*object
, const char *name
)
791 Hkl3DAxis
*axis3d
= hkl3d_geometry_axis_get(self
->geometry
, name
);
792 if (!object
->movable
){
793 if(axis3d
){ /* static -> movable */
794 self
->_btWorld
->removeCollisionObject(object
->btObject
);
795 hkl3d_object_set_movable(object
, true);
796 self
->_btWorld
->addCollisionObject(object
->btObject
);
797 object
->added
= true;
798 hkl3d_axis_attach_object(axis3d
, object
);
801 if(!axis3d
){ /* movable -> static */
802 self
->_btWorld
->removeCollisionObject(object
->btObject
);
803 hkl3d_object_set_movable(object
, false);
804 self
->_btWorld
->addCollisionObject(object
->btObject
);
805 object
->added
= true;
806 }else{ /* movable -> movable */
807 if(strcmp(object
->axis_name
, name
)){ /* not the same axis */
808 hkl3d_axis_detach_object(object
->axis
, object
);
809 hkl3d_axis_attach_object(axis3d
, object
);
813 hkl3d_object_set_axis_name(object
, name
);
816 void hkl3d_load_config(Hkl3D
*self
, const char *filename
)
821 yaml_parser_t parser
;
822 yaml_event_t input_event
;
826 Hkl3DModel
*config
= NULL
;
828 /* Clear the objects. */
829 memset(&parser
, 0, sizeof(parser
));
830 memset(&input_event
, 0, sizeof(input_event
));
832 file
= fopen(filename
, "rb");
834 fprintf(stderr
, "Could not open the %s config file\n", filename
);
838 if (!yaml_parser_initialize(&parser
))
839 fprintf(stderr
, "Could not initialize the parser object\n");
840 yaml_parser_set_input_file(&parser
, file
);
842 /* compute the dirname of the config file as all model files */
843 /* will be relative to this directory */
844 dirc
= strdup(filename
);
848 /* Get the next event. */
849 yaml_parser_parse(&parser
, &input_event
);
851 /* Check if this is the stream end. */
852 if(input_event
.type
== YAML_STREAM_END_EVENT
)
854 if(input_event
.type
== YAML_DOCUMENT_START_EVENT
){
860 // SCALAR fileName key
862 yaml_event_delete(&input_event
);
863 yaml_parser_parse(&parser
, &input_event
);
866 /* the add form file method create a default Hkl3DModel and add it to the HKL3D */
867 /* we just need to update this config with the values from the configuration file */
868 config
= hkl3d_add_model_from_file(self
, (const char *)input_event
.data
.scalar
.value
, dir
);
870 // SCALAR objects key
874 yaml_event_delete(&input_event
);
875 yaml_parser_parse(&parser
, &input_event
);
879 if((input_event
.type
==YAML_MAPPING_START_EVENT
)&& config
){
885 yaml_event_delete(&input_event
);
886 yaml_parser_parse(&parser
, &input_event
);
889 /* get the object id */
890 config
->objects
[j
-1]->id
= atoi((const char *)input_event
.data
.scalar
.value
);
892 /* skip 2 more events */
896 yaml_event_delete(&input_event
);
897 yaml_parser_parse(&parser
, &input_event
);
900 /* get the name of the object from the config file */
901 hkl3d_object_set_axis_name(config
->objects
[j
-1], (const char *)input_event
.data
.scalar
.value
);
904 // SCALAR transformation key
907 yaml_event_delete(&input_event
);
908 yaml_parser_parse(&parser
, &input_event
);
911 /* get the 16 values of the transformation */
913 config
->objects
[j
-1]->transformation
[l
] = atof((const char *)input_event
.data
.scalar
.value
);
914 yaml_event_delete(&input_event
);
915 yaml_parser_parse(&parser
, &input_event
);
922 yaml_event_delete(&input_event
);
923 yaml_parser_parse(&parser
, &input_event
);
926 /* get the hide value */
927 config
->objects
[j
-1]->hide
= strcmp((const char *)input_event
.data
.scalar
.value
, "no");
928 config
->objects
[j
-1]->g3d
->hide
= config
->objects
[j
-1]->hide
;
930 yaml_event_delete(&input_event
);
934 yaml_parser_delete(&parser
);
937 /* now that everythings goes fine we can save the filename */
938 self
->filename
= filename
;
940 hkl3d_connect_all_axes(self
);
943 void hkl3d_save_config(Hkl3D
*self
, const char *filename
)
945 for(size_t i
=0; i
<self
->config
->len
; i
++){
947 int properties1
, key1
, value1
,seq0
;
950 yaml_emitter_t emitter
;
951 yaml_document_t output_document
;
952 yaml_event_t output_event
;
955 memset(&emitter
, 0, sizeof(emitter
));
956 memset(&output_document
, 0, sizeof(output_document
));
957 memset(&output_event
, 0, sizeof(output_event
));
959 if (!yaml_emitter_initialize(&emitter
))
960 fprintf(stderr
, "Could not inialize the emitter object\n");
962 /* Set the emitter parameters */
963 file
= fopen(filename
, "a+");
965 fprintf(stderr
, "Could not open the config file %s to save\n", filename
);
968 yaml_emitter_set_output_file(&emitter
, file
);
969 yaml_emitter_open(&emitter
);
971 /* Create an output_document object */
972 if (!yaml_document_initialize(&output_document
, NULL
, NULL
, NULL
, 0, 0))
973 fprintf(stderr
, "Could not create a output_document object\n");
975 /* Create the root of the config file */
977 root
= yaml_document_add_sequence(&output_document
,
978 (yaml_char_t
*)ctime(&now
),
979 YAML_BLOCK_SEQUENCE_STYLE
);
981 /* create the property of the root sequence */
982 properties1
= yaml_document_add_mapping(&output_document
,
983 (yaml_char_t
*)YAML_MAP_TAG
,
984 YAML_BLOCK_MAPPING_STYLE
);
986 yaml_document_append_sequence_item(&output_document
, root
, properties1
);
988 /* add the map key1 : value1 to the property */
989 key1
= yaml_document_add_scalar(&output_document
,
991 (yaml_char_t
*)"FileName",
993 YAML_PLAIN_SCALAR_STYLE
);
994 value1
= yaml_document_add_scalar(&output_document
,
996 (yaml_char_t
*)self
->config
->models
[i
]->filename
,
998 YAML_PLAIN_SCALAR_STYLE
);
999 yaml_document_append_mapping_pair(&output_document
, properties1
, key1
, value1
);
1001 /* add the map key1 : seq0 to the first property */
1002 key1
= yaml_document_add_scalar(&output_document
,
1004 (yaml_char_t
*)"Objects",
1006 YAML_PLAIN_SCALAR_STYLE
);
1007 /* create the sequence of objects */
1008 seq0
= yaml_document_add_sequence(&output_document
,
1009 (yaml_char_t
*)YAML_SEQ_TAG
,
1010 YAML_BLOCK_SEQUENCE_STYLE
);
1011 for(size_t j
=0; j
<self
->config
->models
[i
]->len
; j
++){
1018 properties
= yaml_document_add_mapping(&output_document
,
1019 (yaml_char_t
*)YAML_MAP_TAG
,
1020 YAML_BLOCK_MAPPING_STYLE
);
1021 yaml_document_append_sequence_item(&output_document
,seq0
, properties
);
1023 key
= yaml_document_add_scalar(&output_document
,
1025 (yaml_char_t
*)"Id", -1,
1026 YAML_PLAIN_SCALAR_STYLE
);
1028 sprintf(number
, "%d", self
->config
->models
[i
]->objects
[j
]->id
);
1029 value
= yaml_document_add_scalar(&output_document
,
1031 (yaml_char_t
*)number
,
1033 YAML_PLAIN_SCALAR_STYLE
);
1034 yaml_document_append_mapping_pair(&output_document
,properties
,key
,value
);
1036 key
= yaml_document_add_scalar(&output_document
,
1038 (yaml_char_t
*)"Name",
1040 YAML_PLAIN_SCALAR_STYLE
);
1041 value
= yaml_document_add_scalar(&output_document
,
1043 (yaml_char_t
*)self
->config
->models
[i
]->objects
[j
]->axis_name
,
1045 YAML_PLAIN_SCALAR_STYLE
);
1046 yaml_document_append_mapping_pair(&output_document
,properties
,key
,value
);
1048 key
= yaml_document_add_scalar(&output_document
,
1050 (yaml_char_t
*)"Transformation",
1052 YAML_PLAIN_SCALAR_STYLE
);
1053 seq1
= yaml_document_add_sequence(&output_document
,
1054 (yaml_char_t
*)YAML_SEQ_TAG
,
1055 YAML_FLOW_SEQUENCE_STYLE
);
1056 yaml_document_append_mapping_pair(&output_document
,properties
, key
, seq1
);
1057 for(k
=0; k
<16; k
++){
1058 sprintf(number
, "%f", self
->config
->models
[i
]->objects
[j
]->transformation
[k
]);
1059 value
= yaml_document_add_scalar(&output_document
,
1061 (yaml_char_t
*)number
,
1063 YAML_PLAIN_SCALAR_STYLE
);
1064 yaml_document_append_sequence_item(&output_document
,seq1
,value
);
1067 key
= yaml_document_add_scalar(&output_document
,
1069 (yaml_char_t
*)"Hide",
1071 YAML_PLAIN_SCALAR_STYLE
);
1072 if(self
->config
->models
[i
]->objects
[j
]->hide
)
1073 value
= yaml_document_add_scalar(&output_document
,
1075 (yaml_char_t
*)"yes",
1077 YAML_PLAIN_SCALAR_STYLE
);
1079 value
= yaml_document_add_scalar(&output_document
,
1081 (yaml_char_t
*)"no",
1083 YAML_PLAIN_SCALAR_STYLE
);
1084 yaml_document_append_mapping_pair(&output_document
,properties
,key
,value
);
1086 yaml_document_append_mapping_pair(&output_document
, properties1
, key1
, seq0
);
1088 /* flush the document */
1089 yaml_emitter_dump(&emitter
, &output_document
);
1092 yaml_document_delete(&output_document
);
1093 yaml_emitter_delete(&emitter
);
1098 * Hkl3D::hide_object:
1100 * update the visibility of an Hkl3DObject in the bullet world
1101 * add or remove the object from the _btWorld depending on the hide
1102 * member of the object.
1104 void hkl3d_hide_object(Hkl3D
*self
, Hkl3DObject
*object
, int hide
)
1106 /* first update the G3DObject */
1107 object
->hide
= hide
;
1108 object
->g3d
->hide
= hide
;
1111 self
->_btWorld
->removeCollisionObject(object
->btObject
);
1112 object
->added
= false;
1116 self
->_btWorld
->addCollisionObject(object
->btObject
);
1117 object
->added
= true;
1122 /* remove an object from the model */
1123 void hkl3d_remove_object(Hkl3D
*self
, Hkl3DObject
*object
)
1125 if(!self
|| !object
)
1128 hkl3d_hide_object(self
, object
, TRUE
);
1129 hkl3d_axis_detach_object(object
->axis
, object
);
1131 /* now remove the G3DObject from the model */
1132 self
->model
->objects
= g_slist_remove(self
->model
->objects
, object
->g3d
);
1133 hkl3d_model_delete_object(object
->model
, object
);
1136 /* use for the transparency of colliding objects */
1137 struct ContactSensorCallback
: public btCollisionWorld::ContactResultCallback
1139 ContactSensorCallback(Hkl3DObject
*object
)
1140 : btCollisionWorld::ContactResultCallback(),
1141 collisionObject(object
->btObject
),
1145 btCollisionObject
*collisionObject
;
1146 Hkl3DObject
*object
;
1148 virtual btScalar
addSingleResult(btManifoldPoint
& cp
,
1149 const btCollisionObjectWrapper
*colObj0
, int partId0
, int index0
,
1150 const btCollisionObjectWrapper
*colObj1
, int partId1
, int index1
)
1152 if(colObj0
->m_collisionObject
== collisionObject
1153 || colObj1
->m_collisionObject
== collisionObject
)
1154 object
->is_colliding
= TRUE
;
1159 int hkl3d_is_colliding(Hkl3D
*self
)
1162 struct timeval debut
, fin
;
1164 /* apply geometry transformation */
1165 hkl3d_apply_transformations(self
);
1167 /* perform the collision detection and get numbers */
1168 gettimeofday(&debut
, NULL
);
1170 self
->_btWorld
->performDiscreteCollisionDetection();
1171 self
->_btWorld
->updateAabbs();
1173 gettimeofday(&fin
, NULL
);
1174 timersub(&fin
, &debut
, &self
->stats
.collision
);
1176 numManifolds
= self
->_btWorld
->getDispatcher()->getNumManifolds();
1178 /* reset all the collisions */
1179 for(size_t i
=0; i
<self
->config
->len
; i
++)
1180 for(size_t j
=0; j
<self
->config
->models
[i
]->len
; j
++)
1181 self
->config
->models
[i
]->objects
[j
]->is_colliding
= FALSE
;
1183 /* check all the collisions */
1184 for(size_t i
=0; i
<self
->config
->len
; i
++)
1185 for(size_t j
=0; j
<self
->config
->models
[i
]->len
; j
++){
1186 Hkl3DObject
*object
= self
->config
->models
[i
]->objects
[j
];
1187 ContactSensorCallback
callback(object
);
1188 self
->_btWorld
->contactTest(object
->btObject
, callback
);
1191 return numManifolds
!= 0;
1195 * Hkl3D::get_bounding_boxes:
1199 * get the bounding boxes of the current world from the bullet internals.
1201 void hkl3d_get_bounding_boxes(Hkl3D
*self
,
1202 struct btVector3
*min
, struct btVector3
*max
)
1204 self
->_btWorld
->getBroadphase()->getBroadphaseAabb(*min
, *max
);
1207 int hkl3d_get_nb_manifolds(Hkl3D
*self
)
1209 return self
->_btDispatcher
->getNumManifolds();
1212 int hkl3d_get_nb_contacts(Hkl3D
*self
, int manifold
)
1214 return self
->_btDispatcher
->getManifoldByIndexInternal(manifold
)->getNumContacts();
1217 void hkl3d_get_collision_coordinates(Hkl3D
*self
, int manifold
, int contact
,
1218 double *xa
, double *ya
, double *za
,
1219 double *xb
, double *yb
, double *zb
)
1221 btPersistentManifold
*contactManifold
;
1223 contactManifold
= self
->_btDispatcher
->getManifoldByIndexInternal(manifold
);
1224 btManifoldPoint
& pt
= contactManifold
->getContactPoint(contact
);
1225 btVector3 ptA
= pt
.getPositionWorldOnA();
1226 btVector3 ptB
= pt
.getPositionWorldOnB();
1236 void hkl3d_fprintf(FILE *f
, const Hkl3D
*self
)
1239 fprintf(f
, "filename : %s\n", self
->filename
);
1240 hkl3d_geometry_fprintf(f
, self
->geometry
);
1242 fprintf(f
, "model : %p\n", self
->model
);
1243 hkl3d_stats_fprintf(f
, &self
->stats
);
1244 hkl3d_config_fprintf(f
, self
->config
);
1246 fprintf(f
, "_btCollisionConfiguration : %p\n", self
->_btCollisionConfiguration
);
1247 fprintf(f
, "_btBroadphase : %p\n", self
->_btBroadphase
);
1248 fprintf(f
, "_btWorld : %p\n", self
->_btWorld
);
1249 fprintf(f
, "_btDispatcher : %p\n", self
->_btDispatcher
);
1250 #ifdef USE_PARALLEL_DISPATCHER
1251 fprintf(f
, "_btThreadSupportInterface : %p\n", self
->_btThreadSupportInterface
);