Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passing an entity as a pointer (Question) #238

Open
ghost opened this issue Apr 23, 2020 · 11 comments
Open

Passing an entity as a pointer (Question) #238

ghost opened this issue Apr 23, 2020 · 11 comments

Comments

@ghost
Copy link

ghost commented Apr 23, 2020

Hi @alecthomas , great library!

I have a scenario in one of my projects, where I need to pass an entity or a component to the physics engine (bullet) as a pointer (void*).

When I am trying to receive the pointer back, if I cast it to an entity for example, I can't access any of the components because It gives me some error like the id is invalid or if I am trying to use the id it tells me that the index is smaller than the component mask (or something close to this).

Is there any other way to pass an entity as a pointer and access it in some other part of the code without being invalid?

Thanks.

@alecthomas
Copy link
Owner

Can you show me the code? void* will almost certainly not work directly, if that's what you're suggesting.

@ghost
Copy link
Author

ghost commented Apr 24, 2020

Hi, I don't know if you know the bullet physics library but in it you can attach to an collision object something called user pointer which is of type void*. This scenario helps you when you have a collision and you want to retrieve that object and do something with it, of course you will have to cast it to your object type.

How I can send a new created entity (ex: auto entity = _ecs.entities.create(); ) to that pointer, without being invalid when I want to retrieve it back.

Thanks.

@alecthomas
Copy link
Owner

Ah, okay. You'll probably want to use the numeric id of the entity instead, as Entity objects are transient values.

@alecthomas
Copy link
Owner

Also if that still doesn't help, first rule of bug reports is to provide as much information as possible: sample code, error messages, etc.

@ghost
Copy link
Author

ghost commented Apr 24, 2020

Ok, thanks @alecthomas I will come with the back with the code and the messages.

@ghost
Copy link
Author

ghost commented Apr 24, 2020

Hi @alecthomas, I got an working solution:

I send the id to the physics in this way:
auto body = new btRigidBody(info);
body->setUserIndex(entity.id().id()); // this is just an int

And I get it in this way:
auto id = _ecs.entities.create_id(hit.m_collisionObject->getUserIndex());
auto entity = _ecs.entities.get(id);

I did not know about that create_id method which is very helpful.

Can I do a pull request with an operator uint64_t for the Entity::Id? it will be nice to avoid this entity.id().id() and use just entity.id() instead.

Thanks.

@makiolo
Copy link

makiolo commented May 3, 2020

I am not sure, is a question: Why you use "uint64_t" instead "Entity::Id" ? Both looks copyable, and second case your call is more readable: "entity.id()" also you don't need use "create_id", you can use "get" directly.

@morphogencc
Copy link

Sorry to hop onto this thread, but I think my issue is similar -- I'm using NVIDIA's PhysX as my physics engine. The engine leaves rigid body actors with a field void* userData that can be used to connect PhysX engine objects with user application objects. documentation is here.

Along the same lines as @iamAdrianIusca , I'm trying to link an entity to this void* pointer. Bullet supports setUserIndex which stores an int, so I think an entity.id() makes sense -- but is there any way that I can store a pointer that links back to an entity as well? This would be the same as bullet's setUserPointer function.

It seems like most of EntityX's types are not pointers, but are essentially custom handles, or static IDs that I can't link a pointer to.

@alecthomas
Copy link
Owner

That is 100% correct. Assuming your machine word size is 64-bit you could store the Entity ID in the void* directly.

@morphogencc
Copy link

Ah, got it!

So I should store the integer ID number into the pointer via:

physx_object->userData = (void*)(entity.id().id());

It can't be dereferenced like a true pointer, but can be brought back with:

auto entity = _ecs.entities.get((uint64_t)(physx_object->userData));

thanks!

@makiolo
Copy link

makiolo commented Feb 2, 2021

Nice morphogencc, I do something different (more complex maybe), and works with 32 bits.

struct IntrospectionComponent : public entityx::Component<IntrospectionComponent>
{
	std::string type;
	entityx::Entity::Id id;
};

Is a component for know, who am I ? (introspection).

In your "PhysX"->userData you can write something like this:

	void set_userdata(PhysXSomeone& node, IntrospectionComponent& introspection)
	{
	    node->userData = (void*)&introspection;
	}

You need a system for fill introspection values (only one time, I use PhysicsDescription like "flag component"):

	es.each<Transform, PhysicsDescription, IntrospectionComponent>([&](entityx::Entity entity, Transform& transform, PhysicsDescription& physics_desc, IntrospectionComponent& introspection)
	{
		introspection.id = entity.id();
		bool is_projectile = entity.has_component<ProjectilComponent>();
		if (is_projectile)
		{
			introspection.type = "projectil";
		}
		else  // is enemy
		{
			introspection.type = "insect";
		}

		entity.assign<plague::PhysicsComponent>(.......);  // create physics using "PhysicsDescription"
		entity.component<PhysicsDescription>().remove();
	});

Yo can recover entity:

        auto obj = static_cast<plague::IntrospectionComponent*>(node_physx->userData);
        auto entity = entities.get(obj->id);

And Finally, when I have collisions, for example, now I can read your userData:

		auto objA = static_cast<plague::IntrospectionComponent*>(physx_node->userData);
		auto objB = static_cast<plague::IntrospectionComponent*>(physx_node->userData);

		if (objA->type == "projectil" && objB->type == "insect")
		{
			// do something
		}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants