I Made a 3D Renderer with just redstone!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
on June 27th I released this video where I made a multi-line renderer with just Minecraft Redstone the end result was a screen with 12 line drawers you could draw 12 straight lines at once by giving each line a start point and an end point if any of what I just said didn't make sense I highly recommend watching that video first before watching this one it's pretty cool you won't regret it so what's next you guys made it pretty clear a logical next step is to render a 3D object like a wireframe cube and rotate it this is going to be a huge challenge but I'm super excited for it so without further Ado let's make a 3D wireframe renderer with just Redstone first things first I don't want to just rotate a cube because it would make the whole thing only do one thing the multi-line renderer was cool because it gave you the freedom to draw whatever lines you want so let's keep that Spirit of Freedom instead of the user choosing a bunch of lines let's allow the user to create their own 3D wireframe but first what is a wireframe and how should we Define it a wireframe is really just a bunch of points and a bunch of lines formally we'll call this a Vertex table and an edge table the vertex Table stores all of your vertices or points and the edge table lists all the pairs of vertices that are connected or the lines for example let's describe a wireframe cube using a Vertex table and an edge table for the vertex table let's list the eight vertices that make up the cube and I'll label these A B C all the way to H now for the edge table let's list the pairs of vertices that make up the lines the front face uses a b b c c d and d a and yeah you get the idea now that we know how to define a wireframe let's build a system for the user to input one since we're in Redstone everything has to be done in binary that means everything in the vertex table and everything in the edge table has to be just zeros and ones so for each vertex let's have the user input three binary numbers X Y and Z and that'll be its 3D location in space and then for each Edge Let's have the user input two binary numbers the address of the first vertex and the address of the second vertex let's stack these a bunch more times I don't know exactly how many I want to do yet but we can always change it later okay here's the vertex table on the top and the edge table on the bottom awesome now the user can type in all their vertices and all their edges since the these edges are in the form of addresses let's label those addresses above each vertex alright perfect so now if I type into three I'm specifically referring to the vertices at 2 3 which are right here now we need a system where we can input an address and output the corresponding vertex like a decoder but unlike a normal decoder we need this to be dynamic it has to change based on what vertices are inputted I'm not exactly sure how to do that but I'll be back when I get something going okay here's my attempt at something that does that let me show you how this works so this part right here is just a bunch of memory and you can tell it's memory because there's a bunch of repeater locks that hold the information in place now when I press this button over here it loads the vertex table into the memory by unlocking all the repeater locks and allowing all the vertices to flow in so let's try loading it I'll just put one one one at address one and I'll put two two two at address two go back here Bop now that it's loaded we can use this coder down here to read whatever address we want so let's see what's at address 1 and it should output right over here yep one one one that's the vertex we put at address one let's see what set address two two two two perfect I'm I'm really happy with this to be honest next up on the list is to render this wireframe rendering is not gonna be easy because the wireframe is in 3D and our screen is only 2D so we need to use some sort of projection something where you take a 3D object like our wireframe and project it onto a 2d screen I'm gonna go research some different types of projection and I'll let you guys know which one looks the best for us alright after glancing through this Wikipedia article on projection I think the best candidate is something called a weak perspective projection a perspective projection is basically how a camera sees it gives you a sense of perspective which at a very high level means that you can tell when objects are closer to you or further away from you based on where they are and how they're stretched alright so given a 3D wireframe how do we create a perspective projection well first remove all the lines let's just project the vertices first we need to figure out where every vertex should be on the screen if it was being looked at by a camera in front of the screen because that's what a perspective projection is trying to simulate to do this let's connect a line from camera to every single vertex if a line passes through the screen or intersects it that's where the vertex should be projected to on the screen because that's kind of where the camera saw it at and this is called raycasting which is a major methodology behind a perspective projection I definitely think we should use this for the Minecraft build I mean based on the pictures in the article it seems like a pretty decent type of projection but first we need to know all the math behind it so let's go figure that out let's say our screen is centered on the XY plane and the Z Direction points into the screen towards the wireframe given a single 3D vertex defined by the location XYZ we're trying to figure out its x y coordinate on the screen once it gets projected and just to make it more clear we'll call that coordinate on the screen X projected y projected so how do we find an equation that takes us from XYZ to X projected y projected well instead of trying to figure out the equation for x projected and Y projected at the same time let's look at a top-down view of the projection and just focus on getting the equation for x projected so we've got like a bird's eye view now this line is our screen this is our vertex behind the screen and this is the camera since we're looking at it from above we don't really care about y anymore because y doesn't change it's not noticeable in this type of view you can just imagine for the time being that we're in a 2d coordinate system now with just x and z and the origin still in the middle okay so just like before let's connect a line from the camera to the vertex as you can see it intersects the screen at a single point remember our goal right now is to get X projected or the x coordinate of that projected point and so that's just this length right here so to get that length let's use some geometry to help us out let's draw two right triangles one from the intersection point and one from the vertex now that we have these two triangles let's label some stuff this distance is X projected which is what we're trying to solve for this distance is the x-coordinate of the vertex this distance is the distance from the camera to the screen which actually has a name it's called the focal length and finally this distance is the sum of two things the focal length and the Z coordinate of the vertex okay so now we have four distances which correspond to the side lengths of these two triangles and these two triangles are actually similar triangles which means that one is just a scaled version of the other what does that tell us well that tells us that the ratio of their side lengths must be equal to each other in other words x projected over the vertex X is equal to focal length over focal length plus vertex Z those are literally just the two ratios of the side lengths of the triangles now to solve for x projected it's pretty easy we just multiply both sides by vertex X and there we go we have an equation for the projected x-coordinate what's even more beautiful is that in this type of projection the top down view is completely symmetric to the side view which means that the equation for the y-coordinate is the exact same thing awesome we now have the equations to go from an x y z vertex to a projected X Y point on the screen you'll notice that we still have this variable focal length in the equations and that's completely normal that just means we get to choose how close the camera is to the screen when we project alright so the last part of projection which I kind of skipped over is how do we project the lines well the really cool thing is we don't have to we can just project all the vertices and then use the edge table to draw the lines because the edge table doesn't change after projection nice that's really cool so in summary to project any 3D wireframe to a screen we need to project every 3D vertex using the equations and then just draw the lines using the edge table that's it that's all there is to projection I still think this will work pretty well for Minecraft but before we make it in Minecraft Let's code it up in Python just to be safe since the final goal is to make something animated let's use a package called pie game pie game is a library meant for game development but it also makes it really easy to just draw some frames and play them in a window which is really all I'm using it for I'll be back when I got it done okay the projection code is all set so here's the vertex table and the edge table that describes a cube and here's the projection function if you're curious it takes a 3D vertex and uses the equations we just derived to return the projected coordinates so now when we press run a window pops up and there's our Cube oh and I also added a slider here for focal length so you can change it while it's running and see what it looks like with different focal lengths it's kinda hard to imagine this being 3D right now but you know what let me see if I can just show it at a different angle one sec okay there we go I rotated it a little and so that is without a doubt definitely our projected Cube awesome that looks really good all right back in Minecraft Let's Make A renderer and when I say renderer I just mean something that does the same thing as the projection function from python the input is XYZ and the output is X projected y projected I was going to call it a projector but I kept thinking of those things from school so I'm just going to call it a renderer instead before we actually build it let's make a little color diagram to see what it might look like alright here's a diagram for the renderer the input down here is X Y and Z and we also have F which stands for focal length and then the output over here is X projected y projected so the basic idea is we're going to multiply X and Y by focal length with two multipliers in the front and that gives us the numerators of the two equations then over here we'll add Z Plus focal length and that gives us the denominator of the two equations once you have the two numerators and the shared denominator coming from over here you can just use two dividers to perform that final Division and if we did everything right then the result from those should be X projected y projected alright nice I honestly really like this layout let's put this thing together foreign [Music] for the multiplier I'm just going to use this 5 Hertz multiplier that I already made from this video right here and speaking of 5 Hertz I think it might be a good idea to try to make the entire renderer five Hertz as well let me show you why so this is the multiplier I was talking about and five Hertz means that the hardware can be pipelined at five calculations per second in other words I can feed it a stream of inputs at a speed of 5 per second and sometime later we get a stream of outputs also at five per second it's kind of like when you're at a car wash you don't have to wait until the person in front of you is done to go in the car wash can work on multiple cars at the same time the reason why this is a good idea for the renderer is because if the renderer is pipelined we could feed the renderer a stream of vertices and it would output a stream of all the projected vertices which is much faster than doing them all one at a time but anyways let's yoink this multiplier and put it into position there we go perfect next up let's grab an Adder for right here where we're going to add Z to the focal length luckily I already have some adders in my schematics folder so let me go grab one and I'll paste it it and there we go this is a 16-bit Adder designed by Amino and this Adder is also 5 Hertz pipelineable just like the multiplier so that's really cool the last thing we need for this renderer is a divider and uh well I don't have a divider I think I'm gonna have to make a 16 bit 5 Hertz divider from scratch because I highly doubt anyone's made one before uh this is uh not gonna be fun don't ask how long this took I'm not gonna answer this is a gigantic 16-bit 5 Hertz combinational divider it takes over 200 Redstone ticks from input to Output or 20 seconds which is really really gross but I mean you only have to suffer that delay once after the 20 seconds are over you're gonna get your stream of outputs just like the multiplier alright let's put this big boy into place holy this just got big dude like compared to the dividers the multipliers are nothing maybe I should have just made a normal divider which would have been way smaller and just not worry about pipelining nah I already spent so much time on this I'm gonna use it I do not care all right at this point we have all the components we need for the renderer all that's left to do is wire everything up I'll see you guys when it's finished okay everything wired up and should be ready to go let's test this thing out I actually haven't tested it yet so it's probably not gonna work first try I'll just input the point um 8 16 32 and let's put in a focal length of 64. so according to the equations we should get five for x and ten for y and that's not even close oh this is gonna be a pain to figure out what I did wrong here oh no uh uh well I don't think I meant to make a floating repeater oh God what is that they're everywhere hold on hold on let me let me fix this all right there were a lot of problems with the renderer not gonna lie but it's been about an hour uh hopefully it's fully working now I just gave it a bunch of test cases and uh they all worked so I would say the renderer is done and at this point we have everything we need to render the wireframe we can't rotate it yet but we can at least see what a single frame looks like so let me go hook everything up and I'll be back when it's time to render our first frame I am so excited all right everything is hooked up and uh this is the button that does it all when I press this button it should render our first wireframe to the screen you ready Bop uh that is not that looks better I think yeah no no no definitely that looks right nice oh that's beautiful we just successfully rendered our first 3D wireframe let's go dude let's summarize what we did so far we started by defining a 3D wireframe as a Vertex table and an edge table we built the system for the user to input those two tables all in binary we derived the equations to render the wireframe based on a perspective projection we simulated those equations in Python just to make sure they actually worked then we built a renderer which performs the equations in Redstone and finally we hooked everything up input wireframe Cube and rendered it wow we're making great progress I mean at this point we can input any wireframe we want press this button and see what it looks like on the screen next I want to try out some more wireframes other than just the cube but let's be honest manually entering binary on these levers sucks so real quick let's make another python script to generate the binary for us specifically let's make a script that takes in a Vertex table and an edge table in Python and produces a Minecraft schematic for us to paste into the world the schematic will have redstone blocks in all the places that the binary is a one or you know the places where you would otherwise need to flip a lever this will make it much faster to create new wireframes and test them out I'll see you guys when it's done alright our schematic generator or whatever you want to call it is finished I used a python package called MC schematic made by my friend sloime MC schematic lets you generate custom schematics super easily and you can learn more about it in the description it's a really powerful tool but anyways up here I quickly made a Vertex table and an edge table for a pyramid so let me run this code to generate it and now we should have a schematic for the pyramid there we go nice so now instead of flipping levers all we have to do is paste it right here and just like that the pyramid is inputted we didn't even have to think about binary or flick any levers that's pretty cool let's go ahead and render this ooh nice that looks pretty good not only did our script generate the right thing but now I have way more confidence that the Redstone actually works for all wireframes not just the cube very nice all right so before we get to the final part which is rotating the wireframe there's one more thing we have to do because right now when you render a frame you can see it drawing the lines but the thing is if we're going to use this for an animation we don't really want to see it drawing the lines instead it would be better to have a system where the screen Waits until the frame is completely done being drawn and then refreshes the screen I've heard some people call this a frame buffer before I don't know if that's the correct term but that's what I'll call it so let's make a frame buffer all right I've been playing around for a while I think I have a good design let me show you how this works what I have here is two sets of latches and this is going to be attached to every single Pixel the first latch back here is where the frame actually gets drawn but it's not connected to the screen yet once the whole frame is finished you press this button which transfers the data from the first latch to the second latch and now it's on the screen so I think this is perfect I mean it gives us the ability to wait until a frame is done and then push the frame let's hook this up and try it out okay frame buffer has been added to the screen so now let's render that pyramid again and as you can see the screen is blank that's normal the pyramid is being drawn but you can't see it because it's still in the first set of latches now that it's ready let's press this button and the entire frame gets displayed at once nice that was actually way simpler than I thought it was going to be okay it's finally time for rotation I'm really excited for this part even though it might be kind of hard if we want to rotate our wireframe all we have to do is rotate all the vertices remember edges are just relationships which don't change during a rotation okay but how do we actually rotate the vertices well there's a concept in linear algebra known as matrix multiplication which is perfect for what we're trying to do here let me explain a matrix is a fancy sounding word but it literally just means a bunch of numbers in a rectangle you could have a two by two Matrix or three by five whatever you want it's just a grouping of numbers so you can represent a 3D vertex as a matrix as well it's just a three by one Matrix where the X Y and Z coordinates make up one column of numbers but why is this useful well one thing you can do with certain matrices is multiply them together to get another Matrix specifically if you take the vertex vector and multiply it by something called a rotation Matrix the output is the rotated vertex in Matrix form now you also have to give it an angle so that it knows how much to rotate by and typically that angle is represented by the symbol Theta the first time it can seem pretty weird like how does one matrix multiplication just magically produce a rotated vertex and I encourage you to watch three blue one Brown series on linear algebra it does a beautiful job of explaining matrix multiplication and so much more the link is in the description I'm not sponsored I genuinely love his videos but anyways the basic idea is we're going to take all of our vertices and multiply them each by the same rotation Matrix now the other question we need to answer is what type of rotation do we actually want to do because that's going to change the rotation Matrix if we want to be able to rotate in any way around any axis then the rotation Matrix looks like this that's really scary I don't want to do that alright so what if we just want to rotate around the x-axis only in that case this is the rotation Matrix still kinda scary but it's definitely a lot simpler another simple one is the rotation around the y-axis and not surprisingly the one for the z-axis isn't too bad either I think it would be awesome if we could Implement all three of these then we could let the user choose which of the three axes they want to rotate on which would give them more freedom but hold on before we go set up all three of these matrices with redstone I want to show you something that might save us a lot of work because I don't know if you noticed this but if you take out all the zeros and ones from the three matrices and ignore the spaces what you're left with is the same thing in all three cases that's not a coincidence this is actually the 2D rotation Matrix which you can use to rotate 2D points on a flat plane wait a minute so a rotation around the X Y or Z axis is always just a 2d rotation in Disguise how is that even possible well the more I thought about it the more it made sense for example let's say you want to rotate around the x-axis sure if you want you can just use the 3X3 version and it'll work just fine but one thing you might notice is that X never changes from the initial vertex to the rotated vertex so another way to do this is to Simply ignore X and multiply the remaining part y z by the 2D rotation Matrix then just add X back in afterwards and this trick does the exact same thing as using the original 3x3 Matrix additionally the y-axis and z-axis rotations also share the property that their respective letter does not change during a rotation so we can use this trick for all three axes this is huge this means that if we want to rotate around the X Y or Z axis we don't have to use three separate matrices instead we can just ignore the letter that corresponds to the axis we want to rotate on and then multiply by the same two by two Matrix every single time pretty clever right I definitely think so so back in Minecraft let's get to it okay I've been building for quite a while and this is the finished uh vertex Rotator sure let's call it that this may look super complicated but if you were following along with what I was explaining well this Hardware just implements it here's where you input your vertex here's where you select the axis that you want to rotate on either X Y or Z and once those are inputted this main part is where the matrix multiplication actually happens these four big chunks are four multipliers that all work together to get it done when they all finish the rotated vertex gets output right here okay so that's all great but what is this giant thing over here well I mentioned earlier that we also have to tell it how much we want to rotate by right we have to give this thing some angle which I'll call Theta because the rotation Matrix has sine of theta and cosine of theta inside of it and that's what this giant thing is for this entire thing just a huge lookup table or memory that stores all the possible sine and cosine values for different values of theta which by the way I did not make by hand I used empty schematic again so all the way over here is actually where you input Theta if you want to rotate by three degrees you just type in a 3 right here once it gets inputted it looks at this memory it finds sine of theta and cosine of theta and plugs them into the correct spots in this rotation Matrix and with that I mean yeah without getting too detailed that's really all there is to it so now with this machine we can take any vertex rotate it around the X Y or Z axis by any angle Theta that is really cool at this point everything we need is built we have an entire rendering system which already works and now we have a Vertex Rotator that can rotate all the vertices I am beyond excited to put these together and finally finish this thing I'll see you guys in a bit it's done let's go this looks insane dude I think this might be the biggest project I've ever made and by the way if you're wondering how slow this is without any speed UPS it's 700 Redstone ticks per frame which is a nice 0.01 frames per second good thing we have carpet mod and with that I think we're done I'll see you in the Showcase [Music] thank you [Music] [Music] [Applause] [Music] thank you if you enjoyed this video subscribe it's free and you can always change your mind later I hope you learned something I hope you enjoyed peace out guys [Music]
Info
Channel: mattbatwings
Views: 919,429
Rating: undefined out of 5
Keywords:
Id: hFRlnNci3Rs
Channel Id: undefined
Length: 24min 56sec (1496 seconds)
Published: Sat Oct 22 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.