Commit 8f79b4d2a8c62271b06fd9f959d01d4d13ff6c9e

Authored by Georg Hopp
1 parent 3087691d

use easel3d crate now

1 1 [package]
2   -name = "wasm-game-of-life"
  2 +name = "easel3d-wasm"
3 3 version = "0.1.0"
4 4 authors = ["hopp@silpion.de"]
5 5 edition = "2018"
... ... @@ -7,29 +7,13 @@ edition = "2018"
7 7 [lib]
8 8 crate-type = ["cdylib", "rlib"]
9 9
10   -[features]
11   -default = ["console_error_panic_hook"]
12   -
13 10 [dependencies]
14 11 wasm-bindgen = "0.2"
15   -lazy_static = "1.4.0"
16   -
17   -# The `console_error_panic_hook` crate provides better debugging of panics by
18   -# logging them with `console.error`. This is great for development, but requires
19   -# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
20   -# code size when deploying.
21   -console_error_panic_hook = { version = "0.1.1", optional = true }
22   -
23   -# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size
24   -# compared to the default allocator's ~10K. It is slower than the default
25   -# allocator, however.
26   -#
27   -# Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now.
  12 +easel3d = { path = "../easel3d" }
28 13 wee_alloc = { version = "0.4.2", optional = true }
29 14
30 15 [dev-dependencies]
31 16 wasm-bindgen-test = "0.2"
32 17
33 18 [profile.release]
34   -# Tell `rustc` to optimize for small code size.
35 19 opt-level = "s"
... ...
1   -<div align="center">
  1 +# Easel3D-WASM
