Hey guys, I have an idea which needs your support.

Hey guys, I have an idea which needs your support. The vision is to create an illusion of „moving through 3d space“. For that I need to shift the observation plane against the projection plane in order to create an illusion of a perspective. What happens, if we shift a square in front of our eyes by 90 degrees away from us? It looks like an trapezoid, right? And if we imagine these square has an infinite size – then it looks like an triangle. So what I need to do is to render a high res square into a low res triangle.

In order to have that running fast (and because it is beyond my coding abilitys) I would love to do it without 3d vector math. I made a drawing, trying to explain to myself, what has to happen. Lets stay with an 8x8 matrix here to keep it simple. I drawed the origin square and an idea how to map that into the triangle. Every letter in the destination triangle contains the average color information from the area in the origin sqare with the same letter (in the same row).

The second drawing shows you what I will to with the triangle(s).
The 3rd drawing is about the ideal source areas for the calculated pixels in the triangle.

I would know how to explain my first drawing in C for every single pixel in the triangle, but then I can nobody show the code and the result will apper not fluid (because of differnt sizes of the source squares in one row)… And with a 16x16 or even 32x32 square it would become a zen exersize to code it.

So my question is: Do you have any idea, how to express this as a formula for x and y or as an algorythm? In horizontal direction it is like a linear interpolation from 8 to 7, 8 to 5, 8 to 3, …
Vertical I would say the sorce area is exponential increasing to maintain an illusion of speed – what is close to the eye appaers moving fast, the further away it is the slower it looks.

Thanks for any ideas, inspiration and support!

End of my longest post here so far,

Stefan

3D to 2D is not so hard — nor is the calculation that costly — I’ll dig up some stuff in a bit

That reminds me a lot of Math I had last year when I was still in school. Basically we need a projection plane wich would be the end result, and a Matrix which could be rewritten into a usuable funtion to transform the points. All that would be left is to get average color of the pixels that later share the same position. I could have another look at analytic geometry and put something together if you’d like.

I think that is called a texture mapper. There should be tons of papers out there. About the perspecive correction: you are lucky and can even replace the slow divide by a table lookup for this single use case.

OK, I worked something up for you. First, look at the diagram here: http://i.imgur.com/sOSBcdX.jpg

What I am imagining is a rectangle shrinking down to a triangle via an intermediate trapezoid. The top left and right corners of the original rectangle “trace” down an inverted isosceles triangle until the original rectangle becomes a triangle. The vanishing point is a height h_v away from the bottom of the rectangle, and the intermediate trapezoids have heigh h_i and top width w_i.

I also wrote some code to simulate this process. The code assumes a rectangle with a discrete (integer) number of LEDs on each side. The code calculates all the possible intermediate trapezoid sizes and shapes you can make given you have an integer number of LEDs. The code also outputs the indexes (based on row) for each trapezoid configuration. All you have to choose is: rectangle height/width, vanishing point, and how fast you transition from rectangle to triangle! Let me know if this code makes: sense: https://github.com/fibonacci162/LEDs/tree/master/RectangleTransformation2014

FYI: on my Uno, it takes 20 ms to calculate all the possible configurations of the trapezoid for a 60 x 60 LED grid (plenty fast and with head room for other calculations while still being able to hit 30 FPS), and 5000 ms to calculate everything for a 1000 x 1000 grid.

Reading this again after some sleep, I realize I may not have helped you much in answering your question. However, I am happy to keep at it if I can better understand what you need.

Hey, thank you a lot for thinking about it! And yes - by problem is still, to get the color information for every point in the triangle/trapezoid from the origin rectangle.

Are you really trying to turn a rectangle into a triangle, or is that just
an abstraction for what you’re really trying to do? Are you actually
wanting to “tilt” the noise patterns I keep seeing you post?

Your code will help me later to change the effect from “infinity tube effect” (triangle) to “looking trough a cube” (trapezoid).

Yes, I need the noise in a triangle. That is not an abstraction, it is the goal. I want to tilt the noise while maintaining the proportions of the content in the origin noise rectangle. I want to map the noise texture down into to a triangle.

Ok, for something to disappear into a vanishing point in a triangular shape, it has to be infinitely long. Do you want to give the impression that you’re traveling down and infinitely long hallway? Also, are you thinking of traveling towards or away from the vanishing point?

Yes, what I imagined was the illusion of a ride into an infinetely long hallway based on a quadratic texture scrolling. So traveling towards the vanishing point, but for now that does not matter, because that can be easiely adjusted by the scrolling direction of the content in the texture. It could also scroll sideways which would create a (kind of) rotating hallway. It is only about the mapping of one texture into one triangle for the beginning.

How far have you come with your work? Cuz I have some more ideas on how to achieve this.

No practical progress so far. I am very interested to hear your ideas!

Ok, I have done some more work. Since the idea is to be looking down an infinitely-long vanishing “hallway,” you would theoretically need an infinite amount of data to populate the image. However, in real life, the resolution of the image is limited by the number of LEDs you have. So, the first step is to determine how much data you need to properly fill in colors for an infinitely long hallway. I am only going to deal with the “floor” of the hallway for now, so from now on, I will call it the sidewalk.

Look at my graphic here: http://i.imgur.com/9x4cQg5.png

It is really important to orient yourself with this graphic before we go further. Don’t fuss with the equations on the graphic quite yet. The first thing to understand is that all the data is in the rectangular “matrix” on the lefthand side of the graphic. I am assuming an LED array that is 40 x 40, my matrix is 240 x 40 with each colored block of data being 40 x 40. The rectangular matrix is then tilted downwards towards a vanishing point that is a height h_v above the bottom of the LED grid (h_v = 20 pixels tall in this case).

When you zoom in on the vanishing point, it becomes clear that at some point, all the data is trying to be crammed into just a single LED pixel. There’s no point generating huge amounts of data if you can’t display it, so I arbitrarily made my cutoff to be where a full row of tilted data can only fit in one pixel. That happens at a height in the data matrix of h_r = w_0 * log(w_0) / log(2). Plugging in 40 for w_0, we get that h_r = 212. So, if you have a rectangular matrix of noise data that is 212 rows a 40 columns, you can completely fill the triangle. I happened to make my rectangle 240 x 40 because that was the next even divisor of 40 (so that the matrix is a group of 6 rectangles instead of 5.32 rectangles).

The next step is to ask, “if I am on the n-th row of LEDs in the triangle, which row of rectangle data does that correspond to?” You can map a vanishing path to the data using this important formula: h_r = w_0 / (1 - h_t / h_v). With this equation, you can easily get the row of noise data as a function of the “height” of the triangle.

Finally, you will want to calculate the width of the triangle as a function of the height of the triangle so that you can scale the 40 columns of noise data to however many LEDs wide the triangle is at that particular position: w_t = w_0 * (1 - h_t / h_v)

The slight challenge will be for you to figure out how to average higher density noise matrix data to fit in a certain LED pixel site. For example, you will have lots of situations where a single LED site covers something like 10 columns and rows of noise matrix data; I recommend using HSV colors and averaging the H, S, and V channels in that cluster. If I were doing it, this would be my procedure:

1.	Choose a row of LEDs you want to fill with color. Let’s pretend and choose the 10th row for now.
2.	The 10th row starts at a height of 9, and ends at a height of 10. So, using h_r = w_0 / (1 - h_t / h_v), and plugging in 40 for w_0 and 20 for h_v, I see that the 10th row of LEDs actually covers rows 73 - 80 (rounded) of the noise data (counting up from the bottom, of course). So, I would then do a column-wise averaging of rows 73 - 80.
3.	Now I am left with a single noise data array that is 40 columns wide and represents the column-wise average of rows 73 - 80. I calculate the width of the triangle at the 10th row and find that the triangle is 20 pixels wide there. So, I would take the average of every 2 columns of noise data from the 1 x 40 array, and end up with a 1 x 20 array of data to populate the 10th row of the triangle. Now, this example was pretty easy because the 10th row happens to be 20 wide, and 40/20 is an integer. What if we were on row 6 of the triangle where it is 30 LEDs wide? Well 40/30 is 1.333 or 4/3, so the first LED would be a weighted average of all (3/3) of the 1st column of the noise data, and 1/3 of the 2nd column. Then the second LED would be a weighted average of 2/3 of the second column and 2/3 of the third column. The 3rd LED would be 1/3 of the third column and 3/3 of the forth column, and so on.

I hope this helps.

Wow @Daniel_Wilson1 that helps a lot! I will study it tomorrow morning with a fresh mind in detail. As far as I see now, your impressive article contains all the math I need to use. I appreciate your efford a lot! Your well structured logical description makes it easy to follow. :slight_smile:
I think in reality I will fill all the different colored squares from your graphic with the same texture. So I can describe any point in the large origin rectangle as a function of one small square - so everything we need for the hallway is contained in just the red one.
Right now I have only a 16x16 matrix here, but a 32x32 is on its way to me. Probably I write the functions in processing first for easy debugging and to test them at a higher resolution in order to see clearly how well it works.
Looking forward to prooving my coding skills. Or improoving where needed…
Thank you again and I hope I can show results soon. Best regards to you!

The approach that I had in mind was a lot more primitive :smiley: This is impressing!

Short update: until now I coded a linear and a log rectangle -> rectangle mapping based on Daniels formulas. That works fine so far. More to come.

Good news! Let us know what happens.

Danny