Distance in 3D - Why does my cube have holes [duplicate] - python

This question already has answers here:
Pygame rotating cubes around axis
(1 answer)
Does PyGame do 3d?
(13 answers)
Depth issue with 3D graphics
(1 answer)
Close range 3d display messed up
(1 answer)
Closed 2 years ago.
Okay, so me and a friend are attempting to create a 3D engine of sorts and we've recently made our way past all the preliminary bugs. At last, we managed to get a block of dirt rendered (I'd post an image but I don't yet have enough reputation). Now, however, we are running into some more problems and this time we have no idea what's wrong.
See, when you move to the either side of the block, holes begin randomly developing in the faces. Example, example. I suppose I ought to explain how our rendering works - we're using Pygame (without any real 3D library, that's kinda the point), and couldn't figure out how we should transform images when moving about in 3D space. So, we decided to split all the pixels into separate Tile classes and render them as polygons with color - much easier, just have to calculate the vertices instead of mapping an image. The way we make sure holes like these don't happen is by sorting them all according to distance from the camera, and rendering in that order.
At some point we'll implement optimizations like backface culling, but until then we have this big problem: our distance function doesn't seem to be working properly!
Here's what we have to calculate distance:
def pointdist(self, point):
return (self.x - point[0]) * (self.x - point[0]) + (self.y - point[1]) * (self.y - point[1]) + (self.z - point[2]) * (self.z - point[2])
We have a list master_buffer that holds all the tiles, and puts the ones to be rendered in draw_buffer - right now, that's all of them, because we don't have any filtering or optimizations implemented yet.
for tile in self.master_buffer:
self.draw_buffer.append(tile)
self.draw_buffer.sort(key=(lambda tile: c.pointdist(tile.center)))
After that, we just go through draw_buffer, calculate, and render. That's all the filtering we're doing, so we can't fathom why it'd form such holes.
If you need additional examples or parts of the code, feel free to ask. Advice on our method in general is also welcome.
RESPONSES:
In response to calculating the sum twice, I'm
doing this for performance - I've read that multiplication is
significantly faster than exponents in python when the exponent is
small, so that is what I am doing.
In response to my question not being clear enough, I am trying to figure out why there are holes in my cube. That is made quite clear, in my opinion.
In response to not having square roots, that's because I don't need the distance, I need to compare distances. If a > b, then sqrt(a) > sqrt(b) always, so leaving out sqrt will improve performance.
c, my camera, is not inside the cube when this is happening. The drawing code performs the calculations, and immediately renders - nothing can happen in between.
EDITS:
I think it may be helpful for everyone to know that the only angle at
which there are no problems is when viewing top and front faces - any
other faces viewed, and things will start falling apart.
Also, if it helps, the axes are: +x to the right, +y going backwards, and +z downward.
Seeing as no one has been able to find a problem, we will attempt to take the approach of calculating distance for each face rather than individual tiles. It will mean we are locked into using cubes, but that's the best route for now.

Related

Using OpenCV to calculate relative angle to a square

Let's say I have a square whose dimensions I know. I have a camera that will likely move around and encounter the square at different angles. I want to calculate the angle at which my camera is pointing at the square.
I know the coordinates of the 4 corner points, and I can calculate all side lengths as seen from the camera (unit is pixels). The point is, I have no problem detecting the square.
The following diagrams will give you an idea of what I mean:
view from camera. Note the distortion of the square causing one side length to be different
view from above, showing angle I am trying to calculate. The grey line is the trajectory of vision of the camera.
I asked on Math SE thinking there might be a mathematical way of doing this by measuring the heights of the two sides of the square. The answer gave me some insight, but it is extremely complicated.
When I asked ChatGPT this question, it appeared to give me a much simpler answer, though incomplete. It suggested that I use a combination of getPerspectiveTransform and decomposeProjectionMatrix to get the desired angles. The answer was grossly incomplete though, so it was only an inspiration.
My question is, how should this be accomplished with perspective transform? Or, if that is the wrong approach altogether, how should this problem be approached?

