Rigs of Rods 2023.09
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
FlexMesh.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 "FlexMesh.h"
23
24#include <Ogre.h>
25
26#include "ApproxMath.h"
27#include "SimData.h"
28#include "GfxActor.h"
29
30using namespace Ogre;
31using namespace RoR;
32
34 Ogre::String const & name,
35 RoR::GfxActor* gfx_actor,
36 NodeNum_t n1,
37 NodeNum_t n2,
38 NodeNum_t nstart,
39 int nrays,
40 Ogre::String const& face_material_name,
41 Ogre::String const& face_material_rg,
42 Ogre::String const& band_material_name,
43 Ogre::String const& band_material_rg,
44 bool rimmed,
45 float rim_ratio
46) :
47 m_is_rimmed(rimmed)
48 , m_num_rays(nrays)
49 , m_gfx_actor(gfx_actor)
50{
51 // Create the mesh via the MeshManager
52 m_mesh = MeshManager::getSingleton().createManual(name, gfx_actor->GetResourceGroup());
53
54 // Create submeshes
55 m_submesh_wheelface = m_mesh->createSubMesh();
56 m_submesh_tiretread = m_mesh->createSubMesh();
57
58 //materials
59 m_submesh_wheelface->setMaterialName(face_material_name, face_material_rg);
60 m_submesh_tiretread->setMaterialName(band_material_name, band_material_rg);
61
62 // Define the vertices
63 size_t vertex_count = 4*nrays+2; // each ray needs 4 verts (2 for sidewalls and 2 for band). The axis needs an extra 2.
64 if (m_is_rimmed) // For truckfile sections "[mesh]wheels2".
65 {
66 vertex_count+=2*nrays; // 1 extra vertex for each sidewall.
67 }
68 m_vertices.resize(vertex_count);
69 m_vertex_nodes.resize(vertex_count, NODENUM_INVALID);
70
71 //define node ids
72 m_vertex_nodes[0]=n1;
73 m_vertex_nodes[1]=n2;
74 int i;
75 for (i=0; i<nrays; i++)
76 {
77 //face
78 m_vertex_nodes[2+i*2]=nstart+i*2;
79 m_vertex_nodes[2+i*2+1]=nstart+i*2+1;
80 if (m_is_rimmed)
81 {
82 //band
83 m_vertex_nodes[2+2*nrays+i*2] = nstart+2*nrays+i*2;
84 m_vertex_nodes[2+2*nrays+i*2+1] = nstart+2*nrays+i*2+1;
85 //face2 (outer)
86 m_vertex_nodes[2+4*nrays+i*2] = nstart+2*nrays+i*2;
87 m_vertex_nodes[2+4*nrays+i*2+1] = nstart+2*nrays+i*2+1;
88 } else
89 {
90 //band
91 m_vertex_nodes[2+2*nrays+i*2] = nstart+i*2;
92 m_vertex_nodes[2+2*nrays+i*2+1] = nstart+i*2+1;
93 }
94 }
95
96 //textures coordinates
97 m_vertices[0].texcoord=Vector2(0.5, 0.5); // Axis vertices - texcoord is middle of the wheelface texture.
98 m_vertices[1].texcoord=Vector2(0.5, 0.5);
99 const bool odd_num_rays = (nrays % 2 == 0);
100 for (i=0; i<nrays; i++)
101 {
102 //band
103 int band_vert = 2+2*nrays+i*2;
104 if (i % 2 == 0) // Even index
105 {
106 if (odd_num_rays && ((i+1) == nrays))
107 {
108 // Finalize a wheel with odd number of rays like 'bombinette.load' in 'miniredmars' map.
109 m_vertices[band_vert].texcoord=Vector2(0.5, 0.0); // Stretch the texture over 2 quads instead of 1... ugly, but best we can do here
110 m_vertices[band_vert+1].texcoord=Vector2(0.5, 1.0);
111 }
112 else
113 {
114 m_vertices[band_vert].texcoord=Vector2(0.0, 0.0);
115 m_vertices[band_vert+1].texcoord=Vector2(0.0, 1.0);
116 }
117 }
118 else // Odd index
119 {
120 m_vertices[band_vert].texcoord=Vector2(1.0, 0.0);
121 m_vertices[band_vert+1].texcoord=Vector2(1.0, 1.0);
122 }
123
124 //face
125 if (m_is_rimmed)
126 {
127 m_vertices[2+i*2].texcoord=Vector2(0.5+0.5*rim_ratio*sin((float)i*2.0*3.14159/nrays), 0.5+0.5*rim_ratio*cos((float)i*2.0*3.14159/nrays));
128 m_vertices[2+i*2+1].texcoord=m_vertices[2+i*2].texcoord;
129 m_vertices[2+4*nrays+i*2].texcoord=Vector2(0.5+0.5*sin(((float)i+0.5)*2.0*3.14159/nrays), 0.5+0.5*cos(((float)i+0.5)*2.0*3.14159/nrays));
130 m_vertices[2+4*nrays+i*2+1].texcoord=m_vertices[2+4*nrays+i*2].texcoord;
131 } else
132 {
133 m_vertices[2+i*2].texcoord=Vector2(0.5+0.5*sin(i*2.0*3.14159/nrays), 0.5+0.5*cos(i*2.0*3.14159/nrays));
134 m_vertices[2+i*2+1].texcoord=m_vertices[2+i*2].texcoord;
135 }
136 }
137
138 // Define triangles
139 // The values in this table refer to vertices in the above table
140 size_t tiretread_num_indices = 3*2*nrays;
141 size_t wheelface_num_indices = 3*2*nrays;
142 if (m_is_rimmed) wheelface_num_indices=wheelface_num_indices*3;
143 m_wheelface_indices.resize(wheelface_num_indices, 0);
144 m_tiretread_indices.resize(tiretread_num_indices, 0);
145 for (i=0; i<nrays; i++)
146 {
147 //wheel sides
148 m_wheelface_indices[3*(i*2)]=0; m_wheelface_indices[3*(i*2)+1]=2+i*2; m_wheelface_indices[3*(i*2)+2]=2+((i+1)%nrays)*2;
149 m_wheelface_indices[3*(i*2+1)]=1; m_wheelface_indices[3*(i*2+1)+2]=2+i*2+1; m_wheelface_indices[3*(i*2+1)+1]=2+((i+1)%nrays)*2+1;
150 if (m_is_rimmed)
151 {
152 m_wheelface_indices[3*(i*4+0+2*nrays)]=2+i*2; m_wheelface_indices[3*(i*4+0+2*nrays)+1]=2+4*nrays+i*2; m_wheelface_indices[3*(i*4+0+2*nrays)+2]=2+((i+1)%nrays)*2;
153 m_wheelface_indices[3*(i*4+1+2*nrays)]=2+4*nrays+i*2; m_wheelface_indices[3*(i*4+1+2*nrays)+1]=2+4*nrays+((i+1)%nrays)*2; m_wheelface_indices[3*(i*4+1+2*nrays)+2]=2+((i+1)%nrays)*2;
154 m_wheelface_indices[3*(i*4+2+2*nrays)]=2+i*2+1; m_wheelface_indices[3*(i*4+2+2*nrays)+2]=2+4*nrays+i*2+1; m_wheelface_indices[3*(i*4+2+2*nrays)+1]=2+((i+1)%nrays)*2+1;
155 m_wheelface_indices[3*(i*4+3+2*nrays)]=2+4*nrays+i*2+1; m_wheelface_indices[3*(i*4+3+2*nrays)+2]=2+4*nrays+((i+1)%nrays)*2+1; m_wheelface_indices[3*(i*4+3+2*nrays)+1]=2+((i+1)%nrays)*2+1;
156 }
157 //wheel band
158 m_tiretread_indices[3*(i*2)]=2+2*nrays+i*2; m_tiretread_indices[3*(i*2)+1]=2+2*nrays+i*2+1; m_tiretread_indices[3*(i*2)+2]=2+2*nrays+((i+1)%nrays)*2;
159 m_tiretread_indices[3*(i*2+1)]=2+2*nrays+((i+1)%nrays)*2; m_tiretread_indices[3*(i*2+1)+2]=2+2*nrays+((i+1)%nrays)*2+1; m_tiretread_indices[3*(i*2+1)+1]=2+2*nrays+i*2+1;
160 }
161
162 //update coords
164
165 // Create vertex data structure for 8 vertices shared between submeshes
166 m_mesh->sharedVertexData = new VertexData();
167 m_mesh->sharedVertexData->vertexCount = vertex_count;
168
169 // Create declaration (memory format) of vertex data
170 m_vertex_format = m_mesh->sharedVertexData->vertexDeclaration;
171 size_t offset = 0;
172 m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_POSITION);
173 offset += VertexElement::getTypeSize(VET_FLOAT3);
174 m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
175 offset += VertexElement::getTypeSize(VET_FLOAT3);
176// m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_DIFFUSE);
177// offset += VertexElement::getTypeSize(VET_FLOAT3);
178 m_vertex_format->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
179 offset += VertexElement::getTypeSize(VET_FLOAT2);
180
181 // Allocate vertex buffer of the requested number of vertices (vertexCount)
182 // and bytes per vertex (offset)
183 m_hw_vbuf =
184 HardwareBufferManager::getSingleton().createVertexBuffer(
185 offset, m_mesh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
186
187 // Upload the vertex data to the card
188 m_hw_vbuf->writeData(0, m_hw_vbuf->getSizeInBytes(), m_vertices.data(), true);
189
190 // Set vertex buffer binding so buffer 0 is bound to our vertex buffer
191 VertexBufferBinding* bind = m_mesh->sharedVertexData->vertexBufferBinding;
192 bind->setBinding(0, m_hw_vbuf);
193
194 //for the sideface
195 // Allocate index buffer of the requested number of vertices (ibufCount)
196 HardwareIndexBufferSharedPtr faceibuf = HardwareBufferManager::getSingleton().
197 createIndexBuffer(
198 HardwareIndexBuffer::IT_16BIT,
199 wheelface_num_indices,
200 HardwareBuffer::HBU_STATIC_WRITE_ONLY);
201
202 // Upload the index data to the card
203 faceibuf->writeData(0, faceibuf->getSizeInBytes(), m_wheelface_indices.data(), true);
204
205 // Set parameters of the submesh
206 m_submesh_wheelface->useSharedVertices = true;
207 m_submesh_wheelface->indexData->indexBuffer = faceibuf;
208 m_submesh_wheelface->indexData->indexCount = wheelface_num_indices;
209 m_submesh_wheelface->indexData->indexStart = 0;
210
211 //for the band
212 // Allocate index buffer of the requested number of vertices (ibufCount)
213 HardwareIndexBufferSharedPtr bandibuf = HardwareBufferManager::getSingleton().
214 createIndexBuffer(
215 HardwareIndexBuffer::IT_16BIT,
216 tiretread_num_indices,
217 HardwareBuffer::HBU_STATIC_WRITE_ONLY);
218
219 // Upload the index data to the card
220 bandibuf->writeData(0, bandibuf->getSizeInBytes(), m_tiretread_indices.data(), true);
221
222 // Set parameters of the submesh
223 m_submesh_tiretread->useSharedVertices = true;
224 m_submesh_tiretread->indexData->indexBuffer = bandibuf;
225 m_submesh_tiretread->indexData->indexCount = tiretread_num_indices;
226 m_submesh_tiretread->indexData->indexStart = 0;
227
228 // Set bounding information (for culling)
229 m_mesh->_setBounds(AxisAlignedBox(-1,-1,0,1,1,0), true);
230
231 m_mesh->load();
232}
233
235{
236 if (m_mesh)
237 {
238 Ogre::MeshManager::getSingleton().remove(m_mesh->getName());
239 m_mesh.reset();
240 }
241}
242
244{
246 Vector3 center = (all_nodes[m_vertex_nodes[0]].AbsPosition + all_nodes[m_vertex_nodes[1]].AbsPosition) / 2.0;
247
248 //optimization possible here : just copy bands on face
249
250 m_vertices[0].position=all_nodes[m_vertex_nodes[0]].AbsPosition-center;
251 //normals
252 m_vertices[0].normal=approx_normalise(all_nodes[m_vertex_nodes[0]].AbsPosition-all_nodes[m_vertex_nodes[1]].AbsPosition);
253
254 m_vertices[1].position=all_nodes[m_vertex_nodes[1]].AbsPosition-center;
255 //normals
256 m_vertices[1].normal=-m_vertices[0].normal;
257
258 for (int i=0; i<m_num_rays*2; i++)
259 {
260 m_vertices[2+i].position=all_nodes[m_vertex_nodes[2+i]].AbsPosition-center;
261 //normals
262 if ((i%2)==0)
263 {
264 m_vertices[2+i].normal=approx_normalise(all_nodes[m_vertex_nodes[0]].AbsPosition-all_nodes[m_vertex_nodes[1]].AbsPosition);
265 } else
266 {
267 m_vertices[2+i].normal=-m_vertices[2+i-1].normal;
268 }
269 if (m_is_rimmed)
270 {
271 m_vertices[2+4*m_num_rays+i].position=all_nodes[m_vertex_nodes[2+4*m_num_rays+i]].AbsPosition-center;
272 //normals
273 if ((i%2)==0)
274 {
275 m_vertices[2+4*m_num_rays+i].normal=approx_normalise(all_nodes[m_vertex_nodes[2+4*m_num_rays+i]].AbsPosition-all_nodes[m_vertex_nodes[2+4*m_num_rays+i+1]].AbsPosition);
276 } else
277 {
278 m_vertices[2+4*m_num_rays+i].normal=-m_vertices[2+4*m_num_rays+i-1].normal;
279 }
280 //bands
281 m_vertices[2+2*m_num_rays+i].position=m_vertices[2+4*m_num_rays+i].position;
282 m_vertices[2+2*m_num_rays+i].normal=approx_normalise(m_vertices[2+4*m_num_rays+i].position);
283 } else
284 {
285 //bands
286 m_vertices[2+2*m_num_rays+i].position=m_vertices[2+i].position;
287 m_vertices[2+2*m_num_rays+i].normal=approx_normalise(m_vertices[2+i].position);
288 }
289 }
290 return center;
291}
292
297
299{
300 m_hw_vbuf->writeData(0, m_hw_vbuf->getSizeInBytes(), m_vertices.data(), true);
301 return m_flexit_center;
302}
Ogre::Vector3 approx_normalise(Ogre::Vector3 v)
Definition ApproxMath.h:146
Manager for all visuals belonging to a single actor.
Core data structures for simulation; Everything affected by by either physics, network or user intera...
std::vector< uint16_t > m_wheelface_indices
Definition FlexMesh.h:101
Ogre::Vector3 m_flexit_center
Definition FlexMesh.h:84
Ogre::SubMesh * m_submesh_wheelface
Definition FlexMesh.h:91
std::vector< FlexMeshVertex > m_vertices
Definition FlexMesh.h:97
Ogre::MeshPtr m_mesh
Definition FlexMesh.h:90
Ogre::HardwareVertexBufferSharedPtr m_hw_vbuf
Definition FlexMesh.h:94
bool m_is_rimmed
Definition FlexMesh.h:87
std::vector< uint16_t > m_tiretread_indices
Definition FlexMesh.h:102
void flexitCompute()
Definition FlexMesh.cpp:293
Ogre::Vector3 updateVertices()
Definition FlexMesh.cpp:243
FlexMesh(Ogre::String const &name, RoR::GfxActor *gfx_actor, NodeNum_t n1, NodeNum_t n2, NodeNum_t nstart, int nrays, Ogre::String const &face_material_name, Ogre::String const &face_material_rg, Ogre::String const &band_material_name, Ogre::String const &band_material_rg, bool rimmed=false, float rimratio=1.f)
Definition FlexMesh.cpp:33
Ogre::VertexDeclaration * m_vertex_format
Definition FlexMesh.h:93
RoR::GfxActor * m_gfx_actor
Definition FlexMesh.h:85
Ogre::SubMesh * m_submesh_tiretread
Definition FlexMesh.h:92
Ogre::Vector3 flexitFinal()
Definition FlexMesh.cpp:298
std::vector< NodeNum_t > m_vertex_nodes
Definition FlexMesh.h:98
Ogre::String GetResourceGroup()
Definition GfxActor.h:146
NodeSB * GetSimNodeBuffer()
Definition GfxActor.h:129
static const NodeNum_t NODENUM_INVALID
uint16_t NodeNum_t
Node position within Actor::ar_nodes; use RoR::NODENUM_INVALID as empty value.
Ogre::Vector3 AbsPosition
Definition SimBuffers.h:69