Пример #1
0
		/// <summary>
		/// Initializes a new instance of the <see cref= "T:WorldWind.BoundingSphere"/> class
		/// from a set of lat/lon values (degrees)
		/// </summary>
		public BoundingSphere( float south, float north, float west, float east, float radius1, float radius2)
		{
			// Compute the points in world coordinates
			const int CornerCount = 8;
			Vector3[] corners = new Vector3[CornerCount];

			float scale = radius2 / radius1;
			corners[0] = MathEngine.SphericalToCartesian(south, west, radius1);
			corners[1] = Vector3.Scale(corners[0], scale);
			corners[2] = MathEngine.SphericalToCartesian(south, east, radius1);
			corners[3] = Vector3.Scale(corners[2], scale);
			corners[4] = MathEngine.SphericalToCartesian(north, west, radius1);
			corners[5] = Vector3.Scale(corners[4], scale);
			corners[6] = MathEngine.SphericalToCartesian(north, east, radius1);
			corners[7] = Vector3.Scale(corners[6], scale);

			//Find the center.  In this case, we'll simply average the coordinates. 
			foreach(Vector3 v in corners)
				Center += v;
			Center.Scale(1/CornerCount);

			//Loop through the coordinates and find the maximum distance from the center.  This is the radius.		
			foreach(Vector3 v in corners)
			{
				float distSq = Vector3.Subtract(v,Center).LengthSq();
				if (distSq > Radius)
					Radius = distSq;
			}

			Radius = (float)Math.Sqrt(Radius);			
		}		
Пример #2
0
		public Vector3 CalculateCenter()
		{
			Vector3 res = new Vector3();
			foreach(Vector3 corner in corners)
			{
				res += corner;
			}

			res.Scale(1.0f / corners.Length);
			return res;
		}
Пример #3
0
        /// <summary>
        /// Return stats about the creature being edited, for display on the VDU
        /// </summary>
        public void Stats(out float radius, out float mass, out float bouyancy, out float resistance, 
            out Vector3 balance, out string name)
        {
            // Ensure the data is accurate after recent edits
            Refresh();															// Make sure that the trees and lists are up-to-date
            CalculateCG();														// Temporarily recalculate the CofG cell
            RecursiveUpdateFrames(rootCell);									// calculate cell positions
            ComputeBoundingSphere();											// update radius and centre

            radius = this.AbsSphere.Radius;										// org radius
            name = genome.Name;													// current name

            mass = 0;
            bouyancy = 0;
            resistance = 0;
            foreach (Cell c in partList)										// sum physical properties
            {
                mass += c.Physiology.Mass * scale;
                bouyancy += c.Physiology.Buoyancy * scale;
                resistance += c.Physiology.Resistance * scale;
            }

            balance = CGCell.AbsSphere.Centre - AbsSphere.Centre;				// distance of CG from geometric centre (on each WORLD axis)
            balance.Scale(1.0f / radius);										// as a fraction of creature's size

            // Clean up
            CGCell = rootCell;													// Set the CofG back to the root cell
        }
Пример #4
0
        /// <summary>
        /// Virtual method implemented by all Renderable objects.
        /// The given cell is in collision with our bounding sphere. Test to see if it actually collides with
        /// one of my parts. If so, return a Vector describing the force we exert on the offending cell
        /// (since we're an organism we'll receive a share of the force too, unlike scenery)
        /// </summary>
        /// <param name="cell">The cell that may have collided with us</param>
        /// <returns> Any force vector acting on the cell </returns>
        public override Vector3 CollisionTest(Cell otherCell)
        {
            Vector3 bounce = new Vector3();

            // Run through our own cells looking for a collision
            foreach (Cell ourCell in partList)
            {
                // Test more deeply by looking at the cell spheres then the
                // bounding boxes of each mesh in the cells
                if (Cell.CollisionTest(ourCell, otherCell) == true)
                {
                    // The bounce direction is a vector in the direction of our centre towards theirs
                    // (in other words, the two cells are treated as spheres and therefore bounce back away from
                    // their centres).
                    bounce = otherCell.AbsSphere.Centre - ourCell.AbsSphere.Centre;
                    bounce.Normalize();

                    // The length of the force vector is proportional to the objects' closing speed
                    Vector3 ourMvt = ourCell.Location - ourCell.OldLocation;			// how much we will move next frame
                    Vector3 hisMvt = otherCell.Location - otherCell.OldLocation;		// how much he will move next frame
                    float speed = Vector3.Length(ourMvt + hisMvt);					// combine to get closing movement
                    bounce.Scale(2.0f + speed * 10.0f);											// arbitrary scaling factor

                    // Also, a force acts on OUR cell, in the reverse direction.
                    // Distribute the two forces inversely proportional to mass
                    Vector3 ourBounce = -bounce;										// effect on us is the inverse of our effect on him
                    float mass = otherCell.Owner.TotalMass;								// get the masses of the two ORGANISMS (not cells)
                    float ourMass = ourCell.Owner.TotalMass;
                    bounce.Scale(ourMass / (ourMass + mass));							// distribute the forces proportionately
                    ourBounce.Scale(mass / (ourMass + mass));
                    ourCell.propulsionForce += ourBounce;								// apply our share as propulsion

                    // Once we've found a collision, we needn't look at any more of our cells
                    return bounce;
                }
            }

            return bounce;
        }
Пример #5
0
        /// <summary>
        /// Check to see if we're touching the water surface, and respond appropriately
        /// </summary>
        private void CheckForSurfaceCollision()
        {
            // We're quite safe if bounding sphere is below water level
            if ((AbsSphere.Centre.Y + AbsSphere.Radius) < Water.WATERLEVEL)
                return;

            // Now check each cell in turn
            foreach (Cell cell in partList)
            {
                // If the dist from centre to surface is smaller than the radius our spheres are in contact
                float aboveSurface = cell.AbsSphere.Centre.Y + cell.AbsSphere.Radius - Water.WATERLEVEL;
                if (aboveSurface >= 0)
                {
                    // TODO: either look deeper at the mesh OBBs, or maybe take account of the density of the object
                    // to derive an approximate flotation height

                    // Our bounce vector is simply a down vector, proportional to our height above surface
                    Vector3 bounce = new Vector3(0,-1,0);
                    bounce.Scale(aboveSurface
                        * 0.5f);								// arbitrary scaling factor

                    // Add the bounce as a force acting on our cell
                    cell.propulsionForce += bounce;
                    //Engine.DebugHUD.WriteLine("Surface!");
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Find the intersection of a ray with the terrain.
        /// </summary>
        /// <param name="p1">Cartesian coordinate of starting point</param>
        /// <param name="p2">Cartesian coordinate of end point</param>
        /// <param name="samplingPrecision">Sample length in meter</param>
        /// <param name="resultPrecision">Final sampling length in meter</param>
        /// <param name="latitude">Out : intersection latitude</param>
        /// <param name="longitude">Out : intersection longitude</param>
        /// <param name="world">Current world</param>
        /// <returns>NaN if no intersection found</returns>
        internal static void RayIntersectionWithTerrain(
            Point3d p1,
            Point3d p2,
            double samplingPrecision,
            double resultPrecision,
            out Angle latitude,
            out Angle longitude,
            World world)
        {
            // Check for sphere intersection first
            // Note : checks for world radius + highest possible elevation
            float vertEx = World.Settings.VerticalExaggeration;
            double maxRadius = world.EquatorialRadius + 9000 * vertEx; // Max altitude for earth - should be dependant on world
            double a = (p2.X - p1.X) * (p2.X - p1.X) + (p2.Y - p1.Y) * (p2.Y - p1.Y) + (p2.Z - p1.Z) * (p2.Z - p1.Z);
            double b = 2.0 * ((p2.X - p1.X) * (p1.X) + (p2.Y - p1.Y) * (p1.Y) + (p2.Z - p1.Z) * (p1.Z));
            double c = p1.X * p1.X + p1.Y * p1.Y + p1.Z * p1.Z - maxRadius * maxRadius;
            double discriminant = b * b - 4 * a * c;
            if (discriminant <= 0)
            {
                // No intersection with sphere
                latitude = Angle.NaN;
                longitude = Angle.NaN;
                return;
            }
            // Factor to intersection
            // Note : if t1 > 0 intersection is forward, < 0 is behind us
            double t1 = ((-1.0) * b - Math.Sqrt(discriminant)) / (2 * a);
            Point3d p1LatLon = MathEngine.CartesianToSpherical(p1.X, p1.Y, p1.Z);
            if (t1 > 0 && p1LatLon.X > maxRadius)
            {
                // Looking from above max altitude : move p1 forward to intersection with max alt sphere
                p1 = new Point3d(p1.X + t1 * (p2.X - p1.X), p1.Y + t1 * (p2.Y - p1.Y), p1.Z + t1 * (p2.Z - p1.Z));
            }

            // Ray sample
            Vector3 sample = new Vector3((float)(p2.X - p1.X), (float)(p2.Y - p1.Y), (float)(p2.Z - p1.Z));
            double maxLength = sample.Length();     // Max length for ray tracing
            double sampleLength = samplingPrecision;// Sampling steps length
            sample.Normalize();
            sample.Scale((float)sampleLength);

            // Casting
            Point3d ray = p1;
            double rayLength = 0;
            while (rayLength < maxLength)
            {
                Point3d rayLatLon = MathEngine.CartesianToSpherical(ray.X, ray.Y, ray.Z);
                // Altitude at ray position
                double rayAlt = rayLatLon.X - world.EquatorialRadius;
                // Altitude at terrain position - from cached data (no download)
                double terrainAlt = world.TerrainAccessor.GetCachedElevationAt(MathEngine.RadiansToDegrees(rayLatLon.Y), MathEngine.RadiansToDegrees(rayLatLon.Z)); // best loaded data
                if (double.IsNaN(terrainAlt)) terrainAlt = 0;
                terrainAlt *= vertEx;
                if (terrainAlt > rayAlt)
                {
                    // Intersection found
                    if (sampleLength > resultPrecision)
                    {
                        // Go back one step
                        ray.X -= sample.X;
                        ray.Y -= sample.Y;
                        ray.Z -= sample.Z;
                        rayLength -= sampleLength;
                        // and refine sampling
                        sampleLength /= 10;
                        sample.Normalize();
                        sample.Scale((float)sampleLength);
                    }
                    else
                    {
                        // return location
                        latitude = Angle.FromRadians(rayLatLon.Y);
                        longitude = Angle.FromRadians(rayLatLon.Z);
                        return;
                    }
                }
                // Move forward
                ray.X += sample.X;
                ray.Y += sample.Y;
                ray.Z += sample.Z;
                rayLength += sampleLength;
            }
            // No intersection with terrain found
            latitude = Angle.NaN;
            longitude = Angle.NaN;
        }
Пример #7
0
        /// <summary>
        /// NOT IMPLEMENTED
        /// </summary>
        /// <param name="normal"></param>
        /// <param name="tangent"></param>
        /// <exception cref="NotImplementedException"></exception>
        public static void OrthoNormalize(ref Vector3 normal, ref Vector3 tangent)
        {
            normal.Normalize();
            var proj = new Vector3();
            proj.Scale(normal);

            throw new NotImplementedException();
        }
Пример #8
0
		bool CalculateRectPlacement(DrawArgs drawArgs)
		{
			int labelLinePoint = FindAnchorPoint();
			if(labelLinePoint < 0)
			{
				// Measure line is not visible
				return false;
			}

			Vector3 referenceCenter = new Vector3(
				(float)drawArgs.WorldCamera.ReferenceCenter.X,
				(float)drawArgs.WorldCamera.ReferenceCenter.Y,
				(float)drawArgs.WorldCamera.ReferenceCenter.Z
				);


			Angle displayAngle = CalcAngle(labelLinePoint, referenceCenter);
			if( Angle.IsNaN(displayAngle) )
				return false;

			const int leg1Len = 30;
			const int leg2Len = 5;

			
			Vector3 screenAnchor = m_drawArgs.WorldCamera.Project(
				new Vector3( 
				measureLine[labelLinePoint].X,
				measureLine[labelLinePoint].Y,
				measureLine[labelLinePoint].Z ) - referenceCenter);

			float x1 = (float)(screenAnchor.X + Math.Cos(displayAngle.Radians)*leg1Len);
			float y1 = (float)(screenAnchor.Y + Math.Sin(displayAngle.Radians)*leg1Len);
			float x2 = x1;
			float y2 = y1;


			// Find direction of 2nd leg.
			int quadrant = (int)((displayAngle.Radians)/(Math.PI/2));
			switch (quadrant % 4)
			{
				case 0:
				case 3:
					x2 += leg2Len;
					break;
				case 1:
				case 2:
					x2 -= leg2Len;
					break;
			}

			// Calculate label box position / size
			if (World.Settings.MeasureMode == MeasureMode.Multi)
			{
				Distance = multiline.getLength();
				//labelText = Distance>=10000 ?
				//	string.Format( "Total Distance: {0:f1}km", Distance/1000 ) :
				//	string.Format( "Total Distance: {0:f1}m", Distance );
				labelText = "Total Distance: " + ConvertUnits.GetDisplayString(Distance);
			}
			else
			{
				//labelText = Distance>=10000 ?
				//	string.Format( "Distance: {0:f1}km", Distance/1000 ) :
				//	string.Format( "Distance: {0:f1}m", Distance );
				labelText = "Distance: " + ConvertUnits.GetDisplayString(Distance);

			}
			labelText += string.Format("\nBearing: {0:f1}°", Azimuth.Degrees );

			labelTextRect = m_drawArgs.defaultDrawingFont.MeasureString(null, labelText, DrawTextFormat.None, 0);
			
			Rectangle tsize = labelTextRect;
			const int xPad = 4;
			const int yPad = 1;
			tsize.Inflate( xPad, yPad );
			labelTextRect.Offset(-tsize.Left, -tsize.Top);
			tsize.Offset(-tsize.Left, -tsize.Top);
			
			rectLineConnection[0].X = screenAnchor.X;
			rectLineConnection[0].Y = screenAnchor.Y;
			rectLineConnection[1].X = x1;
			rectLineConnection[1].Y = y1;
			rectLineConnection[2].X = x2;
			rectLineConnection[2].Y = y2;
			if(x2>x1)
			{
				labelTextRect.Offset((int)x2, 0);
				tsize.Offset((int)x2, 0);
			}
			else
			{
				int xof = (int)(x2-tsize.Width);
				labelTextRect.Offset(xof, 0);
				tsize.Offset(xof, 0);
			}
			tsize.Offset(0, (int)(y2 - tsize.Height/2));
			labelTextRect.Offset(0, (int)(y2 - tsize.Height/2));

			rect[0].X = tsize.Left;
			rect[0].Y = tsize.Top;
			rect[1].X = rect[0].X;
			rect[1].Y = tsize.Bottom;
			rect[2].X = tsize.Right;
			rect[2].Y = rect[0].Y;
			rect[3].X = rect[2].X;
			rect[3].Y = rect[1].Y;
			rect[4].X = rect[0].X;
			rect[4].Y = rect[1].Y;

			rectFrame[0].X = tsize.Left;
			rectFrame[0].Y = tsize.Top;
			rectFrame[1].X = rectFrame[0].X;
			rectFrame[1].Y = tsize.Bottom;
			rectFrame[2].X = tsize.Right;
			rectFrame[2].Y = rectFrame[1].Y;
			rectFrame[3].X = rectFrame[2].X;
			rectFrame[3].Y = rectFrame[0].Y;
			rectFrame[4].X = rectFrame[0].X;
			rectFrame[4].Y = rectFrame[0].Y;


			// Cap at start of measure
			Vector3 a = new Vector3(measureLine[0].X, measureLine[0].Y, measureLine[0].Z );
			Vector3 b = new Vector3(measureLine[1].X, measureLine[1].Y, measureLine[1].Z );
			Vector3 vCap  = Vector3.Cross(a,b);
			vCap.Normalize();
			const int lineCapSize = 6;
			vCap.Scale( (float)m_drawArgs.WorldCamera.Distance/750f*lineCapSize );

			Vector3 worldXyzStart = new Vector3( measureLine[0].X, measureLine[0].Y, measureLine[0].Z );
			Vector3 va = Vector3.Add( worldXyzStart, vCap );
			Vector3 vb = Vector3.Add( worldXyzStart, -vCap );

			startPoint[0].X = va.X;
			startPoint[0].Y = va.Y;
			startPoint[0].Z = va.Z;
			startPoint[1].X = vb.X;
			startPoint[1].Y = vb.Y;
			startPoint[1].Z = vb.Z;

			// Cap at end of measure
			int last = measureLine.Length-1;
			Vector3 worldXyzEnd = new Vector3( 
				measureLine[last].X,
				measureLine[last].Y,
				measureLine[last].Z );

			int beforeLast = last-1;
			vCap = new Vector3( 
				measureLine[beforeLast].X,
				measureLine[beforeLast].Y,
				measureLine[beforeLast].Z );
			vCap.Subtract(worldXyzEnd);
			vCap.Normalize();
			vCap.Scale( (float)(m_drawArgs.WorldCamera.Distance/750f*lineCapSize) );

			vb = va = Vector3.Add( worldXyzEnd , vCap );
			const float arrowHeadAngle = 0.25f*(float)Math.PI;
			va.TransformCoordinate( Matrix.RotationAxis( worldXyzEnd, (float)Math.PI+arrowHeadAngle ));
			vb.TransformCoordinate( Matrix.RotationAxis( worldXyzEnd, arrowHeadAngle));

			endPoint[0].X = va.X;
			endPoint[0].Y = va.Y;
			endPoint[0].Z = va.Z;
			endPoint[1].X = vb.X;
			endPoint[1].Y = vb.Y;
			endPoint[1].Z = vb.Z;

			Matrix rotate90 = Matrix.RotationAxis( worldXyzEnd, (float)Math.PI*0.5f );
			va.TransformCoordinate( rotate90 );
			vb.TransformCoordinate( rotate90 );

			endPoint[2].X = va.X;
			endPoint[2].Y = va.Y;
			endPoint[2].Z = va.Z;
			endPoint[3].X = vb.X;
			endPoint[3].Y = vb.Y;
			endPoint[3].Z = vb.Z;

			return true;
		}
        public static void Test_Vector3_Generic_Scale_Against_Unity3D(float a, float b, float c, float d, float e, float f)
        {
            //arrange
            Vector3<float> genericVec3One = new Vector3<float>(a, b, c);
            Vector3<float> genericVec3Two = new Vector3<float>(d, e, f);

            UnityEngine.Vector3 unityVec3One = new UnityEngine.Vector3(a, b, c);
            UnityEngine.Vector3 unityVec3Two = new UnityEngine.Vector3(d, e, f);

            //act
            Vector3<float> genericScale = genericVec3One.Scale(genericVec3Two);
            unityVec3One.Scale(unityVec3Two);

            //assert
            Assert.IsTrue(isVectorsEqual(unityVec3One, genericScale));
        }