Login [Register]
Don't have an account? Register now to chat, post, use our tools, and much more.
ACagliano wrote:
Ok I need some help. I've been doing some research and have only found results relevant to Unity, or using other libraries that I can't use in ez80 C.

1. Say I have two 3D coordinates. (x1, y1, z1) and (x2, y2, z2). The latter is the coordinate group I need to track towards. The former is the coordinate group of the object doing the tracking. I also have the rotation of the first object.. its vectors on the x,y axis and the z. I want to calculate the degree of rotation that the first object needs to make in order to be facing in the direction of the second object. From there, I want to rotate the first objects direction slowly so its like its slowly turning towards its target <== I already have code set up for this part, its the first part I'm not sure how to do. Would you recommend to do full 3d trig on this, or handle the x/y axis first, and then the final axis separately?

2. My rendering routine goofs up something fierce. As described in the last set of commit notes:
Commit Notes, Star Trek MP wrote:

Rendering Main Function: lcars/render.h References to: lcars/mapdata.h, movement/move3d.h
Issues:
Algorithm botches up something terrible. When you first boot in, assuming you have no save file, everything seems ok. The borg sphere is to scale--ish. It's a little off the left of where it should be though.
However, once you start moving, things quickly go wrong. Angling to the left or right makes it disappear completely or move the wrong way, in spite of the fact that we should still see it. And then, it will randomly just scale up to a massive size, rather than gradually scale up.

Could I possibly ask some people who know rendering better than I to have a look at my code and see where I went wrong. I put it together myself based on my very shaky understanding of 3d trig, but trig in math and rendering in code was never my strongest suite.

3. While the rendering algorithm, once debugged, should handle scaling objects and positioning them on screen properly, it does not clip those sprites to within the viewscreen (as in hide whatever is outside the boundary). That boundary is defined by xStart, yStart, xWidth, and yHeight variables within the game loop in main.c. Can someone please advise me on how to do this.


Try this for putting the object in view of the player, Rotation is output

Code:

Vector = ObjectVector - PlayerVector;
Vector =
 (tan(ObjectRotOffset[0])*Vector[0],tan(ObjectRotOffset[1])*Vector[1]),tan(ObjectRotOffset[2])*Vector[2])
//ObjectRotOffset is Object's offset degrees from global
Rotation = (tan⁻(Vector[2]/Vector[1]),tan⁻(Vector[0]/Vector[1]))
// Vector[0] is X
// Vector[1] is depth
// Vector[2] is Y
// Vectors are translated from global to local coordinates
// Rotation[0] is horizontal
// Rotation[1] is vertical
Return Rotation

Hope this helps!
beckadamtheinventor wrote:

Try this for putting the object in view of the player, Rotation is output

Code:

Vector = ObjectVector - PlayerVector;
Vector =
 (tan(ObjectRotOffset[0])*Vector[0],tan(ObjectRotOffset[1])*Vector[1]),tan(ObjectRotOffset[2])*Vector[2])
//ObjectRotOffset is Object's offset degrees from global
Rotation = (tan⁻(Vector[2]/Vector[1]),tan⁻(Vector[0]/Vector[1]))
// Vector[0] is X
// Vector[1] is depth
// Vector[2] is Y
// Vectors are translated from global to local coordinates
// Rotation[0] is horizontal
// Rotation[1] is vertical
Return Rotation

Hope this helps!

What is "global"? Would global be defined as the default rotation, (0 deg by 0 deg), where the ObjectRotOffset would be defined as the deviation from that? Also, wouldn't there only be 2 rotational vectors, one for the X and Y and one for the Z?

Also, on a related note, how does Star Trek describe rotational data? Like I've heard quotes like "turn to 137.5 degrees, mark 5" or I've heard "20 degrees starboard". Which is the most commonly used?
ACagliano wrote:
beckadamtheinventor wrote:

Try this for putting the object in view of the player, Rotation is output

Code:

Vector = ObjectVector - PlayerVector;
Vector =
 (tan(ObjectRotOffset[0])*Vector[0],tan(ObjectRotOffset[1])*Vector[1]),tan(ObjectRotOffset[2])*Vector[2])
//ObjectRotOffset is Object's offset degrees from global
Rotation = (tan⁻(Vector[2]/Vector[1]),tan⁻(Vector[0]/Vector[1]))
// Vector[0] is X
// Vector[1] is depth
// Vector[2] is Y
// Vectors are translated from global to local coordinates
// Rotation[0] is horizontal
// Rotation[1] is vertical
Return Rotation

Hope this helps!

What is "global"? Would global be defined as the default rotation, (0 deg by 0 deg), where the ObjectRotOffset would be defined as the deviation from that? Also, wouldn't there only be 2 rotational vectors, one for the X and Y and one for the Z?

Also, on a related note, how does Star Trek describe rotational data? Like I've heard quotes like "turn to 137.5 degrees, mark 5" or I've heard "20 degrees starboard". Which is the most commonly used?

global is the coordinate system that the world uses to place objects.
so, Global (0,0,0) is different from local (0,0,0) (unless there is no distance between them and no rotation difference).
Oh ok, I understand now. Lastly, are you treating Y as the third dimension? Or Z? In my code, I treat Z as the third axis, but now that I'm looking at it, it seems that the equations I used treat Y as the third axis. Perhaps that where some of my issues are coming from.
ACagliano wrote:
Oh ok, I understand now. Lastly, are you treating Y as the third dimension? Or Z? In my code, I treat Z as the third axis, but now that I'm looking at it, it seems that the equations I used treat Y as the third axis. Perhaps that where some of my issues are coming from.

Yea, Y is usually up and down in Global coords, and Y is usually Depth (forward) in local or camera-based coordinates.
Ok well let me then share my formulas:


Code:

/* The locational struct that is a member of every moveable object's data */
typedef struct position {
    char sectors[3];
    float coords[3];
    float vectors[3];
    unsigned char angles[2];
} Position_t;
// sectors, coords, and vectors are in the layout (x, y, z)
#define angle_xz 0
#define angle_y 1

/* Converts the two angles to 3 vectors, which get multiplied by speed to move the object */
void AngleToVectors(Position_t *pos){
    char angleXZ = pos->angles[angle_xz];
    char angleY = pos->angles[angle_y];
    pos->vectors[0] = (float)cos(360*angleXZ/255)*cos(360*angleY/255);
    pos->vectors[1] = (float)sin(360*angleXZ/255)*cos(360*angleY/255);
    pos->vectors[2] = (float)sin(360*angleY/255);
}

/ * temporary structure used to hold relative angles and distances (i think this would be what you define as local??)
typedef struct Relativity {
    char xzOffset;
    char yOffset;
    double distance;
} Relativity_t;

