Jump to content

The equivalent of Optimize (U-O), but instead just mark the affected points


Recommended Posts

Sometimes, when using the Cloner and/or Symmetry, you would like to know if any points are ever so slightly out of alignment. This causes the points of clones/symmetric objects to be slightly off, requiring a corresponding subsequent weld with an offset large enough to accommodate the offset caused by the misalignment. This can be accomplished by using a subsequent Connect or by using the Weld feature of the Symmetry itself, for symmetry operations.

 

Interestingly, if you take the combined object created by the Cloner and/or Symmetry and do a "Connect Objects" command on it, then go into points mode on the resulting composite object, you can then use Optimize to weld those pesky just slightly off points.

 

What I am looking for is a way to:

 

After using "Connect Objects" to convert the cloned/symmetrized part, just mark and/or identify the points that would be welded via Optimize with a certain tolerance value.

 

I don't want them removed/welded, just marked so that I know which/where they are. Then I can use this information to locate them in the original pre-Cloner/Symmetry object part and adjust/align the points' positions to resolve the issue(s) at the source.

 

Does such a tool exist and/or is there a way to highlight, select, and/or mark these points somehow in base C4D?

 

See the following attached images for a simple example illustrating the desired operation(s):


Image 1: Object with misaligned points after a symmetry operation followed by Connect Objects (Points mode with all points highlighted, to make them more visible.)

 

misaligned-points1.png.eff08f0bda3cba5f89c10cc139f033e9.png

 

Image 2: Result of an Optimize operation with all points highlighted (the top two points have been welded by Optimize into a single point)

 

misaligned-points2.png.3229f67b53eddc6fac210d94b7b1d489.png

 

 

Desired result (after Undo of Optimize): Don't weld nearby points, just mark them:

 

Image 3: Points marked by highlighting them in the composite object

 

misaligned-points3.png.dd5df39183a65caf53f68fe4009c49ce.png

 

Image 4: Points marked by placing red circle shaped camera facing Null objects at the points' locations in order to mark their positions, without affecting the points themselves - a far better approach that is independent of the temporary composite object which can then be deleted, leaving behind just the point marking Null objects.

 

misaligned-points4.png.65318a9340bd98235c8e5f03c71c1032.png

Link to comment
  • SharpEars changed the title to The equivalent of Optimize (U-O), but instead just mark the affected points

No that functionality does not exist within Cinema AFAIK. I keep asking for / suggesting an optimize command that shows you the before and after point count interactively before confirmation, which would eliminate the 'guess the threshold' thing, and I suppose that functionality could be expanded to also live flag the affected points in the VP, but no joy so far. 

 

If I'm honest I can't think of many situations where seeing those points is more important than actually solving them, so perhaps that's why there hasn't been much demand for this before ?

 

CBR

Link to comment
56 minutes ago, Cerbera said:

No that functionality does not exist within Cinema AFAIK. I keep asking for / suggesting an optimize command that shows you the before and after point count interactively before confirmation, which would eliminate the 'guess the threshold' thing, and I suppose that functionality could be expanded to also live flag the affected points in the VP, but no joy so far. 

 

CBR

Not sure what you mean by the abbreviation of VP, but certainly an option to Optimize would be welcome, or perhaps an addition to the Mesh Checker, not sure how.

 

I just might script it up myself, in the direction of the fourth example image perhaps with an additional target null marking where the point should be moved to, assuming the midpoint is the correct place. This is complicated by the fact that there may be more than two points that are in close proximity and need to be welded together.

 

Also, turns out that optimize doesn't even weld to a location in the middle! It just welds one point to the location of another, somewhat arbitrarily (perhaps having to do with point order or how optimize works).

 

I guess I can compare my results with those of Optimize to make sure I am doing the right thing...

 

Link to comment

First pass attempt at scripting this via a Python generator (make sure to view full size, it's 1080p, sized down from 4k):

 

The reddish circle Nulls identify misaligned neighboring points. The green marker Nulls indicate where the master of the two points should be, in order for them to merge into and occupy one shared point as a result of the Symmetry generator (i.e., mid-point).

 

first-pass-attempt.png.6bdacf2723f668951ae8d6713ab4b0b9.png

 

Another example:

 

Somewhere on the Platonic, below, which has been converted to an Editable Object, lies a point that divides an edge, that shouldn't exist.

 

See it? Neither do I!

 

I just got done cutting one of the many edges into a smaller part and a larger part. But, having zoomed out, they all look the same and even I can't tell or remember which edge it was.

 

Sure, Optimize, with the correct settings (usually found through trial and error, btw!) can fix this and get rid of the smaller (sub-)edge via welding, but where in the world is it? Will Optimize weld correctly, retaining symmetry and alignment? (Note: Probably not, if experience is anything to go by!) Will it remove any points that should not have been removed? Who knows... OK, to be fair with regard to this particular case, all of the edges, except for two, are of the same length, so Optimize will probably do the right thing once set up correctly.

 

platonic-a.png.489f3371f6471d10c84a5f0bd5fc4150.png

 

Anyhow, enough about Optimize. We plop the object into the Python Generator I've started writing the code for, let it do its thing, and we get the following:

 

platonic-b.png.2b2ffe91d853a8d6a130d5c31671b33f.png

 

Ahh, there it is (i.e., well, there they are - the points that make up the shorter of the two edges)! Let's zoom in and take a look at the situation, now that we know where on this complex map, it lies.

 

I have gone ahead and selected all of the points of the modified Platonic, in order to make things more clear.

 

The red circle Nulls (overly large for this case, I know) mark two very close adjacent points. The green sphere Null marks the midpoint to which they can be welded, if so desired. Of course, we can always choose to weld to one of the two points - it's our choice to make:

 

platonic-c.png.069c035422eee4a5244c061c64206110.png

 

Correctly choosing among the three possibilities, with human understanding of the object's point layout, symmetry, role, and context (i.e., something Optimize could never do), we perform a proper spot-weld and restore our poor cut-up Platonic to its former beautiful symmetric glory.

Link to comment
14 hours ago, johanal said:

that is so wicked!!!  You banged this out in less than a day  😮

 

It's Python after all, the language for quickly "banging something out," unless you expect it to also be performant, that is. Everyone that doesn't wear the "blinders of ignorance" knows that you can't do much worse than choosing the poster child for "slow, poorly performing code" - Python.

 

Link to comment
7 hours ago, SharpEars said:

 

It's Python after all, the language for quickly "banging something out," unless you expect it to also be performant, that is. Everyone that doesn't wear the "blinders of ignorance" knows that you can't do much worse than choosing the poster child for "slow, poorly performing code" - Python.

 

 

If you use Python to call C4D API functions, these are executed as native code though, so they are (almost, naturally there is overhead) as fast as if called from C4D or C++ directly.

Naturally, if you use Python for giant nested loop constructions on your own data, then it is... not very efficient. But even then, many a usecase can be covered with a quick Python hack; not everything requires elaborate C++.

Link to comment
5 hours ago, Cairyn said:

 

If you use Python to call C4D API functions, these are executed as native code though, so they are (almost, naturally there is overhead) as fast as if called from C4D or C++ directly.

Naturally, if you use Python for giant nested loop constructions on your own data, then it is... not very efficient. But even then, many a usecase can be covered with a quick Python hack; not everything requires elaborate C++.

 

You are largely correct, with one very large exception. Because objects can be fairly complex and the Python API is barren (as compared to the C++ SDK) and is implemented (strictly) from a "easy to use" rather than a performance perspective, the transfer of information from inside C4D to Python (and back) is often done very inefficiently.

 

The general paradigm is to copy data and create new Python containers (i.e., lists) rather than make incremental changes to whatever data the Python programmer already has available or has received back from a prior call.  There is also, within Cinema 4D the need to (deep) clone objects over and over again, but that's a separate topic that is orthogonal to the use of Python. This "copy everything on request or submission" paradigm in particular is what makes the Python API slow when it comes to creating and/or manipulating the guts (i.e., points/edges/polygons) of large objects, splines with many points/segments, and/or object hierarchies consisting of many objects.

 

If you ask me, the Python API should be enhanced with more performant versions of calls, with backward compatibility, of course, and further enriched. Then there would perhaps be a hope and a prayer towards (better) performance.

 

I did not mention the issue of threading in the above, but that is another Python limitation that is far more difficult for Maxon to address from an API evolution perspective, since it is a limitation within Python itself.

 

Link to comment
1 hour ago, SharpEars said:

 

You are largely correct, with one very large exception. Because objects can be fairly complex and the Python API is barren (as compared to the C++ SDK) and is implemented (strictly) from a "easy to use" rather than a performance perspective, the transfer of information from inside C4D to Python (and back) is often done very inefficiently.

 

The general paradigm is to copy data and create new Python containers (i.e., lists) rather than make incremental changes to whatever data the Python programmer already has available or has received back from a prior call.  There is also, within Cinema 4D the need to (deep) clone objects over and over again, but that's a separate topic that is orthogonal to the use of Python. This "copy everything on request or submission" paradigm in particular is what makes the Python API slow when it comes to creating and/or manipulating the guts (i.e., points/edges/polygons) of large objects, splines with many points/segments, and/or object hierarchies consisting of many objects.

 

If you ask me, the Python API should be enhanced with more performant versions of calls, with backward compatibility, of course, and further enriched. Then there would perhaps be a hope and a prayer towards (better) performance.

 

I did not mention the issue of threading in the above, but that is another Python limitation that is far more difficult for Maxon to address from an API evolution perspective, since it is a limitation within Python itself.

 

 

The difficulty is that Python cannot access C++ data structures directly, so many objects require that kind of copying - or, alternatively, special methods for very low level access. As the C++ structures are not built with Python in mind, the transformation can be time-consuming, yes.

 

If someone expects to handle large numbers of points/polygons in Python on a regular basis, they will be disappointed. That's why I program point-level plugins in C++. However, as long as you pass references or don't have huge data structures to exchange, Python can be fast enough for many a task. Taking a look at simple calls with a huge calculation load in the background, e.g. a brutal RenderDocument() or SendModelingCommand(), the ratio of fast native code to Python slow code can be good enough to achieve satisfying results. Naturally, the opposite is possible 🦊

 

I'm not sure whether Python should be an efficiency focus for Maxon at all - interfaces between languages can be notoriously difficult, and additional efficiency methods would gobble up a lot of developer time while not helping the majority of users. For rapid prototyping, quickly-finished helpers, or rarely needed special functions, Python is good enough... for the faster stuff, we still have C++, and the super fast functionalities even require the use of GPU libraries.

Link to comment
×
×
  • Create New...

Copyright Core 4D © 2023 Powered by Invision Community