/// <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)); }
void UpdateTarget() { var phr = new Vector3d(targetPitch, targetHeading, double.IsNaN(targetRoll) ? 0 : targetRoll); targetRotation = GeometryExtensions.QuaternionFromPitchHeadingRoll(phr); targetDirection = targetRotation * Vector3.up; }
/// <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); }
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; }
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)); }
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); } }
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))); }
//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); } }
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); } }
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; }
// 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); }
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); } }
/// <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); }
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); }
//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); }
public void TargetPitchAndHeading(float pitch, float heading) { var rotation = GeometryExtensions.QuaternionFromPitchHeadingRoll(new Vector3(pitch, heading, 0)); targetDirection = rotation * Vector3.up; }
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); } } }
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); }
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); } }
/// <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)); }