IParticleObjectExt interface with tyFlow returns bones but not a skin
#1
Hello.

I am developer of a renderer plugin for 3ds max. For the tyFlow, I prefer to use IParticleObjectExt() interface to get a list of particles with meshes. This works perfectly for simple shapes like sphere and triangle meshes, but I cannot get a list of skinned meshes.
For example, assume skinned fish mesh with 38 bones (skin modifier with 38 bones above a triangle mesh). tyFlow returns array of 39 particles for every fish actor: 38 of them are bone meshes, 1 is empty slot without geometry.
The same scene without "Enable particle interface" in tyFlow main settings is rendered OK.

Mesh** iPOmesh;

ObjectState os = node->EvalWorldState(timeT);
IParticleObjectExt* iPO = GetParticleObjectExtInterface(os.obj);

iPO->UpdateParticles(node, timeT);
int iPOnum = iPO->NumParticles(); // 39 for single fish

for (int j = 0; j < iPOnum; j++)
{
  int bi = iPO->GetParticleBornIndex(j);
  TimeValue age = iPO->GetParticleAgeByIndex(j);
  if (age >= 0)
  {
    iPOmesh[j] = iPO->GetParticleShapeByIndex(j); // 38 bone meshes and NULL for index #0
    INode* mnd = iPO->GetParticleGroup(j); // null
    iPOtm[j] = iPO->GetParticleTMByIndex(j);
    // ...
  }
}


What is going wrong? 
I can include the scene, if needed. But it requires the Dali Renderer: Dali Renderer 1.5.53
.rar   
bug.rar (Size: 1.67 MB / Downloads: 92)
[Image: 3.png][Image: 2.png][Image: 1.png]
  Reply
#2
Please use the tyParticleObjectExt interface instead. I've attached it here.


Attached Files
.h   tyParticleObjectExt_v2.h (Size: 22.23 KB / Downloads: 50)
  Reply
#3
Ok, thank you!

Is this interface available somewhere ? I would like to update to latest version if this interface changes.
Some plugin developers include their public interface with installation media.
  Reply
#4
Not currently...I provide it to developers when requested.
  Reply
#5
Hello.

I have moved query code to tyParticleInterface.
The only changed in output from tyFlow is that every fish now contains 38 objects instead of 39 before. Every of 38 objects is a bone, not a skin. So 2 questions:

1. tyFlow::tyVector<tyFlow::tyInstanceInfo>* tyInstancesSE = iTF->CollectInstances(scatterNode, tyFlow:Big GrinataFlags::mesh, timeS, timeE, _T("dali"));

Should I delete tyInstancesSE after use?
If I try to call
delete tyInstancesSE;
then it crashes deleting unknown memory block. Note that there are no bits pluginMustDelete set anywhere and I do not touch any internal data. The delete operator recurrently calls delete on internal arrays and crashes somewhere.

2. What should I change in the scene to render the skin, not the bones? I have tried everything without success. If "Enable particle interface" is set, then tyParticleInterface is available and returns bones, not skin.
If checkbox is off, then tyParticleInterface is not available and tyFlow returns (using GetRenderMesh) correct skinned single triangle mesh with all fishes at once that is not appropriate.

Mikhail.
  Reply
#6
Oh sorry, I forgot to mention, since your renderer name isn't hard-coded as an approved renderer, you'll need to call CollectInstances with the plugin name "renderer" to get instances, not "dali" in this case - with just "dali" you're getting regular particle data which only included typical transforms/meshes, not deforming meshes.

As for deleting tyInstancesSE...are you sure it's not a bug in your code? You're not accidentally deleting it twice or something? The function I return it in is akin to:

Code:
tyFlow::tyVector<tyFlow::tyInstanceInfo>* collectInstances(...)
{
    auto arr = new tyFlow::tyVector<tyFlow::tyInstanceInfo>();
    //...do stuff
    return arr;
}

So it should be a unique and valid pointer that's returned, that passes ownership to the caller. Hard to imagine why a crash is occurring when it's deleted...
  Reply
#7
[Image: crash.png]

This is a test example - first line allocates instances, second line deletes them.
  Reply
#8
Does the crash occur in a Release build as well?
  Reply
#9
I will try Release now within few minutes, but previously, there was no difference.
The reason is clear, I have seen this already in other projects. The memory block was allocated with one version of CRT, but is deallocating with different version.
See the picture. Starting from some version of tools, Microsoft VC adds 8 bytes for arrays, allocated with new[]. So pointer to array itself is shifted by 8 bytes comparing to memory block. 
What is the version of VC, Windows SDK used for tyFlow ?

[Image: b1.png]

To prevent from this issue, I use declarations like this:

class iMyPublicClass
{
protected:
  virtual ~iMyPublicClass() {} // prevent from direct calls

public:
  virtual size_t AddRef() = 0;
  virtual size_t Release() = 0;      // use this call to release object

public:
  // functionality
};


So allocating and deallocating will be in same place (library) using same memory manager.

In Release it passes wrong pointer also, but memory manager does not crash. It just ignores this memory block and leaks it.

BTW, _T("renderer") do not help. It still returns bones instead of skin. Something goes wrong.
  Reply
#10
The vector of tyInstanceInfo contains
- a vector of tyInstance, that contains
-- vector of Matrix3
-- vector of tyParticleUVWInfo

deleting of memory block for arrays of Metrix3 or tyParticleUVWInfo is OK.
deleting of memory block for arrays of tyInstance or tyInstanceInfo results in crash.

both Matrix3 and tyParticleUVWInfo are simple structs without complex destructor, so arrays for them do not need to keep a size of array at beginning of memory block. This causes in no shift during memory free.

The arrays for tyInstance and tyInstanceInfo must keep size in beginning of memory block because both classes are complex with destructors. This causes in 8 byte shift during memory free.
Freeing of arrays can be done in different ways and this depends on version of VC tools.

There would be good to add
void tyFreeInstances(tyVector*) = 0;
in addition to
tyVector* tyCollectInstances() = 0;

so tyFlow would delete memory using same VC tools as for allocation.
  Reply
#11
Thanks for the extra info - I was not aware of the padding happening to arrays allocated with new (and the issue hasn't come up before in other renderer's implementation of the interface, so it went unchecked). I will add the release functions to the interface. Let me know the version of Max you're using for your tests and I'll send you a build of tyFlow with that function call, as well as the updated interface.
  Reply
#12
I am using 2021 version of max for the tests.
Any version from 2018 to 2024 is appropriate.
  Reply
#13
Try this build (call "ReleaseInstances" on the pointer returned by CollectInstances, instead of deleting it):


Attached Files
.h   tyParticleObjectExt_v2.h (Size: 22.55 KB / Downloads: 43)
.zip   tyFlow_2020.zip (Size: 48.63 MB / Downloads: 127)
  Reply
#14
Thank you very much!

This new version fixes both issues:
- no crashes now;
- the skin is in output and no bones.

Little remark. Warnings in header file:

1>C:\Compile\Dali Renderer\DaliRenderer3dsMax\tyFlow\tyParticleObjectExt_v2.h(131,3): warning C4309: 'initializing': truncation of constant value
1>C:\Compile\Dali Renderer\DaliRenderer3dsMax\tyFlow\tyParticleObjectExt_v2.h(131,29): warning C4369: 'tyFlow::pluginMustDelete': enumerator value '-2147483648' cannot be represented as 'unsigned int', value is '2147483648'
1>C:\Compile\Dali Renderer\DaliRenderer3dsMax\tyFlow\tyParticleObjectExt_v2.h(246,16): warning C4244: 'argument': conversion from 'double' to 'size_t', possible loss of data
  Reply
#15
Glad it's working, thanks for your help troubleshooting that issue.

As for the warnings, here's a modified header which should suppress those ones.


Attached Files
.h   tyParticleObjectExt_v2.h (Size: 22.57 KB / Downloads: 48)
  Reply


Forum Jump: