public void DrawLine(Vector3 start, Vector3 end, Color color, float width = 0.025f) { Vector3 dir = end - start; dir.Z = 0; Vector3 extDir1; Vector3 extDir2; if (dir.LengthSquared() > 0.0001f) { dir.Normalize(); extDir1.X = -dir.Y; extDir1.Y = dir.X; extDir1.Z = 0; extDir2 = Vector3.Cross(dir, extDir1); } else { extDir1 = Vector3.UnitX; extDir2 = Vector3.UnitY; } _vertexBuffer[0] = new ColoredVertex(start + extDir1 * (width / 2), color); _vertexBuffer[1] = new ColoredVertex(start - extDir1 * (width / 2), color); _vertexBuffer[2] = new ColoredVertex(end + extDir1 * (width / 2), color); _vertexBuffer[3] = new ColoredVertex(end - extDir1 * (width / 2), color); _vertexBuffer[4] = new ColoredVertex(start + extDir2 * (width / 2), color); _vertexBuffer[5] = new ColoredVertex(start - extDir2 * (width / 2), color); _vertexBuffer[6] = new ColoredVertex(end + extDir2 * (width / 2), color); _vertexBuffer[7] = new ColoredVertex(end - extDir2 * (width / 2), color); _indexBuffer[0] = 0; _indexBuffer[1] = 1; _indexBuffer[2] = 2; _indexBuffer[3] = 1; _indexBuffer[4] = 2; _indexBuffer[5] = 3; _indexBuffer[6] = 4; _indexBuffer[7] = 5; _indexBuffer[8] = 6; _indexBuffer[9] = 5; _indexBuffer[10] = 6; _indexBuffer[11] = 7; SetDeclaration(); Device.DrawIndexedUserPrimitives(PrimitiveType.TriangleList, 0, 8, 4, _indexBuffer, Format.Index32, _vertexBuffer, ColoredVertex.Stride); }
/// <summary> /// Creates a right-handed spherical billboard that rotates around a specified object position. /// </summary> /// <param name="objectPosition">The position of the object around which the billboard will rotate.</param> /// <param name="cameraPosition">The position of the camera.</param> /// <param name="cameraUpVector">The up vector of the camera.</param> /// <param name="cameraForwardVector">The forward vector of the camera.</param> public static Matrix BillboardLh(ref Vector3 objectPosition, ref Vector3 cameraPosition, ref Vector3 cameraUpVector, ref Vector3 cameraForwardVector) { var result = new Matrix(); Vector3 crossed; Vector3 final; Vector3 difference = cameraPosition - objectPosition; float lengthSq = difference.LengthSquared(); if (IsZero(lengthSq)) { difference = -cameraForwardVector; } else { difference *= (float)(1.0 / Math.Sqrt(lengthSq)); } Vector3.Cross(ref cameraUpVector, ref difference, out crossed); crossed.Normalize(); Vector3.Cross(ref difference, ref crossed, out final); result.M11 = crossed.X; result.M12 = crossed.Y; result.M13 = crossed.Z; result.M14 = 0.0f; result.M21 = final.X; result.M22 = final.Y; result.M23 = final.Z; result.M24 = 0.0f; result.M31 = difference.X; result.M32 = difference.Y; result.M33 = difference.Z; result.M34 = 0.0f; result.M41 = objectPosition.X; result.M42 = objectPosition.Y; result.M43 = objectPosition.Z; result.M44 = 1.0f; return(result); }
/// <summary> /// Creates the smallest <see cref="BoundingSphere"/> that can contain a specified list of points in 3D-space. /// </summary> /// <param name="points">List of point to create the sphere from.</param> /// <returns>The new <see cref="BoundingSphere"/>.</returns> public static BoundingSphere CreateFromPoints(IEnumerable <Vector3> points) { if (points == null) { throw new ArgumentNullException("points"); } // From "Real-Time Collision Detection" (Page 89) Vector3 minx = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); Vector3 maxx = -minx; Vector3 miny = minx; Vector3 maxy = -minx; Vector3 minz = minx; Vector3 maxz = -minx; // Find the most extreme points along the principle axis. int numPoints = 0; foreach (Vector3 pt in points) { numPoints += 1; if (pt.X < minx.X) { minx = pt; } if (pt.X > maxx.X) { maxx = pt; } if (pt.Y < miny.Y) { miny = pt; } if (pt.Y > maxy.Y) { maxy = pt; } if (pt.Z < minz.Z) { minz = pt; } if (pt.Z > maxz.Z) { maxz = pt; } } if (numPoints == 0) { throw new ArgumentException( "You should have at least one point in points." ); } float sqDistX = Vector3.DistanceSquared(maxx, minx); float sqDistY = Vector3.DistanceSquared(maxy, miny); float sqDistZ = Vector3.DistanceSquared(maxz, minz); // Pick the pair of most distant points. Vector3 min = minx; Vector3 max = maxx; if (sqDistY > sqDistX && sqDistY > sqDistZ) { max = maxy; min = miny; } if (sqDistZ > sqDistX && sqDistZ > sqDistY) { max = maxz; min = minz; } Vector3 center = (min + max) * 0.5f; float radius = Vector3.Distance(max, center); // Test every point and expand the sphere. // The current bounding sphere is just a good approximation and may not enclose all points. // From: Mathematics for 3D Game Programming and Computer Graphics, Eric Lengyel, Third Edition. // Page 218 float sqRadius = radius * radius; foreach (Vector3 pt in points) { Vector3 diff = (pt - center); float sqDist = diff.LengthSquared(); if (sqDist > sqRadius) { float distance = (float)Math.Sqrt(sqDist); // equal to diff.Length(); Vector3 direction = diff / distance; Vector3 G = center - radius * direction; center = (G + pt) / 2; radius = Vector3.Distance(pt, center); sqRadius = radius * radius; } } return(new BoundingSphere(center, radius)); }