How to draw smooth contour/level curves of multivariable functions

G'day programmers and math enthusiasts.
Recently I have been exploring how CAS graphing calculators function; in particular, how they are able to draw level curves and hence contours for multivariable functions.
Just a couple of notes before I ask my question:
I am using Python's Pygame library purely for the window and graphics. Of course there are better options out there but I really wanted to keep my code as primitive as I am comfortable with, in an effort to learn the most.
Yes, yes. I know about matplotlib! God have I seen 100 different suggestions for using other supporting libraries. And while they are definitely stunning and robust tools, I am really trying to build up my knowledge from the foundations here so that one day I may even be able to grow and support libraries such as them.
My ultimate goal is to get plots looking as smooth as this:
Mathematica Contour Plot Circle E.g.
What I currently do is:
Evaluate the function over a grid of 500x500 points equal to 0, with some error tolerance (mine is 0.01). This gives me a rough approximation of the level curve at f(x,y)=0.
Then I use a dodgy distance function to find each point's closest neighbour, and draw an anti-aliased line between the two.
The results of both of these steps can be seen here:
First Evaluating Valid Grid Points
Then Drawing Lines to Closest Points
For obvious reasons I've got gaps in the graph where the next closest point is always keeping the graph discontinuous. Alas! I thought of another janky work around. How about on top of finding the closest point, it actually looks for the next closest point that hasn't already been visited? This idea came close, but still doesn't really seem to be even close to efficient. Here are my results after implementing that:
Slightly Smarter Point Connecting
My question is, how is this sort of thing typically implemented in graphing calculators? Have I been going about this all wrong? Any ideas or suggestions would be greatly appreciated :)
(I haven't included any code, mainly because it's not super clear, and also not particularly relevant to the problem).
Also if anyone has some hardcore math answers to suggest, don't be afraid to suggest them, I've got a healthy background in coding and mathematics (especially numerical and computational methods) so here's me hoping I should be able to cope with them.
so you are evaluating the equation for every x and y point on your plane. then you check if the result is < 0.01 and if so, you are drawing the point.
a better way to check if the point should be drawn is to check if one of the following is true:
(a) if the point is zero
(b) if the point is positive and has at least one negative neighbor
(c) if the point is negative and has at least one positive neighbor
there are 3 problems with this:
it doesn't support any kind of antialisasing so the result will not look as smooth as you would want
you can't make thicker lines (more then 1 pixel)
if the 0-point line is only touching (it's positive on both sides and not positive on one, negative on the other)
this second solution may fix those problems but it was made by me and not tested so it may or may not work:
you assign the value to a corner and then calculate the distance to the zero line for each point from it's corners. this is the algorithm for finding the distance:
def distance(tl, tr, bl, br): # the 4 corners
avg = abs((tl + tr + bl + br) / 4) # getting the absolute average
m = min(map(abs, (tl + tr + bl + br))) # absolute minimum of points
if min == 0: # special case
return float('inf')
return avg / m # distance to 0 point assuming the trend will continue
this returns the estimated distance to the 0 line you can now draw the pixel e.g. if you want a 5-pixel line, then if the result is <4 you draw the pixel full color, elif the pixel is <5 you draw the pixel with an opacity of distance - 4 (*255 if you are using pygames alpha option)
this solution assumes that the function is somewhat linear.
just try it, in the worst case it doesn't work...
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.30.1319&rep=rep1&type=pdf
This 21 Page doc has everything I need to draw the implicit curves accurately and smoothly. It even covers optimisation methods and supports bifurcation points for implicit functions. Would highly recommend to anyone with questions similar to my own above.
Thanks to everyone who had recommendations and clarifying questions, they all helped lead me to this resource.

How to space carve in Python?

This question is likely to be more about the right terminology and subjects to search for more than anything else. It feels like a simple enough concept to the point where tools should be available in Python/NumPy to do it, but I just have no idea what to look for.
I recently watched a video on Space Carving and I would like to implement the basic concept using video game sprites to attempt voxelizing them. I have sprites of characters from 8 equally spaced angles (front on, camera 45 degress right, fully right, back, etc.)
I haven't found a library dedicated to this concept, but I think it should be fairly simple to implement. My thinking is I can make a 3D array that is the max size of the sprite in all dimensions that is a solid block of "clay". Then I need a 2D representation of that 3D array at each rotation angle. For each pixel in that representation I need to be able to iterate down into the 3D array each block that a "laser" fired from that position would hit.
The first step would be removing the clay where the sprite is just alpha layer, (aka setting a bool to false). The next would be "painting" the shape where possible.
The problem is I just have no idea what mathematical or programmatic terms are associated with these concepts. I could get so far as to make a 3D block of clay. But how do I get 2D representations of a 3D array at several rotated angles about one axis that I can essentially fire lasers at?

Ball-Line Collision Bounce Angles Python

I'm writing a program wherein the user creates lines (represented as (x1,y1,x2,y2)) that balls subject to gravity bounce off . These lines are therefor not necessarily horizontal. I've been having trouble with getting the correct bounce angles. I found sources that provided a good method but in order to use it I need to find the line's bounce angle.
Obviously there are two possible normal vectors but I need the one that faces towards the side of the ball collision. The only problem is that I need to use Tkinter in my program and because of the timestep my collision detection works in a way that sometimes lets the ball dip slightly past the line before the collision is detected. So I can't just use the center of the ball (cx, cy) to determine the correct normal vector. I'm probably overcomplicating this in my head, but I'm having trouble coming up with a solution. I think it needs to involve the incident velocity vector (vx, vy) of the ball on collision, but I'm not sure how.
Any ideas would be GREATLY appreciated!!
The correct normal vector to use is the one such that n scalar v = n.x v.x + n.y v.y is negative. Indeed, scalar product is positive when two vectors are globally in the same direction. So wanting it to be negative means you will have two opposite-pointing vectors, which is exactly what you want.
However, you cannot define such a normal vector on angles, so I do not know how you programmed your algorithm but be careful with this edge case.

Pygame: moving and rotating images from center point [duplicate]

This question already has answers here:
How do I rotate an image around its center using Pygame?
(6 answers)
How to rotate an image(player) to the mouse direction?
(2 answers)
Closed 2 years ago.
I'm making a heads-up display, similar to what you'd find in a fighter jet (http://i1.ytimg.com/vi/RYjBjT79hLo/hqdefault.jpg).
Some of the elements just stay in one place on the screen, like the airspeed and altitude. That's easy.
The part I'm having trouble with is the pitch ladder (the bars that show 5, 10, 15, etc degrees above/below the horizon) and horizon line. The way I'm trying to implement it is to have a png file that has all the bars from -90 to +90 already created. This file is much much larger in resolution than my display window, so only the bars that correspond to the current pitch, +/-10 degrees, are displayed on the screen. As the user pitches up, the image moves down, and vice versa. As the drift angle increases (the angle between the heading and the velocity vector, ie, sideslip), the HUD moves left or right. The problem is in rotation. I'd like to be able to specify the location of the center point of the image and the rotation angle, not just the top left corner, and have pygame render it appropriately. I'm not quite clear on exactly how rects work though, which is part of the problem.
My math background tells me the easiest way to do this would be to get an array of each pixel value on the screen, then multiply by a transformation matrix based on the pitch and roll, but I don't think pygame actually lets you access that low-level information.
[EDIT] On second thought, a pixel array may not be easiest. A transformation matrix edits the values of each element in the array, but a pixel array contains RGB information in each element. A transformation matrix would just edit the color of each pixel, not actually transform them. hmmmm.... [/EDIT]
It seems like pygame really really wants everything to be boxed up in rectangles that are parallel to the screen borders, which is kind of a problem for a rolling aircraft. I've thought about using OpenGL instead, but that seems overkill. Can anyone help me do this in pygame? Thanks!

Categories

Resources