public bool Equals(Quaternion rhs, Real tolerance) { Real fCos = Dot(rhs); Real angle = (Real)Utility.ACos(fCos); return(Utility.Abs(angle) <= tolerance); }
/// <summary> /// /// </summary> /// <param name="time"></param> /// <param name="quatA"></param> /// <param name="quatB"></param> /// <param name="useShortestPath"></param> /// <returns></returns> public static Quaternion Slerp(Real time, Quaternion quatA, Quaternion quatB, bool useShortestPath) { Real cos = quatA.Dot(quatB); Real angle = (Real)Utility.ACos(cos); if (Utility.Abs(angle) < EPSILON) { return(quatA); } Real sin = Utility.Sin(angle); Real inverseSin = 1.0f / sin; Real coeff0 = Utility.Sin((1.0f - time) * angle) * inverseSin; Real coeff1 = Utility.Sin(time * angle) * inverseSin; Quaternion result; if (cos < 0.0f && useShortestPath) { coeff0 = -coeff0; // taking the complement requires renormalisation Quaternion t = coeff0 * quatA + coeff1 * quatB; t.Normalize(); result = t; } else { result = (coeff0 * quatA + coeff1 * quatB); } return(result); }
/// <summary> /// Calculates the logarithm of a Quaternion. /// </summary> /// <returns></returns> public Quaternion Log() { // BLACKBOX: Learn this // If q = cos(A)+sin(A)*(x*i+y*j+z*k) where (x,y,z) is unit length, then // log(q) = A*(x*i+y*j+z*k). If sin(A) is near zero, use log(q) = // sin(A)*(x*i+y*j+z*k) since sin(A)/A has limit 1. // start off with a zero quat Quaternion result = Quaternion.Zero; if (Utility.Abs(w) < 1.0f) { Real angle = (Real)Utility.ACos(w); Real sin = Utility.Sin(angle); if (Utility.Abs(sin) >= EPSILON) { Real coeff = angle / sin; result.x = coeff * x; result.y = coeff * y; result.z = coeff * z; } else { result.x = x; result.y = y; result.z = z; } } return(result); }
public bool Equals(Quaternion rhs, float tolerance) { float fCos = Dot(rhs); float angle = (float)Utility.ACos(fCos); return(Utility.Abs(angle) <= tolerance); }
/// <summary> /// /// </summary> /// <param name="angle"></param> /// <param name="axis"></param> /// <returns></returns> public void ToAngleAxis(ref Real angle, ref Vector3 axis) { // The quaternion representing the rotation is // q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k) Real sqrLength = x * x + y * y + z * z; if (sqrLength > 0.0f) { angle = 2.0f * (Real)Utility.ACos(w); Real invLength = Utility.InvSqrt(sqrLength); axis.X = x * invLength; axis.Y = y * invLength; axis.Z = z * invLength; } else { angle = 0.0f; axis.X = 1.0f; axis.Y = 0.0f; axis.Z = 0.0f; } }
/// <summary> /// /// </summary> /// <param name="angle"></param> /// <param name="axis"></param> /// <returns></returns> public void ToAngleAxis(ref Real angle, ref Vector3 axis) { // The quaternion representing the rotation is // q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k) var sqrLength = this.x * this.x + this.y * this.y + this.z * this.z; if (sqrLength > 0.0f) { angle = 2.0f * (Real)Utility.ACos(this.w); var invLength = Utility.InvSqrt(sqrLength); axis.x = this.x * invLength; axis.y = this.y * invLength; axis.z = this.z * invLength; } else { angle = 0.0f; axis.x = 1.0f; axis.y = 0.0f; axis.z = 0.0f; } }
/// <summary> /// /// </summary> /// <param name="angle"></param> /// <param name="axis"></param> /// <returns></returns> public void ToAngleAxis(ref float angle, ref Vector3 axis) { // The quaternion representing the rotation is // q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k) float sqrLength = x * x + y * y + z * z; if (sqrLength > 0.0f) { angle = 2.0f * (float)Utility.ACos(w); float invLength = Utility.InvSqrt(sqrLength); axis.x = x * invLength; axis.y = y * invLength; axis.z = z * invLength; } else { angle = 0.0f; axis.x = 1.0f; axis.y = 0.0f; axis.z = 0.0f; } }
internal unsafe void UpdateGeometry() { if (!this.IsCreated) { return; } // 95% of camera far clip distance float TODO_Radius = this.SkyX.Camera.FarClipDistance * 0.95f; _vertices[0].X = 0; _vertices[0].Z = 0; _vertices[0].Y = TODO_Radius; _vertices[0].NX = 0; _vertices[0].NZ = 0; _vertices[0].NY = 1; _vertices[0].U = 4; _vertices[0].V = 4; _vertices[0].Opacity = 1; float angleStep = (Utility.PI / 2.0f) / (this.Circles - 1.0f); float r, uvr, c, s, sc; int x, y; for (y = 0; y < this.Circles - 1; y++) { r = Utility.Cos(Utility.PI / 2.0f - angleStep * (y + 1.0f)); uvr = (y + 1.0f) / (this.Circles - 1.0f); for (x = 0; x < this.Steps; x++) { c = Utility.Cos(Utility.TWO_PI * x / (float)this.Steps) * r; s = Utility.Sin(Utility.TWO_PI * x / (float)this.Steps) * r; sc = Utility.Sin(Utility.ACos(r)); _vertices[1 + y * this.Steps + x].X = c * TODO_Radius; _vertices[1 + y * this.Steps + x].Z = s * TODO_Radius; _vertices[1 + y * this.Steps + x].Y = sc * TODO_Radius; _vertices[1 + y * this.Steps + x].NX = c; _vertices[1 + y * this.Steps + x].NZ = s; _vertices[1 + y * this.Steps + x].NY = sc; _vertices[1 + y * this.Steps + x].U = (1.0f + c * uvr / r) * 4.0f; _vertices[1 + y * this.Steps + x].V = (1.0f + s * uvr / r) * 4.0f; _vertices[1 + y * this.Steps + x].Opacity = 1; } } r = Utility.Cos(angleStep); uvr = (this.Circles + 1.0f) / (this.Circles - 1.0f); for (x = 0; x < this.Steps; x++) { c = Utility.Cos(Utility.TWO_PI * x / (float)this.Steps) * r; s = Utility.Sin(Utility.TWO_PI * x / (float)this.Steps) * r; _vertices[1 + (this.Circles - 1) * this.Steps + x].X = _vertices[1 + (this.Circles - 2) * this.Steps + x].X; _vertices[1 + (this.Circles - 1) * this.Steps + x].Z = _vertices[1 + (this.Circles - 2) * this.Steps + x].Z; _vertices[1 + (this.Circles - 1) * this.Steps + x].Y = _vertices[1 + (this.Circles - 2) * this.Steps + x].Y - TODO_Radius * this.SkydomeFadingPercent; _vertices[1 + (this.Circles - 1) * this.Steps + x].NX = _vertices[1 + (this.Circles - 2) * this.Steps + x].NX; _vertices[1 + (this.Circles - 1) * this.Steps + x].NZ = _vertices[1 + (this.Circles - 2) * this.Steps + x].NZ; _vertices[1 + (this.Circles - 1) * this.Steps + x].NY = _vertices[1 + (this.Circles - 2) * this.Steps + x].NY; _vertices[1 + (this.Circles - 1) * this.Steps + x].U = (1.0f + c * uvr / 4) * 4.0f; _vertices[1 + (this.Circles - 1) * this.Steps + x].V = (1.0f + s * uvr / 4) * 4.0f; _vertices[1 + (this.Circles - 1) * this.Steps + x].Opacity = this.SmoothSkydomeFading ? 0 : 1; } // Update data fixed(PosUVVertex *addr = &_vertices[0]) { _vertexBuffer.WriteData(0, _vertexBuffer.SizeInBytes, addr, true); } // Update bounds AxisAlignedBox meshBounds = new AxisAlignedBox(new Vector3(-TODO_Radius, 0, -TODO_Radius), new Vector3(TODO_Radius, TODO_Radius, TODO_Radius)); //_mesh.BoundingBox = meshBounds; _mesh._setBounds(meshBounds); _sceneNode.NeedUpdate(); //for (int i = 0; i < _vertices.Length; i++) // LogVertices(_vertices[i]); }