/// <summary> /// Defines the view matrix with an eye position, a look at point and an up vector. /// This method is equivalent to the OpenGL function gluLookAt. /// If Up is a zero vector a default up vector is calculated with a default /// look-right vector (VZ) that lies in the x-z plane. /// </summary> /// <param name="Eye">Eye Vector to the position of the eye (view point)</param> /// <param name="At">At Vector to the target point</param> /// <param name="Up">Up Vector that points from the viewpoint upwards.</param> public void LookAt(SLVec3f Eye, SLVec3f At, SLVec3f Up) { SLVec3f VX, VY, VZ, VT, ZERO; //SLMat3<T> xz(0.0, 0.0, 1.0, // matrix that transforms YZ into a // 0.0, 0.0, 0.0, // vector that is perpendicular to YZ and // -1.0, 0.0, 0.0); // lies in the x-z plane VZ = Eye - At; VZ.Normalize(); VX = new SLVec3f(); ZERO = new SLVec3f(); if (Up == ZERO) { VX.x = VZ.z; VX.y = 0; VX.z = -1 * VZ.x; } else { VX = Up.Cross(VZ); } VY = SLVec3f.CrossProduct(VZ, VX); VX.Normalize(); VY.Normalize(); VZ.Normalize(); VT = -Eye; Set(VX.x, VX.y, VX.z, SLVec3f.DotProduct(VX, VT), VY.x, VY.y, VY.z, SLVec3f.DotProduct(VY, VT), VZ.x, VZ.y, VZ.z, SLVec3f.DotProduct(VZ, VT), 0.0f, 0.0f, 0.0f, 1.0f); }
private SLVec3f trackBallVec(float x, float y) { SLVec3f vec = new SLVec3f(); float r; if (ClientRectangle.Width < ClientRectangle.Height) { r = (float)(ClientRectangle.Width / 2) * 0.88f; } else { r = (float)(ClientRectangle.Height / 2) * 0.88f; } vec.x = (x - ClientRectangle.Width / 2) / r; vec.y = (y - ClientRectangle.Height / 2) / r * -1; float d2 = vec.x * vec.x + vec.y * vec.y; if (d2 < 1f) { vec.z = (float)Math.Sqrt(1f - d2); } else { vec.z = 0f; vec.Normalize(); } return(vec); }
/// <summary> /// calculates mirror effect from normale relative to the light /// </summary> /// <param name="light"></param> /// <returns></returns> public SLVec3f spiegel(SLLight light) { SLVec3f R = 2 * (SLVec3f.DotProduct(light.direction, this.normale)) * this.normale - light.direction; SLVec3f E = -(this.posInView); E.Normalize(); float RsE = (float)Math.Pow(Math.Max(SLVec3f.DotProduct(R, E), 0), 5); return((light.mirror) * RsE); }
/// <summary> /// Conversion to axis and angle in radians /// The matrix must be a rotation matrix for this functions to be valid. The last /// function uses Gram-Schmidt orthonormalization applied to the columns of the /// rotation matrix. The angle must be in radians, not degrees. /// </summary> /// <param name="angleDEG"></param> /// <param name="axis"></param> public void ToAngleAxis(out float angleDEG, out SLVec3f axis) { // Let (x,y,z) be the unit-length axis and let A be an angle of rotation. // The rotation matrix is R = I + sin(A)*P + (1-cos(A))*P^2 where // I is the identity and // // +- -+ // | 0 -z +y | // P = | +z 0 -x | // | -y +x 0 | // +- -+ // // If A > 0, R represents a counterclockwise rotation about the axis in // the sense of looking from the tip of the axis vector towards the // origin. Some algebra will show that // // cos(A) = (trace(R)-1)/2 and R - R^t = 2*sin(A)*P // // In the event that A = pi, R-R^t = 0 which prevents us from extracting // the axis through P. Instead note that R = I+2*P^2 when A = pi, so // P^2 = (R-I)/2. The diagonal entries of P^2 are x^2-1, y^2-1, and // z^2-1. We can solve these for axis (x,y,z). Because the angle is pi, // it does not matter which sign you choose on the square roots. float tr = Trace(); float cs = 0.5f * (tr - 1.0f); double angleRAD = Math.Acos(cs); // in [0,PI] // Init axis axis = SLVec3f.XAxis; if (angleRAD > 0) { if (angleRAD < Math.PI) { axis.x = m[5] - m[7]; axis.y = m[6] - m[2]; axis.z = m[1] - m[3]; axis.Normalize(); } else { // angle is PI float halfInverse; if (m[0] >= m[4]) { // r00 >= r11 if (m[0] >= m[8]) { // r00 is maximum diagonal term axis.x = 0.5f * (float)Math.Sqrt(1 + m[0] - m[4] - m[8]); halfInverse = 0.5f / axis.x; axis.y = halfInverse * m[3]; axis.z = halfInverse * m[6]; } else { // r22 is maximum diagonal term axis.z = 0.5f * (float)Math.Sqrt(1 + m[8] - m[0] - m[4]); halfInverse = 0.5f / axis.z; axis.x = halfInverse * m[6]; axis.y = halfInverse * m[7]; } } else { // r11 > r00 if (m[4] >= m[8]) { // r11 is maximum diagonal term axis.y = 0.5f * (float)Math.Sqrt(1 + m[4] - m[0] - m[8]); halfInverse = 0.5f / axis.y; axis.x = halfInverse * m[3]; axis.z = halfInverse * m[7]; } else { // r22 is maximum diagonal term axis.z = 0.5f * (float)Math.Sqrt(1 + m[8] - m[0] - m[4]); halfInverse = 0.5f / axis.z; axis.x = halfInverse * m[6]; axis.y = halfInverse * m[7]; } } } } angleDEG = (float)(angleRAD * SLUtils.RAD2DEG); }