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).
Update

After a bit of not understanding double buffering and then finally understanding the concepts, I figured it out, and created fairly smooth graphics rather than flickering mayhem. I implemented this only for the view screen, since it should be like you looking out a window. For the other tabs, which are LCARS displays, I left the faint flickers in, since I would think a refreshing LCARS display would have a quick flicker.

Here is a screenshot showing the Borg cube with the new graphics.


=========================
A few more things to do (Bugs):

1. Implement a shunting yard or some other form of algorithm that sorts rendered map objects by distance, so we can render them in order. (help, please?!)

2. Projectile tracking not working. (reviewing)
----- 2-a. Projectiles do not track their targets.
----- 2-b. Sometimes, pressing the fire key fires a phaser, other times it seems not to.

3. The Borg sphere not AI'ing.
----- 3-a. The Borg sphere does not seem to track the player
----- 3-b. The Borg sphere does not seem to fire as its supposed to. This is likely the same bug as 2-b.

4. The collision detection and collision interpolation algorithms might need some work. That depends on what happens after #2 and 3 are resolved.

I'm hoping for a release by Christmas.
Are you going to make the entire game universe from scratch? Or will you generate some of it? Or will all of it be generated?
Good work so far though! Loving this project!
Well, for the demo, there is going to be very little of what's intended in the game. In the demo, you'll fight one Borg sphere with standard, un-upgradeable weaponry, have a simple speed control system (no warp), and sensors will essentially be always online and locked on. The idea is to let people get a feel for *how* the game will handle, without giving too much away. In this demo, the game universe is one sector, with one ship and nothing else. I generate and spawn that ship in the initialization. Keep in mind that while this is a singleplayer demo, the finished product will be multiplayer, and a lot of the routines in this game are being designed in a fashion that would be somewhat bloated for singleplayer, but they're pre-geared towards networking.

For the long term, however, it's gonna be a lot more network-centric. I still do plan to make this as a networking game, that somehow uses the CE's USB protocol, and perhaps a computer-side helper program to communicate with a CALCnet hub. This will allow the game to eventually be made backward-compatible with the older z80's. In this version, when the *server* initializes a game world, it will generate the terrain, and that terrain will be the same for all connected units. When I get to working out how to get started with networking, I'd love to have a look at the Direct USB code Kerm uses for CALCnet, to see if it's adaptable in any way. Also, one of the features I plan to implement is allowing users to, from a computer, upload their own ship model that gets rendered for other players when they see you (kind of like a minecraft skin).

One of the caveats I'll need to overcome is how to get these sprites to the calculator from the network. 3D sprites are way too large to send in the frame update packet (which would only contain data on what is within *sensor range (sensor range because sensor range is the largest range of objects in the world that you'd ever interact with, informationally) -- location, orientation, distance, size, and if a terrain object factors like gravity, burn, etc.). I could easily send sprites related to terrain objects in the join packets, because i can use 2d sprites with a little bit of random rotation and stuff to create irregularity. But, if I were to send 3D sprites for every existing user, that would take a boatload of memory. I could send sprites for every *connected* user, and delete/add them as people quit/join, but that might cause some client lag as we receive that much data. I'm certainly open to suggestions on this.

Also I'd love suggestions on how to make the display to the left of the positional data be a bit more GUI-y. I want to move the coordinates INTO the viewscreen somewhere, perhaps leave sector on the side, and have some cooler way to display your rotation. Ideas?
Ok so I need some advice.

The Problem: When I'm rendering the weapon sprites, the weapons should seem to move from lower on the screen, and then move towards the center, and the ship. I thought of drawing triangles (gfx_FillTriange) to create a perspective beam phaser effect, but that's very hard to control with the degree I need to. I'd need to be able to calculate the starting point and ending point of the phaser beam and draw a line or series of lines. The starting and ending point may not always be on screen, especially when the game goes multiplayer and you'll sometimes see a phaser fly across your viewscreen, heading elsewhere. This seems to not be a problem with the torpedo sprites, as torpedoes are more in one place than beam-like.

The solution I'm leaning towards: Adding to the union member for Projectiles a second Position_t structure. This structure contains the coordinates of trailing end of the phaser beam and would have a "trail lag counter" field that determined how long the trail would take to begin moving with the phaser. In this manner I can create pulse phasers with a shorter counter and more beam-like phasers with a longer counter. Rather than a sprite, the phaser would be either a gfx_Line() or a gfx_FillTriangle(), going from the phaser's head to the end of its tail.


Does anyone have any other suggestions? Or does this seem like a good idea?
Would I be able to recruit some debugging assistance? I've gotten this game mostly debugged, but I'm still struggling with two remaining issues that I can't seem to remove.
  
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 3
» 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