import ddf.minim.*;
Minim minim;
AudioPlayer player;
PImage img;
void setup() {
size(728, 546);
minim = new Minim(this);
player = minim.loadFile("Bassnectar_-_Magical_World_feat.wav");
player.play();
img= loadImage("cat-in-shades-.jpg");
}
void draw() {
image(img, 0, 0);
tint(0, 100, 150);
stroke(255);
strokeWeight(4);
float a = 0;
float angle = (2*PI) / 200;
for(int i=0; i < player.bufferSize() - 1; i++) {
//player.mix.get(i) is a value between [-1,1]
float x = 250 + cos(a) * (20 * player.mix.get(i) + 100);
float x2 = 540 + cos(a) * (20 * player.mix.get(i) + 100);
float y = 230 + sin(a) * (20 * player.mix.get(i) + 100);
float y2 = 240 + sin(a) * (20 * player.mix.get(i) + 100);
float xFinal = 250 + cos(a+angle) * (20 * player.mix.get(i+1) + 100);
float x2Final = 540 + cos(a+angle) * (20 * player.mix.get(i+1) + 100);
float yFinal = 230 + sin(a+angle) * (20 * player.mix.get(i+1) + 100);
float y2Final = 240 + sin(a+angle) * (20 * player.mix.get(i+1) + 100);
line(x,y,xFinal,yFinal);
line(x2,y2,x2Final,y2Final);
a += angle;
}
}
void stop() {
player.close();
minim.stop();
super.stop();
}
The following code above is for creating an audio visualizer in Processing with the Minim library. For some reason I'm struggling to see how a circle is formed within the the code's for loop.
In general I'm also trying to break down the code and get a deeper understanding for what is going on. I am confused about the following:
'float x = 250 + cos(a) * (20 * player.mix.get(i) + 100);'
Is the 20 times and plus 100 used to scale up the sample? If so then why does the circle visualizer not display when I get rid of the 20 times and just have plus 20000? Is the 250 used for placement of the start point of the line on the x-axis within the background image?
Lastly, why is the variable 'angle' needed? When I take it out I notice the visualizer is not as smooth as there looks to be a division between the quadrants.
I have been playing around with this code, and can't find too many examples with detailed explanations so any help would be appreciated. Thank you.
The first thing you need to do is understand basic trigonometry better. There are a ton of resources out there: try googling "sin cos tutorial" or "sin and cos for game development" or "sohcahtoa" for a bunch of results.
But basically, if you have a start point, a rotation, and a distance, you can figure out where the end point is using sin and cos. The basic formula for calculating an end point is this:
endX = startX + cos(rotation)*distance;
endY = startY + sin(rotation)*distance;
Your code is using this formula to find points around a circle so that it can draw lines between them to draw the circle. Each line section of the circle is 2 of the end points.
The angle variable is used to specify how far apart those points are. The smaller you make it, the more "circle-y" it will look. The larger you make it, the more you'll be able to see the straight lines that make up the circle.
It might be easier to work with a simpler example:
void setup(){
size(500, 500);
}
void draw(){
background(0);
//draw white
stroke(255);
//the start point- try changing this to mouseX and mouseY
float centerX = width/2;
float centerY = height/2;
//the distance from the start point
float radius = 100;
//how far apart the points are
float angleIncrement = 30;
//loop to go around the circle. Try changing it to 180 to see what happens.
for(float angleInDegrees = 0; angleInDegrees <= 360; angleInDegrees+=angleIncrement){
//the first "end point" is the start point of the line
float startX = centerX + cos(radians(angleInDegrees))*radius;
float startY = centerY + sin(radians(angleInDegrees))*radius;
//the second "end point" is the end point of the line
//notice that we're adding the angleIncrement to the angle to get the next point
float endX = centerX + cos(radians(angleInDegrees+angleIncrement))*radius;
float endY = centerY + sin(radians(angleInDegrees+angleIncrement))*radius;
//draw the line
line(startX, startY, endX, endY);
}
}
Related
I'm currently working on a raycaster in Java, and so far, I have the floor correctly textured. The problem, however, is that the floor doesn't scroll. In other words, when I move the camera in the projection, the floor stays the same, yet the walls move as expected. I'm really not sure what I'm doing wrong. I took almost all the code from this reference. Note that I took some liberties when pasting the code in that I used some pseudocode.
I tried applying a player offset to the tileX and tileY variables, e.g., tileX += player.x, and all I got was a floor that scrolls far too quickly and incorrectly.
for every ray:
... // other stuff relating to the walls above here.
int start = (int)(wallY + wallHeight + 1);
double directionCos = cos(rad(ray.getAngle()));
double directionSin = sin(rad(ray.getAngle()));
int textureDim = 16;
for (int y = start; y < screenHeight; y++) {
double distance = screenHeight / (2.f * y - screenHeight);
distance /= cos(rad(player.getAngle()) - rad(ray.getAngle()));
// The source I grabbed the code from actually appends the player's x and y to the tileX and tileY variables, but this completely messes up the textures when I try to.
double tileX = distance * directionCos;
double tileY = distance * directionSin;
int textureX = Math.floorMod((int)(tileX * textureDim), textureDim);
int textureY = Math.floorMod((int)(tileY * textureDim), textureDim);
int rgb = floorTexture.getRGB(textureX, textureY);
projectionFloor.setRGB((int)wallX, y, rgb);
}
Below is an image of the floor.
Below is an animation visualizing the problem.
Below is an animation visualizing what happens if I try to apply a player position offset:
Fixed it on my own. Turns out that, yes, you do have to account for the player's position (shocker!); the source I got the code from just didn't do it correctly.
DTPP = distance to projection plane.
for every pixel y from wallY + wallHeight + 1 to projectionHeight:
double r = y - this.getPreferredSize().height / 2.f;
double d = (CAMERA_HEIGHT * DTPP / r) / ANGLE;
double tileX = CAMERA_X + d * RAY_COSANGLE;
double tileY = CAMERA_Y + d * RAY_SINANGLE;
int textureX = Math.floorMod((int) (tileX * TEXTURE_SIZE /
TEXTURE_SCALE), TEXTURE_SIZE);
int textureY = Math.floorMod((int) (tileY * TEXTURE_SIZE /
TEXTURE_SCALE), TEXTURE_SIZE);
... (drawing occurs here)
I'm trying to add some distance (e.g. 10px) between a segment (arc) of the pie chart and it's center without success, here's what i've tried so far:
int value = 20; // example
double arcAngle = (value * 360 / 100);
double angle = 360 - (arcAngle / 2); // direction to add the distance to (center of arc)
double newX = pieCenterX + Math.cos(angle * Math.PI / 180.0) * 10;
double newY = pieCenterY + Math.sin(angle * Math.PI / 180.0) * 10;
// then drawing the arc with new x and y
g.fill(new Arc2D.Double(newX, newY, bounds.getWidth(), bounds.getHeight(), startAngle, arcAngle, Arc2D.PIE));
Ideally i should end up with something like that:
I don't know much on how to approach this, so my code was taken from examples i found elsewhere.
Usually zero angle is OX direction (right). So you have to make correction by 90 degrees (if your coordinate system is counterclockwise)
double angle = 90 + 360 - (arcAngle / 2);
I have a method in my android app that looks like this:
//get point after rotation
public static PointF getRotatedPoint(PointF pt,PointF center, float degrees)
{
double angleInRadians = degrees * (Math.PI / 180);
pt.x = (float) (Math.cos(angleInRadians) * (pt.x-center.x) - Math.sin(angleInRadians) * (pt.y-center.y) + center.x);
pt.y = (float) (Math.sin(angleInRadians) * (pt.x-center.x) + Math.cos(angleInRadians) * (pt.y-center.y) + center.y);
return pt;
}
I have a rectangle that I rotate by 45 degrees. I can touch any point on the rotated rectangle and it gives me the touched point I want to get the coordinates of the point if the rectangle wasn't rotated. So I pass in -45 in the degrees argument. Here is how I call it:
getRotatedPoint(touchedPoint, centerOfRectangle,-45);
When I draw the point on the rectangle before it gets rotated, it gives me a result close to the position I touched on the rotated rectangle but off by a pretty big difference.
Here is a picture to explain my problem:
I think this might be a problem with my math so any answers are greatly appreciated.
You are mixing initial and final values in the calculations. You re-assign pt.x:
pt.x = (float) (Math.cos(angleInRadians) * (pt.x-center.x) - Math.sin(angleInRadians) * (pt.y-center.y) + center.x);
which doesn't immediately pose any problems. But the calculation for pt.y relies on the original value of pt.x, not the rotated value:
pt.y = (float) (Math.sin(angleInRadians) * (pt.x-center.x) + Math.cos(angleInRadians) * (pt.y-center.y) + center.y);
Thus just use some temporary variables to hold the initial values.
public static PointF getRotatedPoint(PointF pt,PointF center, float degrees)
{
double x0 = pt.x;
double y0 = pt.y;
double angleInRadians = degrees * (Math.PI / 180);
pt.x = (float) (Math.cos(angleInRadians) * (x0-center.x) - Math.sin(angleInRadians) * (y0-center.y) + center.x);
pt.y = (float) (Math.sin(angleInRadians) * (x0-center.x) + Math.cos(angleInRadians) * (y0-center.y) + center.y);
return pt;
}
I am struggeling with the rotation of 6 points. These points rotate around a center point in the middle. But what happens is that the shapes area shrinks, and gets smaller and smaller.
The Drawing of the shape takes place on i JPanel with PaintComponent. This means that the canvas only supports integers positioning altough I can store positions in Doubles.
I use Point2D.Double for storing the points position
I Rotate all the points by 1 deegre at each function call
I think my understanding of the rotation is lacking, I can rotate 360 deegre in one call, or 180, this works fine. But 45 deegres or 90 will completely turn my points into a line(picture below).
This problem has been bothering me for a while now, but as always, I am sure there is a simple solution.
Here is the rotation Function
#Override
public synchronized void rotatePoints(int move_x, int move_y) {
// TODO Auto-generated method stub
super.rotatePoints(move_x, move_y);
BottomPanel.appendText("Area of Polygon is: " + UtilClass.calculateAreaOfPolygon(points)+ "\n");
double degrees=1.0;
double radians = degrees * (double)(Math.PI / 180.0);
//GET THE CENTER POINT C
Point2D.Double center = UtilClass.getCenterOfPolygon(points);
//ITERATE THROUGH THE POINTS
Iterator<PointClass> itr = points.iterator();
while(itr.hasNext()) {
//GET THE POINT
PointClass point_class = itr.next();
//point_class = points.get(3);
//FIRST TRANSLATE THE DIFFERENCE
double x1 = point_class.point.x - center.x;
double y1 = point_class.point.y - center.y;
//APPLY ROTATION MATRIX
x1 = (x1 * Math.cos(radians)) - (y1 * Math.sin(radians));
y1 = (x1 * Math.sin(radians)) + (y1 * Math.cos(radians));
//TRANSLATE BACK
point_class.point.setLocation(x1 + center.x, y1 + center.y);
//ADD THE DEEGRES TO POINT CLASS
point_class.angle += Math.toDegrees(radians);
}
}
Here is the code for retriving a center location of a given polygon
public synchronized static Point2D.Double getCenterOfPolygon(List<PointClass> points) {
//GETTING THE CENTER OF A COMPLEX POLYGON
double combined_x = 0;
double combined_y = 0;
Iterator<PointClass> itr = points.iterator();
while(itr.hasNext()) {
PointClass point_class = itr.next();
//ADD TO THE
combined_x += point_class.point.x;
combined_y += point_class.point.y;
}
double center_x = combined_x / (double)points.size();
double center_y = combined_y / (double)points.size();
return new Point2D.Double(center_x, center_y);
}
Here is a picture of the shape rotating all its points by 1 deegre clockwise
After each rotation I output the area of the polygon
here is the result
Area of Polygon is: 6290
Area of Polygon is: 6288
Area of Polygon is: 6286
Area of Polygon is: 6284
Area of Polygon is: 6283
Area of Polygon is: 6281
Here is a picture of the shape rotating all its points by 90 deegre clockwise after one call.
It clearely does not want to do that.
I would be glad for any suggestions or tips.
The error lies here:
//APPLY ROTATION MATRIX
x1 = (x1 * Math.cos(radians)) - (y1 * Math.sin(radians));
y1 = (x1 * Math.sin(radians)) + (y1 * Math.cos(radians));
x1 is being updated too early, such that y1 is calculated based on the new value of x1 instead of the old value.
You could change it to something like this:
//APPLY ROTATION MATRIX
double temp;
temp = (x1 * Math.cos(radians)) - (y1 * Math.sin(radians));
y1 = (x1 * Math.sin(radians)) + (y1 * Math.cos(radians));
x1 = temp;
I have a circle being drawn at a certain position. I can move it just fine with speed set to 10f but when it starts to circle it becomes extremely fast. Its obviously not moving at (units/second) I'm not sure whats going on. I thought that the archSpeed needed to be in radians or something, that slowed it down - still not right though.
Here's the Circle Arc Equation I'm basing off of:
s = r * theta
Here are the functions I'm using:
private void moveOut(double deltaTime)
{
SetPosition(x += direction * speed * deltaTime, y, 0);
if (x - (direction * GetWidth() / 2f) >= centerX + radius + GetWidth() / 2f)
{
//onOutside = true;
}
Log.d(TAG, "moving out");
}
private void circleCenter(double deltaTime)
{
float angleSpeed = (float) (radius * (speed * Math.PI / 180) * deltaTime);
currentAngle += angleSpeed;
if (currentAngle >= 2 * Math.PI)
{
currentAngle = (float) (2 * Math.PI - currentAngle);
}
SetPosition(centerX + radius * FloatMath.cos(currentAngle), centerY + radius * FloatMath.sin(currentAngle), 0);
}
Your angleSpeed formula looks wrong.
I'd work it out first by saying What is the distance I travel in that time. The answer as you already know is speed*deltaTime. Now you have a distance you can work out the angle by using the arc forumla that says arclength = radius*angle. So angle = arclength/radius.
Put these two together to get
angle = speed*deltaTime/radius
This will be in radians of course.
Essentially this boils down to the fact you were multiplying by radius instead of dividing by it (looking at it in terms of units would have helped spot this but that is outside the scope of a programming forum).