Wednesday, April 28, 2010

KeyedCollection

System.Collections.ObjectModel.KeyedCollection is an interesting class, but with one drawback: it serializes in XNA's IntermediateSerializer, but doesn't deserialize. There're ways to write a custom serializer for this class, but I chose a little bit different route - making my own that doesn't need a custom serializer.

Advantages

  • Different methods can be exposed between the pipeline and runtime versions. This can help make the collection immutable if desired.
  • Hides methods that may not be needed at runtime like adding and removing elements.
  • Provides regular for loop access for speed.

Disadvantages

  • Extra complexity of a new class
  • Have to re-implement any methods

Code

This is an abstract base class that serves solely as a container, provides an iterator, and a method of accessing by key.

abstract class KeyedCollection<T> : IEnumerable<T>
{
    #region Internal Data

    [ContentSerializer]
    private List<T> _collection;

    /// <summary>
    /// Keyed lookup: <Key, Collection Index>
    /// </summary>
    [ContentSerializer]
    private Dictionary<int, int> _lookup;

    #endregion;

    #region Properties

    /// <summary>
    /// Indexer
    /// </summary>
    /// <param name="index"></param>
    /// <returns></returns>
    [ContentSerializerIgnore]
    public T this[int index]
    {
        get
        {
            return _collection[_lookup[index]];
        }
    }

    /// <summary>
    /// Number of elements in the collection
    /// </summary>
    [ContentSerializerIgnore]
    public int Count
    {
        get
        {
            return _collection.Count;
        }
    }

    #endregion;

    /// <summary>
    /// Constructor
    /// </summary>
    public KeyedCollection()
    {
        _collection = new List<T>();
        _lookup = new Dictionary<int, int>();
    }

    /// <summary>
    /// Find the neighbor at the given keyed index.
    /// </summary>
    /// <param name="index"></param>
    /// <returns></returns>
    public T Key(int index)
    {
        return _collection[_lookup[index]];
    }

    #region IEnumerable

    /// <summary>
    /// Enumerator
    /// </summary>
    /// <returns></returns>
    public IEnumerator<T> GetEnumerator()
    {
        foreach (T element in _collection)
        {
            yield return element;
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    #endregion;
}

Pipeline compiler directives already included too! It's a bit sparse for now, but a start.

Icons!

Social Networking Icons

p.yusukekamiyamane Fugue Icons

A huuuuuge set of general purpose icons. Not as ubiquitous as the famfamfam icons.

FamFamFam Silk

Entirely ubiquitous now - you see these everywhere.
Silk Companion 1

Friday, April 16, 2010

Shaders!

Learning some HLSL as the plan requires sometime more than what BasicEffect can handle. It doesn't do multiple diffuse textures per vertex. The plan is still very theoretical, and I'm not sure if I'm even smart enough to make it happen.

The screenshots before are simply a Miller projection wrapped around the grid. This means however that the texture border's don't line up to the grid borders. What I want is a more 'cellular' look and feel to it, along with a height map.

Cell Influence

foreach (neighbor in neighbors)
{
    foreach (vertex in neighbor.Vertices)
    {
        Calculate distance and then cell's influence on this vertex
        Cell.NeighborVertices[ neighbor.Index ].Add( Vertex, Influence );
    }
}

Now, we have a list of neighbor vertices that the cell has influence over. The distance and amount can be adjusted like a drawing brush - soft or hard brush. In this step, the neighbor vertices should be given a UV channel that lines up with the cell.

Blended Textures and UV Channels

Each vertex will have a minimum of three UV coordinates as it will have at most, three cell textures to blend (cell brushes shouldn't extend beyond one neighbor). Add in another texture channel or two for normal maps or detail overlays (just a tiled Miller wrap) and soon, every vertex has 5 UV channels. Currently I'm focusing on the first 3.

Paged textures will allow multiple textures to be used and not have to create channels in every cell for each texture. Each neighbor lookup will have assigned to a channels 1 or 2. Then just alternate channels for each neighbor. Except the 12 pentagons... Yeah, going to have to figure out something different there...

Height Maps

The current screenshots show a simple height-map retrieved from the diffuse texture. When moving to a more cellular approach, this kind of height-mapping won't be satisfactory. Instead, a series of small height-maps can be loaded and applied to cells individually. Using the neighbor influence lookup, the map can spill over and scale down into neighboring cell.

Sunday, April 4, 2010

Some Screen Shots

Borders still working. Have it set to wrap a Miller projection to the grid. There's a nasty seem on the back side to figure out. This isn't quite the ultimate goal though - I want a blended grid, not a single texture over the mesh. Height-mapping is working though.

Options:

  • Texture Splatting: more limited textures due to the blending mask. Might need a bit different type of unwrap?
  • Just leave the cell edges: easy, but doesn't look as nice