bounce + low framerate ??

Posted By: 3run

bounce + low framerate ?? - 04/17/18 21:43

Hi!

Can anyone please tell me, why does bounce go wrong when framerate is low?
Please, take a look at this example (my attempt to create bouncing grenade):
Code:
#include <acknex.h>
#include <default.c>

#define PRAGMA_POINTER

// default trace/move flags
#define TRACE_FLAGS (IGNORE_ME | IGNORE_PASSABLE | IGNORE_PASSENTS | IGNORE_MAPS | IGNORE_SPRITES | IGNORE_CONTENT)
#define MOVE_FLAGS (IGNORE_ME | IGNORE_PASSABLE | IGNORE_PASSENTS | IGNORE_MAPS | IGNORE_SPRITES | IGNORE_CONTENT)

action grenade(){
	
	c_setminmax(my);
	set(my, SHADOW | POLYGON);
	
	VECTOR velocity;
	vec_set(&velocity, vector(25, 0, 5));
	vec_rotate(&velocity, &camera->pan);
	
	var _soil_height = 0;		// target height from surface bellow
	var _gravity = 5;		// 1 - 10 (default 5)
	var _restitution = 0.5;		// 0.1 - 0.9 (default - 0.25)
	var counter = 0;
	
	while(my){
		
		// still moving ?
		if(vec_length(&velocity) > 1){
			
			VECTOR temp;
			vec_set(&temp, &velocity);
			vec_scale(&temp, time_step);
			c_move(my, nullvector, &temp, MOVE_FLAGS);
			
			velocity.z -= _gravity * time_step;
			
			if(HIT_TARGET){
				
				var speed = vec_length(&velocity);
				vec_set(&velocity, &bounce);
				vec_normalize(&velocity, _restitution * speed);
				
			}
			
		}
		else{
			
			// reset all movement
			vec_fill(&velocity, 0);
			
		}
		
		DEBUG_VAR(velocity.x, 200);
		DEBUG_VAR(velocity.y, 220);
		DEBUG_VAR(velocity.z, 240);
		
		DEBUG_VAR(bounce.x, 300);
		DEBUG_VAR(bounce.y, 320);
		DEBUG_VAR(bounce.z, 340);
		
		counter += time_frame / 16;
		if(counter >= 3){ break; }
		
		wait(1);
		
	}
	
	safe_remove(my);
	
}

void main(){
	
	shadow_stencil = 2;
	
	fps_max = 60;
	warn_level = 6;
	level_load("");
	wait(3);
	
	camera->arc = 90;
	vec_set(&camera->x, vector(-439, 0, 323));
	vec_set(&camera->pan, vector(0, -36, 0));
	
	level_ent = ent_create(CUBE_MDL, nullvector, NULL);
	vec_set(&level_ent->scale_x, vector(256, 256, 0.1));
	c_setminmax(level_ent);
	set(level_ent, POLYGON | SHADOW);
	
	ENTITY *wall = ent_create(CUBE_MDL, vector(0, 256, 64), NULL);
	vec_set(&wall->scale_x, vector(4, 8, 8));
	c_setminmax(wall);
	set(wall, POLYGON | SHADOW);
	
	int i = 0;	
	var counter = 0, throw = 0;
	
	while(!key_esc){
		
		if(mouse_left){
			
			if(throw == 0){
				
				ent_create(CUBE_MDL, &camera->x, grenade);
				
				throw = 1;
				
			}
			
		}
		
		if(throw == 1){
			
			counter += time_frame / 16;
			if(counter > 0.5){ throw = 0; counter -= 0.5; }
			
		}
		
		// slow down framerate for testing
		if(key_e){ fps_max = 20; }
		else{ fps_max = 60; }
		
		DEBUG_VAR(fps_max, 0);
		
		wait(1);
		
	}

}


As you can see, it starts moving towards the left, slowly... smirk


Why does that happen? Also, there is always small difference in grenade's movement, on different framerate (I guess it's framerate independent, but there is still a difference!).
Any help would be appreciated!

Best regards!
Posted By: Kartoffel

Re: bounce + low framerate ?? - 04/18/18 05:37

Regarding the frame rate problem: I didn't go through your code in detail but one thing you have to make sure is that you're using time and calculating other physical quantities correctly. Here's an example for a while loop:

Force = ...
Acceleration = Force / Mass
Velocity += Acceleration * DeltaTime
Position += Velocity * DeltaTime

In your case you can leave out the acceleration part and modify the velocity manually.


Edit: so I took a look at your code and it seems to follow the basic principle, I guess the problem is somewhere else.

Also what do you mean by "goes wrong"?
Posted By: 3run

Re: bounce + low framerate ?? - 04/18/18 08:04

Hi Kartoffel!

By 'goes wrong' I mean that after moving in a straight line, box starts sliding towards the left, if frame rate is low (just run the code above, hold E and press mouse left). You can see those numbers on the screen, they go for 'velocity.x, y, z and bounce.x, y, z. Y should be equal to zero all the time, but on low frame rate it slightly changes..

As for the frame rate problem, I can't understand why, but it's still there.. Box will land on the different distance away from the camera, if I change fps from 60 to 20/30.

Greets.

Edit: I'll try to explain on the picture as well
Posted By: Kartoffel

Re: bounce + low framerate ?? - 04/18/18 08:31

well I think this much of a difference in distance is caused by the inaccuracy of the simulation at a lower framerate (just like the case where the jump arc can turn out a bit lower when games run at very low fps)

Why it starts moving left I don't know, it's probably continuously bouncing. Might also be related to inaccuracies (standard lite-c vectors only use var).

You could try switching to float vectors or calculate the bounce vector yourself, not sure if thaat helps, though.
Posted By: 3run

Re: bounce + low framerate ?? - 04/18/18 08:38

I tried to calculate bounce vector by myself via vec_bounce, but it didn't help unfortunately :<
Posted By: Kartoffel

Re: bounce + low framerate ?? - 04/18/18 08:55

oh, it's the polygon collisions.

I started completely avoiding c_trace and c_move. using an actual physics engine will probably give you a more solid solution, and in general a better collision detection / scene query (player movement, etc.)
Posted By: 3run

Re: bounce + low framerate ?? - 04/18/18 09:03

Originally Posted By: Kartoffel
I started completely avoiding c_trace and c_move. using an actual physics engine will probably give you a more solid solution, and in general a better collision detection / scene query (player movement, etc.)
native physX implementation sucks.. so I have to use OBB..

edit: I still hope someone will be able to open my eyes on this.
Posted By: Kartoffel

Re: bounce + low framerate ?? - 04/18/18 09:06

im using 3dgssnakes physics implementation and while it's incomplete it has everything I need for collision detection and scene queries: all the essential physics shapes, line- and various volumetric scene queries which are 100 times more robust that c_trace with box mode smirk
Posted By: Ezzett

Re: bounce + low framerate ?? - 04/18/18 12:36

Every book on game physics development will teach you not to depend on the framerate of your game. This will cause all sorts of problems. The physics engine should run separately in another thread.
Posted By: 3run

Re: bounce + low framerate ?? - 04/18/18 12:57

That's a good point, can you please advice me any book to read about game physics development?

Anyway, still looking for a way to handle simple bouncing physics..
Posted By: Kartoffel

Re: bounce + low framerate ?? - 04/18/18 13:06

@Ezzett the way I understood it, 3run is already using calculations that are framerate independent but very low framerates still produce results that are "off"

I'm pretty certain it's due to the lower accuracy when running at a low framerate

@3run I don't really get it? from what I can see, the code is correct and it behaves the way it should?
Posted By: txesmi

Re: bounce + low framerate ?? - 04/18/18 14:05

I think it has nothing to do with the frame rate. It only makes the entity describe a different trajectory, so at 20 fps it hits the edge between the two triangles of the plane, something that at 60 fps does not. But, why does it fail when it hits an edge? Who knows... I would bet it is a variable accuracy issue, as Kartoffel stated. 3dgs somehow interpolates the normals of the triangles when it hits an edge. As far as I know, the data has to be tranformed between coordinate systems and there are some small vectors involved that result in the normal vector. Plowed field for imprecision even for floats.

Code:
MATERIAL* mtlWireframe = {
	effect = "
		float4x4 matWorldViewProj;
		
		void VS (in float4 InPos	: POSITION, out float4 OutPos	: POSITION) {
			OutPos = mul(InPos, matWorldViewProj);
		}
		
		float4 PS() : COLOR0 {
			return float4( 1.0f, 1.0f, 0.0f, 1.0f );
		}
		
		technique t0 {
			pass p0 {
				FillMode = Wireframe;
				VertexShader = compile vs_2_0 VS();
				PixelShader  = compile ps_2_0 PS();
			}
		}
	";
}


Posted By: Ezzett

Re: bounce + low framerate ?? - 04/18/18 14:24

It has something to do with the frame rate. Just replace time_step with 0.2666. This runs the calculation at "60 fps". The block will land on the same spot every time independently from the frame rate. With time_step and 20 fps you'll get some never ending vibrations because time_step gets to large to calculate a stable result.
Posted By: Ezzett

Re: bounce + low framerate ?? - 04/18/18 14:29

I think you need to implement a fourth order Runge-Kutta method to get correct results with large time_steps.

Or just dive into the world of game physics literature that can drive you crazy grin (it depends on the knowledge you already have)

https://www.amazon.com/gp/aw/d/012381976...&ref=plSrch
Posted By: 3run

Re: bounce + low framerate ?? - 04/18/18 14:33

Originally Posted By: Kartoffel
from what I can see, the code is correct and it behaves the way it should?
After some tests I guess it does.. but it just doesn't fit my expectations :<

Originally Posted By: txesmi
Who knows...
Damn... Thank you txesmi, and yes... thanks to your code, I can see that bounce get's fucked up when box hits the edge..

Another thing that I noticed, that it bounces off the surface different amount of time.. with fps 60 - 5 times, 20 - 6 times... If I lower fps while it's already bouncing, then it will cause to bounce off 7 times..

That sliding bounce effect was fixed by calculating bounce manually:
Code:
function get_bounce(VECTOR *speed, VECTOR *bounce_vec){
	
	VECTOR temp_inverse;
	vec_set(&temp_inverse, speed);
	vec_inverse(&temp_inverse);
	
	bounce_vec->x = speed->x + 2 * vec_dot(&normal, &temp_inverse) * normal.x;
	bounce_vec->y = speed->y + 2 * vec_dot(&normal, &temp_inverse) * normal.y;
	bounce_vec->z = speed->z + 2 * vec_dot(&normal, &temp_inverse) * normal.z;
	
}



Best regards! Thank you for your time guys.


Edit:
Originally Posted By: Ezzett
I think you need to implement a fourth order Runge-Kutta method to get correct results with large time_steps.

Or just dive into the world of game physics literature that can drive you crazy grin (it depends on the knowledge you already have)

https://www.amazon.com/gp/aw/d/012381976...&ref=plSrch
Thank you for the link! I'll take a look at it.
Posted By: 3run

Re: bounce + low framerate ?? - 04/18/18 14:47

So far this is the best result I could get right now
Code:
#include <acknex.h>
#include <default.c>

#define PRAGMA_POINTER

// default trace/move flags
#define TRACE_FLAGS (IGNORE_ME | IGNORE_PASSABLE | IGNORE_PASSENTS | IGNORE_MAPS | IGNORE_SPRITES | IGNORE_CONTENT)
#define MOVE_FLAGS (IGNORE_ME | IGNORE_PASSABLE | IGNORE_PASSENTS | IGNORE_MAPS | IGNORE_SPRITES | IGNORE_CONTENT)

// collusion groups/push values
#define PUSH_GROUP							2
#define SWITCH_ITEM_GROUP						3
#define PATHFIND_GROUP							4
#define PLAYER_GROUP							5
#define TRAPS_GROUP							6
#define OBSTACLE_GROUP							7

#define LEVEL_GROUP							10

// vectors
#define speed_x								skill50
#define speed_y								skill51
#define speed_z								skill52

#define obj_soil_contact						skill69

// character controller (CCT) global parameters
var cct_gravity = 4;							// gravity strength
var cct_gravity_max = 90;						// gravity max strength

MATERIAL* mtlWireframe = {
	
	effect = "
	float4x4 matWorldViewProj;
	
	void VS (in float4 InPos	: POSITION, out float4 OutPos	: POSITION) {
		OutPos = mul(InPos, matWorldViewProj);
	}
	
	float4 PS() : COLOR0 {
		return float4( 1.0f, 1.0f, 0.0f, 1.0f );
	}
	
	technique t0 {
		pass p0 {
			FillMode = Wireframe;
			VertexShader = compile vs_2_0 VS();
			PixelShader  = compile ps_2_0 PS();
		}
	}
	";
	
}

// calculate bounce vector
void get_bounce(VECTOR *speed, VECTOR *bounce_vec){
	
	VECTOR temp_inverse;
	vec_set(&temp_inverse, speed);
	vec_inverse(&temp_inverse);
	
	bounce_vec->x = speed->x + 2 * vec_dot(&normal, &temp_inverse) * normal.x;
	bounce_vec->y = speed->y + 2 * vec_dot(&normal, &temp_inverse) * normal.y;
	bounce_vec->z = speed->z + 2 * vec_dot(&normal, &temp_inverse) * normal.z;
	
}

// gravity trace for all npc
void prop_gravity(ENTITY *ent, var *z_force, var *soil, var offset){
	
	if(!ent){ return; }
	
	// gravity
	if(*z_force <= 0){
		
		VECTOR temp, target_vec;
		vec_set(&temp, vector(ent->x, ent->y, ent->z - 150 + offset));
		c_trace(&ent->x, &temp, TRACE_FLAGS | USE_BOX);
		
		vec_set(&target_vec, &temp);		
		if(HIT_TARGET){ vec_set(&target_vec, &target); }		
		*soil = target_vec.z - offset;
		
	}
	
	// additional height buffer when ground contact to avoid player floating on slopes
	if(ent->z > *soil + (5 + 20 * ent->obj_soil_contact) * time_step || *z_force > 0){
		
		ent->obj_soil_contact = 0;
		*z_force = maxv(*z_force - 9 * time_step, -90);
		
	}
	else{
		
		c_move(ent, nullvector, vector(0, 0, *soil - ent->z), MOVE_FLAGS);
		ent->obj_soil_contact = 1;
		*z_force = 0;
		
	}
	
	if(*z_force){
		
		// the maxv command makes sure you never move below the desired height
		c_move(ent, nullvector, vector(0, 0, maxv(*z_force * time_step, *soil - ent->z)), MOVE_FLAGS);
		
	}
	
}

