Witam, tworzę bibliotekę graficzną w Rust / WASM + ugli_webgl i stdweb. Myślę jednak że technologia ani cały kod nie mają tu żadnego znaczenia. Problem jest dość prozaiczny i polega na rozciąganiu się modeli w stosunku do wymiarów okna:
Przedstawione powyżej bryły powinny być sześcianami. Perspektywa wygląda tak:
self.context.viewport(0, 0, window().inner_width(), window().inner_height());
projection = glm::perspective(
(self.camera.get_zoom() as f32).to_radians(),
window().inner_width() as f32 / window().inner_height() as f32,
0.1,
100.0,
);
FOV domyślnie jest ustawiony na 45 stopni, druki argument to tradycyjne stosunek szerokości do wysokości obszaru wyświetlania. Podobne rozwiązanie zastosowałem w wersji desktopowej w C++, tam jednak wszystko działało poprawnie. Nie wiem co mogłem pominąć, będę bardzo wdzięczny za wskazówki. Implementacja kamery:
use stdweb::web::TypedArray;
use ugli_webgl::WebGL2RenderingContext as gl;
use super::exceptions::{EngineResult, EngineRuntimeError};
use nalgebra_glm as glm;
use stdweb::console;
// -----------------------------------------------------------------------------------------------------------
pub enum MovementDirection {
Forward,
Backward,
Left,
Right,
}
// -----------------------------------------------------------------------------------------------------------
pub const DEFAULT_YAW: f32 = -90.0;
pub const DEFAULT_PITCH: f32 = 0.0;
pub const DEFAULT_MOVEMENT_SPEED: f32 = 6.0;
pub const DEFAULT_MOVEMENT_SENSITIVITY: f32 = 1.3;
pub const DEFAULT_ZOOM: f32 = 45.0;
// -----------------------------------------------------------------------------------------------------------
pub struct FPSCamera {
position: glm::TVec3<f32>,
front: glm::TVec3<f32>,
up: glm::TVec3<f32>,
right: glm::TVec3<f32>,
world_up: glm::TVec3<f32>,
yaw: f32,
pitch: f32,
zoom: f32,
// const
movement_speed: f32,
mouse_sensitivity: f32,
}
// -----------------------------------------------------------------------------------------------------------
impl FPSCamera {
pub fn new(
position: glm::TVec3<f32>,
world_up: glm::TVec3<f32>,
yaw: f32,
pitch: f32,
) -> FPSCamera {
let mut camera = FPSCamera {
front: glm::vec3(0.0, 0.0, -1.0),
movement_speed: DEFAULT_MOVEMENT_SPEED,
mouse_sensitivity: DEFAULT_MOVEMENT_SENSITIVITY,
zoom: DEFAULT_ZOOM,
position,
world_up,
yaw,
pitch,
right: glm::vec3(0.5, 0.0, 0.0),
up: glm::vec3(0.5, 0.0, 0.0),
};
camera.update_camera_vectors();
camera
}
fn update_camera_vectors(&mut self) {
let mut front = glm::vec3(0.0, 0.0, 0.0);
front.x = self.yaw.to_radians().cos() * &self.pitch.to_radians().cos();
front.y = self.pitch.to_radians().sin();
front.z = self.yaw.to_radians().sin() * self.pitch.to_radians().cos();
self.front = glm::normalize(&front);
self.right = glm::normalize(&glm::cross(&self.front, &self.world_up));
self.up = glm::normalize(&glm::cross(&self.right, &self.front));
}
pub fn get_view_matrix(&self) -> glm::TMat4<f32> {
glm::look_at(&self.position, &(self.position + self.front), &self.up)
}
pub fn get_zoom(&self) -> f32 {
self.zoom
}
pub fn get_position(&self) -> &glm::TVec3<f32> {
&self.position
}
pub fn process_direction(&mut self, dir: MovementDirection) {
let velocity = self.movement_speed * 0.01;
match dir {
MovementDirection::Forward => self.position += self.front * velocity,
MovementDirection::Backward => self.position -= self.front * velocity,
MovementDirection::Left => self.position -= self.right * velocity,
MovementDirection::Right => self.position += self.right * velocity,
}
}
pub fn process_mouse_movement(&mut self, mut xoffset: f32, mut yoffset: f32) {
xoffset *= self.mouse_sensitivity;
yoffset *= self.mouse_sensitivity;
self.yaw += xoffset;
self.pitch += yoffset;
if self.pitch > 89.0 {
self.pitch = 89.0;
}
if self.pitch < -89.0 {
self.pitch = -89.0;
}
self.update_camera_vectors();
}
}
W razie potrzeby mogę dać resztę kodu lub w ogóle link do repozytorium. Z góry dziękuje za pomoc i pozdrawiam :)