Add UV Coordinates to Polygon
-
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?
-
On 19/08/2017 at 09:54, xxxxxxxx wrote:
I made this gist for this purpose.
https://gist.github.com/gr4ph0s/ebecaabcf90bbdd73a54124544e0b532Then ,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.
-
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 objectProbably 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...
-
On 19/08/2017 at 10:11, xxxxxxxx wrote:
Just saw your extended comment... will dive into that
-
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= -
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)
-
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
-
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())
-
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()
-
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.