Rendering custom particles with Thinking Particles

On 25/04/2018 at 22:17, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   19 
Platform:   Windows  ;   Mac OSX  ; 
Language(s) :     C++  ;  XPRESSO  ;

I have zero experience with Thinking Particles so I am wondering how can I have my particles show up in a PGroup so that I can render them?

What I would like is for my particles to show up similarly to what is shown in this video at 3:05.

The person right clicks on "All" (in the Thinking Particles Settings under Particle Groups) and chooses Add. This adds a RealFlow object to the scene.

How would this RealFlow object be registered? I am currently registering my object as an OBJECT_GENERATOR, but this does not seem to work.

Any help would be much appreciated.


On 26/04/2018 at 06:34, xxxxxxxx wrote:

Hi Kent,

First of all, about the video, It's looks like the group is already here (just folded) even before he adds a group. So it's probably the object within the scene which add a new group.

Here is a CommandData to demonstrate how to add a group, create particles, then assign them to the group and finally move them.
Same things should work for an ObjectData.

#include "c4d.h"
#include <c4d_particles.h>
class TpGenerator : public CommandData
	INSTANCEOF(TpGenerator, CommandData)
	TP_MasterSystem* GetTpMasterSystem(BaseDocument* doc);
	TP_PGroup* GetRootGroup(TP_MasterSystem* master);
	virtual Bool Execute(BaseDocument* doc);
	virtual Int32 GetState(BaseDocument* doc);
TP_MasterSystem* TpGenerator::GetTpMasterSystem(BaseDocument* doc)
	if (!doc)
		return nullptr;
	BaseSceneHook* hook = doc->FindSceneHook(ID_THINKINGPARTICLES);
	if (!hook || hook->GetType() != ID_THINKINGPARTICLES)
		return nullptr;
	return static_cast<TP_MasterSystem*>(hook);
TP_PGroup* TpGenerator::GetRootGroup(TP_MasterSystem* master)
		return nullptr;
	TP_PGroupArray groups;
	Int32 gcnt = master->GetParticleGroups(nullptr, &groups, TP_GETPGROUP_ALL, false);
	if (gcnt == 0)
		return nullptr;
	TP_PGroup* grp = (TP_PGroup* )groups.GetIndex(0);
	return grp;
Bool TpGenerator::Execute(BaseDocument* doc)
	// Get the TP master system
	TP_MasterSystem* master = GetTpMasterSystem(doc);
	if (!master)
		return false;
	// Get the Root Group
	TP_PGroup* rootGroup = GetRootGroup(master);
	if (!rootGroup)
		return false;
	// Create a new group
	TP_PGroup* customGroup = master->AllocParticleGroup();
	if (!customGroup)
		return false;
	customGroup->SetName("Custom Particle Group");
	// Insert customGroup as a child of root ("All") 
	master->SetPGroupHierarchy(rootGroup, customGroup, TP_INSERT_UNDERFIRST);
	// Create 100 particles
	Int32 particleIds[100];
	if (master->AllocParticles(100, particleIds) == NOTOK)
		return false;
	// Set all particles to the group and move them
	for (auto pId : particleIds)
		master->SetGroup(pId, customGroup);
		master->SetPosition(pId, Vector(pId * 10));
	return true;

Moreover please make sure to call InitThinkingParticles before to use any TP function, the recommended way is to call it in C4DPL_STARTACTIVITY

Bool PluginMessage(Int32 id, void* data)
	switch (id)
	retun true;

Hope it helps,


On 30/04/2018 at 01:39, xxxxxxxx wrote:

Thanks Maxime. Got it working.