Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. #include "yUtilsMesh.h"
  2. #include "OgreSubMesh2.h"
  3. #include "Objects/yObject.h"
  4. #include "Graphics/yGraphicsServices.h"
  5. #include "Graphics/yGraphicsSceneNodeManager.h"
  6. #include "OgreSceneManager.h"
  7. #include "OgreBitwise.h"
  8. #include "OgreItem.h"
  9. #include "Vao/OgreAsyncTicket.h"
  10. #include <iostream>
  11.  
  12. yUtilsMesh::yUtilsMesh( yObject* object )
  13. {
  14.     mSceneManager = yGraphicsServices::getGraphicsSceneNodeManager().getMainSceneManager();
  15.  
  16.     mNode = yGraphicsServices::getGraphicsSceneNodeManager().getObjectNode( object );
  17.     mItem = yGraphicsServices::getGraphicsSceneNodeManager().getObjectItem( object );
  18.     mMesh = mItem->getMesh();
  19.  
  20.     getMeshInformation( mVertexCount, mVertices, mIndexCount, mIndices, mUVCoords,
  21.                         Ogre::Vector3::ZERO,
  22.                         Ogre::Quaternion::IDENTITY,
  23.                         Ogre::Vector3::UNIT_SCALE
  24.                         //object->getGraphicsWorldTransform().position,
  25.                         //object->getGraphicsWorldTransform().orientation,
  26.                         //object->getGraphicsWorldTransform().scale
  27.                         );
  28.     mClosestIndex = 0;
  29. }
  30.  
  31. yUtilsMesh::~yUtilsMesh(){
  32.     delete mVertices;
  33.     delete mIndices;
  34.     delete mUVCoords;
  35.  
  36.     mVertices = nullptr;
  37.     mIndices = nullptr;
  38.     mUVCoords = nullptr;
  39. }
  40.  
  41. void yUtilsMesh::getMeshInformation(
  42.    size_t               &vertexCount,
  43.    Ogre::Vector3*         &vertices,
  44.    size_t               &indexCount,
  45.    Ogre::uint32*         &indices,
  46.    Ogre::Vector2*         &uvCoords,
  47.    const Ogre::Vector3      &position,
  48.    const Ogre::Quaternion   &orient,
  49.    const Ogre::Vector3      &scale )
  50. {
  51.     yAssert( yUtils::isGraphicsThread(), "graphics method called by logic thread" );
  52.  
  53.    //First, we compute the total number of vertices and indices and init the buffers.
  54.    unsigned int numVertices = 0;
  55.    unsigned int numIndices = 0;
  56.  
  57.    Ogre::Mesh::SubMeshVec::const_iterator subMeshIterator = mMesh->getSubMeshes().begin();
  58.  
  59.    while (subMeshIterator != mMesh->getSubMeshes().end())
  60.    {
  61.       Ogre::SubMesh *subMesh = *subMeshIterator;
  62.       numVertices += subMesh->mVao[0][0]->getVertexBuffers()[0]->getNumElements();
  63.       numIndices += subMesh->mVao[0][0]->getIndexBuffer()->getNumElements();
  64.  
  65.       subMeshIterator++;
  66.    }
  67.  
  68.    vertices = new Ogre::Vector3[numVertices];
  69.    indices = new Ogre::uint32[numIndices];
  70.    uvCoords = new Ogre::Vector2[numIndices];
  71.  
  72.    vertexCount = numVertices;
  73.    indexCount = numIndices;
  74.  
  75.    unsigned int addedIndices = 0;
  76.  
  77.    unsigned int index_offset = 0;
  78.    unsigned int subMeshOffset = 0;
  79.  
  80.    // Read Submeshes
  81.    subMeshIterator = mMesh->getSubMeshes().begin();
  82.    while (subMeshIterator != mMesh->getSubMeshes().end())
  83.    {
  84.       Ogre::SubMesh *subMesh = *subMeshIterator;
  85.       Ogre::VertexArrayObjectArray vaos = subMesh->mVao[0];
  86.  
  87.       if (!vaos.empty())
  88.       {
  89.          //Get the first LOD level
  90.          Ogre::VertexArrayObject *vao = vaos[0];
  91.          bool indices32 = (vao->getIndexBuffer()->getIndexType() == Ogre::IndexBufferPacked::IT_32BIT);
  92.  
  93.          const Ogre::VertexBufferPackedVec &vertexBuffers = vao->getVertexBuffers();
  94.          Ogre::IndexBufferPacked *indexBuffer = vao->getIndexBuffer();
  95.  
  96.          //request async read from buffer
  97.          Ogre::VertexArrayObject::ReadRequestsArray requests;
  98.          requests.push_back(Ogre::VertexArrayObject::ReadRequests(Ogre::VES_POSITION));
  99.          requests.push_back(Ogre::VertexArrayObject::ReadRequests(Ogre::VES_TEXTURE_COORDINATES));
  100.  
  101.          vao->readRequests(requests);
  102.          vao->mapAsyncTickets(requests);
  103.          unsigned int subMeshVerticiesNum = requests[0].vertexBuffer->getNumElements();
  104.          if (requests[0].type == Ogre::VET_HALF4){
  105.             for (size_t i = 0; i < subMeshVerticiesNum; ++i){
  106.                const Ogre::uint16* pos = reinterpret_cast<const Ogre::uint16*>(requests[0].data);
  107.                Ogre::Vector3 vec;
  108.                vec.x = Ogre::Bitwise::halfToFloat(pos[0]);
  109.                vec.y = Ogre::Bitwise::halfToFloat(pos[1]);
  110.                vec.z = Ogre::Bitwise::halfToFloat(pos[2]);
  111.                requests[0].data += requests[0].vertexBuffer->getBytesPerElement();
  112.                vertices[i + subMeshOffset] = (orient * (vec * scale)) + position;
  113.             }
  114.          }
  115.          else if (requests[0].type == Ogre::VET_FLOAT3){
  116.             for (size_t i = 0; i < subMeshVerticiesNum; ++i){
  117.                const float* pos = reinterpret_cast<const float*>(requests[0].data);
  118.                Ogre::Vector3 vec;
  119.                vec.x = *pos++;
  120.                vec.y = *pos++;
  121.                vec.z = *pos++;
  122.                requests[0].data += requests[0].vertexBuffer->getBytesPerElement();
  123.                vertices[i + subMeshOffset] = (orient * (vec * scale)) + position;
  124.             }
  125.          }
  126.          else{
  127.             //lprint("Error: Vertex Buffer type not recognised in MeshTools::getMeshInformation");
  128.          }
  129.          //UV COORDINATES
  130.          if (requests[1].type == Ogre::VET_HALF2){
  131.  
  132.              for (size_t i = 0; i < subMeshVerticiesNum; ++i){
  133.                 //const float* pos = reinterpret_cast<const float*>(requests[1].data);
  134.                 const Ogre::uint16* pos = reinterpret_cast<const Ogre::uint16*>(requests[1].data);
  135.                 Ogre::Vector2 vec;
  136.                 vec.x = Ogre::Bitwise::halfToFloat(pos[0]);
  137.                 vec.y = Ogre::Bitwise::halfToFloat(pos[1]);
  138.                 requests[1].data += requests[1].vertexBuffer->getBytesPerElement();
  139.                 uvCoords[i + subMeshOffset] = vec;
  140.              }
  141.          }
  142.  
  143.  
  144.          subMeshOffset += subMeshVerticiesNum;
  145.          vao->unmapAsyncTickets(requests);
  146.  
  147.          ////Read index data
  148.          if (indexBuffer)
  149.          {
  150.             Ogre::AsyncTicketPtr asyncTicket = indexBuffer->readRequest(0, indexBuffer->getNumElements());
  151.  
  152.             unsigned int *pIndices = nullptr;
  153.             if( indices32 ) {
  154.                pIndices = (unsigned*)(asyncTicket->map());
  155.             }
  156.             else
  157.             {
  158.                unsigned short *pShortIndices = (unsigned short*)(asyncTicket->map());
  159.                pIndices = new unsigned int[indexBuffer->getNumElements()];
  160.                for (size_t k = 0; k < indexBuffer->getNumElements(); k++) pIndices[k] = static_cast<unsigned int>(pShortIndices[k]);
  161.             }
  162.             unsigned int bufferIndex = 0;
  163.  
  164.             for (size_t i = addedIndices; i < addedIndices + indexBuffer->getNumElements(); i++)
  165.             {
  166.                indices[i] = pIndices[bufferIndex] + index_offset;
  167.                bufferIndex++;
  168.             }
  169.             addedIndices += indexBuffer->getNumElements();
  170.  
  171.             if (!indices32) delete[] pIndices;
  172.  
  173.             asyncTicket->unmap();
  174.          }
  175.          index_offset += vertexBuffers[0]->getNumElements();
  176.       }
  177.       subMeshIterator++;
  178.    }
  179. }
  180.  
  181. Ogre::Vector3 yUtilsMesh::getBarycentricCoordinates(const Ogre::Vector3 &P1, const Ogre::Vector3 &P2, const Ogre::Vector3 &P3, const Ogre::Vector3 &P)
  182. {
  183.     //function got it from http://answers.unity3d.com/questions/383804/calculate-uv-coordinates-of-3d-point-on-plane-of-m.html
  184.     Ogre::Vector3 f1 = P1 - P;
  185.     Ogre::Vector3 f2 = P2 - P;
  186.     Ogre::Vector3 f3 = P3 - P;
  187.  
  188.     float a = (P1-P2).crossProduct(P1-P3).length();
  189.     float a1 = f2.crossProduct(f3).length() / a;
  190.     float a2 = f3.crossProduct(f1).length() / a;
  191.     //float a3 = f1.crossProduct(f2).length() / a; // property: a1 + a2 + a3 = 1
  192.  
  193.     return Ogre::Vector3(a1, a2, 1 - a2 - a1);
  194. }
  195.  
  196. bool yUtilsMesh::getRayIntersectionWithMesh( Ogre::Ray ray, Ogre::Vector3& result )
  197. {
  198.     yAssert( yUtils::isGraphicsThread(), "graphics method called by logic thread" );
  199.     ray.setOrigin(  mNode->_getDerivedOrientation().Inverse() * ( ray.getOrigin() -mNode->_getDerivedPosition() ) );
  200.     ray.setDirection( mNode->_getDerivedOrientation().Inverse() * ray.getDirection() );
  201.  
  202.     Ogre::Real closest_distance = -1.0f;
  203.     Ogre::Vector3 closest_result;
  204.     bool new_closest_found = false;
  205.  
  206.     for(size_t i=0; i<mIndexCount; i+=3){
  207.         // check for a hit against this triangle
  208.         std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(ray, mVertices[mIndices[i]], mVertices[mIndices[i+1]], mVertices[mIndices[i+2]], true, false);
  209.  
  210.         // if it was a hit check if its the closest
  211.         if( hit.first && (closest_distance < 0.0f || hit.second < closest_distance) )
  212.         {
  213.             // this is the closest so far, save it off
  214.             closest_distance = hit.second;
  215.             new_closest_found = true;
  216.             mClosestIndex = i;
  217.         }
  218.     }
  219.  
  220.     if( new_closest_found )
  221.         closest_result = ray.getPoint(closest_distance);
  222.  
  223.     mClosestDistance = closest_distance;
  224.  
  225.     // return the result
  226.     if( closest_distance >= 0.0f ){
  227.         // raycast success
  228.         result = closest_result;
  229.         return true;
  230.     }
  231.  
  232.     // raycast failed
  233.     return false;
  234. }
  235.  
  236. bool yUtilsMesh::getRayIntersectionUVWithMesh( Ogre::Ray ray, Ogre::Vector2& resultUVCoord, float& closestDistance ){
  237.  
  238.     yAssert( yUtils::isGraphicsThread(), "graphics method called by logic thread" );
  239.     Ogre::Vector3 result;
  240.     bool intersect = getRayIntersectionWithMesh( ray, result );
  241.  
  242.     if( intersect ) {
  243.  
  244.         yAssert( mClosestIndex + 2 < mIndexCount, "invalid index" );
  245.         yAssert( mIndices[mClosestIndex] < mVertexCount, "invalid index" );
  246.         yAssert( mIndices[mClosestIndex + 1] < mIndexCount, "invalid index" );
  247.         yAssert( mIndices[mClosestIndex + 2] < mIndexCount, "invalid index" );
  248.         Ogre::Vector3 baryCoord = getBarycentricCoordinates( mVertices[mIndices[mClosestIndex]],
  249.                                                                 mVertices[mIndices[mClosestIndex + 1]],
  250.                                                                 mVertices[mIndices[mClosestIndex + 2]],
  251.                                                                 result );
  252.  
  253.         resultUVCoord = mUVCoords[mIndices[mClosestIndex]] * baryCoord.x +
  254.                         mUVCoords[mIndices[mClosestIndex + 1]] * baryCoord.y +
  255.                         mUVCoords[mIndices[mClosestIndex + 2]] * baryCoord.z;
  256.  
  257.         closestDistance = mClosestDistance;
  258.     }
  259.  
  260.     return intersect;
  261. }