<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Dienst nach Fortschritt]]></title><description><![CDATA[Tech art and stuff related to computer graphics - mainly procedural things and modeling.]]></description><link>http://schdbr.de/</link><image><url>http://schdbr.de/favicon.png</url><title>Dienst nach Fortschritt</title><link>http://schdbr.de/</link></image><generator>Ghost 2.1</generator><lastBuildDate>Sun, 19 Apr 2026 10:25:32 GMT</lastBuildDate><atom:link href="http://schdbr.de/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[logo]]></title><description><![CDATA[<figure class="kg-card kg-image-card"><img src="http://schdbr.de/content/images/2021/02/logo.svg" class="kg-image"></figure>]]></description><link>http://schdbr.de/logo/</link><guid isPermaLink="false">603b4c0d534e560559a62564</guid><dc:creator><![CDATA[Johann Woelper]]></dc:creator><pubDate>Tue, 19 Nov 2024 07:59:00 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="http://schdbr.de/content/images/2021/02/logo.svg" class="kg-image"></figure>]]></content:encoded></item><item><title><![CDATA[Portfolio]]></title><description><![CDATA[<p><em>Some colorful images and stuff I liked working on</em></p>
<h2 id="games">Games</h2>
<h3 id="3dgamesforthemobileplatformpublishedbymadprocessor">3d games for the mobile platform published by Mad Processor.</h3>
<p>Tasks included game/level design, tooling, modeling/texturing and art pipeline as well as marketing/publishing.</p>
<h3 id="parcelpanic2">Parcel Panic 2</h3>
<p>Crazy Taxi inspired game with a huge open-world island to explore,</p>]]></description><link>http://schdbr.de/portfolio/</link><guid isPermaLink="false">5b9fb31e4ec242211f2d3e48</guid><dc:creator><![CDATA[Johann Woelper]]></dc:creator><pubDate>Wed, 15 May 2024 06:49:00 GMT</pubDate><content:encoded><![CDATA[<p><em>Some colorful images and stuff I liked working on</em></p>
<h2 id="games">Games</h2>
<h3 id="3dgamesforthemobileplatformpublishedbymadprocessor">3d games for the mobile platform published by Mad Processor.</h3>
<p>Tasks included game/level design, tooling, modeling/texturing and art pipeline as well as marketing/publishing.</p>
<h3 id="parcelpanic2">Parcel Panic 2</h3>
<p>Crazy Taxi inspired game with a huge open-world island to explore, featuring bullet physics, 300K downloads<br>
<img src="http://schdbr.de/content/images/2017/08/pp1.jpg" alt="pp1"><br>
<a href="https://itunes.apple.com/de/app/parcel-panic-2-post-car-racing/id608204132?mt=8">App Store</a></p>
<h3 id="motorblast">Motorblast</h3>
<p>Mario Kart style fun racer with rockets, damage model and multiplayer, 1M downloads, top 1 in Games category in 9 countries, #14 in Games US<br>
<img src="http://schdbr.de/content/images/2017/08/mb.jpg" alt="mb"><br>
<a href="https://itunes.apple.com/us/app/motorblast/id571217953?mt=8">App Store</a></p>
<h3 id="uberracer">Uber Racer</h3>
<p>Post-apocalyptic racer with configurable cars, 2.8M downloads, top 1 overall in 38 countries, US #2 overall, #1 in games<br>
<img src="http://schdbr.de/content/images/2017/08/screen520x924.jpg" alt="ur"><br>
<a href="https://itunes.apple.com/us/app/uber-racer-3d-sandstorm/id409289600?mt=8">App Store</a></p>
<h2 id="proceduralcontent">Procedural content</h2>
<p>In-house game engine demo: Fully procedural landscape with OpenVDB done in houdini (mobile hardware)<br>
<img src="http://schdbr.de/content/images/2017/08/horror_cropped.jpeg" alt="horror_cropped"></p>
<p>Procedural grass in houdini<br>
<img src="http://schdbr.de/content/images/2017/08/grass2.jpg" alt="grass2"><br>
<img src="http://schdbr.de/content/images/2017/08/grass1.jpg" alt="grass1"></p>
<p>Idmask-based material generation in Substance Designer<br>
(No painting was done)<br>
<img src="http://schdbr.de/content/images/2017/08/train1.png" alt="train1"></p>
<p>Procedural game assets with scalable upgrade stages<br>
<img src="http://schdbr.de/content/images/2017/08/Screen-Shot-2015-09-25-at-15.37.09.png" alt="Screen-Shot-2015-09-25-at-15.37.09"><br>
<img src="http://schdbr.de/content/images/2017/08/Screen-Shot-2015-09-04-at-15.17.56.png" alt="Screen-Shot-2015-09-04-at-15.17.56"></p>
<p>Prop/weapon generator asset<br>
<img src="http://schdbr.de/content/images/2017/08/Screen-Shot-2016-03-31-at-11.49.04.png" alt="Screen-Shot-2016-03-31-at-11.49.04"></p>
<p>Feather asset for texture generation<br>
<img src="http://schdbr.de/content/images/2017/08/feather2.png" alt="feather2"><br>
<img src="http://schdbr.de/content/images/2017/08/feather.gif" alt="feather"></p>
<p>Ivy generator<br>
<img src="http://schdbr.de/content/images/2017/08/ivy-smalldist.gif" alt="ivy-smalldist"><br>
<img src="http://schdbr.de/content/images/2017/08/ivy.jpg" alt="ivy"></p>
<p>Terrain generation<br>
<img src="http://schdbr.de/content/images/2017/08/terrain2.jpg" alt="terrain2"></p>
<p>Live walking rig<br>
<img src="http://schdbr.de/content/images/2017/08/walk.gif" alt="walk"></p>
<p>City building<br>
Any 2d shape produces a house according to ajustable rules. This can form the basis for further refinements and customization.<br>
<img src="http://schdbr.de/content/images/2017/08/city2.png" alt="city2"><br>
<img src="http://schdbr.de/content/images/2017/08/city3.png" alt="city3"><br>
No city without a tilt shift shot:<br>
<img src="http://schdbr.de/content/images/2017/09/Screenshot-from-2017-09-05-14-04-15.png" alt="Screenshot-from-2017-09-05-14-04-15"></p>
<p><img src="http://schdbr.de/content/images/2017/08/houses.gif" alt="houses"><br>
Previz level<br>
<img src="http://schdbr.de/content/images/2017/08/city5.jpg" alt="city5"></p>
<p>Adaptively tesselated geometry makes up for backgrounds or skyboxes without using textures<br>
<img src="http://schdbr.de/content/images/2017/08/vcol1.png" alt="vcol1"><img src="http://schdbr.de/content/images/2017/08/vcol3.png" alt="vcol3"></p>
<p>Temporally and spatially seamless water generator (useful for water/lava animated normal/diffuse maps)<br>
<img src="http://schdbr.de/content/images/2017/08/water1.gif" alt="water1"><br>
<img src="http://schdbr.de/content/images/2017/08/water2.gif" alt="water2"></p>
<p>Simple realtime bird flocking in VEX/houdini<br>
<img src="http://schdbr.de/content/images/2017/08/flock.gif" alt="flock"></p>
<h2 id="modeling">Modeling</h2>
<p><img src="http://schdbr.de/content/images/2017/08/whale.gif" alt="whale"><br>
<img src="http://schdbr.de/content/images/2017/08/Screenshot-from-2017-08-21-13-34-21.png" alt="Screenshot-from-2017-08-21-13-34-21"><br>
<img src="http://schdbr.de/content/images/2017/08/viking2.gif" alt="viking2"><br>
<img src="http://schdbr.de/content/images/2017/08/stag-2.png" alt="stag-2"><br>
<img src="http://schdbr.de/content/images/2017/08/hedgehog.png" alt="hedgehog"><br>
<img src="http://schdbr.de/content/images/2017/08/heli.png" alt="heli"></p>
<h2 id="misc">Misc</h2>
<p>Open Source client/server real time data graphing system<br>
Stream any key/value from any source to visualize.<br>
<img src="http://schdbr.de/content/images/2017/08/vapor.gif" alt="vapor"><br>
<a href="https://github.com/woelper/vaportrail">github page</a></p>
]]></content:encoded></item><item><title><![CDATA[Rust link/build time speedup]]></title><description><![CDATA[<p></p><p></p><p>in <code>~/.cargo/config</code> you can switch to lld as a linker (needs to be installed of course):</p><pre><code>[build]
rustflags = ["-C", "link-arg=-fuse-ld=lld"]</code></pre><p>Linking often took the most of my time when just changing a small amount of code, so the above has a big impact on day-to-day work.</p><p>If</p>]]></description><link>http://schdbr.de/rust-ling-build-time-speedup/</link><guid isPermaLink="false">5f9e5f81efe91b0517cca481</guid><dc:creator><![CDATA[Johann Woelper]]></dc:creator><pubDate>Sun, 01 Nov 2020 07:14:35 GMT</pubDate><content:encoded><![CDATA[<p></p><p></p><p>in <code>~/.cargo/config</code> you can switch to lld as a linker (needs to be installed of course):</p><pre><code>[build]
rustflags = ["-C", "link-arg=-fuse-ld=lld"]</code></pre><p>Linking often took the most of my time when just changing a small amount of code, so the above has a big impact on day-to-day work.</p><p>If you don't need debugging symbols often, you can add <br></p><pre><code>
[profile.dev]
debug = false</code></pre><p>For your project. This can speed up compilation times.</p>]]></content:encoded></item><item><title><![CDATA[Draw a pixel with rust and image]]></title><description><![CDATA[<p>Since the docs are a bit sparse, this is a very short post on how to draw a pixel:</p><p></p><pre><code>use image::{ImageBuffer, Rgb};
fn main()
{
    let green = [0, 255, 0];
    let red = [255, 0, 0];

    let mut image = ImageBuffer::&lt;Rgb&lt;u8&gt;, Vec&lt;u8&gt;&gt;::new(</code></pre>]]></description><link>http://schdbr.de/draw-a-pixel-with-rust-and-image/</link><guid isPermaLink="false">5def6ca2f3460f04a9bf60f8</guid><dc:creator><![CDATA[Johann Woelper]]></dc:creator><pubDate>Tue, 10 Dec 2019 10:00:44 GMT</pubDate><content:encoded><![CDATA[<p>Since the docs are a bit sparse, this is a very short post on how to draw a pixel:</p><p></p><pre><code>use image::{ImageBuffer, Rgb};
fn main()
{
    let green = [0, 255, 0];
    let red = [255, 0, 0];

    let mut image = ImageBuffer::&lt;Rgb&lt;u8&gt;, Vec&lt;u8&gt;&gt;::new(200, 200);
    image.put_pixel(5,5, Rgb(green));
    image.save("output1.png");

    for i in 1..100 {
        image.put_pixel(i, 5, Rgb(red));
    }
    image.save("output2.png");

}</code></pre>]]></content:encoded></item><item><title><![CDATA[Providing test data as a crate]]></title><description><![CDATA[How to include your test data as a crate in your rust project]]></description><link>http://schdbr.de/testdata-as-crate-rust/</link><guid isPermaLink="false">5de61ed4f3460f04a9bf60f0</guid><category><![CDATA[rust]]></category><dc:creator><![CDATA[Johann Woelper]]></dc:creator><pubDate>Tue, 03 Dec 2019 09:25:48 GMT</pubDate><media:content url="http://schdbr.de/content/images/2019/12/Cargo-Logo-Small-c39abeb466d747f3be442698662c5260.png" medium="image"/><content:encoded><![CDATA[<img src="http://schdbr.de/content/images/2019/12/Cargo-Logo-Small-c39abeb466d747f3be442698662c5260.png" alt="Providing test data as a crate"><p>If you want to test your project against some sample data it might be too tedious to deal with all the setup - you might need to clone some repo and clean it up afterwards. Rust already has crates, so can we use them for that?</p><p>Suppose we want to distribute some images to test our tool against. For some reason we want super huge images and maybe a lot of them, maybe for performance testing. This would not be wise to check into our main repo.</p><p>Let's assume we placed the images in <code>images/</code> next to our <code>src/</code> dir (at the crate root)</p><p>Let's start be creating a test crate (library) - I named it <code>testdata</code>:</p><p><code>cargo init --lib</code></p><pre><code>#![feature(option_flattening)]
use std::path::PathBuf;

