Browse Source

remove rust learning stuff

master
Georg Hopp 6 years ago
parent
commit
3087691df9
Signed by: ghopp GPG Key ID: 4C5D226768784538
  1. 14
      .gitignore
  2. 0
      Cargo.toml
  3. 69
      README.md
  4. 6
      branches/Cargo.lock
  5. 9
      branches/Cargo.toml
  6. 31
      branches/src/main.rs
  7. BIN
      fractional/.swp
  8. 12
      fractional/Cargo.toml
  9. BIN
      fractional/notes/09e-textures.pdf
  10. 1
      fractional/notes/frontier-map.url
  11. 7
      fractional/notes/html5
  12. 1
      fractional/notes/math.url
  13. BIN
      fractional/notes/polyhedra.pdf
  14. BIN
      fractional/notes/texmap.pdf
  15. 15
      fractional/notes/texture-mapping.url
  16. 115
      fractional/src/continuous.rs
  17. 252
      fractional/src/fractional.rs
  18. 376
      fractional/src/geometry.rs
  19. 35
      fractional/src/lib.rs
  20. 427
      fractional/src/main.rs
  21. 280
      fractional/src/trigonometry.rs
  22. 272
      fractional/src/xcb.rs
  23. 6
      functions/Cargo.lock
  24. 9
      functions/Cargo.toml
  25. 12
      functions/src/main.rs
  26. 91
      guessing_game/Cargo.lock
  27. 8
      guessing_game/Cargo.toml
  28. 36
      guessing_game/src/main.rs
  29. 6
      hello/Cargo.lock
  30. 7
      hello/Cargo.toml
  31. 3
      hello/src/main.rs
  32. 83
      interesting.md
  33. 6
      loops/Cargo.lock
  34. 9
      loops/Cargo.toml
  35. 64
      loops/src/main.rs
  36. 6
      ownership/Cargo.lock
  37. 9
      ownership/Cargo.toml
  38. 183
      ownership/src/main.rs
  39. 9
      rectangles/Cargo.toml
  40. 90
      rectangles/src/main.rs
  41. 9
      recursion/Cargo.toml
  42. 51
      recursion/src/main.rs
  43. 9
      restaurant/Cargo.toml
  44. 27
      restaurant/src/front_of_house.rs
  45. 23
      restaurant/src/front_of_house/hosting.rs
  46. 93
      restaurant/src/lib.rs
  47. 0
      src/easel.rs
  48. 0
      src/geometry.rs
  49. 0
      src/lib.rs
  50. 0
      src/transform.rs
  51. 0
      src/trigonometry.rs
  52. 0
      src/utils.rs
  53. 0
      src/vector.rs
  54. 0
      tests/web.rs
  55. 7
      tutorial/wasm-game-of-life/.gitignore
  56. 69
      tutorial/wasm-game-of-life/README.md
  57. 3
      tutorial/wasm-game-of-life/package-lock.json
  58. 520
      tutorial/wasm-game-of-life/src/easel.rs
  59. 186
      tutorial/wasm-game-of-life/src/transform.rs
  60. 139
      tutorial/wasm-game-of-life/src/vector.rs
  61. 6
      variables/Cargo.lock
  62. 9
      variables/Cargo.toml
  63. 6
      variables/src/main.rs
  64. 11
      wasm-game-of-life/.appveyor.yml
  65. 0
      wasm-game-of-life/.cargo-ok
  66. 3
      wasm-game-of-life/.gitignore
  67. 69
      wasm-game-of-life/.travis.yml
  68. 34
      wasm-game-of-life/Cargo.toml
  69. 176
      wasm-game-of-life/LICENSE_APACHE
  70. 25
      wasm-game-of-life/LICENSE_MIT
  71. 69
      wasm-game-of-life/README.md
  72. 3
      wasm-game-of-life/package-lock.json
  73. 19
      wasm-game-of-life/src/lib.rs
  74. 10
      wasm-game-of-life/src/utils.rs
  75. 13
      wasm-game-of-life/tests/web.rs
  76. 24
      wasm-game-of-life/www/.bin/create-wasm-app.js
  77. 2
      wasm-game-of-life/www/.gitignore
  78. 5
      wasm-game-of-life/www/.travis.yml
  79. 201
      wasm-game-of-life/www/LICENSE-APACHE
  80. 25
      wasm-game-of-life/www/LICENSE-MIT
  81. 67
      wasm-game-of-life/www/README.md
  82. 5
      wasm-game-of-life/www/bootstrap.js
  83. 11
      wasm-game-of-life/www/index.html
  84. 3
      wasm-game-of-life/www/index.js
  85. 5859
      wasm-game-of-life/www/package-lock.json
  86. 37
      wasm-game-of-life/www/package.json
  87. 14
      wasm-game-of-life/www/webpack.config.js
  88. 0
      www/.bin/create-wasm-app.js
  89. 0
      www/.gitignore
  90. 0
      www/README.md
  91. 0
      www/bootstrap.js
  92. 0
      www/index.html
  93. 0
      www/index.js
  94. 0
      www/package-lock.json
  95. 0
      www/package.json
  96. 0
      www/webpack.config.js
  97. 2
      xcb-test/.gitignore
  98. 11
      xcb-test/Cargo.toml
  99. 12
      xcb-test/Makefile
  100. 132
      xcb-test/alternatives/info.rs

14
.gitignore

@ -1,4 +1,10 @@
**/target
**/*.rs.bk
**/.cargo/*
**/Cargo.lock
# .cargo/*
*.rs.bk
Cargo.lock
wasm-pack.log
target/
bin/
pkg/
wasm-pack/

0
tutorial/wasm-game-of-life/Cargo.toml → Cargo.toml

69
README.md

