| 1 |  | 
|---|
| 2 | #include "OgreOdePrecompiledHeaders.h" | 
|---|
| 3 |  | 
|---|
| 4 | #include "OgreOdeEntityInformer.h" | 
|---|
| 5 | #include "OgreOdeMaintainedList.h" | 
|---|
| 6 | #include "OgreOdeBody.h" | 
|---|
| 7 | #include "OgreOdeGeometry.h" | 
|---|
| 8 | #include "OgreOdeMass.h" | 
|---|
| 9 | #include "OgreOdeEigenSolver.h" | 
|---|
| 10 |  | 
|---|
| 11 | using namespace OgreOde; | 
|---|
| 12 | using namespace Ogre; | 
|---|
| 13 |  | 
|---|
| 14 | //------------------------------------------------------------------------------------------------ | 
|---|
| 15 | void EntityInformer::addVertexData(const VertexData *vertex_data, | 
|---|
| 16 |                                    const VertexData *blended_data, | 
|---|
| 17 |                                    const Mesh::IndexMap *indexMap) | 
|---|
| 18 | { | 
|---|
| 19 |         if (!vertex_data)  | 
|---|
| 20 |         return; | 
|---|
| 21 |  | 
|---|
| 22 |         const VertexData *data = (blended_data) ? blended_data: vertex_data; | 
|---|
| 23 |  | 
|---|
| 24 |         const unsigned int prev_size = _vertex_count; | 
|---|
| 25 |     _vertex_count += (unsigned int)data->vertexCount; | 
|---|
| 26 |  | 
|---|
| 27 |     Ogre::Vector3* tmp_vert = new Ogre::Vector3[_vertex_count]; | 
|---|
| 28 |         if (_vertices) | 
|---|
| 29 |         { | 
|---|
| 30 |                 memcpy(tmp_vert,_vertices,sizeof(Vector3) * prev_size); | 
|---|
| 31 |                 delete[] _vertices; | 
|---|
| 32 |         } | 
|---|
| 33 |         _vertices = tmp_vert; | 
|---|
| 34 |  | 
|---|
| 35 |         // Get the positional buffer element | 
|---|
| 36 |     {    | 
|---|
| 37 |         const Ogre::VertexElement* posElem = data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);                         | 
|---|
| 38 |         Ogre::HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(posElem->getSource()); | 
|---|
| 39 |         const unsigned int vSize = (unsigned int)vbuf->getVertexSize(); | 
|---|
| 40 |  | 
|---|
| 41 |             unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); | 
|---|
| 42 |             float* pReal; | 
|---|
| 43 |         Ogre::Vector3 * curVertices = &_vertices[prev_size]; | 
|---|
| 44 |         const unsigned int vertexCount = (unsigned int)data->vertexCount; | 
|---|
| 45 |             for(unsigned int j = 0; j < vertexCount; ++j) | 
|---|
| 46 |             { | 
|---|
| 47 |                     posElem->baseVertexPointerToElement(vertex, &pReal); | 
|---|
| 48 |             vertex += vSize; | 
|---|
| 49 |  | 
|---|
| 50 |                     curVertices->x = (*pReal++); | 
|---|
| 51 |                     curVertices->y = (*pReal++); | 
|---|
| 52 |                     curVertices->z = (*pReal++); | 
|---|
| 53 |  | 
|---|
| 54 |                     *curVertices = _transform * (*curVertices); | 
|---|
| 55 |              | 
|---|
| 56 |             curVertices++; | 
|---|
| 57 |         } | 
|---|
| 58 |             vbuf->unlock(); | 
|---|
| 59 |     } | 
|---|
| 60 |  | 
|---|
| 61 |         // Get the bone index element | 
|---|
| 62 |         if (_entity->hasSkeleton()) | 
|---|
| 63 |         { | 
|---|
| 64 |  | 
|---|
| 65 |         Ogre::MeshPtr mesh = _entity->getMesh (); | 
|---|
| 66 |  | 
|---|
| 67 |                 const Ogre::VertexElement* bneElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_BLEND_INDICES); | 
|---|
| 68 |                 assert (bneElem); | 
|---|
| 69 |                 { | 
|---|
| 70 |             Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(bneElem->getSource()); | 
|---|
| 71 |             const unsigned int vSize = (unsigned int)vbuf->getVertexSize(); | 
|---|
| 72 |                         unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); | 
|---|
| 73 |  | 
|---|
| 74 |                         unsigned char* pBone; | 
|---|
| 75 |  | 
|---|
| 76 |             if (!_bone_mapping) | 
|---|
| 77 |                 _bone_mapping = new BoneMapping();       | 
|---|
| 78 |             BoneMapping::iterator i; | 
|---|
| 79 |  | 
|---|
| 80 |             Ogre::Vector3 * curVertices = &_vertices[prev_size]; | 
|---|
| 81 |              | 
|---|
| 82 |             const unsigned int vertexCount = (unsigned int)vertex_data->vertexCount; | 
|---|
| 83 |                         for(unsigned int j = 0; j < vertexCount; ++j) | 
|---|
| 84 |                         { | 
|---|
| 85 |                                 bneElem->baseVertexPointerToElement(vertex, &pBone); | 
|---|
| 86 |                 vertex += vSize; | 
|---|
| 87 |                 | 
|---|
| 88 |                 const unsigned char currBone = (indexMap) ? (*indexMap)[*pBone] : *pBone; | 
|---|
| 89 |                                 i = _bone_mapping->find (currBone); | 
|---|
| 90 |                                 Vector3Array* l = 0; | 
|---|
| 91 |                                 if (i == _bone_mapping->end()) | 
|---|
| 92 |                                 { | 
|---|
| 93 |                                         l = new Vector3Array; | 
|---|
| 94 |                                         _bone_mapping->insert(BoneMappingKey(currBone, l)); | 
|---|
| 95 |                                 }                                                | 
|---|
| 96 |                                 else  | 
|---|
| 97 |                 { | 
|---|
| 98 |                     l = i->second; | 
|---|
| 99 |                 } | 
|---|
| 100 |  | 
|---|
| 101 |                                 l->push_back(*curVertices); | 
|---|
| 102 |  | 
|---|
| 103 |                 curVertices++; | 
|---|
| 104 |                         } | 
|---|
| 105 |                         vbuf->unlock(); | 
|---|
| 106 |                 } | 
|---|
| 107 |         } | 
|---|
| 108 | } | 
|---|
| 109 |  | 
|---|
| 110 |  | 
|---|
| 111 | //------------------------------------------------------------------------------------------------ | 
|---|
| 112 | void EntityInformer::addIndexData(IndexData *data, const unsigned int offset) | 
|---|
| 113 | { | 
|---|
| 114 |     const unsigned int prev_size = _index_count; | 
|---|
| 115 |     _index_count += (unsigned int)data->indexCount; | 
|---|
| 116 |  | 
|---|
| 117 |         unsigned int* tmp_ind = new unsigned int[_index_count]; | 
|---|
| 118 |         if (_indices) | 
|---|
| 119 |         { | 
|---|
| 120 |                 memcpy (tmp_ind, _indices, sizeof(unsigned int) * prev_size); | 
|---|
| 121 |                 delete[] _indices; | 
|---|
| 122 |         } | 
|---|
| 123 |         _indices = tmp_ind; | 
|---|
| 124 |  | 
|---|
| 125 |         const unsigned int numTris = (unsigned int) data->indexCount / 3; | 
|---|
| 126 |         HardwareIndexBufferSharedPtr ibuf = data->indexBuffer;   | 
|---|
| 127 |         const bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT); | 
|---|
| 128 |     unsigned int index_offset = prev_size; | 
|---|
| 129 |  | 
|---|
| 130 |         if (use32bitindexes)  | 
|---|
| 131 |     { | 
|---|
| 132 |         const unsigned int* pInt = static_cast<unsigned int*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); | 
|---|
| 133 |         for(unsigned int k = 0; k < numTris; ++k) | 
|---|
| 134 |         { | 
|---|
| 135 |             _indices[index_offset ++] = offset + *pInt++; | 
|---|
| 136 |             _indices[index_offset ++] = offset + *pInt++; | 
|---|
| 137 |             _indices[index_offset ++] = offset + *pInt++; | 
|---|
| 138 |         } | 
|---|
| 139 |         ibuf->unlock(); | 
|---|
| 140 |     } | 
|---|
| 141 |         else  | 
|---|
| 142 |     { | 
|---|
| 143 |         const unsigned short* pShort = static_cast<unsigned short*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); | 
|---|
| 144 |                 for(unsigned int k = 0; k < numTris; ++k) | 
|---|
| 145 |         { | 
|---|
| 146 |             _indices[index_offset ++] = offset + static_cast<unsigned int> (*pShort++); | 
|---|
| 147 |             _indices[index_offset ++] = offset + static_cast<unsigned int> (*pShort++); | 
|---|
| 148 |             _indices[index_offset ++] = offset + static_cast<unsigned int> (*pShort++); | 
|---|
| 149 |         } | 
|---|
| 150 |         ibuf->unlock(); | 
|---|
| 151 |     } | 
|---|
| 152 |  | 
|---|
| 153 | } | 
|---|
| 154 | //------------------------------------------------------------------------------------------------ | 
|---|
| 155 | void EntityInformer::addEntity(Entity *entity,const Matrix4 &transform) | 
|---|
| 156 | { | 
|---|
| 157 |         // Each entity added need to reset size and radius | 
|---|
| 158 |         // next time getRadius and getSize are asked, they're computed. | 
|---|
| 159 |         _size  = Ogre::Vector3(-1,-1,-1); | 
|---|
| 160 |         _radius = -1; | 
|---|
| 161 |  | 
|---|
| 162 |         _entity = entity; | 
|---|
| 163 |         _node = (SceneNode*)(_entity->getParentNode()); | 
|---|
| 164 |         _transform = transform; | 
|---|
| 165 |  | 
|---|
| 166 |         const bool isSkeletonAnimated = _entity->hasSkeleton(); | 
|---|
| 167 |         //const bool isHWanimated = isSkeletonAnimated && entity->isHardwareAnimationEnabled(); | 
|---|
| 168 |         if (isSkeletonAnimated) | 
|---|
| 169 |         { | 
|---|
| 170 |                 _entity->addSoftwareAnimationRequest(false); | 
|---|
| 171 |                 _entity->_updateAnimation(); | 
|---|
| 172 |         } | 
|---|
| 173 |  | 
|---|
| 174 |  | 
|---|
| 175 |         if (_entity->getMesh()->sharedVertexData) | 
|---|
| 176 |         { | 
|---|
| 177 |                 if (!isSkeletonAnimated) | 
|---|
| 178 |                         addVertexData (_entity->getMesh()->sharedVertexData); | 
|---|
| 179 |                 else | 
|---|
| 180 |                         addVertexData (_entity->getMesh()->sharedVertexData,  | 
|---|
| 181 |                         _entity->_getSkelAnimVertexData(), | 
|---|
| 182 |                         &_entity->getMesh()->sharedBlendIndexToBoneIndexMap);  | 
|---|
| 183 |         } | 
|---|
| 184 |  | 
|---|
| 185 |         for(unsigned int i = 0;i < _entity->getNumSubEntities();++i) | 
|---|
| 186 |         { | 
|---|
| 187 |                 SubMesh *sub_mesh = _entity->getSubEntity(i)->getSubMesh(); | 
|---|
| 188 |  | 
|---|
| 189 |                 if (!sub_mesh->useSharedVertices) | 
|---|
| 190 |                 { | 
|---|
| 191 |                         addIndexData(sub_mesh->indexData,_vertex_count); | 
|---|
| 192 |  | 
|---|
| 193 |                         if (!isSkeletonAnimated) | 
|---|
| 194 |                                 addVertexData (sub_mesh->vertexData); | 
|---|
| 195 |                         else | 
|---|
| 196 |                                 addVertexData (sub_mesh->vertexData,  | 
|---|
| 197 |                                 _entity->getSubEntity(i)->_getSkelAnimVertexData(), | 
|---|
| 198 |                                 &sub_mesh->blendIndexToBoneIndexMap);  | 
|---|
| 199 |                 } | 
|---|
| 200 |                 else  | 
|---|
| 201 |                 { | 
|---|
| 202 |                         addIndexData (sub_mesh->indexData); | 
|---|
| 203 |                 } | 
|---|
| 204 |  | 
|---|
| 205 |         } | 
|---|
| 206 |  | 
|---|
| 207 |         if (isSkeletonAnimated)  | 
|---|
| 208 |                 _entity->removeSoftwareAnimationRequest(false); | 
|---|
| 209 | } | 
|---|
| 210 | //------------------------------------------------------------------------------------------------ | 
|---|
| 211 | void EntityInformer::addMesh(const MeshPtr &mesh, const Matrix4 &transform) | 
|---|
| 212 | { | 
|---|
| 213 |         // Each entity added need to reset size and radius | 
|---|
| 214 |         // next time getRadius and getSize are asked, they're computed. | 
|---|
| 215 |         _size  = Ogre::Vector3(-1,-1,-1); | 
|---|
| 216 |         _radius = -1; | 
|---|
| 217 |  | 
|---|
| 218 |         //_entity = entity; | 
|---|
| 219 |         //_node = (SceneNode*)(_entity->getParentNode()); | 
|---|
| 220 |         _transform = transform; | 
|---|
| 221 |  | 
|---|
| 222 |         if (mesh->hasSkeleton ()) | 
|---|
| 223 |                 Ogre::LogManager::getSingleton().logMessage("EntityInformer::addMesh : Mesh " + mesh->getName () + " as skeleton but added to trimesh non animated"); | 
|---|
| 224 | //              OGRE_EXCEPT(1, "Mesh " + mesh->getName () + " as skeleton but added to trimesh non animated",  | 
|---|
| 225 | //                                      "EntityInformer::addMesh"); | 
|---|
| 226 |  | 
|---|
| 227 |         if (mesh->sharedVertexData) | 
|---|
| 228 |         { | 
|---|
| 229 |                 addVertexData (mesh->sharedVertexData); | 
|---|
| 230 |         } | 
|---|
| 231 |  | 
|---|
| 232 |         for(unsigned int i = 0;i < mesh->getNumSubMeshes();++i) | 
|---|
| 233 |         { | 
|---|
| 234 |                 SubMesh *sub_mesh = mesh->getSubMesh(i); | 
|---|
| 235 |  | 
|---|
| 236 |                 if (!sub_mesh->useSharedVertices) | 
|---|
| 237 |                 { | 
|---|
| 238 |                         addIndexData(sub_mesh->indexData, _vertex_count); | 
|---|
| 239 |                         addVertexData (sub_mesh->vertexData); | 
|---|
| 240 |                 } | 
|---|
| 241 |                 else  | 
|---|
| 242 |                 { | 
|---|
| 243 |                         addIndexData (sub_mesh->indexData); | 
|---|
| 244 |                 } | 
|---|
| 245 |  | 
|---|
| 246 |         } | 
|---|
| 247 | } | 
|---|
| 248 | //------------------------------------------------------------------------------------------------ | 
|---|
| 249 | EntityInformer::EntityInformer(Entity *entity,const Matrix4 &transform) : | 
|---|
| 250 |         _vertices (0), | 
|---|
| 251 |         _indices (0), | 
|---|
| 252 |         _vertex_count (0), | 
|---|
| 253 |         _index_count (0), | 
|---|
| 254 |         _size (Vector3(-1,-1,-1)), | 
|---|
| 255 |         _radius (-1), | 
|---|
| 256 |         _bone_mapping (0) | 
|---|
| 257 | { | 
|---|
| 258 |         addEntity(entity, transform);    | 
|---|
| 259 | } | 
|---|
| 260 | //------------------------------------------------------------------------------------------------ | 
|---|
| 261 | EntityInformer::EntityInformer() : | 
|---|
| 262 |                 _vertices (0), | 
|---|
| 263 |                 _indices (0), | 
|---|
| 264 |                 _vertex_count (0), | 
|---|
| 265 |                 _index_count (0), | 
|---|
| 266 |                 _size (Vector3(-1,-1,-1)), | 
|---|
| 267 |                 _radius (-1), | 
|---|
| 268 |         _bone_mapping (0) | 
|---|
| 269 | { | 
|---|
| 270 |          | 
|---|
| 271 | } | 
|---|
| 272 | //------------------------------------------------------------------------------------------------ | 
|---|
| 273 | Real EntityInformer::getRadius() | 
|---|
| 274 | { | 
|---|
| 275 |         if (_radius == (-1)) | 
|---|
| 276 |         { | 
|---|
| 277 |                 getSize(); | 
|---|
| 278 |                 _radius = (std::max(_size.x,std::max(_size.y,_size.z)) * 0.5); | 
|---|
| 279 |         } | 
|---|
| 280 |         return _radius; | 
|---|
| 281 | } | 
|---|
| 282 | //------------------------------------------------------------------------------------------------ | 
|---|
| 283 | Vector3 EntityInformer::getSize() | 
|---|
| 284 | { | 
|---|
| 285 |     const unsigned int vCount = getVertexCount(); | 
|---|
| 286 |         if (_size == Ogre::Vector3(-1,-1,-1) && vCount > 0) | 
|---|
| 287 |         { | 
|---|
| 288 |  | 
|---|
| 289 |                 const Ogre::Vector3 * const v = getVertices(); | 
|---|
| 290 |  | 
|---|
| 291 |         Ogre::Vector3 vmin(v[0]); | 
|---|
| 292 |         Ogre::Vector3 vmax(v[0]); | 
|---|
| 293 |  | 
|---|
| 294 |                 for(unsigned int j = 1; j < vCount; j++) | 
|---|
| 295 |                 { | 
|---|
| 296 |                         vmin.x = std::min(vmin.x, v[j].x); | 
|---|
| 297 |                         vmin.y = std::min(vmin.y, v[j].y); | 
|---|
| 298 |                         vmin.z = std::min(vmin.z, v[j].z); | 
|---|
| 299 |  | 
|---|
| 300 |                         vmax.x = std::max(vmax.x, v[j].x); | 
|---|
| 301 |                         vmax.y = std::max(vmax.y, v[j].y); | 
|---|
| 302 |                         vmax.z = std::max(vmax.z, v[j].z); | 
|---|
| 303 |                 } | 
|---|
| 304 |  | 
|---|
| 305 |                 _size.x = vmax.x - vmin.x; | 
|---|
| 306 |                 _size.y = vmax.y - vmin.y; | 
|---|
| 307 |                 _size.z = vmax.z - vmin.z; | 
|---|
| 308 |         } | 
|---|
| 309 |  | 
|---|
| 310 |         return _size; | 
|---|
| 311 | } | 
|---|
| 312 | //------------------------------------------------------------------------------------------------ | 
|---|
| 313 | const Ogre::Vector3* EntityInformer::getVertices() | 
|---|
| 314 | { | 
|---|
| 315 |         return _vertices; | 
|---|
| 316 | } | 
|---|
| 317 | //------------------------------------------------------------------------------------------------ | 
|---|
| 318 | unsigned int EntityInformer::getVertexCount() | 
|---|
| 319 | { | 
|---|
| 320 |         return _vertex_count; | 
|---|
| 321 | } | 
|---|
| 322 | //------------------------------------------------------------------------------------------------ | 
|---|
| 323 | const unsigned int* EntityInformer::getIndices() | 
|---|
| 324 | { | 
|---|
| 325 |         return _indices; | 
|---|
| 326 | } | 
|---|
| 327 | //------------------------------------------------------------------------------------------------ | 
|---|
| 328 | unsigned int EntityInformer::getIndexCount() | 
|---|
| 329 | { | 
|---|
| 330 |         return _index_count; | 
|---|
| 331 | } | 
|---|
| 332 | //------------------------------------------------------------------------------------------------ | 
|---|
| 333 | Body* EntityInformer::createSingleDynamicSphere(Real mass, World *world, Space* space) | 
|---|
| 334 | { | 
|---|
| 335 |         const Ogre::Real rad = getRadius(); | 
|---|
| 336 |  | 
|---|
| 337 |         assert((rad > 0.0) &&  | 
|---|
| 338 |         ("Sphere radius must be greater than zero")); | 
|---|
| 339 |  | 
|---|
| 340 |         Body* body = new Body(world, "OgreOde::Body_" + _entity->getName()); | 
|---|
| 341 |         body->setMass(SphereMass(mass, rad)); | 
|---|
| 342 |  | 
|---|
| 343 |         SphereGeometry* geom = new SphereGeometry(rad, world, space); | 
|---|
| 344 |         geom->setBody(body); | 
|---|
| 345 |  | 
|---|
| 346 |         body->setPosition(_node->getPosition()); | 
|---|
| 347 |         body->setOrientation(_node->getOrientation()); | 
|---|
| 348 |  | 
|---|
| 349 |         _node->attachObject(body); | 
|---|
| 350 |  | 
|---|
| 351 |         return body; | 
|---|
| 352 | } | 
|---|
| 353 | //------------------------------------------------------------------------------------------------ | 
|---|
| 354 | Body* EntityInformer::createSingleDynamicBox(Real mass, World *world, Space* space) | 
|---|
| 355 | { | 
|---|
| 356 |         const Ogre::Vector3 sz = getSize(); | 
|---|
| 357 |  | 
|---|
| 358 |         assert((sz.x > 0.0) && (sz.y > 0.0) && (sz.y > 0.0) &&  | 
|---|
| 359 |         ("Size of box must be greater than zero on all axes")); | 
|---|
| 360 |  | 
|---|
| 361 |         Body* body = new Body(world, "OgreOde::Body_" + _node->getName()); | 
|---|
| 362 |         body->setMass(BoxMass(mass,sz)); | 
|---|
| 363 |  | 
|---|
| 364 |         BoxGeometry* geom = new BoxGeometry(sz, world, space); | 
|---|
| 365 |         geom->setBody(body); | 
|---|
| 366 |  | 
|---|
| 367 |         body->setPosition(_node->getPosition()); | 
|---|
| 368 |         body->setOrientation(_node->getOrientation()); | 
|---|
| 369 |  | 
|---|
| 370 |         _node->attachObject(body); | 
|---|
| 371 |  | 
|---|
| 372 |         return body; | 
|---|
| 373 | } | 
|---|
| 374 | //------------------------------------------------------------------------------------------------ | 
|---|
| 375 | TriangleMeshGeometry* EntityInformer::createStaticTriangleMesh(World *world, Space* space) | 
|---|
| 376 | { | 
|---|
| 377 |         assert(_vertex_count && (_index_count >= 6) &&  | 
|---|
| 378 |         ("Mesh must have some vertices and at least 6 indices (2 triangles)")); | 
|---|
| 379 |  | 
|---|
| 380 |         return new TriangleMeshGeometry(_vertices, _vertex_count,_indices, _index_count, world, space); | 
|---|
| 381 | } | 
|---|
| 382 | //------------------------------------------------------------------------------------------------ | 
|---|
| 383 | BoxGeometry* EntityInformer::createSingleStaticBox(World *world, Space* space) | 
|---|
| 384 | { | 
|---|
| 385 |         BoxGeometry* geom = new BoxGeometry(getSize(), world, space); | 
|---|
| 386 |  | 
|---|
| 387 |         geom->setPosition(_node->getPosition()); | 
|---|
| 388 |         geom->setOrientation(_node->getOrientation()); | 
|---|
| 389 |  | 
|---|
| 390 |         return geom; | 
|---|
| 391 | } | 
|---|
| 392 | //------------------------------------------------------------------------------------------------ | 
|---|
| 393 | bool EntityInformer::getBoneVertices(unsigned char bone, unsigned int &vertex_count, Ogre::Vector3* &vertices) | 
|---|
| 394 | { | 
|---|
| 395 |         BoneMapping::iterator i = _bone_mapping->find(bone); | 
|---|
| 396 |          | 
|---|
| 397 |     if (i == _bone_mapping->end())  | 
|---|
| 398 |         return false; | 
|---|
| 399 |  | 
|---|
| 400 |         if (i->second->empty())  | 
|---|
| 401 |         return false; | 
|---|
| 402 |  | 
|---|
| 403 |     vertex_count = (unsigned int) i->second->size() + 1; | 
|---|
| 404 |  | 
|---|
| 405 |         vertices = new Ogre::Vector3[vertex_count]; | 
|---|
| 406 |         vertices[0] = _entity->_getParentNodeFullTransform() *  | 
|---|
| 407 |             _entity->getSkeleton()->getBone(bone)->_getDerivedPosition(); | 
|---|
| 408 |  | 
|---|
| 409 |         unsigned int o = 1; | 
|---|
| 410 |         for(Vector3Array::iterator j = i->second->begin(); | 
|---|
| 411 |         j != i->second->end(); ++j,++o)  | 
|---|
| 412 |     { | 
|---|
| 413 |         vertices[o] = (*j); | 
|---|
| 414 |     }        | 
|---|
| 415 |         return true; | 
|---|
| 416 | } | 
|---|
| 417 | //------------------------------------------------------------------------------------------------ | 
|---|
| 418 | BoxGeometry* EntityInformer::createAlignedBox(unsigned char bone, World *world, Space* space) | 
|---|
| 419 | { | 
|---|
| 420 |         unsigned int vertex_count; | 
|---|
| 421 |         Vector3* vertices; | 
|---|
| 422 |         if (!getBoneVertices(bone, vertex_count, vertices))  | 
|---|
| 423 |         return 0; | 
|---|
| 424 |  | 
|---|
| 425 |         Vector3 min_vec(vertices[0]); | 
|---|
| 426 |         Vector3 max_vec(vertices[0]); | 
|---|
| 427 |  | 
|---|
| 428 |         for(unsigned int j = 1; j < vertex_count ;j++) | 
|---|
| 429 |         { | 
|---|
| 430 |                 min_vec.x = std::min(min_vec.x,vertices[j].x); | 
|---|
| 431 |                 min_vec.y = std::min(min_vec.y,vertices[j].y); | 
|---|
| 432 |                 min_vec.z = std::min(min_vec.z,vertices[j].z); | 
|---|
| 433 |  | 
|---|
| 434 |                 max_vec.x = std::max(max_vec.x,vertices[j].x); | 
|---|
| 435 |                 max_vec.y = std::max(max_vec.y,vertices[j].y); | 
|---|
| 436 |                 max_vec.z = std::max(max_vec.z,vertices[j].z); | 
|---|
| 437 |         } | 
|---|
| 438 |     const Ogre::Vector3 maxMinusMin(max_vec - min_vec); | 
|---|
| 439 |     BoxGeometry* box = new BoxGeometry(maxMinusMin, world, space); | 
|---|
| 440 |  | 
|---|
| 441 |     const Ogre::Vector3 pos(min_vec.x + (maxMinusMin.x * 0.5), | 
|---|
| 442 |                       min_vec.y + (maxMinusMin.y * 0.5), | 
|---|
| 443 |                       min_vec.z + (maxMinusMin.z * 0.5)); | 
|---|
| 444 |  | 
|---|
| 445 |         box->setPosition(pos); | 
|---|
| 446 |  | 
|---|
| 447 |         delete[] vertices; | 
|---|
| 448 |  | 
|---|
| 449 |         return box; | 
|---|
| 450 | } | 
|---|
| 451 | //------------------------------------------------------------------------------------------------ | 
|---|
| 452 | BoxGeometry* EntityInformer::createOrientedBox(unsigned char bone, World *world, Space* space) | 
|---|
| 453 | { | 
|---|
| 454 |         unsigned int vertex_count; | 
|---|
| 455 |         Vector3* vertices; | 
|---|
| 456 |         if (!getBoneVertices(bone, vertex_count, vertices))  | 
|---|
| 457 |         return 0; | 
|---|
| 458 |  | 
|---|
| 459 |         Vector3 box_kCenter; | 
|---|
| 460 |     Ogre::Vector3 box_akAxis[3]; | 
|---|
| 461 |    Ogre::Real box_afExtent[3]; | 
|---|
| 462 |  | 
|---|
| 463 |         EigenSolver::GaussPointsFit (vertex_count, vertices, box_kCenter, box_akAxis, box_afExtent); | 
|---|
| 464 |  | 
|---|
| 465 |     // Let C be the box center and let U0, U1, and U2 be the box axes.  Each | 
|---|
| 466 |     // input point is of the form X = C + y0*U0 + y1*U1 + y2*U2.  The | 
|---|
| 467 |     // following code computes min(y0), max(y0), min(y1), max(y1), min(y2), | 
|---|
| 468 |     // and max(y2).  The box center is then adjusted to be | 
|---|
| 469 |     //   C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1 + | 
|---|
| 470 |     //        0.5*(min(y2)+max(y2))*U2 | 
|---|
| 471 |  | 
|---|
| 472 |     Ogre::Vector3 kDiff (vertices[0] - box_kCenter); | 
|---|
| 473 |    Ogre::Real fY0Min = kDiff.dotProduct(box_akAxis[0]), fY0Max = fY0Min; | 
|---|
| 474 |    Ogre::Real fY1Min = kDiff.dotProduct(box_akAxis[1]), fY1Max = fY1Min; | 
|---|
| 475 |    Ogre::Real fY2Min = kDiff.dotProduct(box_akAxis[2]), fY2Max = fY2Min; | 
|---|
| 476 |  | 
|---|
| 477 |     for (unsigned int i = 1; i < vertex_count; i++) | 
|---|
| 478 |     { | 
|---|
| 479 |         kDiff = vertices[i] - box_kCenter; | 
|---|
| 480 |  | 
|---|
| 481 |         const Ogre::Real fY0 = kDiff.dotProduct(box_akAxis[0]); | 
|---|
| 482 |         if ( fY0 < fY0Min ) | 
|---|
| 483 |             fY0Min = fY0; | 
|---|
| 484 |         else if ( fY0 > fY0Max ) | 
|---|
| 485 |             fY0Max = fY0; | 
|---|
| 486 |  | 
|---|
| 487 |         const Ogre::Real fY1 = kDiff.dotProduct(box_akAxis[1]); | 
|---|
| 488 |         if ( fY1 < fY1Min ) | 
|---|
| 489 |             fY1Min = fY1; | 
|---|
| 490 |         else if ( fY1 > fY1Max ) | 
|---|
| 491 |             fY1Max = fY1; | 
|---|
| 492 |  | 
|---|
| 493 |         const Ogre::Real fY2 = kDiff.dotProduct(box_akAxis[2]); | 
|---|
| 494 |         if ( fY2 < fY2Min ) | 
|---|
| 495 |             fY2Min = fY2; | 
|---|
| 496 |         else if ( fY2 > fY2Max ) | 
|---|
| 497 |             fY2Max = fY2; | 
|---|
| 498 |     } | 
|---|
| 499 |  | 
|---|
| 500 |     box_afExtent[0] = ((Real)0.5)*(fY0Max - fY0Min); | 
|---|
| 501 |     box_afExtent[1] = ((Real)0.5)*(fY1Max - fY1Min); | 
|---|
| 502 |     box_afExtent[2] = ((Real)0.5)*(fY2Max - fY2Min); | 
|---|
| 503 |  | 
|---|
| 504 |     box_kCenter += (box_afExtent[0])*box_akAxis[0] + | 
|---|
| 505 |                    (box_afExtent[1])*box_akAxis[1] + | 
|---|
| 506 |                    (box_afExtent[2])*box_akAxis[2]; | 
|---|
| 507 |  | 
|---|
| 508 |         BoxGeometry *geom = new BoxGeometry(Vector3(box_afExtent[0] * 2.0, | 
|---|
| 509 |                                                 box_afExtent[1] * 2.0, | 
|---|
| 510 |                                                 box_afExtent[2] * 2.0), | 
|---|
| 511 |                                         world, space); | 
|---|
| 512 |         geom->setOrientation(Quaternion(box_akAxis[0],box_akAxis[1],box_akAxis[2])); | 
|---|
| 513 |         geom->setPosition(box_kCenter); | 
|---|
| 514 |         return geom; | 
|---|
| 515 | } | 
|---|
| 516 | //------------------------------------------------------------------------------------------------ | 
|---|
| 517 | CapsuleGeometry* EntityInformer::createOrientedCapsule(unsigned char bone, World *world, Space* space) | 
|---|
| 518 | { | 
|---|
| 519 |         unsigned int vertex_count; | 
|---|
| 520 |         Vector3* vertices; | 
|---|
| 521 |  | 
|---|
| 522 |         if (!getBoneVertices(bone,vertex_count,vertices))  | 
|---|
| 523 |         return 0; | 
|---|
| 524 |  | 
|---|
| 525 |         Vector3 cap_orig; | 
|---|
| 526 |         Vector3 cap_dir; | 
|---|
| 527 |         Real cap_rad; | 
|---|
| 528 |  | 
|---|
| 529 |         Vector3 line_orig; | 
|---|
| 530 |         Vector3 line_dir; | 
|---|
| 531 |  | 
|---|
| 532 |         EigenSolver::orthogonalLineFit (vertex_count, vertices, line_orig, line_dir); | 
|---|
| 533 |  | 
|---|
| 534 |    Ogre::Real fMaxRadiusSqr = (Real) 0.0; | 
|---|
| 535 |     unsigned int c; | 
|---|
| 536 |     for (c = 0; c < vertex_count; c++) | 
|---|
| 537 |     { | 
|---|
| 538 |                 const Ogre::Real fRadiusSqr = EigenSolver::SqrDistance(vertices[c], line_orig, line_dir); | 
|---|
| 539 |         if ( fRadiusSqr > fMaxRadiusSqr )  | 
|---|
| 540 |             fMaxRadiusSqr = fRadiusSqr; | 
|---|
| 541 |     } | 
|---|
| 542 |  | 
|---|
| 543 |     Ogre::Vector3 kU, kV, kW = line_dir; | 
|---|
| 544 |         EigenSolver::GenerateOrthonormalBasis (kU, kV, kW, true); | 
|---|
| 545 |  | 
|---|
| 546 |    Ogre::Real fMin = FLT_MAX, fMax = -fMin; | 
|---|
| 547 |     for (c = 0; c < vertex_count; c++) | 
|---|
| 548 |     { | 
|---|
| 549 |         const  Ogre::Vector3 kDiff (vertices[c] - line_orig); | 
|---|
| 550 |         const Ogre::Real fU = kU.dotProduct (kDiff); | 
|---|
| 551 |         const Ogre::Real fV = kV.dotProduct (kDiff); | 
|---|
| 552 |         const Ogre::Real fW = kW.dotProduct (kDiff); | 
|---|
| 553 |         const Ogre::Real fDiscr = fMaxRadiusSqr - (fU*fU + fV*fV); | 
|---|
| 554 |         const Ogre::Real fRadical = sqrtf(fabs(fDiscr)); | 
|---|
| 555 |  | 
|---|
| 556 |         fMin = std::min(fW + fRadical, fMin); | 
|---|
| 557 |         fMax = std::max(fW - fRadical, fMax); | 
|---|
| 558 |     } | 
|---|
| 559 |  | 
|---|
| 560 |     if ( fMin < fMax ) | 
|---|
| 561 |     { | 
|---|
| 562 |         cap_orig = line_orig + fMin*line_dir; | 
|---|
| 563 |         cap_dir = (fMax-fMin)*line_dir; | 
|---|
| 564 |     } | 
|---|
| 565 |     else | 
|---|
| 566 |     { | 
|---|
| 567 |         // enclosing capsule is really a sphere | 
|---|
| 568 |         cap_orig = line_orig + (((Real)0.5)*(fMin+fMax))*line_dir; | 
|---|
| 569 |         //---------------------------- | 
|---|
| 570 |         cap_dir = Ogre::Vector3::ZERO; | 
|---|
| 571 |         //cap_dir = (fMax-fMin)*line_dir; | 
|---|
| 572 |     } | 
|---|
| 573 |  | 
|---|
| 574 |     cap_rad = sqrtf(fMaxRadiusSqr); | 
|---|
| 575 |  | 
|---|
| 576 |  | 
|---|
| 577 |     CapsuleGeometry* geom = 0; | 
|---|
| 578 |     const Ogre::Real cap_dirLength = cap_dir.length(); | 
|---|
| 579 |     if (cap_rad > 0 && cap_dirLength > 0) | 
|---|
| 580 |     { | 
|---|
| 581 |         const Ogre::Vector3 orig_axis (Vector3::UNIT_Z); | 
|---|
| 582 |         const Ogre::Vector3 reqd_axis (cap_dir.normalisedCopy()); | 
|---|
| 583 |         const Ogre::Vector3 rot_axis (orig_axis.crossProduct(reqd_axis)); | 
|---|
| 584 |         const Ogre::Real cos_ang = orig_axis.dotProduct(reqd_axis); | 
|---|
| 585 |        Ogre::Real ang = acos(cos_ang); | 
|---|
| 586 |         if (cos_ang < 0.0)  | 
|---|
| 587 |             ang -= M_PI; | 
|---|
| 588 |  | 
|---|
| 589 |         const Ogre::Quaternion orient = Ogre::Quaternion(Radian(ang),rot_axis); | 
|---|
| 590 |  | 
|---|
| 591 |         geom = new CapsuleGeometry(cap_rad, cap_dirLength, world, space); | 
|---|
| 592 |         geom->setOrientation(orient); | 
|---|
| 593 |         geom->setPosition(cap_orig + (reqd_axis * (cap_dirLength * 0.5))); | 
|---|
| 594 |     } | 
|---|
| 595 |         return geom; | 
|---|
| 596 | } | 
|---|
| 597 | //------------------------------------------------------------------------------------------------ | 
|---|
| 598 | EntityInformer::~EntityInformer() | 
|---|
| 599 | { | 
|---|
| 600 |         delete[] _vertices; | 
|---|
| 601 |         delete[] _indices; | 
|---|
| 602 |  | 
|---|
| 603 |         if (_bone_mapping) | 
|---|
| 604 |         { | 
|---|
| 605 |                 for(BoneMapping::iterator i = _bone_mapping->begin(); | 
|---|
| 606 |             i != _bone_mapping->end(); | 
|---|
| 607 |             ++i) | 
|---|
| 608 |                 { | 
|---|
| 609 |                         delete i->second; | 
|---|
| 610 |                 } | 
|---|
| 611 |                 delete _bone_mapping; | 
|---|
| 612 |         } | 
|---|
| 613 | } | 
|---|