#include "world.h" #include "game.h" World createWorld(const Assets* assets) { World world; world.size = (Vector3){1000.0, 100.0, 1000.0}; // Heightmap image. Image image = GenImagePerlinNoise(100, 100, 0, 0, 5.0); // Heightmap. Mesh mesh = GenMeshHeightmap(image, world.size); world.heightmap = LoadModelFromMesh(mesh); world.texture = LoadTextureFromImage(image); world.heightmap.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = world.texture; UnloadImage(image); int seed = 57; // Entities. for (int index = 0; index < WORLD_ENTITY_MAX; ++index) { FT_RANDOM16(seed); Entity entity = createEntity(seed % ENTITY_COUNT, Vector3Zero()); FT_RANDOM16(seed); entity.position.x = seed % (int)world.size.x; FT_RANDOM16(seed); entity.position.z = seed % (int)world.size.z; entity.position.y = getWorldHeightAtLocation(world, entity.position.x, entity.position.z) + 1.0; world.entities[index] = entity; } return world; } void updateWorld(World* world, Game* game) { DrawModel(world->heightmap, Vector3Zero(), 1.0, WHITE); for (int index = 0; index < WORLD_ENTITY_MAX; ++index) { updateEntity(&world->entities[index], game); } } void freeWorld(World world) { UnloadTexture(world.texture); UnloadModel(world.heightmap); } float getWorldHeightAtLocation(World world, float x, float y) { float toMapX = (float)world.texture.width / world.size.x; float toMapY = (float)world.texture.height / world.size.z; int pixelX = x * toMapX; int pixelY = y * toMapY; int verticeStart = (pixelY * (world.texture.width - 1) + pixelX) * 18; float* vertices = &world.heightmap.meshes[0].vertices[verticeStart]; // Clamp x and y to prevent ray being out of bounds. Vector2 min = (Vector2){vertices[0], vertices[2]}; Vector2 max = (Vector2){vertices[0], vertices[2]}; for (int index = 0; index < 18; index += 3) { Vector2 vertex = (Vector2){vertices[index], vertices[index + 2]}; min = Vector2Min(min, vertex); max = Vector2Max(max, vertex); } // Cast to triangles at pixel. Really hacky indeed. Ray ray = (Ray){ .position = (Vector3){ Clamp(x, min.x, max.x), FLT_MAX_EXP, Clamp(y, min.y, max.y)}, .direction = (Vector3){0.0, -1.0, 0.0} }; RayCollision result = GetRayCollisionTriangle( ray, (Vector3){vertices[0], vertices[1], vertices[2]}, (Vector3){vertices[3], vertices[4], vertices[5]}, (Vector3){vertices[6], vertices[7], vertices[8]}); // Test other triangle. if (!result.hit) { result = GetRayCollisionTriangle( ray, (Vector3){vertices[9], vertices[10], vertices[11]}, (Vector3){vertices[12], vertices[13], vertices[14]}, (Vector3){vertices[15], vertices[16], vertices[17]}); } if (result.hit) { return result.point.y; } else // Fall back. { float height = 0.0; for (int index = 1; index < 18; index += 3) { height += vertices[index]; } return height / 6.0; } } // Abortions are good. Get more abortions.