|
|
Calling all TRIG nuts. Got a wobbley one for you!
#256085
03/14/09 15:53
03/14/09 15:53
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
Sorry I cant get a picture up, but Hey, Im too lazy to get an image provider..
Close your eyes and picture this. (open your eyes now, you need them to read silly!)
Somewhere above or below the Z plane (Z=zero) you have a point in space. It is NOT an entity, just a position in world co-ordinates stored in a vector.
NOW, somewhere below or above (possibly even on the same side of the Z plane) you have another point in space. Again it is NOT an entity, just a position in world co-ordinates stored in a vector.
NOW, draw a mental line of infinite length between those two points. See it? Its a red line I think...
What I need to know from you guys is this, what fast-response trig do I need to use to find the X and Y co-ordinate of where that line CROSSED the Z plane. Also some type of error-recognition for when it doesnt cross the plane but stays parallel or is just a single point, dont need to know why, just valid/invalid.
If need be, I can guarentee at both points are on opposite sides if its necessary, but Id rather avoid that guarentee if I can.
Thanks in advance to any who dare take the challenge.
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: Calling all TRIG nuts. Got a wobbley one for you!
[Re: Tobias]
#256134
03/14/09 20:18
03/14/09 20:18
|
Joined: Mar 2009
Posts: 112 Germany
KDuke
Member
|
Member
Joined: Mar 2009
Posts: 112
Germany
|
Wouldn't vec_lerp get you a point somewhere between p1 and p2? For checking if the resulting line is intersecting with the Z-Plane you simply have to test if p1.z - p2.z is zero. If so the line is parallel to the Z plane and no further check is needed except if p1.z = 0 AND p2.z = 0. That would mean it is parallel to the Z plane and is lying on it so you'll have infinite intersection points.
Well lets see. To get the intersection... really i gotta look that up!
Using A7 Free Click and join the 3dgs irc community! Room: #3dgs
|
|
|
Re: Calling all TRIG nuts. Got a wobbley one for you!
[Re: KDuke]
#256144
03/14/09 21:35
03/14/09 21:35
|
Joined: Mar 2009
Posts: 112 Germany
KDuke
Member
|
Member
Joined: Mar 2009
Posts: 112
Germany
|
Oops Tobias... you said it would be the middle X-D Though the middle between the point isn't necessarily the intersection with the Z plane! Ok lets get going! First of you need the line. A line is described as a point and a direction vector. We'll take p1 as the point. Ok now we need the direction vector which should be normalized. That would be: (p1-p2)/sqrt((p1-p2)²) which we call pv now! Ok now we can describe every point on the line(which we call pl now) with pl = p1 + lambda * pv Or for every element of the line: pl.x = p1.x + lambda*pv.x pl.y = p1.y + lambda*pv.y pl.z = p1.z + lambda*pv.z Alright. The point where the line intersects is where pl.z = 0. This means if we put that into the formular pl.z = p1.z + lambda*pv.z we can get lambda. We just need to rearrange the formular to lambda. this is what I do to rearrange the formula | v 0 = p1.z + lambda*pv.x | -p1.z -p1.z = lambda*pv.x | /pv.x -p1.z/pv.x = lambda Ok! now we can put everything together. And to make your life easier here is the complete formula in code-form.
vector Intersection;
vector point1 = whatever1;
vector point2 = whatever2;
Intersection.x = point1.x + (-point1.z/((point1.x-point2.x)/sqrt((point1.x-point2.x)*(point1.x-point2.x)))*((point1.x-point2.x)/sqrt((point1.x-point2.x)*(point1.x-point2.x)));
Intersection.y = point1.y + (-point1.z/((point1.y-point2.y)/sqrt((point1.y-point2.y)*(point1.y-point2.y)))*((point1.y-point2.y)/sqrt((point1.y-point2.y)*(point1.y-point2.y)));
Intersection.z = 0;
I really hope I did no mistake kind regards KDuke
Using A7 Free Click and join the 3dgs irc community! Room: #3dgs
|
|
|
Re: Calling all TRIG nuts. Got a wobbley one for you!
[Re: KDuke]
#256161
03/15/09 00:12
03/15/09 00:12
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
Errr, thanks KDuke, that will help once Ive crammed it all into my head. I think I'll need to get a bigger one!
I dont understand it yet, as it will take several readings and more coffee, but thank you for the in-depth, step by step tutorial. It WILL help me re-learn some of the things Ive forgotten since school.
BUT, the final 'formula' is pretty huge and evil. Do you (or anyone else) know of a way this formula can be simplified using 3dgs (vector) functions? (Simplified can mean more lines, but more 3dgs-functions)
I'll look at that once Ive understood whats actually being done, but shortcuts supplied by other people are always appreciated.
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: Calling all TRIG nuts. Got a wobbley one for you!
[Re: EvilSOB]
#256184
03/15/09 07:26
03/15/09 07:26
|
Joined: Mar 2009
Posts: 112 Germany
KDuke
Member
|
Member
Joined: Mar 2009
Posts: 112
Germany
|
Well I can take a look at the 3dgs vector functions! Most probably it will be possible to shorten it with them.
Just give me some minutes.
Using A7 Free Click and join the 3dgs irc community! Room: #3dgs
|
|
|
Re: Calling all TRIG nuts. Got a wobbley one for you!
[Re: EvilSOB]
#256185
03/15/09 07:27
03/15/09 07:27
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
No go KDude, it doesnt appear to work. I lightly "suspect" a flaw in your logic, but is the my attempt to implement your formulae, but its bad  I cant explain what its doing wrong, because I cant tell what it is actually doing, but hopefully someone can. This action is supposed to keep its entity directly (visibly) under the mouse, but always positioned at ZERO on the world Z axis. (no matter what the camera's position and rotation are[and NOT changing them]) I will be very appreciative of anyones help with this. action place_block()
{
VECTOR Intersection, point1, point2;
while(me)
{
vec_set(point1, vector(mouse_pos.x,mouse_pos.y,0));
vec_for_screen(point1, camera); //start point, Z always above Zero
vec_set(point2, vector(mouse_pos.x,mouse_pos.y,200000));
vec_for_screen(point2, camera); //end point, Z almost always below Zero
if(point1.z!=point2.z)
{
Intersection.x = point1.x + (-point1.z/((point1.x-point2.x)/sqrt(point1.x-point2.x)*(point1.x-point2.x)))*((point1.x-point2.x)/sqrt((point1.x-point2.x)*(point1.x-point2.x)));
Intersection.y = point1.y + (-point1.z/((point1.y-point2.y)/sqrt(point1.y-point2.y)*(point1.y-point2.y)))*((point1.y-point2.y)/sqrt((point1.y-point2.y)*(point1.y-point2.y)));
Intersection.z = 0;
vec_set(my.x, Intersection); //position entity on the Zero plane, under mouse.
}
/////////////// DEBUG
draw_line(point1.x, vector(128,128, 0), 100);
draw_line(point2.x, vector(128,128,255), 100);
/////////////// DEBUG
wait(1);
}
}
[EDIT] Ive been typing this post for half hour, Im not trying to rush you by posting this straight after your last post...
Last edited by EvilSOB; 03/15/09 07:28.
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: Calling all TRIG nuts. Got a wobbley one for you!
[Re: EvilSOB]
#256188
03/15/09 07:46
03/15/09 07:46
|
Joined: Sep 2003
Posts: 928
Spirit

Moderator
|

Moderator
Joined: Sep 2003
Posts: 928
|
Thats a very simple thing, what for do you need all this bunch of mathematics? Just use vec_lerp. The lerp factor for a point at z=0 is -z1/(z2 - z1). When this lerp factor is less than 0, or above 1, then the line does not intersect the z plane at all. If it is between 0 and 1 then the line intersects the z=0 plane and you can calculate the intersection point xy with vec_lerp, as already written by Tobias: VECTOR intersection; var lerpfactor = -p1.z/(p2.z - p1.z); if (lerpfactor > 0 && lerpfactor < 1) vec_lerp(intersection,p1,p2,lerpfactor); else printf("No intersection!"); Mathematics is very easy! 
|
|
|
Re: Calling all TRIG nuts. Got a wobbley one for you!
[Re: KDuke]
#256191
03/15/09 08:18
03/15/09 08:18
|
Joined: Mar 2009
Posts: 112 Germany
KDuke
Member
|
Member
Joined: Mar 2009
Posts: 112
Germany
|
Alright! Here is a complete function which ` should` give you the intersection point! That is if I did everything right. Haven't really tested it!
// as we want the vector as returning value we still
// need a simple int value for checking IF there was an intersection
typedef struct INTERCHECK
{
int doesIntersect;
VECTOR intersectionPoint;
}INTERCHECK;
INTERCHECK getLineZPlaneIntersect(VECTOR point1, VECTOR point2)
{
vector Intersection; //this one will hold the intersection point between
vector pv; //this vector will hold the direction vector for the line.
vector pl; //and this one is for the line.
double lambda = 0; //this is the scalar we need to get the intersection point.
INTERCHECK result;
vec_diff(pv, point1, point2); //getting the difference between the two given points and put it into pv.
vec_normalize(pv, 1); //this scales the vector to have a length of 1 but it keeps it's direction
if(pv.z == 0) //if the direction vector has no z-value it is parallel to the Z plane
{
//but we still have to check if it EXACTLY lying on the Z plane
if(point1.z == 0 && point2.z == 0)
{
result.doesIntersect = false;
return result;
}
}
//Okay. as we made it past the parallel-check the line does intersect
//with the Z plane. Lets get the point.
lambda = -point1.z/pv.x; // alright now we have the scalar needed to calculate the freakin intersection point.
vec_scale(pv, lambda); // scaling the direction vector by the scalar value to get the right length.
//now we only need to add the scaled direction vector to the origin point.
vec_set(Intersection, point1); // this one isn't really needeb but makes things clear.
vec_add(Intersection, pv);
//To be really sure we check if Intersection.z == 0. Otherwise this ain't an intersection with the Z plane
if(!(Intersection.z == 0))
{
result.doesIntersect = false; //ok! this is bad something went wrong if it come to this line!
return result;
}
else
{
result.doesIntersect = true;
result.intersectionPoint = Intersection;
return result;
}
}
Here is an example:
function whatever()
{
VECTOR myFirstPoint = vector(1, 5, -3);
VECTOR mySecondPoint = vector(3, 1, -9);
INTERCHECK intersectData = getLineZPlaneIntersect(myFirstPoint, mySecondPoint);
if(intersectData.doesIntersect)
{
printf("I got an Intersection at x = %2.3f, y = %2.3f, z = %2.3f!",
intersectData.intersectionPoint.x,
intersectData.intersectionPoint.y,
intersectData.intersectionPoint.z);
}
else
printf("There is no intersection!");
}
kind regards KDuke
Using A7 Free Click and join the 3dgs irc community! Room: #3dgs
|
|
|
Re: Calling all TRIG nuts. Got a wobbley one for you!
[Re: KDuke]
#256219
03/15/09 12:07
03/15/09 12:07
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
Thank you both KDuke and spirit, but I cant check either solution yet, because the code generating my two points is stuffed. So Im going to go away and fix THAT before I post any more replies...
spirit: This looks promising, I dont understand lerp at all so I'll take your word on it. As I thought, there would be a 3dgs function to trim away a lot of KDukes "real world" mathematics.
KDuke: Thanks again for the intensive answer, and I apologies that my faulty source data may have made me imply you solution was at fault. But spirits solution looks more promising than yours, cause this code needs to be slim as it will be run every single frame. Thanks again all the same.
Once Ive fixed my source-points code, I'll post again with the results of my attempts you use these solutions.
Thanks again all....
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
|