RigsofRods
Soft-body Physics Simulation
FlexMeshWheel.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 "FlexMeshWheel.h"
23 
24 #include "Application.h"
25 #include "SimData.h"
26 #include "GfxActor.h"
27 #include "GfxScene.h"
28 
29 #include <Ogre.h>
30 
31 using namespace Ogre;
32 using namespace RoR;
33 
34 FlexMeshWheel::FlexMeshWheel(
35  Ogre::Entity* rim_prop_entity,
36  Ogre::SceneNode* rim_scene_node,
37  RoR::GfxActor* gfx_actor,
38  int axis_node_1_index,
39  int axis_node_2_index,
40  int nstart,
41  int nrays,
42  std::string const& tire_mesh_name,
43  std::string const& tire_mesh_rg,
44  std::string const& tire_material_name,
45  std::string const& tire_material_rg,
46  float rimradius,
47  bool rimreverse
48 ) :
49  m_axis_node0_idx(axis_node_1_index)
50  , m_axis_node1_idx(axis_node_2_index)
51  , m_start_node_idx(nstart)
52  , m_num_rays(static_cast<size_t>(nrays))
53  , m_gfx_actor(gfx_actor)
54  , m_is_rim_reverse(rimreverse)
55  , m_rim_radius(rimradius)
56 {
57  m_rim_entity = rim_prop_entity;
58  m_rim_scene_node = rim_scene_node;
59  m_rim_scene_node->attachObject(m_rim_entity);
60 
61  // Create the tire mesh via the MeshManager
62  m_mesh = MeshManager::getSingleton().createManual(tire_mesh_name, tire_mesh_rg);
63 
64  // Create submeshes
65  m_submesh = m_mesh->createSubMesh();
66 
67  //materials
68  m_submesh->setMaterialName(tire_material_name, tire_material_rg);
69 
70  // Define the vertices
71  m_vertex_count = 6*(nrays+1);
72  m_vertices.resize(m_vertex_count);
73 
74  int i;
75  //textures coordinates
76  for (i=0; i<nrays+1; i++)
77  {
78  m_vertices[i*6 ].texcoord=Vector2((float)i/(float)nrays, 0.00f);
79  m_vertices[i*6+1 ].texcoord=Vector2((float)i/(float)nrays, 0.23f);
80  m_vertices[i*6+2 ].texcoord=Vector2((float)i/(float)nrays, 0.27f);
81  m_vertices[i*6+3 ].texcoord=Vector2((float)i/(float)nrays, 0.73f);
82  m_vertices[i*6+4 ].texcoord=Vector2((float)i/(float)nrays, 0.77f);
83  m_vertices[i*6+5 ].texcoord=Vector2((float)i/(float)nrays, 1.00f);
84  }
85 
86  // Define triangles
87  // The values in this table refer to vertices in the above table
88  m_index_count = 3*10*nrays;
89  m_indices.resize(m_index_count);
90  for (i=0; i<nrays; i++)
91  {
92  m_indices[3*(i*10 )]=i*6; m_indices[3*(i*10 )+1]=i*6+1; m_indices[3*(i*10 )+2]=(i+1)*6;
93  m_indices[3*(i*10+1)]=i*6+1; m_indices[3*(i*10+1)+1]=(i+1)*6+1; m_indices[3*(i*10+1)+2]=(i+1)*6;
94 
95  m_indices[3*(i*10+2)]=i*6+1; m_indices[3*(i*10+2)+1]=i*6+2; m_indices[3*(i*10+2)+2]=(i+1)*6+1;
96  m_indices[3*(i*10+3)]=i*6+2; m_indices[3*(i*10+3)+1]=(i+1)*6+2; m_indices[3*(i*10+3)+2]=(i+1)*6+1;
97 
98  m_indices[3*(i*10+4)]=i*6+2; m_indices[3*(i*10+4)+1]=i*6+3; m_indices[3*(i*10+4)+2]=(i+1)*6+2;
99  m_indices[3*(i*10+5)]=i*6+3; m_indices[3*(i*10+5)+1]=(i+1)*6+3; m_indices[3*(i*10+5)+2]=(i+1)*6+2;
100 
101  m_indices[3*(i*10+6)]=i*6+3; m_indices[3*(i*10+6)+1]=i*6+4; m_indices[3*(i*10+6)+2]=(i+1)*6+3;
102  m_indices[3*(i*10+7)]=i*6+4; m_indices[3*(i*10+7)+1]=(i+1)*6+4; m_indices[3*(i*10+7)+2]=(i+1)*6+3;
103 
104  m_indices[3*(i*10+8)]=i*6+4; m_indices[3*(i*10+8)+1]=i*6+5; m_indices[3*(i*10+8)+2]=(i+1)*6+4;
105  m_indices[3*(i*10+9)]=i*6+5; m_indices[3*(i*10+9)+1]=(i+1)*6+5; m_indices[3*(i*10+9)+2]=(i+1)*6+4;
106  }
107 
108  m_norm_y=1.0;
109  //update coords
110  updateVertices();
111  //compute m_norm_y;
112  m_norm_y=((m_vertices[0].position-m_vertices[1].position).crossProduct(m_vertices[1].position-m_vertices[6+1].position)).length();
113  //recompute for normals
114  updateVertices();
115 
116  // Create position data structure for 8 vertices shared between submeshes
117  m_mesh->sharedVertexData = new VertexData();
118  m_mesh->sharedVertexData->vertexCount = m_vertex_count;
119 
120  // Create declaration (memory format) of position data
121  m_vertex_format = m_mesh->sharedVertexData->vertexDeclaration;
122  size_t offset = 0;
123  m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_POSITION);
124  offset += VertexElement::getTypeSize(VET_FLOAT3);
125  m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
126  offset += VertexElement::getTypeSize(VET_FLOAT3);
127  m_vertex_format->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
128  offset += VertexElement::getTypeSize(VET_FLOAT2);
129 
130  // Allocate position buffer of the requested number of vertices (vertexCount)
131  // and bytes per position (offset)
132  m_hw_vbuf =
133  HardwareBufferManager::getSingleton().createVertexBuffer(
134  offset, m_mesh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
135 
136  // Upload the position data to the card
137  m_hw_vbuf->writeData(0, m_hw_vbuf->getSizeInBytes(), m_vertices.data(), true);
138 
139  // Set position buffer binding so buffer 0 is bound to our position buffer
140  VertexBufferBinding* bind = m_mesh->sharedVertexData->vertexBufferBinding;
141  bind->setBinding(0, m_hw_vbuf);
142 
143  //for the face
144  // Allocate index buffer of the requested number of vertices (m_index_count)
145  HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
146  createIndexBuffer(
147  HardwareIndexBuffer::IT_16BIT,
149  HardwareBuffer::HBU_STATIC_WRITE_ONLY);
150 
151  // Upload the index data to the card
152  ibuf->writeData(0, ibuf->getSizeInBytes(), m_indices.data(), true);
153  m_indices.clear(); // We won't need these anymore.
154 
155  // Set parameters of the submesh
156  m_submesh->useSharedVertices = true;
157  m_submesh->indexData->indexBuffer = ibuf;
158  m_submesh->indexData->indexCount = m_index_count;
159  m_submesh->indexData->indexStart = 0;
160 
161 
162  // Set bounding information (for culling)
163  m_mesh->_setBounds(AxisAlignedBox(-1,-1,0,1,1,0), true);
164 
165  m_mesh->load();
166 }
167 
169 {
170  // Rim: we own both Entity and SceneNode
171  m_rim_scene_node->detachAllObjects();
172  App::GetGfxScene()->GetSceneManager()->destroySceneNode(m_rim_scene_node);
173  App::GetGfxScene()->GetSceneManager()->destroyEntity(m_rim_entity);
174  m_rim_entity = nullptr;
175 
176  // Tyre: we own the Entity, SceneNode is owned by vwheel_t
177  m_tire_entity->detachFromParent();
178  App::GetGfxScene()->GetSceneManager()->destroyEntity(m_tire_entity);
179  m_tire_entity = nullptr;
180 
181  // Delete tyre mesh
182  m_mesh->unload();
183  Ogre::MeshManager::getSingleton().remove(m_mesh->getHandle());
184  m_mesh.setNull();
185 }
186 
188 {
189  RoR::NodeSB* all_nodes = m_gfx_actor->GetSimNodeBuffer();
190  Vector3 center = (all_nodes[m_axis_node0_idx].AbsPosition + all_nodes[m_axis_node1_idx].AbsPosition) / 2.0;
191  Vector3 ray = all_nodes[m_start_node_idx].AbsPosition - all_nodes[m_axis_node0_idx].AbsPosition;
192  Vector3 axis = all_nodes[m_axis_node0_idx].AbsPosition - all_nodes[m_axis_node1_idx].AbsPosition;
193 
194  axis.normalise();
195 
196  for (size_t i=0; i<m_num_rays; i++)
197  {
198  Plane pl=Plane(axis, all_nodes[m_axis_node0_idx].AbsPosition);
199  ray=all_nodes[m_start_node_idx+i*2].AbsPosition-all_nodes[m_axis_node0_idx].AbsPosition;
200  ray=pl.projectVector(ray);
201  ray.normalise();
202  m_vertices[i*6 ].position=all_nodes[m_axis_node0_idx].AbsPosition+m_rim_radius*ray-center;
203 
204  m_vertices[i*6+1].position=all_nodes[m_start_node_idx+i*2].AbsPosition-0.05 *(all_nodes[m_start_node_idx+i*2].AbsPosition-all_nodes[m_axis_node0_idx].AbsPosition)-center;
205  m_vertices[i*6+2].position=all_nodes[m_start_node_idx+i*2].AbsPosition-0.1 *(all_nodes[m_start_node_idx+i*2].AbsPosition-all_nodes[m_start_node_idx+i*2+1].AbsPosition)-center;
206  m_vertices[i*6+3].position=all_nodes[m_start_node_idx+i*2+1].AbsPosition-0.1 *(all_nodes[m_start_node_idx+i*2+1].AbsPosition-all_nodes[m_start_node_idx+i*2].AbsPosition)-center;
207  m_vertices[i*6+4].position=all_nodes[m_start_node_idx+i*2+1].AbsPosition-0.05*(all_nodes[m_start_node_idx+i*2+1].AbsPosition-all_nodes[m_axis_node1_idx].AbsPosition)-center;
208 
209  pl=Plane(-axis, all_nodes[m_axis_node1_idx].AbsPosition);
210  ray=all_nodes[m_start_node_idx+i*2+1].AbsPosition-all_nodes[m_axis_node1_idx].AbsPosition;
211  ray=pl.projectVector(ray);
212  ray.normalise();
213  m_vertices[i*6+5].position=all_nodes[m_axis_node1_idx].AbsPosition+m_rim_radius*ray-center;
214 
215  //normals
216  m_vertices[i*6 ].normal=axis;
217  m_vertices[i*6+1].normal=(m_vertices[i*6].position-m_vertices[i*6+1].position).crossProduct(m_vertices[i*6].position-m_vertices[((i+1)%m_num_rays)*6+1].position)/m_norm_y;
218  m_vertices[i*6+2].normal=ray;
219  m_vertices[i*6+3].normal=ray;
220  m_vertices[i*6+4].normal=(m_vertices[i*6+4].position-m_vertices[i*6+5].position).crossProduct(m_vertices[i*6+4].position-m_vertices[((i+1)%m_num_rays)*6+4].position)/m_norm_y;
221  m_vertices[i*6+5].normal=-axis;
222  }
223  for (int i=0; i<6; i++)
224  {
225  m_vertices[m_num_rays*6+i].position=m_vertices[i].position;
226  m_vertices[m_num_rays*6+i].normal=m_vertices[i].normal;
227  }
228 
229  return center;
230 }
231 
232 void FlexMeshWheel::setVisible(bool visible)
233 {
234  if (m_rim_scene_node) m_rim_scene_node->setVisible(visible);
235 }
236 
238 {
239  RoR::NodeSB* all_nodes = m_gfx_actor->GetSimNodeBuffer();
240  Vector3 center = (all_nodes[m_axis_node0_idx].AbsPosition + all_nodes[m_axis_node1_idx].AbsPosition) / 2.0;
241  m_rim_scene_node->setPosition(center);
242 
243  Vector3 axis = all_nodes[m_axis_node0_idx].AbsPosition - all_nodes[m_axis_node1_idx].AbsPosition;
244  axis.normalise();
245 
246  if (m_is_rim_reverse) axis = -axis;
247  Vector3 ray = all_nodes[m_start_node_idx].AbsPosition - all_nodes[m_axis_node0_idx].AbsPosition;
248  Vector3 onormal = axis.crossProduct(ray);
249  onormal.normalise();
250  ray = axis.crossProduct(onormal);
251  m_rim_scene_node->setOrientation(Quaternion(axis, onormal, ray));
252 
253  return true;
254 }
255 
257 {
259 }
260 
262 {
263  m_hw_vbuf->writeData(0, m_hw_vbuf->getSizeInBytes(), m_vertices.data(), true);
264  return m_flexit_center;
265 }
RoR::FlexMeshWheel::m_vertices
std::vector< FlexMeshWheelVertex > m_vertices
Definition: FlexMeshWheel.h:104
FlexMeshWheel.h
RoR::NodeSB
Definition: SimBuffers.h:67
RoR::FlexMeshWheel::m_hw_vbuf
Ogre::HardwareVertexBufferSharedPtr m_hw_vbuf
Definition: FlexMeshWheel.h:106
RoR::FlexMeshWheel::m_flexit_center
Ogre::Vector3 m_flexit_center
Definition: FlexMeshWheel.h:93
RoR::GfxActor::GetSimNodeBuffer
NodeSB * GetSimNodeBuffer()
Definition: GfxActor.h:120
RoR::FlexMeshWheel::m_tire_entity
Ogre::Entity * m_tire_entity
Definition: FlexMeshWheel.h:98
RoR::FlexMeshWheel::m_rim_scene_node
Ogre::SceneNode * m_rim_scene_node
Definition: FlexMeshWheel.h:99
RoR::FlexMeshWheel::m_index_count
size_t m_index_count
Definition: FlexMeshWheel.h:109
RoR::FlexMeshWheel::m_indices
std::vector< unsigned short > m_indices
Definition: FlexMeshWheel.h:110
RoR::GfxScene::GetSceneManager
Ogre::SceneManager * GetSceneManager()
Definition: GfxScene.h:64
RoR::FlexMeshWheel::m_axis_node1_idx
int m_axis_node1_idx
Definition: FlexMeshWheel.h:89
RoR::FlexMeshWheel::m_submesh
Ogre::SubMesh * m_submesh
Definition: FlexMeshWheel.h:95
RoR::FlexMeshWheel::m_rim_radius
float m_rim_radius
Definition: FlexMeshWheel.h:86
SimData.h
Core data structures for simulation; Everything affected by by either physics, network or user intera...
RoR::FlexMeshWheel::m_vertex_count
size_t m_vertex_count
Definition: FlexMeshWheel.h:103
RoR::FlexMeshWheel::~FlexMeshWheel
~FlexMeshWheel()
Definition: FlexMeshWheel.cpp:168
GfxScene.h
RoR::FlexMeshWheel::flexitFinal
Ogre::Vector3 flexitFinal()
Definition: FlexMeshWheel.cpp:261
RoR::FlexMeshWheel::m_axis_node0_idx
int m_axis_node0_idx
Definition: FlexMeshWheel.h:88
Application.h
Central state/object manager and communications hub.
RoR::FlexMeshWheel::flexitCompute
void flexitCompute()
Definition: FlexMeshWheel.cpp:256
RoR::FlexMeshWheel::m_start_node_idx
int m_start_node_idx
First node (lowest index) belonging to this wheel.
Definition: FlexMeshWheel.h:90
RoR::FlexMeshWheel::m_gfx_actor
RoR::GfxActor * m_gfx_actor
Definition: FlexMeshWheel.h:87
RoR::FlexMeshWheel::flexitPrepare
bool flexitPrepare()
Definition: FlexMeshWheel.cpp:237
RoR::FlexMeshWheel::m_num_rays
size_t m_num_rays
Definition: FlexMeshWheel.h:85
RoR::NodeSB::AbsPosition
Ogre::Vector3 AbsPosition
Definition: SimBuffers.h:69
RoR::FlexMeshWheel::updateVertices
Ogre::Vector3 updateVertices()
Definition: FlexMeshWheel.cpp:187
RoR::FlexMeshWheel::m_norm_y
float m_norm_y
Definition: FlexMeshWheel.h:102
RoR::FlexMeshWheel::m_rim_entity
Ogre::Entity * m_rim_entity
Definition: FlexMeshWheel.h:97
RoR::GfxActor
Definition: GfxActor.h:52
RoR::FlexMeshWheel::m_vertex_format
Ogre::VertexDeclaration * m_vertex_format
Definition: FlexMeshWheel.h:105
Ogre
Definition: ExtinguishableFireAffector.cpp:35
GfxActor.h
Manager for all visuals belonging to a single actor.
RoR::FlexMeshWheel::m_is_rim_reverse
bool m_is_rim_reverse
Definition: FlexMeshWheel.h:96
RoR::FlexMeshWheel::setVisible
void setVisible(bool visible)
Definition: FlexMeshWheel.cpp:232
RoR::FlexMeshWheel::m_mesh
Ogre::MeshPtr m_mesh
Definition: FlexMeshWheel.h:94
RoR
Definition: AppContext.h:36
RoR::App::GetGfxScene
GfxScene * GetGfxScene()
Definition: Application.cpp:276