C++: Hash function for Eigen matrix and vector

If you use Eigen library and C++11 a lot, especially std::unordered_map, you may want to use matrix or vector of Eigen library as key. I encountered this case when I implemented spatial hashing that boosts the performance of collision detection. It requires a hash table that maps integer indices (i, j, k) to a list of vertices and faces in the cell. I picked Eigen::Vec3i type to store three integer indices because it makes other computations easy. Here is the declaration of the unordered map I used.

/* Index of cell -> vertices in the cell. */
unordered_map<Vec3i, vector::<Vertex*>, matrix_hash<Vec3i>> spatial_hashing;

As you can see, I needed to find out what hash function would be good for three ordered integers first to use std::unordered_map as my hash table implementation. I googled it and found several solutions. Among them I’m going to show you one that I think most versatile because you can apply it to Eigen matrix and vector of any length, not only one-by-three. Here is the definition of the hash function matrix_hash, and please let me know if you think there is a better solution!

// Hash function for Eigen matrix and vector.
// The code is from `hash_combine` function of the Boost library. See
// http://www.boost.org/doc/libs/1_55_0/doc/html/hash/reference.html#boost.hash_combine .
template<typename T>
struct matrix_hash : std::unary_function<T, size_t> {
  std::size_t operator()(T const& matrix) const {
    // Note that it is oblivious to the storage order of Eigen matrix (column- or
    // row-major). It will give you the same hash value for two different matrices if they
    // are the transpose of each other in different storage order.
    size_t seed = 0;
    for (size_t i = 0; i < matrix.size(); ++i) {
      auto elem = *(matrix.data() + i);
      seed ^= std::hash<typename T::Scalar>()(elem) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
    }
    return seed;
  }
};
C++: Hash function for Eigen matrix and vector

NumPy: Concatenate three images (RGB) into one

Writing simple codes isn’t simple. Sometimes writing a very simple function costs you more time than a complex one because you think the code should be very concise considering its simple functionality, which is not always true. In my case this code was that sort of thing.

If you have three images representing three different channels (R, G, and B), you may want to concatenate those three 2D arrays into one 3D array to display or write to an image file. In NumPy, there is a simple way to do this as follows:

# Concatenate three (height, width)s into one (height, width, 3).
def concat_channels(r, g, b):
    assert r.ndim == 2 and g.ndim == 2 and b.ndim == 2
    rgb = (r[..., np.newaxis], g[..., np.newaxis], b[..., np.newaxis])
    return np.concatenate(rgb, axis=-1)
NumPy: Concatenate three images (RGB) into one

GL: How to capture OpenGL to video on the fly

If you write an OpenGL program, then there is a very high chance that you want to make the video of your OpenGL rendering to share. Usually, people make their program to write out every frame of the OpenGL rendering to files, and encode them to video afterwards. However, there is a way to save both time and space a lot with a minimal code change. Please see Real-Time Video Capture with FFmpeg by Miles Macklin for the details.

GL: How to capture OpenGL to video on the fly

Blender: Add same texture to all materials

If you are tired of adding the same texture to all materials one by one, the following Python script would save your time a lot. This script was tested in Blender 2.71.

import os
import bpy


# All the objects you want to add texture should have at least one material.
def add_envmap_texture_to_all_materials(img_fname):
    img_fname = os.path.expanduser(img_fname)
    try:
        cubemap_img = bpy.data.images.load(img_fname)
    except:
        raise IOError(&quot;Cannot load image %s&quot; % img_fname)

    cubemap_tex = bpy.data.textures.new('CubeMap', type='ENVIRONMENT_MAP')
    cubemap_tex.environment_map.source = 'IMAGE_FILE'
    cubemap_tex.image = cubemap_img
    cubemap_tex.use_mipmap = True
    cubemap_tex.use_mipmap_gauss = True

    for m in bpy.data.materials:
        t = m.texture_slots.create(1)  # Always add to slot #1.
        t.texture = cubemap_tex
        t.texture_coords = 'REFLECTION'


if __name__ == '__main__':
    add_envmap_texture_to_all_materials('~/Downloads/miramar.jpg')
Blender: Add same texture to all materials

Maya: Install NumPy on MayaPy

Here is a short bash script that you may use to install NumPy on Maya’s internal Python binary. If you want to use NumPy functions in Maya, this would be useful.

#!/usr/bin/env bash

# Before installing separate Python packages for MayaPy, check whether MayaPy just can use
# the system-wide packages in your `site-packages` directory. You can check it by
# inserting the following command in the beginning of your Python script for Maya.
#
# import site; site.addsitedir('/Library/Python/2.7/site-packages/')
#

MAYA_PATH=/Applications/Autodesk/maya2013/Maya.app/Contents/
EZ_SETUP_URL=https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py

wget -O /tmp/ez_setup.py $EZ_SETUP_URL --no-check-certificate
sudo $MAYA_PATH/bin/mayapy /tmp/ez_setup.py
sudo $MAYA_PATH/Frameworks/Python.framework/Versions/Current/bin/easy_install --upgrade numpy
Maya: Install NumPy on MayaPy