예제 #1
0
        private void HandleAttachNodeCd()
        {
            if (VesselPartList == null)
            {
                UpdateShipPartsList();
            }

            if (attachNodeDragDict == null)
            {
                attachNodeDragDict = new Dictionary <Vector3d, attachNodeData>();
            }

            attachNodeDragDict.Clear();

            Dictionary <string, List <AttachNode> > attachNodeGroups = GetAttachNodeGroups();
            Dictionary <string, AttachGroupType>    attachNodeType   = GetAttachGroupTypes(attachNodeGroups);

            if (VesselModelTransforms == null)
            {
                if (HighLogic.LoadedScene == GameScenes.EDITOR)
                {
                    VesselModelTransforms = FARGeoUtil.VesselModelTransforms(EditorLogic.SortedShipList);
                }
                else
                {
                    VesselModelTransforms = FARGeoUtil.VesselModelTransforms(vessel);
                }

                foreach (Part p in VesselPartList)
                {
                    foreach (PartModule m in p.Modules)
                    {
                        if (m is FARBasicDragModel)
                        {
                            (m as FARBasicDragModel).VesselModelTransforms = this.VesselModelTransforms;
                            continue;
                        }
                    }
                }
            }

            foreach (KeyValuePair <string, List <AttachNode> > attachGroup in attachNodeGroups)
            {
                UpdateAttachGroupDrag(attachGroup.Value, attachNodeType[attachGroup.Key], PartModelTransforms, VesselModelTransforms);
            }

            //UpdateNonAttachBluntEnds(attachNodeGroups, attachNodeType, FARGeoUtil.WorldToPartUpMatrix(part), PartModelTransforms, VesselModelTransforms);
            VesselModelTransforms = null;
        }
예제 #2
0
        public override void OnStart(StartState state)
        {
            base.OnStart(state);


            //gear = part.GetComponent<ModuleLandingGear>();

            OnVesselPartsChange += AttachNodeCdAdjust;

            UpdateUpVector(false);
            PartModelTransforms = FARGeoUtil.PartModelTransformArray(part);
            AttachNodeCdAdjust();
            AnimationSetup();
            Fields["currentDrag"].guiActive = FARDebugValues.displayForces;
        }
예제 #3
0
        private void UpdateUpVector(bool init)
        {
            if (init)
            {
                Quaternion rot = FARGeoUtil.GuessUpRotation(part);

                localUpVector      = rot * Vector3d.up;
                localForwardVector = rot * Vector3d.forward;
            }
            //Doesn't work with Vector3d
            //Vector3d.OrthoNormalize(ref localUpVector, ref localForwardVector);

            localUpVector.Normalize();
            localForwardVector = Vector3d.Exclude(localUpVector, localForwardVector).normalized;

            Quaternion to_local = Quaternion.LookRotation(localForwardVector, localUpVector);

            to_model_rotation = Quaternion.Inverse(to_local);
        }
예제 #4
0
        private void CalculatePartBounds(Part p)
        {
            Vector3 minBoundVec, maxBoundVec;

            minBoundVec = maxBoundVec = Vector3.zero;
            Transform[] transformList = FARGeoUtil.PartModelTransformArray(p);
            for (int i = 0; i < transformList.Length; i++)
            {
                Transform t = transformList[i];

                MeshFilter mf = t.GetComponent <MeshFilter>();
                if ((object)mf == null)
                {
                    continue;
                }
                Mesh m = mf.mesh;

                if ((object)m == null)
                {
                    continue;
                }

                var matrix = part.transform.worldToLocalMatrix * t.localToWorldMatrix;

                for (int j = 0; j < m.vertices.Length; j++)
                {
                    Vector3 v = matrix.MultiplyPoint3x4(m.vertices[j]);

                    maxBoundVec.x = Mathf.Max(maxBoundVec.x, v.x);
                    minBoundVec.x = Mathf.Min(minBoundVec.x, v.x);
                    maxBoundVec.y = Mathf.Max(maxBoundVec.y, v.y);
                    minBoundVec.y = Mathf.Min(minBoundVec.y, v.y);
                    maxBoundVec.z = Mathf.Max(maxBoundVec.z, v.z);
                    minBoundVec.z = Mathf.Min(minBoundVec.z, v.z);
                }
                minBoundVec.x *= 1.05f;
                maxBoundVec.x *= 1.05f;
                minBoundVec.z *= 1.05f;
                maxBoundVec.z *= 1.05f;
            }
            minBounds.Add(minBoundVec);
            maxBounds.Add(maxBoundVec);
        }
