<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>MudLog</title>
	<atom:link href="http://mud.mitplw.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://mud.mitplw.com/blog</link>
	<description>Takashi Okamoto @ PLW 2006 - 2008</description>
	<pubDate>Sun, 15 Jun 2008 04:51:38 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>Vacation Over&#8230;</title>
		<link>http://mud.mitplw.com/blog/2008/06/15/vacation-over/</link>
		<comments>http://mud.mitplw.com/blog/2008/06/15/vacation-over/#comments</comments>
		<pubDate>Sun, 15 Jun 2008 04:48:17 +0000</pubDate>
		<dc:creator>mud</dc:creator>
		
		<category><![CDATA[Note]]></category>

		<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://mud.mitplw.com/blog/?p=76</guid>
		<description><![CDATA[My two year vacation is over. This blog is now closed. See you in another life.



]]></description>
			<content:encoded><![CDATA[<p>My two year vacation is over. This blog is now closed. See you in another life.</p>
<p><a href="http://mud.mitplw.com/blog/wp-content/uploads/2008/06/sany0023.jpg"><img class="alignnone size-full wp-image-79" title="sany0023" src="http://mud.mitplw.com/blog/wp-content/uploads/2008/06/sany0023.jpg" alt="" width="500" height="333" /></a></p>
<p><a href="http://mud.mitplw.com/blog/wp-content/uploads/2008/06/sany0002.jpg"><img class="alignnone size-full wp-image-77" title="sany0002" src="http://mud.mitplw.com/blog/wp-content/uploads/2008/06/sany0002.jpg" alt="" width="500" height="333" /></a></p>
<p><a href="http://mud.mitplw.com/blog/wp-content/uploads/2008/06/sany0003.jpg"><img class="alignnone size-full wp-image-78" title="sany0003" src="http://mud.mitplw.com/blog/wp-content/uploads/2008/06/sany0003.jpg" alt="" width="500" height="333" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://mud.mitplw.com/blog/2008/06/15/vacation-over/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Thesis.</title>
		<link>http://mud.mitplw.com/blog/2008/05/20/thesis/</link>
		<comments>http://mud.mitplw.com/blog/2008/05/20/thesis/#comments</comments>
		<pubDate>Tue, 20 May 2008 16:43:42 +0000</pubDate>
		<dc:creator>mud</dc:creator>
		
		<category><![CDATA[Note]]></category>

		<category><![CDATA[PLW]]></category>

		<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://mud.mitplw.com/blog/?p=74</guid>
		<description><![CDATA[
It&#8217;s been almost two months since my last post. E15 development was in full swing as well as thesis writing. We&#8217;re thinking about distributing the binary soon, and we&#8217;ll definitely have to rework the website. The best way is to probably make E15:Web as the E15 site. Anyway, this blog is going to close soon. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://mud.mitplw.com/blog/wp-content/uploads/2008/05/p1020295.png"><img class="alignnone size-full wp-image-75" title="p1020295" src="http://mud.mitplw.com/blog/wp-content/uploads/2008/05/p1020295.png" alt="" width="500" height="375" /></a></p>
<p><a href="http://mud.mitplw.com/blog/wp-content/uploads/2008/05/p1020295.png"></a>It&#8217;s been almost two months since my last post. <a href="http://e15.media.mit.edu">E15</a> development was in full swing as well as thesis writing. We&#8217;re thinking about distributing the binary soon, and we&#8217;ll definitely have to rework the website. The best way is to probably make <a href="http://e15web.media.mit.edu">E15:Web</a> as the E15 site. Anyway, this blog is going to close soon. Graduation is on June 6. My thesis was submitted today&#8230;so I&#8217;m done!</p>
]]></content:encoded>
			<wfw:commentRss>http://mud.mitplw.com/blog/2008/05/20/thesis/feed/</wfw:commentRss>
		</item>
		<item>
		<title>E15: Visual Effects and Texture Management</title>
		<link>http://mud.mitplw.com/blog/2008/03/22/e15-visual-effects-and-texture-management/</link>
		<comments>http://mud.mitplw.com/blog/2008/03/22/e15-visual-effects-and-texture-management/#comments</comments>
		<pubDate>Sun, 23 Mar 2008 01:35:27 +0000</pubDate>
		<dc:creator>mud</dc:creator>
		
		<category><![CDATA[Cocoa]]></category>

		<category><![CDATA[E15]]></category>

		<category><![CDATA[OpenGL]]></category>

		<category><![CDATA[PLW]]></category>

		<guid isPermaLink="false">http://mud.mitplw.com/blog/2008/03/22/e15-visual-effects-and-texture-management/</guid>
		<description><![CDATA[
I&#8217;ve been spending a lot of time on implementing E15&#8217;s texture management. We wanted to have a way to upload textures asynchronously (lazy load) so that when we apply filters to the bitmaps, we don&#8217;t have the whole process blocking. This means we need threading, and I went through some rough waters with OpenGL and [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://mud.mitplw.com/blog/wp-content/uploads/2008/03/picture-1.png" title="picture-1.png"><img src="http://mud.mitplw.com/blog/wp-content/uploads/2008/03/picture-1.thumbnail.png" alt="picture-1.png" /></a></p>
<p>I&#8217;ve been spending a lot of time on implementing E15&#8217;s texture management. We wanted to have a way to upload textures asynchronously (lazy load) so that when we apply filters to the bitmaps, we don&#8217;t have the whole process blocking. This means we need threading, and I went through some rough waters with OpenGL and Cocoa threads.</p>
<p>The design is pretty simple. Whenever a new texture needs to be created, the bitmap is initially split into a series of tiles, then uploaded with mipmaps onto the GPU. For images that require filtering (with <a href="http://developer.apple.com/documentation/GraphicsImaging/Conceptual/CoreImaging/ci_intro/chapter_1_section_1.html">Core Image</a> filters) we create a new thread that will create CIImage instances and applies a series of CIFilters. When the image is processed, the CIImage is converted back into bitmap, then sent to a singleton texture manager which periodically uploads the queue on the main thread. There were some confusing implementation details, and I&#8217;ll write them down after I describe the result.</p>
<p>So far, I implemented a couple different effects. The top picture shows blurring. Elements look blurry when viewed from far away, but becomes focused as you move close. Using this idea of zoomable user interface, I can show different information on the same quad depending on how far away the camera is. Here&#8217;s some captures showing various web pages.</p>
<p><a href="http://mud.mitplw.com/blog/wp-content/uploads/2008/03/picture-3.png" title="picture-3.png"><img src="http://mud.mitplw.com/blog/wp-content/uploads/2008/03/picture-3.thumbnail.png" alt="picture-3.png" /></a></p>
<p><a href="http://mud.mitplw.com/blog/wp-content/uploads/2008/03/picture-4.png" title="picture-4.png"><img src="http://mud.mitplw.com/blog/wp-content/uploads/2008/03/picture-4.thumbnail.png" alt="picture-4.png" /></a></p>
<p><a href="http://mud.mitplw.com/blog/wp-content/uploads/2008/03/picture-5.png" title="picture-5.png"><img src="http://mud.mitplw.com/blog/wp-content/uploads/2008/03/picture-5.thumbnail.png" alt="picture-5.png" /></a></p>
<p>&#8230;and here&#8217;s the obligatory Facebook shot</p>
<p><a href="http://mud.mitplw.com/blog/wp-content/uploads/2008/03/picture-6.png" title="picture-6.png"><img src="http://mud.mitplw.com/blog/wp-content/uploads/2008/03/picture-6.thumbnail.png" alt="picture-6.png" /></a></p>
<p>Now for some implementation notes. For starters, we need to remember that we need to run all OpenGL calls on the main thread. We will have to spawn a new thread for each texture we want to apply textures to, and have a singleton TextureUploader that will upload textures on the main thread. The real pain is to workout how the images should be constructed and processed when in a secondary thread.</p>
<p>I&#8217;ve tried a few different ways, and most of them resulted in unexpected crashes. The one I settled with is the following. During awakeOnNib, a static CIContext is created with the main CGContextRef:</p>
<pre>CGContextRef cgContext = [[NSGraphicsContext currentContext] graphicsPort];</pre>
<pre>_drawingContext = [[CIContext contextWithCGContext:cgContext options:nil] retain];</pre>
<p>This is the CIContext in which all the CIImages will be rendered to a CGImageRef. This method seems to be thread friendly.</p>
<p>In order to lazily create the filtered image, and uploaded; the initial bitmap texture that is uploaded is first converted to a CIImage. This image is sent to a new thread, which applies the CIFilters. The finished image will then be converted as a CGImageRef and drawn to a bitmap. The bitmaps are sent to a singleton class TextureUploader, which will upload textures every 500ms if there are any pending uploads. To convert CIImage to CGImageRef, just use this:</p>
<pre>- (CGImageRef)cgImageCreateFromCIImage:(CIImage *)cimg fromRect:(CGRect)rect

{

    CGImageRef cgImage;

    cgImage = [_drawingContext createCGImage:cimg fromRect:rect];

    if (cgImage == NULL) {

        NSLog(@&#8221;failed to create cgImage&#8221;);

    }

    return cgImage;

}</pre>
<p>This all seems simple, but it took a lot of trial and error. I hate threads&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://mud.mitplw.com/blog/2008/03/22/e15-visual-effects-and-texture-management/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Two OpenGL Optimizations</title>
		<link>http://mud.mitplw.com/blog/2008/02/20/two-opengl-optimizations/</link>
		<comments>http://mud.mitplw.com/blog/2008/02/20/two-opengl-optimizations/#comments</comments>
		<pubDate>Wed, 20 Feb 2008 18:32:20 +0000</pubDate>
		<dc:creator>mud</dc:creator>
		
		<category><![CDATA[Cocoa]]></category>

		<category><![CDATA[E15]]></category>

		<category><![CDATA[OpenGL]]></category>

		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://mud.mitplw.com/blog/2008/02/20/two-opengl-optimizations/</guid>
		<description><![CDATA[ In the last week, I&#8217;ve been working on optimizing E15 for speed and efficiency. So far I&#8217;ve implemented two ways to increase performance: texture tiling and frustrum culling. I&#8217;ll start with texture tiling.
Texture Tiling
We were using non power-of-two (POT) textures in E15, since they are supported, and it makes everything easy since source images [...]]]></description>
			<content:encoded><![CDATA[<p> In the last week, I&#8217;ve been working on optimizing E15 for speed and efficiency. So far I&#8217;ve implemented two ways to increase performance: texture tiling and frustrum culling. I&#8217;ll start with texture tiling.</p>
<p><strong>Texture Tiling</strong></p>
<p>We were using non power-of-two (POT) textures in E15, since they are supported, and it makes everything easy since source images for our textures don&#8217;t necessarily come in POT. For most images, this is fine, since they are small and manageable. With OpenGL 2.1, most things work with non POT. Performance issues arise when you have large textures, in our case rendering web pages. When web pages get turned into a bitmap, they become huge. Blogs are especially large, easily reach 15,000 pixels high. Of course these textures are too large for OpenGL, and so we decided to go back to POT and tile the images by subdividing them in multiple textures applied to multiple quads.</p>
<p>Going back to POT was a good move, since on the ATI X1900 it seems hardware mipmaps are only supported with POT (so originally we where using gluBuildMipmap). Implementing this was relatively straight forward. Here&#8217;s what needs to get done:</p>
<ol>
<li>Obtain texture, then create a new image with the next largest POT dimension.</li>
<li>Create new image by placing original image onto the new image.</li>
<li>Create textures by subdividing image with predefined tile size.</li>
</ol>
<p>All images are supplied as a CGImageRef, so I implemented a new method that will go through and accomplish the above task. It is pretty simple. You pass a CGImageRef and tile size and it will return an array of OpenGL texture ids.</p>
<pre>
- (GLuint *)createTiledTexturesFromCGImage:(CGImageRef)cgImage
                 tileSize:(int)newTileSize
{
  GLuint *textureNames;
  if(cgImage) {
    float image_w = CGImageGetWidth(cgImage);
    float image_h = CGImageGetHeight(cgImage);
    float remain_x = image_w/newTileSize;
    float remain_y = image_h/newTileSize;
    float spacing_w = (ceil(remain_x)-remain_x)*(float)newTileSize;
    float spacing_h = (ceil(remain_y)-remain_y)*(float)newTileSize;
    float width = image_w + spacing_w;
    float height = image_h + spacing_h;

    void* tData = calloc(width * 4, height);
    CGRect rect = CGRectMake(0, spacing_h, image_w, image_h);
    CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB();
    CGContextRef myBitmapContext = CGBitmapContextCreate(
     tData, width, height, 8, width*4, color_space,
     kCGImageAlphaPremultipliedFirst);
    CGContextDrawImage(myBitmapContext, rect, cgImage);

    int perWidth = (int)ceil(width/newTileSize);
    int perHeight = (int)ceil(height/newTileSize);

    int numTextureNames = perWidth*perHeight;
    textureNames = malloc(sizeof(GLuint)*numTextureNames);

    textureType = GL_TEXTURE_2D;
    glEnable(textureType);
    glGenTextures(numTextureNames, textureNames);

    //backup default pixel store state
    glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);

    //setup bitmap attributes
    glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    int onY;
    for(onY = 0; onY &lt; perHeight; onY++) {
      int onX;
      for(onX = 0; onX &lt; perWidth; onX++) {
        int onTexture = onY*perWidth + onX;

        //setup offsets
        int x = onX*newTileSize;
        int y = onY*newTileSize;

        //setup extents
        int dx = MINOF2(width-x, newTileSize);
        int dy = MINOF2(height-y, newTileSize);

        //skip to x,y for read from bitmap
        glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
        glPixelStorei(GL_UNPACK_SKIP_ROWS, y);

        glBindTexture(textureType, textureNames[onTexture]);

        glTexParameteri(textureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(textureType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(textureType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(textureType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(textureType, GL_TEXTURE_BASE_LEVEL, 0);
        glTexParameteri(textureType, GL_TEXTURE_MAX_LEVEL, 4);
        glTexParameteri(textureType, GL_TEXTURE_MIN_LOD, 0);
        glTexParameteri(textureType, GL_TEXTURE_MAX_LOD, 4);

        glTexParameteri(textureType, GL_GENERATE_MIPMAP, GL_TRUE);
        glTexImage2D(textureType, 0, GL_RGBA, newTileSize,
             newTileSize, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, NULL);
        glTexSubImage2D(textureType, 0, 0, 0, dx, dy, GL_BGRA,
                                                GL_UNSIGNED_INT_8_8_8_8, tData);
      }
    }

    //restore default pixel store state
    glPopClientAttrib();

    glDisable(textureType);

    // release
    CGColorSpaceRelease(color_space);
    CGContextRelease(myBitmapContext);
    free(tData);
  }
  return textureNames;
}</pre>
<p>We use glTexImage2D with NULL data and instead use glTexSubImage2D to insert an image of size dx, dy to account for the images at the edges. I&#8217;m not sure if that was necessary. Now all we need to do is iterate through the textures and create the necessary quads in our scene. Initially, I had rendered the quad size to be the texture size (which is the tileSize) but many times the quad sizes are too big and had rendering quirks with overlapping quads. The solution is to make sure you size the quad to be the same size as the original image. So for edge textures, you would have not create square quads, instead you will have whatever size necessary to show the original image. Here&#8217;s a code snippet from the scene:</p>
<pre>unsigned i = 0;
float x, y;

for (y = 0; y &gt; -dob.h; y -= textureSize) {
  float dy = MINOF2(dob.h + y, textureSize);
  glPushMatrix();
  glTranslatef(0, 2*y/mapScaler, 0);
  for (x = 0; x &lt; dob.w; x += textureSize) {
    glPushMatrix();
    glTranslatef(2*x/mapScaler, 0, 0);
    if (dob.textureIds[i]) {
      if (renderMode == GL_SELECT) {
        glLoadName(j);
      }
      float dx = MINOF2(dob.w - x, textureSize);
      glBindTexture(GL_TEXTURE_2D, dob.textureIds[i]);
      glBegin(GL_QUADS);
        //Page textures are flipped. Compensate for that.
        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(0.0f, 0.0f, 0.0f);
        glTexCoord2f(dx/textureSize, 0.0f);
        glVertex3f(2*dx/mapScaler, 0.0f, 0.0f);
        glTexCoord2f(dx/textureSize, dy/textureSize);
        glVertex3f(2*dx/mapScaler, -2*dy/mapScaler, 0.0f);
        glTexCoord2f(0.0f, dy/textureSize);
        glVertex3f(0.0f, -2*dy/mapScaler, 0.0f);
      glEnd();
      glPopMatrix();
    }
    i++;
  }
  glPopMatrix();
}</pre>
<p>Now we can handle large sites since we&#8217;re just rendering 256&#215;256 images.</p>
<p><strong>Frustrum Culling</strong></p>
<p>Implementing frustrum culling was pretty straight forward. I just had problems since I was applying my matrix transformation in the wrong order. Remember, they don&#8217;t commute! <a href="http://www.flipcode.com/archives/Frustum_Culling.shtml">This</a> is a good article that you can follow to implement it. Once implemented, the performance boost was noticeable for examples using lots of large textures. Now we need to work on a texture manager that will do manual mipmapping to display different images at different camera positions.</p>
]]></content:encoded>
			<wfw:commentRss>http://mud.mitplw.com/blog/2008/02/20/two-opengl-optimizations/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Building a Console for E15</title>
		<link>http://mud.mitplw.com/blog/2008/02/16/building-a-console-in-e15/</link>
		<comments>http://mud.mitplw.com/blog/2008/02/16/building-a-console-in-e15/#comments</comments>
		<pubDate>Sat, 16 Feb 2008 21:07:26 +0000</pubDate>
		<dc:creator>mud</dc:creator>
		
		<category><![CDATA[Cocoa]]></category>

		<category><![CDATA[E15]]></category>

		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://mud.mitplw.com/blog/2008/02/16/building-a-console-in-e15/</guid>
		<description><![CDATA[
This week I worked on implementing a console on E15 that can display contents of stdout while also accepting stdin. Until now, we all used the Xcode console, but of course if we want to distribute a binary, we are going to need a console for the users. The task wasn&#8217;t as trivial as I [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://mud.mitplw.com/blog/wp-content/uploads/2008/02/console.png" alt="console.png" /></p>
<p>This week I worked on implementing a console on E15 that can display contents of stdout while also accepting stdin. Until now, we all used the Xcode console, but of course if we want to distribute a binary, we are going to need a console for the users. The task wasn&#8217;t as trivial as I initially thought, and the result is a bit of a hack, but I thought I&#8217;d just write it up.</p>
<p>The console is just a simple NSTextView that is contained in a NSDrawer attached to the bottom of the OpenGLView. The first thing to do is to print the contents of error output into that view. It&#8217;s easy enough to do, we just need to add the contents to the NSTextStorage of the console. This seemed to work fine, but it would hang the application if we write to it repeatedly in a short time. Something like:</p>
<pre>
for i in range(1000):
  print i</pre>
<p>would hang at some arbitrary point. For a while I was convinced it was a problem in appending strings to the text view, but even after trying to append strings every way possible, it still didn&#8217;t work. In the end, the problem was due to threading. The python interpreter runs in a secondary thread, and I had thought that it was fine to modify the GUI from a secondary thread, since drawing to a view from a secondary thread was safe. Anyway, as soon as I used</p>
<pre>[NSObject performSelectorOnMainThread:withObject:waitUntilDone:]</pre>
<p>to write the contents, everything was good to go. It would be nice to know the exact things that must run     on the main thread in Cocoa are, but the <a href="https://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/chapter_950_section_2.html">Apple documentation</a> is pretty bad about that. So the lesson learned: when something barfs unexpectedly,   run in the main thread!</p>
<p>The other part to the console is to accept user input in the console and pipe it to stdin, to the Python interpreter. This is important since sometimes you would want to receive user information from <code>input()</code> or <code>raw_input()</code>. Initially I thought using NSTask and NSPipe would be the best, but that required me to set up the Python interpreter as a subprocess, but Kyle worked out all the stuff dealing with Python and threading and saving states and I didn&#8217;t want to mess with that. I knew that in Python, you can set any file handler as a stdin, stderror or stdout. So this is a total hack, and I don&#8217;t really know if there is a nicer way to go about it, but the idea is to grab the contents of the last line on the console when the user presses return or enter, then create a tmp file with the contents written inside it.</p>
<p>On the Python end, we would have to redefine <code>raw_input()</code>. I instead have a new method <code>console_input()</code> which is defined like this:</p>
<pre>
def console_input(message, magic_string='Yes'):
  print message
  open("/tmp/STDIN.txt", "w").write("# STDIN #")
  saved_state = sys.stdin
  sys.stdin = open("/tmp/STDIN.txt")
  line = sys.stdin.readline().strip()
  prev_result = line
  first_time = True
  while upper(line) != upper(magic_string):
    if prev_result != line and first_time == False:
        print 'Please answer ' + magic_string
        prev_result = line
    first_time = False
    sys.stdin = open("/tmp/STDIN.txt")
    line = sys.stdin.readline().strip()
  sys.stdin = saved_state</pre>
<p>So, the method prints out a message to the console, then also waits for the user to input the magic_string. If the user enters the magic string, the method will exit. Ghetto, I know&#8230;but it works and I can&#8217;t come up with a better solution.</p>
]]></content:encoded>
			<wfw:commentRss>http://mud.mitplw.com/blog/2008/02/16/building-a-console-in-e15/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Web Design is Dead</title>
		<link>http://mud.mitplw.com/blog/2008/02/09/web-design-is-dead/</link>
		<comments>http://mud.mitplw.com/blog/2008/02/09/web-design-is-dead/#comments</comments>
		<pubDate>Sat, 09 Feb 2008 23:45:11 +0000</pubDate>
		<dc:creator>mud</dc:creator>
		
		<category><![CDATA[Note]]></category>

		<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://mud.mitplw.com/blog/2008/02/09/web-design-is-dead/</guid>
		<description><![CDATA[
I know I haven&#8217;t updated with a new entry in a while. I&#8217;ve been working on this post for the last three months or so, but every time I try to write about something, I find it difficult to finish. But here it goes, another attempt at writing.
I said last year that I will work [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://mud.mitplw.com/blog/wp-content/uploads/2007/11/skull.jpg" title="skull.jpg"><img src="http://mud.mitplw.com/blog/wp-content/uploads/2007/11/skull.jpg" alt="skull.jpg" /></a></p>
<p>I know I haven&#8217;t updated with a new entry in a while. I&#8217;ve been working on this post for the last three months or so, but every time I try to write about something, I find it difficult to finish. But here it goes, another attempt at writing.</p>
<p>I said last year that I will work on a web application every month. I failed. Not because it was particularly difficult to implement, but because I thought it was a waste of time. I also don&#8217;t particularly enjoy making web applications or designing web pages. I&#8217;ve been doing it for a while, and the technical challenge isn&#8217;t so exciting; and it seems like everybody these days claims to be a web designer, and it&#8217;s true, being a web designer isn&#8217;t difficult (of course whether they are good is another question). With frameworks like rails and relatively compliant web browsers, it&#8217;s becoming simple to deploy web applications. Of course it is a nice change from the days of writing endless lines of redundant php code, but at this stage, it&#8217;s really about the idea and not about technological challenges. Ideas are hard, therefore I failed.</p>
<p>As a designer I feel the limitations of web browsers growing every day. Of course limitations can be due to security restrictions, and I feel like spending time to circumvent restrictions is a waste of time. Also, we have powerful computers, yet none of the graphics capabilities on the browser takes advantage of powerful graphics cards. This is why I don&#8217;t really spend much time working on web applications anymore. In a research context, when I think about what the &#8220;next thing&#8221; is for the web, I think it&#8217;s about the web as an environment we interact with, without a web browser; and give web designers a whole new set of graphical and interaction possibilities.</p>
<p>I&#8217;m focused on working on <a href="http://e15.media.mit.edu">E15</a>, and it&#8217;s been great. Implementing a desktop application comes with more complexity, but rewards with more flexibility. For the first time in a while, I feel like I can finally build things that I think, without discovering later that it is impossible. I&#8217;ve been knee deep in Cocoa, and I think I&#8217;ll probably focus more on writing about problems and solutions I&#8217;ve come across in future posts&#8230;if I ever decide to write onto this neglected blog of mine&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://mud.mitplw.com/blog/2008/02/09/web-design-is-dead/feed/</wfw:commentRss>
		</item>
		<item>
		<title>E15</title>
		<link>http://mud.mitplw.com/blog/2007/09/25/e15/</link>
		<comments>http://mud.mitplw.com/blog/2007/09/25/e15/#comments</comments>
		<pubDate>Tue, 25 Sep 2007 17:17:17 +0000</pubDate>
		<dc:creator>mud</dc:creator>
		
		<category><![CDATA[PLW]]></category>

		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://mud.mitplw.com/blog/?p=57</guid>
		<description><![CDATA[
E15Â is our newest project. It&#8217;s a new 3D graphics programming environment where we enable users to control the content and presentation. Our vision of what the web will be in the future. We demoed this at Flash Forward 2007, and just recently launched itsÂ website.Â We&#8217;ll be posting new stuff up there.
]]></description>
			<content:encoded><![CDATA[<p><a href="http://e15.media.mit.edu" title="E15"><img src="http://mud.mitplw.com/blog/wp-content/uploads/2007/09/header.jpg" alt="E15" /></a></p>
<p><a href="http://e15.media.mit.edu" title="E15">E15</a>Â is our newest project. It&#8217;s a new 3D graphics programming environment where we enable users to control the content and presentation. Our vision of what the web will be in the future. We demoed this at Flash Forward 2007, and just recently launched itsÂ <a href="http://e15.media.mit.edu">website</a>.Â We&#8217;ll be posting new stuff up there.</p>
]]></content:encoded>
			<wfw:commentRss>http://mud.mitplw.com/blog/2007/09/25/e15/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Modster</title>
		<link>http://mud.mitplw.com/blog/2007/08/08/modster/</link>
		<comments>http://mud.mitplw.com/blog/2007/08/08/modster/#comments</comments>
		<pubDate>Wed, 08 Aug 2007 14:52:11 +0000</pubDate>
		<dc:creator>mud</dc:creator>
		
		<category><![CDATA[Design]]></category>

		<category><![CDATA[OpenID]]></category>

		<category><![CDATA[PLW]]></category>

		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://mud.mitplw.com/blog/?p=55</guid>
		<description><![CDATA[
Finally finished the first application that usesÂ MudSketch.Â ModsterÂ is a graphical exquisite corpse, each of which are drawn by three people. Participants draw a portion of the corpse in sequence: head, torso and leg. Each of the three participants must contribute and submit a drawing â€“ otherwise the corpse will never be completed, making the creation process [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://modster.media.mit.edu" title="Modster"><img src="http://mud.mitplw.com/blog/wp-content/uploads/2007/08/modster.jpg" alt="Modster" /></a></p>
<p>Finally finished the first application that usesÂ <a href="http://mudsketch.media.mit.edu">MudSketch</a>.Â <a href="http://modster.media.mit.edu" title="Modster">Modster</a>Â is a graphical exquisite corpse, each of which are drawn by three people. Participants draw a portion of the corpse in sequence: head, torso and leg. Each of the three participants must contribute and submit a drawing â€“ otherwise the corpse will never be completed, making the creation process truely collaborative and participation dependent.</p>
]]></content:encoded>
			<wfw:commentRss>http://mud.mitplw.com/blog/2007/08/08/modster/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Canvas Drawing Tool</title>
		<link>http://mud.mitplw.com/blog/2007/07/13/canvas-drawing-tool/</link>
		<comments>http://mud.mitplw.com/blog/2007/07/13/canvas-drawing-tool/#comments</comments>
		<pubDate>Fri, 13 Jul 2007 22:33:36 +0000</pubDate>
		<dc:creator>mud</dc:creator>
		
		<category><![CDATA[Design]]></category>

		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://mud.mitplw.com/blog/?p=53</guid>
		<description><![CDATA[
I have a few project ideas that involve drawing, and I needed to start by creating reusable drawing code. I finished it and just wanted to put it up. It&#8217;s calledÂ MudSketch,Â all the interesting work stuff is in the /javascripts/MudSketch directory. Now that the tedious part is done, I can start working on the actual projects! [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://mudsketch.media.mit.edu" title="MudSketch"><img src="http://mud.mitplw.com/blog/wp-content/uploads/2007/07/mudsketch.png" alt="MudSketch" /></a></p>
<p>I have a few project ideas that involve drawing, and I needed to start by creating reusable drawing code. I finished it and just wanted to put it up. It&#8217;s calledÂ <a href="http://mudsketch.media.mit.edu">MudSketch</a>,Â all the interesting work stuff is in the /javascripts/MudSketch directory. Now that the tedious part is done, I can start working on the actual projects! BTW this counts as my July webapp&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://mud.mitplw.com/blog/2007/07/13/canvas-drawing-tool/feed/</wfw:commentRss>
		</item>
		<item>
		<title>RunLog(ger) on Facebook</title>
		<link>http://mud.mitplw.com/blog/2007/06/02/runlogger-on-facebook/</link>
		<comments>http://mud.mitplw.com/blog/2007/06/02/runlogger-on-facebook/#comments</comments>
		<pubDate>Sat, 02 Jun 2007 21:49:46 +0000</pubDate>
		<dc:creator>mud</dc:creator>
		
		<category><![CDATA[Facebook]]></category>

		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://mud.mitplw.com/blog/?p=51</guid>
		<description><![CDATA[
I wanted to see what the new Facebook platform was like, so I created RunLogger, which is RunLog for Facebook. It&#8217;s not attached to the RunLog site, but it will post a mini-feed to your profile, as well as give you running information about
your friends.
]]></description>
			<content:encoded><![CDATA[<p><a href="http://mit.facebook.com/apps/application.php?id=2252436418"><img alt="RunLog Facebook" id="image50" src="http://mud.mitplw.com/blog/wp-content/uploads/2007/06/runlog.png" /></a></p>
<p>I wanted to see what the new <a href="http://www.facebook.com">Facebook</a> platform was like, so I created <a href="http://mit.facebook.com/apps/application.php?id=2252436418">RunLogger</a>, which is <a href="http://runlog.media.mit.edu">RunLog</a> for Facebook. It&#8217;s not attached to the RunLog site, but it will post a mini-feed to your profile, as well as give you running information about<br />
your friends.</p>
]]></content:encoded>
			<wfw:commentRss>http://mud.mitplw.com/blog/2007/06/02/runlogger-on-facebook/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
