├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md ├── assets └── preview.png ├── examples ├── curve │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── pmm │ ├── 1.emm │ ├── 1.pmm │ ├── 2.emm │ ├── 2.pmm │ ├── Cargo.toml │ ├── src │ │ └── main.rs │ └── static │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── js │ │ └── dat.gui.min.js │ │ ├── output_iem.png │ │ └── 安特.pmx ├── pmx │ ├── Cargo.toml │ ├── src │ │ └── main.rs │ └── 安特.pmx ├── vmd │ ├── Cargo.toml │ ├── M.vmd │ └── src │ │ └── main.rs └── webgl │ ├── Cargo.toml │ ├── src │ └── main.rs │ └── static │ ├── favicon.ico │ ├── index.html │ ├── js │ └── dat.gui.min.js │ ├── output_iem.png │ └── 安特.pmx └── src ├── animation ├── animations │ ├── animator.rs │ ├── clip.rs │ ├── curve.rs │ └── mod.rs ├── core │ ├── animation.rs │ ├── error.rs │ ├── evaluate.rs │ ├── interpolator.rs │ ├── loader.rs │ └── mod.rs ├── interpolators │ ├── fixed.rs │ ├── linear.rs │ ├── mod.rs │ └── path.rs ├── keyframes │ ├── keyframe.rs │ └── mod.rs ├── loaders │ ├── mod.rs │ └── vmd.rs └── mod.rs ├── lib.rs ├── math ├── consts.rs ├── dual.rs ├── mat2.rs ├── mat3.rs ├── mat4.rs ├── mod.rs ├── quat.rs ├── ser.rs ├── type_size.rs ├── vec.rs ├── vec2.rs ├── vec3.rs └── vec4.rs ├── models ├── core │ ├── bone.rs │ ├── error.rs │ ├── loader.rs │ ├── material.rs │ ├── mesh.rs │ ├── mod.rs │ ├── model.rs │ └── solver.rs ├── loaders │ ├── mod.rs │ ├── pmd.rs │ └── pmx.rs └── mod.rs ├── renderer ├── core │ ├── canvas.rs │ ├── mod.rs │ └── renderer.rs ├── mod.rs ├── renderer │ ├── forward │ │ ├── forward.rs │ │ ├── mod.rs │ │ ├── shaders.rs │ │ └── uniforms.rs │ └── mod.rs ├── webgl │ ├── mod.rs │ ├── webgl_common.rs │ ├── webgl_context.rs │ ├── webgl_native.rs │ ├── webgl_stdweb_common.rs │ ├── webgl_stdweb_context.rs │ └── webgl_stdweb_native.rs └── window │ ├── mod.rs │ ├── native.rs │ └── web.rs └── scene ├── cameras ├── mod.rs ├── orthographic.rs └── perspective.rs ├── core ├── camera.rs ├── canvas.rs ├── downcast.rs ├── error.rs ├── event.rs ├── format.rs ├── geometry.rs ├── light.rs ├── loader.rs ├── log.rs ├── material.rs ├── mod.rs ├── object.rs ├── resource.rs ├── sampler.rs ├── shape.rs ├── texture.rs ├── transform.rs └── variant.rs ├── geometries ├── circle.rs ├── cone.rs ├── cube.rs ├── cylinder.rs ├── fan.rs ├── mesh.rs ├── mod.rs ├── plane.rs └── sphere.rs ├── lights ├── directional.rs ├── mod.rs ├── point.rs ├── sky.rs └── spot.rs ├── loaders ├── json.rs ├── mod.rs ├── model.rs ├── pmm.rs └── texture.rs ├── materials ├── custom.rs ├── mod.rs ├── skinning.rs ├── skybox.rs └── standard.rs ├── mod.rs ├── scene ├── mod.rs ├── scene.rs ├── scene_data.rs └── scene_node.rs ├── shapes ├── mesh.rs ├── mod.rs └── model.rs ├── spectrum ├── celsius.rs ├── kelvin.rs ├── mod.rs ├── rgb.rs ├── srgb.rs ├── unit.rs └── xyz.rs └── util ├── mod.rs └── uuid.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /examples/webgl/target 3 | /examples/model/target 4 | /examples/pmx/target 5 | /examples/curve/target 6 | /examples/vmd/target 7 | /examples/pmm/target 8 | **/*.rs.bk 9 | Cargo.lock 10 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "octoon" 3 | version = "0.1.7" 4 | license = "MIT" 5 | authors = ["Rui <2221870259@qq.com>"] 6 | edition = "2018" 7 | description = "Graphics library for Rust." 8 | homepage = "https://github.com/octoon/engine" 9 | repository = "https://github.com/octoon/engine.git" 10 | 11 | [dependencies] 12 | byteorder = "1.2.7" 13 | encoding = "0.2.33" 14 | uuid = { version = "0.7.1", features = ["v4","serde"] } 15 | log = { version = "0.4", features = ["std", "serde"] } 16 | rand = { version = "0.6.1", features = ["stdweb"]} 17 | image = { version = "0.20.1" } 18 | base64 = { version = "0.10.1" } 19 | 20 | [dependencies.serde] 21 | default-features = false 22 | features = ["rc"] 23 | optional = true 24 | version = "1.0" 25 | 26 | [dependencies.serde_derive] 27 | default-features = false 28 | optional = true 29 | version = "1.0" 30 | 31 | [dependencies.serde_json] 32 | default-features = false 33 | optional = true 34 | version = "1.0" 35 | 36 | [dependencies.stdweb] 37 | version = "0.4.13" 38 | optional = true 39 | 40 | [dependencies.stdweb-derive] 41 | version = "0.5.1" 42 | optional = true 43 | 44 | [target.'cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))'.dependencies.gl] 45 | version = "0.9.0" 46 | optional = true 47 | 48 | [target.'cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))'.dependencies.glfw] 49 | version = "0.25.0" 50 | optional = true 51 | 52 | [features] 53 | default = ["serde", "serde_derive", "serde_json", "gl", "glfw"] 54 | webgl = ["stdweb", "stdweb-derive"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Rui 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | octoon-math 2 | ------------- 3 | octoon-math is designed for rust developers working on games and compute graphics 4 | 5 | Usage 6 | --------- 7 | Add this to your Cargo.toml: 8 | 9 | ```toml 10 | [dependencies] 11 | octoon-math = { version = "0.1", features = ["serialize"] } 12 | ``` 13 | 14 | Examples 15 | -------- 16 | ```rust 17 | extern crate octoon_math; 18 | 19 | use octoon_math::*; 20 | use octoon_math::consts::*; 21 | 22 | fn main() 23 | { 24 | // new float2 25 | let a = float2::new(1.0,0.0); 26 | let b = float!(0.0,1.0); // same as float2::new 27 | 28 | // new float3 29 | let c = float3::new(1.0,0.0,0.0); 30 | let d = float!(0.0,1.0,0.0); // same as float3::new 31 | 32 | // new float4 33 | let e = float4::new(1.0,0.0,0.0,0.0); 34 | let f = float!(0.0,1.0,0.0,0.0); // same as float4::new 35 | 36 | // new array 37 | let x = 0.5; 38 | let y = 0.5; 39 | let z = 0.5; 40 | 41 | let vertices:Vec = vec![ 42 | float!(-x,-y,-z), float!( x,-y,-z), float!( x, y,-z), float!(-x, y,-z), 43 | float!(-x,-y, z), float!( x,-y, z), float!( x, y, z), float!(-x, y, z), 44 | float!(-x,-y,-z), float!(-x, y,-z), float!(-x, y, z), float!(-x,-y, z), 45 | float!( x,-y,-z), float!( x, y,-z), float!( x, y, z), float!( x,-y, z), 46 | float!(-x,-y,-z), float!(-x,-y, z), float!( x,-y, z), float!( x,-y,-z), 47 | float!(-x, y,-z), float!(-x, y, z), float!( x, y, z), float!( x, y,-z), 48 | ]; 49 | 50 | // operators 51 | let ab = a.dot(b); 52 | let cd = c.cross(d); 53 | let ef = e.lerp(f, 0.5); 54 | let len = a.length(); 55 | 56 | // consts 57 | let pi = f32::pi(); 58 | let pi2 = f32::pi2(); 59 | let pi4 = f32::pi4(); 60 | let one = float2::one(); 61 | let zero = float2::zero(); 62 | let unitx = float3::unit_x(); // say: float3::new(1.0, 0.0, 0.0) 63 | let unity = float3::unit_y(); // say: float3::new(0.0, 1.0, 0.0) 64 | let unitz = float3::unit_z(); // say: float3::new(0.0, 0.0, 1.0) 65 | } 66 | ``` -------------------------------------------------------------------------------- /assets/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octoon/engine/1beee57fb773e940c4e4bf4ce6b1a3eeba151482/assets/preview.png -------------------------------------------------------------------------------- /examples/curve/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "curve" 3 | version = "0.1.0" 4 | license = "MIT" 5 | authors = ["Rui <2221870259@qq.com>"] 6 | homepage = "https://github.com/octoon/engine" 7 | repository = "https://github.com/octoon/engine.git" 8 | keywords = ["model", "load", "read"] 9 | 10 | [dependencies] 11 | octoon = { path="../../"} -------------------------------------------------------------------------------- /examples/curve/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate octoon; 2 | 3 | use octoon::animation::{Keyframe, AnimationCurve, Evaluate}; 4 | 5 | fn main() 6 | { 7 | let mut ks = Vec::new(); 8 | 9 | for i in 0..50 10 | { 11 | ks.push(Keyframe::new(i as f32, f32::sin(i as f32), None)); 12 | } 13 | 14 | let anim = AnimationCurve::new_with(ks, None); 15 | 16 | for i in 0..100 17 | { 18 | println!("{:?}", anim.evaluate(i as f32 / 2.0)); 19 | } 20 | } -------------------------------------------------------------------------------- /examples/pmm/1.emm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octoon/engine/1beee57fb773e940c4e4bf4ce6b1a3eeba151482/examples/pmm/1.emm -------------------------------------------------------------------------------- /examples/pmm/1.pmm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octoon/engine/1beee57fb773e940c4e4bf4ce6b1a3eeba151482/examples/pmm/1.pmm -------------------------------------------------------------------------------- /examples/pmm/2.emm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octoon/engine/1beee57fb773e940c4e4bf4ce6b1a3eeba151482/examples/pmm/2.emm -------------------------------------------------------------------------------- /examples/pmm/2.pmm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octoon/engine/1beee57fb773e940c4e4bf4ce6b1a3eeba151482/examples/pmm/2.pmm -------------------------------------------------------------------------------- /examples/pmm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pmm" 3 | version = "0.1.0" 4 | license = "MIT" 5 | authors = ["Rui <2221870259@qq.com>"] 6 | homepage = "https://github.com/octoon/engine" 7 | repository = "https://github.com/octoon/engine.git" 8 | keywords = ["model", "load", "read"] 9 | 10 | [dependencies] 11 | octoon = { path="../../"} 12 | serde = "*" 13 | serde_json = "*" -------------------------------------------------------------------------------- /examples/pmm/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate serde; 2 | extern crate octoon; 3 | 4 | use std::sync::Arc; 5 | use octoon::scene::{SkyLight, TextureLoader}; 6 | use octoon::renderer::window::Window; 7 | 8 | fn main() 9 | { 10 | let irradiance = Arc::new(TextureLoader::load_from_memory(include_bytes!("../static/output_iem.png")).unwrap()); 11 | let sky = SkyLight::builder(irradiance.clone(), irradiance.clone()).build(); 12 | 13 | let mut scene = octoon::scene::open("./1.pmm").unwrap(); 14 | scene.add(sky); 15 | 16 | println!("{}", octoon::scene::to_string(&scene).unwrap()); 17 | 18 | let mut window = Window::new("PMM Loader"); 19 | window.update(move |canvas, _| 20 | { 21 | scene.update(canvas); 22 | canvas.render(&scene); 23 | }); 24 | } -------------------------------------------------------------------------------- /examples/pmm/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octoon/engine/1beee57fb773e940c4e4bf4ce6b1a3eeba151482/examples/pmm/static/favicon.ico -------------------------------------------------------------------------------- /examples/pmm/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | WebGL Example 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/pmm/static/output_iem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octoon/engine/1beee57fb773e940c4e4bf4ce6b1a3eeba151482/examples/pmm/static/output_iem.png -------------------------------------------------------------------------------- /examples/pmm/static/安特.pmx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octoon/engine/1beee57fb773e940c4e4bf4ce6b1a3eeba151482/examples/pmm/static/安特.pmx -------------------------------------------------------------------------------- /examples/pmx/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pmx" 3 | version = "0.1.0" 4 | license = "MIT" 5 | authors = ["Rui <2221870259@qq.com>"] 6 | homepage = "https://github.com/octoon/engine" 7 | repository = "https://github.com/octoon/engine.git" 8 | keywords = ["model", "load", "read"] 9 | 10 | [dependencies] 11 | octoon = { path="../../"} -------------------------------------------------------------------------------- /examples/pmx/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate octoon; 2 | 3 | fn main() 4 | { 5 | let model = octoon::models::open("./安特.pmx").unwrap(); 6 | 7 | println!("model count: {}", model.meshes.len()); 8 | println!("texture count: {}", model.textures.len()); 9 | println!("material count: {}", model.materials.len()); 10 | println!("bone count: {}", model.bones.len()); 11 | 12 | for (i, mesh) in model.meshes.iter().enumerate() 13 | { 14 | println!("model[{}].mesh.material_id = {:?}", i, mesh.material_id); 15 | println!("model[{}].vertices: {}", i, mesh.positions.len() / 3); 16 | println!("model[{}].normals: {}", i, mesh.normals.len() / 3); 17 | println!("model[{}].texcoords: {}", i, mesh.texcoords.len() / 2); 18 | println!("model[{}].indices: {}", i, mesh.indices.len()); 19 | } 20 | } -------------------------------------------------------------------------------- /examples/pmx/安特.pmx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octoon/engine/1beee57fb773e940c4e4bf4ce6b1a3eeba151482/examples/pmx/安特.pmx -------------------------------------------------------------------------------- /examples/vmd/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vmd" 3 | version = "0.1.0" 4 | license = "MIT" 5 | authors = ["Rui <2221870259@qq.com>"] 6 | homepage = "https://github.com/octoon/engine" 7 | repository = "https://github.com/octoon/engine.git" 8 | keywords = ["model", "load", "read"] 9 | 10 | [dependencies] 11 | octoon = { path="../../"} -------------------------------------------------------------------------------- /examples/vmd/M.vmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octoon/engine/1beee57fb773e940c4e4bf4ce6b1a3eeba151482/examples/vmd/M.vmd -------------------------------------------------------------------------------- /examples/vmd/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate octoon; 2 | 3 | fn main() 4 | { 5 | let mut motion = octoon::animation::open("./M.vmd").unwrap(); 6 | motion.clips[0].add_event(|name, value| println!("{:?}:{:?}", name, value)); 7 | motion.evaluate(7.5); 8 | } -------------------------------------------------------------------------------- /examples/webgl/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "example" 3 | version = "0.1.0" 4 | authors = ["Rui <2221870259@qq.com>"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | octoon = { path="../../", features = ["webgl"]} 9 | 10 | [target.'cfg(any(target_arch = "wasm32", target_arch = "asmjs"))'.dependencies] 11 | stdweb = "0.4.10" -------------------------------------------------------------------------------- /examples/webgl/src/main.rs: -------------------------------------------------------------------------------- 1 | #![recursion_limit = "512"] 2 | 3 | #[macro_use] 4 | extern crate octoon; 5 | 6 | use std::sync::Arc; 7 | 8 | use octoon::math::{float3, float4x4, Quaternion, One}; 9 | use octoon::scene::core::{Object, Light, LightType}; 10 | use octoon::scene::lights::{ PointLight, SkyLight }; 11 | use octoon::scene::cameras::{ PerspectiveCamera }; 12 | use octoon::scene::geometries::{ SphereGeometry }; 13 | use octoon::scene::loaders::{TextureLoader, ModelLoader}; 14 | use octoon::scene::scene::Scene; 15 | use octoon::scene::spectrum::{Kelvin, Lumens, LED}; 16 | use octoon::scene::materials::{StandardMaterial, SkyboxMaterial}; 17 | use octoon::scene::shapes::MeshShape; 18 | use octoon::renderer::window::Window; 19 | 20 | #[macro_use] 21 | #[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))] 22 | extern crate stdweb; 23 | 24 | #[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))] 25 | use stdweb::unstable::TryInto; 26 | 27 | pub fn main() 28 | { 29 | octoon::scene::core::log::init_log().unwrap(); 30 | 31 | let irradiance = Arc::new(TextureLoader::load_from_memory(include_bytes!("../static/output_iem.png"), Some("../static/output_iem.png".to_string())).unwrap()); 32 | 33 | let material = StandardMaterial::builder() 34 | .set_albedo(float!(192./255.,185./255.,176./255.).into()) 35 | .set_smoothness(0.6_f32.into()) 36 | .build(); 37 | 38 | let sky_material = SkyboxMaterial::builder() 39 | .set_color(float3::one().into()) 40 | .set_texture(Some(irradiance.clone())) 41 | .build(); 42 | 43 | let sky_geometry = SphereGeometry::builder() 44 | .set_radius(1000.0) 45 | .set_width_segments(10) 46 | .set_height_segments(10) 47 | .build(); 48 | 49 | let sphere_geometry = SphereGeometry::builder() 50 | .set_radius(1.0) 51 | .set_width_segments(32) 52 | .set_height_segments(32) 53 | .build(); 54 | 55 | let mut camera = PerspectiveCamera::builder() 56 | .main(true) 57 | .set_film_size(36.0) 58 | .set_focal_length(50.0) 59 | .set_translate(float!(0.0,0.1,10.0)) 60 | .build(); 61 | 62 | let mut light = PointLight::builder() 63 | .set_color(Kelvin(6000.0).into()) 64 | .set_intensity(Lumens::from(LED(10.0)).to_cd(LightType::Point).into()) 65 | .set_translate(float3::new(0.0,10.0,0.0)) 66 | .build(); 67 | 68 | let sky = SkyLight::builder(irradiance.clone(), irradiance.clone()) 69 | .build(); 70 | 71 | let sky_shape = MeshShape::builder() 72 | .set_geometry(sky_geometry.into()) 73 | .set_material(sky_material.into()) 74 | .set_rotation(float!(0.0,3.1415926,0.0)) 75 | .build(); 76 | 77 | let sphere = MeshShape::builder() 78 | .set_geometry(sphere_geometry.into()) 79 | .set_material(material.into()) 80 | .set_translate(float!(0.0,0.0,20.0)) 81 | .set_rotation(float!(0.0,3.1415926,0.0)) 82 | .build(); 83 | 84 | /*let mut model = ModelLoader::load_from_memory(include_bytes!("../static/安特.pmx")).unwrap(); 85 | model.set_scale(float!(0.1,0.1,0.1)); 86 | model.set_translate(float!(0.0,-0.8,20.0));*/ 87 | 88 | let mut scene = Scene::new(); 89 | scene.add(&camera); 90 | scene.add(&sky_shape); 91 | scene.add(&sphere); 92 | scene.add(&light); 93 | scene.add(&sky); 94 | //scene.add(model); 95 | 96 | println!("{}", octoon::scene::to_string(&scene).unwrap()); 97 | 98 | #[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))] 99 | js!{ 100 | window.dat.light = { 101 | x:30, 102 | y:30, 103 | z:30, 104 | temperature:6000, 105 | intensity:10, 106 | }; 107 | 108 | window.dat.camera = { 109 | x:0, 110 | y:0, 111 | z:10, 112 | film_size:"35mm", 113 | focal_length:"50mm" 114 | }; 115 | 116 | window.dat.exposure = { 117 | aperture:"1.0", 118 | iso:"100", 119 | shutter_speed:"1/125", 120 | }; 121 | 122 | var gui = new dat.GUI(); 123 | 124 | var light = gui.addFolder("Light"); 125 | light.add(window.dat.light,"x",-180,180); 126 | light.add(window.dat.light,"y",-180,180); 127 | light.add(window.dat.light,"z",-180,180); 128 | light.add(window.dat.light,"temperature",1000,40000); 129 | light.add(window.dat.light,"intensity",0,20); 130 | 131 | var camera = gui.addFolder("Camera"); 132 | camera.add(window.dat.camera,"x",-3,3); 133 | camera.add(window.dat.camera,"y",-3,3); 134 | camera.add(window.dat.camera,"z",0,40); 135 | camera.add(window.dat.camera,"film_size",["7mm","35mm","41mm","62mm"],); 136 | camera.add(window.dat.camera,"focal_length",["15mm","20mm","24mm","28mm","35mm","50mm","80mm","135mm","200mm"]); 137 | 138 | var exposure = gui.addFolder("Exposure"); 139 | exposure.add(window.dat.exposure,"aperture", [,"1.0","1.2","1.4","1.8","2.5","2.8","3.2","4.8","5.6","6.7","2","4","8","11","13","16","18","22","27","32"]); 140 | exposure.add(window.dat.exposure,"iso",["50","100","125","160","200","250","320","400","500","640","800","1000","1250","1600","2000","2500","3200","4000","5000","6400"]); 141 | exposure.add(window.dat.exposure,"shutter_speed",["1","2","4","1/4000","1/2000","1/1000","1/500","1/250","1/125","1/60","1/30","1/15","1/8","1/4","1/2"]); 142 | }; 143 | 144 | let mut window = Window::new("Webgl Example"); 145 | window.update(move |renderer, time| 146 | { 147 | #[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))] 148 | { 149 | let light_x:i32 = (js! { return parseInt(window.dat.light.x); } ).try_into().unwrap(); 150 | let light_y:i32 = (js! { return parseInt(window.dat.light.y); } ).try_into().unwrap(); 151 | let light_z:i32 = (js! { return parseInt(window.dat.light.z); } ).try_into().unwrap(); 152 | let temperature:i32 = (js! { return parseInt(window.dat.light.temperature); } ).try_into().unwrap(); 153 | let intensity:i32 = (js! { return parseInt(window.dat.light.intensity); } ).try_into().unwrap(); 154 | let rotation:float4x4 = Quaternion::euler_xyz(&float!((light_x as f32).to_degrees(),(light_y as f32).to_degrees(),(light_z as f32).to_degrees())).into(); 155 | 156 | light.set_color(Kelvin(temperature as f32).into()); 157 | light.set_intensity(Lumens::from(LED(intensity as f32)).to_cd(LightType::Point).into()); 158 | light.set_translate(float!(0.0,10.0,0.0) * rotation); 159 | } 160 | 161 | #[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))] 162 | { 163 | let camera_x:i32 = (js! { return parseInt(window.dat.camera.x); } ).try_into().unwrap(); 164 | let camera_y:i32 = (js! { return parseInt(window.dat.camera.y); } ).try_into().unwrap(); 165 | let camera_z:i32 = (js! { return parseInt(window.dat.camera.z); } ).try_into().unwrap(); 166 | 167 | camera.set_translate(float!(camera_x as f32,camera_y as f32,camera_z as f32)); 168 | } 169 | 170 | #[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))] 171 | { 172 | let rotation:float4x4 = Quaternion::euler_xyz(&float!(time, time, time)).into(); 173 | light.set_translate(float!(0.0,10.0,0.0) * rotation); 174 | } 175 | 176 | camera.upload(renderer); 177 | 178 | renderer.render(&scene) 179 | }); 180 | } -------------------------------------------------------------------------------- /examples/webgl/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octoon/engine/1beee57fb773e940c4e4bf4ce6b1a3eeba151482/examples/webgl/static/favicon.ico -------------------------------------------------------------------------------- /examples/webgl/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | WebGL Example 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/webgl/static/output_iem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octoon/engine/1beee57fb773e940c4e4bf4ce6b1a3eeba151482/examples/webgl/static/output_iem.png -------------------------------------------------------------------------------- /examples/webgl/static/安特.pmx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octoon/engine/1beee57fb773e940c4e4bf4ce6b1a3eeba151482/examples/webgl/static/安特.pmx -------------------------------------------------------------------------------- /src/animation/animations/animator.rs: -------------------------------------------------------------------------------- 1 | use super::super::animations::{AnimationClip}; 2 | use super::super::core::{Animation}; 3 | 4 | #[derive(Debug)] 5 | pub struct Animator 6 | { 7 | pub name:String, 8 | pub clips:Vec>, 9 | } 10 | 11 | impl Animator 12 | { 13 | pub fn new() -> Self 14 | { 15 | Self 16 | { 17 | name:String::new(), 18 | clips:Vec::new() 19 | } 20 | } 21 | 22 | pub fn add_clip(&mut self, clip:AnimationClip) 23 | { 24 | self.clips.push(clip); 25 | } 26 | 27 | pub fn add_clips(&mut self, clips:Vec>) 28 | { 29 | for clip in clips 30 | { 31 | self.clips.push(clip); 32 | } 33 | } 34 | 35 | pub fn empty(&self) -> bool 36 | { 37 | if self.clips.len() > 0 { true } else { false } 38 | } 39 | 40 | pub fn len(&self) -> usize 41 | { 42 | self.clips.len() 43 | } 44 | } 45 | 46 | impl Animator where T:Animation + Copy 47 | { 48 | pub fn evaluate(&self, time:f32) 49 | { 50 | for clip in self.clips.iter() 51 | { 52 | clip.evaluate(time); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /src/animation/animations/clip.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::ops::Fn; 3 | use std::fmt::Debug; 4 | 5 | use super::super::animations::{AnimationCurve}; 6 | use super::super::core::{Animation, Evaluate}; 7 | 8 | pub struct AnimationClip 9 | { 10 | pub name:String, 11 | pub curves:HashMap>, 12 | pub events:Vec> 13 | } 14 | 15 | impl AnimationClip 16 | { 17 | pub fn new() -> Self 18 | { 19 | Self 20 | { 21 | name:String::new(), 22 | curves:HashMap::new(), 23 | events:Vec::new(), 24 | } 25 | } 26 | 27 | #[inline(always)] 28 | pub fn set_name(&mut self, name:&str) 29 | { 30 | self.name = name.to_string(); 31 | } 32 | 33 | #[inline(always)] 34 | pub fn set_curve(&mut self, name:&str, curve:AnimationCurve) 35 | { 36 | self.curves.insert(name.to_string(), curve); 37 | } 38 | 39 | #[inline(always)] 40 | pub fn empty(&self) -> bool 41 | { 42 | if self.curves.len() > 0 { true } else { false } 43 | } 44 | 45 | #[inline(always)] 46 | pub fn len(&self) -> usize 47 | { 48 | self.curves.len() 49 | } 50 | 51 | #[inline(always)] 52 | pub fn add_event(&mut self, method:T) -> &mut Self where T:Fn(&str, &Elem) + 'static 53 | { 54 | self.events.push(Box::new(method)); 55 | self 56 | } 57 | } 58 | 59 | impl AnimationClip where T:Animation + Copy 60 | { 61 | pub fn evaluate(&self, time:f32) 62 | { 63 | for (key, curve) in self.curves.iter() 64 | { 65 | let value = curve.evaluate(time); 66 | 67 | for event in self.events.iter() 68 | { 69 | event(key, &value) 70 | } 71 | } 72 | } 73 | } 74 | 75 | impl std::fmt::Debug for AnimationClip 76 | { 77 | fn fmt(&self, f:&mut std::fmt::Formatter) -> std::fmt::Result 78 | { 79 | write!(f, "{:?},{:?}", 80 | self.name, 81 | self.curves, 82 | ) 83 | } 84 | } -------------------------------------------------------------------------------- /src/animation/animations/curve.rs: -------------------------------------------------------------------------------- 1 | use super::super::keyframes::Keyframe; 2 | use super::super::core::{Interpolator, Animation, Evaluate}; 3 | use super::super::interpolators::{LinearInterpolator}; 4 | 5 | #[derive(Debug)] 6 | pub struct AnimationCurve 7 | { 8 | pub frames:Vec>, 9 | pub interpolator:Box, 10 | } 11 | 12 | impl AnimationCurve 13 | { 14 | pub fn new() -> Self 15 | { 16 | Self 17 | { 18 | frames:Vec::new(), 19 | interpolator:Box::new(LinearInterpolator::new()) 20 | } 21 | } 22 | 23 | pub fn new_with(frames:Vec>, interpolator:Option>) -> Self 24 | { 25 | Self 26 | { 27 | frames:frames, 28 | interpolator:interpolator.unwrap_or(Box::new(LinearInterpolator::new())) 29 | } 30 | } 31 | 32 | pub fn add(&mut self, key:Keyframe) 33 | { 34 | self.frames.push(key); 35 | } 36 | 37 | pub fn add_keyframe(&mut self, time:Time, value:Elem, interpolator:Option>) 38 | { 39 | self.frames.push(Keyframe::new(time, value, interpolator)); 40 | } 41 | } 42 | 43 | impl Evaluate for AnimationCurve where T:Animation + Copy 44 | { 45 | fn evaluate(&self, time:f32) -> T 46 | { 47 | let index = self.frames.binary_search_by( 48 | |key| 49 | { 50 | key.time.partial_cmp(&time).unwrap() 51 | } 52 | ); 53 | 54 | let x; 55 | match index 56 | { 57 | Ok(value) => { x = value } 58 | Err(value) => { x = value } 59 | } 60 | 61 | if x < self.frames.len() - 1 62 | { 63 | let anim0 = &self.frames[x]; 64 | let anim1 = &self.frames[x + 1]; 65 | let t = (time - anim0.time) / (anim1.time - anim0.time); 66 | 67 | if anim0.interpolator.is_some() 68 | { 69 | let interpolator = anim0.interpolator.as_ref().unwrap(); 70 | anim0.value.animation(&anim1.value, interpolator.interpolator(t)) 71 | } 72 | else 73 | { 74 | anim0.value.animation(&anim1.value, self.interpolator.interpolator(t)) 75 | } 76 | } 77 | else 78 | { 79 | if x >= self.frames.len() - 1 80 | { 81 | self.frames[self.frames.len() - 1].value 82 | } 83 | else 84 | { 85 | self.frames[0].value 86 | } 87 | } 88 | } 89 | } -------------------------------------------------------------------------------- /src/animation/animations/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod curve; 2 | pub mod clip; 3 | pub mod animator; 4 | 5 | pub use curve::*; 6 | pub use clip::*; 7 | pub use animator::*; -------------------------------------------------------------------------------- /src/animation/core/animation.rs: -------------------------------------------------------------------------------- 1 | pub trait Animation 2 | { 3 | fn animation(&self, rhs: &Self, t:T) -> Self; 4 | } 5 | 6 | impl Animation for f32 7 | { 8 | fn animation(&self, rhs: &Self, t:f32) -> Self 9 | { 10 | self * (1.0 - t) + rhs * t 11 | } 12 | } 13 | 14 | impl Animation for f64 15 | { 16 | fn animation(&self, rhs: &Self, t:f64) -> Self 17 | { 18 | self * (1.0 - t) + rhs * t 19 | } 20 | } -------------------------------------------------------------------------------- /src/animation/core/error.rs: -------------------------------------------------------------------------------- 1 | use std::error; 2 | use std::fmt; 3 | use std::io; 4 | 5 | pub struct Error(pub String); 6 | 7 | impl fmt::Display for Error 8 | { 9 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result 10 | { 11 | write!(f, "{}", self.0) 12 | } 13 | } 14 | 15 | impl fmt::Debug for Error 16 | { 17 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result 18 | { 19 | fmt::Display::fmt(self, f) 20 | } 21 | } 22 | 23 | impl std::error::Error for Error 24 | { 25 | fn description(&self) -> &str 26 | { 27 | "I/O Error" 28 | } 29 | 30 | fn cause(&self) -> Option<&error::Error> 31 | { 32 | Some(self) 33 | } 34 | } 35 | 36 | impl From for Error 37 | { 38 | fn from(err: io::Error) -> Error 39 | { 40 | if let Some(inner_err) = err.get_ref() { 41 | Error(format!("Inner error: {:?}", inner_err)) 42 | } else { 43 | Error(format!("No inner error")) 44 | } 45 | } 46 | } 47 | 48 | impl From for Error 49 | { 50 | fn from(_err: std::string::FromUtf8Error) -> Error 51 | { 52 | Error("Failed to convert the Utf8".to_string()) 53 | } 54 | } 55 | 56 | impl From for Error 57 | { 58 | fn from(_err: std::string::FromUtf16Error) -> Error 59 | { 60 | Error("Failed to convert the Utf16".to_string()) 61 | } 62 | } 63 | 64 | pub type Result = std::result::Result; -------------------------------------------------------------------------------- /src/animation/core/evaluate.rs: -------------------------------------------------------------------------------- 1 | pub trait Evaluate 2 | { 3 | fn evaluate(&self, time:Time) -> T; 4 | } -------------------------------------------------------------------------------- /src/animation/core/interpolator.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | 3 | pub trait Interpolator : Debug 4 | { 5 | fn interpolator(&self, t:T) -> T; 6 | } -------------------------------------------------------------------------------- /src/animation/core/loader.rs: -------------------------------------------------------------------------------- 1 | use super::super::{Result, Animator}; 2 | 3 | pub trait Loader 4 | { 5 | fn can_read(&self, buf:&[u8]) -> bool; 6 | 7 | fn do_load(&self, buf:&[u8]) -> Result; 8 | } -------------------------------------------------------------------------------- /src/animation/core/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod error; 2 | pub mod interpolator; 3 | pub mod animation; 4 | pub mod evaluate; 5 | pub mod loader; 6 | 7 | pub use error::*; 8 | pub use interpolator::*; 9 | pub use animation::*; 10 | pub use evaluate::*; 11 | pub use loader::*; -------------------------------------------------------------------------------- /src/animation/interpolators/fixed.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | use super::super::interpolator::*; 3 | 4 | #[derive(Debug, Copy, Clone)] 5 | pub struct FixedInterpolator 6 | { 7 | pub value:T 8 | } 9 | 10 | impl FixedInterpolator 11 | { 12 | pub fn new(value:T) -> Self 13 | { 14 | Self 15 | { 16 | value 17 | } 18 | } 19 | } 20 | 21 | impl Interpolator for FixedInterpolator where T:Debug + Copy 22 | { 23 | fn interpolator(&self, _:T) -> T 24 | { 25 | self.value 26 | } 27 | } -------------------------------------------------------------------------------- /src/animation/interpolators/linear.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | use super::super::interpolator::*; 3 | 4 | #[derive(Debug, Copy, Clone)] 5 | pub struct LinearInterpolator {} 6 | 7 | impl LinearInterpolator 8 | { 9 | pub fn new() -> Self 10 | { 11 | Self {} 12 | } 13 | } 14 | 15 | impl Interpolator for LinearInterpolator where T:Debug + Copy 16 | { 17 | fn interpolator(&self, t:T) -> T 18 | { 19 | t 20 | } 21 | } -------------------------------------------------------------------------------- /src/animation/interpolators/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod linear; 2 | pub mod fixed; 3 | pub mod path; 4 | 5 | pub use linear::*; 6 | pub use fixed::*; 7 | pub use path::*; -------------------------------------------------------------------------------- /src/animation/interpolators/path.rs: -------------------------------------------------------------------------------- 1 | use super::super::interpolator::*; 2 | 3 | #[derive(Debug, Copy, Clone)] 4 | pub struct PathInterpolator 5 | { 6 | pub xa:T, 7 | pub xb:T, 8 | pub ya:T, 9 | pub yb:T, 10 | } 11 | 12 | impl PathInterpolator 13 | { 14 | pub fn new(xa:T,xb:T,ya:T,yb:T) -> Self 15 | { 16 | Self 17 | { 18 | xa, 19 | xb, 20 | ya, 21 | yb 22 | } 23 | } 24 | } 25 | 26 | impl Interpolator for PathInterpolator 27 | { 28 | fn interpolator(&self, t:f32) -> f32 29 | { 30 | let mut min = 0.0; 31 | let mut max = 1.0; 32 | 33 | let mut ct = t; 34 | 35 | loop 36 | { 37 | let x11 = self.xa * ct; 38 | let x12 = self.xa + (self.xb - self.xa) * ct; 39 | let x13 = self.xb + (1.0 - self.xb) * ct; 40 | 41 | let x21 = x11 + (x12 - x11) * ct; 42 | let x22 = x12 + (x13 - x12) * ct; 43 | 44 | let x3 = x21 + (x22 - x21) * ct; 45 | 46 | if f32::abs(x3 - t) < 0.0001 47 | { 48 | let y11 = self.ya * ct; 49 | let y12 = self.ya + (self.yb - self.ya) * ct; 50 | let y13 = self.yb + (1.0 - self.yb) * ct; 51 | 52 | let y21 = y11 + (y12 - y11) * ct; 53 | let y22 = y12 + (y13 - y12) * ct; 54 | 55 | let y3 = y21 + (y22 - y21) * ct; 56 | 57 | return y3; 58 | } 59 | else if x3 < t 60 | { 61 | min = ct; 62 | } 63 | else 64 | { 65 | max = ct; 66 | } 67 | 68 | ct = (min + max) * 0.5; 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /src/animation/keyframes/keyframe.rs: -------------------------------------------------------------------------------- 1 | use std::boxed::Box; 2 | use super::super::core::{Interpolator}; 3 | 4 | #[derive(Debug, Default)] 5 | pub struct Keyframe 6 | { 7 | pub time:Time, 8 | pub value:Elem, 9 | pub interpolator:Option> 10 | } 11 | 12 | impl Keyframe 13 | { 14 | pub fn new(time:Time, value:Elem, interpolator:Option>) -> Self 15 | { 16 | Self 17 | { 18 | time:time, 19 | value:value, 20 | interpolator:interpolator 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/animation/keyframes/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod keyframe; 2 | 3 | pub use keyframe::*; -------------------------------------------------------------------------------- /src/animation/loaders/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod vmd; 2 | 3 | pub use vmd::*; -------------------------------------------------------------------------------- /src/animation/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod core; 2 | pub mod animations; 3 | pub mod interpolators; 4 | pub mod keyframes; 5 | pub mod loaders; 6 | 7 | pub use self::core::*; 8 | pub use self::animations::*; 9 | pub use self::interpolators::*; 10 | pub use self::keyframes::*; 11 | pub use self::loaders::*; 12 | 13 | use std::io::prelude::*; 14 | use std::fs::File; 15 | 16 | pub fn load_from_memory(buf:&[u8]) -> Result 17 | { 18 | let loaders = vec![Box::new(VMDLoader::new())]; 19 | 20 | for loader in loaders 21 | { 22 | if loader.can_read(buf) 23 | { 24 | return Ok(loader.do_load(buf)?); 25 | } 26 | } 27 | 28 | Err(Error("Not supported yet".to_string())) 29 | } 30 | 31 | pub fn load_from_buf(mut r:R) -> Result 32 | { 33 | load_from_memory(r.fill_buf()?) 34 | } 35 | 36 | pub fn open>(path:P) -> Result 37 | { 38 | let mut buffer = Vec::new(); 39 | File::open(path)?.read_to_end(&mut buffer)?; 40 | load_from_memory(&buffer) 41 | } -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_upper_case_globals)] 2 | 3 | #[macro_use] 4 | extern crate serde_derive; 5 | 6 | #[macro_use] 7 | #[cfg(feature = "webgl")] 8 | #[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))] 9 | extern crate stdweb; 10 | 11 | #[macro_use] 12 | #[cfg(feature = "webgl")] 13 | #[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))] 14 | extern crate stdweb_derive; 15 | 16 | #[macro_use] 17 | pub mod math; 18 | pub mod animation; 19 | pub mod models; 20 | pub mod scene; 21 | pub mod renderer; 22 | 23 | pub use self::animation::*; 24 | pub use self::math::*; 25 | pub use self::models::*; 26 | pub use self::renderer::*; 27 | pub use self::scene::*; -------------------------------------------------------------------------------- /src/math/consts.rs: -------------------------------------------------------------------------------- 1 | pub trait One: Sized { fn one() -> Self; } 2 | pub trait Zero: Sized { fn zero() -> Self; } 3 | pub trait Two: Sized { fn two() -> Self; } 4 | pub trait UnitX: Sized { fn unit_x() -> Self; } 5 | pub trait UnitY: Sized { fn unit_y() -> Self; } 6 | pub trait UnitZ: Sized { fn unit_z() -> Self; } 7 | pub trait UnitW: Sized { fn unit_w() -> Self; } 8 | pub trait OneHalf: Sized { fn onehalf() -> Self; } 9 | pub trait Pi: Sized { fn pi() -> Self; } 10 | pub trait Pi2: Sized { fn pi2() -> Self; } 11 | pub trait Pi4: Sized { fn pi4() -> Self; } 12 | pub trait Pi8: Sized { fn pi8() -> Self; } 13 | pub trait PiByC180: Sized { fn pi_by_c180() -> Self; } 14 | pub trait C180ByPi: Sized { fn c180_by_pi() -> Self; } 15 | pub trait Epsilon: Sized { fn epsilon() -> Self; } 16 | 17 | impl One for f32 { #[inline(always)] fn one() -> Self { 1.0_f32 } } 18 | impl Zero for f32 { #[inline(always)] fn zero() -> Self { 0.0_f32 } } 19 | impl Two for f32 { #[inline(always)] fn two() -> Self { 2.0_f32 } } 20 | impl OneHalf for f32 { #[inline(always)] fn onehalf() -> Self { 0.5_f32 } } 21 | impl Pi for f32 { #[inline(always)] fn pi() -> Self { 3.14159265359_f32 } } 22 | impl Pi2 for f32 { #[inline(always)] fn pi2() -> Self { Self::pi() * 2.0_f32 } } 23 | impl Pi4 for f32 { #[inline(always)] fn pi4() -> Self { Self::pi() * 4.0_f32 } } 24 | impl Pi8 for f32 { #[inline(always)] fn pi8() -> Self { Self::pi() * 8.0_f32 } } 25 | impl PiByC180 for f32 { #[inline(always)] fn pi_by_c180() -> Self { 3.14159265359_f32 / 180.0_f32 } } 26 | impl C180ByPi for f32 { #[inline(always)] fn c180_by_pi() -> Self { 180.0_f32 / 3.14159265359_f32 } } 27 | impl Epsilon for f32 { #[inline(always)] fn epsilon() -> Self { 0.00001_f32 } } 28 | 29 | impl One for f64 { #[inline(always)] fn one() -> Self { 1.0_f64 } } 30 | impl Zero for f64 { #[inline(always)] fn zero() -> Self { 0.0_f64 } } 31 | impl Two for f64 { #[inline(always)] fn two() -> Self { 2.0_f64 } } 32 | impl OneHalf for f64 { #[inline(always)] fn onehalf() -> Self { 0.5_f64 } } 33 | impl Pi for f64 { #[inline(always)] fn pi() -> Self { 3.141592653589793238462643383279502884197169399375105820974944592307816406286_f64 } } 34 | impl Pi2 for f64 { #[inline(always)] fn pi2() -> Self { Self::pi() * 2.0_f64 } } 35 | impl Pi4 for f64 { #[inline(always)] fn pi4() -> Self { Self::pi() * 4.0_f64 } } 36 | impl Pi8 for f64 { #[inline(always)] fn pi8() -> Self { Self::pi() * 8.0_f64 } } 37 | impl PiByC180 for f64 { #[inline(always)] fn pi_by_c180() -> Self { Self::pi() / 180.0_f64 } } 38 | impl C180ByPi for f64 { #[inline(always)] fn c180_by_pi() -> Self { 180.0_f64 / Self::pi() } } 39 | impl Epsilon for f64 { #[inline(always)] fn epsilon() -> Self { 0.00000001_f64 } } -------------------------------------------------------------------------------- /src/math/dual.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::fmt::Debug; 3 | use std::ops::{Add, Sub, Mul, Div, Neg}; 4 | use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign}; 5 | use super::vec::{Vec, Math, Lerp, Slerp}; 6 | use super::quat::Quat; 7 | use super::vec3::Vec3; 8 | use super::consts::{Zero, One}; 9 | 10 | // http://wscg.zcu.cz/wscg2012/short/a29-full.pdf 11 | #[repr(C)] 12 | #[derive(Debug, Copy, Clone, Default, Hash, Eq, PartialEq)] 13 | pub struct Dual 14 | { 15 | pub real:Quat, 16 | pub dual:Quat, 17 | } 18 | 19 | impl Neg for Dual where T:Neg 20 | { 21 | type Output = Self; 22 | 23 | fn neg(self) -> Self 24 | { 25 | Self 26 | { 27 | real:self.real, 28 | dual:self.dual, 29 | } 30 | } 31 | } 32 | 33 | impl Add for Dual where T:Add 34 | { 35 | type Output = Self; 36 | 37 | fn add(self, other: Self) -> Self 38 | { 39 | Self 40 | { 41 | real:self.real + other.real, 42 | dual:self.dual + other.dual, 43 | } 44 | } 45 | } 46 | 47 | impl Sub for Dual where T:Sub 48 | { 49 | type Output = Self; 50 | 51 | fn sub(self, other: Self) -> Self 52 | { 53 | Self 54 | { 55 | real:self.real - other.real, 56 | dual:self.dual - other.dual, 57 | } 58 | } 59 | } 60 | 61 | impl Mul for Dual where T:Mul + Add + Copy 62 | { 63 | type Output = Self; 64 | 65 | fn mul(self, other: Self) -> Self 66 | { 67 | Self 68 | { 69 | real:self.real * other.real, 70 | dual:(self.real * other.dual) + (self.dual * other.real), 71 | } 72 | } 73 | } 74 | 75 | impl Mul for Dual where T:Mul + Copy 76 | { 77 | type Output = Self; 78 | 79 | fn mul(self, s: T) -> Self 80 | { 81 | Self 82 | { 83 | real:self.real * s, 84 | dual:self.dual * s, 85 | } 86 | } 87 | } 88 | 89 | impl Div for Dual where T:Div + Copy 90 | { 91 | type Output = Self; 92 | 93 | fn div(self, s: T) -> Self 94 | { 95 | Self 96 | { 97 | real:self.real / s, 98 | dual:self.dual / s, 99 | } 100 | } 101 | } 102 | 103 | impl AddAssign for Dual where T: AddAssign 104 | { 105 | fn add_assign(&mut self, other: Self) 106 | { 107 | self.real += other.real; 108 | self.dual += other.dual; 109 | } 110 | } 111 | 112 | impl SubAssign for Dual where T: SubAssign 113 | { 114 | fn sub_assign(&mut self, other: Self) 115 | { 116 | self.real -= other.real; 117 | self.dual -= other.dual; 118 | } 119 | } 120 | 121 | impl MulAssign for Dual where T: MulAssign + Copy 122 | { 123 | fn mul_assign(&mut self, s: T) 124 | { 125 | self.real *= s; 126 | self.dual *= s; 127 | } 128 | } 129 | 130 | impl<'a, T> MulAssign<&'a T> for Dual where T:MulAssign + Copy 131 | { 132 | fn mul_assign(&mut self, s: &'a T) 133 | { 134 | self.real *= s; 135 | self.dual *= s; 136 | } 137 | } 138 | 139 | impl DivAssign for Dual where T: DivAssign + Copy 140 | { 141 | fn div_assign(&mut self, s: T) 142 | { 143 | self.real /= s; 144 | self.dual /= s; 145 | } 146 | } 147 | 148 | impl<'a, T> DivAssign<&'a T> for Dual where T:DivAssign + Copy 149 | { 150 | fn div_assign(&mut self, s: &'a T) 151 | { 152 | self.real /= s; 153 | self.dual /= s; 154 | } 155 | } 156 | 157 | impl Dual where T:Copy 158 | { 159 | /// Creates a new Dual from two quaternions 160 | pub fn new(real:Quat, dual:Quat) -> Self 161 | { 162 | Self 163 | { 164 | real:real, 165 | dual:dual 166 | } 167 | } 168 | } 169 | 170 | impl Dual where T:Vec + Math 171 | { 172 | pub fn from_transform(rotation:Quat, t:Vec3) -> Self 173 | { 174 | Self 175 | { 176 | real:rotation, 177 | dual:Quat::new(t.x,t.y,t.z,T::zero()) * rotation * T::onehalf() 178 | } 179 | } 180 | 181 | pub fn dot(&self, b: Self) -> T 182 | { 183 | return self.real.dot(b.real); 184 | } 185 | 186 | pub fn length2(&self) -> T 187 | { 188 | return self.dot(*self); 189 | } 190 | 191 | pub fn length(&self) -> T 192 | { 193 | return self.length2().sqrt(); 194 | } 195 | 196 | pub fn normalize(&self) -> Self 197 | { 198 | let mag_sq = self.real.length2(); 199 | if mag_sq.gt(T::zero()) 200 | { 201 | let inv_sqrt = T::one() / mag_sq.sqrt(); 202 | return *self * inv_sqrt; 203 | } 204 | 205 | return *self; 206 | } 207 | 208 | pub fn rotation(&self) -> Quat 209 | { 210 | self.real 211 | } 212 | 213 | pub fn translate(&self) -> Vec3 214 | { 215 | let t = self.dual * T::two() * self.real.conj(); 216 | Vec3::new(t.x, t.y, t.z) 217 | } 218 | 219 | pub fn conj(&self) -> Self 220 | { 221 | Self 222 | { 223 | real: self.real.conj(), 224 | dual: self.dual.conj(), 225 | } 226 | } 227 | 228 | pub fn conjugate(&self) -> Self 229 | { 230 | Self 231 | { 232 | real: self.real.conjugate(), 233 | dual: self.dual.conjugate(), 234 | } 235 | } 236 | 237 | pub fn inverse(&self) -> Self 238 | { 239 | self.conjugate() 240 | } 241 | } 242 | 243 | impl Lerp for Dual where T: Copy + One + Mul + Add + Sub 244 | { 245 | #[inline(always)] 246 | fn lerp(self, b: Self, t: T) -> Self 247 | { 248 | return self*(T::one() - t) + b*t; 249 | } 250 | } 251 | 252 | // http://dcgi.felk.cvut.cz/home/zara/papers/TCD-CS-2006-46.pdf 253 | impl Slerp for Dual where T: Vec + Math 254 | { 255 | fn slerp(self, q2: Self, factor: T) -> Self 256 | { 257 | let dot = self.dot(q2); 258 | 259 | let s = T::one() - factor; 260 | let t = if dot.gt(T::zero()) { factor } else { -factor }; 261 | let q = self * s + q2 * t; 262 | 263 | q.normalize() 264 | } 265 | } 266 | 267 | impl Zero for Dual where T:Zero 268 | { 269 | #[inline(always)] 270 | fn zero() -> Self 271 | { 272 | Self 273 | { 274 | real:Quat::zero(), 275 | dual:Quat::zero(), 276 | } 277 | } 278 | } 279 | 280 | impl One for Dual where T:One 281 | { 282 | #[inline(always)] 283 | fn one() -> Self 284 | { 285 | Self 286 | { 287 | real:Quat::one(), 288 | dual:Quat::one(), 289 | } 290 | } 291 | } 292 | 293 | impl fmt::Display for Dual where T:Debug 294 | { 295 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result 296 | { 297 | write!(f, "({:?}, {:?})", self.real, self.dual) 298 | } 299 | } 300 | 301 | impl AsRef> for Dual 302 | { 303 | fn as_ref(&self) -> &Dual 304 | { 305 | self 306 | } 307 | } 308 | 309 | impl AsMut> for Dual 310 | { 311 | fn as_mut(&mut self) -> &mut Dual 312 | { 313 | self 314 | } 315 | } -------------------------------------------------------------------------------- /src/math/mat2.rs: -------------------------------------------------------------------------------- 1 | use std::ops::{Add, Sub, Mul}; 2 | use super::vec::{Vec, Math}; 3 | use super::vec2::Vec2; 4 | use super::vec3::Vec3; 5 | use super::consts::{Zero, One}; 6 | 7 | #[repr(C)] 8 | #[derive(Debug, Copy, Clone, Default, Hash, Eq, PartialEq)] 9 | pub struct Mat2 10 | { 11 | pub a1:T, pub a2:T, 12 | pub b1:T, pub b2:T, 13 | } 14 | 15 | impl Add for Mat2 where T:Add 16 | { 17 | type Output = Self; 18 | 19 | fn add(self, b: Self) -> Self 20 | { 21 | Mat2 22 | { 23 | a1:self.a1 + b.a1, 24 | a2:self.a2 + b.a2, 25 | b1:self.b1 + b.b1, 26 | b2:self.b2 + b.b2, 27 | } 28 | } 29 | } 30 | 31 | impl Sub for Mat2 where T:Sub 32 | { 33 | type Output = Self; 34 | 35 | fn sub(self, b: Self) -> Self 36 | { 37 | Mat2 38 | { 39 | a1:self.a1 - b.a1, 40 | a2:self.a2 - b.a2, 41 | b1:self.b1 - b.b1, 42 | b2:self.b2 - b.b2, 43 | } 44 | } 45 | } 46 | 47 | impl Mul for Mat2 where T:Copy + Mul + Add 48 | { 49 | type Output = Self; 50 | 51 | fn mul(self, b: Self) -> Self 52 | { 53 | let a = self; 54 | 55 | Mat2 56 | { 57 | a1 : a.a1 * b.a1 + a.b1 * b.a2, 58 | a2 : a.a2 * b.a1 + a.b2 * b.a2, 59 | b1 : a.a1 * b.b1 + a.b1 * b.b2, 60 | b2 : a.a2 * b.b1 + a.b2 * b.b2 61 | } 62 | } 63 | } 64 | 65 | impl Mat2 where T:Copy 66 | { 67 | pub fn new(m11:T, m12:T, m21:T, m22:T) -> Self 68 | { 69 | Self 70 | { 71 | a1:m11, a2:m12, 72 | b1:m21, b2:m22, 73 | } 74 | } 75 | 76 | pub fn right(&self) -> Vec2 77 | { 78 | Vec2::new(self.a1, self.a2) 79 | } 80 | 81 | pub fn up(&self) -> Vec2 82 | { 83 | Vec2::new(self.b1, self.b2) 84 | } 85 | 86 | pub fn as_ptr(&self) -> *const T 87 | { 88 | &self.a1 89 | } 90 | 91 | pub fn to_array(&self) -> [T; 4] 92 | { 93 | [ 94 | self.a1, self.a2, 95 | self.b1, self.b2, 96 | ] 97 | } 98 | } 99 | 100 | impl Mat2 where T:Vec + Math 101 | { 102 | pub fn rotate_x(theta:T) -> Self 103 | { 104 | let (_s,c) = theta.sincos(); 105 | Mat2::new(T::one(), T::zero(), T::zero(), c) 106 | } 107 | 108 | pub fn rotate_y(theta:T) -> Self 109 | { 110 | let (_s,c) = theta.sincos(); 111 | Mat2::new(c, T::zero(), T::zero(), T::one()) 112 | } 113 | 114 | pub fn rotate_z(theta:T) -> Self 115 | { 116 | let (s,c) = theta.sincos(); 117 | Mat2::new(c, -s, s, c) 118 | } 119 | 120 | pub fn rotate(axis:Vec3, theta:T) -> Self 121 | { 122 | let (s,c) = theta.sincos(); 123 | 124 | let x = axis.x; 125 | let y = axis.y; 126 | let z = axis.z; 127 | 128 | let t = T::one() - c; 129 | let tx = t * x; 130 | let ty = t * y; 131 | 132 | let a1 = tx * x + c; 133 | let a2 = tx * y + s * z; 134 | 135 | let b1 = tx * y - s * z; 136 | let b2 = ty * y + c; 137 | 138 | Mat2 139 | { 140 | a1:a1, a2:a2, 141 | b1:b1, b2:b2 142 | } 143 | } 144 | 145 | pub fn scale(x:T, y:T) -> Self 146 | { 147 | Mat2 148 | { 149 | a1:x, a2:T::zero(), 150 | b1:T::zero(), b2:y 151 | } 152 | } 153 | 154 | pub fn transpose(&self) -> Self 155 | { 156 | let (a1, a2) = (self.a1, self.b1); 157 | let (b1, b2) = (self.a2, self.b2); 158 | 159 | Mat2 160 | { 161 | a1:a1, a2:a2, 162 | b1:b1, b2:b2 163 | } 164 | } 165 | } 166 | 167 | impl Zero for Mat2 168 | { 169 | #[inline(always)] 170 | fn zero() -> Self 171 | { 172 | Mat2 173 | { 174 | a1:T::zero(), a2:T::zero(), 175 | b1:T::zero(), b2:T::zero() 176 | } 177 | } 178 | } 179 | 180 | impl One for Mat2 181 | { 182 | #[inline(always)] 183 | fn one() -> Self 184 | { 185 | Mat2 186 | { 187 | a1:T::one(), a2:T::zero(), 188 | b1:T::zero(), b2:T::one() 189 | } 190 | } 191 | } 192 | 193 | impl From<[T;4]> for Mat2 where T:Copy 194 | { 195 | fn from(v:[T;4]) -> Self 196 | { 197 | Self 198 | { 199 | a1:v[0],a2:v[1], 200 | b1:v[2],b2:v[3], 201 | } 202 | } 203 | } 204 | 205 | impl From<(T,T,T,T)> for Mat2 where T:Copy 206 | { 207 | fn from(v:(T,T,T,T)) -> Self 208 | { 209 | Self 210 | { 211 | a1:v.0, 212 | a2:v.1, 213 | b1:v.2, 214 | b2:v.3, 215 | } 216 | } 217 | } 218 | 219 | impl AsRef> for Mat2 220 | { 221 | fn as_ref(&self) -> &Mat2 222 | { 223 | self 224 | } 225 | } 226 | 227 | impl AsMut> for Mat2 228 | { 229 | fn as_mut(&mut self) -> &mut Mat2 230 | { 231 | self 232 | } 233 | } -------------------------------------------------------------------------------- /src/math/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod vec; 2 | pub mod vec2; 3 | pub mod vec3; 4 | pub mod vec4; 5 | pub mod mat2; 6 | pub mod mat3; 7 | pub mod mat4; 8 | pub mod quat; 9 | pub mod dual; 10 | pub mod type_size; 11 | pub mod consts; 12 | pub mod ser; 13 | 14 | pub use self::vec2::*; 15 | pub use self::vec3::*; 16 | pub use self::vec4::*; 17 | pub use self::mat2::*; 18 | pub use self::mat3::*; 19 | pub use self::mat4::*; 20 | pub use self::quat::*; 21 | pub use self::dual::*; 22 | pub use self::consts::*; 23 | pub use self::ser::*; 24 | 25 | #[allow(non_camel_case_types)] pub type i8_1 = i8; 26 | #[allow(non_camel_case_types)] pub type i8_2 = Vec2; 27 | #[allow(non_camel_case_types)] pub type i8_3 = Vec3; 28 | #[allow(non_camel_case_types)] pub type i8_4 = Vec4; 29 | 30 | #[allow(non_camel_case_types)] pub type i16_1 = i16; 31 | #[allow(non_camel_case_types)] pub type i16_2 = Vec2; 32 | #[allow(non_camel_case_types)] pub type i16_3 = Vec3; 33 | #[allow(non_camel_case_types)] pub type i16_4 = Vec4; 34 | 35 | #[allow(non_camel_case_types)] pub type i32_1 = i32; 36 | #[allow(non_camel_case_types)] pub type i32_2 = Vec2; 37 | #[allow(non_camel_case_types)] pub type i32_3 = Vec3; 38 | #[allow(non_camel_case_types)] pub type i32_4 = Vec4; 39 | 40 | #[allow(non_camel_case_types)] pub type u8_1 = u8; 41 | #[allow(non_camel_case_types)] pub type u8_2 = Vec2; 42 | #[allow(non_camel_case_types)] pub type u8_3 = Vec3; 43 | #[allow(non_camel_case_types)] pub type u8_4 = Vec4; 44 | 45 | #[allow(non_camel_case_types)] pub type u16_1 = u16; 46 | #[allow(non_camel_case_types)] pub type u16_2 = Vec2; 47 | #[allow(non_camel_case_types)] pub type u16_3 = Vec3; 48 | #[allow(non_camel_case_types)] pub type u16_4 = Vec4; 49 | 50 | #[allow(non_camel_case_types)] pub type u32_1 = u32; 51 | #[allow(non_camel_case_types)] pub type u32_2 = Vec2; 52 | #[allow(non_camel_case_types)] pub type u32_3 = Vec3; 53 | #[allow(non_camel_case_types)] pub type u32_4 = Vec4; 54 | 55 | #[allow(non_camel_case_types)] pub type float1 = f32; 56 | #[allow(non_camel_case_types)] pub type float2 = Vec2; 57 | #[allow(non_camel_case_types)] pub type float3 = Vec3; 58 | #[allow(non_camel_case_types)] pub type float4 = Vec4; 59 | 60 | #[allow(non_camel_case_types)] pub type double1 = f64; 61 | #[allow(non_camel_case_types)] pub type double2 = Vec2; 62 | #[allow(non_camel_case_types)] pub type double3 = Vec3; 63 | #[allow(non_camel_case_types)] pub type double4 = Vec4; 64 | 65 | #[allow(non_camel_case_types)] pub type float2x2 = Mat2; 66 | #[allow(non_camel_case_types)] pub type float3x3 = Mat3; 67 | #[allow(non_camel_case_types)] pub type float4x4 = Mat4; 68 | 69 | #[allow(non_camel_case_types)] pub type double2x2 = Mat2; 70 | #[allow(non_camel_case_types)] pub type double3x3 = Mat3; 71 | #[allow(non_camel_case_types)] pub type double4x4 = Mat4; 72 | 73 | #[allow(non_camel_case_types)] pub type Quaternion = Quat; 74 | #[allow(non_camel_case_types)] pub type DualQuaternion = Dual; 75 | 76 | #[allow(non_camel_case_types)] pub type float1s = Vec; 77 | #[allow(non_camel_case_types)] pub type float2s = Vec>; 78 | #[allow(non_camel_case_types)] pub type float3s = Vec>; 79 | #[allow(non_camel_case_types)] pub type float4s = Vec>; 80 | 81 | #[allow(non_camel_case_types)] pub type double1s = Vec; 82 | #[allow(non_camel_case_types)] pub type double2s = Vec>; 83 | #[allow(non_camel_case_types)] pub type double3s = Vec>; 84 | #[allow(non_camel_case_types)] pub type double4s = Vec>; 85 | 86 | #[allow(non_camel_case_types)] pub type float2x2s = Vec>; 87 | #[allow(non_camel_case_types)] pub type float3x3s = Vec>; 88 | #[allow(non_camel_case_types)] pub type float4x4s = Vec>; 89 | 90 | #[allow(non_camel_case_types)] pub type double2x2s = Vec>; 91 | #[allow(non_camel_case_types)] pub type double3x3s = Vec>; 92 | #[allow(non_camel_case_types)] pub type double4x4s = Vec>; 93 | 94 | #[macro_export] macro_rules! float 95 | { 96 | ($x:expr,$y:expr) => { float2::new($x,$y) }; 97 | ($x:expr,$y:expr,$z:expr) => { float3::new($x,$y,$z) }; 98 | ($x:expr,$y:expr,$z:expr,$w:expr) => { float4::new($x,$y,$z,$w) }; 99 | ($m11:expr, $m12:expr, $m13:expr, 100 | $m21:expr, $m22:expr, $m23:expr, 101 | $m31:expr, $m32:expr, $m33:expr) => 102 | { 103 | float3x3::new( 104 | $m11, $m12, $m13, 105 | $m21, $m22, $m23, 106 | $m31, $m32, $m33 107 | ) 108 | }; 109 | ($m11:expr, $m12:expr, $m13:expr, $m14:expr, 110 | $m21:expr, $m22:expr, $m23:expr, $m24:expr, 111 | $m31:expr, $m32:expr, $m33:expr, $m34:expr, 112 | $m41:expr, $m42:expr, $m43:expr, $m44:expr) => 113 | { 114 | float4x4::new( 115 | $m11, $m12, $m13, $m14, 116 | $m21, $m22, $m23, $m24, 117 | $m31, $m32, $m33, $m34, 118 | $m41, $m42, $m43, $m44, 119 | ) 120 | }; 121 | } -------------------------------------------------------------------------------- /src/math/type_size.rs: -------------------------------------------------------------------------------- 1 | use super::vec2::*; 2 | use super::vec3::*; 3 | use super::vec4::*; 4 | use super::mat2::*; 5 | use super::mat3::*; 6 | use super::mat4::*; 7 | 8 | pub trait TypeSize { 9 | fn type_size() -> usize { 10 | return std::mem::size_of::(); 11 | } 12 | } 13 | 14 | impl TypeSize for i8 {} 15 | impl TypeSize for i16 {} 16 | impl TypeSize for i32 {} 17 | impl TypeSize for i64 {} 18 | impl TypeSize for isize {} 19 | impl TypeSize for u8 {} 20 | impl TypeSize for u16 {} 21 | impl TypeSize for u32 {} 22 | impl TypeSize for u64 {} 23 | impl TypeSize for usize {} 24 | impl TypeSize for f32 {} 25 | impl TypeSize for f64 {} 26 | impl TypeSize for char {} 27 | impl TypeSize for bool {} 28 | impl TypeSize<()> for () {} 29 | impl TypeSize> for Vec2 {} 30 | impl TypeSize> for Vec3 {} 31 | impl TypeSize> for Vec4 {} 32 | impl TypeSize> for Mat2 {} 33 | impl TypeSize> for Mat3 {} 34 | impl TypeSize> for Mat4 {} -------------------------------------------------------------------------------- /src/models/core/bone.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, Clone, Serialize, Deserialize)] 2 | pub struct Bone 3 | { 4 | pub name:String, 5 | pub parent:Option, 6 | pub position:(f32,f32,f32), 7 | pub rotation:(f32,f32,f32), 8 | } 9 | 10 | impl Bone 11 | { 12 | pub fn new() -> Self 13 | { 14 | Self 15 | { 16 | name:String::new(), 17 | parent:None, 18 | position:(0.0,0.0,0.0), 19 | rotation:(0.0,0.0,0.0), 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/models/core/error.rs: -------------------------------------------------------------------------------- 1 | use std::error; 2 | use std::fmt; 3 | use std::io; 4 | 5 | pub struct Error(pub String); 6 | 7 | impl fmt::Display for Error 8 | { 9 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result 10 | { 11 | write!(f, "{}", self.0) 12 | } 13 | } 14 | 15 | impl fmt::Debug for Error 16 | { 17 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result 18 | { 19 | fmt::Display::fmt(self, f) 20 | } 21 | } 22 | 23 | impl std::error::Error for Error 24 | { 25 | fn description(&self) -> &str 26 | { 27 | "I/O Error" 28 | } 29 | 30 | fn cause(&self) -> Option<&error::Error> 31 | { 32 | Some(self) 33 | } 34 | } 35 | 36 | impl From for Error 37 | { 38 | fn from(err: io::Error) -> Error 39 | { 40 | if let Some(inner_err) = err.get_ref() { 41 | Error(format!("Inner error: {:?}", inner_err)) 42 | } else { 43 | Error(format!("No inner error")) 44 | } 45 | } 46 | } 47 | 48 | impl From for Error 49 | { 50 | fn from(_err: std::string::FromUtf8Error) -> Error 51 | { 52 | Error("Failed to convert the Utf8".to_string()) 53 | } 54 | } 55 | 56 | impl From for Error 57 | { 58 | fn from(_err: std::string::FromUtf16Error) -> Error 59 | { 60 | Error("Failed to convert the Utf16".to_string()) 61 | } 62 | } 63 | 64 | pub type Result = std::result::Result; -------------------------------------------------------------------------------- /src/models/core/loader.rs: -------------------------------------------------------------------------------- 1 | use super::{Model, Result}; 2 | 3 | pub trait Loader 4 | { 5 | fn can_read(&self, buf:&[u8]) -> bool; 6 | 7 | fn do_load(&self, buf:&[u8]) -> Result; 8 | } -------------------------------------------------------------------------------- /src/models/core/material.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | #[derive(Debug, Clone, Serialize, Deserialize)] 4 | pub struct Material 5 | { 6 | pub name: String, 7 | pub ambient: [f32; 3], 8 | pub diffuse: [f32; 3], 9 | pub specular: [f32; 3], 10 | pub shininess: f32, 11 | pub dissolve: f32, 12 | pub optical_density: f32, 13 | pub ambient_texture: Option, 14 | pub diffuse_texture: Option, 15 | pub specular_texture: Option, 16 | pub normal_texture: Option, 17 | pub dissolve_texture: Option, 18 | pub illumination_model: Option, 19 | pub unknown_param: HashMap, 20 | } 21 | 22 | impl Material 23 | { 24 | pub fn new() -> Self 25 | { 26 | Self 27 | { 28 | name: String::new(), 29 | ambient: [0.0; 3], 30 | diffuse: [0.0; 3], 31 | specular: [0.0; 3], 32 | shininess: 0.0, 33 | dissolve: 1.0, 34 | optical_density: 1.0, 35 | ambient_texture: None, 36 | diffuse_texture: None, 37 | specular_texture: None, 38 | normal_texture: None, 39 | dissolve_texture: None, 40 | illumination_model: None, 41 | unknown_param: HashMap::new(), 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/models/core/mesh.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, Clone, Serialize, Deserialize)] 2 | pub struct VertexWeight 3 | { 4 | pub bone:[u16;4], 5 | pub weight:[f32;4], 6 | } 7 | 8 | impl VertexWeight 9 | { 10 | pub fn new() -> Self 11 | { 12 | Self 13 | { 14 | bone:[0,0,0,0], 15 | weight:[0.0,0.0,0.0,0.0] 16 | } 17 | } 18 | } 19 | 20 | #[derive(Debug, Clone, Serialize, Deserialize)] 21 | pub struct Mesh 22 | { 23 | pub name:String, 24 | pub material_id:Option, 25 | pub positions:Vec, 26 | pub normals:Vec, 27 | pub texcoords:Vec, 28 | pub indices:Vec, 29 | pub weights:Vec, 30 | } 31 | 32 | impl Mesh 33 | { 34 | pub fn new() -> Self 35 | { 36 | Self 37 | { 38 | name:String::new(), 39 | material_id:None, 40 | positions:Vec::new(), 41 | normals:Vec::new(), 42 | texcoords:Vec::new(), 43 | indices:Vec::new(), 44 | weights:Vec::new(), 45 | } 46 | } 47 | 48 | pub fn with_capacity(vertex:usize, index:usize) -> Self 49 | { 50 | Self 51 | { 52 | name: String::new(), 53 | positions:Vec::with_capacity(vertex * 3), 54 | normals:Vec::with_capacity(vertex * 3), 55 | texcoords:Vec::with_capacity(vertex * 2), 56 | indices:Vec::with_capacity(index), 57 | weights:Vec::new(), 58 | material_id:None, 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /src/models/core/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod bone; 2 | pub mod error; 3 | pub mod material; 4 | pub mod mesh; 5 | pub mod solver; 6 | pub mod model; 7 | pub mod loader; 8 | 9 | pub use self::bone::*; 10 | pub use self::error::*; 11 | pub use self::material::*; 12 | pub use self::mesh::*; 13 | pub use self::solver::*; 14 | pub use self::model::*; 15 | pub use self::loader::*; -------------------------------------------------------------------------------- /src/models/core/model.rs: -------------------------------------------------------------------------------- 1 | use super::{Mesh, Material, Bone, Solver}; 2 | 3 | #[derive(Debug, Clone, Serialize, Deserialize)] 4 | pub struct Model 5 | { 6 | pub name: String, 7 | pub meshes: Vec, 8 | pub materials: Vec, 9 | pub textures: Vec, 10 | pub bones: Vec, 11 | pub iks: Vec, 12 | } 13 | 14 | impl Model 15 | { 16 | pub fn new() -> Self 17 | { 18 | Self 19 | { 20 | name: String::new(), 21 | meshes: Vec::new(), 22 | materials: Vec::new(), 23 | textures: Vec::new(), 24 | bones:Vec::new(), 25 | iks:Vec::new(), 26 | } 27 | } 28 | 29 | pub fn add_mesh(&mut self, mesh:Mesh) -> &mut Self 30 | { 31 | self.meshes.push(mesh); 32 | self 33 | } 34 | 35 | pub fn add_material(&mut self, material:Material) -> &mut Self 36 | { 37 | self.materials.push(material); 38 | self 39 | } 40 | 41 | pub fn add_texture(&mut self, texture:String) -> &mut Self 42 | { 43 | self.textures.push(texture); 44 | self 45 | } 46 | 47 | pub fn add_bone(&mut self, bone:Bone) -> &mut Self 48 | { 49 | self.bones.push(bone); 50 | self 51 | } 52 | 53 | pub fn add_ik(&mut self, ik:Solver) -> &mut Self 54 | { 55 | self.iks.push(ik); 56 | self 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/models/core/solver.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, Clone, Serialize, Deserialize)] 2 | pub struct BoneLink 3 | { 4 | pub bone:i16, 5 | pub rotate_limited:bool, 6 | pub minimum_radian:(f32,f32,f32), 7 | pub maximum_radian:(f32,f32,f32), 8 | } 9 | 10 | impl BoneLink 11 | { 12 | pub fn new() -> Self 13 | { 14 | Self 15 | { 16 | bone:0, 17 | rotate_limited:false, 18 | minimum_radian:(0.0,0.0,0.0), 19 | maximum_radian:(0.0,0.0,0.0), 20 | } 21 | } 22 | } 23 | 24 | #[derive(Debug, Clone, Serialize, Deserialize)] 25 | pub struct Solver 26 | { 27 | pub bone:i16, 28 | pub target_bone:i16, 29 | pub loop_count:u32, 30 | pub limited_radian:f32, 31 | pub chain_length:u32, 32 | pub links:Vec 33 | } 34 | 35 | impl Solver 36 | { 37 | pub fn new() -> Self 38 | { 39 | Self 40 | { 41 | bone:0, 42 | target_bone:0, 43 | loop_count:0, 44 | limited_radian:0.0, 45 | chain_length:0, 46 | links:Vec::new(), 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/models/loaders/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod pmx; 2 | pub mod pmd; 3 | 4 | pub use self::pmx::*; 5 | pub use self::pmd::*; -------------------------------------------------------------------------------- /src/models/loaders/pmd.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octoon/engine/1beee57fb773e940c4e4bf4ce6b1a3eeba151482/src/models/loaders/pmd.rs -------------------------------------------------------------------------------- /src/models/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod core; 2 | pub mod loaders; 3 | 4 | pub use self::core::*; 5 | pub use self::loaders::*; 6 | 7 | use std::io::prelude::*; 8 | use std::fs::File; 9 | 10 | pub fn load_from_memory(buf:&[u8]) -> Result 11 | { 12 | let loaders = vec![Box::new(PMXLoader::new())]; 13 | 14 | for loader in loaders 15 | { 16 | if loader.can_read(buf) 17 | { 18 | return Ok(loader.do_load(buf)?); 19 | } 20 | } 21 | 22 | Err(Error("Not supported yet".to_string())) 23 | } 24 | 25 | pub fn load_from_buf(mut r:R) -> Result 26 | { 27 | load_from_memory(r.fill_buf()?) 28 | } 29 | 30 | pub fn open>(path:P) -> Result 31 | { 32 | let mut buffer = Vec::new(); 33 | File::open(path)?.read_to_end(&mut buffer)?; 34 | load_from_memory(&buffer) 35 | } -------------------------------------------------------------------------------- /src/renderer/core/canvas.rs: -------------------------------------------------------------------------------- 1 | use crate::scene::Scene; 2 | 3 | pub trait Canvas 4 | { 5 | fn width(&self) -> u32; 6 | fn height(&self) -> u32; 7 | 8 | fn render(&mut self, scene: &Scene); 9 | } -------------------------------------------------------------------------------- /src/renderer/core/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod canvas; 2 | pub mod renderer; 3 | 4 | pub use self::canvas::*; 5 | pub use self::renderer::*; -------------------------------------------------------------------------------- /src/renderer/core/renderer.rs: -------------------------------------------------------------------------------- 1 | use crate::scene::Scene; 2 | use super::Canvas; 3 | 4 | pub trait Renderer : Canvas 5 | { 6 | fn set_width(&mut self, width:u32); 7 | fn set_height(&mut self, height:u32); 8 | 9 | fn render(&mut self, scene: &Scene); 10 | } -------------------------------------------------------------------------------- /src/renderer/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod core; 2 | pub mod renderer; 3 | pub mod webgl; 4 | pub mod window; 5 | 6 | pub use self::core::*; 7 | pub use self::renderer::*; 8 | pub use self::webgl::*; 9 | pub use self::window::*; -------------------------------------------------------------------------------- /src/renderer/renderer/forward/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod shaders; 2 | pub mod uniforms; 3 | pub mod forward; 4 | 5 | pub use self::forward::*; -------------------------------------------------------------------------------- /src/renderer/renderer/forward/uniforms.rs: -------------------------------------------------------------------------------- 1 | use super::super::super::webgl::{ WebGLTexture, WebGLBuffer, WebGLProgram, WebGLUniformLocation }; 2 | 3 | pub struct LightUniform 4 | { 5 | pub color: Option, 6 | pub position: Option, 7 | pub direction: Option, 8 | pub radiance: Option, 9 | pub irradiance: Option, 10 | pub angle: Option, 11 | } 12 | 13 | pub struct MaterialUniform 14 | { 15 | pub program: WebGLProgram, 16 | pub model: Option, 17 | pub view: Option, 18 | pub viewproject: Option, 19 | pub eye_position: Option, 20 | pub exposure: Option, 21 | pub lights:Vec, 22 | pub locations: Vec>, 23 | } 24 | 25 | pub struct TextureUniform 26 | { 27 | pub texture: WebGLTexture, 28 | } 29 | 30 | pub struct GeometryUniform 31 | { 32 | pub vertex_buffer: WebGLBuffer, 33 | pub index_buffer: WebGLBuffer, 34 | pub count:i32, 35 | } 36 | 37 | impl TextureUniform 38 | { 39 | pub fn new(texture:WebGLTexture) -> Self 40 | { 41 | Self 42 | { 43 | texture: texture, 44 | } 45 | } 46 | } 47 | 48 | impl GeometryUniform 49 | { 50 | pub fn new(vertex_buffer:WebGLBuffer, index_buffer:WebGLBuffer, count:i32) -> Self 51 | { 52 | Self 53 | { 54 | vertex_buffer: vertex_buffer, 55 | index_buffer: index_buffer, 56 | count:count 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /src/renderer/renderer/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod forward; -------------------------------------------------------------------------------- /src/renderer/webgl/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))] mod webgl_native; 2 | #[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))] mod webgl_common; 3 | #[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))] mod webgl_context; 4 | 5 | #[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))] pub use self::webgl_common::*; 6 | #[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))] pub use self::webgl_native::*; 7 | #[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))] pub use self::webgl_context::*; 8 | 9 | #[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))] mod webgl_stdweb_common; 10 | #[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))] mod webgl_stdweb_native; 11 | #[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))] mod webgl_stdweb_context; 12 | 13 | #[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))] pub use self::webgl_stdweb_common::*; 14 | #[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))] pub use self::webgl_stdweb_native::*; 15 | #[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))] pub use self::webgl_stdweb_context::*; -------------------------------------------------------------------------------- /src/renderer/webgl/webgl_common.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Deref; 2 | 3 | pub type Reference = u32; 4 | pub type GLbitfield = u32; 5 | pub type GLboolean = bool; 6 | pub type GLbyte = i8; 7 | pub type GLclampf = f32; 8 | pub type GLenum = u32; 9 | pub type GLfloat = f32; 10 | pub type GLint = i32; 11 | pub type GLint64 = i64; 12 | pub type GLintptr = i64; 13 | pub type GLshort = i16; 14 | pub type GLsizei = i32; 15 | pub type GLsizeiptr = i64; 16 | pub type GLubyte = u8; 17 | pub type GLuint = u32; 18 | pub type GLuint64 = u64; 19 | pub type GLushort = u16; 20 | pub type Int32List = Vec; 21 | pub type Uint32List = Vec; 22 | pub type Float32List = Vec; 23 | 24 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 25 | pub struct GLContext{ pub reference: Reference } 26 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 27 | pub struct WebGLRenderingContext{ pub common: GLContext } 28 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 29 | pub struct WebGL2RenderingContext { pub common: GLContext } 30 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 31 | pub struct WebGLBuffer(pub Reference); 32 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 33 | pub struct WebGLSampler(pub Reference); 34 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 35 | pub struct WebGLShader(pub Reference); 36 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 37 | pub struct WebGLProgram(pub Reference); 38 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 39 | pub struct WebGLFramebuffer(pub Reference); 40 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 41 | pub struct WebGLRenderbuffer(pub Reference); 42 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 43 | pub struct WebGLTexture(pub Reference); 44 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 45 | pub struct WebGLVertexArray(pub Reference); 46 | 47 | #[derive(Debug, Clone, PartialEq, Eq)] 48 | pub struct WebGLActiveInfo 49 | { 50 | reference: Reference, 51 | name: String, 52 | size: u32, 53 | kind: u32, 54 | } 55 | 56 | #[derive(Debug, Clone, PartialEq, Eq)] 57 | pub struct WebGLUniformLocation 58 | { 59 | pub reference: Reference, 60 | pub name: String, 61 | } 62 | 63 | impl WebGLActiveInfo 64 | { 65 | pub fn new>(name: T, size: u32, kind: u32, reference: Reference) -> WebGLActiveInfo 66 | { 67 | let nam = name.into(); 68 | WebGLActiveInfo 69 | { 70 | reference, 71 | name: nam, 72 | size, 73 | kind, 74 | } 75 | } 76 | } 77 | 78 | impl WebGLUniformLocation 79 | { 80 | pub fn new(name: String, reference: Reference) -> WebGLUniformLocation 81 | { 82 | WebGLUniformLocation 83 | { 84 | name, 85 | reference 86 | } 87 | } 88 | } 89 | 90 | pub trait AsReference 91 | { 92 | fn as_reference(&self) -> &Reference; 93 | } 94 | 95 | impl AsReference for GLContext 96 | { 97 | fn as_reference(&self) -> &Reference 98 | { 99 | &self.reference 100 | } 101 | } 102 | 103 | impl AsReference for WebGLRenderingContext 104 | { 105 | fn as_reference(&self) -> &Reference 106 | { 107 | &self.common.as_reference() 108 | } 109 | } 110 | 111 | impl AsReference for WebGL2RenderingContext 112 | { 113 | fn as_reference(&self) -> &Reference 114 | { 115 | &self.common.as_reference() 116 | } 117 | } 118 | 119 | impl Deref for WebGLRenderingContext 120 | { 121 | type Target = GLContext; 122 | fn deref(&self) -> &GLContext 123 | { 124 | &self.common 125 | } 126 | } 127 | 128 | impl Deref for WebGL2RenderingContext 129 | { 130 | type Target = GLContext; 131 | fn deref(&self) -> &GLContext 132 | { 133 | &self.common 134 | } 135 | } 136 | 137 | 138 | impl Deref for WebGLBuffer 139 | { 140 | type Target = Reference; 141 | fn deref(&self) -> &Self::Target 142 | { 143 | &self.0 144 | } 145 | } 146 | 147 | impl Deref for WebGLSampler 148 | { 149 | type Target = Reference; 150 | fn deref(&self) -> &Self::Target 151 | { 152 | &self.0 153 | } 154 | } 155 | 156 | impl Deref for WebGLShader 157 | { 158 | type Target = Reference; 159 | fn deref(&self) -> &Self::Target 160 | { 161 | &self.0 162 | } 163 | } 164 | 165 | impl Deref for WebGLProgram 166 | { 167 | type Target = Reference; 168 | fn deref(&self) -> &Self::Target 169 | { 170 | &self.0 171 | } 172 | } 173 | 174 | impl Deref for WebGLFramebuffer 175 | { 176 | type Target = Reference; 177 | fn deref(&self) -> &Self::Target 178 | { 179 | &self.0 180 | } 181 | } 182 | 183 | impl Deref for WebGLRenderbuffer 184 | { 185 | type Target = Reference; 186 | fn deref(&self) -> &Self::Target 187 | { 188 | &self.0 189 | } 190 | } 191 | 192 | impl Deref for WebGLTexture 193 | { 194 | type Target = Reference; 195 | fn deref(&self) -> &Self::Target 196 | { 197 | &self.0 198 | } 199 | } 200 | 201 | impl Deref for WebGLVertexArray 202 | { 203 | type Target = Reference; 204 | fn deref(&self) -> &Self::Target 205 | { 206 | &self.0 207 | } 208 | } 209 | 210 | impl Deref for WebGLUniformLocation 211 | { 212 | type Target = Reference; 213 | fn deref(&self) -> &Self::Target 214 | { 215 | &self.reference 216 | } 217 | } -------------------------------------------------------------------------------- /src/renderer/window/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))] 2 | pub mod web; 3 | 4 | #[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))] 5 | pub mod native; 6 | 7 | #[cfg(any(target_arch = "wasm32", target_arch = "asmjs"))] 8 | pub use self::web::Window; 9 | 10 | #[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))] 11 | pub use self::native::Window; -------------------------------------------------------------------------------- /src/renderer/window/native.rs: -------------------------------------------------------------------------------- 1 | use std::sync::mpsc::Receiver; 2 | 3 | use glfw::{Action, Context, Key, WindowEvent, Glfw}; 4 | 5 | use crate::scene::core::*; 6 | use crate::scene::scene::scene::*; 7 | 8 | use super::super::webgl::*; 9 | use super::super::renderer::forward::*; 10 | 11 | fn handle_window_event(window: &mut glfw::Window, event: glfw::WindowEvent) 12 | { 13 | match event 14 | { 15 | glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => 16 | { 17 | window.set_should_close(true) 18 | } 19 | _ => {} 20 | } 21 | } 22 | 23 | pub struct Window 24 | { 25 | glfw:Glfw, 26 | window:glfw::Window, 27 | renderer:ForwardRenderer, 28 | events:Receiver<(f64, WindowEvent)>, 29 | } 30 | 31 | impl Window 32 | { 33 | pub fn new(tile:&str) -> Self 34 | { 35 | let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap(); 36 | // glfw.window_hint(glfw::WindowHint::ContextVersion(3, 2)); 37 | // glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Compat)); 38 | // glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true)); 39 | glfw.window_hint(glfw::WindowHint::Samples(Some(8))); 40 | 41 | let (mut window, events) = glfw.create_window(1376, 768, tile, glfw::WindowMode::Windowed) 42 | .expect("Failed to create GLFW window."); 43 | 44 | window.make_current(); 45 | 46 | window.set_key_polling(true); 47 | window.set_framebuffer_size_polling(true); 48 | 49 | glfw.set_swap_interval(glfw::SwapInterval::Adaptive); 50 | 51 | let size = window.get_size(); 52 | let context = WebGLRenderingContext::new(|symbol| window.get_proc_address(symbol) as *const _); 53 | 54 | Self 55 | { 56 | glfw:glfw, 57 | window:window, 58 | renderer:ForwardRenderer::new(context, size.0 as u32, size.1 as u32), 59 | events:events, 60 | } 61 | } 62 | 63 | pub fn should_close(&self) -> bool 64 | { 65 | self.window.should_close() 66 | } 67 | 68 | pub fn update(&mut self, mut callback:T) where T:'static + FnMut(&mut Canvas, f32) 69 | { 70 | while !self.should_close() 71 | { 72 | self.glfw.poll_events(); 73 | 74 | for (_, event) in glfw::flush_messages(&self.events) 75 | { 76 | handle_window_event(&mut self.window, event); 77 | } 78 | 79 | let (w, h) = self.window.get_size(); 80 | self.renderer.set_width(w as u32); 81 | self.renderer.set_height(h as u32); 82 | 83 | callback(&mut self.renderer, self.glfw.get_time() as f32); 84 | 85 | self.window.swap_buffers(); 86 | } 87 | } 88 | } 89 | 90 | impl Canvas for Window 91 | { 92 | fn width(&self) -> u32 93 | { 94 | self.window.get_size().0 as u32 95 | } 96 | 97 | fn height(&self) -> u32 98 | { 99 | self.window.get_size().1 as u32 100 | } 101 | 102 | fn render(&mut self, scene: &Scene) 103 | { 104 | self.renderer.render(scene); 105 | } 106 | } -------------------------------------------------------------------------------- /src/renderer/window/web.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::cell::RefCell; 3 | 4 | use crate::scene::core::*; 5 | use crate::scene::scene::scene::*; 6 | 7 | use super::super::renderer::forward::*; 8 | 9 | use stdweb::unstable::TryInto; 10 | use stdweb::web::{ IEventTarget, IHtmlElement, IParentNode, document, window }; 11 | use stdweb::web::event::{ ResizeEvent }; 12 | use stdweb::web::html_element::CanvasElement; 13 | 14 | macro_rules! enclose { 15 | ( ($( $x:ident ),*) $y:expr ) => { 16 | { 17 | $(let $x = $x.clone();)* 18 | $y 19 | } 20 | }; 21 | } 22 | 23 | struct Context 24 | { 25 | pub canvas:CanvasElement, 26 | pub renderer:ForwardRenderer, 27 | } 28 | 29 | impl Context 30 | { 31 | fn step(&mut self) 32 | { 33 | self.renderer.set_width(self.canvas.width()); 34 | self.renderer.set_height(self.canvas.height()); 35 | } 36 | 37 | fn animate(&mut self, rc: Rc>, mut dispatch:T, time:f32) where T:'static + FnMut(&mut Canvas, f32) 38 | { 39 | self.step(); 40 | dispatch(&mut self.renderer, time); 41 | 42 | window().request_animation_frame( 43 | move |time| 44 | { 45 | rc.borrow_mut().animate(rc.clone(), dispatch, (time as f32) * 0.001); 46 | } 47 | ); 48 | } 49 | } 50 | 51 | pub struct Window 52 | { 53 | context:Rc>, 54 | } 55 | 56 | impl Window 57 | { 58 | pub fn new(_tile:&str) -> Self 59 | { 60 | stdweb::initialize(); 61 | 62 | let canvas: CanvasElement = document().query_selector( "#canvas" ).unwrap().unwrap().try_into().unwrap(); 63 | canvas.set_width(canvas.offset_width() as u32); 64 | canvas.set_height(canvas.offset_height() as u32); 65 | 66 | window().add_event_listener(enclose!( (canvas) move |_: ResizeEvent| { 67 | canvas.set_width(canvas.offset_width() as u32); 68 | canvas.set_height(canvas.offset_height() as u32); 69 | })); 70 | 71 | Self 72 | { 73 | context : Rc::new(RefCell::new(Context 74 | { 75 | renderer:ForwardRenderer::new(canvas.get_context().unwrap(), canvas.width(), canvas.height()), 76 | canvas:canvas, 77 | })) 78 | } 79 | } 80 | 81 | pub fn should_close(&self) -> bool 82 | { 83 | false 84 | } 85 | 86 | pub fn update(&mut self, callback:T) where T:'static + FnMut(&mut Canvas, f32) 87 | { 88 | self.context.borrow_mut().animate(self.context.clone(), callback, 0.0); 89 | } 90 | } 91 | 92 | impl Canvas for Window 93 | { 94 | fn width(&self) -> u32 95 | { 96 | self.context.borrow_mut().canvas.width() 97 | } 98 | 99 | fn height(&self) -> u32 100 | { 101 | self.context.borrow_mut().canvas.height() 102 | } 103 | 104 | fn render(&mut self, scene: &Scene) 105 | { 106 | self.context.borrow_mut().renderer.render(scene); 107 | } 108 | } -------------------------------------------------------------------------------- /src/scene/cameras/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod perspective; 2 | pub mod orthographic; 3 | 4 | pub use self::perspective::*; 5 | pub use self::orthographic::*; -------------------------------------------------------------------------------- /src/scene/core/camera.rs: -------------------------------------------------------------------------------- 1 | use std::f32; 2 | use crate::math::{float4x4, One}; 3 | use super::Object; 4 | 5 | #[derive(Debug, Copy, PartialEq, Clone, Serialize, Deserialize)] 6 | pub enum Dimensions 7 | { 8 | Automatic, 9 | Sized(f32), 10 | } 11 | 12 | #[derive(Debug, Copy, PartialEq, Clone, Serialize, Deserialize)] 13 | pub enum CameraType 14 | { 15 | Main, 16 | Shadow, 17 | Custom 18 | } 19 | 20 | impl CameraType 21 | { 22 | pub fn as_int(&self) -> u32 23 | { 24 | match self 25 | { 26 | CameraType::Main => 0, 27 | CameraType::Shadow => 1, 28 | CameraType::Custom => 2, 29 | } 30 | } 31 | 32 | pub fn cmp(&self, other:&Self) -> std::cmp::Ordering 33 | { 34 | self.as_int().cmp(&other.as_int()) 35 | } 36 | } 37 | 38 | #[derive(Debug, Copy, Clone)] 39 | pub struct CameraData 40 | { 41 | pub kind:CameraType, 42 | pub view:float4x4, 43 | pub view_inverse:float4x4, 44 | pub projection:float4x4, 45 | pub projection_inverse:float4x4, 46 | pub view_projection:float4x4, 47 | pub view_projection_inverse:float4x4, 48 | } 49 | 50 | impl CameraData 51 | { 52 | pub fn new() -> Self 53 | { 54 | Self 55 | { 56 | kind:CameraType::Custom, 57 | view:float4x4::one(), 58 | view_inverse:float4x4::one(), 59 | projection:float4x4::one(), 60 | projection_inverse:float4x4::one(), 61 | view_projection:float4x4::one(), 62 | view_projection_inverse:float4x4::one(), 63 | } 64 | } 65 | } 66 | 67 | pub trait Camera : Object 68 | { 69 | fn kind(&self) -> CameraType; 70 | 71 | fn width(&self) -> f32; 72 | fn height(&self) -> f32; 73 | fn ratio(&self) -> f32 { self.width() / self.height() } 74 | 75 | fn focal_length(&self) -> f32; 76 | fn focal_distance(&self) -> f32; 77 | 78 | fn exposure(&self) -> f32; 79 | 80 | fn clear_color(&self) -> (f32,f32,f32,f32); 81 | fn viewport(&self) -> (f32,f32,f32,f32); 82 | 83 | fn view(&self) -> float4x4; 84 | fn view_inverse(&self) -> float4x4; 85 | fn view_projection(&self) -> float4x4; 86 | fn view_projection_inverse(&self) -> float4x4; 87 | fn projection(&self) -> float4x4; 88 | fn projection_inverse(&self) -> float4x4; 89 | 90 | fn set_clear_color(&mut self, r:f32, g:f32, b:f32, a:f32); 91 | fn set_viewport(&mut self, x:f32, y:f32, z:f32, w:f32); 92 | } -------------------------------------------------------------------------------- /src/scene/core/canvas.rs: -------------------------------------------------------------------------------- 1 | use super::super::scene::{Scene}; 2 | 3 | pub trait Canvas 4 | { 5 | fn width(&self) -> u32; 6 | fn height(&self) -> u32; 7 | 8 | fn render(&mut self, scene: &Scene); 9 | } -------------------------------------------------------------------------------- /src/scene/core/downcast.rs: -------------------------------------------------------------------------------- 1 | use std::any::Any; 2 | 3 | pub trait Downcast: Any 4 | { 5 | fn as_any(&self) -> &Any; 6 | fn as_any_mut(&mut self) -> &mut Any; 7 | } -------------------------------------------------------------------------------- /src/scene/core/error.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::io; 3 | use crate::models; 4 | 5 | pub enum Error { 6 | IoError(io::Error), 7 | ImageError(image::ImageError), 8 | ModelError(models::Error), 9 | LoaderError(String) 10 | } 11 | 12 | impl fmt::Display for Error { 13 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 14 | match *self { 15 | Error::IoError(ref err) => write!(f, "IoError {{ {} }}", err), 16 | Error::ImageError(ref err) => write!(f, "ImageError {{ {} }}", err), 17 | Error::ModelError(ref err) => write!(f, "ModelError {{ {} }}", err), 18 | Error::LoaderError(ref err) => write!(f, "LoaderError {{ {} }}", err), 19 | } 20 | } 21 | } 22 | 23 | impl fmt::Debug for Error { 24 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 25 | fmt::Display::fmt(self, f) 26 | } 27 | } 28 | 29 | impl std::error::Error for Error { 30 | fn description(&self) -> &str { 31 | match *self { 32 | Error::IoError(_) => "I/O Error", 33 | Error::ImageError(_) => "Image Error", 34 | Error::ModelError(_) => "Model Error", 35 | Error::LoaderError(_) => "Loader Error", 36 | } 37 | } 38 | 39 | } 40 | 41 | impl From for Error { 42 | fn from(err: io::Error) -> Error { 43 | Error::IoError(err) 44 | } 45 | } 46 | 47 | impl From for Error 48 | { 49 | fn from(err: image::ImageError) -> Self 50 | { 51 | Error::ImageError(err) 52 | } 53 | } 54 | 55 | impl From for Error 56 | { 57 | fn from(err: models::Error) -> Self 58 | { 59 | Error::ModelError(err) 60 | } 61 | } 62 | 63 | impl From for Error 64 | { 65 | fn from(err: String) -> Self 66 | { 67 | Error::LoaderError(err) 68 | } 69 | } 70 | 71 | impl From for Error 72 | { 73 | fn from(_err: std::string::FromUtf8Error) -> Error 74 | { 75 | Error::LoaderError("Failed to convert the Utf8".to_string()) 76 | } 77 | } 78 | 79 | impl From for Error 80 | { 81 | fn from(_err: std::string::FromUtf16Error) -> Error 82 | { 83 | Error::LoaderError("Failed to convert the Utf16".to_string()) 84 | } 85 | } 86 | 87 | pub type Result = std::result::Result; -------------------------------------------------------------------------------- /src/scene/core/event.rs: -------------------------------------------------------------------------------- 1 | use super::Canvas; 2 | 3 | pub trait UpdateEvent 4 | { 5 | fn update(&mut self, canvas:&Canvas); 6 | } -------------------------------------------------------------------------------- /src/scene/core/geometry.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | use serde::ser::{Serialize, Serializer, SerializeStruct}; 3 | use base64; 4 | use crate::math::{float2, float3}; 5 | use crate::models::{VertexWeight}; 6 | use super::{Resource}; 7 | 8 | pub trait Geometry : Debug + Resource 9 | { 10 | fn vertices(&self) -> &[float3]; 11 | fn normals(&self) -> &[float3]; 12 | fn texcoords(&self) -> &[float2]; 13 | fn indices(&self) -> &[u16]; 14 | fn weights(&self) -> &[VertexWeight]; 15 | 16 | #[inline(always)] 17 | fn num_vertices(&self) -> usize { self.vertices().len() } 18 | 19 | #[inline(always)] 20 | fn num_normals(&self) -> usize { self.normals().len() } 21 | 22 | #[inline(always)] 23 | fn num_texcoords(&self) -> usize { self.texcoords().len() } 24 | 25 | #[inline(always)] 26 | fn num_indices(&self) -> usize { self.indices().len() } 27 | 28 | #[inline(always)] 29 | fn num_weights(&self) -> usize { self.weights().len() } 30 | } 31 | 32 | impl Serialize for Geometry 33 | { 34 | fn serialize(&self, serializer: S) -> Result where S: Serializer 35 | { 36 | let mut s = serializer.serialize_struct("mesh", 4)?; 37 | s.serialize_field("uuid", &self.uuid())?; 38 | 39 | unsafe 40 | { 41 | let v = std::slice::from_raw_parts(self.vertices().as_ptr() as *const u8, self.vertices().len() * std::mem::size_of::()); 42 | let n = std::slice::from_raw_parts(self.normals().as_ptr() as *const u8, self.normals().len() * std::mem::size_of::()); 43 | let uv = std::slice::from_raw_parts(self.texcoords().as_ptr() as *const u8, self.texcoords().len() * std::mem::size_of::()); 44 | let i = std::slice::from_raw_parts(self.indices().as_ptr() as *const u8, self.indices().len() * std::mem::size_of::()); 45 | 46 | s.serialize_field("v", &base64::encode(v))?; 47 | s.serialize_field("n", &base64::encode(n))?; 48 | s.serialize_field("uv", &base64::encode(uv))?; 49 | s.serialize_field("i", &base64::encode(i))?; 50 | } 51 | 52 | s.end() 53 | } 54 | } -------------------------------------------------------------------------------- /src/scene/core/light.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | use crate::math::float3; 3 | use super::{Object, Texture}; 4 | use super::super::spectrum::*; 5 | 6 | #[derive(Debug, Copy, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)] 7 | pub enum LightType 8 | { 9 | Sky, 10 | Directional, 11 | Point, 12 | Spot, 13 | } 14 | 15 | #[derive(Debug, Clone)] 16 | pub struct LightData 17 | { 18 | pub kind:LightType, 19 | pub color:Spectrum, 20 | pub intensity:f32, 21 | pub radiance:Option>, 22 | pub irradiance:Option>, 23 | pub direction:float3, 24 | pub cos_angle:f32 25 | } 26 | 27 | impl LightData 28 | { 29 | pub fn intensity(&self) -> f32 30 | { 31 | self.intensity 32 | } 33 | 34 | pub fn cos_angle(&self) -> f32 35 | { 36 | self.cos_angle 37 | } 38 | 39 | pub fn direction(&self) -> float3 40 | { 41 | self.direction 42 | } 43 | } 44 | 45 | pub trait Light : Object 46 | { 47 | fn kind(&self) -> LightType; 48 | 49 | fn color(&self) -> Spectrum; 50 | fn intensity(&self) -> f32; 51 | 52 | fn set_color(&mut self, spectrum:Spectrum); 53 | fn set_intensity(&mut self, cd:f32); 54 | } -------------------------------------------------------------------------------- /src/scene/core/loader.rs: -------------------------------------------------------------------------------- 1 | use super::super::{Result, Scene}; 2 | 3 | pub trait Loader 4 | { 5 | fn can_read(&self, buf:&[u8]) -> bool; 6 | 7 | fn do_load(&self, buf:&[u8]) -> Result; 8 | fn do_save(&self, scene:&Scene) -> Result>; 9 | } -------------------------------------------------------------------------------- /src/scene/core/log.rs: -------------------------------------------------------------------------------- 1 | use log::{Record, Level, Metadata, SetLoggerError,LevelFilter}; 2 | 3 | struct SimpleLogger; 4 | 5 | impl log::Log for SimpleLogger 6 | { 7 | fn enabled(&self, metadata: &Metadata) -> bool 8 | { 9 | metadata.level() <= Level::Info 10 | } 11 | 12 | fn log(&self, record: &Record) 13 | { 14 | if self.enabled(record.metadata()) 15 | { 16 | println!("{} - {}", record.level(), record.args()); 17 | } 18 | } 19 | 20 | fn flush(&self) {} 21 | } 22 | 23 | pub fn init_log() -> Result<(), SetLoggerError> 24 | { 25 | log::set_boxed_logger(Box::new(SimpleLogger)) 26 | .map(|()| log::set_max_level(LevelFilter::Info)) 27 | } -------------------------------------------------------------------------------- /src/scene/core/material.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | use std::collections::hash_map::HashMap; 3 | use serde::ser::{Serialize, Serializer, SerializeStruct}; 4 | use super::{Resource, Format, Variant}; 5 | 6 | #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] 7 | pub enum ClearFlags 8 | { 9 | Color(f32,f32,f32,f32), 10 | Depth(f32), 11 | Stencil(u8) 12 | } 13 | 14 | #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] 15 | pub enum BlendFactor 16 | { 17 | Zero, 18 | One, 19 | DstCol, 20 | SrcColor, 21 | SrcAlpha, 22 | DstAlpha, 23 | OneMinusSrcCol, 24 | OneMinusDstCol, 25 | OneMinusSrcAlpha, 26 | OneMinusDstAlpha, 27 | ConstantColor, 28 | ConstantAlpha, 29 | OneMinusConstantColor, 30 | OneMinusConstantAlpha, 31 | SrcAlphaSaturate, 32 | } 33 | 34 | #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] 35 | pub enum BlendOp 36 | { 37 | Add, 38 | Subtract, 39 | RevSubtract 40 | } 41 | 42 | #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] 43 | pub enum ComparisonFunc 44 | { 45 | Never, 46 | Less, 47 | Equal, 48 | Lequal, 49 | Greater, 50 | Notequal, 51 | Gequal, 52 | Always 53 | } 54 | 55 | #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] 56 | pub enum CullMode 57 | { 58 | None, 59 | Front, 60 | Back, 61 | FrontBack, 62 | } 63 | 64 | #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] 65 | pub enum FrontFace 66 | { 67 | CW, 68 | CCW, 69 | } 70 | 71 | #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] 72 | pub enum PolygonMode 73 | { 74 | Point, 75 | Wireframe, 76 | Solid, 77 | } 78 | 79 | #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] 80 | pub struct VertexAttrib 81 | { 82 | pub index:u8, 83 | pub count:u8, 84 | pub size:u8, 85 | pub stride:u8, 86 | pub offset:u16, 87 | pub format:Format, 88 | } 89 | 90 | impl VertexAttrib 91 | { 92 | pub fn new(index:u8, format:Format, stride:u8, offset:u16) -> Self 93 | { 94 | Self 95 | { 96 | index:index, 97 | count:format.count() as u8, 98 | size:format.type_size() as u8, 99 | stride:stride, 100 | offset:offset, 101 | format:format, 102 | } 103 | } 104 | } 105 | 106 | #[derive(Debug, Serialize, Deserialize)] 107 | pub struct RenderState 108 | { 109 | pub viewport:Option<(f32,f32,f32,f32)>, 110 | pub clear_depth:Option, 111 | pub clear_stencil:Option, 112 | pub clear_color:Option<(f32,f32,f32,f32)>, 113 | pub blend_enable:bool, 114 | pub blend_op:BlendOp, 115 | pub blend_src:BlendFactor, 116 | pub blend_dest:BlendFactor, 117 | pub blend_alpha_op:BlendOp, 118 | pub blend_alpha_src:BlendFactor, 119 | pub blend_alpha_dest:BlendFactor, 120 | pub color_write_mask:u32, 121 | pub polygon_mode:PolygonMode, 122 | pub depth_enable:bool, 123 | pub depth_write_enable:bool, 124 | pub depth_func:ComparisonFunc, 125 | pub cull_mode:CullMode, 126 | pub line_width:f32, 127 | pub front_face:FrontFace, 128 | } 129 | 130 | impl RenderState 131 | { 132 | pub fn new() -> Self 133 | { 134 | Self 135 | { 136 | viewport:None, 137 | clear_depth:None, 138 | clear_stencil:None, 139 | clear_color:None, 140 | blend_enable:false, 141 | blend_op:BlendOp::Add, 142 | blend_src:BlendFactor::SrcAlpha, 143 | blend_dest:BlendFactor::OneMinusConstantAlpha, 144 | blend_alpha_op:BlendOp::Add, 145 | blend_alpha_src:BlendFactor::SrcAlpha, 146 | blend_alpha_dest:BlendFactor::OneMinusConstantAlpha, 147 | color_write_mask:0xFFFFFFFF, 148 | polygon_mode:PolygonMode::Solid, 149 | depth_enable:true, 150 | depth_write_enable:true, 151 | depth_func:ComparisonFunc::Lequal, 152 | cull_mode:CullMode::Back, 153 | line_width:1.0, 154 | front_face:FrontFace::CW, 155 | } 156 | } 157 | } 158 | 159 | pub trait Material : 160 | Debug 161 | + AsRef 162 | + AsMut 163 | + Resource 164 | { 165 | fn input_layout(&self) -> &[VertexAttrib]; 166 | fn uniforms(&self) -> &HashMap; 167 | 168 | fn set_uniform(&mut self, name:&str, value:Variant); 169 | 170 | fn num_uniform(&self) -> usize 171 | { 172 | self.uniforms().len() 173 | } 174 | 175 | fn num_texture(&self) -> u32 176 | { 177 | let mut unit = 0; 178 | 179 | for (_key, value) in self.uniforms() 180 | { 181 | match value 182 | { 183 | Variant::Texture(_) => 184 | { 185 | unit += 1; 186 | }, 187 | _ => {}, 188 | } 189 | } 190 | 191 | return unit; 192 | } 193 | 194 | fn vs(&self) -> &str { "" } 195 | fn fs(&self) -> &str { "" } 196 | 197 | fn viewport(&self) -> Option<&(f32,f32,f32,f32)> { self.as_ref().viewport.as_ref() } 198 | 199 | fn clear_depth(&self) -> &Option { &self.as_ref().clear_depth } 200 | fn clear_stencil(&self) -> &Option { &self.as_ref().clear_stencil } 201 | fn clear_color(&self) -> &Option<(f32,f32,f32,f32)> { &self.as_ref().clear_color } 202 | 203 | fn blend_enable(&self) -> bool { self.as_ref().blend_enable } 204 | fn blend_op(&self) -> BlendOp { self.as_ref().blend_op } 205 | fn blend_src(&self) -> BlendFactor { self.as_ref().blend_src } 206 | fn blend_dest(&self) -> BlendFactor { self.as_ref().blend_dest } 207 | fn blend_alpha_op(&self) -> BlendOp { self.as_ref().blend_alpha_op } 208 | fn blend_alpha_src(&self) -> BlendFactor { self.as_ref().blend_alpha_src } 209 | fn blend_alpha_dest(&self) -> BlendFactor { self.as_ref().blend_alpha_dest } 210 | 211 | fn color_write_mask(&self) -> u32 { self.as_ref().color_write_mask } 212 | 213 | fn polygon_mode(&self) -> PolygonMode { self.as_ref().polygon_mode } 214 | 215 | fn depth_enable(&self) -> bool { self.as_ref().depth_enable } 216 | fn depth_write_enable(&self) -> bool { self.as_ref().depth_write_enable } 217 | fn depth_func(&self) -> ComparisonFunc { self.as_ref().depth_func } 218 | 219 | fn cull_mode(&self) -> CullMode { self.as_ref().cull_mode } 220 | 221 | fn line_width(&self) -> f32 { self.as_ref().line_width } 222 | 223 | fn front_face(&self) -> FrontFace { self.as_ref().front_face } 224 | } 225 | 226 | impl Serialize for Material 227 | { 228 | fn serialize(&self, serializer: S) -> Result where S: Serializer 229 | { 230 | let mut s = serializer.serialize_struct("material", 4)?; 231 | s.serialize_field("attrib", &self.input_layout())?; 232 | s.serialize_field("parameters", &self.uniforms())?; 233 | s.serialize_field("state", &self.as_ref())?; 234 | s.end() 235 | } 236 | } -------------------------------------------------------------------------------- /src/scene/core/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod resource; 2 | pub mod object; 3 | pub mod downcast; 4 | pub mod camera; 5 | pub mod shape; 6 | pub mod light; 7 | pub mod material; 8 | pub mod geometry; 9 | pub mod event; 10 | pub mod transform; 11 | pub mod sampler; 12 | pub mod texture; 13 | pub mod variant; 14 | pub mod format; 15 | pub mod canvas; 16 | pub mod error; 17 | pub mod loader; 18 | pub mod log; 19 | 20 | pub use self::resource::*; 21 | pub use self::object::*; 22 | pub use self::downcast::*; 23 | pub use self::camera::*; 24 | pub use self::shape::*; 25 | pub use self::light::*; 26 | pub use self::material::*; 27 | pub use self::geometry::*; 28 | pub use self::event::*; 29 | pub use self::transform::*; 30 | pub use self::sampler::*; 31 | pub use self::texture::*; 32 | pub use self::variant::*; 33 | pub use self::format::*; 34 | pub use self::canvas::*; 35 | pub use self::error::*; 36 | pub use self::loader::*; -------------------------------------------------------------------------------- /src/scene/core/object.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | use crate::math::{float3, float4x4}; 3 | use super::{Resource, Downcast, Canvas}; 4 | use super::super::scene::{SceneNode, SceneData}; 5 | 6 | pub trait Object : 7 | AsRef 8 | + AsMut 9 | + Debug 10 | + Downcast 11 | + Resource 12 | { 13 | #[inline(always)] 14 | fn is_visible(&self) -> bool 15 | { 16 | self.as_ref().is_visible() 17 | } 18 | 19 | #[inline(always)] 20 | fn set_visible(&mut self, visible: bool) -> &mut SceneNode 21 | { 22 | self.as_mut().set_visible(visible) 23 | } 24 | 25 | #[inline(always)] 26 | fn name(&self) -> String 27 | { 28 | self.as_ref().name() 29 | } 30 | 31 | #[inline(always)] 32 | fn set_name(&mut self, name: &str) -> &mut SceneNode 33 | { 34 | self.as_mut().set_name(name) 35 | } 36 | 37 | #[inline(always)] 38 | fn translate(&self) -> float3 39 | { 40 | self.as_ref().translate() 41 | } 42 | 43 | #[inline(always)] 44 | fn set_translate(&mut self, pos:float3) -> &mut SceneNode 45 | { 46 | self.as_mut().set_translate(pos) 47 | } 48 | 49 | #[inline(always)] 50 | fn scale(&self) -> float3 51 | { 52 | self.as_ref().scale() 53 | } 54 | 55 | #[inline(always)] 56 | fn set_scale(&mut self, sz:float3) -> &mut SceneNode 57 | { 58 | self.as_mut().set_scale(sz) 59 | } 60 | 61 | #[inline(always)] 62 | fn rotation(&self) -> float3 63 | { 64 | self.as_ref().rotation() 65 | } 66 | 67 | #[inline(always)] 68 | fn set_rotation(&mut self, rot:float3) -> &mut SceneNode 69 | { 70 | self.as_mut().set_rotation(rot) 71 | } 72 | 73 | #[inline(always)] 74 | fn transform(&self) -> float4x4 75 | { 76 | self.as_ref().transform() 77 | } 78 | 79 | #[inline(always)] 80 | fn transform_inverse(&self) -> float4x4 81 | { 82 | self.as_ref().transform_inverse() 83 | } 84 | 85 | #[inline(always)] 86 | fn up(&self) -> float3 87 | { 88 | self.transform().up() 89 | } 90 | 91 | #[inline(always)] 92 | fn set_up(&mut self, speed:float3) -> &mut SceneNode 93 | { 94 | let up = self.up(); 95 | self.set_translate(up * speed) 96 | } 97 | 98 | #[inline(always)] 99 | fn right(&self) -> float3 100 | { 101 | self.transform().right() 102 | } 103 | 104 | #[inline(always)] 105 | fn set_right(&mut self, speed:float3) -> &mut SceneNode 106 | { 107 | let right = self.right(); 108 | self.set_translate(right * speed) 109 | } 110 | 111 | #[inline(always)] 112 | fn forward(&self) -> float3 113 | { 114 | self.transform().forward() 115 | } 116 | 117 | #[inline(always)] 118 | fn set_forward(&mut self, speed:float3) -> &mut SceneNode 119 | { 120 | let forward = self.forward(); 121 | self.set_translate(forward * speed) 122 | } 123 | 124 | #[inline(always)] 125 | fn with(&mut self, method:fn(&mut SceneData, &Canvas)) -> &mut SceneNode 126 | { 127 | self.as_mut().with(method) 128 | } 129 | } -------------------------------------------------------------------------------- /src/scene/core/resource.rs: -------------------------------------------------------------------------------- 1 | pub trait Resource 2 | { 3 | fn uuid(&self) -> &uuid::Uuid; 4 | } -------------------------------------------------------------------------------- /src/scene/core/sampler.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::sync::Arc; 3 | use std::cell::RefCell; 4 | 5 | use super::{Resource}; 6 | use super::super::util::uuid::OsRandNewV4; 7 | 8 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] 9 | pub enum SamplerAnis 10 | { 11 | Anis0, 12 | Anis1, 13 | Anis2, 14 | Anis4, 15 | Anis8, 16 | Anis16, 17 | Anis32, 18 | Anis64, 19 | } 20 | 21 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] 22 | pub enum SamplerWrap 23 | { 24 | None, 25 | Repeat, 26 | Mirror, 27 | ClampToEdge, 28 | } 29 | 30 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] 31 | pub enum SamplerFilter 32 | { 33 | Nearest, 34 | Linear, 35 | NearestMipmapLinear, 36 | NearestMipmapNearest, 37 | LinearMipmapNearest, 38 | LinearMipmapLinear, 39 | } 40 | 41 | #[derive(Copy, PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)] 42 | pub struct Sampler 43 | { 44 | pub anis:SamplerAnis, 45 | pub wrap:SamplerWrap, 46 | pub filter_min:SamplerFilter, 47 | pub filter_mag:SamplerFilter, 48 | uuid:uuid::Uuid 49 | } 50 | 51 | impl Sampler 52 | { 53 | pub fn new(wrap:SamplerWrap,filter_min:SamplerFilter, filter_mag:SamplerFilter) -> Self 54 | { 55 | Self 56 | { 57 | uuid:uuid::Uuid::new_v4_osrng(), 58 | anis:SamplerAnis::Anis0, 59 | wrap:wrap, 60 | filter_min:filter_min, 61 | filter_mag:filter_mag, 62 | } 63 | } 64 | } 65 | 66 | impl Resource for Sampler 67 | { 68 | #[inline(always)] 69 | fn uuid(&self) -> &uuid::Uuid 70 | { 71 | &self.uuid 72 | } 73 | } 74 | 75 | impl From for Rc> 76 | { 77 | #[inline(always)] 78 | fn from(sampler:Sampler) -> Self 79 | { 80 | Rc::new(RefCell::new(sampler)) 81 | } 82 | } 83 | 84 | impl From for Arc> 85 | { 86 | #[inline(always)] 87 | fn from(sampler:Sampler) -> Self 88 | { 89 | Arc::new(RefCell::new(sampler)) 90 | } 91 | } -------------------------------------------------------------------------------- /src/scene/core/shape.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | use super::{Object, Geometry, Material}; 3 | 4 | pub trait Shape : Object 5 | { 6 | fn geometry(&self) -> Arc; 7 | fn material(&self) -> Arc; 8 | 9 | fn set_geometry(&mut self, geometry: Arc); 10 | fn set_material(&mut self, material: Arc); 11 | } -------------------------------------------------------------------------------- /src/scene/core/texture.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::sync::Arc; 3 | use std::cell::RefCell; 4 | use serde::ser::{Serialize, Serializer, SerializeStruct}; 5 | use super::{Resource, Sampler, SamplerWrap, SamplerFilter}; 6 | use super::super::util::uuid::OsRandNewV4; 7 | 8 | #[derive(Debug, Copy, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)] 9 | pub enum ColorType 10 | { 11 | Gray(u8), 12 | GrayA(u8), 13 | RGB(u8), 14 | RGBA(u8), 15 | BGR(u8), 16 | BGRA(u8), 17 | Palette(u8), 18 | } 19 | 20 | #[derive(Debug, PartialEq, Eq, Clone, Hash, Deserialize)] 21 | pub struct Texture 22 | { 23 | pub uuid:uuid::Uuid, 24 | pub sampler:Sampler, 25 | pub width:u32, 26 | pub height:u32, 27 | pub color:ColorType, 28 | pub raw_pixels:Vec, 29 | pub name:String 30 | } 31 | 32 | impl Texture 33 | { 34 | pub fn new(color_type:ColorType, width:u32, height:u32, raw_pixels:Vec) -> Self 35 | { 36 | Self 37 | { 38 | uuid:uuid::Uuid::new_v4_osrng(), 39 | sampler:Sampler::new(SamplerWrap::Repeat,SamplerFilter::Nearest,SamplerFilter::Nearest), 40 | color:color_type, 41 | width:width, 42 | height:height, 43 | raw_pixels:raw_pixels, 44 | name:String::new() 45 | } 46 | } 47 | 48 | #[inline(always)] 49 | pub fn width(&self) -> u32 50 | { 51 | self.width 52 | } 53 | 54 | #[inline(always)] 55 | pub fn height(&self) -> u32 56 | { 57 | self.height 58 | } 59 | 60 | #[inline(always)] 61 | pub fn color_type(&self) -> ColorType 62 | { 63 | self.color 64 | } 65 | 66 | #[inline(always)] 67 | pub fn raw_pixels(&self) -> &[u8] 68 | { 69 | &self.raw_pixels 70 | } 71 | 72 | #[inline(always)] 73 | pub fn name(&self) -> &str 74 | { 75 | &self.name 76 | } 77 | 78 | #[inline(always)] 79 | pub fn set_name(&mut self, name:&str) 80 | { 81 | self.name = name.to_string() 82 | } 83 | } 84 | 85 | impl Resource for Texture 86 | { 87 | #[inline(always)] 88 | fn uuid(&self) -> &uuid::Uuid 89 | { 90 | &self.uuid 91 | } 92 | } 93 | 94 | impl From for Rc> 95 | { 96 | #[inline(always)] 97 | fn from(texture:Texture) -> Self 98 | { 99 | Rc::new(RefCell::new(texture)) 100 | } 101 | } 102 | 103 | impl From for Arc> 104 | { 105 | #[inline(always)] 106 | fn from(texture:Texture) -> Self 107 | { 108 | Arc::new(RefCell::new(texture)) 109 | } 110 | } 111 | 112 | impl Serialize for Texture 113 | { 114 | fn serialize(&self, serializer: S) -> Result 115 | { 116 | let mut s = serializer.serialize_struct("texture", 4)?; 117 | s.serialize_field("uuid", &self.uuid)?; 118 | s.serialize_field("name", &self.name)?; 119 | s.serialize_field("sampler", &self.sampler)?; 120 | s.end() 121 | } 122 | } -------------------------------------------------------------------------------- /src/scene/core/transform.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use serde::ser::{Serialize, SerializeStruct, Serializer}; 3 | use crate::math::{float3, Quaternion, float4x4, One, Zero}; 4 | 5 | #[derive(Debug, Default, Clone)] 6 | pub struct Transform 7 | { 8 | translate:float3, 9 | scale:float3, 10 | rotation:float3, 11 | transform:RefCell, 12 | transform_inverse:RefCell, 13 | need_update:RefCell 14 | } 15 | 16 | impl Transform 17 | { 18 | pub fn new() -> Self 19 | { 20 | Self 21 | { 22 | translate:float3::zero(), 23 | scale:float3::one(), 24 | rotation:float3::zero(), 25 | transform:RefCell::new(float4x4::one()), 26 | transform_inverse:RefCell::new(float4x4::one()), 27 | need_update:RefCell::new(true) 28 | } 29 | } 30 | 31 | #[inline(always)] 32 | pub fn translate(&self) -> float3 33 | { 34 | return self.translate; 35 | } 36 | 37 | #[inline(always)] 38 | pub fn scale(&self) -> float3 39 | { 40 | return self.scale; 41 | } 42 | 43 | #[inline(always)] 44 | pub fn rotation(&self) -> float3 45 | { 46 | return self.rotation; 47 | } 48 | 49 | #[inline(always)] 50 | pub fn transform(&self) -> float4x4 51 | { 52 | self.update(); 53 | return *self.transform.borrow(); 54 | } 55 | 56 | #[inline(always)] 57 | pub fn transform_inverse(&self) -> float4x4 58 | { 59 | self.update(); 60 | return *self.transform_inverse.borrow(); 61 | } 62 | 63 | #[inline] 64 | pub fn set_translate(&mut self, pos:float3) 65 | { 66 | if self.translate != pos 67 | { 68 | self.translate = pos; 69 | self.need_update.replace(true); 70 | } 71 | } 72 | 73 | #[inline] 74 | pub fn set_scale(&mut self, sz:float3) 75 | { 76 | if self.scale != sz 77 | { 78 | self.scale = sz; 79 | self.need_update.replace(true); 80 | } 81 | } 82 | 83 | #[inline] 84 | pub fn set_rotation(&mut self, rot:float3) 85 | { 86 | if self.rotation != rot 87 | { 88 | self.rotation = rot; 89 | self.need_update.replace(true); 90 | } 91 | } 92 | 93 | #[inline] 94 | fn update(&self) 95 | { 96 | if *self.need_update.borrow() 97 | { 98 | let translate = float4x4::translate(self.translate.x, self.translate.y, self.translate.z); 99 | let rotation:float4x4 = Quaternion::euler_xyz(&self.rotation).into(); 100 | let scale = float4x4::scale(self.scale.x, self.scale.y, self.scale.z); 101 | let transform = translate * rotation * scale; 102 | 103 | self.transform.replace(transform); 104 | self.transform_inverse.replace(transform.transform_inverse()); 105 | 106 | self.need_update.replace(false); 107 | } 108 | } 109 | } 110 | 111 | impl Serialize for Transform 112 | { 113 | fn serialize(&self, serializer: S) -> Result 114 | { 115 | let mut s = serializer.serialize_struct("transform", 3)?; 116 | s.serialize_field("translate", &self.translate)?; 117 | s.serialize_field("rotation", &self.rotation)?; 118 | s.serialize_field("scale", &self.scale)?; 119 | s.end() 120 | } 121 | } -------------------------------------------------------------------------------- /src/scene/core/variant.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | use crate::math::*; 3 | use super::texture::*; 4 | 5 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 6 | pub enum Variant 7 | { 8 | Boolean(bool), 9 | Int1(i32_1), 10 | Int2(i32_2), 11 | Int3(i32_3), 12 | Int4(i32_4), 13 | Uint1(u32_1), 14 | Uint2(u32_2), 15 | Uint3(u32_3), 16 | Uint4(u32_4), 17 | Float1(float1), 18 | Float2(float2), 19 | Float3(float3), 20 | Float4(float4), 21 | Float2x2(float2x2), 22 | Float3x3(float3x3), 23 | Float4x4(float4x4), 24 | Double2x2(double2x2), 25 | Double3x3(double3x3), 26 | Double4x4(double4x4), 27 | Float2x2s(Vec), 28 | Float3x3s(Vec), 29 | Float4x4s(Vec), 30 | Double2x2s(Vec), 31 | Double3x3s(Vec), 32 | Double4x4s(Vec), 33 | Texture(Option>) 34 | } 35 | 36 | impl From for Variant 37 | { 38 | #[inline(always)] 39 | fn from(v:bool) -> Self 40 | { 41 | Variant::Boolean(v) 42 | } 43 | } 44 | 45 | impl From for Variant 46 | { 47 | #[inline(always)] 48 | fn from(v:i32_1) -> Self 49 | { 50 | Variant::Int1(v) 51 | } 52 | } 53 | 54 | impl From for Variant 55 | { 56 | #[inline(always)] 57 | fn from(v:i32_2) -> Self 58 | { 59 | Variant::Int2(v) 60 | } 61 | } 62 | 63 | impl From for Variant 64 | { 65 | #[inline(always)] 66 | fn from(v:i32_3) -> Self 67 | { 68 | Variant::Int3(v) 69 | } 70 | } 71 | 72 | impl From for Variant 73 | { 74 | #[inline(always)] 75 | fn from(v:i32_4) -> Self 76 | { 77 | Variant::Int4(v) 78 | } 79 | } 80 | 81 | impl From for Variant 82 | { 83 | #[inline(always)] 84 | fn from(v:u32_1) -> Self 85 | { 86 | Variant::Uint1(v) 87 | } 88 | } 89 | 90 | impl From for Variant 91 | { 92 | #[inline(always)] 93 | fn from(v:u32_2) -> Self 94 | { 95 | Variant::Uint2(v) 96 | } 97 | } 98 | 99 | impl From for Variant 100 | { 101 | #[inline(always)] 102 | fn from(v:u32_3) -> Self 103 | { 104 | Variant::Uint3(v) 105 | } 106 | } 107 | 108 | impl From for Variant 109 | { 110 | #[inline(always)] 111 | fn from(v:u32_4) -> Self 112 | { 113 | Variant::Uint4(v) 114 | } 115 | } 116 | 117 | impl From for Variant 118 | { 119 | #[inline(always)] 120 | fn from(v:float1) -> Self 121 | { 122 | Variant::Float1(v) 123 | } 124 | } 125 | 126 | impl From for Variant 127 | { 128 | #[inline(always)] 129 | fn from(v:float2) -> Self 130 | { 131 | Variant::Float2(v) 132 | } 133 | } 134 | 135 | impl From for Variant 136 | { 137 | #[inline(always)] 138 | fn from(v:float3) -> Self 139 | { 140 | Variant::Float3(v) 141 | } 142 | } 143 | 144 | impl From for Variant 145 | { 146 | #[inline(always)] 147 | fn from(v:float4) -> Self 148 | { 149 | Variant::Float4(v) 150 | } 151 | } 152 | 153 | impl From for Variant 154 | { 155 | #[inline(always)] 156 | fn from(v:float2x2) -> Self 157 | { 158 | Variant::Float2x2(v) 159 | } 160 | } 161 | 162 | impl From for Variant 163 | { 164 | #[inline(always)] 165 | fn from(v:float3x3) -> Self 166 | { 167 | Variant::Float3x3(v) 168 | } 169 | } 170 | 171 | impl From for Variant 172 | { 173 | #[inline(always)] 174 | fn from(v:float4x4) -> Self 175 | { 176 | Variant::Float4x4(v) 177 | } 178 | } 179 | 180 | impl From for Variant 181 | { 182 | #[inline(always)] 183 | fn from(v:double2x2) -> Self 184 | { 185 | Variant::Double2x2(v) 186 | } 187 | } 188 | 189 | impl From for Variant 190 | { 191 | #[inline(always)] 192 | fn from(v:double3x3) -> Self 193 | { 194 | Variant::Double3x3(v) 195 | } 196 | } 197 | 198 | impl From for Variant 199 | { 200 | #[inline(always)] 201 | fn from(v:double4x4) -> Self 202 | { 203 | Variant::Double4x4(v) 204 | } 205 | } 206 | 207 | impl From for Variant 208 | { 209 | #[inline(always)] 210 | fn from(texture:Texture) -> Self 211 | { 212 | Variant::Texture(Some(Arc::new(texture))) 213 | } 214 | } 215 | 216 | impl From>> for Variant 217 | { 218 | #[inline(always)] 219 | fn from(texture:Option>) -> Self 220 | { 221 | Variant::Texture(texture) 222 | } 223 | } -------------------------------------------------------------------------------- /src/scene/geometries/circle.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::sync::Arc; 3 | use std::cell::RefCell; 4 | 5 | use crate::math::*; 6 | use crate::models::VertexWeight; 7 | 8 | use super::super::core::{Resource, Geometry}; 9 | use super::super::util::uuid::OsRandNewV4; 10 | 11 | #[derive(Debug, Serialize, Deserialize)] 12 | pub struct CircleGeometry 13 | { 14 | uuid: uuid::Uuid, 15 | radius:f32, 16 | segments:u32, 17 | theta_start:f32, 18 | theta_length:f32, 19 | vertices:float3s, 20 | normals:float3s, 21 | texcoords:float2s, 22 | indices:Vec, 23 | weights:Vec 24 | } 25 | 26 | impl CircleGeometry 27 | { 28 | pub fn new(radius:f32, segments:u32, theta_start:f32, theta_length:f32) -> Self 29 | { 30 | let mut _vertices = Vec::with_capacity(segments as usize); 31 | let mut _normals = Vec::with_capacity(segments as usize); 32 | let mut _texcoords = Vec::with_capacity(segments as usize); 33 | let mut _indices = Vec::with_capacity((segments - 1) as usize * 3); 34 | 35 | let normal = float!(0.0,0.0,1.0); 36 | 37 | for i in 0..segments 38 | { 39 | let segment = theta_start + i as f32 / segments as f32 * theta_length; 40 | 41 | let v = float3 42 | { 43 | x:radius * f32::cos(segment), 44 | y:radius * f32::sin(segment), 45 | z:0.0, 46 | }; 47 | 48 | _vertices.push(v); 49 | _normals.push(normal); 50 | _texcoords.push(float!(v.x / radius + 1.0, (v.y / radius + 1.0) * 0.5)); 51 | } 52 | 53 | for i in 1..segments 54 | { 55 | let v1 = i; 56 | let v2 = i + 1; 57 | let v3 = 0; 58 | 59 | _indices.push(v1 as u16); 60 | _indices.push(v2 as u16); 61 | _indices.push(v3 as u16); 62 | } 63 | 64 | Self 65 | { 66 | uuid:uuid::Uuid::new_v4_osrng(), 67 | radius:radius, 68 | segments:segments, 69 | theta_start:theta_start, 70 | theta_length:theta_length, 71 | vertices:_vertices, 72 | normals:_normals, 73 | texcoords:_texcoords, 74 | indices:_indices, 75 | weights:Vec::new(), 76 | } 77 | } 78 | 79 | pub fn builder() -> CircleGeometryBuilder 80 | { 81 | CircleGeometryBuilder::new() 82 | } 83 | 84 | pub fn radius(&self) -> f32 85 | { 86 | self.radius 87 | } 88 | 89 | pub fn segments(&self) -> u32 90 | { 91 | self.segments 92 | } 93 | 94 | pub fn theta_start(&self) -> f32 95 | { 96 | self.theta_start 97 | } 98 | 99 | pub fn theta_length(&self) -> f32 100 | { 101 | self.theta_length 102 | } 103 | } 104 | 105 | impl Geometry for CircleGeometry 106 | { 107 | fn vertices(&self) -> &[float3] 108 | { 109 | &self.vertices[..] 110 | } 111 | 112 | fn normals(&self) -> &[float3] 113 | { 114 | &self.normals[..] 115 | } 116 | 117 | fn texcoords(&self) -> &[float2] 118 | { 119 | &self.texcoords[..] 120 | } 121 | 122 | fn indices(&self) -> &[u16] 123 | { 124 | &self.indices[..] 125 | } 126 | 127 | fn weights(&self) -> &[VertexWeight] 128 | { 129 | &self.weights[..] 130 | } 131 | } 132 | 133 | impl Resource for CircleGeometry 134 | { 135 | #[inline] 136 | fn uuid(&self) -> &uuid::Uuid 137 | { 138 | &self.uuid 139 | } 140 | } 141 | 142 | impl From for Rc 143 | { 144 | fn from(shape:CircleGeometry) -> Self 145 | { 146 | Rc::new(shape) 147 | } 148 | } 149 | 150 | impl From for Arc 151 | { 152 | fn from(shape:CircleGeometry) -> Self 153 | { 154 | Arc::new(shape) 155 | } 156 | } 157 | 158 | impl From for Rc> 159 | { 160 | fn from(shape:CircleGeometry) -> Self 161 | { 162 | Rc::new(RefCell::new(shape)) 163 | } 164 | } 165 | 166 | impl From for Arc> 167 | { 168 | fn from(shape:CircleGeometry) -> Self 169 | { 170 | Arc::new(RefCell::new(shape)) 171 | } 172 | } 173 | 174 | pub struct CircleGeometryBuilder 175 | { 176 | radius:f32, 177 | segments:u32, 178 | theta_start:f32, 179 | theta_length:f32, 180 | } 181 | 182 | impl CircleGeometryBuilder 183 | { 184 | #[inline] 185 | pub fn new() -> Self 186 | { 187 | Self 188 | { 189 | radius:1.0, 190 | segments:32, 191 | theta_start:0.0, 192 | theta_length:f32::pi(), 193 | } 194 | } 195 | 196 | #[inline] 197 | pub fn build(self) -> CircleGeometry 198 | { 199 | CircleGeometry::new(self.radius, self.segments, self.theta_start, self.theta_length) 200 | } 201 | 202 | #[inline] 203 | pub fn set_radius(mut self, radius:f32) -> Self 204 | { 205 | self.radius = radius; 206 | self 207 | } 208 | 209 | #[inline] 210 | pub fn set_segments(mut self, segments:u32) -> Self 211 | { 212 | self.segments = segments; 213 | self 214 | } 215 | 216 | #[inline] 217 | pub fn set_theta_start(mut self, theta_start:f32) -> Self 218 | { 219 | self.theta_start = theta_start; 220 | self 221 | } 222 | 223 | #[inline] 224 | pub fn set_theta_length(mut self, theta_length:f32) -> Self 225 | { 226 | self.theta_length = theta_length; 227 | self 228 | } 229 | } -------------------------------------------------------------------------------- /src/scene/geometries/cone.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::sync::Arc; 3 | use std::cell::RefCell; 4 | 5 | use crate::math::*; 6 | use crate::models::VertexWeight; 7 | 8 | use super::super::core::{Resource, Geometry}; 9 | use super::super::util::uuid::OsRandNewV4; 10 | 11 | #[derive(Debug, Serialize, Deserialize)] 12 | pub struct ConeGeometry 13 | { 14 | uuid: uuid::Uuid, 15 | radius:f32, 16 | height:f32, 17 | segments:u32, 18 | theta_start:f32, 19 | theta_length:f32, 20 | vertices:float3s, 21 | normals:float3s, 22 | texcoords:float2s, 23 | indices:Vec, 24 | weights:Vec 25 | } 26 | 27 | impl ConeGeometry 28 | { 29 | pub fn new(radius:f32, height:f32, segments:u32, theta_start:f32, theta_length:f32) -> Self 30 | { 31 | let mut _vertices = Vec::with_capacity(segments as usize + 2); 32 | let mut _normals = Vec::with_capacity(segments as usize + 2); 33 | let mut _texcoords = Vec::with_capacity(segments as usize + 2); 34 | let mut _indices = Vec::with_capacity(segments as usize * 6); 35 | 36 | _vertices.push(float!(0.0, 0.0, 0.0)); 37 | _vertices.push(float!(0.0, height as f32, 0.0)); 38 | 39 | _normals.push(float!(0.0, 0.0, 0.0)); 40 | _normals.push(float!(0.0, 1.0, 0.0)); 41 | 42 | _texcoords.push(float!(0.0, 0.0)); 43 | _texcoords.push(float!(1.0, 1.0)); 44 | 45 | let segment = theta_length / segments as f32; 46 | 47 | for i in 0..segments + 2 48 | { 49 | let sin = f32::sin(theta_start + i as f32 * segment); 50 | let cos = f32::cos(theta_start + i as f32 * segment); 51 | 52 | let v = float3 53 | { 54 | x:radius * cos, 55 | y:0.0, 56 | z:-radius * sin, 57 | }; 58 | 59 | _vertices.push(v); 60 | _normals.push(float!(cos, 0.0, sin)); 61 | _texcoords.push(float!(v.x / radius + 1.0, (v.y / radius + 1.0) * 0.5)); 62 | } 63 | 64 | for i in 2..segments + 2 65 | { 66 | let v1 = i; 67 | let v2 = 0; 68 | let v3 = i + 1; 69 | 70 | _indices.push(v1 as u16); 71 | _indices.push(v2 as u16); 72 | _indices.push(v3 as u16); 73 | } 74 | 75 | for i in 2..segments + 2 76 | { 77 | let v1 = i; 78 | let v2 = 1; 79 | let v3 = i + 1; 80 | 81 | _indices.push(v3 as u16); 82 | _indices.push(v2 as u16); 83 | _indices.push(v1 as u16); 84 | } 85 | 86 | Self 87 | { 88 | uuid:uuid::Uuid::new_v4_osrng(), 89 | radius:radius, 90 | height:height, 91 | segments:segments, 92 | theta_start:theta_start, 93 | theta_length:theta_length, 94 | vertices:_vertices, 95 | normals:_normals, 96 | texcoords:_texcoords, 97 | indices:_indices, 98 | weights:Vec::new() 99 | } 100 | } 101 | 102 | pub fn builder() -> ConeGeometryBuilder 103 | { 104 | ConeGeometryBuilder::new() 105 | } 106 | 107 | pub fn radius(&self) -> f32 108 | { 109 | self.radius 110 | } 111 | 112 | pub fn height(&self) -> f32 113 | { 114 | self.height 115 | } 116 | 117 | pub fn segments(&self) -> u32 118 | { 119 | self.segments 120 | } 121 | 122 | pub fn theta_start(&self) -> f32 123 | { 124 | self.theta_start 125 | } 126 | 127 | pub fn theta_length(&self) -> f32 128 | { 129 | self.theta_length 130 | } 131 | } 132 | 133 | impl Geometry for ConeGeometry 134 | { 135 | fn vertices(&self) -> &[float3] 136 | { 137 | &self.vertices[..] 138 | } 139 | 140 | fn normals(&self) -> &[float3] 141 | { 142 | &self.normals[..] 143 | } 144 | 145 | fn texcoords(&self) -> &[float2] 146 | { 147 | &self.texcoords[..] 148 | } 149 | 150 | fn indices(&self) -> &[u16] 151 | { 152 | &self.indices[..] 153 | } 154 | 155 | fn weights(&self) -> &[VertexWeight] 156 | { 157 | &self.weights[..] 158 | } 159 | } 160 | 161 | impl Resource for ConeGeometry 162 | { 163 | #[inline] 164 | fn uuid(&self) -> &uuid::Uuid 165 | { 166 | &self.uuid 167 | } 168 | } 169 | 170 | impl From for Rc 171 | { 172 | fn from(shape:ConeGeometry) -> Self 173 | { 174 | Rc::new(shape) 175 | } 176 | } 177 | 178 | impl From for Arc 179 | { 180 | fn from(shape:ConeGeometry) -> Self 181 | { 182 | Arc::new(shape) 183 | } 184 | } 185 | 186 | impl From for Rc> 187 | { 188 | fn from(shape:ConeGeometry) -> Self 189 | { 190 | Rc::new(RefCell::new(shape)) 191 | } 192 | } 193 | 194 | impl From for Arc> 195 | { 196 | fn from(shape:ConeGeometry) -> Self 197 | { 198 | Arc::new(RefCell::new(shape)) 199 | } 200 | } 201 | 202 | pub struct ConeGeometryBuilder 203 | { 204 | radius:f32, 205 | height:f32, 206 | segments:u32, 207 | theta_start:f32, 208 | theta_length:f32, 209 | } 210 | 211 | impl ConeGeometryBuilder 212 | { 213 | #[inline] 214 | pub fn new() -> Self 215 | { 216 | Self 217 | { 218 | radius:1.0, 219 | height:1.0, 220 | segments:32, 221 | theta_start:0.0, 222 | theta_length:f32::pi(), 223 | } 224 | } 225 | 226 | #[inline] 227 | pub fn build(self) -> ConeGeometry 228 | { 229 | ConeGeometry::new(self.radius, self.height, self.segments, self.theta_start, self.theta_length) 230 | } 231 | 232 | #[inline] 233 | pub fn set_radius(mut self, radius:f32) -> Self 234 | { 235 | self.radius = radius; 236 | self 237 | } 238 | 239 | #[inline] 240 | pub fn set_height(mut self, height:f32) -> Self 241 | { 242 | self.height = height; 243 | self 244 | } 245 | 246 | #[inline] 247 | pub fn set_segments(mut self, segments:u32) -> Self 248 | { 249 | self.segments = segments; 250 | self 251 | } 252 | 253 | #[inline] 254 | pub fn set_theta_start(mut self, theta_start:f32) -> Self 255 | { 256 | self.theta_start = theta_start; 257 | self 258 | } 259 | 260 | #[inline] 261 | pub fn set_theta_length(mut self, theta_length:f32) -> Self 262 | { 263 | self.theta_length = theta_length; 264 | self 265 | } 266 | } -------------------------------------------------------------------------------- /src/scene/geometries/cube.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::sync::Arc; 3 | use std::cell::RefCell; 4 | 5 | use crate::math::*; 6 | use crate::models::VertexWeight; 7 | 8 | use super::super::core::{Resource, Geometry}; 9 | use super::super::util::uuid::OsRandNewV4; 10 | 11 | #[derive(Debug, Serialize, Deserialize)] 12 | pub struct CubeGeometry 13 | { 14 | uuid: uuid::Uuid, 15 | width:f32, 16 | height:f32, 17 | depth:f32, 18 | width_segments:u32, 19 | height_segments:u32, 20 | depth_segments:u32, 21 | vertices:float3s, 22 | normals:float3s, 23 | texcoords:float2s, 24 | indices:Vec, 25 | weights:Vec 26 | } 27 | 28 | impl CubeGeometry 29 | { 30 | pub fn new(width:f32, height:f32, depth:f32, width_segments:u32, height_segments:u32, depth_segments:u32) -> Self 31 | { 32 | let x = width * 0.5; 33 | let y = height * 0.5; 34 | let z = depth * 0.5; 35 | 36 | let vertices:Vec = vec![ 37 | float!(-x,-y,-z), float!( x,-y,-z), float!( x, y,-z), float!(-x, y,-z), 38 | float!(-x,-y, z), float!( x,-y, z), float!( x, y, z), float!(-x, y, z), 39 | float!(-x,-y,-z), float!(-x, y,-z), float!(-x, y, z), float!(-x,-y, z), 40 | float!( x,-y,-z), float!( x, y,-z), float!( x, y, z), float!( x,-y, z), 41 | float!(-x,-y,-z), float!(-x,-y, z), float!( x,-y, z), float!( x,-y,-z), 42 | float!(-x, y,-z), float!(-x, y, z), float!( x, y, z), float!( x, y,-z), 43 | ]; 44 | 45 | let normals:Vec = vec![ 46 | float!(5.,3.,7.), float!(5.,3.,7.), float!(5.,3.,7.), float!(5.,3.,7.), 47 | float!(1.,1.,3.), float!(1.,1.,3.), float!(1.,1.,3.), float!(1.,1.,3.), 48 | float!(0.,0.,1.), float!(0.,0.,1.), float!(0.,0.,1.), float!(0.,0.,1.), 49 | float!(1.,0.,0.), float!(1.,0.,0.), float!(1.,0.,0.), float!(1.,0.,0.), 50 | float!(1.,1.,0.), float!(1.,1.,0.), float!(1.,1.,0.), float!(1.,1.,0.), 51 | float!(0.,1.,0.), float!(0.,1.,0.), float!(0.,1.,0.), float!(0.,1.,0.) 52 | ]; 53 | 54 | let texcoords:Vec = vec![ 55 | float!(0.0, 0.0), float!(1.0, 0.0), float!(1.0, 1.0), float!(0.0, 1.0), 56 | float!(0.0, 0.0), float!(1.0, 0.0), float!(1.0, 1.0), float!(0.0, 1.0), 57 | float!(0.0, 0.0), float!(1.0, 0.0), float!(1.0, 1.0), float!(0.0, 1.0), 58 | float!(0.0, 0.0), float!(1.0, 0.0), float!(1.0, 1.0), float!(0.0, 1.0), 59 | float!(0.0, 0.0), float!(1.0, 0.0), float!(1.0, 1.0), float!(0.0, 1.0), 60 | float!(0.0, 0.0), float!(1.0, 0.0), float!(1.0, 1.0), float!(0.0, 1.0), 61 | ]; 62 | 63 | let indices:Vec = vec![ 64 | 0,1,2, 0,2,3, 4,5,6, 4,6,7, 65 | 8,9,10, 8,10,11, 12,13,14, 12,14,15, 66 | 16,17,18, 16,18,19, 20,21,22, 20,22,23 67 | ]; 68 | 69 | Self 70 | { 71 | uuid:uuid::Uuid::new_v4_osrng(), 72 | width:width, 73 | height:height, 74 | depth:depth, 75 | width_segments:width_segments, 76 | height_segments:height_segments, 77 | depth_segments:depth_segments, 78 | vertices:vertices, 79 | normals:normals, 80 | texcoords:texcoords, 81 | indices:indices, 82 | weights:Vec::new() 83 | } 84 | } 85 | 86 | pub fn width(&self) -> f32 87 | { 88 | return self.width; 89 | } 90 | 91 | pub fn height(&self) -> f32 92 | { 93 | return self.height; 94 | } 95 | 96 | pub fn depth(&self) -> f32 97 | { 98 | return self.depth; 99 | } 100 | 101 | pub fn width_segments(&self) -> u32 102 | { 103 | return self.width_segments; 104 | } 105 | 106 | pub fn height_segments(&self) -> u32 107 | { 108 | return self.height_segments; 109 | } 110 | 111 | pub fn depth_segments(&self) -> u32 112 | { 113 | return self.depth_segments; 114 | } 115 | } 116 | 117 | impl Geometry for CubeGeometry 118 | { 119 | fn vertices(&self) -> &[float3] 120 | { 121 | &self.vertices[..] 122 | } 123 | 124 | fn normals(&self) -> &[float3] 125 | { 126 | &self.normals[..] 127 | } 128 | 129 | fn texcoords(&self) -> &[float2] 130 | { 131 | &self.texcoords[..] 132 | } 133 | 134 | fn indices(&self) -> &[u16] 135 | { 136 | &self.indices[..] 137 | } 138 | 139 | fn weights(&self) -> &[VertexWeight] 140 | { 141 | &self.weights[..] 142 | } 143 | } 144 | 145 | impl Resource for CubeGeometry 146 | { 147 | #[inline] 148 | fn uuid(&self) -> &uuid::Uuid 149 | { 150 | &self.uuid 151 | } 152 | } 153 | 154 | impl From for Rc 155 | { 156 | fn from(geoemtry:CubeGeometry) -> Self 157 | { 158 | Rc::new(geoemtry) 159 | } 160 | } 161 | 162 | impl From for Arc 163 | { 164 | fn from(geoemtry:CubeGeometry) -> Self 165 | { 166 | Arc::new(geoemtry) 167 | } 168 | } 169 | 170 | impl From for Rc> 171 | { 172 | fn from(geoemtry:CubeGeometry) -> Self 173 | { 174 | Rc::new(RefCell::new(geoemtry)) 175 | } 176 | } 177 | 178 | impl From for Arc> 179 | { 180 | fn from(geoemtry:CubeGeometry) -> Self 181 | { 182 | Arc::new(RefCell::new(geoemtry)) 183 | } 184 | } -------------------------------------------------------------------------------- /src/scene/geometries/fan.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::sync::Arc; 3 | use std::cell::RefCell; 4 | 5 | use crate::math::*; 6 | use crate::models::VertexWeight; 7 | 8 | use super::super::core::{Resource, Geometry}; 9 | use super::super::util::uuid::OsRandNewV4; 10 | 11 | #[derive(Debug, Serialize, Deserialize)] 12 | pub struct FanGeometry 13 | { 14 | uuid: uuid::Uuid, 15 | radius_top:f32, 16 | radius_bottom:f32, 17 | segments:u32, 18 | top_length:f32, 19 | bottom_length:f32, 20 | vertices:float3s, 21 | normals:float3s, 22 | texcoords:float2s, 23 | indices:Vec, 24 | weights:Vec 25 | } 26 | 27 | impl FanGeometry 28 | { 29 | pub fn new(top_radius:f32, bottom_radius:f32, segments:u32, top_length:f32, bottom_length:f32) -> Self 30 | { 31 | let mut _vertices = Vec::with_capacity((segments + 1) as usize * 2); 32 | let mut _normals = Vec::with_capacity((segments + 1) as usize * 2); 33 | let mut _texcoords = Vec::with_capacity((segments + 1) as usize * 2); 34 | let mut _indices = Vec::with_capacity(segments as usize * 6); 35 | 36 | let top_start = -(f32::pi() + bottom_length) * 0.5; 37 | let top_segment = top_length / segments as f32; 38 | 39 | let bottom_start = -(f32::pi() + top_length) * 0.5; 40 | let bottom_segment = bottom_length / segments as f32; 41 | 42 | for i in 0..segments + 1 43 | { 44 | let sin = f32::sin(bottom_start + i as f32 * bottom_segment); 45 | let cos = f32::cos(bottom_start + i as f32 * bottom_segment); 46 | 47 | let v = float!(bottom_radius * cos, -bottom_radius * sin, 0.0); 48 | 49 | _vertices.push(v); 50 | _normals.push(float!(0.0,0.0,1.0)); 51 | _texcoords.push(float!(i as f32 / segments as f32, 1.0)); 52 | } 53 | 54 | for i in 0..segments + 1 55 | { 56 | let sin = f32::sin(top_start + i as f32 * top_segment); 57 | let cos = f32::cos(top_start + i as f32 * top_segment); 58 | 59 | let v = float!(top_radius * cos, -top_radius * sin, 0.0); 60 | 61 | _vertices.push(v); 62 | _normals.push(float!(0.0,0.0,1.0)); 63 | _texcoords.push(float!(i as f32 / segments as f32, 0.0)); 64 | } 65 | 66 | for i in 0..segments 67 | { 68 | let v1 = i; 69 | let v3 = i + 1 + segments; 70 | let v4 = i + 2 + segments; 71 | 72 | _indices.push(v1 as u16); 73 | _indices.push(v3 as u16); 74 | _indices.push(v4 as u16); 75 | } 76 | 77 | for i in 0..segments 78 | { 79 | let v1 = i; 80 | let v2 = i + 1; 81 | let v4 = i + 2 + segments; 82 | 83 | _indices.push(v1 as u16); 84 | _indices.push(v4 as u16); 85 | _indices.push(v2 as u16); 86 | } 87 | 88 | Self 89 | { 90 | uuid:uuid::Uuid::new_v4_osrng(), 91 | radius_top:top_radius, 92 | radius_bottom:bottom_radius, 93 | segments:segments, 94 | top_length:top_length, 95 | bottom_length:bottom_length, 96 | vertices:_vertices, 97 | normals:_normals, 98 | texcoords:_texcoords, 99 | indices:_indices, 100 | weights:Vec::new() 101 | } 102 | } 103 | 104 | pub fn builder() -> FanGeometryBuilder 105 | { 106 | FanGeometryBuilder::new() 107 | } 108 | 109 | pub fn top_radius(&self) -> f32 110 | { 111 | self.radius_top 112 | } 113 | 114 | pub fn top_length(&self) -> f32 115 | { 116 | self.top_length 117 | } 118 | 119 | pub fn bottom_radius(&self) -> f32 120 | { 121 | self.radius_top 122 | } 123 | 124 | pub fn bottom_length(&self) -> f32 125 | { 126 | self.bottom_length 127 | } 128 | 129 | pub fn segments(&self) -> u32 130 | { 131 | self.segments 132 | } 133 | } 134 | 135 | impl Geometry for FanGeometry 136 | { 137 | fn vertices(&self) -> &[float3] 138 | { 139 | &self.vertices[..] 140 | } 141 | 142 | fn normals(&self) -> &[float3] 143 | { 144 | &self.normals[..] 145 | } 146 | 147 | fn texcoords(&self) -> &[float2] 148 | { 149 | &self.texcoords[..] 150 | } 151 | 152 | fn indices(&self) -> &[u16] 153 | { 154 | &self.indices[..] 155 | } 156 | 157 | fn weights(&self) -> &[VertexWeight] 158 | { 159 | &self.weights[..] 160 | } 161 | } 162 | 163 | impl Resource for FanGeometry 164 | { 165 | #[inline] 166 | fn uuid(&self) -> &uuid::Uuid 167 | { 168 | &self.uuid 169 | } 170 | } 171 | 172 | impl From for Rc 173 | { 174 | fn from(shape:FanGeometry) -> Self 175 | { 176 | Rc::new(shape) 177 | } 178 | } 179 | 180 | impl From for Arc 181 | { 182 | fn from(shape:FanGeometry) -> Self 183 | { 184 | Arc::new(shape) 185 | } 186 | } 187 | 188 | impl From for Rc> 189 | { 190 | fn from(shape:FanGeometry) -> Self 191 | { 192 | Rc::new(RefCell::new(shape)) 193 | } 194 | } 195 | 196 | impl From for Arc> 197 | { 198 | fn from(shape:FanGeometry) -> Self 199 | { 200 | Arc::new(RefCell::new(shape)) 201 | } 202 | } 203 | 204 | pub struct FanGeometryBuilder 205 | { 206 | top_radius:f32, 207 | bottom_radius:f32, 208 | segments:u32, 209 | top_length:f32, 210 | bottom_length:f32, 211 | } 212 | 213 | impl FanGeometryBuilder 214 | { 215 | #[inline] 216 | pub fn new() -> Self 217 | { 218 | Self 219 | { 220 | top_radius:1.0, 221 | bottom_radius:1.0, 222 | segments:32, 223 | top_length:0.0, 224 | bottom_length:f32::pi(), 225 | } 226 | } 227 | 228 | #[inline] 229 | pub fn build(self) -> FanGeometry 230 | { 231 | FanGeometry::new(self.top_radius, self.bottom_radius, self.segments, self.top_length, self.bottom_length) 232 | } 233 | 234 | #[inline] 235 | pub fn set_top_radius(mut self, top_radius:f32) -> Self 236 | { 237 | self.top_radius = top_radius; 238 | self 239 | } 240 | 241 | #[inline] 242 | pub fn set_bottom_radius(mut self, bottom_radius:f32) -> Self 243 | { 244 | self.bottom_radius = bottom_radius; 245 | self 246 | } 247 | 248 | #[inline] 249 | pub fn set_segments(mut self, segments:u32) -> Self 250 | { 251 | self.segments = segments; 252 | self 253 | } 254 | 255 | #[inline] 256 | pub fn set_top_length(mut self, top_length:f32) -> Self 257 | { 258 | self.top_length = top_length; 259 | self 260 | } 261 | 262 | #[inline] 263 | pub fn set_bottom_length(mut self, bottom_length:f32) -> Self 264 | { 265 | self.bottom_length = bottom_length; 266 | self 267 | } 268 | } -------------------------------------------------------------------------------- /src/scene/geometries/mesh.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::sync::Arc; 3 | use std::cell::RefCell; 4 | 5 | use crate::math::*; 6 | use crate::models::VertexWeight; 7 | 8 | use super::super::core::{Resource, Geometry}; 9 | use super::super::util::uuid::OsRandNewV4; 10 | 11 | #[derive(Debug, Serialize, Deserialize)] 12 | pub struct MeshGeometry 13 | { 14 | uuid: uuid::Uuid, 15 | vertices:float3s, 16 | normals:float3s, 17 | texcoords:float2s, 18 | indices:Vec, 19 | weights:Vec 20 | } 21 | 22 | impl MeshGeometry 23 | { 24 | pub fn new(vertices:float3s, normals:float3s, texcoords:float2s, weights:Vec, indices:Vec) -> Self 25 | { 26 | Self 27 | { 28 | uuid:uuid::Uuid::new_v4_osrng(), 29 | vertices:vertices, 30 | normals:normals, 31 | texcoords:texcoords, 32 | indices:indices, 33 | weights:weights 34 | } 35 | } 36 | 37 | pub fn builder() -> MeshGeometryBuilder 38 | { 39 | MeshGeometryBuilder::new() 40 | } 41 | } 42 | 43 | impl Geometry for MeshGeometry 44 | { 45 | fn vertices(&self) -> &[float3] 46 | { 47 | &self.vertices[..] 48 | } 49 | 50 | fn normals(&self) -> &[float3] 51 | { 52 | &self.normals[..] 53 | } 54 | 55 | fn texcoords(&self) -> &[float2] 56 | { 57 | &self.texcoords[..] 58 | } 59 | 60 | fn indices(&self) -> &[u16] 61 | { 62 | &self.indices[..] 63 | } 64 | 65 | fn weights(&self) -> &[VertexWeight] 66 | { 67 | &self.weights[..] 68 | } 69 | } 70 | 71 | impl Resource for MeshGeometry 72 | { 73 | #[inline] 74 | fn uuid(&self) -> &uuid::Uuid 75 | { 76 | &self.uuid 77 | } 78 | } 79 | 80 | impl From for Rc 81 | { 82 | fn from(shape:MeshGeometry) -> Self 83 | { 84 | Rc::new(shape) 85 | } 86 | } 87 | 88 | impl From for Arc 89 | { 90 | fn from(shape:MeshGeometry) -> Self 91 | { 92 | Arc::new(shape) 93 | } 94 | } 95 | 96 | impl From for Rc> 97 | { 98 | fn from(shape:MeshGeometry) -> Self 99 | { 100 | Rc::new(RefCell::new(shape)) 101 | } 102 | } 103 | 104 | impl From for Arc> 105 | { 106 | fn from(shape:MeshGeometry) -> Self 107 | { 108 | Arc::new(RefCell::new(shape)) 109 | } 110 | } 111 | 112 | pub struct MeshGeometryBuilder 113 | { 114 | vertices:float3s, 115 | normals:float3s, 116 | texcoords:float2s, 117 | indices:Vec, 118 | weights:Vec 119 | } 120 | 121 | impl MeshGeometryBuilder 122 | { 123 | #[inline] 124 | pub fn new() -> Self 125 | { 126 | Self 127 | { 128 | vertices:Vec::new(), 129 | normals:Vec::new(), 130 | texcoords:Vec::new(), 131 | indices:Vec::new(), 132 | weights:Vec::new(), 133 | } 134 | } 135 | 136 | #[inline] 137 | pub fn build(self) -> MeshGeometry 138 | { 139 | assert_eq!(self.vertices.len(), self.normals.len()); 140 | assert_eq!(self.vertices.len(), self.texcoords.len()); 141 | 142 | MeshGeometry::new(self.vertices, self.normals, self.texcoords, self.weights, self.indices) 143 | } 144 | 145 | #[inline] 146 | pub fn vertices_capacity(mut self, num_vertices:usize) -> Self 147 | { 148 | self.vertices = Vec::with_capacity(num_vertices); 149 | self 150 | } 151 | 152 | #[inline] 153 | pub fn normals_capacity(mut self, num_normals:usize) -> Self 154 | { 155 | self.normals = Vec::with_capacity(num_normals); 156 | self 157 | } 158 | 159 | #[inline] 160 | pub fn texcoords_capacity(mut self, num_texcoords:usize) -> Self 161 | { 162 | self.texcoords = Vec::with_capacity(num_texcoords); 163 | self 164 | } 165 | 166 | #[inline] 167 | pub fn weights_capacity(mut self, num_weights:usize) -> Self 168 | { 169 | self.weights = Vec::with_capacity(num_weights); 170 | self 171 | } 172 | 173 | #[inline] 174 | pub fn set_vertices(mut self, vertices:float3s) -> Self 175 | { 176 | self.vertices = vertices; 177 | self 178 | } 179 | 180 | #[inline] 181 | pub fn set_normals(mut self, normals:float3s) -> Self 182 | { 183 | self.normals = normals; 184 | self 185 | } 186 | 187 | #[inline] 188 | pub fn set_texcoords(mut self, texcoords:float2s) -> Self 189 | { 190 | self.texcoords = texcoords; 191 | self 192 | } 193 | 194 | #[inline] 195 | pub fn set_indices(mut self, indices:Vec) -> Self 196 | { 197 | self.indices = indices; 198 | self 199 | } 200 | 201 | #[inline] 202 | pub fn set_weights(mut self, weights:Vec) -> Self 203 | { 204 | self.weights = weights; 205 | self 206 | } 207 | 208 | #[inline] 209 | pub fn add_vertex(mut self, v:float3) -> Self 210 | { 211 | self.vertices.push(v); 212 | self 213 | } 214 | 215 | #[inline] 216 | pub fn add_normal(mut self, n:float3) -> Self 217 | { 218 | self.normals.push(n); 219 | self 220 | } 221 | 222 | #[inline] 223 | pub fn add_texcoord(mut self, uv:float2) -> Self 224 | { 225 | self.texcoords.push(uv); 226 | self 227 | } 228 | 229 | #[inline] 230 | pub fn add_indice(mut self, index:u16) -> Self 231 | { 232 | self.indices.push(index); 233 | self 234 | } 235 | } -------------------------------------------------------------------------------- /src/scene/geometries/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod cube; 2 | pub mod sphere; 3 | pub mod plane; 4 | pub mod circle; 5 | pub mod cone; 6 | pub mod cylinder; 7 | pub mod fan; 8 | pub mod mesh; 9 | 10 | pub use self::cube::*; 11 | pub use self::sphere::*; 12 | pub use self::plane::*; 13 | pub use self::circle::*; 14 | pub use self::cone::*; 15 | pub use self::cylinder::*; 16 | pub use self::fan::*; 17 | pub use self::mesh::*; -------------------------------------------------------------------------------- /src/scene/geometries/plane.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::sync::Arc; 3 | use std::cell::RefCell; 4 | 5 | use crate::math::*; 6 | use crate::models::VertexWeight; 7 | 8 | use super::super::core::{Resource, Geometry}; 9 | use super::super::util::uuid::OsRandNewV4; 10 | 11 | #[derive(Debug, Serialize, Deserialize)] 12 | pub struct PlaneGeometry 13 | { 14 | uuid: uuid::Uuid, 15 | width:f32, 16 | height:f32, 17 | width_segments:u32, 18 | height_segments:u32, 19 | vertices:float3s, 20 | normals:float3s, 21 | texcoords:float2s, 22 | indices:Vec, 23 | weights:Vec 24 | } 25 | 26 | impl PlaneGeometry 27 | { 28 | pub fn new(width:f32, height:f32, width_segments:u32, height_segments:u32) -> Self 29 | { 30 | let capacity = (width_segments * height_segments) as usize; 31 | let capacity_inc = ((width_segments + 1) * (height_segments + 1)) as usize; 32 | 33 | let mut _vertices = Vec::with_capacity(capacity_inc); 34 | let mut _normals = Vec::with_capacity(capacity_inc); 35 | let mut _texcoords = Vec::with_capacity(capacity * 4); 36 | let mut _indices = Vec::with_capacity(capacity * 6); 37 | 38 | let grid = (width_segments, height_segments); 39 | let grid1 = (grid.0 + 1, grid.1 + 1); 40 | 41 | let width_half = width * 0.5; 42 | let height_half = height * 0.5; 43 | let segment_width = width / grid.0 as f32; 44 | let segment_height = height / grid.1 as f32; 45 | 46 | let normal = float!(0.0,1.0,0.0); 47 | 48 | for iz in 0..grid1.1 49 | { 50 | for ix in 0..grid1.0 51 | { 52 | let x = ix as f32 * segment_width - width_half; 53 | let z = iz as f32 * segment_height - height_half; 54 | 55 | _vertices.push(float!(x, 0.0, z)); 56 | _normals.push(normal); 57 | } 58 | } 59 | 60 | for iy in 0..grid.1 61 | { 62 | for ix in 0..grid.0 63 | { 64 | let fx = ix as f32; 65 | let fy = iy as f32; 66 | 67 | let a = ix + grid1.0 * iy; 68 | let b = ix + grid1.0 * (iy + 1); 69 | let c = ix + grid1.0 * (iy + 1) + 1; 70 | let d = ix + grid1.0 * iy + 1; 71 | 72 | _texcoords.push(float!((fx ) / grid.0 as f32, (fy + 1.0) / grid.1 as f32)); 73 | _texcoords.push(float!((fx + 1.0) / grid.0 as f32, (fy + 1.0) / grid.1 as f32)); 74 | _texcoords.push(float!((fx ) / grid.0 as f32, (fy ) / grid.1 as f32)); 75 | _texcoords.push(float!((fx + 1.0) / grid.0 as f32, (fy ) / grid.1 as f32)); 76 | 77 | _indices.push(a as u16); 78 | _indices.push(b as u16); 79 | _indices.push(c as u16); 80 | 81 | _indices.push(c as u16); 82 | _indices.push(d as u16); 83 | _indices.push(a as u16); 84 | } 85 | } 86 | 87 | Self 88 | { 89 | uuid:uuid::Uuid::new_v4_osrng(), 90 | width:width, 91 | height:height, 92 | width_segments:width_segments, 93 | height_segments:height_segments, 94 | vertices:_vertices, 95 | normals:_normals, 96 | texcoords:_texcoords, 97 | indices:_indices, 98 | weights:Vec::new() 99 | } 100 | } 101 | 102 | pub fn builder() -> PlaneGeometryBuilder 103 | { 104 | PlaneGeometryBuilder::new() 105 | } 106 | 107 | pub fn width(&self) -> f32 108 | { 109 | return self.width; 110 | } 111 | 112 | pub fn height(&self) -> f32 113 | { 114 | return self.height; 115 | } 116 | 117 | pub fn width_segments(&self) -> u32 118 | { 119 | return self.width_segments; 120 | } 121 | 122 | pub fn height_segments(&self) -> u32 123 | { 124 | return self.height_segments; 125 | } 126 | } 127 | 128 | impl Geometry for PlaneGeometry 129 | { 130 | fn vertices(&self) -> &[float3] 131 | { 132 | &self.vertices[..] 133 | } 134 | 135 | fn normals(&self) -> &[float3] 136 | { 137 | &self.normals[..] 138 | } 139 | 140 | fn texcoords(&self) -> &[float2] 141 | { 142 | &self.texcoords[..] 143 | } 144 | 145 | fn indices(&self) -> &[u16] 146 | { 147 | &self.indices[..] 148 | } 149 | 150 | fn weights(&self) -> &[VertexWeight] 151 | { 152 | &self.weights[..] 153 | } 154 | } 155 | 156 | impl Resource for PlaneGeometry 157 | { 158 | #[inline] 159 | fn uuid(&self) -> &uuid::Uuid 160 | { 161 | &self.uuid 162 | } 163 | } 164 | 165 | impl From for Rc 166 | { 167 | fn from(geoemtry:PlaneGeometry) -> Self 168 | { 169 | Rc::new(geoemtry) 170 | } 171 | } 172 | 173 | impl From for Arc 174 | { 175 | fn from(geoemtry:PlaneGeometry) -> Self 176 | { 177 | Arc::new(geoemtry) 178 | } 179 | } 180 | 181 | impl From for Rc> 182 | { 183 | fn from(geoemtry:PlaneGeometry) -> Self 184 | { 185 | Rc::new(RefCell::new(geoemtry)) 186 | } 187 | } 188 | 189 | impl From for Arc> 190 | { 191 | fn from(geoemtry:PlaneGeometry) -> Self 192 | { 193 | Arc::new(RefCell::new(geoemtry)) 194 | } 195 | } 196 | 197 | pub struct PlaneGeometryBuilder 198 | { 199 | width:f32, 200 | height:f32, 201 | width_segments:u32, 202 | height_segments:u32, 203 | } 204 | 205 | impl PlaneGeometryBuilder 206 | { 207 | #[inline] 208 | pub fn new() -> Self 209 | { 210 | Self 211 | { 212 | width:1.0, 213 | height:1.0, 214 | width_segments:1, 215 | height_segments:1, 216 | } 217 | } 218 | 219 | #[inline] 220 | pub fn build(self) -> PlaneGeometry 221 | { 222 | PlaneGeometry::new(self.width, self.height, self.width_segments, self.height_segments) 223 | } 224 | 225 | #[inline] 226 | pub fn set_width(mut self, width:f32) -> Self 227 | { 228 | self.width = width; 229 | self 230 | } 231 | 232 | #[inline] 233 | pub fn set_height(mut self, height:f32) -> Self 234 | { 235 | self.height = height; 236 | self 237 | } 238 | 239 | #[inline] 240 | pub fn set_width_segments(mut self, width_segments:u32) -> Self 241 | { 242 | self.width_segments = width_segments; 243 | self 244 | } 245 | 246 | #[inline] 247 | pub fn set_height_segments(mut self, height_segments:u32) -> Self 248 | { 249 | self.height_segments = height_segments; 250 | self 251 | } 252 | } -------------------------------------------------------------------------------- /src/scene/lights/directional.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::sync::Arc; 3 | use std::cell::RefCell; 4 | use std::any::Any; 5 | 6 | use crate::math::*; 7 | 8 | use super::super::core::*; 9 | use super::super::spectrum::*; 10 | use super::super::scene::{ SceneNode, SceneSubData }; 11 | 12 | #[derive(Debug)] 13 | pub struct DirectionalLight 14 | { 15 | pub node:SceneNode, 16 | pub spectrum:Spectrum, 17 | pub intensity:f32, 18 | pub direction:float3 19 | } 20 | 21 | impl DirectionalLight 22 | { 23 | #[inline] 24 | pub fn new() -> Self 25 | { 26 | let userdata = LightData 27 | { 28 | kind:LightType::Directional, 29 | color:Spectrum::one(), 30 | intensity:1.0, 31 | radiance:None, 32 | irradiance:None, 33 | cos_angle:0.0, 34 | direction:-float3::unit_y() 35 | }; 36 | 37 | let mut node = SceneNode::new(SceneSubData::Light); 38 | node.set_user_data(Box::new(userdata)); 39 | 40 | Self 41 | { 42 | node:node, 43 | spectrum:Spectrum::one(), 44 | intensity:1.0, 45 | direction:-float3::unit_y(), 46 | } 47 | } 48 | 49 | #[inline(always)] 50 | pub fn builder() -> DirectionalLightBuilder 51 | { 52 | DirectionalLightBuilder::new() 53 | } 54 | 55 | #[inline(always)] 56 | pub fn direction(&self) -> float3 57 | { 58 | self.direction 59 | } 60 | 61 | #[inline(always)] 62 | pub fn set_direction(&mut self, dir:float3) -> &mut Self 63 | { 64 | self.direction = dir; 65 | 66 | match self.node.data.borrow_mut().user_data.downcast_mut::() 67 | { 68 | Some(data) => { data.direction = self.direction; }, 69 | None => {}, 70 | } 71 | 72 | self 73 | } 74 | } 75 | 76 | impl Light for DirectionalLight 77 | { 78 | fn kind(&self) -> LightType 79 | { 80 | LightType::Directional 81 | } 82 | 83 | fn color(&self) -> Spectrum 84 | { 85 | self.spectrum 86 | } 87 | 88 | fn intensity(&self) -> f32 89 | { 90 | self.intensity 91 | } 92 | 93 | fn set_color(&mut self, spectrum:Spectrum) 94 | { 95 | self.spectrum = spectrum; 96 | 97 | match self.node.data.borrow_mut().user_data.downcast_mut::() 98 | { 99 | Some(data) => { data.color = self.spectrum; }, 100 | None => {}, 101 | } 102 | } 103 | 104 | fn set_intensity(&mut self, intensity:f32) 105 | { 106 | self.intensity = intensity; 107 | 108 | match self.node.data.borrow_mut().user_data.downcast_mut::() 109 | { 110 | Some(data) => { data.intensity = self.intensity; }, 111 | None => {}, 112 | } 113 | } 114 | } 115 | 116 | impl Object for DirectionalLight 117 | { 118 | } 119 | 120 | impl Resource for DirectionalLight 121 | { 122 | #[inline] 123 | fn uuid(&self) -> &uuid::Uuid 124 | { 125 | self.node.uuid() 126 | } 127 | } 128 | 129 | impl Downcast for DirectionalLight 130 | { 131 | fn as_any(&self) -> &Any { self } 132 | fn as_any_mut(&mut self) -> &mut Any { self } 133 | } 134 | 135 | impl AsRef for DirectionalLight 136 | { 137 | fn as_ref(&self) -> &SceneNode 138 | { 139 | &self.node 140 | } 141 | } 142 | 143 | impl AsMut for DirectionalLight 144 | { 145 | fn as_mut(&mut self) -> &mut SceneNode 146 | { 147 | &mut self.node 148 | } 149 | } 150 | 151 | impl From for Box 152 | { 153 | fn from(light:DirectionalLight) -> Self 154 | { 155 | Box::new(light) 156 | } 157 | } 158 | 159 | impl From for Rc 160 | { 161 | fn from(light:DirectionalLight) -> Self 162 | { 163 | Rc::new(light) 164 | } 165 | } 166 | 167 | impl From for Arc 168 | { 169 | fn from(light:DirectionalLight) -> Self 170 | { 171 | Arc::new(light) 172 | } 173 | } 174 | 175 | impl From for Rc> 176 | { 177 | fn from(light:DirectionalLight) -> Self 178 | { 179 | Rc::new(RefCell::new(light)) 180 | } 181 | } 182 | 183 | impl From for Arc> 184 | { 185 | fn from(light:DirectionalLight) -> Self 186 | { 187 | Arc::new(RefCell::new(light)) 188 | } 189 | } 190 | 191 | pub struct DirectionalLightBuilder 192 | { 193 | light:DirectionalLight 194 | } 195 | 196 | impl DirectionalLightBuilder 197 | { 198 | #[inline] 199 | pub fn new() -> Self 200 | { 201 | Self 202 | { 203 | light:DirectionalLight::new() 204 | } 205 | } 206 | 207 | #[inline] 208 | pub fn build(self) -> DirectionalLight 209 | { 210 | self.light 211 | } 212 | 213 | #[inline] 214 | pub fn set_direction(mut self, dir:float3) -> Self 215 | { 216 | self.light.set_direction(dir); 217 | self 218 | } 219 | 220 | #[inline] 221 | pub fn set_color(mut self, spectrum:Spectrum) -> Self 222 | { 223 | self.light.set_color(spectrum); 224 | self 225 | } 226 | 227 | #[inline] 228 | pub fn set_intensity(mut self, intensity:f32) -> Self 229 | { 230 | self.light.set_intensity(intensity); 231 | self 232 | } 233 | 234 | #[inline] 235 | pub fn set_translate(mut self, pos:float3) -> Self 236 | { 237 | self.light.set_translate(pos); 238 | self 239 | } 240 | 241 | #[inline] 242 | pub fn set_scale(mut self, sz:float3) -> Self 243 | { 244 | self.light.set_scale(sz); 245 | self 246 | } 247 | 248 | #[inline] 249 | pub fn set_rotation(mut self, rot:float3) -> Self 250 | { 251 | self.light.set_rotation(rot); 252 | self 253 | } 254 | } -------------------------------------------------------------------------------- /src/scene/lights/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod sky; 2 | pub mod point; 3 | pub mod spot; 4 | pub mod directional; 5 | 6 | pub use self::sky::*; 7 | pub use self::point::*; 8 | pub use self::spot::*; 9 | pub use self::directional::*; -------------------------------------------------------------------------------- /src/scene/lights/point.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::sync::Arc; 3 | use std::cell::RefCell; 4 | use std::any::Any; 5 | 6 | use crate::math::*; 7 | 8 | use super::super::core::*; 9 | use super::super::spectrum::*; 10 | use super::super::scene::{ SceneNode, SceneSubData }; 11 | 12 | #[derive(Debug)] 13 | pub struct PointLight 14 | { 15 | pub node:SceneNode, 16 | pub spectrum:Spectrum, 17 | pub intensity:f32, 18 | } 19 | 20 | impl PointLight 21 | { 22 | #[inline] 23 | pub fn new() -> Self 24 | { 25 | let userdata = LightData 26 | { 27 | kind:LightType::Point, 28 | color:Spectrum::one(), 29 | intensity:1.0, 30 | radiance:None, 31 | irradiance:None, 32 | cos_angle:0.0, 33 | direction:-float3::unit_y() 34 | }; 35 | 36 | let mut node = SceneNode::new(SceneSubData::Light); 37 | node.set_user_data(Box::new(userdata)); 38 | 39 | Self 40 | { 41 | node:node, 42 | spectrum:Spectrum::one(), 43 | intensity:1.0, 44 | } 45 | } 46 | 47 | #[inline] 48 | pub fn builder() -> PointLightBuilder 49 | { 50 | PointLightBuilder::new() 51 | } 52 | } 53 | 54 | impl Light for PointLight 55 | { 56 | fn kind(&self) -> LightType 57 | { 58 | LightType::Point 59 | } 60 | 61 | fn color(&self) -> Spectrum 62 | { 63 | self.spectrum 64 | } 65 | 66 | fn intensity(&self) -> f32 67 | { 68 | self.intensity 69 | } 70 | 71 | fn set_color(&mut self, spectrum:Spectrum) 72 | { 73 | self.spectrum = spectrum; 74 | 75 | match self.node.data.borrow_mut().user_data.downcast_mut::() 76 | { 77 | Some(data) => { data.color = self.spectrum; }, 78 | None => {}, 79 | } 80 | } 81 | 82 | fn set_intensity(&mut self, intensity:f32) 83 | { 84 | self.intensity = intensity; 85 | 86 | match self.node.data.borrow_mut().user_data.downcast_mut::() 87 | { 88 | Some(data) => { data.intensity = self.intensity; }, 89 | None => {}, 90 | } 91 | } 92 | } 93 | 94 | impl Object for PointLight 95 | { 96 | } 97 | 98 | impl Resource for PointLight 99 | { 100 | #[inline] 101 | fn uuid(&self) -> &uuid::Uuid 102 | { 103 | self.node.uuid() 104 | } 105 | } 106 | 107 | impl Downcast for PointLight 108 | { 109 | fn as_any(&self) -> &Any { self } 110 | fn as_any_mut(&mut self) -> &mut Any { self } 111 | } 112 | 113 | impl AsRef for PointLight 114 | { 115 | fn as_ref(&self) -> &SceneNode 116 | { 117 | &self.node 118 | } 119 | } 120 | 121 | impl AsMut for PointLight 122 | { 123 | fn as_mut(&mut self) -> &mut SceneNode 124 | { 125 | &mut self.node 126 | } 127 | } 128 | 129 | impl From for Box 130 | { 131 | fn from(light:PointLight) -> Self 132 | { 133 | Box::new(light) 134 | } 135 | } 136 | 137 | impl From for Rc 138 | { 139 | fn from(light:PointLight) -> Self 140 | { 141 | Rc::new(light) 142 | } 143 | } 144 | 145 | impl From for Arc 146 | { 147 | fn from(light:PointLight) -> Self 148 | { 149 | Arc::new(light) 150 | } 151 | } 152 | 153 | impl From for Rc> 154 | { 155 | fn from(light:PointLight) -> Self 156 | { 157 | Rc::new(RefCell::new(light)) 158 | } 159 | } 160 | 161 | impl From for Arc> 162 | { 163 | fn from(light:PointLight) -> Self 164 | { 165 | Arc::new(RefCell::new(light)) 166 | } 167 | } 168 | 169 | pub struct PointLightBuilder 170 | { 171 | light:PointLight 172 | } 173 | 174 | impl PointLightBuilder 175 | { 176 | #[inline] 177 | pub fn new() -> Self 178 | { 179 | Self 180 | { 181 | light:PointLight::new() 182 | } 183 | } 184 | 185 | #[inline] 186 | pub fn build(self) -> PointLight 187 | { 188 | self.light 189 | } 190 | 191 | #[inline] 192 | pub fn set_color(mut self, spectrum:Spectrum) -> Self 193 | { 194 | self.light.set_color(spectrum); 195 | self 196 | } 197 | 198 | #[inline] 199 | pub fn set_intensity(mut self, intensity:f32) -> Self 200 | { 201 | self.light.set_intensity(intensity); 202 | self 203 | } 204 | 205 | #[inline] 206 | pub fn set_translate(mut self, pos:float3) -> Self 207 | { 208 | self.light.set_translate(pos); 209 | self 210 | } 211 | 212 | #[inline] 213 | pub fn set_scale(mut self, sz:float3) -> Self 214 | { 215 | self.light.set_scale(sz); 216 | self 217 | } 218 | 219 | #[inline] 220 | pub fn set_rotation(mut self, rot:float3) -> Self 221 | { 222 | self.light.set_rotation(rot); 223 | self 224 | } 225 | } -------------------------------------------------------------------------------- /src/scene/lights/sky.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::sync::Arc; 3 | use std::cell::RefCell; 4 | use std::any::Any; 5 | 6 | use crate::math::*; 7 | 8 | use super::super::core::*; 9 | use super::super::spectrum::*; 10 | use super::super::scene::{ SceneNode, SceneSubData }; 11 | 12 | #[derive(Debug)] 13 | pub struct SkyLight 14 | { 15 | pub node:SceneNode, 16 | pub spectrum:Spectrum, 17 | pub intensity:f32, 18 | } 19 | 20 | impl SkyLight 21 | { 22 | #[inline] 23 | pub fn new(irradiance:Arc, radiance:Arc) -> Self 24 | { 25 | let userdata = LightData 26 | { 27 | kind:LightType::Sky, 28 | color:Spectrum::one(), 29 | intensity:1.0, 30 | radiance:Some(irradiance), 31 | irradiance:Some(radiance), 32 | cos_angle:0.0, 33 | direction:-float3::unit_y() 34 | }; 35 | 36 | let mut node = SceneNode::new(SceneSubData::Light); 37 | node.set_user_data(Box::new(userdata)); 38 | 39 | Self 40 | { 41 | node:node, 42 | spectrum:Spectrum::one(), 43 | intensity:1.0, 44 | } 45 | } 46 | 47 | #[inline(always)] 48 | pub fn builder(irradiance:Arc, radiance:Arc) -> SkyLightBuilder 49 | { 50 | SkyLightBuilder::new(irradiance, radiance) 51 | } 52 | 53 | #[inline(always)] 54 | pub fn irradiance(&self) -> Arc 55 | { 56 | match self.node.data.borrow().user_data.downcast_ref::() 57 | { 58 | Some(data) => { data.irradiance.as_ref().unwrap().clone() }, 59 | None => { panic!("No irradiance map"); }, 60 | } 61 | } 62 | 63 | #[inline(always)] 64 | pub fn radiance(&self) -> Arc 65 | { 66 | match self.node.data.borrow().user_data.downcast_ref::() 67 | { 68 | Some(data) => { data.radiance.as_ref().unwrap().clone() }, 69 | None => { panic!("No radiance map"); }, 70 | } 71 | } 72 | } 73 | 74 | impl Light for SkyLight 75 | { 76 | fn kind(&self) -> LightType 77 | { 78 | LightType::Sky 79 | } 80 | 81 | fn color(&self) -> Spectrum 82 | { 83 | self.spectrum 84 | } 85 | 86 | fn intensity(&self) -> f32 87 | { 88 | self.intensity 89 | } 90 | 91 | fn set_color(&mut self, spectrum:Spectrum) 92 | { 93 | self.spectrum = spectrum; 94 | 95 | match self.node.data.borrow_mut().user_data.downcast_mut::() 96 | { 97 | Some(data) => { data.color = self.spectrum; }, 98 | None => {}, 99 | } 100 | } 101 | 102 | fn set_intensity(&mut self, intensity:f32) 103 | { 104 | self.intensity = intensity; 105 | 106 | match self.node.data.borrow_mut().user_data.downcast_mut::() 107 | { 108 | Some(data) => { data.intensity = self.intensity; }, 109 | None => {}, 110 | } 111 | } 112 | } 113 | 114 | impl Resource for SkyLight 115 | { 116 | #[inline] 117 | fn uuid(&self) -> &uuid::Uuid 118 | { 119 | self.node.uuid() 120 | } 121 | } 122 | 123 | impl Object for SkyLight 124 | { 125 | } 126 | 127 | impl Downcast for SkyLight 128 | { 129 | fn as_any(&self) -> &Any { self } 130 | fn as_any_mut(&mut self) -> &mut Any { self } 131 | } 132 | 133 | impl AsRef for SkyLight 134 | { 135 | fn as_ref(&self) -> &SceneNode 136 | { 137 | &self.node 138 | } 139 | } 140 | 141 | impl AsMut for SkyLight 142 | { 143 | fn as_mut(&mut self) -> &mut SceneNode 144 | { 145 | &mut self.node 146 | } 147 | } 148 | 149 | impl From for Box 150 | { 151 | fn from(light:SkyLight) -> Self 152 | { 153 | Box::new(light) 154 | } 155 | } 156 | 157 | impl From for Rc 158 | { 159 | fn from(light:SkyLight) -> Self 160 | { 161 | Rc::new(light) 162 | } 163 | } 164 | 165 | impl From for Arc 166 | { 167 | fn from(light:SkyLight) -> Self 168 | { 169 | Arc::new(light) 170 | } 171 | } 172 | 173 | impl From for Rc> 174 | { 175 | fn from(light:SkyLight) -> Self 176 | { 177 | Rc::new(RefCell::new(light)) 178 | } 179 | } 180 | 181 | impl From for Arc> 182 | { 183 | fn from(light:SkyLight) -> Self 184 | { 185 | Arc::new(RefCell::new(light)) 186 | } 187 | } 188 | 189 | pub struct SkyLightBuilder 190 | { 191 | light:SkyLight 192 | } 193 | 194 | impl SkyLightBuilder 195 | { 196 | #[inline] 197 | pub fn new(irradiance:Arc, radiance:Arc) -> Self 198 | { 199 | Self 200 | { 201 | light:SkyLight::new(irradiance, radiance) 202 | } 203 | } 204 | 205 | #[inline] 206 | pub fn build(self) -> SkyLight 207 | { 208 | self.light 209 | } 210 | 211 | #[inline] 212 | pub fn set_color(mut self, spectrum:Spectrum) -> Self 213 | { 214 | self.light.set_color(spectrum); 215 | self 216 | } 217 | 218 | #[inline] 219 | pub fn set_intensity(mut self, intensity:f32) -> Self 220 | { 221 | self.light.set_intensity(intensity); 222 | self 223 | } 224 | 225 | #[inline] 226 | pub fn set_translate(mut self, pos:float3) -> Self 227 | { 228 | self.light.set_translate(pos); 229 | self 230 | } 231 | 232 | #[inline] 233 | pub fn set_scale(mut self, sz:float3) -> Self 234 | { 235 | self.light.set_scale(sz); 236 | self 237 | } 238 | 239 | #[inline] 240 | pub fn set_rotation(mut self, rot:float3) -> Self 241 | { 242 | self.light.set_rotation(rot); 243 | self 244 | } 245 | } -------------------------------------------------------------------------------- /src/scene/lights/spot.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::sync::Arc; 3 | use std::cell::RefCell; 4 | use std::any::Any; 5 | 6 | use crate::math::*; 7 | 8 | use super::super::core::*; 9 | use super::super::spectrum::*; 10 | use super::super::scene::{ SceneNode, SceneSubData }; 11 | 12 | #[derive(Debug)] 13 | pub struct SpotLight 14 | { 15 | pub node:SceneNode, 16 | pub spectrum:Spectrum, 17 | pub intensity:f32, 18 | pub direction:float3, 19 | pub angle:f32 20 | } 21 | 22 | impl SpotLight 23 | { 24 | #[inline] 25 | pub fn new() -> Self 26 | { 27 | let userdata = LightData 28 | { 29 | kind:LightType::Spot, 30 | color:Spectrum::one(), 31 | intensity:1.0, 32 | radiance:None, 33 | irradiance:None, 34 | cos_angle:70.0, 35 | direction:-float3::unit_y() 36 | }; 37 | 38 | let mut node = SceneNode::new(SceneSubData::Light); 39 | node.set_user_data(Box::new(userdata)); 40 | 41 | Self 42 | { 43 | node:SceneNode::new(SceneSubData::Light), 44 | spectrum:Spectrum::one(), 45 | intensity:1.0, 46 | direction:-float3::unit_y(), 47 | angle:70.0 48 | } 49 | } 50 | 51 | #[inline(always)] 52 | pub fn builder() -> SpotLightBuilder 53 | { 54 | SpotLightBuilder::new() 55 | } 56 | 57 | #[inline(always)] 58 | pub fn direction(&self) -> float3 59 | { 60 | self.direction 61 | } 62 | 63 | #[inline(always)] 64 | pub fn set_direction(&mut self, dir:float3) -> &mut Self 65 | { 66 | self.direction = dir; 67 | 68 | match self.node.data.borrow_mut().user_data.downcast_mut::() 69 | { 70 | Some(data) => { data.direction = self.direction; }, 71 | None => {}, 72 | } 73 | 74 | self 75 | } 76 | 77 | #[inline(always)] 78 | pub fn angle(&self) -> f32 79 | { 80 | self.angle 81 | } 82 | 83 | #[inline(always)] 84 | pub fn cos_angle(&self) -> f32 85 | { 86 | self.angle.to_degrees().cos() 87 | } 88 | 89 | #[inline(always)] 90 | pub fn set_angle(&mut self, angle:f32) -> &mut Self 91 | { 92 | self.angle = angle; 93 | 94 | match self.node.data.borrow_mut().user_data.downcast_mut::() 95 | { 96 | Some(data) => { data.cos_angle = self.cos_angle(); }, 97 | None => {}, 98 | } 99 | 100 | self 101 | } 102 | } 103 | 104 | impl Light for SpotLight 105 | { 106 | fn kind(&self) -> LightType 107 | { 108 | LightType::Spot 109 | } 110 | 111 | fn color(&self) -> Spectrum 112 | { 113 | self.spectrum 114 | } 115 | 116 | fn intensity(&self) -> f32 117 | { 118 | self.intensity 119 | } 120 | 121 | fn set_color(&mut self, spectrum:Spectrum) 122 | { 123 | self.spectrum = spectrum; 124 | 125 | match self.node.data.borrow_mut().user_data.downcast_mut::() 126 | { 127 | Some(data) => { data.color = self.spectrum; }, 128 | None => {}, 129 | } 130 | } 131 | 132 | fn set_intensity(&mut self, intensity:f32) 133 | { 134 | self.intensity = intensity; 135 | 136 | match self.node.data.borrow_mut().user_data.downcast_mut::() 137 | { 138 | Some(data) => { data.intensity = self.intensity; }, 139 | None => {}, 140 | } 141 | } 142 | } 143 | 144 | impl Object for SpotLight 145 | { 146 | } 147 | 148 | impl Resource for SpotLight 149 | { 150 | #[inline] 151 | fn uuid(&self) -> &uuid::Uuid 152 | { 153 | self.node.uuid() 154 | } 155 | } 156 | 157 | impl Downcast for SpotLight 158 | { 159 | fn as_any(&self) -> &Any { self } 160 | fn as_any_mut(&mut self) -> &mut Any { self } 161 | } 162 | 163 | impl AsRef for SpotLight 164 | { 165 | fn as_ref(&self) -> &SceneNode 166 | { 167 | &self.node 168 | } 169 | } 170 | 171 | impl AsMut for SpotLight 172 | { 173 | fn as_mut(&mut self) -> &mut SceneNode 174 | { 175 | &mut self.node 176 | } 177 | } 178 | 179 | impl From for Box 180 | { 181 | fn from(light:SpotLight) -> Self 182 | { 183 | Box::new(light) 184 | } 185 | } 186 | 187 | impl From for Rc 188 | { 189 | fn from(light:SpotLight) -> Self 190 | { 191 | Rc::new(light) 192 | } 193 | } 194 | 195 | impl From for Arc 196 | { 197 | fn from(light:SpotLight) -> Self 198 | { 199 | Arc::new(light) 200 | } 201 | } 202 | 203 | impl From for Rc> 204 | { 205 | fn from(light:SpotLight) -> Self 206 | { 207 | Rc::new(RefCell::new(light)) 208 | } 209 | } 210 | 211 | impl From for Arc> 212 | { 213 | fn from(light:SpotLight) -> Self 214 | { 215 | Arc::new(RefCell::new(light)) 216 | } 217 | } 218 | 219 | pub struct SpotLightBuilder 220 | { 221 | light:SpotLight 222 | } 223 | 224 | impl SpotLightBuilder 225 | { 226 | #[inline] 227 | pub fn new() -> Self 228 | { 229 | Self 230 | { 231 | light:SpotLight::new() 232 | } 233 | } 234 | 235 | #[inline] 236 | pub fn build(self) -> SpotLight 237 | { 238 | self.light 239 | } 240 | 241 | #[inline] 242 | pub fn set_direction(mut self, dir:float3) -> Self 243 | { 244 | self.light.set_direction(dir); 245 | self 246 | } 247 | 248 | #[inline] 249 | pub fn set_angle(mut self, angle:f32) -> Self 250 | { 251 | self.light.set_angle(angle); 252 | self 253 | } 254 | 255 | #[inline] 256 | pub fn set_color(mut self, spectrum:Spectrum) -> Self 257 | { 258 | self.light.set_color(spectrum); 259 | self 260 | } 261 | 262 | #[inline] 263 | pub fn set_intensity(mut self, intensity:f32) -> Self 264 | { 265 | self.light.set_intensity(intensity); 266 | self 267 | } 268 | 269 | #[inline] 270 | pub fn set_translate(mut self, pos:float3) -> Self 271 | { 272 | self.light.set_translate(pos); 273 | self 274 | } 275 | 276 | #[inline] 277 | pub fn set_scale(mut self, sz:float3) -> Self 278 | { 279 | self.light.set_scale(sz); 280 | self 281 | } 282 | 283 | #[inline] 284 | pub fn set_rotation(mut self, rot:float3) -> Self 285 | { 286 | self.light.set_rotation(rot); 287 | self 288 | } 289 | } -------------------------------------------------------------------------------- /src/scene/loaders/json.rs: -------------------------------------------------------------------------------- 1 | use super::super::{Result, Loader, Scene}; 2 | 3 | #[derive(Debug)] 4 | pub struct JsonLoader {} 5 | 6 | impl JsonLoader 7 | { 8 | pub fn new() -> Self 9 | { 10 | Self 11 | { 12 | } 13 | } 14 | } 15 | 16 | impl Loader for JsonLoader 17 | { 18 | fn can_read(&self, _buf:&[u8]) -> bool 19 | { 20 | false 21 | } 22 | 23 | fn do_load(&self, _buf:&[u8]) -> Result 24 | { 25 | Ok(Scene::new()) 26 | } 27 | 28 | fn do_save(&self, scene:&Scene) -> Result> 29 | { 30 | let serialized = serde_json::to_string(scene).unwrap(); 31 | Ok(serialized.into_bytes()) 32 | } 33 | } -------------------------------------------------------------------------------- /src/scene/loaders/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod pmm; 2 | pub mod json; 3 | pub mod model; 4 | pub mod texture; 5 | 6 | pub use self::pmm::*; 7 | pub use self::json::*; 8 | pub use self::model::*; 9 | pub use self::texture::*; -------------------------------------------------------------------------------- /src/scene/loaders/model.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | use std::path::Path; 3 | use std::io::BufRead; 4 | use std::io::prelude::Seek; 5 | use log::*; 6 | 7 | use crate::math::*; 8 | use crate::models; 9 | 10 | use super::super::core::Result; 11 | use super::super::geometries::MeshGeometry; 12 | use super::super::materials::StandardMaterial; 13 | use super::super::shapes::{ MeshShape, ModelShape }; 14 | use super::super::loaders::TextureLoader; 15 | 16 | #[derive(Debug)] 17 | pub struct ModelLoader {} 18 | 19 | impl ModelLoader 20 | { 21 | pub fn load_from_model>(model:models::Model, path:P) -> Result 22 | { 23 | let mut shapes = Vec::new(); 24 | let mut materials = Vec::new(); 25 | let mut textures = Vec::new(); 26 | 27 | info!("model count: {}", model.meshes.len()); 28 | info!("texture count: {}", model.textures.len()); 29 | info!("material count: {}", model.materials.len()); 30 | info!("bone count: {}", model.bones.len()); 31 | info!("ik count: {}", model.iks.len()); 32 | 33 | for name in &model.textures 34 | { 35 | let texture = TextureLoader::load(path.as_ref().join(&name)); 36 | if texture.is_ok() 37 | { 38 | info!("Loading: {} Ok", &name); 39 | textures.push(Some(Arc::new(texture?))); 40 | } 41 | else 42 | { 43 | info!("Loading: {} Failed", &name); 44 | textures.push(None); 45 | } 46 | } 47 | 48 | for material in &model.materials 49 | { 50 | let mut m = StandardMaterial::new(); 51 | m.set_albedo(float!(material.diffuse[0],material.diffuse[1],material.diffuse[2])); 52 | m.set_specular(float!(material.specular[0],material.specular[1],material.specular[2])); 53 | 54 | if material.diffuse_texture.is_some() 55 | { 56 | m.set_albedo_map(textures[material.diffuse_texture.unwrap()].clone()); 57 | } 58 | 59 | materials.push(Arc::new(m)); 60 | } 61 | 62 | for (i, mesh) in model.meshes.iter().enumerate() 63 | { 64 | info!("model[{}].mesh.material_id = {:?}", i, mesh.material_id); 65 | info!("model[{}].vertices: {}", i, mesh.positions.len() / 3); 66 | info!("model[{}].normals: {}", i, mesh.normals.len() / 3); 67 | info!("model[{}].texcoords: {}", i, mesh.texcoords.len() / 2); 68 | info!("model[{}].weights: {}", i, mesh.weights.len()); 69 | info!("model[{}].indices: {}", i, mesh.indices.len()); 70 | 71 | let geometry = MeshGeometry::builder() 72 | .set_vertices(mesh.positions.chunks(3).map(|i| float!(i[0], i[1], i[2])).collect()) 73 | .set_normals(mesh.normals.chunks(3).map(|i| float!(i[0], i[1], i[2])).collect()) 74 | .set_texcoords(mesh.texcoords.chunks(2).map(|i| float!(i[0], i[1])).collect()) 75 | .set_weights(mesh.weights.clone()) 76 | .set_indices(mesh.indices.chunks(1).map(|i| i[0] as u16).collect()); 77 | 78 | shapes.push(MeshShape::new(Arc::new(geometry.build()), materials[mesh.material_id.unwrap() as usize].clone())); 79 | } 80 | 81 | return Ok(ModelShape::new(shapes)); 82 | } 83 | 84 | pub fn open>(path:P) -> Result 85 | { 86 | ModelLoader::load_from_model(models::open(&path)?, path.as_ref().parent().unwrap()) 87 | } 88 | 89 | pub fn load>(path:P) -> Result 90 | { 91 | ModelLoader::load_from_model(models::open(&path)?, path.as_ref().parent().unwrap()) 92 | } 93 | 94 | pub fn load_from_buf(r:R) -> Result 95 | { 96 | ModelLoader::load_from_model(models::load_from_buf(r)?, "") 97 | } 98 | 99 | pub fn load_from_memory(buffer:&[u8]) -> Result 100 | { 101 | ModelLoader::load_from_model(models::load_from_memory(buffer)?, "") 102 | } 103 | } -------------------------------------------------------------------------------- /src/scene/loaders/texture.rs: -------------------------------------------------------------------------------- 1 | use std::io::{Seek, BufRead}; 2 | use image::{ImageResult, GenericImageView, DynamicImage}; 3 | use super::super::core::Result; 4 | use super::super::core::{Texture, ColorType}; 5 | 6 | #[derive(Debug)] 7 | pub struct TextureLoader {} 8 | 9 | impl TextureLoader 10 | { 11 | fn load_from_image(img:ImageResult, name:Option) -> Result 12 | { 13 | let color_type; 14 | let image = img?; 15 | 16 | match image.color() 17 | { 18 | image::ColorType::Gray(n) => { color_type = ColorType::Gray(n); }, 19 | image::ColorType::GrayA(n) => { color_type = ColorType::GrayA(n); }, 20 | image::ColorType::RGBA(n) => { color_type = ColorType::RGBA(n); }, 21 | image::ColorType::RGB(n) => { color_type = ColorType::RGB(n); }, 22 | image::ColorType::BGRA(n) => { color_type = ColorType::BGRA(n); }, 23 | image::ColorType::BGR(n) => { color_type = ColorType::BGR(n); }, 24 | image::ColorType::Palette(n) => { color_type = ColorType::Palette(n); }, 25 | }; 26 | 27 | let mut texture = Texture::new(color_type, image.width(), image.height(), image.raw_pixels()); 28 | match name 29 | { 30 | Some(name) => texture.set_name(&name), 31 | None => {}, 32 | } 33 | Ok(texture) 34 | } 35 | 36 | pub fn load>(path:P) -> Result 37 | { 38 | match path.as_ref().to_str() 39 | { 40 | Some(name) => TextureLoader::load_from_image(image::open(&path), Some(name.to_string())), 41 | None => TextureLoader::load_from_image(image::open(&path), None), 42 | } 43 | } 44 | 45 | pub fn load_from_buf(r:R, format:image::ImageFormat, name:Option) -> Result 46 | { 47 | TextureLoader::load_from_image(image::load(r, format), name) 48 | } 49 | 50 | pub fn load_from_memory(buffer:&[u8], name:Option) -> Result 51 | { 52 | TextureLoader::load_from_image(image::load_from_memory(buffer), name) 53 | } 54 | } -------------------------------------------------------------------------------- /src/scene/materials/custom.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::sync::Arc; 3 | use std::cell::RefCell; 4 | use std::collections::hash_map::HashMap; 5 | 6 | use crate::math::*; 7 | use crate::math::type_size::*; 8 | use super::super::core::*; 9 | use super::super::util::uuid::OsRandNewV4; 10 | 11 | #[derive(Debug)] 12 | pub struct CustomMaterial 13 | { 14 | pub uuid: uuid::Uuid, 15 | pub state:RenderState, 16 | pub attribs:Vec, 17 | pub uniforms:HashMap 18 | } 19 | 20 | impl CustomMaterial 21 | { 22 | pub fn new() -> Self 23 | { 24 | let mut attribs = Vec::new(); 25 | let stride = (float3::type_size() + float3::type_size() + float2::type_size()) as u8; 26 | attribs.push(VertexAttrib::new(0, Format::RGBSFloat(8,8,8), stride, 0)); 27 | attribs.push(VertexAttrib::new(1, Format::RGBSFloat(8,8,8), stride, float3::type_size() as _)); 28 | attribs.push(VertexAttrib::new(2, Format::RGSFloat(8,8), stride, (float3::type_size() * 2) as _)); 29 | 30 | Self 31 | { 32 | uuid:uuid::Uuid::new_v4_osrng(), 33 | state:RenderState::new(), 34 | uniforms:HashMap::new(), 35 | attribs:attribs 36 | } 37 | } 38 | } 39 | 40 | impl Material for CustomMaterial 41 | { 42 | fn input_layout(&self) -> &[VertexAttrib] 43 | { 44 | &self.attribs 45 | } 46 | 47 | fn uniforms(&self) -> &HashMap 48 | { 49 | &self.uniforms 50 | } 51 | 52 | fn set_uniform(&mut self, name:&str, value:Variant) 53 | { 54 | if let Some(x) = self.uniforms.get_mut(name) 55 | { 56 | *x = value; 57 | } 58 | } 59 | 60 | fn cull_mode(&self) -> CullMode 61 | { 62 | return CullMode::None; 63 | } 64 | } 65 | 66 | impl Resource for CustomMaterial 67 | { 68 | #[inline] 69 | fn uuid(&self) -> &uuid::Uuid 70 | { 71 | &self.uuid 72 | } 73 | } 74 | 75 | impl AsRef for CustomMaterial 76 | { 77 | fn as_ref(&self) -> &RenderState 78 | { 79 | &self.state 80 | } 81 | } 82 | 83 | impl AsMut for CustomMaterial 84 | { 85 | fn as_mut(&mut self) -> &mut RenderState 86 | { 87 | &mut self.state 88 | } 89 | } 90 | 91 | impl From for Rc 92 | { 93 | fn from(material:CustomMaterial) -> Self 94 | { 95 | Rc::new(material) 96 | } 97 | } 98 | 99 | impl From for Arc 100 | { 101 | fn from(material:CustomMaterial) -> Self 102 | { 103 | Arc::new(material) 104 | } 105 | } 106 | 107 | impl From for Rc> 108 | { 109 | fn from(material:CustomMaterial) -> Self 110 | { 111 | Rc::new(RefCell::new(material)) 112 | } 113 | } 114 | 115 | impl From for Arc> 116 | { 117 | fn from(material:CustomMaterial) -> Self 118 | { 119 | Arc::new(RefCell::new(material)) 120 | } 121 | } -------------------------------------------------------------------------------- /src/scene/materials/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod standard; 2 | pub mod skybox; 3 | pub mod custom; 4 | pub mod skinning; 5 | 6 | pub use self::standard::*; 7 | pub use self::skybox::*; 8 | pub use self::custom::*; 9 | pub use self::skinning::*; -------------------------------------------------------------------------------- /src/scene/materials/skybox.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::sync::Arc; 3 | use std::cell::RefCell; 4 | use std::collections::hash_map::HashMap; 5 | 6 | use crate::math::*; 7 | use crate::math::type_size::*; 8 | use super::super::core::*; 9 | use super::super::util::uuid::OsRandNewV4; 10 | 11 | pub static SHADER_VERTEX:&'static str = r#" 12 | Result main_vs(Args args) 13 | { 14 | Result result; 15 | result.position = transform(args.position); 16 | result.normal = args.normal; 17 | result.coord = args.coord; 18 | return result; 19 | } 20 | "#; 21 | 22 | pub static SHADER_FRAGMENT:&'static str = r#" 23 | uniform float3 color; 24 | uniform sampler2D texture; 25 | 26 | uniform bool texture_enable; 27 | 28 | Gbuffer main_fs(Args args) 29 | { 30 | Gbuffer buffer; 31 | buffer.albedo = float3(1e-16,1e-16,1e-16); 32 | buffer.specular = float3(0.0,0.0,0.0); 33 | buffer.emissive = color; 34 | buffer.smoothness = 0.0; 35 | buffer.metalness = 0.0; 36 | buffer.normal = normalize(args.normal); 37 | 38 | if (texture_enable) 39 | { 40 | buffer.emissive *= pow(texture2D(texture, ComputeSphereCoord(buffer.normal)).xyz, float3(2.2)); 41 | } 42 | 43 | return buffer; 44 | }"#; 45 | 46 | 47 | #[derive(Debug)] 48 | pub struct SkyboxMaterial 49 | { 50 | pub uuid: uuid::Uuid, 51 | pub state:RenderState, 52 | pub attribs:Vec, 53 | pub uniforms:HashMap 54 | } 55 | 56 | impl SkyboxMaterial 57 | { 58 | pub fn new() -> Self 59 | { 60 | let mut params = HashMap::new(); 61 | params.insert("color".to_string(), float3::one().into()); 62 | params.insert("texture".to_string(), None.into()); 63 | params.insert("texture_enable".to_string(), float1::zero().into()); 64 | 65 | let mut attribs = Vec::new(); 66 | let stride = (float3::type_size() + float3::type_size() + float2::type_size()) as u8; 67 | attribs.push(VertexAttrib::new(0, Format::RGBSFloat(8,8,8), stride, 0)); 68 | attribs.push(VertexAttrib::new(1, Format::RGBSFloat(8,8,8), stride, float3::type_size() as _)); 69 | attribs.push(VertexAttrib::new(2, Format::RGSFloat(8,8), stride, (float3::type_size() * 2) as _)); 70 | 71 | Self 72 | { 73 | uuid:uuid::Uuid::new_v4_osrng(), 74 | state:RenderState::new(), 75 | uniforms:params, 76 | attribs:attribs 77 | } 78 | } 79 | 80 | #[inline] 81 | pub fn builder() -> SkyboxMaterialBuilder 82 | { 83 | SkyboxMaterialBuilder::new() 84 | } 85 | 86 | pub fn set_color(&mut self, value:float3) -> &mut Self 87 | { 88 | self.set_uniform("color", value.into()); 89 | self 90 | } 91 | 92 | pub fn set_texture(&mut self, value:Option>) -> &mut Self 93 | { 94 | self.set_uniform("texture_enable", value.is_some().into()); 95 | self.set_uniform("texture", value.into()); 96 | self 97 | } 98 | } 99 | 100 | impl Material for SkyboxMaterial 101 | { 102 | fn input_layout(&self) -> &[VertexAttrib] 103 | { 104 | &self.attribs 105 | } 106 | 107 | fn uniforms(&self) -> &HashMap 108 | { 109 | &self.uniforms 110 | } 111 | 112 | fn set_uniform(&mut self, name:&str, value:Variant) 113 | { 114 | if let Some(x) = self.uniforms.get_mut(name) { 115 | *x = value; 116 | } 117 | } 118 | 119 | fn vs(&self) -> &str 120 | { 121 | SHADER_VERTEX 122 | } 123 | 124 | fn fs(&self) -> &str 125 | { 126 | SHADER_FRAGMENT 127 | } 128 | 129 | fn cull_mode(&self) -> CullMode 130 | { 131 | return CullMode::None; 132 | } 133 | } 134 | 135 | impl Resource for SkyboxMaterial 136 | { 137 | #[inline] 138 | fn uuid(&self) -> &uuid::Uuid 139 | { 140 | &self.uuid 141 | } 142 | } 143 | 144 | impl AsRef for SkyboxMaterial 145 | { 146 | fn as_ref(&self) -> &RenderState 147 | { 148 | &self.state 149 | } 150 | } 151 | 152 | impl AsMut for SkyboxMaterial 153 | { 154 | fn as_mut(&mut self) -> &mut RenderState 155 | { 156 | &mut self.state 157 | } 158 | } 159 | 160 | impl From for Rc 161 | { 162 | fn from(material:SkyboxMaterial) -> Self 163 | { 164 | Rc::new(material) 165 | } 166 | } 167 | 168 | impl From for Arc 169 | { 170 | fn from(material:SkyboxMaterial) -> Self 171 | { 172 | Arc::new(material) 173 | } 174 | } 175 | 176 | impl From for Rc> 177 | { 178 | fn from(material:SkyboxMaterial) -> Self 179 | { 180 | Rc::new(RefCell::new(material)) 181 | } 182 | } 183 | 184 | impl From for Arc> 185 | { 186 | fn from(material:SkyboxMaterial) -> Self 187 | { 188 | Arc::new(RefCell::new(material)) 189 | } 190 | } 191 | 192 | pub struct SkyboxMaterialBuilder 193 | { 194 | material:SkyboxMaterial 195 | } 196 | 197 | impl SkyboxMaterialBuilder 198 | { 199 | #[inline] 200 | pub fn new() -> Self 201 | { 202 | Self 203 | { 204 | material:SkyboxMaterial::new() 205 | } 206 | } 207 | 208 | #[inline] 209 | pub fn build(self) -> SkyboxMaterial 210 | { 211 | self.material 212 | } 213 | 214 | pub fn set_color(mut self, value:float3) -> Self 215 | { 216 | self.material.set_color(value); 217 | self 218 | } 219 | 220 | pub fn set_texture(mut self, value:Option>) -> Self 221 | { 222 | self.material.set_texture(value); 223 | self 224 | } 225 | } -------------------------------------------------------------------------------- /src/scene/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod core; 2 | pub mod spectrum; 3 | pub mod cameras; 4 | pub mod geometries; 5 | pub mod lights; 6 | pub mod shapes; 7 | pub mod materials; 8 | pub mod scene; 9 | pub mod loaders; 10 | pub mod util; 11 | 12 | pub use self::core::*; 13 | pub use self::spectrum::*; 14 | pub use self::cameras::*; 15 | pub use self::geometries::*; 16 | pub use self::lights::*; 17 | pub use self::shapes::*; 18 | pub use self::materials::*; 19 | pub use self::scene::*; 20 | pub use self::loaders::*; 21 | pub use self::util::*; 22 | 23 | use std::io::prelude::*; 24 | use std::fs::File; 25 | 26 | pub fn load_from_memory(buf:&[u8]) -> Result 27 | { 28 | let loaders = vec![Box::new(PMMLoader::new())]; 29 | 30 | for loader in loaders 31 | { 32 | if loader.can_read(buf) 33 | { 34 | return Ok(loader.do_load(buf)?); 35 | } 36 | } 37 | 38 | Err(Error::LoaderError("Not supported yet".to_string())) 39 | } 40 | 41 | pub fn load_from_buf(mut r:R) -> Result 42 | { 43 | load_from_memory(r.fill_buf()?) 44 | } 45 | 46 | pub fn open>(path:P) -> Result 47 | { 48 | let mut buffer = Vec::new(); 49 | File::open(path)?.read_to_end(&mut buffer)?; 50 | load_from_memory(&buffer) 51 | } 52 | 53 | pub fn to_string(scene:&Scene) -> Result 54 | { 55 | let json = JsonLoader::new(); 56 | let stream = json.do_save(scene)?; 57 | unsafe 58 | { 59 | Ok(String::from_utf8_unchecked(stream)) 60 | } 61 | } 62 | 63 | pub fn dumps(scene:&Scene) -> Result> 64 | { 65 | let json = JsonLoader::new(); 66 | json.do_save(scene) 67 | } 68 | 69 | pub fn dump>(scene:&Scene, path:P) -> Result<()> 70 | { 71 | let mut file = File::create(path)?; 72 | file.write_all(&dumps(scene)?).unwrap(); 73 | Ok(()) 74 | } -------------------------------------------------------------------------------- /src/scene/scene/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod scene; 2 | pub mod scene_data; 3 | pub mod scene_node; 4 | 5 | pub use self::scene::*; 6 | pub use self::scene_data::*; 7 | pub use self::scene_node::*; -------------------------------------------------------------------------------- /src/scene/scene/scene.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::sync::Arc; 3 | use super::{SceneNode, SceneSubData}; 4 | use super::super::core::{Canvas, CameraData, Geometry, Material}; 5 | use serde::ser::{Serialize, Serializer, SerializeStruct, SerializeSeq}; 6 | 7 | pub struct Scene 8 | { 9 | pub cameras:Vec, 10 | pub shapes:Vec, 11 | pub lights:Vec, 12 | pub models:Vec, 13 | } 14 | 15 | impl Scene 16 | { 17 | pub fn new() -> Self 18 | { 19 | Self 20 | { 21 | cameras:Vec::new(), 22 | lights:Vec::new(), 23 | shapes:Vec::new(), 24 | models:Vec::new(), 25 | } 26 | } 27 | 28 | pub fn add>(&mut self, node:T) -> &mut Self 29 | { 30 | match node.as_ref().kind() 31 | { 32 | SceneSubData::Light => 33 | { 34 | self.lights.push(node.as_ref().clone()); 35 | }, 36 | SceneSubData::Shape => 37 | { 38 | self.shapes.push(node.as_ref().clone()); 39 | }, 40 | SceneSubData::Camera => 41 | { 42 | self.cameras.push(node.as_ref().clone()); 43 | self.cameras.sort_by( 44 | |a, b| 45 | { 46 | let a_kind = a.user_data::().unwrap().kind; 47 | let b_kind = b.user_data::().unwrap().kind; 48 | a_kind.cmp(&b_kind) 49 | } 50 | ); 51 | }, 52 | SceneSubData::Group => 53 | { 54 | for actor in node.as_ref().data.borrow().children.iter() 55 | { 56 | self.add(actor); 57 | } 58 | 59 | self.models.push(node.as_ref().clone()); 60 | } 61 | } 62 | 63 | self 64 | } 65 | 66 | pub fn cameras(&self) -> &[SceneNode] 67 | { 68 | &self.cameras[..] 69 | } 70 | 71 | pub fn lights(&self) -> &[SceneNode] 72 | { 73 | &self.lights[..] 74 | } 75 | 76 | pub fn shapes(&self) -> &[SceneNode] 77 | { 78 | &self.shapes[..] 79 | } 80 | 81 | pub fn num_camera(&self) -> usize 82 | { 83 | self.cameras.len() 84 | } 85 | 86 | pub fn num_light(&self) -> usize 87 | { 88 | self.lights.len() 89 | } 90 | 91 | pub fn num_shape(&self) -> usize 92 | { 93 | self.shapes.len() 94 | } 95 | 96 | pub fn update(&mut self, canvas:&Canvas) 97 | { 98 | for camera in self.cameras.iter_mut() 99 | { 100 | camera.update(canvas); 101 | } 102 | 103 | for light in self.lights.iter_mut() 104 | { 105 | light.update(canvas); 106 | } 107 | 108 | for shape in self.shapes.iter_mut() 109 | { 110 | shape.update(canvas); 111 | } 112 | } 113 | } 114 | 115 | struct ShapeSerialize 116 | { 117 | geometries:HashMap> 118 | } 119 | 120 | struct MaterialSerialize 121 | { 122 | materials:HashMap> 123 | } 124 | 125 | impl ShapeSerialize 126 | { 127 | fn new(shapes:&Vec) -> Self 128 | { 129 | let mut geometries = HashMap::new(); 130 | 131 | for shape in shapes 132 | { 133 | match shape.geometry() 134 | { 135 | Some(ref data) => 136 | { 137 | let uuid = data.uuid().clone(); 138 | if !geometries.contains_key(&uuid) 139 | { 140 | geometries.insert(uuid, data.clone()); 141 | } 142 | }, 143 | None => {}, 144 | } 145 | } 146 | 147 | Self 148 | { 149 | geometries 150 | } 151 | } 152 | } 153 | 154 | impl MaterialSerialize 155 | { 156 | fn new(shapes:&Vec) -> Self 157 | { 158 | let mut materials = HashMap::new(); 159 | 160 | for shape in shapes 161 | { 162 | match shape.material() 163 | { 164 | Some(ref data) => 165 | { 166 | let uuid = data.uuid().clone(); 167 | if !materials.contains_key(&uuid) 168 | { 169 | materials.insert(uuid, data.clone()); 170 | } 171 | }, 172 | None => {}, 173 | } 174 | } 175 | 176 | Self 177 | { 178 | materials 179 | } 180 | } 181 | } 182 | 183 | impl Serialize for ShapeSerialize 184 | { 185 | fn serialize(&self, serializer: S) -> Result 186 | { 187 | let mut s = serializer.serialize_seq(Some(self.geometries.len()))?; 188 | for geometry in self.geometries.values() 189 | { 190 | s.serialize_element(&geometry)?; 191 | } 192 | s.end() 193 | } 194 | } 195 | 196 | impl Serialize for MaterialSerialize 197 | { 198 | fn serialize(&self, serializer: S) -> Result 199 | { 200 | let mut s = serializer.serialize_seq(Some(self.materials.len()))?; 201 | for material in self.materials.iter() 202 | { 203 | s.serialize_element(&material)?; 204 | } 205 | s.end() 206 | } 207 | } 208 | 209 | impl Serialize for Scene 210 | { 211 | fn serialize(&self, serializer: S) -> Result 212 | { 213 | let mut s = serializer.serialize_struct("scene", 5)?; 214 | s.serialize_field("model", &ShapeSerialize::new(&self.shapes))?; 215 | s.serialize_field("materials", &MaterialSerialize::new(&self.shapes))?; 216 | s.serialize_field("shape", &self.shapes)?; 217 | s.serialize_field("camera", &self.cameras)?; 218 | s.serialize_field("light", &self.lights)?; 219 | s.end() 220 | } 221 | } -------------------------------------------------------------------------------- /src/scene/scene/scene_data.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | use std::boxed::Box; 3 | use std::any::Any; 4 | use serde::ser::{Serialize, SerializeStruct, Serializer}; 5 | use crate::math::{float3, float4x4}; 6 | 7 | use super::SceneNode; 8 | use super::super::core::{Transform, Geometry, Material, Canvas}; 9 | use super::super::util::uuid::OsRandNewV4; 10 | 11 | #[derive(Debug, Copy, PartialEq, Clone, Serialize, Deserialize)] 12 | pub enum SceneSubData 13 | { 14 | Camera, 15 | Light, 16 | Shape, 17 | Group 18 | } 19 | 20 | pub struct SceneData 21 | { 22 | pub visible:bool, 23 | pub name:String, 24 | pub uuid:uuid::Uuid, 25 | pub transform:Transform, 26 | pub kind:SceneSubData, 27 | pub user_data:Box, 28 | pub geometry:Option>, 29 | pub material:Option>, 30 | pub children:Vec, 31 | pub dispatch:Option, 32 | } 33 | 34 | impl SceneData 35 | { 36 | #[inline] 37 | pub fn new(kind:SceneSubData) -> Self 38 | { 39 | let user_data = (); 40 | 41 | Self 42 | { 43 | kind:kind, 44 | visible:true, 45 | name:String::new(), 46 | uuid:uuid::Uuid::new_v4_osrng(), 47 | transform:Transform::new(), 48 | user_data:Box::new(user_data), 49 | children:Vec::new(), 50 | geometry:None, 51 | material:None, 52 | dispatch:None 53 | } 54 | } 55 | 56 | #[inline(always)] 57 | pub fn kind(&self) -> SceneSubData 58 | { 59 | self.kind 60 | } 61 | 62 | #[inline(always)] 63 | pub fn uuid(&self) -> &uuid::Uuid 64 | { 65 | &self.uuid 66 | } 67 | 68 | #[inline(always)] 69 | pub fn is_visible(&self) -> bool 70 | { 71 | self.visible 72 | } 73 | 74 | #[inline(always)] 75 | pub fn set_visible(&mut self, visible:bool) -> &mut Self 76 | { 77 | self.visible = visible; 78 | self 79 | } 80 | 81 | #[inline(always)] 82 | pub fn name(&self) -> &str 83 | { 84 | &self.name 85 | } 86 | 87 | #[inline(always)] 88 | pub fn set_name(&mut self, name:&str) -> &mut Self 89 | { 90 | self.name = name.to_string(); 91 | self 92 | } 93 | 94 | #[inline(always)] 95 | pub fn add_child(&mut self, child:SceneNode) -> &mut Self 96 | { 97 | self.children.push(child); 98 | self 99 | } 100 | 101 | #[inline(always)] 102 | pub fn remove_child(&mut self, child:&SceneNode) -> &mut Self 103 | { 104 | let mut remove_item = self.children.len(); 105 | 106 | for (i, item) in self.children.iter().enumerate() 107 | { 108 | if item.uuid == child.uuid 109 | { 110 | remove_item = i; 111 | break; 112 | } 113 | } 114 | 115 | if remove_item < self.children.len() 116 | { 117 | self.children.remove(remove_item); 118 | } 119 | 120 | self 121 | } 122 | 123 | #[inline(always)] 124 | pub fn num_children(&self) -> usize 125 | { 126 | self.children.len() 127 | } 128 | 129 | #[inline(always)] 130 | pub fn translate(&self) -> float3 131 | { 132 | self.transform.translate() 133 | } 134 | 135 | #[inline(always)] 136 | pub fn set_translate(&mut self, pos:float3) -> &mut Self 137 | { 138 | self.transform.set_translate(pos); 139 | self 140 | } 141 | 142 | #[inline(always)] 143 | pub fn scale(&self) -> float3 144 | { 145 | self.transform.scale() 146 | } 147 | 148 | #[inline(always)] 149 | pub fn set_scale(&mut self, sz:float3) -> &mut Self 150 | { 151 | self.transform.set_scale(sz); 152 | self 153 | } 154 | 155 | #[inline(always)] 156 | pub fn rotation(&self) -> float3 157 | { 158 | self.transform.rotation() 159 | } 160 | 161 | #[inline(always)] 162 | pub fn set_rotation(&mut self, rot:float3) -> &mut Self 163 | { 164 | self.transform.set_rotation(rot); 165 | self 166 | } 167 | 168 | #[inline(always)] 169 | pub fn transform(&self) -> float4x4 170 | { 171 | self.transform.transform() 172 | } 173 | 174 | #[inline(always)] 175 | pub fn transform_inverse(&self) -> float4x4 176 | { 177 | self.transform.transform_inverse() 178 | } 179 | 180 | #[inline(always)] 181 | pub fn geometry(&self) -> Option> 182 | { 183 | self.geometry.clone() 184 | } 185 | 186 | #[inline(always)] 187 | pub fn set_geometry(&mut self, geometry:Option>) -> &mut Self 188 | { 189 | self.geometry = geometry; 190 | self 191 | } 192 | 193 | #[inline(always)] 194 | pub fn material(&self) -> Option> 195 | { 196 | self.material.clone() 197 | } 198 | 199 | #[inline(always)] 200 | pub fn set_material(&mut self, material:Option>) -> &mut Self 201 | { 202 | self.material = material; 203 | self 204 | } 205 | 206 | #[inline(always)] 207 | pub fn user_data(&self) -> &Box 208 | { 209 | &self.user_data 210 | } 211 | 212 | #[inline(always)] 213 | pub fn set_user_data(&mut self, user_data:Box) -> &mut Self 214 | { 215 | self.user_data = user_data; 216 | self 217 | } 218 | 219 | #[inline(always)] 220 | pub fn with(&mut self, method:fn(&mut Self, &Canvas)) -> &mut Self 221 | { 222 | self.dispatch = Some(method); 223 | self 224 | } 225 | 226 | #[inline(always)] 227 | pub fn update(&mut self, canvas:&Canvas) -> &mut Self 228 | { 229 | match self.dispatch 230 | { 231 | Some(ref mut callback) => { callback(self, canvas) } 232 | _ => {} 233 | } 234 | 235 | self 236 | } 237 | } 238 | 239 | impl std::fmt::Debug for SceneData 240 | { 241 | fn fmt(&self, f:&mut std::fmt::Formatter) -> std::fmt::Result 242 | { 243 | write!(f, "{:?},{:?},{:?},{:?},{:?},{:?},{:?},{:?}", 244 | self.visible, 245 | self.name, 246 | self.uuid, 247 | self.transform, 248 | self.kind, 249 | self.geometry, 250 | self.material, 251 | self.children, 252 | ) 253 | } 254 | } 255 | 256 | impl Serialize for SceneData 257 | { 258 | fn serialize(&self, serializer: S) -> Result 259 | { 260 | let mut s = serializer.serialize_struct("node", 4)?; 261 | s.serialize_field("type", &self.kind)?; 262 | s.serialize_field("uuid", &self.uuid)?; 263 | s.serialize_field("name", &self.name)?; 264 | s.serialize_field("visible", &self.visible)?; 265 | s.serialize_field("transform", &self.transform)?; 266 | 267 | match self.geometry 268 | { 269 | Some(ref data) => { s.serialize_field("model", &data.uuid())? }, 270 | _ => {} 271 | } 272 | 273 | match self.material 274 | { 275 | Some(ref data) => { s.serialize_field("material", &data.uuid())? }, 276 | _ => {} 277 | } 278 | 279 | if self.children.len() > 0 280 | { 281 | s.serialize_field("children", &self.children)?; 282 | } 283 | 284 | s.end() 285 | } 286 | } -------------------------------------------------------------------------------- /src/scene/scene/scene_node.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::cell::RefCell; 3 | use std::sync::Arc; 4 | use std::any::Any; 5 | use serde::ser::{Serialize, Serializer}; 6 | use crate::math::{float3, float4x4}; 7 | 8 | use super::{SceneData, SceneSubData}; 9 | use super::super::core::{Geometry, Material, Canvas}; 10 | 11 | #[derive(Clone)] 12 | pub struct SceneNode 13 | { 14 | pub uuid:uuid::Uuid, 15 | pub data:Rc>, 16 | } 17 | 18 | impl SceneNode 19 | { 20 | #[inline(always)] 21 | pub fn new(sub_data:SceneSubData) -> Self 22 | { 23 | let data = SceneData::new(sub_data); 24 | Self 25 | { 26 | uuid: *data.uuid(), 27 | data: Rc::new(RefCell::new(data)), 28 | } 29 | } 30 | 31 | #[inline(always)] 32 | pub fn kind(&self) -> SceneSubData 33 | { 34 | self.data.borrow().kind() 35 | } 36 | 37 | #[inline(always)] 38 | pub fn uuid(&self) -> &uuid::Uuid 39 | { 40 | &self.uuid 41 | } 42 | 43 | #[inline(always)] 44 | pub fn is_visible(&self) -> bool 45 | { 46 | self.data.borrow().is_visible() 47 | } 48 | 49 | #[inline(always)] 50 | pub fn set_visible(&mut self, visible: bool) -> &mut SceneNode 51 | { 52 | self.data.borrow_mut().set_visible(visible); 53 | self 54 | } 55 | 56 | #[inline(always)] 57 | pub fn transform(&self) -> float4x4 58 | { 59 | self.data.borrow().transform() 60 | } 61 | 62 | #[inline(always)] 63 | pub fn transform_inverse(&self) -> float4x4 64 | { 65 | self.data.borrow().transform_inverse() 66 | } 67 | 68 | #[inline(always)] 69 | pub fn name(&self) -> String 70 | { 71 | self.data.borrow().name().to_string() 72 | } 73 | 74 | #[inline(always)] 75 | pub fn set_name(&mut self, name: &str) -> &mut SceneNode 76 | { 77 | self.data.borrow_mut().set_name(name); 78 | self 79 | } 80 | 81 | #[inline(always)] 82 | pub fn translate(&self) -> float3 83 | { 84 | self.data.borrow().translate() 85 | } 86 | 87 | #[inline(always)] 88 | pub fn set_translate(&mut self, pos:float3) -> &mut SceneNode 89 | { 90 | self.data.borrow_mut().set_translate(pos); 91 | self 92 | } 93 | 94 | #[inline(always)] 95 | pub fn scale(&self) -> float3 96 | { 97 | self.data.borrow().scale() 98 | } 99 | 100 | #[inline(always)] 101 | pub fn set_scale(&mut self, sz:float3) -> &mut SceneNode 102 | { 103 | self.data.borrow_mut().set_scale(sz); 104 | self 105 | } 106 | 107 | #[inline(always)] 108 | pub fn rotation(&self) -> float3 109 | { 110 | self.data.borrow().rotation() 111 | } 112 | 113 | #[inline(always)] 114 | pub fn set_rotation(&mut self, rot:float3) -> &mut SceneNode 115 | { 116 | self.data.borrow_mut().set_rotation(rot); 117 | self 118 | } 119 | 120 | #[inline(always)] 121 | pub fn geometry(&self) -> Option> 122 | { 123 | self.data.borrow().geometry() 124 | } 125 | 126 | #[inline(always)] 127 | pub fn set_geometry(&mut self, geometry: Option>) -> &mut Self 128 | { 129 | self.data.borrow_mut().set_geometry(geometry); 130 | self 131 | } 132 | 133 | #[inline(always)] 134 | pub fn material(&self) -> Option> 135 | { 136 | self.data.borrow().material() 137 | } 138 | 139 | #[inline(always)] 140 | pub fn set_material(&mut self, material: Option>) -> &mut Self 141 | { 142 | self.data.borrow_mut().set_material(material); 143 | self 144 | } 145 | 146 | #[inline(always)] 147 | pub fn set_user_data(&mut self, user_data: Box) -> &mut Self 148 | { 149 | self.data.borrow_mut().set_user_data(user_data); 150 | self 151 | } 152 | 153 | #[inline(always)] 154 | pub fn user_data(&self) -> Result 155 | { 156 | match self.data.borrow().user_data.downcast_ref::() 157 | { 158 | Some(v) => { Ok(v.clone()) }, 159 | None => { Err("Invalid downcast type for user data.") } 160 | } 161 | } 162 | 163 | #[inline(always)] 164 | pub fn add_child(&mut self, child:SceneNode) 165 | { 166 | self.data.borrow_mut().add_child(child); 167 | } 168 | 169 | #[inline(always)] 170 | pub fn remove_child(&mut self, child:&SceneNode) 171 | { 172 | self.data.borrow_mut().remove_child(child); 173 | } 174 | 175 | #[inline(always)] 176 | pub fn with(&mut self, method:fn(&mut SceneData, &Canvas)) -> &mut Self 177 | { 178 | self.data.borrow_mut().with(method); 179 | self 180 | } 181 | 182 | #[inline(always)] 183 | pub fn update(&mut self, canvas:&Canvas) -> &mut Self 184 | { 185 | self.data.borrow_mut().update(canvas); 186 | self 187 | } 188 | } 189 | 190 | impl std::fmt::Debug for SceneNode 191 | { 192 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result 193 | { 194 | write!(f, "{:?}", self.data) 195 | } 196 | } 197 | 198 | impl AsRef for SceneNode 199 | { 200 | fn as_ref(&self) -> &SceneNode 201 | { 202 | self 203 | } 204 | } 205 | 206 | impl AsMut for SceneNode 207 | { 208 | fn as_mut(&mut self) -> &mut SceneNode 209 | { 210 | self 211 | } 212 | } 213 | 214 | impl Serialize for SceneNode 215 | { 216 | fn serialize(&self, serializer: S) -> Result 217 | { 218 | self.data.borrow().serialize(serializer) 219 | } 220 | } -------------------------------------------------------------------------------- /src/scene/shapes/mesh.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::sync::Arc; 3 | use std::cell::RefCell; 4 | use std::any::Any; 5 | 6 | use crate::math::*; 7 | 8 | use super::super::core::*; 9 | use super::super::scene::{ SceneNode, SceneSubData }; 10 | 11 | #[derive(Debug)] 12 | pub struct MeshShape 13 | { 14 | pub node:SceneNode 15 | } 16 | 17 | impl MeshShape 18 | { 19 | pub fn new(geometry:Arc, material: Arc) -> Self 20 | { 21 | let mut node = SceneNode::new(SceneSubData::Shape); 22 | node.set_geometry(Some(geometry)); 23 | node.set_material(Some(material)); 24 | 25 | Self 26 | { 27 | node:node, 28 | } 29 | } 30 | 31 | #[inline] 32 | pub fn builder() -> MeshShapeBuilder 33 | { 34 | MeshShapeBuilder::new() 35 | } 36 | } 37 | 38 | impl Shape for MeshShape 39 | { 40 | #[inline] 41 | fn geometry(&self) -> Arc 42 | { 43 | self.node.geometry().unwrap() 44 | } 45 | 46 | #[inline] 47 | fn set_geometry(&mut self, geometry: Arc) 48 | { 49 | self.node.set_geometry(Some(geometry)); 50 | } 51 | 52 | #[inline] 53 | fn material(&self) -> Arc 54 | { 55 | self.node.material().unwrap() 56 | } 57 | 58 | #[inline] 59 | fn set_material(&mut self, material: Arc) 60 | { 61 | self.node.set_material(Some(material)); 62 | } 63 | } 64 | 65 | impl Object for MeshShape 66 | { 67 | } 68 | 69 | impl Resource for MeshShape 70 | { 71 | #[inline] 72 | fn uuid(&self) -> &uuid::Uuid 73 | { 74 | self.node.uuid() 75 | } 76 | } 77 | 78 | impl Downcast for MeshShape 79 | { 80 | fn as_any(&self) -> &Any { self } 81 | fn as_any_mut(&mut self) -> &mut Any { self } 82 | } 83 | 84 | impl AsRef for MeshShape 85 | { 86 | fn as_ref(&self) -> &SceneNode 87 | { 88 | &self.node 89 | } 90 | } 91 | 92 | impl AsMut for MeshShape 93 | { 94 | fn as_mut(&mut self) -> &mut SceneNode 95 | { 96 | &mut self.node 97 | } 98 | } 99 | 100 | impl From for Box 101 | { 102 | fn from(shape:MeshShape) -> Self 103 | { 104 | Box::new(shape) 105 | } 106 | } 107 | 108 | impl From for Rc 109 | { 110 | fn from(shape:MeshShape) -> Self 111 | { 112 | Rc::new(shape) 113 | } 114 | } 115 | 116 | impl From for Arc 117 | { 118 | fn from(shape:MeshShape) -> Self 119 | { 120 | Arc::new(shape) 121 | } 122 | } 123 | 124 | impl From for Rc> 125 | { 126 | fn from(shape:MeshShape) -> Self 127 | { 128 | Rc::new(RefCell::new(shape)) 129 | } 130 | } 131 | 132 | impl From for Arc> 133 | { 134 | fn from(shape:MeshShape) -> Self 135 | { 136 | Arc::new(RefCell::new(shape)) 137 | } 138 | } 139 | 140 | pub struct MeshShapeBuilder 141 | { 142 | pub position:float3, 143 | pub scale:float3, 144 | pub rotation:float3, 145 | pub geometry:Option>, 146 | pub material:Option> 147 | } 148 | 149 | impl MeshShapeBuilder 150 | { 151 | #[inline] 152 | pub fn new() -> Self 153 | { 154 | Self 155 | { 156 | position:float3::zero(), 157 | scale:float3::one(), 158 | rotation:float3::zero(), 159 | geometry:None, 160 | material:None, 161 | } 162 | } 163 | 164 | #[inline] 165 | pub fn build(self) -> MeshShape 166 | { 167 | assert_eq!(self.geometry.is_some(), true); 168 | assert_eq!(self.material.is_some(), true); 169 | 170 | let mut mesh = MeshShape::new(self.geometry.unwrap(), self.material.unwrap()); 171 | mesh.set_translate(self.position); 172 | mesh.set_scale(self.scale); 173 | mesh.set_rotation(self.rotation); 174 | mesh 175 | } 176 | 177 | #[inline] 178 | pub fn set_geometry(mut self, geometry:Arc) -> Self 179 | { 180 | self.geometry = Some(geometry); 181 | self 182 | } 183 | 184 | #[inline] 185 | pub fn set_material(mut self, material:Arc) -> Self 186 | { 187 | self.material = Some(material); 188 | self 189 | } 190 | 191 | #[inline] 192 | pub fn set_translate(mut self, pos:float3) -> Self 193 | { 194 | self.position = pos; 195 | self 196 | } 197 | 198 | #[inline] 199 | pub fn set_scale(mut self, sz:float3) -> Self 200 | { 201 | self.scale = sz; 202 | self 203 | } 204 | 205 | #[inline] 206 | pub fn set_rotation(mut self, rot:float3) -> Self 207 | { 208 | self.rotation = rot; 209 | self 210 | } 211 | } -------------------------------------------------------------------------------- /src/scene/shapes/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod mesh; 2 | pub mod model; 3 | 4 | pub use self::mesh::*; 5 | pub use self::model::*; -------------------------------------------------------------------------------- /src/scene/shapes/model.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use std::sync::Arc; 3 | use std::cell::RefCell; 4 | use std::any::Any; 5 | 6 | use crate::math::*; 7 | 8 | use super::super::core::*; 9 | use super::super::scene::{ SceneNode, SceneSubData }; 10 | use super::super::shapes::{ MeshShape }; 11 | 12 | #[derive(Debug)] 13 | pub struct ModelShape 14 | { 15 | pub node:SceneNode, 16 | pub shapes:Vec 17 | } 18 | 19 | impl ModelShape 20 | { 21 | pub fn new(shapes:Vec) -> Self 22 | { 23 | let mut node = SceneNode::new(SceneSubData::Group); 24 | 25 | for shape in shapes.iter() 26 | { 27 | let mut shape_node = SceneNode::new(SceneSubData::Shape); 28 | shape_node.set_geometry(Some(shape.geometry())); 29 | shape_node.set_material(Some(shape.material())); 30 | 31 | node.add_child(shape_node); 32 | } 33 | 34 | Self 35 | { 36 | node:node, 37 | shapes:shapes 38 | } 39 | } 40 | 41 | #[inline] 42 | pub fn builder() -> ModelShapeBuilder 43 | { 44 | ModelShapeBuilder::new() 45 | } 46 | } 47 | 48 | impl Object for ModelShape 49 | { 50 | #[inline(always)] 51 | fn set_translate(&mut self, pos:float3) -> &mut SceneNode 52 | { 53 | self.as_mut().set_translate(pos); 54 | 55 | for child in self.node.data.borrow_mut().children.iter_mut() 56 | { 57 | child.set_translate(pos); 58 | } 59 | 60 | self.as_mut() 61 | } 62 | 63 | #[inline(always)] 64 | fn set_scale(&mut self, sz:float3) -> &mut SceneNode 65 | { 66 | self.as_mut().set_scale(sz); 67 | 68 | for child in self.node.data.borrow_mut().children.iter_mut() 69 | { 70 | child.set_scale(sz); 71 | } 72 | 73 | self.as_mut() 74 | } 75 | 76 | #[inline(always)] 77 | fn set_rotation(&mut self, rot:float3) -> &mut SceneNode 78 | { 79 | self.as_mut().set_rotation(rot); 80 | 81 | for child in self.node.data.borrow_mut().children.iter_mut() 82 | { 83 | child.set_rotation(rot); 84 | } 85 | 86 | self.as_mut() 87 | } 88 | } 89 | 90 | impl Resource for ModelShape 91 | { 92 | #[inline] 93 | fn uuid(&self) -> &uuid::Uuid 94 | { 95 | self.node.uuid() 96 | } 97 | } 98 | 99 | impl Downcast for ModelShape 100 | { 101 | fn as_any(&self) -> &Any { self } 102 | fn as_any_mut(&mut self) -> &mut Any { self } 103 | } 104 | 105 | impl AsRef for ModelShape 106 | { 107 | fn as_ref(&self) -> &SceneNode 108 | { 109 | &self.node 110 | } 111 | } 112 | 113 | impl AsMut for ModelShape 114 | { 115 | fn as_mut(&mut self) -> &mut SceneNode 116 | { 117 | &mut self.node 118 | } 119 | } 120 | 121 | impl From for Box 122 | { 123 | fn from(shape:ModelShape) -> Self 124 | { 125 | Box::new(shape) 126 | } 127 | } 128 | 129 | impl From for Rc 130 | { 131 | fn from(shape:ModelShape) -> Self 132 | { 133 | Rc::new(shape) 134 | } 135 | } 136 | 137 | impl From for Arc 138 | { 139 | fn from(shape:ModelShape) -> Self 140 | { 141 | Arc::new(shape) 142 | } 143 | } 144 | 145 | impl From for Rc> 146 | { 147 | fn from(shape:ModelShape) -> Self 148 | { 149 | Rc::new(RefCell::new(shape)) 150 | } 151 | } 152 | 153 | impl From for Arc> 154 | { 155 | fn from(shape:ModelShape) -> Self 156 | { 157 | Arc::new(RefCell::new(shape)) 158 | } 159 | } 160 | 161 | pub struct ModelShapeBuilder 162 | { 163 | pub position:float3, 164 | pub scale:float3, 165 | pub rotation:float3, 166 | pub shapes:Vec 167 | } 168 | 169 | impl ModelShapeBuilder 170 | { 171 | #[inline] 172 | pub fn new() -> Self 173 | { 174 | Self 175 | { 176 | position:float3::zero(), 177 | scale:float3::one(), 178 | rotation:float3::zero(), 179 | shapes:Vec::new(), 180 | } 181 | } 182 | 183 | #[inline] 184 | pub fn build(self) -> ModelShape 185 | { 186 | let mut mesh = ModelShape::new(self.shapes); 187 | mesh.set_translate(self.position); 188 | mesh.set_scale(self.scale); 189 | mesh.set_rotation(self.rotation); 190 | mesh 191 | } 192 | 193 | #[inline] 194 | pub fn add_shape(mut self, shape:MeshShape) -> Self 195 | { 196 | self.shapes.push(shape); 197 | self 198 | } 199 | 200 | #[inline] 201 | pub fn set_translate(mut self, pos:float3) -> Self 202 | { 203 | self.position = pos; 204 | self 205 | } 206 | 207 | #[inline] 208 | pub fn set_scale(mut self, sz:float3) -> Self 209 | { 210 | self.scale = sz; 211 | self 212 | } 213 | 214 | #[inline] 215 | pub fn set_rotation(mut self, rot:float3) -> Self 216 | { 217 | self.rotation = rot; 218 | self 219 | } 220 | } -------------------------------------------------------------------------------- /src/scene/spectrum/celsius.rs: -------------------------------------------------------------------------------- 1 | use super::rgb::*; 2 | use super::kelvin::*; 3 | 4 | #[derive(Debug, Default, Copy, Clone, PartialEq, Serialize, Deserialize)] 5 | pub struct Celsius(pub f32); 6 | 7 | impl From for Kelvin 8 | { 9 | fn from(c:Celsius) -> Self 10 | { 11 | Kelvin(c.0 + 273.15) 12 | } 13 | } 14 | 15 | impl From for Celsius 16 | { 17 | fn from(k:Kelvin) -> Self 18 | { 19 | Celsius(k.0 - 273.15) 20 | } 21 | } 22 | 23 | impl From for RGBSpectrum 24 | { 25 | fn from(c:Celsius) -> Self 26 | { 27 | let k : Kelvin = c.into(); 28 | return k.into(); 29 | } 30 | } -------------------------------------------------------------------------------- /src/scene/spectrum/kelvin.rs: -------------------------------------------------------------------------------- 1 | use std::f32; 2 | use super::rgb::*; 3 | 4 | #[derive(Debug, Default, Copy, Clone, PartialEq, Serialize, Deserialize)] 5 | pub struct Kelvin(pub f32); 6 | 7 | impl From for RGBSpectrum 8 | { 9 | fn from(kelvin:Kelvin) -> Self 10 | { 11 | assert!(kelvin.0 >= 0.0 && kelvin.0 <= 40000.0); 12 | 13 | let temp = kelvin.0 / 100.0; 14 | let temp60 = f32::max(0.0, temp - 60.0); 15 | let red; let green; let blue; 16 | 17 | if temp <= 66.0 { 18 | red = 1.0; 19 | } else { 20 | red = 1.292936186062745 * f32::powf(temp60, -0.1332047592); 21 | }; 22 | 23 | if temp <= 66.0 { 24 | green = 0.3900815787690196 * f32::log(temp, f32::consts::E) - 0.6318414437886275; 25 | } else { 26 | green = 1.129890860895294 * f32::powf(temp60, -0.0755148492); 27 | }; 28 | 29 | if temp >= 66.0 { 30 | blue = 1.0; 31 | } else { 32 | if temp <= 19.0 { 33 | blue = 0.0; 34 | } else { 35 | blue = 0.5432067891101961 * f32::log(temp - 10.0, f32::consts::E) - 1.19625408914; 36 | } 37 | }; 38 | 39 | RGBSpectrum::new(red, green, blue) 40 | } 41 | } -------------------------------------------------------------------------------- /src/scene/spectrum/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod rgb; 2 | pub mod srgb; 3 | pub mod xyz; 4 | pub mod kelvin; 5 | pub mod celsius; 6 | pub mod unit; 7 | 8 | pub use self::rgb::*; 9 | pub use self::srgb::*; 10 | pub use self::xyz::*; 11 | pub use self::kelvin::*; 12 | pub use self::celsius::*; 13 | pub use self::unit::*; 14 | 15 | pub type Spectrum = rgb::RGBSpectrum; -------------------------------------------------------------------------------- /src/scene/spectrum/rgb.rs: -------------------------------------------------------------------------------- 1 | use std::f32; 2 | use std::ops::{Add, Sub, Mul, Div, Neg}; 3 | use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign}; 4 | use crate::math::consts::{Zero, One}; 5 | 6 | #[derive(Debug, Default, Copy, Clone, PartialEq, Serialize, Deserialize)] 7 | pub struct RGB(pub f32, pub f32, pub f32); 8 | 9 | #[derive(Debug, Default, Copy, Clone, PartialEq, Serialize, Deserialize)] 10 | pub struct RGBSpectrum 11 | { 12 | pub x:f32, 13 | pub y:f32, 14 | pub z:f32, 15 | } 16 | 17 | impl RGBSpectrum 18 | { 19 | /// Creates a new RGBSpectrum from multiple components 20 | pub fn new(x: f32, y: f32, z: f32) -> Self 21 | { 22 | Self { x, y, z } 23 | } 24 | 25 | pub fn to_rgb(&self) -> (f32, f32, f32) 26 | { 27 | (self.x, self.y, self.z) 28 | } 29 | 30 | /// return the length of element 31 | pub fn len() -> usize 32 | { 33 | return 3; 34 | } 35 | 36 | pub fn lum(&self) -> f32 37 | { 38 | let lum = (0.212671, 0.715160, 0.072169); 39 | 40 | return 41 | lum.0 * self.x + 42 | lum.1 * self.y + 43 | lum.2 * self.z; 44 | } 45 | } 46 | 47 | impl Neg for RGBSpectrum 48 | { 49 | type Output = RGBSpectrum; 50 | 51 | fn neg(self) -> RGBSpectrum 52 | { 53 | RGBSpectrum 54 | { 55 | x: -self.x, 56 | y: -self.y, 57 | z: -self.z 58 | } 59 | } 60 | } 61 | 62 | impl Add for RGBSpectrum 63 | { 64 | type Output = RGBSpectrum; 65 | 66 | fn add(self, other: RGBSpectrum) -> RGBSpectrum 67 | { 68 | RGBSpectrum 69 | { 70 | x: self.x + other.x, 71 | y: self.y + other.y, 72 | z: self.z + other.z 73 | } 74 | } 75 | } 76 | 77 | impl Sub for RGBSpectrum 78 | { 79 | type Output = RGBSpectrum; 80 | 81 | fn sub(self, other: RGBSpectrum) -> RGBSpectrum 82 | { 83 | RGBSpectrum 84 | { 85 | x: self.x - other.x, 86 | y: self.y - other.y, 87 | z: self.z - other.z 88 | } 89 | } 90 | } 91 | 92 | impl Mul for RGBSpectrum 93 | { 94 | type Output = RGBSpectrum; 95 | 96 | fn mul(self, other: RGBSpectrum) -> RGBSpectrum 97 | { 98 | RGBSpectrum 99 | { 100 | x: self.x * other.x, 101 | y: self.y * other.y, 102 | z: self.z * other.z 103 | } 104 | } 105 | } 106 | 107 | impl Div for RGBSpectrum 108 | { 109 | type Output = RGBSpectrum; 110 | 111 | fn div(self, other: RGBSpectrum) -> RGBSpectrum 112 | { 113 | RGBSpectrum 114 | { 115 | x: self.x / other.x, 116 | y: self.y / other.y, 117 | z: self.z / other.z 118 | } 119 | } 120 | } 121 | 122 | impl AddAssign for RGBSpectrum 123 | { 124 | fn add_assign(&mut self, other: RGBSpectrum) 125 | { 126 | self.x += other.x; 127 | self.y += other.y; 128 | self.z += other.z; 129 | } 130 | } 131 | 132 | impl SubAssign for RGBSpectrum 133 | { 134 | fn sub_assign(&mut self, other: RGBSpectrum) 135 | { 136 | self.x -= other.x; 137 | self.y -= other.y; 138 | self.z -= other.z; 139 | } 140 | } 141 | 142 | impl MulAssign for RGBSpectrum 143 | { 144 | fn mul_assign(&mut self, other: RGBSpectrum) 145 | { 146 | self.x *= other.x; 147 | self.y *= other.y; 148 | self.z *= other.z; 149 | } 150 | } 151 | 152 | impl DivAssign for RGBSpectrum 153 | { 154 | fn div_assign(&mut self, other: RGBSpectrum) 155 | { 156 | self.x /= other.x; 157 | self.y /= other.y; 158 | self.z /= other.z; 159 | } 160 | } 161 | 162 | impl Zero for RGBSpectrum 163 | { 164 | #[inline(always)] 165 | fn zero() -> RGBSpectrum 166 | { 167 | RGBSpectrum 168 | { 169 | x: 0., y: 0., z: 0. 170 | } 171 | } 172 | } 173 | 174 | impl One for RGBSpectrum 175 | { 176 | #[inline(always)] 177 | fn one() -> RGBSpectrum 178 | { 179 | RGBSpectrum 180 | { 181 | x: 1., y: 1., z: 1. 182 | } 183 | } 184 | } 185 | 186 | impl From for RGBSpectrum 187 | { 188 | fn from(rgb:RGB) -> Self 189 | { 190 | RGBSpectrum::new(rgb.0, rgb.1, rgb.2) 191 | } 192 | } -------------------------------------------------------------------------------- /src/scene/spectrum/srgb.rs: -------------------------------------------------------------------------------- 1 | use super::rgb::*; 2 | 3 | #[derive(Debug, Default, Copy, Clone, PartialEq, Serialize, Deserialize)] 4 | pub struct SRGB(pub u8, pub u8, pub u8); 5 | 6 | fn srgb2linear(v: f32) -> f32 7 | { 8 | if v <= 0.04045 9 | { 10 | v / 12.92 11 | } 12 | else 13 | { 14 | ((v + 0.055) * 1.0 / 1.055).powf(2.4) 15 | } 16 | } 17 | 18 | fn linear2srgb(v: f32) -> f32 19 | { 20 | if v <= 0.0031308 21 | { 22 | 12.92 * v 23 | } 24 | else 25 | { 26 | 1.055 * f32::powf(v, 1.0 / 2.4) - 0.055 27 | } 28 | } 29 | 30 | impl From for RGB 31 | { 32 | fn from(srgb:SRGB) -> Self 33 | { 34 | Self 35 | { 36 | 0:srgb2linear(srgb.0 as f32 / 255.0), 37 | 1:srgb2linear(srgb.1 as f32 / 255.0), 38 | 2:srgb2linear(srgb.2 as f32 / 255.0), 39 | } 40 | } 41 | } 42 | 43 | impl From for SRGB 44 | { 45 | fn from(rgb:RGB) -> Self 46 | { 47 | Self 48 | { 49 | 0:(linear2srgb(rgb.0) * 255.0) as u8, 50 | 1:(linear2srgb(rgb.1) * 255.0) as u8, 51 | 2:(linear2srgb(rgb.2) * 255.0) as u8, 52 | } 53 | } 54 | } 55 | 56 | impl From for RGBSpectrum 57 | { 58 | fn from(srgb:SRGB) -> Self 59 | { 60 | let rgb : RGB = srgb.into(); 61 | RGBSpectrum::new(rgb.0, rgb.1, rgb.2) 62 | } 63 | } -------------------------------------------------------------------------------- /src/scene/spectrum/unit.rs: -------------------------------------------------------------------------------- 1 | use crate::math::Pi4; 2 | use super::super::core::LightType; 3 | 4 | #[derive(Debug, Default, Copy, PartialEq, Clone, Serialize, Deserialize)] 5 | pub struct Candela(pub f32); 6 | 7 | #[derive(Debug, Default, Copy, PartialEq, Clone, Serialize, Deserialize)] 8 | pub struct Lumens(pub f32); 9 | 10 | #[derive(Debug, Default, Copy, PartialEq, Clone, Serialize, Deserialize)] 11 | pub struct Incandescent(pub f32); 12 | 13 | #[derive(Debug, Default, Copy, PartialEq, Clone, Serialize, Deserialize)] 14 | pub struct Halogen(pub f32); 15 | 16 | #[derive(Debug, Default, Copy, PartialEq, Clone, Serialize, Deserialize)] 17 | pub struct LED(pub f32); 18 | 19 | #[derive(Debug, Default, Copy, PartialEq, Clone, Serialize, Deserialize)] 20 | pub struct Fluorescent(pub f32); 21 | 22 | impl Lumens 23 | { 24 | pub fn from_cd(kind:LightType, intensity:f32) -> Self 25 | { 26 | let lumens; 27 | 28 | match kind 29 | { 30 | LightType::Sky => lumens = intensity, 31 | LightType::Point => lumens = intensity * f32::pi4(), 32 | LightType::Spot => lumens = intensity * f32::pi4(), 33 | LightType::Directional => lumens = intensity, 34 | } 35 | 36 | return Lumens(lumens); 37 | } 38 | 39 | pub fn to_cd(&self, kind:LightType) -> Candela 40 | { 41 | let intensity; 42 | 43 | match kind 44 | { 45 | LightType::Sky => intensity = self.0, 46 | LightType::Point => intensity = self.0 / f32::pi4(), 47 | LightType::Spot => intensity = self.0 / f32::pi4(), 48 | LightType::Directional => intensity = self.0, 49 | } 50 | 51 | return Candela(intensity); 52 | } 53 | } 54 | 55 | impl From for f32 56 | { 57 | fn from(cd:Candela) -> f32 58 | { 59 | cd.0 60 | } 61 | } 62 | 63 | impl From for f32 64 | { 65 | fn from(lm:Lumens) -> f32 66 | { 67 | lm.0 68 | } 69 | } 70 | 71 | impl From for Lumens 72 | { 73 | fn from(watts:Incandescent) -> Lumens 74 | { 75 | Lumens(watts.0 * f32::pi4()) 76 | } 77 | } 78 | 79 | impl From for Lumens 80 | { 81 | fn from(watts:Halogen) -> Lumens 82 | { 83 | Lumens(watts.0 * 20.0) 84 | } 85 | } 86 | 87 | impl From for Lumens 88 | { 89 | fn from(watts:LED) -> Lumens 90 | { 91 | Lumens(watts.0 * 80.0) 92 | } 93 | } 94 | 95 | impl From for Lumens 96 | { 97 | fn from(watts:Fluorescent) -> Lumens 98 | { 99 | Lumens(watts.0 * 15.0) 100 | } 101 | } 102 | 103 | impl From for Incandescent 104 | { 105 | fn from(lm:Lumens) -> Incandescent 106 | { 107 | Incandescent(lm.0 / f32::pi4()) 108 | } 109 | } 110 | 111 | impl From for Halogen 112 | { 113 | fn from(lm:Lumens) -> Halogen 114 | { 115 | Halogen(lm.0 / 20.0) 116 | } 117 | } 118 | 119 | impl From for LED 120 | { 121 | fn from(lm:Lumens) -> LED 122 | { 123 | LED(lm.0 / 80.0) 124 | } 125 | } 126 | 127 | impl From for Fluorescent 128 | { 129 | fn from(lm:Lumens) -> Fluorescent 130 | { 131 | Fluorescent(lm.0 / 15.0) 132 | } 133 | } -------------------------------------------------------------------------------- /src/scene/spectrum/xyz.rs: -------------------------------------------------------------------------------- 1 | use super::rgb::*; 2 | 3 | #[derive(Debug, Default, Copy, Clone, PartialEq, Serialize, Deserialize)] 4 | pub struct XYZ(f32, f32, f32); 5 | 6 | impl From for RGB 7 | { 8 | fn from(xyz:XYZ) -> Self 9 | { 10 | Self 11 | { 12 | 0:xyz.0 * 3.2404542 - xyz.1 * 1.5371385 - xyz.2 * 0.4985314, 13 | 1:xyz.0 * -0.9692660 + xyz.1 * 1.8760108 + xyz.2 * 0.0415560, 14 | 2:xyz.0 * 0.0556434 - xyz.1 * 0.2040259 + xyz.2 * 1.0572252 15 | } 16 | } 17 | } 18 | 19 | impl From for RGBSpectrum 20 | { 21 | fn from(xyz:XYZ) -> Self 22 | { 23 | let rgb : RGB = xyz.into(); 24 | RGBSpectrum::new(rgb.0, rgb.1, rgb.2) 25 | } 26 | } -------------------------------------------------------------------------------- /src/scene/util/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod uuid; -------------------------------------------------------------------------------- /src/scene/util/uuid.rs: -------------------------------------------------------------------------------- 1 | use rand::prelude::*; 2 | 3 | 4 | pub trait OsRandNewV4 5 | { 6 | fn new_v4_osrng() -> uuid::Uuid; 7 | } 8 | 9 | impl OsRandNewV4 for uuid::Uuid 10 | { 11 | fn new_v4_osrng() -> uuid::Uuid 12 | { 13 | let mut rng = rand::rngs::OsRng::new().unwrap(); 14 | let mut bytes = [0; 16]; 15 | 16 | rng.fill_bytes(&mut bytes); 17 | 18 | uuid::Builder::from_bytes(bytes).build() 19 | } 20 | } --------------------------------------------------------------------------------