Importing morph problem
-
hi,
it's not clear in your code what is
model_points
I creating this example. It will pick the active object and create a morph tag with a morph to match the object next to it.
I've included the use ofParallelFor
but it's not always benefict to parallel things.But instead of loading this to a morph tag, you may want to load the animation to a PLA track ?
(if I'm correct that it's to load MMD animation)BaseObject* target = doc->GetActiveObject(); if (target == nullptr) return maxon::NullptrError(MAXON_SOURCE_LOCATION); if (!target->IsInstanceOf(Opolygon)) return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION); BaseObject* source = target->GetNext(); if (source == nullptr) return maxon::NullptrError(MAXON_SOURCE_LOCATION); if (!source->IsInstanceOf(Opolygon)) return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION); // some checks const Int32 sourcePointCount = ToPoly(source)->GetPointCount(); const Int32 targetPointCount = ToPoly(target)->GetPointCount(); const Matrix sourceMg = source->GetMg(); const Matrix TargetMg = target->GetMg(); const Matrix InvTargetMg = ~TargetMg; const Matrix pointTransfert = InvTargetMg * sourceMg; if (sourcePointCount != targetPointCount) return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION, "source and target doesn't have the same point number"_s); const Vector* padrSource = ToPoly(source)->GetPointR(); CAPoseMorphTag* morph_tag = CAPoseMorphTag::Alloc(); if (morph_tag == nullptr) return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION); target->InsertTag(morph_tag); morph_tag->SetParameter(ID_CA_POSE_POINTS, true, DESCFLAGS_SET::NONE); morph_tag->InitMorphs(); // Create Base Morph morph_tag->ExitEdit(doc, true); CAMorph* base_morph = morph_tag->AddMorph(); if (base_morph == nullptr) return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION, "couldn't create the base morph"_s); base_morph->Store(doc, morph_tag, CAMORPH_DATA_FLAGS::POINTS); morph_tag->UpdateMorphs(); // Create a New morph morph_tag->ExitEdit(doc, true); CAMorph* newMorph = morph_tag->AddMorph(); newMorph->SetName("first morph"_s); newMorph->Store(doc, morph_tag, CAMORPH_DATA_FLAGS::ASTAG); CAMorphNode* mnode = newMorph->GetFirst(); // Set the mode for the morph as CAMORPH_MODE::ABS so we can defined the point position in absolute mode. newMorph->SetMode(doc, morph_tag, CAMORPH_MODE_FLAGS::ALL | CAMORPH_MODE_FLAGS::EXPAND, CAMORPH_MODE::ABS); // Check if point information is preset. if (mnode->GetInfo() & CAMORPH_DATA_FLAGS::POINTS) { mnode->SetPointCount(sourcePointCount); /* for (Int32 pointIndex = 0; pointIndex < sourcePointCount; pointIndex++) { // we need to retrieve the point position in the target's space (source local -> global -> target local) Vector pointPos = pointTransfert * padrSource[pointIndex]; mnode->SetPoint(pointIndex, pointPos); } */ // you can use ParallelFor if you need speed but that could be worst depending of the point number. maxon::ParallelFor::Dynamic(0, sourcePointCount, [&mnode, &pointTransfert, &padrSource](const Int32 pointIndex) { Vector pointPos = pointTransfert * padrSource[pointIndex]; mnode->SetPoint(pointIndex, pointPos); }); } newMorph->SetMode(doc, morph_tag, CAMORPH_MODE_FLAGS::ALL | CAMORPH_MODE_FLAGS::COLLAPSE, CAMORPH_MODE::AUTO); morph_tag->UpdateMorphs(); morph_tag->Message(MSG_UPDATE);
Cheers,
Manuel -
-
hi,
does the provided code works for you ?
i don't know how to read those file and what they contains, specially what they call morph may not be the equivalent of our morph.Cheers,
Manuel -
hi,
I read the code you provided, but I cannot use it.
I want to read the morph data that I want to import from the file, and then write it to the tag instead of importing it from another object.The morph of the MMD model is indeed different from the c4d. I just want to import the morph of the MMD model.
The file records the point index (I have ensured that these points exist in the model.) and the point displacement (this is a Vector32, which represents the displacement of the deformation point, and the final position of the point is "point position + point displacement").I noticed that you used "CAMorphNode". I don't know how to use it. Can you explain it in detail? I can't understand the document.
When I try to use "CAMorphNode", I don't know if the point index recorded in it is the point index of the model.Thank,
AiMiDi -
hi,
Taking the next objet was just to have a source of points/vectors. It can be any kind of source as long as you know if the vector are relative or absolute.
You are saying that the morph vector are relative to the point position so you need to change the last flag of this line
fromCAMORPH_MODE::ABS
toCAMORPH_MODE::REL
newMorph->SetMode(doc, morph_tag, CAMORPH_MODE_FLAGS::ALL | CAMORPH_MODE_FLAGS::EXPAND, CAMORPH_MODE::REL);
That way, the vector you pass will be added to the current point position.
You got our manual about CAMorphNode
It's an object stored specially useful if the morph tag is in Hierarchy mode.The point are the same, that's why you need to set the mode.
First you need toEXPAND
and once you are done, you need toCOLLAPSE
so only delta will be stored in the tag.let me know if it's still not clear
Cheers,
Manuel -
hi,
I modified it based on the code you provided, and it works.
I use multi-threading, but sometimes it will get stuck when calling multi-thread (console display handles are not equal). I don't know how to solve this problem.
And if I use optimization commands, it will destroy morph, what should I do.Thank,
AiMiDi -
hi,
it's a bit hard to tell without more informations.
Could you provide an example of what's going on ? Code, Workflow, does Cinema 4D hangs, crash ? What is your expected result ?
About the optimization command, of course optimizing the mesh may reduce the point number or the order of points.
But what do you call "destroy morph" ? Are only the points that are optimized that get wrong ? Does every points get wrong ?
Is it only the geometry or the uvs ?cheers,
Manuel -
hi,
The problem with multithreading is this:
The cpu is still occupied, but the utilization rate is very low, and the thread does not exit.
When there is a problem, the console often has this:Exception filter was modified, handler is 0x00007ffe2ff9f430 but should be 0x00007ffe2e4f7320
The imported model is available, but after I use the optimization command,
doc->SetSelection(model); doc->SetMode(Mpolygons); BaseSelect* all_select = model->GetPolygonS(); all_select->SelectAll(0, model->GetPolygonCount() - 1); CallCommand(14039); all_select->DeselectAll(); doc->SetMode(Mmodel);
it became as shown in the figure.
The optimization command may change the index of the point, how do I get these changes, I noticed that some messages will be sent after the change, and how to use it.
Thank,
AiMiDi -
hi,
sorry for the delay, we have our internal summit and we have a bit less time this week to work on support cases.
it's a normal result, if you are changing the mesh, than the morph cannot convert the data.
You need to import all your mesh. combine them into one and optimize the mesh and than create your morph.For that you need to track your points from what mesh they are coming from and what was the index on your morph.
To track the points, you can create and add a customDataTag that will store information for each points. (the orginal mesh name and the index from that mesh).
You can create one tag on each mesh part and when you combine all the parts, our core system will combine them. (you can implement the "add" function in your customDataTag to tell how you want to data to be combined)You can read information about CustomDatTag in our manual
We also have examples in our sdk you can found them on githubI will try to test it myself.
Cheers,
Manuel -
Thanks,
I will try it myself, thank you for your help.Thank,
AiMiDi -
Hello @AiMiDi,
without any further feedback or questions, we will consider this topic as solved by Wednesday and flag it accordingly.
Thank you for your understanding,
Ferdinand