@m_adam Shoot, tried calling it 3X and still nothing on the cloner (spline mode) object.
(failing) test file attached
fbxtest_v04.c4d
@m_adam Shoot, tried calling it 3X and still nothing on the cloner (spline mode) object.
(failing) test file attached
fbxtest_v04.c4d
Hello, I would use it quite often if it could be added: a Quaternion rotation setting to the XPresso Mix node... much like there is in the c4d.BaseObject class as it is accessible through the GUI
Attributes of a regular Null object showing Quaternion setting:
Attributes of a Mix node in XPresso, where a boolean checkbox like above could live:
I have constructed a Quaternion Matrix Mix using an XPresso Python node myself, but thought this would be a useful feature to be added in the default XPresso API for users who have not yet learned how to implement Quaternions in Python. Alternatively, perhaps other users will find the following code useful anyway
import c4d
from c4d import utils
#Welcome to the world of Python
def main():
global MatrixMix
q1 = c4d.Quaternion()
q1.SetMatrix(MatrixA)
q2 = c4d.Quaternion()
q2.SetMatrix(MatrixB)
q = c4d.utils.QSlerp(q1, q2, Mix)
MatrixMix = q.GetMatrix()
MatrixMix.off = c4d.utils.MixVec(MatrixA.off, MatrixB.off, Mix)
Cheers!
-Leah
Edit: also I am sorry if this is posted incorrectly. This seemed like the best place to put this post since there is usable Python code included
Hello @ferdinand! I hope this message finds you and your team well.
Sorry for the somewhat off-topic post, but I feel as though I must check back in after the last 2 weeks I have had.
I dove right into Houdini particles for about 10 days and now have a loose understanding of the layout of the program- at least enough to use it for work. I continue to feel tugged to learn more, but just today I came across a person on youtube, Dominik Ruckli, who has been releasing some incredibly deep tutorials using scene nodes that make C4D look like Houdini- even building his own particle setup!
After getting a lay-of-the-land in Houdini and now seeing the high level tool building potential in scene nodes, I can't help but think that C4D is actually not that far off from being able to match Houdini in a lot of ways.
I hope that the new simulation based particle system you've mentioned is in-part integrated into scene nodes workflow, because the vast theory and knowledge of Houdini artists would be almost drag and drop back into C4D (as can be seen with Dominik's work on a few concepts/setups). So much potential.
The future of C4D excites me so much now after what you have said. I hope you have a wonderful day!
@ferdinand said in using c4d.threading with (python) thinking particles:
...
A new particle system based on the simulation framework is an item on our bucket list, but it might take some time until we get there.
...
That makes me very happy to hear, thank you for that!
X-Particles is very powerful and I have used it on many projects with great success over the years, but it misses the mark on UX within c4d due to the nature of it being third party. Working directly within and making use of all core toolsets in an integrated fashion is preferable when it comes to such delicate/intricate procedural tasks as particle motion. I have tried on several occasions to use X-Particles python API, but it as well suffers from severe performance restriction and a deluge of execution order mysteries- which always leads me back to just doing things in thinking particles. Simple.
I am very happy to hear that c4d might someday have a new particle system, though. That is terribly exciting, because in the meantime I now must consider facing the houdini mountain yet again while I wait with hope
Thanks again for your response- you've definitely inspired hope in me to stick around. I really love C4D, and I think you are doing great work with all of the recent improvements!
Thank you so much for the clear response, @ferdinand !
Oof... I have long been avoiding houdini, but I keep running into limits the deeper I go with particles in c4d python. Random things won't work in the TP python API (like trying to get/set a bool TP data channel among others), and the TP system as a whole feels like it hasn't been touched in a decade or maybe longer.
Perhaps procedural particles (controlled with python/xpresso) in c4d are in need of a rebuff? I hope the dev team is talking about it or considers the importance, because at this point a move to houdini seems like the only viable option from a production standpoint as particle counts go up.
I know this forum is mainly for plugin developers, and I appreciate you helping out anyway with this non-plugin-related topic. Thank you again
Hello! I am curious if there are any gotchas to be aware of with using c4d.threading with thinking particles in Python.
Specifically, if I have two particle groups (let's say groupA
and groupB
), will each thread performing calculations on groupA
that depend on groupB
and making changes to either of these groups be able to see the results recorded simultaneously as stored in the document as the threads run through their set of assigned particles to calculate?
Let me break it down even further.
Let's say I have 100k particles in groupA
that I am going to break up into 10k chunks across 10 threads. At some point in the animation, each particle is instructed to find a match with a particle in groupB
to act as a unique target (think of the particle in groupA
acting as a homing missile trying to land on a particle in groupB
). When the groupA
particle gets matched with the groupB
particle, a bool switch stored in a TP data channel (matched
) is set on the groupB
particle to remove it as a potential match for other groupA
particles. This way, there are no groupA
particle overlaps when all the particles have reached their targets.
So essentially what I'm asking is... is this difficult to implement with threading? As each 10k particle count thread calculates, will they be able to see matches made via accessing groupB
TP channel data from other threads as things are calculating? Will the TP channel data touched mid-process by one thread be seen by another thread? If not, is there some way to achieve this goal?
ooh good catch! I would edit that comment if I could. thanks @ferdinand !
pasting again w/ the fix:
def FieldListSample(op, doc, positions, fields):
cnt = len(positions)
sampleFlags = c4d.FIELDSAMPLE_FLAG_VALUE | c4d.FIELDSAMPLE_FLAG_COLOR
fieldInput = c4d.modules.mograph.FieldInput(positions, cnt)
fieldInfo = c4d.modules.mograph.FieldInfo.Create(sampleFlags, None, doc, 0, 1, fieldInput, op)
fieldOutput = c4d.modules.mograph.FieldOutput.Create(cnt, sampleFlags)
fields.DirectInitSampling(fieldInfo)
samplingSuccess = fields.DirectSample(fieldInput, fieldOutput.GetBlock(), fieldInfo)
fields.DirectFreeSampling(fieldInfo)
return fieldOutput
# list of positions
positions = [c4d.Vector(0, 0, 0)]
# store the output (assumes that 'fields' is the FieldList)
fieldOutput = FieldListSample(op, doc, positions, fields)
# grab the weights as a list from fieldOutput
weights = [fieldOutput._value[x] for x in range(fieldOutput.GetCount())]
Extremely useful stuff if writing python generators / effectors or working with thinking particles in python.
A feature request: adding some straight-to-the-point methods or a helper/abstraction class to streamline this in the future. Perhaps the dev team might even consider a few XPresso nodes for sampling Field Lists? Fields are so powerful and super exciting to use. Having a blast!
my final working code(in a Python Tag, only mildly styled from mike's original):
def FieldListSample(op, doc, positions, fields):
cnt = len(positions)
sampleFlags = c4d.FIELDSAMPLE_FLAG_VALUE | c4d.FIELDSAMPLE_FLAG_COLOR
fieldInput = c4d.modules.mograph.FieldInput(positions, cnt)
fieldInfo = c4d.modules.mograph.FieldInfo.Create(sampleFlags, None, doc, 0, 1, fieldInput, op)
fieldOutput = c4d.modules.mograph.FieldOutput.Create(cnt, sampleFlags)
fields.DirectInitSampling(fieldInfo)
samplingSuccess = fields.DirectSample(fieldInput, fieldOutput.GetBlock(), fieldInfo)
fields.DirectFreeSampling(fieldInfo)
return fieldOutput
# list of positions
positions = [c4d.Vector(0, 0, 0)]
# store the output (assumes that 'fields' is the FieldList)
fieldOutput = def FieldListSample(op, doc, positions, fields)
# grab the weights as a list from fieldOutput
weights = [fieldOutput._value[x] for x in range(fieldOutput.GetCount())]
cheers, thanks again to @mikeudin
I found an example by @mikeudin that did the trick!
Thanks so much for sharing!
Hello! It seems that it should be possible to sample a Field List from userdata in a Python Tag, however I am having a hard time getting going since there aren't many examples in existence.
What I would really like to be able to do is this (sorry for the semi-psuedocode):
# get the field list from userdata on the python tag
fieldList = op[c4d.ID_USERDATA,1]
# sample the field at a specific point in global 3D space
weight = fieldList.Sample(c4d.Vector(0, 0, 0))
I know the above code does not work, but maybe it is helpful describing what I'm after.
Is this somehow possible in a Python Tag?
Thanks so much, this points me in the right direction!
Oof, I wish this was more easily accessible/abstracted like c4d.InExcludeData with insert/delete/get/count. Either way I appreciate the tip!
edit 1: Ok, I see that I can just create a new field list and replace the object's data with it, this works.
import c4d
doc: c4d.documents.BaseDocument
op: c4d.BaseTag
def main() -> None:
deformer = op[c4d.ID_USERDATA,1]
splineGroup = op[c4d.ID_USERDATA,2]
fieldList = c4d.FieldList()
deformer[c4d.FIELDS] = fieldList
c4d.EventAdd()
pass
I have a null object splineGroup
containing several c4d.SplineObject
that I would like to add as spline field layers to the FieldList stack
edit 2: Digging through, but I don't see how it is possible to add a Spline Field Layer with python.
edit 3: I figured it out
import c4d
doc: c4d.documents.BaseDocument
op: c4d.BaseTag
def main() -> None:
deformer = op[c4d.ID_USERDATA,1]
splineGroup = op[c4d.ID_USERDATA,2]
splines = splineGroup.GetChildren()
fieldList = c4d.FieldList()
for spline in splines:
fieldLayer = c4d.modules.mograph.FieldLayer(c4d.FLspline)
fieldLayer.SetLinkedObject(spline)
fieldList.InsertLayer(fieldLayer)
deformer[c4d.FIELDS] = fieldList
c4d.EventAdd()
pass
edit 4: Ok, it appears that the script above does not work for multiple splines/layers
edit 5: I know this is probably a simple solve, but it's eluding me.
If I break out the for loop with unique variable names, I can have multiple FieldLayers populating the FieldList.
However, running in a for loop as shown above, I only get one... The last spline in the for loop which is definitely a clue.