Get the random result of Cloner Object
-
I created a Cloner Object and place a cube inside,using Random as clones type.The result clones changed with the order in Cloner Object like below:
But when I try to get the information of the clones like:
Matrix clonerMatrix = clonerObj->GetMg(); BaseTag* motag = clonerObj->GetTag(ID_MOTAGDATA); if (motag == nullptr) return; // populate the GetMoDataMessage instance by sending a MSG_GET_MODATA GetMoDataMessage modataMsg; if (!motag->Message(MSG_GET_MODATA, &modataMsg)) return; if (!modataMsg.modata) return; // access the MoData from the returned GetMoDataMessage and check its validity MoData* moData = modataMsg.modata; if (!moData) return; // retrieve the number of Matrix items as well as the array containing the matrix for each of them Int32 matrixItemsCnt = moData->GetCount(); Matrix* itemsMtxArray = static_cast<Matrix*>(moData->GetArray(MODATA_MATRIX));
the matrixItemsCnt always be 60 ,full of the instances in this case ,same as the Matrix I got.Any way can I just get the clones shown as the random result?Many thanks.
-
Hey @freeze,
Thank you for reaching out to us. I do not understand your question, specifically this part:
the matrixItemsCnt always be 60 ,full of the instances in this case ,same as the Matrix I got.Any way can I just get the clones shown as the random result?
Could you please reiterate what you want to achieve or what you would consider incorrect/surprising about your results?
Cheers,
Ferdinand -
@ferdinand Sure,I mean that how can I get the cubes' matrix shown in the scene in the picture I uploaded for example.
-
Hey @freeze,
I am still not quite sure how you mean that. MoGraph is a particle system under the hood, i.e., you will not find the actual cloned objects in it unless you reach into the cache of the cloner. The particle arrays is all there exists, e.g.,
MODATA_MATRIX
for the transform of the particles. When you want to retrieve the matrix of the input object, you must get that.Cheers,
FerdinandResult
Code
import c4d import mxutils doc: c4d.documents.BaseDocument # The currently active document. op: c4d.BaseObject | None # The primary selected object in `doc`. Can be `None`. def main() -> None: """Called by Cinema 4D when the script is being executed. """ moData: c4d.modules.mograph.MoData | None = c4d.modules.mograph.GeGetMoData(op) if op else None if not moData: raise RuntimeError("Please select an object that holds MoGraph particle data.") print ("Particles:\n") # Iterate over the (local) particle matrices for this MoGraph data. Local means here in relation # to the MoGraph generator, i.e., cloner. for i, ml in enumerate(moData.GetArray(c4d.MODATA_MATRIX)): print(f"{i = }, {ml = }") print ("\nInputs:\n") # Iterate over the child objects of the cloner, i.e., the clone sources. for node in op.GetChildren(): print (f"{node.GetName() = }, {node.GetMg() = }") print ("\nCache:\n") # Look into the cache of the cloner which might contain the flattened particle data (when in # Instance or Render-Instance mode). When the cloner is in Multi-Instance mode, the cache will # not be (fully) populated. cache: c4d.BaseObject | None = op.GetCache() if cache: for node in mxutils.IterateTree(cache): print (f"{node.GetName() = }, {node.GetMg() = }") if __name__ == '__main__': main()
-
@ferdinand So how can I look into the cache of the cloner in c++ in my case with the clonerObj?I already got the moData and op
-
Hey @freeze,
yes,
clonerObj
would be in your case the object which holds the generated MoGraph particle output in its cache. But generally speaking, you should not reach into caches. Sometimes it is necessary, but caches (be it generator or deform caches) are a dynamically generated part of the scene graph you usually should not interact with.Just getting the matrices of the elements in the cache is fine (to print them or do something similar harmless). Establishing pointers into caches or relying on the fact that there is an established cache is not fine (note that my code checks for the cache actually being populated).
I still do not really understand what you want to do, but it strikes me as being on the 'you should really not do that' side. As I said in the beginning, MoGraph is a particle system and you are only supposed to interact with the abstract particle data.
I have the feeling you want to interact with the MoGraph particles as if they were tangible objects in the scene graph. This is simply not supported/intended.
Cheers,
Ferdinand