예제 #1
0
        /// <summary>
        /// Compute target angular velocity in pitch,roll,yaw axes
        /// </summary>
        Vector3 ComputeTargetAngularVelocity(Vector3d torque, Vector3d moi)
        {
            var internalVessel   = vessel.InternalVessel;
            var currentRotation  = ReferenceFrame.RotationFromWorldSpace(internalVessel.ReferenceTransform.rotation);
            var currentDirection = ReferenceFrame.DirectionFromWorldSpace(internalVessel.ReferenceTransform.up);

            QuaternionD rotation;

            if (!double.IsNaN(TargetRoll))
            {
                // Roll angle set => use rotation from currentRotation -> targetRotation
                rotation = targetRotation * currentRotation.Inverse();
            }
            else
            {
                // Roll angle not set => use rotation from currentDirection -> targetDirection
                //FIXME: QuaternionD.FromToRotation method not available at runtime
                rotation = Quaternion.FromToRotation(currentDirection, targetDirection);
            }

            // Compute angles for the rotation in pitch (x), roll (y), yaw (z) axes
            float   angleFloat;
            Vector3 axisFloat;

            //FIXME: QuaternionD.ToAngleAxis method not available at runtime
            ((Quaternion)rotation).ToAngleAxis(out angleFloat, out axisFloat);
            double   angle  = GeometryExtensions.ClampAngle180(angleFloat);
            Vector3d axis   = axisFloat;
            var      angles = axis * angle;

            angles = vessel.ReferenceFrame.DirectionFromWorldSpace(ReferenceFrame.DirectionToWorldSpace(angles));
            return(AnglesToAngularVelocity(angles, torque, moi));
        }
예제 #2
0
        void UpdateTarget()
        {
            var phr = new Vector3d(targetPitch, targetHeading, double.IsNaN(targetRoll) ? 0 : targetRoll);

            targetRotation  = GeometryExtensions.QuaternionFromPitchHeadingRoll(phr);
            targetDirection = targetRotation * Vector3.up;
        }
예제 #3
0
파일: Node.cs 프로젝트: 0000duck/TORO
        /// <summary>
        /// construct list of nodes from a list of points and lines, this method finds the struts that belong
        /// to each node, orient them correctly, and constructs a geometric representation of the individual nodes
        /// from some base geometry which is oriented in a variety of ways
        /// </summary>
        /// <param name="nodeCenters"> the points where the nodes are positioned</param>
        /// <param name="struts"> the lines that represent the struts, these must be intersecting the points at their endpoints</param>
        /// <param name="strutDiameter"> the diameter of the struts</param>
        /// <param name="drillDepth"> the depth that a strut should be sunk into the surface of node</param>
        /// <param name="baseNode"></param>
        /// <param name="nodeOrientationStrategy"></param>
        /// <returns></returns>
        public static List <Node> ByPointsLinesAndGeoOrientationStrategy(List <Point> nodeCenters, List <Line> struts, double strutDiameter, Solid baseNode, OrientationStrategy nodeOrientationStrategy, double drillDepth = 12.7)
        {
            int currentId = 1;
            //prune all duplicate inputs from wireframe
            var prunedPoints = Point.PruneDuplicates(nodeCenters);
            var prunedLines  = GeometryExtensions.PruneDuplicates(struts);

            //find the adjacentLines for each node
            var output = new List <Node>();

            foreach (var centerPoint in prunedPoints)
            {
                //find adjacent struts for this node
                var intersectingLines = findAdjacentLines(centerPoint, prunedLines);
                var currentNode       = new Node("N" + currentId.ToString().PadLeft(4, '0'), centerPoint, baseNode, intersectingLines, strutDiameter, drillDepth, nodeOrientationStrategy);

                //get the most z face and store it as the holder face
                var surfaces = baseNode.Explode().OfType <Surface>().OrderBy(x => x.PointAtParameter(.5, .5).Z).ToList();
                currentNode.holderFacePreTransform = surfaces.Last();
                surfaces.Remove(currentNode.holderFacePreTransform);
                output.Add(currentNode);

                surfaces.ForEach(x => x.Dispose());

                //increment the string ID
                var i = 0;
                currentId = currentId + 1;
                i++;
            }

            //from the set of nodes, find the unique struts and use these to update the ids of the struts as well as trim the lines to the correct length
            // and update the final strut geometry
            var graphEdges = UniqueStruts(output);

            foreach (var edge in graphEdges)
            {
                var strutA = edge.GeometryEdges.First();
                var strutB = edge.GeometryEdges.Last();

                var nodeA = strutA.OwnerNode;
                var nodeB = strutB.OwnerNode;

                var indA = edge.GeometryEdges.First().OwnerNode.Struts.IndexOf(strutA);
                var indB = edge.GeometryEdges.Last().OwnerNode.Struts.IndexOf(strutB);

                var id = nodeA.ID + 'S' + indA.ToString() + "_" + nodeB.ID + 'S' + indB.ToString();

                //update each struts id to a combination of both nodes and the strut index
                foreach (var strut in edge.GeometryEdges)
                {
                    strut.SetId(id);
                    strut.computeTrimmedLine(nodeA, nodeB);
                    strut.computeStrutGeometry();
                }
            }

            return(output);
        }
