// Return quad whos face is always looking to the camera. This is the real billboard, with perspective distortions! // Billboard's orientation is calculated by projecting unit sphere's north pole to billboard's plane. From this we can get up/right vectors. // Idea is this: if camera is in the middle of unit sphere and billboard is touching this sphere at some place (still unit sphere), we // know billboard's plan is perpendicular to the sphere, so if we want billboard's orientation to be like earth's latitude and Colatitude, // we need to find billboard's up vector in the direction. This is when projection cames into place. // Notice that we don't need camera left/up vector. We only need camera position. Because it's about the sphere around the player. Not camera orientation. // IMPORTANT: One problem of this approach is that if billboard is right above the player, its orientation will swing. Thats because we are projecting // Rotation is around vector pointing from camera position to center of the billboard. // the point, but it ends right in the billboard's centre. // So we not use this for particles. We use it only for background sphere (starts, galaxies) prerender. // Return false if billboard wasn't for any reason created (e.g. too close to the camera) public static bool GetBillboardQuadAdvancedRotated(out MyQuadD quad, Vector3D position, float radiusX, float radiusY, float angle, Vector3D cameraPosition) { // Optimized: Vector3 dirVector = MyMwcUtils.Normalize(position - cameraPosition); Vector3D dirVector; dirVector.X = (position.X - cameraPosition.X); dirVector.Y = (position.Y - cameraPosition.Y); dirVector.Z = (position.Z - cameraPosition.Z); // If distance to camera is really small don't draw it. if (dirVector.LengthSquared() <= MyMathConstants.EPSILON) { // Some empty quad quad = new MyQuadD(); return(false); } dirVector = MyUtils.Normalize(dirVector); Vector3D projectedPoint; // Project Up onto plane defined by origin and dirVector Vector3D.Reject(ref Vector3D.Up, ref dirVector, out projectedPoint); Vector3D upVector; if (projectedPoint.LengthSquared() <= MyMathConstants.EPSILON_SQUARED) { // If projected point equals to zero, we know billboard is exactly above or bottom of camera // and we can't calculate proper orientation. So we just select some direction. Good thing we // know is that billboard's plan ix XY, so we can choose any point on this plane upVector = Vector3D.Forward; } else { // Optimized: upVector = MyMwcUtils.Normalize(projectedPoint); MyUtils.Normalize(ref projectedPoint, out upVector); } // Optimized: Vector3 leftVector = MyMwcUtils.Normalize(Vector3.Cross(upVector, dirVector)); Vector3D leftVector; Vector3D.Cross(ref upVector, ref dirVector, out leftVector); leftVector = MyUtils.Normalize(leftVector); // Two main vectors of a billboard rotated around the view axis/vector float angleCos = (float)Math.Cos(angle); float angleSin = (float)Math.Sin(angle); Vector3D billboardAxisX; billboardAxisX.X = (radiusX * angleCos) * leftVector.X + (radiusY * angleSin) * upVector.X; billboardAxisX.Y = (radiusX * angleCos) * leftVector.Y + (radiusY * angleSin) * upVector.Y; billboardAxisX.Z = (radiusX * angleCos) * leftVector.Z + (radiusY * angleSin) * upVector.Z; Vector3D billboardAxisY; billboardAxisY.X = (-radiusX * angleSin) * leftVector.X + (radiusY * angleCos) * upVector.X; billboardAxisY.Y = (-radiusX * angleSin) * leftVector.Y + (radiusY * angleCos) * upVector.Y; billboardAxisY.Z = (-radiusX * angleSin) * leftVector.Z + (radiusY * angleCos) * upVector.Z; // Coordinates of four points of a billboard's quad quad.Point0.X = position.X + billboardAxisX.X + billboardAxisY.X; quad.Point0.Y = position.Y + billboardAxisX.Y + billboardAxisY.Y; quad.Point0.Z = position.Z + billboardAxisX.Z + billboardAxisY.Z; quad.Point1.X = position.X - billboardAxisX.X + billboardAxisY.X; quad.Point1.Y = position.Y - billboardAxisX.Y + billboardAxisY.Y; quad.Point1.Z = position.Z - billboardAxisX.Z + billboardAxisY.Z; quad.Point2.X = position.X - billboardAxisX.X - billboardAxisY.X; quad.Point2.Y = position.Y - billboardAxisX.Y - billboardAxisY.Y; quad.Point2.Z = position.Z - billboardAxisX.Z - billboardAxisY.Z; quad.Point3.X = position.X + billboardAxisX.X - billboardAxisY.X; quad.Point3.Y = position.Y + billboardAxisX.Y - billboardAxisY.Y; quad.Point3.Z = position.Z + billboardAxisX.Z - billboardAxisY.Z; return(true); }
public static bool IsValid(Quaternion q) { return(IsValid(q.X) && IsValid(q.Y) && IsValid(q.Z) && IsValid(q.W) && !MyUtils.IsZero(q)); }
public static bool IsEqual(QuaternionD value1, QuaternionD value2) { return(MyUtils.IsZero(value1.X - value2.X) && MyUtils.IsZero(value1.Y - value2.Y) && MyUtils.IsZero(value1.Z - value2.Z) && MyUtils.IsZero(value1.W - value2.W)); }
public static bool IsEqual(Vector3 value1, Vector3 value2) { return(MyUtils.IsZero(value1.X - value2.X) && MyUtils.IsZero(value1.Y - value2.Y) && MyUtils.IsZero(value1.Z - value2.Z)); }
public static bool IsEqual(float value1, float value2) { return(MyUtils.IsZero(value1 - value2)); }
public MyPlane(ref MyTriangle_Vertexes triangle) { Point = triangle.Vertex0; Normal = MyUtils.Normalize(Vector3.Cross((triangle.Vertex1 - triangle.Vertex0), (triangle.Vertex2 - triangle.Vertex0))); }