/apps/demos/scenery: separate height_at(), position grass right

This commit is contained in:
veclavtalica 2025-01-06 15:34:12 +03:00
parent e914cad0dd
commit 6463ac3dd7

View File

@ -48,6 +48,35 @@ static void process_fly_mode(State *state) {
} }
static float height_at(SceneIngame *scn, Vec2 position) {
float height0, height1, height2, weight0, weight1, weight2;
int const x = (int)(HALF_TERRAIN_DISTANCE + (position.x - scn->pos.x));
int const y = (int)(HALF_TERRAIN_DISTANCE + (position.y - scn->pos.z));
height0 = heightmap[x][y];
height1 = heightmap[x + 1][y + 1];
Vec2 incell = { position.x - floorf(position.x), position.y - floorf(position.y) };
/* who needs barycentric coordinates, am i right? */
weight0 = 1 / sqrtf(powf(incell.x, 2) + powf(incell.y, 2));
weight1 = 1 / sqrtf(powf(1 - incell.x, 2) + powf(1 - incell.y, 2));
/* find which triangle we're directly under */
/* for this manhattan distance is sufficient */
if (incell.x + (1 - incell.y) < (1 - incell.x) + incell.y) {
height2 = heightmap[x][y + 1];
weight2 = 1 / sqrtf(powf(incell.x, 2) + powf(1 - incell.y, 2));
} else {
height2 = heightmap[x + 1][y];
weight2 = 1 / sqrtf(powf(1 - incell.x, 2) + powf(incell.y, 2));
}
return (height0 * weight0 + height1 * weight1 + height2 * weight2) / (weight0 + weight1 + weight2);
}
static void process_ground_mode(State *state) { static void process_ground_mode(State *state) {
SceneIngame *scn = (SceneIngame *)state->scene; SceneIngame *scn = (SceneIngame *)state->scene;
@ -61,35 +90,13 @@ static void process_ground_mode(State *state) {
/* gravity */ /* gravity */
{ {
float height0, height1, height2, weight0, weight1, weight2; float const height = height_at(scn, (Vec2){scn->pos.x, scn->pos.z});
height0 = heightmap[(int)HALF_TERRAIN_DISTANCE][(int)HALF_TERRAIN_DISTANCE];
height1 = heightmap[(int)HALF_TERRAIN_DISTANCE + 1][(int)HALF_TERRAIN_DISTANCE + 1];
Vec2 incell = { scn->pos.x - floorf(scn->pos.x), scn->pos.z - floorf(scn->pos.z) };
/* who needs barycentric coordinates, am i right? */
weight0 = 1 / sqrtf(powf(incell.x, 2) + powf(incell.y, 2));
weight1 = 1 / sqrtf(powf(1 - incell.x, 2) + powf(1 - incell.y, 2));
/* find which triangle we're directly under */
/* for this manhattan distance is sufficient */
if (incell.x + (1 - incell.y) < (1 - incell.x) + incell.y) {
height2 = heightmap[(int)HALF_TERRAIN_DISTANCE][(int)HALF_TERRAIN_DISTANCE + 1];
weight2 = 1 / sqrtf(powf(incell.x, 2) + powf(1 - incell.y, 2));
} else {
height2 = heightmap[(int)HALF_TERRAIN_DISTANCE + 1][(int)HALF_TERRAIN_DISTANCE];
weight2 = 1 / sqrtf(powf(1 - incell.x, 2) + powf(incell.y, 2));
}
float height = (height0 * weight0 + height1 * weight1 + height2 * weight2) / (weight0 + weight1 + weight2);
if (target.y > height + PLAYER_HEIGHT) if (target.y > height + PLAYER_HEIGHT)
target.y = target.y - 0.4f; target.y = target.y - 0.4f;
if (target.y < height + PLAYER_HEIGHT) if (target.y < height + PLAYER_HEIGHT)
target.y = height + PLAYER_HEIGHT; target.y = height + PLAYER_HEIGHT;
} }
/* movement */ /* movement */
@ -159,7 +166,10 @@ static void draw_terrain(SceneIngame *scn) {
(Vec2){ 0, 0 }, (Vec2){ 0, 0 },
(Vec2){ 0, 128 }); (Vec2){ 0, 128 });
draw_billboard("/assets/grasses/10.png", (Vec3){ (float)x, d1 + 0.1f, (float)y }, (Vec2){0.3f, 0.3f}, (Color){255, 255, 255, 255}, true); draw_billboard("/assets/grasses/10.png",
(Vec3){ (float)x, d0 + 0.15f, (float)y },
(Vec2){0.3f, 0.3f},
(Color){255, 255, 255, 255}, true);
} }
} }
} }