Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "yUtilsMesh.h"
- #include "OgreSubMesh2.h"
- #include "Objects/yObject.h"
- #include "Graphics/yGraphicsServices.h"
- #include "Graphics/yGraphicsSceneNodeManager.h"
- #include "OgreSceneManager.h"
- #include "OgreBitwise.h"
- #include "OgreItem.h"
- #include "Vao/OgreAsyncTicket.h"
- #include <iostream>
- yUtilsMesh::yUtilsMesh( yObject* object )
- {
- mSceneManager = yGraphicsServices::getGraphicsSceneNodeManager().getMainSceneManager();
- mNode = yGraphicsServices::getGraphicsSceneNodeManager().getObjectNode( object );
- mItem = yGraphicsServices::getGraphicsSceneNodeManager().getObjectItem( object );
- mMesh = mItem->getMesh();
- getMeshInformation( mVertexCount, mVertices, mIndexCount, mIndices, mUVCoords,
- Ogre::Vector3::ZERO,
- Ogre::Quaternion::IDENTITY,
- Ogre::Vector3::UNIT_SCALE
- //object->getGraphicsWorldTransform().position,
- //object->getGraphicsWorldTransform().orientation,
- //object->getGraphicsWorldTransform().scale
- );
- mClosestIndex = 0;
- }
- yUtilsMesh::~yUtilsMesh(){
- delete mVertices;
- delete mIndices;
- delete mUVCoords;
- mVertices = nullptr;
- mIndices = nullptr;
- mUVCoords = nullptr;
- }
- void yUtilsMesh::getMeshInformation(
- size_t &vertexCount,
- Ogre::Vector3* &vertices,
- size_t &indexCount,
- Ogre::uint32* &indices,
- Ogre::Vector2* &uvCoords,
- const Ogre::Vector3 &position,
- const Ogre::Quaternion &orient,
- const Ogre::Vector3 &scale )
- {
- yAssert( yUtils::isGraphicsThread(), "graphics method called by logic thread" );
- //First, we compute the total number of vertices and indices and init the buffers.
- unsigned int numVertices = 0;
- unsigned int numIndices = 0;
- Ogre::Mesh::SubMeshVec::const_iterator subMeshIterator = mMesh->getSubMeshes().begin();
- while (subMeshIterator != mMesh->getSubMeshes().end())
- {
- Ogre::SubMesh *subMesh = *subMeshIterator;
- numVertices += subMesh->mVao[0][0]->getVertexBuffers()[0]->getNumElements();
- numIndices += subMesh->mVao[0][0]->getIndexBuffer()->getNumElements();
- subMeshIterator++;
- }
- vertices = new Ogre::Vector3[numVertices];
- indices = new Ogre::uint32[numIndices];
- uvCoords = new Ogre::Vector2[numIndices];
- vertexCount = numVertices;
- indexCount = numIndices;
- unsigned int addedIndices = 0;
- unsigned int index_offset = 0;
- unsigned int subMeshOffset = 0;
- // Read Submeshes
- subMeshIterator = mMesh->getSubMeshes().begin();
- while (subMeshIterator != mMesh->getSubMeshes().end())
- {
- Ogre::SubMesh *subMesh = *subMeshIterator;
- Ogre::VertexArrayObjectArray vaos = subMesh->mVao[0];
- if (!vaos.empty())
- {
- //Get the first LOD level
- Ogre::VertexArrayObject *vao = vaos[0];
- bool indices32 = (vao->getIndexBuffer()->getIndexType() == Ogre::IndexBufferPacked::IT_32BIT);
- const Ogre::VertexBufferPackedVec &vertexBuffers = vao->getVertexBuffers();
- Ogre::IndexBufferPacked *indexBuffer = vao->getIndexBuffer();
- //request async read from buffer
- Ogre::VertexArrayObject::ReadRequestsArray requests;
- requests.push_back(Ogre::VertexArrayObject::ReadRequests(Ogre::VES_POSITION));
- requests.push_back(Ogre::VertexArrayObject::ReadRequests(Ogre::VES_TEXTURE_COORDINATES));
- vao->readRequests(requests);
- vao->mapAsyncTickets(requests);
- unsigned int subMeshVerticiesNum = requests[0].vertexBuffer->getNumElements();
- if (requests[0].type == Ogre::VET_HALF4){
- for (size_t i = 0; i < subMeshVerticiesNum; ++i){
- const Ogre::uint16* pos = reinterpret_cast<const Ogre::uint16*>(requests[0].data);
- Ogre::Vector3 vec;
- vec.x = Ogre::Bitwise::halfToFloat(pos[0]);
- vec.y = Ogre::Bitwise::halfToFloat(pos[1]);
- vec.z = Ogre::Bitwise::halfToFloat(pos[2]);
- requests[0].data += requests[0].vertexBuffer->getBytesPerElement();
- vertices[i + subMeshOffset] = (orient * (vec * scale)) + position;
- }
- }
- else if (requests[0].type == Ogre::VET_FLOAT3){
- for (size_t i = 0; i < subMeshVerticiesNum; ++i){
- const float* pos = reinterpret_cast<const float*>(requests[0].data);
- Ogre::Vector3 vec;
- vec.x = *pos++;
- vec.y = *pos++;
- vec.z = *pos++;
- requests[0].data += requests[0].vertexBuffer->getBytesPerElement();
- vertices[i + subMeshOffset] = (orient * (vec * scale)) + position;
- }
- }
- else{
- //lprint("Error: Vertex Buffer type not recognised in MeshTools::getMeshInformation");
- }
- //UV COORDINATES
- if (requests[1].type == Ogre::VET_HALF2){
- for (size_t i = 0; i < subMeshVerticiesNum; ++i){
- //const float* pos = reinterpret_cast<const float*>(requests[1].data);
- const Ogre::uint16* pos = reinterpret_cast<const Ogre::uint16*>(requests[1].data);
- Ogre::Vector2 vec;
- vec.x = Ogre::Bitwise::halfToFloat(pos[0]);
- vec.y = Ogre::Bitwise::halfToFloat(pos[1]);
- requests[1].data += requests[1].vertexBuffer->getBytesPerElement();
- uvCoords[i + subMeshOffset] = vec;
- }
- }
- subMeshOffset += subMeshVerticiesNum;
- vao->unmapAsyncTickets(requests);
- ////Read index data
- if (indexBuffer)
- {
- Ogre::AsyncTicketPtr asyncTicket = indexBuffer->readRequest(0, indexBuffer->getNumElements());
- unsigned int *pIndices = nullptr;
- if( indices32 ) {
- pIndices = (unsigned*)(asyncTicket->map());
- }
- else
- {
- unsigned short *pShortIndices = (unsigned short*)(asyncTicket->map());
- pIndices = new unsigned int[indexBuffer->getNumElements()];
- for (size_t k = 0; k < indexBuffer->getNumElements(); k++) pIndices[k] = static_cast<unsigned int>(pShortIndices[k]);
- }
- unsigned int bufferIndex = 0;
- for (size_t i = addedIndices; i < addedIndices + indexBuffer->getNumElements(); i++)
- {
- indices[i] = pIndices[bufferIndex] + index_offset;
- bufferIndex++;
- }
- addedIndices += indexBuffer->getNumElements();
- if (!indices32) delete[] pIndices;
- asyncTicket->unmap();
- }
- index_offset += vertexBuffers[0]->getNumElements();
- }
- subMeshIterator++;
- }
- }
- Ogre::Vector3 yUtilsMesh::getBarycentricCoordinates(const Ogre::Vector3 &P1, const Ogre::Vector3 &P2, const Ogre::Vector3 &P3, const Ogre::Vector3 &P)
- {
- //function got it from http://answers.unity3d.com/questions/383804/calculate-uv-coordinates-of-3d-point-on-plane-of-m.html
- Ogre::Vector3 f1 = P1 - P;
- Ogre::Vector3 f2 = P2 - P;
- Ogre::Vector3 f3 = P3 - P;
- float a = (P1-P2).crossProduct(P1-P3).length();
- float a1 = f2.crossProduct(f3).length() / a;
- float a2 = f3.crossProduct(f1).length() / a;
- //float a3 = f1.crossProduct(f2).length() / a; // property: a1 + a2 + a3 = 1
- return Ogre::Vector3(a1, a2, 1 - a2 - a1);
- }
- bool yUtilsMesh::getRayIntersectionWithMesh( Ogre::Ray ray, Ogre::Vector3& result )
- {
- yAssert( yUtils::isGraphicsThread(), "graphics method called by logic thread" );
- ray.setOrigin( mNode->_getDerivedOrientation().Inverse() * ( ray.getOrigin() -mNode->_getDerivedPosition() ) );
- ray.setDirection( mNode->_getDerivedOrientation().Inverse() * ray.getDirection() );
- Ogre::Real closest_distance = -1.0f;
- Ogre::Vector3 closest_result;
- bool new_closest_found = false;
- for(size_t i=0; i<mIndexCount; i+=3){
- // check for a hit against this triangle
- std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(ray, mVertices[mIndices[i]], mVertices[mIndices[i+1]], mVertices[mIndices[i+2]], true, false);
- // if it was a hit check if its the closest
- if( hit.first && (closest_distance < 0.0f || hit.second < closest_distance) )
- {
- // this is the closest so far, save it off
- closest_distance = hit.second;
- new_closest_found = true;
- mClosestIndex = i;
- }
- }
- if( new_closest_found )
- closest_result = ray.getPoint(closest_distance);
- mClosestDistance = closest_distance;
- // return the result
- if( closest_distance >= 0.0f ){
- // raycast success
- result = closest_result;
- return true;
- }
- // raycast failed
- return false;
- }
- bool yUtilsMesh::getRayIntersectionUVWithMesh( Ogre::Ray ray, Ogre::Vector2& resultUVCoord, float& closestDistance ){
- yAssert( yUtils::isGraphicsThread(), "graphics method called by logic thread" );
- Ogre::Vector3 result;
- bool intersect = getRayIntersectionWithMesh( ray, result );
- if( intersect ) {
- yAssert( mClosestIndex + 2 < mIndexCount, "invalid index" );
- yAssert( mIndices[mClosestIndex] < mVertexCount, "invalid index" );
- yAssert( mIndices[mClosestIndex + 1] < mIndexCount, "invalid index" );
- yAssert( mIndices[mClosestIndex + 2] < mIndexCount, "invalid index" );
- Ogre::Vector3 baryCoord = getBarycentricCoordinates( mVertices[mIndices[mClosestIndex]],
- mVertices[mIndices[mClosestIndex + 1]],
- mVertices[mIndices[mClosestIndex + 2]],
- result );
- resultUVCoord = mUVCoords[mIndices[mClosestIndex]] * baryCoord.x +
- mUVCoords[mIndices[mClosestIndex + 1]] * baryCoord.y +
- mUVCoords[mIndices[mClosestIndex + 2]] * baryCoord.z;
- closestDistance = mClosestDistance;
- }
- return intersect;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement