Hans Dulimarta

ThreeJS and Yo

Introduction

ThreeJS is a famous library for developing OpenGL programs that run on a web-browser. We generally call them WebGL programs. WebGL and OpenGL ES are both designed based on OpenGL, with redundant APIs removed. ThreeJS itself is built on top of WebGL.

Pre-requisite Steps

  1. Install MinGW (at least you are able to run mingw32-make)
  2. Install Git
  3. Install Python 2.7. Edit your PATH (environment variable) to make sure your can run python from the command prompt
  4. Install Node.js (a run-time environment for running Javascript programs outside of a web browser)
    • Windows Users: you will get an MSI installer
    • Linux users: you will get a .tar.gz file
    • OSX user: you will get a .pkg file
  5. Install YeoMan (web app generator)

    npm install -g global yo bower grunt-cli

    Linux/OSX users may have to run the above command as a super user using sudo.

    sudo npm install -g global yo bower grunt-cli

  6. Install ThreeJS generator

    npm install -g generator-threejs-boilerplate

YeoMan has the following dependencies:

  • bower (package manager)
  • grunt (build system: similar to make, ant, cmake, gradle, …)

Create a ThreeJS webapp

1
2
3
mkdir SampleProject
cd SampleProject
yo threejs-boilerplate

Running the WebApp

1
2
mingw32-make server    # for Windows users
make server            # for Linux/OSX users

Use your Web browser to visit localhost:8000, you should see a spinning cube.

Upgrade ThreeJS

If the local copy of your three.js installed by YeoMan is not the latest revision (you can check it by peeking into vendor/three.js/build/three.js), upgrade to the latest copy (as of March 2015, the latest revision is r70):

bower install threejs

The above command should install the latest copy of threejs under bower_components/threejs/build. To use the updated copy, edit the <script> tag of your index.html from

<script scr="vendor/three.js/build/three.js">

to

<script scr="bower_components/threejs/build/three.js">

The alternate file three.min.js in the same directory is a minified version of three.js. Minified Javascript files are not human readable, unnecessary white spaces are removed, and function names are transcribed to short names (only a few letters). To help debugging rendering problems, we want to use the non-minified version.

Edit the Code

There are several well-known IDEs for Javascript programs (in alphabetical order): Komodo, NetBeans, Notepad++, Sublime Text, Visual Studio, WebStorm, and we have a site license for WebStorm.

A quick browse through the generated code in index.html shows that ThreeJS objects are created by using the new THREE.____ constructor calls:

1
2
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera (45, window.innerWidth / window.innerHeight, 1, 250);

For a complete description of three.js classes, refer to its online documentation. A typical WebGL program uses the following classes:

  • PerspectiveCamera
  • Geometry (BoxGeometry, CubeGeometry, …)
  • PointLight, DirectionalLight, SpotLight
  • MeshBasicMaterial, MeshPhongaterial
  • Vector3, Vector4, Matrix4
  • Mesh
  • WebGLRenderer
  • Scene

Stop the Spinning Cube

If the spinning cube becomes too dizzy to watch, you can stop it by commenting out one of the functions that gets pushed into onRenderFcts array. This array holds all the functions that are invoked by the render “loop” (towards the end of index.html). You will find three functions that are pushed onto the onRenderFcts array:

  1. A function to rotate the cube
  2. A function to change the camera position
  3. A function that renders the graphics

The autogenerated code in index.html can be organized into the following groups:

  1. WebGL setup
  2. Camera, Lighting, and Scene setup
  3. 3D model setup
  4. User interaction handlers (event listeners)
  5. The render “loop”

Mesh: Geometry + Material

In order to render a simple 3D object using Three.js, we have create a Mesh, which in turn requires Geometry and Material. For instance, the cube was created by the following code snippet:

1
2
3
var geometry = new THREE.CubeGeometry (1, 1, 1);
var material = new THREE.MeshPhongMaterial();
var mesh     = new THREE.Mesh (geometry, material);

and to show the cube on your graphics, it must be placed on your scene:

1
scene.add (mesh)

Polymerization

Let’s talk about polymerization.

No, not that one, but this one: a new approach in web app design using programmable and customizable components.

My journey into Polymer began immediately after Google IO 2014 when I learned more about Polymer from the following sessions:

After I was convinced that polymerizing an old web page is relatively easy, I began revamping one of my old AJAX-based Java Examples pages to switch over to Polymer.

The new design looks much nicer (I think) and requires only 20% as much code.

The entire page uses core-drawer-panel as its layout to host the following two customized Polymer elements: * hans-filelist, hosted in the navigation panel, that updates the list of files based on the text input search argument * hans-syntax-hilite, hosted in the main panel, that renders the selected source code

The file-list Polymer component uses core-ajax, core-input, core-field, and core-list. The syntax-hilite element is built on top of core-header-panel and core-toolbar.

