cosmol-viewer 0.1.2.dev2__tar.gz → 0.1.2.dev4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cosmol-viewer might be problematic. Click here for more details.
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/Cargo.lock +24 -23
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/Cargo.toml +4 -3
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/PKG-INFO +1 -1
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/core/Cargo.toml +0 -1
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/core/src/lib.rs +8 -7
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/core/src/scene.rs +22 -9
- cosmol_viewer-0.1.2.dev4/crates/core/src/shapes/mod.rs +6 -0
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/core/src/shapes/molecules.rs +27 -19
- cosmol_viewer-0.1.2.dev4/crates/core/src/shapes/sphere.rs +173 -0
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/core/src/shapes/stick.rs +12 -12
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/core/src/utils.rs +1 -1
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/python/Cargo.toml +2 -5
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/python/src/lib.rs +173 -106
- cosmol_viewer-0.1.2.dev4/crates/python/src/shapes.rs +287 -0
- cosmol_viewer-0.1.2.dev4/crates/wasm/Cargo.toml +42 -0
- cosmol_viewer-0.1.2.dev4/crates/wasm/src/lib.rs +245 -0
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/pyproject.toml +1 -1
- cosmol_viewer-0.1.2.dev2/crates/core/src/shapes/mod.rs +0 -3
- cosmol_viewer-0.1.2.dev2/crates/core/src/shapes/sphere.rs +0 -246
- cosmol_viewer-0.1.2.dev2/crates/python/src/shapes.rs +0 -102
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/core/src/parser/mod.rs +0 -0
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/core/src/parser/sdf.rs +0 -0
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/core/src/shader/bg_fragment.glsl +0 -0
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/core/src/shader/bg_vertex.glsl +0 -0
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/core/src/shader/canvas.rs +0 -0
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/core/src/shader/fragment.glsl +0 -0
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/core/src/shader/mod.rs +0 -0
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/core/src/shader/vertex.glsl +0 -0
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/python/README.md +0 -0
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/python/build.rs +0 -0
- {cosmol_viewer-0.1.2.dev2 → cosmol_viewer-0.1.2.dev4}/crates/python/src/parser.rs +0 -0
|
@@ -4,9 +4,9 @@ version = 4
|
|
|
4
4
|
|
|
5
5
|
[[package]]
|
|
6
6
|
name = "ab_glyph"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.31"
|
|
8
8
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
-
checksum = "
|
|
9
|
+
checksum = "e074464580a518d16a7126262fffaaa47af89d4099d4cb403f8ed938ba12ee7d"
|
|
10
10
|
dependencies = [
|
|
11
11
|
"ab_glyph_rasterizer",
|
|
12
12
|
"owned_ttf_parser",
|
|
@@ -243,7 +243,7 @@ dependencies = [
|
|
|
243
243
|
"futures-lite",
|
|
244
244
|
"parking",
|
|
245
245
|
"polling",
|
|
246
|
-
"rustix 1.0.
|
|
246
|
+
"rustix 1.0.8",
|
|
247
247
|
"slab",
|
|
248
248
|
"tracing",
|
|
249
249
|
"windows-sys 0.59.0",
|
|
@@ -275,7 +275,7 @@ dependencies = [
|
|
|
275
275
|
"cfg-if",
|
|
276
276
|
"event-listener",
|
|
277
277
|
"futures-lite",
|
|
278
|
-
"rustix 1.0.
|
|
278
|
+
"rustix 1.0.8",
|
|
279
279
|
"tracing",
|
|
280
280
|
]
|
|
281
281
|
|
|
@@ -302,7 +302,7 @@ dependencies = [
|
|
|
302
302
|
"cfg-if",
|
|
303
303
|
"futures-core",
|
|
304
304
|
"futures-io",
|
|
305
|
-
"rustix 1.0.
|
|
305
|
+
"rustix 1.0.8",
|
|
306
306
|
"signal-hook-registry",
|
|
307
307
|
"slab",
|
|
308
308
|
"windows-sys 0.59.0",
|
|
@@ -558,9 +558,9 @@ dependencies = [
|
|
|
558
558
|
|
|
559
559
|
[[package]]
|
|
560
560
|
name = "clipboard-win"
|
|
561
|
-
version = "5.4.
|
|
561
|
+
version = "5.4.1"
|
|
562
562
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
563
|
-
checksum = "
|
|
563
|
+
checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4"
|
|
564
564
|
dependencies = [
|
|
565
565
|
"error-code",
|
|
566
566
|
]
|
|
@@ -647,7 +647,7 @@ dependencies = [
|
|
|
647
647
|
|
|
648
648
|
[[package]]
|
|
649
649
|
name = "cosmol_viewer"
|
|
650
|
-
version = "0.1.2-nightly.
|
|
650
|
+
version = "0.1.2-nightly.4"
|
|
651
651
|
dependencies = [
|
|
652
652
|
"bytemuck",
|
|
653
653
|
"cosmol_viewer_core",
|
|
@@ -658,12 +658,11 @@ dependencies = [
|
|
|
658
658
|
"serde_json",
|
|
659
659
|
"sha2",
|
|
660
660
|
"wasm-bindgen-futures",
|
|
661
|
-
"web-sys",
|
|
662
661
|
]
|
|
663
662
|
|
|
664
663
|
[[package]]
|
|
665
664
|
name = "cosmol_viewer_core"
|
|
666
|
-
version = "0.1.2-nightly.
|
|
665
|
+
version = "0.1.2-nightly.4"
|
|
667
666
|
dependencies = [
|
|
668
667
|
"bytemuck",
|
|
669
668
|
"eframe",
|
|
@@ -675,7 +674,6 @@ dependencies = [
|
|
|
675
674
|
"serde_json",
|
|
676
675
|
"serde_repr",
|
|
677
676
|
"wasm-bindgen-futures",
|
|
678
|
-
"web-sys",
|
|
679
677
|
]
|
|
680
678
|
|
|
681
679
|
[[package]]
|
|
@@ -684,22 +682,25 @@ version = "0.0.0"
|
|
|
684
682
|
dependencies = [
|
|
685
683
|
"base64",
|
|
686
684
|
"cosmol_viewer_core",
|
|
685
|
+
"cosmol_viewer_wasm",
|
|
687
686
|
"eframe",
|
|
688
687
|
"egui_extras",
|
|
689
688
|
"pyo3",
|
|
690
689
|
"serde_json",
|
|
691
|
-
"uuid",
|
|
692
|
-
"wasm-bindgen",
|
|
693
690
|
]
|
|
694
691
|
|
|
695
692
|
[[package]]
|
|
696
693
|
name = "cosmol_viewer_wasm"
|
|
697
|
-
version = "0.1.2-nightly.
|
|
694
|
+
version = "0.1.2-nightly.4"
|
|
698
695
|
dependencies = [
|
|
696
|
+
"base64",
|
|
699
697
|
"cosmol_viewer_core",
|
|
700
698
|
"eframe",
|
|
701
699
|
"log",
|
|
700
|
+
"pyo3",
|
|
701
|
+
"serde",
|
|
702
702
|
"serde_json",
|
|
703
|
+
"uuid",
|
|
703
704
|
"wasm-bindgen",
|
|
704
705
|
"wasm-bindgen-futures",
|
|
705
706
|
"web-sys",
|
|
@@ -2256,7 +2257,7 @@ dependencies = [
|
|
|
2256
2257
|
"concurrent-queue",
|
|
2257
2258
|
"hermit-abi",
|
|
2258
2259
|
"pin-project-lite",
|
|
2259
|
-
"rustix 1.0.
|
|
2260
|
+
"rustix 1.0.8",
|
|
2260
2261
|
"tracing",
|
|
2261
2262
|
"windows-sys 0.59.0",
|
|
2262
2263
|
]
|
|
@@ -2468,15 +2469,15 @@ dependencies = [
|
|
|
2468
2469
|
|
|
2469
2470
|
[[package]]
|
|
2470
2471
|
name = "rustix"
|
|
2471
|
-
version = "1.0.
|
|
2472
|
+
version = "1.0.8"
|
|
2472
2473
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2473
|
-
checksum = "
|
|
2474
|
+
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
|
|
2474
2475
|
dependencies = [
|
|
2475
2476
|
"bitflags 2.9.1",
|
|
2476
2477
|
"errno",
|
|
2477
2478
|
"libc",
|
|
2478
2479
|
"linux-raw-sys 0.9.4",
|
|
2479
|
-
"windows-sys 0.
|
|
2480
|
+
"windows-sys 0.60.2",
|
|
2480
2481
|
]
|
|
2481
2482
|
|
|
2482
2483
|
[[package]]
|
|
@@ -2749,7 +2750,7 @@ dependencies = [
|
|
|
2749
2750
|
"fastrand",
|
|
2750
2751
|
"getrandom",
|
|
2751
2752
|
"once_cell",
|
|
2752
|
-
"rustix 1.0.
|
|
2753
|
+
"rustix 1.0.8",
|
|
2753
2754
|
"windows-sys 0.59.0",
|
|
2754
2755
|
]
|
|
2755
2756
|
|
|
@@ -3915,9 +3916,9 @@ dependencies = [
|
|
|
3915
3916
|
|
|
3916
3917
|
[[package]]
|
|
3917
3918
|
name = "zbus"
|
|
3918
|
-
version = "5.
|
|
3919
|
+
version = "5.9.0"
|
|
3919
3920
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3920
|
-
checksum = "
|
|
3921
|
+
checksum = "4bb4f9a464286d42851d18a605f7193b8febaf5b0919d71c6399b7b26e5b0aad"
|
|
3921
3922
|
dependencies = [
|
|
3922
3923
|
"async-broadcast",
|
|
3923
3924
|
"async-executor",
|
|
@@ -3972,9 +3973,9 @@ dependencies = [
|
|
|
3972
3973
|
|
|
3973
3974
|
[[package]]
|
|
3974
3975
|
name = "zbus_macros"
|
|
3975
|
-
version = "5.
|
|
3976
|
+
version = "5.9.0"
|
|
3976
3977
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3977
|
-
checksum = "
|
|
3978
|
+
checksum = "ef9859f68ee0c4ee2e8cde84737c78e3f4c54f946f2a38645d0d4c7a95327659"
|
|
3978
3979
|
dependencies = [
|
|
3979
3980
|
"proc-macro-crate",
|
|
3980
3981
|
"proc-macro2",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[workspace.package]
|
|
2
2
|
edition = "2024"
|
|
3
|
-
version = "0.1.2-nightly.
|
|
3
|
+
version = "0.1.2-nightly.4"
|
|
4
4
|
authors = ["9028 wjt@cosmol.org"]
|
|
5
5
|
repository = "https://github.com/COSMol-repl/COSMol-viewer"
|
|
6
6
|
homepage = "https://github.com/COSMol-repl/COSMol-viewer"
|
|
@@ -13,10 +13,11 @@ resolver = "2"
|
|
|
13
13
|
members = ["crates/python"]
|
|
14
14
|
|
|
15
15
|
[workspace.dependencies]
|
|
16
|
-
cosmol_viewer = { version = "0.1.2-nightly.
|
|
17
|
-
cosmol_viewer_core = { version = "0.1.2-nightly.
|
|
16
|
+
cosmol_viewer = { version = "0.1.2-nightly.4", path = "cosmol_viewer"}
|
|
17
|
+
cosmol_viewer_core = { version = "0.1.2-nightly.4", path = "crates/core" }
|
|
18
18
|
|
|
19
19
|
eframe = { version = "0.32.0", features = ["wayland","x11"] }
|
|
20
|
+
pyo3 = { version = "0.25.1", features = ["extension-module", "abi3-py37"] }
|
|
20
21
|
egui-winit = { version = "0.32.0", features = ["wayland","x11"] }
|
|
21
22
|
egui_extras = { version = "0.32.0" }
|
|
22
23
|
serde = { version = "1.0.219" , features = ["derive"] }
|
|
@@ -67,12 +67,10 @@ impl eframe::App for App {
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
#[cfg(not(target_arch = "wasm32"))]
|
|
71
70
|
pub struct NativeGuiViewer {
|
|
72
71
|
pub app: Arc<Mutex<Option<App>>>,
|
|
73
72
|
}
|
|
74
73
|
|
|
75
|
-
#[cfg(not(target_arch = "wasm32"))]
|
|
76
74
|
impl NativeGuiViewer {
|
|
77
75
|
pub fn render(scene: &Scene) -> Self {
|
|
78
76
|
use std::{
|
|
@@ -80,17 +78,22 @@ impl NativeGuiViewer {
|
|
|
80
78
|
thread,
|
|
81
79
|
};
|
|
82
80
|
|
|
81
|
+
#[cfg(not(target_arch = "wasm32"))]
|
|
83
82
|
use eframe::{
|
|
84
83
|
NativeOptions,
|
|
85
84
|
egui::{Vec2, ViewportBuilder},
|
|
86
85
|
};
|
|
87
86
|
|
|
87
|
+
let viewport_size = scene.viewport.unwrap_or([800, 500]);
|
|
88
|
+
|
|
88
89
|
let app: Arc<Mutex<Option<App>>> = Arc::new(Mutex::new(None));
|
|
89
90
|
let app_clone = Arc::clone(&app);
|
|
90
91
|
|
|
91
92
|
let scene = Arc::new(Mutex::new(scene.clone()));
|
|
92
|
-
|
|
93
|
+
#[cfg(not(target_arch = "wasm32"))]
|
|
93
94
|
thread::spawn(move || {
|
|
95
|
+
use std::process;
|
|
96
|
+
|
|
94
97
|
use eframe::{EventLoopBuilderHook, run_native};
|
|
95
98
|
let event_loop_builder: Option<EventLoopBuilderHook> =
|
|
96
99
|
Some(Box::new(|event_loop_builder| {
|
|
@@ -98,24 +101,21 @@ impl NativeGuiViewer {
|
|
|
98
101
|
{
|
|
99
102
|
use egui_winit::winit::platform::windows::EventLoopBuilderExtWindows;
|
|
100
103
|
event_loop_builder.with_any_thread(true);
|
|
101
|
-
println!("Running on windows")
|
|
102
104
|
}
|
|
103
105
|
#[cfg(feature = "wayland")]
|
|
104
106
|
{
|
|
105
107
|
use egui_winit::winit::platform::wayland::EventLoopBuilderExtWayland;
|
|
106
108
|
event_loop_builder.with_any_thread(true);
|
|
107
|
-
println!("Running on wayland")
|
|
108
109
|
}
|
|
109
110
|
#[cfg(feature = "x11")]
|
|
110
111
|
{
|
|
111
112
|
use egui_winit::winit::platform::x11::EventLoopBuilderExtX11;
|
|
112
113
|
event_loop_builder.with_any_thread(true);
|
|
113
|
-
println!("Running on X11")
|
|
114
114
|
}
|
|
115
115
|
}));
|
|
116
116
|
|
|
117
117
|
let native_options = NativeOptions {
|
|
118
|
-
viewport: ViewportBuilder::default().with_inner_size(Vec2::new(
|
|
118
|
+
viewport: ViewportBuilder::default().with_inner_size(Vec2::new(viewport_size [0] as f32, viewport_size[1] as f32)),
|
|
119
119
|
depth_buffer: 24,
|
|
120
120
|
event_loop_builder,
|
|
121
121
|
..Default::default()
|
|
@@ -130,6 +130,7 @@ impl NativeGuiViewer {
|
|
|
130
130
|
Ok(Box::new(AppWrapper(app.clone())))
|
|
131
131
|
}),
|
|
132
132
|
);
|
|
133
|
+
process::exit(0);
|
|
133
134
|
});
|
|
134
135
|
|
|
135
136
|
Self { app: app_clone }
|
|
@@ -2,8 +2,11 @@ use std::collections::HashMap;
|
|
|
2
2
|
|
|
3
3
|
use serde::{Deserialize, Serialize};
|
|
4
4
|
|
|
5
|
-
use crate::{
|
|
6
|
-
|
|
5
|
+
use crate::{
|
|
6
|
+
Shape,
|
|
7
|
+
shader::CameraState,
|
|
8
|
+
utils::{self, ToMesh},
|
|
9
|
+
};
|
|
7
10
|
|
|
8
11
|
#[derive(Deserialize, Serialize, Clone)]
|
|
9
12
|
pub struct Scene {
|
|
@@ -12,6 +15,7 @@ pub struct Scene {
|
|
|
12
15
|
pub named_shapes: HashMap<String, Shape>,
|
|
13
16
|
pub unnamed_shapes: Vec<Shape>,
|
|
14
17
|
pub scale: f32,
|
|
18
|
+
pub viewport: Option<[usize; 2]>,
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
impl Scene {
|
|
@@ -30,6 +34,7 @@ impl Scene {
|
|
|
30
34
|
named_shapes: HashMap::new(),
|
|
31
35
|
unnamed_shapes: Vec::new(),
|
|
32
36
|
scale: 1.0,
|
|
37
|
+
viewport: None,
|
|
33
38
|
}
|
|
34
39
|
}
|
|
35
40
|
|
|
@@ -46,12 +51,6 @@ impl Scene {
|
|
|
46
51
|
}
|
|
47
52
|
}
|
|
48
53
|
|
|
49
|
-
pub fn delete_shape(&mut self, id: &str) {
|
|
50
|
-
if self.named_shapes.remove(id).is_none() {
|
|
51
|
-
panic!("Sphere with ID '{}' not found", id);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
54
|
pub fn update_shape<S: Into<Shape>>(&mut self, id: &str, shape: S) {
|
|
56
55
|
let shape = shape.into();
|
|
57
56
|
if let Some(existing_shape) = self.named_shapes.get_mut(id) {
|
|
@@ -60,4 +59,18 @@ impl Scene {
|
|
|
60
59
|
panic!("Shape with ID '{}' not found", id);
|
|
61
60
|
}
|
|
62
61
|
}
|
|
63
|
-
|
|
62
|
+
|
|
63
|
+
pub fn delete_shape(&mut self, id: &str) {
|
|
64
|
+
if self.named_shapes.remove(id).is_none() {
|
|
65
|
+
panic!("Sphere with ID '{}' not found", id);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
pub fn set_viewport(&mut self, width: usize, height: usize) {
|
|
70
|
+
self.viewport = Some([width, height]);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
pub fn set_background_color(&mut self, background_color: [f32; 3]) {
|
|
74
|
+
self.background_color = background_color;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -64,16 +64,16 @@ impl AtomType {
|
|
|
64
64
|
|
|
65
65
|
pub fn radius(&self) -> f32 {
|
|
66
66
|
match self {
|
|
67
|
-
AtomType::H
|
|
68
|
-
AtomType::C
|
|
69
|
-
AtomType::N
|
|
70
|
-
AtomType::O
|
|
71
|
-
AtomType::F
|
|
72
|
-
AtomType::P
|
|
73
|
-
AtomType::S
|
|
67
|
+
AtomType::H => 1.20,
|
|
68
|
+
AtomType::C => 1.70,
|
|
69
|
+
AtomType::N => 1.55,
|
|
70
|
+
AtomType::O => 1.52,
|
|
71
|
+
AtomType::F => 1.47,
|
|
72
|
+
AtomType::P => 1.80,
|
|
73
|
+
AtomType::S => 1.80,
|
|
74
74
|
AtomType::Cl => 1.75,
|
|
75
75
|
AtomType::Br => 1.85,
|
|
76
|
-
AtomType::I
|
|
76
|
+
AtomType::I => 1.98,
|
|
77
77
|
AtomType::Unknown => 1.5,
|
|
78
78
|
}
|
|
79
79
|
}
|
|
@@ -163,11 +163,8 @@ impl Molecules {
|
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
self
|
|
169
|
-
}
|
|
170
|
-
|
|
166
|
+
/// Centers the molecule by translating all atoms so that the geometric center
|
|
167
|
+
/// is at the origin (0.0, 0.0, 0.0).
|
|
171
168
|
pub fn centered(mut self) -> Self {
|
|
172
169
|
if self.atoms.is_empty() {
|
|
173
170
|
return self;
|
|
@@ -207,8 +204,13 @@ impl Molecules {
|
|
|
207
204
|
|
|
208
205
|
// 1. 原子 -> Sphere
|
|
209
206
|
for (i, pos) in self.atoms.iter().enumerate() {
|
|
210
|
-
let radius = self
|
|
211
|
-
|
|
207
|
+
let radius = self
|
|
208
|
+
.atom_types
|
|
209
|
+
.get(i)
|
|
210
|
+
.unwrap_or(&AtomType::Unknown)
|
|
211
|
+
.radius()
|
|
212
|
+
* 0.2;
|
|
213
|
+
let color = self.style.color.unwrap_or(self.atom_types.get(i).unwrap_or(&AtomType::Unknown).color());
|
|
212
214
|
|
|
213
215
|
let mut sphere = Sphere::new(*pos, radius);
|
|
214
216
|
sphere.interaction = self.interaction;
|
|
@@ -234,14 +236,14 @@ impl Molecules {
|
|
|
234
236
|
}
|
|
235
237
|
|
|
236
238
|
// 2. 键 -> Stick
|
|
237
|
-
for (
|
|
239
|
+
for (_i, bond) in self.bonds.iter().enumerate() {
|
|
238
240
|
let [a, b] = *bond;
|
|
239
241
|
let pos_a = self.atoms[a as usize];
|
|
240
242
|
let pos_b = self.atoms[b as usize];
|
|
241
243
|
|
|
242
|
-
let mut stick = Stick::new(pos_a, pos_b, 0.1);
|
|
243
|
-
stick.interaction = self.interaction;
|
|
244
|
-
stick = stick.color([0.7, 0.7, 0.7]);
|
|
244
|
+
let mut stick = Stick::new(pos_a, pos_b, 0.1);
|
|
245
|
+
// stick.interaction = self.interaction;
|
|
246
|
+
stick = stick.color(self.style.color.unwrap_or([0.7, 0.7, 0.7]));
|
|
245
247
|
|
|
246
248
|
let mesh = stick.to_mesh(1.0);
|
|
247
249
|
|
|
@@ -271,3 +273,9 @@ impl Molecules {
|
|
|
271
273
|
}
|
|
272
274
|
}
|
|
273
275
|
}
|
|
276
|
+
|
|
277
|
+
impl VisualShape for Molecules {
|
|
278
|
+
fn style_mut(&mut self) -> &mut VisualStyle {
|
|
279
|
+
&mut self.style
|
|
280
|
+
}
|
|
281
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
use serde::{Deserialize, Serialize};
|
|
2
|
+
|
|
3
|
+
use crate::{
|
|
4
|
+
Shape,
|
|
5
|
+
scene::Scene,
|
|
6
|
+
utils::{Interaction, MeshData, VisualShape, VisualStyle},
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
use once_cell::sync::Lazy;
|
|
10
|
+
use std::collections::HashMap;
|
|
11
|
+
use std::sync::Mutex;
|
|
12
|
+
|
|
13
|
+
#[derive(Clone)]
|
|
14
|
+
struct SphereMeshTemplate {
|
|
15
|
+
vertices: Vec<[f32; 3]>,
|
|
16
|
+
normals: Vec<[f32; 3]>,
|
|
17
|
+
indices: Vec<u32>,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static SPHERE_TEMPLATE_CACHE: Lazy<Mutex<HashMap<u32, SphereMeshTemplate>>> =
|
|
21
|
+
Lazy::new(|| Mutex::new(HashMap::new()));
|
|
22
|
+
|
|
23
|
+
fn get_or_generate_sphere_mesh_template(quality: u32) -> SphereMeshTemplate {
|
|
24
|
+
let mut cache = SPHERE_TEMPLATE_CACHE.lock().unwrap();
|
|
25
|
+
|
|
26
|
+
if let Some(template) = cache.get(&quality) {
|
|
27
|
+
return template.clone(); // 直接返回已有的
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let lat_segments = 10 * quality;
|
|
31
|
+
let lon_segments = 20 * quality;
|
|
32
|
+
|
|
33
|
+
let mut vertices = Vec::new();
|
|
34
|
+
let mut normals = Vec::new();
|
|
35
|
+
let mut indices = Vec::new();
|
|
36
|
+
|
|
37
|
+
for i in 0..=lat_segments {
|
|
38
|
+
let theta = std::f32::consts::PI * (i as f32) / (lat_segments as f32);
|
|
39
|
+
let sin_theta = theta.sin();
|
|
40
|
+
let cos_theta = theta.cos();
|
|
41
|
+
|
|
42
|
+
for j in 0..=lon_segments {
|
|
43
|
+
let phi = 2.0 * std::f32::consts::PI * (j as f32) / (lon_segments as f32);
|
|
44
|
+
let sin_phi = phi.sin();
|
|
45
|
+
let cos_phi = phi.cos();
|
|
46
|
+
|
|
47
|
+
let nx = sin_theta * cos_phi;
|
|
48
|
+
let ny = cos_theta;
|
|
49
|
+
let nz = sin_theta * sin_phi;
|
|
50
|
+
|
|
51
|
+
vertices.push([nx, ny, nz]); // 单位球
|
|
52
|
+
normals.push([nx, ny, nz]);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
for i in 0..lat_segments {
|
|
57
|
+
for j in 0..lon_segments {
|
|
58
|
+
let first = i * (lon_segments + 1) + j;
|
|
59
|
+
let second = first + lon_segments + 1;
|
|
60
|
+
|
|
61
|
+
indices.push(first);
|
|
62
|
+
indices.push(first + 1);
|
|
63
|
+
indices.push(second);
|
|
64
|
+
|
|
65
|
+
indices.push(second);
|
|
66
|
+
indices.push(first + 1);
|
|
67
|
+
indices.push(second + 1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let template = SphereMeshTemplate {
|
|
72
|
+
vertices,
|
|
73
|
+
normals,
|
|
74
|
+
indices,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
cache.insert(quality, template.clone());
|
|
78
|
+
|
|
79
|
+
template
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
|
83
|
+
pub struct Sphere {
|
|
84
|
+
pub center: [f32; 3],
|
|
85
|
+
pub radius: f32,
|
|
86
|
+
pub quality: u32,
|
|
87
|
+
|
|
88
|
+
pub style: VisualStyle,
|
|
89
|
+
pub interaction: Interaction,
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
impl Into<Shape> for Sphere {
|
|
93
|
+
fn into(self) -> Shape {
|
|
94
|
+
Shape::Sphere(self)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
impl Sphere {
|
|
99
|
+
pub fn new(center: [f32; 3], radius: f32) -> Self {
|
|
100
|
+
Self {
|
|
101
|
+
center,
|
|
102
|
+
radius,
|
|
103
|
+
quality: 2,
|
|
104
|
+
style: VisualStyle {
|
|
105
|
+
opacity: 1.0,
|
|
106
|
+
visible: true,
|
|
107
|
+
..Default::default()
|
|
108
|
+
},
|
|
109
|
+
interaction: Default::default(),
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
pub fn set_center(mut self, center: [f32; 3]) -> Self {
|
|
114
|
+
self.center = center;
|
|
115
|
+
self
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
pub fn set_radius(mut self, radius: f32) -> Self {
|
|
119
|
+
self.radius = radius;
|
|
120
|
+
self
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// pub fn clickable(mut self, val: bool) -> Self {
|
|
124
|
+
// self.interaction.clickable = val;
|
|
125
|
+
// self
|
|
126
|
+
// }
|
|
127
|
+
|
|
128
|
+
pub fn to_mesh(&self, scale: f32) -> MeshData {
|
|
129
|
+
let template = get_or_generate_sphere_mesh_template(self.quality);
|
|
130
|
+
|
|
131
|
+
let [cx, cy, cz] = self.center;
|
|
132
|
+
let r = self.radius;
|
|
133
|
+
|
|
134
|
+
let transformed_vertices: Vec<[f32; 3]> = template
|
|
135
|
+
.vertices
|
|
136
|
+
.iter()
|
|
137
|
+
.map(|v| {
|
|
138
|
+
[
|
|
139
|
+
(v[0] * r + cx) * scale,
|
|
140
|
+
(v[1] * r + cy) * scale,
|
|
141
|
+
(v[2] * r + cz) * scale,
|
|
142
|
+
]
|
|
143
|
+
})
|
|
144
|
+
.collect();
|
|
145
|
+
|
|
146
|
+
let transformed_normals: Vec<[f32; 3]> = template
|
|
147
|
+
.normals
|
|
148
|
+
.iter()
|
|
149
|
+
.map(|n| n.map(|x| x * scale)) // 你可以不乘 scale,如果只用于方向
|
|
150
|
+
.collect();
|
|
151
|
+
|
|
152
|
+
let base_color = self.style.color.unwrap_or([1.0, 1.0, 1.0]);
|
|
153
|
+
let alpha = self.style.opacity.clamp(0.0, 1.0);
|
|
154
|
+
let color = [base_color[0], base_color[1], base_color[2], alpha];
|
|
155
|
+
|
|
156
|
+
let colors = vec![color; transformed_vertices.len()];
|
|
157
|
+
|
|
158
|
+
MeshData {
|
|
159
|
+
vertices: transformed_vertices,
|
|
160
|
+
normals: transformed_normals,
|
|
161
|
+
indices: template.indices.clone(),
|
|
162
|
+
colors: Some(colors),
|
|
163
|
+
transform: None,
|
|
164
|
+
is_wireframe: self.style.wireframe,
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
impl VisualShape for Sphere {
|
|
170
|
+
fn style_mut(&mut self) -> &mut VisualStyle {
|
|
171
|
+
&mut self.style
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -10,11 +10,11 @@ use crate::{
|
|
|
10
10
|
pub struct Stick {
|
|
11
11
|
pub start: [f32; 3],
|
|
12
12
|
pub end: [f32; 3],
|
|
13
|
-
pub
|
|
13
|
+
pub thickness_radius: f32,
|
|
14
14
|
pub quality: u32,
|
|
15
15
|
|
|
16
16
|
pub style: VisualStyle,
|
|
17
|
-
|
|
17
|
+
interaction: Interaction,
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
impl Into<Shape> for Stick {
|
|
@@ -28,7 +28,7 @@ impl Stick {
|
|
|
28
28
|
Self {
|
|
29
29
|
start,
|
|
30
30
|
end,
|
|
31
|
-
radius,
|
|
31
|
+
thickness_radius: radius,
|
|
32
32
|
quality: 6,
|
|
33
33
|
style: VisualStyle {
|
|
34
34
|
opacity: 1.0,
|
|
@@ -39,25 +39,25 @@ impl Stick {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
pub fn
|
|
43
|
-
self.
|
|
42
|
+
pub fn set_thickness(mut self, thickness: f32) -> Self {
|
|
43
|
+
self.thickness_radius = thickness;
|
|
44
44
|
self
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
pub fn
|
|
47
|
+
pub fn set_start(mut self, start: [f32; 3]) -> Self {
|
|
48
48
|
self.start = start;
|
|
49
49
|
self
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
pub fn
|
|
52
|
+
pub fn set_end(mut self, end: [f32; 3]) -> Self {
|
|
53
53
|
self.end = end;
|
|
54
54
|
self
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
57
|
+
// fn clickable(mut self, val: bool) -> Self {
|
|
58
|
+
// self.interaction.clickable = val;
|
|
59
|
+
// self
|
|
60
|
+
// }
|
|
61
61
|
|
|
62
62
|
pub fn to_mesh(&self, scale: f32) -> MeshData {
|
|
63
63
|
let mut vertices = Vec::new();
|
|
@@ -66,7 +66,7 @@ impl Stick {
|
|
|
66
66
|
let mut colors = Vec::new();
|
|
67
67
|
|
|
68
68
|
let segments = 20 * self.quality;
|
|
69
|
-
let r = self.
|
|
69
|
+
let r = self.thickness_radius;
|
|
70
70
|
|
|
71
71
|
let start = glam::Vec3::from_array(self.start);
|
|
72
72
|
let end = glam::Vec3::from_array(self.end);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
use glam::Mat4;
|
|
2
2
|
use serde::{Deserialize, Serialize};
|
|
3
3
|
|
|
4
|
-
use crate::shapes::{
|
|
4
|
+
use crate::shapes::{Molecules, Sphere, Stick};
|
|
5
5
|
|
|
6
6
|
#[derive(Serialize, Deserialize, Debug, Clone, Default, Copy)]
|
|
7
7
|
pub struct VisualStyle {
|