Blender Python Script:  Modifying a Square Mesh of Polygons  (Part 3): Automating Vertice Creation.

Version Française
 Main Index                                       Python Index Previous Python (2): Iterations Python (4): automating face creation Next

(Note: starting from here, this text could become unpleasing, and perhaps even: tiresome)

Thus, we have two problems to solve:

1. we need two nested (one inside the other) for/next loops in order to construct a two dimensional array, in which to store our square mesh's vertices.
2. it is necessary to distribute the elements contained in the vertice list, which has only one dimension, into a two dimensional array so that we can locate and recover the vertices of juxtaposed (adjacent) faces. These faces must form a continuous surface.
For the first problem, Python provides a solution which consists of temporarily creating, within the limits of the subroutine, a new list containing all of the necessary values, by using the function:

range(start_value, end_value, increment_value)

If the starting value is 0, the number of elements 100 and the increment value 1, range(0, 100, 1) will build a list, whose value which is stored at  index [ 0 ] will be 0, with the index [ 1 ] will be 1, and so on.
If the increment value had been two, it would have been necessary to write: range(0, 100, 2), the value stored at [ 0 ] would have been:   0,
in [ 1 ]: 2,
in [ 2 ]: 4,
in [ 3 ]: 6, etc.

 # example of a Python loop  for i in range(0, 100, 1):     # The first subroutine begins here     # with four spaces of indentation    ...

Note that although the range function returns integer (whole number) values, when these values are passed to the NMesh.Vert() function, they will be automatically converted to floating point (decimal) values before they are saved. This is similiar to when you select the vertex of a mesh in Edit mode and press 'n' to view the numerical entries of the selected (active) vertex. If you Shift + Left mouse button click the LocX numerical entry button, press Shift + [backspace], then enter a value of 0, the integer value 0, is automatically converted to the float value 0.00 . Despite the fact, that most well written functions will do a type check to ensure that the values entered are in the right format, in some instances, it is important that you ensure that the number is the correct type, as we shall discover in Part (4).

For the second problem, it is necessary to do a little deductive reasoning. Let us imagine for one moment, a square mesh of polygons made up of 4 faces, with each face having 4 vertices. Thus, we would have 9 vertices to distribute. Note that although the total number of vertices is equal to 16, the number of "unique" vertices is less, since the "faces - to be" share 4 edges where they are joined. For example: The center vertex is common to all 4 "faces" and therefore has 3 "duplicate" vertices. The 4 vertices connected to the central vertex also each contain a duplicate, producing another 4 duplicates for a grand total of 7 duplicates. Thus, the total number of unique vertices is equal to 16 - 7 = 9. (Refer to the sketch below). These vertices are arranged, in a list, in the following manner: [ 0,1,2,3,4,5,6,7,8 ] . With a quick sketch, one clearly sees that there are three rows, each consisting of three vertices. The number of rows could be assigned to a variable "i" and the number of the vertices in each row could be stored in variable "j" . Or, if you prefer, you could think of "i" as the horizontal row number and "j" as the vertical column number.

 0 1 2   3 4 5   6 7 8

The question to ask now is :
What values must be assigned to variables i and j ? (if we have to use both variables to access the first vertex which is at  index 0).
One can postulate:  (i relation j) = 0, the assumption: (0 relation 0)  = 0, looks promising (at least for the first row). Note that this relationship makes it necessary that both variables i and j start with a value of zero. For the next index,  in the same row, i continues to be worth 0, but it is necessary to increase the value of j to arrive at 1. The relation could be i + j, but is this always true? In fact, for the following row, i will be worth 1, but to arrive at index 3, the relation i + j will not produce the value that we were hoping for, as j will initially be worth 0. For this to succeed, it is necessary to multiply i by 3 to obtain the result that we are looking for. The formula which makes it possible to locate an element in this mesh is i*3+j .
Is it possible to replace the "magical" value 3 by a variable which could be determined automatically without any intervention and according to the total number of vertices of the list? Yes. If the mesh of polygons is square, this value will always be the square root of the total number of vertices in the list. (One can arrive at these results with integer (whole number) division, and the remainder of integer division, when the mesh is not square, but that's another story which we will reserve for another tutorial.)

 import Blender from Blender NMesh import # Some mathematical functions from the Python module # would be very useful,   but since Python is very efficient, # it only loads the minimum that it requires.  # Thus, we must request that the math module be imported. import math from math import * # Creation of the mesh of polygons me=NMesh.GetRaw() # Without tackling the problem of local and global variables, # it is better (I prefer) to declare and initialize  # the variables outside of the subroutines.  i=0 j=0 # This is an example of what was  explained in the text. # The value 9 is assigned to the variable totalvert. totalvert = 9 #  Applying the results of our discussion systematically, #  the square root of totalvert is obtained with  #  the function sqrt(). Notice that if the line: #  " from math import * " had not been used in the script above, #  it would have been necessary to write " math.sqrt(totalvert) " n = sqrt(totalvert) for i in range(0, n, 1):     # The first subroutine begins here     # with four spaces of indentation     for j in range(0, n, 1):         # The second loop begins here         # with eight spaces of indentation         v=NMesh.Vert(j, i, 0.0)         me.verts.append(v)         # End of the internal loop     # End of the external loop # Let's take a break before continuing  # with automating face creation. # It's always possible to test this script  # in its present state, but you must add:  # NMesh.PutRaw(me, "plane", 1) # and # Blender.Redraw()
 Previous Python (2): Iterations Python(4): automating face creation Next Top of page