distance between line <-> point?

Posted By: Germanunkol

distance between line <-> point? - 08/07/09 08:22

Hi,
I have a huge sun entity in my level. It is passable and it can damage the spaceships by using a vec_dist(sun.x,ship.x) command to see if the ship is too close.
I also have a scanner system on the users HUD. He can scan for enemies who are within his range. Now I have two issues:

a) If there's something in the way (between player ship and enemy), the player should not be able to "see" the enemy on his scanner, meaning he can't target him either. With asteroids, it's no problem, I send a c_trace outand if it gets blocked I disable the targeting. The problem is with the sun: since it's passable, the trace doesn't hit anything. Can anyone think of a way of checking if the c_trace passed within XY quants of the sun's origin? I know about line-point calculation, but I'd like to see if there's a simpler trick.

b) For the commands "next enemy" and "previous enemy", I currently just "scroll" through an array and return the next/previous entry. Problem here is that I don't yet know how many enemies there will be at the end, and will never know, cause players can buy more objects that are also seens as enemies. So I was thinking if anyone had a doubly-linked-listed coded? You know... re-inventing the wheel and stuff.
Or can anyone think of simpler solutions?
I want to be able to add to that list (when a new enemy joins the battlefield) or remove enemies from the list, I also need to clear it somehow at the end of a round.
Posted By: EvilSOB

Re: distance between line <-> point? - 08/07/09 09:41

A couple of ideas spring to mind for A)

1> How about when you do the scanner c_scan, set the sun NON-passable for the duration of the scan.

2> Change the scanner "c_scan" to INCLUDE passable objects.

B) Do a deep scan of the "Lite-C Contributions" forum for "linked-list". There IS one in there somewhere... Maybe 6 months back I think?
Posted By: Germanunkol

Re: distance between line <-> point? - 08/07/09 09:53

sorry, the scanner's not using a c_scan... I just call it scanner. I'm using c_trace. Still, the solutions seem to be similar.
setting the sun non-passable and then back to passable: will that hurt any other c_move? and how about frame rate etc? is it fast? cause then this would be a great and simple idea.

linked list -> will do. exactly what I'm looking for. Do you remember if it's double-linked though? it wouldn't be terrible if not, it would just simplify things.
Posted By: Claus_N

Re: distance between line <-> point? - 08/07/09 10:02

a) Do you need to use IGNORE_PASSABLE in your trace code? smile

b) Yeah, a linked list does indeed sound like the best solution, and shouldn't be too hard making smile
Posted By: Saturnus

Re: distance between line <-> point? - 08/07/09 11:15

Hello!

A code with various vector functions (including distance between point/line, point/line segment etc.):
vec3d

A doubly linked list:
list

vec3d uses own vector structs, because the range of var is too limited for some operations.

Sorry, I can't give you more info about this at the moment, as I'm at work. However it's pretty well documented (in german) and I'm back at home this evening if you have any questions or problems.

Hope this helps. : )
Posted By: boyax

Re: distance between line <-> point? - 08/07/09 11:47

@Kombucha:
Do you have english translation for the comments? If it's possible anyway... I'm interested with this & I'll give it a try.. Sorry, I can't understand german.

Cheers!:)
Posted By: Saturnus

Re: distance between line <-> point? - 08/07/09 14:34

@boyax
I've translated the header files to clumsy English. All structs and global functions are documented there. If you just want to use the code this should be sufficient, I hope. : )
vec3d_en
list_en
Posted By: Germanunkol

Re: distance between line <-> point? - 08/07/09 15:37

I got it to work!

Thank you very, very much. The player can now hide behind the sun, without being target-able (is that even a word?).
Awesome License :P... never heard of that one before. Had to google it first.

I really missed "ll_sphere3d_initialize"
and "ll_line3d_initialize"
functions... it took me a while to understand that I can't do line.from = ll_vector3d_1; because the from and to in the ll_line3d aren't pointers...

