RigsofRods
Soft-body Physics Simulation
FlexAirfoil.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 
6  For more information, see http://www.rigsofrods.org/
7 
8  Rigs of Rods is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License version 3, as
10  published by the Free Software Foundation.
11 
12  Rigs of Rods is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include "FlexAirfoil.h"
22 
23 #include "AeroEngine.h"
24 #include "Airfoil.h"
25 #include "ApproxMath.h"
26 #include "Actor.h"
27 #include "SimData.h"
28 #include "GfxActor.h"
29 
30 using namespace RoR;
31 
32 float refairfoilpos[90]={
33  0.00, 0.50, 0.00,
34  1.00, 0.50, 0.00,
35 
36  0.00, 0.70, 0.03,
37  1.00, 0.70, 0.03,
38  0.00, 0.30, 0.03,
39  1.00, 0.30, 0.03,
40 
41  0.00, 0.90, 0.10,
42  1.00, 0.90, 0.10,
43  0.00, 0.10, 0.10,
44  1.00, 0.10, 0.10,
45 
46  0.00, 1.00, 0.25,
47  1.00, 1.00, 0.25,
48  0.00, 0.00, 0.25,
49  1.00, 0.00, 0.25,
50 
51  0.00, 1.00, 0.50,
52  1.00, 1.00, 0.50,
53  0.00, 0.00, 0.50,
54  1.00, 0.00, 0.50,
55 
56  //updated with control surface chord ratio
57  0.00, 0.75, 0.75,
58  1.00, 0.75, 0.75,
59  0.00, 0.25, 0.75,
60  1.00, 0.25, 0.75,
61 
62  0.00, 0.75, 0.75,
63  1.00, 0.75, 0.75,
64  0.00, 0.25, 0.75,
65  1.00, 0.25, 0.75,
66 
67  //moving with control surface
68  0.00, 0.50, 1.00,
69  1.00, 0.50, 1.00,
70 
71  0.00, 0.50, 1.00,
72  1.00, 0.50, 1.00
73  };
74 
75 using namespace Ogre;
76 
77 FlexAirfoil::FlexAirfoil(Ogre::String const & name, ActorPtr actor, NodeNum_t pnfld, NodeNum_t pnfrd, NodeNum_t pnflu, NodeNum_t pnfru, NodeNum_t pnbld, NodeNum_t pnbrd, NodeNum_t pnblu, NodeNum_t pnbru, std::string const & texband, Vector2 texlf, Vector2 texrf, Vector2 texlb, Vector2 texrb, char mtype, float controlratio, float mind, float maxd, Ogre::String const & afname, float lift_coef, bool break_able)
78  :nfld(pnfld)
79  ,nfrd(pnfrd)
80  ,nflu(pnflu)
81  ,nfru(pnfru)
82  ,nbld(pnbld)
83  ,nbrd(pnbrd)
84  ,nblu(pnblu)
85  ,nbru(pnbru)
86 {
87  ROR_ASSERT(pnfld != NODENUM_INVALID);
88  ROR_ASSERT(pnfrd != NODENUM_INVALID);
89  ROR_ASSERT(pnflu != NODENUM_INVALID);
90  ROR_ASSERT(pnfru != NODENUM_INVALID);
91  ROR_ASSERT(pnbld != NODENUM_INVALID);
92  ROR_ASSERT(pnbrd != NODENUM_INVALID);
93  ROR_ASSERT(pnblu != NODENUM_INVALID);
94  ROR_ASSERT(pnbru != NODENUM_INVALID);
95 
96  liftcoef=lift_coef;
97  breakable=break_able;
98  broken=false;
99  free_wash=0;
101  nodes=actor->ar_nodes;
102  useInducedDrag=false;
103 
104  mindef=mind;
105  maxdef=maxd;
106  airfoil=new Airfoil(afname);
107  int i;
108  for (i=0; i<90; i++) airfoilpos[i]=refairfoilpos[i];
109  type=mtype;
110  hascontrol=(mtype!='n' && mtype!='S'&& mtype!='T' && mtype!='U'&& mtype!='V');
111  isstabilator=(mtype=='S' || mtype=='T' || mtype=='U' || mtype=='V');
112  stabilleft=(mtype=='T' || mtype=='V');
113  deflection=0.0;
114  chordratio=controlratio;
115 
116  if (hascontrol)
117  {
118  //setup control surface
119  airfoilpos[56]=controlratio;
120  airfoilpos[56+3]=controlratio;
121  airfoilpos[56+6]=controlratio;
122  airfoilpos[56+9]=controlratio;
123 
124  airfoilpos[55]=-controlratio+1.5;
125  airfoilpos[55+3]=-controlratio+1.5;
126  airfoilpos[55+6]=controlratio-0.5;
127  airfoilpos[55+9]=controlratio-0.5;
128  for (i=0; i<12; i++) airfoilpos[54+12+i]=airfoilpos[54+i];
129  }
131  msh = MeshManager::getSingleton().createManual(name, actor->GetGfxActor()->GetResourceGroup());
132 
134  subface = msh->createSubMesh();
135  subband = msh->createSubMesh();
136  subcup = msh->createSubMesh();
137  subcdn = msh->createSubMesh();
138 
139  //materials
140  subface->setMaterialName(texband);
141  subband->setMaterialName(texband);
142  subcup->setMaterialName(texband);
143  subcdn->setMaterialName(texband);
144 
146  nVertices = 24*2+4+2;
147  vbufCount = (2*3+2)*nVertices;
148  vertices=(float*)malloc(vbufCount*sizeof(float));
149 
150  //textures coordinates
151  covertices[0].texcoord=texlf;
152  covertices[1].texcoord=texrf;
153 
154  covertices[2].texcoord=texlf+(texlb-texlf)*0.03;
155  covertices[3].texcoord=texrf+(texrb-texrf)*0.03;
156  covertices[4].texcoord=texlf+(texlb-texlf)*0.03;
157  covertices[5].texcoord=texrf+(texrb-texrf)*0.03;
158 
159  covertices[6].texcoord=texlf+(texlb-texlf)*0.10;
160  covertices[7].texcoord=texrf+(texrb-texrf)*0.10;
161  covertices[8].texcoord=texlf+(texlb-texlf)*0.10;
162  covertices[9].texcoord=texrf+(texrb-texrf)*0.10;
163 
164  covertices[10].texcoord=texlf+(texlb-texlf)*0.25;
165  covertices[11].texcoord=texrf+(texrb-texrf)*0.25;
166  covertices[12].texcoord=texlf+(texlb-texlf)*0.25;
167  covertices[13].texcoord=texrf+(texrb-texrf)*0.25;
168 
169  covertices[14].texcoord=texlf+(texlb-texlf)*0.45;
170  covertices[15].texcoord=texrf+(texrb-texrf)*0.45;
171  covertices[16].texcoord=texlf+(texlb-texlf)*0.45;
172  covertices[17].texcoord=texrf+(texrb-texrf)*0.45;
173 
174  covertices[18].texcoord=texlf+(texlb-texlf)*airfoilpos[56];
175  covertices[19].texcoord=texrf+(texrb-texrf)*airfoilpos[56];
176  covertices[20].texcoord=texlf+(texlb-texlf)*airfoilpos[56];
177  covertices[21].texcoord=texrf+(texrb-texrf)*airfoilpos[56];
178 
183 
184  covertices[26].texcoord=texlb;
185  covertices[27].texcoord=texrb;
186  covertices[28].texcoord=texlb;
187  covertices[29].texcoord=texrb;
188 
189  for (i=0; i<24; i++) covertices[i+30].texcoord=covertices[i].texcoord;
190 
193  bandibufCount = 3*20;
194  faceibufCount = 3*20;
195  cupibufCount=3*2;
196  cdnibufCount=3*2;
197  facefaces=(unsigned short*)malloc(faceibufCount*sizeof(unsigned short));
198  bandfaces=(unsigned short*)malloc(bandibufCount*sizeof(unsigned short));
199  cupfaces=(unsigned short*)malloc(cupibufCount*sizeof(unsigned short));
200  cdnfaces=(unsigned short*)malloc(cdnibufCount*sizeof(unsigned short));
201 
202  //attack
203  bandfaces[0]=0;
204  bandfaces[1]=2;
205  bandfaces[2]=1;
206 
207  bandfaces[3]=2;
208  bandfaces[4]=3;
209  bandfaces[5]=1;
210 
211  bandfaces[6]=0;
212  bandfaces[7]=1;
213  bandfaces[8]=4;
214 
215  bandfaces[9]=4;
216  bandfaces[10]=1;
217  bandfaces[11]=5;
218  for (i=0; i<5; i++)
219  {
220  //band
221  int v=i*4+2;
222  if (i!=4)
223  {
224  bandfaces[i*12+12]=v;
225  bandfaces[i*12+13]=v+4;
226  bandfaces[i*12+14]=v+1;
227 
228  bandfaces[i*12+15]=v+4;
229  bandfaces[i*12+16]=v+5;
230  bandfaces[i*12+17]=v+1;
231 
232  bandfaces[i*12+18]=v+2;
233  bandfaces[i*12+19]=v+3;
234  bandfaces[i*12+20]=v+6;
235 
236  bandfaces[i*12+21]=v+6;
237  bandfaces[i*12+22]=v+3;
238  bandfaces[i*12+23]=v+7;
239  }
240 
241  //sides
242  facefaces[i*12]=30+0;
243  facefaces[i*12+1]=30+v+4;
244  facefaces[i*12+2]=30+v;
245 
246  facefaces[i*12+3]=30+0;
247  facefaces[i*12+4]=30+v+2;
248  facefaces[i*12+5]=30+v+6;
249 
250  facefaces[i*12+6]=30+1;
251  facefaces[i*12+7]=30+v+1;
252  facefaces[i*12+8]=30+v+5;
253 
254  facefaces[i*12+9]=30+1;
255  facefaces[i*12+10]=30+v+7;
256  facefaces[i*12+11]=30+v+3;
257  if (i==4)
258  {
259  facefaces[i*12]=30+0;
260  facefaces[i*12+1]=30+v+2;
261  facefaces[i*12+2]=30+v;
262 
263  facefaces[i*12+3]=30+v+4;
264  facefaces[i*12+4]=30+v;
265  facefaces[i*12+5]=30+v+2;
266 
267  facefaces[i*12+6]=30+1;
268  facefaces[i*12+7]=30+v+1;
269  facefaces[i*12+8]=30+v+3;
270 
271  facefaces[i*12+9]=30+v+5;
272  facefaces[i*12+10]=30+v+3;
273  facefaces[i*12+11]=30+v+1;
274  }
275 
276  }
277  cupfaces[0]=22;
278  cupfaces[1]=26;
279  cupfaces[2]=23;
280  cupfaces[3]=26;
281  cupfaces[4]=27;
282  cupfaces[5]=23;
283 
284  cdnfaces[0]=24;
285  cdnfaces[1]=25;
286  cdnfaces[2]=29;
287  cdnfaces[3]=24;
288  cdnfaces[4]=29;
289  cdnfaces[5]=28;
290 
291  float tsref=2.0*(nodes[nfrd].RelPosition-nodes[nfld].RelPosition).crossProduct(nodes[nbld].RelPosition-nodes[nfld].RelPosition).length();
292  sref=2.0*(nodes[nfrd].RelPosition-nodes[nfld].RelPosition).crossProduct(nodes[nbrd].RelPosition-nodes[nfrd].RelPosition).length();
293  if (tsref>sref) sref=tsref;
294  sref=sref*sref;
295 
298 
300 
301  //update coords
302  this->updateVerticesPhysics();
303  this->updateVerticesGfx(actor->GetGfxActor());
304 
306  msh->sharedVertexData = new VertexData();
307  msh->sharedVertexData->vertexCount = nVertices;
308 
310  decl = msh->sharedVertexData->vertexDeclaration;
311  size_t offset = 0;
312  decl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
313  offset += VertexElement::getTypeSize(VET_FLOAT3);
314  decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
315  offset += VertexElement::getTypeSize(VET_FLOAT3);
316 // decl->addElement(0, offset, VET_FLOAT3, VES_DIFFUSE);
317 // offset += VertexElement::getTypeSize(VET_FLOAT3);
318  decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
319  offset += VertexElement::getTypeSize(VET_FLOAT2);
320 
323  vbuf =
324  HardwareBufferManager::getSingleton().createVertexBuffer(
325  offset, msh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
326 
328  vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true);
329 
331  VertexBufferBinding* bind = msh->sharedVertexData->vertexBufferBinding;
332  bind->setBinding(0, vbuf);
333 
334  //for the face
336  HardwareIndexBufferSharedPtr faceibuf = HardwareBufferManager::getSingleton().
337  createIndexBuffer(
338  HardwareIndexBuffer::IT_16BIT,
340  HardwareBuffer::HBU_STATIC_WRITE_ONLY);
341 
343  faceibuf->writeData(0, faceibuf->getSizeInBytes(), facefaces, true);
344 
346  subface->useSharedVertices = true;
347  subface->indexData->indexBuffer = faceibuf;
348  subface->indexData->indexCount = faceibufCount;
349  subface->indexData->indexStart = 0;
350 
351  //for the band
353  HardwareIndexBufferSharedPtr bandibuf = HardwareBufferManager::getSingleton().
354  createIndexBuffer(
355  HardwareIndexBuffer::IT_16BIT,
357  HardwareBuffer::HBU_STATIC_WRITE_ONLY);
358 
360  bandibuf->writeData(0, bandibuf->getSizeInBytes(), bandfaces, true);
361 
363  subband->useSharedVertices = true;
364  subband->indexData->indexBuffer = bandibuf;
365  subband->indexData->indexCount = bandibufCount;
366  subband->indexData->indexStart = 0;
367 
368  //for the aileron up
370  HardwareIndexBufferSharedPtr cupibuf = HardwareBufferManager::getSingleton().
371  createIndexBuffer(
372  HardwareIndexBuffer::IT_16BIT,
373  cupibufCount,
374  HardwareBuffer::HBU_STATIC_WRITE_ONLY);
375 
377  cupibuf->writeData(0, cupibuf->getSizeInBytes(), cupfaces, true);
378 
380  subcup->useSharedVertices = true;
381  subcup->indexData->indexBuffer = cupibuf;
382  subcup->indexData->indexCount = cupibufCount;
383  subcup->indexData->indexStart = 0;
384 
385  //for the aileron down
387  HardwareIndexBufferSharedPtr cdnibuf = HardwareBufferManager::getSingleton().
388  createIndexBuffer(
389  HardwareIndexBuffer::IT_16BIT,
390  cdnibufCount,
391  HardwareBuffer::HBU_STATIC_WRITE_ONLY);
392 
394  cdnibuf->writeData(0, cdnibuf->getSizeInBytes(), cdnfaces, true);
395 
397  subcdn->useSharedVertices = true;
398  subcdn->indexData->indexBuffer = cdnibuf;
399  subcdn->indexData->indexCount = cdnibufCount;
400  subcdn->indexData->indexStart = 0;
401 
403  msh->_setBounds(AxisAlignedBox(-20,-20,-20,20,20,20), true);
404  //msh->_setBoundingSphereRadius(20.0);
405 
407  //MeshManager::getSingleton().setPrepareAllMeshesForShadowVolumes(false);
408  //msh->prepareForShadowVolume();
409  msh->load();
410  //MeshManager::getSingleton().setPrepareAllMeshesForShadowVolumes()
411 }
412 
414 {
415  Vector3 center;
416  center=nodes[nfld].AbsPosition;
417 
419  Vector3 vyl=nodes[nflu].AbsPosition-nodes[nfld].AbsPosition;
420  Vector3 vzl=nodes[nbld].AbsPosition-nodes[nfld].AbsPosition;
421  Vector3 vyr=nodes[nfru].AbsPosition-nodes[nfrd].AbsPosition;
422  Vector3 vzr=nodes[nbrd].AbsPosition-nodes[nfrd].AbsPosition;
423 
424  if (breakable) {broken=broken || (vx.crossProduct(vzl).squaredLength()>sref)||(vx.crossProduct(vzr).squaredLength()>sref);}
425  else {broken=(vx.crossProduct(vzl).squaredLength()>sref)||(vx.crossProduct(vzr).squaredLength()>sref);}
426 
427  //control surface
428  if (hascontrol)
429  {
430  float radius=1.0-chordratio;
431  airfoilpos[82]=0.5+radius*sin(deflection/57.0)/rratio;
432  airfoilpos[79]=0.5+radius*sin(deflection/57.0)/lratio;
433  airfoilpos[83]=chordratio+radius*cos(deflection/57.0);
434  airfoilpos[80]=airfoilpos[83];
435  airfoilpos[89]=airfoilpos[83];
436  airfoilpos[88]=airfoilpos[82];
437  airfoilpos[86]=airfoilpos[80];
438  airfoilpos[85]=airfoilpos[79];
439  }
440 }
441 
443 {
444  auto gfx_nodes = gfx_actor->GetSimNodeBuffer();
445  int i;
446  Vector3 center;
447  center=gfx_nodes[nfld].AbsPosition;
448 
449  Vector3 vx=gfx_nodes[nfrd].AbsPosition-gfx_nodes[nfld].AbsPosition;
450  Vector3 vyl=gfx_nodes[nflu].AbsPosition-gfx_nodes[nfld].AbsPosition;
451  Vector3 vzl=gfx_nodes[nbld].AbsPosition-gfx_nodes[nfld].AbsPosition;
452  Vector3 vyr=gfx_nodes[nfru].AbsPosition-gfx_nodes[nfrd].AbsPosition;
453  Vector3 vzr=gfx_nodes[nbrd].AbsPosition-gfx_nodes[nfrd].AbsPosition;
454 
455  Vector3 facenormal=vx;
456  facenormal.normalise();
457 
458  if (!broken)
459  {
460  for (i=0; i<30; i++)
461  {
462  if (i%2)
463  covertices[i].vertex=airfoilpos[i*3]*vx+airfoilpos[i*3+1]*vyr+airfoilpos[i*3+2]*vzr;
464  else
465  covertices[i].vertex=airfoilpos[i*3]*vx+airfoilpos[i*3+1]*vyl+airfoilpos[i*3+2]*vzl;
466  if (i<22) covertices[i+30].vertex=covertices[i].vertex;
467  }
468  covertices[30+22].vertex=covertices[28].vertex;
469  covertices[30+23].vertex=covertices[29].vertex;
470  }
471  else
472  {
473  for (i=0; i<30; i++)
474  {
475  if (i%2)
476  covertices[i].vertex=airfoilpos[i*3]*Vector3(0.01,0,0)+airfoilpos[i*3+1]*Vector3(0,0.01,0)+airfoilpos[i*3+2]*Vector3(0,0,0.01);
477  else
478  covertices[i].vertex=airfoilpos[i*3]*Vector3(0.01,0,0)+airfoilpos[i*3+1]*Vector3(0,0.01,0)+airfoilpos[i*3+2]*Vector3(0,0,0.01);
479  if (i<22) covertices[i+30].vertex=covertices[i].vertex;
480  }
481  covertices[30+22].vertex=covertices[28].vertex;
482  covertices[30+23].vertex=covertices[29].vertex;
483  }
484 
485  if (isstabilator)
486  {
487  //rotate stabilator
488  Vector3 rcent, raxis;
489  if (!stabilleft)
490  {
491  rcent=((gfx_nodes[nflu].AbsPosition+gfx_nodes[nbld].AbsPosition)/2.0+(gfx_nodes[nflu].AbsPosition-gfx_nodes[nblu].AbsPosition)/4.0)-center;
492  raxis=(gfx_nodes[nflu].AbsPosition-gfx_nodes[nfld].AbsPosition).crossProduct(gfx_nodes[nflu].AbsPosition-gfx_nodes[nblu].AbsPosition);
493  }
494  else
495  {
496  rcent=((gfx_nodes[nfru].AbsPosition+gfx_nodes[nbrd].AbsPosition)/2.0+(gfx_nodes[nfru].AbsPosition-gfx_nodes[nbru].AbsPosition)/4.0)-center;
497  raxis=(gfx_nodes[nfru].AbsPosition-gfx_nodes[nfrd].AbsPosition).crossProduct(gfx_nodes[nfru].AbsPosition-gfx_nodes[nbru].AbsPosition);
498  }
499  raxis.normalise();
500  Quaternion rot=Quaternion(Degree(deflection), raxis);
501  for (i=0; i<54; i++)
502  {
503  covertices[i].vertex=rcent+rot*(covertices[i].vertex-rcent);
504  }
505  }
506 
507  //init normals
508  for (i=0; i<(int)nVertices; i++)
509  {
510  covertices[i].normal=Vector3::ZERO;
511  }
512  //normals
513  //accumulate normals per triangle
514  for (i=0; i<(int)bandibufCount/3; i++)
515  {
516  Vector3 v1, v2;
519  v1=v1.crossProduct(v2);
520  v1.normalise();
521  covertices[bandfaces[i*3]].normal+=v1;
522  covertices[bandfaces[i*3+1]].normal+=v1;
523  covertices[bandfaces[i*3+2]].normal+=v1;
524  }
525  for (i=0; i<(int)cupibufCount/3; i++)
526  {
527  Vector3 v1, v2;
530  v1=v1.crossProduct(v2);
531  v1.normalise();
532  covertices[cupfaces[i*3]].normal+=v1;
533  covertices[cupfaces[i*3+1]].normal+=v1;
534  covertices[cupfaces[i*3+2]].normal+=v1;
535  }
536  for (i=0; i<(int)cdnibufCount/3; i++)
537  {
538  Vector3 v1, v2;
541  v1=v1.crossProduct(v2);
542  v1.normalise();
543  covertices[cdnfaces[i*3]].normal+=v1;
544  covertices[cdnfaces[i*3+1]].normal+=v1;
545  covertices[cdnfaces[i*3+2]].normal+=v1;
546  }
547  //normalize
548  for (i=0; i<30; i++)
549  {
550  covertices[i].normal.normalise();
551  }
552 
553  //for the faces
554  for (i=0; i<24; i++)
555  if (i%2)
556  covertices[i+30].normal=facenormal;
557  else
558  covertices[i+30].normal=-facenormal;
559 
560  return center;
561 }
562 
564 {
565  vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true);
566 }
567 
568 
570 {
571  if (val<0) deflection=-val*mindef;
572  else deflection=val*maxdef;
573 }
574 
575 void FlexAirfoil::enableInducedDrag(float span, float area, bool l)
576 {
577  idSpan=span;
578  idArea=area;
579  useInducedDrag=true;
580  idLeft=l;
581 }
582 
583 void FlexAirfoil::addwash(int propid, float ratio)
584 {
585  washpropnum[free_wash]=propid;
586  washpropratio[free_wash]=ratio;
587  free_wash++;
588 }
589 
591 {
592  if (!airfoil) return;
593  if (broken) return;
594 
595  //evaluate wind direction
596  Vector3 wind=-(nodes[nfld].Velocity+nodes[nfrd].Velocity)/2.0;
597  //add wash
598  int i;
599  for (i=0; i<free_wash; i++)
600  wind-=(0.5*washpropratio[i]*aeroengines[washpropnum[i]]->getpropwash())*aeroengines[washpropnum[i]]->getAxis();
601  float wspeed=wind.length();
602  //chord vector, front to back
603  Vector3 chordv=((nodes[nbld].RelPosition-nodes[nfld].RelPosition)+(nodes[nbrd].RelPosition-nodes[nfrd].RelPosition))/2.0;
604  float chord=chordv.length();
605  //span vector, left to right
606  Vector3 spanv=((nodes[nfrd].RelPosition-nodes[nfld].RelPosition)+(nodes[nbrd].RelPosition-nodes[nbld].RelPosition))/2.0;
607  float span=spanv.length();
608  //lift vector
609  Vector3 liftv=spanv.crossProduct(-wind);
610 
611  //wing normal
612  float s=span*chord;
613  Vector3 normv=chordv.crossProduct(spanv);
614  normv.normalise();
615  //calculate angle of attack
616  Vector3 pwind;
617  pwind=Plane(Vector3::ZERO, normv, chordv).projectVector(-wind);
618  Vector3 dumb;
619  Degree daoa;
620  chordv.getRotationTo(-pwind).ToAngleAxis(daoa, dumb);
621  aoa=daoa.valueDegrees();
622  float raoa=daoa.valueRadians();
623  if (dumb.dotProduct(spanv)>0) {aoa=-aoa; raoa=-raoa;};
624 
625  //get airfoil data
626  float cz, cx, cm;
627  if (isstabilator)
628  airfoil->getparams(aoa-deflection, chordratio, 0, &cz, &cx, &cm);
629  else
630  airfoil->getparams(aoa, chordratio, deflection, &cz, &cx, &cm);
631 
632 
633  //tropospheric model valid up to 11.000m (33.000ft)
634  float altitude=nodes[nfld].AbsPosition.y;
635  float sea_level_pressure=101325; //in Pa
636  float airpressure=sea_level_pressure*approx_pow(1.0-0.0065*altitude/288.15, 5.24947); //in Pa
637  float airdensity=airpressure*0.0000120896;//1.225 at sea level
638 
639  Vector3 wforce=Vector3::ZERO;
640  //drag
641  wforce=(cx*0.5*airdensity*wspeed*s)*wind;
642 
643  //induced drag
644  if (useInducedDrag)
645  {
646  Vector3 idf=(cx*cx*0.25*airdensity*wspeed*idArea*idArea/(3.14159*idSpan*idSpan))*wind;
647 
648  if (idLeft)
649  {
650  nodes[nblu].Forces+=idf;
651  nodes[nbld].Forces+=idf;
652  }
653  else
654  {
655  nodes[nbru].Forces+=idf;
656  nodes[nbrd].Forces+=idf;
657  }
658  }
659 
660  //lift
661  wforce+=(cz*0.5*airdensity*wspeed*chord)*liftv;
662 
663  //moment
664  float moment=-cm*0.5*airdensity*wspeed*wspeed*s;//*chord;
665  //apply forces
666 
667  Vector3 f1=wforce*(liftcoef * 0.75/4.0f)+normv*(liftcoef *moment/(4.0f*0.25f));
668  Vector3 f2=wforce*(liftcoef *0.25/4.0f)-normv*(liftcoef *moment/(4.0f*0.75f));
669 
670  //focal at 0.25 chord
671  nodes[nfld].Forces+=f1;
672  nodes[nflu].Forces+=f1;
673  nodes[nfrd].Forces+=f1;
674  nodes[nfru].Forces+=f1;
675  nodes[nbld].Forces+=f2;
676  nodes[nblu].Forces+=f2;
677  nodes[nbrd].Forces+=f2;
678  nodes[nbru].Forces+=f2;
679 
680 }
681 
683 {
684  if (airfoil) delete airfoil;
685  if (!msh.isNull())
686  {
687  msh->unload();
688  Ogre::MeshManager::getSingleton().remove(msh->getHandle()); // Necessary to truly erase manually created resource.
689  msh.setNull(); // Important! It's a shared pointer.
690  }
691 
692  if (vertices != nullptr) { free (vertices); }
693  if (facefaces != nullptr) { free (facefaces); }
694  if (bandfaces != nullptr) { free (bandfaces); }
695  if (cupfaces != nullptr) { free (cupfaces); }
696  if (cdnfaces != nullptr) { free (cdnfaces); }
697 }
ROR_ASSERT
#define ROR_ASSERT(_EXPR)
Definition: Application.h:40
RoR::FlexAirfoil::bandibufCount
size_t bandibufCount
Definition: FlexAirfoil.h:104
RoR::node_t::Velocity
Ogre::Vector3 Velocity
Definition: SimData.h:294
RoR::FlexAirfoil::washpropratio
float washpropratio[MAX_AEROENGINES]
Definition: FlexAirfoil.h:134
RoR::FlexAirfoil::idArea
float idArea
Definition: FlexAirfoil.h:127
RoR::FlexAirfoil::stabilleft
bool stabilleft
Definition: FlexAirfoil.h:119
RoR::FlexAirfoil::updateVerticesGfx
Ogre::Vector3 updateVerticesGfx(RoR::GfxActor *gfx_actor)
Definition: FlexAirfoil.cpp:442
RoR::FlexAirfoil::nfld
NodeNum_t nfld
Definition: FlexAirfoil.h:59
RoR::node_t::AbsPosition
Ogre::Vector3 AbsPosition
absolute position in the world (shaky)
Definition: SimData.h:293
RoR::FlexAirfoil::aoa
float aoa
Definition: FlexAirfoil.h:57
RoR::FlexAirfoil::lratio
float lratio
Definition: FlexAirfoil.h:120
RoR::GfxActor::GetSimNodeBuffer
NodeSB * GetSimNodeBuffer()
Definition: GfxActor.h:120
RoR::FlexAirfoil::isstabilator
bool isstabilator
Definition: FlexAirfoil.h:118
RoR::FlexAirfoil::vbuf
Ogre::HardwareVertexBufferSharedPtr vbuf
Definition: FlexAirfoil.h:92
RoR::NODENUM_INVALID
static const NodeNum_t NODENUM_INVALID
Definition: ForwardDeclarations.h:53
RoR::FlexAirfoil::rratio
float rratio
Definition: FlexAirfoil.h:121
refairfoilpos
float refairfoilpos[90]
Definition: FlexAirfoil.cpp:32
RoR::FlexAirfoil::liftcoef
float liftcoef
Definition: FlexAirfoil.h:70
RoR::FlexAirfoil::subcdn
Ogre::SubMesh * subcdn
Definition: FlexAirfoil.h:89
RoR::FlexAirfoil::washpropnum
int washpropnum[MAX_AEROENGINES]
Definition: FlexAirfoil.h:133
RoR::FlexAirfoil::thickness
float thickness
Definition: FlexAirfoil.h:124
RoR::FlexAirfoil::bandfaces
unsigned short * bandfaces
Definition: FlexAirfoil.h:108
RoR::FlexAirfoil::setControlDeflection
void setControlDeflection(float val)
Definition: FlexAirfoil.cpp:569
RoR::FlexAirfoil::covertices
CoVertice_t * covertices
Definition: FlexAirfoil.h:100
RoR::FlexAirfoil::breakable
bool breakable
Definition: FlexAirfoil.h:69
RoR::FlexAirfoil::nflu
NodeNum_t nflu
Definition: FlexAirfoil.h:61
Airfoil.h
RoR::Actor::GetGfxActor
GfxActor * GetGfxActor()
Definition: Actor.h:263
RoR::node_t::RelPosition
Ogre::Vector3 RelPosition
relative to the local physics origin (one origin per actor) (shaky)
Definition: SimData.h:292
RoR::FlexAirfoil::broken
bool broken
Definition: FlexAirfoil.h:68
RefCountingObjectPtr< Actor >
Actor.h
RoR::FlexAirfoil::uploadVertices
void uploadVertices()
Definition: FlexAirfoil.cpp:563
RoR::FlexAirfoil::deflection
float deflection
Definition: FlexAirfoil.h:115
RoR::FlexAirfoil::CoVertice_t::vertex
Ogre::Vector3 vertex
Definition: FlexAirfoil.h:78
RoR::FlexAirfoil::maxdef
float maxdef
Definition: FlexAirfoil.h:123
RoR::FlexAirfoil::addwash
void addwash(int propid, float ratio)
Definition: FlexAirfoil.cpp:583
RoR::Actor::ar_aeroengines
AeroEngine * ar_aeroengines[MAX_AEROENGINES]
Definition: Actor.h:323
RoR::FlexAirfoil::FlexAirfoil
FlexAirfoil(Ogre::String const &wname, ActorPtr actor, NodeNum_t pnfld, NodeNum_t pnfrd, NodeNum_t pnflu, NodeNum_t pnfru, NodeNum_t pnbld, NodeNum_t pnbrd, NodeNum_t pnblu, NodeNum_t pnbru, std::string const &texname, Ogre::Vector2 texlf, Ogre::Vector2 texrf, Ogre::Vector2 texlb, Ogre::Vector2 texrb, char mtype, float controlratio, float mind, float maxd, Ogre::String const &afname, float lift_coef, bool break_able)
Definition: FlexAirfoil.cpp:77
RoR::FlexAirfoil::aeroengines
AeroEngine ** aeroengines
Definition: FlexAirfoil.h:131
RoR::FlexAirfoil::nbld
NodeNum_t nbld
Definition: FlexAirfoil.h:63
RoR::NodeNum_t
uint16_t NodeNum_t
Node position within Actor::ar_nodes; use RoR::NODENUM_INVALID as empty value.
Definition: ForwardDeclarations.h:52
RoR::FlexAirfoil::airfoil
Airfoil * airfoil
Definition: FlexAirfoil.h:130
RoR::FlexAirfoil::airfoilpos
float airfoilpos[90]
Definition: FlexAirfoil.h:74
SimData.h
Core data structures for simulation; Everything affected by by either physics, network or user intera...
approx_pow
float approx_pow(const float x, const float y)
Definition: ApproxMath.h:91
RoR::FlexAirfoil::faceibufCount
size_t faceibufCount
Definition: FlexAirfoil.h:103
RoR::FlexAirfoil::nfrd
NodeNum_t nfrd
Definition: FlexAirfoil.h:60
RoR::Airfoil::getparams
void getparams(float a, float cratio, float cdef, float *ocl, float *ocd, float *ocm)
Definition: Airfoil.cpp:105
RoR::FlexAirfoil::cupfaces
unsigned short * cupfaces
Definition: FlexAirfoil.h:109
RoR::FlexAirfoil::subcup
Ogre::SubMesh * subcup
Definition: FlexAirfoil.h:88
RoR::FlexAirfoil::vertices
float * vertices
Definition: FlexAirfoil.h:99
RoR::FlexAirfoil::type
char type
Definition: FlexAirfoil.h:58
RoR::FlexAirfoil::cdnfaces
unsigned short * cdnfaces
Definition: FlexAirfoil.h:110
RoR::FlexAirfoil::nbru
NodeNum_t nbru
Definition: FlexAirfoil.h:66
RoR::FlexAirfoil::updateVerticesPhysics
void updateVerticesPhysics()
Definition: FlexAirfoil.cpp:413
RoR::FlexAirfoil::sref
float sref
Definition: FlexAirfoil.h:113
ApproxMath.h
RoR::FlexAirfoil::chordratio
float chordratio
Definition: FlexAirfoil.h:116
FlexAirfoil.h
RoR::FlexAirfoil::subface
Ogre::SubMesh * subface
Definition: FlexAirfoil.h:85
RoR::NodeSB::AbsPosition
Ogre::Vector3 AbsPosition
Definition: SimBuffers.h:69
RoR::FlexAirfoil::CoVertice_t::normal
Ogre::Vector3 normal
Definition: FlexAirfoil.h:79
RoR::FlexAirfoil::enableInducedDrag
void enableInducedDrag(float span, float area, bool l)
Definition: FlexAirfoil.cpp:575
RoR::FlexAirfoil::cupibufCount
size_t cupibufCount
Definition: FlexAirfoil.h:105
RoR::FlexAirfoil::subband
Ogre::SubMesh * subband
Definition: FlexAirfoil.h:86
RoR::FlexAirfoil::idSpan
float idSpan
Definition: FlexAirfoil.h:126
RoR::Actor::ar_nodes
node_t * ar_nodes
Definition: Actor.h:273
RoR::FlexAirfoil::vbufCount
size_t vbufCount
Definition: FlexAirfoil.h:95
RoR::FlexAirfoil::cdnibufCount
size_t cdnibufCount
Definition: FlexAirfoil.h:106
RoR::FlexAirfoil::hascontrol
bool hascontrol
Definition: FlexAirfoil.h:117
RoR::FlexAirfoil::free_wash
int free_wash
Definition: FlexAirfoil.h:132
RoR::FlexAirfoil::updateForces
void updateForces()
Definition: FlexAirfoil.cpp:590
RoR::FlexAirfoil::idLeft
bool idLeft
Definition: FlexAirfoil.h:128
AeroEngine.h
RoR::Airfoil
Represents an airfoil http://en.wikipedia.org/wiki/Airfoil.
Definition: Airfoil.h:31
RoR::GfxActor
Definition: GfxActor.h:52
RoR::FlexAirfoil::facefaces
unsigned short * facefaces
Definition: FlexAirfoil.h:107
Ogre
Definition: ExtinguishableFireAffector.cpp:35
GfxActor.h
Manager for all visuals belonging to a single actor.
RoR::FlexAirfoil::decl
Ogre::VertexDeclaration * decl
Definition: FlexAirfoil.h:91
RoR::FlexAirfoil::nodes
node_t * nodes
Definition: FlexAirfoil.h:111
RoR::FlexAirfoil::CoVertice_t::texcoord
Ogre::Vector2 texcoord
Definition: FlexAirfoil.h:81
RoR::FlexAirfoil::mindef
float mindef
Definition: FlexAirfoil.h:122
RoR::FlexAirfoil::useInducedDrag
bool useInducedDrag
Definition: FlexAirfoil.h:125
RoR::FlexAirfoil::nblu
NodeNum_t nblu
Definition: FlexAirfoil.h:65
RoR::FlexAirfoil::nfru
NodeNum_t nfru
Definition: FlexAirfoil.h:62
RoR::FlexAirfoil::nVertices
size_t nVertices
Definition: FlexAirfoil.h:94
RoR::GfxActor::GetResourceGroup
Ogre::String GetResourceGroup()
Definition: GfxActor.h:139
RoR::FlexAirfoil::nbrd
NodeNum_t nbrd
Definition: FlexAirfoil.h:64
RoR
Definition: AppContext.h:36
RoR::FlexAirfoil::msh
Ogre::MeshPtr msh
Definition: FlexAirfoil.h:84
RoR::FlexAirfoil::~FlexAirfoil
~FlexAirfoil()
Definition: FlexAirfoil.cpp:682
RoR::node_t::Forces
Ogre::Vector3 Forces
Definition: SimData.h:295