Beginner Python Exercise in Blender: Make a cube from a list of vertices

Sdílet
Vložit
  • čas přidán 26. 07. 2024
  • This is a video exercise for Blender Python beginners.
    We will write a Python script that creates a Cube from a list of vertices and faces.
    Final code:
    gist.github.com/CGArtPython/4...
    00:00 - Intro
    00:30 - Setup Workspace
    00:58 - Adding Lists
    01:28 - Create mesh data
    03:02 - Add a vert
    03:27 - Create an object
    05:18 - Add to the Scene Collection
    06:09 - Removing orphan data
    06:35 - Adding verts to form a face
    07:13 - Show vert indices
    08:23 - Define a face
    09:17 - Check face orientation
    09:30 - Define remaining verts
    10:03 - Define remaining faces
    11:18 - Inspecting a face
    12:52 - What is a Python script?
    13:53 - Exercise #1
    14:34 - Exercise #2
    15:08 - Outro
    Intro Music
    Fiery Trails - Silent Partner
    Outro Music
    Geographer - Easy Shake
    #blender #python #scripting

Komentáře • 63

  • @opticaudio9750
    @opticaudio9750 Před rokem +8

    You are the most useful resource I have found on python/blender scripts. Thanks you!

    • @CGPython
      @CGPython  Před rokem

      Thank you for your kind words!

  • @jessiecampanero9297
    @jessiecampanero9297 Před rokem +6

    love this.
    I made the exercise 1 in a different way than yours.
    I just add variables on edges. 😀
    Thanks again Victor! you are the best!🤘

  • @BrettKromkamp
    @BrettKromkamp Před 2 lety +2

    I'll make sure to watch it this evening. As always... thanks for your efforts :)

    • @CGPython
      @CGPython  Před 2 lety +2

      Thanks for your support Brett! :)

  • @PowNyTales
    @PowNyTales Před 6 měsíci +1

    Thank you! That was a great tutorial!
    The big advantage of it, that you are able to solve the task. That’s greate to have a little success, after you got the exercises done. Those little portions combined with success in my opinion, are a key to learn further. This is a kind of lessons I needed for python.
    Like and Abo and big thanks 🙏🍀

    • @CGPython
      @CGPython  Před 6 měsíci

      Woohoo! 😆
      You're very welcome! 💖

  • @user-le2zv6go3v
    @user-le2zv6go3v Před rokem +1

    thank you so much for this .. I was trying exactly this a few months ago, but wanted to figure it out on my own .. and was even less used to blender than I am today .. now I can finally improvise on this! :)

    • @CGPython
      @CGPython  Před rokem +1

      That is awesome!
      Really happy this was useful to you.

  • @philippe6724
    @philippe6724 Před 2 lety +1

    Super well taught! Thank you for sharing your knowledge!!!

  • @alirezakhademi6093
    @alirezakhademi6093 Před 6 měsíci

    bro i just started python in blender with you and your descriptions are amazing , thank you very much!

    • @CGPython
      @CGPython  Před 5 měsíci

      Glad you like them! ❤️‍🔥

  • @DenisTrebushnikov
    @DenisTrebushnikov Před rokem +2

    Note to run scripts less than possible: for faces choose verts *CONTRAclockwise* to set normals outward (blue color), and clockwise to set normals inward (red color).
    Note 2: with indices view enable, be sure that you in vertices selection mode (Edit Mode -> 1), otherwise, indices will be shown to edges (2), faces (3) - I checked, if it created the edges automatically, and forget to set back to verts selection, and spent time to figure out what the problem was... now, you know how to solve this issue.

    • @CGPython
      @CGPython  Před rokem +1

      Thanks for sharing your notes!

  • @JM-jk9vz
    @JM-jk9vz Před rokem +1

    Thanks for the video. I just recently ventured into using python with blender and I'm excited about it. Real quick though, has anyone ever told you you looked like Peter Dinklage? :D

    • @CGPython
      @CGPython  Před rokem

      Glad you found the channel! 😀
      You are the first one to tell me that I look like Peter Dinklage 🙃

  • @btornqvist
    @btornqvist Před rokem

    This was really useful. Thank you!

  • @user-so4jh7wl3i
    @user-so4jh7wl3i Před rokem +1

    amazing video, keep it up!!

  • @leslyskugga
    @leslyskugga Před rokem

    thank you!!!!!!!

  • @aleksanderk5695
    @aleksanderk5695 Před rokem

    You made bpybb - just use them, no need to repeat "old truths" every video. Great job man!

    • @CGPython
      @CGPython  Před rokem +3

      Thanks Aleksander!
      At some point, I’ll start doing that for some videos.
      Just trying to keep the code setup easy so more people would follow along. Especially for beginner videos.
      Installing bpybb would introduce friction and some people would fall off.
      With copy & paste, the only function is opening the link in the browser ;)
      But thank you for encouraging this

    • @jmfs3497
      @jmfs3497 Před rokem

      @@CGPython Thank you for keeping it to the foundational rudiments, honestly! When I get to a place where I understand what bpybb is, I'm sure I will appreciate that, too, in same way I now appreciate tuples.

    • @CGPython
      @CGPython  Před rokem +1

      @@jmfs3497 I'm glad to hear that you think this is important.
      Thanks for sharing your thoughts

  • @honestyrocksu
    @honestyrocksu Před 10 měsíci

    The very last clip was the most interesting, which looked like a randomly positioned objects floating.. Go over the code for that.

  • @arturertel
    @arturertel Před rokem +1

    hello Victor, thanks for the tutorials. At the end I wanted to recalculate the normals so that they point outwards, but I did not succeed.

    • @CGPython
      @CGPython  Před rokem +1

      Hey Artur,
      I'm glad you liked it!
      If you want to recalculate the normals you can add this code to the end of your script
      ```
      # set the mesh object as the active object
      bpy.context.view_layer.objects.active = mesh_obj
      # switch to Edit Mode
      bpy.ops.object.mode_set(mode='EDIT')
      # recalculate the normals
      bpy.ops.mesh.normals_make_consistent(inside=False)
      # switch to Object Mode
      bpy.ops.object.mode_set(mode='OBJECT')
      ```
      The catch here is that you need to set the mesh object as the active object and then enter Edit mode.
      Here is the full example
      gist.github.com/CGArtPython/1f294c42d72583e4c766ed7ed7454608

    • @arturertel
      @arturertel Před rokem

      ​@@CGPython It works now! So you can't just use anything from the Log of Operations as a command :D

  • @kronenapp2918
    @kronenapp2918 Před rokem

    Hi, this video came up on the search of my problem and it was a huge help.
    I need to automat the creation of some specific modular gameobjects. Creating those within Unity would be no problem. However I do want to create an atlas of modular elements within blender and I am new to this topic of programming within blender. Creating those intended base modules within the gameengine and trying to export those (however?) for specific variations into blender does sound more complicated. So I am trying to use blender directly.
    Following those steps I managed to create some prototypes like intended. However the upcoming problem is the following:
    While defining the faces I would also like to specify the UV-positions of each vertex of the current face.
    I was hoping to find something like:
    UV_POSITION_OF_VERTICES_OF_FACES=[[(0,1),(0.2,1),(0.2,0),(0,0)],[...],[...],[...]] ?
    mesh_data.from_pydata(verts, edges, faces, UV_POSITIONS_OF_VERTICES_OF_FACES) ?
    Does such a similar function with those intended parameters exist or something similar?
    I was searching for an answer, but I assume I do not even know how to search in this category correctly for my problem. All I got were examples concerning unwrapping or answers with loops, where I could not find a single assignation with a 2d-vector position.
    Thanks for this tutorial

    • @CGPython
      @CGPython  Před rokem +1

      Hey,
      Glad you liked the tutorial!
      That is an interesting problem.
      UVs are represented as loops under the hood of Blender
      I think this should help you
      b3d.interplanety.org/en/how-to-create-a-new-mesh-uv-with-the-blender-python-api/

    • @kronenapp2918
      @kronenapp2918 Před rokem

      @@CGPython Thanks for the example. This example helped me to solve this problem.

  • @briantriesart
    @briantriesart Před 3 měsíci

    Thank you very much! Are you providing online lessons? Thanks!

  • @oishiiyum
    @oishiiyum Před 9 měsíci +1

    why does the order of the indexes change the face orientation? how do you know which order to go?

    • @CGPython
      @CGPython  Před 8 měsíci

      This is due to the "winding order." The winding order is a concept in 3D graphics that determines where the front side of a face is.
      here is a good definition from LearnWebGL: "The order of a triangle's vertices are used to determine which side of a triangle is the front side. If you are looking at a triangle and the order of the vertices is counter-clockwise, then, by convention, you are looking at the front of the triangle. The order of a triangle's vertices is called the winding order. "
      Just make sure that the vert indices are in a counter-clockwise order to get the result you want.

  • @smikhasko2758
    @smikhasko2758 Před rokem

    Привет. Не подскажите, куда копать, чтобы добавить элементы интерактивности в скрипты. Как определить выделенные вершины или ребра, как отследить положение курсора (мыши) и в реальном времени строить объекты кликами. Пришел из C# и многие вещи в Python кажутся дикими :). Имеются ли какие-то код-конвеншн по написанию скриптов, чтобы приучить себя сразу? Спасибо и удачи с каналом.

    • @CGPython
      @CGPython  Před rokem

      Thanks, friend!
      To make a script interactive, you would need to start learning about Blender add-ons.
      Blender has a lot of template add-ons that you can use as examples. These templates were written by the Blender devs and serve as examples of how you should write add-ons.
      You can find these examples and other scripts that ship with Blender in the install dir of Blender under \scripts, for example `3.4\scripts`.
      I have a video about going over one of the templates here:
      czcams.com/video/x3QRp2k013k/video.html
      I would recommend installing VSCode (if you haven't already) and setting up pylint and auto-formatting with black.readthedocs.io/
      Also set up this extension marketplace.visualstudio.com/items?itemName=JacquesLucke.blender-development
      I plan to make videos about all of this.

    • @CGPython
      @CGPython  Před rokem

      For tracking the cursor position, I would start looking at the operator_modal_draw.py template example.

  • @opticaudio9750
    @opticaudio9750 Před rokem

    Is there an easy-ish solution to place text at each one of the indices?
    (Specifically text that I can manipulate)

    • @CGPython
      @CGPython  Před rokem +1

      Thank you for your question! 😀
      Try this
      gist.github.com/CGArtPython/0a116fd19d66ecf2bd3ad42c18dc1bd8
      To stop drawing the text run the script again with `run = False`

    • @opticaudio9750
      @opticaudio9750 Před rokem

      @@CGPython Thank you for the example!
      this clears up a few things for me.
      I didn't realize blender had another import option specifically for fonts. (was trying to do everything from the bpy API).

  • @spirosmarinis2510
    @spirosmarinis2510 Před rokem

    very helpful thanks! But let me ask you Is there a way to declare the variable of vertices (more than 68) so that some function can update the coordinates?
    For a simple list, you can use verts=list(range(208))
    For verts=[(1,0,1),(1,2,3)....] how ?

    • @spirosmarinis2510
      @spirosmarinis2510 Před rokem

      Finnaly i used verts[] ... verts.append((0,0,0))

    • @CGPython
      @CGPython  Před rokem

      Hello,
      I'm glad it was helpful!
      Where will you get the coordinates from, and what will define the faces or edges?

    • @spirosmarinis2510
      @spirosmarinis2510 Před rokem

      @@CGPython coordinates calculated by a function
      #faces defined by this function
      def appendfaces():
      i=0
      ln=int(len(verts)*0.5)
      for x in range(1,ln):
      faces.append(i+1,i,i+2,i+3)
      i+=2
      faceappend(i+1,i,0,1)
      ln=int(len(verts))
      t=tuple( i for i in range(ln) if i%2==1 )
      faces.append(t)
      s=tuple( i for i in range(ln-2,-1,-2) )
      faces.append(s)
      #but one more function is nesesary to appendfaces can work
      def vertsappend(xx,yy,zz,height):
      verts.append((xx,yy,zz))
      verts.append((xx,yy,zz+height))
      # i give you an exemple for simple cube
      def simplecube():
      vertsappend(0,0,0,1)
      vertsappend(1,0,0,1)
      vertsappend(1,1,0,1)
      vertsappend(0,1,0,1)
      from your video i noticed that number 1 vertice is above 0 vertice not next to 0
      why? ...
      becauce the face become 0,1,3,2 .... 2,3,5,4 .....
      the last two faces are 1,3,5,7 ... and ..... 6,4,2,0
      so you can make every profile you can imagine

    • @CGPython
      @CGPython  Před rokem

      @@spirosmarinis2510 > from your video i noticed that number 1 vertice is above 0 vertice not next to 0 why?
      vertex 1 is actually next to vertex 0 (on the Y)
      (-1.0, -1.0, -1.0),
      (-1.0, 1.0, -1.0),
      Sorry, still not sure where you are getting the 68 vertices. In your example, you only have 8?

    • @spirosmarinis2510
      @spirosmarinis2510 Před rokem

      @@CGPython
      i am new in python and blender
      i am sending you the final text i hope it will work in my pc is ok
      these are the 68 vertices
      import bpy
      import math
      def aktinia(mires):
      return mires * (math.atan(1)/45)
      def iparxi_object(obj_name):
      rs=False
      try:
      oj=bpy.data.objects[obj_name]
      rs=True
      except:
      oj=None
      print("there is not object such name " + obj_name )
      finally:
      return rs
      class Tapa_L:
      def __init__(self,onoma,tx,ty,tz,paxos,batos,ypsos,r):
      self.verts=[]
      self.edges=[]
      self.faces=[]
      self.name=onoma
      self.new_obj= True
      self.tx= tx
      self.ty=ty
      self.tz=tz
      self.paxos=paxos
      self.batos=batos
      self.ypsos=ypsos
      self.r=r
      self.ob=None
      self.vr=None
      self.j=0
      def set_ob(self):
      if iparxi_object(self.name):
      self.ob= bpy.data.objects[self.name]
      self.new_obj=False
      self.redraw_tapa()
      else:
      self.new_obj=True
      self.draw_tapa()
      def draw_tapa(self):
      self.verts.clear()
      self.tapa_v()
      mesh_data=bpy.data.meshes.new(self.name)
      self.faces_table()
      mesh_data.from_pydata(self.verts,self.edges,self.faces)
      self.ob=bpy.data.objects.new(self.name,mesh_data)
      bpy.context.collection.objects.link(self.ob)
      self.ob.location[0]=self.tx
      self.ob.location[1]=self.ty
      self.ob.location[2]=self.tz
      def redraw_tapa(self):
      self.vr=self.ob.data.vertices
      self.tapa_v()
      self.ob.location[0]=self.tx
      self.ob.location[1]=self.ty
      self.ob.location[2]=self.tz
      def tapa_v(self):
      self.j=0
      dx=list(range(6))
      self.pinakasshmeioon(self.r,dx)
      self.sira(0,0,0,self.paxos,self.batos,self.r)
      self.sira(0,0,self.ypsos-self.r,self.paxos,self.batos,self.r)
      idr=5
      teshz= self.ypsos-self.r
      for x in range(1,6):
      r1 = dx[x]
      dk=self.r-r1
      self.sira(0+dk,0,teshz + dx[idr],self.paxos-dk,self.batos-dk,r1)
      idr-=1
      dk=self.r
      self.siraΤelos(0+dk,0,0+self.ypsos,self.paxos-dk,self.batos-dk, self.r)
      def faces_table(self):
      self.faces.clear()
      i=0
      for x in range(1,7):
      for y in range(1,9):
      self.faces.append((i,i+1,i+10,i+9))
      i+=1
      i+=1
      self.faces.append((i,i+1,i+10,i+9))
      i+=1
      for x in range(1,7):
      self.faces.append((i,i+1,64))
      i+=1
      self.faces.append((i,i+1,i+4,i+3))
      i+=1
      self.faces.append((i+1,i+2,i+3,i+4))
      self.faces.append((67,66,65,62,53,44,35,26,17,8))
      self.faces.append((66,67,0,9,18,27,36,45,54,63,66))
      self.faces.append((0,67,8,7,5,4,3,2,1,0))
      def vertsappend( self,xx,yy,zz):
      if self.new_obj:
      self.verts.append((xx,yy,zz))
      else:
      jj=self.j
      self.vr[jj].co[0]=xx
      self.vr[jj].co[1]=yy
      self.vr[jj].co[2]=zz
      self.j+=1
      def sira(self,txx,tyy,tzz,apaxos,abatos,rr):
      rtx= list(range(6))
      self.pinakasshmeioon(rr,rtx)
      ktx = txx + rr
      kty = tyy - abatos + rr
      self.vertsappend(txx,tyy,tzz)
      self.vertsappend(txx,tyy-abatos+rr,tzz)
      dix=1
      diy=5
      j=2
      for x in range(1,6):
      self.vertsappend (ktx-rtx[dix],kty-rtx[diy],tzz)
      dix+=1
      diy-=1
      j+=1
      self.vertsappend(ktx,kty-rr,tzz)
      self.vertsappend(txx+apaxos,tyy-abatos,tzz)
      def siraΤelos(self,txx,tyy,tzz,apaxos ,abatos,rr):
      self.vertsappend(txx,tyy,tzz)
      self.vertsappend(txx,tyy-abatos,tzz)
      self.vertsappend(txx+apaxos,tyy-abatos,tzz)
      self.vertsappend(txx+apaxos,tyy,tzz)
      self.vertsappend(txx+apaxos,tyy,0)
      def pinakasshmeioon(self,aktina,dr):
      bhma=aktinia(15)
      for x in range(1,6):
      dr[x]=(aktina * math.cos(bhma * x))

      #onoma,tx,ty,tz,paxos,batos,ypsos,r
      tap=Tapa_L('Sm_tap',0,0,0,1.2,4,1,0.03)
      tap.set_ob()

  • @ashhaf63
    @ashhaf63 Před 8 měsíci

    I wrote a script before in that similar way after months of trying (I am not a programmer). I had x,y & z values. There were a lot of points. I wanted to edit the Z values only. However, when you have a lot of points, it becomes very confusing and difficult to find the points to change. Is there a way to add a menu for the z values that can be edited?

    • @CGPython
      @CGPython  Před 7 měsíci

      Maybe you can use the "is this point selected" property and only edit the Z of the selected points?
      How do you determine what points you want to edit?

    • @ashhaf63
      @ashhaf63 Před 7 měsíci

      @@CGPython
      I had an excel example but I guess we cannot attach documents here. Basically the Z-values are elevations of the floor (lets say your house). So every they will change for every new job or house. I liked blender because I could actually animate the foundation movement of the structure.

    • @CGPython
      @CGPython  Před 6 měsíci

      @@ashhaf63 so you want to animate the Z values of your points?
      Can you use the X, Y of the points to understand what Z the points need to be at?

  • @sci-fifun5039
    @sci-fifun5039 Před 2 měsíci

    What app or software did u use ?

  • @ced9302
    @ced9302 Před 9 měsíci

    Do you think it is possible to automate the creation of vertices, edges and faces? For the vertices and edges I was able to find a way to do it but I am stuck with the faces (vertex order problem). Here is the code to automate the creation of the vertices:
    # size of cube
    d = 1
    # starting summit
    x,y,z = 0,0,0
    # coordinates listes
    list_x = [x, x+d]
    list_y = [y, y+d]
    list_z = [z, z+d]
    # calculation of coordinates (dirty nested loops)
    verts = []
    for i in range(len(list_x)):
    for j in range(len(list_y)):
    for k in range(len(list_z)):
    verts.append((list_x[i], list_y[j],list_z[k]))
    thank you

    • @CGPython
      @CGPython  Před 8 měsíci

      The first thing that comes to mind is a KDTree data structure.
      You would add the verts into a KDTree, then visit the verts going counterclockwise based on the next coordinate of the vert you need. This way, you don't need to know the exact vert index to use in the face creation. You just need to know what verts at what coordinates make up the face you are trying to get.
      docs.blender.org/api/current/mathutils.kdtree.html
      But there might be a more elegant formula for this.

  • @jmfs3497
    @jmfs3497 Před rokem

    Thanks again, CGPython! Just completed this one. I kept the original vertices for the entire thing and simply added a 9th vertex for the point of the pyramid. I'm using a lot of #comments to keep track, and toggling out one set of face tuples for the next shape's tuples. I definitely got a few faces flipped or overlapping while trying to keep the 2nd Cube w/triangle faces built, but I learned a lot. I am so excited for the next one with repeating code with for loops! 🐍🟦

    • @CGPython
      @CGPython  Před rokem

      Yeah, comments are fantastic for keeping track of what is going on!
      Thanks for sharing your experience!