I'm looking at this example in particular:
http://www.airtightinteractive.com/demos/processing_js/noisefield08.html
And here's the code for it:
http://www.airtightinteractive.com/demos/processing_js/noisefield08.pjs
I guess I need explaining for what these lines do in the particle class:
d=(noise(id,x/mouseY,y/mouseY)-0.5)*mouseX;
x+=cos(radians(d))*s;
y+=sin(radians(d))*s;
I understand that noise calculates a value based on the coordinates given, but I don't get the logic in dividing the particles' x pos by the mouseY, or the y pos by the mouseY. I also don't understand what 'id', which seems to be a counter stands for, or what the next two lines accomplish.
Thanks
Move mouse to change particle motion.
d seems to be the direction of motion. By putting mouseY and mouseX into the calculation of d it allows the underlying field to depend on the mouse position. Without a better understanding of the function itself I can't tell you exactly what affect mouseY and mouseX have on the field.
By running cos(radians(d)) and sin(radians(d)) the code turns an angle (d) into a unit vector. For example, if d was 1 radian then cos(radians(d)) would be -1 and sin(radians(d)) would be 0 so it turns the angle 1 radians into the unit vector (-1,0).
So it appears that there is some underlying motion field which determines the direction the particles move. The motion field is represented by the noise function and takes in the current position of the particle, the particle id (perhaps to give each particle independent motion or perhaps to remember a history of the particle's motion and base the future motion on that history) and the current position of the mouse.
The actual distance the particle moves is s which is determined randomly to be between 2 and 7 pixels.
By running cos(radians(d)) and sin(radians(d)) the code turns an angle (d) into a unit vector. For example, if d was 1 radian then cos(radians(d)) would be -1 and sin(radians(d)) would be 0 so it turns the angle 1 radians into the unit vector (-1,0).
Slight correction: that is a rotation of pi radians (180 degrees), not 1 radian (around 57 degrees).
Related
In a Cartesian coordinate system / Euclidian plane, a vehicle travels clockwise around the origin with radius 1 and currently at angle θ = PI/4 (45°), so its heading is 7/4*PI (315°).
To reach its new destination (the origin) it should change course (instantly) to -5/4*PI (-135°).
This angle can be obtained with e.g. atan2 on the components of the vector from position to target (with the target at origin, it's the the inverted position vector)b:
Finding Signed Angle Between Vectors
Using atan2 to find angle between two vectors
Algorithm Improvement: Calculate signed change in heading
However, due to inertia, the vehicle cannot change its course instantly and crosses the X-axis (x=1, y=0, θ=0), where a new calculation results in a course of PI (180°).
The vehicle tries to achieve this new (positive angle) course by a positive turn (counterclockwise, CCW), which takes it back across the X-axis, and so on (it "wiggles" away from the target along the x-axis).
It breaks also if negative angles are "wrapped" into the absolute positive range 0...2PI - example data of the southbound vehicle passing west of the target:
course -0.00477
adjust 6.27840
course 0.00034
adjust 0.00034
The proportional control then basically causes a negative (clockwise) turn, which is the wrong direction.
Do I eliminate this "overflow" somehow (not limit to 0...2PI but map absolute angles to the vehicle's) or should I use a different strategy altogether (which)? 😕
Not limiting the vehicle angle to 0...2PI, i.e. allowing negative and large angles seems to be a promising approach.
E.g. going from 10° to 350°=-10° means a -20° turn.
This determines the heading with the smallest turn angle:
delta = course - heading%fullcircle
if (delta > halfcircle)
delta = delta - fullcircle
if (delta < -halfcircle)
delta = delta + fullcircle
newheading = heading + delta
halfcircle and fullcircle correspond to 180°/PI and 360°/2*PI respectively.
The vehicles heading will "wind up" if it's going circles, but if need be, this could be restored by an occasional modulo operation.
Currently I'm working on a orbit system for a game. I've got it so an object will move along a circle based on a progress value that'll be between 0.0 and 1.0 (0.5 being half way around the circle). I calculate this like this:
float angle = Mathf.Deg2Rad * 360 * t;
float xPos = Mathf.Sin(angle) * xAxis;
float yPos = Mathf.Cos(angle) * yAxis;
return new Vector3(xPos, yPos, 0.0f);
With t simply being deltatime and the xAxis/yAxis variables being the radius of the circle.
What I'm a little stuck on currently though is how I could possibly get the progress around the circle based on a poisition. So if I have an object that hits the bottom of the circle, how do I calculate that to be a progress of 0.5?
First step: Find out the angle of your given position with the y-axis.
Second step: Calculate the fraction of a full circle (360 degs) that your angle has.
First step involves a bit of trigonometry, and there you have to make sure to get the right type of angle based on what quadrant you're in. Second step should be trivial then.
You can check out the atan2 function that's available in many programming languages: https://en.wikipedia.org/wiki/Atan2
It gives the angle between a point (x, y) and the positive x-axis. So then in your case, depending on where your circle starts, you'd then shift that by 90 degrees to get the angle with the positive y-axis. Other than that it should work fine though.
So I have one point in 3D space, and I have location and rotation of the Camera in 3D space.
So basically there is Vector3 on the object.
Camera Vector3 and Quaternion.
I need to get how to look at that point.
I want to tell user how to move to that point.
Should user direct camera left or right or behind?
One way to do this is to calculate the direction the camera is currently facing as a yaw angle (like a compass heading), and calculate the direction it needs to face in order to be looking at the point.
Subtract one from the other and adjust the result so that it is in the range of -180 to 180 degrees (or -pi to pi radians) and then tell the user to turn left or right based on the sign. If the absolute value is more than 120 degrees (or some configurable value) then tell them it is behind them.
To find the camera's current heading, transform the vector (0, 0, 1) by the quaternion to get the forward vector, then calculate the heading using atan2(forward.z, forward.x).
To calculate the heading required to look at the point, subtract the current camera position from the point to get a desired forward vector and then pass to atan:
Vector3 desired_forward = point - camera_pos;
float desired_heading = atan2(desired_forward.z, desired_forward.x);
Then find the rotation needed:
float rotation_needed = desired_heading - heading;
if(rotation_needed > Math.PI)
rotation_needed -= 2 * Math.PI;
if(rotation_needed < -Math.PI)
rotation_needed += 2 * Math.PI;
Now tell the user to rotate left or right based on the sign of the rotation needed.
If you want to do it for look up/down, you can calculate a pitch angle by first calculating the length of the forward vector in the XZ plane and then using atan2 again:
float xzLength = sqrt(forward.x * forward.x + forward.z * forward.z);
float pitch_angle = atan2(forward.y, xzLength);
Do the same for the desired forward vector and subtract the current from the desired. Check the sign to tell the user whether to look up or down.
There's a few likely complications. For example, depending on whether the camera quaternion specifies the transform from world space to camera space or vice versa, you might need to negate the calculated camera heading.
I'm trying to build a to scale model of the solar system. I wanted to see if someone could explain to me how the rotation speed works. Here's the important piece:
objects[index].rotation.y += calculateRotationSpeed(value.radius,value.revolution) * delta;
How does the rotation speed relate to actual time? So if you have a speed of 1, is that a movement of 1 px per millisecond? Or if you have a speed of 0.1, is that less that a px a second?
Basically I'm trying to calculate the correct rotation speed for the planets given their radius and amount of hours in a day. So if you were on earth, it would complete 1 rotation in 24 hours. Here's the function that I wrote that's doing the calculation now:
/* In a day */
function calculateRotationSpeed(radius,hrs,delta) {
var cir = findCircumference(radius);
if(delta) {
var d = delta;
} else {
var d = 1;
}
var ms = hrs2ms(hrs) * d;
var pxPerMS = km2px(cir) / ms;
return pxPerMS;
}
I gave it a try and it still seems to be moving too fast. I also need something similar to calculate orbit speeds.
Rotation and Units
Rotation in Three.JS is measured in radians. For those that are completely unfamiliar with radians (a small excerpt from an old paper of mine):
Like the mathematical constant Pi, a radian (roughly 57.3 degrees) is derived from the relationship between a circle's radius (or diameter) and its circumference. One radian is the angle which will always span an arc on the circumference of a circle which is equal in length to the radius of that same circle (true for any circle, regardless of size). Similarly, Pi is the ratio of circumference over diameter, such that the circumference of the unit circle is precisely Pi. Radians and degrees are not actually true units, in fact angles are in general dimensionless (like percentages and fractions, we do not use actual units to describe them).
However, unlike the degree, the radian was not defined arbitrarily, making it the more natural choice in most cases; often times being much easier and much more elegant, clear, and concise than using degrees in mathematical formulae. The Babylonians probably gave us the degree, dividing their circle into 6 equal sections (using the angle of an equilateral triangle). each of these 6 sections were probably further subdivided into 60 equal parts given their sexagesimal (base 60) number system. This would also allow them to use such a system for astronomy because the estimated number of days in a year was much less accurate during their time and was often considered 360.
Basic Rotation in Three.JS
So now, knowing you're working in radians, if you increment the rotation of an object by 1 you will be incrementing the rotation of the object by one radian. For example, consider making the following calls in the callback to requestAnimationFrame:
mesh.rotation.x += 1; // Rotates by 1 radian per frame
mesh.rotation.x += Math.PI / 180; // Rotates by 1 degree per frame
mesh.rotation.x += 45 * Math.PI / 180 // Rotates by 45 degrees per frame
As the above examples show, we can easily convert a value in degrees into a value in radians by multiplying by a constant factor of Math.PI / 180.
Taking Framerate Into Account
In your case, you will also need to take into consideration how much time passes with each frame. This is your delta. Think about it like this: What framerate are we running at? We'll declare a global clock variable which will store a THREE.Clock object which has an interface to the information we require:
clock = new THREE.Clock();
Then, in the callback to requestAnimationFrame, we can use clock to get two values that will be useful for our animation logic:
time = clock.getElapsedTime(); // seconds since clock was instantiated
delta = clock.getDelta(); // seconds since getDelta was last called
The delta value is meant to represent the time between each frame. However, note that this is only true when clock.getDelta is called consistently, exactly once in the same place somewhere within the callback to requestAnimationFrame. If clock.getDelta somehow gets called more than once or is called inconsistently it's going to screw things up.
Rotating With A Delta Factor
Now, if your scene doesn't bog down the processor or the GPU, then Three.JS and it's included requestAnimationFrame will try to keep things running at a smooth 60 frames per second. This means that ideally we will have approximately 1/60 = .016666 seconds between each frame. This is your delta value which can be obtained by calling clock.getDelta each frame.
We can use the delta value to decouple the rate at which we animate objects by multiplying as shown below. In this case, multiplying by delta will allow us to update our rotation at a rate defined in terms of seconds (as opposed to updating the rotation per frame as we did before). Multiplying by the delta value will also allow us to smoothly animate objects at a constant velocity without being effected by any small variations in the framerate from frame to frame and will even maintain that velocity even in the case that the framerate drops below the target 60fps (for example 30FPS, 45FPS, etc).
So, the examples we considered previously now become:
mesh.rotation.x += delta * 1; // Rotates 1 radian per second
mesh.rotation.x += delta * Math.PI / 180; // Rotates 1 degree per second
mesh.rotation.x += delta * 45 * Math.PI / 180; // Rotates 45 degrees per second
Rotational Speed and Units
Because radians and degrees are not actually units defined in terms of distance/size), then when we we calculate our rotational speed (angular velocity) you'll see that it is going to be a function only of time and is not dependent on the radius as in your code.
Calculating Rotational Speeds Based On Time
For example, you don't need the radius of a planet to calculate its angular velocity, instead you can calculate it using only the number of hours in a day or the amount of time it takes for the planet to complete a single revolution (ie. the duration it takes for the planet to rotate 2 * PI radians on it's axis).
If we assume that the Earth has exactly 24 hours = 24 * 60 * 60 = 86,400 seconds in a day (it doesn't). Then, given that there are 2 * PI radians in a complete revolution (360 deg), we can calculate the Earth's constant angular velocity in radians as:
radsPerRevolution = 2 * Math.PI;
secsPerRevolution = 24 * 60 * 60;
angularVelocity = radsPerRevolution / secsPerRevolution ; // 0.0000727 rad/sec
The above only needs to be calculated once, outside of the callback to requestAnimationFrame, as the value never changes. You could probably find textbook values that will be more accurate than this (taking into account a more accurate measurement than our 24 hour flat figure for the amount of time it takes for Earth to complete a revolution).
At this point, rotating our mesh with the same angular velocity as Earth would be as simple as updating its rotation every frame by incrementing its value by delta multiplied by the constant angularVelocity. If angularVelocity is defined as above, this can be done by calling the following in the callback to requestAnimationFrame:
mesh.rotation.x += delta * angularVelocity;
In Conclusion
I wouldn't worry about making sure you have all of the angular velocities for the planets exactly correct. Instead, a better idea might be to work out what the ratios between each of the angular velocities (of the planets) are and use those. This might work better since it will allow you to speed up or slow down the animation as desired, and as when working with any model (particularly astronomical models) the most important thing is that you keep it to scale, not necessarily, the scale doesn't necessarily have to be 1:1.
I am writing a drawing program, Whyteboard -- http://code.google.com/p/whyteboard/
I have implemented image rotating functionality, except that its behaviour is a little odd. I can't figure out the proper logic to make rotating the image in relation to the mouse position
My code is something similar to this:
(these are called from a mouse event handler)
def resize(self, x, y, direction=None):
"""Rotate the image"""
self.angle += 1
if self.angle > 360:
self.angle = 0
self.rotate()
def rotate(self, angle=None):
"""Rotate the image (in radians), turn it back into a bitmap"""
rad = (2 * math.pi * self.angle) / 360
if angle:
rad = (2 * math.pi * angle) / 360
img = self.img.Rotate(rad, (0, 0))
So, basically the angle to rotate the image keeps getting increased when the user moves the mouse. However, this sometimes means you have to "circle" the mouse many times to rotate an image 90 degrees, let alone 360.
But, I need it similar to other programs - how the image is rotated in relation to your mouse's position to the image.
This is the bit I'm having trouble with. I've left the question language-independent, although using Python and wxPython it could be applicable to any language
I'm assuming resize() is called for every mouse movement update. Your problem seems to be the self.angle += 1, which makes you update your angle by 1 degree on each mouse event.
A solution to your problem would be: pick the point on the image where the rotation will be centered (on this case, it's your (0,0) point on self.img.Rotate(), but usually it is the center of the image). The rotation angle should be the angle formed by the line that goes from this point to the mouse cursor minus the angle formed by the line that goes from this point to the mouse position when the user clicked.
To calculate the angle between two points, use math.atan2(y2-y1, x2-x1) which will give you the angle in radians. (you may have to change the order of the subtractions depending on your mouse position axis).
fserb's solution is the way I would go about the rotation too, but something additional to consider is your use of:
img = self.img.Rotate(rad, (0, 0))
If you are performing a bitmap image rotation in response to every mouse drag event, you are going to get a lot of data loss from the combined effect of all the interpolation required for the rotation. For example, rotating by 1 degree 360 times will give you a much blurrier image than the original.
Try having a rotation system something like this:
display_img = self.img.Rotate(rad, pos)
then use the display_img image while you are in rotation mode. When you end rotation mode (onMouseUp maybe), img = display_img.
This type of strategy is good whenever you have a lossy operation with a user preview.
Here's the solution in the end,
def rotate(self, position, origin):
""" position: mouse x/y position, origin: x/y to rotate around"""
origin_angle = self.find_angle(origin, self.center)
mouse_angle = self.find_angle(position, self.center)
angle = mouse_angle - origin_angle
# do the rotation here
def find_angle(self, a, b):
try:
answer = math.atan2((a[0] - b[0]) , (a[1] - b[1]))
except:
answer = 0
return answer