@ -1,3 +1,72 @@
<div align="center">
<h1><code>wasm-pack-template</code></h1>
<strong>A template for kick starting a Rust and WebAssembly project using <a href="https://github.com/rustwasm/wasm-pack">wasm-pack</a>.</strong>
<p>
<a href="https://travis-ci.org/rustwasm/wasm-pack-template"><img src="https://img.shields.io/travis/rustwasm/wasm-pack-template.svg?style=flat-square" alt="Build Status" /></a>
</p>
<h3>
<a href="https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html">Tutorial</a>
<span> | </span>
<a href="https://discordapp.com/channels/442252698964721669/443151097398296587">Chat</a>
</h3>
<sub>Built with 🦀🕸 by <a href="https://rustwasm.github.io/">The Rust and WebAssembly Working Group</a></sub>
</div>
## About
[**📚 Read this template tutorial! 📚**][template-docs]
This template is designed for compiling Rust libraries into WebAssembly and
publishing the resulting package to NPM.
Be sure to check out [other `wasm-pack` tutorials online][tutorials] for other
templates and usages of `wasm-pack`.
[tutorials]: https://rustwasm.github.io/docs/wasm-pack/tutorials/index.html
[template-docs]: https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html
## 🚴 Usage
### 🐑 Use `cargo generate` to Clone this Template
[Learn more about `cargo generate` here.](https://github.com/ashleygwilliams/cargo-generate)
```
cargo generate --git https://github.com/rustwasm/wasm-pack-template.git --name my-project
cd my-project
```
### 🛠️ Build with `wasm-pack build`
```
wasm-pack build
```
### 🔬 Test in Headless Browsers with `wasm-pack test`
```
wasm-pack test --headless --firefox
```
### 🎁 Publish to NPM with `wasm-pack publish`
```
wasm-pack publish
```
## 🔋 Batteries Included
* [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) for communicating
between WebAssembly and JavaScript.
* [`console_error_panic_hook`](https://github.com/rustwasm/console_error_panic_hook)
for logging panic messages to the developer console.
* [`wee_alloc`](https://github.com/rustwasm/wee_alloc), an allocator optimized
for small code size.
# Rust playground # Rust playground
Things I have recently done while learning the Rust programming language. Things I have recently done while learning the Rust programming language.

6
branches/Cargo.lock

@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "branches"
version = "0.1.0"

9
branches/Cargo.toml

@ -1,9 +0,0 @@
[package]
name = "branches"
version = "0.1.0"
authors = ["Georg Hopp <georg@steffers.org>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

31
branches/src/main.rs

@ -1,31 +0,0 @@
//
// Control Flow Examples
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
fn main() {
let condition = true;
let number = if condition {
5
} else {
6
};
println!("The value of number is: {}", number);
}

BIN
fractional/.swp

12
fractional/Cargo.toml

@ -1,12 +0,0 @@
[package]
name = "fractional"
version = "0.1.0"
authors = ["Georg Hopp <georg@steffers.org>"]
edition = "2018"
[dependencies]
lazy_static = "1.4.0"
libc = "0.2"
gl = "0.5.2"
x11 = { version = "2.3", features = ["glx"] }
xcb = { version = "0.8", features = ["dri2", "randr", "thread", "xlib_xcb", "shm"] }

BIN
fractional/notes/09e-textures.pdf

1
fractional/notes/frontier-map.url

@ -1 +0,0 @@
http://www.jongware.com/galaxy1.html

7
fractional/notes/html5

@ -1,7 +0,0 @@
I really would like to see a HTML5 canvas as canvas for the 3D code.
Some URLs:
- https://stackoverflow.com/questions/42806037/modify-canvas-from-wasm
- https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.HtmlCanvasElement.html
- https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.CanvasRenderingContext2d.html
- https://stackoverflow.com/questions/49935207/editing-canvas-pixel-data-in-webassembly-rust

1
fractional/notes/math.url

@ -1 +0,0 @@
https://www.themathpage.com/Alg/reciprocals.htm

BIN
fractional/notes/polyhedra.pdf

BIN
fractional/notes/texmap.pdf

15
fractional/notes/texture-mapping.url

@ -1,15 +0,0 @@
https://en.wikipedia.org/wiki/Texture_mapping
http://www.gamers.org/dEngine/quake/papers/checker_texmap.html
https://www.cs.uic.edu/~jbell/CourseNotes/ComputerGraphics/TextureMapping.html
http://www.decew.net/OSS/References/chapter_2_texture_mapping.pdf
# example affine texture mapping
http://archive.gamedev.net/archive/reference/articles/article852.html
http://www.lysator.liu.se/~mikaelk/doc/perspectivetexture/
# Shader... This also describes z-Buffer... :)
https://people.ece.cornell.edu/land/OldStudentProjects/cs490-95to96/GUO/report.html
https://software.intel.com/en-us/articles/the-basics-of-the-art-of-lighting-part-3-lighting-and-shaders/
https://docs.unity3d.com/Manual/Lighting.html

115
fractional/src/continuous.rs

@ -1,115 +0,0 @@
//
// A «continued fraction» is a representation of a fraction as a vector
// of integrals… Irrational fractions will result in infinite most of the
// time repetitive vectors. They can be used to get a resonable approximation
// for sqrt on fractionals.
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
use crate::Fractional;
#[derive(Debug)]
pub struct Continuous (Vec<i64>);
impl Continuous {
// calculate a sqrt as continued fraction sequence. Taken from:
// https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#
// Continued_fraction_expansion
pub fn sqrt(x :i64, a0 :i64) -> Self {
fn inner(v :&mut [i64], x :i64, a0 :i64, mn :i64, dn :i64, an :i64) {
let mn_1 = dn * an - mn;
let dn_1 = (x - mn_1 * mn_1) / dn;
let an_1 = (a0 + mn_1) / dn_1;
v[0] = an;
// The convergence criteria „an_1 == 2 * a0“ is not good for
// very small x thus I decided to break the iteration at constant
// time. Which is the 5 below.
if v.len() > 1 {
inner(&mut v[1..], x, a0, mn_1, dn_1, an_1);
}
}
let mut v :Vec<i64> = vec!(0; 5);
inner(&mut v, x, a0, 0, 1, a0);
Continuous(v)
}
// general continous fraction form of a fractional...
pub fn from_prec(f :&Fractional, prec :Option<usize>) -> Self {
fn inner(v :&mut Vec<i64>, f :Fractional, prec :Option<usize>) {
let mut process = |prec :Option<usize>| {
let Fractional(n, d) = f;
let a = n / d;
let Fractional(_n, _d) = f.noreduce_sub(a.into());
v.push(a);
match _n {
1 => v.push(_d),
0 => {},
_ => inner(v, Fractional(_d, _n), prec),
}
};
match prec {
Some(0) => {},
None => process(None),
Some(p) => process(Some(p - 1)),
}
}
let mut v = match prec {
None => Vec::with_capacity(100),
Some(p) => Vec::with_capacity(p + 1),
};
inner(&mut v, *f, prec);
Continuous(v)
}
pub fn into_prec(&self, prec :Option<usize>) -> Fractional {
let Continuous(c) = self;
let p = match prec {
Some(p) => if p <= c.len() { p } else { c.len() },
None => c.len(),
};
let to_frac = |acc :Fractional, x :&i64| {
let Fractional(an, ad) = acc.noreduce_add((*x).into());
Fractional(ad, an)
};
let Fractional(n, d) = c[..p]
. into_iter()
. rev()
. fold(Fractional(0, 1), to_frac);
Fractional(d, n)
}
}
impl From<&Fractional> for Continuous {
fn from(x :&Fractional) -> Self {
Self::from_prec(x, None)
}
}
impl Into<Fractional> for &Continuous {
fn into(self) -> Fractional {
(&self).into_prec(None)
}
}

252
fractional/src/fractional.rs

@ -1,252 +0,0 @@
//
// Some code to support fractional numbers for full precision rational number
// calculations. (At least for the standard operations.)
// This also implements a sqrt on fractional numbers, which can not be precise
// because of the irrational nature of most sqare roots.
// Fractions can only represent rational numbers precise.
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
use std::cmp::Ordering;
use std::convert::{TryFrom, TryInto};
use std::fmt::{Formatter, Display};
use std::num::TryFromIntError;
use std::ops::{Add,Sub,Neg,Mul,Div};
use crate::continuous::Continuous;
#[derive(Debug, Eq, Clone, Copy)]
pub struct Fractional (pub i64, pub i64);
#[inline]
fn hcf(x :i64, y :i64) -> i64 {
match y {
0 => x,
_ => hcf(y, x % y),
}
}
pub fn from_vector(xs: &Vec<i64>) -> Vec<Fractional> {
xs.iter().map(|x| Fractional(*x, 1)).collect()
}
impl Fractional {
#[inline]
pub fn gcd(self, other: Self) -> i64 {
let Fractional(_, d1) = self;
let Fractional(_, d2) = other;
(d1 * d2) / hcf(d1, d2)
}
#[inline]
pub fn reduce(self) -> Self {
let Fractional(n, d) = self;
let (_n, _d) = if n > d { (n, d) } else { (d, n) };
// if the difference from _n % _d to _n is very big we are close to
// a whole number and can ignore the fractional part... this reduces
// the precision but ensures smaller numbers for numerator and
// denominator.
if _d > 1 && (_n % _d) * 10000000 < _n {
if n == _n {
Self(_n / _d, 1)
} else {
Self(1, _n / _d)
}
} else {
// Self(n / hcf(n, d), d / hcf(n, d))
// The above reduces prcisely but results in very large numerator
// or denominator occasionally. The below is less precise but
// keeps the numbers small… the bad point is, that it is not very
// fast.
let cont = Continuous::from_prec(&self, Some(5));
(&cont).into()
}
}
pub fn noreduce_add(self, other: Self) -> Self {
let Fractional(n1, d1) = self;
let Fractional(n2, d2) = other;
let n = n1 * (self.gcd(other) / d1) + n2 * (self.gcd(other) / d2);
Self(n, self.gcd(other))
}
pub fn noreduce_sub(self, other: Self) -> Self {
self.noreduce_add(other.noreduce_neg())
}
pub fn noreduce_neg(self) -> Self {
let Fractional(n, d) = self;
Self(-n, d)
}
}
impl From<i64> for Fractional {
fn from(x: i64) -> Self {
Self(x, 1)
}
}
impl From<i32> for Fractional {
fn from(x: i32) -> Self {
Self(x as i64, 1)
}
}
impl TryFrom<usize> for Fractional {
type Error = &'static str;
fn try_from(x: usize) -> Result<Self, Self::Error> {
let v = i64::try_from(x);
match v {
Err(_) => Err("Conversion from usize to i32 failed"),
Ok(_v) => Ok(Self(_v, 1)),
}
}
}
impl TryInto<f64> for Fractional {
type Error = TryFromIntError;
fn try_into(self) -> Result<f64, Self::Error> {
let n :i32 = self.0.try_into()?;
let d :i32 = self.1.try_into()?;
Ok(f64::from(n) / f64::from(d))
}
}
impl TryInto<(i32, i32)> for Fractional {
type Error = TryFromIntError;
fn try_into(self) -> Result<(i32, i32), Self::Error> {
let a :i32 = (self.0 / self.1).try_into()?;
let b :i32 = (self.0 % self.1).try_into()?;
Ok((a, b))
}
}
impl Display for Fractional {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "({}/{})", self.0, self.1)
}
}
impl PartialEq for Fractional {
fn eq(&self, other: &Self) -> bool {
let Fractional(n1, d1) = self;
let Fractional(n2, d2) = other;
n1 * (self.gcd(*other) / d1) == n2 * (self.gcd(*other) / d2)
}
}
impl PartialOrd for Fractional {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Fractional {
fn cmp(&self, other: &Self) -> Ordering {
let Fractional(n1, d1) = self;
let Fractional(n2, d2) = other;
let x = n1 * (self.gcd(*other) / d1);
let y = n2 * (self.gcd(*other) / d2);
x.cmp(&y)
}
}
impl Add for Fractional {
type Output = Self;
fn add(self, other: Self) -> Self {
self.noreduce_add(other).reduce()
}
}
impl Sub for Fractional {
type Output = Self;
fn sub(self, other: Self) -> Self {
self + -other
}
}
impl Neg for Fractional {
type Output = Self;
fn neg(self) -> Self {
let Fractional(n, d) = self;
Self(-n, d)
}
}
impl Mul for Fractional {
type Output = Self;
fn mul(self, other :Self) -> Self {
let Fractional(n1, d1) = self;
let Fractional(n2, d2) = other;
Self(n1 * n2, d1 * d2).reduce()
}
}
impl Div for Fractional {
type Output = Self;
fn div(self, other: Self) -> Self {
let Fractional(n, d) = other;
self * Fractional(d, n)
}
}
/* some stuff that could be tested...
let x = Fractional(1, 3);
let y = Fractional(1, 6);
println!(
"Greatest common denominator of {} and {}: {}", x, y, x.gcd(y));
println!("Numerator of {}: {}", x, x.numerator());
println!("Denominator of {}: {}", x, x.denominator());
assert_eq!(Fractional(1, 3), Fractional(2, 6));
assert_eq!(Fractional(1, 3), Fractional(1, 3));
assert_eq!(y < x, true);
assert_eq!(y > x, false);
assert_eq!(x == y, false);
assert_eq!(x == x, true);
assert_eq!(x + y, Fractional(1, 2));
println!("{} + {} = {}", x, y, x + y);
assert_eq!(x - y, Fractional(1, 6));
println!("{} - {} = {}", x, y, x - y);
assert_eq!(y - x, Fractional(-1, 6));
println!("{} - {} = {}", y, x, y - x);
assert_eq!(-x, Fractional(-1, 3));
println!("-{} = {}", x, -x);
assert_eq!(x * y, Fractional(1, 18));
println!("{} * {} = {}", x, y, x * y);
assert_eq!(x / y, Fractional(2, 1));
println!("{} / {} = {}", x, y, x / y);
assert_eq!(y / x, Fractional(1, 2));
println!("{} / {} = {}", y, x, y / x);
println!("Fractional from 3: {}", Fractional::from(3));
let z :f64 = Fractional::into(x);
println!("Floating point of {}: {}", x, z);
let (d, r) = Fractional::into(x);
println!("(div, rest) of {}: ({}, {})", x, d, r);
*/

376
fractional/src/geometry.rs

@ -1,376 +0,0 @@
//
// Basic geometric things...
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
use std::convert::{From, Into};
use std::ops::{Add,Sub,Neg,Mul,Div};
use std::fmt::Debug;
use crate::easel::{Canvas, Coordinate, Coordinates, Polygon};
use crate::transform::{TMatrix, Transformable};
use crate::trigonometry::Trig;
use crate::vector::Vector;
#[derive(Debug, Clone)]
pub struct Face<T>
where T: Add + Sub + Neg + Mul + Div + Copy + Trig {
corners :Vec<usize>,
normal :Option<Vector<T>>,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct Point<T>(pub Vector<T>, T)
where T: Add + Sub + Neg + Mul + Div + PartialEq + Copy + Trig;
impl<T> Point<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ PartialEq + Trig + Copy + From<i32> {
pub fn new(x :T, y :T, z :T) -> Self {
Self(Vector(x, y, z), 1.into())
}
}
impl<T> Add for Point<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ PartialEq + Trig + Copy {
type Output = Self;
fn add(self, other :Self) -> Self {
let Point(v1, w1) = self;
let Point(v2, w2) = other;
Self(v1 + v2, w1 + w2)
}
}
impl<T> Neg for Point<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ PartialEq + Trig + Copy {
type Output = Self;
fn neg(self) -> Self {
let Point(v, w) = self;
Self(-v, -w)
}
}
impl<T> Sub for Point<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ PartialEq + Trig + Copy {
type Output = Self;
fn sub(self, other :Self) -> Self {
self + -other
}
}
impl<T> Mul for Point<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ PartialEq + Trig + Copy + From<i32> {
type Output = Self;
fn mul(self, other :Self) -> Self {
let a :Vector<T> = self.into();
let b :Vector<T> = other.into();
Point(a * b, 1.into())
}
}
impl<T> From<Vector<T>> for Point<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ PartialEq + Trig + Copy + From<i32> {
fn from(v :Vector<T>) -> Self {
Point(v, 1.into())
}
}
impl<T> Into<Vector<T>> for Point<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ PartialEq + Trig + Copy + From<i32> {
fn into(self) -> Vector<T> {
let Point(v, w) = self;
if w == 0.into() {
v
} else {
v.mul(&w.recip())
}
}
}
impl<T> Transformable<T> for Point<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ PartialEq + Debug + Trig + Copy + From<i32> {
fn transform(&self, m :&TMatrix<T>) -> Self {
let Point(v, w) = *self;
let (v, w) = m.apply(&v, w);
if w == 0.into() {
v.into()
} else {
v.mul(&w.recip()).into()
}
}
}
#[derive(Debug)]
pub struct Polyeder<T>
where T: Add + Sub + Neg + Mul + Div + PartialEq + Copy + Trig {
points :Vec<Point<T>>,
faces :Vec<Face<T>>,
}
pub trait Primitives<T>
where T: Add + Sub + Neg + Mul + Div + Debug + Copy + Trig + From<i32> {
fn transform(&self, m :&TMatrix<T>) -> Self;
fn project( &self
, camera :&Camera<T>
, light :&DirectLight<T>
, col :u32 ) -> Vec<(Polygon<T>, u32)>;
}
pub struct Camera<T>
where T: Add + Sub + Neg + Mul + Div + Debug + Copy + Trig + From<i32> {
width :T,
height :T,
distance :T,
project :TMatrix<T>,
}
pub struct DirectLight<T>
where T: Add + Sub + Neg + Mul + Div + Debug + Copy + Trig + From<i32> {
direction: Vector<T>,
}
impl<T> Camera<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ PartialEq + Debug + Copy + Trig + From<i32> {
// This code assumes that the size of the viewport is always
// equal to the size of the physical screen… e.g. window/canvas thus some
// effects can't be done. See book for examples with different viewport
// and screen sizes.
pub fn new(c :&dyn Canvas<T>, angle :i32) -> Self {
let width :T = (c.width() as i32).into();
let height :T = (c.height() as i32).into();
let d :T = 1.into();
let fov = T::cot(angle) * width;
let wh = width / 2.into();
let hh = height / 2.into();
Camera { width: width
, height: height
, distance: d
, project: TMatrix::new(
( fov, 0.into(), wh, 0.into())
, (0.into(), fov, hh, 0.into())
, (0.into(), 0.into(), d, 1.into())
, (0.into(), 0.into(), 1.into(), 0.into()) ) }
}
pub fn get_distance(&self) -> T {
self.distance
}
pub fn get_projection(&self) -> TMatrix<T> {
self.project
}
pub fn project(&self, p :Point<T>) -> Point<T> {
p.transform(&self.project)
}
}
impl<T> DirectLight<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ Debug + Copy + Trig + From<i32> {
pub fn new(v :Vector<T>) -> Self {
DirectLight{ direction: v }
}
pub fn dir(&self) -> Vector<T> {
self.direction
}
}
impl<T> Face<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ PartialEq + Debug + Copy + Trig + From<i32> {
fn new(corners :Vec<usize>, ps :&[Point<T>]) -> Self {
let mut f = Face{ corners: corners, normal: None };
f.update_normal(ps);
f
}
fn update_normal(&mut self, ps :&[Point<T>]) {
let edge10 :Vector<T> = (ps[self.corners[1]] - ps[self.corners[0]]).into();
let edge12 :Vector<T> = (ps[self.corners[1]] - ps[self.corners[2]]).into();
self.normal = Some(edge10 * edge12);
}
}
impl<T> Polyeder<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ PartialEq + Debug + Copy + Trig + From<i32> {
fn update_normals(&mut self) {
for f in self.faces.iter_mut() {
f.update_normal(&self.points);
}
}
// construct via cube, see polyhedra.pdf
pub fn tetrahedron(a :T) -> Polyeder<T> {
let f2 :T = 2.into();
let ch = a / (f2 * T::sqrt(f2).unwrap());
let ps = vec!( Point::new(-ch, -ch, ch) // A
, Point::new(-ch, ch, -ch) // C
, Point::new( ch, -ch, -ch) // E
, Point::new( ch, ch, ch) ); // G
// bottom: 1, 2, 3
let fs = vec!( Face::new(vec!(2, 1, 0), &ps) // bottom
, Face::new(vec!(3, 2, 0), &ps)
, Face::new(vec!(0, 1, 3), &ps)
, Face::new(vec!(1, 2, 3), &ps) );
//let fs = vec!( Face::new(vec!(0, 1, 2), &ps) // bottom
// , Face::new(vec!(0, 2, 3), &ps)
// , Face::new(vec!(3, 1, 0), &ps)
// , Face::new(vec!(3, 2, 1), &ps) );
Polyeder{ points: ps, faces: fs }
}
pub fn triangle(a :T) -> Polyeder<T> {
let f0 :T = 0.into();
let f3 :T = 3.into();
let f6 :T = 6.into();
let zi :T = T::sqrt(f3).unwrap() / f6 * a;
let zc :T = T::sqrt(f3).unwrap() / f3 * a;
let ah :T = a / 2.into();
let ps = vec!( Point::new(-ah, f0, -zi)
, Point::new( f0, f0, zc)
, Point::new( ah, f0, -zi) );
let fs = vec!(Face::new(vec!(0, 1, 2), &ps));
Polyeder{ points: ps, faces: fs }
}
pub fn cube(a :T) -> Polyeder<T> {
let ah :T = a / From::<i32>::from(2);
let ps = vec!( Point::new(-ah, ah, -ah) // 0 => front 1
, Point::new(-ah, -ah, -ah) // 1 => front 2
, Point::new( ah, -ah, -ah) // 2 => front 3
, Point::new( ah, ah, -ah) // 3 => front 4
, Point::new(-ah, ah, ah) // 4 => back 1
, Point::new(-ah, -ah, ah) // 5 => back 2
, Point::new( ah, -ah, ah) // 6 => back 3
, Point::new( ah, ah, ah) ); // 7 => back 4
let fs = vec!( Face::new(vec!(0, 1, 2, 3), &ps) // front
, Face::new(vec!(7, 6, 5, 4), &ps) // back
, Face::new(vec!(1, 5, 6, 2), &ps) // top
, Face::new(vec!(0, 3, 7, 4), &ps) // bottom
, Face::new(vec!(0, 4, 5, 1), &ps) // left
, Face::new(vec!(2, 6, 7, 3), &ps) ); // right
Polyeder{ points: ps, faces: fs }
}
}
impl<T> Primitives<T> for Polyeder<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ Debug + Copy + Trig + From<i32> + PartialOrd {
// TODO Maybe this should also be an instance of Transformable…
fn transform(&self, m :&TMatrix<T>) -> Self {
let Polyeder{ points: ps, faces: fs } = self;
let mut p = Polyeder{
points: ps.iter().map(|p| p.transform(m)).collect()
, faces: fs.to_vec()
};
// TODO alternatively we could rotate the normals too, but this cannot
// done with the original matrix… the question is, what is faster.
p.update_normals();
p
}
fn project( &self
, camera :&Camera<T>
, light :&DirectLight<T>
, color :u32 ) -> Vec<(Polygon<T>, u32)> {
// Helper to create a Polygon from Coordinates…
// TODO probably there needs to be a Polygon constructor for this.
fn polygon<I, T>(c :I) -> Polygon<T>
where I: Iterator<Item = Coordinate<T>> {
Polygon(Coordinates(c.collect()))
}
// this one does the projection... as the projection was the last
// matrix we do not need to do it here.
let to_coord = |p :&usize| {
let Point(v, _) = camera.project(self.points[*p]);
Coordinate(T::round(&v.x()), T::round(&v.y()), v.z() - 1.into())
};
let to_poly = |f :&Face<T>| {
let pg = polygon(f.corners.iter().map(to_coord));
let mut r :T = (((color >> 16) & 0xFF) as i32).into();
let mut g :T = (((color >> 8) & 0xFF) as i32).into();
let mut b :T = (((color ) & 0xFF) as i32).into();
let lf :T = match f.normal {
None => 1.into(),
Some(n) => n.dot(light.dir())
/ (n.mag() * light.dir().mag()),
};
// this "if" represents a first simple backface culling
// approach. We only return face that face towards us.
if lf < 0.into() {
r = r * -lf;
g = g * -lf;
b = b * -lf;
let c :u32 = (r.round() as u32) << 16
| (g.round() as u32) << 8
| (b.round() as u32);
Some((pg, c))
} else {
None
}};
self.faces.iter().filter_map(to_poly).collect()
}
}

35
fractional/src/lib.rs

@ -1,35 +0,0 @@
//
// Lib for fractional calculations.
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
extern crate lazy_static;
pub type Error = &'static str;
pub mod continuous;
pub mod easel;
pub mod fractional;
pub mod transform;
pub mod trigonometry;
pub mod vector;
pub mod xcb;
pub mod geometry;
use fractional::Fractional;
use vector::Vector;

427
fractional/src/main.rs

@ -1,427 +0,0 @@
//
// Test our fractional crate / module...
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
use std::convert::{TryFrom, TryInto, Into};
use std::f64::consts::PI as FPI;
use std::fmt::{Debug, Display};
use std::marker::Send;
use std::num::TryFromIntError;
use std::ops::{Add,Sub,Neg,Mul,Div};
use std::sync::mpsc;
use std::thread;
use std::time::{Duration, Instant};
use fractional::continuous::Continuous;
use fractional::easel::{ Coordinate, Coordinates, Drawable, Line, Polyline
, Polygon, Canvas, Fillable };
use fractional::fractional::{Fractional, from_vector};
use fractional::trigonometry::Trig;
use fractional::vector::Vector;
use fractional::transform::{TMatrix, Transformable};
use fractional::xcb::XcbEasel;
use fractional::geometry::{Camera, DirectLight, Polyeder, Primitives};
fn mean(v: &Vec<i64>) -> Result<Fractional, TryFromIntError> {
let r = v.iter().fold(0, |acc, x| acc + x);
let l = i64::try_from(v.len())?;
Ok(Fractional(r, l))
}
fn common_fractional() {
let a = vec![3, 6, 1, 9];
let b = from_vector(&a);
let c = mean(&a).unwrap(); // This might fail if the len of the
// vector (usize) does not fit into i32.
let cr :f64 = c.try_into().unwrap();
println!(" [i32] : {:?}", a);
println!(" [Fractional] : {:?}", b);
println!(" mean of [i32] : {}" , c);
println!(" as f64 : {}" , cr);
println!(" again as f64 : {}" , TryInto::<f64>::try_into(c).unwrap());
}
fn continuous() {
let d = Fractional(45, 16);
let e = Fractional(16, 45);
let dc :Continuous = (&d).into();
let ec :Continuous = (&e).into();
println!("cont frac of d : {} => {:?}", d, dc);
println!("cont frac of e : {} => {:?}", e, ec);
println!(" reverted dc : {:?} {}", dc, Into::<Fractional>::into(&dc));
println!(" reverted ec : {:?} {}", ec, Into::<Fractional>::into(&ec));
}
fn sqrt() {
let f = Fractional(-9, 4);
let fr :f64 = f.try_into().unwrap();
let sq = f.sqrt();
let _sq = fr.sqrt();
println!("{:>14} : {:?} / {}", format!("sqrt {}", f), sq, _sq);
for f in [ Fractional(9, 4)
, Fractional(45, 16)
, Fractional(16, 45)
, Fractional(9, 3) ].iter() {
let fr :f64 = (*f).try_into().unwrap();
let sq = f.sqrt().unwrap();
let sqr :f64 = sq.try_into().unwrap();
let _sqr = fr.sqrt();
println!("{:>14} : {} {} / {}", format!("sqrt {}", f), sq, sqr, _sqr);
}
}
fn pi() {
let pi = Fractional::pi();
let pir :f64 = pi.try_into().unwrap();
let pit :(i32, i32) = pi.try_into().unwrap();
let pi2r :f64 = (pi * pi).try_into().unwrap();
println!(" Rust π : {}" , FPI);
println!(" π : {} {}" , pi, pir);
println!(" π as tuple : {:?}" , pit);
println!(" Rust π² : {}" , FPI * FPI);
println!(" π² : {} {}" , pi * pi, pi2r);
}
fn _sin() {
for d in [ 0, 30, 45, 90, 135, 180, 225, 270, 315
, 9, 17, 31, 73, 89, 123, 213, 312, 876 ].iter() {
let s = Fractional::sin(*d as i32);
let sr :f64 = s.try_into().unwrap();
let _s = f64::sin(*d as f64 * FPI / 180.0);
println!("{:>14} : {} {} / {}", format!("sin {}", d), s, sr, _s);
}
}
fn _tan() {
for d in [ 0, 30, 45, 90, 135, 180, 225, 270, 315
, 9, 17, 31, 73, 89, 123, 213, 312, 876 ].iter() {
let t = Fractional::tan(*d as i32);
let tr :f64 = t.try_into().unwrap();
let _t = f64::tan(*d as f64 * FPI / 180.0);
println!("{:>14} : {} {} / {}", format!("tan {}", d), t, tr, _t);
}
}
fn _cos() {
for d in [ 0, 30, 45, 90, 135, 180, 225, 270, 315
, 9, 17, 31, 73, 89, 123, 213, 312, 876 ].iter() {
let c = Fractional::cos(*d as i32);
let cr :f64 = c.try_into().unwrap();
let _c = f64::cos(*d as f64 * FPI / 180.0);
println!("{:>14} : {} {} / {}", format!("cos {}", d), c, cr, _c);
}
}
fn _vector1() {
let v1 = Vector(1.into(), 2.into(), 3.into());
let v2 = Vector(2.into(), 2.into(), 3.into());
let s :Fractional = 3.into();
_vector(v1, v2, s);
}
fn _vector2() {
let v1 = Vector(1.0, 2.0, 3.0);
let v2 = Vector(2.0, 2.0, 3.0);
let s = 3.0;
_vector(v1, v2, s);
}
fn _vector<T>(v1 :Vector<T>, v2 :Vector<T>, s :T)
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T> + Trig + Copy + Display {
println!("{:>14} : {}", "Vector v1", v1);
println!("{:>14} : {}", "Vector v2", v2);
println!("{:>14} : {}", "magnitude v1", v1.mag());
println!("{:>14} : {}", "-v1", -v1);
println!("{:>14} : {}", "v1 + v1", v1 + v1);
println!("{:>14} : {}", "v1 - v1", v1 - v1);
println!("{:>14} : {}", "v2 - v1", v2 - v1);
println!("{:>14} : {}", format!("v1 * {}", s), v1.mul(&s));
println!("{:>14} : {}", "norm v1", v1.norm());
println!("{:>14} : {}", "magnitude norm v1", v1.norm().mag());
println!("{:>14} : {}", "magnitude v1", v1.mag());
println!("{:>14} : {}", "norm * magnitude", v1.norm().mul(&v1.mag()));
println!("{:>14} : {}", "distance v1 v2", v1.distance(v2));
println!("{:>14} : {}", "distance v2 v1", v2.distance(v1));
println!("{:>14} : {}", "v1 dot v2", v1.dot(v2));
println!("{:>14} : {}", "v2 dot v1", v2.dot(v1));
println!("{:>14} : {}", "v1 * v2", v1 * v2);
println!("{:>14} : {}", "v2 * v1", v2 * v1);
}
fn _transform1() {
let v = Vector(Fractional(1,1), Fractional(1,1), Fractional(1,1));
let v1 = Vector(Fractional(1,1), Fractional(2,1), Fractional(3,1));
let v2 = Vector(Fractional(1,1), Fractional(1,1), Fractional(0,1));
let v3 = Vector(Fractional(1,1), Fractional(0,1), Fractional(1,1));
_transform(v, v1, v2, v3);
}
fn _transform2() {
let v = Vector(1.0, 1.0, 1.0);
let v1 = Vector(1.0, 2.0, 3.0);
let v2 = Vector(1.0, 1.0, 0.0);
let v3 = Vector(1.0, 0.0, 1.0);
_transform(v, v1, v2, v3);
}
fn _transform<T>(v :Vector<T>, v1 :Vector<T>, v2 :Vector<T>, v3 :Vector<T>)
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T> + Trig
+ Debug + From<i32> + Copy + Display {
println!("{:>14} : {}", "Vector v1", v1);
println!( "{:>14} : {}", "translate v1"
, v.transform(&TMatrix::translate(v)));
println!();
fn _rot<T>( o :&str , n :&str , v :&Vector<T>
, fs :&[&dyn Fn(i32) -> TMatrix<T>] )
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T> + Trig
+ Debug + From<i32> + Copy + Display {
for d in [ 30, 45, 60, 90, 120, 135, 150, 180
, 210, 225, 240, 270, 300, 315, 330 ].iter() {
let mi = fs.iter().map(|f| f(*d as i32));
println!( "{:>14} : {}"
, format!("{} {} {}", o, d, n)
, v.transform(&TMatrix::combine(mi)) );
}
}
println!("{:>14} : {}", "Vector v2", v2);
_rot("rot_x", "v2", &v2, &[&TMatrix::rotate_x]);
println!();
_rot("rot_y", "v2", &v2, &[&TMatrix::rotate_y]);
println!();
_rot("rot_xy", "v2", &v2, &[&TMatrix::rotate_x, &TMatrix::rotate_y]);
println!();
println!("{:>14} : {}", "Vector v3", v3);
_rot("rot_z", "v3", &v3, &[&TMatrix::rotate_z]);
println!();
for d in [ 30, 45, 60, 90, 120, 135, 150, 180
, 210, 225, 240, 270, 300, 315, 330 ].iter() {
println!( "{:>14} : {}"
, format!("rot_v {} v2", d)
, v2.transform(&TMatrix::rotate_v(&v, *d as i32)) );
}
}
fn _line() {
let a = (Coordinate(0, 1, 0.0), Coordinate(6, 4, 0.0));
let b = (Coordinate(0, 4, 0.0), Coordinate(6, 1, 0.0));
let c = (Coordinate(1, 0, 0.0), Coordinate(6, 8, 0.0));
let d = (Coordinate(1, 8, 0.0), Coordinate(6, 0, 0.0));
for i in [a, b, c, d].iter() {
println!("{:>14} : {}", Line(i.0, i.1), Line(i.0, i.1).plot());
println!("{:>14} : {}", Line(i.1, i.0), Line(i.1, i.0).plot());
}
println!();
let pl = Polyline(
Coordinates(vec!(a.0, a.1, b.0, b.1, c.0, c.1, d.0, d.1)));
println!("{:>14} : {}", pl, pl.plot());
println!();
let pg = Polygon(
Coordinates(vec!( Coordinate( 0, -10, 0.0)
, Coordinate( 10, 10, 0.0)
, Coordinate(-10, 10, 0.0) )));
println!("{:>14} : {}", pg, pg.plot());
let i = Vector(Fractional( 0,1), Fractional(-30,1), Fractional(0,1));
let j = Vector(Fractional( 30,1), Fractional( 30,1), Fractional(0,1));
let k = Vector(Fractional(-30,1), Fractional( 30,1), Fractional(0,1));
let rot :TMatrix<Fractional> = TMatrix::rotate_z(20);
let Vector(ix, iy, _) = i.transform(&rot);
let Vector(jx, jy, _) = j.transform(&rot);
let Vector(kx, ky, _) = k.transform(&rot);
fn to_i32(x :Fractional) -> i32 {
let Fractional(n, d) = x;
(n / d + if (n % d).abs() < (n / 2).abs() { 0 } else { 1 }) as i32
}
println!();
let pg = Polygon(
Coordinates(vec!( Coordinate(to_i32(ix) + 100, to_i32(iy) + 100, 0.0)
, Coordinate(to_i32(jx) + 100, to_i32(jy) + 100, 0.0)
, Coordinate(to_i32(kx) + 100, to_i32(ky) + 100, 0.0) )));
println!("{:>14} : {}", pg, pg.plot());
let i = Vector( 0.0, -30.0, 0.0);
let j = Vector( 30.0, 30.0, 0.0);
let k = Vector(-30.0, 30.0, 0.0);
let rot :TMatrix<f64> = TMatrix::rotate_z(20);
let Vector(ix, iy, _) = i.transform(&rot);
let Vector(jx, jy, _) = j.transform(&rot);
let Vector(kx, ky, _) = k.transform(&rot);
fn to_i32_2(x :f64) -> i32 {
x.round() as i32
}
println!();
let pg = Polygon(
Coordinates(vec!( Coordinate(to_i32_2(ix) + 100, to_i32_2(iy) + 100, 0.0)
, Coordinate(to_i32_2(jx) + 100, to_i32_2(jy) + 100, 0.0)
, Coordinate(to_i32_2(kx) + 100, to_i32_2(ky) + 100, 0.0) )));
println!("{:>14} : {}", pg, pg.plot());
}
fn _democanvas<T>( xcb :&XcbEasel
, title :&'static str
, tx :mpsc::Sender<i32>
, _triangle :Polyeder<T>
, tetrahedron :Polyeder<T>
, cube :Polyeder<T>
, light :DirectLight<T> )
where T: 'static + Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ Debug + Copy + Trig + Send + From<i32> + PartialOrd {
let mut canvas = xcb.canvas(151, 151).unwrap();
let camera = Camera::<T>::new(&canvas, 45); // the orig. view angle
// was 50.
canvas.set_title(title);
canvas.init_events();
canvas.start_events(tx.clone());
thread::spawn(move || {
let start = Instant::now();
let step = Duration::from_millis(25);
let mut last = Instant::now();
let t = TMatrix::translate(Vector(0.into() , 0.into() , 150.into()));
loop {
let deg = ((start.elapsed() / 25).as_millis() % 360) as i32;
let rz = TMatrix::rotate_z(deg);
let rx = TMatrix::rotate_x(-deg*2);
let ry = TMatrix::rotate_y(-deg*2);
let rot1 = TMatrix::combine(vec!(rz, rx, t));
let rot2 = TMatrix::combine(vec!(rz, ry, t));
let objects = vec!( (tetrahedron.transform(&rot1), 0xFFFF00)
, ( cube.transform(&rot2), 0x0000FF) );
//let objects = vec!( ( cube.transform(&rot2), 0x0000FF) );
//let objects = vec!( (tetrahedron.transform(&rot1), 0xFFFF00) );
//let objects = vec!( (triangle.transform(&rot1), 0xFFFF00) );
canvas.clear();
for (o, color) in objects {
for (pg, c) in o.project(&camera, &light, color) {
//canvas.draw(&pg, Coordinate(0, 0, 0.into()), c);
(&pg).fill(&mut canvas, c);
//(&pg).debug();
//println!("\n");
}
}
let passed = Instant::now() - last;
let f = (passed.as_nanos() / step.as_nanos()) as u32;
if f > 1 {
println!("{} !!! Detected frame drop", title);
}
last = last + step*(f + 1);
canvas.put_text( Coordinate(10, 15, 0.into())
, &format!( "sleep: {:?}"
, last - Instant::now() ));
canvas.show();
thread::sleep(last - Instant::now());
}
});
}
fn main() {
common_fractional();
println!();
continuous();
println!();
sqrt();
println!();
pi();
println!();
_sin();
println!();
_cos();
println!();
_tan();
println!();
_vector1();
println!();
_vector2();
println!();
_transform1();
println!();
_transform2();
println!();
_line();
let xcb = XcbEasel::new().unwrap();
let (tx, rx) = mpsc::channel();
_democanvas( &xcb, "Something...(f64)", tx.clone()
, Polyeder::triangle(60.0)
, Polyeder::tetrahedron(100.0)
, Polyeder::cube(56.25)
, DirectLight::new(Vector(0.0, 0.0, 1.0)) );
/*
_democanvas( &xcb, "Something...(Fractional)", tx.clone()
, Polyeder::triangle(Fractional(60,1))
, Polyeder::tetrahedron(Fractional(80,1))
, Polyeder::cube(Fractional(55,1))
, DirectLight::new(Vector( Fractional(0,1)
, Fractional(0,1)
, Fractional(1,1) )) );
*/
for x in rx {
match x {
1 => break,
_ => {},
}
}
}

280
fractional/src/trigonometry.rs

@ -1,280 +0,0 @@
//
// Some trigonometic functions with Fractions results.
// Currently only sin, cos and tan are implemented.
// As I was unable to find a really good integral approximation for them I
// implement them as a table which is predefined using the floating point
// function f64::sin and then transformed into a fraction of a given
// PRECISION.
// These approximations are quite good and for a few edge cases
// even better than the floating point implementations.
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
use std::cmp::Ordering;
use std::ops::Div;
use std::ops::Neg;
use std::marker::Sized;
use crate::{Fractional, Error};
use crate::continuous::Continuous;
pub trait Trig {
fn pi() -> Self;
fn recip(self) -> Self;
fn round(&self) -> i32;
fn sqrt(self) -> Result<Self, Error> where Self: Sized;
fn sintab() -> Vec<Self> where Self: Sized;
fn tantab() -> Vec<Self> where Self: Sized;
fn sin(d :i32) -> Self
where Self: Sized + Neg<Output = Self> + Copy {
match d {
0 ..=90 => Self::sintab()[d as usize],
91 ..=180 => Self::sintab()[180 - d as usize],
181..=270 => -Self::sintab()[d as usize - 180],
271..=359 => -Self::sintab()[360 - d as usize],
_ => {
Self::sin(if d < 0 { d % 360 + 360 } else { d % 360 })
},
}
}
fn cos(d :i32) -> Self
where Self: Sized + Neg<Output = Self> + Copy {
match d {
0 ..=90 => Self::sintab()[90 - d as usize],
91 ..=180 => -Self::sintab()[90 - (180 - d as usize)],
181..=270 => -Self::sintab()[90 - (d as usize - 180)],
271..=359 => Self::sintab()[90 - (360 - d as usize)],
_ => {
Self::cos(if d < 0 { d % 360 + 360 } else { d % 360 })
},
}
}
fn tan(d :i32) -> Self where Self: Sized + Copy {
match d {
0 ..=179 => Self::tantab()[d as usize],
180..=359 => Self::tantab()[d as usize - 180],
_ => {
Self::tan(if d < 0 { d % 360 + 360 } else { d % 360 })
},
}
}
fn cot(d :i32) -> Self
where Self: Sized + Copy + From<i32> + Div<Output = Self> {
Into::<Self>::into(1) / Self::tan(d)
}
}
// Try to keep precision as high as possible while having a denominator
// as small as possible. The values are taken by try and error.
const PRECISION :i64 = 1000000;
const MAX_DENOMINATOR :i64 = 7000;
// This is a really close fractional approximation for pi.
impl Trig for Fractional {
fn pi() -> Self {
Fractional(355, 113)
}
fn recip(self) -> Self {
let Fractional(n, d) = self;
Fractional(d, n)
}
fn round(&self) -> i32 {
let Fractional(n, d) = self;
(n / d) as i32
}
// This is a really bad approximation of sqrt for a fractional...
// for (9/3) it will result 3 which if way to far from the truth,
// which is ~1.7320508075
// BUT we can use this value as starting guess for creating a
// continous fraction for the sqrt... and create a much better
// fractional representation of the sqrt.
// So, if inner converges, but is not a perfect square (does not
// end up in an Ordering::Equal - which is the l > h case)
// we use the l - 1 as starting guess for sqrt_cfrac.
// taken from:
// https://www.geeksforgeeks.org/square-root-of-an-integer/
fn sqrt(self) -> Result<Self, Error> {
// find the sqrt of x in O(log x/2).
// This stops if a perfect sqare was found. Else it passes
// the found value as starting guess to the continous fraction
// sqrt function.
fn floor_sqrt(x :i64) -> Fractional {
fn inner(l :i64, h :i64, x :i64) -> Fractional {
if l > h {
(&Continuous::sqrt(x, l - 1)).into()
} else {
let m = (l + h) / 2;
match x.cmp(&(m * m)) {
Ordering::Equal => m.into(),
Ordering::Less => inner(l, m - 1, x),
Ordering::Greater => inner(m + 1, h, x),
}
}
}
match x {
0 => 0.into(),
1 => 1.into(),
_ => inner(1, x / 2, x),
}
}
let Fractional(n, d) = self;
let n = match n.cmp(&0) {
Ordering::Equal => 0.into(),
Ordering::Less => return Err("sqrt on negative undefined"),
Ordering::Greater => floor_sqrt(n),
};
let d = match d.cmp(&0) {
Ordering::Equal => 0.into(),
Ordering::Less => return Err("sqrt on negative undefined"),
Ordering::Greater => floor_sqrt(d),
};
Ok(n / d)
}
fn sintab() -> Vec<Self> {
// hold sin Fractionals from 0 to 89 ...
// luckily with a bit of index tweeking this can also be used for
// cosine values.
lazy_static::lazy_static! {
static ref SINTAB :Vec<Fractional> =
(0..=90).map(|x| _sin(x)).collect();
}
// fractional sin from f64 sin. (From 0° to 90°)
fn _sin(d: u32) -> Fractional {
match d {
0 => Fractional(0, 1),
90 => Fractional(1, 1),
_ => generate(d, PRECISION, &f64::sin),
}
}
SINTAB.to_vec()
}
fn tantab() -> Vec<Self> {
// This table exists only because the sin(α) / cos(α) method
// yields very large unreducable denominators in a lot of cases.
lazy_static::lazy_static! {
static ref TANTAB :Vec<Fractional> =
(0..180).map(|x| _tan(x)).collect();
}
// fractional tan from f64 tan. (From 0° to 179°)
fn _tan(d: u32) -> Fractional {
match d {
0 => Fractional(0, 1),
45 => Fractional(1, 1),
90 => Fractional(1, 0), // although they are both inf and -inf.
135 => -Fractional(1, 1),
_ => generate(d, PRECISION, &f64::tan),
}
}
TANTAB.to_vec()
}
}
// search for a fraction with a denominator less than MAX_DENOMINATOR that
// provides the minimal PRECISION criteria.
// !! With f = &f64::tan and d close to the inf boundarys of tan
// we get very large numerators because the numerator becomes a
// multiple of the denominator.
fn generate(d :u32, p :i64, f :&dyn Fn(f64) -> f64) -> Fractional {
// This is undefined behaviour for very large f64, but our f64
// is always between 0.0 and 1000000.0 which should be fine.
let s = (f((d as f64).to_radians()) * p as f64).round() as i64;
let Fractional(n, dn) = Fractional(s, p).reduce();
match dn.abs().cmp(&MAX_DENOMINATOR) {
Ordering::Less => Fractional(n, dn),
_ => generate(d, p + 1, f),
}
}
impl Trig for f64 {
fn pi() -> Self {
std::f64::consts::PI
}
fn recip(self) -> Self {
self.recip()
}
fn round(&self) -> i32 {
f64::round(*self) as i32
}
fn sqrt(self) -> Result<Self, Error> {
let x = self.sqrt();
match x.is_nan() {
true => Err("sqrt on negative undefined"),
false => Ok(x),
}
}
fn sintab() -> Vec<Self> {
lazy_static::lazy_static! {
static ref SINTAB :Vec<f64> =
(0..=90).map(|x| _sin(x)).collect();
}
// f64 sin. (From 0° to 90°)
fn _sin(d: u32) -> f64 {
match d {
0 => 0.0,
90 => 1.0,
_ => (d as f64).to_radians().sin(),
}
}
SINTAB.to_vec()
}
fn tantab() -> Vec<Self> {
// This table exists only because the sin(α) / cos(α) method
// yields very large unreducable denominators in a lot of cases.
lazy_static::lazy_static! {
static ref TANTAB :Vec<f64> =
(0..180).map(|x| _tan(x)).collect();
}
// fractional tan from f64 tan. (From 0° to 179°)
fn _tan(d: u32) -> f64 {
match d {
0 => 0.0,
45 => 1.0,
90 => std::f64::INFINITY,
135 => -1.0,
_ => (d as f64).to_radians().tan(),
}
}
TANTAB.to_vec()
}
}

272
fractional/src/xcb.rs

@ -1,272 +0,0 @@
//
// XCB implementation for drawing some stuff...
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
extern crate xcb;
use std::sync::Arc;
use std::ptr; //::{null, null_mut};
use std::thread;
use std::sync::mpsc;
use std::ops::{Add, Sub, Div};
use crate::easel::{Easel, Canvas, Drawable, Coordinate, Coordinates};
#[derive(Clone)]
pub struct XcbEasel (Arc<xcb::Connection>, i32);
pub struct XcbCanvas<'a, T> { conn :Arc<xcb::Connection>
, width :u16
, height :u16
, window :u32
, pixmap :u32
, gc :u32
, zbuf :Vec<T>
, shm :Box<&'a mut [u32]> }
impl XcbEasel {
pub fn new() -> Result<XcbEasel, xcb::ConnError> {
let (conn, num) = xcb::Connection::connect(None)?;
Ok(XcbEasel(Arc::new(conn), num))
}
pub fn setup(&self) -> xcb::Setup {
let XcbEasel(conn, _) = self;
conn.get_setup()
}
pub fn screen(&self) -> Option<xcb::Screen> {
let XcbEasel(_, num) = self;
self.setup().roots().nth(*num as usize)
}
pub fn canvas<'a, T>( &self
, width :u16
, height :u16) -> Option<XcbCanvas<'a, T>>
where T: Clone + From<i32> {
let Self(conn, _) = self;
let conn = conn.clone();
let screen = match self.screen() {
None => return None,
Some(screen) => screen,
};
println!("root depth: {}", screen.root_depth());
let shmseg = conn.generate_id();
let gc = conn.generate_id();
let pixmap = conn.generate_id();
let window = conn.generate_id();
xcb::create_window( &conn, xcb::COPY_FROM_PARENT as u8, window
, screen.root(), 0, 0, width, width, 0
, xcb::WINDOW_CLASS_INPUT_OUTPUT as u16
, screen.root_visual()
, &[(xcb::CW_BACK_PIXEL, screen.black_pixel())] );
xcb::create_gc( &conn, gc, screen.root()
, &[ (xcb::GC_FOREGROUND, screen.white_pixel())
, (xcb::GC_GRAPHICS_EXPOSURES, 0) ] );
let zbuf :Vec<T> = vec!(0.into(); (width * height) as usize);
let (shmid, shm) = getshm((width * height) as usize);
xcb::shm::attach(&conn, shmseg, shmid as u32, false);
unsafe { libc::shmctl(shmid, libc::IPC_RMID, ptr::null_mut()); }
xcb::shm::create_pixmap( &conn, pixmap, window, width, height
, screen.root_depth(), shmseg, 0 );
xcb::map_window(&conn, window);
conn.flush();
Some(XcbCanvas{ conn: conn
, width: width
, height: height
, window: window
, pixmap: pixmap
, gc: gc
, zbuf: zbuf
, shm: Box::new(shm) } )
}
}
impl<'a, T> XcbCanvas<'a, T> {
pub fn set_title(&self, title :&str) {
let c = xcb::change_property_checked( &self.conn
, xcb::PROP_MODE_REPLACE as u8
, self.window
, xcb::ATOM_WM_NAME
, xcb::ATOM_STRING
, 8
, title.as_bytes() );
if self.conn.has_error().is_err() || c.request_check().is_err() {
println!("Error setting title");
}
}
}
fn getshm<'a>(size :usize) -> (i32, &'a mut [u32]) {
use std::slice::from_raw_parts_mut;
unsafe {
let id = libc::shmget( libc::IPC_PRIVATE
, size * 4
, libc::IPC_CREAT | 0o744 );
let ptr = libc::shmat(id, ptr::null(), 0);
(id as i32, from_raw_parts_mut(ptr as *mut u32, size))
}
}
impl Easel for XcbEasel {}
impl<'a, T> Canvas<T> for XcbCanvas<'a, T>
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
+ Copy + From<i32> + PartialOrd {
fn init_events(&self) {
let mask = [( xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE
| xcb::EVENT_MASK_KEY_PRESS
| xcb::EVENT_MASK_STRUCTURE_NOTIFY
| xcb::EVENT_MASK_PROPERTY_CHANGE )];
xcb::change_window_attributes(&self.conn, self.window, &mask);
self.conn.flush();
}
fn start_events(&self, tx :mpsc::Sender<i32>) {
let conn = self.conn.clone();
let window = self.window;
let pixmap = self.pixmap;
let gc = self.gc;
let width = self.width;
let height = self.height;
thread::spawn(move || {
loop {
let event = conn.wait_for_event();
match event {
None => break,
Some(event) => {
match event.response_type() & !0x80 {
xcb::PROPERTY_NOTIFY => {
let prop_notify :&xcb::PropertyNotifyEvent
= unsafe { xcb::cast_event(&event) };
if prop_notify.atom() == xcb::ATOM_WM_NAME {
// retrieving title
let cookie
= xcb::get_property( &conn
, false
, window
, xcb::ATOM_WM_NAME
, xcb::ATOM_STRING
, 0, 1024 );
if let Ok(reply) = cookie.get_reply() {
let r = reply.value();
let r = std::str::from_utf8(r).unwrap();
println!("title changed to: {}", r);
}
}
},
xcb::EXPOSE => {
xcb::copy_area( &conn, pixmap, window, gc
, 0, 0, 0, 0
, width, height );
conn.flush();
},
xcb::KEY_PRESS => {
let key_press: &xcb::KeyPressEvent
= unsafe { xcb::cast_event(&event) };
println!( "Key '{}' pressed"
, key_press.detail() );
// Q (on qwerty)
if key_press.detail() == 0x18 {
tx.send(1).unwrap();
break;
}
},
_ => {},
}
},
}
}
});
}
fn width(&self) -> u16 {
self.width
}
fn height(&self) -> u16 {
self.height
}
fn clear(&mut self) {
self.zbuf = vec!(0.into(); self.zbuf.len());
unsafe {
let ptr = self.shm.as_mut_ptr();
ptr::write_bytes( ptr, 0
, self.width as usize * self.height as usize);
}
}
fn draw(&mut self, d :&dyn Drawable<T>, ofs :Coordinate<T>, color: u32) {
let Coordinates(c) = d.plot();
let Coordinate(xofs, yofs, _) = ofs;
for Coordinate(x, y, zr) in c {
let idx :usize = ((y+yofs)*(self.width as i32)+x+xofs) as usize;
if self.zbuf[idx] < zr {
self.zbuf[idx] = zr;
self.shm[idx] = color;
}
}
}
fn put_text(&self, ofs :Coordinate<T>, s :&str) {
let Coordinate(xofs, yofs, _) = ofs;
xcb::xproto::image_text_8( &self.conn, self.pixmap, self.gc
, xofs as i16, yofs as i16, s );
self.conn.flush();
}
fn set_pixel(&mut self, c :Coordinate<T>, color :u32) {
let Coordinate(x, y, zr) = c;
let idx :usize = (y * (self.width as i32) + x) as usize;
if self.zbuf[idx] < zr {
self.zbuf[idx] = zr;
self.shm[idx] = color;
}
}
fn show(&self) {
xcb::copy_area( &self.conn, self.pixmap, self.window, self.gc
, 0, 0, 0, 0
, self.width, self.height );
self.conn.flush();
}
}

6
functions/Cargo.lock

@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "functions"
version = "0.1.0"

9
functions/Cargo.toml

@ -1,9 +0,0 @@
[package]
name = "functions"
version = "0.1.0"
authors = ["Georg Hopp <georg@steffers.org>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

12
functions/src/main.rs

@ -1,12 +0,0 @@
fn main() {
another_function(5, add_five(6));
}
fn another_function(x: i32, y: i32) {
println!("The value of x id: {}", x);
println!("The value of y id: {}", y);
}
fn add_five(x: i32) -> i32 {
x + 5
}

91
guessing_game/Cargo.lock

@ -1,91 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "guessing_game"
version = "0.1.0"
dependencies = [
"rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
version = "0.2.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rand"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8"
"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

8
guessing_game/Cargo.toml

@ -1,8 +0,0 @@
[package]
name = "guessing_game"
version = "0.1.0"
authors = ["Georg Hopp <georg@steffers.org>"]
edition = "2018"
[dependencies]
rand = "0.3.14"

36
guessing_game/src/main.rs

@ -1,36 +0,0 @@
use std::io;
use std::cmp::Ordering;
use rand::Rng;
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng()
.gen_range(1, 101);
loop {
println!("Please input your guess.");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed to read line");
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
println!("You guessed: {}", guess);
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
}
}
}

6
hello/Cargo.lock

@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "hello"
version = "0.1.0"

7
hello/Cargo.toml

@ -1,7 +0,0 @@
[package]
name = "hello"
version = "0.1.0"
authors = ["Georg Hopp <georg@steffers.org>"]
edition = "2018"
[dependencies]

3
hello/src/main.rs

@ -1,3 +0,0 @@
fn main() {
println!("Hello, world!");
}

83
interesting.md

@ -1,83 +0,0 @@
# Here I collect some interesting links.
## cargo environment
Currently I always build all dependencies within th projects own .cargo subdir
by setting the environment variable CARGO_HOME.
export CARGO_HOME=./.cargo
Actually I am quite unsure if that is really a good idea because this results
in a lot of rebuilds for each new project.
## Implement Monads with rust.
Which is currently difficult through impossible, but might be feasible with
some small additions to the rust type system, namely
«(generic) associated traits.»
[Read here](https://varkor.github.io/blog/2019/03/28/idiomatic-monads-in-rust.html)
### Is impl Trait what we needed?
A new language feature which sounded a bit like the needed one for above is:
[impl Trait](https://medium.com/@iopguy/impl-trait-in-rust-explanation-efde0d94946a)
Crossreading it a bit seems to indicate that this is not like the above needed
language feature.
## WASM ... on gentoo ...
Right now rust is not really a first class citizen within the gentoo eco
system. For that reason at least when compiling rust with the `system-llvm`
use flag some manual preparations are needed.
### general informations about Wasm from MDN ...
[WebAssembly](https://developer.mozilla.org/en-US/docs/WebAssembly)
### rustwasm tutorial
[rustwasm](https://rustwasm.github.io/book/introduction.html)
### location of rustlib ...
`wasm-pack` expects the wasm runtime under /usr/lib/rustlib/ but a gentoo
installation puts it under /usr/lib/rust-1.39.0/rustlib/. To come around this
issue I just created a symlink.
Maybe it would be best to send a patch for also settings this symlink to
upstream eselect-rust.
### Missing lld
Again `wasm-pack` searches for llvm-lld or rust-lld for the link phase. This
is currently not a dependency for llvm with WASM support, so I installed it
manually. Finally you have to tell rustc to use lld as linker via this
environment variable:
export RUSTFLAGS="-C linker=lld"
## Traits when, how & why
A slightly old but still worthwhile post about rusts standard traits.
[About traits](https://llogiq.github.io/2015/07/30/traits.html)
# Side note... 3d math
[3d math primer](https://www.3dgep.com/3d-math-primer-for-game-programmers-vector-operations/)
[basic 3d math](https://matrix44.net/cms/notes/opengl-3d-graphics/basic-3d-math-vectors/)
[vector calculator](https://www.mathportal.org/calculators/matrices-calculators/vector-calculator.php)
[3d vector mathematics](https://vvvv.org/documentation/3d-vector-mathematics)
[sin appr. with fractions](https://dsp.stackexchange.com/questions/46629/finding-polynomial-approximations-of-a-sine-wave)
# transformations within a coordinate system.
[migenius](https://www.migenius.com/articles/3d-transformations-part1-matrices)
[tutorialspoint](https://www.tutorialspoint.com/computer_graphics/3d_transformation.htm)
# more math...
A whole lot of interesting stuff about continued fractions:
[continues fractions](http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/cfINTRO.html)

6
loops/Cargo.lock

@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "loops"
version = "0.1.0"

9
loops/Cargo.toml

@ -1,9 +0,0 @@
[package]
name = "loops"
version = "0.1.0"
authors = ["Georg Hopp <georg@steffers.org>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

64
loops/src/main.rs

@ -1,64 +0,0 @@
//
// Loops examples.
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
fn main() {
// It seams that to use loops this way you absolutely need a mutable.
// If I build it with a normal type and try to shadow it within the loop
// the outer variable is always used as input for the shadow, thus it is
// always the same.... that really sucks.
let mut counter = 0;
let result = loop {
counter = counter + 1;
if counter == 10 {
break counter * 2;
}
};
println!("The result is {}", result);
// The same is true with «while» ... which again sucks.
let mut number = 3;
while number != 0 {
println!("{}!", number);
number = number - 1;
}
println!("LIFTOFF!!!");
// apart from beeing frustrated about the above facts... lets continue.
let a = [10, 20, 30, 40, 50];
let mut index = 0;
while index < 5 {
println!("the value is: {}", a[index]);
index = index + 1;
}
for element in a.iter() {
println!("the value is still: {}", element);
}
for number in (1..4).rev() {
println!("for {}!", number);
}
}

6
ownership/Cargo.lock

@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "ownership"
version = "0.1.0"

9
ownership/Cargo.toml

@ -1,9 +0,0 @@
[package]
name = "ownership"
version = "0.1.0"
authors = ["Georg Hopp <georg@steffers.org>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

183
ownership/src/main.rs

@ -1,183 +0,0 @@
//
// Examples related to ownership, also introducing String.
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
fn main() {
concat();
move_variable();
clone_variable();
let s = String::from("hello"); // s comes into scope
take_ownership(s); // s's value moves into the function
// … and so is no longer valid here.
let x = 5; // x comes into scope
makes_copy(x); // the scalar value has the Copy trait and
// lives on the stack and thus is still
// valid here.
let _s1 = gives_ownership(); // move the return value into _s1
let s2 = String::from("hello"); // s2 comes into scope
let _s3 = takes_and_gives(s2); // s2 is moved into function, which in
// turn moves the return value into _s3.
let s1 = String::from("hello"); // s1 comes into scope.
let len = calculate_length(&s1); // A reference to s1 is given to a
// calculate_length which effectively is
// not s1 itself but another pointer to
// s1… which is the reason that we still
// can use it below.
let _another_s = &s1; // again only a reference which does not
// take ownership, thus s1 can still be
// used below.
println!("The length of '{}' is {}.", s1, len);
// Passing values as reference to a function is called borrowing. A
// borrowed value can't be changed.
change(&s1);
// but we can force this… which is probably not the best of ideas most
// of the time…
let mut s_mut = String::from("hello");
change_mutable(&mut s_mut);
// but you can have only one mutable reference of a value in a single
// scope. The following would fail with:
// cannot borrow `s_mut` as mutable more than once at a time second
// mutable borrow occurs here
// let r1 = &mut s_mut;
// let r2 = &mut s_mut;
// println!("{}, {}", r1, r2);
// We also can't have an immutable reference while we have a mutable one.
// Look on Page 98 for an explanation.
// The scope of references is not the whole block they are introduced in
// but goes only until their last usage. Thus if you first have an
// immutable reference but never use it after a mutable reference is
// declared, that would be ok… At all this is kind of confusing and very
// Mozzilaish. :D
// Now we demonstrate string slices…
let s4 = String::from("hello world");
let s_slice = first_word(&s4);
// working with an mutable reference like with s4.clear() will not
// compile at this point because we already have and use later on an
// immutable reference.
println!("The slice was: {}", s_slice);
// not that string literals are slices. They are immutable references of
// the programs TEXT segment. Thats the reason why they are immutable.
// Thus try generic_first_word…
println!("First word on literal: {}", generic_first_word("hello world"));
println!("First word on String: {}", generic_first_word(&s4[..]));
} // x and s go out of scope but nothing happens for s because this function
// has no longer the ownership of s.
// s3 goes out of scope and is dropped. s2 was moved and s1 is dropped.
fn concat() {
let mut s = String::from("hello");
s.push_str(", world!");
println!("{}", s);
}
fn move_variable() {
let s1 = String::from("hello");
let s2 = s1; // does not copy data but only the String structure.
// when using s1 below we get an error that a moved value was borrowed.
println!("{}, world!", s2);
}
fn clone_variable() {
let s1 = String::from("hello");
let s2 = s1.clone();
// this time both are valid.
println!("s1 = {}, s2 = {}", s1, s2)
}
fn take_ownership(some_string: String) { // some_string comes into scope
println!("{}", some_string);
} // some_string goes out of scope and «drop» is called, thus memory freed.
fn makes_copy(some_integer: i32) { // some integer comes into scope
println!("{}", some_integer);
} // Here, some_integer goes out of scope but because it was a copy and on the
// stack nothing special happens… beside that stack space is freed.
fn gives_ownership() -> String { // this will move the return value into the
// calling function.
let some_string = String::from("hello"); // some_string comes into scope
some_string
}
fn takes_and_gives(a_string: String) -> String { // a_string comes into scope
a_string // and is returned and moved
// to the calling function.
} // a_string goes out of scope but nothing happens as it is moved.
fn calculate_length(s: &String) -> usize { // s comes into scope. It is a
// reference. References do not
// take ownership of the underlying
// value which is the String in
// main.
s.len()
} // Here s goes out of scope but because it has no ownership of the String
// nothing happens.
fn change(_some_string: &String) {
// the following would give this error:
// `_some_string` is a `&` reference, so the data it refers to cannot be
// borrowed as mutable
// _some_string.push_str(", world!");
}
fn change_mutable(some_string: &mut String) {
some_string.push_str(", world");
}
fn first_word(s: &String) -> &str {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[..i];
}
}
&s[..]
}
// To make first_word work on either string literals (which are in fact string
// slices, s.o.) one would write first_word like this…
fn generic_first_word(s: &str) -> &str {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[..i];
}
}
&s[..]
}

9
rectangles/Cargo.toml

@ -1,9 +0,0 @@
[package]
name = "rectangles"
version = "0.1.0"
authors = ["Georg Hopp <georg@steffers.org>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

90
rectangles/src/main.rs

@ -1,90 +0,0 @@
//
// Examples related to structs…
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
fn can_hold(&self, inner: &Rectangle) -> bool {
self.width >= inner.width && self.height >= inner.height
}
fn square(size: u32) -> Rectangle {
Rectangle { width: size, height: size }
}
}
fn main() {
let width1 = 30;
let height1 = 50;
println!(
"The area of the rectangle ist {} square pixels.",
area(width1, height1));
let rect1 = (30, 50);
println!(
"The area of the rectangle ist {} square pixels.",
_area(rect1));
let rect1 = Rectangle { width: 30, height: 50 };
println!(
"The area of the rectangle ist {} square pixels.",
__area(&rect1));
println!("_rect1 is {:?}", rect1);
println!(
"The area of the rectangle ist {} square pixels.",
rect1.area());
let rect2 = Rectangle { width: 10, height: 40};
let rect3 = Rectangle { width: 60, height: 45};
println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2));
println!("Can rect1 hold rect3? {}", rect1.can_hold(&rect3));
let square1 = Rectangle::square(32);
println!("Got the square rectange: {:?}", square1);
}
fn area(width: u32, height: u32) -> u32 {
width * height
}
fn _area(dimensions: (u32, u32)) -> u32 {
let (width, height) = dimensions;
width * height
}
fn __area(rectangle: &Rectangle) -> u32 {
rectangle.width * rectangle.height
}

9
recursion/Cargo.toml

@ -1,9 +0,0 @@
[package]
name = "recursion"
version = "0.1.0"
authors = ["Georg Hopp <georg@steffers.org>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

51
recursion/src/main.rs

@ -1,51 +0,0 @@
//
// Try some recursion with pattern matching... especially in
// conjunction with match to get a similar behavious as in e.g.
// haskell...
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Borrowing rules do not apply here because everything lives on the stack.
fn faculty(x: u32) -> u32 {
match x {
0 => 1,
_ => x * faculty(x - 1),
}
}
// for a tail recursive version we need to pass the currently calculated
// faculty to an inner tail recursive function.
// This will probably be optimized better, because the compiler would be
// able to unroll the complete recursion.
fn tail_faculty(x: u32) -> u32 {
fn faculty(x: u32, f: u32) -> u32 {
match x {
0 => f,
_ => faculty(x - 1, x * f),
}
};
faculty(x, 1)
}
fn main() {
for i in 0..10 {
println!("Fakultät {} = {}", i, faculty(i));
println!("tail recursive Fakultät {} = {}", i, tail_faculty(i));
}
}

9
restaurant/Cargo.toml

@ -1,9 +0,0 @@
[package]
name = "restaurant"
version = "0.1.0"
authors = ["Georg Hopp <georg@steffers.org>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

27
restaurant/src/front_of_house.rs

@ -1,27 +0,0 @@
//
// Move some restaurant stuff in a different file....
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
pub mod hosting;
mod serving {
fn take_order() {}
fn take_payment() {}
}

23
restaurant/src/front_of_house/hosting.rs

@ -1,23 +0,0 @@
//
// Now also sepatate hosting....
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
pub fn add_to_waitlist() {}
fn seat_at_table() {}

93
restaurant/src/lib.rs

@ -1,93 +0,0 @@
//
// Restaurant lib for demontrating rust modules.
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
mod front_of_house;
fn serve_order() {}
mod back_of_house {
pub struct Breakfast {
pub toast: String,
seasonal_fruit: String,
}
impl Breakfast {
pub fn summer(toast: &str) -> Breakfast {
Breakfast {
toast: String::from(toast),
seasonal_fruit: String::from("peaches"),
}
}
}
pub enum Appetizer {
Soup,
Salad,
}
fn fix_incorrect_order() {
cook_order();
super::serve_order();
}
fn cook_order() {}
}
// Either absolute:
// use crate::front_of_house::hosting;
// or relaive:
use front_of_house::hosting;
// we can also provide new names...
use crate::front_of_house::hosting as host;
// Public definitions braught into scope with use are
// private in this scope except we use «pub use»
pub use front_of_house::hosting as pubhost;
pub fn eat_at_restaurant() {
// Absolute path
crate::front_of_house::hosting::add_to_waitlist();
// Relative path
front_of_house::hosting::add_to_waitlist();
// With use'd path
hosting::add_to_waitlist();
// With renamed used path
host::add_to_waitlist();
pubhost::add_to_waitlist();
// Order a breakfast in the summer with Rye toast
let mut meal = back_of_house::Breakfast::summer("Rye");
// Change our mind about what bread we'd like
meal.toast = String::from("Wheat");
println!("I'd like {} toast please", meal.toast);
// The next line won't compile if we uncomment it; we're not allowed
// to see or modify the seasonal fruit that comes with the meal
// meal.seasonal_fruit = String::from("blueberries");
let order1 = back_of_house::Appetizer::Soup;
let order2 = back_of_house::Appetizer::Salad;
}

0
fractional/src/easel.rs → src/easel.rs

0
tutorial/wasm-game-of-life/src/geometry.rs → src/geometry.rs

0
tutorial/wasm-game-of-life/src/lib.rs → src/lib.rs

0
fractional/src/transform.rs → src/transform.rs

0
tutorial/wasm-game-of-life/src/trigonometry.rs → src/trigonometry.rs

0
tutorial/wasm-game-of-life/src/utils.rs → src/utils.rs

0
fractional/src/vector.rs → src/vector.rs

0
tutorial/wasm-game-of-life/tests/web.rs → tests/web.rs

7
tutorial/wasm-game-of-life/.gitignore

@ -1,7 +0,0 @@
/target
**/*.rs.bk
Cargo.lock
bin/
pkg/
wasm-pack/
wasm-pack.log

69
tutorial/wasm-game-of-life/README.md

@ -1,69 +0,0 @@
<div align="center">
<h1><code>wasm-pack-template</code></h1>
<strong>A template for kick starting a Rust and WebAssembly project using <a href="https://github.com/rustwasm/wasm-pack">wasm-pack</a>.</strong>
<p>
<a href="https://travis-ci.org/rustwasm/wasm-pack-template"><img src="https://img.shields.io/travis/rustwasm/wasm-pack-template.svg?style=flat-square" alt="Build Status" /></a>
</p>
<h3>
<a href="https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html">Tutorial</a>
<span> | </span>
<a href="https://discordapp.com/channels/442252698964721669/443151097398296587">Chat</a>
</h3>
<sub>Built with 🦀🕸 by <a href="https://rustwasm.github.io/">The Rust and WebAssembly Working Group</a></sub>
</div>
## About
[**📚 Read this template tutorial! 📚**][template-docs]
This template is designed for compiling Rust libraries into WebAssembly and
publishing the resulting package to NPM.
Be sure to check out [other `wasm-pack` tutorials online][tutorials] for other
templates and usages of `wasm-pack`.
[tutorials]: https://rustwasm.github.io/docs/wasm-pack/tutorials/index.html
[template-docs]: https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html
## 🚴 Usage
### 🐑 Use `cargo generate` to Clone this Template
[Learn more about `cargo generate` here.](https://github.com/ashleygwilliams/cargo-generate)
```
cargo generate --git https://github.com/rustwasm/wasm-pack-template.git --name my-project
cd my-project
```
### 🛠️ Build with `wasm-pack build`
```
wasm-pack build
```
### 🔬 Test in Headless Browsers with `wasm-pack test`
```
wasm-pack test --headless --firefox
```
### 🎁 Publish to NPM with `wasm-pack publish`
```
wasm-pack publish
```
## 🔋 Batteries Included
* [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) for communicating
between WebAssembly and JavaScript.
* [`console_error_panic_hook`](https://github.com/rustwasm/console_error_panic_hook)
for logging panic messages to the developer console.
* [`wee_alloc`](https://github.com/rustwasm/wee_alloc), an allocator optimized
for small code size.

3
tutorial/wasm-game-of-life/package-lock.json

@ -1,3 +0,0 @@
{
"lockfileVersion": 1
}

520
tutorial/wasm-game-of-life/src/easel.rs

@ -1,520 +0,0 @@
//
// This is an abstraction over a drawing environment.
// Future note: z-Buffer is described here:
// https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/perspective-correct-interpolation-vertex-attributes
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
use std::cmp;
use std::fmt::{Formatter, Debug, Display, Result};
use std::ops::{Add, Sub, Div};
use std::sync::mpsc;
pub trait Easel {
//fn canvas(&mut self, width :u16, height :u16) -> Option<&dyn Canvas>;
}
pub trait Canvas<T> {
fn init_events(&self);
fn start_events(&self, tx :mpsc::Sender<i32>);
fn width(&self) -> u16;
fn height(&self) -> u16;
fn clear(&mut self);
fn draw(&mut self, c :&dyn Drawable<T>, ofs :Coordinate<T>, color :u32);
fn put_text(&self, ofs :Coordinate<T>, s :&str);
fn set_pixel(&mut self, c :Coordinate<T>, color :u32);
fn show(&self);
}
pub trait Drawable<T> {
fn plot(&self) -> Coordinates<T>;
}
pub trait Fillable<T>
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
+ Debug + Copy + From<i32> {
fn fill(&self, canvas :&mut dyn Canvas<T>, color :u32);
}
#[derive(Debug, Clone, Copy)]
pub struct Coordinate<T>(pub i32, pub i32, pub T);
#[derive(Debug, Clone)]
pub struct Coordinates<T>(pub Vec<Coordinate<T>>);
#[derive(Debug, Clone, Copy)]
pub struct LineIterator<T> where T: Debug {
a :Option<Coordinate<T>>
, b :Coordinate<T>
, dx :i32
, dy :i32
, dz :T
, sx :i32
, sy :i32
, err :i32
, only_edges :bool
}
impl<T> Iterator for LineIterator<T>
where T: Add<Output = T> + Debug + Copy + From<i32> {
type Item = Coordinate<T>;
fn next(&mut self) -> Option<Self::Item> {
match self.a {
None => None,
Some(a) => {
let Coordinate(ax, ay, az) = a;
let Coordinate(bx, by, _) = self.b;
if ax != bx || ay != by {
match (2 * self.err >= self.dy, 2 * self.err <= self.dx ) {
(true, false) => {
let r = self.a;
self.a = Some(Coordinate( ax + self.sx
, ay
, az + self.dz ));
self.err = self.err + self.dy;
if self.only_edges { self.next() } else { r }
},
(false, true) => {
let r = self.a;
self.a = Some(Coordinate( ax
, ay + self.sy
, az + self.dz ));
self.err = self.err + self.dx;
r
},
_ => {
let r = self.a;
self.a = Some(Coordinate( ax + self.sx
, ay + self.sy
, az + self.dz ));
self.err = self.err + self.dx + self.dy;
r
},
}
} else {
self.a = None;
Some(self.b)
}
}
}
}
}
impl<T> Coordinate<T>
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
+ Debug + Clone + Copy + From<i32> {
fn iter(self, b :&Self, only_edges :bool) -> LineIterator<T> {
let Coordinate(ax, ay, az) = self;
let Coordinate(bx, by, bz) = *b;
let dx = (bx - ax).abs();
let dy = -(by - ay).abs();
LineIterator { a: Some(self)
, b: *b
, dx: dx
, dy: dy
, dz: (bz - az) / cmp::max(dx, -dy).into()
, sx: if ax < bx { 1 } else { -1 }
, sy: if ay < by { 1 } else { -1 }
, err: dx + dy
, only_edges: only_edges
}
}
fn line_iter(self, b :&Self) -> LineIterator<T> {
self.iter(b, false)
}
fn line(self, b :&Self) -> Vec<Self> {
self.line_iter(b).collect()
}
fn edge_iter(self, b :&Self) -> LineIterator<T> {
self.iter(b, true)
}
fn edge(self, b :&Self) -> Vec<Self> {
self.edge_iter(b).collect()
}
fn face(edges :&[Self]) -> Vec<Self> {
edges.to_vec()
}
}
impl<T> Display for Coordinate<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
write!(f, "<{},{}>", self.0, self.1)
}
}
impl<T> Display for Coordinates<T> where T: Copy {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let Coordinates(is) = self;
let c = match is[..] {
[] => String::from(""),
[a] => format!("{}", a),
_ => {
let mut a = format!("{}", is[0]);
for i in is[1..].iter() {
a = a + &format!(",{}", i);
}
a
}
};
write!(f, "Coordinates[{}]", c)
}
}
#[derive(Debug, Clone, Copy)]
pub struct Point<T>(pub Coordinate<T>);
impl<T> Drawable<T> for Point<T> where T: Copy {
fn plot(&self) -> Coordinates<T> {
let Point(c) = *self;
Coordinates(vec!(c))
}
}
impl<T> Display for Point<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let Point(p) = self;
write!(f, "Point[{}]", p)
}
}
#[derive(Debug, Clone, Copy)]
pub struct Line<T>(pub Coordinate<T>, pub Coordinate<T>);
impl<T> Drawable<T> for Line<T>
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
+ Debug + Clone + Copy + From<i32> {
fn plot(&self) -> Coordinates<T> {
let Line(a, b) = *self;
Coordinates(a.line(&b))
}
}
impl<T> Display for Line<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let Line(a, b) = self;
write!(f, "Line[{},{}]", a, b)
}
}
#[derive(Debug, Clone)]
pub struct Polyline<T>(pub Coordinates<T>);
impl<T> Drawable<T> for Polyline<T>
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
+ Debug + Clone + Copy + From<i32> {
fn plot(&self) -> Coordinates<T> {
let Polyline(Coordinates(cs)) = self;
match cs[..] {
[] => Coordinates(Vec::<Coordinate<T>>::new()),
[a] => Coordinates(vec!(a)),
[a, b] => Coordinates(a.line(&b)),
_ => {
let (a, b) = (cs[0], cs[1]);
let mut r = a.line(&b);
let mut i = b;
for j in cs[2..].iter() {
r.append(&mut i.line(j)[1..].to_vec());
i = *j;
}
Coordinates(r)
},
}
}
}
impl<T> Display for Polyline<T> where T: Copy {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let Polyline(a) = self;
write!(f, "PLine[{}]", a)
}
}
#[derive(Debug, Clone, Copy)]
enum Direction { Left, Right }
#[derive(Debug, Clone)]
pub struct Polygon<T>(pub Coordinates<T>);
#[derive(Debug, Clone)]
enum VertexIteratorMode { Vertex, Edge }
#[derive(Debug, Clone)]
pub struct VertexIterator<'a,T> where T: Debug {
p :&'a Polygon<T>,
top :usize,
current :Option<usize>,
edge :Option<LineIterator<T>>,
mode :VertexIteratorMode,
direction :Direction,
}
impl<'a,T> VertexIterator<'a,T>
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
+ Debug + Copy + From<i32> {
fn edge(p :&'a Polygon<T>, direction :Direction) -> Self {
let top = p.vert_min(direction);
let next = p.next_y(top, direction);
let edge = match next {
None => None,
Some(next) => Some(p.vertex(top).edge_iter(&p.vertex(next))),
};
VertexIterator { p: p
, top: top
, current: next
, edge: edge
, mode: VertexIteratorMode::Edge
, direction: direction }
}
fn vertex(p :&'a Polygon<T>, direction :Direction) -> Self {
let top = p.vert_min(direction);
let next = p.next_y(top, direction);
VertexIterator { p: p
, top: top
, current: next
, edge: None
, mode: VertexIteratorMode::Vertex
, direction: direction }
}
// if this yields "None" we are finished.
fn next_edge(&mut self) -> Option<LineIterator<T>> {
let current = self.current?;
let next = self.p.next_y(current, self.direction)?;
let mut edge = self.p.vertex(current).edge_iter(&self.p.vertex(next));
match edge.next() {
// It should be impossible that a new edge iterator has no values
// at all… anyway, just in case I handle it here.
None => self.next_edge(),
Some(_) => {
self.current = Some(next);
self.edge = Some(edge);
self.edge
},
}
}
}
impl<'a,T> Iterator for VertexIterator<'a,T>
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
+ Debug + Copy + From<i32> {
type Item = Coordinate<T>;
fn next(&mut self) -> Option<Self::Item> {
match self.mode {
VertexIteratorMode::Edge => {
// if for whatever reason edge is "None" finish this iterator.
let next = self.edge.as_mut()?.next();
match next {
Some(_) => next,
None => {
self.next_edge()?;
self.next()
},
}
},
VertexIteratorMode::Vertex => {
let current = self.current?;
self.current = self.p.next_y(current, self.direction);
Some(self.p.vertex(current))
},
}
}
}
impl<T> Polygon<T>
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
+ Copy + Debug + From<i32> {
#[inline]
fn vertex(&self, v :usize) -> Coordinate<T> {
let Polygon(Coordinates(cs)) = self;
cs[v]
}
fn vert_min<'a>(&'a self, d :Direction) -> usize {
let Polygon(Coordinates(cs)) = self;
type ICoord<'a,T> = (usize, &'a Coordinate<T>);
// TODO I guess the problem here is that it does not account for the
// same y vertex on the beggining and the end. So i guess correct
// would be finding the first one and then dependings on the
// given direction either search left or right for same y's.
let fold = |acc :Option<ICoord<'a,T>>, x :ICoord<'a,T>|
match acc {
None => Some(x),
Some(a) => {
let Coordinate(_, ay, _) = a.1;
let Coordinate(_, xy, _) = x.1;
if xy < ay {Some(x)} else {Some(a)}
},
};
let mut min = cs.iter().enumerate().fold(None, fold).unwrap().0;
let mut next = self.step(min, d);
while self.vertex(min).1 == self.vertex(next).1 {
min = next;
next = self.step(min, d);
}
min
}
fn left_edge(&self) -> VertexIterator<T> {
VertexIterator::edge(self, Direction::Left)
}
fn right_edge(&self) -> VertexIterator<T> {
VertexIterator::edge(self, Direction::Right)
}
fn left_vertices(&self) -> VertexIterator<T> {
VertexIterator::vertex(self, Direction::Left)
}
fn right_vertices(&self) -> VertexIterator<T> {
VertexIterator::vertex(self, Direction::Right)
}
fn left(&self, v :usize) -> usize {
let Polygon(Coordinates(cs)) = self;
match v {
0 => cs.len() - 1,
_ => v - 1,
}
}
fn right(&self, v :usize) -> usize {
let Polygon(Coordinates(cs)) = self;
(v + 1) % cs.len()
}
fn step(&self, v :usize, d :Direction) -> usize {
match d {
Direction::Left => self.left(v),
Direction::Right => self.right(v),
}
}
fn next_y(&self, c :usize, d :Direction) -> Option<usize> {
fn inner<T>( p :&Polygon<T>
, c :usize
, n :usize
, d :Direction) -> Option<usize>
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
+ Copy + Debug + From<i32> {
if c == n {
None
} else {
let Coordinate(_, cy, _) = p.vertex(c);
let Coordinate(_, ny, _) = p.vertex(n);
if ny < cy { None } else { Some(n) }
}
}
inner(self, c, self.step(c, d), d)
}
pub fn debug(&self) {
let mut left = self.left_vertices();
let mut right = self.right_vertices();
if left.find(|l| right.find(|r| l.0 == r.0).is_some()).is_some() {
let left :Vec<Coordinate<T>> = self.left_vertices().collect();
let right :Vec<Coordinate<T>> = self.right_vertices().collect();
println!("===");
println!("== poly : {:?}", self);
println!("== ltop : {:?}", self.vert_min(Direction::Left));
println!("== rtop : {:?}", self.vert_min(Direction::Right));
println!("== left : {:?}", left);
println!("== right : {:?}", right);
println!("===");
}
}
}
impl<T> Drawable<T> for Polygon<T>
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
+ Debug + Clone + Copy + From<i32> {
fn plot(&self) -> Coordinates<T> {
let Polygon(Coordinates(cs)) = self;
match cs[..] {
[] => Coordinates(Vec::<Coordinate<T>>::new()),
[a] => Coordinates(vec!(a)),
[a, b] => Coordinates(a.line(&b)),
_ => {
let (a, b) = (cs[0], cs[1]);
let mut r = a.line(&b);
let mut i = b;
for j in cs[2..].iter() {
r.append(&mut i.line(j)[1..].to_vec());
i = *j;
}
let mut j = a.line(&i);
let l = j.len();
if l > 1 {
r.append(&mut j[1..l-1].to_vec());
}
Coordinates(r)
},
}
}
}
impl<T> Fillable<T> for Polygon<T>
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
+ Debug + Clone + Copy + From<i32> {
fn fill(&self, canvas :&mut dyn Canvas<T>, color :u32) {
let scanlines = self.left_edge().zip(self.right_edge());
for l in scanlines.flat_map(|(l, r)| l.line_iter(&r)) {
canvas.set_pixel(l, color);
}
}
}
impl<T> Display for Polygon<T> where T: Copy {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let Polygon(a) = self;
write!(f, "Poly[{}]", a)
}
}

186
tutorial/wasm-game-of-life/src/transform.rs

@ -1,186 +0,0 @@
//
// Transformation of vectors in a given coordinate system...
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
use std::ops::{Add, Sub, Neg, Mul, Div};
use std::fmt::Debug;
use crate::Vector;
use crate::trigonometry::Trig;
#[derive(Debug, Clone, Copy)]
pub struct TMatrix<T>( (T, T, T, T)
, (T, T, T, T)
, (T, T, T, T)
, (T, T, T, T) )
where T: Add + Sub + Neg + Mul + Div + Debug + Trig + From<i32> + Copy;
pub trait Transformable<T>
where T: Add + Sub + Neg + Mul + Div + Debug + Trig + From<i32> + Copy {
fn transform(&self, m :&TMatrix<T>) -> Self;
}
impl<T> TMatrix<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ Debug + Trig + From<i32> + Copy {
pub fn new( r1 :(T, T, T, T)
, r2 :(T, T, T, T)
, r3 :(T, T, T, T)
, r4 :(T, T, T, T) ) -> Self {
TMatrix(r1, r2, r3, r4)
}
pub fn unit() -> Self {
Self::new( (1.into(), 0.into(), 0.into(), 0.into())
, (0.into(), 1.into(), 0.into(), 0.into())
, (0.into(), 0.into(), 1.into(), 0.into())
, (0.into(), 0.into(), 0.into(), 1.into()) )
}
pub fn translate(v :Vector<T>) -> Self {
let Vector(x, y, z) = v;
Self::new( (1.into(), 0.into(), 0.into(), x)
, (0.into(), 1.into(), 0.into(), y)
, (0.into(), 0.into(), 1.into(), z)
, (0.into(), 0.into(), 0.into(), 1.into()) )
}
pub fn rotate_x(a :i32) -> Self {
let sin :T = Trig::sin(a);
let cos :T = Trig::cos(a);
Self::new( (1.into(), 0.into(), 0.into(), 0.into())
, (0.into(), cos , -sin , 0.into())
, (0.into(), sin , cos , 0.into())
, (0.into(), 0.into(), 0.into(), 1.into()) )
}
pub fn rotate_y(a :i32) -> Self {
let sin :T = Trig::sin(a);
let cos :T = Trig::cos(a);
Self::new( (cos , 0.into(), sin , 0.into())
, (0.into(), 1.into(), 0.into(), 0.into())
, (-sin , 0.into(), cos , 0.into())
, (0.into(), 0.into(), 0.into(), 1.into()) )
}
pub fn rotate_z(a :i32) -> Self {
let sin :T = Trig::sin(a);
let cos :T = Trig::cos(a);
Self::new( (cos , -sin , 0.into(), 0.into())
, (sin , cos , 0.into(), 0.into())
, (0.into(), 0.into(), 1.into(), 0.into())
, (0.into(), 0.into(), 0.into(), 1.into()) )
}
pub fn rotate_v(v :&Vector<T>, a :i32) -> Self {
let Vector(x, y, z) = *v;
let sin :T = Trig::sin(a);
let cos :T = Trig::cos(a);
let zero :T = 0.into();
let one :T = 1.into();
Self::new( ( (one - cos) * x * x + cos
, (one - cos) * x * y - sin * z
, (one - cos) * x * z + sin * y
, zero )
, ( (one - cos) * x * y + sin * z
, (one - cos) * y * y + cos
, (one - cos) * y * z - sin * x
, zero )
, ( (one - cos) * x * z - sin * y
, (one - cos) * y * z + sin * x
, (one - cos) * z * z + cos
, zero )
, (0.into(), 0.into(), 0.into(), 1.into()) )
}
pub fn scale(v :Vector<T>) -> Self {
let Vector(x, y, z) = v;
Self::new( ( x, 0.into(), 0.into(), 0.into())
, (0.into(), y, 0.into(), 0.into())
, (0.into(), 0.into(), z, 0.into())
, (0.into(), 0.into(), 0.into(), 1.into()) )
}
pub fn combine<I>(mi :I) -> TMatrix<T>
where I: IntoIterator<Item = TMatrix<T>> {
mi.into_iter().fold(Self::unit(), |acc, x| x * acc)
}
pub fn apply(&self, v :&Vector<T>, w :T) -> (Vector<T>, T) {
let TMatrix( (a11, a12, a13, a14)
, (a21, a22, a23, a24)
, (a31, a32, a33, a34)
, (a41, a42, a43, a44) ) = *self;
let Vector(x, y, z) = *v;
let v = Vector( a11 * x + a12 * y + a13 * z + a14 * w
, a21 * x + a22 * y + a23 * z + a24 * w
, a31 * x + a32 * y + a33 * z + a34 * w );
let w = a41 * x + a42 * y + a43 * z + a44 * w;
//v.mul(&w.recip())
(v, w)
}
}
impl<T> Mul for TMatrix<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ Debug + Trig + From<i32> + Copy {
type Output = Self;
// ATTENTION: This is not commutative, nor assoziative.
fn mul(self, other :Self) -> Self {
let TMatrix( (a11, a12, a13, a14)
, (a21, a22, a23, a24)
, (a31, a32, a33, a34)
, (a41, a42, a43, a44) ) = self;
let TMatrix( (b11, b12, b13, b14)
, (b21, b22, b23, b24)
, (b31, b32, b33, b34)
, (b41, b42, b43, b44) ) = other;
TMatrix( ( a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41
, a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42
, a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43
, a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44 )
, ( a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41
, a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42
, a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43
, a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44 )
, ( a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41
, a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42
, a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43
, a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44 )
, ( a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41
, a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42
, a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43
, a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44 ) )
}
}

139
tutorial/wasm-game-of-life/src/vector.rs

@ -1,139 +0,0 @@
//
// Stuff for manipulating 3 dimensional vectors.
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
use std::fmt::{Debug, Display, Formatter, Result};
use std::ops::{Add, Sub, Neg, Mul, Div};
use crate::trigonometry::Trig;
use crate::transform::{TMatrix, Transformable};
#[derive(Debug, Eq, Clone, Copy)]
pub struct Vector<T>(pub T, pub T, pub T)
where T: Add + Sub + Neg + Mul + Div + Trig + Copy;
impl<T> Vector<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T> + Trig + Copy {
pub fn x(self) -> T { self.0 }
pub fn y(self) -> T { self.1 }
pub fn z(self) -> T { self.2 }
pub fn mag(self) -> T {
let Vector(x, y, z) = self;
(x * x + y * y + z * z).sqrt().unwrap()
}
pub fn mul(self, s :&T) -> Self {
let Vector(x, y, z) = self;
Vector(x * *s, y * *s, z * *s)
}
pub fn dot(self, other :Self) -> T {
let Vector(x1, y1, z1) = self;
let Vector(x2, y2, z2) = other;
x1 * x2 + y1 * y2 + z1 * z2
}
pub fn norm(self) -> Self {
// TODO This can result in 0 or inf Vectors…
// Maybe we need to handle zero and inf magnitude here…
self.mul(&self.mag().recip())
}
pub fn distance(self, other :Self) -> T {
(self - other).mag()
}
}
impl<T> Display for Vector<T>
where T: Add + Sub + Neg + Mul + Div + Trig + Display + Copy {
fn fmt(&self, f :&mut Formatter<'_>) -> Result {
let Vector(x, y, z) = self;
write!(f, "({}, {}, {})", x, y, z)
}
}
impl<T> PartialEq for Vector<T>
where T: Add + Sub + Neg + Mul + Div + Trig + PartialEq + Copy {
fn eq(&self, other :&Self) -> bool {
let Vector(x1, y1, z1) = self;
let Vector(x2, y2, z2) = other;
x1 == x2 && y1 == y2 && z1 == z2
}
}
impl<T> Add for Vector<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T> + Trig + Copy {
type Output = Self;
fn add(self, other :Self) -> Self {
let Vector(x1, y1, z1) = self;
let Vector(x2, y2, z2) = other;
Vector(x1 + x2, y1 + y2, z1 + z2)
}
}
impl<T> Sub for Vector<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T> + Trig + Copy {
type Output = Self;
fn sub(self, other :Self) -> Self {
self + -other
}
}
impl<T> Neg for Vector<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T> + Trig + Copy {
type Output = Self;
fn neg(self) -> Self {
let Vector(x, y, z) = self;
Self(-x, -y, -z)
}
}
impl<T> Mul for Vector<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T> + Trig + Copy {
type Output = Self;
fn mul(self, other :Self) -> Self {
let Vector(ax, ay, az) = self;
let Vector(bx, by, bz) = other;
Vector( ay * bz - az * by
, az * bx - ax * bz
, ax * by - ay * bx )
}
}
impl<T> Transformable<T> for Vector<T>
where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
+ Mul<Output = T> + Div<Output = T>
+ Trig + Copy + Debug + From<i32> {
fn transform(&self, m :&TMatrix<T>) -> Self {
let (v, _) = m.apply(self, 0.into());
v
}
}

6
variables/Cargo.lock

@ -1,6 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "variables"
version = "0.1.0"

9
variables/Cargo.toml

@ -1,9 +0,0 @@
[package]
name = "variables"
version = "0.1.0"
authors = ["Georg Hopp <georg@steffers.org>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

6
variables/src/main.rs

@ -1,6 +0,0 @@
fn main() {
let mut x = 5;
println!("The value of x is: {}", x);
x = 6;
println!("The value of x is: {}", x);
}

11
wasm-game-of-life/.appveyor.yml

@ -1,11 +0,0 @@
install:
- appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
- if not defined RUSTFLAGS rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
- rustc -V
- cargo -V
build: false
test_script:
- cargo test --locked

0
wasm-game-of-life/.cargo-ok

3
wasm-game-of-life/.gitignore

@ -1,3 +0,0 @@
bin/
pkg/
wasm-pack.log

69
wasm-game-of-life/.travis.yml

@ -1,69 +0,0 @@
language: rust
sudo: false
cache: cargo
matrix:
include:
# Builds with wasm-pack.
- rust: beta
env: RUST_BACKTRACE=1
addons:
firefox: latest
chrome: stable
before_script:
- (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
- (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate)
- cargo install-update -a
- curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f
script:
- cargo generate --git . --name testing
# Having a broken Cargo.toml (in that it has curlies in fields) anywhere
# in any of our parent dirs is problematic.
- mv Cargo.toml Cargo.toml.tmpl
- cd testing
- wasm-pack build
- wasm-pack test --chrome --firefox --headless
# Builds on nightly.
- rust: nightly
env: RUST_BACKTRACE=1
before_script:
- (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
- (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate)
- cargo install-update -a
- rustup target add wasm32-unknown-unknown
script:
- cargo generate --git . --name testing
- mv Cargo.toml Cargo.toml.tmpl
- cd testing
- cargo check
- cargo check --target wasm32-unknown-unknown
- cargo check --no-default-features
- cargo check --target wasm32-unknown-unknown --no-default-features
- cargo check --no-default-features --features console_error_panic_hook
- cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook
- cargo check --no-default-features --features "console_error_panic_hook wee_alloc"
- cargo check --target wasm32-unknown-unknown --no-default-features --features "console_error_panic_hook wee_alloc"
# Builds on beta.
- rust: beta
env: RUST_BACKTRACE=1
before_script:
- (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
- (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate)
- cargo install-update -a
- rustup target add wasm32-unknown-unknown
script:
- cargo generate --git . --name testing
- mv Cargo.toml Cargo.toml.tmpl
- cd testing
- cargo check
- cargo check --target wasm32-unknown-unknown
- cargo check --no-default-features
- cargo check --target wasm32-unknown-unknown --no-default-features
- cargo check --no-default-features --features console_error_panic_hook
- cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook
# Note: no enabling the `wee_alloc` feature here because it requires
# nightly for now.

34
wasm-game-of-life/Cargo.toml

@ -1,34 +0,0 @@
[package]
name = "wasm-game-of-life"
version = "0.1.0"
authors = ["Georg Hopp <georg@steffers.org>"]
edition = "2018"
[lib]
crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies]
wasm-bindgen = "0.2"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.1", optional = true }
# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size
# compared to the default allocator's ~10K. It is slower than the default
# allocator, however.
#
# Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now.
wee_alloc = { version = "0.4.2", optional = true }
[dev-dependencies]
wasm-bindgen-test = "0.2"
[profile.release]
# Tell `rustc` to optimize for small code size.
opt-level = "s"

176
wasm-game-of-life/LICENSE_APACHE

@ -1,176 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

25
wasm-game-of-life/LICENSE_MIT

@ -1,25 +0,0 @@
Copyright (c) 2018 Georg Hopp <georg@steffers.org>
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

69
wasm-game-of-life/README.md

@ -1,69 +0,0 @@
<div align="center">
<h1><code>wasm-pack-template</code></h1>
<strong>A template for kick starting a Rust and WebAssembly project using <a href="https://github.com/rustwasm/wasm-pack">wasm-pack</a>.</strong>
<p>
<a href="https://travis-ci.org/rustwasm/wasm-pack-template"><img src="https://img.shields.io/travis/rustwasm/wasm-pack-template.svg?style=flat-square" alt="Build Status" /></a>
</p>
<h3>
<a href="https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html">Tutorial</a>
<span> | </span>
<a href="https://discordapp.com/channels/442252698964721669/443151097398296587">Chat</a>
</h3>
<sub>Built with 🦀🕸 by <a href="https://rustwasm.github.io/">The Rust and WebAssembly Working Group</a></sub>
</div>
## About
[**📚 Read this template tutorial! 📚**][template-docs]
This template is designed for compiling Rust libraries into WebAssembly and
publishing the resulting package to NPM.
Be sure to check out [other `wasm-pack` tutorials online][tutorials] for other
templates and usages of `wasm-pack`.
[tutorials]: https://rustwasm.github.io/docs/wasm-pack/tutorials/index.html
[template-docs]: https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html
## 🚴 Usage
### 🐑 Use `cargo generate` to Clone this Template
[Learn more about `cargo generate` here.](https://github.com/ashleygwilliams/cargo-generate)
```
cargo generate --git https://github.com/rustwasm/wasm-pack-template.git --name my-project
cd my-project
```
### 🛠️ Build with `wasm-pack build`
```
wasm-pack build
```
### 🔬 Test in Headless Browsers with `wasm-pack test`
```
wasm-pack test --headless --firefox
```
### 🎁 Publish to NPM with `wasm-pack publish`
```
wasm-pack publish
```
## 🔋 Batteries Included
* [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) for communicating
between WebAssembly and JavaScript.
* [`console_error_panic_hook`](https://github.com/rustwasm/console_error_panic_hook)
for logging panic messages to the developer console.
* [`wee_alloc`](https://github.com/rustwasm/wee_alloc), an allocator optimized
for small code size.

3
wasm-game-of-life/package-lock.json

@ -1,3 +0,0 @@
{
"lockfileVersion": 1
}

19
wasm-game-of-life/src/lib.rs

@ -1,19 +0,0 @@
mod utils;
use wasm_bindgen::prelude::*;
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
extern {
fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, wasm-game-of-life! {}", name));
}

10
wasm-game-of-life/src/utils.rs

@ -1,10 +0,0 @@
pub fn set_panic_hook() {
// When the `console_error_panic_hook` feature is enabled, we can call the
// `set_panic_hook` function at least once during initialization, and then
// we will get better error messages if our code ever panics.
//
// For more details see
// https://github.com/rustwasm/console_error_panic_hook#readme
#[cfg(feature = "console_error_panic_hook")]
console_error_panic_hook::set_once();
}

13
wasm-game-of-life/tests/web.rs

@ -1,13 +0,0 @@
//! Test suite for the Web and headless browsers.
#![cfg(target_arch = "wasm32")]
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1 + 1, 2);
}

24
wasm-game-of-life/www/.bin/create-wasm-app.js

@ -1,24 +0,0 @@
#!/usr/bin/env node
const { spawn } = require("child_process");
const fs = require("fs");
let folderName = '.';
if (process.argv.length >= 3) {
folderName = process.argv[2];
if (!fs.existsSync(folderName)) {
fs.mkdirSync(folderName);
}
}
const clone = spawn("git", ["clone", "https://github.com/rustwasm/create-wasm-app.git", folderName]);
clone.on("close", code => {
if (code !== 0) {
console.error("cloning the template failed!")
process.exit(code);
} else {
console.log("🦀 Rust + 🕸 Wasm = ❤");
}
});

2
wasm-game-of-life/www/.gitignore

@ -1,2 +0,0 @@
node_modules
dist

5
wasm-game-of-life/www/.travis.yml

@ -1,5 +0,0 @@
language: node_js
node_js: "10"
script:
- ./node_modules/.bin/webpack

201
wasm-game-of-life/www/LICENSE-APACHE

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

25
wasm-game-of-life/www/LICENSE-MIT

@ -1,25 +0,0 @@
Copyright (c) [year] [name]
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

67
wasm-game-of-life/www/README.md

@ -1,67 +0,0 @@
<div align="center">
<h1><code>create-wasm-app</code></h1>
<strong>An <code>npm init</code> template for kick starting a project that uses NPM packages containing Rust-generated WebAssembly and bundles them with Webpack.</strong>
<p>
<a href="https://travis-ci.org/rustwasm/create-wasm-app"><img src="https://img.shields.io/travis/rustwasm/create-wasm-app.svg?style=flat-square" alt="Build Status" /></a>
</p>
<h3>
<a href="#usage">Usage</a>
<span> | </span>
<a href="https://discordapp.com/channels/442252698964721669/443151097398296587">Chat</a>
</h3>
<sub>Built with 🦀🕸 by <a href="https://rustwasm.github.io/">The Rust and WebAssembly Working Group</a></sub>
</div>
## About
This template is designed for depending on NPM packages that contain
Rust-generated WebAssembly and using them to create a Website.
* Want to create an NPM package with Rust and WebAssembly? [Check out
`wasm-pack-template`.](https://github.com/rustwasm/wasm-pack-template)
* Want to make a monorepo-style Website without publishing to NPM? Check out
[`rust-webpack-template`](https://github.com/rustwasm/rust-webpack-template)
and/or
[`rust-parcel-template`](https://github.com/rustwasm/rust-parcel-template).
## 🚴 Usage
```
npm init wasm-app
```
## 🔋 Batteries Included
- `.gitignore`: ignores `node_modules`
- `LICENSE-APACHE` and `LICENSE-MIT`: most Rust projects are licensed this way, so these are included for you
- `README.md`: the file you are reading now!
- `index.html`: a bare bones html document that includes the webpack bundle
- `index.js`: example js file with a comment showing how to import and use a wasm pkg
- `package.json` and `package-lock.json`:
- pulls in devDependencies for using webpack:
- [`webpack`](https://www.npmjs.com/package/webpack)
- [`webpack-cli`](https://www.npmjs.com/package/webpack-cli)
- [`webpack-dev-server`](https://www.npmjs.com/package/webpack-dev-server)
- defines a `start` script to run `webpack-dev-server`
- `webpack.config.js`: configuration file for bundling your js with webpack
## License
Licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally
submitted for inclusion in the work by you, as defined in the Apache-2.0
license, shall be dual licensed as above, without any additional terms or
conditions.

5
wasm-game-of-life/www/bootstrap.js

@ -1,5 +0,0 @@
// A dependency graph that contains any wasm must all be imported
// asynchronously. This `bootstrap.js` file does the single async import, so
// that no one else needs to worry about it again.
import("./index.js")
.catch(e => console.error("Error importing `index.js`:", e));

11
wasm-game-of-life/www/index.html

@ -1,11 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello wasm-pack!</title>
</head>
<body>
<noscript>This page contains webassembly and javascript content, please enable javascript in your browser.</noscript>
<script src="./bootstrap.js"></script>
</body>
</html>

3
wasm-game-of-life/www/index.js

@ -1,3 +0,0 @@
import * as wasm from "wasm-game-of-life";
wasm.greet("Georg");

5859
wasm-game-of-life/www/package-lock.json
File diff suppressed because it is too large
View File

37
wasm-game-of-life/www/package.json

@ -1,37 +0,0 @@
{
"name": "create-wasm-app",
"version": "0.1.0",
"description": "create an app to consume rust-generated wasm packages",
"main": "index.js",
"bin": {
"create-wasm-app": ".bin/create-wasm-app.js"
},
"scripts": {
"build": "webpack --config webpack.config.js",
"start": "webpack-dev-server"
},
"repository": {
"type": "git",
"url": "git+https://github.com/rustwasm/create-wasm-app.git"
},
"keywords": [
"webassembly",
"wasm",
"rust",
"webpack"
],
"author": "Ashley Williams <ashley666ashley@gmail.com>",
"license": "(MIT OR Apache-2.0)",
"bugs": {
"url": "https://github.com/rustwasm/create-wasm-app/issues"
},
"homepage": "https://github.com/rustwasm/create-wasm-app#readme",
"devDependencies": {
"wasm-game-of-life": "file:../pkg",
"hello-wasm-pack": "^0.1.0",
"webpack": "^4.29.3",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5",
"copy-webpack-plugin": "^5.0.0"
}
}

14
wasm-game-of-life/www/webpack.config.js

@ -1,14 +0,0 @@
const CopyWebpackPlugin = require("copy-webpack-plugin");
const path = require('path');
module.exports = {
entry: "./bootstrap.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bootstrap.js",
},
mode: "development",
plugins: [
new CopyWebpackPlugin(['index.html'])
],
};

0
tutorial/wasm-game-of-life/www/.bin/create-wasm-app.js → www/.bin/create-wasm-app.js

0
tutorial/wasm-game-of-life/www/.gitignore → www/.gitignore

0
tutorial/wasm-game-of-life/www/README.md → www/README.md

0
tutorial/wasm-game-of-life/www/bootstrap.js → www/bootstrap.js

0
tutorial/wasm-game-of-life/www/index.html → www/index.html

0
tutorial/wasm-game-of-life/www/index.js → www/index.js

0
tutorial/wasm-game-of-life/www/package-lock.json → www/package-lock.json

0
tutorial/wasm-game-of-life/www/package.json → www/package.json

0
tutorial/wasm-game-of-life/www/webpack.config.js → www/webpack.config.js

2
xcb-test/.gitignore

@ -1,2 +0,0 @@
xcbshm
xcbshm2

11
xcb-test/Cargo.toml

@ -1,11 +0,0 @@
[package]
name = "xcb-test"
version = "0.1.0"
authors = ["Georg Hopp <georg@steffers.org>"]
edition = "2018"
[dependencies]
libc = "0.2"
gl = "0.5.2"
x11 = { version = "2.3", features = ["glx"] }
xcb = { version = "0.8", features = ["dri2", "randr", "thread", "xlib_xcb", "shm"] }

12
xcb-test/Makefile

@ -1,12 +0,0 @@
all: xcbshm xcbshm2
xcbshm2: xcbshm2.c
gcc -o $@ -lxcb -lxcb-shm -lxcb-image $<
xcbshm: xcbshm.c
gcc -o $@ -lxcb -lxcb-shm -lxcb-image $<
.PHONY: clean
clean:
@rm -f xcbshm xcbshm2

132
xcb-test/alternatives/info.rs

@ -1,132 +0,0 @@
extern crate xcb;
use std::iter::{Iterator};
use xcb::randr;
fn main() {
let dpy = ":0";
let (conn, screen_num) = xcb::Connection::connect(Some(&dpy)).unwrap();
let setup = conn.get_setup();
let screen = setup.roots().nth(screen_num as usize).unwrap();
println!("");
println!("Informations of screen {}:", screen.root());
println!(" width..........: {}", screen.width_in_pixels());
println!(" height.........: {}", screen.height_in_pixels());
println!(" white pixel....: {:x}", screen.white_pixel());
println!(" black pixel....: {:x}", screen.black_pixel());
let window_dummy = conn.generate_id();
xcb::create_window(
&conn, 0, window_dummy, screen.root()
, 0, 0, 1, 1, 0, 0, 0, &[]);
conn.flush();
let cookie = randr::get_screen_info(&conn, window_dummy);
let reply = cookie.get_reply().unwrap();
let sizes = reply.sizes();
for (i, size) in sizes.enumerate() {
if i != 0 { println!(""); }
println!("size of screen {}:", i+1);
println!(" {} x {} ({}mm x {}mm)", size.width(), size.height(),
size.mwidth(), size.mheight());
}
// ====
let window = conn.generate_id();
let values = [
(xcb::CW_BACK_PIXEL, screen.white_pixel()),
(xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE | xcb::EVENT_MASK_KEY_PRESS),
];
xcb::create_window(&conn,
xcb::COPY_FROM_PARENT as u8,
window,
screen.root(),
0, 0,
150, 150,
10,
xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
screen.root_visual(),
&values);
xcb::map_window(&conn, window);
let title = "Basic Window";
// setting title
xcb::change_property(&conn, xcb::PROP_MODE_REPLACE as u8, window,
xcb::ATOM_WM_NAME, xcb::ATOM_STRING, 8, title.as_bytes());
conn.flush();
// retrieving title
let cookie = xcb::get_property(&conn, false, window, xcb::ATOM_WM_NAME,
xcb::ATOM_STRING, 0, 1024);
if let Ok(reply) = cookie.get_reply() {
assert_eq!(std::str::from_utf8(reply.value()).unwrap(), title);
} else {
panic!("could not retrieve window title!");
}
// retrieving a few atoms
let (wm_state, wm_state_maxv, wm_state_maxh) = {
let cook = xcb::intern_atom(&conn, true, "_NET_WM_STATE");
let cook_maxv = xcb::intern_atom(&conn, true, "_NET_WM_STATE_MAXIMIZED_VERT");
let cook_maxh = xcb::intern_atom(&conn, true, "_NET_WM_STATE_MAXIMIZED_HORZ");
(cook.get_reply().unwrap().atom(),
cook_maxv.get_reply().unwrap().atom(),
cook_maxh.get_reply().unwrap().atom())
};
let mut maximized = false;
loop {
let event = conn.wait_for_event();
match event {
None => { break; }
Some(event) => {
let r = event.response_type();
if r == xcb::KEY_PRESS as u8 {
let key_press : &xcb::KeyPressEvent = unsafe {
xcb::cast_event(&event)
};
println!("Key '{}' pressed", key_press.detail());
if key_press.detail() == 0x3a { // M (on qwerty)
// toggle maximized
println!("toggle maximized: {} {}", wm_state_maxv, wm_state_maxh);
// ClientMessageData is a memory safe untagged union
let data = xcb::ClientMessageData::from_data32([
if maximized { 0 } else { 1 },
wm_state_maxv, wm_state_maxh,
0, 0
]);
let ev = xcb::ClientMessageEvent::new(32, window,
wm_state, data);
xcb::send_event(&conn, false, screen.root(),
xcb::EVENT_MASK_STRUCTURE_NOTIFY, &ev);
conn.flush();
maximized = !maximized;
}
else if key_press.detail() == 0x18 { // Q (on qwerty)
break;
}
}
}
}
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save