Пример #1
0
        private double WingInterference(Vector3 rayDirection, List <Part> PartList, float dist)
        {
            double interferencevalue = 1;

            Ray ray = new Ray();

            ray.origin    = parentWingModule.WingCentroid();
            ray.direction = rayDirection;

            RaycastHit hit = new RaycastHit();

            bool gotSomething = false;

            hit.distance = 0;
            RaycastHit[] hits = Physics.RaycastAll(ray, dist, FARAeroUtil.RaycastMask);
            for (int i = 0; i < hits.Length; i++)
            {
                RaycastHit h = hits[i];
                if (h.collider != null)
                {
                    for (int j = 0; j < PartList.Count; j++)
                    {
                        Part p = PartList[j];

                        if (p == null)
                        {
                            continue;
                        }

                        if (p == parentWingPart)
                        {
                            continue;
                        }

                        FARWingAerodynamicModel w = p.GetComponent <FARWingAerodynamicModel>();

                        if (w != null)
                        {
                            Collider[] colliders = w.PartColliders;

                            for (int k = 0; k < colliders.Length; k++)
                            {
                                if (h.collider == colliders[k] && h.distance > 0)
                                {
                                    double tmp = h.distance / dist;
                                    tmp = FARMathUtil.Clamp(tmp, 0, 1);
                                    double tmp2 = Math.Abs(Vector3.Dot(parentWingPart.partTransform.forward, w.part.partTransform.forward));
                                    tmp = 1 - (1 - tmp) * tmp2;
                                    interferencevalue = Math.Min(tmp, interferencevalue);
                                    gotSomething      = true;

                                    break;
                                }
                            }
                        }
                        if (gotSomething)
                        {
                            break;
                        }
                    }
                }
            }
            return(interferencevalue);
        }
Пример #2
0
        /// <summary>
        /// Accounts for increments in lift due to camber changes from upstream wings, and returns changes for this wing part; returns true if there are wings in front of it
        /// </summary>
        /// <param name="thisWingAoA">AoA of this wing in rad</param>
        /// <param name="thisWingMachNumber">Mach Number of this wing in rad</param>
        /// <param name="ACWeight">Weighting value for applying ACshift</param>
        /// <param name="ACShift">Value used to shift the wing AC due to interactive effects</param>
        /// <param name="ClIncrementFromRear">Increase in Cl due to this</param>
        /// <returns></returns>
        public void CalculateEffectsOfUpstreamWing(double thisWingAoA, double thisWingMachNumber, Vector3d parallelInPlaneLocal,
                                                   ref double ACweight, ref double ACshift, ref double ClIncrementFromRear)
        {
            double thisWingMAC, thisWingb_2;

            thisWingMAC = parentWingModule.GetMAC();
            thisWingb_2 = parentWingModule.Getb_2();

            effectiveUpstreamMAC  = 0;
            effectiveUpstreamb_2  = 0;
            effectiveUpstreamArea = 0;

            effectiveUpstreamLiftSlope     = 0;
            effectiveUpstreamStall         = 0;
            effectiveUpstreamCosSweepAngle = 0;
            effectiveUpstreamAoAMax        = 0;
            effectiveUpstreamAoA           = 0;
            effectiveUpstreamCd0           = 0;
            effectiveUpstreamInfluence     = 0;

            double wingForwardDir   = parallelInPlaneLocal.y;
            double wingRightwardDir = parallelInPlaneLocal.x * srfAttachFlipped;

            if (wingForwardDir > 0)
            {
                wingForwardDir *= wingForwardDir;
                UpdateUpstreamValuesFromWingModules(nearbyWingModulesForwardList, nearbyWingModulesForwardInfluence, wingForwardDir, thisWingAoA);
            }
            else
            {
                wingForwardDir *= wingForwardDir;
                UpdateUpstreamValuesFromWingModules(nearbyWingModulesBackwardList, nearbyWingModulesBackwardInfluence, wingForwardDir, thisWingAoA);
            }

            if (wingRightwardDir > 0)
            {
                wingRightwardDir *= wingRightwardDir;
                UpdateUpstreamValuesFromWingModules(nearbyWingModulesRightwardList, nearbyWingModulesRightwardInfluence, wingRightwardDir, thisWingAoA);
            }
            else
            {
                wingRightwardDir *= wingRightwardDir;
                UpdateUpstreamValuesFromWingModules(nearbyWingModulesLeftwardList, nearbyWingModulesLeftwardInfluence, wingRightwardDir, thisWingAoA);
            }

            double MachCoeff = FARMathUtil.Clamp(1 - thisWingMachNumber * thisWingMachNumber, 0, 1);

            if (!MachCoeff.NearlyEqual(0))
            {
                double flapRatio     = FARMathUtil.Clamp(thisWingMAC / (thisWingMAC + effectiveUpstreamMAC), 0, 1);
                float  flt_flapRatio = (float)flapRatio;
                double flapFactor    = wingCamberFactor.Evaluate(flt_flapRatio);     //Flap Effectiveness Factor
                double dCm_dCl       = wingCamberMoment.Evaluate(flt_flapRatio);     //Change in moment due to change in lift from flap

                //This accounts for the wing possibly having a longer span than the flap
                double WingFraction = FARMathUtil.Clamp(thisWingb_2 / effectiveUpstreamb_2, 0, 1);
                //This accounts for the flap possibly having a longer span than the wing it's attached to
                double FlapFraction = FARMathUtil.Clamp(effectiveUpstreamb_2 / thisWingb_2, 0, 1);

                double ClIncrement = flapFactor * effectiveUpstreamLiftSlope * effectiveUpstreamAoA;                            //Lift created by the flap interaction
                ClIncrement *= (parentWingModule.S * FlapFraction + effectiveUpstreamArea * WingFraction) / parentWingModule.S; //Increase the Cl so that even though we're working with the flap's area, it accounts for the added lift across the entire object

                ACweight = ClIncrement * MachCoeff;                                                                             // Total flap Cl for the purpose of applying ACshift, including the bit subtracted below

                ClIncrement -= FlapFraction * effectiveUpstreamLiftSlope * effectiveUpstreamAoA;                                //Removing additional angle so that lift of the flap is calculated as lift at wing angle + lift due to flap interaction rather than being greater

                ACshift = (dCm_dCl + 0.75 * (1 - flapRatio)) * (thisWingMAC + effectiveUpstreamMAC);                            //Change in Cm with change in Cl

                ClIncrementFromRear = ClIncrement * MachCoeff;
            }
        }
