|
Camera passing through wall
#470947
02/14/18 07:29
02/14/18 07:29
|
Joined: Jun 2010
Posts: 590 California
Ruben
OP
User
|
OP
User
Joined: Jun 2010
Posts: 590
California
|
I am trying to make it so that if the player moves near a wall, and turns its back toward it while turning its body, the camera following the player will glide along the inside of the wall, pushing itself closer to the player's back, and then backs up to its normal following distance once the player's back is turned away from the wall. I have a function that mostly does this. However, for some reason, while the player is turning its body while facing its front away from the wall (back toward wall), the camera will go behind the wall for the first 90 degrees on the left side of the turn instead of gliding on the inside of the wall, staying at the same distance behind the player as it would have with no collision detected, but then for the second 90 degrees of the turn on the right, the camera will start doing what I want it to do by gliding on the inside of the wall coming closer to the player's back for the remainder of the turn. It is always the first 90 degrees on the left side of the turn where the camera goes through the wall behind the player (what I do NOT want to happen), and always the second 90 degrees on the right of that same turn where the camera does not go through the wall and instead glides on the inside of the wall (what I would like to happen for the whole 180 degrees of this turn). This happens in the exact same manner from left to right, no matter what the wall, no matter where the wall is. Here is my camera function:
void _handle_cam_3rdperson()
{
c_rotate ( me, vector(-mickey.x * 0.3, 0, 0), IGNORE_ME |
IGNORE_PASSABLE | IGNORE_SPRITES | USE_POLYGON |
GLIDE );
my.skNextPan = my.pan;
my.skNextTilt = clamp ( my.skNextTilt - mickey.y * 0.3,
-90, 90 );
my.skNextRoll = 0;
VECTOR vecOrigin;
vec_set ( vecOrigin, vector(5,-25,40) );
vec_rotate ( vecOrigin, vector(my.pan,0,0) );
vec_add ( vecOrigin, my.x );
VECTOR vecTarget;
vec_for_angle ( vecTarget, my.skNextPan );
vec_scale ( vecTarget, -80 );
vec_add ( vecTarget, vecOrigin );
// THIS SEEMS TO BE WHERE THE ERROR LIES
var distance = c_trace ( vecOrigin, vecTarget, IGNORE_ME |
IGNORE_PASSABLE | IGNORE_SPRITES |
USE_POLYGON );
if ( HIT_TARGET )
{
beep(); // THIS BEEPS DURING THE 2ND 90 DEGREES OF THE TURN IN
// QUESTION, NOT DURING THE 1ST 90 DEGREES.
vec_set ( vecTarget, hit.x );
if ( distance > 0 )
reset ( me, TRANSLUCENT );
else
set ( me, TRANSLUCENT );
}
else
{
reset ( me, TRANSLUCENT );
}
vec_lerp ( camera.x, camera.x, vecTarget, time_step );
vec_sub ( vecOrigin, camera.x );
vec_to_angle ( camera.pan, vecOrigin );
}
It appears that this line of code is causing the error in question:
var distance = c_trace ( vecOrigin, vecTarget, IGNORE_ME |
IGNORE_PASSABLE | IGNORE_SPRITES |
USE_POLYGON );
The beep() right after the HIT_TARGET beeps like crazy during the 2nd 90 degrees of the turn sensing the collision, but does not beep at all during the 1st 90 degrees of the turn which shows that collision is not being detected. Why is the c_trace line from vecOrigin and vecTarget not being detected during the first 90 degrees of the turn, but is being detected during the second 90 degrees of the same turn? Any help will be greatly appreciated. Thank you.
Last edited by Ruben; 02/16/18 03:31.
|
|
|
Re: Camera passing through wall
[Re: Ruben]
#471014
02/16/18 05:21
02/16/18 05:21
|
Joined: Jun 2010
Posts: 590 California
Ruben
OP
User
|
OP
User
Joined: Jun 2010
Posts: 590
California
|
Okay, made a little progress. I find that altering the xyz coordinates in: ...for this code:
vec_set ( vecOrigin, vector(5,-25,40) );
...is changing the location of the c_trace line, and making the first part of the turn where the camera is behind the wall last shorter (like maybe first 30 degrees of turn), and more quickly start gliding inside the wall like I want it to (for about the last 110 degrees of the turn). Only thing is that I have to permanently change the camera position to accomplish this. It might work great for turning player with its back facing a wall, but when the player's back faces away from the wall, the camera is not in a position that I want it to be in. Trying to make it so that the camera does not go through a wall when facing player's back against it during a turn, and also having the camera be where I want it to be when the player's back is facing away from a wall as well.
Last edited by Ruben; 02/16/18 05:23.
|
|
|
Re: Camera passing through wall
[Re: Ruben]
#471015
02/16/18 05:50
02/16/18 05:50
|
Joined: Jul 2014
Posts: 72
DriftWood
Junior Member
|
Junior Member
Joined: Jul 2014
Posts: 72
|
|
|
|
Re: Camera passing through wall
[Re: Ruben]
#471113
02/20/18 01:02
02/20/18 01:02
|
Joined: Jun 2010
Posts: 590 California
Ruben
OP
User
|
OP
User
Joined: Jun 2010
Posts: 590
California
|
So, it seems I made some progress. I changed this code:
var distance = c_trace ( vecOrigin, vecTarget, IGNORE_ME |
IGNORE_PASSABLE | IGNORE_SPRITES |
USE_POLYGON );
...to this:
var distance = c_trace ( player.x, vecTarget, IGNORE_ME |
IGNORE_PASSABLE | IGNORE_SPRITES |
USE_POLYGON );
The beep() just after the HIT_TARGET now beeps whenever the camera touches the wall (which is great), and the camera does not go behind the wall (which is also great), at least not entirely (which still gives me an issue). The issue is, lets say you are the player, and your player's front side is facing a wall. You move your mouse left, making the player rotate left. The camera rotates with and behind the player, facing the player's back at all times, all while the right side of the camera moves closer toward the wall given that the player is rotating. The camera's right side makes contact with the wall, and glides along the wall, making it move closer to the player's back as the player keeps rotating, all the way till the player rotates so far to the point that its back is not facing the wall anymore, at which point the camera detaches from the wall and moves back to its original distance behind the player. In the first half of this rotation where the camera makes contact with the wall, I can see a vertical sliver of blue on the right side of the screen past the wall (which is not great). The camera is not entirely moving through the wall like before, but it feels like a small section on the right side of the camera is peeking through the wall, as the camera glides along the wall. Once the camera reaches the middle of the rotation, making the camera face directly away from the wall and toward the player's back, the blue disappears (which is great). Once the camera reaches the opposite side of this same rotation, no blueness is present at all (which is great). This gives the feeling like the right side of the camera peeks through the wall, and the left side of the camera does not. Does anyone have a clue on how to prevent the camera from peeking past the wall for the entire rotation, while the player's back is facing the wall?
Last edited by Ruben; 02/20/18 01:52.
|
|
|
Re: Camera passing through wall
[Re: Ruben]
#471118
02/20/18 03:03
02/20/18 03:03
|
Joined: Jul 2014
Posts: 72
DriftWood
Junior Member
|
Junior Member
Joined: Jul 2014
Posts: 72
|
The solution is to move the camera further away from the wall.
I don't read 3dgs code perfectly anymore. Ok you seem to be placing the camera right at hit.x or in other words *on the surface of the wall.*
My solution would be to simply move vecTarget closer to the player after the set . Assume the camera has a size of 20.
Vec_set(vecTarget,hit.x) **Now adjust the vec say 20 closer to the player. Get the Vector from vecTarget to the player. Normalize it to 20. Then vec_add it to vecTarget ?? Or is vec_sub I forget. Bam! Camera has extra room and is off the surface of the wall. So I'll have to look at the manual and remember how to do that.
Last edited by DriftWood; 02/20/18 03:04.
|
|
|
Re: Camera passing through wall
[Re: DriftWood]
#471119
02/20/18 03:17
02/20/18 03:17
|
Joined: Jul 2014
Posts: 72
DriftWood
Junior Member
|
Junior Member
Joined: Jul 2014
Posts: 72
|
I'm guessing something like this.
Vec_set ( vecTarget, hit.x);
Vec_set (temp_vecA, player.x);
Vec_set (temp_vecB, vecTarget);
Vec_sub (temp_vecA, temp_vecB);
Vec_nomalize(temp_vecA, 20);
Vec_add (vecTarget, temp_vecA);
//Now vecTarget "should be" 20 units off the wall and closer to the player.
Other solutions could be putting the camera in abox. Using side traces from the camera. Using 3 traces to the wall and blending the vecTarget further to the open side. Or hiring a virtual monkey to fly the camera in the dangerous isolation of 3dgs space!!!
|
|
|
Re: Camera passing through wall
[Re: DriftWood]
#471120
02/20/18 03:29
02/20/18 03:29
|
Joined: Jul 2014
Posts: 72
DriftWood
Junior Member
|
Junior Member
Joined: Jul 2014
Posts: 72
|
Wait!!! Cool idea! Why not just push off the wall using it's own normal?! Yeah that could work!
Vec_set( vecTarget, hit.x);
Vec_set ( vec_temp, hit.nx);
Vec_normalize ( vec_temp, 20);
Vec_add ( vecTarget, vec_temp);
// Bam!!! Virtual Monkey!!!
|
|
|
Re: Camera passing through wall
[Re: DriftWood]
#471126
02/20/18 08:42
02/20/18 08:42
|
Joined: Jun 2010
Posts: 590 California
Ruben
OP
User
|
OP
User
Joined: Jun 2010
Posts: 590
California
|
Wait!!! Cool idea! Why not just push off the wall using it's own normal?! Yeah that could work!
Vec_set( vecTarget, hit.x);
Vec_set ( vec_temp, hit.nx);
Vec_normalize ( vec_temp, 20);
Vec_add ( vecTarget, vec_temp);
// Bam!!! Virtual Monkey!!!
Interesting, I never heard of ".nx". I cannot seem to find it in the manual, or online. Where does it discuss the concept of ".nx"?*
|
|
|
Re: Camera passing through wall
[Re: DriftWood]
#471155
02/21/18 03:01
02/21/18 03:01
|
Joined: Jun 2010
Posts: 590 California
Ruben
OP
User
|
OP
User
Joined: Jun 2010
Posts: 590
California
|
Kartoffel answers perfectly.
Haha - did the "hit" part escape you? Go to c_trace in the manual. There you'll find the link to the "hit" struc that holds even more cool data after a trace. The concept of nx is the a Normal. A Normal unit vector is common in all 3D. It would truly be amazing if you have been working with 3D for so long and have no idea what a Normal are.
Here is your reading https://en.m.wikipedia.org/wiki/Normal_(geometry) Thanks for the sprinkling of condescension in your tone. I saw that one coming. I knew you couldn't reasonably be that chipper. ;-) However, as long as I have been doing this, this is a part-time gig for me, as I have my full time bread and butter job. Got to keep a roof over my head. :-) You are right, though. I should have linked it to the hit variable, and looked that one up. Learned a lesson. Thank you for the advice on what a Normal is.
Last edited by Ruben; 02/21/18 03:24.
|
|
|
Re: Camera passing through wall
[Re: DriftWood]
#471157
02/21/18 03:10
02/21/18 03:10
|
Joined: Jun 2010
Posts: 590 California
Ruben
OP
User
|
OP
User
Joined: Jun 2010
Posts: 590
California
|
Wait!!! Cool idea! Why not just push off the wall using it's own normal?! Yeah that could work!
Vec_set( vecTarget, hit.x);
Vec_set ( vec_temp, hit.nx);
Vec_normalize ( vec_temp, 20);
Vec_add ( vecTarget, vec_temp);
// Bam!!! Virtual Monkey!!!
I tried both your ideas inside the HIT_TARGET brackets, and both of them are not working. I am still seeing the vertical blue line on the right, in the first half of the rotation when turning right to left near a wall, with the player's back facing the wall. In other words, I am getting the exact same result I already had. Nothing changed.
Last edited by Ruben; 02/21/18 03:13.
|
|
|
Re: Camera passing through wall
[Re: Ruben]
#471158
02/21/18 03:20
02/21/18 03:20
|
Joined: Jul 2014
Posts: 72
DriftWood
Junior Member
|
Junior Member
Joined: Jul 2014
Posts: 72
|
I see. Well great enjoy your hobby. It's impossible for *"Nothing changed" to change. It is possible that the change was too small. After all we moved the vecTarget so something change. So let's assume the change is just too small. Than try this.
vec_set( vecTarget, hit.x);
vec_set ( vec_temp, hit.nx);
vec_normalize ( vec_temp, 555);// Huge change
vec_add ( vecTarget, vec_temp);
If you still see no change something else is happening. If you see a big change, than adjust 555 down until close to correct. I also don't understand this lerp
vec_lerp ( camera.x, camera.x, vecTarget, time_step );]
The value of Time_step is a small decimal. It's not collecting or adding to anything or itself. This could be a your big problem. Try
..............
var range = 0;
.............
if(Taget_hit)
{
.........
if (range < 1)
range += time_step;
}
else
{
.....
range = 0;
}
vec_lerp ( camera.x, camera.x, vecTarget, range );]
I would like you to understand, I don't use this engine, I haven't in over a year. I don't have this engine installed and I work from memory, logic and looking in the manual to answer your questions. Finally I get nothing out of helping you, I answer for your benefit, my involvement is volunteer and I can stop if it's not to you're taste. We all have jobs or other things to take our time. I currently am working on a project in another community and also learning a second engine, so my free time has other things to fill it than answering here.
Last edited by DriftWood; 02/21/18 03:59.
|
|
|
Re: Camera passing through wall
[Re: DriftWood]
#471161
02/21/18 04:12
02/21/18 04:12
|
Joined: Jun 2010
Posts: 590 California
Ruben
OP
User
|
OP
User
Joined: Jun 2010
Posts: 590
California
|
I see. Well great enjoy your hobby. It's impossible for *"Nothing changed" to change. It is possible that the change was too small. After all we moved the vecTarget so something change. So let's assume the change is just too small. Than try this.
vec_set( vecTarget, hit.x);
vec_set ( vec_temp, hit.nx);
vec_normalize ( vec_temp, 555);// Huge change
vec_add ( vecTarget, vec_temp);
If you still see no change something else is happening. If you see a big change, than adjust 555 down until close to correct. I also don't understand this lerp
vec_lerp ( camera.x, camera.x, vecTarget, time_step );]
The value of Time_step is a small decimal. It's not collecting or adding to anything or itself. This could be a your big problem. Try
..............
var range = 0;
.............
if(Taget_hit)
{
.........
if (range < 1)
range += time_step;
}
else
{
.....
range = 0;
}
vec_lerp ( camera.x, camera.x, vecTarget, range );]
I would like you to understand, I don't use this engine, I haven't in over a year. I don't have this engine installed and I work from memory, logic and looking in the manual to answer your questions. Finally I get nothing out of helping you, I answer for your benefit, my involvement is volunteer and I can stop if it's not to you're taste. We all have jobs or other things to take our time. I currently am working on a project in another community and also learning a second engine, so my free time has other things to fill it than answering here. I apologize. I really do sincerely appreciate your help. I am realizing that your code actually does work. I am just seeing blue on the right half of the camera before the HIT_TARGET is activated in the exact middle of the camera, and once it is activated, the camera is pushed inside the wall using your code, as it needs to do. So, thank you. Thanks to you, the code is working as it should after the HIT_TARGET is activated. Now I am trying to make it so that the:
var distance = c_trace ( player.x, vecTarget, IGNORE_ME |
IGNORE_PASSABLE | IGNORE_SPRITES | USE_POLYGON );
...before the HIT_TARGET call makes collision on the right side of the camera, instead of its dead center. It seems to me that collision is happening only in the middle of the camera, instead of the actual side of the camera, making it so that the camera's right half peeks past the wall, until the wall hits center on the camera lens, then collision happens, and activates your code. I am trying to figure out how to make collision happen on the right side of the camera, so that I do not have to see the blue at all when turning the player's back toward the wall. I will try to use your logic before the HIT_TARGET call to make the same thing happen before that call, as it does after.
Last edited by Ruben; 02/21/18 04:15.
|
|
|
Re: Camera passing through wall
[Re: Ruben]
#471163
02/21/18 05:54
02/21/18 05:54
|
Joined: Jul 2014
Posts: 72
DriftWood
Junior Member
|
Junior Member
Joined: Jul 2014
Posts: 72
|
Here is my best attempt from my mobile. Two extra traces from camera left and right.
if ( HIT_TARGET )
{
vec_set ( vecTarget, hit.x );
vec_set( vecTarget, hit.x);
vec_set ( vec_temp, hit.nx);
vec_normalize ( vec_temp, 20);
vec_add ( vecTarget, vec_temp);
if ( distance > 0 )
reset ( me, TRANSLUCENT );
else
set ( me, TRANSLUCENT );
}
else
{
// CREATE A SIDE VECTOR FROM CAMERA
vec_set(vec_temp,vector(0,20,0));
// ROTATE TO BY CAM PAN AND ADD CAM VEC
vec_rotate ( vec_temp, vector(camera.pan,0,0) );
vec_add ( vec_temp camera.x );
// YOUR CODE
reset ( me, TRANSLUCENT );
// TRACE SIDEWAYS FROM CAMERA
distance = c_trace ( camera.x, vec_temp, IGNORE_ME |
IGNORE_PASSABLE | IGNORE_SPRITES |
USE_POLYGON | IGNORE_MODELS );
//CHECK HIT
if(HIT_TARGET)
{
/* ANOTHER WAY
// SET DISTANCE INTO TEMP.Y ( POS trace = NEG Distance
vec_set( vec_temp, vector(0,-distance,0));
// ROTATE BY CAM PAN
vec_rotate(vec_temp, vector (camera.pan,0,0);
// ADD TO VecTarget ** because it's already available
vec_add(vecTarget, vec_temp); */
vec_set ( vec_temp, hit.nx);
vec_normalize ( vec_temp, 20);
vec_add ( vecTarget, vec_temp);
}
// REPEAT FOR LEFT TRACE !!!
// CREATE A SIDE VECTOR FROM CAMERA ** CHANGE TO NEG VEC
vec_set(vec_temp,vector(0,-20,0));
// ROTATE TO BY CAM PAN AND ADD CAM VEC
vec_rotate ( vec_temp, vector(camera.pan,0,0) );
vec_add ( vec_temp camera.x );
// TRACE SIDEWAYS FROM CAMERA
distance = c_trace ( camera.x, vec_temp, IGNORE_ME |
IGNORE_PASSABLE | IGNORE_SPRITES |
USE_POLYGON | IGNORE_MODELS);
//CHECK HIT
if(HIT_TARGET)
{
/* // SET DISTANCE INTO TEMP.Y (*! NEG trace = POS Distance
vec_set( vec_temp, vector(0,distance,0));
// ROTATE BY CAM PAN
vec_rotate(vec_temp, vector (camera.pan,0,0);
// ADD TO VecTarget ** because it's already available
vec_add(vecTarget, vec_temp); */
vec_set ( vec_temp, hit.nx);
vec_normalize ( vec_temp, 20);
vec_add ( vecTarget, vec_temp);
}
}
// REMOVED
//vec_lerp ( camera.x, camera.x, vecTarget, time_step );
vec_set(camera.x, vecTarget);
vec_sub ( vecOrigin, camera.x );
vec_to_angle ( camera.pan, vecOrigin );
}
BTW vec_scale messes up the direction it should also be vec_nornalize
VECTOR vecTarget;
vec_for_angle ( vecTarget, my.skNextPan );
// vec_scale ( vecTarget, -80 );
vec_normalize( vecTarget, -80);
Bonus homework - vec_scale and vec_normalize both multiply the elements of a vector. So find out what is the difference and why it is important.
Last edited by DriftWood; 02/21/18 06:20.
|
|
|
Re: Camera passing through wall
[Re: DriftWood]
#471173
02/21/18 12:30
02/21/18 12:30
|
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
|
That workaround fails when the view ray is nearly parallel to a surface the camera ends close to and the c_trace did not collide to. The only solution I know is the use of a dummy entity and USE_BOX in the trace.
action actCameraCollider () {
proc_mode = PROC_LATE; // execute after player action
my->flags |= INVISIBLE | PASSABLE | FAT | NARROW;
vec_set(&my->max_x, vector(16, 16, 16)); // collision hull
vec_set(&my->min_x, vector(-16, -16, -16));
VECTOR vOffset;
vec_set(&vOffset, vector(0, -7, 35)); // camera rotation center in player space
var nCamDist = 200; // distance to the center
...
vec_set(&my->x, &vOffset); // set the collider position in reference to the player position and orientation
vec_rotate(&my->x, &player->pan);
vec_add(&my->x, &player->x);
VECTOR vDir;
vec_for_angle(&vDir, &camera->pan); // compute the inverse of the view ray; the trace is backwards
vec_scale(&vDir, -nCamDist);
VECTOR vTarget; // compute the target position for c_trace
vec_set(&vTarget, &my->x); // it is also the final camera position when the trace collides nothing
vec_add(&vTarget, &vDir);
you = player;
var nDist = c_trace(&my->x, &vTarget, IGNORE_YOU | IGNORE_PASSABLE | USE_BOX);
if (nDist > 0) { // when it collides
vec_normalize(&vDir, nDist); // enshort the view ray
vec_set(&camera->x, &my->x); // and recompute the position of the camera
vec_add(&camera->x, &vDir);
} else { // when it does not collide
vec_set(&camera->x, &vTarget); // set the already computed position of the camera
}
...
Salud!
|
|
|
Re: Camera passing through wall
[Re: txesmi]
#471176
02/21/18 16:06
02/21/18 16:06
|
Joined: Jul 2014
Posts: 72
DriftWood
Junior Member
|
Junior Member
Joined: Jul 2014
Posts: 72
|
@Ruban txesmi presents the best solution and far better code( always) than I do. Take his advice. I do reference you to my prior post which I suggest camera in a box. Txesmi presents the end evolution of using an invisible box entity for camera collision. @txesmi you're still the best under the sun!
|
|
|
Re: Camera passing through wall
[Re: txesmi]
#471202
02/23/18 09:01
02/23/18 09:01
|
Joined: Jun 2010
Posts: 590 California
Ruben
OP
User
|
OP
User
Joined: Jun 2010
Posts: 590
California
|
That workaround fails when the view ray is nearly parallel to a surface the camera ends close to and the c_trace did not collide to. The only solution I know is the use of a dummy entity and USE_BOX in the trace.
action actCameraCollider () {
proc_mode = PROC_LATE; // execute after player action
my->flags |= INVISIBLE | PASSABLE | FAT | NARROW;
vec_set(&my->max_x, vector(16, 16, 16)); // collision hull
vec_set(&my->min_x, vector(-16, -16, -16));
VECTOR vOffset;
vec_set(&vOffset, vector(0, -7, 35)); // camera rotation center in player space
var nCamDist = 200; // distance to the center
...
vec_set(&my->x, &vOffset); // set the collider position in reference to the player position and orientation
vec_rotate(&my->x, &player->pan);
vec_add(&my->x, &player->x);
VECTOR vDir;
vec_for_angle(&vDir, &camera->pan); // compute the inverse of the view ray; the trace is backwards
vec_scale(&vDir, -nCamDist);
VECTOR vTarget; // compute the target position for c_trace
vec_set(&vTarget, &my->x); // it is also the final camera position when the trace collides nothing
vec_add(&vTarget, &vDir);
you = player;
var nDist = c_trace(&my->x, &vTarget, IGNORE_YOU | IGNORE_PASSABLE | USE_BOX);
if (nDist > 0) { // when it collides
vec_normalize(&vDir, nDist); // enshort the view ray
vec_set(&camera->x, &my->x); // and recompute the position of the camera
vec_add(&camera->x, &vDir);
} else { // when it does not collide
vec_set(&camera->x, &vTarget); // set the already computed position of the camera
}
...
Salud! Hello Txesmi. Thank you for your help again. Believe it or not, I am kind of new to the idea of using a dummy entity. Does it go something like this?
action actCameraCollider()
{
proc_mode = PROC_LATE; // execute after player action
my->flags |= INVISIBLE | PASSABLE | FAT | NARROW;
vec_set(&my->max_x, vector(16, 16, 16)); // collision hull
vec_set(&my->min_x, vector(-16, -16, -16));
VECTOR vOffset;
vec_set(&vOffset, vector(0, -7, 35)); // camera rotation center
// in player space
var nCamDist = 200; // distance to the center
vec_set(&my->x, &vOffset); // set the collider position in
// reference to the player position
// and orientation
vec_rotate(&my->x, &player->pan);
vec_add(&my->x, &player->x);
VECTOR vDir;
vec_for_angle(&vDir, &camera->pan); // compute the inverse of the
// view ray; the trace is
// backwards
vec_scale(&vDir, -nCamDist);
VECTOR vTarget; // compute the target position for c_trace
vec_set(&vTarget, &my->x); // it is also the final camera position
// when the trace collides nothing
vec_add(&vTarget, &vDir);
you = player;
var nDist = c_trace(&my->x, &vTarget, IGNORE_YOU | IGNORE_PASSABLE
| USE_BOX);
if (nDist > 0)
{ // when it collides
vec_normalize(&vDir, nDist); // enshort the view ray
vec_set(&camera->x, &my->x); // and recompute the position of
// the camera
vec_add(&camera->x, &vDir);
}
else
{ // when it does not collide
vec_set(&camera->x, &vTarget); // set the already computed
// position of the camera
}
}
action cameraDummy()
{
actCameraCollider();
}
void _handle_cam_3rdperson()
{
camDummy = ent_create(NULL,nullvector,cameraDummy);
}
action playerAction()
{
...
_handle_cam_3rdperson();
...
}
Last edited by Ruben; 02/23/18 09:02.
|
|
|
Re: Camera passing through wall
[Re: Ruben]
#471209
02/23/18 14:30
02/23/18 14:30
|
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
|
here goes the whole thing
#include <acknex.h>
#define PRAGMA_PATH "%EXE_DIR%\templates\models"
#define skOffsetX skill1
#define skOffsetY skill2
#define skOffsetZ skill3
#define skDistance skill4
#define skDistSoft skill5
action actCameraCollider () {
proc_mode = PROC_LATE;
wait(1);
my->flags |= INVISIBLE | PASSABLE;
my->eflags = FAT | NARROW;
vec_set(&my->max_x, vector(8, 8, 8));
vec_set(&my->min_x, vector(-8, -8, -8));
vec_set(&my->skOffsetX, vector(0, -7, 35));
my->skDistance = 200;
my->skDistSoft = my->skDistance;
my->parent = player;
while (my->parent == player) {
my->skDistance = clamp(my->skDistance + mickey.z * 0.3, 20, 400);
camera->pan = player->pan;
camera->tilt = clamp(camera->tilt - mickey.y * 0.2, -80, 45);
vec_set(&my->pan, &camera->pan);
vec_set(&my->x, &my->skOffsetX);
vec_rotate(&my->x, &player->pan);
vec_add(&my->x, &player->x);
VECTOR vDir;
vec_for_angle(&vDir, &camera->pan);
vec_scale(&vDir, -my->skDistance);
VECTOR vTarget;
vec_set(&vTarget, &my->x);
vec_add(&vTarget, &vDir);
you = player;
var nDist = c_trace(&my->x, &vTarget, IGNORE_YOU | IGNORE_PASSABLE | USE_BOX);
if (nDist > 0)
my->skDistSoft += (nDist - my->skDistSoft) * time_step;
else
my->skDistSoft += (my->skDistance - my->skDistSoft) * time_step;
vec_normalize(&vDir, my->skDistSoft);
vec_set(&camera->x, &my->x);
vec_add(&camera->x, &vDir);
wait(1);
}
ent_remove(me);
}
#define skPan skill1
#define skAngle skill2
#define skMoveX skill3
#define skMoveY skill4
#define skMoveZ skill5
action actPlayer () {
player = me;
ent_create(NULL, &my->x, actCameraCollider);
wait(1);
my->eflags |= FAT | NARROW;
vec_set(&my->max_x, vector(16, 16, 32));
vec_set(&my->min_x, vector(-16, -16, -32));
my->skPan = 0;
my->skMoveZ = 0;
while (me == player) {
my->skPan = ang(my->skPan - mickey.x * 0.2);
my->skAngle = ang(my->skPan - my->pan) * time_step;
c_rotate(me, vector(my->skAngle, 0, 0), IGNORE_PASSABLE | GLIDE);
my->skMoveX = key_w - key_s;
my->skMoveY = key_a - key_d;
vec_normalize(&my->skMoveX, time_step * 10);
c_move(me, &my->skMoveX, NULL, IGNORE_PASSABLE | GLIDE);
wait(1);
}
ent_remove(me);
}
void main () {
video_mode = 10;
fps_max = 60;
wait(1);
level_load("level.wmb");
camera->clip_near = 1;
ent_create("player.mdl", vector(100, 100, 32), actPlayer);
while(!key_esc)
wait(1);
player = NULL;
wait(1);
sys_exit(NULL);
}
|
|
|
Re: Camera passing through wall
[Re: Ruben]
#471227
02/24/18 03:18
02/24/18 03:18
|
Joined: Jun 2010
Posts: 590 California
Ruben
OP
User
|
OP
User
Joined: Jun 2010
Posts: 590
California
|
Hello Txesmi. I tried using just your code, without using my code at all. It seems to work great, except if I turn quickly with my mouse. If I turn somewhat slow to medium speed, the camera stays within the wall while turning. If I turn quickly, I can see the blue past the wall for a split moment, before the camera moves back within the wall.
I am sure if I edit and tweek it as needed, that blue will disappear. This is just the first try with the code as it is, with no changes. Thank you.
Last edited by Ruben; 02/24/18 03:20.
|
|
|
Re: Camera passing through wall
[Re: Ruben]
#471229
02/24/18 09:25
02/24/18 09:25
|
Joined: Jun 2010
Posts: 590 California
Ruben
OP
User
|
OP
User
Joined: Jun 2010
Posts: 590
California
|
Okay. I changed some of the bounding box and camera location vec_set numbers in Txesmi's code to try and fit what I hope to have for my game. I probably should have mentioned this before, but I prefer the player model to be in between the left side of the screen and screen center, kind of like the video game "Dead Space". To do this, I changed:
vec_set(&my->skOffsetX, vector(0, -7, 35)); // CENTER BEHIND PLAYER
to
vec_set(&my->skOffsetX, vector(0, -27, 65)); // PLAYER IS BETWEEN
// LEFT SIDE OF
// SCREEN AND SCREEN
// CENTER.
Because I changed the location of the player to this location, I am now getting the same bug in Txesmi's code as I got in my original code shown in the beginning of this thread. The camera is again passing through the wall when the player pan rotates left close to a wall and its back starts facing the wall while turning, until it gets to about center, and then moves back inside the wall like it should for the remainder of the turn.
Last edited by Ruben; 02/24/18 09:30.
|
|
|
Re: Camera passing through wall
[Re: Ruben]
#471230
02/24/18 11:14
02/24/18 11:14
|
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
|
Ok, I understand. That happens because the camera rotation center is orbiting out of player collision bounds and the trace starts cutting or in the other side of the wall so it does not collide. You might trace from a 'safe' point inside the player bounds to the hypothetical final position of the camera. But it will shake the whole projection for sure. Hard to be softened. I have not the clue.(not really) You might prevent the player get close to walls edited____________________________
#include <acknex.h>
#define PRAGMA_PATH "%EXE_DIR%\templates\models"
#define skOffsetX skill1
#define skOffsetY skill2
#define skOffsetZ skill3
#define skDistance skill4
#define skDistSoft skill5
#define skDirX skill6
#define skDirY skill7
#define skDirZ skill8
#define skTargetX skill9
#define skTargetY skill10
#define skTargetZ skill11
#define skOriginX skill12
#define skOriginY skill13
#define skOriginZ skill14
#define skCenterX skill15
#define skCenterY skill16
#define skCenterZ skill17
action actCameraCollider () {
proc_mode = PROC_LATE;
wait(1);
my->flags |= INVISIBLE | PASSABLE;
my->eflags = FAT | NARROW;
vec_set(&my->max_x, vector(8, 8, 8));
vec_set(&my->min_x, vector(-8, -8, -8));
vec_set(&my->skOriginX, vector(0, -5, 32));
vec_set(&my->skOffsetX, vector(0, -60, 40));
my->skDistance = 200;
my->skDistSoft = my->skDistance;
my->parent = player;
while (my->parent == player) {
my->skDistance = clamp(my->skDistance + mickey.z * 0.3, 20, 400);
camera->pan = player->pan;
camera->tilt = clamp(camera->tilt - mickey.y * 0.2, -80, 45);
vec_set(&my->pan, &player->pan);
vec_set(&my->x, &my->skOriginX);
vec_rotate(&my->x, &player->pan);
vec_add(&my->x, &player->x);
vec_set(&my->skCenterX, &my->skOffsetX);
vec_rotate(&my->skCenterX, &player->pan);
vec_add(&my->skCenterX, &player->x);
vec_for_angle(&my->skDirX, &camera->pan);
vec_scale(&my->skDirX, -my->skDistance);
vec_set(&my->skTargetX, &my->skCenterX);
vec_add(&my->skTargetX, &my->skDirX);
you = player;
var nDist = c_trace(&my->x, &my->skTargetX, IGNORE_YOU | IGNORE_PASSABLE | USE_BOX);
if (nDist > 0)
my->skDistSoft += (nDist - my->skDistSoft) * time_step * 2;
else
my->skDistSoft += (my->skDistance - my->skDistSoft) * time_step * 2;
vec_diff(&my->skDirX, &my->skTargetX, &my->x);
vec_normalize(&my->skDirX, my->skDistSoft);
vec_set(&camera->x, &my->x);
vec_add(&camera->x, &my->skDirX);
wait(1);
}
ent_remove(me);
}
#define skPan skill1
#define skAngle skill2
#define skMoveX skill3
#define skMoveY skill4
#define skMoveZ skill5
action actPlayer () {
player = me;
ent_create(NULL, &my->x, actCameraCollider);
wait(1);
my->eflags |= FAT | NARROW;
vec_set(&my->max_x, vector(16, 16, 32));
vec_set(&my->min_x, vector(-16, -16, -32));
my->skPan = 0;
my->skMoveZ = 0;
while (me == player) {
my->skPan = ang(my->skPan - mickey.x * 0.2);
my->skAngle = ang(my->skPan - my->pan) * time_step * 2;
c_rotate(me, vector(my->skAngle, 0, 0), IGNORE_PASSABLE | GLIDE);
my->skMoveX = key_w - key_s;
my->skMoveY = key_a - key_d;
vec_normalize(&my->skMoveX, time_step * 10);
c_move(me, &my->skMoveX, NULL, IGNORE_PASSABLE | GLIDE);
wait(1);
}
ent_remove(me);
}
void main () {
video_mode = 10;
fps_max = 60;
wait(1);
level_load("level.wmb");
camera->clip_near = 1;
ent_create("player.mdl", vector(100, 100, 32), actPlayer);
while(!key_esc)
wait(1);
player = NULL;
wait(1);
sys_exit(NULL);
}
Last edited by txesmi; 02/24/18 11:45.
|
|
|
Moderated by mk_1, Perro, rayp, Realspawn, Rei_Ayanami, rvL_eXile, Spirit, Superku, Tobias, TSG_Torsten, VeT
|