Blender Python Scripting Fundamentals | Simon Van Den Hende | Skillshare

Playback Speed

  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

Blender Python Scripting Fundamentals

teacher avatar Simon Van Den Hende, Pipeline Developer

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.



    • 2.

      Interface Overview: Introduction


    • 3.

      Interface Overview: Scripting Workspace


    • 4.

      Interface Overview: Info Panel


    • 5.

      Interface Overview: Integrated Console


    • 6.

      Interface Overview: Text Editor


    • 7.

      Interface Overview: System Console


    • 8.

      Creating Objects with Code


    • 9.

      Cleaning up a scene using Code


    • 10.

      Ideas to build on top of this project


    • 11.

      Controlled Randomization: Introduction


    • 12.

      Controlled Randomization ( Creating a Fence )


    • 13.

      Creating a sine wave: Introduction


    • 14.

      Creating a sine wave


    • 15.

      Read and Visualize Real Data: Introduction


    • 16.

      Reading the data ( .csv )


    • 17.

      Reading the data ( .txt )


    • 18.

      Creating the bar chart


    • 19.

      Adding Labels


    • 20.

      Adding Ticks


    • 21.

      Labeling the ticks


    • 22.

      Creating and Randomizing Materials


    • 23.

      Controlled Color Randomization


  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.





About This Class

This course will teach you Python from the ground up.
No previous knowledge on Blender nor Python is required to follow along.

We will start slow, by discussing all utilities and tools that Blender has to offer. This way, you know exactly what is available and how to use it.
Using these features we will build a proficient workflow that allows us to work very effeciently.

From the beginning we start coding. This course is very applied, so be prepared to write some code!
But do not be afraid. We tackle every step and problem together.

During this course we will create 5 scripts from scratch, covering multiple topics including:

  • Overview of all tools and utilities Blender has to offer

  • Using the console and tooltips efficiently

  • Close look at how to structure and group your code

  • Converting and Applying Best Practices in Programming / Scripting

  • Data Structures in Python (┬áList, Dictionary, Float, String, Int )

  • Generating Objects through Code

  • Generating and Modifying Curves through Code

  • Creating and Assigning Materials through Code

  • Controlled Randomization

  • Working with existing modules to generate interesting geometry

  • Reading and Visualizing Data from .csv and .txt files in Blender using Python

  • Many Many More

If at any point you are completely lost, don't be afraid to reach out to me. I will be very pleased to help you get through whatever issue you encounter. You are not alone in this process.

Let's start together.

Meet Your Teacher

Teacher Profile Image

Simon Van Den Hende

Pipeline Developer


Pipeline Developer with solid experience and a passion for automation.


Worked at Outpost VFX on multiple feature films and television projects. Focusing on Pipeline and Data Flow as well as research and development. Main tools I used here were Python, Maya and Houdini


Worked at Prompto on the Pipeline and Data Flow. Focusing on Unreal and Blender tools / automation. All done with Python


Besides CGI, I have a strong love for web development / programming in general.


If there is anything I can help you with, don't hesitate to reach out on my email address:

I look forward to hearing from you!

See full profile

Level: Beginner

Class Ratings

Expectations Met?
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.


1. Overview: Learn how to make production quality Python scripts today get expert rating for me, pipeline, Technical Director, see mobile and ended with lessons that are affected production proven techniques while still being easy to follow and to the point, go beyond the just learning the basics as I teach programming concepts, efficient workflows, and final execution that will make you work so much more efficiently. We'll begin by looking at all of the coding panels and utilities are blender offers are the box. And we will directly apply these tools and techniques in order to solidify a proficient or cool. We did not need any experience in programming or blender. In order to follow along, I will guide you through the basics and we will discover the possibilities together. Our record will be structured and understandable. And this way we can easily push ourselves further than we would ever be able to do otherwise. As we get more and more comfortable programming and blender, We will always be focusing on art direction to make sure that our scripts include plenty of artistic detail and control. The goal here is to create a strong foundation. By the end of this course, you will have created five scripts from scratch, and you will be well on your way to becoming a proficient programmer. So join me and improve your old work or learn something new today. 2. Interface Overview: Introduction: Hey guys, and it's part of the course and we're gonna be talking about our development environment, which is where we're going to be building our programs and scripts. We're gonna go over all of decoding panels that blender has to offer and just talk about their individual use cases and pitfalls and just make sure that you understand how to use them because they're really, really powerful. All of them really just much more than, than writing a couple of lines of code. This is just going to show you how I work as a developer interactively with these panels, I can take information from Brian and use it in another. So this is going to be very exciting. It's going to be talking about my workflow in general, but on a high level, so it's very understandable for everyone. And then while progress through the course and you're going to keep referring back and forth through these panels and you'll see me use them. But for now I just want to make sure that you understand their uses and just know what they are. 3. Interface Overview: Scripting Workspace: Alright, let's talk about our development environment. Just launched Blender. I'm using version 2.81, or he doesn't matter too much, you can just use any version. I do recommend using anything above 2.80. So it needs, we're looking kinda the same thing. But once you have put a blender, you should see something like this, which is just fine. But not for scripting. So for scripting or programming, you're going to have to write some kind of text or execute some commands we cannot do right now. So we're going to have to move workspaces or just unable panels. But this is done by default if you move workspaces. So it's easier if we would just go to the scripting workspace, which you can find that the top middle here. So you can just click this guy. And you will see this intimidating looking layout or just text panels and stuff you might have not seen before. But don't be afraid it's going to be going over these just making sure you know what, everything is. Fine, everything. So let's focus up and let's do just that. 4. Interface Overview: Info Panel: The first panel I'm going to be talking about is the little guy down here. You can see my cursor. I, it's hiding its name right now, but it is the info battle right here you, so under scripting, These are the three panels that we're going to be talking about. The first one is going to be scripting than full panel, sorry. So as of now it does look a bit empty. Saw this ln of beer. But what this battle does, it just keeps track of your history. But in gold. So this is a bit of an abstract concepts or maybe all it was treat. So you can just do any, any operation or command or whatever in your viewport or just by clicking on on things as you do normally scripting. And it will register down here. So this is the actual Python command is executed in order to get the exact same result. So if we analyze this, let me maybe I can zoom in here, so I'll just paste it in here. This, this is what we're going to go over next to. Don't be afraid. Maybe just maybe make this a bit bigger. I can click here, here I can control. Let me see. Okay, so I'm going to zoom in is going to be a bit faster. So if you can see the commander has just gotten executed is BP. Why dot-dot-dot translate, translate, right? We know what this means. This is moving something. So I just press G and I moved it. And you can see maybe why dot-dot-dot transform not translate. So this is just moving something in Python code. So this is really valuable. You can even, let's say you can go into edit mode to face select face, extruded phase. And all of your history is just recorded down here. So extrude, reasonable is just a simple extrusion within Python code. And by just going back, tracing backwards steps, you can really easily automate anything really, This is usually my first go to if I don't know a certain command or how I, how I should do something in Python. I just do it manually. And then look at this window and see what the blender do. An encoding way in order to achieve what I just did manually. 5. Interface Overview: Integrated Console: And the next panel I'm going to be talking about this, the Python interactive console, the one on the left here. You can see the console there. I'm just going to drag it out a little bit to make it a bit bigger so you could actually read what I'm typing. This case here is basically allowing you to execute commands like you would see here. So let's say, let me just start off fresh. But let's say you create a cube. You can see this is the command to create a cube where this is the last one we did. You can copy this and you can place it here. And by pressing Enter, you just created the cube. You can see, see I just remove them so you can see that with more visually. So let's say you do this, boom, click you appears. And this is just a way to test your commands really quickly execute single lines or like a block of code interactively in your scene to make sure it works. So let's say I want to try out creating a scene or like a queue, which is a bit bigger, size 20, okay, this is how you do that. And I went, you have your your line. You can just move it out to the next panel will be talking about, which is the actual text editor. 6. Interface Overview: Text Editor: So you can see here that takes the editor, sorry, which is where you will be changing your commands. So this is basically where you will be writing your program or script to this into your final output. The main thing that you have to remember about this is output like does this text editor, which is where you let me writing your script, is that you always, always, always have to import be PY. And maybe why you might have noticed is the prefix of all of the commands that you're seeing. So everything that the blender does is driven by this BPI package. And this is how we importance in our script. So this is something that is a Pythonic. You're basically just including a library of commands and code by going in for it to be PY. And this allows you to access all of these, all of these commands and this window. Maybe one more thing and we wanna make sure about this text editor is that you actually create a bit of text. So when you open it at first, it will look like this and you can't actually type anything in here, even though I'm clicking, you can't type. I actually have to create a new data block, new text data block, by just clicking the new, like the plus icon, the New button here. So this will create a file for you. Kinda diseases called Texas is only stored internally in blender. So I can just write Important Big UI here with you. Can never forget, can save this. But this script is actually a script narrative, a piece of text, and let's maybe make it a bit, a bit more with this in here as well. Maybe let's, let me, let me show you how I can actually build this up. So right now I have to commend for creating a cube and here, so if I were to run this script, just get rid of everything so we can really see what's going on here. Can I run the script by clicking this button on there? On the right are just pressing all p like you can see there, which is a shortcuts. So let me do that. Which will execute the script, which will just execute its signal line, which will essentially be the same as doing this here. But the, the main benefit of using this window here that we can actually chain commands. So let's say we want to create it and everyone and move it out. So we also want to do this. You can just paste that in there. And now we have two commands in the single window, in a single text file. And I want to execute that. We'll create a queue, but then we will move it. So now we can see there is a cube. They're in school, but again, space debt. So this where you can just keep adding commands, adding stuff to your script. If I were to get rid of these, executed this, I just created a cube, Move it, it's a molding and all at once. But now let's say you want to try rotating so you wanna see, okay, so this is the command for rotating. Now you know, you can just put it, put it back here. And let's say you want to test it first, you could run it here first. And then if I rotate the current cube without having to go through all of these, these commands everytime. So I could face it here and then execute it and see if that works. You know it well because now knew I will. But maybe you don't. Maybe you have like a whole script or like a whole bunch of stuff that goes on as well, besides creating the queue and moving into rotating it. I don't always wanted to do all the whole process or you just want to test out a couple of commands and isolation. You can just do that. Here. You can even assign variables. You can store your data, all kinds of stuff. You can just do everything here once you know what works and does transfer it over to the actual text, to the actual script. And then that way you build up your, your script, your code, your program, whatever you wanna call it. 7. Interface Overview: System Console: One last window that I want to mention is the system console. So we have a depicts an interactive console down here. You can see Python console. There is another window that's actually hiding. So there's not a real bundles or it's not. And here, you only console that we have here is a Python console. If we were to go to Window. And then here you can see double system console. And this is essentially the console or determinable in which that blender is currently running. So if I were to output anything to the console by using the print function which is built into blender. So I could say print, hello world, which is very cliche pressure at its appropriate English word, but you've probably seen this before so you can print how the world, and by running this year you'll actually see nothing's happened. I'll run it again to show you. So does descriptors actually running, but nothing's happening even though I am doing something. And if you were to learn or read up on blender, you would see I've vitamins or you would see that this actually is outputting stuff to the console where you see here in the console, nothing is being outputted, right? And if you were to look at the system console, you would see it actually gets output here. So D side-by-side for a second. Let's say I'll just something else. Else, whatever doesn't really matter. You could see everything just gets put out here. And this is very important to notice because it every time you put something out to the console, you're actually going to have to look into the system console. So you can throw all this offer on. I really haven't on one thing you're going to actually do, I'll actually quit out of Blender. I created a new console window. Sorry, it's on the screen so that I just run blend there from here. So now this works for me because I have blender in my environment variables. You could also just get your blender file path. So I'm just going to quickly show you how to get there. Usually it should be in your C drive program files, but then their foundation. And whatever version you have installed here, you would have blender dot EXE. So this is the path to it. This is just editing my environments variable, but you don't have to go through all that trouble. You can also just drag this exit file in your terminal. It will look something like this. There are two quotes because air spaces in the path. So be sure you have those. And then just hitting Enter will actually launch blend there as well. And that way or system console is this guy down here actually not related to, to blend there at all. I mean, it's, it's its own console, which is a lot more easy to handle. So let's say I want to print out Hello world again. Make sure the syntax is right. Execute this. And we'll see in our custom, I mean, in our own console, we've printed out with hello world. And this is especially handy when, let's say blender crashes or something. So you're running your script and in the middle of descript, blender crushes, your terminal would be closed as well because a terminal is bound to Blender, the terminal actually runs inside of Blender. When you use the default one where you just, you just launch blender. But one when you launch blender from_id terminal, lender runs inside of this terminal and it render crashes. Or if I close it down, the terminal still exists. So that's actually very useful. In certain cases when blender question it's sometimes get through just I run it through your own career terminal and then just to make sure you can actually see whatever the prints or to debugging statements are before it crashed. 8. Creating Objects with Code: So the first thing we're gonna do again, just got rid of this cube. I know it's kinda gets the community to delete the default cube. Well, that's just going to add it back again in order to see what it takes to add it. Just copy just like we did before. Creative new textbook or script or whatever, imports VP alike because this is our necessary step that we can never forget. And then based r command's going to click Save as seen here, whatever. So now essentially we have already written the script. So we've written a script node, I will create a cube. So if you see if I execute it by pressing all your, by burning the scripts and the right, so the outliner, you can see the cube gets edits every time I run the script. So, you know, that's something, all right. But let's make it a bit more interesting. So what we wanna do is we want to have them read an, a random positions. So we basically just want to, I mean, there's, there's multiple ways to do this. Of course, there's always multiple ways to do anything with scripting or programming or, and blender, even sometimes in general. So what we could do is we could create a cube and then translate it. So move it. That's one way to do it with another way. If you look closely to the cube add command, maybe bringing this out to bit, we can see that you can actually specify size and the location. When you create the cube. This is the same as if to create a QC here, can actually assign, I mean, you can actually change these values here as well. Make it bigger. And you see here our comment updates. So if I were to copy that and put it next to it, you can see the size can be changed by changing this value. And our location can be changed by changing these values. So you can see these are x, y, and z coordinates. So if I were to get rid of everything again and get rid of this guy. So let's say I want to, I want to create a cube. So again, every time you want to modify or do anything in this window, you have to make sure your cursor is here. So if I'm my cursor's here and I do backspace, it's not gonna do anything. Friday, what's here? I'm expats, they are equal. So this is a, something some stem too, you have to get used to. So if I were to execute this, now, do it's, you have a cube of size 3.9 to o here. But it's actually a normalized but the, it actually, if you measure this out, this should be 3.92 and the location is 9.39 on the x axis, which you can see and see here as well. So this way we can really easily. Modify our QQ when we create it. So what we wanna do is actually instead of locking this location down to a certain value, whether it's 0 or nine or whatever, we want to have that randomized. So in order to randomize, it avoids the random library. This is a package just like with Blender, comes with Python in general. And this allows us to generate random numbers. So maybe I can show you by printing a uniform function. If I were to print this out. I mean, executing this is not going to show you anything. You actually have to go open up your console, which probably gonna wanna do like window, firewall system console. And the console window should appear. Do starlight again is gone and then brings it back. Alright, so I just printed out a random number between 01. If I were to do this again, I will print this one. Do it again. So you can see it's just any random number between 01 could also test the cell by running it in the interactive console. Actually, this is probably better way to do it. Have to reimport it, of course. So again, these, these two windows, they are not related to each other at all. They don't talk to each other. All of the variables that you have in here that say I create a variable, assign it to 250 if I were to print 50, and here I print VAR, for instance. Is it actually going to say name VAR is not defined? If I were to print bar here, it would print out 50 because in this bit, nose while var is and here it doesn't. So that's something to keep in mind. But that's the sowed a bunch of times by pressing the up arrow on our, on our arrows. In the up arrow, you can pull back recent commands. You can just kinda cycle through your history by pressing up and down. So you can just keep executing this guy. You can see that it will always return a value between 01. But if I were to say 010, it'll give me a value between 010 is very useful for minus 1010. So I think that that point is clear. So we can utilize this random value and in our cube add function. So let's say that this is so long as we actually split this up line by line, we don't really meet this guy either. If you were to go, we will look at the references. Maybe let's, let's maybe do that together. So there was a huge Whew, sorry, I said that. A huge blender. Python API website. So this guy here probably gonna want to bookmark this guy. This contains all the information about BPI. So if I were to look up our function here, to just copy it and paste it in here. And the search. You'll see the actual documentation about this function. So you can see all of the parameters that we saw before, resize, enter Edit Mode, location, Rotation. None of these things are available within this function. And then you can see the default. So these sorted defaults. So if I weren't, if I wouldn't set the size, it will just take two. And if I wouldn't specify, and through Edit mode, it will go to false. And this is essentially just repeating the default so I can take it up. But this might be a bit too much already. So maybe we'll probably get back into the documentations and how to read this properly. I just know that it exists and all of the, everything that has to do with be PY or any other blender module that is listed down here. As explained on this website, on the API, there's just one thing that you have to notice is the version. You're always going to be wanting, wanting to use the latest version or even better just to version that you are using a blender. So I'm using Blender version 2.81, but I'm using the API docs of 2.83. And if anything changes between 2.832.81, I'm actually going to have to the newer version while I'm using the older version. But the differences between 2.812.83 or so small that it doesn't really matter. I mean, at least on a scripting point of view, but it's generally best, best practice to just use the latest version always. So that aside, let's go back here. So if we were to execute this, that should work. We're just creating cubes on the 00 location for the 3.92 size. So if I were to put this, then you can see how that affects the QC is created. Alright? But the thing is that we don't always want to use 00 or 0 size. We can lock it down as you skews towards the default. We can even leave it out if you're used to, but I'll just leave it in. But this is why we want to, we want to be, we want to change this location. So let's again take our random value. So let's call this random value and assign our random value to this variable. So this is essentially how to use variables that might be a bit of a abstract, abstract concepts variables, but it's really simple. It's essentially just assigning a value. This can be any type to just a word representation. So it's generally good practice to give it a meaningful name. So this is essentially, Yeah, this is a random value, you could say between minus 1010 or whatever, but random values more than enough. So this is self-explanatory and this is good practice. So let's, let's use it. Let's put this instead of R 0. So now instead of a 0 reference to are randomly generated number. So this. Bit of code that return some value between negative 1010. So let's say it returns 9.93. Random value will be equal to 3.9. So if I were to say my location equals, or any value between negative ten. And then see if I run this, you'll see, it turns out the random value that was generated with this function was negative 3.56. And then our q was created at that location. Or to do it again. And nu over n value will be taken and a new cube will be created at that location. We did it as a bunch of times. We'll see recreate these cubes, but they're all in this straight line. So this is actually not all you want to write. This is we want them to be just all over. Big R cubed, just a bunch of cubes inside. But because we take the same random value for all three accesses, will always create them in this three-dimensional line. So what we wanna do is we want to create three individual numbers with three random values, one for x, one for y, and one for Zed. So let's do that. We can duplicate any line that our cursor risen by pressing control D. So I did do that twice. And then I'll rename the value because you can actually never have duplicate variable names. Well, in Python you can, but it will just override the previous one. So I'll assign it through, let's say one. Then it will be overwritten to whatever this one returns, and then it'll be overwritten again. So it's essentially still the same time. I mean the same value just to eat times. If I were to call this random value X or Y or Z. And change these guys accordingly. Which is important because random value at this point that doesn't exist anymore. It's just random value X, Y, and Z at random value is now going to be created. So it's not going to know what it is. So if I were to run this guy, we have a cube at a truly random location within our dendrite, then grid cell would just spamming. I'll be there just to show you a bit more cubes. So this line is what we had before. And now with our individual random numbers, we actually have a nice-looking result. So let's get rid of this savour seen. Maybe you run it again a couple times. So you can see what that looks like. Alright, so this is a randomly generated cube script, but again, we still don't have a 100 cubes or 500 groups, which is where scripting is so powerful, we still have to just press this thing over and over and over. So in order to get around tags, I'm gonna create a for loop. So for the people who are new to programming altogether, a for loop is essentially a programming structure that will execute certain, like certain lines of code a certain amount of time. So let's say I create a for loop here to write it off. So I will loop over. I mean, I will execute this bit of code 100 times. This is essentially the concept of a for loop. So whatever bits of code that are inside of the for loop will be executed x amount of times. So let's say amount of cubes equals a 100. And then I can just swap these around. So I will go over a 100 times and I will just print out i. I is basically this changing variable that will represent the current iteration. So we will iterate to a 100 times, and then I will actually keep track of what the duration that we are currently on. This is just for demonstration purposes. So I will just make sure discord is ignored for now. And I'll, I'm sorry, I'll run this. I'm actually returns an error. So let's look at what that says. Ok, I have to put the for i in range. I'm sorry. So if I run this, we will see that this variable is i changes for every iteration. So it starts out being 0, and then it just increments until it is 99. So by this point, we've executed this code a 100 times. So if I were to actually write r cube script and hear, execute this, we will have a 100 cubes just like that out of the box. So if I were to remove all of them, run it again. A 100 cubes, all with random locations within this ten by ten grid on all three x's. So by using this for loop, you can create a lot of geometry at once. So you just figure out how to do it once. And now you're just a wrapper that this end is four loop structure and everything that will be indented, retake it. This is, this is one. So one tab. Everything at this indentation level will be executed 100 times or whatever he wanted times that you specify here. So if I wanted to great 50 cubes, delete everything. Or in this we'll have 50 cubes. So you can see here. 9. Cleaning up a scene using Code: One more thing that I would like to mention is that every time when we execute this script, that r cubed z a pile on top of each other. So what we should do is just select everything deleted around it. Okay, well that's fine. Let's create 50 and open. And with this script it doesn't matter that much, but sometimes you just don't want to always, when you're like creating some procedural geometry with scripting or grading something else. You always want to have to go in and delete everything and, you know, it's tedious work that you're trying to avoid with scripting. So it's kind of gotten their intuitive if you continuously have to do a tedious work. So I'm just going to quickly show you how to not have to do that. So afford us, let's actually go in here and are interactive console because we're gonna be testing stuff out, trying to find out. The first thing I'm going to be showing you is how to grab all of the objects in your scene. So just go Man is called BPO I dot-dot-dot objects. So you can see there is currently 50 objects in the scene, but just normal because I created 250 cubes and I deleted everything before. Let's say I create a 100. Now, execute that. Hit the up arrow, can execute the previous commands in R console or interactive console weather. And now we can see there was a 150 objects, sort of 50 that were there before and a 100 extra because I use granted more. But we essentially we just want to have a 100 at this point. So what we could do is we could list. So now we have a list of all of these objects. We can just remove all of them. And we're gonna do so with the for loop again. So what do we did our for loop this way? We could actually specify how many times we want to loop. We know I went to a 100 and you know, every time you run it, you live a 100 cubes. But at this point, you know, you don't know how many objects that we're going to be in the scene. You could say, well, yeah, for I know 100 again, you know, remove everything but then if you want to put it to 50, it's not gonna work anymore. It's really not dynamic this weight. So essentially what we wanna do is we want to iterate over many objects there are, but without knowing how many objects there are first. So I don't want to say for i in range of 150, because there's not always going to be 150 objects. But what we could do is we can say for the current object BY dot data objects. And let's just for now just prints current object. So what we do here makes me scroll all the way up for current object in APY dot-dot-dot objects. So for every object in this collection of objects or in this yet, and this collection of objects. Show me your main. So like I was our variable that would keep track of our current iteration. This variable here give strike over our current item within this collection. So this is basically an array or a list for you programmers out there. And this is basically every element within that list. So if you have a list of objects, this is the current item, the current object that you're currently iterating over. So whatever object this is, it's part of this collection. So by using this, you can see I have all of these cubes. Like I can grab all of the cubes. So again, for my object and that object, so for every object in the collection of objects, I wanna remove it essentially, right? They want to get rid of every object theories. So for this we can do PPA dot-dot-dot and object dot remove. And then you want to specify the object that it has to be removed, which is the current object. And just like that, everything is gone. The whole every object in this scene is gone. Now this will also delete cameras and lights because they are also objects, right? So if I were to do this again, the camera will be gone. So you have to keep that in mind to remove everything. You could also list meshes, materials, images, pretty much everything. So if I were to go to BPI dot data and then press control space, which is a really cool trick. It will show you all of the things that are within this data. So you can have texture, sounds, screens, meshes, materials, light. So you get to just so basically everything that has. But we'll just do objects for now. So the code that we wrote here actually works. It is dynamic. It will work for any amount of objects. So let's actually now included in our script. So how should we do that? We can just do it before. So just like we did. And aligned appropriately, boom, now it is in place. So every script will be executed from line one to line, just the last line. So down one through desist corn logically. So it will come here, look at all of the objects in the scene, remove them all, and then create a 100 new ones. If I were to do this, I would have a 100 objects is the same as it would be before it. If I do it now, I want you to get to a 100 different objects. If I were to look here really quickly, just printing all of our objects, it would see it's still a list of a 100. And I can execute this 2020 times or however many times you will always be under it. Or to change this to 50. Now I'll have 50 and all of the hundreds will be deleted. Pirates per 500 again. First it will delete the 50, then it will create 500 new ones. But you don't have to specify how many objects there will be at the start because you can never know. As like Now, I don't notice 500 that can maybe be sneaky and create one. And I could create a circle, we know is right. But if I were to run it again and this is my friend is a bit too much. And moving to circles gone as well because everything is always going to be gone and replaced with around it. 10. Ideas to build on top of this project: Alright, so we've gotten quite far, are already in this first chapter of the course. But I would like for you guys to really deepen your understanding of what we're doing here is try something out yourself. So there's generally a best practice to just, you know, go, go out on your own and try out some different stuff maybe while you are creating disregard inspired or you got them, you know, just inspiration to do something else. And I would like for us to proceed that now see if you can add to this. One thing that I could suggest is figuring out how to randomize their rotation as well. So as if now is just random locations and you can see if you place our place, your camera somewhere in here. Nobody looks quite interesting. But in order to take this to the next level, you can maybe randomized more star. So this could be a rotation, this could be scale. This could even be yeah, this could be anything really just I'm not gonna I'm not gonna say too much because I don't want to limit your imagination. So just kind of go through what you would add to this and then try it out, look up stuff on the documentation. So one more time, quickly plugged this link to EI. So blender, Python API stepped up and, and Google. And you'll get the most recent one. Make sure you're on the most recent ones is actually 2.90 now, since I think since a couple of days ago where the fourth of September right now. So I'm not going to make the switch from MIT course. Maybe I'll, I'll just look into the change log and if anything changes, I'll keep you guys updated. But for now, the API is identical to 0.812.832.9 for all the stuff that we're covering in this course is all going to work. It's all going to be same, so don't worry about that. But yes, here you can just kinda lookups himself may realize quickly, copy this guy here, see what we can do with this. So this is me just gonna show you how you could take this. So we can see there is a size that's one could be randomized. So this is just set to two. Here, it's also set to two. So this is just a static number, so you can randomize it the same way we do here. They can kind of just pick your boundaries. And that way you can really add more dimensions to this location, your rotation or scale again, so this is set to 0, which is a little bit weird because usually when you scale to 0, you just make it infinitely small. You should just scale by one to keep the same dimensions. This is just a multiplier. And so this is a bit confusing. So I wouldn't worry about this one if you want to randomize the size, I would just do it through here. This does, is, this is a uniform scaling. So this is just a scaling of every X is equally. You get maybe something you could do is scale it and said something and then seal it. And why a little bit? Let's kill them, an x, something else. So you really get these rectangular shapes. So I'm, if we use the size parameter, you're always gonna have a cube. So that's something to keep in mind. You can always look here and see what we did. Kinda just make some interesting stuff and then tried to script it. Just have some fun and just try some stuff out on yourself. This is a really, really going to be the difference between a, you just watching the course and you actually understanding what we talk about, actually applying what we talk about. Its always good to kinda tried to create your own stuff. And if you do, be sure to send it over through email or through my socials, there'll be a description of the course. I'm always really interested to see how you guys, uh, or you just create a foot with the stuff I I tried to teach, sort that would be really cool to actually see how you guys to have your own look on what he's created and how you guys think it can be improved. 11. Controlled Randomization: Introduction: And in order to take proceduralism and randomization to the next level, we have to think about when and where to use it. Sometimes it's generally better to randomize something because as humans, we are always trying to find Recognizable Patterns. And that's just the way we artists, the way our brain works. We always try to recognize patterns. We always try to create patterns. And even when you try to create a 100, playing through, always focusing on two or three. But then over time you just become recognizable and it's become repetitive. And that's just problems that a machine doesn't have to deal with, which are purely mathematical. I mean, if you, if you ask a machine for a number between 01, it doesn't think about, it just gives you the number and it just moves on. So if you ask it a 100 times, you'll get a 100 random values. When you ask a human, there will be always, there always will be some kind of pattern inside. And that is exactly what we have to try to avoid. And that is exactly what Python and blender, and I mean just proceduralism and randomization and generalists. So good. It is being not biased as being not predictable, being not recognizable. And when you really see that value. And then you can really push it to the next level. 12. Controlled Randomization ( Creating a Fence ): So this is what are going to be making and this chapter, it's completely randomized fence. You can see there is some offset in the rotation and then the height as well. So this looks aesthetically pleasing, it's really easy to make. So yeah, that's what we're going to be the width. Let's start off with a new C may actually completely buying going to scripting as we are used to by now. Let's drag this out a little, save it. Do all of the essentials before we can actually start to create a script important beat BY some of this therapeutic stuff. And now we are ready. So let's actually start by putting in the less stuff that we did in the previous chapter, which is cleaning up the scene. So if we don't remember completely, I will repeat it. So the thing that we'll do is we'll grab every object in the scene. So for objects to be DY dot-dot-dot objects, and then we will remove it. So if I add up the texts, that will just get rid of everything every time there is a lot easier while you're working. I mean, I'm not saying you should leave. Or you actually publish this script or when you actually start using it because you are just, maybe you want to create a fence in the scene that's already existing and you just want to don't want to get rid of everything, right? But for now it's just really tedious to always remove or we created because I mean, from the first iteration we're going to create a queue. And as you're going to be annoying to always remove it. So that being said, let's start by creating our cube. So again, you should notice by now already this command, but even I forget very often. So let's place it in again, creating a cube of size two and location 000. And it's actually move this down to one. It's a bit easier to work with and then enter Edit mode like we saw before, it can be deleted. So this will still work. And now we just have a smaller cube. Notice how the big one disappeared, which is awesome. It's just such a little thing, but yeah, just keeps you sane as a person. I could tell you that much. Alright. But this doesn't look very much like blank, does it. So to make it look like a blank, refers need to move it up. Of course, I mean, scale it up. So as Z, say ten centimeters, which is a bit much, but I mean, That's fine. It's maybe scale it down in the x. And this much, which is 0.25. so again, you're going to have to keep using these, these, these panels. Just mix them together the whole time. It's super useful. So if we actually take a step back and see what we did, so we scaled it up right then. And there we scaled it down by 0.25 and the x. So that's how we can actually create that. So let's copy here. And that's commensurate actually what we can see, maybe they can note stick is the PEC. Again. This is the same command that we execute twice after each other. And then once we execute 3D riskier than the zeros and ones riskier than the x. So we can probably combine these two. So let's get rid of this one. Let's see if that actually worked. So now you just create a queue of size one and then we scale it to place unless maybe move it up by five, which will be the half of whatever this is, whatever the item. So that's that. Then we essentially have created a blank. Looks good. The scale is completely wrong. Are not gonna be worrying about that. But just as a side note. But yeah, okay, so this is basically the recipe of how to create a blank. So maybe we should bundle this up into function. I'm going to go over it. It's quite quickly because there's just grouping of code. For now. You don't have to know anything more than district being grouping of code. So let's say Create Blank and is put all of this stuff inside. So if we run it now, actually it, nothing's going to happen. But if we call our function, then it will actually execute this code. So discord is only executed when we call this function, which is great. So let's step one. This is already looking good. Let's now try to caret, let's say ten blanks. So again, like we did with the cubes and the first chapter, we're going to loop over a certain amount of values. So let's say for i in range of them. Do want to create a blank. For now we should have ten links. Of course, we don't want them all to be in the same location, so we want to have them offset. And why this amount? All right, so we know that the actual width, let's see if this is a width. However much it is on the y-axis is going to be one. Because we created this a cube of size one. And we didn't scale it down. And y, so y is still as I just scaling by a factor of one. So it's essentially multiplying one by one, which is still a one. So we know that this is one. So if we create a blank and then move it over by one, or let's say, let's actually identify a gap. So let's say we want to have we get the 0.1. just 10% over the thickness. So let's say one plus gap. So we always want to do one because that is just the amount over the previous one. And I just want to add a little bit of a gap of 0.1. So if we were to do this, That didn't work because this is not actually moving it. This is not actually a delta y, this is actually a, an actual y. So this is the new y position, which is actually not what we want. We should probably just use i, right? So we can do i times one. And I just want to incrementally to gap. There we go. So now we have ten blanks as maybe make it a bit bigger of a cap. I'm not sure this is you're actually working. I don't think it is as maybe not through this gap and I multiply that by i. So why the current iteration? That's even worse, right? And I'm the one. Alright, there we go. So now we have our planks and we have a little gap in between 0.1.2. It might be a bit too big. Alright, so this is not looking too shabby, right? Nicer looking at fence, but it's a bit too perfect. And that's how it's like a 3D artists to the really noticeable and it's like tool perfect decisions to illustrate everything. So that's where the randomness comes in Suez it as a human again, it's really hard to grab this stop phase and then this move it out and take a little bit to, to have it a bit offset. So that's what we're going to be trying to avoid right now. So let's start. So what we wanna do for every blank is we want to have accustom height. So the hydrogen very everytime. So in our loop, we will declare a variable and set our height to be ten. So for now, let's keep it actually a hard coded or not variable. I mean, it's still a variable that it's a, it's a set number, so it's not going to change. And that's actually pass this in. Recreates are blink. So I tight, tight. So this height is going to be holding here. We want to replace our initial height. So our scaling of zed, which was setting up the height, since we are using one. So this now will still be the same outcome, but using this variable here will give us a bit more control, especially by passing it through this function. So if we were to execute this exact same, and now if I want to change it to either 15, this will happen here. Now of course, we were moving it up by five since our height was aesthetically set to ten. But now that we changed to 15, it's not looking good anymore because you'd actually use 7.5. If I were to run this, it's again, it's going to be aligned. Yeah. But we don't always want to. I mean, since we want to change this, we also have to change this. So it is just a half of whatever the height is. So this will work regardless of whatever I put here, it, we'll just always align it to the bottom. And that's really, really important. Almost never when I use these magic numbers. Same as like, like even here like this, 0.25. it's not good to have this in here. We should have this be like a thickness variable. Alright, sorry, thickness here. And of course we have to put thickness here as well. So that's a They cause 0.25. and essentially it's still the same code. It does the exact same thing, but it's a lot more readable. It's a lot more comprehensive. If we run it again and yet this is the same outcome. But it's, it's a lot more clear and then just scaling in the x, y. And now you know this is a thickness. Alright, so let's put it up. So the thing is though, we want to have the variable height, this has to be dynamic, is has to change for every blank. So again, we're going to be using our random functions is well, let's import random. And now instead of sending it to ten, we will be, we will choose a value between 910. Let's say. Maybe 911 might be too much. Random dot uniform. Of course, this is the, the actual name of the function. And you can see already the blanks are now ferrying height might be a bit too much. So that's like a factor of one. So the difference between the maximum min is one. So we will see a maximum change of height. One. Does it might still be of it too much. Let's do Component_2 or something. You can play with these numbers, right? These are just the thickness is finite. It's like a little, little variable. Okay, so this is good. This is already something that's already looking a lot better than, than it was before. And again, you know, this is taking small steps and we're just creating then now. So you might think, you know, this is dumb, I couldn't do this minute. But let's say you want to have a 100 planks, like offensive and they go, Hollywood stick here. And this is especially useful when you have like a scene which has a bunch of fences or just yeah, when this becomes reusable, you will see a lot of value. And even once you get good at scripting, you can write this up in like a minute or something, just goes really, really fast. These are the same commands, right? You can just pull them out here, parliament a for-loop and BAM, there you go. So it doesn't take long, it actually takes less time to scripted and to create Andra blanks libraries. So yeah, just to give some perspective. Cool. So I have planks and put them back to ten to focus up a little bit more. And let's add an, another dimension of randomness, right? So they're all aligned perfectly. Whoever put these down is master. Baby Austerlitz, maybe a randomize it thickens a little bit. I want you to have this in place with the variables and you follow this. This structure is really easy to just add to this, right? Maybe let's make this a bit more varying. Yeah. You can just take every aspect and just make it a bit more unique, a bit more randomized to, to add detail rather than just, I mean, detail is also in scripting. You don't just have the tiling modelling or lecturing or in whatever it can have detailing scripting as well. Alright, so we have height, thickness, listen, I'll do rotation. As we saw in the previous video in the documentation, there is a field for rotation when creating a cube. If we look here, cube, we have this rotation, this rotation values here as well. So you can see in our cube add method, every location, there's also a rotation. And you can see these values are quite small. So I'm assuming this is an irradiance rather than degrees. So that might be a, I mean, you just have to keep that in mind that these are radius and not degrees. So now that we know that this exists, oops, lets actually copy this. So this is annoying. Rotation. Let's move this out and let's based up on the end. So now again, our rotation is set in stone, which is not dynamic at all, but for demonstration purposes. And while you're creating this program, this is just fine as just making sure it works and see what it looks like it's not. And it also gotten a lot thicker as it because you're actually resizing globally. So 4N type global, that's maybe see if this works better. If you do local, that works. Yet it does. So now we are rotating a little bit. Every xs, which is now what we wanna do, actually want to rotate on zed, i think, right? Yeah. So we'd actually want to keep these non-zero x and y. Just wanna rotate and said, Let's put this one. Make sure that works. So you can see they're all slightly tilted, slightly angled, they're just all the same. Let's add an angle variable here. And then let's set it to a random uniform, reappoint wine and it's not that bad. So I'll do 0.1.1, negative one, and positive 0 to one. Sorry about that. I wanted them to love each other. But still the thickness. Yeah, we actually randomize it thickness where I guess that's fine. So if we look at it here now, this is not a bevy reads of it through thick. Boom. There we go. Let's see how it looks when we have a bit more. There we go. Look at that. You just created a 100, I mean, to relatively big feds. And just a second. And it's very, very dynamic. Say Well, I wanted to be carrying a bit more in height. You can just type. But this 3-11. Now you have a bit more variation in ICT. And it's very, very flexible just because of the way we set this up. 13. Creating a sine wave: Introduction: Alright, so we're quite comfortable with randomization and proceduralism. Now I think we're going to be moving on from random to just general math. Now, we're not going to be solving for x are doing and equations or anything like that. We're just going to be using the math function library, like we did use the random library. So it's now going to be any more complex or theoretical or anything like we did with the random. This is just going to be applying the math function library. 14. Creating a sine wave: All right guys, let's get ready for our next program. So are we going to move over to the scripting workspace once again, get rid of everything that is there. Create a new data block, zoom in a little bit of control, scroll real, and figured that out by now. Importantly PY and couple of N3 is just to get us ready for our script. For this one, I'm going to have it a little bit of a different approach. We're not just going to be starting off with a cube and then going from there, actually going to recreating or mesh from scratch this time. So let's get into it. In order to do this, we'll be creating our mesh. All right, so, so this might look a little bit familiar to when we carried all of our objects. We use BPI dot data dot objects in order to list all the objects, which also allowed us to remove them. And you can also just create them. By doing this, we work to create an object to be pure and all the other objects about new. Call it sin curve as well maybe. And this is actually going to come in and the two link arm through our object. So once we have a mesh and an object, we can deeply full-text link. It's a mouthful. Obj. Maybe we should best mesh at this point as well. If I'm not mistaken. Let's run that. Okay, so now we can see we have our object which has a forward. If I wouldn't do this, this will object stuff. Just create a mesh. Maybe career. Get rid of the object. Selected, delete it. You could see I could run this as many times as a one. There's never going to be an object here and it is going to be a bunch of meshes down here. So this is a bit confusing. These things are hiding in the background like this cube mesh. We believe it is a long time ago, but it's still hiding. So let's actually go through our deletion routine. So we've, we've done this a couple times where the objects, so I remember for OBJ and BP right up data objects. Data objects dot remove the sort of current object. So every object is listed and then it is removed like so we can actually do the same for a meshes. So for mesh in the BPI dot the yellow meshes, BPI dot, Mesh. So this is actually going to get rid of all of the missions that are currently in the scene. And then it will create a new one. So let's see if that works, right, it seems like it did. And so there's only one mesh here, it is still no objects. So let's uncomment these guys again. And we have it all setup now. Alright, cool. Our meshes still a little bit boring, right? There's no actual data insight. So we can change that by doing mashed up British's dots, ad, ad. A 100100 vertices through the mesh. I will also add a couple of edges. So we actually need one less than the amount of over leverage is because an edge is always a connection line between two vertexes. So there will always be one less Edge and there were four Dixit. So maybe we should actually put this in there and a variable. So let's say a 100 samples. So I want to have a 100 vertices and then minus one edges. All right, so now we should have known that there are still all in the same locations where there's still not really doing anything. But first, let's maybe go a bit more basically than the click rating to sinewave. Let's just create a simple flat line, a flat curve. So we will go over every vertex. So for i in range of samples, because that is exactly the same amount of vertices. So amount of samples. We will grab the current vertex, which will be meshed up for each of the index i. And then we'll say current vertex C, o, which is the coordinate. We will set that equal to, let's say 0 on x and y, and then one in z or something, so it's not flat on the ground. Sort of reward to run this. Look at the curve. Okay, that's not bad. Still no actual geometry. So we can see the points that had been offset, but the edges are not. I mean, there there's edges there, but they don't know what to await you for addicts is deep along or what they should do. So that's actually set that up as well. So I'm not going to want to do is for every edge, for every four ticks, I want to do this for every vertex except for the last one. So if i is less than simple, minus1, I wanted say, mesh edges. The current I adopt the vertices equals the current vertex and then the next one. And this is basically just a signing. So I'm assigning a vertex to vertex is for every mission ever, every edge. So every edge is essentially biggest ever. This is a vertex, this asterix here. And you have a vertex here. What I wanna do is we, so you just connect these when an edge. So this is the current vertex, vertices I. So current vertex as an index of i. And then the next vertex to this guy, which is the end of the connection, is i plus one. The next one. Or you have to make sure that we never go over samples minus one. Because then i plus one would be 101 or 100. And that vertex doesn't exist because it goes from 0 to 99. So we have to make sure we never exceed that bound. Because if we were to say you were to leave this out, we would get an error. May actually load up the console. So you can see it's a reader out of range index 99. So that doesn't exist apparently. So we have to do to make sure it keeps its still in range. We can still we always have to go into relative to double-tap tab is selected in order to see our curve. So that's a bit annoying. Let's actually add a modifier to it, so it's a proper piece of geometry. So that's where we take skin is finite. We can script this as well as movie quickly do that. So we'll do this by doing OBJ file modifiers, that new type equals skin and then name. It doesn't really matter what's called his kin were to do this, then we actually already, so after we create the objects, we create a modifier of type skin, which is just a bit easier to see it if you point. Alright, so this is already looking pretty cool. Let me actually apply it to a C to vertexes because it's not really letting me see it. Alright, cool. So this is human samples. If we were to put like take that sample and that's a lot shorter, maybe we shouldn't do that. Well for now, it's fine. Let's go into here, apply the modifier. I see, the I, I see. So it's always going to be changed by one. So as may read that. And forests. For sine wave, we should add a couple more variables. So let's add a frequency. I'll just put this on 30 length because it should be more variable. And then height three maybe. And then we could do a step which would be the length divided by our sample, which will straighten everything out. That makes a bit more sense. You'll see how that looks in a second. All right, so in order to do the, to get the sine wave, we have to import math, which allows us to access a bunch more modules. So if we can begin to be explored and the console a little bit, enlarge. One thing you could do it through. Third, math. This, this function is derived, function is just standard Python function. I will list out all of the things that you can do with the currently selected method or class. And here, so you can see math offers sine square roots. Maybe I can show you with random to make it a bit more visually as well. If I were to do the random, you could see random uniform. So that's the function that we used before, right, to random uniform. And here you can just kinda go looking for stuff. So let's say I wanted to do something with sin or irradiance or with power, I guess, kinda look for it. So I see ok, so it's called sin. And I can maybe like have metrics in, and then it will return the sine of x, sine x return a sine of x. So if I were to do sine 90 is 0.9, that's correct. Measured in radians. Well, of course that's not great as so does your method. Because it's one here as well. Alright, so MATLAB radiance, yeah, 90. That's 1.5 sites do. Yeah. So the sine of 90 is actually one that works up, so you just had to press it on and in radiance. But yeah, that's just a bit more about how you can actually play and discover these, these modules. If you just print this out, you can kind of go through what it all offers, what else has you can also, of course, check out the documentation. So let me just quickly box whatever go into here. So you can go sign. Maybe at a bracket. Yes. There's a sine of x radians. Yes, and x radians, of course, a target return is in radians, but a sign in radians. That doesn't make any sense. I find that besides. So now we know how math works. So we can actually grab our, let's say our value is what we wanna do. Yeah, let's instead of one, listens to this method sine of i t we get now you get sine wave that has very, very blocky a very, very long as well because we have 500 samples. So this is going to be 500 and link because yeah, this is always going to be one. So yeah, we definitely don't want that. We want to have some kind of step. I mean, every evidence already in place. So let's say my value equals i times step. And then I wanted to do, instead of this, I want to do value, which will make it a bit more controllable and a bit smoother because we have these extra steps. Rather than this just being one, it will be 30 divided by 500. And this way we can actually control the length. If we put this on 20, it will be smaller, but it won't actually change the frequency you would hide or anything. And it's actually include ICT. So let's multiply our xy coordinates by the height. So this way, if you do 33.55, will actually affect the height. Let's put this on three. I kinda like that. Okay, so it's kinda looking it already. Maybe. I'll show you what samples very swiftly to have less samples, you have less vertices. So it's less resolution. 500 and smooth. That runs fast as fine. 15. Read and Visualize Real Data: Introduction: I guys, in this part of the course, I'm going to be talking about reading in actual data from a CSV file and displaying it as appropriate 3D graphics 3D bar chart. We're going to go over step-by-step, reading into data, displaying it nicely. And eventually, we'll end up with a proper 3D bar charts, like you see here. 16. Reading the data ( .csv ): Alright guys. I just deleted all over our gold in order to generate this stuff. So I'm gonna get rid of it as well. That one, let's look before he's gone. And I'll just start off fresh, important BP as we're used to. That's also important. Csv, which is standard module for Python and blender. I just included by default so we don't have to do any other installation or anything. I let's just comes in by default. So maybe let's quickly up into our console and run this as well where it's actually still already here. I already did a little recording that I had to start over so we can actually see what the output was or that are that come in. So you can kind of see some other stuff here might be a little bit abstract. I'm just not going to go over to watch the two load the CSV library. We're just going to be using it to, to import our data. So the main thing we'll need is a file path. This will be the actual bath on this over our CSV file that we want to read it. So let's open up this guy, don't need to see in it is actually a sneak peek of what Alcott come in. But as you go into the bar charts, and this is the actual data file. And we relativists opened this up real quick. So you guys can have a look what's inside. If you're not familiar. Csv files, comma separated value file is basically just values separated by comas. Maybe if I were to show you how to add a text file or like in a Notepad. It might be a bit more clear. Again, this is just the de Gama hours worked and then you can just see all of the data down here. So essentially on Friday, the 4z seven hours, that's what the data says. So as a brief overview of what we're gonna be looking at. So in order to get the file path of this guy, you can just click in here on the top of the Explorer and cultural c, all of that. So this is d directory and then the name of the file. We'll just do F2 to rename Control a to select everything and Control C. Make sure you have the extension there, none. So you actually have tutorial dot CSV or whatever your file is, dot csv. And this is actually important because otherwise blender won't be able to find it. So this looks like a good bath. One thing we have to do is press as art I front of it. This is because we have backslashes in our string. Everything between quotes is called a string and programming. And Python is actually, you actually have to tell Python not to handle these backslashes because you can actually do like a backslash n for a backslash r, which is like special characters, are not going to get into those today. You just need to make sure you either best art and front or escape every backslash with another backslash. So both of these bats are valid. If you were to just do Beck's lectures, that's not gonna work and they're going to be able to resolve its path. So be aware of that. I'll just use the first one because it's who reads the best. So alright, now we have our file path declared. We're just going to have to read out the actual CSV data that is stored inside of this file. So I'll create a variable in which I will store all the data. So maybe I'll just called data, maybe a bit cleaner. And then we will open up our file. So this is a bit of Python code is, is not bound to Blender this, this is just general Python code for opening a file. So with open and a path to the file, the claim and how the new line is a point that says reading matter as a CSV file. So inside of this, we'll be able to interact with our file by using the CSV file variable that is best in here. Using, I mean, this is just a way of opening a file and then having it close directly if you're familiar to programming. If you're not, it's really, it really doesn't matter. This is not a tutorial on file IO or anything, so just take my word on it. Then we will declare our CSV reader and give it our CSV file as a, as an input. Which will actually, I'll just show what this, what this returns by executing this. And I'm doubling our console because printing actually prints out to the system console, like we said before. And that Peri's course chapter, this actually returns a CSV reader object, which is not really anything that we can work with, right? Obviously going to have to rent over our reader results. So a reader is actually a list of rows. So what we can do is loop over all of our rules inside of the reader and then put that in our dictionary, our actual results dictionary. And again, all of this, what I'm explaining now is very Pythonic. Gold. This isn't, this has nothing to do with the blender or this has nothing to do. That is just not until they blend everyday decisions, all kinds of stuff in order to extract data out of a CSV file. You can look this up online. There's plenty of like stack overflow answers. I will give you exactly this. I'm just going to not spend too much time on this because this is really not the focus of today. But yeah, let's see what this gives us. Actually. Let's change this back to data because actually used data here. Let's print out data and see what this gives us. We will get a dictionary. So our first index will be day and hours work. So this is actually the first row. So that's maybe compared to inputs at output to what we wrote. So first of all, we get are either variable which is CSV type, and then we can loop over, so we can iterate over all of the rows at our indices we file. So if we were to open up our CSV file again, I'll use Excel this time so you can really clearly see the rows. You can see per row. So maybe I'll print out the length of this. So the length of reader will essentially be the amount of robes every have but didn't actually expected the work. Let me quickly show this. Yeah, it doesn't have it's not an actual list. For some reason you can iterate over it, but it's not like a list type. Like we saw before. This is the CSV reader object. So it's a little bit different, but you can loop over it, which is the most important thing. So you can scroll over all of the rows. I use the enumerate function in order to also be able to X as our index sorta currently rose Ed next. So this way we can actually have a unique keys. This is because if I were to use do for row reader, and then I could print out my rule. Let's do this for a second. Execute that. You can see these are all of the rows that are inside of my reader. So you'll see they are reserved Monday, right? So if we look here, we can put next to each other and choose a four when z3. So these are, this is the data and in their rows. So for every row, I'm printing out whatever is inside. But now when I have this, there is no unique key that I have. Because the problem with dictionaries is that you can never have a key twice. So if I were to say data, and I could put row 0, which is the first index with this list, which will be Monday or Tuesday or Wednesday or whatever. So if I were to take this guy and set that equal to one, which is the hours worked. So 84, three. Then I would only have one entry for Monday, one entry for Tuesday and so on. Because it will constantly overwrite the previous entry inside. That's just how I discuss how dictionaries work in Python. So that's something you have to be aware of. Your key will always have to be unique. Because again, if it finds, so, you see here Mondays eight with this is a bad example. So Tuesday is one, but it's actually, there's like four hours or six or however many. It only remembers the list, choose a and the rows. So in order to fix that, we have to keep track of the index. And if you want to do this, this is not a torus and error because there's not enough values to mpeg. Or actually, it doesn't really say it specifically. But this is just something I know. So you have to do enumerates over this, sorry, I get the actual overwhelmed check, but you also get the index and they can use our index has a key. And then we can actually create a dictionary inside of our dictionary that will store our data. So this would be the label and this would be the value for like, what did I call it. That's fine. And then we'll see we have an entry for each and every day, each Monday, Tuesday. They're not overwritten. This way we can actually extract all of the data. So that's already a big chunk of work done. We have our data neatly in a dictionary and it's ready to be worked through. 17. Reading the data ( .txt ): Hey guys, I'm quickly going to go over all. We can also extract our data when it comes from a text file. So you can see here is the CSV, which might be a bit too complicated for what we're trying to achieve. Now. Essentially the data is the same, even the way it's written, it's the same. I just changed the extension to read dot TXT. So if we would lay these next to each other, we would see that it's essentially the same. But this is a dot TXT file which makes it a little bit easier to work with and to interact with. So let's open up Blender. This is just an empty scene. Let's go to our Scripting battle. Greater New File. And then imports would be BWI, just like we're used to. Save scene, like that. Alright, and we are ready. Okay, so the first thing we're going to have to do is locate or file because we want to import it in blender. You have to know where it is. I'm just gonna quickly click in here. This is the same equity with the CSV, but if you haven't seen that video, I'll just go over this again. So we're going to have to copy the directory. So click in the top of the Explorer and people see that. Come in here and let's set up a variable called file path and then copy that. And so, so far, so good. Let's come back over here, grab our actual filename, make sure you have the extensions or it's not TXT. You need the whole the whole. We had all text here. And I can just add another backslash. And based on a filename, one less thing we have to do to make this a valid path in Python is a bar just before the string. There is some handling OPEX lectures that Python does by default and we don't want it to do it right now. So we can just tell it not to by bringing these are in front. So this is actually important. You cannot forget this. Alright, so essentially what we've done now is we've grabbed AAC file, but we still haven't done anything with it. So let's open it up. And I didn't even do like so. So with open file path, we want to read the file. So let's put r here, which is viewing mode. And then we will say as TXT file. So it was actually already done, now opened up our file. And you think, why didn't this within this declaration, so at this indentation level will be accessing the file. So whenever we are inside here are followed BY open, but whenever we are back out here, the file will be close. So this is really nice. This is automatically done with this width open syntax. The blender offers that Bitcoin offers better. Alright, so we're in our file at this point because my cursor is one indentation over from the start or from this width. In the file. And let's just print it out for now. So let's print out file path dot, read lines. Let's just read out all the lines and just see what that gives us and just click on Execute. It's gonna give me an error. So let's check that out by opening our system console. This is how we can actually see what writen as to say. So it doesn't have any attribute relay. Okay, so this is because whenever we are inside of our text file, we have to use our DEX file where we can't use our file beds because our felt bad is just the location of the file, text file. That's this one that we declared here is actually the content of the file. So whatever it's opened up, you've got to be referred to as txt file in this example. So that's not what I wanted to do. This execute that, that worked. Let's go back to our system console because it's still printing has also got to be output to the system console servers are gonna have to look here. And we can see we now have all of our lines in here. So this is a list essentially. So this is a collection of lines. Readlines function returns as a collection of lines. And we can see that here. There is this backslash n, which is one of the, the backslash character that I was talking about here. The backslash n is essentially telling your, your file this is an enter, so this is a new line character. And we don't really want this in our, in our data, so we can get rid of that. So let's actually create a dictionary like we did before. So this will be, your data, will be an empty dictionary like so. So this is how you can declare an empty dictionary. So it's essentially the same as saying this. But I was just typing labors for now. I'm sorry, my alarm. Alright, so we have an empty dictionary. Let's now loop over all of our lines. So we have X amount of lines. We never know how many lenses or do we have this collection of lines? So just like we did with the objects, we can just iterate over each and every line there we can find. So four-line TXT file dot read lines. So this will be our collection of lines over every line. One thing that we have to do, so let me just print line. For illustration purposes. We can see we have these, all these lines. And now notice that this backslash n character is not here anymore. But instead we have this enter. We have this line in between, which is essentially out is backslash. N character gets interpreted in blend in Python, which is not what we want, of course. So one thing we could do is record our strip this character out. So why are stripping? We can essentially strip anything from the right of our current string. So my line would be equal to. See you next Monday, fate. And I'm backslash n by saying our strip, we can actually start from the right and you can strip out this backslash n. So whatever we put here is going to be stripped out. So we will actually get this instead. So if we were to print that out to the console, run our script. You can see now that the enters our, our gotten disappear. So this is essentially the line that we want to store in our data dictionary. So let's redefine our line. Set it equal to the line without this enter at the end. And then we can actually use this in our dictionary. There's still one more thing that we have to do. So to see as reuse started, each column was already split by string, by the, by the function. But now we're actually going to have to do that ourselves. So we can see this line, for example, says Sunday comma five. But we actually need to split this up. So our day is Sunday and our hours worked is, is five. But as of now, this is just one entity, this is one string. So we have to split that up. So in order to split the string, we can use the split function. And it's really not that hard. It's, that's a nice thing about Python. It's all very readable and it's not that abstract. So we could say our day. This line dot split and one is split at the comma. So this will essentially return a list of our, of our string that we give it to a line as a string. We want to split this overdue coma. So we're going to take whatever is before the comma, whatever is after the comma. And that's going to be basically our list. Let me show you. I'm just gonna print day right now. This is not going to be the actual day. This is just going to be the list that was split over the comma. Sorry, this is not my correct yet, so let's run that. And now we will see we have our day and our hours worked separate. So this is now a list with 22 items and so one for each column. Since our columns are split with this comma. So our day is actually the first one. So we can say and next is 0 because we always have to start with index 0. And our hours worked would be index one. So that will be at everything after the colon is everything before. And this is everything after. Well, of course, if there were multiple commas, there would be more than two indexes in this list because that is how spreading works. It will split before every chroma. But since there's only one, will only have whatever is before and whatever is after. So that's exactly what we want. So what if we could know, for instance, they would print hours worked and we'll see that this is exactly what we want. So right now there's still, we still don't want this for each line here. This is just a header or labeling or whatever you wanna call it. So one thing I'm gonna do, I'm gonna use the enumerate function again. So this is a nice way of bytes and allowing us to get a hold of our current and next. So while we're looping over all of our lines. And the way we had before. So for line in file, read length, read only, grab our lined object. Three only grab the actual string object that is in the list that we don't know what the current index or the current iteration is, we just get the object. But by using the enumerate function, we grab our index, so our current iteration and online as well. So this is actually a lot more Pythonic we could also do for index in range and then the length or like the amount of lines that we have and then are lying would be the text file is read lines in a. And the variable as well, an acre just gravity can exploit this might already get a bit confusing. So let's just get back to this way of reading it. So now use essentially by using this enumerate function and our collection, we've essentially unlocked this index queryable in our for loop. So we can now access this as well. So like we did before, we will take our data dictionary or key has to be unique, so we'll put the index here, and then we will stored our data in here. So I call this labeled this as actually, as we call it a day for now, but it's a bit more self-explanatory. And ours worked is hours worked. And if we were to print data down here, we would see that we have, well, we still, we still have this first line. Let's just get rid of that now since we are using the spin index, we can filter. So we can say if my index is greater than 0. So for the first line, our index will be 0 because this will be the first iteration and we always start at 0. So this will be a look here. And 0 will be this line. So we don't want to be, we're basically just gonna ignore this line. So whenever it is, my index is more than 0. So whenever we are here or here, or wherever, we're going to actually do what we wanted to. But before that, just skip it. Essentially. That's why we put this if statement, this filtering all the way at the top. Because you don't even want to strip. We don't even want to bother if it's the first line, just go on this continuum. It doesn't matter. If you print this out to our console. We'll see it starts at one. And then we just get all of our days and over hours worked. Alright, so maybe let me just quickly show you how that would look if we didn't use our index here, because this is a pitfall of or dictionary that you have to be River. So let's say we just put our day in here and then we would set that equal to however always that we worked. It just looks a bit pretty array list could just work. So let's execute that. And now as you see, we only have seven entries here. We only have one entry per day. And that is because a dictionary key can never be, can ever be in there twice. It will always just overwrite the previous dictionary key. So let's say we had Monday, so we put in eight. Ok, that's all very well. But then we'll have Monday again and then he will just override it with one. So if you, if you look closely, you will see that this line is essentially just a last week that the sinner doesn't hear. So Sunday to Saturday six, so it just kind of goes back and it overwrites whatever we have inside. So that's not good. So if you have data that is duplicated here, I mean, if the label is duplicated or, or if any column is duplicate it you cannot use, cannot use that column as a key or dictionary because you'll lose data. You will, you will only remain the last, the less entries. So that's not what we want. So we'll use our index, which is going to be unique because it's just the current iteration of the line. So this is basically the line number. So I use this instead. And that will just create a dictionary inside and store our data here. So we actually don't lose anything. Will execute that. Though we have all of our data neatly and the same format as we had when we used to see as V library. 18. Creating the bar chart: Alright, so now that we have our data, let me actually quickly rename this back to the same way that you guys over at the csv side habit sort. It's really label and value. If you haven't checked out the video, I did. I did a bit more explaining over how you would like to file opening and and the file path and stuff works. So if you know that's a bit unclear for you still, you can maybe go check that video out as well. Some more info for enumeration as well. So it's not a bad one to check out. But once you are here and your data is printed, you're actually ready to go to the next step, which is actually visualizing the data, because that's why we're here, right? Do you want to create our 3D 3D bar chart? No, it blender. So that's what we gotta be doing right now. Maybe first, let's write up our little clean up portion that we've been doing for the last couple of scripts as well because we don't want to go in and remove all of the geometry or I'll be objects every time because they've gotta be creating cubes and stuff from now on every iteration, every time we run the script and we don't want to always go into view point and we remove everything. So you should remember it is by now. So for every object in BPI dot data dot objects, so all of the objects are a collection of objects. And let's go over everyone individually. And then we will every object individually. So we run this, everything's gone. Meshes might still be here. So this is what we saw before in our and our sign course or math course. Maybe I won't write it here. So if you want to get rid of it, this is a good exercise for you guys tried to, tried to remember how to do it. It's very similar to what we've written here. Keep in mind that we don't want him to move objects, but we want to remove meshes. And that should be a good hint for the guys who want to try this out at home. So I'm not gonna go into it at this time. So let's actually maybe a little bit. So let's say the data type is here. Cleanup happens here. And now we all do and visualize data. Alright, cool. So essentially what we wanna do is for every index, for every row, or every bit of data that we have, we want to create a bar. So what we're going to want to do is go over all of our data entries. We could do is we do for data entry and data. Let's print that out. Let's print out data entry. See what we get. We get step-by-step. You get all of our indexes, which is now essentially what we want. But we could use this in order to grab our data through me on an HLOOKUP, our current data entry in our data dictionary. So if we were to run that, we would see what we want to see. So this would be our data. Let me open up a text file so it's a quicker. So you would see lines. But then in Blender and bison. So, so far so good. And we will kick-off, sorry. Alright, should we get so we have our data, we are looping over its story or checking every data entry individually. And essentially what we wanna do now is we want to create a buck. So to do so we'll just create a cube quickly to make sure we know how this works again, because we keep on forgetting. This is a simple cue. Now, the thing is I want to resize this in order to make it, to make the height b the current value or the current, the amount of hours that we've worked. So in order to do so Alex, but to size down to one, because I'm going to end up with resizing this up. And I want to just multiply it by one so it's a little bit better. So you don't have it twice as long as it should be resolved before they can get rid of this enter Edit mode. And the location is going to have to change as well. So we don't just want all these bars to be overlapping each other. So let's just put them in the y direction. So it says we are using a size of one. Our width or the cube will be one at all times and are index or hour. Iteration will also increments with one. So let's again use the enumerate function, which is one I use all the time. So to, to repeat one more time, the enumerate. Using enumerates before our collection unlocks, our index, unlocks our current iteration. So why we'd just, for data entry or for item in data, we only excess or items that you can print. Item that's fine. But there's no way of keeping track of what iteration railroad or how many times we've already run this loop. We could of course set a variable i equals 0 and just I equals, equals one every time in our loop. But this is very non Pythonic. So Python offers this functionality by default, by just putting enumerate here. So unlocking our idx, our index, and make sure you have this order setup correctly so it's index first and then actual item. So that's an important one to note. So we have our index now. So you might as well just put that as our y-coordinate. So at the first iteration, our index will be 0. So our y index r, y coordinate will be one, will be 0. I'm sorry, let me actually illustrate. So our y-coordinate till v 0. And our next cube, or next iteration or IV, x will be one and our y coordinates will be one. And this just goes on and on. So we have 2345 and so on. So this way we can really easily just line up or cubes. Since we know that the length is always going to be one. And this is always going to increment with one. So this is works out fine. Okay, now, it's already looks like a bar chart, but it's not really interesting, it's all just the same. So we're going to have to scale these up. So let's do it manually again to make sure we know how to do this. And I began to steal the command down here. So we can just resize it, the value, whatever. So this actually shouldn't be ten, right? It should be our actual value. It is absolutely love. This should be a two or six. So in order to get this value, we will need to look up our current data entry and data dictionary. And then we still won't actually have, let me actually show you what we have if we do this. So now we have just the venture cubes, but this is our value. And we don't just want this right. We want to look up our value within our data entry. So we actually have to look up twice because we have a dictionary inside of a dictionary here. So we're going to have to look it up again. So by using these brackets and then we want to type in values. And this is the key that we used in order to store our data, our hours worked. So if we use this, we will see our value is actually our value. So now that we have it, we can place it instead of R, then it becomes dynamic, but it actually stops working. So let's check this out. Expected sequence item of type float, not string. Ok, so we print this out. This looks like numbers. All right, this looks like for but essentially what DEX files or CSV files as well do is they guessed whatever value it finds two string. So instead of storing forward, it will actually stored a string representation or for same with any other data type. So let's say you have a list of numbers. So that's 123. It will actually just wrap this in quotes and turn it into a string. So you won't actually have it. You won't be able to use it as a list. You would have guessed it back to a list first. So that's something to keep in mind. But we know that this is always going to be a float because we do have some control over our data. So we can just explicitly cast it to a float. So this will, during your number into a float. Now you have to be aware. So essentially what we have now, so value is a string that is four. So if you were to print value or maybe just print it like so, it would look. Like it's a value to a float. But if we, let's say we do value plus three, this wouldn't work as you see, can then be concatenated string to string. So our value is a string. Still. We were to do this more explicitly n-type, get the type of our value. This would be a float. So in order to change that, we can say value equals float representation of R value. We would see that our value is of type float. And if we were now to 3-2, it, this would work. But there is one thing that you have to be aware of. So let's say my value is string, an actual string. So whether this is a string of four or a string of tests, this is the same thing if I were to type, to look up the type. So B string, let's say my value equals desks. That value is, it's still a string, it doesn't know what, what there is inside. Now we know that four is an, is a float, so we can guess it to a float. But let's say our value equals destiny or try to, try to guess this to a float. This isn't going to work. Could not convert string to float test because this is not a, this is not a number, it is not going to work. So what we do here, as we guesses to afloat, but let's say our value is actually not, it can't be converted to float. This is, this is going to crash our program. So this is something you have to be wary about. Now we know that this is all gonna be numbers or this is fine. But just keep that in mind. That you shouldn't just recklessly cast everything to float because this might not always work. But in our example this is always going to work. So let's do that and we see our bars are the correct size. Now one more thing to note is that this kind of looks like like a sound wave or something which is not really what we want. We want them all to be flat on the floor. So you're going to have to move them up individually. And as you can see, it scales it from the center. So half of the, half of it is going to be below 0.5 of it is going to be above 0. So basically what we have to do is we just have to move it up half of the height. So this value is a height, changes to ICT. So this would be the height and then this would be the height divided by two. So if you were to run this, we can see everything is aligned properly. We haven't as one queries you want, let me maybe she in this, in the data, I changed this to 19. C. That's teachers back down. So it looks a bit better. And there you go. Now I have a bar chart that there's an actual 3D bar chart, not like somebody's word imposters trying to achieve. So you can build on top of this, of course, you could also use use this reading of data from a text file and create a cityscape or something in the background to get, just get some numbers and then get some buildings. But for now this is just a bar chart. It does not say that much. We can maybe add some some labeling or some some other things kids do way we set this up in our dictionary. We actually know what our label is, right? So we might as well use this, print this out, or actually store this. So this works. So we could maybe have it like laying on the floor here. So maybe try that. 19. Adding Labels: Alright, so now that we have access to our label in here, so maybe let me quickly print this out and make sure that this is exactly what we wanted to be. So this is just a days. Let's actually put this into our 3D as well. So we don't just want to have to look in our console, right? So that's what it is. Any 3D. Maybe we should create some text for it. I think that's the best way to represent this. So doesn't make me do this manually first to kinda make sure how this would work. Okay? So what did we do? We add it. We deleted, and then we went back. Alright, so that means utilize data. Actually, I'll just put this here as well. So this is for the bar. And then we will label the bar down here. As our label is this. You want to add some text. So the same, this kinda looks similar, right? So instead of primitive cube at this will be decks add, enter, Edit mode equals false. I think we do want this to happen. Our location can be the same as the as r cube. We cannot offset this and eggs. So that's offset by 1.2 should be a static one because we know are actually not. So we know this is one, so this size is one. And we can see the lines it already on the center. So we don't have to do it by 1.2. We can do it by 0.6. So this distance from here to here will be 0.05. and we would just want it a bit further. So let's do that. Let's maybe already see what that looks like. So we should have a bunch of text here. And we should push it back a little bit on the, on the y. Because I see already aligns it as well. Yet already aligns it like this. But our Q was actually going both ways. If we were to do this should look a bit better. We keep going into edit mode, which is normal because that's what we tell it to do. So let's now actually already edited. So first we're going to have to get rid of the text that is there. So we'll just do this. Now one thing we have to do here is instead of previous or selection, or it's going to have to change this to previous word. Because we, we could also just do this five times like we did here is pressed backspace five times B. This way, we're actually just gonna removed all world, removes all word because a bit easier. And then let's actually insert our texts that we want. So text insert text recalls early. So we want to I'm sorry, man, Open. Golfing all time has really annoying. And we're going to try not to do it anymore. But so we're basically setting up our label and the text and then we just want to get out of edit mode. So let me copy this. Oh, sorry, we're ready for the next one. So what we do now is we look up our label. Here we create a bit of text. We get rid of the, the sample text. So this is a stacks. We don't want that. We input our label text that we want. So our day And I will just go back to two LLC mode. So if we run this, we can see we have our day's. Looks nice. Maybe one thing we could do, because this is just now flat. There's a extroverted, maybe it's like a bevel or something. So complex object which is going to be current object dot data. But to own the 0.01. See how that looks. And now we have some thickness at least. So if we compare, if we don't do this, it's flat, do it. We have some Robin is it's quite pretty thin. Scale it up on Z. So dry that maybe it's already, but I think that's fine because it looks a lot better with the shading because air is like actual geometry because this is just, Well, this is already with the bevel, but it's like quite flat. With this, we have a bit more three-dimensionality. I would say, well, this is all just personal preference, right? I'll scale it up by two, just make it twice as thick as it should be as it was before. So we can have it like this. Exaggerate to show you, she's basically the thickness. Ok. I'll put this in the variable as well to make it pretty so we don't have all of these magic numbers. I'm actually a couple of them. So our thickness set that to let this guy here level that would be 0.01. We also have text which will be 0.6. So I'm basically just translating all of these values, variables. So when we read this, it's not just magic numbers and we can have this centralized location of where we adjust these values. So there's no more. I mean, this was 0.05. is because we have one here. I mean, can leave that in. So I take now let's get, you generally just want to avoid having numbers in your, in these nice functions. You just want to have it be x because then you always have to go look for where these values are in IA, this is our y set the thickness. So I have to look at the zed value here. Now you can just call it x thickness. Boom, to change it right there. It's a lot more convenient. Okay, so now we have sudden labeling going on. This is already looking quite nice. Maybe we can have some labeling on the, on the zed axis as well. 21. Labeling the ticks: Alright, so we have our thick silicon, okay, the replacer kinda giving some more meaning to the data, but not really that much. This is just kind of a visual thing. So now we'll actually add up our additional information in here as well. So we're going to put the number or the ticks are next to, to take so they say a little bit more and then use where the. So for this we're just basically gonna do the same as we did with our labeling down here. So we're just gonna put a bit of text down a line that's appropriately, make sure that position is right. Yeah, so how are we going to be doing is just copying this over and then just changing so values. So maybe the location they can miss and the size is actually fine. So I'm just gonna not mess with this whole stuff here. The actual tax is going to be different at another location, of course. So for starters, I can actually copy the location of our our dick. I just put that in here. And then the text I will just make 0 for now just as a dummy to see how this works. And we can already see our texts as being positioned roughly in the right place. Well, at least it stir it matches a thick, but it's not really aligned properly. So we're going to have to push that up a little bit. In our location zed value, or current value is going to have to be a little bit bigger. Here we're going to have to through the thick thickness divided by two in order to put it on the top. And then our our actual number also has thickness or you're going to have to add that as well. So this will be our bevel that times r thickness. So let's do that as well. And so you want to be quite a big one, so that's maybe create a variable for it. So number, not sure this is a correct way. Number because they shouldn't look to set x is, let's just call it that for now. So we will have set here as well. Just so it works out. It'll do all our calculations here. So we'll take the current value, which is the middle of this block, will add the thick thickness. So half of this is taken is thought to it. And then we will also add our battle that if I can find that level of depth times texts thickness as K here. And this is a mouthful just to make sure that it's aligned. So let me show you. And I was perfectly on top of of Arctic For every, every tick. So that works out nicely. Now one more thing we have to do is we have to rotate it. So this will be around z and then around y. So if I were to do our set 90 or 90 or to pull it up, I could just copy these guys down here. So after you've done this, it doesn't really matter where we put this. So we want to do it around, does that, and then around the y. So for execute, they're all going to be. Standing where they should be bowl. So we already have some number on ticks. So that's not bad. Now we just have to make sure that it's to correct one. So basically what we wanna do is we just want to put the, whatever is at position it is as a, as a value here. So we will just take current value and put that here. Now this isn't going to work because our current value, that's going to be a float. It says actually got to be a number, but we need a string type. So instead of saying, I'll just go here and the console be quick to illustrate. Instead of saying my text equals to 40, which is you want to be a float or an integer at this point. But this is not a direct because we explicitly need a string. So you can see here expected this string. So if we look, our type is not string, so it's wrong. And if we were to do this and then type, get the type, we would see that it is a string, so everything that is between quotes is always going to be of type string. That's important to note. So, well, we can't just grab quotes around this because its current value is actually referencing the value. If you were to do this, we would just see the word current value here because we don't want to do that, right? So you want to actually guessed the value that is inside of the variable current value. We want to display that as it next. So one way to do that is to SDR and then the value. So if I were to put x or let's say current value equals 40 is 0.02 mature it's a float. And then we type where you get the type of value. So this is gonna be float. Right? Now, if you were to cast it to a string, you can see the crops are going to be wrapped around it. We don't have to do this, we just have to write this. And let's actually reassign it to its current value equals the string representation. And then if you were to type it out, so we can see this is a string now. So STR brackets, just like we did with the float, a bit higher up. So every guest, whatever is inside here, to a floating point value, we're gonna do the same to a string. So here we're just going to cast it to a string. And if we were to do this, we would actually get there. They are. Now the alignment is still a bit off, so you can see that it actually gets aligned to the left. You'll want to align it to the right. So we can just get, get the, the size of this. So this is now three characters and this is four characters. So the offset is going to be a little bit different. So let's actually add a variable here and it's a value as string or SSD storage there. Because one additional thing that we can do now, if we come back here, start current value is here of type string. And now we can actually query to lengthen. So the length will be four. So that means there were four characters in the current and district. So a 1234, it can even get the index of u1. So current value 0, this has got a report. The first index is going to be 0.23 and see you next year. This has four characters to query for it. It's not going to work because the index doesn't exist, because there is only four and we start at 0, so it's 0 or one to three. So that out of the way, we have a couple of characters and we basically want to offset it accordingly. So here every set are thick offset, we want to either add or we want to add to it, but we don't always want to add the same amount. So what we wanna do here is we want to add the length of our current value times a certain letter with variable. So let's assign this one letter width. And I'm going to estimate this to be one. And let's see what we get. Now. Not what you want. So this is the only reason. So I reckon this is a little bit too much. And this might have to be negative because you are going in the opposite direction. So let's look what we have now. Yeah, this is definitely not one strip fire yet their ego. So because we just use a default size of this text, we can just, it's going to be one, so we can take half of it and it's going to be the single letter size. So this looks good. And let's maybe then. So this is now a line on the right. And that's maybe just to tick opposite. To be. L is still gonna be, May I figured they're going to be relative to pet. So basically what we want to do is to go sit divided by two, separate, a bit less far out. It's not that Bertier that. So yeah, there's just comes down to personal preference. Again, I just kind of figuring out where to put this. Maybe I wanna do a little bit more even. So that's an additional offset. So this is a number. Let's make this 0.1. And then this, this here. Let's have a look at it, a bit bigger to make sure this is how you want it to be. And you can play with this position. Of course, this is just personal preference. I'm just showing you how you can get it's alive and how you can get the values and where you put them exactly. Doesn't really matter that much can even make him a bit smaller. If let's say you were like pack, there might be a little bit pig. And now let's actually see if they adapt properly. So let's bring back our data quickly going to browse to it. Okay, so tutorial TXT. Lower this down to nine again. Let's see. Now we have something like this. You'll also, because now it might be a bit stupid to have 0 everywhere cast to an integer, but then you lose some precision, of course. So this is a, some things you have to take into account. Let's put 39 quickly to see how this behaves. We are always going one over current setup. So make sure you like this. I usually do. It doesn't matter that much. The main thing is that it works. This, that shouldn't happen. But now we do have some rounding issues while it is rounded by default, so by blender, but our numbers are way too long now we don't want to display this, might appreciate it. So let's actually take this into account as well. So the alignments still work. So that's quite cool. So it's still going to be aligned to the right. So R, S the works. But let's round this off. So our value as string is going to be occurring value but rounded. So let's take two values after the comma to the good around him point. Alright. Maybe quickly to illustrate scissor, round function and blender. So you can just round any float up until any amount of precision. So if I were to have a number which is 0.0.0 is five, and that would split a number. Well, maybe it's a bad number. Number equals 15, something. Number. I could round this number up until one value behind the comma I would get this. Would actually be clever enough to round this up because the next value is a nine. If it were to be 16.128, show you. It would be six simple went to was one, it will be 11, so codon. So that's a bit more about the rounding function. Isn't already two important. It works the way you expect it to work. So that's always nice. And this is how we can add more meaning to our data, to our graph. 22. Creating and Randomizing Materials: Alright, so we've been talking a lot about objects and about meshes and all that stuff. By the ended, of course again, I want to cover a little bit more ground and I want to talk about materials as well. So the way we use materials is quite, quite similar to the way we use objects. So maybe I'll just illustrate it with a quick. You can just create a new material and see what that looks like. Cbp, why not upstart material dot nu. So upstart material that knew, okay, it's a little different. But if we were to script this out, it would actually work the same way. So let's create one material at the end now. And we will see they have 10, actually have a couple materials. They go already run this a couple of times. So you see every time you run this, a new materials kinda be created. But the old Walden's are also going to be there. So maybe let's quickly get rid of those. We're going to do so by the same way that we get rid of our objects. So maybe I'll pause for a littles, little bit. I mean, you should pause the video, figure out how you can actually remove all of these materials. It's very similar to what we've done before, and it's very similar to what is on the screen now. So I'm gonna do it. Pause if you again, three-to-one, let's go. So we want to go over all of our materials, grab the current material. So for every material in our materials, just like we do for every object and other objects. Bpi dot data dot materials because we're checking materials now, remove guarantee material. That's if I were to run this now, there will only be one material, which is this one here. I'm not sure if I can pass a name here. Well, actually, as a quick side note, it is generally bad practice to use BPI dot ops. Is it just something that we're going to say and not explain too much? Because there is a whole reasoning behind this. Mainly context and balls and, and there's blenders stuff, blender, API stuff that I'm not gonna get into. It. It's a bit too complex for the current scope of this course. It's mainly just good to remember that BPO i dot is something you should only use when absolutely necessary. So when you want to create geometry is used to way to do it. But when you create the material, it's essentially whether to use BPI dot data, dot materials. And here I can just call this whatever its artists use name for now. And doing this way is actually a bit more, a bit less error prone. So actually we can see here this is varies. Or do you say restricted, the ui.R stuff. It's operators are quite locked down to their environment, so it's best not to think of it those and do just use PPI dot data stuff or any other calls essentially. And now we can even assign this to a variable and we can print it out just to check what that looks like. So you can see we have a material. It's called name. I can call this whatever material. Alright, so now essentially we know how to create a single material. So let's do that for every cube. So we can do this by pressing Tab and the beginning of the line, which is, whoops, which is you want to push our, our line into our for loop. So again, everything that is at this indentation level is going to be looped over x amount of times. So this line is now going to be executed to a 100 times. So if I run this and see we have a 100 materials, the name is static, but it just adds this dot 048 or dot, dot whatever dot, dot number. Behind this. There's other really mattered, the name just at URI or wherever that. So now essentially we have created a material as we create the cube. So the only thing that lasts us assign our material 3D cube. So we can do this by doing BPI dot context object, which is are currently active objects with which is our R cubed have you've just added, we can access the data materials of this object, and then we can just append our current material to it. So we can see now essentially BPI dot context of objects dot data dot materials, which is a, quite a mouthful, is referring to this here to our materials. And by clicking this button, we are appending to it. So it actually is creating a new one and then assigning it directly already with this way, creating it and then we're appending it to the current object. So the currently active object, the active, the object and it's just been created by this function. So if you were to do this, we would see that every cube now as a material, C cube 017, that's material 017, and so on. So that's already looking cool, but all of the materials are still the same. So power to go to the shader editor. Equilibrium, not even using notes are being displayed here. But yeah, they're all looking exactly the same. And we don't even need to use nodes to make it not be the same. So one thing we could do is a material that diffuse color equals. Let's just make it red for now. Just see whether this works or not. Reduced need for. So this would be our G be a. So if we worry too, I'm gonna run this. So basically what we're setting as our base color. So as you can see on the, on the tool tip it says dot diffuse color. And here you can see f, r, g, b, a. So 1001. We don't want them all to be read. Of course we want them all to be random. So we can use our random function like we have here to get a random number between 01. And this. We want to do it for every channel. So we wanted this for red, green, and blue. I'll follow you is always going to have one. It's always going to be fully transparent or opaque as the word transparent to the other guy. So by doing this, we're basically generating a random color. So I ran them color for every cube, or assigning that color through the new material that we have created for each q. And then we are assigning the material with a random color to it, a cube. 23. Controlled Color Randomization: Alright, so we have our random colors assigned to our random cubes. If I were to run this a couple more times, you would see that all of these cubes now have individual colors. So some lookalike, but they're all unique. I mean, there might be one duplicate that there's like a thousand cubed. Let's just assume that for every cube we're actually randomizing. So for every Q will get a unique material. But let's say we wanted to take a bit more control and we want to not just have a 100 random colors, but let's say we want to have like ten random colors. So what we could do is amount colors equals ten. And then same way like recreating our Android cubes, you can create a 100 materials. So for i in range of a mountain colors, we can do our material creation or randomization. And then this assigning, that's actually not going to work. This point because we don't have our queues yet. But let's for now just copy this in here. So we will do is we will create X amount of materials and then we will randomize their colors. So now it wears out. Get rid of this. So we're not going to create a material for each cube anymore. There were still have to assign material to the current cube. So this is this can still stay. But does material references and our broken because there's no access to these materials here. So maybe let's keep track of our materials by creating an empty list at the top. And then actually appending our material through this list. So what we've done here is we have created our material. But this line, we've randomized and then we've added it to this collection of materials. This is where reinitialize this collection. So we just get an empty collection and empty list of materials. And then as we go through our list, as we create these materials are filling up our collection. So by the end of it, if I were to print our materials and I'll just run this. I'm gonna just chalk thermal developer console and it keeps disappearing. We'll see now we have a collection of material. Objects are BPO, adult tail dot materials, doped material. And this is actually a material object and you can see this is a collection of material objects. So this is what we want, right? There is a reference of the material being kept in memory because this is also called the material. But I'm, so that's why we actually do see a color and this doesn't crash. If I were to call this anything else, it will break. But let's just leave it for now. So we basically just want to take any, any material out of our collection. So what we could do, it would quickly grab our console again as you use the random function. So random dot uniform, well actually we're logged on, I want to use random dot uniform. We're going to use something else. Because like we saw, three dual random dot uniform between 010 because we have, we have ten colors. So actually what we would do with a month of colors equals ten, just kinda make sure we have the same, same look we would go from here to amount of colors. But like you see here, we keep getting these, these floating point numbers. Random dot uniform butter is a floating point number three, we're do random dot uniform. You would see methods of random, random instance get a random number in the range of a or B depending on rounding. Well, it's not explicitly saying it's floats, but we could tell, right? So we can, we can debug or good programmers. So let's actually check out what randomize to offer. Besides random dot uniform does a bunch more functions in here. Not a thing you could do is just Google. It got like a random integer between a cupola, couple of boundaries, but let's do it. Blender way for now, just hardcore. I can already see rent int is probably going to be a good one. Random range. Let's get the help on. I wanted those random dots. Range. Chooses a random item from arrange, start, stop. This fixes the programmer to rent, which includes the endpoint. So in Python, this is usually not what we want and it's actually here. It's also an over one. So we don't want to include the endpoints. So if I were to get a random dot-dot-dot range between 0 and the amount of colors, we would get an integer. And now this should actually never be returning. Then, because we see here nine, this should actually be the highest value that this returns. So let's do this a couple times and make sure we never get anything above night. Like we never get ten. I'll we shouldn't because we read the help, but it's always good to check and be sure. Because as we know, a list, just like this materials here, uses indexing and the indexing starts at 0. So when we have ten items in the list, the last item will be accessed by the ninth index. So if that doesn't make sense, we have index 0, index 123456789. If we look here, we actually have ten items. So we have 12345678910 items. But it's something you really have to keep in mind when working with lists is that you always have to start from 0. That's just something that you have to really, really remember. So this works random renderings. So you wrote two amount of colors. So now instead of just taking the last material that we have here, we can just go query certain index from our materials collection. So we will get a hold of our materials collection and then we will basically just query a random index. So this will be a random index which will be used to look up a value in the materials list. And this will just return a random material. So if we were to run this, you will get then random materials which should be quite equally distributed. Maybe let's do like to materials to make it a bit more obvious. And I can see we only have to count this way. You can take even more control over our, our randomization. So it's not just completely random.