Relativity_t GetPositional( int x1, int y1, int z1, int x2, int y2, int z2){
    Relativity_t temp;
    int xzangle = atan( (y2 - y1) / (x2 - x1) );
    temp.xzOffset = (z2 < z1) - (z1 < z2);
    temp.yOffset = 255 * xzangle / 360;
    temp.distance = sqrt((x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2);
    return temp;
}


That right there is the meat of what drives movement and rendering in the engine. How much of this is wrong haha :p
ACagliano wrote:
Ok well let me then share my formulas:


Code:

/* The locational struct that is a member of every moveable object's data */
typedef struct position {
    char sectors[3];
    float coords[3];
    float vectors[3];
    unsigned char angles[2];
} Position_t;
// sectors, coords, and vectors are in the layout (x, y, z)
#define angle_xz 0
#define angle_y 1

/* Converts the two angles to 3 vectors, which get multiplied by speed to move the object */
void AngleToVectors(Position_t *pos){
    char angleXZ = pos->angles[angle_xz];
    char angleY = pos->angles[angle_y];
    pos->vectors[0] = (float)cos(360*angleXZ/255)*cos(360*angleY/255);
    pos->vectors[1] = (float)sin(360*angleXZ/255)*cos(360*angleY/255);
    pos->vectors[2] = (float)sin(360*angleY/255);
}

/ * temporary structure used to hold relative angles and distances (i think this would be what you define as local??)
typedef struct Relativity {
    char xzOffset;
    char yOffset;
    double distance;
} Relativity_t;

Relativity_t GetPositional( int x1, int y1, int z1, int x2, int y2, int z2){
    Relativity_t temp;
    int xzangle = atan( (y2 - y1) / (x2 - x1) );
    temp.xzOffset = (z2 < z1) - (z1 < z2);
    temp.yOffset = 255 * xzangle / 360;
    temp.distance = sqrt((x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2);
    return temp;
}


That right there is the meat of what drives movement and rendering in the engine. How much of this is wrong haha :p


I'm sorry, but all I can help you with is the equation in python (similar language) right now (my knowledge of c is VERY limited).

Code:

def Rot3d(x,y,z,rad1,rad2):
    s1,c1,s2,c2 = 255*sin(rad1)/360 , 255*cos(rad1)/360 , 255*sin(rad2)/360 , 255*cos(rad2)/360
    //If this above code doesn't work, try reversing the multiplier and divisor
    x,z = (x*c1-z*s1 , z*c1+x*s1)
    y,z = (y*c2-z*s2 , z*c2+y*s2)
    y = maxrender / y
    x,z = x*y , z*y
    if x-y<screen_Xmin or x+y>screen_Xmax or z-y<screen_Ymin or z+y>screen_Ymax:
        return -1
    return x,z,xs,zs
# This code translates the 3d coordinates (x,y,z)(y = up&down) to screen coordinates (x,y), using radXZ (1) and radYZ (2)
After implementing some of your suggestions (the best I could port them to C) and correcting the inconsistencies in the vertical axis within my program, the rendering routine has acquired more stability. Scaling based on distance is still off, but response to moving your ship left/right/up/down causes predictable behavior --- the borg sphere moves up/down/left/right as excepted.... except for when our ship jumps from 255 degrees to 0 degrees or 0 degrees to 255 degrees (overflowing the char type). In cases like this, where, for example, the player would be facing 254 degrees on the xz axis and the AI is at 2 degrees relative to the ship, the algorithm thinks that the ship is 252 degrees away, thus out of visual range, when in reality is is only 4 degrees away. How would I work around this?
ACagliano wrote:
After implementing some of your suggestions (the best I could port them to C) and correcting the inconsistencies in the vertical axis within my program, the rendering routine has acquired more stability. Scaling based on distance is still off, but response to moving your ship left/right/up/down causes predictable behavior --- the borg sphere moves up/down/left/right as excepted.... except for when our ship jumps from 255 degrees to 0 degrees or 0 degrees to 255 degrees (overflowing the char type). In cases like this, where, for example, the player would be facing 254 degrees on the xz axis and the AI is at 2 degrees relative to the ship, the algorithm thinks that the ship is 252 degrees away, thus out of visual range, when in reality is is only 4 degrees away. How would I work around this?

oh 0x5 I thought that you were working in 360s!
I'll 'beam you up' some new code soon! Laughing
beckadamtheinventor wrote:

oh 0x5 I thought that you were working in 360s!
I'll 'beam you up' some new code soon! 0x5


Well I sort of "map" the 360 degrees to the 0-255 range, in this fashion:


Code:

void GetOffsets( Relativity_t *data, int delta_x, int delta_y, int delta_z){
    int xzangle = atan( delta_y / delta_z );
    int yangle = atan( delta_x / delta_z );
    data->xzOffset = 255 * xzangle / 360;
    data->yOffset = 255 * yangle / 360;
    data->distance = sqrt((delta_x)^2 + (delta_y)^2 + (delta_z)^2);
}

In the code above, *data is a pointer to a temporary structure that holds the local position data. Delta_[axis] is the position on the axis for the object moving minus the position for the object it is seeking towards. (for viewscreen, its player position subtracted FROM object position)

The code that handles whether or not to render is:

Code:

if( data.distance <= VISUAL_RANGE ){
                if( (abs(data.xzOffset - PlayerData->Position.angles[0]) <= 45) && (abs(data.yOffset - PlayerData->Position.angles[1]) <= 45) ){
                    int xcoord = data.xzOffset - PlayerData->Position.angles[0] + 45;
                    char ycoord = data.yOffset - PlayerData->Position.angles[1] +45;
                    char scale = 10 - (data.distance * 10 / VISUAL_RANGE);
                    scale += (scale == 0);
                    xcoord = (xcoord * vWidth) / 91;
                    ycoord = (ycoord * vHeight) / 91;
                    if(object->type == OBJ_SHIP)
                        gfx_ScaledTransparentSprite_NoClip(sprite_BorgSphere, xcoord, ycoord, scale, scale);
                    if(object->type == OBJ_PROJ)
                        gfx_ScaledTransparentSprite_NoClip(sprite_Phaser, xcoord, ycoord, scale, scale);
                }
            }

In THIS code, data is the same struct that the first code populates, VISUAL_RANGE is a defined constant, and the rest should be fairly easy to interpret.
Today, I succeeded in fixing the issues with the axis, and fixing the issues with differences between the angles overflowing, causing the renderer to improperly read a larger angle offset than there is. Two final issues remain in the rendering routine.

1) The calculations for scaling are wrong. As we approach the sphere, I can see it scale up nicely, but it starts off way too big. For a starting sprite size of 15x15, that certain doesn't start off at a scale of 1, or 2, or 3... or anything less than 8 imo. I've tried messing with the data types, using ints, floats. I even corrected an earlier mistake, using the ^ character for exponents, and replacing it with value * value for value ^ 2.
If anyone can take a look at the pastebin'd source and find any possible thing I may have overlooked, why scaling doesn't work, you'll be doing better than me!
https://pastebin.com/NjxP5pMV


2) This is a question directly for Mateo or anyone else who has used the C libs in this fashion. I need a way to clip sprites such that the parts of them that are outside of the viewscreen window do not render, but the part of the sprite that is within it still renders. Constants for the viewscreen's starting x and y, as well as its width and height are in the program. The examples in the libs that I have seen don't do this, although I admittedly haven't looked specifically for this. When I attempt to address this tomorrow and take a second look, if i find something, ill edit this one.
Update

Scaling fixed. This has revealed a bug where sometimes we don't see the borg cube when we reload the game after quitting it. It also reveals that projectile tracking entities needs fixing as well.

Still need conceptual help with clipping sprites.
ACagliano wrote:
Still need conceptual help with clipping sprites.

You can set a clipping window? What is the issue.
MateoConLechuga wrote:

You can set a clipping window? What is the issue.

woooooa... all the times I've scrolled up and down that file looking for info on clipped sprites I've totally missed _SetClipRegion.... Well I guess that's that solved. Smile

But wait, are the only scaled sprite routines available unclipped?

Edit: Since there are no scaled transparent sprite routines that clip (yet), I combined the gfx_ScaleSprite() with gfx_TransparentSprite(). I also created a very large malloc() as a "graphics buffer" that I use to decompress/scale/etc. It's a 24,000 byte block of memory.
Alright, so I'm down to two remaining issues. One of them I'm working on now. The other I need some feedback on.

So when my code renders the borg sphere in the viewscreen, it renders when I increase the angle (turn the ship right) and the borg sphere moves to the left. When I move the ship to the left, however, and the angle of the ship on the XZ axis hits zero and then overflows to 255, the borg sphere disappears, as it's seeing a difference of ~> 250 degrees between the object and the ship's rotation. I added a line of code:

Code:
if(xzangle >128)  xzangle = 256 - xzangle;

Not even this corrected that behavior, so now I'm confused as to where that is occuring.
Here's the code I'm using: https://pastebin.com/9sAPE4HW
Any ideas?


Edit: I actually resolved this. Turns out I was stupidly flailing around with the intricacies of overflow and correcting it, when all I needed to do was use a signed char. /me facepalms.

Edit: LCARS interface full-screen flicker removed. Field of vision overflow errors removed. FOV now maps properly to the screen width in all directions except down (have yet to test this for all scales of the AI sprite).
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 2 of 2
» All times are GMT - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement