SO3Engine
SO3RayCast.cpp
Go to the documentation of this file.
1/*
2-----------------------------------------------------------------------------
3This source file is part of OpenSpace3D
4For the latest info, see http://www.openspace3d.com
5
6Copyright (c) 2012 I-maginer
7
8This program is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License as published by the Free Software
10Foundation; either version 2 of the License, or (at your option) any later
11version.
12
13This program is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public License along with
18this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20http://www.gnu.org/copyleft/lesser.txt
21
22-----------------------------------------------------------------------------
23*/
24
25#include "SO3Utils/SO3RayCast.h"
29
30namespace SO3
31{
32
38{
39 scene = 0;
40 sceneName = "";
41 viewport = 0;
42 entity = 0;
43 entityName = "";
44 material = 0;
45 indexSubEntity = -1;
46
47 closestDistance = -1.0f;
48 point = Ogre::Vector3::ZERO;
49 indexFace = 0;
50 v1 = Ogre::Vector3::ZERO;
51 v2 = Ogre::Vector3::ZERO;
52 v3 = Ogre::Vector3::ZERO;
53 pReal1 = Ogre::Vector2::ZERO;
54 pReal2 = Ogre::Vector2::ZERO;
55 pReal3 = Ogre::Vector2::ZERO;
56 uvResult = Ogre::Vector2(0.0f, 0.0f);
57}
58
60{
61 scene = copiedRaycast.scene;
62 sceneName = copiedRaycast.sceneName;
63 viewport = copiedRaycast.viewport;
64 entity = copiedRaycast.entity;
65 entityName = copiedRaycast.entityName;
66 material = copiedRaycast.material;
67
68 closestDistance = copiedRaycast.closestDistance;
69 point = copiedRaycast.point;
70 indexSubEntity = copiedRaycast.indexSubEntity;
71 indexFace = copiedRaycast.indexFace;
72 v1 = copiedRaycast.v1;
73 v2 = copiedRaycast.v2;
74 v3 = copiedRaycast.v3;
75 pReal1 = copiedRaycast.pReal1;
76 pReal2 = copiedRaycast.pReal2;
77 pReal3 = copiedRaycast.pReal3;
78 uvResult = copiedRaycast.uvResult;
79}
80
81SRaycast::SRaycast()
82{
83 // Private constructor
84}
85
86void SRaycast::GetMeshInformation(const Ogre::MeshPtr mesh,
87 size_t &vertex_count,
88 Ogre::Vector3* &vertices,
89 size_t &index_count,
90 unsigned long* &indices,
91 const Ogre::Vector3 &position,
92 const Ogre::Quaternion &orient,
93 const Ogre::Vector3 &scale)
94{
95 bool added_shared = false;
96 size_t current_offset = 0;
97 size_t shared_offset = 0;
98 size_t next_offset = 0;
99 size_t index_offset = 0;
100
101 vertex_count = index_count = 0;
102
103 // Calculate how many vertices and indices we're going to need
104 for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
105 {
106 Ogre::SubMesh* submesh = mesh->getSubMesh(i);
107 // We only need to add the shared vertices once
108 if (submesh->useSharedVertices)
109 {
110 if (!added_shared)
111 {
112 vertex_count += mesh->sharedVertexData->vertexCount;
113 added_shared = true;
114 }
115 }
116 else
117 {
118 vertex_count += submesh->vertexData->vertexCount;
119 }
120 // Add the indices
121 index_count += submesh->indexData->indexCount;
122 }
123
124 // Allocate space for the vertices and indices
125 vertices = new Ogre::Vector3[vertex_count];
126 indices = new unsigned long[index_count];
127
128 added_shared = false;
129
130 // Run through the submeshes again, adding the data into the arrays
131 for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
132 {
133 Ogre::SubMesh* submesh = mesh->getSubMesh(i);
134
135 Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
136
137 if ((!submesh->useSharedVertices) || (submesh->useSharedVertices && !added_shared))
138 {
139 if (submesh->useSharedVertices)
140 {
141 added_shared = true;
142 shared_offset = current_offset;
143 }
144
145 const Ogre::VertexElement* posElem =
146 vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
147
148 Ogre::HardwareVertexBufferSharedPtr vbuf =
149 vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
150
151 unsigned char* vertex =
152 static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
153
154 // There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
155 // as second argument. So make it float, to avoid trouble when Ogre::Real will
156 // be comiled/typedefed as double:
157 //Ogre::Real* pReal;
158 float* pReal;
159
160 for (size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
161 {
162 posElem->baseVertexPointerToElement(vertex, &pReal);
163 Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]);
164 vertices[current_offset + j] = (orient * (pt * scale)) + position;
165 }
166
167 vbuf->unlock();
168 next_offset += vertex_data->vertexCount;
169 }
170
171 Ogre::IndexData* index_data = submesh->indexData;
172 size_t numTris = index_data->indexCount / 3;
173 Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
174
175 bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
176 size_t offset = (submesh->useSharedVertices) ? shared_offset : current_offset;
177
178 if (use32bitindexes)
179 {
180 Ogre::uint32* pLong = static_cast<Ogre::uint32*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
181 for (size_t k = 0; k < numTris * 3; ++k)
182 {
183 indices[index_offset++] = pLong[k] + static_cast<unsigned long>(offset);
184 }
185 }
186 else
187 {
188 Ogre::uint16* pShort = static_cast<Ogre::uint16*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
189 for (size_t k = 0; k < numTris * 3; ++k)
190 {
191 indices[index_offset++] = static_cast<unsigned long>(pShort[k]) + static_cast<unsigned long>(offset);
192 }
193 }
194
195 ibuf->unlock();
196 current_offset = next_offset;
197 }
198}
199
200SRaycastResult SRaycast::Cast(SCamera* camera, const float& relativePosX, const float& relativePosY, Ogre::SubEntity* subEntity, bool getUvCoordonate)
201{
202 SRaycastResult results = Cast(camera->GetOgreCameraPointer(), relativePosX, relativePosY, subEntity, getUvCoordonate);
203 results.viewport = camera->getCurrentViewPort();
204
205 return results;
206}
207
208SRaycastResult SRaycast::Cast(Ogre::Camera* camera, const float& relativePosX, const float& relativePosY, Ogre::SubEntity* subEntity, bool getUvCoordonate)
209{
210 // Our return struct.
211 SRaycastResult results;
212
213 if (!subEntity)
214 return results;
215
216 Ogre::Any bindedCustomEntity = subEntity->getUserObjectBindings().getUserAny("SEntity");
217
218 assert(bindedCustomEntity.has_value());
219 results.entity = Ogre::any_cast<SEntity*> (bindedCustomEntity);
220 results.entityName = results.entity->GetName();
221 results.scene = results.entity->GetParentScene();
222 results.sceneName = results.scene->GetName();
223 results.material = results.scene->GetMaterial(results.entity->GetGroupName(), subEntity->getMaterial()->getName());
224
225 // Should we force uv coordonate retrieving too?
226 if(!getUvCoordonate && results.material)
227 if(results.material->GetAssociatedWidget() != 0)
228 getUvCoordonate = true;
229
230 // Cast from camera
231 Ogre::Ray ray = camera->getCameraToViewportRay(fabs(relativePosX), fabs(relativePosY));
232
233 // Then, pseudo ray cast to the polygon level.
234 float closest_distance = -1.0f;
235 Ogre::SubMesh* submesh = subEntity->getSubMesh();
236
237 Ogre::RenderOperation tmpRenderOperation;
238 submesh->_getRenderOperation(tmpRenderOperation);
239 if (tmpRenderOperation.operationType == Ogre::RenderOperation::OT_TRIANGLE_LIST)
240 {
241 // Count vertexes
242 size_t vertex_count = 0;
243 if (submesh->useSharedVertices)
244 vertex_count = submesh->parent->sharedVertexData->vertexCount;
245 else
246 vertex_count = submesh->vertexData->vertexCount;
247
248 // Count indices
249 size_t index_count = submesh->indexData->indexCount;
250 unsigned long* indices = new unsigned long[index_count];
251
252 // Copy indexes informations
253 Ogre::IndexData* index_data = submesh->indexData;
254 size_t numTris = index_data->indexCount / 3;
255 Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
256 bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
257
258 size_t index_offset = 0;
259 if (use32bitindexes)
260 {
261 Ogre::uint32* pLong = static_cast<Ogre::uint32*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
262 for (size_t k = 0; k < numTris * 3; ++k)
263 indices[index_offset++] = pLong[k];
264 }
265 else
266 {
267 Ogre::uint16* pShort = static_cast<Ogre::uint16*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
268 for (size_t k = 0; k < numTris * 3; ++k)
269 indices[index_offset++] = static_cast<unsigned long>(pShort[k]);
270 }
271 ibuf->unlock();
272
273 Ogre::Entity* parentEntity = subEntity->getParent();
274 bool useSoftwareBlendingVertices = parentEntity->hasSkeleton();
275 bool useSoftwareMorphingVertices = parentEntity->hasVertexAnimation();
276
277 Ogre::SceneNode* attachedNode = parentEntity->getParentSceneNode();
278 assert(attachedNode != 0);
279 Ogre::Vector3 position = attachedNode->_getDerivedPosition();
280 Ogre::Quaternion orient = attachedNode->_getDerivedOrientation();
281 Ogre::Vector3 scale = attachedNode->_getDerivedScale();
282
283 int closestVerticeIndex = 0;
284
285 // Retrieve vertex data
286 Ogre::VertexData* vertex_data;
287 if (useSoftwareBlendingVertices && parentEntity->_isAnimated())
288 vertex_data = submesh->useSharedVertices ? parentEntity->_getSkelAnimVertexData() : subEntity->_getSkelAnimVertexData();
289 else if (!useSoftwareBlendingVertices && useSoftwareMorphingVertices && parentEntity->_isAnimated() && (parentEntity->getMesh()->getPoseList().size() == 0))
290 vertex_data = submesh->useSharedVertices ? parentEntity->_getSoftwareVertexAnimVertexData() : subEntity->_getSoftwareVertexAnimVertexData();
291 else
292 vertex_data = submesh->useSharedVertices ? submesh->parent->sharedVertexData : submesh->vertexData;
293
294 const Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
295 Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
296 if (!vbuf->isLocked())
297 {
298 unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
299
300 for (int j = 0; j < static_cast<int>(index_count); j += 3)
301 {
302 float* pReal1;
303 float* pReal2;
304 float* pReal3;
305 posElem->baseVertexPointerToElement(vertex + indices[j] * vbuf->getVertexSize(), &pReal1);
306 posElem->baseVertexPointerToElement(vertex + indices[j + 1] * vbuf->getVertexSize(), &pReal2);
307 posElem->baseVertexPointerToElement(vertex + indices[j + 2] * vbuf->getVertexSize(), &pReal3);
308
309 Ogre::Vector3 pt1(pReal1[0], pReal1[1], pReal1[2]);
310 Ogre::Vector3 pt2(pReal2[0], pReal2[1], pReal2[2]);
311 Ogre::Vector3 pt3(pReal3[0], pReal3[1], pReal3[2]);
312 pt1 = (orient * (pt1 * scale)) + position;
313 pt2 = (orient * (pt2 * scale)) + position;
314 pt3 = (orient * (pt3 * scale)) + position;
315
316 std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(ray, pt1, pt2, pt3, true, false);
317 if (hit.first)
318 {
319 if ((closest_distance < 0.0f) || (hit.second < closest_distance))
320 {
321 // this is the closest so far, save it off
322 closest_distance = hit.second;
323 closestVerticeIndex = j;
324
325 results.indexFace = j / 3;
326 results.v1 = pt1;
327 results.v2 = pt2;
328 results.v3 = pt3;
329 results.point = ray.getPoint(hit.second);
330 }
331 }
332 }
333 vbuf->unlock();
334 results.closestDistance = closest_distance;
335
336 // Get hit point uv coordinates, see the end of this page for an explanation: http://www.blackpawn.com/texts/pointinpoly/default.html
337 if (getUvCoordonate)
338 {
339 Ogre::VertexData* vertex_data = submesh->useSharedVertices ? submesh->parent->sharedVertexData : submesh->vertexData;
340 const Ogre::VertexElement* vertex_element = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES);
341 if (vertex_data->vertexDeclaration->getElementCount() > 2)
342 {
343 float* pReal1;
344 float* pReal2;
345 float* pReal3;
346
347 Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(vertex_element->getSource());
348 unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
349
350 vertex_element->baseVertexPointerToElement(vertex + indices[closestVerticeIndex] * vbuf->getVertexSize(), &pReal1);
351 vertex_element->baseVertexPointerToElement(vertex + indices[closestVerticeIndex + 1] * vbuf->getVertexSize(), &pReal2);
352 vertex_element->baseVertexPointerToElement(vertex + indices[closestVerticeIndex + 2] * vbuf->getVertexSize(), &pReal3);
353
354 vbuf->unlock();
355
356 // Get face points uvs
357 results.pReal1.x = pReal1[0];
358 results.pReal1.y = pReal1[1];
359 results.pReal2.x = pReal2[0];
360 results.pReal2.y = pReal2[1];
361 results.pReal3.x = pReal3[0];
362 results.pReal3.y = pReal3[1];
363
364 // Compute vectors
365 Ogre::Vector3 v0 = results.v3 - results.v1;
366 Ogre::Vector3 v1 = results.v2 - results.v1;
367 Ogre::Vector3 v2 = results.point - results.v1;
368
369 // Compute dot products
370 float dot00 = v0.dotProduct(v0);
371 float dot01 = v0.dotProduct(v1);
372 float dot02 = v0.dotProduct(v2);
373 float dot11 = v1.dotProduct(v1);
374 float dot12 = v1.dotProduct(v2);
375
376 // Compute barycentric coordinates
377 float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01);
378 float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
379 float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
380
381 // Compute uv range
382 Ogre::Vector2 t2 = results.pReal2 - results.pReal1;
383 Ogre::Vector2 t1 = results.pReal3 - results.pReal1;
384
385 // Finally, store uv coordinates of our point
386 results.uvResult = results.pReal1 + t1*u + t2*v;
387 }
388 }
389
390 delete[] indices;
391 }
392 }
393
394 return results;
395}
396
397SRaycastResult SRaycast::Cast(SScene* sm, Ogre::Vector3 pos, Ogre::Vector3 dir, Ogre::Real maxdist, bool getUvCoordonate)
398{
399 // Our return struct.
400 SRaycastResult results;
401 Ogre::RaySceneQuery* rq = sm->GetRayquery();
402 Ogre::Ray ray = Ogre::Ray(pos, dir);
403 rq->setRay(ray);
404
405 if (rq->execute().size() <= 0)
406 {
407 // raycast did not hit an objects bounding box
408 return results;
409 }
410
411 Ogre::Real closestDist = -1.0f;
412 Ogre::Vector3 closestResult;
413 Ogre::RaySceneQueryResult queryResult = rq->getLastResults();
414 bool toofar = false;
415 for (size_t qr_idx = 0; qr_idx < queryResult.size(); qr_idx++)
416 {
417 // stop checking if we have found a raycast hit that is closer
418 // than all remaining entities
419 if (((closestDist >= 0.0f) && (closestDist < queryResult[qr_idx].distance)) || closestDist >= maxdist)
420 {
421 if (closestDist >= maxdist)
422 toofar = true;
423 break;
424 }
425
426 // only check this result if its a hit against an entity
427 if ((queryResult[qr_idx].movable != NULL) && (queryResult[qr_idx].movable->getMovableType().compare("Entity") == 0))
428 {
429 // get the entity to check
430 Ogre::Entity *pentity = static_cast<Ogre::Entity*>(queryResult[qr_idx].movable);
431
432 // mesh data to retrieve
433 size_t vertex_count;
434 size_t index_count;
435 Ogre::Vector3 *vertices;
436 unsigned long *indices;
437
438 // get the mesh information
439 GetMeshInformation(pentity->getMesh(), vertex_count, vertices, index_count, indices,
440 pentity->getParentNode()->_getDerivedPosition(),
441 pentity->getParentNode()->_getDerivedOrientation(),
442 pentity->getParentNode()->_getDerivedScale());
443
444 // test for hitting individual triangles on the mesh
445 bool new_closest_found = false;
446 for (int i = 0; i < static_cast<int>(index_count); i += 3)
447 {
448 // check for a hit against this triangle
449 std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(ray, vertices[indices[i]],
450 vertices[indices[i + 1]], vertices[indices[i + 2]], true, false);
451
452 // if it was a hit check if its the closest
453 if (hit.first)
454 {
455 if ((closestDist < 0.0f) || (hit.second < closestDist))
456 {
457 // this is the closest so far, save it off
458 closestDist = hit.second;
459 new_closest_found = true;
460
461 }
462 }
463 }
464
465 // free the verticies and indicies memory
466 delete[] vertices;
467 delete[] indices;
468
469 // if we found a new closest raycast for this object, update the
470 // closest_result before moving on to the next object.
471 if (new_closest_found)
472 {
473 closestResult = ray.getPoint(closestDist);
474 }
475 }
476 }
477
478 // return the result
479 if ((closestDist >= 0.0f) && !toofar)
480 {
481 // raycast success
482 results.point = closestResult;
483 results.closestDistance = closestDist;
484 }
485
486 /*
487 // If our ogre is anterior to v1.7
488#if OGRE_VERSION < ((1 << 16) | (7 << 8) | 0)
489 Ogre::Any bindedCustomEntity = subEntity->getUserAny();
490#else
491 Ogre::Any bindedCustomEntity = subEntity->getUserObjectBindings().getUserAny("SEntity");
492#endif
493
494 assert(!bindedCustomEntity.isEmpty());
495 results.entity = Ogre::any_cast<SEntity*> (bindedCustomEntity);
496 results.entityName = results.entity->GetName();
497 results.scene = sm;
498 results.sceneName = sm->GetName();
499 results.viewport = NULL;
500 results.material = sm->GetMaterial(results.entity->GetGroupName(), subEntity->getMaterial()->getName());
501
502 // Should we force uv coordonate retrieving too?
503 if (!getUvCoordonate && results.material)
504 if (results.material->GetAssociatedWidget() != 0)
505 getUvCoordonate = true;
506
507
508 // Then, pseudo ray cast to the polygon level.
509 float closest_distance = -1.0f;
510 size_t vertex_count;
511 size_t index_count;
512 Ogre::Vector3* vertices;
513 unsigned long* indices;
514 Ogre::SubMesh* submesh = subEntity->getSubMesh();
515 GetSubEntityInformation(subEntity, vertex_count, vertices, index_count, indices);
516
517 Ogre::RenderOperation tmpRenderOperation;
518 submesh->_getRenderOperation(tmpRenderOperation);
519 if (tmpRenderOperation.operationType == Ogre::RenderOperation::OT_TRIANGLE_LIST)
520 {
521 int closestVerticeIndex = 0;
522 for (int j = 0; j < static_cast<int>(index_count); j += 3)
523 {
524 std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(ray, vertices[indices[j]], vertices[indices[j + 1]], vertices[indices[j + 2]], true, false);
525 if (hit.first)
526 {
527 if ((closest_distance < 0.0f) || (hit.second < closest_distance))
528 {
529 // this is the closest so far, save it off
530 closest_distance = hit.second;
531 closestVerticeIndex = j;
532
533 results.indexFace = j / 3;
534 results.v1 = vertices[indices[j]];
535 results.v2 = vertices[indices[j + 1]];
536 results.v3 = vertices[indices[j + 2]];
537 results.point = ray.getPoint(hit.second);
538 }
539 }
540 }
541 results.closestDistance = closest_distance;
542
543 // Get hit point uv coordinates, see the end of this page for an explanation: http://www.blackpawn.com/texts/pointinpoly/default.html
544 if (getUvCoordonate)
545 {
546 Ogre::VertexData* vertex_data = submesh->useSharedVertices ? submesh->parent->sharedVertexData : submesh->vertexData;
547 const Ogre::VertexElement* vertex_element1 = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES);
548 if (vertex_data->vertexDeclaration->getElementCount()>2)
549 {
550 float* pReal1;
551 float* pReal2;
552 float* pReal3;
553
554 Ogre::HardwareVertexBufferSharedPtr vbuf1 = vertex_data->vertexBufferBinding->getBuffer(vertex_element1->getSource());
555 unsigned char* vertex1 = static_cast<unsigned char*>(vbuf1->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
556 vertex1 += indices[closestVerticeIndex] * vbuf1->getVertexSize();
557 vertex_element1->baseVertexPointerToElement(vertex1, &pReal1);
558 vbuf1->unlock();
559
560 const Ogre::VertexElement* vertex_element2 = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES);
561 Ogre::HardwareVertexBufferSharedPtr vbuf2 = vertex_data->vertexBufferBinding->getBuffer(vertex_element2->getSource());
562 unsigned char* vertex2 = static_cast<unsigned char*>(vbuf2->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
563 vertex2 += indices[closestVerticeIndex + 1] * vbuf2->getVertexSize();
564 vertex_element2->baseVertexPointerToElement(vertex2, &pReal2);
565 vbuf2->unlock();
566
567 const Ogre::VertexElement* vertex_element3 = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES);
568 Ogre::HardwareVertexBufferSharedPtr vbuf3 = vertex_data->vertexBufferBinding->getBuffer(vertex_element3->getSource());
569 unsigned char* vertex3 = static_cast<unsigned char*>(vbuf3->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
570 vertex3 += indices[closestVerticeIndex + 2] * vbuf3->getVertexSize();
571 vertex_element3->baseVertexPointerToElement(vertex3, &pReal3);
572 vbuf3->unlock();
573
574 // Get face points uvs
575 results.pReal1.x = pReal1[0];
576 results.pReal1.y = pReal1[1];
577 results.pReal2.x = pReal2[0];
578 results.pReal2.y = pReal2[1];
579 results.pReal3.x = pReal3[0];
580 results.pReal3.y = pReal3[1];
581
582 // Compute vectors
583 Ogre::Vector3 v0 = results.v3 - results.v1;
584 Ogre::Vector3 v1 = results.v2 - results.v1;
585 Ogre::Vector3 v2 = results.point - results.v1;
586
587 // Compute dot products
588 float dot00 = v0.dotProduct(v0);
589 float dot01 = v0.dotProduct(v1);
590 float dot02 = v0.dotProduct(v2);
591 float dot11 = v1.dotProduct(v1);
592 float dot12 = v1.dotProduct(v2);
593
594 // Compute barycentric coordinates
595 float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01);
596 float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
597 float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
598
599 // Compute uv range
600 Ogre::Vector2 t2 = results.pReal2 - results.pReal1;
601 Ogre::Vector2 t1 = results.pReal3 - results.pReal1;
602
603 // Finally, store uv coordinates of our point
604 results.uvResult = results.pReal1 + t1*u + t2*v;
605 }
606 }
607 }
608 delete[] vertices;
609 delete[] indices;
610 */
611 return results;
612}
613
614void SRaycast::GetSubEntityInformation(Ogre::SubEntity* subEntity, size_t &vertex_count, Ogre::Vector3* &vertices, size_t &index_count, unsigned long* &indices)
615{
616 size_t index_offset = 0;
617
618 Ogre::SubMesh* submesh = subEntity->getSubMesh();
619 Ogre::Entity* parentEntity = subEntity->getParent();
620 bool useSoftwareBlendingVertices = parentEntity->hasSkeleton();
621 bool useSoftwareMorphingVertices = parentEntity->hasVertexAnimation();
622
623 Ogre::SceneNode* attachedNode = parentEntity->getParentSceneNode();
624 assert(attachedNode != 0);
625 Ogre::Vector3 position = attachedNode->_getDerivedPosition();
626 Ogre::Quaternion orient = attachedNode->_getDerivedOrientation();
627 Ogre::Vector3 scale = attachedNode->_getDerivedScale();
628
629 // Count vertexes
630 if(submesh->useSharedVertices)
631 vertex_count = submesh->parent->sharedVertexData->vertexCount;
632 else
633 vertex_count = submesh->vertexData->vertexCount;
634
635 // Count indices
636 index_count = submesh->indexData->indexCount;
637
638 // Create buffers with the calculated sizes.
639 vertices = new Ogre::Vector3[vertex_count];
640 indices = new unsigned long[index_count];
641
642 // Retrieve vertex data
643 Ogre::VertexData* vertex_data;
644 if(useSoftwareBlendingVertices && parentEntity->_isAnimated())
645 vertex_data = submesh->useSharedVertices ? parentEntity->_getSkelAnimVertexData() : subEntity->_getSkelAnimVertexData();
646 else if(!useSoftwareBlendingVertices && useSoftwareMorphingVertices && parentEntity->_isAnimated() && (parentEntity->getMesh()->getPoseList().size() == 0))
647 vertex_data = submesh->useSharedVertices ? parentEntity->_getSoftwareVertexAnimVertexData() : subEntity->_getSoftwareVertexAnimVertexData();
648 else
649 vertex_data = submesh->useSharedVertices ? submesh->parent->sharedVertexData : submesh->vertexData;
650
651 const Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
652 Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
653 if(!vbuf->isLocked())
654 {
655 unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
656
657 float* pReal;
658 for(size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
659 {
660 posElem->baseVertexPointerToElement(vertex, &pReal);
661 Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]);
662 vertices[j] = (orient * (pt * scale)) + position;
663 }
664 vbuf->unlock();
665
666 // Copy indexes informations
667 Ogre::IndexData* index_data = submesh->indexData;
668 size_t numTris = index_data->indexCount / 3;
669 Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
670 bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
671 Ogre::uint32* pLong = static_cast<Ogre::uint32*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
672 if (use32bitindexes)
673 {
674 Ogre::uint32* pLong = static_cast<Ogre::uint32*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
675 for (size_t k = 0; k < numTris * 3; ++k)
676 indices[index_offset++] = pLong[k];
677 }
678 else
679 {
680 Ogre::uint16* pShort = static_cast<Ogre::uint16*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
681 for (size_t k = 0; k < numTris * 3; ++k)
682 indices[index_offset++] = static_cast<unsigned long>(pShort[k]);
683 }
684 ibuf->unlock();
685 }
686}
687
688}
Ogre::Camera * GetOgreCameraPointer()
Definition SO3Camera.cpp:50
SViewPort * getCurrentViewPort()
Definition SO3Camera.cpp:55
std::string GetName() const
std::string GetGroupName()
SWidget * GetAssociatedWidget()
SScene * GetParentScene()
static SRaycastResult Cast(SCamera *camera, const float &relativePosX, const float &relativePosY, Ogre::SubEntity *subEntity, bool getUvCoordonate=false)
static void GetMeshInformation(const Ogre::MeshPtr mesh, size_t &vertex_count, Ogre::Vector3 *&vertices, size_t &index_count, unsigned long *&indices, const Ogre::Vector3 &position, const Ogre::Quaternion &orient, const Ogre::Vector3 &scale)
Ogre::Vector3 point
Definition SO3RayCast.h:50
std::string sceneName
Definition SO3RayCast.h:44
std::string entityName
Definition SO3RayCast.h:47
SMaterial * material
Definition SO3RayCast.h:48
SViewPort * viewport
Definition SO3RayCast.h:45
Ogre::Vector2 pReal2
Definition SO3RayCast.h:57
Ogre::Vector3 v1
Definition SO3RayCast.h:53
Ogre::Vector3 v2
Definition SO3RayCast.h:54
Ogre::Vector2 uvResult
Definition SO3RayCast.h:59
Ogre::Vector2 pReal3
Definition SO3RayCast.h:58
Ogre::Vector3 v3
Definition SO3RayCast.h:55
Ogre::Vector2 pReal1
Definition SO3RayCast.h:56
SMaterial * GetMaterial(const std::string &groupName, const std::string &materialName, bool searchOtherGroups=true)
Ogre::RaySceneQuery * GetRayquery()
Definition SO3Scene.h:591