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;
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;
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)
FlexBody(RoR::FlexBodyCacheData *preloaded_from_cache, RoR::GfxActor *gfx_actor, Ogre::Entity *entity, NodeNum_t ref, NodeNum_t nx, NodeNum_t ny, Ogre::Vector3 offset, Ogre::Quaternion const &rot, std::vector< unsigned int > &node_indices, std::vector< ForvertTempData > &forvert_data)