예제 #4
0
        void UpdateTarget()
        {
            var phr = new Vector3d(targetPitch, targetHeading, double.IsNaN(targetRoll) ? 0 : targetRoll);

            targetRotation  = GeometryExtensions.QuaternionFromPitchHeadingRoll(phr);
            targetRotation  = vessel.SurfaceReferenceFrame.Rotation * targetRotation;
            targetRotation  = ReferenceFrame.Rotation.Inverse() * targetRotation;
            targetDirection = targetRotation * Vector3.up;
        }
예제 #5
0
파일: Orbit.cs 프로젝트: v0lat1le/krpc
        public double RelativeInclination(Vessel target)
        {
            if (ReferenceEquals(target, null))
            {
                throw new ArgumentNullException(nameof(target));
            }
            var degrees = FinePrint.Utilities.OrbitUtilities.GetRelativeInclination(InternalOrbit, target.Orbit.InternalOrbit);

            return(GeometryExtensions.ToRadians(degrees));
        }
예제 #6
0
        public void GrahamScan(PdfPoint[] points, PdfPoint[] expected)
        {
            expected = expected.OrderBy(p => p.X).ThenBy(p => p.Y).ToArray();
            var convexHull = GeometryExtensions.GrahamScan(points).OrderBy(p => p.X).ThenBy(p => p.Y).ToArray();

            for (var i = 0; i < expected.Length; i++)
            {
                Assert.Equal(expected[i], convexHull[i], PointComparer);
            }
        }
예제 #7
0
파일: Orbit.cs 프로젝트: v0lat1le/krpc
        public double TrueAnomalyAtDN(Vessel target)
        {
            if (ReferenceEquals(target, null))
            {
                throw new ArgumentNullException(nameof(target));
            }
            var degrees = FinePrint.Utilities.OrbitUtilities.AngleOfDescendingNode(InternalOrbit, target.Orbit.InternalOrbit);

            return(GeometryExtensions.ToRadians(GeometryExtensions.ClampAngle180(degrees)));
        }
예제 #8
0
파일: Node.cs 프로젝트: 0000duck/TORO
        //debug
        private static void DebugFailure(List <Point> nodeCenters, List <Line> struts, Solid baseNode)
        {
            //prune all duplicate inputs from wireframe
            var prunedPoints = Point.PruneDuplicates(nodeCenters);
            var prunedLines  = GeometryExtensions.PruneDuplicates(struts);

            foreach (var centerPoint in prunedPoints)
            {
                //find adjacent struts for this node
                var intersectingLines = findAdjacentLines(centerPoint, prunedLines);
            }
        }
예제 #9
0
        public void MinimumAreaRectangle(PdfPoint[] points, PdfPoint[] expected)
        {
            expected = expected.OrderBy(p => p.X).ThenBy(p => p.Y).ToArray();

            var marRectangle = GeometryExtensions.MinimumAreaRectangle(points);
            var mar = new[] { marRectangle.BottomLeft, marRectangle.BottomRight, marRectangle.TopLeft, marRectangle.TopRight }.OrderBy(p => p.X).ThenBy(p => p.Y).ToArray();

            for (var i = 0; i < expected.Length; i++)
            {
                Assert.Equal(expected[i], mar[i], PointComparer);
            }
        }
예제 #10
0
 public double BedrockHeight (double latitude, double longitude)
 {
     if (InternalBody.pqsController == null)
         return 0;
     var latitudeRadians = GeometryExtensions.ToRadians (latitude);
     var longitudeRadians = GeometryExtensions.ToRadians (longitude);
     var cosLatitude = Math.Cos (latitudeRadians);
     var sinLatitude = Math.Sin (latitudeRadians);
     var cosLongitude = Math.Cos (longitudeRadians);
     var sinLongitude = Math.Sin (longitudeRadians);
     var position = new Vector3d (cosLatitude * cosLongitude, sinLatitude, cosLatitude * sinLongitude);
     return InternalBody.pqsController.GetSurfaceHeight (position) - InternalBody.pqsController.radius;
 }
예제 #11
0
        // NEED TO IMPLEMENT ROUNDING
        private static PdfRectangle GetBoundingBoxOther(Letter letter)
        {
            // not very useful, need axis aligned bbox anyway
            // -> rotate back? or normalise?
            var points = new[]
            {
                letter.StartBaseLine,
                letter.EndBaseLine,
                letter.GlyphRectangle.TopLeft,
                letter.GlyphRectangle.TopRight
            };

            // Candidates bounding boxes
            var obb  = GeometryExtensions.MinimumAreaRectangle(points);
            var obb1 = new PdfRectangle(obb.BottomLeft, obb.TopLeft, obb.BottomRight, obb.TopRight);
            var obb2 = new PdfRectangle(obb.BottomRight, obb.BottomLeft, obb.TopRight, obb.TopLeft);
            var obb3 = new PdfRectangle(obb.TopRight, obb.BottomRight, obb.TopLeft, obb.BottomLeft);

            // Find the orientation of the OBB, using the baseline angle
            // Assumes line order is correct

            var baseLineAngle = Distances.BoundAngle180(Distances.Angle(letter.GlyphRectangle.BottomLeft, letter.GlyphRectangle.BottomRight));

            double deltaAngle  = Math.Abs(Distances.BoundAngle180(obb.Rotation - baseLineAngle));
            double deltaAngle1 = Math.Abs(Distances.BoundAngle180(obb1.Rotation - baseLineAngle));

            if (deltaAngle1 < deltaAngle)
            {
                deltaAngle = deltaAngle1;
                obb        = obb1;
            }

            double deltaAngle2 = Math.Abs(Distances.BoundAngle180(obb2.Rotation - baseLineAngle));

            if (deltaAngle2 < deltaAngle)
            {
                deltaAngle = deltaAngle2;
                obb        = obb2;
            }

            double deltaAngle3 = Math.Abs(Distances.BoundAngle180(obb3.Rotation - baseLineAngle));

            if (deltaAngle3 < deltaAngle)
            {
                obb = obb3;
            }

            return(obb);
        }
예제 #12
0
        public void Issue458(PdfPoint[] points, PdfPoint[] expected)
        {
            /*
             * https://github.com/UglyToad/PdfPig/issues/458
             * An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in System.Linq.dll: 'Specified argument was out of the range of valid values.'
             *  at System.Linq.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument)
             *  at System.Linq.Enumerable.ElementAt[TSource](IEnumerable`1 source, Int32 index)
             */

            var result = GeometryExtensions.GrahamScan(points);

            // Data is noisy so we just check it does not throw an exception
            // and that key points are present (other points might be present,
            // e.g. 'not enough equal dupplicates' or 'not collinear enough' points)
            foreach (var point in expected)
            {
                Assert.Contains(point, result);
            }
        }
예제 #13
0
        /// <summary>
        /// Convert a vector of angles to a vector of angular velocities. This
        /// implements the function f(x) from the documentation.
        /// </summary>
        Vector3d AnglesToAngularVelocity(Vector3d angles, Vector3d torque, Vector3d moi)
        {
            var result = Vector3d.zero;

            for (int i = 0; i < 3; i++)
            {
                var theta            = GeometryExtensions.ToRadians(angles [i]);
                var maxAcceleration  = torque [i] / moi [i];
                var maxVelocity      = maxAcceleration * StoppingTime [i];
                var acceleration     = Math.Min(maxAcceleration, maxVelocity / DecelerationTime [i]);
                var velocity         = -Math.Sign(angles [i]) * Math.Min(maxVelocity, Math.Sqrt(2.0 * Math.Abs(theta) * acceleration));
                var attenuationAngle = GeometryExtensions.ToRadians(AttenuationAngle [i]);
                var attenuation      = 1.0 / (1.0 + Math.Exp(-((Math.Abs(theta) - attenuationAngle) * (6.0 / attenuationAngle))));
                if (double.IsNaN(attenuation))
                {
                    attenuation = 0;
                }
                result [i] = velocity * attenuation;
            }
            return(result);
        }
예제 #14
0
파일: AutoPilot.cs 프로젝트: pipi1226/krpc
        void DoAutoPiloting(PilotAddon.ControlInputs state)
        {
            SAS = false;
            var currentDirection = ReferenceFrame.DirectionFromWorldSpace(InternalVessel.ReferenceTransform.up);

            rotationRateController.ReferenceFrame = ReferenceFrame;
            var targetRotation = Vector3d.zero;

            if (targetDirection != Vector3d.zero)
            {
                targetRotation += (Vector3.Cross(targetDirection, currentDirection) * RotationSpeedMultiplier).ClampMagnitude(0f, MaxRotationSpeed);
            }
            if (!Double.IsNaN(TargetRoll))
            {
                float currentRoll = (float)ReferenceFrame.RotationFromWorldSpace(InternalVessel.ReferenceTransform.rotation).PitchHeadingRoll().z;
                var   rollError   = GeometryExtensions.NormAngle(TargetRoll - currentRoll) * (Math.PI / 180f);
                targetRotation += targetDirection * (rollError * RollSpeedMultiplier).Clamp(-MaxRollSpeed, MaxRollSpeed);
            }
            rotationRateController.Target = targetRotation;
            rotationRateController.Update(state);
        }
예제 #15
0
        //TODO: Add request for adopter by username

        public Adopter AssignLand(Adopter adopter)
        {
            connection.Open();

            AssignPlotOfLand assigner = new AssignPlotOfLand();

            SqlGeometry startingSquareKm = GeometryExtensions.FromWkt("POLYGON((12390034 -32564, 12390034 -32565, 12390035 -32565, 12390035 -32564, 12390034 -32564))", Constants.SRID_INT);

            assigner.SetStartingPoint(startingSquareKm.STPointN(1));
            {
                foreach (var geom in connection.Query <string>("select top 1 geom.STAsText() from " + Constants.LandTable))
                {
                    assigner.SetOuterBoundary(SqlGeometry.STGeomFromText(new SqlChars(geom), Constants.SRID_INT));
                }
            }
            connection.Close();

            var adopters = GetAllAdopters();

            //Check if transaction does not exist, else return null
            foreach (var a in adopters)
            {
                if (a.transaction_nr == adopter.transaction_nr)
                {
                    return(null);
                }
            }

            var assignedGeom = assigner.Assign(adopter.area, Constants.SRID_INT, adopters);

            if (assignedGeom == null)
            {
                return(null);
            }

            adopter.geom = new string(assignedGeom.STAsText().Value);

            return(adopter);
        }
예제 #16
0
파일: AutoPilot.cs 프로젝트: pipi1226/krpc
        public void TargetPitchAndHeading(float pitch, float heading)
        {
            var rotation = GeometryExtensions.QuaternionFromPitchHeadingRoll(new Vector3(pitch, heading, 0));

            targetDirection = rotation * Vector3.up;
        }
예제 #17
0
        public override void ProcessSplats(TerrainWrapper wrapper, LayerBase baseLayer, int stencilKey)
        {
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }
            if (!Network || Configuration == null)
            {
                return;
            }
            var config = Configuration.GetConfig <Config>();

            if (config == null)
            {
                Debug.LogError("Invalid configuration! Expected ConnectionTerrainHeightConfiguration");
                return;
            }

            var terrain    = wrapper.Terrain;
            var splatRes   = wrapper.Terrain.terrainData.alphamapResolution;
            var mainSpline = NodeConnection.GetSpline();
            var radius     = config.Radius;

            // Create bounds to encapsulate spline (axis aligned)
            var bounds = mainSpline.GetApproximateBounds();

            bounds.Expand(radius * 2 * Vector3.one);

            // Create object bounds
            var objectBounds = mainSpline.GetApproximateXZObjectBounds();

            objectBounds.Expand(radius * 2 * Vector3.one);
            objectBounds.Expand(Vector3.up * 10000);

            // Early cull
            var axisBounds    = objectBounds.ToAxisBounds();
            var terrainBounds = wrapper.Terrain.GetComponent <Collider>().bounds;

            if (!terrainBounds.Intersects(axisBounds))
            {
                return;
            }

            float planeGive = -(wrapper.Terrain.terrainData.size.x / wrapper.Terrain.terrainData.alphamapResolution) * SplatOffset;
            Plane startPlane, endPlane;

            GenerateSplinePlanes(planeGive, mainSpline, out startPlane, out endPlane);

            // Get matrix space min/max
            var matrixMin = terrain.WorldToSplatCoord(bounds.min, TerrainX.RoundType.Floor);
            var matrixMax = terrain.WorldToSplatCoord(bounds.max, TerrainX.RoundType.Ceil);

            matrixMin = new Common.Coord(Mathf.Clamp(matrixMin.x, 0, terrain.terrainData.alphamapResolution), Mathf.Clamp(matrixMin.z, 0, terrain.terrainData.alphamapResolution));
            matrixMax = new Common.Coord(Mathf.Clamp(matrixMax.x, 0, terrain.terrainData.alphamapResolution), Mathf.Clamp(matrixMax.z, 0, terrain.terrainData.alphamapResolution));

            var floatArraySize = new Common.Coord(matrixMax.x - matrixMin.x, matrixMax.z - matrixMin.z);

            // Get all the existing compound splats
            var currentPrototypes = wrapper.GetCompoundSplatPrototypes(layer, true);
            var baseData          = layer.GetSplatMaps(matrixMin.x, matrixMin.z, floatArraySize.x, floatArraySize.z, splatRes);

            stencilKey = GetStencilKey();
            Serializable2DFloatArray thisPatchStencil = new Serializable2DFloatArray(floatArraySize.x,
                                                                                     floatArraySize.z);

            foreach (var splatConfiguration in config.SplatConfigurations)
            {
                var splatPrototypeWrapper = splatConfiguration.SplatPrototype;
                Serializable2DByteArray baseLayerSplat;
                if (!baseData.TryGetValue(splatPrototypeWrapper, out baseLayerSplat))
                {
                    baseLayerSplat = new Serializable2DByteArray(floatArraySize.x, floatArraySize.z);
                    baseData[splatPrototypeWrapper] = baseLayerSplat;
                }

                for (var dz = 0; dz < floatArraySize.z; ++dz)
                {
                    for (var dx = 0; dx < floatArraySize.x; ++dx)
                    {
                        var coordX   = matrixMin.x + dx;
                        var coordZ   = matrixMin.z + dz;
                        var worldPos = terrain.SplatCoordToWorldPos(new Common.Coord(coordX, coordZ));
                        worldPos = new Vector3(worldPos.x, objectBounds.center.y, worldPos.z);

                        if (terrain.ContainsPointXZ(worldPos) &&
                            objectBounds.Contains(worldPos) &&
                            GeometryExtensions.BetweenPlanes(worldPos, startPlane, endPlane))
                        {
                            var uniformT                   = mainSpline.GetClosestUniformTimeOnSplineXZ(worldPos.xz()); // Expensive!
                            var closestOnSpline            = mainSpline.GetUniformPointOnSpline(uniformT);
                            var normalizedFlatDistToSpline = (worldPos - closestOnSpline).xz().magnitude / (config.Radius);
                            if (normalizedFlatDistToSpline != Mathf.Clamp01(normalizedFlatDistToSpline))
                            {
                                continue;
                            }
                            var maskValue       = config.SplatFalloff.Evaluate(normalizedFlatDistToSpline);
                            var writeFloatValue = splatConfiguration.SplatStrength * maskValue;
                            var writeValue      = (byte)Mathf.RoundToInt(Mathf.Clamp(writeFloatValue * 255f, 0, 255));
                            var mainRead        = baseLayerSplat[dx, dz];
                            var newVal          = (byte)Mathf.Clamp(Mathf.Max(writeValue, mainRead), 0, 255);
                            var delta           = newVal - mainRead;

                            if (delta < 1 / 255f)
                            {
                                continue;
                            }

                            foreach (var currentPrototype in currentPrototypes)
                            {
                                if (!baseData.ContainsKey(currentPrototype))
                                {
                                    continue;
                                }
                                if (currentPrototype == splatPrototypeWrapper)
                                {
                                    continue;
                                }
                                var otherSplatFloatValue    = baseData[currentPrototype][dx, dz] / 255f;
                                var otherSplatFloatWriteVal = (otherSplatFloatValue * (1 - (delta / 255f)));
                                var write = (byte)Mathf.Clamp(Mathf.RoundToInt(otherSplatFloatWriteVal * 255), 0, 255);
                                baseData[currentPrototype][dx, dz] = write;
                            }
                            //DebugHelper.DrawPoint(worldPos, 1, Color.red, 10);
                            baseLayerSplat[dx, dz]        = newVal;
                            layer.Stencil[coordX, coordZ] = MiscUtilities.CompressStencil(stencilKey, 1);
                            thisPatchStencil[dx, dz]      = 1;
                        }
                        else
                        {
                            thisPatchStencil[dx, dz] = 0;
                        }
                    }
                }
            }

            foreach (var existingSplatPrototype in baseData)
            {
                var splat = existingSplatPrototype.Key;
                var data  = existingSplatPrototype.Value;
                layer.SetSplatmap(splat, matrixMin.x, matrixMin.z, data, wrapper.Terrain.terrainData.alphamapResolution, thisPatchStencil);
            }
        }
        private void Spawn()
        {
            var randomPointInsideBox = GeometryExtensions.RandomPointInBox(_spawnAreaBounds.center, _spawnAreaBounds.size);

            FireSpawnEvent(randomPointInsideBox);
        }
        public override void ProcessVegetationStudio(TerrainWrapper wrapper, LayerBase baseLayer, int stencilKey)
        {
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }
            if (!Network)
            {
                Debug.LogError("Unable to find network! " + name, this);
                return;
            }
            if (Configuration == null)
            {
                return;
            }
            var config = Configuration.GetConfig <Config>();

            if (config == null)
            {
                Debug.LogError("Invalid configuration! Expected ConnectionTerrainHeightConfiguration");
                return;
            }

            var mainSpline = NodeConnection.GetSpline();
            var radius     = config.InstanceRemoveDistance;

            // Create bounds to encapsulate spline (axis aligned)
            var bounds = mainSpline.GetApproximateBounds();

            bounds.Expand(radius * 2 * Vector3.one);

            // Create object bounds
            var objectBounds = mainSpline.GetApproximateXZObjectBounds();

            objectBounds.Expand(radius * 2 * Vector3.one);
            objectBounds.Expand(Vector3.up * 10000);

            var flatCullbounds = objectBounds.ToAxisBounds();
            //DebugHelper.DrawCube(flatCullbounds.center, flatCullbounds.extents, Quaternion.identity, Color.yellow, 20);
            //DebugHelper.DrawCube(objectBounds.center, objectBounds.extents, objectBounds.Rotation, Color.cyan, 20);

            Plane startPlane, endPlane;

            GenerateSplinePlanes(0, mainSpline, out startPlane, out endPlane);

            var vsData = wrapper.GetCompoundVegetationStudioData(layer, true, flatCullbounds);

            for (int i = vsData.Count - 1; i >= 0; i--)
            {
                var vsInstance = vsData[i];
                if (config.IgnoredPrototypes.Contains(vsInstance.VSID))
                {
                    continue;
                }
                var wPos = wrapper.Terrain.TreeToWorldPos(vsInstance.Position);
                if (!objectBounds.Contains(wPos) || !GeometryExtensions.BetweenPlanes(wPos, startPlane, endPlane))
                {
                    continue;
                }

                var ut        = mainSpline.GetClosestUniformTimeOnSplineXZ(wPos.xz());
                var splinePos = mainSpline.GetUniformPointOnSpline(ut);
                var d         = splinePos.xz() - wPos.xz();

                if (d.sqrMagnitude < config.InstanceRemoveDistance * config.InstanceRemoveDistance && !layer.VSRemovals.Contains(vsInstance.Guid))
                {
                    layer.VSRemovals.Add(vsInstance.Guid);
                    //DebugHelper.DrawPoint(wPos, .5f, Color.red, 20);
                }
            }
        }
예제 #20
0
        public override void ProcessHeights(TerrainWrapper wrapper, LayerBase baseLayer, int stencilKey)
        {
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }
            if (!Network || Configuration == null)
            {
                return;
            }
            var config = Configuration.GetConfig <Config>();

            if (config == null)
            {
                Debug.LogError("Invalid configuration! Expected ConnectionTerrainHeightConfiguration");
                return;
            }
            var terrain     = wrapper.Terrain;
            var terrainPos  = wrapper.Terrain.GetPosition();
            var terrainSize = wrapper.Terrain.terrainData.size;
            var heightRes   = terrain.terrainData.heightmapResolution;

            var mainSpline   = NodeConnection.GetSpline();
            var radius       = config.Radius;
            var falloffCurve = config.Falloff;
            var heightCurve  = config.Height;

            // Create bounds to encapsulate spline (axis aligned)
            var bounds = mainSpline.GetApproximateBounds();

            bounds.Expand(radius * 2 * Vector3.one);

            // Create object bounds
            var objectBounds = mainSpline.GetApproximateXZObjectBounds();

            objectBounds.Expand(radius * 2 * Vector3.one);
            objectBounds.Expand(Vector3.up * 10000);

            // Early cull
            var axisBounds    = objectBounds.ToAxisBounds();
            var terrainBounds = terrain.GetComponent <Collider>().bounds;

            terrainBounds.Expand(Vector3.up * 10000);
            if (!terrainBounds.Intersects(axisBounds))
            {
                return;
            }

            // Get matrix space min/max
            var matrixMin = terrain.WorldToHeightmapCoord(bounds.min, TerrainX.RoundType.Floor) - Coord.One;

            matrixMin = matrixMin.Clamp(0, heightRes);
            var matrixMax = terrain.WorldToHeightmapCoord(bounds.max, TerrainX.RoundType.Ceil) + Coord.One;

            matrixMax = matrixMax.Clamp(0, heightRes);

            var xDelta = matrixMax.x - matrixMin.x;
            var zDelta = matrixMax.z - matrixMin.z;

            var floatArraySize = new Common.Coord(
                Mathf.Min(xDelta, terrain.terrainData.heightmapResolution - matrixMin.x),
                Mathf.Min(zDelta, terrain.terrainData.heightmapResolution - matrixMin.z));

            float planeGive = (wrapper.Terrain.terrainData.size.x / wrapper.Terrain.terrainData.heightmapResolution) * 0;
            Plane startPlane, endPlane;

            GenerateSplinePlanes(planeGive, mainSpline, out startPlane, out endPlane);

            var layerHeights = layer.GetHeights(matrixMin.x, matrixMin.z, floatArraySize.x, floatArraySize.z, heightRes) ??
                               new Serializable2DFloatArray(floatArraySize.x, floatArraySize.z);

            stencilKey = GetStencilKey();
            if (layer.Stencil == null || layer.Stencil.Width != heightRes || layer.Stencil.Height != heightRes)
            {
                layer.Stencil = new Stencil(heightRes, heightRes);
            }

            for (var dz = 0; dz < floatArraySize.z; ++dz)
            {
                for (var dx = 0; dx < floatArraySize.x; ++dx)
                {
                    var coordX = matrixMin.x + dx;
                    var coordZ = matrixMin.z + dz;

                    var worldPos = terrain.HeightmapCoordToWorldPos(new Common.Coord(coordX, coordZ));
                    worldPos = new Vector3(worldPos.x, objectBounds.center.y, worldPos.z);
                    if (!terrain.ContainsPointXZ(worldPos) ||
                        !objectBounds.Contains(worldPos) ||
                        !GeometryExtensions.BetweenPlanes(worldPos, startPlane, endPlane))
                    {
                        // Cull if we're outside of the approx bounds
                        continue;
                    }

                    var uniformT                   = mainSpline.GetClosestUniformTimeOnSplineXZ(worldPos.xz()); // Expensive!
                    var closestOnSpline            = mainSpline.GetUniformPointOnSpline(uniformT);
                    var normalizedFlatDistToSpline = (worldPos - closestOnSpline).xz().magnitude / (radius);
                    if (normalizedFlatDistToSpline >= 1)
                    {
                        continue;
                    }

                    var maskValue   = Mathf.Clamp01(falloffCurve.Evaluate(normalizedFlatDistToSpline));
                    var heightDelta = heightCurve.Evaluate(normalizedFlatDistToSpline);

                    float existingStencilStrength;
                    int   existingStencilKey;
                    MiscUtilities.DecompressStencil(layer.Stencil[coordX, coordZ], out existingStencilKey, out existingStencilStrength);

                    if (existingStencilKey != stencilKey &&
                        existingStencilKey > stencilKey &&
                        !(existingStencilStrength < maskValue && maskValue > 0))
                    {
                        continue;
                    }

                    // Refine our worldposition to be on the same XZ plane as the spline point
                    worldPos = new Vector3(worldPos.x, closestOnSpline.y, worldPos.z);

                    // Find the point on the spline closest to this given point
                    var naturalT = mainSpline.UniformToNaturalTime(uniformT);

                    // Get the upvec from the natural time
                    var up = mainSpline.GetUpVector(naturalT).normalized;

                    // Create a plane and cast against it
                    var plane = new Plane(up, closestOnSpline);

                    float dist    = 0;
                    var   castRay = new Ray(worldPos, Vector3.down);
                    plane.Raycast(castRay, out dist);
                    var castPoint     = castRay.GetPoint(dist);
                    var heightAtPoint = (castPoint.y + heightDelta);

                    heightAtPoint -= terrainPos.y;
                    heightAtPoint /= terrainSize.y;
                    heightAtPoint  = MiscUtilities.FloorToUshort(heightAtPoint);

                    var existingHeight = layerHeights[dx, dz];
                    var newHeight      = Mathf.Lerp(existingHeight, heightAtPoint, Mathf.Clamp01(maskValue));

                    layerHeights[dx, dz] = newHeight;

                    var key = maskValue > existingStencilStrength ? stencilKey : existingStencilKey;
                    var newRawStencilValue = MiscUtilities.CompressStencil(key, /*stencilKey == existingStencilKey ?*/ Mathf.Max(maskValue, existingStencilStrength) /* : maskValue + existingStencilStrength*/);
                    //newRawStencilValue = MiscUtilities.CompressStencil(key, 1);

                    layer.Stencil[coordX, coordZ] = newRawStencilValue;
                }
            }

            layer.SetHeights(matrixMin.x, matrixMin.z,
                             layerHeights, wrapper.Terrain.terrainData.heightmapResolution);
        }
예제 #21
0
        public static Mesh[] MeshesForWall(this Wall wall)
        {
            sortTo = wall.Start.Point;

            float   angle      = GeometryExtensions.GetAngleRadian(wall.Start.Point.ToVector2(), wall.End.Point.ToVector2());
            Vector3 frontStart = wall.Start.Point;
            Vector3 frontEnd   = wall.End.Point;

            Vector2 outerStart = GeometryExtensions.Polar2Cartesian(wall.Start.Point.ToVector2(), angle - Mathf.PI / 2, wall.Thickness);
            Vector2 outerEnd   = GeometryExtensions.Polar2Cartesian(wall.End.Point.ToVector2(), angle - Mathf.PI / 2, wall.Thickness);
            Vector3 backStart  = new Vector3(outerStart.x, wall.Start.Point.y, outerStart.y);
            Vector3 backEnd    = new Vector3(outerEnd.x, wall.End.Point.y, outerEnd.y);

            if (wall.Openings.Count == 0)
            {
                return(new Mesh[] { WallMesh.GenerateWallMesh(frontStart, frontEnd, backStart, backEnd, wall.Height) });
            }
            else
            {
                int      openingsLength = wall.Openings.Count;
                string[] tagsForMeshes  = new string[1 + openingsLength * 3];

                Mesh[] meshes   = new Mesh[1 + openingsLength * 3];
                var    openings = wall.Openings.ToArray();
                Array.Sort(openings, new OpeningComparer());

                //miért az elsõ opening méreteit vesszük alapul és nem ciklusban mindig a sajátját

                float length = Vector3.Distance(openings[0].Start.Point, openings[0].End.Point);
                float ll     = Mathf.Sqrt(wall.Thickness * wall.Thickness + length * length);

                Vector2 openingStart = new Vector2(openings[0].Start.Point.x, openings[0].Start.Point.z);
                Vector2 openingEnd   = new Vector2(openings[0].End.Point.x, openings[0].End.Point.z);

                Vector2 outerOpeningStart = GeometryExtensions.GetPointFrom2Points2Distances(openingStart, wall.Thickness, openingEnd, ll, false);
                Vector2 outerOpeningEnd   = GeometryExtensions.GetPointFrom2Points2Distances(openingEnd, wall.Thickness, openingStart, ll, false);

                meshes[0] = WallMesh.GenerateWallMesh(
                    frontStart,
                    new Vector3(openingStart.x, frontStart.y, openingStart.y),
                    backStart,
                    new Vector3(outerOpeningStart.x, frontStart.y, outerOpeningStart.y),
                    wall.Height
                    );
                tagsForMeshes[0] = "fullWallSegment";

                for (int i = 0; i < openingsLength; i++)
                {
                    length = Vector3.Distance(openings[i].Start.Point, openings[i].End.Point);
                    ll     = Mathf.Sqrt(wall.Thickness * wall.Thickness + length * length);

                    openingStart = new Vector2(openings[i].Start.Point.x, openings[i].Start.Point.z);
                    openingEnd   = new Vector2(openings[i].End.Point.x, openings[i].End.Point.z);

                    outerOpeningStart = GeometryExtensions.GetPointFrom2Points2Distances(openingStart, wall.Thickness, openingEnd, ll, false);
                    outerOpeningEnd   = GeometryExtensions.GetPointFrom2Points2Distances(openingEnd, wall.Thickness, openingStart, ll, true);

                    //Debug.Log(i + ". opening start:  " + openings[i].Start.Position.x + ", " + openings[i].Start.Position.y + ", " + openings[i].Start.Position.z);
                    meshes[1 + i * 3] = WallMesh.GenerateWallMesh(
                        new Vector3(openingStart.x, frontStart.y, openingStart.y),
                        new Vector3(openingEnd.x, frontStart.y, openingEnd.y),
                        new Vector3(outerOpeningStart.x, frontStart.y, outerOpeningStart.y),
                        new Vector3(outerOpeningEnd.x, frontStart.y, outerOpeningEnd.y),
                        openings[i].Sill
                        );
                    tagsForMeshes[1 + i * 3] = "partialWallSegment";

                    meshes[2 + i * 3] = WallMesh.GenerateWallMesh(
                        new Vector3(openingStart.x, frontStart.y + openings[i].Height + openings[i].Sill, openingStart.y),
                        new Vector3(openingEnd.x, frontStart.y + openings[i].Height + openings[i].Sill, openingEnd.y),
                        new Vector3(outerOpeningStart.x, frontStart.y + openings[i].Height + openings[i].Sill, outerOpeningStart.y),
                        new Vector3(outerOpeningEnd.x, frontStart.y + openings[i].Height + openings[i].Sill, outerOpeningEnd.y),
                        wall.Height - (openings[i].Sill + openings[i].Height)
                        );
                    tagsForMeshes[2 + i * 3] = "partialWallSegment";

                    if (i < openingsLength - 1)
                    {
                        float lengthn = Vector3.Distance(openings[i + 1].Start.Point, openings[i + 1].End.Point);
                        float lln     = Mathf.Sqrt(wall.Thickness * wall.Thickness + lengthn * lengthn);

                        Vector2 openingStartn = new Vector2(openings[i + 1].Start.Point.x, openings[i + 1].Start.Point.z);
                        Vector2 openingEndn   = new Vector2(openings[i + 1].End.Point.x, openings[i + 1].End.Point.z);

                        Vector2 outerOpeningStartn = GeometryExtensions.GetPointFrom2Points2Distances(openingStartn, wall.Thickness, openingEndn, lln, true);

                        meshes[3 + i * 3] = WallMesh.GenerateWallMesh(
                            new Vector3(openingEnd.x, frontStart.y, openingEnd.y),
                            new Vector3(openingStartn.x, frontStart.y, openingStartn.y),
                            new Vector3(outerOpeningEnd.x, frontStart.y, outerOpeningEnd.y),
                            new Vector3(outerOpeningStartn.x, frontStart.y, outerOpeningStartn.y),
                            wall.Height
                            );
                        tagsForMeshes[3 + i * 3] = "fullWallSegment";
                    }
                }

                float lengthlast = Vector3.Distance(openings[openingsLength - 1].Start.Point, openings[openingsLength - 1].End.Point);
                float lllast     = Mathf.Sqrt(wall.Thickness * wall.Thickness + lengthlast * lengthlast);

                Vector2 openingStartLast = new Vector2(openings[openingsLength - 1].Start.Point.x, openings[openingsLength - 1].Start.Point.z);
                Vector2 openingEndLast   = new Vector2(openings[openingsLength - 1].End.Point.x, openings[openingsLength - 1].End.Point.z);

                Vector2 outerOpeningEndLast = GeometryExtensions.GetPointFrom2Points2Distances(openingEndLast, wall.Thickness, openingStartLast, lllast, true);

                meshes[openingsLength * 3] = WallMesh.GenerateWallMesh(
                    new Vector3(openingEndLast.x, frontStart.y, openingEndLast.y),
                    frontEnd,
                    new Vector3(outerOpeningEndLast.x, frontStart.y, outerOpeningEndLast.y),
                    backEnd,
                    wall.Height
                    );
                tagsForMeshes[openingsLength * 3] = "fullWallSegment";
                return(meshes);
            }
        }