Пример #3
0
 private void AoAOffsetFromFlapDeflection()
 {
     AoAdesiredFlap = maxdeflectFlap * flapLocation * flapDeflectionLevel * 0.33333333333;
     AoAdesiredFlap = FARMathUtil.Clamp(AoAdesiredFlap, -Math.Abs(maxdeflectFlap), Math.Abs(maxdeflectFlap));
 }
Пример #4
0
        public void SetControlStateEditor(Vector3 CoM, Vector3 velocityVec, float pitch, float yaw, float roll, int flap, bool brake)
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                Transform partTransform = part.partTransform;
                Transform rootTransform = EditorLogic.RootPart.partTransform;

                Vector3 CoMoffset = (partTransform.position - CoM);
                PitchLocation       = Vector3.Dot(partTransform.forward, rootTransform.forward) * Math.Sign(Vector3.Dot(CoMoffset, rootTransform.up));
                YawLocation         = -Vector3.Dot(partTransform.forward, rootTransform.right) * Math.Sign(Vector3.Dot(CoMoffset, rootTransform.up));
                RollLocation        = Vector3.Dot(partTransform.forward, rootTransform.forward) * Math.Sign(Vector3.Dot(CoMoffset, -rootTransform.right));
                BrakeRudderLocation = Vector3.Dot(partTransform.forward, rootTransform.forward);
                BrakeRudderSide     = Mathf.Sign(Vector3.Dot(CoMoffset, rootTransform.right));
                AoAsign             = Math.Sign(Vector3.Dot(partTransform.up, rootTransform.up));
                AoAdesiredControl   = 0;
                if (pitchaxis != 0.0)
                {
                    AoAdesiredControl += PitchLocation * pitch * pitchaxis * 0.01;
                }
                if (yawaxis != 0.0)
                {
                    AoAdesiredControl += YawLocation * yaw * yawaxis * 0.01;
                }
                if (rollaxis != 0.0)
                {
                    AoAdesiredControl += RollLocation * roll * rollaxis * 0.01;
                }
                if (brakeRudder != 0.0)
                {
                    AoAdesiredControl += BrakeRudderLocation * Math.Max(0.0, BrakeRudderSide * yawaxis) * brakeRudder * 0.01;
                }
                AoAdesiredControl *= maxdeflect;
                if (pitchaxisDueToAoA != 0.0)
                {
                    Vector3 tmpVec = rootTransform.up * Vector3.Dot(rootTransform.up, velocityVec) + rootTransform.forward * Vector3.Dot(rootTransform.forward, velocityVec); //velocity vector projected onto a plane that divides the airplane into left and right halves
                    double  AoA    = base.CalculateAoA(tmpVec.normalized);                                                                                                    //using base.CalculateAoA gets the deflection using WingAeroModel's code, which does not account for deflection; this gives us the AoA that the surface _would_ be at if it hadn't deflected at all.
                    AoA = FARMathUtil.rad2deg * AoA;
                    if (double.IsNaN(AoA))
                    {
                        AoA = 0;
                    }
                    AoAdesiredControl += AoA * pitchaxisDueToAoA * 0.01;
                }

                AoAdesiredControl *= AoAsign;
                AoAdesiredControl  = FARMathUtil.Clamp(AoAdesiredControl, -Math.Abs(maxdeflect), Math.Abs(maxdeflect));
                AoAcurrentControl  = AoAdesiredControl;
                AoAcurrentFlap     = 0;

                if (part.symMethod == SymmetryMethod.Mirror || part.symmetryCounterparts.Count < 1)
                {
                    if (HighLogic.LoadedSceneIsFlight)
                    {
                        flapLocation = Math.Sign(Vector3.Dot(vessel.ReferenceTransform.forward, part.partTransform.forward));      //figure out which way is up
                    }
                    else
                    {
                        flapLocation = Math.Sign(Vector3.Dot(EditorLogic.RootPart.partTransform.forward, part.partTransform.forward));      //figure out which way is up
                    }
                    spoilerLocation = -flapLocation;
                }
                else if (part.parent != null)
                {
                    flapLocation    = Math.Sign(Vector3.Dot(part.partTransform.position - part.parent.partTransform.position, part.partTransform.forward));
                    spoilerLocation = flapLocation;
                }
                else
                {
                    flapLocation    = 1;
                    spoilerLocation = flapLocation;
                }

                if (isFlap)
                {
                    AoAcurrentFlap += maxdeflectFlap * flapLocation * flap * 0.3333333333333;
                }
                else if (isSpoiler)
                {
                    AoAcurrentFlap += brake ? maxdeflectFlap * spoilerLocation : 0;
                }

                AoAdesiredFlap = AoAcurrentFlap;
                AoAoffset      = AoAcurrentFlap + AoAcurrentControl;
                DeflectionAnimation();
            }
        }
