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);