Reduce overdraw by hashing points.

This pull request reduces memory consumption on visualization of very large models by reducing the number of stored points and normals. ASM sends triangulated meshes that have duplicate face vertex coordinates and normals. This improvement hashes the location and normal of a vertex and does a lookup before storing if another vertex has the same location and normal.

@pboyer ptal.
Thanks @pboyer. Now flooring ```double``` values is always a bad idea and it'll be rejected anytime we ask. I think the *right* way to deal with this is to remove the error from ```double``` values, as we do have precision specified in the system, use the same thing to determine if two ```double``` values are the same. The implementation of ```Double.GetHashCode``` seems to perform a direct cast to ```long``` for hash code:

```cs
//The hashcode for a double is the absolute value 
//of the integer representation of that double.
//
public unsafe override int GetHashCode() {
    double d = m_value;
    if (d == 0) {
        // Ensure that 0 and -0 have the same hash code
        return 0;
    }
    long value = *(long*)(&d);
    return unchecked((int)value) ^ ((int)(value >> 32));
}
```

I am not expert in specifics about ```double```, but is there a way we first truncate, say, ```12.3456789012``` to just ```12.3456000000```, and then get the hash code out of it? This way we can do:

```cs
var truncatedX = ..., truncatedY = ..., truncatedZ = ...;
var hashCode = truncatedX ^ truncatedY ^ truncatedZ;
if (!pointHashCodes.Contains(hashCode))
{
    // Add to collection...
}
```