Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Add UV Coordinates to Polygon

    PYTHON Development
    0
    10
    1.8k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      On 19/08/2017 at 09:06, xxxxxxxx wrote:

      Hi all

      I'm reading and parsing a file (glTF JSON). It contains:
      A bunch of points: p1, p2, p3, p4, p5, .... (3d-Vectors)
      A bunch of UV coordinates: uv1, uv2, uv3, ... (2d-Vectors with values between 0 and 1)
      A bunch of materials: mat1, mat2, ... (bitmaps)
      A list of indices on how to assemble everything: 1, 2, 3,  1, 2, 4,  2, 3, 5, ...

      I can easily create the triangles from the points and indices.
      I can easily create the materials and assign them to the right triangles.

      What I can't figure out is:

      How do I assign UV coordinates to each point of a triangle?

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 19/08/2017 at 09:54, xxxxxxxx wrote:

        I made this gist for this purpose.
        https://gist.github.com/gr4ph0s/ebecaabcf90bbdd73a54124544e0b532

        Then ,you can set uv with point id with this simple function.

        tag_uvw = doc.GetActiveTag()
        if not tag_uvw:
            return
          
        uv_coord = c4d.Vector()
        pt_id = 1
        poly_id = 0
          
        // se the uv of the pt_id 1 for the poly_id 0
        set_uv(tag, pt_id, uv_coord, poly_id)
          
          
        // se the uv of the pt_id 1 for all poly_id
        set_uv(tag, pt_id, uv_coord)
        

        If you have any issue or any missunderstand in my code, don't hesite to told it, I will take time to comment.

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 19/08/2017 at 10:10, xxxxxxxx wrote:

          Hm... I don't get that gist... I would expect that I have to:
          1. Add a texture tag to the object
          2. Add UV coordinates to the vertices of the object

          Probably something like:

            
          indices = <a list of integers>  
          coords  = <a list of 3d vectors>  
          uvs     = <a list of 2d vectors> # same amount as coords  
          faces   = [tuple(indices[i:i + 3]) for i in range(0, len(indices), 3)]  
                              
          # create object to hold points  
          obj = c4d.BaseObject(c4d.Opolygon)  
          obj.SetName(mesh["name"])  
          obj.ResizeObject(len(coords), len(faces))  
                              
          # fill points into polygon object  
          for i, v in enumerate(coords) :  
            obj.SetPoint(i, c4d.Vector(v[0], v[1], v[2]))  
                              
          # fill trangles into polygon object  
          for i, f in enumerate(faces) :  
            obj.SetPolygon(i, c4d.CPolygon(f[0], f[1], f[2]))  
            
          # fill uv tex coordinates  
          tag = c4d.BaseTag(c4d.Tuvw)  
          obj.InsertTag(tag)  
          # loop to set uv coords... <- this is what I'm looking for...  
          
          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 19/08/2017 at 10:11, xxxxxxxx wrote:

            Just saw your extended comment... will dive into that 🙂

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 19/08/2017 at 10:31, xxxxxxxx wrote:

              Even if in other software it work like you said, where uv_pt_id = mesh_pt_id is not the case in c4d.

              Actually uv_pt_id for c4d belong to pt_id INSIDE a c4d.Cpolygon(wich is a representation of a polygon with the following pt_id 0 ,1, 2 or 3 if quad). About ngon, in c4d there is wrapper about it but they didn't exist, understand them as polygon of 3/4 side melt together. So in all cases a polygon is always made from 3 or 4 points.

              My script allow you to use directly mesh_pt_id to uv_pt_id for set an uv point.
              I made this script after this question, this can maybe help you to have a better understanding of how uv are handle in the uvwtag.
              https://developers.maxon.net/forum/topic/435/13576_continuous-uv-solved&KW=

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                On 19/08/2017 at 10:36, xxxxxxxx wrote:

                Hm... it doesn't work...

                My guess is, that since the UV tag doesn't exist yet (I create it), your proposed solution breaks when doing the

                buffer_uv = tag.GetSlow(data["poly_id"])
                

                with an index out of bounds error...

                Here's what my code looks like right now:

                  
                # add a texture tag to the object  
                tag = c4d.BaseTag(c4d.Tuvw)  
                obj.InsertTag(tag)  
                  
                  
                # fill points into polygon object  
                for i, v in enumerate(coords) :  
                  obj.SetPoint(i, c4d.Vector(v[0], v[1], v[2]))  
                  
                # fill trangles into polygon object and set UV coords  
                for i, f in enumerate(faces) :  
                  obj.SetPolygon(i, c4d.CPolygon(f[0], f[1], f[2]))  
                  set_uv(tag, f[0], i, c4d.Vector(uvs[f[0]][0], uvs[f[0]][1], 0))  
                  set_uv(tag, f[1], i, c4d.Vector(uvs[f[1]][0], uvs[f[1]][1], 0))  
                  set_uv(tag, f[2], i, c4d.Vector(uvs[f[2]][0], uvs[f[2]][1], 0))  
                  
                #print mesh["name"], len(coords), len(faces), len(uvs), len(indices)  
                                
                doc.InsertObject(obj)  
                obj.InsertUnder(root)  
                
                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  On 19/08/2017 at 10:39, xxxxxxxx wrote:

                  Originally posted by xxxxxxxx

                  Actually uv_pt_id for c4d belong to pt_id INSIDE a c4d.Cpolygon(wich is a representation of a polygon with the following pt_id 0 ,1, 2 or 3 if quad).

                  So, since I know the point which are used to create the poly and the correct UV for them, I should basically be able to just set the UV coordinates of points 0-2, right?

                  Question would then be, how do I do that 😉

                  1 Reply Last reply Reply Quote 0
                  • H
                    Helper
                    last edited by

                    On 19/08/2017 at 10:49, xxxxxxxx wrote:

                    Ok, got it 🙂

                    1. Make sure to create a UV Tag with enough "entries" to hold all polys
                    2. Use SetSlow to directly set the UVs...

                      
                                      # add a texture tag to the object  
                                      tag = c4d.UVWTag(len(faces))  
                                      obj.InsertTag(tag)  
                      
                                      # fill points into polygon object  
                                      for i, v in enumerate(coords) :  
                                          obj.SetPoint(i, c4d.Vector(v[0], v[1], v[2]))  
                      
                                      # fill trangles into polygon object and set UV coords  
                                      for i, f in enumerate(faces) :  
                                          obj.SetPolygon(i, c4d.CPolygon(f[0], f[1], f[2]))  
                                          tag.SetSlow(i, c4d.Vector(uvs[f[0]][0], uvs[f[0]][1], 0),  
                                                         c4d.Vector(uvs[f[1]][0], uvs[f[1]][1], 0),  
                                                         c4d.Vector(uvs[f[2]][0], uvs[f[2]][1], 0),  
                                                         c4d.Vector())  
                    
                    1 Reply Last reply Reply Quote 0
                    • H
                      Helper
                      last edited by

                      On 19/08/2017 at 11:34, xxxxxxxx wrote:

                      Since I use neighboor to know which point id are shared with wich polygon id, my script is more a way for dealing with mesh that already exist. At least I think in this way when I builded it. So rry about that and forget it since you are in the creation.

                      But regarding your question here is a litlle exemple wich create, 2 polygons with uv wich I hope will make more sense.

                      import c4d
                        
                      #pt_id are correctly ordered
                      points = [
                          c4d.Vector(0, 0, 0),
                          c4d.Vector(200, 0, 0),
                          c4d.Vector(200, 0, 200),
                          c4d.Vector(0, 0, 200),
                          c4d.Vector(200, 100, 0),
                          c4d.Vector(200, 100, 200)
                      ]
                        
                      #uv_id are ordered like points and get same count than points
                      uvs = [
                          c4d.Vector(1, 1, 1),
                          c4d.Vector(0.6, 1, 1),
                          c4d.Vector(0.6, 0, 1),
                          c4d.Vector(1, 0, 1),
                          c4d.Vector(0, 1, 1),
                          c4d.Vector(0, 0, 1)
                      ]
                        
                      #hold pt_id
                      polys = [
                          [0 ,1, 2 ,3],
                          [1, 2, 5 ,4]
                      ]
                          
                      def main() :
                          doc.StartUndo()
                          
                          nb_pts = len(points)
                          nb_polys = len(polys)
                          obj  = c4d.BaseObject(c4d.Opolygon)
                          uv_tag = c4d.UVWTag(nb_polys)
                        
                          #Firstly we prepare our polygon object to store this amount of value
                          obj.ResizeObject(nb_pts, nb_polys)
                          
                          #Then we build point I could use objet.SetAllPoints(points) 
                          #    since my points list is already ordered
                          for pt_id, pos in enumerate(points) :
                              obj.SetPoint(pt_id, pos)
                          
                          #Then we define our polygon and our uv. 
                          # UV belong to pt_id FROM polygon. That mean we need polygon ;)
                          for poly_id, pt_ids in enumerate(polys) :
                              poly = None
                              #Handle triangle
                              if len(pt_ids) > 3:
                                  poly = c4d.CPolygon(
                                              pt_ids[0],
                                              pt_ids[1],
                                              pt_ids[2],
                                              pt_ids[3]
                                          )
                              else:
                                  poly = c4d.CPolygon(
                                              pt_ids[0],
                                              pt_ids[1],
                                              pt_ids[2],
                                              pt_ids[2]
                                          )
                              
                              obj.SetPolygon(poly_id, poly)
                              
                              #remember poly.a is pt_id. We use poly data since we already managed triangle before
                              uv_tag.SetSlow(poly_id, uvs[poly.a], uvs[poly.b], uvs[poly.c], uvs[poly.d])
                                  
                          
                          obj.Message(c4d.MSG_UPDATE)
                          
                          doc.InsertObject(obj)
                          doc.AddUndo(c4d.UNDOTYPE_NEW, obj)
                          
                          obj.InsertTag(uv_tag)
                          doc.AddUndo(c4d.UNDOTYPE_NEW, uv_tag)
                          
                          c4d.EventAdd()
                          
                          doc.EndUndo()
                        
                      if __name__=='__main__':
                          main()
                      
                      1 Reply Last reply Reply Quote 0
                      • H
                        Helper
                        last edited by

                        On 21/08/2017 at 03:26, xxxxxxxx wrote:

                        Hi,

                        For more information on UVWTag class see the UVWTag Manual of the C++ SDK docs and its documentation in the Python SDK docs.

                        1 Reply Last reply Reply Quote 0
                        • First post
                          Last post