also, this gives me a "wrong number/type of parameters":
vec_set(temp,vector(sunEnt.x,sunEnt.y,sunEnt.z));
ll_vec3d_set(ll_sunPos,temp);
even though I did
#define acknex_h
and have acknex.h included.
What's wrong with my code there?
Posted By: Saturnus

Re: distance between line <-> point? - 08/07/09 18:04

Originally Posted By: germanunkol
also, this gives me a "wrong number/type of parameters":
vec_set(temp,vector(sunEnt.x,sunEnt.y,sunEnt.z));
ll_vec3d_set(ll_sunPos,temp);
even though I did
#define acknex_h
and have acknex.h included.
What's wrong with my code there?

Normally the lite-C compiler automatically detects if a variable has to be passed by value or by reference. However, this does not work for overloaded functions, so you have to use the address operator here for your local structs:
Code:
LL_VECTOR3D ll_sunPos;
VECTOR temp;
...
vec_set(temp,vector(sunEnt.x,sunEnt.y,sunEnt.z));
ll_vec3d_set(&ll_sunPos, &temp); // using address operators is necessary here


Of course you can omit the &-operator for "ll_sunPos" if this vector is global.

Quote:
I really missed "ll_sphere3d_initialize" and "ll_line3d_initialize" functions...

Yes, good idea. I'll add those functions. : )
Posted By: Germanunkol

Re: distance between line <-> point? - 08/07/09 19:02

I am so stupid. I was using the line-Sphere intersection all along, when i should have been using the segment-sphere command.

Anyways, I build a nice little app to show you the "bug", and while posting, I realized my stupidity.
If you want the app to showcase your code, here it is. simply save it as test.c into the same folder as vec3d.c, and run it.

left click -> place first line point
right click -> place second line point
mouse wheel -> change radius

It works great, but I'm stupid... I just spent 2 hours trying to figure out why it didn't work right. maybe even longer.

Code:
#include <acknex.h>
#include <default.c>

#include "vec3d.c";


VECTOR vec1;
VECTOR vec2;
VECTOR vec3;

VECTOR temp;

LL_SPHERE sphere;
LL_LINE3D line;

STRING* toWrite = "#30";

int isIntersecting = OFF;

var radius = 100;

VECTOR center;

void draw_circle(VECTOR* pos, var radius)
{
	var angle = 0;
			vec_set(temp,vector(radius*cos(angle),radius*sin(angle),0));
		vec_add(temp,center);
	draw_line(temp,NULL,0);
	draw_line(temp,vector(255,255,255),100);
	
	while(angle <= 360)
	{
		vec_set(temp,vector(radius*cos(angle),radius*sin(angle),0));
		vec_add(temp,center);
		draw_line(temp,vector(255,255,255),100);
		angle += 10;
	}
}

void draw_info()
{
	while(1)
	{
		str_for_num(toWrite,vec1.x);
		draw_text(toWrite,20,20,vector(255,255,255));
		str_for_num(toWrite,vec1.y);
		draw_text(toWrite,20,40,vector(255,255,255));
		str_for_num(toWrite,vec1.z);
		draw_text(toWrite,20,60,vector(255,255,255));
		
		str_for_num(toWrite,vec2.x);
		draw_text(toWrite,20,80,vector(255,255,255));
		str_for_num(toWrite,vec2.y);
		draw_text(toWrite,20,100,vector(255,255,255));
		str_for_num(toWrite,vec2.z);
		draw_text(toWrite,20,120,vector(255,255,255));
		
		str_for_num(toWrite,vec3.x);
		draw_text(toWrite,20,140,vector(255,255,255));
		str_for_num(toWrite,vec3.y);
		draw_text(toWrite,20,160,vector(255,255,255));
		str_for_num(toWrite,vec3.z);
		draw_text(toWrite,20,180,vector(255,255,255));
				str_for_num(toWrite,mouse_pos.x);
		draw_text(toWrite,20,280,vector(255,255,255));
				str_for_num(toWrite,mouse_pos.y);
		draw_text(toWrite,20,300,vector(255,255,255));
		
		if(isIntersecting)
		draw_text("Intersect",20,200,vector(255,255,255));
		else
		draw_text("Don't intersect",20,200,vector(255,255,255));
		
		vec_set(temp,vec2);vec_add(temp,center);
		
		draw_line(temp,NULL,100);
		draw_line(temp,vector(255,255,255),100);
		
		vec_set(temp,vec3);vec_add(temp,center);
		draw_line(temp,vector(255,255,255),100);
		
		draw_circle(vec1,radius);
		wait(1);
	}
}


