# johnb

Member

469

351 Neutral

• Rank
Member
1. ## Interpolating Curves + B-Splines

You want Catmull-Rom splines - do a web search on Catmull-Rom and take your pick.
2. ## When to normalise a quaternion

Quote:Original post by pauls_1979 Unfortunately this doesn't work and I think it's because (as MrRowl pointed out) I can't just remove two components, then normalise the quaternion and expect to get a valid rotation. Does anyone have any suggestions as to how I might correctly limit the rotation? I did think I could just convert the quaternion to eular angles, then create a new rotation using only the y component like this ... I've a feeling this might result in a loss of precision though and precision is farily important here. You are always going to lose some information, and for some rotations there may not be a right answer, but this is how I would do it: Work out what your forward/preferred direction is, perpendicular to the Y axis. Suppose it is X, i.e. the X axis X = (1, 0, 0) Rotate this using your quaternion. you will get a new unit vector V = (vx, vy, vz) Zero the y coordinate of this, and renormalise (note that the sort of rotations this doesn't work for tend to make vy the largest component), to get U = (ux, 0, uz) Then the rotation you want about the Y axis is from X to U. You can work out the angle and use a quaternion from angle-axis, or work it out more directly.
3. ## cross product

Perhaps the easiest way is as follows. if p = (1, 0, 0) and q = (0, 1, 0) There are two candidates for the perpendicular to these two vectors, p ^ q, and we chose p ^ q = (0, 0, 1) not (0, 0, -1) by convention. Note that this is the vx.wy of (vy.wz − wy.vz, vz.wx − wz.vx, vx.wy − wx.vy) Then if r = (0, 0, 1) you can similarly write down p ^ r, r ^ p. Reversed they are negated as the cross product is anti-symmetric. You should find they correspond to the other terms in the formula for v ^ w. The rest follows by linearity, i.e. because (a ^ b) + (a ^ c) = a ^ (b + c) and m(a ^ b) = (ma) ^ b You can combine them to produce the full cross product.
4. ## Compressed quaternions

Quote:Original post by Promethium Doom 3's MD5 file format stores unit quaternions as 3 floats: x, y and z. Using those three it's easy to find the fourth since x*x + y*y + z*z + w*w = 1. There are a couple of issues with this. First you need an additional sign bit to distinguish between w being posive and negative, both of which are possible. You can avoid this though by checking the sign of w before compressing and if it's negative multiply the whole quaternion by -1, so w is always positive and you take the positive square root when decompressing. But this can cause problems for some data - e.g. by introducing jumps into a sequence of keyframes of an animation, requiring extra checks when interpolating them. Another issue is the formula w = sqrt( 1 - x^2 + y^2 + z^2 ) In not uniformly accurate - the larger D^2 = (x^2 + y^2 + z^2) is, and the smaller w is, the worse the error. you can show this numerically but the easiest way is to consider the derivate, e.g. of w with respect to x dw/dx = -x / sqrt( 1 - D^2) If D^2 = 0.25, x= 0.5 dw/dx = -2/3 if D^2 = 0.99, x = 0.5 dw/dx = 50 This means the rate of change of w with respect to x (or y or z) increases significantly as w approaches zero. This impacts the accuracy of it, as fp and rounding errors are multiplied by this, so near zero calculations of w are increasingly inaccurate. One solution is to store X, Y and z more accurately, using e.g. doubles, but this is not much use for compression. A better solution is to store the smallest three of X, Y, Z and W, with a couple of bits to say which you've stored. In 32 bits this needs 10 bits per float, 2 bits to select the largest and so which three are stored, by e.g. describing how many times {X, Y, Z, W} needs to be permuted after decompression.
5. ## Camera rotation: angles - quaternion

You should have a quaternion to matrix function somewhere, probably in your quaternion library. If you don't have one it's not too difficult to write one - search the web for source or the maths. The problem is the code, in particular the line (I've corrected it as I think it should be as follows) Matrix cameraRotation = Matrix.CreateRotationX(cameraAngles.Z) * Matrix.CameraRotationY(cameraAngles.X); is working in two different frames of reference, converting form world space to screen space coordinates. You can do this in your quaternion, before converting to a matrix, by swapping the X, Y and Z as the above formula suggests so e.g. (x=A, y=B, z=C w=D) becomes (x=C, y=A, z=B, w=D), Probably something like Quat qScreen(qCam.Z, qCam.X, qCam.Y, qCam.W); Matrix cameraRotation(qScreen);
6. ## Operations between normalized Quaternions

In more detail the magnitudes of the quaternion multiply. As normalised quaternions have magnitude 1, multiply two quaternions together and the magnitude is 1 * 1 = 1, so the result is also normalised. Quote:Original post by erissian Yes; excepting any floating point errors. The same goes for vectors (the magnitude will be 1, for scalar or vector products). It is not true for these vector products, except in special cases (e.g .the cross product of perpendicular vectors). The only non-trivial product of vectors that this holds for is the geometric/Clifford product.
7. ## Collision Normal - AABB - sphere

The collision normal of a sphere with anything is always along a line from the centre of the sphere to the contact point - along a radius. As for whether it collides with a corner, edge or face this is determined by the location of the sphere's centre. One way of looking at it is as follows: Suppose the box is defined by x1 < x < x2 y1 < y < y2 z1 < z < z2 and the sphere is at (X, Y, Z) Simply count how many of the following are true x1 < X < x2 y1 < Y < y2 z1 < Z < z2 If none are true the sphere hits a corner. If one is true the sphere hits an edge. If two are true the sphere hits a face (if three are true the sphere is inside the box, which is case you probably want to exclude). More formally the planes x = x1, x = x2 etc. divide the space into Voronoi regions, of which this is an application. You can work them out for other polygonal bodies, though the maths quickly gets a lot more complicated.
8. ## wtf unit cross product

The cross product of two unit vectors is a unit vector only if they are perpendicular. If they are parallel the cross product is zero. The general rule is | u1 x u2 | = | u1 | | u2 | sin t where t is the angle between the vectors. If they are both unit vectors this reduces to | u1 x u2 | = sin t , which is what you have, and from which you can work out the angle between the vectors.
9. ## What information do you need to calculate a collision between two entities?

To do it properly you need to do collision detection between the sword and bob, using a collision mesh matching bob. I think you need more than a cylinder - a person in combat is not especially cylindrical, so e.g. joe's sword will swing through bob's outstretched sword arm without it registering. So you model bob and the sword using polygons and use one of a number collision systems. Or you do what any number of games have done and just give each weapon a 'reach' value and say that when joe and bob are within this distance the weapon hits, subject to weapon skill and shielding modifiers etc.. Many games don't even bother with this, giving all weapons the same reach, unless they are ranged.
10. ## Using a Tablet to enter mathematical notation.

I don't think it's possible, or at least it would be very challenging to do. Handwriting recognition works by not only looking at the forms of letters but the order in which they are written, so it can use a dictionary to guess badly recognised letters. Equations are generally non-linear. They use not only the shapes (from a much larger set) but the 2D arrangement, size, and format (bold/italic) of letters and symbols to convey meaning in the smallest space possible. I can't see how it could be done with any degree of accuracy, unless the symbols and layouts possible were very limited. I've used TeX when editing mathematical formulae for e.g. inclusion into PDF, and would recommend it for such, especially to a programmer as it's as much a programming language as a markup language. And as it's text based in theory you could use a tablet to input it, though as a programming language it would fox any dictionary based handwriting recognition system.
11. ## Direct quaternion rotation

Eqation 30 is using the quaternion derived in equation 29, which is a unit vector (not proven but easy to prove). Unit vectors have length 1 so have the same inverse and conjugate. As for your code it looks right. If it isn't working I would suggest checking your quaternion is a unit quaternion, and check the quaternion * quaternion calculation as it's about the most complex quaternion operation most people have to deal with. Also try it with some simple cases, such as he identity quaternion, rotation through pi/2 etc..
12. ## Quaternions yielding wrong result

Quote:Original post by 0v3rloader PS: The Mul method in Vector4 is taking the 2 parameter as an output one, therefore storing the result of the operation in it, which is why it isn't const. This is just a (very small) way of saving on object construction overheads. But then you do this outQuat._w = ((_w * mulQuat._w) - (vec1.Dot(vec2))); vec1.Cross(vec2, cross); vec1._x *= mulQuat._w; vec1._y *= mulQuat._w; vec1._z *= mulQuat._w; i.e. modify outQuat._w, and immediately after use mulQuat._w. If they are the same quaternions then they are the same, so you are modifying w of your input before you use it ! Don't worry about construction overheads - you get for more performance back by making all parameters const anyway, as the compiler can do a lot more aggressive optimisation on such functions, including eliminating unnecessary constructors.
13. ## Quaternions yielding wrong result

This: // Calculates cross between this vector and another. Stores // result in another vector object. Vector3<T>& Vector3<T>::Cross(const Vector3<T>& vector, Vector3<T>& cross) const throw() { cross._x = (_y * vector._z) - (vector._z * _y); cross._y = (_z * vector._x) - (vector._x * _z); cross._z = (_x * vector._y) - (vector._y * _x); return(cross); } is wrong, as it always returns (0, 0, 0). Your quaternion multiplicaiton function also has problems as you write your result to one of the parameters as you calculate it, but are also using the same as input when e.g. you do. Mul(resultQuat, resultQuat); It's generally best practice to make any parameters you pass by reference const, returning results by value. Otherwise it's not obvious what code like the above does and such mistakes are made.
14. ## Affine transformation

I think the answer is yes, but you need two rotations. E.g. If you rotate, axis scale then rotate you in general get a non-trivial affine transformation without translation. The degrees of freedom also agree: rotate+axis scale+rotate = 1+2+1 = 4, the same as the number of elements in the 2x2 matrix describing the transformation.
15. ## Why is this billards physics (article) slightly different to mine?

That's correct if the masses are travelling in the same direction as the line of contact, so all velocities are parallel. In the more general case you need to do something like this. Vector n = (pos1 - pos2).normal(); float speed1 = vel1.dot(n); float speed2 = vel2.dot(n); vf1 = vel1 + n * ((speed2*2*m2 + speed1*(m1-m2) )/(m1+m2) - speed1); vf2 = vel2 + n * ((speed1*2*m1 - speed2*(m1-m2) )/(m1+m2) - speed2); to modify the speeds in the direction of collision, i.e, parallel to n. This is again for a perfectly elastic collision with no friction.