first commit

This commit is contained in:
Matthieu Baumann
2024-10-11 18:15:29 +02:00
committed by Matthieu Baumann
parent 9b098fdcdd
commit 97b51f1567
17 changed files with 436 additions and 817 deletions

View File

@@ -19,23 +19,18 @@ where
}
}
}
use crate::texture::Texture2DArray;
use crate::texture::{Tex3D, Texture2DArray};
use wasm_bindgen::JsValue;
impl<F> Image for Bitmap<F>
where
F: ImageFormat + Clone,
{
fn tex_sub_image_3d(
fn insert_into_3d_texture<T: Tex3D>(
&self,
textures: &Texture2DArray,
textures: &T,
offset: &Vector3<i32>,
) -> Result<(), JsValue> {
textures.bind().tex_sub_image_3d_with_image_bitmap(
offset.z,
offset.x,
offset.y,
&self.image,
);
textures.tex_sub_image_3d_with_image_bitmap(offset.x, offset.y, offset.z, &self.image);
Ok(())
}

View File

@@ -19,24 +19,24 @@ where
use crate::image::format::ImageFormat;
use crate::image::Image;
use crate::texture::Texture2DArray;
use crate::texture::{Tex3D, Texture2DArray};
use cgmath::Vector3;
use wasm_bindgen::JsValue;
impl<F> Image for Canvas<F>
where
F: ImageFormat,
{
fn tex_sub_image_3d(
fn insert_into_3d_texture<T: Tex3D>(
&self,
// The texture array
textures: &Texture2DArray,
textures: &T,
// An offset to write the image in the texture array
offset: &Vector3<i32>,
) -> Result<(), JsValue> {
textures.bind().tex_sub_image_3d_with_html_canvas_element(
offset.z,
textures.tex_sub_image_3d_with_html_canvas_element(
offset.x,
offset.y,
offset.z,
&self.canvas,
);

View File

@@ -116,58 +116,62 @@ impl<'a> Fits<'a> {
}
}*/
use crate::image::Image;
use crate::Texture2DArray;
use crate::{image::Image, texture::Tex3D};
impl Image for Fits<'_> {
fn tex_sub_image_3d(
fn insert_into_3d_texture<T: Tex3D>(
&self,
// The texture array
textures: &Texture2DArray,
textures: &T,
// An offset to write the image in the texture array
offset: &Vector3<i32>,
) -> Result<(), JsValue> {
match &self.data {
Data::U8(data) => {
let view = unsafe { R8UI::view(&data) };
textures.bind().tex_sub_image_3d_with_opt_array_buffer_view(
offset.z,
textures.tex_sub_image_3d_with_opt_array_buffer_view(
offset.x,
offset.y,
offset.z,
self.size.x,
self.size.y,
1,
Some(view.as_ref()),
);
}
Data::I16(data) => {
let view = unsafe { R16I::view(&data) };
textures.bind().tex_sub_image_3d_with_opt_array_buffer_view(
offset.z,
textures.tex_sub_image_3d_with_opt_array_buffer_view(
offset.x,
offset.y,
offset.z,
self.size.x,
self.size.y,
1,
Some(view.as_ref()),
);
}
Data::I32(data) => {
let view = unsafe { R32I::view(&data) };
textures.bind().tex_sub_image_3d_with_opt_array_buffer_view(
offset.z,
textures.tex_sub_image_3d_with_opt_array_buffer_view(
offset.x,
offset.y,
offset.z,
self.size.x,
self.size.y,
1,
Some(view.as_ref()),
);
}
Data::F32(data) => {
let view = unsafe { R32F::view(&data) };
textures.bind().tex_sub_image_3d_with_opt_array_buffer_view(
offset.z,
textures.tex_sub_image_3d_with_opt_array_buffer_view(
offset.x,
offset.y,
offset.z,
self.size.x,
self.size.y,
1,
Some(view.as_ref()),
);
}

View File

@@ -19,24 +19,24 @@ where
use crate::image::format::ImageFormat;
use crate::image::Image;
use crate::texture::Texture2DArray;
use crate::texture::{Tex3D, Texture2DArray};
use cgmath::Vector3;
use wasm_bindgen::JsValue;
impl<F> Image for HTMLImage<F>
where
F: ImageFormat,
{
fn tex_sub_image_3d(
fn insert_into_3d_texture<T: Tex3D>(
&self,
// The texture array
textures: &Texture2DArray,
textures: &T,
// An offset to write the image in the texture array
offset: &Vector3<i32>,
) -> Result<(), JsValue> {
textures.bind().tex_sub_image_3d_with_html_image_element(
offset.z,
textures.tex_sub_image_3d_with_html_image_element(
offset.x,
offset.y,
offset.z,
&self.image,
);

View File

@@ -184,10 +184,10 @@ use self::html::HTMLImage;
use super::Texture2DArray;
use wasm_bindgen::JsValue;
pub trait Image {
fn tex_sub_image_3d(
fn insert_into_3d_texture<T: Tex3D>(
&self,
// The texture array
textures: &Texture2DArray,
textures: &T,
// An offset to write the image in the texture array
offset: &Vector3<i32>,
) -> Result<(), JsValue>;
@@ -197,15 +197,15 @@ impl<'a, I> Image for &'a I
where
I: Image,
{
fn tex_sub_image_3d(
fn insert_into_3d_texture<T: Tex3D>(
&self,
// The texture array
textures: &Texture2DArray,
textures: &T,
// An offset to write the image in the texture array
offset: &Vector3<i32>,
) -> Result<(), JsValue> {
let image = &**self;
image.tex_sub_image_3d(textures, offset)?;
image.insert_into_3d_texture(textures, offset)?;
Ok(())
}
@@ -216,15 +216,15 @@ impl<I> Image for Rc<I>
where
I: Image,
{
fn tex_sub_image_3d(
fn insert_into_3d_texture<T: Tex3D>(
&self,
// The texture array
textures: &Texture2DArray,
textures: &T,
// An offset to write the image in the texture array
offset: &Vector3<i32>,
) -> Result<(), JsValue> {
let image = &**self;
image.tex_sub_image_3d(textures, offset)?;
image.insert_into_3d_texture(textures, offset)?;
Ok(())
}
@@ -251,7 +251,10 @@ where
#[cfg(feature = "webgl2")]
use crate::image::format::{R16I, R32I, R64F, R8UI};
use crate::image::format::{R32F, RGB8U, RGBA8U};
use crate::{
image::format::{R32F, RGB8U, RGBA8U},
texture::Tex3D,
};
use bitmap::Bitmap;
use fits::Fits;
@@ -288,10 +291,10 @@ pub enum ImageType {
use cgmath::Vector3;
impl Image for ImageType {
fn tex_sub_image_3d(
fn insert_into_3d_texture<T: Tex3D>(
&self,
// The texture array
textures: &Texture2DArray,
textures: &T,
// An offset to write the image in the texture array
offset: &Vector3<i32>,
) -> Result<(), JsValue> {
@@ -305,19 +308,23 @@ impl Image for ImageType {
let mut bytes_reader = Cursor::new(raw_bytes.as_slice());
let fits_img = Fits::from_byte_slice(&mut bytes_reader)?;
fits_img.tex_sub_image_3d(textures, offset)?
fits_img.insert_into_3d_texture(textures, offset)?
}
ImageType::Canvas { canvas } => canvas.tex_sub_image_3d(textures, offset)?,
ImageType::ImageRgba8u { image } => image.tex_sub_image_3d(textures, offset)?,
ImageType::ImageRgb8u { image } => image.tex_sub_image_3d(textures, offset)?,
ImageType::HTMLImageRgba8u { image } => image.tex_sub_image_3d(textures, offset)?,
ImageType::HTMLImageRgb8u { image } => image.tex_sub_image_3d(textures, offset)?,
ImageType::RawRgb8u { image } => image.tex_sub_image_3d(textures, offset)?,
ImageType::RawRgba8u { image } => image.tex_sub_image_3d(textures, offset)?,
ImageType::RawR32f { image } => image.tex_sub_image_3d(textures, offset)?,
ImageType::RawR32i { image } => image.tex_sub_image_3d(textures, offset)?,
ImageType::RawR16i { image } => image.tex_sub_image_3d(textures, offset)?,
ImageType::RawR8ui { image } => image.tex_sub_image_3d(textures, offset)?,
ImageType::Canvas { canvas } => canvas.insert_into_3d_texture(textures, offset)?,
ImageType::ImageRgba8u { image } => image.insert_into_3d_texture(textures, offset)?,
ImageType::ImageRgb8u { image } => image.insert_into_3d_texture(textures, offset)?,
ImageType::HTMLImageRgba8u { image } => {
image.insert_into_3d_texture(textures, offset)?
}
ImageType::HTMLImageRgb8u { image } => {
image.insert_into_3d_texture(textures, offset)?
}
ImageType::RawRgb8u { image } => image.insert_into_3d_texture(textures, offset)?,
ImageType::RawRgba8u { image } => image.insert_into_3d_texture(textures, offset)?,
ImageType::RawR32f { image } => image.insert_into_3d_texture(textures, offset)?,
ImageType::RawR32i { image } => image.insert_into_3d_texture(textures, offset)?,
ImageType::RawR16i { image } => image.insert_into_3d_texture(textures, offset)?,
ImageType::RawR8ui { image } => image.insert_into_3d_texture(textures, offset)?,
}
Ok(())

View File

@@ -1,5 +1,6 @@
use crate::image::format::ImageFormat;
use crate::texture::pixel::Pixel;
use crate::texture::Tex3D;
#[derive(Debug)]
#[allow(dead_code)]
pub struct ImageBuffer<T>
@@ -143,21 +144,22 @@ impl<I> Image for ImageBuffer<I>
where
I: ImageFormat,
{
fn tex_sub_image_3d(
fn insert_into_3d_texture<T: Tex3D>(
&self,
// The texture array
textures: &Texture2DArray,
textures: &T,
// An offset to write the image in the texture array
offset: &Vector3<i32>,
) -> Result<(), JsValue> {
let js_array =
<<<I as ImageFormat>::P as Pixel>::Container as ArrayBuffer>::new(&self.data);
textures.bind().tex_sub_image_3d_with_opt_array_buffer_view(
offset.z,
textures.tex_sub_image_3d_with_opt_array_buffer_view(
offset.x,
offset.y,
offset.z,
self.width(),
self.height(),
1,
Some(js_array.as_ref()),
);

View File

@@ -1,282 +1,81 @@
use crate::image::format::ImageFormat;
use web_sys::HtmlCanvasElement;
use web_sys::WebGlTexture;
use crate::Abort;
use crate::texture::Texture2DMeta;
use crate::webgl_ctx::WebGlContext;
use crate::webgl_ctx::WebGlRenderingCtx;
use std::cell::RefCell;
use std::rc::Rc;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::HtmlCanvasElement;
use web_sys::HtmlImageElement;
/// Some GPU texture relative:
// * Usual texture parameters when defining a texture
pub const TEX_PARAMS: &'static [(u32, u32); 4] = &[
(
WebGlRenderingCtx::TEXTURE_MIN_FILTER,
WebGlRenderingCtx::NEAREST,
),
(
WebGlRenderingCtx::TEXTURE_MAG_FILTER,
WebGlRenderingCtx::NEAREST,
),
// Prevents s-coordinate wrapping (repeating)
(
WebGlRenderingCtx::TEXTURE_WRAP_S,
WebGlRenderingCtx::CLAMP_TO_EDGE,
),
// Prevents t-coordinate wrapping (repeating)
(
WebGlRenderingCtx::TEXTURE_WRAP_T,
WebGlRenderingCtx::CLAMP_TO_EDGE,
),
];
pub static mut CUR_IDX_TEX_UNIT: u8 = 0;
#[derive(Clone)]
#[allow(dead_code)]
struct Texture3DMeta {
pub format: u32,
pub internal_format: i32,
pub type_: u32,
pub width: u32,
pub height: u32,
}
use web_sys::WebGlTexture;
#[derive(Clone)]
pub struct Texture3D {
pub texture: Option<WebGlTexture>,
gl: WebGlContext,
metadata: Option<Rc<RefCell<Texture3DMeta>>>,
texture: Option<WebGlTexture>,
metadata: Option<Rc<RefCell<Texture2DMeta>>>,
depth: i32,
}
pub enum SamplerType {
Float,
Integer,
Unsigned,
}
use crate::image::format::ImageFormat;
//use super::pixel::PixelType;
use std::cell::RefCell;
use std::path::Path;
use std::rc::Rc;
impl Texture3D {
/*pub fn create_from_path<P: AsRef<Path>, F: ImageFormat>(
gl: &WebGlContext,
name: &'static str,
src: &P,
tex_params: &'static [(u32, u32)],
) -> Result<Texture3D, JsValue> {
let image = HtmlImageElement::new().unwrap_abort();
let texture = gl.create_texture();
let onerror = {
Closure::wrap(Box::new(move || {
println!("Cannot load texture located at: {:?}", name);
}) as Box<dyn Fn()>)
};
let width = image.width();
let height = image.height();
let metadata = Rc::new(RefCell::new(Texture3DMeta {
width: width,
height: height,
internal_format: F::INTERNAL_FORMAT,
format: F::FORMAT,
type_: F::TYPE,
}));
let onload = {
let image = image.clone();
let gl = gl.clone();
let texture = texture.clone();
let metadata = metadata.clone();
Closure::wrap(Box::new(move || {
gl.bind_texture(WebGlRenderingCtx::TEXTURE_2D, texture.as_ref());
for (pname, param) in tex_params.iter() {
gl.tex_parameteri(WebGlRenderingCtx::TEXTURE_2D, *pname, *param as i32);
}
#[cfg(feature = "webgl2")]
gl.tex_image_2d_with_u32_and_u32_and_html_image_element(
WebGlRenderingCtx::TEXTURE_2D,
0,
F::INTERNAL_FORMAT,
F::FORMAT,
F::TYPE,
&image,
)
.expect("Texture 2D");
metadata.borrow_mut().width = image.width();
metadata.borrow_mut().height = image.height();
//gl.generate_mipmap(WebGl2RenderingContext::TEXTURE_2D);
}) as Box<dyn Fn()>)
};
image.set_onload(Some(onload.as_ref().unchecked_ref()));
image.set_onerror(Some(onerror.as_ref().unchecked_ref()));
image.set_cross_origin(Some(""));
image.set_src(src.as_ref().to_str().unwrap_abort());
onload.forget();
onerror.forget();
let gl = gl.clone();
Ok(Texture3D {
texture,
gl,
metadata: Some(metadata),
})
}*/
pub fn create_from_raw_pixels<F: ImageFormat>(
pub fn create_empty<F: ImageFormat>(
gl: &WebGlContext,
// The weight of the individual textures
width: i32,
// Their height
height: i32,
// The depth of the cube
depth: i32,
tex_params: &'static [(u32, u32)],
data: Option<&[<F::P as Pixel>::Item]>,
) -> Result<Texture3D, JsValue> {
let texture = Texture3D::create_empty_with_format::<F>(gl, width, height, tex_params)?;
if let Some(data) = data {
let buf_data = unsafe { F::view(data) };
texture
.bind()
.tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_array_buffer_view(
0,
0,
width,
height,
Some(buf_data.as_ref()),
);
}
Ok(texture)
}
pub fn create_from_raw_bytes<F: ImageFormat>(
gl: &WebGlContext,
width: i32,
height: i32,
tex_params: &'static [(u32, u32)],
bytes: Option<&[u8]>,
) -> Result<Texture3D, JsValue> {
) -> Result<Self, JsValue> {
let texture = gl.create_texture();
gl.bind_texture(WebGlRenderingCtx::TEXTURE_2D, texture.as_ref());
gl.bind_texture(WebGlRenderingCtx::TEXTURE_3D, texture.as_ref());
for (pname, param) in tex_params.iter() {
gl.tex_parameteri(WebGlRenderingCtx::TEXTURE_2D, *pname, *param as i32);
gl.tex_parameteri(WebGlRenderingCtx::TEXTURE_3D, *pname, *param as i32);
}
gl.tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array(
WebGlRenderingCtx::TEXTURE_2D,
0,
F::INTERNAL_FORMAT,
gl.tex_storage_3d(
WebGlRenderingCtx::TEXTURE_3D,
1,
F::INTERNAL_FORMAT as u32,
width,
height,
0,
F::FORMAT,
F::TYPE,
bytes,
)
.expect("Texture 2D");
let gl = gl.clone();
let metadata = Some(Rc::new(RefCell::new(Texture3DMeta {
width: width as u32,
height: height as u32,
internal_format: F::INTERNAL_FORMAT,
format: F::FORMAT,
type_: F::TYPE,
})));
Ok(Texture3D {
texture,
gl,
metadata,
})
}
pub fn create_empty_with_format<F: ImageFormat>(
gl: &WebGlContext,
width: i32,
height: i32,
tex_params: &'static [(u32, u32)],
) -> Result<Texture3D, JsValue> {
let texture = gl.create_texture();
gl.bind_texture(WebGlRenderingCtx::TEXTURE_2D, texture.as_ref());
for (pname, param) in tex_params.iter() {
gl.tex_parameteri(WebGlRenderingCtx::TEXTURE_2D, *pname, *param as i32);
}
gl.tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array(
WebGlRenderingCtx::TEXTURE_2D,
0,
F::INTERNAL_FORMAT,
width,
height,
0,
F::FORMAT,
F::TYPE,
None,
)
.expect("Texture 2D");
let gl = gl.clone();
let metadata = Some(Rc::new(RefCell::new(Texture3DMeta {
width: width as u32,
height: height as u32,
internal_format: F::INTERNAL_FORMAT,
format: F::FORMAT,
type_: F::TYPE,
})));
Ok(Texture3D {
texture,
gl,
metadata,
})
}
pub fn attach_to_framebuffer(&self) {
self.gl.framebuffer_texture_2d(
WebGlRenderingCtx::FRAMEBUFFER,
WebGlRenderingCtx::COLOR_ATTACHMENT0,
WebGlRenderingCtx::TEXTURE_2D,
self.texture.as_ref(),
0,
depth,
);
let gl = gl.clone();
let metadata = Some(Rc::new(RefCell::new(Texture2DMeta {
width: width as u32,
height: height as u32,
internal_format: F::INTERNAL_FORMAT,
format: F::FORMAT,
type_: F::TYPE,
})));
Ok(Texture3D {
texture,
gl: gl.clone(),
depth,
metadata,
})
}
pub fn get_size(&self) -> (u32, u32) {
(
self.metadata.as_ref().unwrap_abort().borrow().width,
self.metadata.as_ref().unwrap_abort().borrow().height,
)
pub fn generate_mipmap(&self) {
self.gl.generate_mipmap(WebGlRenderingCtx::TEXTURE_3D);
}
pub fn width(&self) -> u32 {
self.metadata.as_ref().unwrap_abort().borrow().width
}
pub fn bind(&self) -> Texture3DBound {
self.gl
.bind_texture(WebGlRenderingCtx::TEXTURE_3D, self.texture.as_ref());
pub fn height(&self) -> u32 {
self.metadata.as_ref().unwrap_abort().borrow().height
Texture3DBound { tex: self }
}
pub fn active_texture(&self, idx_tex_unit: u8) -> &Self {
@@ -284,162 +83,84 @@ impl Texture3D {
.active_texture(WebGlRenderingCtx::TEXTURE0 + idx_tex_unit as u32);
self
}
pub fn bind(&self) -> Texture3DBound {
self.gl
.bind_texture(WebGlRenderingCtx::TEXTURE_2D, self.texture.as_ref());
Texture3DBound { texture: self }
}
pub fn bind_mut(&mut self) -> Texture3DBoundMut {
self.gl
.bind_texture(WebGlRenderingCtx::TEXTURE_2D, self.texture.as_ref());
Texture3DBoundMut { texture: self }
}
pub fn read_pixel(&self, x: i32, y: i32) -> Result<JsValue, JsValue> {
// Create and bind the framebuffer
let reader = self.gl.create_framebuffer();
self.gl
.bind_framebuffer(WebGlRenderingCtx::FRAMEBUFFER, reader.as_ref());
// Attach the texture as the first color attachment
//self.attach_to_framebuffer();
self.gl.framebuffer_texture_2d(
WebGlRenderingCtx::READ_FRAMEBUFFER,
WebGlRenderingCtx::COLOR_ATTACHMENT0,
WebGlRenderingCtx::TEXTURE_2D,
self.texture.as_ref(),
0,
);
let status = self
.gl
.check_framebuffer_status(WebGlRenderingCtx::FRAMEBUFFER);
if status != WebGlRenderingCtx::FRAMEBUFFER_COMPLETE {
// Unbind the framebuffer
self.gl
.bind_framebuffer(WebGlRenderingCtx::FRAMEBUFFER, None);
// Delete the framebuffer
self.gl.delete_framebuffer(reader.as_ref());
Err(JsValue::from_str("incomplete framebuffer"))
} else {
// set the viewport as the FBO won't be the same dimension as the screen
let metadata = self.metadata.as_ref().unwrap_abort().borrow();
self.gl
.viewport(x, y, metadata.width as i32, metadata.height as i32);
#[cfg(feature = "webgl2")]
let value = match (metadata.format, metadata.type_) {
(WebGlRenderingCtx::RED_INTEGER, WebGlRenderingCtx::UNSIGNED_BYTE) => {
let p = <[u8; 1]>::read_pixel(&self.gl, x, y)?;
Ok(serde_wasm_bindgen::to_value(&p[0])?)
}
(WebGlRenderingCtx::RED_INTEGER, WebGlRenderingCtx::SHORT) => {
let p = <[i16; 1]>::read_pixel(&self.gl, x, y)?;
Ok(serde_wasm_bindgen::to_value(&p[0])?)
}
(WebGlRenderingCtx::RED_INTEGER, WebGlRenderingCtx::INT) => {
let p = <[i32; 1]>::read_pixel(&self.gl, x, y)?;
Ok(serde_wasm_bindgen::to_value(&p[0])?)
}
(WebGlRenderingCtx::RED, WebGlRenderingCtx::FLOAT) => {
let p = <[f32; 1]>::read_pixel(&self.gl, x, y)?;
Ok(serde_wasm_bindgen::to_value(&p[0])?)
}
(WebGlRenderingCtx::RGB, WebGlRenderingCtx::UNSIGNED_BYTE) => {
let p = <[u8; 3]>::read_pixel(&self.gl, x, y)?;
Ok(serde_wasm_bindgen::to_value(&p)?)
}
(WebGlRenderingCtx::RGBA, WebGlRenderingCtx::UNSIGNED_BYTE) => {
let p = <[u8; 4]>::read_pixel(&self.gl, x, y)?;
Ok(serde_wasm_bindgen::to_value(&p)?)
}
_ => Err(JsValue::from_str(
"Pixel retrieval not implemented for that texture format.",
)),
};
// Unbind the framebuffer
self.gl
.bind_framebuffer(WebGlRenderingCtx::FRAMEBUFFER, None);
// Delete the framebuffer
self.gl.delete_framebuffer(reader.as_ref());
// set the viewport as the FBO won't be the same dimension as the screen
let canvas = self
.gl
.canvas()
.unwrap_abort()
.dyn_into::<web_sys::HtmlCanvasElement>()
.unwrap_abort();
self.gl
.viewport(0, 0, canvas.width() as i32, canvas.height() as i32);
value
}
}
}
impl Drop for Texture3D {
fn drop(&mut self) {
self.gl.delete_texture(self.texture.as_ref());
// free the texture unit
/*let i = (self.idx_texture_unit - WebGl2RenderingContext::TEXTURE0) as usize;
unsafe {
AVAILABLE_TEX_UNITS[i] = Some(self.idx_texture_unit);
}*/
}
}
use crate::Abort;
use super::CUR_IDX_TEX_UNIT;
use crate::shader::UniformType;
use web_sys::WebGlUniformLocation;
impl UniformType for Texture3D {
fn uniform(gl: &WebGlContext, location: Option<&WebGlUniformLocation>, tex: &Self) {
unsafe {
let _ = tex
// 1. Active the texture unit of the texture
.active_texture(CUR_IDX_TEX_UNIT)
// 2. Bind the texture to that texture unit
.bind();
gl.uniform1i(location, CUR_IDX_TEX_UNIT as i32);
CUR_IDX_TEX_UNIT += 1;
};
}
}
pub struct Texture3DBound<'a> {
texture: &'a Texture3D,
tex: &'a Texture3D,
}
impl<'a> Texture3DBound<'a> {
pub fn tex_sub_image_2d_with_u32_and_u32_and_html_image_element(
pub fn tex_sub_image_3d_with_html_image_element(
&self,
dx: i32,
dy: i32,
dz: i32,
image: &HtmlImageElement,
) {
let metadata = self.texture.metadata.as_ref().unwrap_abort().borrow();
let metadata = self.tex.metadata.as_ref().unwrap_abort().borrow();
#[cfg(feature = "webgl2")]
self.texture
self.tex
.gl
.tex_sub_image_2d_with_u32_and_u32_and_html_image_element(
WebGlRenderingCtx::TEXTURE_2D,
.tex_sub_image_3d_with_html_image_element(
WebGlRenderingCtx::TEXTURE_3D,
0,
dx,
dy,
dz,
image.width() as i32,
image.height() as i32,
1,
metadata.format,
metadata.type_,
image,
)
.expect("Sub texture 2d");
.expect("Sub texture 3d");
}
pub fn tex_sub_image_2d_with_u32_and_u32_and_html_canvas_element(
pub fn tex_sub_image_3d_with_html_canvas_element(
&self,
dx: i32,
dy: i32,
dz: i32,
canvas: &HtmlCanvasElement,
) {
let metadata = self.texture.metadata.as_ref().unwrap_abort().borrow();
let metadata = self.tex.metadata.as_ref().unwrap_abort().borrow();
#[cfg(feature = "webgl2")]
self.texture
self.tex
.gl
.tex_sub_image_2d_with_u32_and_u32_and_html_canvas_element(
WebGlRenderingCtx::TEXTURE_2D,
.tex_sub_image_3d_with_html_canvas_element(
WebGlRenderingCtx::TEXTURE_3D,
0,
dx,
dy,
dz,
canvas.width() as i32,
canvas.height() as i32,
1,
metadata.format,
metadata.type_,
canvas,
@@ -447,22 +168,26 @@ impl<'a> Texture3DBound<'a> {
.expect("Sub texture 2d");
}
pub fn tex_sub_image_2d_with_u32_and_u32_and_image_bitmap(
pub fn tex_sub_image_3d_with_image_bitmap(
&self,
dx: i32,
dy: i32,
dz: i32,
image: &web_sys::ImageBitmap,
) {
let metadata = self.texture.metadata.as_ref().unwrap_abort().borrow();
let metadata = self.tex.metadata.as_ref().unwrap_abort().borrow();
#[cfg(feature = "webgl2")]
self.texture
self.tex
.gl
.tex_sub_image_2d_with_u32_and_u32_and_image_bitmap(
WebGlRenderingCtx::TEXTURE_2D,
.tex_sub_image_3d_with_image_bitmap(
WebGlRenderingCtx::TEXTURE_3D,
0,
dx,
dy,
dz,
image.width() as i32,
image.height() as i32,
1,
metadata.format,
metadata.type_,
image,
@@ -470,25 +195,29 @@ impl<'a> Texture3DBound<'a> {
.expect("Sub texture 2d");
}
pub fn tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_array_buffer_view(
pub fn tex_sub_image_3d_with_opt_array_buffer_view(
&self,
dx: i32,
dy: i32,
width: i32, // Width of the image
height: i32, // Height of the image
dz: i32,
w: i32,
h: i32,
d: i32,
image: Option<&js_sys::Object>,
) {
let metadata = self.texture.metadata.as_ref().unwrap_abort().borrow();
let metadata = self.tex.metadata.as_ref().unwrap_abort().borrow();
self.texture
self.tex
.gl
.tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_array_buffer_view(
WebGlRenderingCtx::TEXTURE_2D,
.tex_sub_image_3d_with_opt_array_buffer_view(
WebGlRenderingCtx::TEXTURE_3D,
0,
dx,
dy,
width,
height,
dz,
w,
h,
d,
metadata.format,
metadata.type_,
image,
@@ -497,24 +226,28 @@ impl<'a> Texture3DBound<'a> {
}
#[allow(dead_code)]
pub fn tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_u8_array(
pub fn tex_sub_image_3d_with_opt_u8_array(
&self,
idx: i32,
dx: i32,
dy: i32,
width: i32, // Width of the image
height: i32, // Height of the image
w: i32,
h: i32,
d: i32,
pixels: Option<&[u8]>,
) {
let metadata = self.texture.metadata.as_ref().unwrap_abort().borrow();
self.texture
let metadata = self.tex.metadata.as_ref().unwrap_abort().borrow();
self.tex
.gl
.tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_u8_array(
WebGlRenderingCtx::TEXTURE_2D,
.tex_sub_image_3d_with_opt_u8_array(
WebGlRenderingCtx::TEXTURE_3D,
0,
dx,
dy,
width,
height,
idx,
w,
h,
d,
metadata.format,
metadata.type_,
pixels,
@@ -522,70 +255,3 @@ impl<'a> Texture3DBound<'a> {
.expect("Sub texture 2d");
}
}
pub struct Texture3DBoundMut<'a> {
texture &'a mut Texture3D,
}
impl<'a> Texture3DBoundMut<'a> {
#[allow(dead_code)]
pub fn tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array(
&mut self,
width: i32, // Width of the image
height: i32, // Height of the image
internal_format: i32,
src_format: u32,
src_type: u32,
pixels: Option<&[u8]>,
) {
self.texture
.gl
.tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array(
WebGlRenderingCtx::TEXTURE_2D,
0,
internal_format as i32,
width as i32,
height as i32,
0,
src_format,
src_type,
pixels,
)
.expect("Sub texture 2d");
//self.texture.gl.generate_mipmap(WebGlRenderingCtx::TEXTURE_2D);
self.texture.metadata = Some(Rc::new(RefCell::new(Texture3DMeta {
format: src_format,
internal_format,
type_: src_type,
width: width as u32,
height: height as u32,
})));
}
pub fn tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_array_buffer_view(
&self,
dx: i32,
dy: i32,
width: i32, // Width of the image
height: i32, // Height of the image
image: Option<&js_sys::Object>,
) {
let metadata = self.texture.metadata.as_ref().unwrap_abort().borrow();
self.texture
.gl
.tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_array_buffer_view(
WebGlRenderingCtx::TEXTURE_2D,
0,
dx,
dy,
width,
height,
metadata.format,
metadata.type_,
image,
)
.expect("Sub texture 2d");
}
}

View File

@@ -1,41 +1,22 @@
pub mod texture_array;
pub use texture_array::Texture2DArray;
pub mod array;
pub use array::Texture2DArray;
pub mod pixel;
pub use pixel::*;
#[path = "3d.rs"]
pub mod mod_3d;
pub use mod_3d::Texture3D;
use web_sys::HtmlCanvasElement;
use web_sys::WebGlTexture;
use crate::image::format::ChannelType;
use crate::webgl_ctx::WebGlContext;
use crate::webgl_ctx::WebGlRenderingCtx;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::HtmlImageElement;
/// Some GPU texture relative:
// * Usual texture parameters when defining a texture
pub const TEX_PARAMS: &'static [(u32, u32); 4] = &[
(
WebGlRenderingCtx::TEXTURE_MIN_FILTER,
WebGlRenderingCtx::NEAREST,
),
(
WebGlRenderingCtx::TEXTURE_MAG_FILTER,
WebGlRenderingCtx::NEAREST,
),
// Prevents s-coordinate wrapping (repeating)
(
WebGlRenderingCtx::TEXTURE_WRAP_S,
WebGlRenderingCtx::CLAMP_TO_EDGE,
),
// Prevents t-coordinate wrapping (repeating)
(
WebGlRenderingCtx::TEXTURE_WRAP_T,
WebGlRenderingCtx::CLAMP_TO_EDGE,
),
];
pub static mut CUR_IDX_TEX_UNIT: u8 = 0;
#[derive(Clone)]
@@ -134,10 +115,6 @@ impl Texture2D {
metadata.borrow_mut().width = image.width();
metadata.borrow_mut().height = image.height();
if F::CHANNEL_TYPE == ChannelType::RGBA8U || F::CHANNEL_TYPE == ChannelType::RGB8U {
gl.generate_mipmap(WebGlRenderingCtx::TEXTURE_2D);
}
}) as Box<dyn Fn()>)
};
@@ -221,10 +198,6 @@ impl Texture2D {
)
.expect("Texture 2D");
if F::CHANNEL_TYPE == ChannelType::RGBA8U || F::CHANNEL_TYPE == ChannelType::RGB8U {
gl.generate_mipmap(WebGlRenderingCtx::TEXTURE_2D);
}
let gl = gl.clone();
let metadata = Some(Rc::new(RefCell::new(Texture2DMeta {
width: width as u32,
@@ -292,6 +265,10 @@ impl Texture2D {
);
}
pub fn generate_mipmap(&self) {
self.gl.generate_mipmap(WebGlRenderingCtx::TEXTURE_2D);
}
pub fn get_size(&self) -> (u32, u32) {
(
self.metadata.as_ref().unwrap_abort().borrow().width,
@@ -602,3 +579,177 @@ impl<'a> Texture2DBound<'a> {
.expect("Sub texture 2d");
}
}
pub trait Tex3D {
fn tex_sub_image_3d_with_html_image_element(
&self,
dx: i32,
dy: i32,
dz: i32,
image: &HtmlImageElement,
);
fn tex_sub_image_3d_with_html_canvas_element(
&self,
dx: i32,
dy: i32,
dz: i32,
canvas: &HtmlCanvasElement,
);
fn tex_sub_image_3d_with_image_bitmap(
&self,
dx: i32,
dy: i32,
dz: i32,
image: &web_sys::ImageBitmap,
);
fn tex_sub_image_3d_with_opt_array_buffer_view(
&self,
dx: i32,
dy: i32,
dz: i32,
w: i32,
h: i32,
d: i32,
view: Option<&js_sys::Object>,
);
fn tex_sub_image_3d_with_opt_u8_array(
&self,
dx: i32,
dy: i32,
dz: i32,
w: i32,
h: i32,
d: i32,
pixels: Option<&[u8]>,
);
}
impl Tex3D for Texture3D {
fn tex_sub_image_3d_with_html_image_element(
&self,
dx: i32,
dy: i32,
dz: i32,
image: &HtmlImageElement,
) {
self.bind()
.tex_sub_image_3d_with_html_image_element(dx, dy, dz, image);
}
fn tex_sub_image_3d_with_html_canvas_element(
&self,
dx: i32,
dy: i32,
dz: i32,
canvas: &HtmlCanvasElement,
) {
self.bind()
.tex_sub_image_3d_with_html_canvas_element(dx, dy, dz, canvas);
}
fn tex_sub_image_3d_with_image_bitmap(
&self,
dx: i32,
dy: i32,
dz: i32,
image: &web_sys::ImageBitmap,
) {
self.bind()
.tex_sub_image_3d_with_image_bitmap(dx, dy, dz, image);
}
fn tex_sub_image_3d_with_opt_array_buffer_view(
&self,
dx: i32,
dy: i32,
dz: i32,
w: i32,
h: i32,
d: i32,
view: Option<&js_sys::Object>,
) {
self.bind()
.tex_sub_image_3d_with_opt_array_buffer_view(dx, dy, dz, w, h, d, view);
}
fn tex_sub_image_3d_with_opt_u8_array(
&self,
dx: i32,
dy: i32,
dz: i32,
w: i32,
h: i32,
d: i32,
pixels: Option<&[u8]>,
) {
self.bind()
.tex_sub_image_3d_with_opt_u8_array(dx, dy, dz, w, h, d, pixels);
}
}
impl Tex3D for Texture2DArray {
fn tex_sub_image_3d_with_html_image_element(
&self,
dx: i32,
dy: i32,
dz: i32,
image: &HtmlImageElement,
) {
self.bind()
.tex_sub_image_3d_with_html_image_element(dx, dy, dz, image);
}
fn tex_sub_image_3d_with_html_canvas_element(
&self,
dx: i32,
dy: i32,
dz: i32,
canvas: &HtmlCanvasElement,
) {
self.bind()
.tex_sub_image_3d_with_html_canvas_element(dx, dy, dz, canvas);
}
fn tex_sub_image_3d_with_image_bitmap(
&self,
dx: i32,
dy: i32,
dz: i32,
image: &web_sys::ImageBitmap,
) {
self.bind()
.tex_sub_image_3d_with_image_bitmap(dx, dy, dz, image);
}
fn tex_sub_image_3d_with_opt_array_buffer_view(
&self,
dx: i32,
dy: i32,
dz: i32,
w: i32,
h: i32,
_d: i32,
view: Option<&js_sys::Object>,
) {
self.bind()
.tex_sub_image_3d_with_opt_array_buffer_view(dx, dy, dz, w, h, view);
}
fn tex_sub_image_3d_with_opt_u8_array(
&self,
dx: i32,
dy: i32,
dz: i32,
w: i32,
h: i32,
_d: i32,
pixels: Option<&[u8]>,
) {
self.bind()
.tex_sub_image_3d_with_opt_u8_array(dx, dy, dz, w, h, pixels);
}
}

View File

@@ -1,252 +0,0 @@
use crate::image::format::ImageFormat;
use web_sys::HtmlCanvasElement;
use web_sys::WebGlTexture;
use crate::texture::Texture2DMeta;
use crate::webgl_ctx::WebGlContext;
use crate::webgl_ctx::WebGlRenderingCtx;
use crate::Abort;
use std::cell::RefCell;
use std::rc::Rc;
use wasm_bindgen::prelude::*;
use web_sys::HtmlImageElement;
pub struct Texture2DArray {
gl: WebGlContext,
texture: Option<WebGlTexture>,
metadata: Option<Rc<RefCell<Texture2DMeta>>>,
pub num_slices: i32,
}
impl Texture2DArray {
pub fn create_empty<F: ImageFormat>(
gl: &WebGlContext,
// The weight of the individual textures
width: i32,
// Their height
height: i32,
// How many texture slices it contains
num_slices: i32,
tex_params: &'static [(u32, u32)],
) -> Result<Texture2DArray, JsValue> {
let texture = gl.create_texture();
gl.bind_texture(WebGlRenderingCtx::TEXTURE_2D_ARRAY, texture.as_ref());
for (pname, param) in tex_params.iter() {
gl.tex_parameteri(WebGlRenderingCtx::TEXTURE_2D_ARRAY, *pname, *param as i32);
}
gl.tex_storage_3d(
WebGlRenderingCtx::TEXTURE_2D_ARRAY,
1,
F::INTERNAL_FORMAT as u32,
width,
height,
num_slices,
);
let gl = gl.clone();
let metadata = Some(Rc::new(RefCell::new(Texture2DMeta {
width: width as u32,
height: height as u32,
internal_format: F::INTERNAL_FORMAT,
format: F::FORMAT,
type_: F::TYPE,
})));
Ok(Texture2DArray {
texture,
gl: gl.clone(),
num_slices,
metadata,
})
}
pub fn generate_mipmap(&self) {
self.gl.generate_mipmap(WebGlRenderingCtx::TEXTURE_2D_ARRAY);
}
pub fn bind(&self) -> Texture2DArrayBound {
self.gl
.bind_texture(WebGlRenderingCtx::TEXTURE_2D_ARRAY, self.texture.as_ref());
Texture2DArrayBound { tex: self }
}
pub fn active_texture(&self, idx_tex_unit: u8) -> &Self {
self.gl
.active_texture(WebGlRenderingCtx::TEXTURE0 + idx_tex_unit as u32);
self
}
}
impl Drop for Texture2DArray {
fn drop(&mut self) {
self.gl.delete_texture(self.texture.as_ref());
}
}
use super::CUR_IDX_TEX_UNIT;
use crate::shader::UniformType;
use web_sys::WebGlUniformLocation;
impl UniformType for Texture2DArray {
fn uniform(gl: &WebGlContext, location: Option<&WebGlUniformLocation>, tex: &Self) {
unsafe {
let _ = tex
// 1. Active the texture unit of the texture
.active_texture(CUR_IDX_TEX_UNIT)
// 2. Bind the texture to that texture unit
.bind();
gl.uniform1i(location, CUR_IDX_TEX_UNIT as i32);
CUR_IDX_TEX_UNIT += 1;
};
}
}
pub struct Texture2DArrayBound<'a> {
tex: &'a Texture2DArray,
}
impl<'a> Texture2DArrayBound<'a> {
pub fn tex_sub_image_3d_with_html_image_element(
&self,
idx: i32,
dx: i32,
dy: i32,
image: &HtmlImageElement,
) {
let metadata = self.tex.metadata.as_ref().unwrap_abort().borrow();
self.tex
.gl
.tex_sub_image_3d_with_html_image_element(
WebGlRenderingCtx::TEXTURE_2D_ARRAY,
0,
dx,
dy,
idx,
image.width() as i32,
image.height() as i32,
1,
metadata.format,
metadata.type_,
image,
)
.expect("Sub texture 3d");
}
pub fn tex_sub_image_3d_with_html_canvas_element(
&self,
idx: i32,
dx: i32,
dy: i32,
canvas: &HtmlCanvasElement,
) {
let metadata = self.tex.metadata.as_ref().unwrap_abort().borrow();
self.tex
.gl
.tex_sub_image_3d_with_html_canvas_element(
WebGlRenderingCtx::TEXTURE_2D_ARRAY,
0,
dx,
dy,
idx,
canvas.width() as i32,
canvas.height() as i32,
1,
metadata.format,
metadata.type_,
canvas,
)
.expect("Sub texture 2d");
}
pub fn tex_sub_image_3d_with_image_bitmap(
&self,
idx: i32,
dx: i32,
dy: i32,
image: &web_sys::ImageBitmap,
) {
let metadata = self.tex.metadata.as_ref().unwrap_abort().borrow();
self.tex
.gl
.tex_sub_image_3d_with_image_bitmap(
WebGlRenderingCtx::TEXTURE_2D_ARRAY,
0,
dx,
dy,
idx,
image.width() as i32,
image.height() as i32,
1,
metadata.format,
metadata.type_,
image,
)
.expect("Sub texture 2d");
}
pub fn tex_sub_image_3d_with_opt_array_buffer_view(
&self,
idx: i32,
dx: i32,
dy: i32,
w: i32,
h: i32,
image: Option<&js_sys::Object>,
) {
let metadata = self.tex.metadata.as_ref().unwrap_abort().borrow();
self.tex
.gl
.tex_sub_image_3d_with_opt_array_buffer_view(
WebGlRenderingCtx::TEXTURE_2D_ARRAY,
0,
dx,
dy,
idx,
w,
h,
1,
metadata.format,
metadata.type_,
image,
)
.expect("Sub texture 2d");
}
#[allow(dead_code)]
pub fn tex_sub_image_3d_with_opt_u8_array(
&self,
idx: i32,
dx: i32,
dy: i32,
w: i32,
h: i32,
pixels: Option<&[u8]>,
) {
let metadata = self.tex.metadata.as_ref().unwrap_abort().borrow();
self.tex
.gl
.tex_sub_image_3d_with_opt_u8_array(
WebGlRenderingCtx::TEXTURE_2D_ARRAY,
0,
dx,
dy,
idx,
w,
h,
1,
metadata.format,
metadata.type_,
pixels,
)
.expect("Sub texture 2d");
}
}

View File

@@ -35,7 +35,7 @@ impl Inertia {
// where:
// * k is the stiffness of the ressort
// * m is its mass
let w0 = 4.0;
let w0 = 10.0;
// The angular distance goes from d0 to 0.0
//self.speed = self.ampl * ((-w0 * t).exp());
// The angular distance goes from d0 to 0.0

View File

@@ -2,6 +2,7 @@ pub mod cuts;
pub mod grid;
pub mod subdivide_texture;
use al_core::webgl_ctx::WebGlRenderingCtx;
use std::fmt::Debug;
use std::marker::Unpin;
use std::vec;
@@ -70,7 +71,6 @@ pub struct Image {
coo_sys: CooSystem,
}
use al_core::pixel::Pixel;
use al_core::texture::TEX_PARAMS;
use fitsrs::hdu::header::extension;
use fitsrs::hdu::AsyncHDU;
use futures::io::BufReader;
@@ -151,7 +151,26 @@ impl Image {
gl,
width as i32,
height as i32,
TEX_PARAMS,
&[
(
WebGlRenderingCtx::TEXTURE_MIN_FILTER,
WebGlRenderingCtx::NEAREST_MIPMAP_NEAREST,
),
(
WebGlRenderingCtx::TEXTURE_MAG_FILTER,
WebGlRenderingCtx::NEAREST,
),
// Prevents s-coordinate wrapping (repeating)
(
WebGlRenderingCtx::TEXTURE_WRAP_S,
WebGlRenderingCtx::CLAMP_TO_EDGE,
),
// Prevents t-coordinate wrapping (repeating)
(
WebGlRenderingCtx::TEXTURE_WRAP_T,
WebGlRenderingCtx::CLAMP_TO_EDGE,
),
],
Some(slice),
)?;
@@ -169,6 +188,10 @@ impl Image {
.await?
};
for tex in &textures {
tex.generate_mipmap();
}
let start = cuts.start * scale + offset;
let end = cuts.end * scale + offset;

View File

@@ -5,7 +5,7 @@ use futures::AsyncReadExt;
use super::cuts;
use al_core::image::format::ImageFormat;
use al_core::texture::pixel::Pixel;
use al_core::texture::TEX_PARAMS;
use al_core::webgl_ctx::WebGlRenderingCtx;
use al_core::Texture2D;
use al_core::WebGlContext;
use std::ops::Range;
@@ -35,12 +35,33 @@ where
];
for _ in 0..num_textures {
tex_chunks.push(Texture2D::create_empty_with_format::<F>(
let tex_chunk = Texture2D::create_empty_with_format::<F>(
gl,
max_tex_size as i32,
max_tex_size as i32,
TEX_PARAMS,
)?);
&[
(
WebGlRenderingCtx::TEXTURE_MIN_FILTER,
WebGlRenderingCtx::NEAREST_MIPMAP_NEAREST,
),
(
WebGlRenderingCtx::TEXTURE_MAG_FILTER,
WebGlRenderingCtx::NEAREST,
),
// Prevents s-coordinate wrapping (repeating)
(
WebGlRenderingCtx::TEXTURE_WRAP_S,
WebGlRenderingCtx::CLAMP_TO_EDGE,
),
// Prevents t-coordinate wrapping (repeating)
(
WebGlRenderingCtx::TEXTURE_WRAP_T,
WebGlRenderingCtx::CLAMP_TO_EDGE,
),
],
)?;
tex_chunk.generate_mipmap();
tex_chunks.push(tex_chunk);
}
let mut pixels_written = 0;

View File

@@ -585,7 +585,7 @@ fn send_to_gpu<I: Image>(
idx_slice,
);
image.tex_sub_image_3d(&texture_array, &offset)?;
image.insert_into_3d_texture(texture_array, &offset)?;
Ok(())
}

View File

@@ -89,8 +89,9 @@ use al_core::{
};
use cgmath::Vector3;
/*
impl Image for EmptyTileImage {
fn tex_sub_image_3d(
fn insert(
&self,
// The texture array
textures: &Texture2DArray,
@@ -100,6 +101,7 @@ impl Image for EmptyTileImage {
self.inner.tex_sub_image_3d(textures, offset)
}
}
*/
use al_core::image::format::{ChannelType, ImageFormatType, RGB8U, RGBA8U};
@@ -508,10 +510,10 @@ impl HiPSConfig {
self.format.is_colored()
}
#[inline(always)]
/*#[inline(always)]
pub fn get_default_image(&self) -> &EmptyTileImage {
&self.empty_image
}
}*/
}
use al_core::shader::{SendUniforms, ShaderBound};

View File

@@ -1,4 +1,5 @@
pub mod bitvector;
pub mod buffer;
pub mod config;
pub mod hpx_cubic_tile;
pub mod texture;

View File

@@ -79,14 +79,15 @@ export class Selector {
}
start(mode, callback) {
this.setMode(mode);
this.dispatch('start', {callback})
this.view.aladin.removeStatusBarMessage('selector')
this.view.aladin.addStatusBarMessage({
id: 'selector',
message: 'You entered the selection mode',
type: 'info'
})
this.setMode(mode);
this.dispatch('start', {callback})
}
cancel() {

View File

@@ -95,7 +95,6 @@ import { requestAnimFrame } from "./libs/RequestAnimationFrame.js";
function interpolateFrame() {
// Check if interpolation is complete
if (self.stop) {
console.log("stop")
self.isZooming = false;
self.stop = false;
} else {
@@ -110,7 +109,6 @@ import { requestAnimFrame } from "./libs/RequestAnimationFrame.js";
self.fov = interpolatedZoom;
if (self.x >= self.x2 || Math.abs(interpolatedZoom - self.finalZoom) < 1e-4) {
console.log("finish")
self.view.setZoom(self.finalZoom);
self.isZooming = false;