3 registered members (Ayumi, Akow, AndrewAMD),
1,505
guests, and 9
spiders. |
Key:
Admin,
Global Mod,
Mod
|
|
|
Problem with OBB
#450457
04/14/15 20:42
04/14/15 20:42
|
Joined: May 2009
Posts: 5,370 Caucasus
3run
OP
Senior Expert
|
OP
Senior Expert
Joined: May 2009
Posts: 5,370
Caucasus
|
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
|
|
|
Re: Problem with OBB
[Re: 3run]
#450459
04/14/15 21:03
04/14/15 21:03
|
Joined: Sep 2003
Posts: 6,861 Kiel (Germany)
Superku
Senior Expert
|
Senior Expert
Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
|
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 to 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).
Last edited by Superku; 04/14/15 21:03.
"Falls das Resultat nicht einfach nur dermassen gut aussieht, sollten Sie nochmal von vorn anfangen..." - Manual Check out my new game: Pogostuck: Rage With Your Friends
|
|
|
Re: Problem with OBB
[Re: jcl]
#450526
04/16/15 16:39
04/16/15 16:39
|
Joined: May 2009
Posts: 5,370 Caucasus
3run
OP
Senior Expert
|
OP
Senior Expert
Joined: May 2009
Posts: 5,370
Caucasus
|
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: WED setup: Running demo with scaled box (32x32x32): Greets
|
|
|
Re: Problem with OBB
[Re: 3run]
#450530
04/16/15 20:10
04/16/15 20:10
|
Joined: Mar 2011
Posts: 3,150 Budapest
sivan
Expert
|
Expert
Joined: Mar 2011
Posts: 3,150
Budapest
|
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:
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);
}
}
|
|
|
Re: Problem with OBB
[Re: sivan]
#450535
04/16/15 21:01
04/16/15 21:01
|
Joined: May 2009
Posts: 5,370 Caucasus
3run
OP
Senior Expert
|
OP
Senior Expert
Joined: May 2009
Posts: 5,370
Caucasus
|
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 ), and if it's not even working correctly I'm sick of it. best regards
|
|
|
Re: Problem with OBB
[Re: 3run]
#450541
04/16/15 22:57
04/16/15 22:57
|
Joined: Feb 2012
Posts: 371
Dico
Senior Member
|
Senior Member
Joined: Feb 2012
Posts: 371
|
This is really prob , i think when we add a force to wall the problem is gone o0
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;
}
|
|
|
|