SO3Engine
OgreNewt_CollisionPrimitives.cpp
Go to the documentation of this file.
7#include <OgreEntity.h>
8#include <OgreSubMesh.h>
9#include <OgreSceneNode.h>
10
11namespace OgreNewt
12{
13
14 namespace CollisionPrimitives
15 {
16
17 // OgreNewt::CollisionPrimitives::Null
18 Null::Null(const OgreNewt::World *world) : Collision(world)
19 {
20 m_col = NewtonCreateNull(m_world->getNewtonWorld());
21 }
22
23
24 // OgreNewt::CollisionPrimitives::Box
25 Box::Box(const World* world) : ConvexCollision(world)
26 {}
27
28 Box::Box(const World* world, const Ogre::Vector3& size, int id, const Ogre::Quaternion& orient, const Ogre::Vector3& pos) : ConvexCollision(world)
29 {
30 dFloat matrix[16];
31 OgreNewt::Converters::QuatPosToMatrix(orient, pos, &matrix[0]);
32
33 if (m_col)
34 {
35 NewtonDestroyCollision(m_col);
36 m_col = 0;
37 }
38
39 m_col = NewtonCreateBox(m_world->getNewtonWorld(), dFloat(size.x), dFloat(size.y), dFloat(size.z), id, &matrix[0]);
40 if (!m_col)
41 m_col = NewtonCreateNull(m_world->getNewtonWorld());
42 }
43
44
45
46 // OgreNewt::CollisionPrimitives::Ellipsoid
48 {
49 }
50
51 Ellipsoid::Ellipsoid(const World* world, const Ogre::Vector3& size, int id, const Ogre::Quaternion& orient, const Ogre::Vector3& pos) : ConvexCollision(world)
52 {
53 dFloat matrix[16];
54 OgreNewt::Converters::QuatPosToMatrix(orient, pos, &matrix[0]);
55
56 if (m_col)
57 {
58 NewtonDestroyCollision(m_col);
59 m_col = 0;
60 }
61
62 NewtonCollision* sphere_col = 0;
63 if ((size.x == size.y) && (size.y == size.z))
64 m_col = NewtonCreateSphere(m_world->getNewtonWorld(), (float)size.x, id, &matrix[0]);
65 else
66 {
67 float radius = std::min(std::min(size.x, size.y), size.z);
68 Ogre::Vector3 scale = Ogre::Vector3(size.x / radius, size.y / radius, size.z / radius);
69 m_col = NewtonCreateSphere(m_world->getNewtonWorld(), dFloat(radius), id, &matrix[0]);
70 NewtonCollisionSetScale(m_col, dFloat(scale.x), dFloat(scale.y), dFloat(scale.z));
71 }
72
73 if (!m_col)
74 m_col = NewtonCreateNull(m_world->getNewtonWorld());
75 }
76
77 // OgreNewt::CollisionPrimitives::Cylinder
79 {}
80
81 Cylinder::Cylinder(const World* world, Ogre::Real radius, Ogre::Real height, int id,
82 const Ogre::Quaternion& orient, const Ogre::Vector3& pos) : ConvexCollision(world)
83 {
84 dFloat matrix[16];
85 OgreNewt::Converters::QuatPosToMatrix(orient, pos, &matrix[0]);
86
87 if (m_col)
88 {
89 NewtonDestroyCollision(m_col);
90 m_col = 0;
91 }
92
93 m_col = NewtonCreateCylinder(m_world->getNewtonWorld(), dFloat(radius), dFloat(height), id, &matrix[0]);
94
95 if (!m_col)
96 m_col = NewtonCreateNull(m_world->getNewtonWorld());
97 }
98
99
100 // OgreNewt::CollisionPrimitives::Capsule
102 {}
103
104 Capsule::Capsule(const World* world, Ogre::Real radius, Ogre::Real height, int id,
105 const Ogre::Quaternion& orient, const Ogre::Vector3& pos) : ConvexCollision(world)
106 {
107 dFloat matrix[16];
108 OgreNewt::Converters::QuatPosToMatrix(orient, pos, &matrix[0]);
109
110 if (m_col)
111 {
112 NewtonDestroyCollision(m_col);
113 m_col = 0;
114 }
115
116 m_col = NewtonCreateCapsule(m_world->getNewtonWorld(), dFloat(radius), dFloat((height - (radius * 2.0))), id, &matrix[0]);
117
118 if (!m_col)
119 m_col = NewtonCreateNull(m_world->getNewtonWorld());
120 }
121
122
123 // OgreNewt::CollisionPrimitives::Cone
124 Cone::Cone(const World* world) : ConvexCollision(world)
125 {}
126
127 Cone::Cone(const World* world, Ogre::Real radius, Ogre::Real height, int id,
128 const Ogre::Quaternion& orient, const Ogre::Vector3& pos) : ConvexCollision(world)
129 {
130 dFloat matrix[16];
131 OgreNewt::Converters::QuatPosToMatrix(orient, pos, &matrix[0]);
132
133 if (m_col)
134 {
135 NewtonDestroyCollision(m_col);
136 m_col = 0;
137 }
138
139 m_col = NewtonCreateCone(m_world->getNewtonWorld(), dFloat(radius), dFloat(height), id, &matrix[0]);
140
141 if (!m_col)
142 m_col = NewtonCreateNull(m_world->getNewtonWorld());
143 }
144
145 // OgreNewt::CollisionPrimitives::ChamferCylinder
148
149 ChamferCylinder::ChamferCylinder(const World* world, Ogre::Real radius, Ogre::Real height, int id,
150 const Ogre::Quaternion& orient, const Ogre::Vector3& pos) : ConvexCollision(world)
151 {
152 dFloat matrix[16];
153 OgreNewt::Converters::QuatPosToMatrix(orient, pos, &matrix[0]);
154
155 if (m_col)
156 {
157 NewtonDestroyCollision(m_col);
158 m_col = 0;
159 }
160
161 m_col = NewtonCreateChamferCylinder(m_world->getNewtonWorld(), dFloat(radius), dFloat(height), id, &matrix[0]);
162
163 if (!m_col)
164 m_col = NewtonCreateNull(m_world->getNewtonWorld());
165 }
166
167
168
169 // OgreNewt::CollisionPrimitives::ConvexHull
171 {}
172
173 ConvexHull::ConvexHull(const World* world, Ogre::Entity* obj, int id, const Ogre::Quaternion& orient, const Ogre::Vector3& pos, Ogre::Real tolerance, const Ogre::Vector3& scale) : ConvexCollision(world)
174 {
175 //get the mesh!
176 //Ogre::Entity* obj = (Ogre::Entity*)node->getAttachedObject(0);
177 Ogre::MeshPtr mesh = obj->getMesh();
178
179 //find number of submeshes
180 unsigned short sub = mesh->getNumSubMeshes();
181
182 size_t total_verts = 0;
183
184 Ogre::VertexData* v_data;
185 bool addedShared = false;
186
187 for (unsigned short i = 0; i < sub; i++)
188 {
189 Ogre::SubMesh* sub_mesh = mesh->getSubMesh(i);
190 if (sub_mesh->useSharedVertices)
191 {
192 if (!addedShared)
193 {
194 v_data = mesh->sharedVertexData;
195 total_verts += v_data->vertexCount;
196
197 addedShared = true;
198 }
199 }
200 else
201 {
202 v_data = sub_mesh->vertexData;
203 total_verts += v_data->vertexCount;
204 }
205 }
206
207 addedShared = false;
208
209 //make array to hold vertex positions!
210 Ogre::Vector3* vertices = new Ogre::Vector3[total_verts];
211 unsigned int offset = 0;
212
213 //loop back through, adding vertices as we go!
214 for (unsigned short i = 0; i < sub; i++)
215 {
216 Ogre::SubMesh* sub_mesh = mesh->getSubMesh(i);
217 Ogre::VertexDeclaration* v_decl;
218 const Ogre::VertexElement* p_elem;
219 float* v_Posptr;
220 size_t v_count;
221
222 v_data = NULL;
223
224 if (sub_mesh->useSharedVertices)
225 {
226 if (!addedShared)
227 {
228 v_data = mesh->sharedVertexData;
229 v_count = v_data->vertexCount;
230 v_decl = v_data->vertexDeclaration;
231 p_elem = v_decl->findElementBySemantic(Ogre::VES_POSITION);
232 addedShared = true;
233 }
234 }
235 else
236 {
237 v_data = sub_mesh->vertexData;
238 v_count = v_data->vertexCount;
239 v_decl = v_data->vertexDeclaration;
240 p_elem = v_decl->findElementBySemantic(Ogre::VES_POSITION);
241 }
242
243 if (v_data)
244 {
245 size_t start = v_data->vertexStart;
246 //pointer
247 Ogre::HardwareVertexBufferSharedPtr v_sptr = v_data->vertexBufferBinding->getBuffer(p_elem->getSource());
248 unsigned char* v_ptr = static_cast<unsigned char*>(v_sptr->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
249 unsigned char* v_offset;
250
251 //loop through vertex data...
252 for (size_t j = start; j < (start + v_count); j++)
253 {
254 //get offset to Position data!
255 v_offset = v_ptr + (j * v_sptr->getVertexSize());
256 p_elem->baseVertexPointerToElement(v_offset, &v_Posptr);
257
258 //now get vertex positions...
259 vertices[offset].x = *v_Posptr; v_Posptr++;
260 vertices[offset].y = *v_Posptr; v_Posptr++;
261 vertices[offset].z = *v_Posptr; v_Posptr++;
262
263 vertices[offset] *= scale;
264 offset++;
265 }
266
267 //unlock buffer
268 v_sptr->unlock();
269 }
270 }
271
272 dFloat matrix[16];
273
274 OgreNewt::Converters::QuatPosToMatrix(orient, pos, &matrix[0]);
275
276 //okay, let's try making the ConvexHull!
277 if (m_col)
278 {
279 NewtonDestroyCollision(m_col);
280 m_col = 0;
281 }
282
283 m_col = NewtonCreateConvexHull(m_world->getNewtonWorld(), (int)total_verts, (float*)&vertices[0].x, sizeof(Ogre::Vector3), tolerance, id, &matrix[0]);
284
285 if (!m_col)
286 m_col = NewtonCreateNull(m_world->getNewtonWorld());
287
288 delete[]vertices;
289
290 }
291
292
293 // OgreNewt::CollisionPrimitives::ConvexHull
294 ConvexHull::ConvexHull(const World* world, const Ogre::Vector3* verts, int vertcount, int id, const Ogre::Quaternion& orient, const Ogre::Vector3& pos, Ogre::Real tolerance) : ConvexCollision(world)
295 {
296 dFloat matrix[16];
297 OgreNewt::Converters::QuatPosToMatrix(orient, pos, &matrix[0]);
298
299 //make the collision primitive.
300 if (m_col)
301 {
302 NewtonDestroyCollision(m_col);
303 m_col = 0;
304 }
305
306 m_col = NewtonCreateConvexHull(m_world->getNewtonWorld(), vertcount, (float*)&verts[0].x, sizeof(Ogre::Vector3), tolerance, id, &matrix[0]);
307 if (!m_col)
308 m_col = NewtonCreateNull(m_world->getNewtonWorld());
309 }
310
311
312 // OgreNewt::CollisionPrimitives::ConcaveHull
314 {}
315
316 ConcaveHull::ConcaveHull(const World* world, Ogre::Entity* obj, int id, Ogre::Real tolerance, const Ogre::Vector3& scale) : ConvexCollision(world)
317 {
318 if (m_col)
319 {
320 NewtonDestroyCollision(m_col);
321 m_col = 0;
322 }
323
324 //first create a mesh
325 NewtonMesh* const nmesh = NewtonMeshCreate(m_world->getNewtonWorld());
326 NewtonMeshBeginFace(nmesh);
327
328 Ogre::MeshPtr mesh = obj->getMesh();
329 //find number of sub-meshes
330 unsigned short sub = mesh->getNumSubMeshes();
331
332 for (unsigned short cs = 0; cs < sub; cs++)
333 {
334 Ogre::SubMesh* sub_mesh = mesh->getSubMesh(cs);
335
336 //vertex data!
337 Ogre::VertexData* v_data;
338
339 if (sub_mesh->useSharedVertices)
340 {
341 v_data = mesh->sharedVertexData;
342 }
343 else
344 {
345 v_data = sub_mesh->vertexData;
346 }
347
348 //let's find more information about the Vertices...
349 Ogre::VertexDeclaration* v_decl = v_data->vertexDeclaration;
350 const Ogre::VertexElement* p_elem = v_decl->findElementBySemantic(Ogre::VES_POSITION);
351
352 // get pointer!
353 Ogre::HardwareVertexBufferSharedPtr v_sptr = v_data->vertexBufferBinding->getBuffer(p_elem->getSource());
354 unsigned char* v_ptr = static_cast<unsigned char*>(v_sptr->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
355
356 //now find more about the index!!
357 Ogre::IndexData* i_data = sub_mesh->indexData;
358 size_t index_count = i_data->indexCount;
359 size_t poly_count = index_count / 3;
360
361 // get pointer!
362 Ogre::HardwareIndexBufferSharedPtr i_sptr = i_data->indexBuffer;
363
364 // 16 or 32 bit indices?
365 bool uses32bit = (i_sptr->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
366 Ogre::uint32* i_Longptr;
367 Ogre::uint16* i_Shortptr;
368
369 if (uses32bit)
370 {
371 i_Longptr = static_cast<Ogre::uint32*>(i_sptr->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
372
373 }
374 else
375 {
376 i_Shortptr = static_cast<Ogre::uint16*>(i_sptr->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
377 }
378
379
380 //now loop through the indices, getting polygon info!
381 int i_offset = 0;
382
383 for (size_t i = 0; i < poly_count; i++)
384 {
385 Ogre::Vector3 poly_verts[3];
386 unsigned char* v_offset;
387 float* v_Posptr;
388 int idx;
389
390 if (uses32bit)
391 {
392 for (int j = 0; j < 3; j++)
393 {
394 idx = i_Longptr[i_offset + j]; // index to first vertex!
395 v_offset = v_ptr + (idx * v_sptr->getVertexSize());
396 p_elem->baseVertexPointerToElement(v_offset, &v_Posptr);
397 //now get vertex position from v_Posptr!
398 poly_verts[j].x = *v_Posptr; v_Posptr++;
399 poly_verts[j].y = *v_Posptr; v_Posptr++;
400 poly_verts[j].z = *v_Posptr; v_Posptr++;
401
402 poly_verts[j] *= scale;
403 }
404 }
405 else
406 {
407 for (int j = 0; j < 3; j++)
408 {
409 idx = i_Shortptr[i_offset + j]; // index to first vertex!
410 v_offset = v_ptr + (idx * v_sptr->getVertexSize());
411 p_elem->baseVertexPointerToElement(v_offset, &v_Posptr);
412 //now get vertex position from v_Posptr!
413
414 // switch poly winding.
415 poly_verts[j].x = *v_Posptr; v_Posptr++;
416 poly_verts[j].y = *v_Posptr; v_Posptr++;
417 poly_verts[j].z = *v_Posptr; v_Posptr++;
418
419 poly_verts[j] *= scale;
420 }
421 }
422 NewtonMeshAddFace(nmesh, 3, (float*)&poly_verts[0].x, sizeof(Ogre::Vector3), cs);
423
424 i_offset += 3;
425 }
426
427 //unlock the buffers!
428 v_sptr->unlock();
429 i_sptr->unlock();
430
431 }
432 //done!
433 NewtonMeshEndFace(nmesh);
434 NewtonMeshFixTJoints(nmesh);
435 NewtonMesh* const omesh = NewtonMeshApproximateConvexDecomposition(nmesh, 0.5f, 0.1f, 10, 1000, NULL, NULL);
436
437 if (nmesh)
438 NewtonMeshDestroy(nmesh);
439
440 if (m_col)
441 {
442 NewtonDestroyCollision(m_col);
443 m_col = 0;
444 }
445
446 m_col = NewtonCreateCompoundCollisionFromMesh(m_world->getNewtonWorld(), omesh, tolerance, id, id);
447 if (!m_col)
448 m_col = NewtonCreateNull(m_world->getNewtonWorld());
449
450 if (omesh)
451 NewtonMeshDestroy(omesh);
452
453 //CollisionSerializer serializer = CollisionSerializer();
454 //serializer.exportCollision(OgreNewt::CollisionPtr(this), std::string("d:/") + (obj->getName()));
455 }
456
457 // OgreNewt::CollisionPrimitives::ConcaveHull
458 ConcaveHull::ConcaveHull(const World* world, const Ogre::Vector3* verts, int vertcount, int id, Ogre::Real tolerance) : ConvexCollision(world)
459 {
460 }
461
462
464 {
465 }
466
467
468 TreeCollision::TreeCollision(const World* world, Ogre::Entity* obj, bool optimize, int id, FaceWinding fw, const Ogre::Vector3& scale) : Collision(world)
469 {
470 start(id);
471
472 Ogre::MeshPtr mesh = obj->getMesh();
473
474 //find number of sub-meshes
475 unsigned short sub = mesh->getNumSubMeshes();
476 int countConvexFaces = 0;
477
478 for (unsigned short cs = 0; cs < sub; cs++)
479 {
480 Ogre::SubMesh* sub_mesh = mesh->getSubMesh(cs);
481
482 //vertex data!
483 Ogre::VertexData* v_data;
484
485 if (sub_mesh->useSharedVertices)
486 {
487 v_data = mesh->sharedVertexData;
488 }
489 else
490 {
491 v_data = sub_mesh->vertexData;
492 }
493
494 //let's find more information about the Vertices...
495 Ogre::VertexDeclaration* v_decl = v_data->vertexDeclaration;
496 const Ogre::VertexElement* p_elem = v_decl->findElementBySemantic(Ogre::VES_POSITION);
497
498 // get pointer!
499 Ogre::HardwareVertexBufferSharedPtr v_sptr = v_data->vertexBufferBinding->getBuffer(p_elem->getSource());
500 unsigned char* v_ptr = static_cast<unsigned char*>(v_sptr->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
501
502 //now find more about the index!!
503 Ogre::IndexData* i_data = sub_mesh->indexData;
504 size_t index_count = i_data->indexCount;
505 size_t poly_count = index_count / 3;
506
507 // get pointer!
508 Ogre::HardwareIndexBufferSharedPtr i_sptr = i_data->indexBuffer;
509
510 // 16 or 32 bit indices?
511 bool uses32bit = (i_sptr->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
512 Ogre::uint32* i_Longptr;
513 Ogre::uint16* i_Shortptr;
514
515 if (uses32bit)
516 {
517 i_Longptr = static_cast<Ogre::uint32*>(i_sptr->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
518
519 }
520 else
521 {
522 i_Shortptr = static_cast<Ogre::uint16*>(i_sptr->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
523 }
524
525 //now loop through the indices, getting polygon info!
526 int i_offset = 0;
527
528 for (size_t i = 0; i < poly_count; i++)
529 {
530 Ogre::Vector3 poly_verts[3];
531 unsigned char* v_offset;
532 float* v_Posptr;
533 int idx;
534
535 if (uses32bit)
536 {
537 for (int j = 0; j < 3; j++)
538 {
539 idx = i_Longptr[i_offset + j]; // index to first vertex!
540 v_offset = v_ptr + (idx * v_sptr->getVertexSize());
541 p_elem->baseVertexPointerToElement(v_offset, &v_Posptr);
542 //now get vertex position from v_Posptr!
543 poly_verts[j].x = *v_Posptr; v_Posptr++;
544 poly_verts[j].y = *v_Posptr; v_Posptr++;
545 poly_verts[j].z = *v_Posptr; v_Posptr++;
546
547 poly_verts[j] *= scale;
548 }
549 }
550 else
551 {
552 for (int j = 0; j < 3; j++)
553 {
554 idx = i_Shortptr[i_offset + j]; // index to first vertex!
555 v_offset = v_ptr + (idx * v_sptr->getVertexSize());
556 p_elem->baseVertexPointerToElement(v_offset, &v_Posptr);
557 //now get vertex position from v_Posptr!
558
559 // switch poly winding.
560 poly_verts[j].x = *v_Posptr; v_Posptr++;
561 poly_verts[j].y = *v_Posptr; v_Posptr++;
562 poly_verts[j].z = *v_Posptr; v_Posptr++;
563
564 poly_verts[j] *= scale;
565 }
566 }
567
568 if (fw == FW_DEFAULT)
569 {
570 addPoly(poly_verts, cs);
571 }
572 else
573 {
574 Ogre::Vector3 rev_poly_verts[3];
575 rev_poly_verts[0] = poly_verts[0];
576 rev_poly_verts[0] = poly_verts[2];
577 rev_poly_verts[0] = poly_verts[1];
578
579 addPoly(rev_poly_verts, cs);
580 }
581
582 //check concativity the same way newton do to add tree collision faces
583 bool convexface = true;
584 Ogre::Vector3 p0(poly_verts[2]);
585 for (int k = 0; k < 3; k++)
586 {
587 Ogre::Vector3 p1(poly_verts[k]);
588 Ogre::Vector3 edge(p1 - p0);
589 float mag2 = edge.dotProduct(edge);
590 if (mag2 < 1.0e-6f)
591 convexface = false;
592 p0 = p1;
593 }
594
595 if (convexface)
596 {
597 Ogre::Vector3 edge0(poly_verts[2] - poly_verts[0]);
598 Ogre::Vector3 edge1(poly_verts[1] - poly_verts[0]);
599 Ogre::Vector3 normal(edge0 * edge1);
600 float mag2 = normal.dotProduct(normal);
601 if ((mag2 != 0.0) && (mag2 < 1.0e-7f))
602 convexface = false;
603 }
604
605 if (convexface)
606 countConvexFaces++;
607
608 i_offset += 3;
609 }
610
611 //unlock the buffers!
612 v_sptr->unlock();
613 i_sptr->unlock();
614
615 }
616
617 //done!
618 if (countConvexFaces)
619 finish(optimize);
620 else
621 {
622 //failed!
623 if (m_col)
624 {
625 NewtonDestroyCollision(m_col);
626 m_col = 0;
627 }
628
629 m_col = NewtonCreateNull(m_world->getNewtonWorld());
630 }
631
632 //CollisionSerializer serializer = CollisionSerializer();
633 //serializer.exportCollision(OgreNewt::CollisionPtr(this), std::string("d:/") + (obj->getName()));
634 }
635
636 TreeCollision::TreeCollision(const World* world, const Ogre::SceneNode* node, bool optimize, int id, FaceWinding fw, const Ogre::Vector3& scale) : Collision(world)
637 {
638 start(id);
639 AddEntities(node, node, scale, fw);
640 finish(optimize);
641 }
642
643 TreeCollision::TreeCollision(const OgreNewt::World *world, int numVertices, int numIndices, const float *vertices, const int *indices, bool optimize, int id, FaceWinding fw) : OgreNewt::Collision(world)
644 {
645 start(id);
646
647 int numPolys = numIndices / 3;
648
649 Ogre::Vector3 *vecVertices = new Ogre::Vector3[numVertices];
650
651 for (int curVertex = 0; curVertex < numVertices; curVertex++)
652 {
653 vecVertices[curVertex].x = vertices[0 + curVertex * 3];
654 vecVertices[curVertex].y = vertices[1 + curVertex * 3];
655 vecVertices[curVertex].z = vertices[2 + curVertex * 3];
656 }
657
658 for (int poly = 0; poly < numPolys; poly++)
659 {
660 Ogre::Vector3 poly_verts[3];
661
662 if (fw == FW_DEFAULT)
663 {
664 poly_verts[0] = vecVertices[indices[0 + poly * 3]];
665 poly_verts[1] = vecVertices[indices[1 + poly * 3]];
666 poly_verts[2] = vecVertices[indices[2 + poly * 3]];
667 }
668 else
669 {
670 poly_verts[0] = vecVertices[indices[0 + poly * 3]];
671 poly_verts[2] = vecVertices[indices[1 + poly * 3]];
672 poly_verts[1] = vecVertices[indices[2 + poly * 3]];
673 }
674
675 addPoly(poly_verts, 0);
676 }
677
678 delete[] vecVertices;
679
680 finish(optimize);
681 }
682
683
684 TreeCollision::TreeCollision(const World* world, int numVertices, Ogre::Vector3* vertices, Ogre::IndexData* indexData, bool optimize, int id, FaceWinding fw) : Collision(world)
685 {
686 start(id);
687
688 unsigned int numPolys = indexData->indexCount / 3;
689 Ogre::HardwareIndexBufferSharedPtr hwIndexBuffer = indexData->indexBuffer;
690 size_t indexSize = hwIndexBuffer->getIndexSize();
691 void* indices = hwIndexBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY);
692
693 assert((indexSize == 2) || (indexSize == 4));
694
695 if (indexSize == 2)
696 {
697 unsigned short* curIndex = (unsigned short*)indices;
698 for (unsigned int poly = 0; poly < numPolys; poly++)
699 {
700 Ogre::Vector3 poly_verts[3];
701
702 //invert vertex winding (otherwise, raycasting won't work???)
703 if (fw == FW_DEFAULT)
704 {
705 poly_verts[0] = vertices[*curIndex]; curIndex++;
706 poly_verts[1] = vertices[*curIndex]; curIndex++;
707 poly_verts[2] = vertices[*curIndex]; curIndex++;
708 }
709 else
710 {
711 poly_verts[0] = vertices[*curIndex]; curIndex++;
712 poly_verts[2] = vertices[*curIndex]; curIndex++;
713 poly_verts[1] = vertices[*curIndex]; curIndex++;
714 }
715
716 addPoly(poly_verts, 0);
717 }
718 }
719 else
720 {
721 unsigned int* curIndex = (unsigned int*)indices;
722 for (unsigned int poly = 0; poly < numPolys; poly++)
723 {
724 Ogre::Vector3 poly_verts[3];
725
726 if (fw == FW_DEFAULT)
727 {
728 poly_verts[0] = vertices[*curIndex]; curIndex++;
729 poly_verts[1] = vertices[*curIndex]; curIndex++;
730 poly_verts[2] = vertices[*curIndex]; curIndex++;
731 }
732 else
733 {
734 poly_verts[0] = vertices[*curIndex]; curIndex++;
735 poly_verts[2] = vertices[*curIndex]; curIndex++;
736 poly_verts[1] = vertices[*curIndex]; curIndex++;
737 }
738
739 addPoly(poly_verts, 0);
740 }
741 }
742
743 hwIndexBuffer->unlock();
744 finish(optimize);
745 }
746
747 void TreeCollision::AddEntities(const Ogre::SceneNode* node, const Ogre::SceneNode* mainNode, const Ogre::Vector3 scale, FaceWinding fw)
748 {
749 Ogre::SceneNode::ObjectMap objmap = node->getAttachedObjects();
750 for (unsigned int i = 0; i < objmap.size(); i++)
751 {
752 Ogre::MovableObject* mobj = objmap[i];
753 if (mobj->getMovableType() == "Entity")
754 {
755 Ogre::Entity* obj = static_cast<Ogre::Entity*>(mobj);
756 Ogre::Vector3 npos = node->_getDerivedPosition();
757 Ogre::Vector3 nscale = node->_getDerivedScale();
758 Ogre::Quaternion nquat = node->_getDerivedOrientation();
759 Ogre::MeshPtr mesh = obj->getMesh();
760
761 //find number of sub-meshes
762 unsigned short sub = mesh->getNumSubMeshes();
763
764 for (unsigned short cs = 0; cs < sub; cs++)
765 {
766 Ogre::SubMesh* sub_mesh = mesh->getSubMesh(cs);
767
768 //vertex data!
769 Ogre::VertexData* v_data;
770
771 if (sub_mesh->useSharedVertices)
772 {
773 v_data = mesh->sharedVertexData;
774 }
775 else
776 {
777 v_data = sub_mesh->vertexData;
778 }
779
780 //let's find more information about the Vertices...
781 Ogre::VertexDeclaration* v_decl = v_data->vertexDeclaration;
782 const Ogre::VertexElement* p_elem = v_decl->findElementBySemantic(Ogre::VES_POSITION);
783
784 // get pointer!
785 Ogre::HardwareVertexBufferSharedPtr v_sptr = v_data->vertexBufferBinding->getBuffer(p_elem->getSource());
786 unsigned char* v_ptr = static_cast<unsigned char*>(v_sptr->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
787
788 //now find more about the index!!
789 Ogre::IndexData* i_data = sub_mesh->indexData;
790 size_t index_count = i_data->indexCount;
791 size_t poly_count = index_count / 3;
792
793 // get pointer!
794 Ogre::HardwareIndexBufferSharedPtr i_sptr = i_data->indexBuffer;
795
796 // 16 or 32 bit indices?
797 bool uses32bit = (i_sptr->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
798 Ogre::uint32* i_Longptr;
799 Ogre::uint16* i_Shortptr;
800
801 if (uses32bit)
802 {
803 i_Longptr = static_cast<Ogre::uint32*>(i_sptr->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
804
805 }
806 else
807 {
808 i_Shortptr = static_cast<unsigned short*>(i_sptr->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
809 }
810
811 //now loop through the indices, getting polygon info!
812 int i_offset = 0;
813
814 for (size_t i = 0; i < poly_count; i++)
815 {
816 Ogre::Vector3 poly_verts[3];
817 unsigned char* v_offset;
818 float* v_Posptr;
819 int idx;
820
821 if (uses32bit)
822 {
823 for (int j = 0; j < 3; j++)
824 {
825 idx = i_Longptr[i_offset + j]; // index to first vertex!
826 v_offset = v_ptr + (idx * v_sptr->getVertexSize());
827 p_elem->baseVertexPointerToElement(v_offset, &v_Posptr);
828 //now get vertex position from v_Posptr!
829 poly_verts[j].x = *v_Posptr; v_Posptr++;
830 poly_verts[j].y = *v_Posptr; v_Posptr++;
831 poly_verts[j].z = *v_Posptr; v_Posptr++;
832
833 poly_verts[j] = mainNode->_getDerivedOrientation().Inverse() * ((nquat * (poly_verts[j] * nscale)) + npos - mainNode->_getDerivedPosition()) / mainNode->_getDerivedScale() * scale;
834 }
835 }
836 else
837 {
838 for (int j = 0; j < 3; j++)
839 {
840 idx = i_Shortptr[i_offset + j]; // index to first vertex!
841 v_offset = v_ptr + (idx * v_sptr->getVertexSize());
842 p_elem->baseVertexPointerToElement(v_offset, &v_Posptr);
843 //now get vertex position from v_Posptr!
844
845 // switch poly winding.
846 poly_verts[j].x = *v_Posptr; v_Posptr++;
847 poly_verts[j].y = *v_Posptr; v_Posptr++;
848 poly_verts[j].z = *v_Posptr; v_Posptr++;
849
850 poly_verts[j] = mainNode->_getDerivedOrientation().Inverse() * ((nquat * (poly_verts[j] * nscale)) + npos - mainNode->_getDerivedPosition()) / mainNode->_getDerivedScale() * scale;
851 }
852 }
853
854 if (fw == FW_DEFAULT)
855 {
856 addPoly(poly_verts, cs);
857 }
858 else
859 {
860 Ogre::Vector3 rev_poly_verts[3];
861 rev_poly_verts[0] = poly_verts[0];
862 rev_poly_verts[0] = poly_verts[2];
863 rev_poly_verts[0] = poly_verts[1];
864
865 addPoly(rev_poly_verts, cs);
866 }
867
868 i_offset += 3;
869 }
870
871 //unlock the buffers!
872 v_sptr->unlock();
873 i_sptr->unlock();
874 }
875 }
876 }
877
878 // Iterate through all the child-nodes
879 Ogre::SceneNode::ConstChildNodeIterator nodei = node->getChildIterator();
880
881 while (nodei.hasMoreElements())
882 {
883 const Ogre::SceneNode* subNode = static_cast<const Ogre::SceneNode*>(nodei.getNext());
884 // Add this subnode and its children...
885 AddEntities(subNode, mainNode, scale, fw);
886 }
887 }
888
890 {
891 if (m_col)
892 {
893 NewtonDestroyCollision(m_col);
894 m_col = 0;
895 }
896
897 m_col = NewtonCreateTreeCollision(m_world->getNewtonWorld(), id);
898 if (!m_col)
899 m_col = NewtonCreateNull(m_world->getNewtonWorld());
900
901 NewtonTreeCollisionBeginBuild(m_col);
902 }
903
904 void TreeCollision::addPoly(Ogre::Vector3* polys, unsigned int ID)
905 {
906 NewtonTreeCollisionAddFace(m_col, 3, (float*)&polys[0].x, sizeof(Ogre::Vector3), ID);
907 }
908
909 void TreeCollision::finish(bool optimize)
910 {
911 try
912 {
913 NewtonTreeCollisionEndBuild(m_col, optimize);
914
915 if (!m_col)
916 m_col = NewtonCreateNull(m_world->getNewtonWorld());
917 }
918 catch (std::exception &)
919 {
920 if (m_col)
921 {
922 NewtonDestroyCollision(m_col);
923 m_col = 0;
924 }
925
926 if (!m_col)
927 m_col = NewtonCreateNull(m_world->getNewtonWorld());
928 }
929 }
930
931 // Newton >= 2.30
932 dFloat _CDECL TreeCollision::newtonRayCastCallback(const NewtonBody* const body, const NewtonCollision* const treeCollision, dFloat distance, dFloat *normal, int faceId, void *userData)
933 {
934 Body* bod = (OgreNewt::Body*)NewtonBodyGetUserData(body);
935
937 if (!bod)
938 return 0;
939
940 ((Raycast*)userData)->userCallback(bod, Ogre::Real(distance), Ogre::Vector3(Ogre::Real(normal[0]), Ogre::Real(normal[1]), Ogre::Real(normal[2])), faceId);
941
942 ((Raycast*)userData)->m_treecollisioncallback_bodyalreadyadded = true;
943
944 return distance;
945 }
946
947 /*
948 float _CDECL TreeCollision::newtonRayCastCallback(float interception, float *normal, int faceId, void *userData)
949 {
950 Body* bod = ((Raycast*)userData)->m_treecollisioncallback_lastbody;
951
953 if(!bod)
954 return 0;
955
956 ((Raycast*)userData)->userCallback( bod, interception, Ogre::Vector3(normal[0], normal[1], normal[2]), faceId );
957
958 ((Raycast*)userData)->m_treecollisioncallback_bodyalreadyadded = true;
959
960 return interception;
961 }
962*/
963 void TreeCollision::setRayCastCallbackactive(bool active, const NewtonCollision *col)
964 {
965 if (active)
966 NewtonTreeCollisionSetUserRayCastCallback(col, newtonRayCastCallback);
967 else
968 NewtonTreeCollisionSetUserRayCastCallback(col, NULL);
969 }
970
971 int TreeCollisionSceneParser::count = 0;
972
973
977
978 void TreeCollisionSceneParser::parseScene(Ogre::SceneNode *startNode, int id, bool optimize, FaceWinding fw)
979 {
980 count = 0;
981
982 start(id);
983
984 // parse the individual nodes.
985 Ogre::Quaternion rootOrient = Ogre::Quaternion::IDENTITY;
986 Ogre::Vector3 rootPos = Ogre::Vector3::ZERO;
987 Ogre::Vector3 rootScale = startNode->getScale();;
988
989 _parseNode(startNode, rootOrient, rootPos, rootScale, fw);
990
991 finish(optimize);
992 }
993
994 void TreeCollisionSceneParser::_parseNode(Ogre::SceneNode *node, const Ogre::Quaternion &curOrient, const Ogre::Vector3 &curPos, const Ogre::Vector3 &curScale, FaceWinding fw)
995 {
996 // parse this scene node.
997 // do children first.
998 Ogre::Quaternion thisOrient = curOrient * node->getOrientation();
999 Ogre::Vector3 thisPos = curPos + (curOrient * (node->getPosition() * curScale));
1000 Ogre::Vector3 thisScale = curScale * node->getScale();
1001
1002 Ogre::SceneNode::ChildNodeIterator child_it = node->getChildIterator();
1003
1004 while (child_it.hasMoreElements())
1005 {
1006 _parseNode((Ogre::SceneNode*)child_it.getNext(), thisOrient, thisPos, thisScale, fw);
1007 }
1008
1009
1010 // now add the polys from this node.
1011 //now get the mesh!
1012 Ogre::SceneNode::ObjectMap objmap = node->getAttachedObjects();
1013 for (unsigned int co = 0; co < objmap.size(); co++)
1014 {
1015 Ogre::MovableObject* obj = objmap[co];
1016 if (obj->getMovableType() != "Entity")
1017 continue;
1018
1019 Ogre::Entity* ent = (Ogre::Entity*)obj;
1020
1021 if (!entityFilter(node, ent, fw))
1022 continue;
1023
1024 Ogre::MeshPtr mesh = ent->getMesh();
1025
1026 //find number of sub-meshes
1027 unsigned short sub = mesh->getNumSubMeshes();
1028
1029 for (unsigned short cs = 0; cs < sub; cs++)
1030 {
1031 Ogre::SubMesh* sub_mesh = mesh->getSubMesh(cs);
1032
1033 //vertex data!
1034 Ogre::VertexData* v_data;
1035
1036 if (sub_mesh->useSharedVertices)
1037 {
1038 v_data = mesh->sharedVertexData;
1039 }
1040 else
1041 {
1042 v_data = sub_mesh->vertexData;
1043 }
1044
1045 //let's find more information about the Vertices...
1046 Ogre::VertexDeclaration* v_decl = v_data->vertexDeclaration;
1047 const Ogre::VertexElement* p_elem = v_decl->findElementBySemantic(Ogre::VES_POSITION);
1048
1049 // get pointer!
1050 Ogre::HardwareVertexBufferSharedPtr v_sptr = v_data->vertexBufferBinding->getBuffer(p_elem->getSource());
1051 unsigned char* v_ptr = static_cast<unsigned char*>(v_sptr->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
1052
1053 //now find more about the index!!
1054 Ogre::IndexData* i_data = sub_mesh->indexData;
1055 size_t index_count = i_data->indexCount;
1056 size_t poly_count = index_count / 3;
1057
1058 // get pointer!
1059 Ogre::HardwareIndexBufferSharedPtr i_sptr = i_data->indexBuffer;
1060
1061 // 16 or 32 bit indices?
1062 bool uses32bit = (i_sptr->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
1063 Ogre::uint32* i_Longptr;
1064 Ogre::uint16* i_Shortptr;
1065
1066 if (uses32bit)
1067 {
1068 i_Longptr = static_cast<Ogre::uint32*>(i_sptr->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
1069 }
1070 else
1071 {
1072 i_Shortptr = static_cast<Ogre::uint16*>(i_sptr->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
1073 }
1074
1075 //now loop through the indices, getting polygon info!
1076 int i_offset = 0;
1077
1078 for (size_t i = 0; i < poly_count; i++)
1079 {
1080 Ogre::Vector3 poly_verts[3];
1081 unsigned char* v_offset;
1082 float* v_Posptr;
1083 int idx;
1084
1085 if (uses32bit)
1086 {
1087 for (int j = 0; j < 3; j++)
1088 {
1089 idx = i_Longptr[i_offset + j]; // index to first vertex!
1090 v_offset = v_ptr + (idx * v_sptr->getVertexSize());
1091 p_elem->baseVertexPointerToElement(v_offset, &v_Posptr);
1092 //now get vertex position from v_Posptr!
1093 poly_verts[j].x = *v_Posptr; v_Posptr++;
1094 poly_verts[j].y = *v_Posptr; v_Posptr++;
1095 poly_verts[j].z = *v_Posptr; v_Posptr++;
1096
1097 poly_verts[j] = thisPos + (thisOrient * (poly_verts[j] * curScale));
1098 }
1099 }
1100 else
1101 {
1102 for (int j = 0; j < 3; j++)
1103 {
1104 idx = i_Shortptr[i_offset + j]; // index to first vertex!
1105 v_offset = v_ptr + (idx * v_sptr->getVertexSize());
1106 p_elem->baseVertexPointerToElement(v_offset, &v_Posptr);
1107 //now get vertex position from v_Posptr!
1108
1109 // switch poly winding.
1110 poly_verts[j].x = *v_Posptr; v_Posptr++;
1111 poly_verts[j].y = *v_Posptr; v_Posptr++;
1112 poly_verts[j].z = *v_Posptr; v_Posptr++;
1113
1114 poly_verts[j] = thisPos + (thisOrient * (poly_verts[j] * curScale));
1115 }
1116 }
1117
1118 if (fw == FW_DEFAULT)
1119 {
1120 addPoly(poly_verts, cs);
1121 }
1122 else
1123 {
1124 Ogre::Vector3 rev_poly_verts[3];
1125 rev_poly_verts[0] = poly_verts[0];
1126 rev_poly_verts[0] = poly_verts[2];
1127 rev_poly_verts[0] = poly_verts[1];
1128
1129 addPoly(rev_poly_verts, cs);
1130 }
1131
1132 i_offset += 3;
1133 }
1134
1135 //unlock the buffers!
1136 v_sptr->unlock();
1137 i_sptr->unlock();
1138
1139 }
1140 }
1141
1142 }
1143
1144
1145
1146
1147
1148 // OgreNewt::CollisionPrimitives::CompoundCollision
1151
1152 CompoundCollision::CompoundCollision(const World* world, std::vector<OgreNewt::CollisionPtr> col_array, int id) : Collision(world)
1153 {
1154 if (m_col)
1155 {
1156 NewtonDestroyCollision(m_col);
1157 m_col = 0;
1158 }
1159
1160 m_col = NewtonCreateCompoundCollision(world->getNewtonWorld(), id);
1161 if (!m_col)
1162 m_col = NewtonCreateNull(m_world->getNewtonWorld());
1163 else
1164 {
1165 //get the number of elements.
1166 unsigned int num = col_array.size();
1167 NewtonCompoundCollisionBeginAddRemove(m_col);
1168 for (unsigned int i = 0; i < num; i++)
1169 {
1170 NewtonCompoundCollisionAddSubCollision(m_col, (NewtonCollision*)col_array[i]->getNewtonCollision());
1171 }
1172 NewtonCompoundCollisionEndAddRemove(m_col);
1173 }
1174 }
1175
1176
1177 // OgreNewt::CollisionPrimitives::Pyramid
1179 {}
1180
1181 Pyramid::Pyramid(const World* world, const Ogre::Vector3& size, int id, const Ogre::Quaternion& orient, const Ogre::Vector3& pos, Ogre::Real tolerance) : ConvexCollision(world)
1182 {
1183 dFloat matrix[16];
1184
1185 OgreNewt::Converters::QuatPosToMatrix(orient, pos, &matrix[0]);
1186
1187 // create a simple pyramid collision primitive using the Newton Convex Hull interface.
1188 // this function places the center of mass 1/3 up y from the base.
1189
1190 dFloat* vertices = new dFloat[15];
1191 unsigned short idx = 0;
1192
1193 // make the bottom base.
1194 for (int ix = -1; ix <= 1; ix += 2)
1195 {
1196 for (int iz = -1; iz <= 1; iz += 2)
1197 {
1198 vertices[idx++] = (size.x / 2.0f) * ix;
1199 vertices[idx++] = -(size.y / 3.0f);
1200 vertices[idx++] = (size.z / 2.0f) * iz;
1201 }
1202 }
1203
1204 // make the tip.
1205 vertices[idx++] = 0.0f;
1206 vertices[idx++] = (size.y*2.0f / 3.0f);
1207 vertices[idx++] = 0.0f;
1208
1209 //make the collision primitive.
1210 if (m_col)
1211 {
1212 NewtonDestroyCollision(m_col);
1213 m_col = 0;
1214 }
1215
1216 m_col = NewtonCreateConvexHull(m_world->getNewtonWorld(), 5, vertices, sizeof(dFloat) * 3, tolerance, id, &matrix[0]);
1217 if (!m_col)
1218 m_col = NewtonCreateNull(m_world->getNewtonWorld());
1219
1220 delete[]vertices;
1221 }
1222
1223 /*
1224 HeightField::HeightField(const OgreNewt::World *world, int width, int height, int gridsDiagonals, unsigned short *elevationMap, char *attributeMap, Ogre::Real horizontalScale, Ogre::Real verticleScale, int shapeID) : OgreNewt::Collision (world)
1225 {
1226 m_col = NewtonCreateHeightFieldCollision(world->getNewtonWorld(),width,height,gridsDiagonals,elevationMap,attributeMap,float(horizontalScale),float(verticleScale),shapeID);
1227 }
1228
1229 HeightField::HeightField(const OgreNewt::World *world, Ogre::Terrain *terrain, int shapeID) : OgreNewt::Collision (world)
1230 {
1231 int width = terrain->getSize();
1232 int height = width;
1233 int gridsDiagonals = 0;
1234
1235 char *attributes;
1236 unsigned short *elevations;
1237
1238 float *hData = terrain->getHeightData();
1239 float verticleScale = 65535 / (terrain->getMaxHeight() - terrain->getMinHeight());
1240 Ogre::Real horizontalScale = terrain->getWorldSize() / (terrain->getSize() - 1);
1241
1242 elevations = (unsigned short*) malloc (width * height * sizeof (unsigned short));
1243 attributes = (char*) malloc (width * height * sizeof (char));
1244 memset (attributes, 1, width * height * sizeof (char));
1245
1246 //HeightData reversed and mirror on X axis
1247 int x = 0;
1248
1249 for (int i = width * height - 1; i >= 0; i--)
1250 {
1251 elevations[i-width+(x*2)+1] = unsigned short(*(hData)*verticleScale);
1252 hData++;
1253 x++;
1254 if (x == width) x = 0;
1255 }
1256
1257 createHeightFieldCollision(world, width, height, gridsDiagonals, elevations, attributes, horizontalScale, float(1 / verticleScale), shapeID);
1258
1259 free (elevations);
1260 free (attributes);
1261 }
1262
1263 void HeightField::createHeightFieldCollision(const OgreNewt::World *world, int width, int height, int gridsDiagonals, unsigned short *elevationMap, char *attributeMap, Ogre::Real horizontalScale, Ogre::Real verticleScale, int shapeID)
1264 {
1265 m_col = NewtonCreateHeightFieldCollision(world->getNewtonWorld(), width, height, gridsDiagonals, elevationMap, attributeMap, float(horizontalScale), float(verticleScale), shapeID);
1266 }
1267 */
1268 } // end namespace CollisionPrimitives
1269} // end namespace OgreNewt
main class for all Rigid Bodies in the system.
represents a shape for collision detection
NewtonCollision * m_col
NewtonCollision *const getNewtonCollision() const
retrieve the Newton pointer
TreeCollision - complex polygonal collision.
void start(int id)
start a tree collision creation
static dFloat _CDECL newtonRayCastCallback(const NewtonBody *const body, const NewtonCollision *const treeCollision, dFloat distance, dFloat *normal, int faceId, void *userData)
used internally
void AddEntities(const Ogre::SceneNode *node, const Ogre::SceneNode *mainNode, const Ogre::Vector3 scale, FaceWinding fw=FW_DEFAULT)
void setRayCastCallbackactive(bool active=true)
set RayCastCallback active/disabled
void finish(bool optimize)
finish the tree collision
void addPoly(Ogre::Vector3 *polys, unsigned int ID)
add a poly to the tree collision
virtual bool entityFilter(const Ogre::SceneNode *currentNode, const Ogre::Entity *currentEntity, FaceWinding &fw)
this is a user-inherited function that lets you filter which Entities will be added to the treeCollis...
void parseScene(Ogre::SceneNode *startNode, int id, bool optimize=true, FaceWinding fw=FW_DEFAULT)
parse the scene.
represents a collision shape that is explicitly convex.
general raycast
represents a physics world.
NewtonWorld * getNewtonWorld() const
retrieves a pointer to the NewtonWorld
_OgreNewtExport void QuatPosToMatrix(const Ogre::Quaternion &quat, const Ogre::Vector3 &pos, dFloat *matrix)
Take a Quaternion and Position Matrix and create a Newton-happy float matrix!