Пример #5
0
        private void AttachNodeCdAdjust()
        {
            if (part.Modules.Contains("FARPayloadFairingModule"))       //This doesn't apply blunt drag drag to fairing parts if one of their "exempt" attach nodes is used, indicating attached fairings
            {
                return;
            }
            if (VesselPartList == null)
            {
                UpdateShipPartsList();
            }

            if (attachNodeDragList == null)
            {
                attachNodeDragList = new List <attachNodeData>();
            }

            attachNodeDragList.Clear();

            Transform transform = part.partTransform;

            if (transform == null)
            {
                transform = part.transform;
            }
            if (transform == null)
            {
                Debug.LogError("Part " + part.partInfo.title + " has null transform; drag interactions cannot be applied.");
                return;
            }

            SPlusAttachArea = S;

            Vector3d partUpVector = transform.TransformDirection(localUpVector);

            //print("Updating drag for " + part.partInfo.title);
            foreach (AttachNode Attach in part.attachNodes)
            {
                if (Attach.nodeType == AttachNode.NodeType.Stack)
                {
                    if (Attach.attachedPart != null)
                    {
                        continue;
                    }
                    if (Attach.id.ToLowerInvariant() == "strut")
                    {
                        continue;
                    }

                    Ray ray = new Ray();

                    Vector3d relPos = Attach.position + Attach.offset;

                    if (part.Modules.Contains("FARCargoBayModule"))
                    {
                        FARCargoBayModule bay = (FARCargoBayModule)part.Modules["FARCargoBayModule"];

                        Vector3d maxBounds = bay.maxBounds;
                        Vector3d minBounds = bay.minBounds;

                        if (relPos.x < maxBounds.x && relPos.y < maxBounds.y && relPos.z < maxBounds.z && relPos.x > minBounds.x && relPos.y > minBounds.y && relPos.z > minBounds.z)
                        {
                            return;
                        }
                    }

                    Vector3d origToNode = transform.localToWorldMatrix.MultiplyVector(relPos);

                    double mag = (origToNode).magnitude;



                    //print(part.partInfo.title + " Part Loc: " + part.transform.position + " Attach Loc: " + (origToNode + part.transform.position) + " Dist: " + mag);

                    ray.direction = origToNode;
                    ray.origin    = transform.position;

                    double attachSize = FARMathUtil.Clamp(Attach.size, 0.5, double.PositiveInfinity);

                    bool         gotIt = false;
                    RaycastHit[] hits  = Physics.RaycastAll(ray, (float)(mag + attachSize), FARAeroUtil.RaycastMask);
                    foreach (RaycastHit h in hits)
                    {
                        if (h.collider == part.collider)
                        {
                            continue;
                        }
                        if (h.distance < (mag + attachSize) && h.distance > (mag - attachSize))
                        {
                            foreach (Part p in VesselPartList)
                            {
                                if (p.collider == h.collider)
                                {
                                    gotIt = true;
                                    break;
                                }
                            }
                        }
                        if (gotIt)
                        {
                            break;
                        }
                    }

                    if (!gotIt)
                    {
                        double exposedAttachArea = attachSize * FARAeroUtil.attachNodeRadiusFactor;
                        exposedAttachArea *= exposedAttachArea;
                        exposedAttachArea *= Math.PI * FARAeroUtil.areaFactor;

                        SPlusAttachArea += exposedAttachArea;

                        exposedAttachArea /= FARMathUtil.Clamp(S, 0.01, double.PositiveInfinity);

                        attachNodeData newAttachNodeData = new attachNodeData();
                        newAttachNodeData.areaValue = exposedAttachArea;
                        if (Vector3d.Dot(origToNode, partUpVector) > 1)
                        {
                            newAttachNodeData.pitchesAwayFromUpVec = true;
                        }
                        else
                        {
                            newAttachNodeData.pitchesAwayFromUpVec = false;
                        }

                        newAttachNodeData.location = transform.worldToLocalMatrix.MultiplyVector(origToNode);

                        attachNodeDragList.Add(newAttachNodeData);
                    }
                }
            }
        }