Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
57ce3a64ed
|
@@ -7,6 +7,4 @@ edition = "2021"
|
|||||||
glium = "0.32.1"
|
glium = "0.32.1"
|
||||||
image = "0.24.4"
|
image = "0.24.4"
|
||||||
glutin = "0.29.1"
|
glutin = "0.29.1"
|
||||||
obj = "0.10.2"
|
|
||||||
phf = { version = "0.11.1", features = ["macros"]}
|
|
||||||
load_file = "1.0.1"
|
load_file = "1.0.1"
|
||||||
@@ -1,9 +1 @@
|
|||||||
# LemnosLife Rust
|
# LemnosLife Rust
|
||||||
|
|
||||||
Download `Extensions/` from [issues/8#issue-732](https://gitea.lemnoslife.com/LemnosLife/LemnosLife_Rust/issues/8#issue-732).
|
|
||||||
|
|
||||||
First install [Rust](https://rustup.rs), then build and run the client by executing:
|
|
||||||
|
|
||||||
```
|
|
||||||
cargo run --release
|
|
||||||
```
|
|
||||||
|
|||||||
+94
-586
@@ -5,191 +5,13 @@ extern crate glium;
|
|||||||
extern crate load_file;
|
extern crate load_file;
|
||||||
|
|
||||||
use glium::texture::SrgbTexture2d;
|
use glium::texture::SrgbTexture2d;
|
||||||
use phf::phf_map;
|
|
||||||
use std::f32::consts::PI;
|
|
||||||
use std::fs;
|
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use std::time::Instant;
|
|
||||||
|
|
||||||
use crate::support::CHUNK_SIZE;
|
|
||||||
use glium::vertex::VertexBufferAny;
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use glium::{glutin, Surface};
|
use glium::{glutin, Surface};
|
||||||
|
|
||||||
mod support;
|
mod support;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
struct PerInstance {
|
|
||||||
pub w_position: (f32, f32, f32),
|
|
||||||
pub w_rotation: f32,
|
|
||||||
}
|
|
||||||
implement_vertex!(PerInstance, w_position, w_rotation);
|
|
||||||
|
|
||||||
const STRUCTURES_TEXTURES_NUMBER: usize = 78;
|
|
||||||
const STRUCTURES_TEXTURES: [&str; STRUCTURES_TEXTURES_NUMBER] = [
|
|
||||||
"redNoise.jpg",
|
|
||||||
"cargoLightBlue.jpg",
|
|
||||||
"beigeNoise.jpg",
|
|
||||||
"wallStone.jpg",
|
|
||||||
"cargoWhite.jpg",
|
|
||||||
"b_ficusc2d_f.png",
|
|
||||||
"basketball_court.jpg",
|
|
||||||
"zinc.jpg",
|
|
||||||
"solarPowerPlant.png",
|
|
||||||
"cargoSand.jpg",
|
|
||||||
"water.jpg",
|
|
||||||
"solarPowerPlantAccumulator.jpg",
|
|
||||||
"blueNoise.jpg",
|
|
||||||
"30kmh.jpg",
|
|
||||||
"white.jpg",
|
|
||||||
"blackYellow.jpg",
|
|
||||||
"stopText.jpg",
|
|
||||||
"cargoOrange.jpg",
|
|
||||||
"redWhite.jpg",
|
|
||||||
"grid.png",
|
|
||||||
"blueTile.jpg",
|
|
||||||
"blueWhiteNoise.jpg",
|
|
||||||
"reinforcedConcrete.jpg",
|
|
||||||
"log.jpg",
|
|
||||||
"green.jpg",
|
|
||||||
"fanWallGrey.jpg",
|
|
||||||
"cargoCyan.jpg",
|
|
||||||
"glass.png",
|
|
||||||
"wallGrey.jpg",
|
|
||||||
"greenGate.png",
|
|
||||||
"greyNoise.jpg",
|
|
||||||
"cattail.png",
|
|
||||||
"palmLayer.png",
|
|
||||||
"cargoLightGreen.jpg",
|
|
||||||
"palm.png",
|
|
||||||
"branch1.png",
|
|
||||||
"cargoYellow.jpg",
|
|
||||||
"blackNoise.jpg",
|
|
||||||
"pipes.jpg",
|
|
||||||
"whiteTile.jpg",
|
|
||||||
"darkBlueNoise.jpg",
|
|
||||||
"planks.png",
|
|
||||||
"trunk.jpg",
|
|
||||||
"greenNoise.jpg",
|
|
||||||
"wallBlue.jpg",
|
|
||||||
"stop.jpg",
|
|
||||||
"wallGreyATM.jpg",
|
|
||||||
"iron_bars.png",
|
|
||||||
"tile.jpg",
|
|
||||||
"horizontalBrick.jpg",
|
|
||||||
"steel.jpg",
|
|
||||||
"yellowBars.png",
|
|
||||||
"whiteDoor.jpg",
|
|
||||||
"cargoBlue.jpg",
|
|
||||||
"barbed.png",
|
|
||||||
"woodBlue.jpg",
|
|
||||||
"bamboo.png",
|
|
||||||
"b_ficusc1s_f.png",
|
|
||||||
"whiteNoise.jpg",
|
|
||||||
"fanWall.jpg",
|
|
||||||
"wood.jpg",
|
|
||||||
"crossover.jpg",
|
|
||||||
"gridHexa.png",
|
|
||||||
"lightBlue.jpg",
|
|
||||||
"helipad.png",
|
|
||||||
"binBarrel.jpg",
|
|
||||||
"brick.jpg",
|
|
||||||
"wallBlueATM.jpg",
|
|
||||||
"yellow.jpg",
|
|
||||||
"blueDoor.jpg",
|
|
||||||
"parking.jpg",
|
|
||||||
"cargoGrey.jpg",
|
|
||||||
"haystack.jpg",
|
|
||||||
"cargoRed.jpg",
|
|
||||||
"yellowNoise.jpg",
|
|
||||||
"gridFull.jpg",
|
|
||||||
"rust.jpg",
|
|
||||||
"cargo.jpg",
|
|
||||||
];
|
|
||||||
|
|
||||||
// This approach works as there isn't file names having several file extensions.
|
|
||||||
// `phf` doesn't propose any `bimap`.
|
|
||||||
static STRUCTURES_TEXTURES_REVERSED: phf::Map<&'static str, u32> = phf_map! {
|
|
||||||
"redNoise" => 0,
|
|
||||||
"cargoLightBlue" => 1,
|
|
||||||
"beigeNoise" => 2,
|
|
||||||
"wallStone" => 3,
|
|
||||||
"cargoWhite" => 4,
|
|
||||||
"b_ficusc2d_f" => 5,
|
|
||||||
"basketball_court" => 6,
|
|
||||||
"zinc" => 7,
|
|
||||||
"solarPowerPlant" => 8,
|
|
||||||
"cargoSand" => 9,
|
|
||||||
"water" => 10,
|
|
||||||
"solarPowerPlantAccumulator" => 11,
|
|
||||||
"blueNoise" => 12,
|
|
||||||
"30kmh" => 13,
|
|
||||||
"white" => 14,
|
|
||||||
"blackYellow" => 15,
|
|
||||||
"stopText" => 16,
|
|
||||||
"cargoOrange" => 17,
|
|
||||||
"redWhite" => 18,
|
|
||||||
"grid" => 19,
|
|
||||||
"blueTile" => 20,
|
|
||||||
"blueWhiteNoise" => 21,
|
|
||||||
"reinforcedConcrete" => 22,
|
|
||||||
"log" => 23,
|
|
||||||
"green" => 24,
|
|
||||||
"fanWallGrey" => 25,
|
|
||||||
"cargoCyan" => 26,
|
|
||||||
"glass" => 27,
|
|
||||||
"wallGrey" => 28,
|
|
||||||
"greenGate" => 29,
|
|
||||||
"greyNoise" => 30,
|
|
||||||
"cattail" => 31,
|
|
||||||
"palmLayer" => 32,
|
|
||||||
"cargoLightGreen" => 33,
|
|
||||||
"palm" => 34,
|
|
||||||
"branch1" => 35,
|
|
||||||
"cargoYellow" => 36,
|
|
||||||
"blackNoise" => 37,
|
|
||||||
"pipes" => 38,
|
|
||||||
"whiteTile" => 39,
|
|
||||||
"darkBlueNoise" => 40,
|
|
||||||
"planks" => 41,
|
|
||||||
"trunk" => 42,
|
|
||||||
"greenNoise" => 43,
|
|
||||||
"wallBlue" => 44,
|
|
||||||
"stop" => 45,
|
|
||||||
"wallGreyATM" => 46,
|
|
||||||
"iron_bars" => 47,
|
|
||||||
"tile" => 48,
|
|
||||||
"horizontalBrick" => 49,
|
|
||||||
"steel" => 50,
|
|
||||||
"yellowBars" => 51,
|
|
||||||
"whiteDoor" => 52,
|
|
||||||
"cargoBlue" => 53,
|
|
||||||
"barbed" => 54,
|
|
||||||
"woodBlue" => 55,
|
|
||||||
"bamboo" => 56,
|
|
||||||
"b_ficusc1s_f" => 57,
|
|
||||||
"whiteNoise" => 58,
|
|
||||||
"fanWall" => 59,
|
|
||||||
"wood" => 60,
|
|
||||||
"crossover" => 61,
|
|
||||||
"gridHexa" => 62,
|
|
||||||
"lightBlue" => 63,
|
|
||||||
"helipad" => 64,
|
|
||||||
"binBarrel" => 65,
|
|
||||||
"brick" => 66,
|
|
||||||
"wallBlueATM" => 67,
|
|
||||||
"yellow" => 68,
|
|
||||||
"blueDoor" => 69,
|
|
||||||
"parking" => 70,
|
|
||||||
"cargoGrey" => 71,
|
|
||||||
"haystack" => 72,
|
|
||||||
"cargoRed" => 73,
|
|
||||||
"yellowNoise" => 74,
|
|
||||||
"gridFull" => 75,
|
|
||||||
"rust" => 76,
|
|
||||||
"cargo" => 77,
|
|
||||||
};
|
|
||||||
|
|
||||||
const BIOMES_NUMBER: usize = 19;
|
const BIOMES_NUMBER: usize = 19;
|
||||||
const BIOMES: [&str; BIOMES_NUMBER] = [
|
const BIOMES: [&str; BIOMES_NUMBER] = [
|
||||||
"dirt",
|
"dirt",
|
||||||
@@ -216,16 +38,14 @@ const BIOMES: [&str; BIOMES_NUMBER] = [
|
|||||||
fn main() {
|
fn main() {
|
||||||
// building the display, ie. the main object
|
// building the display, ie. the main object
|
||||||
let event_loop = glutin::event_loop::EventLoop::new();
|
let event_loop = glutin::event_loop::EventLoop::new();
|
||||||
let wb = glutin::window::WindowBuilder::new()
|
let wb = glutin::window::WindowBuilder::new();
|
||||||
.with_title("LemnosLife")
|
|
||||||
.with_maximized(true);
|
|
||||||
let cb = glutin::ContextBuilder::new().with_depth_buffer(24);
|
let cb = glutin::ContextBuilder::new().with_depth_buffer(24);
|
||||||
let display = glium::Display::new(wb, cb, &event_loop).unwrap();
|
let display = glium::Display::new(wb, cb, &event_loop).unwrap();
|
||||||
|
|
||||||
// building the vertex and index buffers
|
// building the vertex and index buffers
|
||||||
let ground_vertex_buffer = support::load_ground(&display);
|
let (vertex_buffer, chunks) = support::load_ground(&display);
|
||||||
|
|
||||||
let ground_textures: [SrgbTexture2d; BIOMES_NUMBER] = BIOMES.map(|biome| {
|
let textures: [SrgbTexture2d; BIOMES_NUMBER] = BIOMES.map(|biome| {
|
||||||
println!("{}", biome);
|
println!("{}", biome);
|
||||||
let image = image::load(
|
let image = image::load(
|
||||||
Cursor::new(&load_bytes!(&format!(
|
Cursor::new(&load_bytes!(&format!(
|
||||||
@@ -242,125 +62,8 @@ fn main() {
|
|||||||
glium::texture::SrgbTexture2d::new(&display, image).unwrap()
|
glium::texture::SrgbTexture2d::new(&display, image).unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
let structures_textures: [SrgbTexture2d; STRUCTURES_TEXTURES_NUMBER] =
|
|
||||||
STRUCTURES_TEXTURES.map(|structure_texture| {
|
|
||||||
println!("{}", structure_texture);
|
|
||||||
let image = image::load(
|
|
||||||
Cursor::new(&load_bytes!(&format!(
|
|
||||||
"../Extensions/LemnosLife/Assets/Downloads/{}",
|
|
||||||
structure_texture
|
|
||||||
))),
|
|
||||||
if structure_texture.ends_with(".png") {
|
|
||||||
image::ImageFormat::Png
|
|
||||||
} else {
|
|
||||||
image::ImageFormat::Jpeg
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
.to_rgba8();
|
|
||||||
let image_dimensions = image.dimensions();
|
|
||||||
let image = glium::texture::RawImage2d::from_raw_rgba_reversed(
|
|
||||||
&image.into_raw(),
|
|
||||||
image_dimensions,
|
|
||||||
);
|
|
||||||
glium::texture::SrgbTexture2d::new(&display, image).unwrap()
|
|
||||||
});
|
|
||||||
|
|
||||||
let uniform_sampler_2d_str = (0..BIOMES_NUMBER)
|
|
||||||
.map(|i| format!("tex{}", i))
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join(", ");
|
|
||||||
|
|
||||||
let switch_v_biome_str = (0..BIOMES_NUMBER)
|
|
||||||
.map(|i| {
|
|
||||||
format!(
|
|
||||||
"
|
|
||||||
case {}u:
|
|
||||||
f_color = texture(tex{}, v_tex_coords);
|
|
||||||
break;
|
|
||||||
",
|
|
||||||
i, i
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join("")
|
|
||||||
+ &format!(
|
|
||||||
"
|
|
||||||
default: // case {}u:
|
|
||||||
f_color = texture(tex{}, v_tex_coords);
|
|
||||||
",
|
|
||||||
BIOMES_NUMBER - 1,
|
|
||||||
BIOMES_NUMBER - 1
|
|
||||||
);
|
|
||||||
|
|
||||||
let ground_fragment = &format!(
|
|
||||||
"
|
|
||||||
#version 140
|
|
||||||
|
|
||||||
in vec2 v_tex_coords;
|
|
||||||
flat in uint v_biome;
|
|
||||||
|
|
||||||
out vec4 f_color;
|
|
||||||
|
|
||||||
uniform sampler2D {};
|
|
||||||
|
|
||||||
void main() {{
|
|
||||||
switch (v_biome) {{
|
|
||||||
{}
|
|
||||||
}}
|
|
||||||
}}
|
|
||||||
",
|
|
||||||
uniform_sampler_2d_str, switch_v_biome_str
|
|
||||||
);
|
|
||||||
|
|
||||||
let uniform_sampler_2d_str = (0..STRUCTURES_TEXTURES_NUMBER)
|
|
||||||
.map(|i| format!("tex{}", i))
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join(", ");
|
|
||||||
|
|
||||||
let switch_v_texture_index_str = (0..STRUCTURES_TEXTURES_NUMBER)
|
|
||||||
.map(|i| {
|
|
||||||
format!(
|
|
||||||
"
|
|
||||||
case {}u:
|
|
||||||
f_color = texture(tex{}, v_texture_coordinates);
|
|
||||||
break;
|
|
||||||
",
|
|
||||||
i, i
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join("")
|
|
||||||
+ &format!(
|
|
||||||
"
|
|
||||||
default: // case {}u:
|
|
||||||
f_color = texture(tex{}, v_texture_coordinates);
|
|
||||||
",
|
|
||||||
STRUCTURES_TEXTURES_NUMBER - 1,
|
|
||||||
STRUCTURES_TEXTURES_NUMBER - 1
|
|
||||||
);
|
|
||||||
|
|
||||||
let structures_fragment = &format!(
|
|
||||||
"
|
|
||||||
#version 140
|
|
||||||
|
|
||||||
in vec2 v_texture_coordinates;
|
|
||||||
flat in uint v_texture_index;
|
|
||||||
out vec4 f_color;
|
|
||||||
|
|
||||||
uniform sampler2D {};
|
|
||||||
|
|
||||||
void main() {{
|
|
||||||
switch (v_texture_index) {{
|
|
||||||
{}
|
|
||||||
}}
|
|
||||||
}}
|
|
||||||
",
|
|
||||||
uniform_sampler_2d_str, switch_v_texture_index_str
|
|
||||||
);
|
|
||||||
|
|
||||||
// the program
|
// the program
|
||||||
let ground_program = program!(&display,
|
let program = program!(&display,
|
||||||
140 => {
|
140 => {
|
||||||
vertex: "
|
vertex: "
|
||||||
#version 140
|
#version 140
|
||||||
@@ -370,277 +73,110 @@ fn main() {
|
|||||||
|
|
||||||
in uint index;
|
in uint index;
|
||||||
in float altitude;
|
in float altitude;
|
||||||
in uint biome;
|
|
||||||
in uvec2 chunk;
|
|
||||||
|
|
||||||
out vec2 v_tex_coords;
|
out vec2 v_tex_coords;
|
||||||
flat out uint v_biome;
|
|
||||||
|
|
||||||
const uint TILE_SIZE = 4u;
|
|
||||||
const uint TILES_PER_CHUNK_ROW = 250u;
|
|
||||||
const uint TRIANGLES_PER_CHUNK_ROW = TILES_PER_CHUNK_ROW * 2u + 2u;
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
uint index_mod_triangles_per_chunk_row = index % TRIANGLES_PER_CHUNK_ROW;
|
uint index_mod = index % 6u;
|
||||||
uint index_div_triangles_per_chunk_row = index / TRIANGLES_PER_CHUNK_ROW;
|
uint index_div = index / 6u;
|
||||||
uint index_div_triangles_per_chunk_row_mod_2 = index_div_triangles_per_chunk_row % 2u;
|
uint z = index_div / 250u;
|
||||||
uint index_mod_triangles_per_chunk_row_div_2 = index_mod_triangles_per_chunk_row / 2u;
|
uint x = index_div % 250u;
|
||||||
|
if(index_mod == 0u)
|
||||||
uint x = index_div_triangles_per_chunk_row_mod_2 == 0u ? index_mod_triangles_per_chunk_row_div_2 : TILES_PER_CHUNK_ROW - index_mod_triangles_per_chunk_row_div_2;
|
v_tex_coords = vec2(0, 0);
|
||||||
uint z = index_div_triangles_per_chunk_row + index % 2u;
|
else if(index_mod == 1u || index_mod == 4u)
|
||||||
|
{
|
||||||
switch (index % 4u) {
|
v_tex_coords = vec2(0, 1);
|
||||||
case 0u:
|
x++;
|
||||||
v_tex_coords = vec2(index_div_triangles_per_chunk_row_mod_2, 0);
|
|
||||||
break;
|
|
||||||
case 1u:
|
|
||||||
v_tex_coords = vec2(index_div_triangles_per_chunk_row_mod_2, 1);
|
|
||||||
break;
|
|
||||||
case 2u:
|
|
||||||
v_tex_coords = vec2(1u - index_div_triangles_per_chunk_row_mod_2, 0);
|
|
||||||
break;
|
|
||||||
default: // case 3u
|
|
||||||
v_tex_coords = vec2(1u - index_div_triangles_per_chunk_row_mod_2, 1);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
v_biome = biome;
|
else if(index_mod == 2u || index_mod == 3u)
|
||||||
|
{
|
||||||
x *= TILE_SIZE;
|
v_tex_coords = vec2(1, 0);
|
||||||
z *= TILE_SIZE;
|
z++;
|
||||||
|
}
|
||||||
x += chunk.x;
|
else //if(index_mod == 5u)
|
||||||
z += chunk.y;
|
{
|
||||||
|
v_tex_coords = vec2(1, 1);
|
||||||
gl_Position = persp_matrix * view_matrix * vec4(vec3(x, altitude, z), 1.0);
|
x++;
|
||||||
|
z++;
|
||||||
|
}
|
||||||
|
gl_Position = persp_matrix * view_matrix * vec4(vec3(x, altitude, z) * 0.005, 1.0);
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
|
|
||||||
fragment: ground_fragment,
|
fragment: "
|
||||||
|
#version 140
|
||||||
|
|
||||||
|
flat in vec3 normal;
|
||||||
|
in vec2 v_tex_coords;
|
||||||
|
out vec4 f_color;
|
||||||
|
flat in uint biome;
|
||||||
|
|
||||||
|
uniform sampler2D tex0, tex1, tex2, tex3, tex4, tex5, tex6, tex7, tex8, tex9, tex10, tex11, tex12, tex13, tex14, tex15, tex16, tex17, tex18;
|
||||||
|
|
||||||
|
const vec3 LIGHT = vec3(0.0, -1.0, 0.0);
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
float lum = max(dot(normalize(normal), normalize(LIGHT)), 0.0);
|
||||||
|
|
||||||
|
if(biome == 0u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex0, v_tex_coords);
|
||||||
|
else if(biome == 1u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex1, v_tex_coords);
|
||||||
|
else if(biome == 2u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex2, v_tex_coords);
|
||||||
|
else if(biome == 3u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex3, v_tex_coords);
|
||||||
|
else if(biome == 4u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex4, v_tex_coords);
|
||||||
|
else if(biome == 5u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex5, v_tex_coords);
|
||||||
|
else if(biome == 6u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex6, v_tex_coords);
|
||||||
|
else if(biome == 7u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex7, v_tex_coords);
|
||||||
|
else if(biome == 8u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex8, v_tex_coords);
|
||||||
|
else if(biome == 9u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex9, v_tex_coords);
|
||||||
|
else if(biome == 10u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex10, v_tex_coords);
|
||||||
|
else if(biome == 11u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex11, v_tex_coords);
|
||||||
|
else if(biome == 12u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex12, v_tex_coords);
|
||||||
|
else if(biome == 13u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex13, v_tex_coords);
|
||||||
|
else if(biome == 14u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex14, v_tex_coords);
|
||||||
|
else if(biome == 15u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex15, v_tex_coords);
|
||||||
|
else if(biome == 16u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex16, v_tex_coords);
|
||||||
|
else if(biome == 17u) f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex17, v_tex_coords);
|
||||||
|
else /*if(biome == 18u)*/ f_color = (0.3 + 0.7 * lum, 1.0) * texture(tex18, v_tex_coords);
|
||||||
|
}
|
||||||
|
"
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut camera = support::camera::CameraState::new();
|
let mut camera = support::camera::CameraState::new();
|
||||||
|
|
||||||
let structures_folder = "Extensions/LemnosLife/Map/Common/Structures/";
|
|
||||||
let paths = fs::read_dir(structures_folder).unwrap();
|
|
||||||
let mut structures_vertex_buffer: Vec<(usize, VertexBufferAny)> = vec![];
|
|
||||||
|
|
||||||
for path in paths {
|
|
||||||
let path = path.unwrap().path();
|
|
||||||
let file_path = path.to_str().unwrap();
|
|
||||||
if file_path.ends_with(".obj") {
|
|
||||||
let file = file_path.replace(structures_folder, "");
|
|
||||||
println!("{}", file);
|
|
||||||
structures_vertex_buffer.push((
|
|
||||||
file.replace(".obj", "").parse().unwrap(),
|
|
||||||
support::load_wavefront(&display, load_bytes!(&format!("../{}", file_path))),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut structures_per_instance: Vec<Vec<PerInstance>> = Vec::with_capacity(926); // As the maximum structure id is 925.
|
|
||||||
for _ in 0..=925 {
|
|
||||||
structures_per_instance.push(vec![]);
|
|
||||||
}
|
|
||||||
|
|
||||||
let structures_program = program!(&display,
|
|
||||||
140 => {
|
|
||||||
vertex: "
|
|
||||||
#version 140
|
|
||||||
|
|
||||||
uniform mat4 persp_matrix;
|
|
||||||
uniform mat4 view_matrix;
|
|
||||||
|
|
||||||
in vec3 w_position;
|
|
||||||
in float w_rotation;
|
|
||||||
in vec3 position;
|
|
||||||
in uint texture_index;
|
|
||||||
in vec2 texture_coordinates;
|
|
||||||
flat out uint v_texture_index;
|
|
||||||
out vec2 v_texture_coordinates;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
float cos_rotation = cos(w_rotation);
|
|
||||||
float sin_rotation = sin(w_rotation);
|
|
||||||
|
|
||||||
vec3 rotated_position = position;
|
|
||||||
|
|
||||||
rotated_position.x = cos_rotation * position.x + sin_rotation * position.z;
|
|
||||||
rotated_position.z = -sin_rotation * position.x + cos_rotation * position.z;
|
|
||||||
|
|
||||||
v_texture_index = texture_index;
|
|
||||||
v_texture_coordinates = texture_coordinates;
|
|
||||||
gl_Position = persp_matrix * view_matrix * vec4(rotated_position + w_position, 1.0);
|
|
||||||
}
|
|
||||||
",
|
|
||||||
|
|
||||||
fragment: structures_fragment,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let objects_folder = "Extensions/LemnosLife/Map/Altis/Objects/";
|
|
||||||
let paths = fs::read_dir(objects_folder).unwrap();
|
|
||||||
|
|
||||||
for path in paths {
|
|
||||||
let path = path.unwrap().path();
|
|
||||||
let file_path = path.to_str().unwrap();
|
|
||||||
let file = file_path.replace(objects_folder, "");
|
|
||||||
println!("{}", file);
|
|
||||||
let file_name = file.replace(".objects", "");
|
|
||||||
let file_name_parts: Vec<&str> = file_name.split(' ').collect();
|
|
||||||
|
|
||||||
let objects_contents = fs::read_to_string(file_path)
|
|
||||||
.unwrap_or_else(|_| panic!("Unable to load {} file!", file_path));
|
|
||||||
|
|
||||||
let chunk = [0, 1].map(|file_name_parts_index| {
|
|
||||||
file_name_parts[file_name_parts_index]
|
|
||||||
.parse::<f32>()
|
|
||||||
.unwrap()
|
|
||||||
* (CHUNK_SIZE as f32)
|
|
||||||
});
|
|
||||||
|
|
||||||
let objects_lines: Vec<&str> = objects_contents.split('\n').collect();
|
|
||||||
|
|
||||||
let (mut offset_x, mut offset_y) = (0.0, 0.0);
|
|
||||||
for object_line in objects_lines {
|
|
||||||
let object_line_parts: Vec<&str> = object_line.split(' ').collect();
|
|
||||||
if object_line_parts.len() == 2 {
|
|
||||||
offset_x = object_line_parts[0].parse::<f32>().unwrap() * 100.0 + chunk[0];
|
|
||||||
offset_y = object_line_parts[1].parse::<f32>().unwrap() * 100.0 + chunk[1];
|
|
||||||
} else {
|
|
||||||
let structure_id: usize = object_line_parts[0].parse().unwrap();
|
|
||||||
let x: f32 = object_line_parts[1].parse().unwrap();
|
|
||||||
let y: f32 = object_line_parts[2].parse().unwrap();
|
|
||||||
let z = object_line_parts[3].parse().unwrap();
|
|
||||||
let rotation: f32 = object_line_parts[4].parse().unwrap();
|
|
||||||
let structure_per_instance: &mut Vec<PerInstance> =
|
|
||||||
structures_per_instance.get_mut(structure_id).unwrap();
|
|
||||||
structure_per_instance.push(PerInstance {
|
|
||||||
w_position: (offset_x + x, z, offset_y + y),
|
|
||||||
w_rotation: 2.0 * PI * rotation / 360.0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// the main loop
|
// the main loop
|
||||||
support::start_loop(event_loop, move |events| {
|
support::start_loop(event_loop, move |events| {
|
||||||
camera.update();
|
camera.update();
|
||||||
|
|
||||||
// building the uniforms
|
// building the uniforms
|
||||||
let ground_uniforms = uniform! {
|
let uniforms = uniform! {
|
||||||
persp_matrix: camera.get_perspective(),
|
persp_matrix: camera.get_perspective(),
|
||||||
view_matrix: camera.get_view(),
|
view_matrix: camera.get_view(),
|
||||||
tex0: &ground_textures[0],
|
tex0: &textures[0],
|
||||||
tex1: &ground_textures[1],
|
tex1: &textures[1],
|
||||||
tex2: &ground_textures[2],
|
tex2: &textures[2],
|
||||||
tex3: &ground_textures[3],
|
tex3: &textures[3],
|
||||||
tex4: &ground_textures[4],
|
tex4: &textures[4],
|
||||||
tex5: &ground_textures[5],
|
tex5: &textures[5],
|
||||||
tex6: &ground_textures[6],
|
tex6: &textures[6],
|
||||||
tex7: &ground_textures[7],
|
tex7: &textures[7],
|
||||||
tex8: &ground_textures[8],
|
tex8: &textures[8],
|
||||||
tex9: &ground_textures[9],
|
tex9: &textures[9],
|
||||||
tex10: &ground_textures[10],
|
tex10: &textures[10],
|
||||||
tex11: &ground_textures[11],
|
tex11: &textures[11],
|
||||||
tex12: &ground_textures[12],
|
tex12: &textures[12],
|
||||||
tex13: &ground_textures[13],
|
tex13: &textures[13],
|
||||||
tex14: &ground_textures[14],
|
tex14: &textures[14],
|
||||||
tex15: &ground_textures[15],
|
tex15: &textures[15],
|
||||||
tex16: &ground_textures[16],
|
tex16: &textures[16],
|
||||||
tex17: &ground_textures[17],
|
tex17: &textures[17],
|
||||||
tex18: &ground_textures[18],
|
tex18: &textures[18],
|
||||||
};
|
chunks: &chunks,
|
||||||
|
|
||||||
// That way we *load* far too many textures per structure but until haven't treated http://gitea.lemnoslife.com:3006/Benjamin_Loison/LemnosLife_Rust/issues/6#issuecomment-240, can't do better.
|
|
||||||
// Except if we proceed with a disjunction on the number of textures used in a structure which is 8, thanks to `find Extensions/LemnosLife/Map/Common/Structures/ -name '*.obj' -exec sh -c 'grep -o usemtl {} | wc -l' \; | sort -n | tail -1`.
|
|
||||||
let structures_uniforms = uniform! {
|
|
||||||
persp_matrix: camera.get_perspective(),
|
|
||||||
view_matrix: camera.get_view(),
|
|
||||||
tex0: &structures_textures[0],
|
|
||||||
tex1: &structures_textures[1],
|
|
||||||
tex2: &structures_textures[2],
|
|
||||||
tex3: &structures_textures[3],
|
|
||||||
tex4: &structures_textures[4],
|
|
||||||
tex5: &structures_textures[5],
|
|
||||||
tex6: &structures_textures[6],
|
|
||||||
tex7: &structures_textures[7],
|
|
||||||
tex8: &structures_textures[8],
|
|
||||||
tex9: &structures_textures[9],
|
|
||||||
tex10: &structures_textures[10],
|
|
||||||
tex11: &structures_textures[11],
|
|
||||||
tex12: &structures_textures[12],
|
|
||||||
tex13: &structures_textures[13],
|
|
||||||
tex14: &structures_textures[14],
|
|
||||||
tex15: &structures_textures[15],
|
|
||||||
tex16: &structures_textures[16],
|
|
||||||
tex17: &structures_textures[17],
|
|
||||||
tex18: &structures_textures[18],
|
|
||||||
tex19: &structures_textures[19],
|
|
||||||
tex20: &structures_textures[20],
|
|
||||||
tex21: &structures_textures[21],
|
|
||||||
tex22: &structures_textures[22],
|
|
||||||
tex23: &structures_textures[23],
|
|
||||||
tex24: &structures_textures[24],
|
|
||||||
tex25: &structures_textures[25],
|
|
||||||
tex26: &structures_textures[26],
|
|
||||||
tex27: &structures_textures[27],
|
|
||||||
tex28: &structures_textures[28],
|
|
||||||
tex29: &structures_textures[29],
|
|
||||||
tex30: &structures_textures[30],
|
|
||||||
tex31: &structures_textures[31],
|
|
||||||
tex32: &structures_textures[32],
|
|
||||||
tex33: &structures_textures[33],
|
|
||||||
tex34: &structures_textures[34],
|
|
||||||
tex35: &structures_textures[35],
|
|
||||||
tex36: &structures_textures[36],
|
|
||||||
tex37: &structures_textures[37],
|
|
||||||
tex38: &structures_textures[38],
|
|
||||||
tex39: &structures_textures[39],
|
|
||||||
tex40: &structures_textures[40],
|
|
||||||
tex41: &structures_textures[41],
|
|
||||||
tex42: &structures_textures[42],
|
|
||||||
tex43: &structures_textures[43],
|
|
||||||
tex44: &structures_textures[44],
|
|
||||||
tex45: &structures_textures[45],
|
|
||||||
tex46: &structures_textures[46],
|
|
||||||
tex47: &structures_textures[47],
|
|
||||||
tex48: &structures_textures[48],
|
|
||||||
tex49: &structures_textures[49],
|
|
||||||
tex50: &structures_textures[50],
|
|
||||||
tex51: &structures_textures[51],
|
|
||||||
tex52: &structures_textures[52],
|
|
||||||
tex53: &structures_textures[53],
|
|
||||||
tex54: &structures_textures[54],
|
|
||||||
tex55: &structures_textures[55],
|
|
||||||
tex56: &structures_textures[56],
|
|
||||||
tex57: &structures_textures[57],
|
|
||||||
tex58: &structures_textures[58],
|
|
||||||
tex59: &structures_textures[59],
|
|
||||||
tex60: &structures_textures[60],
|
|
||||||
tex61: &structures_textures[61],
|
|
||||||
tex62: &structures_textures[62],
|
|
||||||
tex63: &structures_textures[63],
|
|
||||||
tex64: &structures_textures[64],
|
|
||||||
tex65: &structures_textures[65],
|
|
||||||
tex66: &structures_textures[66],
|
|
||||||
tex67: &structures_textures[67],
|
|
||||||
tex68: &structures_textures[68],
|
|
||||||
tex69: &structures_textures[69],
|
|
||||||
tex70: &structures_textures[70],
|
|
||||||
tex71: &structures_textures[71],
|
|
||||||
tex72: &structures_textures[72],
|
|
||||||
tex73: &structures_textures[73],
|
|
||||||
tex74: &structures_textures[74],
|
|
||||||
tex75: &structures_textures[75],
|
|
||||||
tex76: &structures_textures[76],
|
|
||||||
tex77: &structures_textures[77],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// draw parameters
|
// draw parameters
|
||||||
let ground_params = glium::DrawParameters {
|
let params = glium::DrawParameters {
|
||||||
depth: glium::Depth {
|
depth: glium::Depth {
|
||||||
test: glium::DepthTest::IfLess,
|
test: glium::DepthTest::IfLess,
|
||||||
write: true,
|
write: true,
|
||||||
@@ -651,58 +187,30 @@ fn main() {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut structures_params = ground_params.clone();
|
|
||||||
structures_params.blend = glium::draw_parameters::Blend::alpha_blending(); // Could disable per opaque structure to optimize.
|
|
||||||
// Doesn't seem to apply transparency from a structure instance to the other.
|
|
||||||
|
|
||||||
// drawing a frame
|
// drawing a frame
|
||||||
let start = Instant::now();
|
|
||||||
let mut target = display.draw();
|
let mut target = display.draw();
|
||||||
target.clear_color_and_depth((0.0, 0.0, 0.0, 0.0), 1.0);
|
target.clear_color_and_depth((0.0, 0.0, 0.0, 0.0), 1.0);
|
||||||
target
|
target
|
||||||
.draw(
|
.draw(
|
||||||
&ground_vertex_buffer,
|
&vertex_buffer,
|
||||||
&glium::index::NoIndices(glium::index::PrimitiveType::TriangleStrip),
|
&glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList),
|
||||||
&ground_program,
|
&program,
|
||||||
&ground_uniforms,
|
&uniforms,
|
||||||
&ground_params,
|
¶ms,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
for (structure_id, structure_vertex_buffer) in &structures_vertex_buffer {
|
|
||||||
let structure_per_instance = &structures_per_instance[*structure_id];
|
|
||||||
if !structure_per_instance.is_empty() {
|
|
||||||
let structure_per_instance_buffer =
|
|
||||||
glium::vertex::VertexBuffer::new(&display, structure_per_instance).unwrap();
|
|
||||||
|
|
||||||
target
|
|
||||||
.draw(
|
|
||||||
(
|
|
||||||
structure_vertex_buffer,
|
|
||||||
structure_per_instance_buffer.per_instance().unwrap(),
|
|
||||||
),
|
|
||||||
&glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList),
|
|
||||||
&structures_program,
|
|
||||||
&structures_uniforms,
|
|
||||||
&structures_params,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
target.finish().unwrap();
|
target.finish().unwrap();
|
||||||
let duration = start.elapsed();
|
|
||||||
println!("Time elapsed is: {:?}", duration);
|
|
||||||
|
|
||||||
let mut action = support::Action::Continue;
|
let mut action = support::Action::Continue;
|
||||||
|
|
||||||
// polling and handling the events received by the window
|
// polling and handling the events received by the window
|
||||||
for event in events {
|
for event in events {
|
||||||
if let glutin::event::Event::WindowEvent { event, .. } = event {
|
match event {
|
||||||
match event {
|
glutin::event::Event::WindowEvent { event, .. } => match event {
|
||||||
glutin::event::WindowEvent::CloseRequested => action = support::Action::Stop,
|
glutin::event::WindowEvent::CloseRequested => action = support::Action::Stop,
|
||||||
ev => camera.process_input(ev),
|
ev => camera.process_input(&ev),
|
||||||
}
|
},
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+22
-24
@@ -13,14 +13,12 @@ pub struct CameraState {
|
|||||||
rotate_right: bool,
|
rotate_right: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
const SPEED: f32 = 10.0; //1.0;
|
|
||||||
|
|
||||||
impl CameraState {
|
impl CameraState {
|
||||||
pub fn new() -> CameraState {
|
pub fn new() -> CameraState {
|
||||||
CameraState {
|
CameraState {
|
||||||
aspect_ratio: 1_920.0 / 1_080.0,
|
aspect_ratio: 1024.0 / 768.0,
|
||||||
|
position: (0.1, 0.1, 1.0),
|
||||||
// The second coordinate is for the altitude.
|
// The second coordinate is for the altitude.
|
||||||
position: (3_646.41, 12.3622, 13_113.7),
|
|
||||||
direction: (0.0, 0.0, -1.0),
|
direction: (0.0, 0.0, -1.0),
|
||||||
moving_up: false,
|
moving_up: false,
|
||||||
moving_left: false,
|
moving_left: false,
|
||||||
@@ -34,8 +32,8 @@ impl CameraState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_perspective(&self) -> [[f32; 4]; 4] {
|
pub fn get_perspective(&self) -> [[f32; 4]; 4] {
|
||||||
let fov: f32 = std::f32::consts::PI / 2.0;
|
let fov: f32 = 3.141592 / 2.0;
|
||||||
let zfar = 53_209.0;
|
let zfar = 8000.0;
|
||||||
let znear = 0.01;
|
let znear = 0.01;
|
||||||
|
|
||||||
let f = 1.0 / (fov / 2.0).tan();
|
let f = 1.0 / (fov / 2.0).tan();
|
||||||
@@ -121,39 +119,39 @@ impl CameraState {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if self.moving_up {
|
if self.moving_up {
|
||||||
self.position.0 += u.0 * SPEED;
|
self.position.0 += u.0 * 0.01;
|
||||||
self.position.1 += u.1 * SPEED;
|
self.position.1 += u.1 * 0.01;
|
||||||
self.position.2 += u.2 * SPEED;
|
self.position.2 += u.2 * 0.01;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.moving_left {
|
if self.moving_left {
|
||||||
self.position.0 -= s.0 * SPEED;
|
self.position.0 -= s.0 * 0.01;
|
||||||
self.position.1 -= s.1 * SPEED;
|
self.position.1 -= s.1 * 0.01;
|
||||||
self.position.2 -= s.2 * SPEED;
|
self.position.2 -= s.2 * 0.01;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.moving_down {
|
if self.moving_down {
|
||||||
self.position.0 -= u.0 * SPEED;
|
self.position.0 -= u.0 * 0.01;
|
||||||
self.position.1 -= u.1 * SPEED;
|
self.position.1 -= u.1 * 0.01;
|
||||||
self.position.2 -= u.2 * SPEED;
|
self.position.2 -= u.2 * 0.01;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.moving_right {
|
if self.moving_right {
|
||||||
self.position.0 += s.0 * SPEED;
|
self.position.0 += s.0 * 0.01;
|
||||||
self.position.1 += s.1 * SPEED;
|
self.position.1 += s.1 * 0.01;
|
||||||
self.position.2 += s.2 * SPEED;
|
self.position.2 += s.2 * 0.01;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.moving_forward {
|
if self.moving_forward {
|
||||||
self.position.0 += f.0 * SPEED;
|
self.position.0 += f.0 * 0.01;
|
||||||
self.position.1 += f.1 * SPEED;
|
self.position.1 += f.1 * 0.01;
|
||||||
self.position.2 += f.2 * SPEED;
|
self.position.2 += f.2 * 0.01;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.moving_backward {
|
if self.moving_backward {
|
||||||
self.position.0 -= f.0 * SPEED;
|
self.position.0 -= f.0 * 0.01;
|
||||||
self.position.1 -= f.1 * SPEED;
|
self.position.1 -= f.1 * 0.01;
|
||||||
self.position.2 -= f.2 * SPEED;
|
self.position.2 -= f.2 * 0.01;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.rotate_left {
|
if self.rotate_left {
|
||||||
|
|||||||
+101
-156
@@ -1,5 +1,4 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use crate::STRUCTURES_TEXTURES_REVERSED;
|
|
||||||
use glium::glutin::event::{Event, StartCause};
|
use glium::glutin::event::{Event, StartCause};
|
||||||
use glium::glutin::event_loop::{ControlFlow, EventLoop};
|
use glium::glutin::event_loop::{ControlFlow, EventLoop};
|
||||||
use glium::vertex::VertexBufferAny;
|
use glium::vertex::VertexBufferAny;
|
||||||
@@ -22,10 +21,10 @@ where
|
|||||||
let mut next_frame_time = Instant::now();
|
let mut next_frame_time = Instant::now();
|
||||||
event_loop.run(move |event, _, control_flow| {
|
event_loop.run(move |event, _, control_flow| {
|
||||||
let run_callback = match event.to_static() {
|
let run_callback = match event.to_static() {
|
||||||
Some(Event::NewEvents(cause)) => matches!(
|
Some(Event::NewEvents(cause)) => match cause {
|
||||||
cause,
|
StartCause::ResumeTimeReached { .. } | StartCause::Init => true,
|
||||||
StartCause::ResumeTimeReached { .. } | StartCause::Init
|
_ => false,
|
||||||
),
|
},
|
||||||
Some(event) => {
|
Some(event) => {
|
||||||
events_buffer.push(event);
|
events_buffer.push(event);
|
||||||
false
|
false
|
||||||
@@ -58,211 +57,157 @@ where
|
|||||||
|
|
||||||
fn get_biome(line: &str, index: usize) -> u32 {
|
fn get_biome(line: &str, index: usize) -> u32 {
|
||||||
let biome_char = line.chars().nth(index).unwrap();
|
let biome_char = line.chars().nth(index).unwrap();
|
||||||
if ('0'..='9').contains(&biome_char) {
|
return if '0' <= biome_char && biome_char <= '9' {
|
||||||
biome_char.to_digit(10).unwrap()
|
biome_char.to_digit(10).unwrap()
|
||||||
} else {
|
} else {
|
||||||
(10 + (biome_char as u8 - b'A')) as u32
|
(10 + (biome_char as u8 - 'A' as u8)) as u32
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_altitude(height_columns: &[&str], columns_index: usize) -> f32 {
|
fn get_altitude(height_columns: &Vec<&str>, columns_index: usize) -> f32 {
|
||||||
let height_str = height_columns[columns_index];
|
let height_str = height_columns[columns_index];
|
||||||
if height_str == "N" {
|
return if height_str == "N" {
|
||||||
SEABED_ALTITUDE
|
-100.0
|
||||||
} else {
|
} else {
|
||||||
height_str.parse::<f32>().unwrap()
|
height_str.parse::<f32>().unwrap()
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const SEABED_ALTITUDE: f32 = -100.0;
|
|
||||||
// seabed altitude - biggest drop * tiles in a chunk * (chunks in a row - 1)
|
|
||||||
const ALTITUDE_BETWEEN_CHUNKS: f32 = SEABED_ALTITUDE - 16.17 * 250.0 * 30.0;
|
|
||||||
pub const CHUNK_SIZE: u32 = 1_000;
|
|
||||||
|
|
||||||
/// Returns a vertex buffer that should be rendered as `TrianglesList`.
|
/// Returns a vertex buffer that should be rendered as `TrianglesList`.
|
||||||
pub fn load_ground(display: &Display) -> VertexBufferAny {
|
pub fn load_ground(display: &Display) -> (VertexBufferAny, Vec<[u32; 2]>) {
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
altitude: f32,
|
altitude: f32,
|
||||||
|
normal: [f32; 3],
|
||||||
index: u32,
|
index: u32,
|
||||||
biome: u32,
|
biome: u32,
|
||||||
chunk: [u32; 2],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
implement_vertex!(Vertex, altitude, index, biome, chunk);
|
implement_vertex!(Vertex, altitude, normal, index, biome);
|
||||||
|
|
||||||
let mut vertex_data: Vec<Vertex> = Vec::new();
|
let mut vertex_data: Vec<Vertex> = Vec::new();
|
||||||
|
let mut chunks: Vec<[u32; 2]> = Vec::new();
|
||||||
|
|
||||||
let ground_folder = "Extensions/LemnosLife/Map/Altis/Ground/";
|
let ground_folder = "Extensions/LemnosLife/Map/Altis/Ground/";
|
||||||
let paths = fs::read_dir(ground_folder).unwrap();
|
let paths = fs::read_dir(ground_folder).unwrap();
|
||||||
|
|
||||||
for (i, path) in (0_u32..).zip(paths) {
|
let mut i: u32 = 0;
|
||||||
|
|
||||||
|
for path in paths {
|
||||||
let file_name = path
|
let file_name = path
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.path()
|
.path()
|
||||||
.to_str()
|
.to_str()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.replace(ground_folder, "")
|
.replace("Extensions/LemnosLife/Map/Altis/Ground/", "")
|
||||||
.replace(".height", "");
|
.replace(".height", "");
|
||||||
println!("{}", file_name);
|
println!("{}", file_name);
|
||||||
let file_name_parts: Vec<&str> = file_name.split(' ').collect();
|
let file_name_parts: Vec<&str> = file_name.split(' ').collect();
|
||||||
|
|
||||||
let chunk = [0, 1].map(|file_name_parts_index| {
|
chunks.push([file_name_parts[0].parse().unwrap(), file_name_parts[1].parse().unwrap()]);
|
||||||
file_name_parts[file_name_parts_index]
|
|
||||||
.parse::<u32>()
|
|
||||||
.unwrap()
|
|
||||||
* CHUNK_SIZE
|
|
||||||
});
|
|
||||||
|
|
||||||
// have deleted a few height files to make it work
|
// have deleted a few height files to make it work
|
||||||
let [height_contents, biomes_contents] =
|
// TODO: use triangle strip
|
||||||
[["Ground", "height"], ["Biomes", "biomes"]].map(|[folder, extension]| {
|
let height_contents = fs::read_to_string(&format!(
|
||||||
fs::read_to_string(&format!(
|
"Extensions/LemnosLife/Map/Altis/Ground/{}.height",
|
||||||
"Extensions/LemnosLife/Map/Altis/{folder}/{file_name}.{extension}"
|
file_name
|
||||||
))
|
))
|
||||||
.unwrap_or_else(|_| panic!("Unable to load {} file!", extension))
|
.expect("Unable to load ground file!");
|
||||||
});
|
|
||||||
|
|
||||||
let height_lines: Vec<&str> = height_contents.split('\n').rev().collect();
|
let biomes_contents = fs::read_to_string(&format!(
|
||||||
|
"Extensions/LemnosLife/Map/Altis/Biomes/{}.biomes",
|
||||||
|
file_name
|
||||||
|
))
|
||||||
|
.expect("Unable to load biomes file!");
|
||||||
|
println!("alpha");
|
||||||
|
|
||||||
|
let height_lines: Vec<&str> = height_contents.split('\n').collect();
|
||||||
|
|
||||||
let biomes_lines: Vec<&str> = biomes_contents.split('\n').collect();
|
let biomes_lines: Vec<&str> = biomes_contents.split('\n').collect();
|
||||||
|
println!("beta");
|
||||||
|
|
||||||
let mut index: u32 = 0;
|
let mut index: u32 = 0;
|
||||||
|
|
||||||
for lines_index in 0..height_lines.len() - 1 {
|
for lines_index in 0..height_lines.len() - 1 {
|
||||||
let [height_columns, height_next_columns]: [Vec<&str>; 2] =
|
let height_line = height_lines[lines_index];
|
||||||
[height_lines[lines_index], height_lines[lines_index + 1]]
|
let height_next_line = height_lines[lines_index + 1];
|
||||||
.map(|height_line| height_line.split(' '))
|
let height_columns: Vec<&str> = height_line.split(' ').collect();
|
||||||
.map(|height_columns_split| {
|
let height_next_columns: Vec<&str> = height_next_line.split(' ').collect();
|
||||||
if lines_index % 2 == 0 {
|
|
||||||
height_columns_split.collect()
|
|
||||||
} else {
|
|
||||||
height_columns_split.rev().collect()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let biomes_line = biomes_lines[lines_index / 2];
|
let biomes_line = biomes_lines[lines_index / 2];
|
||||||
|
|
||||||
for columns_index in 0..height_columns.len() {
|
for columns_index in 0..height_columns.len() - 1 {
|
||||||
let [column, column_below]: [f32; 2] = [&height_columns, &height_next_columns]
|
let column = get_altitude(&height_columns, columns_index);
|
||||||
.map(|height_columns| get_altitude(height_columns, columns_index));
|
let column_right = get_altitude(&height_columns, columns_index + 1);
|
||||||
|
let column_below = get_altitude(&height_next_columns, columns_index);
|
||||||
|
let column_below_right = get_altitude(&height_next_columns, columns_index + 1);
|
||||||
|
|
||||||
let biome_index = if lines_index % 2 == 0 {
|
let biome = get_biome(biomes_line, columns_index / 2);
|
||||||
columns_index
|
|
||||||
} else {
|
|
||||||
height_columns.len() - columns_index
|
|
||||||
} / 2;
|
|
||||||
let biome = get_biome(biomes_line, biome_index);
|
|
||||||
|
|
||||||
if lines_index == 0 && columns_index == 0 {
|
// TODO: compute normals if necessary.
|
||||||
// These vertexes respectively define the end of the wall below the ground and make the cursor ready to be used.
|
|
||||||
[ALTITUDE_BETWEEN_CHUNKS, column]
|
|
||||||
.into_iter()
|
|
||||||
.for_each(|altitude| {
|
|
||||||
vertex_data.push(Vertex {
|
|
||||||
altitude,
|
|
||||||
index,
|
|
||||||
biome,
|
|
||||||
chunk,
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[column, column_below].into_iter().for_each(|altitude| {
|
// First triangle.
|
||||||
vertex_data.push(Vertex {
|
|
||||||
altitude,
|
vertex_data.push(Vertex {
|
||||||
index,
|
altitude: column,
|
||||||
biome,
|
normal: [0.0, 0.0, 1.0],
|
||||||
chunk,
|
index,
|
||||||
});
|
biome,
|
||||||
index += 1
|
|
||||||
});
|
});
|
||||||
|
index += 1;
|
||||||
|
|
||||||
|
vertex_data.push(Vertex {
|
||||||
|
altitude: column_right,
|
||||||
|
normal: [0.0, 0.0, 1.0],
|
||||||
|
index,
|
||||||
|
biome,
|
||||||
|
});
|
||||||
|
index += 1;
|
||||||
|
|
||||||
|
vertex_data.push(Vertex {
|
||||||
|
altitude: column_below,
|
||||||
|
normal: [0.0, 0.0, 1.0],
|
||||||
|
index,
|
||||||
|
biome,
|
||||||
|
});
|
||||||
|
index += 1;
|
||||||
|
|
||||||
|
// Second triangle.
|
||||||
|
|
||||||
|
vertex_data.push(Vertex {
|
||||||
|
altitude: column_below,
|
||||||
|
normal: [0.0, 0.0, 1.0],
|
||||||
|
index,
|
||||||
|
biome,
|
||||||
|
});
|
||||||
|
index += 1;
|
||||||
|
|
||||||
|
vertex_data.push(Vertex {
|
||||||
|
altitude: column_right,
|
||||||
|
normal: [0.0, 0.0, 1.0],
|
||||||
|
index,
|
||||||
|
biome,
|
||||||
|
});
|
||||||
|
index += 1;
|
||||||
|
|
||||||
|
vertex_data.push(Vertex {
|
||||||
|
altitude: column_below_right,
|
||||||
|
normal: [0.0, 0.0, 1.0],
|
||||||
|
index,
|
||||||
|
biome,
|
||||||
|
});
|
||||||
|
index += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// This vertex remove the wall across the chunks above the ground.
|
i += 1;
|
||||||
vertex_data.push(Vertex {
|
|
||||||
altitude: ALTITUDE_BETWEEN_CHUNKS,
|
|
||||||
index,
|
|
||||||
biome: 0,
|
|
||||||
chunk,
|
|
||||||
});
|
|
||||||
// i == 250 thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: BufferCreationError(OutOfMemory)', src/support/mod.rs:203:10
|
// i == 250 thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: BufferCreationError(OutOfMemory)', src/support/mod.rs:203:10
|
||||||
/*if i == 1 {
|
if i == 200 {
|
||||||
break;
|
break;
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
println!("charlie");
|
println!("charlie");
|
||||||
|
|
||||||
glium::vertex::VertexBuffer::new(display, &vertex_data)
|
(glium::vertex::VertexBuffer::new(display, &vertex_data)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into()
|
.into(), chunks)
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load_wavefront(display: &Display, data: &[u8]) -> VertexBufferAny {
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
struct Vertex {
|
|
||||||
position: [f32; 3],
|
|
||||||
texture_index: u32,
|
|
||||||
texture_coordinates: [f32; 2],
|
|
||||||
}
|
|
||||||
|
|
||||||
implement_vertex!(Vertex, position, texture_index, texture_coordinates);
|
|
||||||
|
|
||||||
let mut data = ::std::io::BufReader::new(data);
|
|
||||||
let data = obj::ObjData::load_buf(&mut data).unwrap();
|
|
||||||
|
|
||||||
let mut vertex_data = Vec::new();
|
|
||||||
|
|
||||||
for object in data.objects.iter() {
|
|
||||||
for group in object.groups.iter() {
|
|
||||||
for poly in &group.polys {
|
|
||||||
match poly {
|
|
||||||
obj::SimplePolygon(indices) => {
|
|
||||||
for v in indices.iter().take(3) {
|
|
||||||
let position = data.position[v.0];
|
|
||||||
let position = [position[0], position[2], position[1]];
|
|
||||||
let texture_coordinates = data.texture[v.1.unwrap()];
|
|
||||||
|
|
||||||
let texture_index = if let obj::ObjMaterial::Ref(texture) =
|
|
||||||
group.material.as_ref().unwrap()
|
|
||||||
{
|
|
||||||
STRUCTURES_TEXTURES_REVERSED[texture]
|
|
||||||
} else {
|
|
||||||
panic!()
|
|
||||||
};
|
|
||||||
|
|
||||||
vertex_data.push(Vertex {
|
|
||||||
position,
|
|
||||||
texture_index,
|
|
||||||
texture_coordinates,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
for i in [0, 2, 3] {
|
|
||||||
let v = indices[i];
|
|
||||||
let position = data.position[v.0];
|
|
||||||
let position = [position[0], position[2], position[1]];
|
|
||||||
let texture_coordinates = data.texture[v.1.unwrap()];
|
|
||||||
|
|
||||||
let texture_index = if let obj::ObjMaterial::Ref(texture) =
|
|
||||||
group.material.as_ref().unwrap()
|
|
||||||
{
|
|
||||||
STRUCTURES_TEXTURES_REVERSED[texture]
|
|
||||||
} else {
|
|
||||||
panic!()
|
|
||||||
};
|
|
||||||
|
|
||||||
vertex_data.push(Vertex {
|
|
||||||
position,
|
|
||||||
texture_index,
|
|
||||||
texture_coordinates,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
glium::vertex::VertexBuffer::new(display, &vertex_data)
|
|
||||||
.unwrap()
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user