Rigs of Rods 2023.09
Soft-body Physics Simulation
Loading...
Searching...
No Matches
FlexObj.cpp
Go to the documentation of this file.
1/*
2 This source file is part of Rigs of Rods
3 Copyright 2005-2012 Pierre-Michel Ricordel
4 Copyright 2007-2012 Thomas Fischer
5 Copyright 2013-2020 Petr Ohlidal
6
7 For more information, see http://www.rigsofrods.org/
8
9 Rigs of Rods is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 3, as
11 published by the Free Software Foundation.
12
13 Rigs of Rods is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "FlexObj.h"
23
24#include "ApproxMath.h" // fast_normalise()
25#include "GfxActor.h"
26
27#include <Ogre.h>
28
29using namespace Ogre;
30using namespace RoR;
31
32FlexObj::FlexObj(RoR::GfxActor* gfx_actor, node_t* all_nodes, std::vector<CabTexcoord>& texcoords, int numtriangles,
33 int* triangles, std::vector<CabSubmesh>& submesh_defs,
34 char* texname, const char* name, char* backtexname, char* transtexname):
35 m_gfx_actor(gfx_actor)
36{
37 m_triangle_count = numtriangles;
38
39 // Create the mesh via the MeshManager
40 m_mesh = MeshManager::getSingleton().createManual(name, gfx_actor->GetResourceGroup());
41
42 // Create submeshes
43 m_submeshes.reserve(submesh_defs.size());
44 for (size_t j=0; j<submesh_defs.size(); j++)
45 {
46 Ogre::SubMesh* submesh = m_mesh->createSubMesh();
47 switch (submesh_defs[j].backmesh_type)
48 {
49 case CabSubmesh::BACKMESH_OPAQUE: submesh->setMaterialName(backtexname); break;
50 case CabSubmesh::BACKMESH_TRANSPARENT: submesh->setMaterialName(transtexname); break;
51 default: submesh->setMaterialName(texname);
52 }
53 m_submeshes.push_back(submesh);
54 };
55
56 // Define the m_vertices_raw (8 vertices, each consisting of 3 groups of 3 floats
57 m_vertex_count = texcoords.size();
58 m_vertices_raw=(float*)malloc(((2*3+2)*m_vertex_count)*sizeof(float));
59 m_vertex_nodes=(int*)malloc(m_vertex_count*sizeof(int));
60
61 for (size_t i=0; i<m_vertex_count; i++)
62 {
63 m_vertex_nodes[i] = texcoords[i].node_id; //define node ids
64 m_vertices[i].texcoord=Vector2(texcoords[i].texcoord_u, texcoords[i].texcoord_v); //textures coordinates
65 }
66
67 // Define triangles
68 // The values in this table refer to vertices in the above table
69 m_index_count = 3*numtriangles;
70 m_indices=(unsigned short*)malloc(m_index_count*sizeof(unsigned short));
71 for (size_t i=0; i<m_index_count; i++)
72 {
73 m_indices[i]=ComputeVertexPos(static_cast<int>(i/3), triangles[i], submesh_defs);
74 }
75
76 m_s_ref=(float*)malloc(numtriangles*sizeof(float));
77
78 for (size_t i=0; i<(unsigned int)numtriangles;i++)
79 {
80 Ogre::Vector3 base_pos = all_nodes[m_vertex_nodes[m_indices[i*3]]].RelPosition;
81 Ogre::Vector3 v1 = all_nodes[m_vertex_nodes[m_indices[i*3+1]]].RelPosition - base_pos;
82 Ogre::Vector3 v2 = all_nodes[m_vertex_nodes[m_indices[i*3+2]]].RelPosition - base_pos;
83 m_s_ref[i]=v1.crossProduct(v2).length()*2.0;
84 }
85
86 this->UpdateMesh(); // Initialize the dynamic mesh
87
88 // Create vertex data structure for vertices shared between submeshes
89 m_mesh->sharedVertexData = new VertexData();
90 m_mesh->sharedVertexData->vertexCount = m_vertex_count;
91
92 // Create declaration (memory format) of vertex data
93 m_vertex_format = m_mesh->sharedVertexData->vertexDeclaration;
94 size_t offset = 0;
95 m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_POSITION);
96 offset += VertexElement::getTypeSize(VET_FLOAT3);
97 m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
98 offset += VertexElement::getTypeSize(VET_FLOAT3);
99 m_vertex_format->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
100 offset += VertexElement::getTypeSize(VET_FLOAT2);
101
102 // Allocate vertex buffer of the requested number of vertices (vertexCount)
103 // and bytes per vertex (offset)
104 m_hw_vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
105 offset, m_mesh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
106
107 // Upload the vertex data to the card
108 m_hw_vbuf->writeData(0, m_hw_vbuf->getSizeInBytes(), m_vertices_raw, true);
109
110 // Set vertex buffer binding so buffer 0 is bound to our vertex buffer
111 VertexBufferBinding* bind = m_mesh->sharedVertexData->vertexBufferBinding;
112 bind->setBinding(0, m_hw_vbuf);
113
114 // Set parameters of the submeshes
115 for (size_t j=0; j<m_submeshes.size(); j++)
116 {
117 size_t index_count;
118 if (j == 0)
119 index_count = 3*submesh_defs[j].cabs_pos;
120 else
121 index_count = 3*(submesh_defs[j].cabs_pos-submesh_defs[j-1].cabs_pos); // 3 indices per triangle
122
123 m_submeshes[j]->useSharedVertices = true;
124 HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().createIndexBuffer(
125 HardwareIndexBuffer::IT_16BIT,
126 index_count,
127 HardwareBuffer::HBU_STATIC_WRITE_ONLY);
128
129 // Upload the index data to the card
130 unsigned short* faces_ptr;
131 if (j == 0)
132 faces_ptr = &m_indices[0];
133 else
134 faces_ptr = &m_indices[submesh_defs[j-1].cabs_pos * 3];
135
136 ibuf->writeData(0, ibuf->getSizeInBytes(), faces_ptr, true);
137 m_submeshes[j]->indexData->indexBuffer = ibuf;
138 m_submeshes[j]->indexData->indexCount = index_count;
139 m_submeshes[j]->indexData->indexStart = 0;
140 }
141
142 // Set bounding information (for culling)
143 m_mesh->_setBounds(AxisAlignedBox(-100,-100,-100,100,100,100), true);
144
145 // Notify Mesh object that it has been loaded
146 m_mesh->load();
147}
148
149void FlexObj::ScaleFlexObj(float factor)
150{
151 for (int i=0; i<m_triangle_count;i++)
152 {
153 m_s_ref[i] *= factor;
154 }
155}
156
158int FlexObj::ComputeVertexPos(int tidx, int v, std::vector<CabSubmesh>& submeshes)
159{
160 // --- NOTE: The following logic is arcane, I'm keeping it mostly like I found it for stability ~ only_a_ptr, 08/2017
161
162 // Find the 'context' - a submesh (and respective span of vertices) which the vertex belong to.
163 int context;
164 int num_submeshes = static_cast<int>(submeshes.size());
165 for (context = 0; context < num_submeshes; ++context)
166 {
167 if (tidx < submeshes[context].cabs_pos)
168 {
169 --context;
170 break;
171 }
172 }
173
174 // Find the vertex itself
175 int i_min = (context < 0) ? 0 : static_cast<int>(submeshes[context].texcoords_pos); // Fix for single-submesh case... It seems to have worked with a negative index until now ~ only_a_ptr, 08/2017
176 int i_max = static_cast<int>(submeshes[context + 1].texcoords_pos);
177 for (int i = i_min; i < i_max; ++i)
178 {
179 if (m_vertex_nodes[i] == v)
180 return i;
181 }
182
183 return 0;
184}
185
187{
189 Ogre::Vector3 center=(all_nodes[m_vertex_nodes[0]].AbsPosition+all_nodes[m_vertex_nodes[1]].AbsPosition)/2.0;
190 for (size_t i=0; i<m_vertex_count; i++)
191 {
192 //set position
193 m_vertices[i].position=all_nodes[m_vertex_nodes[i]].AbsPosition-center;
194 //reset normals
195 m_vertices[i].normal=Vector3::ZERO;
196 }
197 //accumulate normals per triangle
198 for (size_t i=0; i<m_index_count/3; i++)
199 {
200 Vector3 v1, v2;
201 v1=all_nodes[m_vertex_nodes[m_indices[i*3+1]]].AbsPosition-all_nodes[m_vertex_nodes[m_indices[i*3]]].AbsPosition;
202 v2=all_nodes[m_vertex_nodes[m_indices[i*3+2]]].AbsPosition-all_nodes[m_vertex_nodes[m_indices[i*3]]].AbsPosition;
203 v1=v1.crossProduct(v2);
204 float s=v1.length();
205
206 //avoid large tris
207 if (s>m_s_ref[i])
208 {
209 m_vertices[m_indices[i*3+1]].position=m_vertices[m_indices[i*3]].position+Vector3(0.1,0,0);
210 m_vertices[m_indices[i*3+2]].position=m_vertices[m_indices[i*3]].position+Vector3(0,0,0.1);
211 }
212
213 if (s == 0)
214 continue;
215
216 v1=v1/s;
217 m_vertices[m_indices[i*3]].normal+=v1;
218 m_vertices[m_indices[i*3+1]].normal+=v1;
219 m_vertices[m_indices[i*3+2]].normal+=v1;
220 }
221 //normalize
222 for (size_t i=0; i<m_vertex_count; i++)
223 {
225 }
226
227 return center;
228}
229
231{
232 Ogre::Vector3 center = this->UpdateMesh();
233 m_hw_vbuf->writeData(0, m_hw_vbuf->getSizeInBytes(), m_vertices_raw, true);
234 return center;
235}
236
238{
239 if (m_mesh)
240 {
241 Ogre::MeshManager::getSingleton().remove(m_mesh->getHandle());
242 m_mesh.reset();
243 }
244
245 if (m_vertices_raw != nullptr) { free (m_vertices_raw); }
246 if (m_vertex_nodes != nullptr) { free (m_vertex_nodes); }
247 if (m_indices != nullptr) { free (m_indices); }
248 if (m_s_ref != nullptr) { free (m_s_ref); }
249}
Ogre::Vector3 approx_normalise(Ogre::Vector3 v)
Definition ApproxMath.h:146
Manager for all visuals belonging to a single actor.
FlexObjVertex * m_vertices
Definition FlexObj.h:105
Ogre::Vector3 UpdateMesh()
Definition FlexObj.cpp:186
unsigned short * m_indices
Definition FlexObj.h:109
int ComputeVertexPos(int tidx, int v, std::vector< CabSubmesh > &submeshes)
Compute vertex position in the vertexbuffer (0-based offset) for node v of triangle tidx
Definition FlexObj.cpp:158
size_t m_index_count
Definition FlexObj.h:108
int m_triangle_count
Definition FlexObj.h:110
int * m_vertex_nodes
Definition FlexObj.h:99
Ogre::MeshPtr m_mesh
Definition FlexObj.h:93
FlexObj(RoR::GfxActor *gfx_actor, node_t *all_nodes, std::vector< CabTexcoord > &texcoords, int numtriangles, int *triangles, std::vector< CabSubmesh > &submeshes, char *texname, const char *name, char *backtexname, char *transtexname)
Definition FlexObj.cpp:32
RoR::GfxActor * m_gfx_actor
Definition FlexObj.h:95
float * m_s_ref
Definition FlexObj.h:96
size_t m_vertex_count
Definition FlexObj.h:98
std::vector< Ogre::SubMesh * > m_submeshes
Definition FlexObj.h:94
void ScaleFlexObj(float factor)
Definition FlexObj.cpp:149
Ogre::HardwareVertexBufferSharedPtr m_hw_vbuf
Definition FlexObj.h:101
Ogre::Vector3 UpdateFlexObj()
Definition FlexObj.cpp:230
float * m_vertices_raw
Definition FlexObj.h:104
Ogre::VertexDeclaration * m_vertex_format
Definition FlexObj.h:100
Ogre::String GetResourceGroup()
Definition GfxActor.h:146
NodeSB * GetSimNodeBuffer()
Definition GfxActor.h:129
@ BACKMESH_TRANSPARENT
Definition FlexObj.h:48
Ogre::Vector2 texcoord
Definition FlexObj.h:86
Ogre::Vector3 position
Definition FlexObj.h:84
Ogre::Vector3 AbsPosition
Definition SimBuffers.h:69
Physics: A vertex in the softbody structure.
Definition SimData.h:260
Ogre::Vector3 RelPosition
relative to the local physics origin (one origin per actor) (shaky)
Definition SimData.h:266