Last active
March 16, 2021 23:24
-
-
Save ericoporto/0c092da235209336d683fb7cd6968a02 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// I can't figure any good way that makes the sprite be properly positioned in place, so I am making a bad way. | |
// first thing, we are going to find the distance that the sprite is from the camera plane. | |
// this will give us a z distance | |
// Then we are going to use this z distance in the renderer algorithm we have for the voxel engine | |
// which should make it easier to find the point we are interested, in a way that moves just like the renderer we have | |
// this is wasteful, but we are probably not going to have many sprites anyway... | |
ScreenPoint* PositionBillboardX(Vec3* cam_pos, float cam_angle, float horizon, float scale_height, Vec3* obj_pos) | |
{ | |
int y_on_screen, x_on_screen; // intermediary | |
ScreenPoint* p = new ScreenPoint; | |
// just storing because we are using these values twice | |
float sinphi = Maths.Sin(cam_angle); | |
float cosphi = Maths.Cos(cam_angle); | |
// relative position in x,y of the obj in relation to camera | |
float bill_rel_x = obj_pos.x - cam_pos.x; | |
float bill_rel_y = obj_pos.y - cam_pos.y; | |
float bill_rel_z = obj_pos.z - cam_pos.z; | |
//float rotd_x = bill_rel_x*cosphi - bill_rel_y*sinphi; // x axis in camera, but doesn't look good, discarding... | |
float rotd_z = bill_rel_x*sinphi + bill_rel_y*cosphi; // distance from camera | |
// positive means it's behind the player, so we return the position off the screen | |
if(rotd_z > 0.0) { | |
p.x = -2; | |
p.y = -2; | |
return p; | |
} | |
float z, invz_scaled; | |
z = IntToFloat(FloatToInt(-rotd_z-1.0)); | |
float end_z = z + 3.0; | |
for (;z<end_z;z+=1.0) | |
{ | |
if(AbsF(z) <= 1.0) z = 1.0; | |
invz_scaled = scale_height/z; | |
// Find line on map. This calculation corresponds to a field of view of 90° | |
float plx = -cosphi * z - sinphi * z; | |
float ply = sinphi * z - cosphi * z; | |
float prx = cosphi * z - sinphi * z; | |
float pry = -sinphi * z - cosphi * z; | |
// A little segment of line dx,dy that is normal to player angle, we will use to traverse from pl(x,y) to pr(x,y) | |
float dx = (prx - plx) / ScreenWidth_AsFloat; | |
float dy = (pry - ply) / ScreenWidth_AsFloat; | |
float ddx = ClampF(2.0*AbsF(dx), 0.5, 32.0); | |
float ddy = ClampF(2.0*AbsF(dy), 0.5, 32.0); | |
// makes the camera coordinate in the same world space of the player | |
plx+=cam_pos.x; | |
ply+=cam_pos.y; | |
float p_line_x = plx; | |
float p_line_y = ply; | |
y_on_screen = FloatToInt( (-bill_rel_z) * invz_scaled + horizon ); | |
for (int i=0; i<ScreenWidth; i+=1) { | |
if(p_line_x - ddx <= obj_pos.x && obj_pos.x <= p_line_x + ddx && | |
p_line_y - ddy <= obj_pos.y && obj_pos.y <= p_line_y + ddy) { | |
x_on_screen = i; | |
break; | |
} | |
p_line_x = plx + dx*IntToFloat(i); | |
p_line_y = ply + dy*IntToFloat(i); | |
} | |
if(x_on_screen != 0) break; | |
} | |
if(x_on_screen != 0) | |
{ | |
p.x = x_on_screen; | |
p.y = y_on_screen; | |
p.z = z; | |
p.w = rotd_z; | |
} | |
else | |
{ | |
p.x = -1; | |
p.y = -1; | |
} | |
return p; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment