Saturday, December 27, 2008

gluPerspective to glFrustrumf

gluPerspective is a nice, intuitive helper function for setting the projection matrix in OpenGL. However, it's part of the glu library, which doesn't seem to be (readily) available for the iPhone (OpenGL ES).

Here is how to call glFrustrumf with the values you would give to gluPerspective:

float fov = 45;
float near = 0.01, far = 10;
float aspect = (float)windowWidth / (float)windowHeight;

// glPerspective(fov, aspect, near, far);

top = tan(toRad(fov)) * near;
bottom = -top;
left = aspect * bottom;
right = aspect * top;

glFrustumf(left, right, bottom, top, near, far);

Saturday, December 20, 2008

"error: syntax error before '*' token"

I recently began porting Jumper to the iPhone as a winter project. After adding another source file (Level.c in this case), I started getting thousands of build errors, along the lines of:

error: syntax error before '@' token
error: syntax error before '*' token

These were from files in /Developer/Platforms/iPhoneSimulator.platform/..., which was not encouraging. Something weird was going on.

Actually, it was really simple. Turns out that should have been Level.m, not .c. Whoops.

Saturday, December 13, 2008

Drawing triangles for height maps

Two ways of drawing triangles for HeightMap h1:

Simple, like this:

----
|/|/
----



int ndx = 0;
for (int r = 0; r < h1->rows-1; r ++) {
glBegin(GL_TRIANGLE_STRIP); {
for (int c = 0; c < h1->cols; c ++, ndx ++) {
int cols = h1->cols;
glVertex3fv(h1->verts[ndx+cols].xyz);
glVertex3fv(h1->verts[ndx].xyz);
}
glEnd();
}
}



More complex, but lends itself to simplification over distance, like this:

----
|\/|
----
|/\|
----



for (int r = 1; r < h1->rows-1; r += 2) {
for (int c = 1; c < h1->cols-1; c += 2) {
int cols = h1->cols;
int mid = r*cols + c;
glBegin(GL_TRIANGLE_FAN); {
glVertex3fv(h1->verts[mid].xyz);
glVertex3fv(h1->verts[mid-1].xyz);
glVertex3fv(h1->verts[mid-cols-1].xyz);
glVertex3fv(h1->verts[mid-cols].xyz);
glVertex3fv(h1->verts[mid-cols+1].xyz);
glVertex3fv(h1->verts[mid+1].xyz);
glVertex3fv(h1->verts[mid+cols+1].xyz);
glVertex3fv(h1->verts[mid+cols].xyz);
glVertex3fv(h1->verts[mid+cols-1].xyz);
glVertex3fv(h1->verts[mid-1].xyz);
}
glEnd();
}
}

Tuesday, December 9, 2008

Keep ssh connections open

While in college, I've had to do a lot of work by sshing into school machines. Unfortunately, they allow a rather short "idle" time before they kick me out of whatever I was doing (littering my code folders with .swp files in the process :-P)

While one way around this is to run all your sessions in screen, it's still annoying to me to have my sessions freeze every time I go for a snack.

Fortunately, you can keep your sessions open by putting the following into ~/.ssh/config on your (client) machine:

ServerAliveInterval 60

According to the man page:
"Sets a timeout interval in seconds after which if no data has been received from the server, ssh will send a message through the encrypted channel to request a response from the server."

Sunday, November 23, 2008

Wireframe mode in OpenGL

Here's an easy way to have a togglable wireframe mode in OpenGL (useful for debuging):

bool isWire = true;
...
if (isWire) {
glPolygonMode(GL_FRONT, GL_LINE);
glPolygonMode(GL_BACK, GL_LINE);
}
...(draw)...
glPolygonMode(GL_FRONT, GL_FILL);
glPolygonMode(GL_BACK, GL_FILL);

Sunday, November 2, 2008

xrandr for external windows (thinkpad t61)

For reference, here are my bash aliases for setting up external monitors on my Thinkpad T61:


alias lcd='xrandr --addmode VGA 1280x1024 && xrandr --output LVDS --auto && xrandr --output VGA --mode 1280x1024 --left-of LVDS'
alias internal='xrandr --output VGA --off && xrandr --output TMDS-1 --off && xrandr --output LVDS --auto'
alias dual_lcd='xrandr --output LVDS --off && xrandr --output VGA --mode 1280x1024 && xrandr --output TMDS-1 --mode 1280x1024 --left-of VGA'


LVDS: internal screen
VGA: DSUB (blue) (on left of laptop or a dock)
TMDS-1: DVI (white) (on a dock)

lcd: one external monitor (the DSUB slot on the left)
dual_lcd: two external monitors (via a dock)
internal: just the internal screen

Note: Only two screens can be active at once (you'll get an error if you try to add a third; that's why the shortcuts are so complicated)

Making your own programs float in awesome window manager

I do a fair bit of graphics/game coding in my spare time (and occasionally for classes). These don't fit well into tiling environments, since I usually want them to be a specific resolution, and in-front of all other windows. Fortunately, there's an easy way to do this with the awesome window manager (note: this is with version 2.3).

The normal way of making things float in awesome is like this:

rule { name = "Gimp" float = true }


However, this didn't work so well for my stuff. I tried variations of a.out (which I swore I got to work before...wish I'd backed up that conf file...) to no avail. However, you can also use xproperties, obtainable from xprop (run xprop in a terminal, click on the window you want info for, and the x properties will be printed in the terminal).

For my current project, this gave me:

$ xprop
WM_STATE(WM_STATE):
window state: Normal
icon window: 0x0
_AWESOME_PROPERTIES(STRING) = "0010000000"
WM_PROTOCOLS(ATOM): protocols WM_DELETE_WINDOW
WM_LOCALE_NAME(STRING) = "C"
WM_HINTS(WM_HINTS):
Initial state is Normal State.
WM_NORMAL_HINTS(WM_SIZE_HINTS):
user specified location: 100, 100
user specified size: 800 by 600
WM_CLIENT_MACHINE(STRING) = "Gecko"
WM_ICON_NAME(STRING) = "Asteroid Game"
WM_NAME(STRING) = "Asteroid Game"


In the rules section of ~/.awesomerc, I added the following:

rule {xproperty_name = "WM_NAME" xproperty_value="Asteroid Game" float = true }


It worked! (A bit tedious to add for each new app you work on, but better than nothing for now....I'll update post if I figure out how my old a.out trick worked).

Saturday, November 1, 2008

Some good trayer flags

While good documentation is hard to find for Linux in general, it's almost non-existent for smaller, less used (read: non-gnome/kde) apps. One such app is trayer, which gives you a stand alone system tray (for icons of apps like pidgin, gmail notifier, and the like). It's especially useful for minimalistic window managers that don't come with panels (such as wmii, awesome wm, or xmonad).

Here is a spiffy example of trayer usage that I found (tested in xmonad):
trayer --edge top --align right --SetDockType true --SetPartialStrut true --expand true --width 10 --transparent true --tint 0x191970 --height 12

Monday, October 20, 2008

Better search script (ruby)

Turns out I can kick off a text based browser from Ruby just fine. The trick is to use sytem("elinks") instead of `elinks`. Here's the Ruby version of my search script (cleaner):


#!/usr/bin/ruby
require 'open-uri'

site = ARGV[0]
query = URI.escape(ARGV[1..-1].join(" "))

case site
when "google": url = "http://www.google.com/search?q=#{query}"
when "wikipedia": url = "http://en.wikipedia.org/wiki/Special\:Search?search=#{query}"
when "torrentz": url = "http://www.torrentz.com/search?q=#{query}"
when "isohunt": url = "http://isohunt.com/torrents/?ihq=#{query}"
when "mininova": url = "http://www.mininova.org/search/?search=#{query}"
end

system("elinks #{url}")

Saturday, October 18, 2008

Setting destination directory for wget

The phrase "destination directory" does not appear in the wget man page. Turns out they call it the "directory prefix":

wget -P ~/dest/dir www.foo.com/myfile.png

Saturday, August 9, 2008

Remap keys in Windows with SharpKeys

Caps lock is such a useless key. I almost never hit it intentionally. When I do strike it, the results are at best annoying (I LOOK LIKE I'M SHOUTING) and at worst are catastrophic! (try hitting caps lock in the middle of a vim session sometime. Or better yet, try hitting it in the middle of someone else's. I guarantee you there will be profanity. :)

Given my vim-ish tendencies, I decided to map Caps Lock to Escape (a very important key in vim, which is in a crappy location on many keyboards). There are several ways to do this under Linux. Under Windows, registry magic is needed.

Fortunately, a free program called SharpKeys will do this for you. (It looks like it can map just about any key to any other key. I haven't played with it.)

Thursday, August 7, 2008

Updated weather script

Since the weather page I used for my previous weather script changed, reducing half of my scripts output to an ascii-splosion, I decided to take another stab at it. Turns out Google supports weather searching. I rewrote the regular expressions and incorporated some new ruby tricks I've learned since. I'm actually rather pleased with the result: weather.rb

The regular expressions are a bit yucky, but that's to be expected. I think the rest of the code is pretty readable. Cool feature: that bit with the join and URI.escape at the top lets you use it like so:

weather san francisco, ca

"san", "francisco,", and "ca" will be passed as separate arguments, but the line at the top will join them together and convert the resulting string into something you could type in a URL bar. (ie: spaces -> %20).

Makes it easy to be sloppy on the command line. :)

Monday, August 4, 2008

Interesting case of "for x in xs" in Javascript

Recently, I began experimenting with Javascript (mostly to see what the fuss was all about.) I'm making a web page form to help students computer their current grade in a class, based on the grading (weighting) system outlined in the syllabus and the known scores on assignments. (Pretty simple, but hopefully useful.) More on that in a future post.

As I was working, I stumbled on some rather bizzare behavior (at least to me, Javascript neophyte) that I figured was worth remarking on, in case someone else (or my future self) encounters a similar problem.

In part of my code, I wanted to be able to search the array by matching against member variables of its elements. After hunting around online a bit, I was led to the conclusion that extending the Array class was the accepted (and clever?) thing to do here:


Array.prototype.getNdx = function(id) {
for (i in this) {
if (this[i].id == id) {
return parseInt(i);
}
}

return -1;
}


I got busy with other things, and weeks went by. Tonight, I resumed work on the code. I was trying to generalize the task of dynamically adding rows to tables, since this was going to happen in several places on the page. This task involves appending children to a node, so I wrote the row adding code to iterate over an array of cell objects and add each of them to the node. Seemed simple enough.


for (col in cells) {
var cell = row.insertCell(col);
...
cell.appendChile(node);
}


However, the alignment was off. After poking around a bit with Firebug (a lifesaver, by the way; I see us becoming close friends), I determined that an extra node was being added to the beginning of the row.

After assuring myself that my indexes all started where I intended them to, I decided to add an "alert('col = ' + col)" line to the each phase of the adding process, to show me what was going on (a variant of the classic "print("x = " + x)" line for debugging purposes.) The alerts showed me the indexes as:

0...1...2...3...*etc*...getNdx

...wtf?

I didn't research this in depth (this entry was mostly for future reference in case I hit this problem again...sometimes school/work makes me go a while between pet projects). However, my theory is that my custom "getNdx" function was picked up as another element of cells by the "for" iterator. Which...sort of...makes sense. I guess. In a free-form, loosely typed, Javascripty sort of way.

At any rate, maybe that will clear this up if anyone else hits this issue. Simplified code to show this behavior:


Array.prototype.getNdx = function(id) {
for (i in this) {
if (this[i].id == id) {
return parseInt(i);
}
}

return -1;
}

var col = 0;
var cells = new Array();

cells[col++] = "asdf"
cells[col++] = "fdsa"

for (j in cells) {
alert(j);
}

Tuesday, July 15, 2008

Bring some sanity to Windows window management

I am fed up with all the precision mouse-work required to simply move and resize windows under most non-X11 window managers. (Read: Windows and Mac). On most X11 window managers, you can hold down the "alt" key and click and drag on the window. Left clicking moves the window, and right clicking resizes the window. So much more humane than trying to grab those edges!

In the midst of frustration today at too-tiny default windows, I hunted around for a solution. Behold: KDE-SizerXP.

I myself never associated this behavior with KDE specifically, but I'm not one to complain!

(Mac users, take a look at Window Dragon. I haven't used it, but I believe it solves the same problem).

Monday, June 9, 2008

Fixing DPI changes in Linux

(or, how to enforce a constant DPI)

Lately, I found that repeatedly enabling and disabling an external monitor for my laptop caused the fonts to get smaller and smaller. It appears this was linked to the DPI getting changed somehow. With a bit of hunting, I found the following useful bit of info:

"...some distributions launch X using "-dpi 100". Fonts will appear as intended..."
(http://scanline.ca/dpi/)

Indeed, adding -dpi 100 to defaultserverargs in /usr/bin/startx did the trick. (At least for now...we'll see if it holds.)

Saturday, April 5, 2008

Search shortcuts for text based browsers (with bash)

Recently, I started experimenting with text-based web browsers (such as elinks or w3m). Of course, I still use firefox for pages that are more complex or need images, but sometimes it is nice to just have the text version in a console (no distractions, consistent colors, and ad blocking!)

However, one thing I really missed from firefox was the ease with which I could search google, wikipedia. or other sites. Well, with a bash script and some aliases, I can now do basically the same thing with a text based browser.

Here is the bash script:

#!/bin/bash
# Open a search for on in a text-based browser
# Usage: search.sh

browser=elinks # could also put w3m here

site=$1
query=$2%20$3%20$4%20$5%20$6%20$7%20$8%20$9 # hack to pick up >1 search terms

case $site in
"google" ) $browser 'http://www.google.com/search?q='$query;;
"wikipedia" ) $browser 'http://en.wikipedia.org/wiki/Special\:Search?search='$query;;
"torrentz" ) $browser 'http://www.torrentz.com/search?q='$query;;
"isohunt" ) $browser 'http://isohunt.com/torrents/?ihq='$query;;
"portage" ) $browser 'http://gentoo-portage.com/Search?search='$query;;
* ) echo "Unknown site";;
esac


I then added the following aliases to my .bashrc (the script is in ~/bin/)

alias google='~/bin/search.sh google'
alias wiki='~/bin/search.sh wikipedia'
alias torrentz='~/bin/search.sh torrentz'
alias iso='~/bin/search.sh isohunt'
alias port='~/bin/search.sh portage'


Now, if I want to quickly look up, say, a package in portage, I just type portage package_name in my terminal.

Saturday, March 29, 2008

More ruby: comics

My next foray into Ruby (see previous post) came to me while I was catching up on my favorite web comics over break. While ordinarily not much of a hassle, some of the pages were taking especially long to load all of the images, most of which were not the comic I actually cared about. Wouldn't it be nice to have a script that made me a page with just the comics themselves?

It turned out to be pretty straightforward. Here's the result: comics.rb

I then created a simple bash script to make loading comics.html into a browser cleaner:

#!/bin/bash
# Generate an updated comics page and load it in browser du jour

BROWSER='firefox -new-window'

ruby ~/bin/comics/comics.rb
$BROWSER comics.html &

Friday, March 28, 2008

Some nifty ruby scripts

Update: A better version of the weather script is discussed above

Lately, I've revisited ruby for various small code projects. It's virtues are extolled at length here, so I won't bother other than to say I like it. The following programs are some practical examples of ruby (though not the most elegant ways of doing so), and are just plain useful (at least to me).

Weather
I wanted to fetch weather forecasts for my area (or any other I happened to be visiting). There are several weather reporters available, and I've tried many of them. However, they were all in widget form, and tied to some desktop environment, dock, or some such. I decided to create one I could call from the command line (handy, since I soon moved to awesomewm, which has no desktop or dock to speak of. More on that another time.)

My weather reporter downloads two different pages off of weather.com (the "now" page and the "forecast" page), scans them for the relevant temperatures, and displays them neatly on the screen (with ASCII colors :). It defaults to San Luis Obispo (my current home base), but will take a zip code as an argument.

The code: weather-old.rb

Battery
For similar reasons to the weather, I wanted a script to give me a simple battery readout, perfect for status bars or command lines. After a bit of research, I found that (in Linux) the battery information is stored in various files in /proc/acpi/battery/BAT#. It was just a matter of scanning these files, doing a bit of division, and formatting the output.

Here is the code: battery.rb