void setfirst()
{
	vec2.x = mouse_pos.x - center.x;
	vec2.y = mouse_pos.y - center.y;
}

void setsecond()
{
	vec3.x = mouse_pos.x - center.x;
	vec3.y = mouse_pos.y - center.y;
}


void main()
{
	vec_set(vec1,vector(0,0,0));
	vec_set(vec2,vector(0,0,0));
	vec_set(vec3,vector(0,0,0));
	vec_set(center,vector(screen_size.x/2,screen_size.y/2,0));
	
	mouse_mode = 4;

	on_mouse_left = setfirst;
	on_mouse_right = setsecond;


	draw_info();

	while(1)
	{
		radius += mickey.z*time_step*5;
		sphere.pos.x = vec1.x;sphere.pos.y = vec1.y;sphere.pos.z = vec1.z;
		sphere.radius = radius;
		line.from.x = vec2.x;line.from.y = vec2.y;line.from.z = vec2.z;
		line.to.x = vec3.x;line.to.y = vec3.y;line.to.z = vec3.z;
		
		isIntersecting = ll_vec3d_lineSphereIntersect(line, sphere);
		wait(1);
	}
}


Posted By: Saturnus

Re: distance between line <-> point? - 08/07/09 20:06

Thank you for this example, Germanunkol!

Up to now I have used these vector functions only to select edges/lines with the mouse cursor. However it was possible to do some simple obstacle avoidance with them as well. : )

Now I have added initialization functions for spheres and lines/line segments:
vec3d (09AUG07)

ll_line3d_set()
ll_sphere_set()

They are overloaded like ll_vec3d_set(), so you can pass LL_VECTOR3D, VECTOR or individual values.

I have modified the while loop from your example and implemented the initialization functions:
Code:
while(1)
{
	radius += mickey.z*time_step*5;
	ll_sphere_set(&sphere, &vec1, (ll_vec3dtype)radius);
	ll_line3d_set(&line, &vec2, &vec3);
	isIntersecting = ll_vec3d_segSphereIntersect(line, sphere);
	wait(1);
}



BTW: In my previous post I mistakenly wrote that "you can omit the &-operator for 'll_sunPos' if this vector is global". What I actually meant was, that you can omit this operator if 'll_sunPos' is a pointer.
Posted By: Germanunkol

Re: distance between line <-> point? - 08/07/09 20:25

Great, thank you smile

I changed the "line" to segment in my code, and it works like a charm now. No targeting if the sun's in the way.
Posted By: Saturnus

Re: distance between line <-> point? - 08/07/09 21:34

That's nice to hear. : )

Please let me know if you have suggestions for impovements or if you encounter any bugs.
Posted By: Germanunkol

Re: distance between line <-> point? - 08/08/09 19:45

suggestions:
idea behind these is that I want to add entities to a list.
given any one entity I want to then find the next and the previous entity in the list easily. Sorry, I don't see a way of doing it without these functions

//change this to return the index of the newly added element:
int ll_list_add(LL_LIST* self, void* data);

//returns the element with the current index
//returns NULL if element with index not found.
LL_LIST_ELEM* ll_list_find(LL_LIST* self, int index);

//of course the second function would require that the object is not yet in the list.

the implementation I would then use would be something like this:
Code:
my.listIndex = ll_list_add(ll_entity_list, my );
//...
//...
LL_LIST_ELEM* currentElement;
currentElement = ll_list_find(targetEnt.listIndex);

while(currentElement != NULL)
{
   if(isMyEnemey(currentElement.data) == ON) break;
   currentElement = currentElement.next;
}
if(currentElement != NULL)
targetEnt = currentEnt.data;



