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
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
31using namespace Ogre;
32using namespace RoR;
33
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);
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;
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
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
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();
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.reset();
185}
186
188{
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
233{
234 if (m_rim_scene_node) m_rim_scene_node->setVisible(visible);
235}
236
238{
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
260
262{
263 m_hw_vbuf->writeData(0, m_hw_vbuf->getSizeInBytes(), m_vertices.data(), true);
264 return m_flexit_center;
265}
Central state/object manager and communications hub.
Manager for all visuals belonging to a single actor.
Core data structures for simulation; Everything affected by by either physics, network or user intera...
Ogre::Vector3 flexitFinal()
Ogre::Entity * m_rim_entity
std::vector< FlexMeshWheelVertex > m_vertices
Ogre::HardwareVertexBufferSharedPtr m_hw_vbuf
int m_start_node_idx
First node (lowest index) belonging to this wheel.
std::vector< unsigned short > m_indices
FlexMeshWheel(Ogre::Entity *rim_prop_entity, Ogre::SceneNode *rim_scene_node, RoR::GfxActor *gfx_actor, int axis_node_1_index, int axis_node_2_index, int nstart, int nrays, std::string const &tire_mesh_name, std::string const &tire_mesh_rg, std::string const &tire_material_name, std::string const &tire_material_rg, float rimradius, bool rimreverse)
Ogre::SceneNode * m_rim_scene_node
RoR::GfxActor * m_gfx_actor
Ogre::SubMesh * m_submesh
void setVisible(bool visible)
Ogre::MeshPtr m_mesh
Ogre::Vector3 m_flexit_center
Ogre::VertexDeclaration * m_vertex_format
Ogre::Vector3 updateVertices()
Ogre::Entity * m_tire_entity
NodeSB * GetSimNodeBuffer()
Definition GfxActor.h:129
Ogre::SceneManager * GetSceneManager()
Definition GfxScene.h:83
GfxScene * GetGfxScene()
Ogre::Vector3 AbsPosition
Definition SimBuffers.h:69