 Home
 » Viewing Profile: Reputation: Álvaro
Álvaro
Member Since 07 Mar 2002Offline Last Active Yesterday, 09:36 PM
Community Stats
 Group Crossbones+
 Active Posts 6,895
 Profile Views 15,937
 Submitted Links 0
 Member Title Member
 Age Age Unknown
 Birthday Birthday Unknown

Gender
Not Telling

Location
New York (USA)
User Tools
Latest Visitors
#5173013 Understanding the Zcoordinate.
Posted by Álvaro on 11 August 2014  11:10 PM
#5173012 Offsetting 3D Points Based On Rotation + Position Of Camera
Posted by Álvaro on 11 August 2014  11:04 PM
If that's clear, we just need to know how to scale things that are farther away from or closer to the eye than the screen. The answer is that point (x,y,z) maps to pixel (512+x*1000/(z+1000), 384y*1000/(z+1000)). You can convince yourself that this is correct by making a picture of the situation (I suggest from above, to get the formula for the x coordinate) and using triangle similarity.
Now you need to know how to handle other camera positions and angles. Let's handle yaw first. You can rotate the whole world around the origin on the XY plane by using these formulas:
x' = x * cos(angle)  y * sin(angle)
y' = x * sin(angle) + y * cos(angle)
Do that to every point in the scene and your whole world has now rotated around the origin. If you want the rotation to happen around any other point, first subtract the coordinates of the center of rotation, then rotate, then add them back. In particular, you can now perform rotations around the camera, which has the same effect as rotating the camera.
For pitch you can do the same thing in the YZ plane. The order of rotations does matter. You probably want to apply pitch first and then yaw, but if that doesn't do what you want, reverse the order.
Moving the camera around is pretty easy, since all you have to do is again move the whole world in the opposite direction, by subtracting some vector from every point.
That's the closest I can get to "simplified math". I hope it helps. But you should really really try to find a gentle introduction to the algebra of matrices and vectors and try to understand the formulas you've found in other places.
#5172291 Triangle vectors on the circle
Posted by Álvaro on 08 August 2014  08:59 AM
#5172241 Debugging memory leak(?) or logic problem
Posted by Álvaro on 08 August 2014  04:30 AM
See if you can simplify your program a lot and still have the behavior you observe, then try to understand what's going on in the simpler program.
#5172068 Safely using IEEE754 Float types.
Posted by Álvaro on 07 August 2014  10:53 AM
http://docs.oracle.com/cd/E1995701/8063568/ncg_goldberg.html
I think that's way too much information for the "For Beginners" forum. You might scare people off by drowning them in details.
#5172057 Safely using IEEE754 Float types.
Posted by Álvaro on 07 August 2014  09:58 AM
#2 What is the absollutely safe range (maximum and minimum) in floats without losing information(end ressult the number will be represented exactly).
That question doesn't make much sense. There is no entire range of real numbers that can be represented exactly. Here's a description of what can be represented:
From 1 to 2 you can represent anything in increments of 2^23. So these numbers can be represented exactly:
1.00000000000000000000000
1.00000011920928955078125
1.00000023841857910156250
1.00000035762786865234375
1.00000047683715820312500
1.00000059604644775390625
1.00000071525573730468750
1.00000083446502685546875
1.00000095367431640625000
1.00000107288360595703125
1.00000119209289550781250
1.00000131130218505859375
...
1.99999904632568359375000
1.99999916553497314453125
1.99999928474426269531250
1.99999940395355224609375
1.99999952316284179687500
1.99999964237213134765625
1.99999976158142089843750
1.99999988079071044921875
2.00000000000000000000000
Between 2 and 4 the step is 2^22, then between 4 and 8 the step is 2^21 and so on. For numbers smaller than 1, it works similarly: Between 0.5 and 1 the step is 2^24, between 0.25 and 0.5 the step is 2^25, and so on.
That is a almost a full description of the situation. Of course there is a maximum number that can be represented and things are different for numbers very close to zero.
If in light of this explanation you still have a question, post it.
#5171946 Turn Based AI Technics
Posted by Álvaro on 06 August 2014  03:25 PM
Or you can just take the basic idea (write a function that returns how happy you are with an action (the "expected utility" of the action) and then pick the action with the highest value) and experiment with it. Chances are you'll discover everything that's in the book by yourself. But still, Dave is a nice guy and you should buy his book.
#5171613 Cohesion and coupling
Posted by Álvaro on 05 August 2014  07:09 AM
#5171388 Quaternion angle with itself > 0.001
Posted by Álvaro on 04 August 2014  05:47 AM
I just wanted to point a couple things out. I can't be 100% sure, but I believe the original quaternions were already normalized. After a lot of testing and examining, it looks as though the normalization simply traded error on one side for error on the other side, which resulted in a SEEMINGLY better angle result. I noticed this because I can literally renormalize a quaternion over and over again, and get different results each time.
I think the quaternion you posted originally was not properly normalized. Do you care to post a particular quaternion for which the renormalization isn't stable?
Even something as simple as 1+1=2 can turn your game world upsidedown if its not interpreted as 1+1=almost definitely 2.
That seems to indicate you don't understand floatingpoint numbers very much: 1 + 1 is most definitely exactly 2.
#5171262 good random permutation?
Posted by Álvaro on 03 August 2014  08:17 AM
x = (x ^ seed ^ 1234567890) & 2147483647; x = ((x << 5) ^ (x >> 26)) & 2147483647; x = (x + 675788137) & 2147483647; x ^= 751504984u; x = (x * 2020831389) & 2147483647; x = ((x << 15) ^ (x >> 16)) & 2147483647; x = (x + 1804049603) & 2147483647; x ^= 1028562816u; x = (x * 1430376653) & 2147483647; x = ((x << 15) ^ (x >> 16)) & 2147483647; x = (x + 1804049603) & 2147483647; x ^= 1028562816u; x = (x * 1430376653) & 2147483647; return x;
#5171260 good random permutation?
Posted by Álvaro on 03 August 2014  08:07 AM
g(0) = g(1431655765) = 0
So your function ends up not being a permutation. With seed = 0:
f(0) = f(297859934) = f(719478613) = f(1927211019) = 1905156899
EDIT: I didn't check carefully, but `x = (x + ((x << 5) ^ (x >> 12))) & 2147483647;' is probably also problematic.
#5171209 Floats vs Ints.
Posted by Álvaro on 02 August 2014  08:34 PM
Float32s cannot perfectly represent all values within their range. They cannot even represent every single possible Int32, which may surprise some people.
How can that possibly surprise anybody? There are 2^32 different Int32 values, and floats are represented using 32 bits. So for every noninteger number that can be represented as a Float32s, there is an integer that cannot be represented as a Float32s.
#5171068 Spring phisic and quaternion
Posted by Álvaro on 02 August 2014  05:06 AM
Dampening is next step. It would be more easier. Now it would be good if spring make harmonic vibration from start to target, opposite side and back, without unexpected rotation and flying into deep space.
Is that not what you are getting?
I added a `main' and a couple of extra operators for vectors to show that integrating this torque works. You can set `angular_dampening' to 0.0 if you want to see it oscillate forever. For simplicity, I am assuming the moment of inertia is the identity matrix.
#include <iostream> #include <cmath> #include <boost/math/quaternion.hpp> typedef boost::math::quaternion<double> Quaternion; struct Vector { double x, y, z; Vector(double x, double y, double z) : x(x), y(y), z(z) { } }; std::ostream &operator<<(std::ostream &os, Vector v) { return os << '(' << v.x << ',' << v.y << ',' << v.z << ')'; } Vector operator*(double s, Vector v) { return Vector(s * v.x, s * v.y, s * v.z); } Vector operator(Vector v1, Vector v2) { return Vector(v1.x  v2.x, v1.y  v2.y, v1.z  v2.z); } Vector &operator+=(Vector &v1, Vector v2) { v1.x += v2.x; v1.y += v2.y; v1.z += v2.z; return v1; } Vector cross_product(Vector v1, Vector v2) { return Vector(v1.y * v2.z  v1.z * v2.y, v1.z * v2.x  v1.x * v2.z, v1.x * v2.y  v1.y * v2.x); } double dot_product(Vector v1, Vector v2) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; } double squared_length(Vector v) { return dot_product(v, v); } double length(Vector v) { return std::sqrt(squared_length(v)); } Quaternion most_natural_rotation(Vector v1, Vector v2) { Vector v = cross_product(v1, v2); Quaternion q(std::sqrt(squared_length(v1) * squared_length(v2)) + dot_product(v1, v2), v.x, v.y, v.z); return q / abs(q); } Vector apply_rotation(Quaternion q, Vector v) { Quaternion result = q * Quaternion(0.0, v.x, v.y, v.z) * conj(q); return Vector(result.R_component_2(), result.R_component_3(), result.R_component_4()); } Vector log_of_unit_quaternion(Quaternion q) { double angle = std::acos(q.real()); Vector axis(q.R_component_2(), q.R_component_3(), q.R_component_4()); return (angle / length(axis)) * axis; } Vector compute_torque(Quaternion current_attitude, Vector model_needle, Vector target, double spring_force) { Vector needle = apply_rotation(current_attitude, model_needle); Quaternion rotation = most_natural_rotation(needle, target); return spring_force * log_of_unit_quaternion(rotation); } int main() { Vector model_needle(1.0, 0.0, 0.0); Quaternion attitude(1.0, 0.0, 0.0, 0.0); Vector angular_velocity(0.0, 0.0, 0.0); double const angular_dampening = 1.0; double const dt = 0.1; for (int i=0; i<1000; ++i) { std::cout << apply_rotation(attitude, model_needle) << ' ' << attitude << ' ' << angular_velocity << '\n'; Vector torque = compute_torque(attitude, model_needle, Vector(0.0, 1.0, 0.0), 1.0); Vector angular_acceleration = torque  angular_dampening * angular_velocity; angular_velocity += dt * angular_acceleration; attitude *= exp(dt * Quaternion(0.0, angular_velocity.x, angular_velocity.y, angular_velocity.z)); } }
#5170872 Spring phisic and quaternion
Posted by Álvaro on 01 August 2014  07:04 AM
This should be close to what you need. It is a bit math heavy, so don't feel too bad if you don't understand it all: Just ask me about what parts you don't understand and I'll try to explain them.
#include <iostream> #include <cmath> #include <boost/math/quaternion.hpp> typedef boost::math::quaternion<double> Quaternion; struct Vector { double x, y, z; Vector(double x, double y, double z) : x(x), y(y), z(z) { } }; std::ostream &operator<<(std::ostream &os, Vector v) { return os << '(' << v.x << ',' << v.y << ',' << v.z << ')'; } Vector operator*(double s, Vector v) { return Vector(s * v.x, s * v.y, s * v.z); } Vector cross_product(Vector v1, Vector v2) { return Vector(v1.y * v2.z  v1.z * v2.y, v1.z * v2.x  v1.x * v2.z, v1.x * v2.y  v1.y * v2.x); } double dot_product(Vector v1, Vector v2) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; } double squared_length(Vector v) { return dot_product(v, v); } double length(Vector v) { return std::sqrt(squared_length(v)); } Quaternion most_natural_rotation(Vector v1, Vector v2) { Vector v = cross_product(v1, v2); Quaternion q(std::sqrt(squared_length(v1) * squared_length(v2)) + dot_product(v1, v2), v.x, v.y, v.z); return q / abs(q); } Vector apply_rotation(Quaternion q, Vector v) { Quaternion result = q * Quaternion(0.0, v.x, v.y, v.z) * conj(q); return Vector(result.R_component_2(), result.R_component_3(), result.R_component_4()); } Vector log_of_unit_quaternion(Quaternion q) { double angle = std::acos(q.real()); Vector axis(q.R_component_2(), q.R_component_3(), q.R_component_4()); return (angle / length(axis)) * axis; } Vector compute_torque(Quaternion current_attitude, Vector model_needle, Vector target, double spring_force) { Vector needle = apply_rotation(current_attitude, model_needle); Quaternion rotation = most_natural_rotation(needle, target); return spring_force * log_of_unit_quaternion(rotation); }
#5170674 Why NDC and how to convert?
Posted by Álvaro on 31 July 2014  02:05 PM
I chose [1,1] instead of [0,1] because that's the typical range of NDC. If I remember correctly, OpenGL uses [1,1] for all three axes, and DirectX uses [1,1] for x and y and [0,1] for z.
Oh, so by adding 1 you make it positive and later divide by 2 to make up for adding 'that half of the screen' ???
Yes. One way to think about it is that (x + 1) / 2 maps the interval [1,1] to [0,1], and multiplying by Width maps [0,1] to [0,Width].