46     Ogre::Quaternion 
const & rot,
 
   47     std::vector<unsigned int> & node_indices,
 
   48     std::vector<ForvertTempData>& forvert_data
 
   50       m_center_offset(offset)
 
   55     , m_gfx_actor(gfx_actor)
 
   60     Ogre::Vector3* vertices = 
nullptr;
 
   61     std::string mesh_name = ent->getMesh()->getName();
 
   63     Vector3 normal = Vector3::UNIT_Y;
 
   64     Vector3 position = Vector3::ZERO;
 
   65     Quaternion orientation = Quaternion::ZERO;
 
   71         Vector3 diffX = 
nodes[nx].AbsPosition-
nodes[ref].AbsPosition;
 
   72         Vector3 diffY = 
nodes[ny].AbsPosition-
nodes[ref].AbsPosition;
 
   74         normal = (diffY.crossProduct(diffX)).normalisedCopy();
 
   77         position = 
nodes[ref].AbsPosition + offset.x * diffX + offset.y * diffY;
 
   78         position = position + offset.z * normal;
 
   81         Vector3 refX = diffX.normalisedCopy();
 
   82         Vector3 refY = refX.crossProduct(normal);
 
   83         orientation  = Quaternion(refX, normal, refY) * rot;
 
   88         normal = Vector3::UNIT_Y;
 
   89         position = 
nodes[0].AbsPosition + offset;
 
   93     Ogre::MeshPtr mesh=ent->getMesh();
 
   95     int num_submeshes = 
static_cast<int>(mesh->getNumSubMeshes());
 
   96     if (preloaded_from_cache == 
nullptr)
 
   99         if (mesh->sharedVertexData && mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES)==0)
 
  103         for (
int i=0; i<num_submeshes; i++)
 
  105             if (!mesh->getSubMesh(i)->useSharedVertices && mesh->getSubMesh(i)->vertexData->vertexDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES)==0) 
 
  112             LOG(
"FLEXBODY Warning: at least one part of this mesh does not have texture coordinates, switching off texturing!");
 
  117         bool havenormal=
