Blender 3D: Noob to Pro/Export scripts
Blender yalnızca tam animasyon yaratmada faydalı değil fakat iyi bir modelleyicidir de! Blender tam 3B sahneler kurabilirsiniz. Ve kullanışlı bir formatta da export edebilirsiniz. Aslında daha ileri işler için de kullanabilirsiniz. Örneğin, başkasının yaptığı 2B freeware bir oyunda level editör olarak kullanıyordum. Oyunu bitirmeye kısa bir zor bölüm vardı. İki haftalık bir süre kalmış olmasına rağmen level editör yoktu. ASCII düzeyinde formatta materyallerin listesi noktalar üçgenler ve nesneler. Blender Python exporter'ı hatırladık. Blender için bir export scripti yazmak için cesaret verdim. Böylece level editör olarak kullanıldı. Çok iyi çalıştı. Halen blender bu oyun için tam bir level editör olarak kullanılmaktadır. Bu klavuzda Blender için python export scripti yazmayı öğreneceğiz. Önceden python bilgisine sahip olmaksızın, sahnenizdeki objeleri nasıl sorgulayacağınızı ve onları bir dosyaya nasıl yazacağınızı açıklayacak. Aynı zamanda export script kullanmanın yararlarını, export esnasında verileri nasıl işleyeceğinizi gösterecek, varolan diğer formatları kullanılarak yapılamayacak işleri yapabileceksiniz.
Ve blender açın(2.44 veya daha üst), default sahnenin yüklendiğinden emin olun. Haydi başlayalım.
[edit]Sahne hakkındaki şeyleri ortaya çıkarmak scripts penceresinde pencere tipini değiştirmek
Bir şey export etmeden önce, neyi export edeceğimizi bilmeliyiz. Bu bilgiyi almanın bir yolu Outliner penceresidir (SHIFT+F9). BLENDER a tanıtılmış her şeyin listesini gösterir. Şimdi bu bilgiyi scriptten alacağız. Scripts penceresini açın (yeşil yılan sembolü). Csripts isimli menüye tıklayın. Scripts → System → Interactive Python Console a girin.
Şimdi büyük an için hazırsınız, ilk Blender script komutunu çalıştırmak üzeresiniz. Bunu yaz ve RETURN a bas. (Veya scripts penceresine en üste import Blender yaz alrtına şu satırları 'dir (x)' satırların başına print koy )file->Execute): seç. [Not:t(" işareti olmaksızın) "import bpy" yazmışsan list functiondan önce (bpy.data.objects) kullanmalısın aksi halde blender da "python error " alacaksın]
list(bpy.data.objects)
Sonuç olarak şunu göreceksiniz.
[[Object "Camera"], [Object "Cube"], [Object "Lamp"]]
Now, what just happened? The line "list(bpy.data.objects)" consists of three words, separated by two dots, The dots just separate different things. The first, "bpy", means to use a function from the bpy module. data is a sub-module of Blender. And finally objects is an iterator of bpy.data. The list() function is used to loop through all data in bpy.data.objects and return that as a list of all available objects. In our case, this is a Camera, a Cube, and a Lamp.
To get more information about an object, you can use the object name as a key in bpy.data.objects, and assign it to a variable, like this:
camera = bpy.data.objects["Camera"] cube = bpy.data.objects["Cube"] lamp = bpy.data.objects["Lamp"]
Be sure to import the bpy library first.
import bpy
We just assigned the three objects to three variables, camera, cube and lamp. To see the contents of a variable, type just its name:
cube [Object "Cube"]
camera [Object "Camera"]
lamp [Object "Lamp"]
Sometimes it's useful to use Python's dir() function to get more information about an object. For example
dir(cube)
will write the names of all functions and properties of the object. Quite a lot. But don't worry, soon you will know how to use all of them. You also may want to find out the type of something, which you can do like this:
type(cube)
In this case, just typing "cube" already displays the type, but from within an actual script, you would use type(). Something else which can be useful is viewing the documentation of Python objects. To do so, use the help() function on a variable or object.
help(bpy.data.objects)
This will print the documentation of the bpy.data.objects function we used. Of course, an easier way to view the documentation is the online HTML help. Click on Help->Python Scripting Reference. Hopefully now your browser opens and displays the online documentation of the Blender Python API. If not, you should find it also here:
http://www.blender.org/documentation/244PythonDoc/index.html
In the documentation, click on bpy, then on data and you can see more examples. Using the documentation will get absolutely vital whenever you need to do something in a script not covered in a tutorial. And you will need to do so, else you wouldn't want to learn scripting at all.
Another resource you will need, depending on how far you will go with scripting, is the Python reference:
For this tutorial, maybe read the "Tutorial" başlık in the python docs, but you will understand everything without doing so.
Now, let's try to find out more about our cube. Type:
cube.type
It will tell us that the cube really is a Mesh object in Blender. Look up "type" in the online docs. Since the variable cube holds an Object, and "type" is an attribute of that Object, click on Object. There you find its "type".
Now that we know that the cube is a mesh, let's find out more about the mesh.
mesh = cube.getData(mesh=1)
Every Blender object has data assigned to it, depending on the type. In the case of a mesh, the data are of type Mesh. In the documentation, go to the top again, and look for the Mesh module. It will contain documentation for the Mesh type. You can also try
dir(mesh)
to get an idea about the available functions and properties. Try these:
dir(mesh.verts) dir(mesh.faces)
The first line will list the 8 vertices of the cube's mesh. The second line will list its 6 faces.
To get a member out of a list, you specify the index in square brackets, starting with 0. So:
v = mesh.verts[0]
This will assign the first vertex of the cube to the variable v. By now, you already know how to use dir() to get a list of possibly interesting things in v, find out about its type with type(), and where to look for the API documentation. It is in the module Blender/Mesh, when you click one "MVert" under "Classes".
v.co
This will display the 3D coordinates of the first vertex. Now, what if we want to know the coordinates of all vertices? We could of course assign them all to a variable, but the real way to do this is using a looping constructs. There are numerous ways to do this, but one simple way looks like this:
for v in mesh.verts: print v.co
The for variable in list: construct assigns each element of the list to the variable in turn, and then executes the commands after the colon with the variable having the value of one particular list element. In a real script, you will have much more than a single command after the colon - so you would write them in the following lines.
By now, you should know enough to try yourself at a real script in the next başlık. [edit] Creating a script
You can write scripts either in an external text editor, or in Blender's built in text editor. The built in text editor can be hard to use if it doesn't have the standard shortcuts of your preferred text editor. To copy text to and from your clipboard in blender, you have to use CTR+SHIFT-C and CTR+SHIFT+V, otherwise it uses an internal clipboard. Otherwise, it is quite usable. You reach it over the window selector, or by pressing SHIFT+F10 (SHIFT+F11 for Blender 2.41 and up). If you want, you can enable line numbers and syntax coloring with the buttons at the bottom. Create a new script with File → New, paste the code below into it, and save it. Or alternatively, paste the code below into a file, and open that file with File → Open in Blender. As name choose something with the extension .py, for example wikibooks.py. Put it into Blender's user scripts path.
For different operating systems this is:
* Linux: ~/.blender/scripts * Windows XP: C:\Program Files\Blender Foundation\Blender\.blender\scripts * Windows XP (alt): C:\Documents and Settings\USERNAME\Application Data\Blender Foundation\Blender\.blender\scripts * Windows Vista: C:\Users\USERNAME\AppData\Roaming\Blender Foundation\Blender\.blender\scripts * Mac OS X: o Under Mac OSX the path is actually hidden in the blender.app so to know the path you would have to know that the script folder is actually hidden in the blender.app itself. Assuming that Blender is in the applications directory the path would be "/Applications/blender/blender.app/Contents/MacOS/.blender/scripts" If you try to open the .app contents from the finder you will notice that .blender başlık of the path is not visible, while blender will still be able to navigate to this folder. o Right-click (or ctrl-click) the file "blender", and select "Show Package Contents" in the popup-menu. It will display all the hidden files under blender's folder, and select "scripts" folder inside it. o To see this folder from the OSX terminal use the ls -a command (lists all folders/files even hidden) in the MacOS folder of the listed path. It is probably a good idea to create an alias to the scripts folder in the "/Applications/blender-2.37a-OSX-10.3-powerpc" folder so that scripts can be easily manipulated through the finder. I know that its confusing that Blender should have its script folder buried inside the app but it is necessary to keep the app portable and not require an install. o A safer approach than the one above consists in keeping your scripts somewhere in your home folder: with this scheme, there is no risk of deleting your scripts when you upgrade your blender application, as they are not contained within its folder. A method that follows this principle is as follows: create a folder that will contain your scripts (or some of them) inside your own home directory; then, instead of putting your files directly in the .../.blender/scripts/ folder discussed above, simply add a link to your script directory in the .../.blender/scripts/ folder (for instance with the "ln -s" Unix command, or by doing "open /Applications/blender-2.37a-OSX-10.3-powerpc/blender.app/Contents/MacOS/.blender/scripts/" [adapted to your version of blender] and then creating a link through the Finder, with File->Make Alias). Blender will now find all the scripts that you put in your home directory: it will follow the link you created in its .../.blender/scripts/ folder and go to the corresponding folder in your own directory, and find all the python scripts you put there.
- !BPY
""" Name: 'Wikibooks' Blender: 244 Group: 'Export' Tooltip: 'Wikibooks sample exporter' """ import Blender import bpy
def write(filename):
out = file(filename, "w") sce= bpy.data.scenes.active for ob in sce.objects: out.write(ob.type + ": " + ob.name + "\n")
Blender.Window.FileSelector(write, "Export")
Now, go back into the scripts window, and in its menu, click Scripts → Update Menus. If you saved it into the right path, from now on there should be an entry "Wikibooks" in the File → Export menu. Try exporting any scene with it. It should open the file chooser dialog, and after you select a file and press the "Export" button, write a list of all objects in the scene into it. There will be one object per line, with the type, followed by a colon and the name.
How does it work? If you look at the script, you probably already know. But just in case, let's look at the script line by line. The first line contains this:
- !BPY
It tells Blender that this is a Blender script, and therefore it will consider it when scanning for scripts. Next simply follows a string, enclosed in triple quotation marks, so it can span multiple lines.
""" Name: 'Wikibooks' Blender: 244 Group: 'Export' Tooltip: 'Wikibooks sample exporter' """
It contains four items, which Blender uses to place the script into its menus. The name, group (menu location), and tooltip, all enclosed in single quotes. And the Blender version this is for.
import Blender import bpy
Remember how we said all functions from the bpy module start with "Blender."? In the interactive shell, we could simply use them, but in a python script, all used modules must be declared with an import statement (if you want to directly use functions from the Blender module in a script, you can simply replace the import statement above with "from Blender import *": no "Blender." prefix is necessary anymore; however, this slows down the loading of your script). So the above simply allows us to use the functions from the Blender module in our script.
the bpy module is new and will replace Blender for data access.
def write(filename):
This defines a function in Python. The syntax is def name(parameters):. In our case, the name is "write", and we have one parameter, called "filename".
out = file(filename, "w")
Here we open a file for writing (the "w"), with the name passed to the function (filename). The python function "file" will open the file, and return a reference to it, which we store in the variable "out".
sce= bpy.data.scenes.active for ob in sce.objects: out.write(ob.type + ": " + ob.name + "\n")
These three lines are our real export script. You already know what the first line does - first we get the current scene, then get a list of all objects in that scene, the for loop is assigning each one in turn to the variable "ob". The second line writes to the file - first the type of the object, then the string ": ", then the name of the object, and finally a newline.
Blender.Window.FileSelector(write, "Export")
This is where execution of the script starts. It is simply a call of a Blender function (look it up in the API docs), which opens the file selector. It will display an "Export" button, and when the user clicks it, our function "write" from above gets called and is passed the selected filename.
This script isn't really very useful yet, but it shows the basics. You should now be able to e.g. also list all the materials in the scene. (Hint: They are just like objects, try to find them in the API docs.)
In the next başlık, we will learn how to export additional information about objects to our text file. [edit] Exporting a Mesh
Our export script lists the type and name of every object, but that's not very useful yet. If we want to load the exported data in another application, we need more. Let's try to export a mesh object in the OBJ format.
The example below is a cube in the OBJ file format.
v 1.000000 1.000000 -1.000000 v 1.000000 -1.000000 -1.000000 v -1.000000 -1.000000 -1.000000 v -1.000000 1.000000 -1.000000 v 1.000001 1.000000 1.000000 v 0.999999 -1.000000 1.000000 v -1.000000 -1.000000 1.000000 v -1.000000 1.000000 1.000000 f 1 2 3 4 f 5 8 7 6 f 1 5 6 2 f 2 6 7 3 f 3 7 8 4 f 5 1 4 8
Here is a simple obj export script that exports a selected mesh object, used to export the OBJ file above.
import Blender import bpy
def write_obj(filepath): out = file(filepath, 'w') sce = bpy.data.scenes.active ob = sce.objects.active mesh = ob.getData(mesh=1) for vert in mesh.verts: out.write( 'v %f %f %f\n' % (vert.co.x, vert.co.y, vert.co.z) )
for face in mesh.faces: out.write('f')
for vert in face.v: out.write( ' %i' % (vert.index + 1) ) out.write('\n') out.close() Blender.Window.FileSelector(write_obj, "Export")
This script will export an OBJ file that can be read by many applications. Let's look at whats going on.
sce = bpy.data.scenes.active ob = sce.objects.active
Here we are getting the object you last selected in the current scene. This will raise an error if there are no selected objects, but its an easy way to test a new exporter.
mesh = ob.getData(mesh=1)
This gets the objects linked datablock. At the moment we dont know its a mesh, another case where error checking would need to be added.
for vert in mesh.verts: out.write( 'v %f %f %f\n' % (vert.co.x, vert.co.y, vert.co.z) )
Here we write a line for every vertex, using string formatting to replace the "%f" on the left, with the 3 values on the right.
for face in mesh.faces: out.write('f')
for vert in face.v: out.write( ' %i' % (vert.index + 1) ) out.write('\n')
In the OBJ format each face references a number of vertex indices. For every face we have a line starting with "f", then loop through the vertices in the face. Just as mesh.verts are a list of all the the vertices in a mesh, face.v is a list of verts in the face limited to 4 vertices maximum. (where mesh and face are arbitrary variable names assigned to Mesh and MFace objects) Every vertex writes its index on that same line with 1 added. This is because with the OBJ file format the first vertex is indexed at 1, whereas with Python and Blender the first item in a list is 0.
A new line is written so the next face will start on a new line. - in python '\n' represents a new line when written to a file.