pub fn get_project_path() -&gt; Option&lt;PathBuf&gt; {
    PathBuf::from(file!()).parent()
    .map(|p| p.parent())
    .flatten()
    .map(|p| p.join("images"))
}


#[test]
fn test_path() {
    dbg!(get_project_path());
}</code></pre><p>Pretty simple, no? The main part is just the <code>file!()</code> macro. This returns the absolute path to <code>lib.rs</code> whether it is local or compiled somewhere on your computer or whatever shit you run this on.</p><p>In our actual crate, include the test crate either from crates.io, locally or from git - whatever you like. See here for more info:</p><p><a href="https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html">https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html</a></p><p>We specify the dependencies as dev-dependencies so they do not get build on a regular build:</p><pre><code>[dev-dependencies]
testdata = { path = "../testdata"}
#testdata = { git = "https://github..."}</code></pre><p>Then in <code>main.rs</code>:</p><pre><code>#[cfg(test)]
use testdata;
#[cfg(test)]
use std::fs;

fn main() {
    println!("Yo");
}

#[test]
fn show_pics() {
    let dir = testdata::get_project_path().unwrap();
    for entry in fs::read_dir(dir).unwrap(){
        println!("{:?}", entry.unwrap());
    }
}</code></pre><p>If you then run your test with <code>cargo test -- --nocapture</code> (shows regular output as opposed to <code>cargo test</code>) you should now get access/see all your images supplied in your <code>images/</code> folder of your testdata crate.</p>]]></content:encoded></item><item><title><![CDATA[A proper terminal on Windows]]></title><description><![CDATA[<p></p><p>For quite some time, cmder and it's ecosystem seemed like the default.</p><p>Now there is a great new option: Alacritty. <a href="https://github.com/jwilm/alacritty">https://github.com/jwilm/alacritty</a></p><p>Below are some settings to make it more unix-like and setup some defaults.</p><h2 id="config-file-">Config file:</h2><p>Your config file is in %APPDATA%/alacritty/alacritty.yml.</p><h3 id="getting-ctrl-c-to-work-">Getting</h3>]]></description><link>http://schdbr.de/a-proper-terminal-on-windows/</link><guid isPermaLink="false">5ddbd159f3460f04a9bf60eb</guid><dc:creator><![CDATA[Johann Woelper]]></dc:creator><pubDate>Mon, 25 Nov 2019 13:13:30 GMT</pubDate><content:encoded><![CDATA[<p></p><p>For quite some time, cmder and it's ecosystem seemed like the default.</p><p>Now there is a great new option: Alacritty. <a href="https://github.com/jwilm/alacritty">https://github.com/jwilm/alacritty</a></p><p>Below are some settings to make it more unix-like and setup some defaults.</p><h2 id="config-file-">Config file:</h2><p>Your config file is in %APPDATA%/alacritty/alacritty.yml.</p><h3 id="getting-ctrl-c-to-work-">Getting CTRL-c to work:</h3><p>If you have issues with command sequences such as ctrl-c, consider enabling the conpty backend.</p><p>Locate <code>enable_experimental_conpty_backend</code> in the config file and set it to true:</p><p><code>enable_experimental_conpty_backend: true</code></p><h3 id="set-up-color-schemes-">Set up color schemes:</h3><p>Visit this page <a href="https://github.com/jwilm/alacritty/wiki/Color-schemes">https://github.com/jwilm/alacritty/wiki/Color-schemes</a> and copy out a scheme, then replace the section in your config file.</p><p>See more powershell config here: <a href="https://blog.schdbr.de/powershell/">https://blog.schdbr.de/powershell/</a></p>]]></content:encoded></item><item><title><![CDATA[Rust, travis CI and multiple targets]]></title><description><![CDATA[<p>One thing you might want to do at some stage is set up continuous integration.</p><p>I was looking for an option that gave me rust support and windows, mac and linux builds. Travis does offer all of that and is free to use for open source projects. I spent too</p>]]></description><link>http://schdbr.de/rust-travis-ci-and-multiple-targets/</link><guid isPermaLink="false">5d60d08df3460f04a9bf60db</guid><dc:creator><![CDATA[Johann Woelper]]></dc:creator><pubDate>Sun, 25 Aug 2019 05:27:35 GMT</pubDate><content:encoded><![CDATA[<p>One thing you might want to do at some stage is set up continuous integration.</p><p>I was looking for an option that gave me rust support and windows, mac and linux builds. Travis does offer all of that and is free to use for open source projects. I spent too much time setting it up, especially with the uploading part, so here we go:</p><p></p><pre><code>language: rust
rust:
  - nightly-2019-06-24
cache: cargo
script:
  - cargo build --release
  - git config --local user.name "Johann Woelper"
  - git config --local user.email "woelper@gmail.com"
os:
  - linux
  - osx
  - windows
before_deploy:
  - cd $TRAVIS_BUILD_DIR
  - export TRAVIS_TAG="latest"-$TRAVIS_OS_NAME
deploy:
  provider: releases
  skip_cleanup: true
  file_glob: true
  # draft: true
  overwrite: true
  name: $TRAVIS_OS_NAME
  file:
    - target/release/my_executable
    - target/release/my_executable.exe
  api_key:
    secure: &lt;done with travis setup releases&gt;</code></pre><p>First of all, I wanted to pin a specific nightly version because a dependency did not work with the latest nightly - and by default travis installs the latest before building. You can now specify a specific version like <code>nightly-2019-06-24</code>.</p><p>Next up, on the <code>os:</code> section all operating systems are added</p><p>in the <code>script:</code> section, declare your git credentials</p><p><code>before deploy:</code> will run on each VM that has spun up, so that's where we set the <code>TRAVIS_TAG</code> to the tag we want for our build and change to the build dir.</p><p>This will create three releases, one for each OS. If you want to have a single release make sure you have unique executable names for each operating systems - then you could set <code>draft</code> to <code>true</code> so the release does not trigger at each <code>os</code> build step and realease it after all builds are done.</p><p>Lastly, <code>travis setup releases</code> is convenient to modify your config file automatically with the correct oauth token.</p>]]></content:encoded></item><item><title><![CDATA[building a python module with rust]]></title><description><![CDATA[<p>Setup:</p><p><code>cargo init --lib</code> (from within a folder you created)</p><p>If you want to support OSX:</p><p><code>.cargo/config</code></p><pre><code>[target.x86_64-apple-darwin]
rustflags = [
  "-C", "link-arg=-undefined",
  "-C", "link-arg=dynamic_lookup",
]</code></pre><p>Dependencies:</p><p><code>Cargo.toml</code>:</p><pre><code>[package]
name = "mypackage"
version = "0.1.0"
authors = ["Me &lt;me@domain.com&gt;"]
edition = "2018"

[lib]
name</code></pre>]]></description><link>http://schdbr.de/building-a-python-module-with-rust/</link><guid isPermaLink="false">5d4933e7f3460f04a9bf60d2</guid><dc:creator><![CDATA[Johann Woelper]]></dc:creator><pubDate>Tue, 06 Aug 2019 09:39:50 GMT</pubDate><content:encoded><![CDATA[<p>Setup:</p><p><code>cargo init --lib</code> (from within a folder you created)</p><p>If you want to support OSX:</p><p><code>.cargo/config</code></p><pre><code>[target.x86_64-apple-darwin]
rustflags = [
  "-C", "link-arg=-undefined",
  "-C", "link-arg=dynamic_lookup",
]</code></pre><p>Dependencies:</p><p><code>Cargo.toml</code>:</p><pre><code>[package]
name = "mypackage"
version = "0.1.0"
authors = ["Me &lt;me@domain.com&gt;"]
edition = "2018"