Event Handling

To synchronize the contents of the main panel (on the right) and the navigation panel (on the left) the on-core-activate event handler of core-list uses core-ajax element to load the selected file and then fires a file-selected event. The corresponding handler in the syntax-hilite component then renders a syntax highlighted code on the main panel.

My old Java examples page uses Geshi (PHP) for syntax highlighting, but swithing over to Polyer requires me to find a Javascript-based highlighter. After some net shopping, I decided to use highlightjs.org.

Android ProgressDialog With Delay

A progress dialog gives a visual feedback to a user who is waiting for a relatively long task to complete. When the task involves retrieving external data from the network, the completion time can be unpredictable and it may vary significantly. On the extreme case when the task finishes in a blink of an eye, it may be unnecessary to show the progress dialog altogether.

The current set of Android widgets does not provide an easy way to postpone displaying a dialog, a feature that can be useful to selectively show a dialog only when the task may potentially require longer time to complete. Combining this feature with Android AsyncTask, a progress dialog that provides a “showAfter(millisecond_delay)” functionally can be used as follow:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void onPreExecute()
{
    /* 800 msec delay */
    progress = DelayedProgressDialog.show (..., 800);
}

void doInBackground(....)
{

}

void onPostExecute(Void unused)
{
    if (progress.isShowing())
        progress.dismiss();
    progress.cancel();  /* remove the dialog */
}

In the above hypothetical example, the dialog will show up approximately 800msec after it is built. When the background task finished in less than 800 ms, the dialog will never show up.

Implementing the Code

The following class inherits the ProgressDialog class and defines a static show() method (similar to that of ProgressDialog except with a fourth parameter to control the millisecond delay before the dialog actually appears). The delayed appearance of the dialog is handled by the Handler#postDelayed method.

When the dialog is not needed anymore, its cancel() method can be invoked, thus removing it from the Handler’s message queue.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class DelayedProgressDialog extends ProgressDialog {
    private static Handler dialogHandler;
    private Runnable runner;

    static {
        dialogHandler = new Handler();
    }

    public DelayedProgressDialog (Context c)
    {
        super (c);
    }

    public static ProgressDialog show (Context c,
        CharSequence title, CharSequence msg,
        long delayMilliSec)
    {
        final DelayedProgressDialog pd = new DelayedProgressDialog(c);
        pd.setTitle (title);
        pd.setMessage (msg);
        pd.setCancelable (true);
        pd.runner = new Runnable() {

            public void run() {
                try {
                    pd.show();
                }
                catch (Exception e) {
                    /* do nothing */
                }
            }
        };
        dialogHandler.postDelayed (pd.runner, delayMilliSec);
        return pd;
    }

    @Override
    public void cancel()
    {
        dialogHandler.removeCallbacks (runner);
        super.cancel();
    }
}

The sample Android code can be viewed on my GitHub Gists

Android Maps API V2

I recently updated one of my Android apps to use the Android Maps API v2. The modifications required to the code base go beyond changing packages from com.google.android.maps to com.google.android.gms.maps. With the Maps client being part of the Google Play Services, any Android apps that use Google Maps v2 must be setup to use the Google Play Services library. In addition, the may also use a few utilities from the Android Maps Utility library.

The Google Play Services Setup instructions for installing the library on Eclipse, Android Studio (or gradle-based IntelliJ), but for IntelliJ users who transition from Eclipse, the instructions lack some details.

See the details in the video below:

Octopress Rsync