예제 #5
0
        private void UpdateNonAttachBluntEnds(Dictionary <string, List <AttachNode> > attachNodeGroups, Dictionary <string, AttachGroupType> attachNodeType, Matrix4x4 partUpMatrix, Transform[] ModelTransforms, Transform[] VesselModelTransforms)
        {
            bool upperEndHandled = false;
            bool lowerEndHandled = false;

            Vector2 verticalPartMeshBounds = FARGeoUtil.PartLengthBounds(part, Vector3.zero, partUpMatrix, ModelTransforms);

            foreach (KeyValuePair <string, List <AttachNode> > pair in attachNodeGroups)
            {
                Vector3 avgPos    = Vector3.zero;
                Vector3 avgOrient = Vector3.zero;
                foreach (AttachNode node in pair.Value)
                {
                    avgPos    += node.position;
                    avgOrient += node.orientation;
                }
                avgPos /= pair.Value.Count;
                avgOrient.Normalize();

                if (Mathf.Abs(avgPos.y - verticalPartMeshBounds.x) <= 0.3f)
                {
                    upperEndHandled = true;
                }
                if (Mathf.Abs(avgPos.y - verticalPartMeshBounds.y) <= 0.3f)
                {
                    lowerEndHandled = true;
                }

                if (upperEndHandled && lowerEndHandled)
                {
                    break;
                }
            }

            if (!upperEndHandled)
            {
                Vector3 position = Vector3.up * verticalPartMeshBounds.x;

                Vector2 bounds = FARGeoUtil.NodeBoundaries(part, position, position, Vector3.zero, 0.05f, ModelTransforms);

                double area = (bounds.x + bounds.y);
                area *= 0.5;
                area *= area;
                area *= Math.PI;       //Calculate area based on circular cross-section


                area = FARMathUtil.Clamp(area, 0, double.PositiveInfinity);


                //Update attachNodeDragDict with new data
                attachNodeData newAttachNodeData = new attachNodeData();
                newAttachNodeData.areaValue = area / FARMathUtil.Clamp(S, 0.01, double.PositiveInfinity);

                Vector3 orientation = position;

                if (Vector3d.Dot(orientation, localUpVector) > 1)
                {
                    newAttachNodeData.pitchesAwayFromUpVec = true;
                }
                else
                {
                    newAttachNodeData.pitchesAwayFromUpVec = false;
                }


                if (attachNodeDragDict.ContainsKey(orientation))
                {
                    attachNodeData tmp = attachNodeDragDict[orientation];
                    tmp.areaValue += newAttachNodeData.areaValue;
                    attachNodeDragDict[orientation] = tmp;
                }
                else
                {
                    attachNodeDragDict.Add(orientation, newAttachNodeData);
                }
            }

            if (!lowerEndHandled)
            {
                Vector3 position = Vector3.up * verticalPartMeshBounds.y;

                Vector2 bounds = FARGeoUtil.NodeBoundaries(part, position, position, Vector3.zero, 0.05f, ModelTransforms);

                double area = (bounds.x + bounds.y);
                area *= 0.5;
                area *= area;
                area *= Math.PI;       //Calculate area based on circular cross-section


                area = FARMathUtil.Clamp(area, 0, double.PositiveInfinity);


                //Update attachNodeDragDict with new data
                attachNodeData newAttachNodeData = new attachNodeData();
                newAttachNodeData.areaValue = area / FARMathUtil.Clamp(S, 0.01, double.PositiveInfinity);

                Vector3 orientation = position;

                if (Vector3d.Dot(orientation, localUpVector) > 1)
                {
                    newAttachNodeData.pitchesAwayFromUpVec = true;
                }
                else
                {
                    newAttachNodeData.pitchesAwayFromUpVec = false;
                }


                if (attachNodeDragDict.ContainsKey(orientation))
                {
                    attachNodeData tmp = attachNodeDragDict[orientation];
                    tmp.areaValue += newAttachNodeData.areaValue;
                    attachNodeDragDict[orientation] = tmp;
                }
                else
                {
                    attachNodeDragDict.Add(orientation, newAttachNodeData);
                }
            }
        }
예제 #6
0
        private void UpdateAttachGroupDrag(List <AttachNode> attachNodeGroup, AttachGroupType attachGroupType, Transform[] ThisPartModelTransforms, Transform[] AllVesselModelTransforms)
        {
            //This is standard single node; the blunt area is to be determined by everything near it
            if (attachGroupType == AttachGroupType.INDEPENDENT_NODE)
            {
                //Get area represented by current node
                Vector2 bounds = FARGeoUtil.NodeBoundaries(part, attachNodeGroup, Vector3.zero, 0.05f, ThisPartModelTransforms);

                double area = (bounds.x + bounds.y);
                area *= 0.5;
                area *= area;
                area *= Math.PI;       //Calculate area based on circular cross-section

                //Get area covered by other parts
                Transform[] OtherTransforms = FARGeoUtil.ChooseNearbyModelTransforms(part, attachNodeGroup, bounds, ThisPartModelTransforms, AllVesselModelTransforms);
                Vector2     otherBounds     = FARGeoUtil.NodeBoundaries(part, attachNodeGroup, Vector3.zero, 0.05f, OtherTransforms);

                double opposedArea = (otherBounds.x + otherBounds.y);
                opposedArea *= 0.5f;
                opposedArea *= opposedArea;
                opposedArea *= Math.PI;       //Calculate area based on circular cross-section

                //Debug.Log(part.partInfo.title + " Area: " + area + " Opposed area: " + opposedArea + " OtherTransforms: " + OtherTransforms.Length);

                area = FARMathUtil.Clamp(area - opposedArea, 0, double.PositiveInfinity);


                //Update attachNodeDragDict with new data
                attachNodeData newAttachNodeData = new attachNodeData();
                newAttachNodeData.areaValue = area / FARMathUtil.Clamp(S, 0.01, double.PositiveInfinity);

                Vector3 orientation = attachNodeGroup[0].position;

                if (Vector3d.Dot(orientation, localUpVector) > 1)
                {
                    newAttachNodeData.pitchesAwayFromUpVec = true;
                }
                else
                {
                    newAttachNodeData.pitchesAwayFromUpVec = false;
                }


                if (attachNodeDragDict.ContainsKey(orientation))
                {
                    attachNodeData tmp = attachNodeDragDict[orientation];
                    tmp.areaValue += newAttachNodeData.areaValue;
                    attachNodeDragDict[orientation] = tmp;
                }
                else
                {
                    attachNodeDragDict.Add(orientation, newAttachNodeData);
                }


                return;
            }
            //This is a group of nodes that can be used for clustered tanks/engines; the area calculated must be divided over them
            else if (attachGroupType == AttachGroupType.PARALLEL_NODES)
            {
                //Get area represented by current nodes
                Vector2 bounds = FARGeoUtil.NodeBoundaries(part, attachNodeGroup, Vector3.zero, 0.05f, ThisPartModelTransforms);

                double area = (bounds.x + bounds.y);
                area *= 0.5;
                area *= area;
                area *= Math.PI;       //Calculate area based on circular cross-section

                //Get area covered by other parts
                Transform[] OtherTransforms = FARGeoUtil.ChooseNearbyModelTransforms(part, attachNodeGroup, bounds, ThisPartModelTransforms, AllVesselModelTransforms);
                Vector2     otherBounds     = FARGeoUtil.NodeBoundaries(part, attachNodeGroup, Vector3.zero, 0.05f, OtherTransforms);

                double opposedArea = (otherBounds.x + otherBounds.y);
                opposedArea *= 0.5;
                opposedArea *= opposedArea;
                opposedArea *= Mathf.PI;       //Calculate area based on circular cross-section

                //Debug.Log(part.partInfo.title + " Area: " + area + " Opposed area: " + opposedArea + " OtherTransforms: " + OtherTransforms.Length);

                area = FARMathUtil.Clamp(area - opposedArea, 0, double.PositiveInfinity);

                //Update attachNodeDragDict with new data
                attachNodeData newAttachNodeData = new attachNodeData();
                newAttachNodeData.areaValue = area / FARMathUtil.Clamp(S, 0.01, double.PositiveInfinity);

                Vector3 orientation = Vector3.zero;
                foreach (AttachNode attach in attachNodeGroup)
                {
                    orientation += attach.position;
                }
                orientation /= attachNodeGroup.Count;

                if (Vector3d.Dot(orientation, localUpVector) > 1)
                {
                    newAttachNodeData.pitchesAwayFromUpVec = true;
                }
                else
                {
                    newAttachNodeData.pitchesAwayFromUpVec = false;
                }


                if (attachNodeDragDict.ContainsKey(orientation))
                {
                    attachNodeData tmp = attachNodeDragDict[orientation];
                    tmp.areaValue += newAttachNodeData.areaValue;
                    attachNodeDragDict[orientation] = tmp;
                }
                else
                {
                    attachNodeDragDict.Add(orientation, newAttachNodeData);
                }


                return;
            }
            //This represents a vertical stack of nodes, for different payload heights, multiple payload fairings, etc.  One node being used means that they are all used
            else if (attachGroupType == AttachGroupType.VERTICAL_NODES)
            {
                double     area = 0;
                AttachNode usedNode;
                Vector2    bounds      = Vector2.zero;
                Vector3    orientation = Vector3.zero;

                foreach (AttachNode attach in attachNodeGroup)
                {
                    //Get area represented by current node
                    bounds = FARGeoUtil.NodeBoundaries(part, attach, Vector3.zero, 0.05f, ThisPartModelTransforms);

                    double tmpArea = (bounds.x + bounds.y);
                    tmpArea *= 0.5;
                    tmpArea *= tmpArea;
                    tmpArea *= Math.PI;       //Calculate area based on circular cross-section

                    if (tmpArea > area)
                    {
                        area     = tmpArea;
                        usedNode = attach;
                    }
                    orientation += attach.position;
                }
                //Get area covered by other parts
                Transform[] OtherTransforms = FARGeoUtil.ChooseNearbyModelTransforms(part, attachNodeGroup, bounds, ThisPartModelTransforms, AllVesselModelTransforms);
                Vector2     otherBounds     = FARGeoUtil.NodeBoundaries(part, attachNodeGroup, Vector3.zero, 0.05f, OtherTransforms);

                double opposedArea = (otherBounds.x + otherBounds.y);
                opposedArea *= 0.5;
                opposedArea *= opposedArea;
                opposedArea *= Math.PI;       //Calculate area based on circular cross-section

                area = FARMathUtil.Clamp(area - opposedArea, 0, double.PositiveInfinity);

                //Update attachNodeDragDict with new data
                attachNodeData newAttachNodeData = new attachNodeData();
                newAttachNodeData.areaValue = area / FARMathUtil.Clamp(S, 0.01, double.PositiveInfinity);

                orientation /= attachNodeGroup.Count;

                if (Vector3d.Dot(orientation, localUpVector) > 1)
                {
                    newAttachNodeData.pitchesAwayFromUpVec = true;
                }
                else
                {
                    newAttachNodeData.pitchesAwayFromUpVec = false;
                }


                if (attachNodeDragDict.ContainsKey(orientation))
                {
                    attachNodeData tmp = attachNodeDragDict[orientation];
                    tmp.areaValue += newAttachNodeData.areaValue;
                    attachNodeDragDict[orientation] = tmp;
                }
                else
                {
                    attachNodeDragDict.Add(orientation, newAttachNodeData);
                }

                return;
            }
        }