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
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
30using namespace RoR;
31
32float 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
75using namespace Ogre;
76
77FlexAirfoil::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{
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,
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,
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
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 }
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 }
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
575void FlexAirfoil::enableInducedDrag(float span, float area, bool l)
576{
577 idSpan=span;
578 idArea=area;
579 useInducedDrag=true;
580 idLeft=l;
581}
582
583void FlexAirfoil::addwash(int propid, float ratio)
584{
585 washpropnum[free_wash]=propid;
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)
686 {
687 msh->unload();
688 Ogre::MeshManager::getSingleton().remove(msh->getHandle()); // Necessary to truly erase manually created resource.
689 msh.reset(); // 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}
#define ROR_ASSERT(_EXPR)
Definition Application.h:40
float approx_pow(const float x, const float y)
Definition ApproxMath.h:91
float refairfoilpos[90]
Manager for all visuals belonging to a single actor.
Core data structures for simulation; Everything affected by by either physics, network or user intera...
node_t * ar_nodes
Definition Actor.h:330
GfxActor * GetGfxActor()
Definition Actor.h:309
AeroEnginePtr ar_aeroengines[MAX_AEROENGINES]
Definition Actor.h:388
Represents an airfoil http://en.wikipedia.org/wiki/Airfoil.
Definition Airfoil.h:32
void getparams(float a, float cratio, float cdef, float *ocl, float *ocd, float *ocm)
Definition Airfoil.cpp:105
unsigned short * cdnfaces
void updateVerticesPhysics()
int washpropnum[MAX_AEROENGINES]
Ogre::SubMesh * subface
Definition FlexAirfoil.h:85
Ogre::MeshPtr msh
Definition FlexAirfoil.h:84
Airfoil * airfoil
unsigned short * bandfaces
void enableInducedDrag(float span, float area, bool l)
CoVertice_t * covertices
Ogre::VertexDeclaration * decl
Definition FlexAirfoil.h:91
AeroEnginePtr * aeroengines
Ogre::SubMesh * subcup
Definition FlexAirfoil.h:88
unsigned short * facefaces
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)
Ogre::HardwareVertexBufferSharedPtr vbuf
Definition FlexAirfoil.h:92
void setControlDeflection(float val)
float washpropratio[MAX_AEROENGINES]
float airfoilpos[90]
Definition FlexAirfoil.h:74
Ogre::Vector3 updateVerticesGfx(RoR::GfxActor *gfx_actor)
Ogre::SubMesh * subband
Definition FlexAirfoil.h:86
Ogre::SubMesh * subcdn
Definition FlexAirfoil.h:89
void addwash(int propid, float ratio)
unsigned short * cupfaces
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
Ogre::Vector3 AbsPosition
absolute position in the world (shaky)
Definition SimData.h:267
Ogre::Vector3 Velocity
Definition SimData.h:268
Ogre::Vector3 Forces
Definition SimData.h:269
Ogre::Vector3 RelPosition
relative to the local physics origin (one origin per actor) (shaky)
Definition SimData.h:266