Problem with OBB

Posted By: 3run

Problem with OBB - 04/14/15 20:42

I've noticed some collusion problems recently in my several prototypes, and as far I as know, I'm not the only one facing exactly the same problem, so I've decided to report this as a bug, cause it's seems to be one.

I don't really know what it's related to, but moving entity get's stuck while moving close to the walls and edges. I also noticed that it get's stuck in those lines (tessellation, on the screen below), maybe it's related to problems with block normals, I'm not sure.


Anyway, I've made a simple demo, that shows the problem and uploaded a video:
Youtube video

On the video you can see the input so you are aware that I'm not moving against the cube, but just trying to get straight ahead near by the cube. You can also notice that 'AUCH' appearing in the upper left corner, that text is triggered by the BLOCK event. GLIDE flag is SET in the 'c_move'.

Here you can get and test the small demo I've made to show the bug:
Download link


Greets
Posted By: Superku

Re: Problem with OBB - 04/14/15 21:03

I have not tested the demo yet but I can confirm having similar problems in the past, in 3d or my sidescrolling game - which is why I changed all WED blocks from

Code:
aa| |
__|_|x
____|


to
Code:
aa| |
__| |x
__|_|


so the player would not randomly get stuck at the x position when falling down. Obviously I doublechecked my code back then and figured it would be some precision problem with the collision detection and the block surfaces (and corresponding normals) in question.
As a workaround I chose a system which keeps the player's bounding box away from the walls (+ ground and ceiling) at all times but obviously this is a little harder to do in 3d (esp. on let's say 6 axis movement, like in a space fighting game).
Posted By: alibaba

Re: Problem with OBB - 04/15/15 00:20

Yeah, perfectly describes my problem I am fighting currently!
Posted By: jcl

Re: Problem with OBB - 04/16/15 14:16

We also had observed such problems from time to time. The reason was normally a not large enough bounding box so when you frontally run into a wall, collision detection stopped the object a little too late when the hull already penetrated the wall a bit. If you then move the object sidewards, it gets stuck at every little nook and cranny inside the wall.

Try to widen the bounding box - does it solve the problem?
Posted By: 3run

Re: Problem with OBB - 04/16/15 16:39

When I first faced this problem, I was using 32x32x64 bounding box, but in the demo I've uploaded it's pretty small, only 14x14x14. I just scaled it up till 32x32x32, but unfortunately problem is still there.

BTW in the demo which I've uploaded (on the video as well) you can see that I'm not even walking towards the wall. Entity placed next to the wall and moves UP and DOWN (from top-down perspective), so there is no penetration at all.

Few screens:
Quote:
WED setup:

Running demo with scaled box (32x32x32):



Greets
Posted By: sivan

Re: Problem with OBB - 04/16/15 20:10

I had similar problems with map entities, and even with models converted from map entities having polygonal collision. In MapBuilder player test I solved it by using an additional forward c_trace that if hits something, movement is prevented. Bigger collision box could result in ugly gameplay behaviour. Search for "// allow no bad collision with small polygon models" section:

Code:
action PlayarTest01_Wizard_Walk()
{
	//---------------------------------
	// events
	
	my.event = PlayarTest01_Wizard_Hit;
	my.emask |= ENABLE_IMPACT;   
 	
//	wait(3);
//	printf("player init");
 	
 	//--------------------------------- 	
	// set z always by c_tracing
	
	VECTOR vFeet;
	vec_for_min(vFeet,me);
	vec_mul(vFeet,my.scale_x);
	
	c_trace(vector(my.x, my.y, 5000.0), vector(my.x, my.y, -1000.0), IGNORE_ME | IGNORE_CONTENT | IGNORE_PASSABLE | USE_POLYGON | USE_BOX);		// | USE_BOX for smoother ground detection
	if (HIT_TARGET)
		{
			my.z = hit.z - vFeet.z;
		}
	
	//---------------------------------
	// boundary box

 	wait(1);
	my.eflags |= FAT | NARROW; 				// set both flags to prevent automatic recalculation on scale changes
	vec_set(my.min_x,vector(-8,-8, -3)); 	// better step if xy are lower and z is higher - but worse small wall detection
	vec_set(my.max_x,vector(16, 8, 32));	// better step if x is lower
//	vec_set(my.max_x,vector(25,8,30));		// no wall penetration
	wait(1);	
	
	//---------------------------------
	// material settings
	
	my.ambient = 12;	// 0..100, 10 = 25.5 in 0..255
	
//	my.material = mtl_model;
	
	// normalmapped
	playermat = mtl_create();
	vec_set(playermat.ambient_blue, mat_model.ambient_blue);
	vec_set(playermat.diffuse_blue, mat_model.diffuse_blue);
	vec_set(playermat.specular_blue, mat_model.specular_blue);
	vec_set(playermat.emissive_blue, mat_model.emissive_blue);
	playermat.power = mat_model.power;
	playermat.albedo = mat_model.albedo;
	effect_load(playermat, "sc_obj_modelN_MB.fx");					// the correct normal mapping shader okay with scsm or without
	
	my.material = playermat;
	
	//---------------------------------
	// flags
	
// set FLAG2 to make the wizard detectable by c_scan, 
// and store the wizard pointer in its own CREATOR skill 
// so that the detecting entity knows its enemy	
	set(my, FLAG2 | SHADOW);
		
   my.CREATOR = me;         
	my.STATE = 1;
	
//	printf("player ready");
	
	//---------------------------------
	
	var distance 			= 0;
	var jump_in_progress = 0;
	var actual_gravity	= 0;	
	
	while (UIMode==(var)UIMODE_PLAYTEST01)
	{
		//-----------------------------------------------------------	
		// state 1: walking 
		if (my.STATE == 1)
		{
			//-----------------------------------------------------------
			
			my.ANIMATION %= 100;
			
			//-----------------------------------------------------------
			// rotate the entity with the arrow keys     
			
			if ((window_focus) && (mouse_valid))
				{
					my.pan += (key_a-key_d)*5*time_step;
					
//					// or rotate with collision to avoid going through polygon thin walls at mesh borders
//					var rot_angle = (key_a-key_d)*5*time_step;
//					c_rotate(me, vector(rot_angle, 0, 0), IGNORE_PASSABLE);		
				}
			
			//-----------------------------------------------------------
			// move the entity forward/backward with the arrow keys
			
			if (jump_in_progress == (var)0)										// keep previous distance during jump
				{
					distance	= 0;
						
					if ((window_focus) && (mouse_valid))
						{
							distance = (key_w-key_s) * time_step;														
							
							if ((key_shift) && (distance > 0))					// only forward
								{
									distance *= play01_runspeed;
								}
							else if ((key_ctrl) && (distance != (var)0))		// moving
								{
									distance *= play01_crawlspeed;																		
								}
							else
								{
									distance *= play01_walkspeed;
								}
							
							if (key_ctrl)
								{
									// smaller bbox
									vec_set(my.min_x,vector(-8,-8, -12)); 
									vec_set(my.max_x,vector(16, 8, 20));	
								}
							else
								{
									// standard bbox
									vec_set(my.min_x,vector(-8,-8, -3)); 	
									vec_set(my.max_x,vector(16, 8, 32));	
								}
						}
				}
			
			// simple move
//			c_move(me, vector(distance,0,0), NULL, GLIDE | IGNORE_PASSABLE );
			
			//-----------------------------------------------------------
			// prevent under water movement
			
			VECTOR temp_vec;
			vec_set(temp_vec, vector(distance, 0, 0));
			vec_rotate(temp_vec, my.pan);
			vec_add(temp_vec, my.x);
			
			VECTOR temp2_vec;
			vec_set(temp2_vec, vector(temp_vec.x, temp_vec.y, temp_vec.z - 1000.0));
			
			c_trace(temp_vec, temp2_vec, IGNORE_ME | IGNORE_PASSABLE | USE_POLYGON);		// | USE_BOX for smoother ground detection
			
			var water_hit = -1000;
			if (HIT_TARGET)
				{
					water_hit = hit.z;
				}
			
#ifdef PLAY01_DEBUG			
			// debug - ok
			draw_line3d(temp_vec, NULL, 100);
			draw_line3d(temp2_vec, COLOR_WHITE, 100);
#endif			
			//-----------------------------------------------------------
			// allow no bad collision with small polygon models
			
			vec_set(temp_vec, vector(my.max_x*sign(distance),0,0));		// *sign(distance) needed to check forward or backward move
			vec_rotate(temp_vec, my.pan);
			vec_add(temp_vec, my.x);
			temp_vec.z += my.min_z;
			
//			vec_set(temp2_vec, vector(my.x, my.y, my.z+my.min_z));
			vec_set(temp2_vec, vector(my.min_x*sign(distance),0,0));		// *sign(distance) needed to check forward or backward move
			vec_rotate(temp2_vec, my.pan);
			vec_add(temp2_vec, my.x);
			temp2_vec.z += my.min_z;
			
			var polygon_hit = c_trace(temp2_vec, temp_vec, IGNORE_ME | IGNORE_PASSABLE | USE_POLYGON);				
			
#ifdef PLAY01_DEBUG				
			// debug - ok
			draw_line3d(temp_vec, NULL, 100);
			draw_line3d(temp2_vec, COLOR_RED, 100);
#endif			
			//-----------------------------------------------------------
			// gravity						
			
			var move_z	= 0;			
			
			// ground
			var grounddist = c_trace(my.x, vector(my.x, my.y, my.z-10000), IGNORE_ME | IGNORE_PASSABLE);
			
			// acceleration - if ground is lower or jumping
			if((grounddist + vFeet.z > 0) || (actual_gravity < 0))
				{					
					actual_gravity += play01_gravity_force * time_step;
					
					// apply acceleration
					move_z -= minv(actual_gravity * time_step, grounddist + vFeet.z);
				}
			else
				{
					actual_gravity = 0;
					
					move_z = (hit.z - vFeet.z) - my.z;
//					move_z -= grounddist + vFeet.z;
				}
			
			// jump by acceleration
			if ((window_focus) && (mouse_valid))
				{
					if(key_space)					
						{							
							// allow jump
							if(grounddist + vFeet.z - minv(actual_gravity * time_step, grounddist + vFeet.z) == (var)0)
								{
									actual_gravity = -play01_jumpspeed;
									jump_in_progress = 1;
								}
						}
				}
			
			my.z += move_z;
			
			//-----------------------------------------------------------
			// do move if allowed
			
			if (
					(water_hit > -GetMapTileSize()) 
					&& 
					(
						(polygon_hit > (var)GetMapTileSize() * 0.71)							// polygone detection HIT_TARGET and it is far enough
						||
						(polygon_hit <= (var)0)														// no polygon detection HIT_TARGET
					)
				)
				{
					c_move(me, vector(distance,0,0), nullvector, IGNORE_PASSABLE);		// | USE_POLYGON	| GLIDE
				}
						
			//-----------------------------------------------------------	
			// adjust entity to the ground height, using a downwards trace
			
//			c_trace(my.x, vector(my.x, my.y, my.z-1000), IGNORE_ME | IGNORE_PASSABLE);
//			my.z = hit.z - vFeet.z; 																				// always place player's feet on the ground
			
//			// smoother on-stairs movement, slower (but still ugly) falling - some underground placement errors... XXX
//			c_trace(vector(my.x, my.y, my.z), vector(my.x, my.y, my.z - 1000.0), IGNORE_ME | IGNORE_PASSABLE);		// | USE_BOX for smoother ground detection
//			if (HIT_TARGET)
//				{
//					my.z = smooth(hit.z - vFeet.z, 0.50);
//				}
			
			//-----------------------------------------------------------		
			// animate the entity    
			
//			my.ANIMATION += 2*distance;
//			ent_animate(me,"walk",my.ANIMATION,ANM_CYCLE);
			
			var anim = sign(distance);					// forward or backward move
			
			ent_animate(me,NULL,0,0); 					// reset all bones
			
			if (jump_in_progress)												// jump
				{
					my.ANIMATION += 7*time_step;
					ent_animate(me, "jump", my.ANIMATION, NULL);		
					if (my.ANIMATION >= (var)100)
						{
							jump_in_progress = 0;
							my.ANIMATION %= 100;
						}					
				}
			else if ((key_shift) && (anim))									// run
				{
					my.ANIMATION += 10*time_step*anim;
					ent_animate(me, "run", my.ANIMATION, ANM_CYCLE);
					my.ANIMATION %= 100;
				}
			else if ((key_ctrl) && (anim))									// crawl, move
				{
					my.ANIMATION += 4*time_step*anim;
					ent_animate(me, "crawl", my.ANIMATION, ANM_CYCLE);
					my.ANIMATION %= 100;
				}
			else if ((key_ctrl) && (!anim))									// crawl, no move
				{
					ent_animate(me, "crawl", my.ANIMATION, NULL);
				}
			else if (anim)															// walk
				{
					my.ANIMATION += 10*time_step*anim;
					ent_animate(me, "walk", my.ANIMATION, ANM_CYCLE);
					my.ANIMATION %= 100;
				}
			else																		// no move, no jump, no crawl
				{
					my.ANIMATION += 3*time_step;
					ent_animate(me, "lstand", my.ANIMATION, ANM_CYCLE);
					my.ANIMATION %= 100;
				}
			
			ent_animate(me, "wpose", my.ANIMATION, ANM_ADD);			
			
			//-----------------------------------------------------------	
			// key e pressed -> go to state 2
			
			if ((key_e) && ((window_focus) && (mouse_valid)))			
				{ 
					my.ANIMATION = 0;
					my.STATE = 2;
				}
			
			//-----------------------------------------------------------
		}
		
		//-----------------------------------------------------------
		//-----------------------------------------------------------
		// state 2: casting a spell 
		if (my.STATE == 2) 
		{
//			my.ANIMATION += 8*time_step;
//			ent_animate(me,"attack",my.ANIMATION,0);
//			
//			if (my.ANIMATION > 100) 
				{ // create the spell and go to state 3
	//				ent_create("spell.mdl",vector(my.x,my.y,my.z+20), PlayarTest01_Spell_Fly);
					
					VECTOR vGunEnd;
					vec_for_vertex(vGunEnd,my,5035);
					ent_create("spell.mdl",vGunEnd, PlayarTest01_Spell_Fly);
					
					my.ANIMATION = 0;
					my.STATE = 3;
				}
		}  
		
		//-----------------------------------------------------------
		//-----------------------------------------------------------
		// state 3: waiting for key release 
		if (my.STATE == 3) 
		{
			if (!key_e) 
				{
//					my.ANIMATION += 3*time_step;
//					ent_animate(me,NULL,0,0); 	
//					ent_animate(me,"lstand",my.ANIMATION,0);
//					ent_animate(me,"reload",my.ANIMATION,ANM_ADD);
//					
//	//				my.ANIMATION += 8*time_step;
//	//				ent_animate(me,"reload",my.ANIMATION,0);
//					
//					if (my.ANIMATION > 100) 
						my.STATE = 1; 											// when key was released, back to state 1
				}
//			my.STATE = 1; 														// fast shooting test
		}
		
		//-----------------------------------------------------------
		//-----------------------------------------------------------
		// state 4: death animation 
		if (my.STATE == 4) 
		{
			play01_winner = 2; // other wizard won
			my.ANIMATION += 3*time_step; 
			ent_animate(me,"death",my.ANIMATION,0);
			if (my.ANIMATION > 70)
				return;
		}		
		
		//-----------------------------------------------------------
		//-----------------------------------------------------------
//		// create decal as shadow
//		c_trace(my.x,vector(my.x,my.y,my.z-100) , IGNORE_ME | IGNORE_CONTENT | IGNORE_PASSABLE | IGNORE_FLAG2  | IGNORE_SPRITES | SCAN_TEXTURE );		
//		if (HIT_TARGET)
//			{
//				PARTICLE* shadow_p = ent_decal(you,shadow_bmp,(abs(me.max_x)+abs(me.max_y)+abs(me.max_z)),0);			// A7
//				shadow_p.material = mtl_decalshadow; 																								// assign another material when contact material is not suitable for decals like terraintex.fx
//				set(shadow_p,TRANSLUCENT);
//				shadow_p.alpha = 50;						
//				shadow_p.lifespan = 0.01;				
//			}
		
		//-----------------------------------------------------------
		
		PlayarTest01_Camera_Follow(me);			// own camera
		
		wait(1);
	}
}

Posted By: 3run

Re: Problem with OBB - 04/16/15 21:01

Originally Posted By: sivan
I had similar problems with map entities, and even with models converted from map entities having polygonal collision. In MapBuilder player test I solved it by using an additional forward c_trace that if hits something, movement is prevented. Bigger collision box could result in ugly gameplay behaviour. Search for "// allow no bad collision with small polygon models" section:
Thank you sivan for trying to help, but I've alredy avoided this problem (check out my movement template demo). Its not about me suffering from this, and trying to make a workaround, but about finding out whether it's a bug or not, and if it is, it needs to be fixed! Cause I'm already fed up with tons of workarounds in order to avoid those ugly 'elipsoid' hull problems (I guess jcl remembers how almost everyone asked for additional shapes for OBB, and it's was ignored frown ), and if it's not even working correctly I'm sick of it.

best regards
Posted By: sivan

Re: Problem with OBB - 04/16/15 21:04

I just confirmed that it is a real problem...
Posted By: 3run

Re: Problem with OBB - 04/16/15 21:18

Originally Posted By: sivan
I just confirmed that it is a real problem...
I thought you were trying to help me, but never mind grin
Posted By: Dico

Re: Problem with OBB - 04/16/15 22:57

This is really prob , i think when we add a force to wall the problem is gone o0

Code:
void playerEvent(){
	if(event_type == EVENT_BLOCK){
		draw_text("AUCH!", 10, 120, COLOR_WHITE);
	}
}

action actHero(){
	set(my, TRANSLUCENT);

	vec_fill(my.scale_x, 1);
	wait(1);
	c_setminmax(my);

	my.emask |= ENABLE_BLOCK;
	my.event = playerEvent;
	var speed_x;
	while(my){
		
		my.skill1 = ((key_w || key_cuu) - (key_s || key_cud));
		my.skill2 = ((key_a || key_cul) - (key_d || key_cur));
		my.skill3 = 0;
		vec_rotate(my.skill1, vector(camera.pan, 0, 0));
		
		accelerate(my.skill4, my.skill1 * 5 * time_step, 0.9);
		accelerate(my.skill5, my.skill2 * 5 * time_step, 0.9);
		my.skill6 = 0;
		
		var result2  = c_trace(my.x,vector(my.x+my.max_x+1,my.y,my.z),IGNORE_ME|IGNORE_SPRITES|IGNORE_CONTENT);
		draw_text("RESULT:", 10, 50, COLOR_WHITE);
		draw_text(str_for_num(NULL, result2), 150, 50, COLOR_RED);
		if(result2 > 0)
		{
			speed_x = 1;
		}
		else
		{
			speed_x = 0;
		}
		
		move_friction = 0.1;
		c_move(my, nullvector, vector(my.skill4+speed_x, my.skill5, 0), GLIDE);
		
		draw_text("Y INPUT:", 10, 150, COLOR_WHITE);
		draw_text(str_for_num(NULL, my.skill1), 150, 150, COLOR_RED);
		draw_text("X INPUT:", 10, 170, COLOR_WHITE);
		draw_text(str_for_num(NULL, my.skill2), 150, 170, COLOR_RED);
		
		my.z = 8;
		
		vec_set(camera.x, vector(my.x, my.y, my.z + 250));
		vec_set(camera.pan, vector(90, -90, 0));
		
		wait(1);
	}
}

// main game function:
void main(){
	warn_level = 6;
	fps_max = 60;
	freeze_mode = 1;
	level_load("map.wmb");
	wait(3);
	freeze_mode = 0;
}

Posted By: Rackscha

Re: Problem with OBB - 04/17/15 14:54

Shoudn't the engine do a penetration correction? Lets say the character collides with a wall, and because it's so fast it benetrates by 3 units. Instead of stopping where it is, isn't it common to move the character backwards by the penetration value?
Posted By: jcl

Re: Problem with OBB - 04/17/15 15:07

The problem is that the OBB library makes no difference between mere touching and penetrating an obstacle. But we're now aware of the problem and will try to find a solution.
© 2024 lite-C Forums