Or is there some easier way?

Posted By: Saturnus

Re: distance between line <-> point? - 08/08/09 21:48

Lets see if i have fully understood what you want to achieve here. : )

Code:
//returns the element with the current index
//returns NULL if element with index not found.
LL_LIST_ELEM* ll_list_find(LL_LIST* self, int index);


This function is already implemented:
LL_LIST_ELEM *ll_list_getNth(LL_LIST *self, int index)

Code:
//change this to return the index of the newly added element:
int ll_list_add(LL_LIST* self, void* data);


According to my changelog this function should be overloaded (so you can either pass a list element or a void* as second parameter) and return a pointer to the added element. However, this is not the case obviously.^^

I've re-implemented this now: list 09AUG08

So you can use ll_list_add() like this:
Code:
// 1)
elem = ll_lelem_create(data);
ll_list_add(list, elem);

// 2) directly adds the data
// element is created internally and returned by the function
elem = ll_list_add(list, data);


As ll_list_add() appends elements at the end of the list the index of the added element will always be list->count - 1. So it's not necessary to return an elements index.

In your code you store the index of the list element in which an entity is contained. However, it would be better to store a pointer to the element instead. This would be faster (static instead of linear complexity). Also the index of an element can change, if elements are inserted in or removed from the list.

Does this answer your question?
Posted By: Germanunkol

Re: distance between line <-> point? - 08/09/09 20:32

"Does this answer your question?"

It does, but only if I can put that pointer into a skill of an entity? then all of this won't be a problem...
Posted By: Saturnus

Re: distance between line <-> point? - 08/09/09 21:04

Quote:
It does, but only if I can put that pointer into a skill of an entity?

Yes, you can.
I regularly do this to associate entities with structs.

entity->listElem = ll_list_add(entity_list, (void *)enity);
elem = entity->listElem;

Works fine. : )
Posted By: Germanunkol

Re: distance between line <-> point? - 08/10/09 08:07

great!
I had never thought of doing this...

yes, then all of this works. I don't even think I'll need an index any more (an index changes, after all, when I remove a part of the list... doesn't it?).

I'll just work with .next and .prev to scroll through the list and return the previous and the next target. Thank you again!
Posted By: Saturnus

Re: distance between line <-> point? - 08/10/09 09:30

Quote:
yes, then all of this works. I don't even think I'll need an index any more (an index changes, after all, when I remove a part of the list... doesn't it?).

Yes, when adding or removing an element, the indices of all following elements will change. Searching list elements by their index (and in general) is slow anyway, as you have only sequential access to them. So to access list elements randomly, storing pointers to them is the best and fastest way.
Posted By: Germanunkol

Re: distance between line <-> point? - 08/10/09 20:33

grrr, I'm sorry, but I can't figure this out.

I create the list like this:

LL_LIST* ll_objectList = NULL; //global
//...
if(ll_objectList == NULL) ll_objectList = ll_list_create();
else ll_list_clear(ll_objectList,NULL);

in the entity function, I call this at the beginning:
my.objectListElement = ll_list_add(ll_objectList,(void*) my);

and this at the end:
ll_list_remove(ll_objectList,my.objectListElement,NULL);

but it gives me a "crash in ll_list_remove".

I also tried:
LL_LIST_ELEM* ll_objectTempElem = NULL;
//...
ll_objectTempElem = my.objectListElement;
ll_list_remove(ll_objectList,ll_objectTempElem,NULL);

But it says the same thing.
I'm probably doing something stupid again... sorry frown
Posted By: Saturnus

Re: distance between line <-> point? - 08/10/09 21:04

No, your code is fine.

It's me who did something wrong here: the reimplemented ll_list_add() function had a wrong return value. I missed this, as I don't use this return value in my codes yet.

Here is the fix: list 09AUG10

Sorry for this!
Posted By: Germanunkol

Re: distance between line <-> point? - 08/12/09 06:50

Thanks, got it to work smile
© 2024 lite-C Forums