Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
I was considering the scenario when I have the object and let say one single point/null next to it.
And base on the distance between the null and my mesh I would like to delete the mesh points gradually. I tried xpresso a bit today with point node but I cant figured out how to do it.
From my understanding I would need position attribute from my mesh points and the distance from my null to the mesh as a variables and then I can run if condition saying if the distance is less then something remove points from my geo. If you Guys can help my with that using python or coffee I would be delighted
Thanks
Hello and welcome to the Plugincafe,
as always, please mark your post as a question and use tags. See
Also, please do not cross post your questions on different forums.
Please notice that the COFFEE programming language has been removed since Cinema 4D R20.
I guess with "delete the mesh points gradually" you mean you want to have a slider that defines the radius of the effect. The best (and most Cinema 4D-like) way to implement that, would be to create a generator object plugin (ObjectData). This generator object would use the polygon object and the control object as input objects and would create a virtual object in its cache according to your algorithm. Such an object would work similiar to the "Polygon Reduction" object.
A generator plugin has to implement the function GetVirtualObjects(). You find an example of such a generator on GitHub: https://github.com/PluginCafe/cinema4d_py_sdk_extended/tree/master/plugins/py-rounded_tube_r13
Within that GetVirtualObjects() function, you can use GetHierarchyClone() to create a polygonal clone of an input object. You can apply your algorithm to this clone accordingly.
You want to delete points, but you most not forget also to delete the corresponding polygons that were referencing the delete points. I guess the best way of handling that is to use SendModelingCommand() with MCOMMAND_DELETE.
selection = op.GetPointS() # clear existing selection selection.DeselectAll() # define a new selection selection.Select(0) mode = c4d.MODELINGCOMMANDMODE_POINTSELECTION res = c4d.utils.SendModelingCommand(c4d.MCOMMAND_DELETE, list = [op], doc = None, mode = mode)
best wishes, Sebastian
Hi,
I was considering the scenario when I have the object and let say one single point/null next to it. And based on the distance between the null and my mesh I would like to delete the mesh points gradually. I tried xpresso a bit today with point node but I cant figured out how to do it.
It is custom to post either existing code or some sort of principal work when one asks for help in coding forums as people are usually happy to help with your problem but not willing to solve it for you. So show us what you got
From my understanding I would need position attribute from my mesh points and the distance from my null to the mesh as a variables and then I can run if condition saying if the distance is less then something remove points from my geo.
You have three points: The origin of your null object (A), the origin of your polygon object (B) and the vertex point (C) in your polygon object you want to evaluate for deletion. From your wording I assume you want the orthogonal projection of C onto the line segment AB (i.e sample the linear volumetric gradient G spanned between the points A and B at the position of your vertex point C). The magnitude of AB proposed by you is a constant and the magnitude of AC depends on the topology of your polygon object and is probably not what you mean by gradually. The Python SDK offers c4d.utils.PointLineSegmentDistance() for line segment projections.
c4d.utils.PointLineSegmentDistance()
There is also more ambiguity in your wording when you say gradually. Since deletion is a binary decision (you either do it or you don't) you need a third component to determine if you want to delete a point. You could get extra fancy here, but the most straight forward thing would be to just generate a random number based on C.The full decision to delete a point would be then something like this (in pseudo code):
if gradient(a, b, c) * random(c) > threshold: #threshold could be .5 for example delete(c)
Cheers zipit
Hey Sebastian,
It's sound for me really complicated What I would like to achieve is this :
Based on the distance between two object, remove points from the object_1 while the object_2 is close enough to the object_1.
Would that be possible in Xpresso and its point node?
Thanks again for your input. Thanks, Andrzej
Hey zipit,
Thanks for your suggestions. I am coming from vex Houdini so I can picture the code here how I can get this type of effect in Houdini I know it's not relevant to C4D but I am trying to make this simple effect in C4D.
In H it would be like this :
Hope that make sense:) I did never script in c4d so I can not post here any examples:( Ta
@andmotion The question is what kind of user interaction do you have in mind. As far as I can see, the Point operator in Xpresso does not allow to delete points.
If a simple script is good enough, the desired effect of deleting points in a given radius is not that complicated. This is the code for a script executed in the Script Manager:
import c4d def main(): # get null object by name nullObj = doc.SearchObject("null") # get polygon object by name polyObj = doc.SearchObject("polygon") if nullObj is None: return if polyObj is None: return # get world space position of null object nullObjPos = nullObj.GetMg().off # get world space matrix and points of the polygon object mg = polyObj.GetMg() points = polyObj.GetAllPoints() # prepare the point selection of the polygon object selection = polyObj.GetPointS() selection.DeselectAll() # check each point for idx, point in enumerate(points): # get world space position of the point pointPos = mg * point # get the distance from the point to the null object diff = pointPos - nullObjPos distance = diff.GetLength() # check distance if distance < 100: selection.Select(idx) # delete selected points mode = c4d.MODELINGCOMMANDMODE_POINTSELECTION res = c4d.utils.SendModelingCommand(c4d.MCOMMAND_DELETE, list = [polyObj], doc = doc, mode = mode) c4d.EventAdd() if __name__=='__main__': main()
@s_bach Thanks for the quick reply. That's is simply awesome that you made this code so I can dive in and actually grasp some python basic.
I noticed that also yesterday, Xpresso wont allow me to delete points, I can iterate thru them but I could find the way how to literally delete it.
Will go thru the code and let you know my thoughts, for now THANKS A LOT for help. Thanks
@s_bach
While trying to understand your code some questions raised in my head :
polyObj.GetAllPoints(). Is it not each point vector? If it's I don't understand the idea of looping thru those vectors to get each pointPos.....
It's hard for me also to pick up the idea of calculation pointPos inside the for loop. In your code you are multiplying polyObj global Matrix with point.....
At the moment if I have both null and Sphere at 0,0,0 coordinates all points are deleted. if I move sphere a few units in Y axis strangely the middle of the sphere get deleted.
I will spend more time on it to find out the solution. It seems like I will need some kind of channel(slider) while doing if distance < 100 so I could specified the radius by the slider.
I would also need to have this distance updated in real time so when I move null close to the sphere in the viewport the points inside the radius are automatically deleted.
I am really appreciated Sebastian your input here...Thanks
Here is the code I am playing with now
import c4d from c4d import gui from c4d import utils #Welcome to the world of Python def main(): nullObj = doc.SearchObject("Null") polyObj = doc.SearchObject("Sphere") if nullObj: print("Null is") if not nullObj: print("no Null") if polyObj: print("Sphere is") if not polyObj: print("no Sphere") #get nullObj world space position nullWSMg = nullObj.GetMg().off print nullWSMg #get matrix and points from polyObj polyObjWSMg = polyObj.GetMg().off polyObjPointsPos = polyObj.GetAllPoints() #print polyObjPointsPos print polyObjWSMg #point selection of the polygon object selection = polyObj.GetPointS() selection.DeselectAll() #check each point for i, point in enumerate(polyObjPointsPos): #get WS pos of the points pointPos = polyObjWSMg * point #get the distance from point to the null diff = nullWSMg - pointPos distance = diff.GetLength() #check distance if distance < 100: selection.Select(i) #delete selected points mode = c4d.MODELINGCOMMANDMODE_POINTSELECTION res = c4d.utils.SendModelingCommand(c4d.MCOMMAND_DELETE, list = [polyObj], doc = doc, mode = mode) c4d.EventAdd() if __name__=='__main__': main()
Here I uploaded the effect I am after :
https://vimeo.com/359336806?activityReferer=1
I know that using Boole in C4D I can have exactly the same effect BUT my goal is to start from this simple effect as a python journey. Thanks for any suggestion. Thanks
@andmotion said:
#get matrix and points from polyObj polyObjWSMg = polyObj.GetMg().off
You did not assign a matrix topolyObjWSMg but the offset vector off the global matrix of polyObj.
polyObjWSMg
polyObj
pointPos = polyObjWSMg * point
Which will make pointPos here not a c4d.Vector but a float - the dot product of two vectors. You also don't have to calculate the global point positions in your loop if you find that distracting, you can just do:
pointPos
c4d.Vector
float
mg = polyObj.GetMg() global_points = [mg * p for p in polyObj.GetAllPoints()] distance_squared = 100 ** 2 null_mg = null.GetMg() for pid, point in enumerate(global_points): if (null_mg * point).GetLengthSquared() < distance_squared: selection.Select(pid)
And regarding odd behaviour and want you want to do, I would point to my first post. Still sounds to me you actually want to evaluate a gradient.
Hello,
PointObject.GetAllPoints() returns a list of vectors; each vector is the object space position of the point of the corresponding index.
To get the world space position, you have to multiply that object space position with the world space matrix.
You find some information on matrix calculations here: Matrix Fundamentals.
If you want to have an interactive slider, you cannot use a script anymore. You have to write a plugin.
As described above, the best way would be to implement the functionality as a ObjectData based generator. This way a procedural workflow could be maintained.
ObjectData
Best wishes, Sebastian
I thing after short research that c4d.plugins.ObjectData could actually be the solution I am after. I will be posting my progress here. Once again Thanks Guys for heads up!!!!! Thanks