true;
 
  118         if (mesh->sharedVertexData && mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL)==0)
 
  122         for (
int i=0; i<num_submeshes; i++)
 
  124             if (!mesh->getSubMesh(i)->useSharedVertices && mesh->getSubMesh(i)->vertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL)==0) 
 
  131             LOG(
"FLEXBODY Error: at least one part of this mesh does not have normal vectors, export your mesh with normal vectors! Disabling flexbody");
 
  142     VertexDeclaration* optimalVD=HardwareBufferManager::getSingleton().createVertexDeclaration();
 
  143     optimalVD->addElement(0, 0, VET_FLOAT3, VES_POSITION);
 
  144     optimalVD->addElement(1, 0, VET_FLOAT3, VES_NORMAL);
 
  146     if (
m_has_texture) optimalVD->addElement(3, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES);
 
  148     optimalVD->closeGapsInSource();
 
  149     BufferUsageList optimalBufferUsages;
 
  150     for (
size_t u = 0; u <= optimalVD->getMaxSource(); ++u)
 
  152         optimalBufferUsages.push_back(HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
 
  158         if (mesh->sharedVertexData)
 
  160             if (mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)==0)
 
  163                 int index=mesh->sharedVertexData->vertexDeclaration->getMaxSource()+1;
 
  164                 mesh->sharedVertexData->vertexDeclaration->addElement(index, 0, VET_COLOUR_ARGB, VES_DIFFUSE);
 
  165                 mesh->sharedVertexData->vertexDeclaration->sort();
 
  166                 index=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource();
 
  167                 HardwareVertexBufferSharedPtr vbuf=HardwareBufferManager::getSingleton().createVertexBuffer(VertexElement::getTypeSize(VET_COLOUR_ARGB), mesh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
 
  168                 mesh->sharedVertexData->vertexBufferBinding->setBinding(index, vbuf);
 
  171         for (
int i=0; i<num_submeshes; i++)
 
  173             if (!mesh->getSubMesh(i)->useSharedVertices)
 
  175                 Ogre::VertexData* vertex_data = mesh->getSubMesh(i)->vertexData;
 
  176                 Ogre::VertexDeclaration* vertex_decl = vertex_data->vertexDeclaration;
 
  177                 if (vertex_decl->findElementBySemantic(VES_DIFFUSE)==0)
 
  180                     int index = vertex_decl->getMaxSource()+1;
 
  181                     vertex_decl->addElement(index, 0, VET_COLOUR_ARGB, VES_DIFFUSE);
 
  183                     vertex_decl->findElementBySemantic(VES_DIFFUSE)->getSource();
 
  184                     HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
 
  185                         VertexElement::getTypeSize(VET_COLOUR_ARGB), vertex_data->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
 
  186                     vertex_data->vertexBufferBinding->setBinding(index, vbuf);
 
  194     if (mesh->sharedVertexData)
 
  196         mesh->sharedVertexData->reorganiseBuffers(optimalVD, optimalBufferUsages);
 
  197         mesh->sharedVertexData->removeUnusedBuffers();
 
  198         mesh->sharedVertexData->closeGapsInBindings();
 
  200     Mesh::SubMeshIterator smIt = mesh->getSubMeshIterator();
 
  201     while (smIt.hasMoreElements())
 
  203         SubMesh* sm = smIt.getNext();
 
  204         if (!sm->useSharedVertices)
 
  206             sm->vertexData->reorganiseBuffers(optimalVD->clone(), optimalBufferUsages);
 
  207             sm->vertexData->removeUnusedBuffers();
 
  208             sm->vertexData->closeGapsInBindings();
 
  220     if (preloaded_from_cache == 
nullptr)
 
  225         if (mesh->sharedVertexData)
 
  230         for (
int i=0; i<num_submeshes; i++)
 
  232             if (!mesh->getSubMesh(i)->useSharedVertices)
 
  246     double stat_manual_buffers_created_time = -1;
 
  247     double stat_transformed_time = -1;
 
  248     double stat_located_time = -1;
 
  249     if (preloaded_from_cache != 
nullptr)
 
  261         if (mesh->sharedVertexData)
 
  266             int source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource();
 
  267             m_shared_vbuf_pos=mesh->sharedVertexData->vertexBufferBinding->getBuffer(source);
 
  269             source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL)->getSource();
 
  274                 source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource();
 
  278         unsigned int curr_submesh_idx = 0;
 
  279         for (
int i=0; i<num_submeshes; i++)
 
  281             const Ogre::SubMesh* submesh = mesh->getSubMesh(i);
 
  282             if (submesh->useSharedVertices)
 
  286             const Ogre::VertexData* vertex_data = submesh->vertexData;
 
  289             int source_pos  = vertex_data->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource();
 
  290             int source_norm = vertex_data->vertexDeclaration->findElementBySemantic(VES_NORMAL)->getSource();
 
  291             m_submesh_vbufs_pos [curr_submesh_idx] = vertex_data->vertexBufferBinding->getBuffer(source_pos);
 
  292             m_submesh_vbufs_norm[curr_submesh_idx] = vertex_data->vertexBufferBinding->getBuffer(source_norm);
 
  296                 int source_color = vertex_data->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource();
 
  313         Vector3* vpt=vertices;
 
  315         if (mesh->sharedVertexData)
 
  319             int source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource();
 
  320             m_shared_vbuf_pos=mesh->sharedVertexData->vertexBufferBinding->getBuffer(source);
 
  321             m_shared_vbuf_pos->readData(0, mesh->sharedVertexData->vertexCount*
sizeof(Vector3), (
void*)vpt);
 
  322             vpt+=mesh->sharedVertexData->vertexCount;
 
  324             source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL)->getSource();
 
  326             m_shared_vbuf_norm->readData(0, mesh->sharedVertexData->vertexCount*
sizeof(Vector3), (
void*)npt);
 
  327             npt+=mesh->sharedVertexData->vertexCount;
 
  331                 source=mesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource();
 
  337         for (
int i=0; i<num_submeshes; i++)
 
  339             const Ogre::SubMesh* submesh = mesh->getSubMesh(i);
 
  340             if (submesh->useSharedVertices)
 
  344             const Ogre::VertexData* vertex_data = submesh->vertexData;
 
  345             int vertex_count = (int)vertex_data->vertexCount;
 
  348             int source = vertex_data->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource();
 
  353             source = vertex_data->vertexDeclaration->findElementBySemantic(VES_NORMAL)->getSource();
 
  360                 source = vertex_data->vertexDeclaration->findElementBySemantic(VES_DIFFUSE)->getSource();
 
  370             vertices[i]=(orientation*vertices[i])+position;
 
  377             auto forvert_itor = std::find_if(forvert_data.begin(), forvert_data.end(),
 
  379             if (forvert_itor != forvert_data.end())
 
  385                 LOG(
fmt::format(
"FLEXBODY vertex {} overriden for nodes REF:{}, VX:{}, VY:{}",
 
  392                 float closest_node_distance = std::numeric_limits<float>::max();
 
  393                 int closest_node_index = -1;
 
  394                 for (
auto node_index : node_indices)
 
  396                     float node_distance = vertices[i].squaredDistance(
nodes[node_index].AbsPosition);
 
  397                     if (node_distance < closest_node_distance)
 
  399                         closest_node_distance = node_distance;
 
  400                         closest_node_index = node_index;
 
  403                 if (closest_node_index == -1)
 
  405                     LOG(
"FLEXBODY ERROR on mesh " + mesh_name + 
": REF node not found");
 
  406                     closest_node_index = 0;
 
  411                 closest_node_distance = std::numeric_limits<float>::max();
 
  412                 closest_node_index = -1;
 
  413                 for (
auto node_index : node_indices)
 
  419                     float node_distance = vertices[i].squaredDistance(
nodes[node_index].AbsPosition);
 
  420                     if (node_distance < closest_node_distance)
 
  422                         closest_node_distance = node_distance;
 
  423                         closest_node_index = node_index;
 
  426                 if (closest_node_index == -1)
 
  428                     LOG(
"FLEXBODY ERROR on mesh " + mesh_name + 
": VX node not found");
 
  429                     closest_node_index = 0;
 
  434                 closest_node_distance = std::numeric_limits<float>::max();
 
  435                 closest_node_index = -1;
 
  437                 for (
auto node_index : node_indices)
 
  443                     float node_distance = vertices[i].squaredDistance(
nodes[node_index].AbsPosition);
 
  444                     if (node_distance < closest_node_distance)
 
  447                         float cost = vx.dotProduct(vt);
 
  448                         if (std::abs(cost) > std::sqrt(2.0f) / 2.0f)
 
  452                         closest_node_distance = node_distance;
 
  453                         closest_node_index = node_index;
 
  456                 if (closest_node_index == -1)
 
  458                     LOG(
"FLEXBODY ERROR on mesh " + mesh_name + 
": VY node not found");
 
  459                     closest_node_index = 0;
 
  468             mat.SetColumn(0, diffX);
 
  469             mat.SetColumn(1, diffY);
 
  470             mat.SetColumn(2, (diffX.crossProduct(diffY)).normalisedCopy()); 
 
  483     AxisAlignedBox aab=mesh->getBounds();
 
  484     Vector3 v=aab.getMinimum();
 
  495     aab.setMinimum(Vector3(-ma,-ma,-ma));
 
  496     aab.setMaximum(Vector3(ma,ma,ma));
 
  497     mesh->_setBounds(aab, 
true);
 
  504     if (preloaded_from_cache == 
nullptr)
 
  512             mat.SetColumn(0, diffX);
 
  513             mat.SetColumn(1, diffY);
 
  514             mat.SetColumn(2, diffX.crossProduct(diffY).normalisedCopy()); 
 
  523     if (vertices != 
nullptr) { free(vertices); }
 
  526     for (
unsigned int nodenum : node_indices)
 
  592         Ogre::MeshManager::getSingleton().remove(mesh->getHandle());
 
  631         Ogre::Vector3 flexit_normal = 
fast_normalise(diffY.crossProduct(diffX));
 
  729         if (nd->
nd_is_wet ^ ((col&0x000000FF)>0))
 
  765 template<
typename u
int_T> 
void reorderIndexBuffer(Ogre::IndexData* idx_data, std::vector<int> 
const& new_index_lookup)
 
  767     uint_T* workibuf = 
new uint_T[idx_data->indexCount];
 
  768     idx_data->indexBuffer->readData(0, idx_data->indexBuffer->getSizeInBytes(), workibuf);
 
  769     for (
size_t i = 0; i < idx_data->indexCount; i++)
 
  771         workibuf[i] = new_index_lookup[workibuf[i]];
 
  773     idx_data->indexBuffer->writeData(0, idx_data->indexBuffer->getSizeInBytes(), workibuf);
 
  777 void reorderVertexBuffer(Ogre::HardwareVertexBufferSharedPtr vert_buf, 
const Ogre::VertexElement* vert_elem, std::vector<int> 
const& new_index_lookup)
 
  779     char* workbuf_src = 
new char[vert_buf->getSizeInBytes()];
 
  780     char* workbuf_dst = 
new char[vert_buf->getSizeInBytes()];
 
  781     vert_buf->readData(0, vert_buf->getSizeInBytes(), workbuf_src);
 
  782     for (
size_t i = 0; i < vert_buf->getNumVertices(); i++)
 
  784         void* src = workbuf_src + (i * vert_elem->getSize());
 
  785         void* dst = workbuf_dst + (new_index_lookup[i] * vert_elem->getSize());
 
  786         std::memcpy(dst, src, vert_elem->getSize());
 
  788     vert_buf->writeData(0, vert_buf->getSizeInBytes(), workbuf_dst);
 
  789     delete[] workbuf_src;
 
  790     delete[] workbuf_dst;
 
  796     NodeNum_t forset_max = std::numeric_limits<NodeNum_t>::min();
 
  797     NodeNum_t forset_min = std::numeric_limits<NodeNum_t>::max();
 
  800         if (n > forset_max) { forset_max = n; }
 
  801         if (n < forset_min) { forset_min = n; }
 
  807         new_index_lookup[i] = i;
 
  812     prev_loc.
ref =  forset_min;
 
  813     prev_loc.
nx =  forset_min;
 
  814     prev_loc.
ny =  forset_min;
 
  821         int closest_loc_penalty = INT_MAX;
 
  825             if (penalty < closest_loc_penalty)
 
  827                 closest_loc_penalty = penalty;
 
  835         int idx_tmp = new_index_lookup[closest_loc];
 
  839         new_index_lookup[closest_loc] = new_index_lookup[i];
 
  843         new_index_lookup[i] = idx_tmp;    
 
  854             inverted_lookup[new_index_lookup[i]] = i;
 
  858             new_index_lookup[i] = inverted_lookup[i];
 
  867         Ogre::VertexData* vert_data = 
nullptr;
 
  877         const Ogre::VertexElement* uv_elem = vert_data->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES);
 
  878         Ogre::HardwareVertexBufferSharedPtr uv_buf = vert_data->vertexBufferBinding->getBuffer(uv_elem->getSource());
 
  885         Ogre::IndexData* idx_data = 
m_scene_entity->getMesh()->getSubMesh(0)->indexData;
 
  887         if (idx_data->indexBuffer->getType() == Ogre::HardwareIndexBuffer::IT_16BIT)
 
  889             reorderIndexBuffer<uint16_t>(idx_data, new_index_lookup);
 
  893             reorderIndexBuffer<uint32_t>(idx_data, new_index_lookup);