void TestObject::Update(float p_right, float p_forward) { p_forward *= -1; float moveSpeed = 0.5; float rotationSpeed = 1; float moveRotationSpeed = 1; //rotation around y-axis (changes direction the object moves) if (p_right != 0) { m_moveDirection = GetXYZ(vec4(m_moveDirection, 0)*rotate(p_right*rotationSpeed, vec3(0, 1, 0))); m_lookDirection = GetXYZ(vec4(m_lookDirection, 0)*rotate(p_right*rotationSpeed, vec3(0, 1, 0))); m_up = GetXYZ(vec4(m_up, 0)*rotate(p_right*rotationSpeed, vec3(0, 1, 0))); } //movement forward if (p_forward != 0) { m_position += m_moveDirection*moveSpeed*p_forward; //rotation when moving forwards (the roll) vec3 right = cross(m_lookDirection, m_up); m_lookDirection = GetXYZ(vec4(m_lookDirection, 0)*rotate(p_forward*moveRotationSpeed, right)); m_up = GetXYZ(vec4(m_up, 0)*rotate(p_forward*moveRotationSpeed, right)); } m_worldMatrix = inverse(lookAt(m_position, m_lookDirection + m_position, m_up))*scale(m_scale); }
/** * @function GoToXYZ */ bool JTFollower::GoToXYZ( Eigen::VectorXd &_q, Eigen::VectorXd _targetXYZ, std::vector<Eigen::VectorXd> &_workspacePath ) { Eigen::VectorXd dXYZ; Eigen::VectorXd dConfig; int iter; //-- Initialize dXYZ = ( _targetXYZ - GetXYZ(_q) ); // GetXYZ also updates the config to _q, so Jaclin use an updated value iter = 0; printf("New call to GoToXYZ \n"); while( dXYZ.norm() > mWorkspaceThresh && iter < mMaxIter ) { printf("XYZ Error: %f \n", dXYZ.norm() ); Eigen::MatrixXd Jt = GetPseudoInvJac(_q); dConfig = Jt*dXYZ; printf("dConfig : %.3f \n", dConfig.norm() ); if( dConfig.norm() > mConfigStep ) { double n = dConfig.norm(); dConfig = dConfig *(mConfigStep/n); printf("NEW dConfig : %.3f \n", dConfig.norm() ); } _q = _q + dConfig; _workspacePath.push_back( _q ); dXYZ = (_targetXYZ - GetXYZ(_q) ); iter++; } if( iter >= mMaxIter ) { return false; } else { return true; } }
TEST(cpdf_dest, GetXYZ) { bool hasX; bool hasY; bool hasZoom; float x; float y; float zoom; auto dest = pdfium::MakeUnique<CPDF_Dest>(); EXPECT_FALSE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom)); auto array = pdfium::MakeUnique<CPDF_Array>(); array->AddNew<CPDF_Number>(0); // Page Index. array->AddNew<CPDF_Name>("XYZ"); array->AddNew<CPDF_Number>(4); // X // Not enough entries. dest = pdfium::MakeUnique<CPDF_Dest>(array.get()); EXPECT_FALSE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom)); array->AddNew<CPDF_Number>(5); // Y array->AddNew<CPDF_Number>(6); // Zoom. dest = pdfium::MakeUnique<CPDF_Dest>(array.get()); EXPECT_TRUE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom)); EXPECT_TRUE(hasX); EXPECT_TRUE(hasY); EXPECT_TRUE(hasZoom); EXPECT_EQ(4, x); EXPECT_EQ(5, y); EXPECT_EQ(6, zoom); // Set zoom to 0. array->SetNewAt<CPDF_Number>(4, 0); dest = pdfium::MakeUnique<CPDF_Dest>(array.get()); EXPECT_TRUE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom)); EXPECT_FALSE(hasZoom); // Set values to null. array->SetNewAt<CPDF_Null>(2); array->SetNewAt<CPDF_Null>(3); array->SetNewAt<CPDF_Null>(4); dest = pdfium::MakeUnique<CPDF_Dest>(array.get()); EXPECT_TRUE(dest->GetXYZ(&hasX, &hasY, &hasZoom, &x, &y, &zoom)); EXPECT_FALSE(hasX); EXPECT_FALSE(hasY); EXPECT_FALSE(hasZoom); }
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFDest_GetLocationInPage(FPDF_DEST pDict, FPDF_BOOL* hasXVal, FPDF_BOOL* hasYVal, FPDF_BOOL* hasZoomVal, FS_FLOAT* x, FS_FLOAT* y, FS_FLOAT* zoom) { if (!pDict) return false; auto dest = pdfium::MakeUnique<CPDF_Dest>(CPDFArrayFromFPDFDest(pDict)); // FPDF_BOOL is an int, GetXYZ expects bools. bool bHasX; bool bHasY; bool bHasZoom; if (!dest->GetXYZ(&bHasX, &bHasY, &bHasZoom, x, y, zoom)) return false; *hasXVal = bHasX; *hasYVal = bHasY; *hasZoomVal = bHasZoom; return true; }
void QVX_Object::ExportXYZ(void) { QString OutFilePath = QFileDialog::getSaveFileName(NULL, "Export XYZ Coordinates", GetLastDir(), "TXT Files (*.txt)"); QFile File(OutFilePath); if (!File.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::warning(NULL, "File read error", "Could not open file. Aborting."); return; } QTextStream out(&File); out << "MatIndex" << "\t" << "X (m)" << "\t" << "Y (m)" << "\t" << "Z (m)" << "\n"; Vec3D<> Coord; int Mat; for (int i=0; i<GetStArraySize(); i++){ Mat = GetMat(i); if (Mat != 0){ Coord = GetXYZ(i); out << Mat << "\t" << Coord.x << "\t" << Coord.y << "\t" << Coord.z << "\n"; } } File.close(); SetLastDir(OutFilePath); }
vec3 Quaternion::GetAxis() const { float x = 1.0f - w * w; if (x < 0.0000001f) // Divide by zero safety check return vec3::XAxis(); float x2 = x * x; return GetXYZ() / x2; }
void CQDM_Edit::DrawSectionPlane(bool FastMode)//draw a slice plane to reference where we're cutting { Vec3D<> WS = GetWorkSpace(); Vec3D<> v1, v2, v12, v21, ArrDir; CColor CutColor = CColor(0.3, 0.3, 0.5, 1.0); double PadOut = WS.Length()/10.0; double Plane; switch (CurSecAxis){ case ZAXIS: // DrawSecZ(CurSecLayer, LAYERMAX, CurSecFromNeg, GetCurSel()); Plane = GetXYZ(0, 0, CurSecLayer).z; v1 = Vec3D<>(-PadOut, -PadOut, Plane); v2 = Vec3D<>(WS.x+PadOut, WS.y+PadOut, Plane); v12 = Vec3D<>(v1.x, v2.y, v1.z); v21 = Vec3D<>(v2.x, v1.y, v1.z); ArrDir = Vec3D<>(0,0, CurSecFromNeg?-PadOut:PadOut); break; case YAXIS: // DrawSecY(CurSecLayer, LAYERMAX, CurSecFromNeg, GetCurSel()); Plane = GetXYZ(0, CurSecLayer, 0).y; v1 = Vec3D<>(-PadOut, Plane, -PadOut); v2 = Vec3D<>(WS.x+PadOut, Plane, WS.z+PadOut); v12 = Vec3D<>(v1.x, v1.y, v2.z); v21 = Vec3D<>(v2.x, v1.y, v1.z); ArrDir = Vec3D<>(0,CurSecFromNeg?-PadOut:PadOut, 0); break; case XAXIS: // DrawSecX(CurSecLayer, LAYERMAX, CurSecFromNeg, GetCurSel()); Plane = GetXYZ(CurSecLayer, 0, 0).x; v1 = Vec3D<>(Plane, -PadOut, -PadOut); v2 = Vec3D<>(Plane, WS.y+PadOut, WS.z+PadOut); v12 = Vec3D<>(v1.x, v1.y, v2.z); v21 = Vec3D<>(v1.x, v2.y, v1.z); ArrDir = Vec3D<>(CurSecFromNeg?-PadOut:PadOut,0,0); break; } CGL_Utils::DrawRectangle(v1, v2, !FastMode, 0, CColor(CutColor.r, CutColor.g, CutColor.b, 0.3)); CGL_Utils::DrawArrow(v1, ArrDir, CutColor); CGL_Utils::DrawArrow(v2, ArrDir, CutColor); CGL_Utils::DrawArrow(v12, ArrDir, CutColor); CGL_Utils::DrawArrow(v21, ArrDir, CutColor); }
bool CMOOSNavTopDownCalEngine::MakeVantagePoints() { OBSLIST * pAcoustic = m_pStore->GetListByType(CMOOSObservation::LBL_BEACON_2WR); if(pAcoustic==NULL) return false; if(pAcoustic->size()<10) return true; OBSLIST::iterator p; //build a list using only the observations on our selected //channel... double dfX,dfXOld=0; double dfY,dfYOld=0; double dfZ; for(p = pAcoustic->begin(); p!=pAcoustic->end(); p++) { CMOOSObservation & rObs = *p; if(rObs.m_nChan==m_nSelectedChan) { if(GetXYZ(dfX,dfY,dfZ,rObs.m_dfTime,0.5)) { double dfS = sqrt(pow(dfX-dfXOld,2)+pow(dfY-dfYOld,2)); if(dfS>m_dfSpacing || p == pAcoustic->begin() ) { CVantagePoint VP; VP.m_dfX = dfX; VP.m_dfY = dfY; VP.m_dfZ = 0; VP.m_dfTOF = rObs.m_dfData; VP.m_dfTOFStd = rObs.m_dfDataStd; VP.m_dfTime = rObs.m_dfTime; VP.m_pInterrogateSensor = rObs.m_pInterrogateSensor; m_VantagePoints.push_back(VP); dfXOld = dfX; dfYOld = dfY; } } } } return !m_VantagePoints.empty(); }
void CQDM_Edit::Draw2DOverlay() { glPushMatrix(); Vec3D<> Center; Vec3D<> Normal; int x, y, z; double OverlayAdvance = Lattice.GetLatticeDim()/1.95 ; //amount to draw the outlines above the actual voxel center point // if (Voxel.GetVoxName() == VS_SPHERE) OverlayAdvance /= 2.0; //don't want to offset too much for sphere to deal with layers in multiple planes switch (CurSecAxis){ case XAXIS: Normal = Vec3D<>(1.0, 0.0, 0.0); if (CurSecFromNeg) glTranslated(-OverlayAdvance, 0, 0); else glTranslated(OverlayAdvance, 0, 0); break; case YAXIS: Normal = Vec3D<>(0.0, 1.0, 0.0); if (CurSecFromNeg) glTranslated(0, -OverlayAdvance, 0); else glTranslated(0, OverlayAdvance, 0); break; default: //case ZAXIS: Normal = Vec3D<>(0.0, 0.0, 1.0); if (CurSecFromNeg) glTranslated(0, 0, -OverlayAdvance); else glTranslated(0, 0, OverlayAdvance); break; } for (int i = 0; i<Structure.GetArraySize(); i++) //go through all the voxels... { GetXYZNom(&x, &y, &z, i); switch (CurSecAxis){ case ZAXIS: if (z != CurSecLayer) continue; break; case YAXIS: if (y != CurSecLayer) continue; break; case XAXIS: if (x != CurSecLayer) continue; break; } GetXYZ(&Center, i); bool DrawHighlighted = false; for (int j=0; j<(int)CurHighlighted.size(); j++){ if (i==CurHighlighted[j]){ glColor4f(1.0f, 0.0f, 0.0f, 0.1f); DrawHighlighted = true; continue; } } Voxel.DrawVoxel2D(&Center, Lattice.GetLatticeDim(), &Normal, DrawHighlighted); //draw this voxel if we got this far! } glPopMatrix(); }
int CQDM_Edit::V2DFindVoxelUnder(Vec3D<> Coord) //returns the index of a voxel under the coordinates { //Could be rewritten better!! Vec3D<> Bounds = GetWorkSpace(); switch(CurSecAxis){ //put the "undefined" coordinate from 2d projection to something reasonable... case ZAXIS: Coord.z = GetXYZ(0,0,CurSecLayer).z; break; case YAXIS: Coord.y = GetXYZ(0,CurSecLayer,0).y; break; case XAXIS: Coord.x = GetXYZ(CurSecLayer,0,0).x; break; } if (Coord.x<0.0 || Coord.x > Bounds.x || Coord.y<0.0 || Coord.y > Bounds.y || Coord.z<0.0 || Coord.z > Bounds.z) return -1; //do easy check to see if we're even within the area int tX, tY, tZ, tInd; Vec3D<> tVec; Vec3D<> BB = Vec3D<>(Lattice.GetXDimAdj(), Lattice.GetYDimAdj(), Lattice.GetZDimAdj())*GetLatticeDim()/2; tX = Coord.x/Bounds.x*GetVXDim(); //approximate... tY = Coord.y/Bounds.y*GetVYDim(); tZ = Coord.z/Bounds.z*GetVZDim(); //estimates for (int i=-1; i<=1; i++){ //for +/- 1 in each direction.. for (int j=-1; j<=1; j++){ switch(CurSecAxis){ case ZAXIS: tInd = GetIndex(tX+i, tY+j, CurSecLayer); break; case YAXIS: tInd = GetIndex(tX+i, CurSecLayer, tZ+j); break; case XAXIS: tInd = GetIndex(CurSecLayer, tY+i, tZ+j); break; } tVec = GetXYZ(tInd); if ((CurSecAxis == XAXIS || (Coord.x > tVec.x-BB.x && Coord.x < tVec.x+BB.x)) && (CurSecAxis == YAXIS || (Coord.y > tVec.y-BB.y && Coord.y < tVec.y+BB.y)) && (CurSecAxis == ZAXIS || (Coord.z > tVec.z-BB.z && Coord.z < tVec.z+BB.z))) return tInd; } } return -1; }
void CEasyGenView::OnRButtonDown(UINT nFlags, CPoint point) { CEasyGenDoc *pDoc = GetDocument(); CNmVec3 ray; CNmVec3 p; int tab; BOOL kCTRL = nFlags & MK_CONTROL; BOOL kSHIFT = nFlags & MK_SHIFT; BOOL GotPoint = GetXYZ(point, p); BOOL GotRay = GetRay(point, ray); m_RDP = point; SetCapture(); switch (tab = pDoc->GetActiveTab()) { case (TAB_GRID): break; case (TAB_MODIFIER): break; case (TAB_ALPHAMAP): break; case (TAB_MODELS): // MD3 - Move an Md3Highlighted model if (!kCTRL && kSHIFT && GotRay && m_Md3Highlight) { CNmVec3 pos; float dist; if (g_Grid.GetDistanceTrisRay(m_Eye, ray, pos, dist)) { m_Md3Highlight->m_egvPos = pos; InvalidateRect(NULL, FALSE); } } break; } CView::OnRButtonDown(nFlags, point); }
void CItem::EncodeInsertPacket(LPENTITY ent) { LPDESC d; if (!(d = ent->GetDesc())) return; const PIXEL_POSITION & c_pos = GetXYZ(); struct packet_item_ground_add pack; pack.bHeader = HEADER_GC_ITEM_GROUND_ADD; pack.x = c_pos.x; pack.y = c_pos.y; pack.z = c_pos.z; pack.dwVnum = GetVnum(); pack.dwVID = m_dwVID; //pack.count = m_dwCount; d->Packet(&pack, sizeof(pack)); if (m_pkOwnershipEvent != NULL) { item_event_info * info = dynamic_cast<item_event_info *>(m_pkOwnershipEvent->info); if ( info == NULL ) { sys_err( "CItem::EncodeInsertPacket> <Factor> Null pointer" ); return; } TPacketGCItemOwnership p; p.bHeader = HEADER_GC_ITEM_OWNERSHIP; p.dwVID = m_dwVID; strlcpy(p.szName, info->szOwnerName, sizeof(p.szName)); d->Packet(&p, sizeof(TPacketGCItemOwnership)); } }
void CEasyGenView::OnRButtonDblClk(UINT nFlags, CPoint point) { CEasyGenDoc *pDoc = GetDocument(); S_POSINFO inf; CNmVec3 p; BOOL kCTRL = nFlags & MK_CONTROL; BOOL kSHIFT = nFlags & MK_SHIFT; BOOL GotPoint = GetXYZ(point, p); switch (pDoc->GetActiveTab()) { case (TAB_GRID): break; case (TAB_MODIFIER): // Modifier get height if (kCTRL && GotPoint) { if (g_Grid.GetInfo(p.x, p.y, &inf)) { g_Mod.HeightSet(inf.z); InvalidateRect(NULL, FALSE); pDoc->m_bInvalidateGridPreview = TRUE; } } break; case (TAB_ALPHAMAP): break; case (TAB_MODELS): break; } CView::OnRButtonDblClk(nFlags, point); }
void CQDM_Edit::FillHighlighted(bool CtrlDown) //fill the CurHighlighted array based on current drawing tool and coordinates { switch (CurDrawTool){ case DT_PEN:{ int ToAdd = V2DFindVoxelUnder(CurCoord); if (!IsInHighlighted(ToAdd) && ToAdd != -1) CurHighlighted.push_back(ToAdd); break; } case DT_BOX: { //could be shortened a little... Vec3D<> Loc; int x, y, z; Vec3D<> BB = Vec3D<>(Lattice.GetXDimAdj(), Lattice.GetYDimAdj(), Lattice.GetZDimAdj())*GetLatticeDim()/2; Vec3D<> V1 = CurCoord.Min(DownCoord); Vec3D<> V2 = CurCoord.Max(DownCoord); CurHighlighted.clear(); for (int i=0; i<Structure.GetArraySize(); i++){ //go through all voxels... GetXYZNom(&x, &y, &z, i); Loc = GetXYZ(i); //float LatDim = GetLatticeDim(); switch(CurSecAxis){ case ZAXIS: if (CurSecLayer != z) continue; //don't care if its not in this layer... if (Loc.x>V1.x-BB.x && Loc.x<V2.x+BB.x && Loc.y>V1.y-BB.y && Loc.y<V2.y+BB.y) CurHighlighted.push_back(i); break; case YAXIS: if (CurSecLayer != y) continue; //don't care if its not in this layer... if (Loc.x>V1.x-BB.x && Loc.x<V2.x+BB.x && Loc.z>V1.z-BB.z && Loc.z<V2.z+BB.z) CurHighlighted.push_back(i); break; case XAXIS: if (CurSecLayer != x) continue; //don't care if its not in this layer... if (Loc.y>V1.y-BB.y && Loc.y<V2.y+BB.y && Loc.z>V1.z-BB.z && Loc.z<V2.z+BB.z) CurHighlighted.push_back(i); break; } } break; } case DT_ELLIPSE: { Vec3D<> Offset, Off2, Size2; int x, y, z; Vec3D<> V1 = CurCoord.Min(DownCoord); Vec3D<> V2 = CurCoord.Max(DownCoord); int VoxN = V2DFindVoxelUnder(V1); //rounds to outside corners of voxels we've selected int VoxP = V2DFindVoxelUnder(V2); Vec3D<> LocN = GetXYZ(VoxN)-GetLatDimEnv()/2.0; Vec3D<> LocP = GetXYZ(VoxP)+GetLatDimEnv()/2.0; Vec3D<> Cen = (LocN+LocP)/2.0; Vec3D<> Size = (LocP-LocN)/2.0; CurHighlighted.clear(); for (int i=0; i<Structure.GetArraySize(); i++){ //go through all voxels... GetXYZNom(&x, &y, &z, i); Offset = GetXYZ(i)-Cen; Off2 = Offset.Scale(Offset); Size2 = Size.Scale(Size); double LatDim = GetLatticeDim(); switch(CurSecAxis){ case ZAXIS: if (CurSecLayer != z) continue; //don't care if its not in this layer... if (Off2.x/Size2.x + Off2.y/Size2.y<1.0001) CurHighlighted.push_back(i); break; case YAXIS: if (CurSecLayer != y) continue; //don't care if its not in this layer... if (Off2.x/Size2.x + Off2.z/Size2.z<1.0001) CurHighlighted.push_back(i); break; case XAXIS: if (CurSecLayer != x) continue; //don't care if its not in this layer... if (Off2.y/Size2.y + Off2.z/Size2.z<1.0001) CurHighlighted.push_back(i); break; } } break; } case DT_BUCKET: { int CVox = V2DFindVoxelUnder(CurCoord); int ThisMat = GetMat(CVox); CurHighlighted.clear(); CurHighlighted.push_back(CVox); //put the first index on the buffer... // if (ViewSection) int Iter = 0; int Xi, Yi, Zi, curInd, tmpInd; while (Iter != (int)CurHighlighted.size()){ curInd = CurHighlighted[Iter]; GetXYZNom(&Xi, &Yi, &Zi, curInd); //this location... for (int i=-1; i<=1; i++){for (int j=-1; j<=1; j++){for (int k=-1; k<=1; k++){ if (i!=0 && !CtrlDown && (ViewSection && CurSecAxis == XAXIS)) continue; //if we are out of plane of current viewing section if (j!=0 && !CtrlDown&& (ViewSection && CurSecAxis == YAXIS)) continue; if (k!=0 && !CtrlDown && (ViewSection && CurSecAxis == ZAXIS)) continue; tmpInd = GetIndex(Xi+i, Yi+j, Zi+k); if (IsAdjacent(curInd, tmpInd, true) && GetMat(tmpInd) == ThisMat && !IsInHighlighted(tmpInd)) CurHighlighted.push_back(tmpInd); }}} Iter++; } } } }
void HeliBrain::CollisionCheck(void) { float relAz, relEl, range, reactTime; float hRange = 200.0F; /* range to miss a hostile tgt / fireball */ float hRangeSq = 40000.0F; /* square of hRange */ //float reactFact = 0.75F; /* fudge factor for reaction time */ float timeToImpact,rngSq,dt,pastRngSq; float ox,oy,oz,tx,ty,tz; int collision; SimObjectType* obj; Falcon4EntityClassType* classPtr; SimObjectLocalData* localData; /*----------------------------------------------------------*/ /* Reaction time is a function of gs available and */ /* agression level (gs allowed). 2 seconds is the bare */ /* minimum for most situations. Modify with reaction factor */ /*----------------------------------------------------------*/ // reactTime = ((GS_LIMIT / af->gsAvail) // + (GS_LIMIT / maxGs)) * reactFact; // just hard coded in.... reactTime = 2.0; collision = FALSE; /*---------------*/ /* check objects */ /*---------------*/ obj = self->targetList; while (obj) { localData = obj->localData; /*-----------------------*/ /* aircraft objects only */ /*-----------------------*/ classPtr = (Falcon4EntityClassType*)obj->BaseData()->EntityType(); if (classPtr->vuClassData.classInfo_[VU_TYPE] == TYPE_AIRPLANE || classPtr->vuClassData.classInfo_[VU_TYPE] == TYPE_HELICOPTER ) { /*----------------*/ /* time to impact */ /*----------------*/ timeToImpact = (localData->range - hRange) / localData->rangedot; /*---------------*/ /* not a problem */ /*---------------*/ if (timeToImpact < 0.0 || timeToImpact > reactTime) { obj = obj->next; continue; } /*-------------------------------------------------------------*/ /* check for close approach. Linearly extrapolate out velocity */ /* vector for react time. */ /*-------------------------------------------------------------*/ pastRngSq = 10.0e7F; dt = 0.05F; while (dt < reactTime) { ox = self->XPos() + self->XDelta()*dt; oy = self->YPos() + self->YDelta()*dt; oz = self->ZPos() + self->ZDelta()*dt; tx = obj->BaseData()->XPos() + obj->BaseData()->XDelta()*dt; ty = obj->BaseData()->YPos() + obj->BaseData()->YDelta()*dt; tz = obj->BaseData()->ZPos() + obj->BaseData()->ZDelta()*dt; rngSq = (ox-tx)*(ox-tx) + (oy-ty)*(oy-ty) + (oz-tz)*(oz-tz); /*------------------------------------------------*/ /* collision possible if within hRange of target */ /*------------------------------------------------*/ if (rngSq <= hRangeSq) { collision = TRUE; break; } /*----------------------------------------------*/ /* break out of loop if range begins to diverge */ /*----------------------------------------------*/ if (rngSq > pastRngSq) break; pastRngSq = rngSq; dt += 0.1F; } /*------------------------------*/ /* take action or bite the dust */ /*------------------------------*/ if (collision) { /*------------------------------------*/ /* Find a point in the maneuver plane */ /*------------------------------------*/ // relEl = 45.0F * DTR; relEl = 0.0; if (localData->droll > 0.0) relAz = -90.0F * DTR; else relAz = 90.0F * DTR; range = 4000.0F; GetXYZ (self, relAz, relEl, range, &trackX, &trackY, &trackZ); AddMode(CollisionAvoidMode); break; } } obj = obj->next; } /*---------------------------------------------*/ /* exit mode when collision no longer probable */ /*---------------------------------------------*/ if (curMode == CollisionAvoidMode && !collision) { } }
void CQDM_Edit::DrawMe(bool FastMode, bool ShowSelected, int NumBehindSection) //draws the digital part in initialized OpenGL window //Show Selected highlights current sleceted voxel, Section view uses the currently selected axis and direction to show section, FadeBehindSelection optionally fades out the layers (for 2D view) { int Selected = GetCurSel(); if (!ShowSelected) Selected = -1; //don't draw the selected one... if (FastMode && NumBehindSection != LAYERMAX) NumBehindSection = 0; //in fast mode don't draw faded out ones... CVXC_Material* pMaterial; bool IsVis; int aS = Structure.GetArraySize(); int x, y, z, MatIndex; int XMin=0, YMin=0, ZMin=0, XMax=LAYERMAX, YMax=LAYERMAX, ZMax=LAYERMAX; if (ViewSection){ if (CurSecAxis == XAXIS){ if (CurSecFromNeg){ XMin = CurSecLayer; XMax = CurSecLayer+NumBehindSection;} else {XMin = CurSecLayer-NumBehindSection; XMax = CurSecLayer;} } else if (CurSecAxis == YAXIS){ if (CurSecFromNeg){ YMin = CurSecLayer; YMax = CurSecLayer+NumBehindSection;} else {YMin = CurSecLayer-NumBehindSection; YMax = CurSecLayer;} } else if (CurSecAxis == ZAXIS){ if (CurSecFromNeg){ ZMin = CurSecLayer; ZMax = CurSecLayer+NumBehindSection;} else {ZMin = CurSecLayer-NumBehindSection; ZMax = CurSecLayer;} } } Vec3D<> Center; Vec3D<> Squeeze(Voxel.GetXSqueeze(), Voxel.GetYSqueeze(), Voxel.GetZSqueeze()); double Dim = GetLatticeDim(); Vec3D<> VoxEnv = GetLatDimEnv(); Vec3D<> WS(GetVXDim()*VoxEnv.x, GetVYDim()*VoxEnv.y, GetVZDim()*VoxEnv.z); int NumCellAround = 0; if (ViewTiled) NumCellAround = 1; for (int ix=-NumCellAround; ix<=NumCellAround; ix++){ //for showing repeated unit cells for (int jy=-NumCellAround; jy<=NumCellAround; jy++){ for (int kz=-NumCellAround; kz<=NumCellAround; kz++){ if(ViewSection){ //don't draw ones that aren't in current plane section if (CurSecAxis == XAXIS && ix != 0) continue; else if (CurSecAxis == YAXIS && jy != 0) continue; else if (CurSecAxis == ZAXIS && kz != 0) continue; } glPushMatrix(); glTranslated(ix*WS.x, jy*WS.y, kz*WS.z); for (int i = 0; i<aS; i++){ //go through all the voxels... GetXYZNom(&x, &y, &z, i); if (ViewSection && (x<XMin || x>XMax || y<YMin || y>YMax || z<ZMin || z>ZMax)) continue; //jump ship here if we're outside of the section view: MatIndex = Structure[i]; if (MatIndex <= 0) continue; //don't draw if nothing there if (FastMode){ //disable picking, show selected, and resolving composite materials glColor3f(Palette[MatIndex].GetRedf(), Palette[MatIndex].GetGreenf(), Palette[MatIndex].GetBluef()); } else { //NOT fastmode: enable picking, show selected, and resolve composite materials glLoadName(i); //to enable picking bool IsVis; pMaterial = GetLeafMat(i, &IsVis); if (pMaterial == NULL || !IsVis) continue; if (pMaterial->GetAlphai() == 0) continue; double FadeOut = 0.0; if (ViewSection && NumBehindSection != LAYERMAX){ //if there's fading out to be done... if (CurSecAxis == XAXIS) FadeOut = abs((double)(x - CurSecLayer))/(NumBehindSection+1); else if (CurSecAxis == YAXIS) FadeOut = abs((double)(y - CurSecLayer))/(NumBehindSection+1); else if (CurSecAxis == ZAXIS) FadeOut = abs((double)(z - CurSecLayer))/(NumBehindSection+1); } SetCurGLColor(pMaterial, i==Selected, FadeOut); } GetXYZ(&Center, i); glPushMatrix(); glTranslated(Center.x, Center.y, Center.z); glScaled(Dim*Squeeze.x, Dim*Squeeze.y, Dim*Squeeze.z); switch (Voxel.GetVoxName()){ case VS_SPHERE: CGL_Utils::DrawSphereFace(); break; case VS_BOX: CGL_Utils::DrawCubeFace(); break; case VS_CYLINDER: CGL_Utils::DrawCylFace(); break; default: break; } glPopMatrix(); } if (!FastMode && Voxel.GetVoxName() != VS_SPHERE){ //no lines in fast mode or for spheres! glDisable(GL_LIGHTING); glLineWidth(1.0); for (int i = 0; i<aS; i++){ //go through all the voxels... GetXYZNom(&x, &y, &z, i); if (ViewSection && (x<XMin || x>XMax || y<YMin || y>YMax || z<ZMin || z>ZMax)) continue; //jump ship here if we're outside of the section view: if (Structure[i] <= 0) continue; //don't draw if nothing there glColor3f(0, 0, 0); GetXYZ(&Center, i); glPushMatrix(); glTranslated(Center.x, Center.y, Center.z); glScaled(Dim*Squeeze.x, Dim*Squeeze.y, Dim*Squeeze.z); switch (Voxel.GetVoxName()){ case VS_BOX: CGL_Utils::DrawCubeEdge(); break; case VS_CYLINDER: CGL_Utils::DrawCylEdge(); break; default: break; } glPopMatrix(); } glEnable(GL_LIGHTING); } glPopMatrix(); } } } //if (!ViewSection){//if not in section mode, draw it all! // //if(FastMode) // DrawFast(Selctd, FastMode); // //else Draw(Selctd); //} //else { //otherwise draw the appropriate section view // switch (CurSecAxis){ // case ZAXIS: DrawSecZ(CurSecLayer, NumBehindSection, CurSecFromNeg, Selctd); break; // case YAXIS: DrawSecY(CurSecLayer, NumBehindSection, CurSecFromNeg, Selctd); break; // case XAXIS: DrawSecX(CurSecLayer, NumBehindSection, CurSecFromNeg, Selctd); break; // } //} }
void CEasyGenView::OnLButtonDblClk(UINT nFlags, CPoint point) { CEasyGenDoc *pDoc = GetDocument(); CNmVec3 ray; CNmVec3 p; BOOL kCTRL = nFlags & MK_CONTROL; BOOL kSHIFT = nFlags & MK_SHIFT; BOOL GotPoint = GetXYZ(point, p); BOOL GotRay = GetRay(point, ray); switch (pDoc->GetActiveTab()) { case (TAB_GRID): // player place if (!kCTRL && kSHIFT && GotPoint && g_Grid.PtInGrid(p.x, p.y)) { pDoc->m_vPlayer.x = p.x; pDoc->m_vPlayer.y = p.y; S_POSINFO inf; if (g_Grid.GetInfo(pDoc->m_vPlayer.x, pDoc->m_vPlayer.y, &inf)) { pDoc->m_vPlayer.z = inf.z; } m_vGenericPos.Set(p.x, p.y, pDoc->m_vPlayer.z); UpdateStatusBar(); InvalidateRect(NULL, FALSE); } break; case (TAB_MODIFIER): // modifier place if (kCTRL && !kSHIFT && GotPoint && g_Grid.PtInGrid(p.x, p.y)) { pDoc->m_modX = p.x; pDoc->m_modY = p.y; g_Mod.PositionSet(p.x, p.y); UpdateStatusBar(); InvalidateRect(NULL, FALSE); pDoc->m_bInvalidateGridPreview = TRUE; } break; case (TAB_ALPHAMAP): break; case (TAB_MODELS): // MD3 - Insert model if (kCTRL && !kSHIFT && GotRay) { CNmVec3 pos; float dist; S_MD3PTR *md3ptr; if (g_Grid.GetDistanceTrisRay(m_Eye, ray, pos, dist)) { md3ptr = g_Md3Man.m_Placed.Append(); // g_Md3Man.m_Placed.Append( pDoc->GetMd3SelectedTabModels() ); if (md3ptr) { md3ptr->pMd3 = pDoc->GetMd3SelectedTabModels(); md3ptr->m_egvPos = pos; InvalidateRect(NULL, FALSE); } } } break; } // CAMERA - camera place [EVERY TAB] if (!kSHIFT && !kCTRL && GotPoint && g_Grid.PtInGrid(p.x, p.y)) { m_Eye.x = p.x; m_Eye.y = p.y; InvalidateRect(NULL, FALSE); } CView::OnLButtonDblClk(nFlags, point); }
void CEasyGenView::OnMouseMove(UINT nFlags, CPoint point) { CView::OnMouseMove(nFlags, point); CEasyGenDoc *pDoc = GetDocument(); BOOL Refresh = FALSE; BOOL UpdStatus = FALSE; CNmVec3 p; S_POSINFO inf; int tab; int mod = pDoc->GetModifier(); BOOL kCTRL = nFlags & MK_CONTROL; BOOL kSHIFT = nFlags & MK_SHIFT; BOOL m_LBD = nFlags & MK_LBUTTON; BOOL m_RBD = nFlags & MK_RBUTTON; CPoint Ldelta = point - m_LDP; CPoint Rdelta = point - m_RDP; if (!m_LBD) { m_VertexGot = -1; } switch (tab = pDoc->GetActiveTab()) { case (TAB_GRID): break; case (TAB_MODIFIER): // move Modifier CTRL + Left if (m_LBD && kCTRL && !kSHIFT) { float f = (float)u_deg2rad(-m_yRot + 90); float dx = -(float)(Ldelta.x) * pDoc->m_modXYstep; float dy = (float)(Ldelta.y) * pDoc->m_modXYstep; pDoc->m_modY += float(sin(f) * dx + cos(f) * dy); pDoc->m_modX += float(cos(f) * dx - sin(f) * dy); g_Mod.MoveDelta(float(cos(f) * dx - sin(f) * dy), float(sin(f) * dx + cos(f) * dy)); UpdStatus = TRUE; pDoc->m_bInvalidateGridPreview = TRUE; Refresh = TRUE; } // inc Strength CTRL + Right if (m_RBD && kCTRL && !kSHIFT && (mod != MOD_NONE)) { pDoc->m_modStrength -= (float)(Rdelta.y) * 4.f; g_Mod.HeightDelta(-(float)(Rdelta.y) * 4.f); UpdStatus = TRUE; pDoc->m_bInvalidateGridPreview = TRUE; Refresh = TRUE; } // inc Radius SHIFT + Right if (m_RBD && !kCTRL && kSHIFT && (mod != MOD_NONE)) { pDoc->m_modRadius -= (float)(Rdelta.y) * 4.f; g_Mod.RadiusDelta(-(float)(Rdelta.y) * 4.f); if (pDoc->m_modRadius < 0) { pDoc->m_modRadius = 0; } UpdStatus = TRUE; pDoc->m_bInvalidateGridPreview = TRUE; Refresh = TRUE; } // Vertex dragging if (m_LBD && kCTRL && kSHIFT && (m_VertexGot != -1) && (mod == MOD_NONE)) { float *z = g_Grid.GetPtr(m_VertexGot); *z = floor(*z - g_Prefs.m_fVertexDragStep * (float)Ldelta.y); if (*z < ASSUME_ZERO) { *z = 0; } m_vGenericPos.Set(g_Grid.GetX(m_VertexGot), g_Grid.GetY(m_VertexGot), *z); UpdStatus = TRUE; pDoc->m_bInvalidateGridPreview = TRUE; Refresh = TRUE; } break; case (TAB_ALPHAMAP): int curindex; curindex = g_AlphamapMan.GetCurSel(); // Alphamap paint if (m_LBD && kCTRL && kSHIFT && curindex != -1) { if (GetXYZ(point, p)) { if (g_Grid.GetInfo(p.x, p.y, &inf)) { m_VertexGot = g_Grid.GetK(inf.i, inf.j); // g_Grid.SetAlphaIndex(m_VertexGot, curindex ); g_Grid.PaintAlphaIndex(inf.i, inf.j, pDoc->m_dwPaintRadius, curindex); Refresh = TRUE; } } } break; case (TAB_MODELS): break; } // rotate X/Y if (m_LBD && !m_RBD && !kCTRL && !kSHIFT) { m_yRot += (float)(Ldelta.x) / 2.0f; // left / right m_xRot += (float)(Ldelta.y) / 2.0f; // up / dn if (m_xRot > 85) { m_xRot = 85; } if (m_xRot < -85) { m_xRot = -85; } Refresh = TRUE; } // pan if (m_RBD && !m_LBD && !kCTRL && !kSHIFT) { float f = (float)u_deg2rad(-m_yRot + 90); float dx = -(float)(Ldelta.x) * 16; float dy = (float)(Ldelta.y) * 16; m_Eye.y += float(sin(f) * dx + cos(f) * dy); m_Eye.x += float(cos(f) * dx - sin(f) * dy); Refresh = TRUE; } // up/dn if (m_RBD && m_LBD && !kCTRL && !kSHIFT) { m_Eye.z -= (float)(Rdelta.y) * 32; Refresh = TRUE; } if (Refresh) { InvalidateRect(NULL, FALSE); } if (UpdStatus) { UpdateStatusBar(); } m_LDP = point; m_RDP = point; }
void FGBallonet::Calculate(double dt) { const double ParentPressure = Parent->GetPressure(); // [lbs/ft^2] const double AirPressure = in.Pressure; // [lbs/ft^2] const double OldTemperature = Temperature; const double OldPressure = Pressure; unsigned int i; //-- Gas temperature -- // The model is based on the ideal gas law. // However, it does look a bit fishy. Please verify. // dT/dt = dU / (Cv n R) dU = 0.0; for (i = 0; i < HeatTransferCoeff.size(); i++) { dU += HeatTransferCoeff[i]->GetValue(); } // dt is already accounted for in dVolumeIdeal. if (Contents > 0) { Temperature += (dU * dt - Pressure * dVolumeIdeal) / (Cv_air * Contents * R); } else { Temperature = Parent->GetTemperature(); } //-- Pressure -- const double IdealPressure = Contents * R * Temperature / MaxVolume; // The pressure is at least that of the parent gas cell. Pressure = max(IdealPressure, ParentPressure); //-- Blower input -- if (BlowerInput) { const double AddedVolume = BlowerInput->GetValue() * dt; if (AddedVolume > 0.0) { Contents += Pressure * AddedVolume / (R * Temperature); } } //-- Pressure relief and manual valving -- // FIXME: Presently the effect of valving is computed using // an ad hoc formula which might not be a good representation // of reality. if ((ValveCoefficient > 0.0) && ((ValveOpen > 0.0) || (Pressure > AirPressure + MaxOverpressure))) { const double DeltaPressure = Pressure - AirPressure; const double VolumeValved = ((Pressure > AirPressure + MaxOverpressure) ? 1.0 : ValveOpen) * ValveCoefficient * DeltaPressure * dt; // FIXME: Too small values of Contents sometimes leads to NaN. // Currently the minimum is restricted to a safe value. Contents = max(1.0, Contents - Pressure * VolumeValved / (R * Temperature)); } //-- Volume -- Volume = Contents * R * Temperature / Pressure; dVolumeIdeal = Contents * R * (Temperature / Pressure - OldTemperature / OldPressure); // Compute the inertia of the ballonet. // Consider the ballonet as a shape of uniform density. // FIXME: If the ballonet isn't ellipsoid or cylindrical the inertia will // be wrong. ballonetJ = FGMatrix33(); const double mass = Contents * M_air; double Ixx, Iyy, Izz; if ((Xradius != 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && (Xwidth == 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) { // Ellipsoid volume. Ixx = (1.0 / 5.0) * mass * (Yradius*Yradius + Zradius*Zradius); Iyy = (1.0 / 5.0) * mass * (Xradius*Xradius + Zradius*Zradius); Izz = (1.0 / 5.0) * mass * (Xradius*Xradius + Yradius*Yradius); } else if ((Xradius == 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && (Xwidth != 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) { // Cylindrical volume (might not be valid with an elliptical cross-section). Ixx = (1.0 / 2.0) * mass * Yradius * Zradius; Iyy = (1.0 / 4.0) * mass * Yradius * Zradius + (1.0 / 12.0) * mass * Xwidth * Xwidth; Izz = (1.0 / 4.0) * mass * Yradius * Zradius + (1.0 / 12.0) * mass * Xwidth * Xwidth; } else { // Not supported. Revert to pointmass model. Ixx = Iyy = Izz = 0.0; } // The volume is symmetric, so Ixy = Ixz = Iyz = 0. ballonetJ(1,1) = Ixx; ballonetJ(2,2) = Iyy; ballonetJ(3,3) = Izz; // Transform the moments of inertia to the body frame. ballonetJ += MassBalance->GetPointmassInertia(GetMass(), GetXYZ()); }
void CEasyGenView::OnLButtonDown(UINT nFlags, CPoint point) { CEasyGenDoc *pDoc = GetDocument(); S_POSINFO inf; CTris *t; CNmVec3 p; int tab; m_LDP = point; BOOL kCTRL = nFlags & MK_CONTROL; BOOL kSHIFT = nFlags & MK_SHIFT; BOOL Refresh = FALSE; int mod = pDoc->GetModifier(); switch (tab = pDoc->GetActiveTab()) { case (TAB_GRID): break; case (TAB_MODIFIER): // Get a vertex to drag(CTRL+SHIFT+LeftBut) if (kCTRL && kSHIFT) { if (GetXYZ(point, p)) { if (g_Grid.GetInfo(p.x, p.y, &inf)) { m_VertexGot = g_Grid.GetK(inf.i, inf.j); } } } // Exclude triangle from export | to prevent erroneus exclusion if (!kCTRL && kSHIFT && g_Grid.OptionExcludedTrisGet()) { if (GetXYZ(point, p)) { t = g_Grid.GetTris(g_Grid.GetTris(p.x, p.y)); if (t) { t->SetExcluded(!t->GetExcluded()); pDoc->m_bInvalidateGridColor = TRUE; Refresh = TRUE; } } } break; case (TAB_ALPHAMAP): int curindex; curindex = g_AlphamapMan.GetCurSel(); // paint the alphamap (CTRL+SHIFT+LeftBut) if (kCTRL && kSHIFT && curindex != -1) { if (GetXYZ(point, p)) { if (g_Grid.GetInfo(p.x, p.y, &inf)) { m_VertexGot = g_Grid.GetK(inf.i, inf.j); // g_Grid.SetAlphaIndex(m_VertexGot, curindex ); g_Grid.PaintAlphaIndex(inf.i, inf.j, pDoc->m_dwPaintRadius, curindex); Refresh = TRUE; } } } int indexgot; // copy alphamap index (SHIFT+LeftBut) if (!kCTRL && kSHIFT) { if (GetXYZ(point, p)) { if (g_Grid.GetInfo(p.x, p.y, &inf)) { m_VertexGot = g_Grid.GetK(inf.i, inf.j); indexgot = g_Grid.GetAlphaIndex(m_VertexGot); if (indexgot != g_AlphamapMan.GetCurSel()) { g_AlphamapMan.SetCurSel(indexgot); pDoc->UpdateFormView(TAB_ALPHAMAP); } } } } break; case (TAB_MODELS): // MD3 - Selecting if (!kCTRL && kSHIFT) { CNmVec3 ray, dummy; float md3_dist, hitterra_dist; bool hitterra; S_MD3PTR *oldh = m_Md3Highlight; S_MD3PTR *hit_md3; if (GetRay(point, ray)) { if (g_Md3Man.GetByRay(m_Eye, ray, hit_md3, md3_dist)) { // check if is covered by terrain!!! hitterra = g_Grid.GetDistanceTrisRay(m_Eye, ray, dummy, hitterra_dist); if (!hitterra) { m_Md3Highlight = hit_md3; } else if (hitterra_dist > md3_dist) { m_Md3Highlight = hit_md3; } } } if (m_Md3Highlight != oldh) { Refresh = TRUE; } } break; } // rotate tris (CTRL+LeftBut) if ((tab == TAB_GRID || tab == TAB_MODIFIER || tab == TAB_ALPHAMAP) && mod == MOD_NONE && kCTRL && !kSHIFT) { if (GetXYZ(point, p)) { if (g_Grid.GetInfo(p.x, p.y, &inf)) { int i, j, k; int mt1; S_FACEDATAEX *f; mt1 = g_Grid.GetTris(p.x, p.y); mt1 &= ~1; k = mt1 / 2; i = k % g_Grid.GetCellsX(); j = k / g_Grid.GetCellsX(); f = g_Grid.GetFace(k); if ((f->flags & FACE_FL_TRISINV)) { f->flags &= ~FACE_FL_TRISINV; } else { f->flags |= FACE_FL_TRISINV; } g_Grid.FaceOrientateTris(i, j, f->flags & FACE_FL_TRISINV); Refresh = TRUE; } } } if (Refresh) { InvalidateRect(NULL, FALSE); } // SetCapture(); CView::OnLButtonDown(nFlags, point); }
void FGGasCell::Calculate(double dt) { const double AirTemperature = in.Temperature; // [Rankine] const double AirPressure = in.Pressure; // [lbs/ft^2] const double AirDensity = in.Density; // [slug/ft^3] const double g = in.gravity; // [lbs/slug] const double OldTemperature = Temperature; const double OldPressure = Pressure; unsigned int i; const size_t no_ballonets = Ballonet.size(); //-- Read ballonet state -- // NOTE: This model might need a more proper integration technique. double BallonetsVolume = 0.0; double BallonetsHeatFlow = 0.0; for (i = 0; i < no_ballonets; i++) { BallonetsVolume += Ballonet[i]->GetVolume(); BallonetsHeatFlow += Ballonet[i]->GetHeatFlow(); } //-- Gas temperature -- if (HeatTransferCoeff.size() > 0) { // The model is based on the ideal gas law. // However, it does look a bit fishy. Please verify. // dT/dt = dU / (Cv n R) double dU = 0.0; for (i = 0; i < HeatTransferCoeff.size(); i++) { dU += HeatTransferCoeff[i]->GetValue(); } // Don't include dt when accounting for adiabatic expansion/contraction. // The rate of adiabatic cooling looks about right: ~5.4 Rankine/1000ft. if (Contents > 0) { Temperature += (dU * dt - Pressure * dVolumeIdeal - BallonetsHeatFlow) / (Cv_gas() * Contents * R); } else { Temperature = AirTemperature; } } else { // No simulation of complex temperature changes. // Note: Making the gas cell behave adiabatically might be a better // option. Temperature = AirTemperature; } //-- Pressure -- const double IdealPressure = Contents * R * Temperature / (MaxVolume - BallonetsVolume); if (IdealPressure > AirPressure + MaxOverpressure) { Pressure = AirPressure + MaxOverpressure; } else { Pressure = max(IdealPressure, AirPressure); } //-- Manual valving -- // FIXME: Presently the effect of manual valving is computed using // an ad hoc formula which might not be a good representation // of reality. if ((ValveCoefficient > 0.0) && (ValveOpen > 0.0)) { // First compute the difference in pressure between the gas in the // cell and the air above it. // FixMe: CellHeight should depend on current volume. const double CellHeight = 2 * Zradius + Zwidth; // [ft] const double GasMass = Contents * M_gas(); // [slug] const double GasVolume = Contents * R * Temperature / Pressure; // [ft^3] const double GasDensity = GasMass / GasVolume; const double DeltaPressure = Pressure + CellHeight * g * (AirDensity - GasDensity) - AirPressure; const double VolumeValved = ValveOpen * ValveCoefficient * DeltaPressure * dt; Contents = max(0.0, Contents - Pressure * VolumeValved / (R * Temperature)); } //-- Update ballonets. -- // Doing that here should give them the opportunity to react to the // new pressure. BallonetsVolume = 0.0; for (i = 0; i < no_ballonets; i++) { Ballonet[i]->Calculate(dt); BallonetsVolume += Ballonet[i]->GetVolume(); } //-- Automatic safety valving. -- if (Contents * R * Temperature / (MaxVolume - BallonetsVolume) > AirPressure + MaxOverpressure) { // Gas is automatically valved. Valving capacity is assumed to be infinite. // FIXME: This could/should be replaced by damage to the gas cell envelope. Contents = (AirPressure + MaxOverpressure) * (MaxVolume - BallonetsVolume) / (R * Temperature); } //-- Volume -- Volume = Contents * R * Temperature / Pressure + BallonetsVolume; dVolumeIdeal = Contents * R * (Temperature / Pressure - OldTemperature / OldPressure); //-- Current buoyancy -- // The buoyancy is computed using the atmospheres local density. Buoyancy = Volume * AirDensity * g; // Note: This is gross buoyancy. The weight of the gas itself and // any ballonets is not deducted here as the effects of the gas mass // is handled by FGMassBalance. vFn.InitMatrix(0.0, 0.0, - Buoyancy); // Compute the inertia of the gas cell. // Consider the gas cell as a shape of uniform density. // FIXME: If the cell isn't ellipsoid or cylindrical the inertia will // be wrong. gasCellJ = FGMatrix33(); const double mass = Contents * M_gas(); double Ixx, Iyy, Izz; if ((Xradius != 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && (Xwidth == 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) { // Ellipsoid volume. Ixx = (1.0 / 5.0) * mass * (Yradius*Yradius + Zradius*Zradius); Iyy = (1.0 / 5.0) * mass * (Xradius*Xradius + Zradius*Zradius); Izz = (1.0 / 5.0) * mass * (Xradius*Xradius + Yradius*Yradius); } else if ((Xradius == 0.0) && (Yradius != 0.0) && (Zradius != 0.0) && (Xwidth != 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) { // Cylindrical volume (might not be valid with an elliptical cross-section). Ixx = (1.0 / 2.0) * mass * Yradius * Zradius; Iyy = (1.0 / 4.0) * mass * Yradius * Zradius + (1.0 / 12.0) * mass * Xwidth * Xwidth; Izz = (1.0 / 4.0) * mass * Yradius * Zradius + (1.0 / 12.0) * mass * Xwidth * Xwidth; } else { // Not supported. Revert to pointmass model. Ixx = Iyy = Izz = 0.0; } // The volume is symmetric, so Ixy = Ixz = Iyz = 0. gasCellJ(1,1) = Ixx; gasCellJ(2,2) = Iyy; gasCellJ(3,3) = Izz; Mass = mass; // Transform the moments of inertia to the body frame. gasCellJ += MassBalance->GetPointmassInertia(Mass, GetXYZ()); gasCellM.InitMatrix(); gasCellM(eX) += GetXYZ(eX) * Mass*slugtolb; gasCellM(eY) += GetXYZ(eY) * Mass*slugtolb; gasCellM(eZ) += GetXYZ(eZ) * Mass*slugtolb; if (no_ballonets > 0) { // Add the mass, moment and inertia of any ballonets. for (i = 0; i < no_ballonets; i++) { Mass += Ballonet[i]->GetMass(); // Add ballonet moments due to mass (in the structural frame). gasCellM(eX) += Ballonet[i]->GetXYZ(eX) * Ballonet[i]->GetMass()*slugtolb; gasCellM(eY) += Ballonet[i]->GetXYZ(eY) * Ballonet[i]->GetMass()*slugtolb; gasCellM(eZ) += Ballonet[i]->GetXYZ(eZ) * Ballonet[i]->GetMass()*slugtolb; gasCellJ += Ballonet[i]->GetInertia(); } } }