字幕表 動画を再生する 英語字幕をプリント Hello, welcome to a coding challenge! And I can summarize this coding challenge very quickly in one sentence! This is a spinning cube. It is a three dimensional cube that you are seeing on your two dimensional screen. I am able to create this three dimensional cube because I am using the P3D renderer, processing, Java based, creative coding, development, platform thing. I can make 3D stuff using the P3D rendering engine and then functions like box, and rotate X, and rotate Z, and that is how I get this! But how does this really work? How does the processing even make this happen?! I am going to do the most basic, simple thing. I am going, I said one sentence and I'm like 12 sentences, I'm like 200 hundred sentences in if I'm being perfectly honest. I am going to change this from P3D to P2D. I'm going to eliminate all of the 3D rendering capabilities. I'm not going to allow myself to use any of them, and yet I'm going to recreate exactly the same digitalization. I'm going to do matrix rotations, projections, those sorts of things. So this is not going to be comprehensive, like how to build a 3D engine with ray casting, ray tracing, and lighting, and shadow, and sorts of complicated stuff. I'm going to just do the basics, just to create this 3D illusion in 2D really because, because if I can use the P3D, if I can create the 3D illusion and render it into 2D space, what if I create a 4D shape and then render it into P3D space, right? If I can project a 3D object into 2D space, there's no reason why I couldn't project a 4D object into 3D space. and then I dunno, I dunno, my computer's going to melt, and I'm never going to make any videos again. But let's just stick with this! Okay so let's begin coding. So I am going to take out, I'm going to hit save, and I'm going to take out all of this 3D stuff. I'm going to leave translate, stroke, strokeWeight, noFill. I'm not going to be able to use these anymore. I'm not going to be able to use these anymore. I'm going to leave all this, and I'm in P2D. Actually, I'm going to take out P2D The default renderer is also a 2D engine, so I don't need to actually say P2D. Now, I should also mention that I, in this particular video, I'm making use of a few functions I've previously written. I actually might have a video. I definitely did it on a livestream, so either way in the video description I'm going to link to where you can watch me code all these functions. But what these functions are for are for certain matrix operations that I'm going to do. Don't worry, I will talk about what they are when I use them. So the first thing that I want to do is let me just get some points on the screen. Hmm, how am I going to do this? Let me make a, so I'm going to make pretty heavy use of the PVector object, and I'm going to say, I'm going to make an array of PVectors that just has four points in it. And I'm going to say points index zero is a PVector at, and I'm just going to build a little square. So I'm going to say the first one is like at -50, -50, and then second, third, fourth, is at 50, -50, then 50, 50, then -50, 50. These should be the four points of a square. So, what I want to do here now is just say for every vector in points, just draw a point at v.x, v.y. So now, oh but these are. The whole point of me doing is I can't do this, right? Okay, so these are actually going to be 3D. The point of this is they're going to be in 3D. Bear with me for a second. All will come to pass. Those are going to be 3D points, but right now I haven't done anything 3D yet. Let's make the strokeWeight quite a bit bigger so I can see them. There we go. So those are my four points. So, first, what I need to do, and actually hmm. I'm not going to worry about this part right now. Okay, so, what do I need to do make a 3D engine? Okay, here's the thing. I'm going to search for some props. Okay, I found some props. I'm actually going to turn this light off too. I'm going to try to do a demonstration in the dark. This is a 3D object. It is the book A Million Random Digits with 100000 Normal Deviates. The way that a 3D object is rendered on a 2D dimension screen is through something called a projection. That projection you could think of is basically like a shadow. So if I have this book here, and I shine this cellphone flashlight, you can see that there's a projection onto the wall. It looks like a square. If I rotate this it rotates. If I rotate around the Y axis, well actually I'll have to do this. If I rotated around the Y axis, you can see it starts to become thinner. I can rotate around the X axis, it does this. So, you know, so this is the idea. I need to create this same exact I need to create that same exact idea but in code. And the way that that's done is with something called a projection matrix. So, the point, the 3D point, is actually something like this. It's a matrix that has X, Y, and Z in it. This is actually three rows by one column. This is something that I've gone over in other matrix math videos. Here's kind of a summary of it. A projection matrix, if I'm projecting into 2D, right? If I'm projecting this 3D point into a new 2D point, what I need is a projection matrix. Now here's a really simple projection matrix. This projection matrix has a one in the X spot, a one in the Y spot. X, Y, Z, X, Y, Z, and it has both zeros in this sort of Z column here of this projection matrix. What this is actually always going to do is give a two dimensional matrix, not two dimensional, sorry, a two column matrix with just the X and Y. This projection matrix just eliminates the Z. And actually, this will get us pretty far. In fact, this exact matrix is what's used for like orthographic projection. There's all different, stereographic, and all different kinds of projection matrices. This one is going to work just fine for us. So, let's put this in our code. Okay, so the first thing that I need to do is I need to create that projection matrix, and this is actually an easy thing. Now of course if I were doing this in more sort of robust way I'd probably have like a matrix math library. I just have a few matrix math functions that are in this tab that I wrote in a previous video. So, I'm going to say make a projection matrix, and I'm going to just make it as a two dimensional array. So one, zero, zero, comma, zero, one, zero. So this is my representation of a two row by three column matrix. Two row by three column matrix, that is this right here represented as a two dimensional array. Now, what I'm going to do here is I'm going to say for every point, for every 3D point here, I'm going to move this over a little bit. So what I want to do is, okay, so what I want to do here for every single 3D point, right? And this was sort of pointless that I did before. what I want to do is I want to create a PVector. I'm going to call it the projected2d vector, and what I'm going to do is I'm going to say matrix multiply the projection times v. So this is what I want to do to project a 3D point into 2D I need a projection matrix which I just made, and then I need to matrix multiply the projection matrix and the vector. Now, how the math for that work involves this times this, plus this times this, plus this times this, goes here, and this times this, plus times this, plus this times this. I'll refer you to matrixmultiplication.xyz. That website has a nice visualization, and I've made other videos about how matrix multiplication works, which I've also linked to. I'm just going to assume that matrix multiplication works. And you could see how this makes sense. This one leaves us only with the X. This one leave us only with the Y. So now I'm going to then say point projected2d.x, projected2d.Y. I probably could come up with a better name than that. And now if I run this, same exact thing, right? Because in this case it's as if the point light and the place that I'm projecting onto, and the thing, they're all kind of in exactly the same spot. So there's no skewing, there's no skewing of the sort of prospective. So, if I were to move that light around, and change the projection matrix, different things could happen. But I'm not going to worry about that right now. What I want to do now is see if I can apply some rotation. Okay, so how do I apply rotation? Well, I know that I could, I could just say like rotate by angle, right? If I say rotate by angle, processing is going to do that transformation for me. But what if I want to rotate X, rotate around the X axis? I can't do that. I'm getting some sort of error somewhere or nothing. I mean it should say not available with this renderer. Oh yeah, rotateX can only be used with a renderer that supports P3D. I need to write my own rotateX function! And guess what I need for that! Rotation matrix! I think the ding is better after. Guess what I need for that! Rotation matrix! Oh yeah, that was great. That was exactly what I meant to do. Okay, so now I am going to create a rotation matrix. Now how does that work? Luckily for me, I already have this Wikipedia page opened up. Look at this. A rotation matrix is a matrix that is used to perform a rotate in Euclidean space, and this kind of makes sense, right? Look at this rotation matrix. Have you ever done one of things where you do polar to Cartesian coordinate transformation, and you take the angle, and you keep increasing the angle, and then you convert that to X and Y points, and you have this like spiraling thing? I've made videos where I do that. Basically, to rotate in two dimensions, this is all I need. So just for fun, let's first just do this. I'm going to say float, I'm going to make another, I'm going to call this rotation, and I'm going to make another matrix, and I'm going to do exactly this. It's going to be two by two, and it's going to be cosine theta negative sine theta. And I'm calling it angle, cosine angle, negative sine angle. And then it's going to be, what was it? Sine angle, cosine angle, is that right? So this is, I didn't get this right. There's, this needs a bracket. I dunno what I'm doing here. And this needs a bracket, right? It's a two dimensional matrix. There we go, nope? Semicolon, there we go! So this is my rotation matrix, this is my rotation matrix. So what now, what if I were to say, no, I'm going to take out this rotateX. Not using the native rotate function, and I'm going to say PVector rotated equals matmul, rotation times projected2d. And now I'm going to draw the point at rotated. So I am projecting, V is a 3D vector. I'm projecting it into 2D, and then I'm rotating it, just a 2D rotation. And if we run this, okay, what's wrong? Columns of A must match rows of B. Oh, oh boy, I made a problem. Okay, something horrible happened. I got this out, I got columns of A must match rows of B. I made a mistake in my matrix multiplication thing. Here's the thing, I'm trying to be all clever to show you in 2D first. The truth of the matter is, PVectors, they're 3D. Even if I'm drawing just the X and Y, there's always that Z component. So I actually need include this extra column with zeros in it to do this demonstration. So now you can see that's me doing 2D rotation. And actually, I'm actually do 3D rotation, right? Because really what this should be is this. This is, what I would call, XY rotation. I am rotating around the Z axis by, you know, using the X and Y axes, right? Look at this. Now I'm going to say, but if I kept scrolling down this Wikipedia page, we would see this. We would find this right here. This is the one that I'm doing. Rotation Z, right? Oh, I need a one there, of course, not a zero there, very important. I don't want to lose the Z point. I want to rotate the X and Y axes around the Z axis, but I don't want to lose the Z point, so I need a one there. In the 2D case, oh okay, so I need this here. So this I'm going to call rotationZ, and now I'm going to make some other ones. Let's call them rotationX. And the rotationX is Y and Z. So I need to have my rotation values in the Y and Z spots. So hard to do this. I should just copy it from somewhere but this will work. And I think this is right. So this should be, right, you can see this is, am I spacing this off? Help me! This was rotationZ, this is rotationX, and let's do one more. Let's do rotationY. So I need to have zero, one, zero in the middle. The last one will be sine of angle, zero, cosine of angle, and the first one will be cosine of angle, negative sine of angle, with a zero in the <