I have two objects: one is a ball, whose velocity is given by a vector of components velocity.x and velocity.y, such that, at every frame, the (x, y) position of the ball gets updated to (x + velocity.x, y + velocity.y); the other is a very thin horizontal rectangle that cannot move. Of course, I'd love the ball to change its trajectory whenever it hits the rectangle either from above or from below.
However, I've run into a problem I don't know how to fix: whenever the ball travels fast enough to go from one side of the rectangle to the other side in just one frame, the collision isn't detected because the ball never actually comes in contact with the rectangle. Being the rectangle very thin, the minimum velocity beyond which this behaviour occurs isn't even too high.
I know this is a problem that usually occurs when you want to keep an object inside the screen: in fact, if you just change the sign of its velocity as soon as it exits the screen, this doesn't necessarily make your object rebound off the side of the window (because it could travel so fast that a part of it gets stuck outside the edge), so you actually have to reposition it inside the window first, and then change the sign of its velocity accordingly. But I cannot use this trick here, because the behaviours of the ball on the two sides of the rectangle are supposed to be different: if the ball hits it from above, it will bounce upwards; if from below, it will bounce downwards. But when the ball manages to go past the rectangle in just one frame, how can I tell the program which side the ball should be repositioned? After all, once that frame is drawn, the program isn't able to know whether the ball came 'from the other side' of the rectangle, or if it's always been on that side.
I hope I managed to explain my problem clearly enough. What can I do to solve it?
Take the previous position of the ball and the current position of the ball, and create a line. Use that line to perform collision detection instead of the ball itself. Test for collision detection between the line and the rectangle.
This is going to be a bit more complicated than testing for collision detection between a circle and a rectangle, but googling "line rectangle collision detection" will return a ton of results. Basically you'll want to break the rectangle down into 4 lines and then check whether each line intersects your path line.
This question might help: How do you detect where two line segments intersect?
Related
I'm writing a drawing program that uses a pressure sensitive table for input. I'd like to be able to simulate the soft pencil effect that many other art programs have (such as Paint Tool SAI, Art Rage). Technique I'm using at the moment is functional, but is missing the cleanness I see in more professional programs.
My algorithm at the moment works like this:
Create a bitmap representing the head of the brush. This is just a transparent bitmap with a black circle drawn on it. The circle has an inner radius that is solid black and an outer radius. The blackness linearly fades from opaque to transparent as you move from the inner to the outer radius.
Capture input events from my tablet. Each point contains an (x, y) coordinate as well as a pressure value
For every point after the first one, draw a line from the previous point to the current one. This is done by drawing (daubing) the brush bitmap several times between the two points. The step size between each daub is chosen so there is an overlap between subsequent daubs.
This works reasonably well, but the result is a line that is somewhat blobby and jagged.
One thing I need to do is somehow smooth out the input points so that the stroke as a whole is smooth.
The other thing I need to do is figure out how to 'drag' the brush head along this path to make the stroke. If the spacing is too far apart, the stroke looks like a line of circles. If too close together, the stroke builds up on itself and becomes very dark. (I tried to fix this by attenuating the brush by the spacing. This does make things more consistent, but stops the stroke from being fully opaque).
Anyhow, I'd expect that there's a lot of research already done on this, if only I knew where to look. Please let me know if there are any better pencil drawing algorithms out there.
Instead of drawing the new circle over what has already been drawn, using the standard blending functions (so that regions of overlap get a higher opacity), you need to keep the maximum opacity so far.
Only after you have built up the complete stroke (as on a white sheet), you can blend it to the existing line art.
The picture illustrates the difference between blending and keeping the maximum opacity.
When several objects overlap on the same plane, they start to flicker. How do I tell the renderer to put one of the objects in front?
I tried to use .renderDepth, but it only works partly -
see example here: http://liveweave.com/ahTdFQ
Both boxes have the same size and it works as intended. I can change which of the boxes is visible by setting .renderDepth. But if one of the boxes is a bit smaller (say 40,50,50) the contacting layers are flickering and the render depth doesn't work anymore.
How to fix that issue?
When .renderDepth() doesn't work, you have to set the depths yourself.
Moving whole meshes around is indeed not really efficient.
What you are looking for are offsets bound to materials:
material.polygonOffset = true;
material.polygonOffsetFactor = -0.1;
should solve your issue. See update here: http://liveweave.com/syC0L4
Use negative factors to display and positive factors to hide.
Try for starters to reduce the far range on your camera. Try with 1000. Generally speaking, you shouldn't be having overlapping faces in your 3d scene, unless they are treated in a VERY specific way (look up the term 'decal textures'/'decals'). So basically, you have to create depth offsets, and perhaps even pre sort the objects when doing this, which all requires pretty low-level tinkering.
If the far range reduction helps, then you're experiencing a lack of precision (depending on the device). Also look up 'z fighting'
UPDATE
Don't overlap planes.
How do I tell the renderer to put one of the objects in front?
You put one object in front of the other :)
For example if you have a camera at 0,0,0 looking at an object at 0,0,10, if you want another object to be behind the first object put it at 0,0,11 it should work.
UPDATE2
What is z-buffering:
http://en.wikipedia.org/wiki/Z-buffering
http://msdn.microsoft.com/en-us/library/bb976071.aspx
Take note of "floating point in range of 0.0 - 1.0".
What is z-fighting:
http://en.wikipedia.org/wiki/Z-fighting
...have similar values in the z-buffer. It is particularly prevalent with
coplanar polygons, where two faces occupy essentially the same space,
with neither in front. Affected pixels are rendered with fragments
from one polygon or the other arbitrarily, in a manner determined by
the precision of the z-buffer.
"The renderer cannot reposition anything."
I think that this is completely untrue. The renderer can reposition everything, and probably does if it's not shadertoy, or some video filter or something. Every time you move your camera the renderer repositions everything (the camera is actually the only thing that DOES NOT MOVE).
It seems that you are missing some crucial concepts here, i'd start with this:
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/
About the depth offset mentioned:
How this would work, say you want to draw a decal on a surface. You can 'draw' another mesh on this surface - by say, projecting a quad onto it. You want to draw a bullet hole over a concrete wall and end up with two coplanar surfaces - the wall, the bullet hole. You can figure out the depth buffer precision, find the smallest value, and then move the bullet hole mesh by that value towards the camera. The object does not get scaled (you're doing this in NDC which you can visualize as a cube and moving planes back and forth in the smallest possible increment), but does translate in depth direction, ending up in front of the other.
I don't see any flicker. The cube movement in 3D seems to be super-smooth. Can you try in a different computer (may be faster one)? I used Chrome on Macbook Pro.
I have a general question (I know I should present specific code with a problem, but in my case the problem is of a more general nature).
In Processing, let's say I make an ellipse:
ellipse(30, 30, 10, 10);
Now, is there a way to get the pixels where this ellipse is on the canvas? The reason would be to have a way of creating user interaction with the mouse (for instance). So when someone clicks the mouse over the ellipse, something happens.
I thought of turning everything into objects and use a constructor to somehow store the position of the shape, but this is easier said than done, particularly for more complex shapes. And that is what I am interested in. It's one thing to calculate the position of an ellipse, but what about more complex shapes? Are there any libraries?
Check out the geomerative library. It has a way to check whether the mouse is inside any SVG shape. I can't remember off the top of my head but it works something like you make a shape:
myShape = RG.loadShape("shape.svg");
and a point:
RPoint p = new RPoint(mouseX, mouseY);
and the boolean function contains() will tell you if the point is inside the shape:
myShape.contains(p);
It's better to use a mathematical formula than pixel-by-pixel checking of the mouse position (it's much faster, and involves less code).
For a perfect circle, you can calculate the Euclidean distance using Pythagoras' theorem. Assume your circle is centred at position (circleX,circleY), and has a radius (not diameter) of circleR. You can check if the mouse is over the circle like this:
if(sq(mouseX-circleX)+sq(mouseY-circleY) <= sq(circleR)) {
// mouse is over circle
} else {
// mouse is not over circle
}
This approach basically imagines a right-angled triangle, where the hypotenuse (the longest side) runs from the centre of the circle to the mouse position. It uses Pythagoras' theorem to calculate the length of that hypotenuse, and if it's less than the circle's radius then the mouse is inside the circle. (It includes a slight optimisation though -- it's comparing squares to avoid doing a square root, as that can be comparatively slow.)
An alternative to my original mathematical answer also occurred to me. If you can afford the memory and processing power of drawing all your UI elements twice then you can get good results by using a secondary buffer.
The principle involves having an off-screen graphics buffer (e.g. using PGraphics). It must be exactly the same size as the main display, and have anti-aliasing disabled. Draw all your interactive UI elements (buttons etc.) to this buffer. However, instead of drawing them the normal way, give each one a unique colour which it uses for fill and stroke (don't add any text or images... just solid colours). For example, one button might be entirely red, and another entirely green. Any other RGB value works, as long as each item has a unique colour. Make sure the background has a unique colour too.
The user never sees that buffer, so don't draw it to the screen (unless you're debugging or something). When you want to detect what item the mouse is over, just lookup the mouse position on that off-screen buffer. Get the pixel colour at that location, and match it to the UI element.
After you've done all that, just go ahead and draw everything to the main display as normal.
It's worth noting that you can cut-down the processing time of this approach a lot if your UI elements never (or rarely) move. You only need to redraw the secondary buffer when something appears/disappears, animates, or changes size/position.
I'm working on a small iPhone/iPad game with the Cocos2d framework. Basically the idea of the game is very simple, there a ball which is moving at a certain speed. The user can draw a line so that the ball bounces in the opposite direction.
Now I've already have the ball moving and the user can draw a line also. (When he draw a line it becomes a member of an array and dissapears a few seconds later.)
But the question is how to detect a collision between the ball and a line? The line doesn't need to be horizontal or vertical, it can be diagonal also. It all depends on how the user draws this line.
I've the coordinates of the line: see the answer to my previous question: CGRect with an angle
Can you guys point in me right direction?
Thanks in advance!
You can use box2d to detect collisions. Actually, if your ball and these lines will have bodies in b2World, you will be able not to check collisions by yourself. All changes, bounces, etc. physics will done for you. You will only have to synchronize object's view position (also you can synchronize angle) according to the position of it's body in physical world.
You can use the Pixel perfect collision so when ball and line collide it is not check the rect but it check the pixel collision...
in this forum you got that you want..
http://www.cocos2d-iphone.org/forum/topic/18522/page/3
I'm looking to create a jog wheel in an iPhone / iPad application. I know that you can subclass UIGestureRecognizer to write your own recognizers. Does anyone know how (mainly the maths behind it) to create one that would detect a circular movement, perhaps in combination with a pan gesture?
Thanks
this question isn't easy. I spend some time thinking of a possible solution:
I think what you need are some key properties you have to set:
The center of the circular movement (in this case no problem, because you know the center of the jog wheel)
A corridor in which the movement should happen.
so you need the inner radius and the outer radius.
Now you have something like this (unfortunately I haven't got enough reputation so only the link: http://img17.imageshack.us/img17/4416/bildschirmfoto20100721u.png
Now the maths behind this starts:
First of all you arrange the corridor in four quarters:
From 0° to 90°
From 90° to 180°
From 180° to 270°
From 270° to 360°
For each quarter you have to figure out when the finger is moving (let's say that the 0°-line is from the center point straight to the top):
if the finger is in the first quarter you know if the x changes to the left that the rotation must be anti-clockwise. If the x changes to the right the rotation must be clockwise.
Apply this logic for all quarters. Now you know if the jog wheel is moved clockwise or anti-clockwise. You have to make sure, that the finger is never leaving the corridor (if you test this logic and the movement stops because of leaving the corridor, make the corridor bigger - Thanks to CrystalSkull for his comment: Use 44px as a minimum width for the corridor to apply to the Human Interface Guidelines).
Sumary
So now you can conclude that you need a center point and a corridor the finger can move in.
You have to figure out in which quarter the finger is in and find out (using the x-value) if the rotation is clockwise or anti-clockwise.
I hope this helps you a little bit.