When I first installed Octopress in May 2013 it was configured for “subdirectory deployment”: both my Octopress installation directory and HTTP publishing reside on the same server (our school server (http://www.cis.gvsu.edu).

Today, I decided to migrate the Octopress installation directory to my Mac. The easiest part of this migration is running git clone from the command line. The more challenging task is reconfiguration of the Octopress installation directory. I spent a whole evening figuring out all the details it is done correctly.

Using the instructions provided by Belyamani, I installed rvm and Ruby

1
2
3
4
5
rvm --create use 2.1.0@octopress
rvm use 2.1.0@octopress
cd /path/to/my/octopress/dir
gem install bundler
bundle install

Later on, I also installed POW to allow me preview the generated site locally.

Failed Reconfiguration Attempt

  • Because we run rake to do many different Octopress tasks, the first file I changed was Rakefile. Failing to understand how Compass, Jekyll, and Rackup work together, I also attempted to update value in the public_dir variabe, but later found out that Rackup was not able to render the page contents correctly.

  • I also tinkered with _config.yml and changed the settings of source and destination. Later on, after reading the Rakefile, I learned that Jekyll’s configuration settings are defined in this file. Jekyll’s reads its input from the directory given as source and generates its output into a directory given as destination

  • The next file I attempted to modify was config.rb, the configuration file for Compass (SASS to CSS compiler). At first, I did not understand the differences between the http_xxxx_path and zzzz_dir variables. Compass Style Configuration Reference helps me understand these two groups of variables.

  • The fourth file is config.ru, Rackup configuration file. I did not change anything in this file. Nevertheless, I learned that using the default setting, Rackup server will render the contents of public directory

Interconnections

Now I understand that Octopress relies on the following four utilities:

  1. Compass, a SASS to CSS compiler that reads its input from sass and generates stylesheets into source/stylesheets. Related config.rb variables: sass_dir and css_dir
  2. Jekyll then reads the contents of source and generates the HTML files into public. Related _config.yml variables: source and destination.
  3. Rackup renders the HTML contents locally by reading its input from public. Related config.ru variables: none. The ‘public’ directory is hardcoded into the code.
  4. When we deploy the site to the remote server, rsync transfers the contents in the public directory. Related Rakefile variables: source_dir and public_dir

During this time, I also learned the powerful feature of rake set_root_dir that allows me to switch my deployment/publishing destination from the command line.

1
2
3
4
5
rake set_root_dir[~dulimarh/Oktopus]
# The current URI of my local contents on POW is http://octopress.dev/~dulimarh/Oktopus
rake deploy
rake set_root_dir[/]
# The current URI of my local contents on POW is http://octopress.dev/

Summary of Changes

FileVariableValue
config.rb http_path /~dulimarh/Okto
http_images_path http_path + "images"
sass_dir sass
css_dir public/stylesheets
images_dir source/images
_config.yml root /~dulimarh/Okto
source source
destination public
Rakefile ssh_user myusername@hostname.cis.gvsu.edu
document_root ~/public_html/Okto
rsync_delete true
rsync_args --verbose --progress

C++ Move Semantics

I received the following email from a student: > I’m getting an infinite loop on the following code. It keeps going between these two functions whenever I try to assign a RationalNumber to another (and then crashes). I don’t see where the infinite copying is happening.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* copy constructor */
RationalNumber::RationalNumber (const RationalNumber&amp; num)
{
    numerator = num.numerator;
    denominator = num.denominator;
}

/* copy assignment */
RationalNumber&amp; RationalNumber::operator= (const RationalNumber& num)
{
    RationalNumber tmp{num};  // invoke lines 2-6 above
    std::swap (tmp, *this);

    return *this;
}

When we try to assign r1 to r2 in the following code

1
2
3
4
RationalNumber r1;         // this line invokes a constructor with no args
RationalNumber r2{15, 27}; // this line invokes a constructor with 2 args

r1 = r2;    // this line invokes the copy assignment at lines 9-19 above

Recall that a typical swap (x,y) requires a third (local) variable and the entire operation translates to the following sequence that requires one clone constructor and two assignments:

1
2
3
TypeOfX aux {x};    // optimized for "move" clone
x = y;              // optimized for "move" assign
y = aux;            // optimized for "move" assign

When possible std::swap will attempt to use the move clone constructor and move assignment (to avoid copying overhead). However, when RationalNumber provides neither “move constructor” nor “move assignment”, std::swap will fall back to the copy constructor and copy assignment. The latter invocation results in an infinite chain of recursive calls. (The std::swap call at line 12 attempts to make a recursive call to the copy assignment at line 9).

Safari Technical Books

One of the databases in the GVSU Library collection is the Safari Technical Books. You can select various titles from a large collection of electronic textbooks.

Once you are connected to the Safari Technical Books site, browse and select one of the categories.

One of the books on C++ is authored by Bjarne Stroustrup, the father of C++. The "Tour of C++" sections covered in chapters 2-5 give an overview the the (new) C++11 features.

Using C99 Standard

On Eclipse

  1. Right click on your project
  2. Select Properties
  3. Follow the steps in the following screenshot

On Codeblocks

On Xcode

Unbuffered I/O

One student sent me the following email and my response is posted below his email.

Dr. Dulimarta,

Greetings! I am in your EGR261 class this summer. I wanted to let you know I searched online and found a great fix for the printf issue we’ve been having with Eclipse in Windows.

The issue is automatically resolved when these two lines are added at the beginning of the main function:

1
2
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);

The nice thing about this method is that it does not require the fflush line after every printf for it to show in the console. Perhaps you’d like to add it to your arsenal of fixes for this problem, if it wasn’t already on your radar.

I hope you are having a great week. See you in class Thursday!

Dave

I just want to make sure you know when [not] to use the above technique. The two calls above disable output buffering on stdout and stderr.

I/O operations are several order of magnitude slower than other operations on your computer. To improve the performance, we use buffers to temporarily hold the data before they are actually delivered to the output device.

Let’s say your program is about to print a 413-character message to stdout.

  • Without using an output buffer, your program will perform 413 I/O calls to print the message one character at a time.
  • Using an output buffer, your program will perform only ONE I/O call to transfer the entire 413 characters as a group.