Inconsistent Matrix Behavior



  • Hello,

    I had previously posted here about accessing a virtual matrix object. I am able to successfully get access to the MoData from the matrix by creating a Matrix set to Object Mode in a virtual document and linking a cloned object to it. Moving along with that process I am now trying to get the MoData from a Boole object utilizing the same process with this code.

            BaseContainer *matrixData = matrixObj->GetDataInstance();
    	matrixData->SetInt32(ID_MG_MOTIONGENERATOR_MODE, 0);
    	matrixData->SetLink(MG_OBJECT_LINK, cloneObj);
    	matrixData->SetInt32(MG_POLY_MODE_, 0);
    
    	virtualDoc->ExecutePasses(nullptr, true, true, true, BUILDFLAGS::NONE);
    
    	BaseTag *tag = matrixObj->GetTag(ID_MOTAGDATA); 
    	if (tag == nullptr)
    		return maxon::NullptrError(MAXON_SOURCE_LOCATION);
    	
    	GetMoDataMessage msg = GetMoDataMessage();
    	tag->Message(MSG_GET_MODATA, &msg);
    	
    	MoData *md = msg.modata;
    	
    	if (md == nullptr)
    		return maxon::NullptrError(MAXON_SOURCE_LOCATION);
    
    
    	MDArray<maxon::Matrix> mdmg = md->GetMatrixArray(MODATA_MATRIX);
    

    Post.png
    This setup is working inside of the live document and does not work inside of the virtual document because no tag for the MoTagData is being created.

    If I have the "Create Single Object" checkbox turned on I can successfully generate the tag for the MoData inside of my virtual document, it doesn't matter for the live document.

    Can anyone tell me why this behavior is inconsistent between this two circumstances? Any help would be appreciated.

    John Thomas



  • 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.). So MoData 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:

    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 the MoDataTag 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


Log in to reply