Help with Trigonometry?

Discussion in 'Discussion and Q&A Archive' started by FireRat, Feb 25, 2016.

  1. FireRat

    FireRat Do Not Interact With This User, Anywhere!!! Exiled

    Joined:
    Oct 31, 2009
    Messages:
    535
    Hello. I am CrazyMonkey, and I have been lurking around for some time. I am attempting to do an effect in VDP, but right now I am stuck trying to figure out how to rotate the sprite pieces on the screen.

    I am very hard-minded about trigonometry; Although I have accomplished a lot of stuff regarding rotation, the little to nothing I know about has all been learnt through trial and error - at first using the rotating emeralds code from the Ending in Sonic 1 as quick reference, until I learnt that the sine and cosine are pretty much used as "X/Y inclination percentage" here (that's just the impression I get about it).
    To rotate the sprite pieces around the screen, I thought on the following: For each piece (I'm talking about VDP sprites (as seen in the RAM table for latter DMA), not "objects"), find the angle against xpos=0x80+(320/2) and ypos=0x80+(224/2) (in other words, the center of screen), get the radius against the previously mentioned center, add an X value to the previously found angle, and finally recalculate the new sprite's position using: The new angle and previously calculated radius, all against the center of screen.

    However, I do not know how to calculate the radius here. How to get it?
     
  2. AURORA☆FIELDS

    AURORA☆FIELDS so uh yes Exiled

    Joined:
    Oct 7, 2011
    Messages:
    759
    Could you give an example of what you want to do? I am not sure I get what you exactly mean.
    However, given the example, I assume you want to do something along the lines of what the ending in Sonic 1 does with the emeralds? If so, I am also gathering you'd like a way to calculate the radius of the sprites, or in other words approximate offset from screen center? I am not entirely sure if there is a method to easily calculate it based on the shifting/multiplying values, however those control it. I have always used trial and error to get it to my liking so I couldn't help with a precise method anyway.
     
  3. MarkeyJester

    MarkeyJester ♡ ! Member

    Joined:
    Jun 27, 2009
    Messages:
    2,867
    Assuming you want the radius in pixels, then I would suggest the following:
    1. Get the X and Y distance between the centre and the sprite piece (We'll call this the main distance)
    2. Use CalcAngle to obtain the angle.
    3. Use CalcSine using that angle to get the sine wave X and Y distances (this will be the shortest/rawest, containing the distances between 0 and 1 pixels in fractions).
    4. At this point it would be beneficial to use either X or Y depending on which one is longer in distance, so if X is further, you use X, otherwise use Y.
    5. You now have to count how many times you should add that raw sine wave distance to get to the same distance as the main distance. (This count will be the number of pixels the radius is).
    For 5, an alternative would be to take the raw sine wave distance, multiply it by $100 pixels, then divide it by the main distance, this should get you a pixel count from 0 to $100. Though one thing to keep in mind is that obviously; if the object is already at the centre, it's main distance will be 0, therefore cannot divide the raw sine wave distance. Additionally, if a sprite happens to be further than $100 pixels from the centre (in this case it shouldn't since the screen size is smaller than that), the results may be unpredictable, or worst case point, the division will fail.

    Another thing to take into account, is that the sprite pieces' X and Y positions are NOT centre of the sprite, but rather the top left. So you may need to use the shape of the sprite to calculate the exact centre of the piece before calculating the radius.

    Doing the above for all sprites in the spite buffer table seems like it would be very heavy on the 68k, it might be worth finding an alternative approach such as a lookup table full of predetermined results. The entire sprite space range is $200 x $200. So $200 is the maximum distance between two points possible on both X and Y. $200 x $200 = $40000 x 2 for word retrieval would be $80000 bytes (half a Mega Byte). ...then x$40000 = too large for the ROM. OK, scratch that idea dX

    I wouldn't be surprised however, if a more mathematically optimal approach already exists to collect the radius given only X and Y coordinates, though since I've never needed to collect the radius for any reason, I've never searched nor studied it, so you'll have to excuse my ignorance.
     
    FireRat likes this.
  4. Unused Account

    Unused Account Well-Known Member Member

    Joined:
    May 10, 2013
    Messages:
    153
    Trigonometry triggers my nometry.

    (i'm so sorry i don't have anything useful to post i just wanted to pun.
    Good luck with your problems though. I do wish I could give a helping hand.)
     
  5. FireRat

    FireRat Do Not Interact With This User, Anywhere!!! Exiled

    Joined:
    Oct 31, 2009
    Messages:
    535
    Excuse me for the late reply.

    @ᑎค੮ςυɱɿ: It is for a Special Stage I have on my drafts; an extended concept seen in a couple of Sonic games, in all 8/16/32/up bits. The issue is that I do not want to spoil too much about what am I going to attempt to do just yet, and I want to keep all at its due time. I promise I do not want to appear "rude" by not giving too much information to my question, but I hope you understand my decision.

    @RaideinSlash: I am not too interested on help just yet, this project is still in diapers, and I want to have sure of what will be done without needing to change (at least too much) nor trash bad ideas in the middle of the process; I want to take good approach of my tiny available time. I might want a hand later though, especially if I get mad and decide to run for a date - What can/want you do?

    @MarkeyJester:
    To be honest, I got the idea of trying-until-get (the 5th step) not much before submitting the thread, but the issue is that the slowdown is very high in-game, and even worse, it breaks my HInt-based effects and this time, I find it just impossible to find any way to avoid it =/ (EDIT: Fixed, thank you LazloPsylus!). I might be an ignorant too, because just like you, I thought there would be a more known and better method to do this, and I was expecting just that-

    Today, however, just recently I got a great idea that might... "work": At home, I found my family to be watching a Batman movie. It made me think about the Adventures of Batman & Robin game, for the Sega Genesis. While thinking about its effects, I realized how often the plane rotations seem to split the image into many columns 16px width each, and thus I came to the conclusion it runs some code that individually sets amounts of "scanline shifting" between HScroll and VScroll in such a maneer it gives the illusion of actual rotation.. all just because VScroll can't work with less than 16 pixels of width - too bad for the VDP, but great news for my task. I could try a similar process: To generate two lookup tables in RAM with X/V values separately, each one in a maneer that graphically looks like this (the arithmetical progression is generated with a code similar to GHZ's water deformation, by the way!):
    [​IMG]
    (Xpos table)

    The tables (or let's say the "edges" of them) are generated using -X160/X159 and -Y112/Y111 with the returned sine and cosine values of the given angle. The X and Y positions of the sprite center's (thank you for reminding me that for VDP the positions are top-left!) could be used as the indexes for the X and Y tables, the routine takes the "shifting" value from the proper slots within the tables, and adds or substracts the value to the sprite's position as necessary. I do not think I will have to rotate more than in between the -45 and 45 degrees, but just in the case it is necessary and the calculation breaks, I suposse that dividing the process into quadrants, just like the Sonic physics do, may do the trick.. negating the necessary values and the like...
    I do not know if I will get a proper result, neither if the issue described above is going to happen, so all I have left to do is to give it a try.
    Thank you anyways. This is going to be a long night =)
     
    Last edited: Mar 2, 2016
  6. AURORA☆FIELDS

    AURORA☆FIELDS so uh yes Exiled

    Joined:
    Oct 7, 2011
    Messages:
    759
    one other thing you could do is do simply a big file with the necessary values in, and then you only need to calculate index. Considering you said it is too slow already, adding in branches to flip the quadrants will just make things worse if anything. If you've seen final boss of my hack, SonicMT, I use some form of sine calculations for the boss itself. But as you may see the pointer, the arrow in the middle actually uses (a small) lookup table to position itself around the boss icon, and then flips itself for 4 different quadrants. Just doing all of this for the boss, 6 turrets (which are actually 4 different objects), and the boss pointer, I am already running tight on CPU time. I could not simply pull of the expensive algorithm for that ground shake in the next phase.
    So, the moral of the story is, lookup tables are really useful sometimes.
     
  7. MarkeyJester

    MarkeyJester ♡ ! Member

    Joined:
    Jun 27, 2009
    Messages:
    2,867
    I did warn you it'd be slow~

    By the way, would you happen to be attempting something along the lines of this:



    If so, you should have just said, the very tables responsible for slicing the H/V lines are the same tables used to reposition the sprite pieces. The real danger comes into play however, when you find that what you've got is not a sine wave at all, but rather a... triangle wave, or diamond as such. Additionally, the positioning can only be rotated so far before it's distorted beyond visual acceptance, which is why the rotation was harshly reduced per angle.