예제 #22
0
        /// <summary>
        /// Compute target angular velocity in pitch,roll,yaw axes
        /// </summary>
        Vector3 ComputeTargetAngularVelocity(Vector3d torque, Vector3d moi)
        {
            var internalVessel     = vessel.InternalVessel;
            var currentRotation    = ReferenceFrame.RotationFromWorldSpace(internalVessel.ReferenceTransform.rotation);
            var tmpTargetRotation  = TargetRotation;
            var tmpTargetDirection = TargetDirection;

            var phr     = DirectionBias;
            var right   = currentRotation * Vector3d.right;
            var forward = currentRotation * Vector3d.forward;
            var up      = currentRotation * Vector3d.up;
            var q       = QuaternionD.AngleAxis(phr.x, right);

            q = q * QuaternionD.AngleAxis(phr.y, forward);
            q = q * QuaternionD.AngleAxis(phr.z, up);
            QuaternionD directionBiasQuaternion = q;

            currentRotation = directionBiasQuaternion * currentRotation;
            var currentDirection = currentRotation * Vector3d.up;

            if (PlaneMode)
            {
                var tmpdirection = internalVessel.GetSrfVelocity();
                if (tmpdirection.magnitude <= 0)
                {
                    tmpdirection = ReferenceFrame.Rotation * currentDirection;
                }
                tmpdirection = vessel.SurfaceReferenceFrame.Rotation.Inverse() * tmpdirection;
                var sq = GeometryExtensions.ToQuaternion(tmpdirection.normalized, TargetRoll);
                sq      = ReferenceFrame.Rotation.Inverse() * vessel.SurfaceReferenceFrame.Rotation * sq;
                right   = sq * Vector3d.right;
                forward = sq * Vector3d.forward;
                var tmpq = QuaternionD.AngleAxis(-(float)TargetPitch, right);
                tmpTargetRotation = tmpq * sq;
                tmpq = QuaternionD.AngleAxis(-(float)TargetHeading, forward);
                tmpTargetRotation  = tmpq * tmpTargetRotation;
                tmpTargetDirection = tmpTargetRotation * Vector3d.up;
            }


            QuaternionD rotation = Quaternion.FromToRotation(currentDirection, tmpTargetDirection);
            // Compute angles for the rotation in pitch (x), roll (y), yaw (z) axes
            float   angleFloat;
            Vector3 axisFloat;

            // FIXME: QuaternionD.ToAngleAxis method not available at runtime
            ((Quaternion)rotation).ToAngleAxis(out angleFloat, out axisFloat);
            double   angle  = GeometryExtensions.ClampAngle180(angleFloat);
            Vector3d axis   = axisFloat;
            var      angles = new Vector3d(0, 0, 0);

            angles = angles + axis * angle;
            if (!double.IsNaN(TargetRoll))
            {
                // Roll angle set => use rotation from currentRotation -> targetRotation
                rotation = rotation.Inverse() * tmpTargetRotation;
                rotation = rotation * currentRotation.Inverse();
                ((Quaternion)rotation).ToAngleAxis(out angleFloat, out axisFloat);
                if (!float.IsInfinity(axisFloat.magnitude))
                {
                    angle  = GeometryExtensions.ClampAngle180(angleFloat);
                    axis   = axisFloat;
                    angles = angles + axis * angle;
                }
            }
            // else Roll angle not set => use rotation from currentDirection -> targetDirection
            // FIXME: QuaternionD.FromToRotation method not available at runtime
            angles = directionBiasQuaternion * angles;
            angles = vessel.ReferenceFrame.DirectionFromWorldSpace(ReferenceFrame.DirectionToWorldSpace(angles));
            angles = transitionMat.MultiplyVector(angles);
            return(AnglesToAngularVelocity(angles, torque, moi));
        }