[lib]
name = "pymod"
crate-type = ["cdylib"]

[dependencies]


[dependencies.pyo3]
version = "0.7.0"
features = ["extension-module"]</code></pre><p>At this point, <code>cargo build</code> should already produce a <code>pymod.dll/so/dylib</code> in <code>target/debug</code>.</p><p>Now we need some actual code so we can play with it in python.</p><pre><code>use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
use pyo3::exceptions;

// #[pyclass] tells pyo3 that this should be treated as a python class
#[pyclass]
struct Vehicle {
    #[pyo3(get, set)]
    model: String,
    #[pyo3(get, set)]
    manufacturer: String,
    #[pyo3(get, set)]
    range: f32,
    #[pyo3(get, set)]
    price: i32
}

// This macro tells pyo3 that this function is accessible from python
#[pyfunction]
fn vehicles() -&gt; PyResult&lt;Vec&lt;Vehicle&gt;&gt; {
    // Let's keep it simple: a vec to hold our vehicles
    let mut vehicles = vec![];

    vehicles.push(Vehicle {
        model: "Model S".to_string(),
        manufacturer: "Tesla".to_string(),
        range: 520.0,
        price: 81980
    });

    vehicles.push(Vehicle {
        model: "Leaf".to_string(),
        manufacturer: "Nissan".to_string(),
        range: 172.0,
        price: 36800
    });

    vehicles.push(Vehicle {
        model: "Urban".to_string(),
        manufacturer: "Desiknio".to_string(),
        range: 100.0,
        price: 3790
    });


    Ok(vehicles) //return positive PyResult

    //If you want exceptions, use PyErr with the pyo3::exceptions already provided for you
    //Err(PyErr::new::&lt;exceptions::IOError, _&gt;("Can't open ffproj"))

}

