MoData's GetFalloffs() returns only 0 while rendering
-
This riddle has stumped me:
I create a simple Python effector. Here's a trimmed-down version:
import c4d from c4d.modules import mograph as mo def main() : moData = c4d.modules.mograph.GeGetMoData(op) if moData is None: return False hasField = op[c4d.FIELDS].HasContent() print ("hasField:", hasField) farr = moData.GetFalloffs() print ("Falloffs:", farr) return True
It does nothing to the clones in this case, just shows me the falloffs (the original modifies the clones, but it behaves the same and doesn't add to the question). The scene is also very simple, the effector has a box field that moves over some cube clones.
Now here's the riddle:
When I animate this scene in the viewport, the console shows me the expected falloffs, changing as the animation runs. All is well with the world.
When I render the same scene however, the console shows me a constant 0.0 for all falloffs.I am not able to find any explanation, any flag to set, any function to call. There are multiple examples for Python effectors, and multiple threads on this forum, none of which mentions any issue with rendering.
I can put a MoGraph Cache Tag on the cloner, which works fine, and which replays fine (also with the more complicated original scene). But I don't see it mentioned anywhere that a cache is mandatory. The rendering should IMO just work.(I tried this on R21 too, with the same results.)
-
Hi,
You don't need to write you own code, just using the default python effector on
full control
, once you add a field, the effector will not work at render time.
I've reported the bug a few times ago, but it is still there.Cheers,
Manuel -
Ouch! In R25 still? Thanks for the confirmation; so I may need to rewrite my effector in Parameter mode (since you mentioned the mode, I suppose it'll work this way?)
-
Okay, Parameter Mode is even worse when it comes to falloffs.
GetFalloffs()
results in an actual error raised.
GetArray(c4d.MODATA_FALLOFF_WGT)
results in None.
GetArray(c4d.MODATA_WEIGHT)
returns a proper array, but it's filled with zeroes no matter where the field is.Also, the auto-gen sample code (at least in R23) is faulty:
it uses an attributedata
which is undefined, causing an error (I found on the forum that the mode can be read viaGetBlendID
, though); and it reads theMoData
from thegen
variable instead ofop
, which results inGetCurrentIndex
always returning 0.It doesn't work in the expected way anyhow. The vector returned by the Python code for
ID_MG_BASEEFFECTOR_POSITION
is not an absolute, but kind of a weight for the value set in the GUI. I'd need to return the final value though, which cannot be expressed as a product. This works in Full Control mode, but as the falloffs will not work there either with a field while rendering, I guess... I lost the game. -
hi,
I don't remember the version, but we fixed the default script, now it is working in parameter control. I just remember there was no workaround for the python effector to work in full control mode.
Cheers,
Manuel -
@m_magalhaes Meanwhile, I found one (more or less): calculating the falloff myself. I just need to access the field list and perform a
SampleList
on the clones' positions. This actually works within the render process as well. Looks approx. like this:md = mo.GeGetMoData(op) if not md: return False cnt = md.GetCount() marr = md.GetArray(c4d.MODATA_MATRIX) fieldlist = op[c4d.FIELDS] matCloner = gen.GetMg() inputField = c4d.modules.mograph.FieldInput([marr[i].off * matCloner for i in range(cnt)], cnt) info = c4d.modules.mograph.FieldInfo.Create(c4d.FIELDSAMPLE_FLAG_VALUE, None, doc, 0, 1, inputField, gen) outputs = c4d.modules.mograph.FieldOutput.Create(cnt, c4d.FIELDSAMPLE_FLAG_VALUE) fieldlist.SampleList(info, inputField, outputs) # print (outputs.GetValue(0)) for i in range(0, cnt): fieldStrength = outputs.GetValue(i) # usw usf
-
Aaaand of course I forgot a crucial point: After modifying the clone positions in marr, you need to write them back to the MoData, but the last parameter
apply_strength
must be False:moData.SetArray(c4d.MODATA_MATRIX, marr, False)
This is at first glance unintuitive since we want the strength to be present but when looking closely, you can fathom that the function will internally multiply with the falloff strength that it calculated itself, and that probably comes from
GetFalloffs()
again, so it's 0 and nothing is won. We do not wantSetArray
to do that at all, because we have already applied the falloffs that we calculated ourselves, andSetArray
should keep its buggy hands off it!