Copy mesh from one object to another with Python
-
Hi! I'm looking for quick way to copy all points, edges and polygons data from one poly object to another with Python tag.
Right now i'm using this loops:
for i in range(0, pointCount): targetObj.SetPoint(i, sourceObj.GetPoint(i)) for i in range(0, polygonCount): poly = sourceObj.GetPolygon(i) if poly.IsTriangle(): targetObj.SetPolygon(i, c4d.CPolygon(poly.a, poly.b, poly.c)) else: targetObj.SetPolygon(i, c4d.CPolygon(poly.a, poly.b, poly.c, poly.d))
It's missing hidden edges for Ngons feature but already really slow on 10k+ polygons. Is there way to do it faster?
I'm looking into Edit->Copy & Edit->Paste commands but its really hacky way since its tag, not a single execution script.
Also C4DAtom.CopyTo() looks promising but I have no idea what flag I should pass to copy only mesh, not every object property -
Hello @karpique,
Thank you for reaching out to us. There are two things you could optimize out in your code. Frist, the loop around
targetObj.SetPoint
, since there isPointObject.SetAllPoints
, taking a list of points and being much faster. Secondly, you could also optimize away the branching in your code withpoly.IsTriangle()
, since both tris and quads are being handled as quads by Cinema 4D (a tri is a handled as aCPolygon
wherec == d
). So, you could just write:for i in range(0, polygonCount): poly = sourceObj.GetPolygon(i) targetObj.SetPolygon(i, c4d.CPolygon(poly.a, poly.b, poly.c, poly.d))
Unlike for points, there is unfortunately no method in Python to write
CPolygon
in bulk with, making writing polygons in Python quite slow. As you mentioned, you could also useC4DAtom.CopyTo
, but there is no clean way to "copy only (the) mesh", since geometry information is being stored in tags and not the node itself. This will also copy n-gons:"""Example for copying polygons and n-gons from one node to another. Run this with a polygon object selected in the script manger. """ import c4d def main(): """ """ # Create a Opolygon node of matching size res = c4d.PolygonObject(op.GetPointCount(), op.GetPolygonCount()) # We first have to insert that new node into a document, this could also # be a temporary document. doc.InsertObject(res) c4d.EventAdd() # Then we just copy over stuff from the source. We cannot use the # COPYFLAGS_NO_BRANCHES flag, as this will prevent copying tag data, # which is also being used to store point and polygon information. flags = c4d.COPYFLAGS_NO_ANIMATION | c4d.COPYFLAGS_NO_HIERARCHY | c4d.COPYFLAGS_NO_BITS op.CopyTo(res, flags) if __name__=='__main__': main()
There are some other routes you could take, like.
c4d.utils.SendModelingCommand
and joining your mesh to copy with an empty mesh or handling it in a more hands-on-fashion by copying over theTpoint
andTpolygon
tags manually, and thereby avoid copying unwanted tag information.Cheers,
Ferdinand -
@ferdinand thanks for qiuck answer and quality info! I went with copying Tpoint and Tpolygn tags, but now stuck with translating hidden Ngon edges — can you point the right way to do that?
I feel like it sholud be some functions from c4d.PolygonObject class but stuck in here:
bs = c4d.BaseSelect() bs.SetAll([0] * polyObj.GetPolygonCount() * 4) ng = c4d.utils.Neighbor() ng.Init(polyObj) #doesnt work as expected, hidden ngon edges are not showing up polyObj.SetSelectedEdges(ng, bs, c4d.EDGESELECTIONTYPE_HIDDEN)
-
Hi:
Do you want to make a complete copy of another polygon object from scratch using Python tags?Including n-gon edges.
You hide edges incorrectly, it's still not an n-gon edge, it's just an edge selection.I have the full Python tag code, which is fast, but I won't post it here.However, this Python tag only runs in R23 and up.Since Python cannot directly create polygons with n-gon edges, it can only be done with the Model Elimination command in versions R23 and above.
Your Python code isn't optimal, so it's not fast.The fastest way to do this is to use C++, which can create polygons with n-gon edges directly and at tens of times the speed of Python tags.Also, Python tags create n-gon polygons that don't have the same edge indexes as the n-gon polygons that copy objects, which is one of Python's flaws.
-
Hello @karpique,
the Ngon interface is not being exposed to Python, which makes handling them always a bit harder there. You will have to either copy the
PolygonObject
itself, like shown by me above, which will handle Ngons properly. Or you have to usePolygonObject.GetNGonTranslationMap
to manually recrate the Ngons on the newPolygonObject
. Due to the absence of the Ngon interface in Python, you would have to do this withc4d.utils.SendModelingCommand
and the symbolMCOMMAND_MELT
. Due to this being rather cumbersome, I showed the more general solution in my previous posting. If you want to clean up an object with that more general solution, you could iterate over all tags and remove any tag that is not of typeTphong
,Tpoint
, orTpolygon
(you might want to include other tag types, depending on what your goals are).Cheers,
Ferdinand -
This post is deleted! -
@ferdinand thanks! I have one more question: after replacing
Tpoint
andTpolygon
tags object seems to keep it's old bounding box parameters and disappear from viewport accordigly to them. Is there a way to update this property? -
Hi @karpique,
hard to say from the outside without any code to see what you are doing, but my educated guess would be that
myObjectWithFaultyBòundingBox.Message(c4d.MSG_UPDATE) c4d.EventAdd()
will solve your porblem.
Cheers,
Ferdinand -
@ferdinand I get Ngon translation map and applied
MCOMMAND_MELT
but stuck again — as I understandSendModellingCommand
only returns new object with melted ngons, but my goal is to correct object that already exists in scene...Is there any other ways of setting up Ngon translation map with python?