ENIGMA Forums

Outsourcing saves money => Issues Help Desk => Topic started by: polygone on May 20, 2012, 08:56:59 PM

Title: Path trouble
Post by: polygone on May 20, 2012, 08:56:59 PM
Harri, can you add in the functions surface_destroy (which is missing) and path_get_position?
Title: Re: Path trouble
Post by: TheExDeus on May 21, 2012, 08:36:03 AM
Quote
surface_destroy (which is missing)
Its called surface_free in both GM and ENIGMA. It was briefly called surface_destroy() in ENIGMA (until I found this mistake). If you want, then you can create a macro or a wrapper so you can use surface_destroy() as well, but I think we should standardize and use one whenever possible (this case _free, for compatibility with GM). We could also add both functions, but document only _destroy() and leave _free() undocumented for GM compatibility.

Quote
path_get_position
And what would it return? The 0-1 position on the path? But path_position is part of the object struct you created, so you might as well create the function. I don't use or save any variables between frames, so I don't have any "position" I could return.
Title: Re: Path trouble
Post by: polygone on May 21, 2012, 10:23:02 AM
Quote
surface_destroy (which is missing)
Its called surface_free in both GM and ENIGMA. It was briefly called surface_destroy() in ENIGMA (until I found this mistake). If you want, then you can create a macro or a wrapper so you can use surface_destroy() as well, but I think we should standardize and use one whenever possible (this case _free, for compatibility with GM). We could also add both functions, but document only _destroy() and leave _free() undocumented for GM compatibility.
Oh I didn't realise, it was with testing a game that you previously made so that will explain it as I presume you used the wrong name with it (note you might want to update some of your edc game files). But yeah there should probably still be a wrapper for surface_destroy to surface_free.

Quote
Quote
path_get_position
And what would it return? The 0-1 position on the path? But path_position is part of the object struct you created, so you might as well create the function. I don't use or save any variables between frames, so I don't have any "position" I could return.
It was thinking of path_get_point_position(ind,n) much like the other path_get_point_* functions. But when actually looking at it, I see this wouldn't be nice to do.
Title: Re: Path trouble
Post by: polygone on May 21, 2012, 05:32:20 PM
me again

Unfortunately I've encountered an issue with the path_get_x/y functionality. I'm using this value:

Code: [Select]
v = path_get_x(pth, 24/path_get_length(pth)) - path_get_x(pth, 0)
//to note the path length is around 13500, which is roughly the same in GM and ENIGMA

The place it's checking is completely flat (y values are same) so it should be returning 24 and it does in GM, but in ENIGMA it is returning completely wrong like 2.322
Title: Re: Path trouble
Post by: TheExDeus on May 21, 2012, 06:35:06 PM
Not sure what you mean. Position argument in get_x function should be from 0 to 1, so I am not sure why you do 24/get_length. Maybe make an example? I know that there are some problems with get_x and get_y functions (they don't match GM's exactly), but the difference shouldn't be that big.
Title: Re: Path trouble
Post by: polygone on May 21, 2012, 07:01:08 PM
Not sure what you mean. Position argument in get_x function should be from 0 to 1, so I am not sure why you do 24/get_length. Maybe make an example? I know that there are some problems with get_x and get_y functions (they don't match GM's exactly), but the difference shouldn't be that big.
24/get_length is between 0 and 1, it's 24/13500 which is 0.001846

I'm using that as it should be get the x position 24 pixels from the start, but it's returning 2.322 pixels from the start. I'll make an example though.

EDIT: Here is example https://www.box.com/s/b882e87a7eb210ae7b86
What I'm trying to achieve is draw a line of length 24 along the path, I cannot think of another way of doing it.
Title: Re: Path trouble
Post by: TheExDeus on May 23, 2012, 02:53:23 AM
Looking at the example I must say that it is normal. I didn't think you have a path that is so long. On very long paths this difference is a lot bigger. If you make it go around the path at constant speed, then you will see that it will slow down at times and go faster at other times, that is what creates this error. Me and Josh were not able to fix that problem, as theoretically (mathematically and code wise) everything should be fine. Maybe I will look at it again at some point. Basically, the problem arises (I think) from wrong length calculation. I need to calculate the length of each segment and then divide by total to get the position on where one segment ends and another begins, and while I tried 3 different algorithms for that (which returned almost the same values) I still was not able to fix that problem... maybe the problem is somewhere else then. I won't have time to look into this for a few weeks now (need to do my thesis).

edit: Poly, the "precision" thing I used and you as well in functions like path_get_direction should probably be like 1/path_get_length, because now if the path is very long then it could return wrong number. Although 0.0005 seems reasonably small.
Title: Re: Path trouble
Post by: polygone on May 23, 2012, 08:28:26 AM
Yes, I can see it works out when you go all around the entire path. But this error produces a big problem when trying to achieve what I am; to draw a line of a certain length along the path. The fact that this isn't returning correct at a point which is completely straight shows that part of the algorithm must be fundamentally wrong, GM manages to return precisely the correct length.

And it's nothing to do with the total path length, you're multiplying back by that in the t value so it doesn't matter. Using a path with 3 points in a straight line produces the same problem: https://www.box.com/s/8a3d612ef7f36580ab97

EDIT: OK I just checked with a straight path instead of smooth and everything is perfect when using a straight path. But like I said, I don't see how it could be wrong going between two points on a horizontal straight line. The smoothing doesn't affect the path between these points at all.

For anyone else interested, it's the path_getXY function:
https://github.com/enigma-dev/enigma-dev/blob/master/ENIGMAsystem/SHELL/Universal_System/pathstruct.cpp

EDIT 2: OK, after looking at it for a bit, firstly I think the method should be changed to a fourth-order equation so it takes points behind it into account but that's a completely different story. But back to the problem, I presume now that you're right about the length being the issue and the problem with this is the t length calculation needs to be set non-linearly when using a smooth path.
Title: Re: Path trouble
Post by: TheExDeus on May 23, 2012, 12:04:37 PM
Quote
And it's nothing to do with the total path length, you're multiplying back by that in the t value so it doesn't matter.
Not the total path length, but the length of each segment.

Quote
The smoothing doesn't affect the path between these points at all.
The short answer is that it does affect it.

Quote
fourth-order equation
Then it will not look like interpolation used in GM.

The length itself is actually correct (that is why total length is correct as well), but the "distribution" is wrong, in that point 0 has length non-zero while in linear paths its correct (zero). The problem is that the quadratic bezier spline does not start or end at the points, but between them. Here is a picture I made in last august for Josh:
https://www.dropbox.com/s/cth3rda3lh0q8na/path_interp.png

I will look into some methods on how to fix that.
Title: Re: Path trouble
Post by: polygone on May 23, 2012, 01:30:55 PM
hmm, I've just been looking over things I see that when you're calling pth->pointarray[ppi->second].length it's half the value when the path is set smooth. Why is that?
Title: Re: Path trouble
Post by: TheExDeus on May 23, 2012, 01:44:15 PM
The reason I posted previously. Look at the picture, there you will see where the length is calculated. I have made some changes and for a straight line the length is calculated correctly, but I still have problems with returning the correct 24pixel length. It is a lot closer now though.
Title: Re: Path trouble
Post by: polygone on May 23, 2012, 02:15:48 PM
If you set t not linearly like I suggested:

Code: [Select]
      if (pth->smooth)
        t = sqrt((position - ppi->first) * pth->total_length/double(pth->pointarray[ppi->second].length));
      else
        t = (position - ppi->first) * pth->total_length / double(pth->pointarray[ppi->second].length);
This then sets the 24 correctly and the total length of the path is still correct. However it then becomes not smooth at later points in the path.
Title: Re: Path trouble
Post by: TheExDeus on May 23, 2012, 02:46:44 PM
And using this code:
Code: [Select]
    static inline double blen(const path_point* p0, const path_point* p1, const path_point* p2)
    {
      double x1=p0->x, y1=p0->y,
            x2=p1->x, y2=p1->y,
            x3=p2->x, y3=p2->y,
            length=0,/*lx=0.5*(x1+x2), ly=0.5*(y1+y2)*/lx,ly,x,y;

      double t=0.5;
      lx = 0.5 * (((x1 - 2 * x2 + x3) * t + 2 * x2 - 2 * x1) * t + x1 + x2);
      ly = 0.5 * (((y1 - 2 * y2 + y3) * t + 2 * y2 - 2 * y1) * t + y1 + y2);
      t+=0.05;
      for (int i=0; i<=19; i++){
        x = 0.5 * (((x1 - 2 * x2 + x3) * t + 2 * x2 - 2 * x1) * t + x1 + x2);
        y = 0.5 * (((y1 - 2 * y2 + y3) * t + 2 * y2 - 2 * y1) * t + y1 + y2);
        length += hypot(x-lx,y-ly);
        lx = x, ly = y;
        //std::cout << "i: " << i << " t: " << t << "length: " << length << " x: " << x << " y: " << x << " dx: " << dx << " dy: " << dy << std::endl;
        t += 0.05;
      }
      return length;
    };
You can get correct lengths for points when in straight line, but this is still not correct, because lengths for curved path is still wrong (by as much as 200 pixel difference between GM and ENIGMA for a simple path). I still don't have time to do this right now, so I will have to postpone it. Maybe you will be able to figure this out.
Title: Re: Path trouble
Post by: polygone on May 23, 2012, 05:22:33 PM
Meh, I'm still looking at it. Not got anywhere though.
Title: Re: Path trouble
Post by: polygone on May 23, 2012, 09:50:32 PM
I give up, don't think I'm gonna work it out.
Title: Re: Path trouble
Post by: polygone on May 25, 2012, 07:03:00 PM
I suddenly thought of a way to do this, right after I switch methods for what I needed doing so I don't need it any more. It should have been obvious to me near the start as well .

If you use a quadratic bezier for the path instead, then alter the value of t for smooth paths so it runs against it linearly. I have tested the values in a spreadsheet which I wrote before and it works perfectly.

You have:  D = 2(1-t)t*Q + tt*R

Where D is the distance it should be moving linearly calculated, which in the script is the value of (position - ppi->position)*total_length. Q is the length of 2nd-path point to the 1st one and R is the length of the 3rd-path point to the 1st one. Then that can be rearranged using the quadratic formula to:

t = (-2Q + SQRT((4QQ + 4D(R – 2Q))) / (2(R – 2Q))     //You have to check for 2(R – 2Q) = 0 also, in which case set t to 0.5

Then just use that value for t with a regular quadratic bezier equation to calculate the x/y positions and it will work correctly linearly as well as curving correctly. But to be honest I really can't actually be fucked programming this, maybe in a month or something lol. I really don't need it any more myself so until maybe it's an issue for someone else I can't be bothered doing it.