Inconsistent Matrix Behavior
-
Hi,
@JohnThomas said in Inconsistent Matrix Behavior:
I am now trying to get the MoData from a Boole object utilizing the same process with this code.
I might be overlooking something here, but why would you expect a Boole Object to have a
MoTagData
tag?MoData
is basically just a bunch of arrays each holding the values for all clones for a specific attribute (e.g.: the matrix, weight, color, etc.). SoMoData
is only generated for objects that generate such MoGraph clones.I am not quite sure why you are under the impression that you code is working on a live document, but for the scene graph/ the Boole Object provided in your screenshot
tag
should always be the null pointer.Cheers
zipit -
Hi JohnThomas, thanks for reaching out us.
With regard to your issue, I confirm exactly what @zipit already stated: MoData information are actually made available only by MoGraph-related generator and in the case of the Boole Object, it's actually not the case.
The MoGraph related objects are:
- Cloner Object
- Matrix Object
- Fracture Object
- Voronoi Fracture
- MoInstance Object
- Text Object
- Motion Graphics Tracer Object
- MoSpline
- MoExtrude
- Poly FX
Best, Riccardo
-
Hello,
Thanks for the responses, sorry I wasn't clear with what my process was.
In my code I am creating a virtual document and inserting a Matrix object into it along with a clone of the object that I want to get the point data from.I set the parameters for the Matrix Object so that it is in Object Mode and link the cloned object to it. With this process I've been able to get the point data for most of the objects I want with the exception of the Boole object via getting the MoData tag.
John Thomas
-
Hi,
I do not want to come across pedantic, but since I do not fully understand your problem, let us sort out some terminology first, so that we are sure, we are talking about the same things:
In my code I am creating a virtual document [...]
I assume with a virtual document you are referring to a temporary document, i.e. a document which has not been added to the list of documents in c4d, right?
With this process I've been able to get the point data for most of the objects [...]
I assume with point data you are referring to
MODATA_MATRIX
, i.e. the matrices of the clones?I want with the exception of the Boole object via getting the MoData tag.
And just to be sure, you trying to get the
MoData
from theMoDataTag
on your MoGraph generator object, not the Boole Object?Aside from that this all sounds very mysterious. Providing a more extensive code example (regarding your temporary document and setup) would be helpful. At least I cannot think of any circumstances that would prevent you from reading out the matrices of your clones when they are instances of a Boole Object. This does not mean that this cannot be the case, it would just make things easier when we would have your actual code.
Cheers
zipit -
Thanks for the response.
Yes I am trying to get the MoData from the MoDataTag on a MoGraph generator object, and I am utilizing a Virtual document that has not added to the list of documents. Sorry for using the incorrect terminology, I am trying to get the MODATA_MATRIX.
This is the code that I am using.
BaseObject *matrixObj = BaseObject::Alloc(1018545); // Matrix Object if (matrixObj == nullptr) return nullptr; BaseObject *boolebj = op->GetDown(); // I know for a fact that this is a Boole object if (boolebj == nullptr) return nullptr; BaseDocument *virtualDoc = BaseDocument::Alloc(); BaseObject *clonedBooleObj = (BaseObject*)boolebj->GetClone(COPYFLAGS::NONE, nullptr); if (clonedBooleObj == nullptr) return nullptr; virtualDoc->InsertObject(clonedBooleObj, nullptr, nullptr); virtualDoc->InsertObject(matrixObj, nullptr, nullptr); BaseContainer *matrixData = matrixObj->GetDataInstance(); matrixData->SetInt32(ID_MG_MOTIONGENERATOR_MODE, 0); // Setting to Object Mode matrixData->SetLink(MG_OBJECT_LINK, clonedBooleObj); matrixData->SetInt32(MG_POLY_MODE_, 0); // Set to Surface Distribution Mode matrixData->SetInt32(MG_POLYSURFACE_SEED, 1234567); matrixData->SetInt32(MG_POLYSURFACE_COUNT, 20); matrixData->SetBool(MG_OBJECT_ALIGN, FALSE); matrixData->SetVector(ID_MG_TRANSFORM_SCALE, Vector(0)); virtualDoc->ExecutePasses(nullptr, true, true, true, BUILDFLAGS::NONE); if (virtualDoc->GetFirstObject() != nullptr) { BaseTag *tmp = matrixObj->GetTag(ID_MOTAGDATA); // This tag is not found inside of the Virtual document if (!tmp) return nullptr; GetMoDataMessage modataMsg; if (!tmp->Message(MSG_GET_MODATA, &modataMsg)) return nullptr; MoData *matrixData = modataMsg.modata; if (!matrixData) return nullptr; Int32 matrixItemsCnt = matrixData->GetCount(); MDArray<Matrix> mdmat = modataMsg.modata->GetMatrixArray(MODATA_MATRIX); Matrix* itemsMtxArray = static_cast<Matrix*>(matrixData->GetArray(MODATA_MATRIX)); maxon::Int32* flags = static_cast<maxon::Int32*>(matrixData->GetArray(MODATA_FLAGS)); for (Int32 index2 = 0; index2 < matrixItemsCnt; index2++) { if (flags[index2] & MOGENFLAG_CLONE_ON == MOGENFLAG_CLONE_ON) { } } }
This code has worked as expected with most objects but not with a Boole object.
John Thomas
-
Hi JohnThomas, thanks for following up here and providing the additional notes.
Looking at the code, since you're not explicitly showing it, question is if you're cloning, together with Boole generator also the children used as input objects. If not, then, your boolean object will simply return null.
Best, R
-
Thanks for the response.
I am getting the clone of the Boole generator along with its children and I know that its children are also being inserted into the virtual document. If on the Boole generator I have the "Create Single Object" checkbox turned on I can get the MoData from the virtual document. So the problem is getting the data from the Boole generator in the virtual document without that checkbox turned on.
John Thomas
-
Hi,
have you tried replicating your core problem - that the matrix object is returning no particles/clones for a boole object (with the connected paramter enabled) as the distribution source - in the c4d app? With all this information this now actually sounds more like a bug of the application itself. What comes to mind is that the boole object generates some cache that the matrix object cannot handle properly - i.e. reads as a null - and therefore returns no clones. This all speculation though
Cheers
zipit -
If I have my code insert a Matrix object with all of its controls set to the proper values into the c4d app active document along with a cloned version of the Boole object with its children I can get the particles/clones from the Matrix object. This is the case if the "Create Single Object" parameter for the Boole object is on or off.
If the code creates the virtual document and goes through the same procedure as the example above it does not return the particles/clones from the Matrix object unless "Create Single Object" is turned on. I have verified that the parameters of the objects inside of the virtual document are all set to the proper values and that the Boole object has its children.
John Thomas
-
Hi JohnThomas, thanks for following up here.
To speed up debugging I've created the following code below (sorry it's just python) that basically execute the same steps of your code.
# allocate a mograph matrix matrixObj = c4d.BaseObject(1018545) if matrixObj is None: return # get the Boole object from the current document (assume it's selected in the OM and it's a Boole object) boolObj = op if boolObj is None: return # clone the Boole object clonedBoolObj = boolObj.GetClone(c4d.COPYFLAGS_NONE) # set the matrix parameters accordingly matrixData = matrixObj.GetDataInstance() matrixData.SetInt32(c4d.ID_MG_MOTIONGENERATOR_MODE, 0) matrixData.SetLink(c4d.MG_OBJECT_LINK, clonedBoolObj) matrixData.SetInt32(c4d.MG_POLY_MODE_, 0) matrixData.SetInt32(c4d.MG_POLYSURFACE_SEED, 1234567) matrixData.SetInt32(c4d.MG_POLYSURFACE_COUNT, 20) matrixData.SetBool(c4d.MG_OBJECT_ALIGN, False) matrixData.SetVector(c4d.ID_MG_TRANSFORM_SCALE, c4d.Vector(0)) # allocate a temp document tmpDoc = c4d.documents.BaseDocument() if tmpDoc is None: return # insert the objects in the temp document tmpDoc.InsertObject(matrixObj) tmpDoc.InsertObject(clonedBoolObj) # execute a scene evaluation tmpDoc.ExecutePasses(None, True, True, True, c4d.BUILDFLAGS_NONE) # access the MoData data from the matrix object moData = c4d.modules.mograph.GeGetMoData(matrixObj) if moData is None: return # access the data about cloned items transformation matrixes moDataMatrixArray = moData.GetArray(c4d.MODATA_MATRIX) # check the array of matrixes if moDataMatrixArray is None: return # print each entry in the array for i in moDataMatrixArray: print i
The code is executed properly and I'm able to return the matrix of the clones even when a Boole object is used to define the distribution in the MoGraph Matrix object.
I'll try later today to come with the C++ representation and see if any issue is spotted there.
Cheers, R -
Hi JohnThomas,
I've tested also the C++ counterpart and actually everything run smooth here. Here's the code I've tested
iferr_scope; AutoAlloc<BaseDocument> tmpDoc; if (!tmpDoc) return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION); AutoAlloc<BaseObject> matrixObj(1018545); if (!matrixObj) return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION); BaseObject* boolObj = doc->GetActiveObject(); if (!boolObj) return maxon::OK; // nothing selected // assume that the currently selected object is a Boole Object BaseObject* clonedBoolObj = static_cast<BaseObject*>(boolObj->GetClone(COPYFLAGS::NONE, nullptr)); if (!clonedBoolObj) return maxon::UnexpectedError(MAXON_SOURCE_LOCATION); // set the matrix object parameters BaseContainer* matrixData = matrixObj->GetDataInstance(); if (!matrixData) return maxon::UnexpectedError(MAXON_SOURCE_LOCATION); matrixData->SetInt32(ID_MG_MOTIONGENERATOR_MODE, 0); matrixData->SetLink(MG_OBJECT_LINK, clonedBoolObj); matrixData->SetInt32(MG_POLY_MODE_, 0); matrixData->SetInt32(MG_POLYSURFACE_SEED, 1234567); matrixData->SetInt32(MG_POLYSURFACE_COUNT, 20); matrixData->SetBool(MG_OBJECT_ALIGN, FALSE); matrixData->SetVector(ID_MG_TRANSFORM_SCALE, Vector(0)); tmpDoc->InsertObject(matrixObj, nullptr, nullptr); tmpDoc->InsertObject(clonedBoolObj, nullptr, nullptr); tmpDoc->ExecutePasses(nullptr, true, true, true, BUILDFLAGS::NONE); // retrieve the MoData information upon evaluating the scene BaseTag *modataTag = matrixObj->GetTag(ID_MOTAGDATA); if (!modataTag) return maxon::UnexpectedError(MAXON_SOURCE_LOCATION); GetMoDataMessage modataMsg; if (!modataTag->Message(MSG_GET_MODATA, &modataMsg)) return maxon::UnexpectedError(MAXON_SOURCE_LOCATION); MoData *matrixMoData = modataMsg.modata; if (!matrixData) return maxon::UnexpectedError(MAXON_SOURCE_LOCATION); Int matrixItemsCnt = matrixMoData->GetCount(); MDArray<Matrix> mdmat = modataMsg.modata->GetMatrixArray(MODATA_MATRIX); for (Int i = 0; i < matrixItemsCnt; i++) { DiagnosticOutput("@", mdmat[i]); } return maxon::OK;
At this stage, I'm thinking to exclude issues with the code but rather there could be issue with your scene. Could you provide a test scene to replicate the behavior?
Thanks, R
-
Thanks for the response.
I changed my code to match the example you gave and it seems like that fixes the immediate problem I was running into. It will take some tests to verify if this covers all of the circumstances that I need it to.
I appreciate the help.
John Thomas