action grenade(){
	
	c_setminmax(my);
	set(my, SHADOW | POLYGON);
	
	VECTOR velocity;
	vec_set(&velocity, vector(25, 0, 5));
	vec_rotate(&velocity, &camera->pan);
	
	var soil_height = 0;		// target height from surface bellow
	var gravity = 5;		// 1 - 10 (default 5)
	var restitution = 0.5;		// 0.1 - 0.9 (default - 0.5)
	var hit_count = 0;
	var counter = 0;
	
	while(my){
		
		// still got go bounce ?
		if(hit_count < 5){
			
			VECTOR temp;
			vec_set(&temp, &velocity);
			vec_scale(&temp, time_step);
			c_move(my, nullvector, &temp, MOVE_FLAGS);
			
			velocity.z -= gravity * time_step;
			
			if(HIT_TARGET){
				
				hit_count++;
				
				VECTOR bounce_vec;
				get_bounce(&velocity, &bounce_vec);
				var speed = vec_length(&velocity);
				vec_set(&velocity, &bounce_vec);
				vec_normalize(&velocity, restitution * speed);
				
			}
			
		}
		else{
			
			// reset all movement
			vec_fill(&velocity, 0);
			
			// simple gravity ?
			prop_gravity(my, &my->speed_z, &soil_height, my->min_z);
			
		}
		
		counter += time_frame / 16;
		if(counter >= 3){ break; }
		
		wait(1);
		
	}
	
	safe_remove(my);
	
}

void main(){
	
	shadow_stencil = 2;
	
	fps_max = 60;
	warn_level = 6;
	level_load("");
	wait(3);
	
	camera->arc = 90;
	vec_set(&camera->x, vector(-439, 0, 323));
	vec_set(&camera->pan, vector(0, -36, 0));
	
	level_ent = ent_create(CUBE_MDL, nullvector, NULL);
	vec_set(&level_ent->scale_x, vector(256, 256, 0.1));
	c_setminmax(level_ent);
	set(level_ent, POLYGON | SHADOW);
	//level_ent->material = mtlWireframe;
	
	ENTITY *wall = ent_create(CUBE_MDL, vector(0, 256, 64), NULL);
	vec_set(&wall->scale_x, vector(4, 8, 8));
	c_setminmax(wall);
	set(wall, POLYGON | SHADOW);
	//wall->material = mtlWireframe;
	
	int i = 0;	
	var counter = 0, throw = 0;
	
	while(!key_esc){
		
		if(mouse_left){
			
			if(throw == 0){
				
				ent_create(CUBE_MDL, &camera->x, grenade);
				
				throw = 1;
				
			}
			
		}
		
		if(throw == 1){
			
			counter += time_frame / 16;
			if(counter > 0.5){ throw = 0; counter -= 0.5; }
			
		}
		
		// slow down framerate for testing
		if(key_e){ fps_max = 20; }
		else{ fps_max = 60; }
		
		DEBUG_VAR(fps_max, 0);
		
		wait(1);
		
	}

}

Posted By: txesmi

Re: bounce + low framerate ?? - 04/18/18 15:03

Originally Posted By: 3run
That sliding bounce effect was fixed by calculating bounce manually

I am not sure of that. You have probably modified the trajectory only. The source of the problem is the normal of the surface returned by the trace. I am afraid there is nothing you can do frown
Posted By: Superku

Re: bounce + low framerate ?? - 04/18/18 15:06

It's perfectly fine the way it is, that's game dev.
I bet txesmi has found the reason for why it behaves like it does.

In case you need deterministic/ framerate independent outcome (which you normally do NOT need), use a lockstep or fixed step approach and blend the visuals between old and new pos. I do/ did that for some multiplayer stuff, that's it.
Posted By: 3run

Re: bounce + low framerate ?? - 04/18/18 15:06

Well, at least it does slide (right now grin ).

Originally Posted By: Superku
It's perfectly fine the way it is, that's game dev.
I bet txesmi has found the reason for why it behaves like it does.

In case you need deterministic/ framerate independent outcome (which you normally do NOT need), use a lockstep or fixed step approach and blend the visuals between old and new pos. I do/ did that for some multiplayer stuff, that's it.
Thank you, Superku! laugh
© 2024 lite-C Forums