static circle not colliding

Official forum for the Chipmunk2D Physics Library.
Post Reply
dnldd
Posts: 32
Joined: Mon Jan 21, 2013 4:57 am
Contact:

static circle not colliding

Post by dnldd »

Hi, in my physics world I have a circle that drops from the top which is supposed to collide with whatever it encounters. I've tested this with a static polygon and this works just fine. With a static circle however no collision occurs between the two circles. I have confirmed that the static circle is indeed in the right position and has the radius I assigned it. It also has the same properties I used for the polygon which worked [sensor, elasticity, friction, group, layer, position]. What am I doing wrong here? Thanks.

Update: I used two non static circles and that works, they collide just fine. Btw the body the shape is assigned to is created by calling cpBodyNewStatic().
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: static circle not colliding

Post by slembcke »

Dunno. It's definitely not broken. The following works fine:

Code: Select all

	// static circle
	cpBody *staticCircleBody = cpBodyNewStatic();
	cpSpaceAddShape(space, cpCircleShapeNew(staticCircleBody, 100.0, cpv(10, -240)));
	
	// dynamic circle
	cpFloat radius = 15.0f;
	body = cpSpaceAddBody(space, cpBodyNew(10.0f, cpMomentForCircle(10.0f, 0.0f, radius, cpvzero)));

	shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero));
	cpShapeSetElasticity(shape, 0.0f);
	cpShapeSetFriction(shape, 0.9f);
The only possible mistake I can think of is if you set both the position of the static circle's body and the offset of the circle shape. You want to set only one or the other. If you set both, the static circle will end up at 2x the position you wanted it.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
dnldd
Posts: 32
Joined: Mon Jan 21, 2013 4:57 am
Contact:

Re: static circle not colliding

Post by dnldd »

Setting the position of the shape using the offset solves the problem, leaving the actual body at 0,0. Doing the same through cpBodySetPos() for the static body doesn't work however. The documentation suggests calling cpSpaceRehashStatic() if a static body is moved. It's not in chipmunk.h or chipmunk_private.h, Searched through the header files, still can't find the function.
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: static circle not colliding

Post by slembcke »

Did you create and add the static shape/body and then move the body? That wouldn't work. You'd need to move the static body into place first, and then add shapes to it. The moment you add a a static body to a space it becomes fixed. and you then you need to use cpSpaceReindex*() to update it. They are defined in cpSpace.h. The cpSpaceRehash*() functions were replaced about a year or so ago when updating the last major version.

http://chipmunk-physics.net/release/Chi ... alIndexing
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
dnldd
Posts: 32
Joined: Mon Jan 21, 2013 4:57 am
Contact:

Re: static circle not colliding

Post by dnldd »

Yep, that does work for circles. I positioned the body before creating the shape. That bit is resolved now, I followed the same steps for a static polygon but that doesn't work. The 'incorrect' way - creating the body & shape and then positioning the body does work. Thoughts?

Update: calling cpSpaceReindexStatic() does not resolve the problem for static polygons if you position the polygon body before creating the shape.

Sorry if this is being a drag. I've perused my code and after several tries still no dice. Looking forward to your suggestions :)
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: static circle not colliding

Post by slembcke »

Adding a shape to the space is what causes it's collision detection data to be set up. For static shapes, this is the only time it happens unless you call the cpSpaceReindex*() functions.

Can you post the code that didn't work?
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
dnldd
Posts: 32
Joined: Mon Jan 21, 2013 4:57 am
Contact:

Re: static circle not colliding

Post by dnldd »

These are the functions that create the physics bodies. add_poly_entity_to_space() is the function with the problem currently even though I am positioning the body before creating it's shape.

Code: Select all

	void  * add_poly_entity_to_space(Sandbox * sandbox, bool static_body, cpFloat mass, int vertex_number, cpVect * vertices, cpVect offset, Entity_properties * properties){
		cpBody * body = NULL;
		cpShape * shape = NULL;
		cpFloat moment = cpMomentForPoly(mass, vertex_number, vertices, offset); 
		
		if(!static_body){  
			body = cpSpaceAddBody(sandbox->space, cpBodyNew(mass, moment));
			shape = cpSpaceAddShape(sandbox->space, cpPolyShapeNew(body, vertex_number, vertices, offset));
			set_dynamic_entity_properties(shape, body, properties);
			Entity * entity = init_entity(body, shape);
			add_entity(sandbox->entity_list, entity);
			return entity;
		}
		else if(static_body){ 
			body = cpBodyNewStatic();
			cpBodySetPos(body, properties->position);
			shape = cpSpaceAddShape(sandbox->space, cpPolyShapeNew(body, vertex_number, vertices, offset));
			set_generic_entity_properties(shape, properties);
			Outline * outline = init_outline(body, shape);
			add_outline(sandbox->level_outline, outline);
			return outline;
		}
		
		return NULL;
	}

void set_generic_entity_properties(cpShape * shape, Entity_properties * properties){
		cpShapeSetSensor(shape, properties->sensor); /* is the shape a sensor or not? */
		cpShapeSetElasticity(shape, properties->elasticity); /* set the elasticity of the shape, [0, 1] */
		cpShapeSetFriction(shape, properties->friction); /* set the friction of the shape, [0, 1] */
		cpShapeSetGroup(shape,properties->group); /* set the group of the shape */
		cpShapeSetLayers(shape, properties->layers); /* set the layers of the shape, default is CP_ALL_LAYERS */
	}
	
	void set_dynamic_entity_properties(cpShape * shape, cpBody * body, Entity_properties * properties){
		set_generic_entity_properties(shape, properties);
		cpBodySetPos(body, properties->position);   /* set the position of the body */
	}

void build_level(Level * level, Sandbox * sandbox){
	 	fetch_level_trace(level->info->trace_info, sandbox);
	 	fetch_trace_properties(level->info->trace_properties_info, sandbox);
	 	outline_level(sandbox);
	 	//cpSpaceReindexStatic(sandbox->space);
		
		/* Entity_properties * properties = init_entity_properties(false, 0.9f, 0.1f, 1, CP_ALL_LAYERS, cpv(25, 25));
		
		for(size_t idx = 0; idx < sandbox->vertex_set_size; ++ idx){
			Entity * add_poly_entity_to_space(Sandbox * sandbox, cpFloat mass, int vertex_number, cpVect * vertices, cpVect offset, Entity_properties * properties)
		} */
		
		//Outline * outline = tlist_tail(&sandbox->level_outline->outline_list, list);
		Entity_properties * properties = init_entity_properties(false, 0.9f, 0.1f, 2, CP_ALL_LAYERS, cpv(625, 25));
		Entity * entity  = add_circular_entity_to_space(sandbox, false, 10.0f , 0.0f, 50.0f,  cpvzero, properties);
		level->player  = init_player("Frames/ball.png", entity);
		
		cpBodySetUserData(level->player->entity->body, level->player); 
		level->info->in_sandbox = true;
		
		//size_t layer_mask = 0;
		//set_mask(&layer_mask, LEVEL_LAYER);
		//Entity_properties * prop = init_entity_properties(false, 1.0f, 0.4f, LEVEL_GROUP, layer_mask,  cpv(640, 316));
		
		//cpBody * body = cpBodyNewStatic();
		//cpShape * shape = cpSpaceAddShape(sandbox->space, cpCircleShapeNew(body, 113.0, cpv(640, 316)));
		//set_dynamic_entity_properties(shape, body, prop);
	}

void outline_level(Sandbox * sandbox){
		Trace * trace = NULL;
		Trace * next_trace = NULL;
			
		tlist_for_each_safe(&(sandbox->level_trace->trace_list), trace, next_trace, list){	
			switch(trace->type){
				case POLYGON : { 
					cpVect polygon_centroid = cpCentroidForPoly(trace->data->vertices_data->size, trace->data->vertices_data->vertices);
					Entity_properties * polygon_properties = malloc(sizeof(Entity_properties));
					*polygon_properties = *sandbox->trace_properties;
					polygon_properties->position = polygon_centroid;
					printf(" %f, %f \n", polygon_properties->position.x, polygon_properties->elasticity);
					add_poly_entity_to_space(sandbox, true, 0.0f , trace->data->vertices_data->size, trace->data->vertices_data->vertices, cpv(0,0), polygon_properties); 
					printf("poly shape placed at -> [%f, %f]\n", polygon_centroid.x, polygon_centroid.y);
					free(polygon_properties);
				} break;
				case CIRCLE : { 
					Entity_properties * circle_properties = malloc(sizeof(Entity_properties));
					*circle_properties = *sandbox->trace_properties;
					circle_properties->position = trace->data->circle_data->center;
					printf("radius is -> %zu\n", trace->data->circle_data->radius);
					cpFloat diameter = trace->data->circle_data->radius * 2.0f;
					add_circular_entity_to_space(sandbox, true, 50.0f, 0.0f, diameter, cpvzero, circle_properties);
					printf("circle shape placed at -> [%f, %f]\n", circle_properties->position.x, circle_properties->position.y); 
					free(circle_properties);
				} break;
				case LINE_PATH : {
					cpVect * a  = &trace->data->vertices_data->vertices[0];
					cpVect * b = &trace->data->vertices_data->vertices[1];
					cpVect midpoint = segment_midpoint(a, b);
					Entity_properties * line_properties = malloc(sizeof(Entity_properties));
					*line_properties = *sandbox->trace_properties;
					line_properties->position = midpoint;
					add_segment_entity_to_space(sandbox, true, 0.0f, a, b, 0.0f, line_properties);
					free(line_properties);
				} break;
			}
		}
	}

void fetch_trace_properties(json_t * trace_properties_JSON, Sandbox * sandbox){
		json_t * sensor_JSON = json_object_get(trace_properties_JSON, SENSOR);
		json_t * friction_JSON = json_object_get(trace_properties_JSON, FRICTION);
		json_t * elasticity_JSON = json_object_get(trace_properties_JSON, ELASTICITY);
		json_t * group_JSON = json_object_get(trace_properties_JSON, GROUP);
		json_t * layer_JSON = json_object_get(trace_properties_JSON, LAYER);
		
		bool sensor = (bool) json_integer_value(sensor_JSON);
		cpFloat friction = (cpFloat) json_real_value(friction_JSON);
		cpFloat elasticity = (cpFloat) json_real_value(elasticity_JSON);
		cpFloat group = (Collision_layer) json_integer_value(group_JSON);
		
		size_t layer_size = json_array_size(layer_JSON);
		Collision_layer * layers = malloc(sizeof(Collision_layer) * layer_size);
		
		for(size_t idx = 0; idx < layer_size; ++idx){
			json_t * sub_layer_JSON = json_array_get(layer_JSON, idx);
			layers[idx] = (Collision_layer) json_integer_value(sub_layer_JSON);
		}
		
		size_t layer_mask = 0;
		for(size_t idx = 0; idx < layer_size; ++idx){ set_mask(&layer_mask, layers[idx]); } /* create a bitmask from the layers */
		printf("final value of the mask -> %zu\n", layer_mask);
		
		sandbox->trace_properties = init_entity_properties(sensor, elasticity, friction, group,  layer_mask, cpv(0,0));
		free(layers);
	}
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: static circle not colliding

Post by slembcke »

Ok, so I don't see anywhere you are modifying the static body after adding the shape.

What does happen? Are the shapes in the space, but just at the wrong position? Again, are you certain that you aren't offsetting both the body and the polygon vertexes (that would cause shapes to be at twice their intended position). What happens if you call cpSpaceReindexStatic() after setting up all of the static bodies? If that fixes the issue, then it's because the body is getting moved after setup. If it doesn't fix the issue then it's because the shapes really are in the wrong place.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
dnldd
Posts: 32
Joined: Mon Jan 21, 2013 4:57 am
Contact:

Re: static circle not colliding

Post by dnldd »

Yeah I'm not modifying the static body when it's created. I'm tracing the bodies from a level so I set their positions at the centroids/center of the trace. If you noticed, with static bodies I call set_generic_entity_properties() after setting the position of the body, which sets all other properties excluding the position, and I also have the offset set to cpvzero. With that I'm unsure how I could be setting wrong positions of the positions of the objects. I'm doing the same thing for static circles now and that works. It's not working for polygons however. I know I could just ignore this and have the bodies at 0,0 and then use the offsets to set the positions of the shapes but I thin k it's more intuitive to have the shapes where the bodies actually are. I'm unsure what I'm doing wrong here however.

Updated: like I expected, when created the shape without positioning the body at the centroid of the polygon everything worked fine. However that means the body's position remains 0,0
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: static circle not colliding

Post by slembcke »

So I'm still not exactly certain, but from your last post it sounds like your issue is that you are offsetting the polygon twice.

The vertexes you pass to cpPolyShapeNew() have the "offset" parameter added to them, and are also affected by the body's position/rotation. If you pass vertexes to cpPolyShapeNew() that define a polygon in absolute coordinates, they need to be attached to a body at (0, 0) with no rotation. If you move the body to the centroid of the polygon, the polygon shape will be shifted to 2x its intended position.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Post Reply

Who is online

Users browsing this forum: Heise IT-Markt [Crawler] and 27 guests