|
bounce + low framerate ??
#472238
04/17/18 21:43
04/17/18 21:43
|
Joined: May 2009
Posts: 5,370 Caucasus
3run
OP
Senior Expert
|
OP
Senior Expert
Joined: May 2009
Posts: 5,370
Caucasus
|
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):
#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... 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!
|
|
|
Re: bounce + low framerate ??
[Re: 3run]
#472247
04/18/18 05:37
04/18/18 05:37
|
Joined: Jun 2009
Posts: 2,210 Bavaria, Germany
Kartoffel
Expert
|
Expert
Joined: Jun 2009
Posts: 2,210
Bavaria, Germany
|
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"?
Last edited by Kartoffel; 04/18/18 06:20.
POTATO-MAN saves the day! - Random
|
|
|
Re: bounce + low framerate ??
[Re: Kartoffel]
#472250
04/18/18 08:04
04/18/18 08:04
|
Joined: May 2009
Posts: 5,370 Caucasus
3run
OP
Senior Expert
|
OP
Senior Expert
Joined: May 2009
Posts: 5,370
Caucasus
|
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
Last edited by 3run; 04/18/18 08:12.
|
|
|
Re: bounce + low framerate ??
[Re: 3run]
#472251
04/18/18 08:31
04/18/18 08:31
|
Joined: Jun 2009
Posts: 2,210 Bavaria, Germany
Kartoffel
Expert
|
Expert
Joined: Jun 2009
Posts: 2,210
Bavaria, Germany
|
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.
POTATO-MAN saves the day! - Random
|
|
|
Re: bounce + low framerate ??
[Re: 3run]
#472253
04/18/18 08:55
04/18/18 08:55
|
Joined: Jun 2009
Posts: 2,210 Bavaria, Germany
Kartoffel
Expert
|
Expert
Joined: Jun 2009
Posts: 2,210
Bavaria, Germany
|
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.)
POTATO-MAN saves the day! - Random
|
|
|
Re: bounce + low framerate ??
[Re: Kartoffel]
#472255
04/18/18 09:03
04/18/18 09:03
|
Joined: May 2009
Posts: 5,370 Caucasus
3run
OP
Senior Expert
|
OP
Senior Expert
Joined: May 2009
Posts: 5,370
Caucasus
|
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.
Last edited by 3run; 04/18/18 09:04.
|
|
|
Re: bounce + low framerate ??
[Re: 3run]
#472264
04/18/18 13:06
04/18/18 13:06
|
Joined: Jun 2009
Posts: 2,210 Bavaria, Germany
Kartoffel
Expert
|
Expert
Joined: Jun 2009
Posts: 2,210
Bavaria, Germany
|
@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?
POTATO-MAN saves the day! - Random
|
|
|
Re: bounce + low framerate ??
[Re: Kartoffel]
#472269
04/18/18 14:05
04/18/18 14:05
|
Joined: Jun 2007
Posts: 1,337 Hiporope and its pain
txesmi
Serious User
|
Serious User
Joined: Jun 2007
Posts: 1,337
Hiporope and its pain
|
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.
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();
}
}
";
}
|
|
|
Re: bounce + low framerate ??
[Re: txesmi]
#472273
04/18/18 14:33
04/18/18 14:33
|
Joined: May 2009
Posts: 5,370 Caucasus
3run
OP
Senior Expert
|
OP
Senior Expert
Joined: May 2009
Posts: 5,370
Caucasus
|
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 :< 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:
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: 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 (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.
Last edited by 3run; 04/18/18 14:35.
|
|
|
Re: bounce + low framerate ??
[Re: 3run]
#472275
04/18/18 14:47
04/18/18 14:47
|
Joined: May 2009
Posts: 5,370 Caucasus
3run
OP
Senior Expert
|
OP
Senior Expert
Joined: May 2009
Posts: 5,370
Caucasus
|
So far this is the best result I could get right now
#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);
}
}
|
|
|
Re: bounce + low framerate ??
[Re: txesmi]
#472280
04/18/18 15:06
04/18/18 15:06
|
Joined: May 2009
Posts: 5,370 Caucasus
3run
OP
Senior Expert
|
OP
Senior Expert
Joined: May 2009
Posts: 5,370
Caucasus
|
Well, at least it does slide (right now ). 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!
Last edited by 3run; 04/18/18 15:07.
|
|
|
|