I need to calculate a triangle and saw wave but it is a little complicate because of my model and the data I'm able to work with (but maybe I'm just confused).
I'm able to calculate my sine wave but I'm not really using a frame counter. What I do is, calculate a theta_increment variable which I can use the next time I need to calculate a sample. This works like this:
float x = note.frequency / AppSettings::sampleRate;
float theta_increment = 2.0f * M_PI * x;
float value = 0;
if(waveType == SINE){
value = sin(note.theta) * fixedAmplitude;
}
Now that I have the value of the currend frame/sample I store theta_increment inside my note.theta member so I can use it for the next sample:
note.theta += theta_increment;
I've looked at tons of examples on how I should calculate a saw or a triangle but I can't figure it out. (I only have the data mentioned above at my disposal) This is my last attempt but it's not working and giving me tons of glitches:
value = 1.0f - (2.0f * ((float)note.theta / (float)44100));
If you have a loop generating your values like this:
for (size_t frame=0; frame!=n_frames; ++frame) {
float pos = fmod(frequency*frame/sample_rate,1.0);
value[frame] = xFunc(pos)*fixedAmplitude;
}
Then you can use these functions for different types of waves:
float sinFunc(float pos)
{
return sin(pos*2*M_PI);
}
float sawFunc(float pos)
{
return pos*2-1;
}
float triangleFunc(float pos)
{
return 1-fabs(pos-0.5)*4;
}
The basic idea is that you want a value (pos) that goes from 0.0 to 1.0 over each cycle. You can then shape this however you want.
For a sine wave, the sin() function does the job, you just need to multiply by 2*PI to convert the 0.0 to 1.0 range into a 0.0 to 2*PI range.
For a sawtooth wave, you just need to convert the 0.0 to 1.0 range into a -1.0 to 1.0 range. Multiplying by two and subtracting one does that.
For a triangle wave, you can use the absolute value function to cause the sudden change in direction. First we map the 0.0 to 1.0 range into a -0.5 to 0.5 range by subtracting -0.5. Then we make this into a 0.5 to 0.0 to 0.5 shape by taking the absolute value. By multiplying by 4, we convert this into a 2.0 to 0.0 to 2.0 shape. And finally by subtracting it from one, we get a -1.0 to 1.0 to -1.0 shape.
A sawtooth wave could be calculated like this:
value = x - floor(x);
A triangle could be calculated like this:
value = 1.0 - fabs(fmod(x,2.0) - 1.0);
where x is note.theta.
Related
I've been trying to make one object orbiting another:
//childX,childY,childZ are my starting coordinates
//here I count distance to the middle of my coordinate plane
float r = (float) Math.sqrt(Math.pow(childX, 2)+Math.pow(childY, 2)+Math.pow(childZ,2));
//here i convert my angles to radians
float alphaToRad = (float) Math.toRadians(findParent(figure.parentId).rotate[1]);//up_down
float betaToRad = (float) Math.toRadians(findParent(figure.parentId).rotate[0]);//left_right
float newX = (float) (r*Math.cos(betaToRad)*Math.cos(alphaToRad));
float newY = (float) (r*Math.cos(betaToRad)*Math.sin(alphaToRad));
float newZ = (float) (r*Math.sin(betaToRad));'
I have coordinates of my starting point(5,5,0) and angles 0° and 0°, so it means, that coordinates shouldn't change after calculating the new ones. But the result is:
newX: 7.071068 newY: 0.0 newZ: 0.0
Every method I try to calculate new coordinates there is always this strange result. What is that 7.07 and how can I get correct result?
#edit
To make my new point relative to the old one I just added angles of old point to the new one:
float alphaToRad = (float) Math.toRadians(findParent(figure.parentId).rotate[1]) + Math.atan(childY/childX);
float betaToRad = (float) Math.toRadians(findParent(figure.parentId).rotate[0]) + Math.asin(childZ/r);
Everything now works like it should have. Solved
7.07 is the value of r in your code, which is the distance of your point from the origin:
sqrt(5 * 5 + 5 * 5) = sqrt(50) = 7.0711
With both angles being zero, all the cos() values will be 1.0, and the sin() values 0.0. Which means that newX becomes r, which is 7.07, and both newY and newZ become 0.0. Which is exactly what you got, so there is no mystery in this result.
What you're basically doing is place the point at a given direction and distance from the origin. The distance is the same as the original distance. The direction is given by the two angles, where both angles being 0.0 corresponds to the x-axis direction.
In other words, what you're missing is that you're not taking the original direction of the point relative to the origin into account. You're placing the point at an absolute direction, based on the two angles, instead of at a direction relative to the original direction of the point.
To rotate the point by the given angles, the easiest approach is to build rotation matrices from the angles, and apply them to your points.
I'm having an issue with floating point arithmetic in c++ (using doubles) that I've never had before, and so I'm wondering how people usually deal with this type of problem.
I'm trying to represent a curve in polar coordinates as a series of Point objects (Point is just a class that holds the coordinates of a point in 3D). The collection of Points representing the curve are stored in a vector (of Point*). The curve I'm representing is a function r(theta), which I can compute. This function is defined on the range of theta contained in [0,PI]. I am representing PI as 4.0*atan(1.0), storing it as a double.
To represent the surface, I specify the desired number of points (n+1), for which I am currently using n=80, and then I determine the interval in theta required to divide [0,PI] into 80 equal intervals (represented by n+1=81 Points). So dTheta = PI / n. dTheta is a double. I next assign coordinates to my Points. (See sample code below.)
double theta0 = 0.0; // Beginning of inteval in theta
double thetaF = PI; // End of interval in theta
double dTheta = (thetaF - theta0)/double(nSegments); // segment width
double theta = theta0; // Initialize theta to start at beginning of inteval
vector<Point*> pts; // Declare a variable to hold the Points.
while (theta <= thetaF)
{
// Store Point corresponding to current theta and r(theta) in the vector.
pts.push_back(new Point(theta, rOfTheta(theta), 0.0));
theta += dTheta; // Increment theta
}
rofTheta(theta) is some function that computes r(theta). Now the problem is that the very last point somehow doesn't satisfy the (theta <= thetaF) requirement to enter the loop one final time. Actually, after the last pass through the loop, theta is very slightly greater than PI (it's like PI + 1e-15). How should I deal with this? The function is not defined for theta > PI. One idea is to just test for ((theta > PI) and (theta < (PI+delta))) where delta is very small. If that's true, I could just set theta=PI, get and set the coordinates of the corresponding Point, and exit the loop. This seems like a reasonable problem to have, but interestingly I have never faced such a problem before. I had been using gcc 4.4.2, and now I'm using gcc 4.8.2. Could that be the problem? What is the normal way to handle this kind of problem? Thanks!
Never iterate over a range with a floating point value (theta) by adding increments if you have the alternative of computing the next value by
theta = theta0 + idx*dTheta.
Control the iteration using the integer number of steps and compute the float as indicated.
If dTheta is small compared to the entire interval, you'll accumulate errors.
You may not insert the computed last value of the range[theta0, thetaF]. That value is actually theta = theta0 + n * (dTheta + error). Skip that last calculated value and use thetaF instead.
What I might try:
while (theta <= thetaF)
{
// Store Point corresponding to current theta and r(theta) in the vector.
pts.push_back(new Point(theta, rOfTheta(theta), 0.0));
theta += dTheta; // Increment theta
}
if (theta >= thetaF) {
pts.push_back(new Point(thetaF, rOfTheta(thetaF), 0.0));
}
you might want to cehck the if statement with pts.length() == nSegments, just experiment and see which produces the better results.
If you know that there would be 81 values of theta, then why not run a for loop 81 times?
int i;
theta = theta0;
for(i = 0; i < nSegments; i++) {
pts.push_back(new Point(theta, rOfTheta(theta), 0.0));
theta += dTheta;
}
First of all: get rid of the naked pointer :-)
You know the number of segments you have, so instead of using the value of theta in the while-block:
for (auto idx = 0; idx != nSegments - 1; ++idx) {
// Store Point corresponding to current theta and r(theta) in the vector.
pts.emplace_back(theta, rOfTheta(theta), 0.0);
theta += dTheta; // Increment theta
}
pts.emplace_back(thetaF, /* rOfTheta(PI) calculated exactly */, 0.0);
for (int i = 0; i < nSegments; ++i)
{
theta = (double) i / nSegments * PI;
…
}
This:
produces the correct number of iterations (since the loop counter is maintained as an integer),
does not accumulate any error (since theta is calculated freshly each time), and
produces exactly the desired value (well, PI, not π) in the final iteration (since (double) i / nSegments will be exactly one).
Unfortunately, it contains a division, which is typically a time-consuming instruction.
(The loop counter could also be a double, and this will avoid the cast from to double inside the loop. As long as integer values are used, the arithmetic for it will be exact, until you get beyond 253 iterations.)
I am trying to experiment with pixel shaders in WPF, and I want to try out this code:
-1.0 + 2.0 * gl_FragCoord.xy / resolution.xy
But I am not sure what range of values that would produce. I am applying mine to image as a filter and I have access to u and v values [0-1]. When I do this:
-1.0 + 2.0 * {U,V};
I am not getting the same result. I know the above also must be a normalized value range but not sure if -1 to 1, or 0 to 1, etc.
Any ideas?
gl_FragCoord.xy / resolution.xy gives you the range [0,1].
Multiplying by 2 gives you the range [0,2].
Substracting 1 gives you the range [-1,1]
example:
http://glsl.heroku.com/e#7712.0
reading through this like a compiler would. -1.0 + 2.0 get's reduced to 1.0. The statment then becomes 1.0 * glFragCoord.xy / resolution.xy. 1 * x = x, given that, the equastion then becomes glFragCoord.xy / resolution.xy.
In effect, you're going to wind up with a range of [0, 1/resolution].
If What you mean the equasion to be is -1.0 + (2.0 * glFragCoord.xy / resolution.xy) then you have [0, 2/resolution], subracting 1 becomes [-1, (2/resolution)-1].
I am building a ray Tracer from scratch. My question is:
When I change camera coordinates the Sphere changes to ellipse. I don't understand why it's happening.
Here are some images to show the artifacts:
Sphere: 1 1 -1 1.0 (Center, radius)
Camera: 0 0 5 0 0 0 0 1 0 45.0 1.0 (eyepos, lookat, up, foy, aspect)
But when I changed camera coordinate, the sphere looks distorted as shown below:
Camera: -2 -2 2 0 0 0 0 1 0 45.0 1.0
I don't understand what is wrong. If someone can help that would be great!
I set my imagePlane as follows:
//Computing u,v,w axes coordinates of Camera as follows:
{
Vector a = Normalize(eye - lookat); //Camera_eye - Camera_lookAt
Vector b = up; //Camera Up Vector
m_w = a;
m_u = b.cross(m_w);
m_u.normalize();
m_v = m_w.cross(m_u);
}
After that I compute directions for each pixel from the Camera position (eye) as mentioned below:
//Then Computing direction as follows:
int half_w = m_width * 0.5;
int half_h = m_height * 0.5;
double half_fy = fovy() * 0.5;
double angle = tan( ( M_PI * half_fy) / (double)180.0 );
for(int k=0; k<pixels.size(); k++){
double j = pixels[k].x(); //width
double i = pixels[k].y(); //height
double XX = aspect() * angle * ( (j - half_w ) / (double)half_w );
double YY = angle * ( (half_h - i ) / (double)half_h );
Vector dir = (m_u * XX + m_v * YY) - m_w ;
directions.push_back(dir);
}
After that:
for each dir:
Ray ray(eye, dir);
int depth = 0;
t_color += Trace(g_primitive, ray, depth);
After playing a lot and with the help of the comments of all you guys I was able to create successfully my rayTracer properly. Sorry for answering late, but I would like to close this thread with few remarks.
So, the above mentioned code is perfectly correct. Based on my own assumptions (as mentioned in above comments) I have decided to set my Camera parameters like that.
The problem I mentioned above is a normal behaviour of the camera (as also mentioned above in the comments).
I have got good results now but there are few things to check while coding a rayTracer:
Always make sure to take care of Radians to Degrees (or vice versa) conversion while computing FOV and ASPECT RATIO. I did it as follows:
double angle = tan((M_PI * 0.5 * fovy) / 180.0);
double y = angle;
double x = aspect * angle;
2) While computing Triangle intersections, make sure to implement cross product properly.
3) While using intersections of different objects make sure to find the intersection which is at a minimum distance from the camera.
Here's the result I got:
Above is a very simple model (courtesy UCBerkeley), which I rayTraced.
This is the correct behavior. Get a camera with a wide angle lens, put the sphere near the edge of the field of view and take a picture. Then in a photo app draw a circle on top of the photo of the sphere and you will see that it's not a circular projection.
This effect will be magnified by the fact that you set aspect to 1.0 but your image is not square.
A few things to fix:
A direction vector is (to - from). You have (from - to), so a is pointing backward. You'll want to add m_w at the end, rather than subtract it. Also, this fix will rotate your m_u,m_v by 180 degrees, which will make you about to change (j - half_w) to (half_w - j).
Also, putting all the pixels and all the directions in lists is not as efficient as just looping over x,y values.
I'm in a strange situation where I have a value of 0.5 and I want to convert the values from 0.5 to 1 to be a percentage and from 0.5 to 0 to be a negative percentage.
As it says in the title 0.4 should be -20%, 0.3 should be -40% and 0.1 should be -80%.
I'm sure this is a simple problem, but my mind is just refusing to figure it out :)
Can anyone help? :)
What we want to do is to scale the range (0; 1) to (-100; 100):
percentage = (value - 0.5) * 200;
The subtraction transforms the value so that it's in the range (-0.5; 0.5), and the multiplication scales it to the range of (-100; 100).
percent = ((value - 0.5) / 0.5) * 100
This will generate from -100 to 100. You want to subtract your zero value (0.5) from the given value, and divide by the range that should give 100% (also 0.5 in your example). Then multiply by 100 to convert to percentage.
Normalize it, and you're done:
// Assuming x is in the range (0,1)
x *= 2.0; // x is in the range (0,2)
x -= 1.0; // (-1,1)
x *= 100; // (-100,100)