Skip to content

Instantly share code, notes, and snippets.

@ericoporto
Last active March 16, 2021 23:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ericoporto/0c092da235209336d683fb7cd6968a02 to your computer and use it in GitHub Desktop.
Save ericoporto/0c092da235209336d683fb7cd6968a02 to your computer and use it in GitHub Desktop.
// 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