//The name of this function has to match our [lib] name in Cargo.toml
#[pymodule]
fn pymod(py: Python, m: &amp;PyModule) -&gt; PyResult&lt;()&gt; {
    m.add_wrapped(wrap_pyfunction!(vehicles))?;
    Ok(())
}</code></pre><p>now just copy <code>pymod.dylib</code> to <code>pymod.so</code> on mac, on windows <code>pymod.dll</code> to <code>pymod.pyd</code> and on linux <code>pymod.so</code> to <code>pymod.so</code>. </p><p>In python:</p><pre><code>import pymod

for vehicle in pymod.vehicles():
    print(vehicle.manufacturer, vehicle.model, "\n\tEuro / KM:", round(vehicle.price/vehicle.range))</code></pre><p></p><p>Here are the pyo3 docs:</p><p><a href="https://docs.rs/pyo3/0.7.0/pyo3/index.html">https://docs.rs/pyo3/0.7.0/pyo3/index.html</a></p>]]></content:encoded></item><item><title><![CDATA[AC1200 wireless drivers]]></title><description><![CDATA[Soatasoa 1200M 8812BU]]></description><link>http://schdbr.de/ac1200-wireless-drivers/</link><guid isPermaLink="false">5c0f8a582c7ca7516bdde3ea</guid><dc:creator><![CDATA[Johann Woelper]]></dc:creator><pubDate>Tue, 11 Dec 2018 10:05:56 GMT</pubDate><content:encoded><![CDATA[<p></p><p>This is geared towards gentoo but should work in every system if you have your kernel sources available.</p><p>If you come across the notorious hard-to-install AC1200 USB wifi devices and want to get them to work with linux, here is how it goes:</p><p>The chipset is a bit of a mystery, this is what lsusb says:</p><pre><code>  idVendor           0x0bda Realtek Semiconductor Corp.
  idProduct          0xb812 
  bcdDevice            2.10
  iManufacturer           1 Realtek
  iProduct                2 USB3.0 802.11ac 1200M Adapter
  iSerial                 3 123456</code></pre><p>It's actually a 8812BU chipset from realtek. It will not work with a stock kernel and the available drivers usually do not work with a recent kernel (I use <code>4.19.8-gentoo</code>)</p><p>Make sure you have the kernel sources for your current kernel and <code>/usr/src/linux/</code> points to your current kernel.</p><p>You will need to clone the following repo:</p><pre><code>git clone https://github.com/cilynx/rtl88x2BU_WiFi_linux_v5.2.4.4_26334.20180126_COEX20171012-5044
cd trl88x*
make
make install</code></pre><p>You can test it without restarting if you <code>modprobe 88x2bu</code>. <code>dmesg</code> should show that a new network device was added.</p>]]></content:encoded></item><item><title><![CDATA[Image compression]]></title><description><![CDATA[<p>Some recipes for reducing disk size of images</p><p></p><p>PNG, lossy: </p><p><code>pngquant -f -v --ext .png --quality 70-100 --speed 2 --skip-if-larger FILE.png</code></p><p>speed: default 3, 1-11, more is less quality and faster processing<br>quality is the target quality to aim for</p><p>PNG, lossless (also, as a post-pass on the lossless</p>]]></description><link>http://schdbr.de/image-compression/</link><guid isPermaLink="false">5bc452f72c7ca7516bdde3de</guid><dc:creator><![CDATA[Johann Woelper]]></dc:creator><pubDate>Mon, 15 Oct 2018 08:53:32 GMT</pubDate><content:encoded><![CDATA[<p>Some recipes for reducing disk size of images</p><p></p><p>PNG, lossy: </p><p><code>pngquant -f -v --ext .png --quality 70-100 --speed 2 --skip-if-larger FILE.png</code></p><p>speed: default 3, 1-11, more is less quality and faster processing<br>quality is the target quality to aim for</p><p>PNG, lossless (also, as a post-pass on the lossless png)</p><p><code>optipng -o7 FILE.png</code></p><p>-oN: 7 is the slowest and the smallest, usually <code>-o3</code> is a good tradeoff.</p><p>JPG, lossy: <br><code>find . -name "*.jpg" | xargs jpegoptim -m 80 -t</code></p><p>JPG, lossless:</p><p><code>find . -name "*.jpg" | xargs jpegoptim -t</code></p>]]></content:encoded></item><item><title><![CDATA[Git]]></title><description><![CDATA[<h4 id="betteroverview">Better overview:</h4>
<p>Who touched what files and when?<br>
<code>git log --name-status</code><br>
What was my last commit again? I don't see it with <em>git status</em> anymore...<br>
<code>git show --name-status</code></p>
<p>You can put these and others into shortcuts in your <code>~/.gitconfig</code>:</p>
<pre><code>[alias]
    co = checkout
    ci = commit
    br = branch
    hist = log --pretty=format:</code></pre>]]></description><link>http://schdbr.de/git/</link><guid isPermaLink="false">5b9fb31e4ec242211f2d3e42</guid><dc:creator><![CDATA[Johann Woelper]]></dc:creator><pubDate>Mon, 20 Aug 2018 14:47:43 GMT</pubDate><content:encoded><![CDATA[<h4 id="betteroverview">Better overview:</h4>
<p>Who touched what files and when?<br>
<code>git log --name-status</code><br>
What was my last commit again? I don't see it with <em>git status</em> anymore...<br>
<code>git show --name-status</code></p>
<p>You can put these and others into shortcuts in your <code>~/.gitconfig</code>:</p>
<pre><code>[alias]
    co = checkout
    ci = commit
    br = branch
    hist = log --pretty=format:\&quot;%h %ad | %s%d [%an]\&quot; --graph --date=short --name-status
    lg = log --name-status
    p = pull
    f = fetch
[core]
    excludesfile = /Users/you/.gitignore_global
    editor = vim
</code></pre>
<h4 id="inversegitignore">Inverse .gitignore:</h4>
<p>sometimes (as in managing my home directories' config files) i just want to track specific files. Here's the trick:</p>
<pre><code># ignore everything
*
# add stuff to track
!.vim/
!.bashrc
!some_pattern*
# aand of course...
!.gitignore
</code></pre>
<h4 id="merging">Merging</h4>
<p><code>git merge -Xignore-all-space</code> might be helpful sometimes</p>
<h4 id="miscstuff">Misc stuff</h4>
<p>These are probably known to most if you use git, but it might be helpful as a primer for some.</p>
<h6 id="branchrelated">Branch related</h6>
<p>Create a new branch<br>
<code>git checkout -b &lt;branchName&gt;</code></p>
<p>If you want to push this to a remote, making it available to others:<br>
<code>git push -u origin &lt;branchName&gt;</code></p>
<p>Delete local branch<br>
<code>git branch -D bugfix</code></p>
<p>Delete remote branch<br>
<code>git push origin --delete &lt;branchName&gt;</code></p>
<h6 id="configrelated">Config related</h6>
<p>Set editor<br>
<code>git config --global core.editor &quot;vim&quot;</code><br>
(see above for more)</p>
]]></content:encoded></item><item><title><![CDATA[Rust cookbook]]></title><description><![CDATA[<p>Some findings and notes about using rust on some real-world stuff</p>
<h3 id="handlingjson">Handling JSON</h3>
<p>A small example how to dump your struct to a file and read it again.</p>
<p>Cargo.toml:</p>
<pre><code>[dependencies]
serde = { version = &quot;1.0&quot;, features = [&quot;derive&quot;] }
serde_json = &quot;1.0&quot;
</code></pre>
<pre><code>use serde::{Serialize,</code></pre>]]></description><link>http://schdbr.de/rust-cookbook/</link><guid isPermaLink="false">5b9fb31e4ec242211f2d3e52</guid><dc:creator><![CDATA[Johann Woelper]]></dc:creator><pubDate>Tue, 24 Jul 2018 09:56:40 GMT</pubDate><content:encoded><![CDATA[<p>Some findings and notes about using rust on some real-world stuff</p>
<h3 id="handlingjson">Handling JSON</h3>
<p>A small example how to dump your struct to a file and read it again.</p>
<p>Cargo.toml:</p>
<pre><code>[dependencies]
serde = { version = &quot;1.0&quot;, features = [&quot;derive&quot;] }
serde_json = &quot;1.0&quot;
</code></pre>
<pre><code>use serde::{Serialize, Deserialize};
use serde_json;
use std::io::BufWriter;
use std::io::BufReader;
use std::fs::File;

#[derive(Serialize, Deserialize, Debug)]
enum CarClass {
    Race,
    Offroad,
    Hover
}

#[derive(Serialize, Deserialize, Debug)]
struct Car {
    maxspeed: f64,
    weight: f64,
    class: CarClass
}

fn main() {
    let new_car = Car {
        maxspeed: 120.0,
        weight: 4000.0,
        class: CarClass::Offroad
        };
    
    // write out the file
    let writer = BufWriter::new(File::create(&quot;car.json&quot;).unwrap());
    serde_json::to_writer_pretty(writer, &amp;new_car).unwrap();

    // read it back again
    let reader = BufReader::new(File::open(&quot;car.json&quot;).unwrap());
    let loaded_car: Car = serde_json::from_reader(reader).unwrap();
    println!(&quot;{:?}&quot;, loaded_car);
}
</code></pre>
<h3 id="safelyreadingjson">Safely reading JSON</h3>
<p>Let's revisit the above example and see how we can ditch the <code>unwrap()</code>s.</p>
<p>let's look at this line:</p>
<pre><code>let loaded_car: Car = serde_json::from_reader(reader).unwrap();
</code></pre>
<p>we could break this up of course. The challenge is that we need to tell serde exaclty what to expect so it can deserialize the data properly. All we really know is that we get a result, and there should be a <code>Car</code> in it. So let's just put the <code>_</code> as a placeholder in there (a.k.a. I don't care, please figure it out for me)</p>
<pre><code>let loaded_car: Result&lt;Car, _&gt; = serde_json::from_reader(BufReader::new(&amp;open_file));
</code></pre>
<p>Nice! But what if we want to go more functional and not store any intermediate variables?</p>
<p>We'll just apply what we learned using the turbofish (<a href="https://techblog.tonsser.com/posts/what-is-rusts-turbofish">https://techblog.tonsser.com/posts/what-is-rusts-turbofish</a>):</p>
<pre><code>match serde_json::from_reader::&lt;_, Car&gt;(BufReader::new(open_file)) {...}
</code></pre>
<p>See the example in action:</p>
<pre><code>#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
use std::io::BufWriter;
use std::io::BufReader;
use std::fs::File;

#[derive(Serialize, Deserialize, Debug)]
enum CarClass {
    Race,
    Offroad,
    Hover
}

#[derive(Serialize, Deserialize, Debug)]
struct Car {
    maxspeed: f64,
    weight: f64,
    class: CarClass
}

fn main() {

    match File::open(&quot;car.json&quot;) {
        Ok(open_file) =&gt; {
            match serde_json::from_reader::&lt;_, Car&gt;(BufReader::new(open_file)) {
                Ok(car) =&gt; println!(&quot;{:?}&quot;, car),
                Err(e) =&gt; println!(&quot;{:?}&quot;,e)
            }
        },
        Err(e) =&gt; println!(&quot;{:?}&quot;,e)
    }


</code></pre>
<h3 id="iteratefolder">Iterate folder:</h3>
<p><a href="https://doc.rust-lang.org/std/fs/fn.read_dir.html">https://doc.rust-lang.org/std/fs/fn.read_dir.html</a></p>
<pre><code>use std::io;
use std::fs::{self, DirEntry};
use std::path::Path;


fn iterate_path(dir: &amp;Path, cb: &amp;Fn(&amp;DirEntry)) -&gt; io::Result&lt;()&gt; {
    if dir.is_dir() {
        for entry in fs::read_dir(dir)? {
            let entry = entry?;
            let path = entry.path();
            if path.is_dir() {
                visit_dirs(&amp;path, cb)?;
            } else {
                cb(&amp;entry);
            }
        }
    }
    Ok(())
}
</code></pre>
<h4 id="orwalkdir">or walkdir:</h4>
<pre><code>[dependencies]
walkdir = &quot;2&quot;
</code></pre>
<pre><code>extern crate walkdir
use walkdir::WalkDir;

for entry in WalkDir::new(&quot;foo&quot;) {
    dbg!(entry);
}
</code></pre>
<h3 id="argumentparsingwithclap">Argument parsing with <code>clap</code></h3>
<pre><code>[dependencies]
clap = &quot;2&quot;
</code></pre>
<pre><code>extern crate clap;
use clap::{Arg, App, SubCommand};

fn main() {
    let matches = App::new(&quot;myapp&quot;)
                          .version(&quot;0.1&quot;)
                          .arg(Arg::with_name(&quot;dir&quot;)
                               .value_name(&quot;DIRECTORY&quot;)
                               .help(&quot;Sets a starting directory&quot;)
                               .takes_value(true)
                               .required(true)
                          )
                          .get_matches();
    
    let dir  = matches.value_of(&quot;dir&quot;).unwrap();
    println!(&quot;Value for root: {}&quot;, dir);

}
</code></pre>
<pre><code>cargo run -- somedir
</code></pre>
<h3 id="xml">XML</h3>
<pre><code>use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use treexml::Document;

   
match File::open(&quot;yo.xml&quot;) {
    Ok(f) =&gt; {
        let mut buf_reader = BufReader::new(f);
        let doc = Document::parse(buf_reader).unwrap();
    },
    Err(_e) =&gt; ()
}


</code></pre>
<h3 id="runsystemcommand">Run system command</h3>
<pre><code>use std::process::Command;

let output = 
Command::new(&quot;ls&quot;)
        .args(&amp;[&quot;-l&quot;, &quot;-R&quot;])
        .output()
        .expect(&quot;failed to execute process&quot;);
let res = output.stdout;
println!(&quot;{:?}&quot;, res);

</code></pre>
<h3 id="gracefullyhandlingoptionsandresultsiniterators">Gracefully handling Options and Results in iterators</h3>
<pre><code>fn main() {
    let animals = vec![Some(&quot;Bear&quot;), Some(&quot;Dog&quot;), None, Some(&quot;Cat&quot;)];
    let valid_animals = animals.iter().flat_map(|x| x).collect::&lt;Vec&lt;_&gt;&gt;()
}
</code></pre>
<h3 id="parsestringtotype">Parse string to type</h3>
<pre><code>let i = String::from(&quot;42&quot;).parse::&lt;i32&gt;().unwrap();
// or let the compiler figure that out from annotating the variable
let i: i32 = String::from(&quot;42&quot;).parse().unwrap();
</code></pre>
<h3 id="defaultsforstructs">Defaults for structs</h3>
<p>Derive from Default is the easiest:</p>
<pre><code>#[derive(Default)]
struct Animal {
    hitpoints: i32,
    speed: f64,
    weight: f64
}
fn main() {
    // use all defaults
    let snake = Animal::default();
    //just specify one, use Default for everything else
    let birdy = Animal {
        hitpoints: 500,
        ..
        Default::default()
    };
}
</code></pre>
<p>If you want to have hand-crafted defaults, you need to impl your own Default:</p>
<pre><code>struct Animal {
    hitpoints: i32,
    speed: f64,
    weight: f64
}

impl Default for Animal {
    fn default () -&gt; Animal {
        Animal{hitpoints: 500, speed: 3.141, weight: 55.5}
    }
}

fn main() {
    let snake = Animal::default();
}
</code></pre>
<h2 id="buildinggotchasandcargostuff">Building gotchas and Cargo stuff</h2>
<h3 id="osxrpath">OSX @rpath</h3>
<p>you can use <code>install_name_tool</code> to add a relative library search path to your executable like that:<br>
<code>install_name_tool -add_rpath @executable_path/. your_binary</code><br>
in case you are using a gui library like libui you can then bundle the libui.A.dylib with your app bundle.<br>
<code>cargo bundle</code> is recommended for packaging the actual app.</p>
<h3 id="createmultiplebinaries">create multiple binaries</h3>
<p>Let's say you want a GUI app and one for the command line that has minimal size and dependencies. All you need to do is the following in your <code>Cargo.toml</code>:</p>
<pre><code>[[bin]]
name = &quot;cli&quot;
path = &quot;src/cli.rs&quot;

[[gui]]
name = &quot;cli&quot;
path = &quot;src/gui.rs&quot;
</code></pre>
<p><code>cargo build</code> will then build both. Run the binary of your choice with <code>cargo run --bin cli</code>.</p>
<h3 id="windowsprogramswithoutaconsolewindow">Windows programs without a console window</h3>
<pre><code>#![windows_subsystem = &quot;windows&quot;]
</code></pre>
<p>If you use this in your crate root, no console window will be shown if you run the resulting executable.</p>
<h3 id="gitdependencies">Git dependencies</h3>
<pre><code>[dependencies]
rand = { git = &quot;https://github.com/rust-lang-nursery/rand&quot; }
</code></pre>
<p>But what if your repo is private? <code>Relative url without a base</code>?<br>
First: if you are cloning with ssh, use the appropriate protocol and use an absolute-style url - github will accept replacing <code>:</code> with a <code>/</code>:</p>
<pre><code>[dependencies]
rand = { git = &quot;ssh://git@github.myorg.com/myuser/myrepo.git&quot; }
</code></pre>
<p>In order for this to work, <code>.cargo/config</code> needs to specify</p>
<pre><code>[net]
git-fetch-with-cli = true
</code></pre>
<p>This file can be in your <code>~</code> home dir or in the project itself which makes sense if other people want to build your project.</p>
]]></content:encoded></item><item><title><![CDATA[Powershell]]></title><description><![CDATA[<p>Edit the configuration</p>
<pre><code>If ((Test-Path $Profile) -eq &quot;True&quot;) {Notepad $Profile}
</code></pre>
<p>(create one)</p>
<pre><code>New-Item -path $profile -type file -force
</code></pre>
<p>oh-my-posh (<a href="https://github.com/JanDeDobbeleer/oh-my-posh">https://github.com/JanDeDobbeleer/oh-my-posh</a>) is useful, together with posh-git.<br>
in a nutshell:</p>
<pre><code>Install-Module posh-git -Scope CurrentUser
Install-Module oh-my-posh -Scope CurrentUser
</code></pre>
<p>Add this to your profile to activate it:</p>]]></description><link>http://schdbr.de/powershell/</link><guid isPermaLink="false">5b9fb31e4ec242211f2d3e51</guid><dc:creator><![CDATA[Johann Woelper]]></dc:creator><pubDate>Tue, 17 Jul 2018 13:35:30 GMT</pubDate><content:encoded><![CDATA[<p>Edit the configuration</p>
<pre><code>If ((Test-Path $Profile) -eq &quot;True&quot;) {Notepad $Profile}
</code></pre>
<p>(create one)</p>
<pre><code>New-Item -path $profile -type file -force
</code></pre>
<p>oh-my-posh (<a href="https://github.com/JanDeDobbeleer/oh-my-posh">https://github.com/JanDeDobbeleer/oh-my-posh</a>) is useful, together with posh-git.<br>
in a nutshell:</p>
<pre><code>Install-Module posh-git -Scope CurrentUser
Install-Module oh-my-posh -Scope CurrentUser
</code></pre>
<p>Add this to your profile to activate it:</p>
<pre><code># Import-Module posh-git
Import-Module oh-my-posh
# Set-Theme Paradox
# Speed up large repos
$GitPromptSettings.EnableFileStatus = $false
</code></pre>
<p>Some useful settings:</p>
<pre><code>function f_timer($program) {
    $allArgs = $PsBoundParameters.Values + $args
    $sw = [Diagnostics.Stopwatch]::StartNew();
    iex &quot;$allArgs&quot;;
    $sw.Stop();
    $sw.Elapsed;
}

Set-Alias which where
Set-Alias time f_timer
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Procedural city doodles]]></title><description><![CDATA[<p>This is a sketchbook for some work done for this demo:<br>
<a href="https://www.kdab.com/lots-lights-generating-cities/">https://www.kdab.com/lots-lights-generating-cities/</a></p>
<p>Any 2d shape produces a house according to ajustable rules. This can form the basis for further refinements and customization.<br>
<img src="http://schdbr.de/content/images/2017/08/city2.png" alt="city2"><br>
<img src="http://schdbr.de/content/images/2017/08/city3.png" alt="city3"><br>
No city without a tilt shift shot:<br>
<img src="http://schdbr.de/content/images/2017/09/Screenshot-from-2017-09-05-14-04-15.png" alt="Screenshot-from-2017-09-05-14-04-15"></p>
<p><img src="http://schdbr.de/content/images/2017/08/houses.gif" alt="houses"><br>
Previz level<br>
<img src="http://schdbr.de/content/images/2017/08/city5.jpg" alt="city5"></p>]]></description><link>http://schdbr.de/procedural-city-doodles/</link><guid isPermaLink="false">5b9fb31e4ec242211f2d3e50</guid><dc:creator><![CDATA[Johann Woelper]]></dc:creator><pubDate>Mon, 05 Mar 2018 14:55:22 GMT</pubDate><media:content url="http://schdbr.de/content/images/2018/03/Screenshot-from-2017-09-05-14-04-15.png" medium="image"/><content:encoded><![CDATA[<img src="http://schdbr.de/content/images/2018/03/Screenshot-from-2017-09-05-14-04-15.png" alt="Procedural city doodles"><p>This is a sketchbook for some work done for this demo:<br>
<a href="https://www.kdab.com/lots-lights-generating-cities/">https://www.kdab.com/lots-lights-generating-cities/</a></p>
<p>Any 2d shape produces a house according to ajustable rules. This can form the basis for further refinements and customization.<br>
<img src="http://schdbr.de/content/images/2017/08/city2.png" alt="Procedural city doodles"><br>
<img src="http://schdbr.de/content/images/2017/08/city3.png" alt="Procedural city doodles"><br>
No city without a tilt shift shot:<br>
<img src="http://schdbr.de/content/images/2017/09/Screenshot-from-2017-09-05-14-04-15.png" alt="Procedural city doodles"></p>
<p><img src="http://schdbr.de/content/images/2017/08/houses.gif" alt="Procedural city doodles"><br>
Previz level<br>
<img src="http://schdbr.de/content/images/2017/08/city5.jpg" alt="Procedural city doodles"></p>
]]></content:encoded></item><item><title><![CDATA[web.py  and wscgi]]></title><description><![CDATA[<p>After tinkering, you might want to make your app a bit more production ready and/or make it start when the system boots.</p>
<p>Although it is very handy to have it run on a local port, using WSCGI and apache makes it straightforward to do just that. There are a</p>]]></description><link>http://schdbr.de/web-py-and-wscgi/</link><guid isPermaLink="false">5b9fb31e4ec242211f2d3e4f</guid><dc:creator><![CDATA[Johann Woelper]]></dc:creator><pubDate>Tue, 26 Dec 2017 23:13:50 GMT</pubDate><content:encoded><![CDATA[<p>After tinkering, you might want to make your app a bit more production ready and/or make it start when the system boots.</p>
<p>Although it is very handy to have it run on a local port, using WSCGI and apache makes it straightforward to do just that. There are a few gotchas though:</p>
<p>(this is on ubuntu 16.04, but it should apply to most OSes)</p>
<p>apt-get install libapache2-mod-wsgi</p>
<p>in /etc/apache2/sites-available:<br>
vi subdomain.domain.com.conf</p>
<pre><code>&lt;VirtualHost *:80&gt;
        ServerAdmin you@whatnot.com
        WSGIScriptAlias / /var/www/yourapp/app.py/
        AddType text/html .py
        ServerName subdomain.domain.com

        ErrorLog ${APACHE_LOG_DIR}/error_myapp.log
        CustomLog ${APACHE_LOG_DIR}/access_myapp.log combined
&lt;/VirtualHost&gt;
</code></pre>
<p>then a2ensite subdomain.domain.com<br>
and reload apache.</p>
<p>in python:</p>
<pre><code>application = web.application(urls, globals()).wsgifunc()
</code></pre>
<p>please note that <code>application</code> must appear exactly as above, you can't name it anything else.</p>
<p>since apache does not allow you to <code>import MyModule</code> directly, you need to add it like this (assuming it's in the same folder as your app)</p>
<pre><code>import os
import sys
CURDIR = os.path.dirname(__file__)
sys.path.append(CURDIR)
import MyModule
</code></pre>
<p>--- also please see <a href="http://webpy.org/cookbook/mod_wsgi-apache-ubuntu">http://webpy.org/cookbook/mod_wsgi-apache-ubuntu</a></p>
]]></content:encoded></item></channel></rss>