2 2
3   - <h1><code>wasm-pack-template</code></h1>
4   -
5   - <strong>A template for kick starting a Rust and WebAssembly project using <a href="https://github.com/rustwasm/wasm-pack">wasm-pack</a>.</strong>
6   -
7   - <p>
8   - <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>
9   - </p>
10   -
11   - <h3>
12   - <a href="https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html">Tutorial</a>
13   - <span> | </span>
14   - <a href="https://discordapp.com/channels/442252698964721669/443151097398296587">Chat</a>
15   - </h3>
16   -
17   - <sub>Built with 🦀🕸 by <a href="https://rustwasm.github.io/">The Rust and WebAssembly Working Group</a></sub>
18   -</div>
19   -
20   -## About
21   -
22   -[**📚 Read this template tutorial! 📚**][template-docs]
23   -
24   -This template is designed for compiling Rust libraries into WebAssembly and
25   -publishing the resulting package to NPM.
26   -
27   -Be sure to check out [other `wasm-pack` tutorials online][tutorials] for other
28   -templates and usages of `wasm-pack`.
29   -
30   -[tutorials]: https://rustwasm.github.io/docs/wasm-pack/tutorials/index.html
31   -[template-docs]: https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html
32   -
33   -## 🚴 Usage
34   -
35   -### 🐑 Use `cargo generate` to Clone this Template
36   -
37   -[Learn more about `cargo generate` here.](https://github.com/ashleygwilliams/cargo-generate)
38   -
39   -```
40   -cargo generate --git https://github.com/rustwasm/wasm-pack-template.git --name my-project
41   -cd my-project
42   -```
43   -
44   -### 🛠️ Build with `wasm-pack build`
45   -
46   -```
47   -wasm-pack build
48   -```
49   -
50   -### 🔬 Test in Headless Browsers with `wasm-pack test`
51   -
52   -```
53   -wasm-pack test --headless --firefox
54   -```
55   -
56   -### 🎁 Publish to NPM with `wasm-pack publish`
57   -
58   -```
59   -wasm-pack publish
60   -```
61   -
62   -## 🔋 Batteries Included
63   -
64   -* [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) for communicating
65   - between WebAssembly and JavaScript.
66   -* [`console_error_panic_hook`](https://github.com/rustwasm/console_error_panic_hook)
67   - for logging panic messages to the developer console.
68   -* [`wee_alloc`](https://github.com/rustwasm/wee_alloc), an allocator optimized
69   - for small code size.
70   -# Rust playground
71   -
72   -Things I have recently done while learning the Rust programming language.
  3 +WebAssembly demo application using Easel3D...
73 4
74 5 ## Synopsis
75 6
76   -Change in one of the toplevel subdirectories and try `cargo build` or
77   -`cargo run`. Maybe not everything is working oob. Feel free to fix whatever
78   -you want.
  7 +Checkout this repository as well as the _easel3d_ repository to the same
  8 +destination directory.
79 9
80   -## Description
  10 +In the root of this repository call `wasm-pack build`.
  11 +Then change to www and call `npm install`.
81 12
82   -Various small examples I have tried while learning rust. The biggest and
83   -currently most active project is **fractional** which started as an
84   -implamentation of a rational number data type and then switched to a 3D
85   -math playground visualizing using **XCB** (in future it might also use
86   -a **HTML5 Canvas** for drawing as WebAssembly application.
87   -Using fractions with 3D math has several drawbacks:
  13 +To test the stuff call `npm run start` from www directory and in your browser
  14 +open http:://localhost:8080/.
88 15
89   -1. A huge part of 3D math is non rational, like sin, cos, tan and sqrt.
90   -2. The numerator and denominator tend to become very huge while nearing to non
91   - rational numbers and reduction is difficult and time consuming.
92   -3. Because of 2 it is way slower than the floating point calculation (at least
93   - with a decent coprocessor).
  16 +## Description
94 17
95   -Anyway, implementing the vector math stuff for both fractions and floating
96   -point was a nice playground for generics and traits. In future I might add
97   -another data type which implements the math as done by David Braben for the
98   -elite computer game.
  18 +A demo application using easel3d to draw in an HTML5 canvas element in a web
  19 +page.
99 20
100 21 ## Requirements
101 22
102   -### Always
103   -
104 23 - A recent version of the Rust programming language as well as tooling.
105 24 Currently I use Rust 1.39.0.
  25 +- wasm-pack to build to wasm target
  26 +- npm for Javascript code.
  27 +- A browser capable of executing WebAssembly.
106 28
107   -### For fractional
  29 +## Dependencies
108 30
109   -- A running X Server with **XCB** and **X11-SHM** extentions
  31 +### Rust crates.
110 32
111   -## Dependencies
  33 +- easel3d (from parent directory)
  34 +- wasm-bindgen =0.2
  35 +- wee-alloc =0.4.2 (optional)
  36 +
  37 +Along with the dependencies of the external crates. `wasm-pack build` should
  38 +take care of having them available.
  39 +
  40 +### Javascript
112 41
113   -...
  42 +Various things npm installs.
114 43
115 44 ## Contributing
116 45
... ...
1   -//
2   -// This is an abstraction over a drawing environment.
3   -// Future note: z-Buffer is described here:
4   -// https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/perspective-correct-interpolation-vertex-attributes
5   -//
6   -// Georg Hopp <georg@steffers.org>
7   -//
8   -// Copyright © 2019 Georg Hopp
9   -//
10   -// This program is free software: you can redistribute it and/or modify
11   -// it under the terms of the GNU General Public License as published by
12   -// the Free Software Foundation, either version 3 of the License, or
13   -// (at your option) any later version.
14   -//
15   -// This program is distributed in the hope that it will be useful,
16   -// but WITHOUT ANY WARRANTY; without even the implied warranty of
17   -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18   -// GNU General Public License for more details.
19   -//
20   -// You should have received a copy of the GNU General Public License
21   -// along with this program. If not, see <http://www.gnu.org/licenses/>.
22   -//
23   -use std::cmp;
24   -use std::fmt::{Formatter, Debug, Display, Result};
25   -use std::ops::{Add, Sub, Div};
26   -use std::sync::mpsc;
27   -
28   -pub trait Easel {
29   - //fn canvas(&mut self, width :u16, height :u16) -> Option<&dyn Canvas>;
30   -}
31   -
32   -pub trait Canvas<T> {
33   - fn init_events(&self);
34   - fn start_events(&self, tx :mpsc::Sender<i32>);
35   -
36   - fn width(&self) -> u16;
37   - fn height(&self) -> u16;
38   -
39   - fn clear(&mut self);
40   - fn draw(&mut self, c :&dyn Drawable<T>, ofs :Coordinate<T>, color :u32);
41   - fn put_text(&self, ofs :Coordinate<T>, s :&str);
42   - fn set_pixel(&mut self, c :Coordinate<T>, color :u32);
43   - fn show(&self);
44   -}
45   -
46   -pub trait Drawable<T> {
47   - fn plot(&self) -> Coordinates<T>;
48   -}
49   -
50   -pub trait Fillable<T>
51   -where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
52   - + Debug + Copy + From<i32> {
53   - fn fill(&self, canvas :&mut dyn Canvas<T>, color :u32);
54   -}
55   -
56   -#[derive(Debug, Clone, Copy)]
57   -pub struct Coordinate<T>(pub i32, pub i32, pub T);
58   -
59   -#[derive(Debug, Clone)]
60   -pub struct Coordinates<T>(pub Vec<Coordinate<T>>);
61   -
62   -#[derive(Debug, Clone, Copy)]
63   -pub struct LineIterator<T> where T: Debug {
64   - a :Option<Coordinate<T>>
65   - , b :Coordinate<T>
66   - , dx :i32
67   - , dy :i32
68   - , dz :T
69   - , sx :i32
70   - , sy :i32
71   - , err :i32
72   - , only_edges :bool
73   -}
74   -
75   -impl<T> Iterator for LineIterator<T>
76   -where T: Add<Output = T> + Debug + Copy + From<i32> {
77   - type Item = Coordinate<T>;
78   -
79   - fn next(&mut self) -> Option<Self::Item> {
80   - match self.a {
81   - None => None,
82   - Some(a) => {
83   - let Coordinate(ax, ay, az) = a;
84   - let Coordinate(bx, by, _) = self.b;
85   -
86   - if ax != bx || ay != by {
87   - match (2 * self.err >= self.dy, 2 * self.err <= self.dx ) {
88   - (true, false) => {
89   - let r = self.a;
90   - self.a = Some(Coordinate( ax + self.sx
91   - , ay
92   - , az + self.dz ));
93   - self.err = self.err + self.dy;
94   - if self.only_edges { self.next() } else { r }
95   - },
96   - (false, true) => {
97   - let r = self.a;
98   - self.a = Some(Coordinate( ax
99   - , ay + self.sy
100   - , az + self.dz ));
101   - self.err = self.err + self.dx;
102   - r
103   - },
104   - _ => {
105   - let r = self.a;
106   - self.a = Some(Coordinate( ax + self.sx
107   - , ay + self.sy
108   - , az + self.dz ));
109   - self.err = self.err + self.dx + self.dy;
110   - r
111   - },
112   - }
113   - } else {
114   - self.a = None;
115   - Some(self.b)
116   - }
117   - }
118   - }
119   - }
120   -}
121   -
122   -impl<T> Coordinate<T>
123   -where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
124   - + Debug + Clone + Copy + From<i32> {
125   - fn iter(self, b :&Self, only_edges :bool) -> LineIterator<T> {
126   - let Coordinate(ax, ay, az) = self;
127   - let Coordinate(bx, by, bz) = *b;
128   -
129   - let dx = (bx - ax).abs();
130   - let dy = -(by - ay).abs();
131   -
132   - LineIterator { a: Some(self)
133   - , b: *b
134   - , dx: dx
135   - , dy: dy
136   - , dz: (bz - az) / cmp::max(dx, -dy).into()
137   - , sx: if ax < bx { 1 } else { -1 }
138   - , sy: if ay < by { 1 } else { -1 }
139   - , err: dx + dy
140   - , only_edges: only_edges
141   - }
142   - }
143   -
144   - fn line_iter(self, b :&Self) -> LineIterator<T> {
145   - self.iter(b, false)
146   - }
147   -
148   - fn line(self, b :&Self) -> Vec<Self> {
149   - self.line_iter(b).collect()
150   - }
151   -
152   - fn edge_iter(self, b :&Self) -> LineIterator<T> {
153   - self.iter(b, true)
154   - }
155   -
156   - fn edge(self, b :&Self) -> Vec<Self> {
157   - self.edge_iter(b).collect()
158   - }
159   -
160   - fn face(edges :&[Self]) -> Vec<Self> {
161   - edges.to_vec()
162   - }
163   -}
164   -
165   -impl<T> Display for Coordinate<T> {
166   - fn fmt(&self, f: &mut Formatter<'_>) -> Result {
167   - write!(f, "<{},{}>", self.0, self.1)
168   - }
169   -}
170   -
171   -impl<T> Display for Coordinates<T> where T: Copy {
172   - fn fmt(&self, f: &mut Formatter<'_>) -> Result {
173   - let Coordinates(is) = self;
174   -
175   - let c = match is[..] {
176   - [] => String::from(""),
177   - [a] => format!("{}", a),
178   - _ => {
179   - let mut a = format!("{}", is[0]);
180   - for i in is[1..].iter() {
181   - a = a + &format!(",{}", i);
182   - }
183   - a
184   - }
185   - };
186   -
187   - write!(f, "Coordinates[{}]", c)
188   - }
189   -}
190   -
191   -
192   -#[derive(Debug, Clone, Copy)]
193   -pub struct Point<T>(pub Coordinate<T>);
194   -
195   -impl<T> Drawable<T> for Point<T> where T: Copy {
196   - fn plot(&self) -> Coordinates<T> {
197   - let Point(c) = *self;
198   - Coordinates(vec!(c))
199   - }
200   -}
201   -
202   -impl<T> Display for Point<T> {
203   - fn fmt(&self, f: &mut Formatter<'_>) -> Result {
204   - let Point(p) = self;
205   - write!(f, "Point[{}]", p)
206   - }
207   -}
208   -
209   -#[derive(Debug, Clone, Copy)]
210   -pub struct Line<T>(pub Coordinate<T>, pub Coordinate<T>);
211   -
212   -impl<T> Drawable<T> for Line<T>
213   -where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
214   - + Debug + Clone + Copy + From<i32> {
215   - fn plot(&self) -> Coordinates<T> {
216   - let Line(a, b) = *self;
217   - Coordinates(a.line(&b))
218   - }
219   -}
220   -
221   -impl<T> Display for Line<T> {
222   - fn fmt(&self, f: &mut Formatter<'_>) -> Result {
223   - let Line(a, b) = self;
224   - write!(f, "Line[{},{}]", a, b)
225   - }
226   -}
227   -
228   -#[derive(Debug, Clone)]
229   -pub struct Polyline<T>(pub Coordinates<T>);
230   -
231   -impl<T> Drawable<T> for Polyline<T>
232   -where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
233   - + Debug + Clone + Copy + From<i32> {
234   - fn plot(&self) -> Coordinates<T> {
235   - let Polyline(Coordinates(cs)) = self;
236   -
237   - match cs[..] {
238   - [] => Coordinates(Vec::<Coordinate<T>>::new()),
239   - [a] => Coordinates(vec!(a)),
240   - [a, b] => Coordinates(a.line(&b)),
241   - _ => {
242   - let (a, b) = (cs[0], cs[1]);
243   - let mut r = a.line(&b);
244   - let mut i = b;
245   - for j in cs[2..].iter() {
246   - r.append(&mut i.line(j)[1..].to_vec());
247   - i = *j;
248   - }
249   - Coordinates(r)
250   - },
251   - }
252   - }
253   -}
254   -
255   -impl<T> Display for Polyline<T> where T: Copy {
256   - fn fmt(&self, f: &mut Formatter<'_>) -> Result {
257   - let Polyline(a) = self;
258   - write!(f, "PLine[{}]", a)
259   - }
260   -}
261   -
262   -#[derive(Debug, Clone, Copy)]
263   -enum Direction { Left, Right }
264   -
265   -#[derive(Debug, Clone)]
266   -pub struct Polygon<T>(pub Coordinates<T>);
267   -
268   -#[derive(Debug, Clone)]
269   -enum VertexIteratorMode { Vertex, Edge }
270   -#[derive(Debug, Clone)]
271   -pub struct VertexIterator<'a,T> where T: Debug {
272   - p :&'a Polygon<T>,
273   - top :usize,
274   - current :Option<usize>,
275   - edge :Option<LineIterator<T>>,
276   - mode :VertexIteratorMode,
277   - direction :Direction,
278   -}
279   -
280   -impl<'a,T> VertexIterator<'a,T>
281   -where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
282   - + Debug + Copy + From<i32> {
283   - fn edge(p :&'a Polygon<T>, direction :Direction) -> Self {
284   - let top = p.vert_min(direction);
285   - let next = p.next_y(top, direction);
286   - let edge = match next {
287   - None => None,
288   - Some(next) => Some(p.vertex(top).edge_iter(&p.vertex(next))),
289   - };
290   -
291   - VertexIterator { p: p
292   - , top: top
293   - , current: next
294   - , edge: edge
295   - , mode: VertexIteratorMode::Edge
296   - , direction: direction }
297   - }
298   -
299   - fn vertex(p :&'a Polygon<T>, direction :Direction) -> Self {
300   - let top = p.vert_min(direction);
301   - let next = p.next_y(top, direction);
302   -
303   - VertexIterator { p: p
304   - , top: top
305   - , current: next
306   - , edge: None
307   - , mode: VertexIteratorMode::Vertex
308   - , direction: direction }
309   - }
310   -
311   - // if this yields "None" we are finished.
312   - fn next_edge(&mut self) -> Option<LineIterator<T>> {
313   - let current = self.current?;
314   - let next = self.p.next_y(current, self.direction)?;
315   - let mut edge = self.p.vertex(current).edge_iter(&self.p.vertex(next));
316   -
317   - match edge.next() {
318   - // It should be impossible that a new edge iterator has no values
319   - // at all… anyway, just in case I handle it here.
320   - None => self.next_edge(),
321   - Some(_) => {
322   - self.current = Some(next);
323   - self.edge = Some(edge);
324   - self.edge
325   - },
326   - }
327   - }
328   -}
329   -
330   -impl<'a,T> Iterator for VertexIterator<'a,T>
331   -where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
332   - + Debug + Copy + From<i32> {
333   - type Item = Coordinate<T>;
334   -
335   - fn next(&mut self) -> Option<Self::Item> {
336   - match self.mode {
337   - VertexIteratorMode::Edge => {
338   - // if for whatever reason edge is "None" finish this iterator.
339   - let next = self.edge.as_mut()?.next();
340   -
341   - match next {
342   - Some(_) => next,
343   - None => {
344   - self.next_edge()?;
345   - self.next()
346   - },
347   - }
348   - },
349   - VertexIteratorMode::Vertex => {
350   - let current = self.current?;
351   - self.current = self.p.next_y(current, self.direction);
352   - Some(self.p.vertex(current))
353   - },
354   - }
355   - }
356   -}
357   -
358   -impl<T> Polygon<T>
359   -where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
360   - + Copy + Debug + From<i32> {
361   - #[inline]
362   - fn vertex(&self, v :usize) -> Coordinate<T> {
363   - let Polygon(Coordinates(cs)) = self;
364   - cs[v]
365   - }
366   -
367   - fn vert_min<'a>(&'a self, d :Direction) -> usize {
368   - let Polygon(Coordinates(cs)) = self;
369   -
370   - type ICoord<'a,T> = (usize, &'a Coordinate<T>);
371   -
372   - // TODO I guess the problem here is that it does not account for the
373   - // same y vertex on the beggining and the end. So i guess correct
374   - // would be finding the first one and then dependings on the
375   - // given direction either search left or right for same y's.
376   - let fold = |acc :Option<ICoord<'a,T>>, x :ICoord<'a,T>|
377   - match acc {
378   - None => Some(x),
379   - Some(a) => {
380   - let Coordinate(_, ay, _) = a.1;
381   - let Coordinate(_, xy, _) = x.1;
382   - if xy < ay {Some(x)} else {Some(a)}
383   - },
384   - };
385   -
386   - let mut min = cs.iter().enumerate().fold(None, fold).unwrap().0;
387   - let mut next = self.step(min, d);
388   -
389   - while self.vertex(min).1 == self.vertex(next).1 {
390   - min = next;
391   - next = self.step(min, d);
392   - }
393   -
394   - min
395   - }
396   -
397   - fn left_edge(&self) -> VertexIterator<T> {
398   - VertexIterator::edge(self, Direction::Left)
399   - }
400   -
401   - fn right_edge(&self) -> VertexIterator<T> {
402   - VertexIterator::edge(self, Direction::Right)
403   - }
404   -
405   - fn left_vertices(&self) -> VertexIterator<T> {
406   - VertexIterator::vertex(self, Direction::Left)
407   - }
408   -
409   - fn right_vertices(&self) -> VertexIterator<T> {
410   - VertexIterator::vertex(self, Direction::Right)
411   - }
412   -
413   - fn left(&self, v :usize) -> usize {
414   - let Polygon(Coordinates(cs)) = self;
415   -
416   - match v {
417   - 0 => cs.len() - 1,
418   - _ => v - 1,
419   - }
420   - }
421   -
422   - fn right(&self, v :usize) -> usize {
423   - let Polygon(Coordinates(cs)) = self;
424   -
425   - (v + 1) % cs.len()
426   - }
427   -
428   - fn step(&self, v :usize, d :Direction) -> usize {
429   - match d {
430   - Direction::Left => self.left(v),
431   - Direction::Right => self.right(v),
432   - }
433   - }
434   -
435   - fn next_y(&self, c :usize, d :Direction) -> Option<usize> {
436   - fn inner<T>( p :&Polygon<T>
437   - , c :usize
438   - , n :usize
439   - , d :Direction) -> Option<usize>
440   - where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
441   - + Copy + Debug + From<i32> {
442   - if c == n {
443   - None
444   - } else {
445   - let Coordinate(_, cy, _) = p.vertex(c);
446   - let Coordinate(_, ny, _) = p.vertex(n);
447   -
448   - if ny < cy { None } else { Some(n) }
449   - }
450   - }
451   -
452   - inner(self, c, self.step(c, d), d)
453   - }
454   -
455   - pub fn debug(&self) {
456   - let mut left = self.left_vertices();
457   - let mut right = self.right_vertices();
458   -
459   - if left.find(|l| right.find(|r| l.0 == r.0).is_some()).is_some() {
460   - let left :Vec<Coordinate<T>> = self.left_vertices().collect();
461   - let right :Vec<Coordinate<T>> = self.right_vertices().collect();
462   -
463   - println!("===");
464   - println!("== poly : {:?}", self);
465   - println!("== ltop : {:?}", self.vert_min(Direction::Left));
466   - println!("== rtop : {:?}", self.vert_min(Direction::Right));
467   - println!("== left : {:?}", left);
468   - println!("== right : {:?}", right);
469   - println!("===");
470   - }
471   - }
472   -}
473   -
474   -impl<T> Drawable<T> for Polygon<T>
475   -where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
476   - + Debug + Clone + Copy + From<i32> {
477   - fn plot(&self) -> Coordinates<T> {
478   - let Polygon(Coordinates(cs)) = self;
479   -
480   - match cs[..] {
481   - [] => Coordinates(Vec::<Coordinate<T>>::new()),
482   - [a] => Coordinates(vec!(a)),
483   - [a, b] => Coordinates(a.line(&b)),
484   - _ => {
485   - let (a, b) = (cs[0], cs[1]);
486   - let mut r = a.line(&b);
487   - let mut i = b;
488   - for j in cs[2..].iter() {
489   - r.append(&mut i.line(j)[1..].to_vec());
490   - i = *j;
491   - }
492   - let mut j = a.line(&i);
493   - let l = j.len();
494   - if l > 1 {
495   - r.append(&mut j[1..l-1].to_vec());
496   - }
497   - Coordinates(r)
498   - },
499   - }
500   - }
501   -}
502   -
503   -impl<T> Fillable<T> for Polygon<T>
504   -where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
505   - + Debug + Clone + Copy + From<i32> {
506   - fn fill(&self, canvas :&mut dyn Canvas<T>, color :u32) {
507   - let scanlines = self.left_edge().zip(self.right_edge());
508   -
509   - for l in scanlines.flat_map(|(l, r)| l.line_iter(&r)) {
510   - canvas.set_pixel(l, color);
511   - }
512   - }
513   -}
514   -
515   -impl<T> Display for Polygon<T> where T: Copy {
516   - fn fmt(&self, f: &mut Formatter<'_>) -> Result {
517   - let Polygon(a) = self;
518   - write!(f, "Poly[{}]", a)
519   - }
520   -}
  1 +use std::sync::mpsc;
  2 +
  3 +use easel3d::easel::canvas::{Canvas, Vertex};
  4 +use easel3d::easel::drawable::Drawable;
  5 +
  6 +#[derive(Clone, Copy, Debug, PartialEq, Eq)]
  7 +pub struct Color(u8, u8, u8, u8);
  8 +
  9 +pub struct WasmCanvas { width :u16
  10 + , height :u16
  11 + , size :usize
  12 + , zbuf :Vec<f64>
  13 + , image :Vec<Color> }
  14 +
  15 +impl WasmCanvas {
  16 + pub fn new(width :u16, height :u16) -> Self {
  17 + let size = width as usize * height as usize;
  18 +
  19 + Self { width: width
  20 + , height: height
  21 + , size: size
  22 + , zbuf: vec!(0.0; size)
  23 + , image: vec!(Color(0, 0, 0, 0xFF); size) }
  24 + }
  25 +
  26 + pub fn image(&self) -> *const Color {
  27 + self.image.as_ptr()
  28 + }
  29 +}
  30 +
  31 +impl Canvas<f64> for WasmCanvas {
  32 + #[inline]
  33 + fn width(&self) -> u16 {
  34 + self.width
  35 + }
  36 +
  37 + #[inline]
  38 + fn height(&self) -> u16 {
  39 + self.height
  40 + }
  41 +
  42 + fn clear(&mut self) {
  43 + self.zbuf = vec!(0.0; self.size);
  44 + self.image = vec!(Color(0, 0, 0, 0xFF); self.size);
  45 + }
  46 +
  47 + fn set_pixel(&mut self, c :Vertex<f64>, color :u32) {
  48 + let (x, y, zr) = c.as_tuple();
  49 + let idx :usize = (y * (self.width as i32) + x) as usize;
  50 +
  51 + let r = ((color >> 16) & 0xFF) as u8;
  52 + let g = ((color >> 8) & 0xFF) as u8;
  53 + let b = ( color & 0xFF) as u8;
  54 +
  55 + if self.zbuf[idx] < zr {
  56 + self.zbuf[idx] = zr;
  57 + self.image[idx] = Color(r, g, b, 0xFF);
  58 + }
  59 + }
  60 +
  61 + // Empty implementations for now… mostly not needed because it is
  62 + // done from JavaScript…
  63 + fn init_events(&self) {}
  64 + fn start_events(&self, _ :mpsc::Sender<i32>) {}
  65 + fn draw(&mut self, _ :&dyn Drawable<f64>, _ :u32) {}
  66 + fn put_text(&self, _ :Vertex<f64>, _ :&str) {}
  67 + fn show(&self) {}
  68 +}
... ...
1   -//
2   -// Basic geometric things...
3   -//
4   -// Georg Hopp <georg@steffers.org>
5   -//
6   -// Copyright © 2019 Georg Hopp
7   -//
8   -// This program is free software: you can redistribute it and/or modify
9   -// it under the terms of the GNU General Public License as published by
10   -// the Free Software Foundation, either version 3 of the License, or
11   -// (at your option) any later version.
12   -//
13   -// This program is distributed in the hope that it will be useful,
14   -// but WITHOUT ANY WARRANTY; without even the implied warranty of
15   -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16   -// GNU General Public License for more details.
17   -//
18   -// You should have received a copy of the GNU General Public License
19   -// along with this program. If not, see <http://www.gnu.org/licenses/>.
20   -//
21   -use std::convert::{From, Into};
22   -use std::ops::{Add,Sub,Neg,Mul,Div};
23   -use std::fmt::Debug;
24   -
25   -use crate::easel::{Canvas, Coordinate, Coordinates, Polygon};
26   -use crate::transform::{TMatrix, Transformable};
27   -use crate::trigonometry::Trig;
28   -use crate::vector::Vector;
29   -
30   -#[derive(Debug, Clone)]
31   -pub struct Face<T>
32   -where T: Add + Sub + Neg + Mul + Div + Copy + Trig {
33   - corners :Vec<usize>,
34   - normal :Option<Vector<T>>,
35   -}
36   -
37   -#[derive(Debug, PartialEq, Eq, Clone, Copy)]
38   -pub struct Point<T>(pub Vector<T>, T)
39   - where T: Add + Sub + Neg + Mul + Div + PartialEq + Copy + Trig;
40   -
41   -impl<T> Point<T>
42   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
43   - + Mul<Output = T> + Div<Output = T>
44   - + PartialEq + Trig + Copy + From<i32> {
45   - pub fn new(x :T, y :T, z :T) -> Self {
46   - Self(Vector(x, y, z), 1.into())
47   - }
48   -}
49   -
50   -impl<T> Add for Point<T>
51   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
52   - + Mul<Output = T> + Div<Output = T>
53   - + PartialEq + Trig + Copy {
54   - type Output = Self;
55   -
56   - fn add(self, other :Self) -> Self {
57   - let Point(v1, w1) = self;
58   - let Point(v2, w2) = other;
59   - Self(v1 + v2, w1 + w2)
60   - }
61   -}
62   -
63   -impl<T> Neg for Point<T>
64   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
65   - + Mul<Output = T> + Div<Output = T>
66   - + PartialEq + Trig + Copy {
67   - type Output = Self;
68   -
69   - fn neg(self) -> Self {
70   - let Point(v, w) = self;
71   - Self(-v, -w)
72   - }
73   -}
74   -
75   -impl<T> Sub for Point<T>
76   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
77   - + Mul<Output = T> + Div<Output = T>
78   - + PartialEq + Trig + Copy {
79   - type Output = Self;
80   -
81   - fn sub(self, other :Self) -> Self {
82   - self + -other
83   - }
84   -}
85   -
86   -impl<T> Mul for Point<T>
87   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
88   - + Mul<Output = T> + Div<Output = T>
89   - + PartialEq + Trig + Copy + From<i32> {
90   - type Output = Self;
91   -
92   - fn mul(self, other :Self) -> Self {
93   - let a :Vector<T> = self.into();
94   - let b :Vector<T> = other.into();
95   -
96   - Point(a * b, 1.into())
97   - }
98   -}
99   -
100   -impl<T> From<Vector<T>> for Point<T>
101   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
102   - + Mul<Output = T> + Div<Output = T>
103   - + PartialEq + Trig + Copy + From<i32> {
104   - fn from(v :Vector<T>) -> Self {
105   - Point(v, 1.into())
106   - }
107   -}
108   -
109   -impl<T> Into<Vector<T>> for Point<T>
110   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
111   - + Mul<Output = T> + Div<Output = T>
112   - + PartialEq + Trig + Copy + From<i32> {
113   - fn into(self) -> Vector<T> {
114   - let Point(v, w) = self;
115   -
116   - if w == 0.into() {
117   - v
118   - } else {
119   - v.mul(&w.recip())
120   - }
121   - }
122   -}
123   -
124   -impl<T> Transformable<T> for Point<T>
125   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
126   - + Mul<Output = T> + Div<Output = T>
127   - + PartialEq + Debug + Trig + Copy + From<i32> {
128   - fn transform(&self, m :&TMatrix<T>) -> Self {
129   - let Point(v, w) = *self;
130   - let (v, w) = m.apply(&v, w);
131   -
132   - if w == 0.into() {
133   - v.into()
134   - } else {
135   - v.mul(&w.recip()).into()
136   - }
137   - }
138   -}
139   -
140   -#[derive(Debug)]
141   -pub struct Polyeder<T>
142   -where T: Add + Sub + Neg + Mul + Div + PartialEq + Copy + Trig {
143   - points :Vec<Point<T>>,
144   - faces :Vec<Face<T>>,
145   -}
146   -
147   -pub trait Primitives<T>
148   -where T: Add + Sub + Neg + Mul + Div + Debug + Copy + Trig + From<i32> {
149   - fn transform(&self, m :&TMatrix<T>) -> Self;
150   - fn project( &self
151   - , camera :&Camera<T>
152   - , light :&DirectLight<T>
153   - , col :u32 ) -> Vec<(Polygon<T>, u32)>;
154   -}
155   -
156   -#[derive(Debug, Clone, Copy)]
157   -pub struct Camera<T>
158   -where T: Add + Sub + Neg + Mul + Div + Debug + Copy + Trig + From<i32> {
159   - width :T,
160   - height :T,
161   - distance :T,
162   - project :TMatrix<T>,
163   -}
164   -
165   -pub struct DirectLight<T>
166   -where T: Add + Sub + Neg + Mul + Div + Debug + Copy + Trig + From<i32> {
167   - direction: Vector<T>,
168   -}
169   -
170   -impl<T> Camera<T>
171   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
172   - + Mul<Output = T> + Div<Output = T>
173   - + PartialEq + Debug + Copy + Trig + From<i32> {
174   - // This code assumes that the size of the viewport is always
175   - // equal to the size of the physical screen… e.g. window/canvas thus some
176   - // effects can't be done. See book for examples with different viewport
177   - // and screen sizes.
178   - pub fn new(c :&dyn Canvas<T>, angle :i32) -> Self {
179   - let width :T = (c.width() as i32).into();
180   - let height :T = (c.height() as i32).into();
181   - let d :T = 1.into();
182   - let fov = T::cot(angle) * width;
183   - let wh = width / 2.into();
184   - let hh = height / 2.into();
185   -
186   - Camera { width: width
187   - , height: height
188   - , distance: d
189   - , project: TMatrix::new(
190   - ( fov, 0.into(), wh, 0.into())
191   - , (0.into(), fov, hh, 0.into())
192   - , (0.into(), 0.into(), d, 1.into())
193   - , (0.into(), 0.into(), 1.into(), 0.into()) ) }
194   - }
195   -
196   - pub fn get_distance(&self) -> T {
197   - self.distance
198   - }
199   -
200   - pub fn get_projection(&self) -> TMatrix<T> {
201   - self.project
202   - }
203   -
204   - pub fn project(&self, p :Point<T>) -> Point<T> {
205   - p.transform(&self.project)
206   - }
207   -}
208   -
209   -impl<T> DirectLight<T>
210   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
211   - + Mul<Output = T> + Div<Output = T>
212   - + Debug + Copy + Trig + From<i32> {
213   - pub fn new(v :Vector<T>) -> Self {
214   - DirectLight{ direction: v }
215   - }
216   -
217   - pub fn dir(&self) -> Vector<T> {
218   - self.direction
219   - }
220   -}
221   -
222   -impl<T> Face<T>
223   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
224   - + Mul<Output = T> + Div<Output = T>
225   - + PartialEq + Debug + Copy + Trig + From<i32> {
226   - fn new(corners :Vec<usize>, ps :&[Point<T>]) -> Self {
227   - let mut f = Face{ corners: corners, normal: None };
228   - f.update_normal(ps);
229   - f
230   - }
231   -
232   - fn update_normal(&mut self, ps :&[Point<T>]) {
233   - let edge10 :Vector<T> = (ps[self.corners[1]] - ps[self.corners[0]]).into();
234   - let edge12 :Vector<T> = (ps[self.corners[1]] - ps[self.corners[2]]).into();
235   - self.normal = Some(edge10 * edge12);
236   - }
237   -}
238   -
239   -impl<T> Polyeder<T>
240   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
241   - + Mul<Output = T> + Div<Output = T>
242   - + PartialEq + Debug + Copy + Trig + From<i32> {
243   - fn update_normals(&mut self) {
244   - for f in self.faces.iter_mut() {
245   - f.update_normal(&self.points);
246   - }
247   - }
248   -
249   - // construct via cube, see polyhedra.pdf
250   - pub fn tetrahedron(a :T) -> Polyeder<T> {
251   - let f2 :T = 2.into();
252   - let ch = a / (f2 * T::sqrt(f2).unwrap());
253   -
254   - let ps = vec!( Point::new(-ch, -ch, ch) // A
255   - , Point::new(-ch, ch, -ch) // C
256   - , Point::new( ch, -ch, -ch) // E
257   - , Point::new( ch, ch, ch) ); // G
258   -
259   - // bottom: 1, 2, 3
260   - let fs = vec!( Face::new(vec!(2, 1, 0), &ps) // bottom
261   - , Face::new(vec!(3, 2, 0), &ps)
262   - , Face::new(vec!(0, 1, 3), &ps)
263   - , Face::new(vec!(1, 2, 3), &ps) );
264   - //let fs = vec!( Face::new(vec!(0, 1, 2), &ps) // bottom
265   - // , Face::new(vec!(0, 2, 3), &ps)
266   - // , Face::new(vec!(3, 1, 0), &ps)
267   - // , Face::new(vec!(3, 2, 1), &ps) );
268   -
269   - Polyeder{ points: ps, faces: fs }
270   - }
271   -
272   - pub fn triangle(a :T) -> Polyeder<T> {
273   - let f0 :T = 0.into();
274   - let f3 :T = 3.into();
275   - let f6 :T = 6.into();
276   - let zi :T = T::sqrt(f3).unwrap() / f6 * a;
277   - let zc :T = T::sqrt(f3).unwrap() / f3 * a;
278   - let ah :T = a / 2.into();
279   -
280   - let ps = vec!( Point::new(-ah, f0, -zi)
281   - , Point::new( f0, f0, zc)
282   - , Point::new( ah, f0, -zi) );
283   -
284   - let fs = vec!(Face::new(vec!(0, 1, 2), &ps));
285   -
286   - Polyeder{ points: ps, faces: fs }
287   - }
288   -
289   - pub fn cube(a :T) -> Polyeder<T> {
290   - let ah :T = a / From::<i32>::from(2);
291   -
292   - let ps = vec!( Point::new(-ah, ah, -ah) // 0 => front 1
293   - , Point::new(-ah, -ah, -ah) // 1 => front 2
294   - , Point::new( ah, -ah, -ah) // 2 => front 3
295   - , Point::new( ah, ah, -ah) // 3 => front 4
296   - , Point::new(-ah, ah, ah) // 4 => back 1
297   - , Point::new(-ah, -ah, ah) // 5 => back 2
298   - , Point::new( ah, -ah, ah) // 6 => back 3
299   - , Point::new( ah, ah, ah) ); // 7 => back 4
300   -
301   - let fs = vec!( Face::new(vec!(0, 1, 2, 3), &ps) // front
302   - , Face::new(vec!(7, 6, 5, 4), &ps) // back
303   - , Face::new(vec!(1, 5, 6, 2), &ps) // top
304   - , Face::new(vec!(0, 3, 7, 4), &ps) // bottom
305   - , Face::new(vec!(0, 4, 5, 1), &ps) // left
306   - , Face::new(vec!(2, 6, 7, 3), &ps) ); // right
307   -
308   - Polyeder{ points: ps, faces: fs }
309   - }
310   -}
311   -
312   -impl<T> Primitives<T> for Polyeder<T>
313   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
314   - + Mul<Output = T> + Div<Output = T>
315   - + Debug + Copy + Trig + From<i32> + PartialOrd {
316   - // TODO Maybe this should also be an instance of Transformable…
317   - fn transform(&self, m :&TMatrix<T>) -> Self {
318   - let Polyeder{ points: ps, faces: fs } = self;
319   -
320   - let mut p = Polyeder{
321   - points: ps.iter().map(|p| p.transform(m)).collect()
322   - , faces: fs.to_vec()
323   - };
324   -
325   - // TODO alternatively we could rotate the normals too, but this cannot
326   - // done with the original matrix… the question is, what is faster.
327   - p.update_normals();
328   - p
329   - }
330   -
331   - fn project( &self
332   - , camera :&Camera<T>
333   - , light :&DirectLight<T>
334   - , color :u32 ) -> Vec<(Polygon<T>, u32)> {
335   - // Helper to create a Polygon from Coordinates…
336   - // TODO probably there needs to be a Polygon constructor for this.
337   - fn polygon<I, T>(c :I) -> Polygon<T>
338   - where I: Iterator<Item = Coordinate<T>> {
339   - Polygon(Coordinates(c.collect()))
340   - }
341   -
342   - // this one does the projection... as the projection was the last
343   - // matrix we do not need to do it here.
344   - let to_coord = |p :&usize| {
345   - let Point(v, _) = camera.project(self.points[*p]);
346   - Coordinate(T::round(&v.x()), T::round(&v.y()), v.z() - 1.into())
347   - };
348   - let to_poly = |f :&Face<T>| {
349   - let pg = polygon(f.corners.iter().map(to_coord));
350   - let mut r :T = (((color >> 16) & 0xFF) as i32).into();
351   - let mut g :T = (((color >> 8) & 0xFF) as i32).into();
352   - let mut b :T = (((color ) & 0xFF) as i32).into();
353   - let lf :T = match f.normal {
354   - None => 1.into(),
355   - Some(n) => n.dot(light.dir())
356   - / (n.mag() * light.dir().mag()),
357   - };
358   -
359   - // this "if" represents a first simple backface culling
360   - // approach. We only return face that face towards us.
361   - if lf < 0.into() {
362   - r = r * -lf;
363   - g = g * -lf;
364   - b = b * -lf;
365   -
366   - let c :u32 = (r.round() as u32) << 16
367   - | (g.round() as u32) << 8
368   - | (b.round() as u32);
369   -
370   - Some((pg, c))
371   - } else {
372   - None
373   - }};
374   -
375   - self.faces.iter().filter_map(to_poly).collect()
376   - }
377   -}
1   -extern crate lazy_static;
  1 +extern crate easel3d;
2 2
3   -pub type Error = &'static str;
  3 +mod easel3d_wasm;
  4 +use easel3d_wasm::{WasmCanvas, Color};
4 5
5   -pub mod easel;
6   -pub mod transform;
7   -pub mod trigonometry;
8   -pub mod vector;
9   -pub mod geometry;
  6 +use easel3d::easel::canvas::Canvas;
  7 +use easel3d::easel::fillable::Fillable;
10 8
11   -mod utils;
  9 +use easel3d::math::transform::TMatrix;
  10 +use easel3d::math::vector::Vector;
12 11
13   -use vector::Vector;
14   -use easel::{Canvas, Coordinate, Drawable, Fillable};
15   -use geometry::{Camera, DirectLight, Polyeder, Primitives};
16   -use transform::{TMatrix};
  12 +use easel3d::space::camera::Camera;
  13 +use easel3d::space::light::DirectLight;
  14 +use easel3d::space::polyeder::Polyeder;
  15 +use easel3d::space::primitives::Primitives;
17 16
18   -use std::fmt::{Display, Formatter, Result};
19   -use std::sync::mpsc;
20   -use std::time::Instant;
21 17 use wasm_bindgen::prelude::*;
22 18
23 19 // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
... ... @@ -27,56 +23,37 @@ use wasm_bindgen::prelude::*;
27 23 static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
28 24
29 25 #[wasm_bindgen]
30   -#[derive(Clone, Copy, Debug, PartialEq, Eq)]
31   -pub struct Color(u8, u8, u8, u8);
32   -
33   -#[wasm_bindgen]
34   -pub struct View3d { width :u16
35   - , height :u16
36   - , size :usize
  26 +pub struct View3d { canvas :WasmCanvas
37 27 , degree :i32
38   - //, start :Instant
39 28 , tetrahedron :Polyeder<f64>
40 29 , cube :Polyeder<f64>
41   - , camera :Option<Camera<f64>>
42   - , light :DirectLight<f64>
43   - , zbuf :Vec<f64>
44   - , image :Vec<Color>
45   -}
  30 + , camera :Camera<f64>
  31 + , light :DirectLight<f64> }
46 32
47 33 #[wasm_bindgen]
48 34 impl View3d {
49 35 pub fn new(width :u16, height :u16) -> Self {
50   - let size = width as usize * height as usize;
51 36 let light_vector = Vector(0.0, 0.0, 1.0);
  37 + let canvas = WasmCanvas::new(width, height);
  38 + let camera = Camera::<f64>::new(&canvas, 45);
52 39
53   - let mut view3d = Self { width: width
54   - , height: height
55   - , size: size
56   - , degree: 0
57   - //, start: Instant::now()
58   - , tetrahedron: Polyeder::tetrahedron(100.0)
59   - , cube: Polyeder::cube(56.25)
60   - , camera: None
61   - , light: DirectLight::new(light_vector)
62   - , zbuf: vec!(0.0; size)
63   - , image: vec!(Color(0, 0, 0, 0xFF); size)
64   - };
65   -
66   - view3d.camera = Some(Camera::<f64>::new(&view3d, 45));
67   - view3d
  40 + Self { canvas: canvas
  41 + , degree: 0
  42 + , tetrahedron: Polyeder::tetrahedron(100.0)
  43 + , cube: Polyeder::cube(56.25)
  44 + , camera: camera
  45 + , light: DirectLight::new(light_vector) }
68 46 }
69 47
70 48 pub fn width(&self) -> u16 {
71   - self.width
  49 + self.canvas.width()
72 50 }
73 51
74 52 pub fn height(&self) -> u16 {
75   - self.height
  53 + self.canvas.height()
76 54 }
77 55
78 56 pub fn update(&mut self) {
79   - //let deg = ((self.start.elapsed() / 25).as_millis() % 360) as i32;
80 57 let t = TMatrix::translate(Vector(0.0, 0.0, 150.0));
81 58 let rz = TMatrix::rotate_z(self.degree);
82 59 let rx = TMatrix::rotate_x(-self.degree*2);
... ... @@ -88,176 +65,22 @@ impl View3d {
88 65 let objects = vec!( (self.tetrahedron.transform(&rot1), 0xFFFF00)
89 66 , ( self.cube.transform(&rot2), 0x0000FF) );
90 67
91   - self.degree = (self.degree + 1) % 360;
92   -
93   - self.clear();
94   -
95   - match self.camera {
96   - None => {},
97   - Some(camera) => {
98   - for (o, color) in objects {
99   - for (pg, c) in o.project(&camera, &self.light, color) {
100   - (&pg).fill(self, c);
101   - }
102   - }
103   - },
104   - }
105   - }
106   -
107   - pub fn image(&self) -> *const Color {
108   - self.image.as_ptr()
109   - }
110   -}
111   -
112   -impl Canvas<f64> for View3d {
113   - fn width(&self) -> u16 {
114   - self.width
115   - }
116   -
117   - fn height(&self) -> u16 {
118   - self.height
119   - }
120   -
121   - fn clear(&mut self) {
122   - self.zbuf = vec!(0.0; self.size);
123   - self.image = vec!(Color(0, 0, 0, 0xFF); self.size);
124   - }
125   -
126   - fn set_pixel(&mut self, c :Coordinate<f64>, color :u32) {
127   - let Coordinate(x, y, zr) = c;
128   - let idx :usize = (y * (self.width as i32) + x) as usize;
129   -
130   - let r = ((color >> 16) & 0xFF) as u8;
131   - let g = ((color >> 8) & 0xFF) as u8;
132   - let b = ( color & 0xFF) as u8;
133   -
134   - if self.zbuf[idx] < zr {
135   - self.zbuf[idx] = zr;
136   - self.image[idx] = Color(r, g, b, 0xFF);
137   - }
138   - }
139   -
140   - // Empty implementations for now… mostly not needed because it is
141   - // done from JavaScript…
142   - fn init_events(&self) {}
143   - fn start_events(&self, _ :mpsc::Sender<i32>) {}
144   - fn draw( &mut self, _ :&dyn Drawable<f64>, _ :Coordinate<f64>, _ :u32 ) {}
145   - fn put_text(&self, _ :Coordinate<f64>, _ :&str) {}
146   - fn show(&self) {}
147   -}
148   -
149   -#[wasm_bindgen]
150   -#[repr(u8)]
151   -#[derive(Clone, Copy, Debug, PartialEq, Eq)]
152   -pub enum Cell {
153   - Dead = 0,
154   - Alive = 1,
155   -}
156   -
157   -#[wasm_bindgen]
158   -pub struct Universe {
159   - width :u32,
160   - height :u32,
161   - cells :Vec<Cell>,
162   -}
163   -
164   -#[wasm_bindgen]
165   -impl Universe {
166   - pub fn new() -> Universe {
167   - let width = 64;
168   - let height = 64;
169   -
170   - let init_cells = |i :u32| {
171   - if i % 2 == 0 || i % 7 == 0 { Cell::Alive } else { Cell::Dead }
172   - };
173   -
174   - let cells = (0..width * height).map(init_cells).collect();
175   -
176   - Universe {
177   - width: width,
178   - height: height,
179   - cells: cells,
180   - }
181   - }
182   -
183   - pub fn width(&self) -> u32 {
184   - self.width
185   - }
186   -
187   - pub fn height(&self) -> u32 {
188   - self.height
189   - }
190   -
191   - pub fn cells(&self) -> *const Cell {
192   - self.cells.as_ptr()
193   - }
194   -
195   - pub fn render(&self) -> String {
196   - self.to_string()
197   - }
198   -
199   - pub fn tick(&mut self) {
200   - let mut next = self.cells.clone();
  68 + let rlx = TMatrix::rotate_x(-self.degree/4);
  69 + let rly = TMatrix::rotate_y(-self.degree/1);
  70 + let light = self.light.transform(&TMatrix::combine(vec!(rlx, rly)));
201 71
202   - for row in 0..self.height {
203   - for col in 0..self.width {
204   - let idx = self.get_index(row, col);
205   - let cell = self.cells[idx];
206   - let live_neighbors = self.live_neighbor_count(row, col);
  72 + self.degree = (self.degree + 1) % (4*360);
207 73
208   - // Game of life rules....
209   - let next_cell = match (cell, live_neighbors) {
210   - (Cell::Alive, 2) |
211   - (Cell::Alive, 3) => Cell::Alive,
212   - (Cell::Alive, _) => Cell::Dead,
213   - ( Cell::Dead, 3) => Cell::Alive,
214   - ( otherwise, _) => otherwise,
215   - };
  74 + self.canvas.clear();
216 75
217   - next[idx] = next_cell;
  76 + for (o, color) in objects {
  77 + for (pg, c) in o.project(&self.camera, &light, color) {
  78 + (&pg).fill(&mut self.canvas, c);
218 79 }
219 80 }
220   -
221   - self.cells = next;
222   - }
223   -
224   - fn get_index(&self, row :u32, col :u32) -> usize {
225   - (row * self.width + col) as usize
226 81 }
227 82
228   - fn live_neighbor_count(&self, row :u32, col :u32) -> u8 {
229   - let mut count = 0;
230   -
231   - for delta_row in [self.height - 1, 0, 1].iter().cloned() {
232   - for delta_col in [self.width - 1, 0, 1].iter().cloned() {
233   - if delta_row == 0 && delta_col == 0 {
234   - continue;
235   - }
236   -
237   - let neighbor_row = (row + delta_row) % self.height;
238   - let neighbor_col = (col + delta_col) % self.width;
239   - let idx = self.get_index(neighbor_row, neighbor_col);
240   - count += self.cells[idx] as u8;
241   - }
242   - }
243   -
244   - count
245   - }
246   -}
247   -
248   -impl Display for Universe {
249   - fn fmt(&self, f :&mut Formatter) -> Result {
250   - for line in self.cells.as_slice().chunks(self.width as usize) {
251   - for &cell in line {
252   - let symbol = match cell {
253   - Cell::Dead => ' ',
254   - Cell::Alive => '*',
255   - };
256   - write!(f, "{}", symbol)?;
257   - }
258   - write!(f, "\n")?;
259   - }
260   -
261   - Ok(())
  83 + pub fn image(&self) -> *const Color {
  84 + self.canvas.image()
262 85 }
263 86 }
... ...
1   -//
2   -// Transformation of vectors in a given coordinate system...
3   -//
4   -// Georg Hopp <georg@steffers.org>
5   -//
6   -// Copyright © 2019 Georg Hopp
7   -//
8   -// This program is free software: you can redistribute it and/or modify
9   -// it under the terms of the GNU General Public License as published by
10   -// the Free Software Foundation, either version 3 of the License, or
11   -// (at your option) any later version.
12   -//
13   -// This program is distributed in the hope that it will be useful,
14   -// but WITHOUT ANY WARRANTY; without even the implied warranty of
15   -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16   -// GNU General Public License for more details.
17   -//
18   -// You should have received a copy of the GNU General Public License
19   -// along with this program. If not, see <http://www.gnu.org/licenses/>.
20   -//
21   -use std::ops::{Add, Sub, Neg, Mul, Div};
22   -use std::fmt::Debug;
23   -
24   -use crate::Vector;
25   -use crate::trigonometry::Trig;
26   -
27   -#[derive(Debug, Clone, Copy)]
28   -pub struct TMatrix<T>( (T, T, T, T)
29   - , (T, T, T, T)
30   - , (T, T, T, T)
31   - , (T, T, T, T) )
32   - where T: Add + Sub + Neg + Mul + Div + Debug + Trig + From<i32> + Copy;
33   -
34   -pub trait Transformable<T>
35   -where T: Add + Sub + Neg + Mul + Div + Debug + Trig + From<i32> + Copy {
36   - fn transform(&self, m :&TMatrix<T>) -> Self;
37   -}
38   -
39   -impl<T> TMatrix<T>
40   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
41   - + Mul<Output = T> + Div<Output = T>
42   - + Debug + Trig + From<i32> + Copy {
43   - pub fn new( r1 :(T, T, T, T)
44   - , r2 :(T, T, T, T)
45   - , r3 :(T, T, T, T)
46   - , r4 :(T, T, T, T) ) -> Self {
47   - TMatrix(r1, r2, r3, r4)
48   - }
49   -
50   - pub fn unit() -> Self {
51   - Self::new( (1.into(), 0.into(), 0.into(), 0.into())
52   - , (0.into(), 1.into(), 0.into(), 0.into())
53   - , (0.into(), 0.into(), 1.into(), 0.into())
54   - , (0.into(), 0.into(), 0.into(), 1.into()) )
55   - }
56   -
57   - pub fn translate(v :Vector<T>) -> Self {
58   - let Vector(x, y, z) = v;
59   -
60   - Self::new( (1.into(), 0.into(), 0.into(), x)
61   - , (0.into(), 1.into(), 0.into(), y)
62   - , (0.into(), 0.into(), 1.into(), z)
63   - , (0.into(), 0.into(), 0.into(), 1.into()) )
64   - }
65   -
66   - pub fn rotate_x(a :i32) -> Self {
67   - let sin :T = Trig::sin(a);
68   - let cos :T = Trig::cos(a);
69   -
70   - Self::new( (1.into(), 0.into(), 0.into(), 0.into())
71   - , (0.into(), cos , -sin , 0.into())
72   - , (0.into(), sin , cos , 0.into())
73   - , (0.into(), 0.into(), 0.into(), 1.into()) )
74   - }
75   -
76   - pub fn rotate_y(a :i32) -> Self {
77   - let sin :T = Trig::sin(a);
78   - let cos :T = Trig::cos(a);
79   -
80   - Self::new( (cos , 0.into(), sin , 0.into())
81   - , (0.into(), 1.into(), 0.into(), 0.into())
82   - , (-sin , 0.into(), cos , 0.into())
83   - , (0.into(), 0.into(), 0.into(), 1.into()) )
84   - }
85   -
86   - pub fn rotate_z(a :i32) -> Self {
87   - let sin :T = Trig::sin(a);
88   - let cos :T = Trig::cos(a);
89   -
90   - Self::new( (cos , -sin , 0.into(), 0.into())
91   - , (sin , cos , 0.into(), 0.into())
92   - , (0.into(), 0.into(), 1.into(), 0.into())
93   - , (0.into(), 0.into(), 0.into(), 1.into()) )
94   - }
95   -
96   - pub fn rotate_v(v :&Vector<T>, a :i32) -> Self {
97   - let Vector(x, y, z) = *v;
98   -
99   - let sin :T = Trig::sin(a);
100   - let cos :T = Trig::cos(a);
101   -
102   - let zero :T = 0.into();
103   - let one :T = 1.into();
104   -
105   - Self::new( ( (one - cos) * x * x + cos
106   - , (one - cos) * x * y - sin * z
107   - , (one - cos) * x * z + sin * y
108   - , zero )
109   - , ( (one - cos) * x * y + sin * z
110   - , (one - cos) * y * y + cos
111   - , (one - cos) * y * z - sin * x
112   - , zero )
113   - , ( (one - cos) * x * z - sin * y
114   - , (one - cos) * y * z + sin * x
115   - , (one - cos) * z * z + cos
116   - , zero )
117   - , (0.into(), 0.into(), 0.into(), 1.into()) )
118   - }
119   -
120   - pub fn scale(v :Vector<T>) -> Self {
121   - let Vector(x, y, z) = v;
122   -
123   - Self::new( ( x, 0.into(), 0.into(), 0.into())
124   - , (0.into(), y, 0.into(), 0.into())
125   - , (0.into(), 0.into(), z, 0.into())
126   - , (0.into(), 0.into(), 0.into(), 1.into()) )
127   - }
128   -
129   - pub fn combine<I>(mi :I) -> TMatrix<T>
130   - where I: IntoIterator<Item = TMatrix<T>> {
131   -
132   - mi.into_iter().fold(Self::unit(), |acc, x| x * acc)
133   - }
134   -
135   - pub fn apply(&self, v :&Vector<T>, w :T) -> (Vector<T>, T) {
136   - let TMatrix( (a11, a12, a13, a14)
137   - , (a21, a22, a23, a24)
138   - , (a31, a32, a33, a34)
139   - , (a41, a42, a43, a44) ) = *self;
140   - let Vector(x, y, z) = *v;
141   -
142   - let v = Vector( a11 * x + a12 * y + a13 * z + a14 * w
143   - , a21 * x + a22 * y + a23 * z + a24 * w
144   - , a31 * x + a32 * y + a33 * z + a34 * w );
145   - let w = a41 * x + a42 * y + a43 * z + a44 * w;
146   -
147   - //v.mul(&w.recip())
148   - (v, w)
149   - }
150   -}
151   -
152   -impl<T> Mul for TMatrix<T>
153   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
154   - + Mul<Output = T> + Div<Output = T>
155   - + Debug + Trig + From<i32> + Copy {
156   - type Output = Self;
157   -
158   - // ATTENTION: This is not commutative, nor assoziative.
159   - fn mul(self, other :Self) -> Self {
160   - let TMatrix( (a11, a12, a13, a14)
161   - , (a21, a22, a23, a24)
162   - , (a31, a32, a33, a34)
163   - , (a41, a42, a43, a44) ) = self;
164   - let TMatrix( (b11, b12, b13, b14)
165   - , (b21, b22, b23, b24)
166   - , (b31, b32, b33, b34)
167   - , (b41, b42, b43, b44) ) = other;
168   -
169   - TMatrix( ( a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41
170   - , a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42
171   - , a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43
172   - , a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44 )
173   - , ( a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41
174   - , a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42
175   - , a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43
176   - , a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44 )
177   - , ( a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41
178   - , a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42
179   - , a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43
180   - , a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44 )
181   - , ( a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41
182   - , a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42
183   - , a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43
184   - , a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44 ) )
185   - }
186   -}
1   -//
2   -// Some trigonometic functions with Fractions results.
3   -// Currently only sin, cos and tan are implemented.
4   -// As I was unable to find a really good integral approximation for them I
5   -// implement them as a table which is predefined using the floating point
6   -// function f64::sin and then transformed into a fraction of a given
7   -// PRECISION.
8   -// These approximations are quite good and for a few edge cases
9   -// even better than the floating point implementations.
10   -//
11   -// Georg Hopp <georg@steffers.org>
12   -//
13   -// Copyright © 2019 Georg Hopp
14   -//
15   -// This program is free software: you can redistribute it and/or modify
16   -// it under the terms of the GNU General Public License as published by
17   -// the Free Software Foundation, either version 3 of the License, or
18   -// (at your option) any later version.
19   -//
20   -// This program is distributed in the hope that it will be useful,
21   -// but WITHOUT ANY WARRANTY; without even the implied warranty of
22   -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23   -// GNU General Public License for more details.
24   -//
25   -// You should have received a copy of the GNU General Public License
26   -// along with this program. If not, see <http://www.gnu.org/licenses/>.
27   -//
28   -use std::ops::Div;
29   -use std::ops::Neg;
30   -use std::marker::Sized;
31   -use crate::Error;
32   -
33   -pub trait Trig {
34   - fn pi() -> Self;
35   - fn recip(self) -> Self;
36   - fn round(&self) -> i32;
37   - fn sqrt(self) -> Result<Self, Error> where Self: Sized;
38   - fn sintab() -> Vec<Self> where Self: Sized;
39   - fn tantab() -> Vec<Self> where Self: Sized;
40   -
41   - fn sin(d :i32) -> Self
42   - where Self: Sized + Neg<Output = Self> + Copy {
43   - match d {
44   - 0 ..=90 => Self::sintab()[d as usize],
45   - 91 ..=180 => Self::sintab()[180 - d as usize],
46   - 181..=270 => -Self::sintab()[d as usize - 180],
47   - 271..=359 => -Self::sintab()[360 - d as usize],
48   - _ => {
49   - Self::sin(if d < 0 { d % 360 + 360 } else { d % 360 })
50   - },
51   - }
52   - }
53   -
54   - fn cos(d :i32) -> Self
55   - where Self: Sized + Neg<Output = Self> + Copy {
56   - match d {
57   - 0 ..=90 => Self::sintab()[90 - d as usize],
58   - 91 ..=180 => -Self::sintab()[90 - (180 - d as usize)],
59   - 181..=270 => -Self::sintab()[90 - (d as usize - 180)],
60   - 271..=359 => Self::sintab()[90 - (360 - d as usize)],
61   - _ => {
62   - Self::cos(if d < 0 { d % 360 + 360 } else { d % 360 })
63   - },
64   - }
65   - }
66   -
67   - fn tan(d :i32) -> Self where Self: Sized + Copy {
68   - match d {
69   - 0 ..=179 => Self::tantab()[d as usize],
70   - 180..=359 => Self::tantab()[d as usize - 180],
71   - _ => {
72   - Self::tan(if d < 0 { d % 360 + 360 } else { d % 360 })
73   - },
74   - }
75   - }
76   -
77   - fn cot(d :i32) -> Self
78   - where Self: Sized + Copy + From<i32> + Div<Output = Self> {
79   - Into::<Self>::into(1) / Self::tan(d)
80   - }
81   -}
82   -
83   -impl Trig for f64 {
84   - fn pi() -> Self {
85   - std::f64::consts::PI
86   - }
87   -
88   - fn recip(self) -> Self {
89   - self.recip()
90   - }
91   -
92   - fn round(&self) -> i32 {
93   - f64::round(*self) as i32
94   - }
95   -
96   - fn sqrt(self) -> Result<Self, Error> {
97   - let x = self.sqrt();
98   - match x.is_nan() {
99   - true => Err("sqrt on negative undefined"),
100   - false => Ok(x),
101   - }
102   - }
103   -
104   - fn sintab() -> Vec<Self> {
105   - lazy_static::lazy_static! {
106   - static ref SINTAB :Vec<f64> =
107   - (0..=90).map(|x| _sin(x)).collect();
108   - }
109   -
110   - // f64 sin. (From 0° to 90°)
111   - fn _sin(d: u32) -> f64 {
112   - match d {
113   - 0 => 0.0,
114   - 90 => 1.0,
115   - _ => (d as f64).to_radians().sin(),
116   - }
117   - }
118   -
119   - SINTAB.to_vec()
120   - }
121   -
122   - fn tantab() -> Vec<Self> {
123   - // This table exists only because the sin(α) / cos(α) method
124   - // yields very large unreducable denominators in a lot of cases.
125   - lazy_static::lazy_static! {
126   - static ref TANTAB :Vec<f64> =
127   - (0..180).map(|x| _tan(x)).collect();
128   - }
129   -
130   - // fractional tan from f64 tan. (From 0° to 179°)
131   - fn _tan(d: u32) -> f64 {
132   - match d {
133   - 0 => 0.0,
134   - 45 => 1.0,
135   - 90 => std::f64::INFINITY,
136   - 135 => -1.0,
137   - _ => (d as f64).to_radians().tan(),
138   - }
139   - }
140   -
141   - TANTAB.to_vec()
142   - }
143   -}
1   -pub fn set_panic_hook() {
2   - // When the `console_error_panic_hook` feature is enabled, we can call the
3   - // `set_panic_hook` function at least once during initialization, and then
4   - // we will get better error messages if our code ever panics.
5   - //
6   - // For more details see
7   - // https://github.com/rustwasm/console_error_panic_hook#readme
8   - #[cfg(feature = "console_error_panic_hook")]
9   - console_error_panic_hook::set_once();
10   -}
1   -//
2   -// Stuff for manipulating 3 dimensional vectors.
3   -//
4   -// Georg Hopp <georg@steffers.org>
5   -//
6   -// Copyright © 2019 Georg Hopp
7   -//
8   -// This program is free software: you can redistribute it and/or modify
9   -// it under the terms of the GNU General Public License as published by
10   -// the Free Software Foundation, either version 3 of the License, or
11   -// (at your option) any later version.
12   -//
13   -// This program is distributed in the hope that it will be useful,
14   -// but WITHOUT ANY WARRANTY; without even the implied warranty of
15   -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16   -// GNU General Public License for more details.
17   -//
18   -// You should have received a copy of the GNU General Public License
19   -// along with this program. If not, see <http://www.gnu.org/licenses/>.
20   -//
21   -use std::fmt::{Debug, Display, Formatter, Result};
22   -use std::ops::{Add, Sub, Neg, Mul, Div};
23   -
24   -use crate::trigonometry::Trig;
25   -use crate::transform::{TMatrix, Transformable};
26   -
27   -#[derive(Debug, Eq, Clone, Copy)]
28   -pub struct Vector<T>(pub T, pub T, pub T)
29   - where T: Add + Sub + Neg + Mul + Div + Trig + Copy;
30   -
31   -impl<T> Vector<T>
32   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
33   - + Mul<Output = T> + Div<Output = T> + Trig + Copy {
34   - pub fn x(self) -> T { self.0 }
35   - pub fn y(self) -> T { self.1 }
36   - pub fn z(self) -> T { self.2 }
37   -
38   - pub fn mag(self) -> T {
39   - let Vector(x, y, z) = self;
40   - (x * x + y * y + z * z).sqrt().unwrap()
41   - }
42   -
43   - pub fn mul(self, s :&T) -> Self {
44   - let Vector(x, y, z) = self;
45   - Vector(x * *s, y * *s, z * *s)
46   - }
47   -
48   - pub fn dot(self, other :Self) -> T {
49   - let Vector(x1, y1, z1) = self;
50   - let Vector(x2, y2, z2) = other;
51   -
52   - x1 * x2 + y1 * y2 + z1 * z2
53   - }
54   -
55   - pub fn norm(self) -> Self {
56   - // TODO This can result in 0 or inf Vectors…
57   - // Maybe we need to handle zero and inf magnitude here…
58   - self.mul(&self.mag().recip())
59   - }
60   -
61   - pub fn distance(self, other :Self) -> T {
62   - (self - other).mag()
63   - }
64   -}
65   -
66   -impl<T> Display for Vector<T>
67   -where T: Add + Sub + Neg + Mul + Div + Trig + Display + Copy {
68   - fn fmt(&self, f :&mut Formatter<'_>) -> Result {
69   - let Vector(x, y, z) = self;
70   - write!(f, "({}, {}, {})", x, y, z)
71   - }
72   -}
73   -
74   -impl<T> PartialEq for Vector<T>
75   -where T: Add + Sub + Neg + Mul + Div + Trig + PartialEq + Copy {
76   - fn eq(&self, other :&Self) -> bool {
77   - let Vector(x1, y1, z1) = self;
78   - let Vector(x2, y2, z2) = other;
79   - x1 == x2 && y1 == y2 && z1 == z2
80   - }
81   -}
82   -
83   -impl<T> Add for Vector<T>
84   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
85   - + Mul<Output = T> + Div<Output = T> + Trig + Copy {
86   - type Output = Self;
87   -
88   - fn add(self, other :Self) -> Self {
89   - let Vector(x1, y1, z1) = self;
90   - let Vector(x2, y2, z2) = other;
91   - Vector(x1 + x2, y1 + y2, z1 + z2)
92   - }
93   -}
94   -
95   -impl<T> Sub for Vector<T>
96   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
97   - + Mul<Output = T> + Div<Output = T> + Trig + Copy {
98   - type Output = Self;
99   -
100   - fn sub(self, other :Self) -> Self {
101   - self + -other
102   - }
103   -}
104   -
105   -impl<T> Neg for Vector<T>
106   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
107   - + Mul<Output = T> + Div<Output = T> + Trig + Copy {
108   - type Output = Self;
109   -
110   - fn neg(self) -> Self {
111   - let Vector(x, y, z) = self;
112   - Self(-x, -y, -z)
113   - }
114   -}
115   -
116   -impl<T> Mul for Vector<T>
117   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
118   - + Mul<Output = T> + Div<Output = T> + Trig + Copy {
119   - type Output = Self;
120   -
121   - fn mul(self, other :Self) -> Self {
122   - let Vector(ax, ay, az) = self;
123   - let Vector(bx, by, bz) = other;
124   -
125   - Vector( ay * bz - az * by
126   - , az * bx - ax * bz
127   - , ax * by - ay * bx )
128   - }
129   -}
130   -
131   -impl<T> Transformable<T> for Vector<T>
132   -where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
133   - + Mul<Output = T> + Div<Output = T>
134   - + Trig + Copy + Debug + From<i32> {
135   - fn transform(&self, m :&TMatrix<T>) -> Self {
136   - let (v, _) = m.apply(self, 0.into());
137   - v
138   - }
139   -}
1   -#!/usr/bin/env node
2   -
3   -const { spawn } = require("child_process");
4   -const fs = require("fs");
5   -
6   -let folderName = '.';
7   -
8   -if (process.argv.length >= 3) {
9   - folderName = process.argv[2];
10   - if (!fs.existsSync(folderName)) {
11   - fs.mkdirSync(folderName);
12   - }
13   -}
14   -
15   -const clone = spawn("git", ["clone", "https://github.com/rustwasm/create-wasm-app.git", folderName]);
16   -
17   -clone.on("close", code => {
18   - if (code !== 0) {
19   - console.error("cloning the template failed!")
20   - process.exit(code);
21   - } else {
22   - console.log("🦀 Rust + 🕸 Wasm = ❤");
23   - }
24   -});
1   -<div align="center">
2   -
3   - <h1><code>create-wasm-app</code></h1>
4   -
5   - <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>
6   -
7   - <p>
8   - <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>
9   - </p>
10   -
11   - <h3>
12   - <a href="#usage">Usage</a>
13   - <span> | </span>
14   - <a href="https://discordapp.com/channels/442252698964721669/443151097398296587">Chat</a>
15   - </h3>
16   -
17   - <sub>Built with 🦀🕸 by <a href="https://rustwasm.github.io/">The Rust and WebAssembly Working Group</a></sub>
18   -</div>
19   -
20   -## About
21   -
22   -This template is designed for depending on NPM packages that contain
23   -Rust-generated WebAssembly and using them to create a Website.
24   -
25   -* Want to create an NPM package with Rust and WebAssembly? [Check out
26   - `wasm-pack-template`.](https://github.com/rustwasm/wasm-pack-template)
27   -* Want to make a monorepo-style Website without publishing to NPM? Check out
28   - [`rust-webpack-template`](https://github.com/rustwasm/rust-webpack-template)
29   - and/or
30   - [`rust-parcel-template`](https://github.com/rustwasm/rust-parcel-template).
31   -
32   -## 🚴 Usage
33   -
34   -```
35   -npm init wasm-app
36   -```
37   -
38   -## 🔋 Batteries Included
39   -
40   -- `.gitignore`: ignores `node_modules`
41   -- `LICENSE-APACHE` and `LICENSE-MIT`: most Rust projects are licensed this way, so these are included for you
42   -- `README.md`: the file you are reading now!
43   -- `index.html`: a bare bones html document that includes the webpack bundle
44   -- `index.js`: example js file with a comment showing how to import and use a wasm pkg
45   -- `package.json` and `package-lock.json`:
46   - - pulls in devDependencies for using webpack:
47   - - [`webpack`](https://www.npmjs.com/package/webpack)
48   - - [`webpack-cli`](https://www.npmjs.com/package/webpack-cli)
49   - - [`webpack-dev-server`](https://www.npmjs.com/package/webpack-dev-server)
50   - - defines a `start` script to run `webpack-dev-server`
51   -- `webpack.config.js`: configuration file for bundling your js with webpack
52   -
53   -## License
54   -
55   -Licensed under either of
56   -
57   -* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
58   -* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
59   -
60   -at your option.
61   -
62   -### Contribution
63   -
64   -Unless you explicitly state otherwise, any contribution intentionally
65   -submitted for inclusion in the work by you, as defined in the Apache-2.0
66   -license, shall be dual licensed as above, without any additional terms or
67   -conditions.
... ... @@ -2,7 +2,7 @@
2 2 <html>
3 3 <head>
4 4 <meta charset="utf-8">
5   - <title>wasm-game-of-life!</title>
  5 + <title>easel3d</title>
6 6 <style>
7 7 body {
8 8 position: absolute;
... ...
1   -import { View3d } from "wasm-game-of-life";
2   -import { memory } from "wasm-game-of-life/wasm_game_of_life_bg";
  1 +import { View3d } from "easel3d-wasm";
  2 +import { memory } from "easel3d-wasm/easel3d_wasm_bg";
3 3
4 4 // 3D canvas stuff
5   -const view3d = View3d.new(300, 300);
  5 +const view3d = View3d.new(301, 301);
6 6
7 7 const view3d_canvas = document.getElementById("view3d");
8 8 view3d_canvas.width = view3d.width();
... ... @@ -17,7 +17,6 @@ const view3d_renderLoop = () => {
17 17 }
18 18
19 19 const drawView3d = () => {
20   - const view3d_imagePtr = view3d.image();
21 20 const view3d_image = new ImageData(
22 21 new Uint8ClampedArray( memory.buffer
23 22 , view3d.image()
... ...
1 1 {
2   - "name": "create-wasm-app",
  2 + "name": "easel3d-wasm",
3 3 "version": "0.1.0",
4 4 "lockfileVersion": 1,
5 5 "requires": true,
... ... @@ -1486,6 +1486,9 @@
1486 1486 "stream-shift": "^1.0.0"
1487 1487 }
1488 1488 },
  1489 + "easel3d-wasm": {
  1490 + "version": "file:../pkg"
  1491 + },
1489 1492 "ee-first": {
1490 1493 "version": "1.1.1",
1491 1494 "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
... ... @@ -2836,12 +2839,6 @@
2836 2839 "minimalistic-assert": "^1.0.1"
2837 2840 }
2838 2841 },
2839   - "hello-wasm-pack": {
2840   - "version": "0.1.0",
2841   - "resolved": "https://registry.npmjs.org/hello-wasm-pack/-/hello-wasm-pack-0.1.0.tgz",
2842   - "integrity": "sha512-3hx0GDkDLf/a9ThCMV2qG4mwza8N/MCtm8aeFFc/cdBCL2zMJ1kW1wjNl7xPqD1lz8Yl5+uhnc/cpui4dLwz/w==",
2843   - "dev": true
2844   - },
2845 2842 "hmac-drbg": {
2846 2843 "version": "1.0.1",
2847 2844 "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
... ... @@ -5511,9 +5508,6 @@
5511 5508 "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
5512 5509 "dev": true
5513 5510 },
5514   - "wasm-game-of-life": {
5515   - "version": "file:../pkg"
5516   - },
5517 5511 "watchpack": {
5518 5512 "version": "1.6.0",
5519 5513 "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
... ...
1 1 {
2   - "name": "create-wasm-app",
  2 + "name": "easel3d-wasm",
3 3 "version": "0.1.0",
4 4 "description": "create an app to consume rust-generated wasm packages",
5 5 "main": "index.js",
6   - "bin": {
7   - "create-wasm-app": ".bin/create-wasm-app.js"
8   - },
9 6 "scripts": {
10 7 "build": "webpack --config webpack.config.js",
11 8 "start": "webpack-dev-server"
12 9 },
13 10 "repository": {
14 11 "type": "git",
15   - "url": "git+https://github.com/rustwasm/create-wasm-app.git"
  12 + "url": "https://git.silpion.de/scm/~hopp/easel3d-wasm.git"
16 13 },
17 14 "keywords": [
18 15 "webassembly",
19 16 "wasm",
20 17 "rust",
21   - "webpack"
  18 + "webpack",
  19 + "easel3d"
22 20 ],
23   - "author": "Ashley Williams <ashley666ashley@gmail.com>",
24   - "license": "(MIT OR Apache-2.0)",
25   - "bugs": {
26   - "url": "https://github.com/rustwasm/create-wasm-app/issues"
27   - },
28   - "homepage": "https://github.com/rustwasm/create-wasm-app#readme",
  21 + "author": "Georg Hopp <hopp@silpion.de>",
  22 + "license": "GPL-3.0-or-later",
29 23 "devDependencies": {
30   - "wasm-game-of-life": "file:../pkg",
31   - "hello-wasm-pack": "^0.1.0",
32 24 "webpack": "^4.29.3",
33 25 "webpack-cli": "^3.1.0",
34 26 "webpack-dev-server": "^3.1.5",
35 27 "copy-webpack-plugin": "^5.0.0"
36 28 },
37 29 "dependencies": {
38   - "wasm-game-of-life": "file:../pkg"
  30 + "easel3d-wasm": "file:../pkg"
39 31 }
40 32 }
... ...
Please register or login to post a comment