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>
35 #include "btBulletCollisionCommon.h"
36 #include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h"
37 #include "BulletCollision/Gimpact/btGImpactShape.h"
39 #ifdef USE_PARALLEL_DISPATCHER
40 # include "BulletMultiThreaded/SpuGatheringCollisionDispatcher.h"
41 # include "BulletMultiThreaded/PlatformDefinitions.h"
42 # include "BulletMultiThreaded/PosixThreadSupport.h"
43 # include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h"
50 static float identity
[] = {1, 0, 0, 0,
59 static btTriangleMesh
*trimesh_from_g3dobject(G3DObject
*object
)
61 btTriangleMesh
*trimesh
;
65 trimesh
= new btTriangleMesh();
66 trimesh
->preallocateVertices(object
->vertex_count
);
67 faces
= object
->faces
;
68 vertex
= object
->vertex_data
;
72 face
= (G3DFace
*)faces
->data
;
73 btVector3
vertex0(vertex
[3*(face
->vertex_indices
[0])],
74 vertex
[3*(face
->vertex_indices
[0])+1],
75 vertex
[3*(face
->vertex_indices
[0])+2]);
76 btVector3
vertex1(vertex
[3*(face
->vertex_indices
[1])],
77 vertex
[3*(face
->vertex_indices
[1])+1],
78 vertex
[3*(face
->vertex_indices
[1])+2]);
79 btVector3
vertex2(vertex
[3*(face
->vertex_indices
[2])],
80 vertex
[3*(face
->vertex_indices
[2])+1],
81 vertex
[3*(face
->vertex_indices
[2])+2]);
82 trimesh
->addTriangle(vertex0
, vertex1
, vertex2
, true);
84 faces
= g_slist_next(faces
);
90 static btCollisionShape
* shape_from_trimesh(btTriangleMesh
*trimesh
, int movable
)
92 btCollisionShape
* shape
;
95 * create the bullet shape depending on the static status or not of the piece
96 * static : do not move
97 * movable : connected to a HklGeometry axis.
100 shape
= dynamic_cast<btGImpactMeshShape
*>(new btGImpactMeshShape(trimesh
));
101 shape
->setMargin(btScalar(0));
102 shape
->setLocalScaling(btVector3(1,1,1));
103 /* maybe usefull for softbodies (useless for now) */
104 (dynamic_cast<btGImpactMeshShape
*>(shape
))->postUpdate();
105 /* needed for the collision and must be call after the postUpdate (doc) */
106 (dynamic_cast<btGImpactMeshShape
*>(shape
))->updateBound();
108 shape
= dynamic_cast<btBvhTriangleMeshShape
*>(new btBvhTriangleMeshShape (trimesh
, true));
109 shape
->setMargin(btScalar(0));
110 shape
->setLocalScaling(btVector3(1,1,1));
116 static btCollisionObject
* btObject_from_shape(btCollisionShape
* shape
)
118 btCollisionObject
*btObject
;
120 /* create the Object and add the shape */
121 btObject
= new btCollisionObject();
122 btObject
->setCollisionShape(shape
);
123 btObject
->activate(true);
129 static struct Hkl3DObject
*hkl3d_object_new(G3DObject
*object
, int id
, const char* filename
)
133 G3DMaterial
* material
;
134 struct Hkl3DObject
*self
= NULL
;
136 self
= HKL_MALLOC(Hkl3DObject
);
138 // extract the color from the first face
139 faces
= object
->faces
;
140 material
= ((G3DFace
*)faces
->data
)->material
;
142 // fill the hkl3d object structure.
144 self
->axis_name
= strdup(object
->name
);
145 self
->g3dObject
= object
;
146 self
->meshes
= trimesh_from_g3dobject(object
);
147 self
->btShape
= shape_from_trimesh(self
->meshes
, false);
148 self
->btObject
= btObject_from_shape(self
->btShape
);
149 self
->color
= new btVector3(material
->r
, material
->g
, material
->b
);
150 self
->hide
= object
->hide
;
152 self
->selected
= false;
153 self
->movable
= false;
154 self
->filename
= filename
;
157 * if the object already contain a transformation set the Hkl3DObject
158 * transformation with this transformation. Otherwise set it with the
161 if(object
->transformation
){
163 self
->transformation
[i
] = object
->transformation
->matrix
[i
];
165 /* create one as we requiered it to apply our transformations */
166 object
->transformation
= g_new0(G3DTransformation
, 1);
168 self
->transformation
[i
] = identity
[i
];
169 object
->transformation
->matrix
[i
] = identity
[i
];
173 self
->is_colliding
= false;
178 static void hkl3d_object_free(struct Hkl3DObject
*self
)
184 free(self
->axis_name
);
185 self
->axis_name
= NULL
;
192 delete self
->btShape
;
193 self
->btShape
= NULL
;
196 delete self
->btObject
;
197 self
->btObject
= NULL
;
203 /* memory leak in libg3d */
204 if(self
->g3dObject
&& self
->g3dObject
->transformation
){
205 g_free(self
->g3dObject
->transformation
);
206 self
->g3dObject
->transformation
= NULL
;
212 /* return 0 if identical 1 if not */
213 static int hkl3d_object_cmp(struct Hkl3DObject
*object1
,
214 struct Hkl3DObject
*object2
)
216 if((!strcmp(object1
->filename
, object2
->filename
))
217 && (object1
->id
== object2
->id
))
223 static void hkl3d_object_set_axis_name(struct Hkl3DObject
*self
, const char *name
)
225 if(!self
|| !name
|| self
->axis_name
== name
)
229 free(self
->axis_name
);
230 self
->axis_name
= strdup(name
);
233 void hkl3d_object_fprintf(FILE *f
, const struct Hkl3DObject
*self
)
236 G3DMaterial
* material
;
238 faces
= self
->g3dObject
->faces
;
239 material
= ((G3DFace
*)faces
->data
)->material
;
240 fprintf(f
, "id : %d\n", self
->id
);
241 fprintf(f
, "name : %s (%p)\n", self
->axis_name
, self
->axis_name
);
242 fprintf(f
, "btObject : %p\n", self
->btObject
);
243 fprintf(f
, "g3dObject : %p\n", self
->g3dObject
);
244 fprintf(f
, "btShape : %p\n", self
->btShape
);
245 fprintf(f
, "meshes : %p\n", self
->meshes
);
246 fprintf(f
, "color : %f, %f, %f\n", material
->r
, material
->g
, material
->b
);
247 fprintf(f
, "is_colliding : %d\n", self
->is_colliding
);
248 fprintf(f
, "hide : %d\n", self
->hide
);
249 fprintf(f
, "added : %d\n", self
->added
);
250 fprintf(f
, "selected : %d\n", self
->selected
);
257 static struct Hkl3DConfig
*hkl_config_new(void)
259 struct Hkl3DConfig
*self
= NULL
;
261 self
= HKL_MALLOC(Hkl3DConfig
);
263 self
->objects
= NULL
;
269 static void hkl3d_config_add_object(struct Hkl3DConfig
*self
, struct Hkl3DObject
*object
)
274 self
->objects
= (typeof(self
->objects
))realloc(self
->objects
, sizeof(*self
->objects
) * (self
->len
+ 1));
275 self
->objects
[self
->len
++] = object
;
279 * hkl3d_config_release:
283 * release the memory of an Hkl3dConfig. It also detach all btObjects from the btCollisionWorld
285 static void hkl3d_config_release(struct Hkl3DConfig
*config
, btCollisionWorld
*btWorld
)
289 free(config
->filename
);
290 for(i
=0; i
<config
->len
; ++i
){
291 btWorld
->removeCollisionObject(config
->objects
[i
]->btObject
);
292 hkl3d_object_free(config
->objects
[i
]);
294 free(config
->objects
);
295 config
->objects
= NULL
;
299 void hkl3d_config_fprintf(FILE *f
, const struct Hkl3DConfig
*self
)
302 fprintf(f
, "config (%d):\n", self
->len
);
303 for(i
=0; i
<self
->len
; ++i
)
304 hkl3d_object_fprintf(f
, self
->objects
[i
]);
311 static struct Hkl3DConfigs
* hkl3d_configs_new(void)
313 struct Hkl3DConfigs
* self
= NULL
;
315 self
= (struct Hkl3DConfigs
*)malloc(sizeof(struct Hkl3DConfigs
));
319 self
->configs
= NULL
;
325 static void hkl3d_configs_free(struct Hkl3DConfigs
*self
)
333 static void hkl3d_configs_release(struct Hkl3DConfigs
*self
, btCollisionWorld
*_btWorld
)
337 for(i
=0; i
<self
->len
; ++i
)
338 hkl3d_config_release(self
->configs
[i
], _btWorld
);
341 static struct Hkl3DConfig
* hkl3d_configs_get_last(struct Hkl3DConfigs
*self
)
343 return self
->configs
[self
->len
- 1];
347 static void hkl3d_configs_add_config(struct Hkl3DConfigs
*self
, struct Hkl3DConfig
*config
)
349 self
->configs
= (typeof(self
->configs
))realloc(self
->configs
, sizeof(*self
->configs
) * (self
->len
+ 1));
350 self
->configs
[self
->len
++] = config
;
353 void hkl3d_configs_fprintf(FILE *f
, const struct Hkl3DConfigs
*self
)
356 fprintf(f
, "configs (%d):\n", self
->len
);
357 for(i
=0; i
<self
->len
; ++i
)
358 hkl3d_config_fprintf(f
, self
->configs
[i
]);
365 double hkl3d_stats_get_collision_ms(const struct Hkl3DStats
*self
)
367 return self
->collision
.tv_sec
*1000. + self
->collision
.tv_usec
/1000.;
370 void hkl3d_stats_fprintf(FILE *f
, const struct Hkl3DStats
*self
)
372 fprintf(f
, "transformation : %f ms collision : %f ms \n",
373 self
->transformation
.tv_sec
*1000. + self
->transformation
.tv_usec
/1000.,
374 hkl3d_stats_get_collision_ms(self
));
381 static struct Hkl3DAxis
*hkl3d_axis_new(void)
383 struct Hkl3DAxis
*self
= NULL
;
385 self
= HKL_MALLOC(Hkl3DAxis
);
387 self
->objects
= NULL
;
393 static void hkl3d_axis_free(struct Hkl3DAxis
*self
)
402 /* should be optimized (useless if the Hkl3DObject had a connection with the Hkl3DAxis */
403 static void hkl3d_axis_attach_object(struct Hkl3DAxis
*self
, struct Hkl3DObject
*object
)
405 self
->objects
= (Hkl3DObject
**)realloc(self
->objects
, sizeof(*self
->objects
) * (self
->len
+ 1));
406 self
->objects
[self
->len
++] = object
;
409 /* should be optimized (useless if the Hkl3DObject had a connection with the Hkl3DAxis */
410 static void hkl3d_axis_detach_object(struct Hkl3DAxis
*self
, struct Hkl3DObject
*object
)
414 for(i
=0; i
<self
->len
; ++i
)
415 if(!hkl3d_object_cmp(self
->objects
[i
], object
)){
417 /* move all above objects of 1 position */
419 memmove(&self
->objects
[i
], &self
->objects
[i
+1], sizeof(*self
->objects
) * (self
->len
- i
));
427 static struct Hkl3DGeometry
*hkl3d_geometry_new(int n
)
430 struct Hkl3DGeometry
*self
= NULL
;
432 self
= HKL_MALLOC(Hkl3DGeometry
);
434 self
->axes
= (Hkl3DAxis
**)malloc(n
* sizeof(*self
->axes
));
438 self
->axes
[i
] = hkl3d_axis_new();
443 static void hkl3d_geometry_free(struct Hkl3DGeometry
*self
)
451 for(i
=0; i
<self
->len
; ++i
)
452 hkl3d_axis_free(self
->axes
[i
]);
464 * Initialize the bullet collision environment.
465 * create the Hkl3DObjects
466 * create the Hkl3DConfigs
468 static void hkl3d_init_internals(struct Hkl3D
*self
, G3DModel
*model
, const char *filename
)
470 struct Hkl3DConfig
*config
;
471 GSList
*objects
; // lets iterate from the first object.
473 if(!self
|| !model
|| !filename
)
476 config
= hkl_config_new();
477 objects
= model
->objects
;
481 object
= (G3DObject
*)objects
->data
;
482 if(object
->vertex_count
){
484 struct Hkl3DObject
*hkl3dObject
;
486 id
= g_slist_index(model
->objects
, object
);
487 hkl3dObject
= hkl3d_object_new(object
, id
, filename
);
489 // insert collision Object in collision world
490 self
->_btWorld
->addCollisionObject(hkl3dObject
->btObject
);
491 hkl3dObject
->added
= true;
493 // remembers objects to avoid memory leak
494 hkl3d_config_add_object(config
, hkl3dObject
);
496 objects
= g_slist_next(objects
);
499 config
->filename
= strdup(filename
);
500 hkl3d_configs_add_config(self
->configs
, config
);
503 static void hkl3d_apply_transformations(struct Hkl3D
*self
)
507 struct timeval debut
, fin
;
509 // set the right transformation of each objects and get numbers
510 gettimeofday(&debut
, NULL
);
511 for(i
=0; i
<self
->geometry
->holders_len
; i
++){
513 btQuaternion
btQ(0, 0, 0, 1);
515 size_t len
= self
->geometry
->holders
[i
].config
->len
;
516 for(j
=0; j
<len
; j
++){
518 size_t idx
= self
->geometry
->holders
[i
].config
->idx
[j
];
519 HklAxis
*axis
= &self
->geometry
->axes
[idx
];
522 // conversion beetween hkl -> bullet coordinates
523 btQ
*= btQuaternion(-axis
->q
.data
[1],
528 // move each object connected to that hkl Axis.
529 for(k
=0; k
<self
->movingObjects
->axes
[idx
]->len
; ++k
){
530 self
->movingObjects
->axes
[idx
]->objects
[k
]->btObject
->getWorldTransform().setRotation(btQ
);
531 self
->movingObjects
->axes
[idx
]->objects
[k
]->btObject
->getWorldTransform().getOpenGLMatrix( G3DM
);
532 memcpy(self
->movingObjects
->axes
[idx
]->objects
[k
]->g3dObject
->transformation
->matrix
, &G3DM
[0], sizeof(G3DM
));
537 gettimeofday(&fin
, NULL
);
538 timersub(&fin
, &debut
, &self
->stats
.transformation
);
541 void hkl3d_connect_all_axes(struct Hkl3D
*self
)
546 /* connect use the axes names */
547 for(i
=0;i
<self
->configs
->len
;i
++)
548 for(j
=0;j
<self
->configs
->configs
[i
]->len
;j
++)
549 hkl3d_connect_object_to_axis(self
,
550 self
->configs
->configs
[i
]->objects
[j
],
551 self
->configs
->configs
[i
]->objects
[j
]->axis_name
);
563 struct Hkl3D
*hkl3d_new(const char *filename
, HklGeometry
*geometry
)
565 struct Hkl3D
*self
= NULL
;
567 self
= HKL_MALLOC(Hkl3D
);
569 self
->geometry
= geometry
;
570 self
->configs
= hkl3d_configs_new();
571 self
->movingObjects
= hkl3d_geometry_new(geometry
->len
);
573 // first initialize the _movingObjects with the right len.
574 self
->_context
= g3d_context_new();
575 self
->model
= g3d_model_new();
577 // initialize the bullet part
578 self
->_btCollisionConfiguration
= new btDefaultCollisionConfiguration();
580 #ifdef USE_PARALLEL_DISPATCHER
581 int maxNumOutstandingTasks
= 2;
582 PosixThreadSupport::ThreadConstructionInfo
constructionInfo("collision",
583 processCollisionTask
,
584 createCollisionLocalStoreMemory
,
585 maxNumOutstandingTasks
);
586 self
->_btThreadSupportInterface
= new PosixThreadSupport(constructionInfo
);
587 self
->_btDispatcher
= new SpuGatheringCollisionDispatcher(self
->_btThreadSupportInterface
,
588 maxNumOutstandingTasks
,
589 self
->_btCollisionConfiguration
);
591 self
->_btDispatcher
= new btCollisionDispatcher(self
->_btCollisionConfiguration
);
593 btGImpactCollisionAlgorithm::registerAlgorithm(self
->_btDispatcher
);
595 btVector3
worldAabbMin(-1000,-1000,-1000);
596 btVector3
worldAabbMax( 1000, 1000, 1000);
598 self
->_btBroadphase
= new btAxisSweep3(worldAabbMin
, worldAabbMax
);
600 self
->_btWorld
= new btCollisionWorld(self
->_btDispatcher
,
602 self
->_btCollisionConfiguration
);
604 self
->filename
= filename
;
606 hkl3d_load_config(self
, filename
);
611 void hkl3d_free(struct Hkl3D
*self
)
619 // _remove objects from the collision world and delete all objects and shapes
620 hkl3d_configs_release(self
->configs
, self
->_btWorld
);
621 hkl3d_configs_free(self
->configs
);
622 hkl3d_geometry_free(self
->movingObjects
);
625 delete self
->_btWorld
;
626 if (self
->_btBroadphase
)
627 delete self
->_btBroadphase
;
628 if (self
->_btDispatcher
)
629 delete self
->_btDispatcher
;
630 #ifdef USE_PARALLEL_DISPATCHER
631 if (self
->_btThreadSupportInterface
){
632 //delete _btThreadSupportInterface;
633 //_btThreadSupportInterface = 0;
636 if (self
->_btCollisionConfiguration
)
637 delete self
->_btCollisionConfiguration
;
638 g3d_model_free(self
->model
);
639 g3d_context_free(self
->_context
);
644 struct Hkl3DConfig
*hkl3d_add_model_from_file(struct Hkl3D
*self
,
645 const char *filename
, const char *directory
)
649 G3DMaterial
*material
;
650 char current
[PATH_MAX
];
651 struct Hkl3DConfig
*config
= NULL
;
654 /* first set the current directory using the directory parameter*/
655 getcwd(current
, PATH_MAX
);
656 res
= chdir(directory
);
657 model
= g3d_model_load_full(self
->_context
, filename
, 0);
658 res
= chdir(current
);
661 /* concatenate the added Model with the one from Hkl3D */
662 self
->model
->objects
= g_slist_concat(self
->model
->objects
, model
->objects
);
663 self
->model
->materials
= g_slist_concat(self
->model
->materials
, model
->materials
);
665 /* update the Hkl3D internals from the model */
666 hkl3d_init_internals(self
, model
, filename
);
668 /* if resp == true there is a problem in the diffractometer model. */
669 config
= hkl3d_configs_get_last(self
->configs
);
674 /* check that the axis name is really available in the Geometry */
675 /* if axis name not valid make the object static object->name = NULL */
676 /* ok so check if the axis was already connected or not */
677 /* if already connected check if it was a different axis do the job */
678 /* if not yet connected do the job */
679 /* fill movingCollisionObject and movingG3DObjects vectors for transformations */
680 void hkl3d_connect_object_to_axis(struct Hkl3D
*self
,
681 struct Hkl3DObject
*object
, const char *name
)
684 bool connect
= false;
685 int idx
= hkl_geometry_get_axis_idx_by_name(self
->geometry
, name
);
686 if (!object
->movable
){
687 if(idx
>= 0){ /* static -> movable */
690 object
->movable
= true;
693 if(idx
< 0){ /* movable -> static */
694 object
->movable
= false;
697 }else{ /* movable -> movable */
698 if(strcmp(object
->axis_name
, name
)){ /* not the same axis */
701 int i
= hkl_geometry_get_axis_idx_by_name(self
->geometry
, object
->axis_name
);
702 struct Hkl3DObject
**objects
;
704 for(int k
=0;k
<self
->movingObjects
->axes
[i
]->len
;k
++){
705 objects
= self
->movingObjects
->axes
[i
]->objects
;
706 if(!hkl3d_object_cmp(objects
[k
], object
)){
707 hkl3d_axis_detach_object(self
->movingObjects
->axes
[i
], object
);
714 hkl3d_object_set_axis_name(object
, name
);
716 /* first deconnected if already connected with a different axis */
717 self
->_btWorld
->removeCollisionObject(object
->btObject
);
718 delete object
->btObject
;
719 delete object
->btShape
;
720 object
->btShape
= shape_from_trimesh(object
->meshes
, object
->movable
);
721 object
->btObject
= btObject_from_shape(object
->btShape
);
722 // insert collision Object in collision world
723 self
->_btWorld
->addCollisionObject(object
->btObject
);
724 object
->added
= true;
727 hkl3d_axis_attach_object(self
->movingObjects
->axes
[idx
], object
);
730 void hkl3d_load_config(struct Hkl3D
*self
, const char *filename
)
735 yaml_parser_t parser
;
736 yaml_event_t input_event
;
740 struct Hkl3DConfig
*config
;
742 /* Clear the objects. */
743 memset(&parser
, 0, sizeof(parser
));
744 memset(&input_event
, 0, sizeof(input_event
));
746 file
= fopen(filename
, "rb");
748 fprintf(stderr
, "Could not open the %s config file\n", filename
);
752 if (!yaml_parser_initialize(&parser
))
753 fprintf(stderr
, "Could not initialize the parser object\n");
754 yaml_parser_set_input_file(&parser
, file
);
757 * compute the dirname of the config file as all model files
758 * will be relative to this directory
760 dirc
= strdup(filename
);
764 /* Get the next event. */
765 yaml_parser_parse(&parser
, &input_event
);
767 /* Check if this is the stream end. */
768 if(input_event
.type
== YAML_STREAM_END_EVENT
)
770 if(input_event
.type
== YAML_DOCUMENT_START_EVENT
){
776 // SCALAR fileName key
778 yaml_event_delete(&input_event
);
779 yaml_parser_parse(&parser
, &input_event
);
782 /* the add form file method create a default Hkl3DConfig and add it to the HKL3D */
783 /* we just need to update this config with the values from the configuration file */
784 config
= hkl3d_add_model_from_file(self
, (const char *)input_event
.data
.scalar
.value
, dir
);
786 // SCALAR objects key
790 yaml_event_delete(&input_event
);
791 yaml_parser_parse(&parser
, &input_event
);
795 if((input_event
.type
==YAML_MAPPING_START_EVENT
)&& config
){
801 yaml_event_delete(&input_event
);
802 yaml_parser_parse(&parser
, &input_event
);
805 /* get the object id */
806 config
->objects
[j
-1]->id
= atoi((const char *)input_event
.data
.scalar
.value
);
808 /* skip 2 more events */
812 yaml_event_delete(&input_event
);
813 yaml_parser_parse(&parser
, &input_event
);
816 /* get the name of the object from the config file */
817 hkl3d_object_set_axis_name(config
->objects
[j
-1], (const char *)input_event
.data
.scalar
.value
);
820 // SCALAR transformation key
823 yaml_event_delete(&input_event
);
824 yaml_parser_parse(&parser
, &input_event
);
827 /* get the 16 values of the transformation */
829 config
->objects
[j
-1]->transformation
[l
] = atof((const char *)input_event
.data
.scalar
.value
);
830 yaml_event_delete(&input_event
);
831 yaml_parser_parse(&parser
, &input_event
);
838 yaml_event_delete(&input_event
);
839 yaml_parser_parse(&parser
, &input_event
);
842 /* get the hide value */
843 config
->objects
[j
-1]->hide
= strcmp((const char *)input_event
.data
.scalar
.value
, "no");
844 config
->objects
[j
-1]->g3dObject
->hide
= config
->objects
[j
-1]->hide
;
846 yaml_event_delete(&input_event
);
850 yaml_parser_delete(&parser
);
853 /* now that everythings goes fine we can save the filename */
854 self
->filename
= filename
;
856 hkl3d_connect_all_axes(self
);
859 void hkl3d_save_config(struct Hkl3D
*self
, const char *filename
)
863 for(i
=0; i
<self
->configs
->len
; i
++){
866 int properties1
, key1
, value1
,seq0
;
869 yaml_emitter_t emitter
;
870 yaml_document_t output_document
;
871 yaml_event_t output_event
;
874 memset(&emitter
, 0, sizeof(emitter
));
875 memset(&output_document
, 0, sizeof(output_document
));
876 memset(&output_event
, 0, sizeof(output_event
));
878 if (!yaml_emitter_initialize(&emitter
))
879 fprintf(stderr
, "Could not inialize the emitter object\n");
881 /* Set the emitter parameters */
882 file
= fopen(filename
, "a+");
884 fprintf(stderr
, "Could not open the config file %s to save\n", filename
);
887 yaml_emitter_set_output_file(&emitter
, file
);
888 yaml_emitter_open(&emitter
);
890 /* Create an output_document object */
891 if (!yaml_document_initialize(&output_document
, NULL
, NULL
, NULL
, 0, 0))
892 fprintf(stderr
, "Could not create a output_document object\n");
894 /* Create the root of the config file */
896 root
= yaml_document_add_sequence(&output_document
,
897 (yaml_char_t
*)ctime(&now
),
898 YAML_BLOCK_SEQUENCE_STYLE
);
900 /* create the property of the root sequence */
901 properties1
= yaml_document_add_mapping(&output_document
,
902 (yaml_char_t
*)YAML_MAP_TAG
,
903 YAML_BLOCK_MAPPING_STYLE
);
905 yaml_document_append_sequence_item(&output_document
, root
, properties1
);
907 /* add the map key1 : value1 to the property */
908 key1
= yaml_document_add_scalar(&output_document
,
910 (yaml_char_t
*)"FileName",
912 YAML_PLAIN_SCALAR_STYLE
);
913 value1
= yaml_document_add_scalar(&output_document
,
915 (yaml_char_t
*)self
->configs
->configs
[i
]->filename
,
917 YAML_PLAIN_SCALAR_STYLE
);
918 yaml_document_append_mapping_pair(&output_document
, properties1
, key1
, value1
);
920 /* add the map key1 : seq0 to the first property */
921 key1
= yaml_document_add_scalar(&output_document
,
923 (yaml_char_t
*)"Objects",
925 YAML_PLAIN_SCALAR_STYLE
);
926 /* create the sequence of objects */
927 seq0
= yaml_document_add_sequence(&output_document
,
928 (yaml_char_t
*)YAML_SEQ_TAG
,
929 YAML_BLOCK_SEQUENCE_STYLE
);
930 for(j
=0; j
<self
->configs
->configs
[i
]->len
; j
++){
937 properties
= yaml_document_add_mapping(&output_document
,
938 (yaml_char_t
*)YAML_MAP_TAG
,
939 YAML_BLOCK_MAPPING_STYLE
);
940 yaml_document_append_sequence_item(&output_document
,seq0
, properties
);
942 key
= yaml_document_add_scalar(&output_document
,
944 (yaml_char_t
*)"Id", -1,
945 YAML_PLAIN_SCALAR_STYLE
);
947 sprintf(number
, "%d", self
->configs
->configs
[i
]->objects
[j
]->id
);
948 value
= yaml_document_add_scalar(&output_document
,
950 (yaml_char_t
*)number
,
952 YAML_PLAIN_SCALAR_STYLE
);
953 yaml_document_append_mapping_pair(&output_document
,properties
,key
,value
);
955 key
= yaml_document_add_scalar(&output_document
,
957 (yaml_char_t
*)"Name",
959 YAML_PLAIN_SCALAR_STYLE
);
960 value
= yaml_document_add_scalar(&output_document
,
962 (yaml_char_t
*)self
->configs
->configs
[i
]->objects
[j
]->axis_name
,
964 YAML_PLAIN_SCALAR_STYLE
);
965 yaml_document_append_mapping_pair(&output_document
,properties
,key
,value
);
967 key
= yaml_document_add_scalar(&output_document
,
969 (yaml_char_t
*)"Transformation",
971 YAML_PLAIN_SCALAR_STYLE
);
972 seq1
= yaml_document_add_sequence(&output_document
,
973 (yaml_char_t
*)YAML_SEQ_TAG
,
974 YAML_FLOW_SEQUENCE_STYLE
);
975 yaml_document_append_mapping_pair(&output_document
,properties
, key
, seq1
);
977 sprintf(number
, "%f", self
->configs
->configs
[i
]->objects
[j
]->transformation
[k
]);
978 value
= yaml_document_add_scalar(&output_document
,
980 (yaml_char_t
*)number
,
982 YAML_PLAIN_SCALAR_STYLE
);
983 yaml_document_append_sequence_item(&output_document
,seq1
,value
);
986 key
= yaml_document_add_scalar(&output_document
,
988 (yaml_char_t
*)"Hide",
990 YAML_PLAIN_SCALAR_STYLE
);
991 if(self
->configs
->configs
[i
]->objects
[j
]->hide
)
992 value
= yaml_document_add_scalar(&output_document
,
994 (yaml_char_t
*)"yes",
996 YAML_PLAIN_SCALAR_STYLE
);
998 value
= yaml_document_add_scalar(&output_document
,
1000 (yaml_char_t
*)"no",
1002 YAML_PLAIN_SCALAR_STYLE
);
1003 yaml_document_append_mapping_pair(&output_document
,properties
,key
,value
);
1005 yaml_document_append_mapping_pair(&output_document
, properties1
, key1
, seq0
);
1007 /* flush the document */
1008 yaml_emitter_dump(&emitter
, &output_document
);
1011 yaml_document_delete(&output_document
);
1012 yaml_emitter_delete(&emitter
);
1017 * Hkl3D::hide_object:
1019 * update the visibility of an Hkl3DObject in the bullet world
1020 * add or remove the object from the _btWorld depending on the hide
1021 * member of the object.
1023 void hkl3d_hide_object(struct Hkl3D
*self
, struct Hkl3DObject
*object
, int hide
)
1025 // first update the G3DObject
1026 object
->hide
= hide
;
1027 object
->g3dObject
->hide
= hide
;
1030 self
->_btWorld
->removeCollisionObject(object
->btObject
);
1031 object
->added
= false;
1035 self
->_btWorld
->addCollisionObject(object
->btObject
);
1036 object
->added
= true;
1041 /* use for the transparency of colliding objects */
1042 struct ContactSensorCallback
: public btCollisionWorld::ContactResultCallback
1044 ContactSensorCallback(struct Hkl3DObject
*object
)
1045 : btCollisionWorld::ContactResultCallback(),
1046 collisionObject(object
->btObject
),
1050 btCollisionObject
*collisionObject
;
1051 struct Hkl3DObject
*object
;
1053 virtual btScalar
addSingleResult(btManifoldPoint
& cp
,
1054 const btCollisionObject
*colObj0
, int partId0
, int index0
,
1055 const btCollisionObject
*colObj1
, int partId1
, int index1
)
1057 if(colObj0
== collisionObject
1058 || colObj1
== collisionObject
)
1059 object
->is_colliding
= TRUE
;
1064 int hkl3d_is_colliding(struct Hkl3D
*self
)
1070 struct timeval debut
, fin
;
1072 //apply geometry transformation
1073 hkl3d_apply_transformations(self
);
1074 // perform the collision detection and get numbers
1075 gettimeofday(&debut
, NULL
);
1077 self
->_btWorld
->performDiscreteCollisionDetection();
1078 self
->_btWorld
->updateAabbs();
1080 gettimeofday(&fin
, NULL
);
1081 timersub(&fin
, &debut
, &self
->stats
.collision
);
1083 numManifolds
= self
->_btWorld
->getDispatcher()->getNumManifolds();
1085 /* reset all the collisions */
1086 for(i
=0; i
<self
->configs
->len
; i
++)
1087 for(j
=0; j
<self
->configs
->configs
[i
]->len
; j
++)
1088 self
->configs
->configs
[i
]->objects
[j
]->is_colliding
= FALSE
;
1090 /* check all the collisions */
1091 for(i
=0; i
<self
->configs
->len
; i
++)
1092 for(j
=0; j
<self
->configs
->configs
[i
]->len
; j
++){
1093 struct Hkl3DObject
*object
= self
->configs
->configs
[i
]->objects
[j
];
1094 ContactSensorCallback
callback(object
);
1095 self
->_btWorld
->contactTest(object
->btObject
, callback
);
1098 return numManifolds
!= 0;
1102 * Hkl3D::get_bounding_boxes:
1106 * get the bounding boxes of the current world from the bullet internals.
1108 void hkl3d_get_bounding_boxes(struct Hkl3D
*self
,
1109 struct btVector3
*min
, struct btVector3
*max
)
1111 self
->_btWorld
->getBroadphase()->getBroadphaseAabb(*min
, *max
);
1114 int hkl3d_get_nb_manifolds(struct Hkl3D
*self
)
1116 return self
->_btDispatcher
->getNumManifolds();
1119 int hkl3d_get_nb_contacts(struct Hkl3D
*self
, int manifold
)
1121 return self
->_btDispatcher
->getManifoldByIndexInternal(manifold
)->getNumContacts();
1124 void hkl3d_get_collision_coordinates(struct Hkl3D
*self
, int manifold
, int contact
,
1125 double *xa
, double *ya
, double *za
,
1126 double *xb
, double *yb
, double *zb
)
1128 btPersistentManifold
*contactManifold
;
1130 contactManifold
= self
->_btDispatcher
->getManifoldByIndexInternal(manifold
);
1131 btManifoldPoint
& pt
= contactManifold
->getContactPoint(contact
);
1132 btVector3 ptA
= pt
.getPositionWorldOnA();
1133 btVector3 ptB
= pt
.getPositionWorldOnB();