Sunday, December 27, 2009

Louder SMPlayer volume

For some reason, a number of my shows and movies seem to be at a low volume. SMPlayer, my video player of choice, didn't seem to have a way of boosting the sound beyond 100%. Turns out it does, you just have to hunt for it:

Options->Preferences: General->Audio->Max. Amplification

Set that to 200 or so to allow further amplification in software.

Audio->Filters->Volume Normalization is another way to help boost sound.

Sunday, December 20, 2009

PowerShell script to play latest video linked on web page

My auto-piracy machine do-it-yourself media center lists the most recently downloaded TV shows in a way that looks like this (in HTML, that is):

<a href="http://www.blogger.com/tv/How%20I%20Met%20Your%20Mother/05/how.i.met.your.mother.s05e11.720p.hdtv.x264-ctu.mkv">Season 5 Episode 11</a>;

The web interface isn't bad, but I like to mess around with scripting and command line stuff, so here's a powershell script that will play the latest show matching a given string. (Examples: latest how, latest -n 2 dollhouse)


param(
[switch]$switch = $false,
[string]$query = $(Read-Host -prompt "Keyword"),
[int]$num = $(if ($switch) {Read-Host -prompt "Number"} else {1})
)

$player = "C:\Program Files\SMPlayer\smplayer.exe"
$client = New-Object System.Net.WebClient
$data = $client.DownloadData("http://spot/")
$page = [System.Text.Encoding]::ASCII.GetString($data)

# They are displayed on the page with newest on top, but we want to play them in order (oldest to newest)
$matches = [regex]::Matches($page, "href=`"([^\<\>]*?$query[^\<\>]*?\.[^\<\>]*?)`"", "IgnoreCase") | Select-Object -first $num | Sort-Object

$files = ""
foreach ($m in $matches) {
$files += "'http://spot/$($m.groups[1])' "
}

if ($files.Length -gt 0) {
echo $files
Start-Process $player $files
}
else { echo "Could not find anything matching '$query'" }


Notes:

  • [^\<\>] means "any character except < or >". The *? means "any number of the preceding". So in this case, it means "any number of characters except < or >". Useful for reading the text between tags.

  • The bit at the top lets you optionally specify the number of matches to use with -num (or -n), defaulting to 1 otherwise. If you don't give it a query, it will prompt you. (It doesn't properly handle the case of -num w/o a number, but I don't care at this point. You'll get an error message, just not a nice one).

Tuesday, December 1, 2009

Notes-to-self: actually applying the sine curve stuff

A practical variation of the previous idea:

Use one quarter of the sine wave (covex up, convex down, concave down, concave up) for each block. Every other height will be used as an actual height, and the heights in-between will be used to determine whether the segment is convex or concave.

Saturday, November 28, 2009

Web-scraping web comics

A template for web-scraping comics, using Piled Higher & Deeper as an example (in Python; if on windows, you'll need wget from Cygwin):

import urllib2
import re
import os
import sys

url = "http://www.phdcomics.com/comics/archive.php?comicid="

for id in range(int(sys.argv[1]), int(sys.argv[2])):
print `id`+"..."
try:
page = urllib2.urlopen(url+`id`).read()
img = re.search('img src=(http://www.phdcomics.com/comics/archive/.+?.gif)', page).group(1)
os.system('wget -nc '+img)
except urllib2.HTTPError:
print "No page_id " + `id`

Friday, November 27, 2009

Notes-to-self: sinusoidal curve fitting

One ppt
Another ppt

y = C + Asin(Bx - D)

A = (largest-smallest)/2 (determine the amplitude)
C = (largest+smallest)/2 (determine the vertical shift)
B = 2pi/P (P = period? delta time/distance?) (determine period?)
D = "must use A, B, C and a point (x,y)" (determine horizontal shift)

Looks like it requires 3 points. Maybe divide height-map into 3x3 "squares"?
- Can't find sin(x)*sin(z) that goes through them all, how to handle that?
- Some points will have to be left out

Maybe do it like this?
0 z 0
x x/z x
0 z 0
- Results in about half the points being left out...much of a problem? (increase height-map resolution)

Notes-to-self: next steps for sine-based terrain

(notes to self; not intended to be interesting/meaningful/relevant to anyone else)

So I have terrain based on sin(x)*sin(z) working pretty well (where "pretty well" is defined as 40-60+ fps on my iMac...the shader is too complicated to run on my laptop's integrated intel card, but more on that later...maybe). It would look alright if used for, say, an open stretch of ocean, but it's way too boring for something that's supposed to be actual land. So...what's next?

Well, first, some irritations with my current method. Chief among them is that I cannot change the landscape without changing both the code and the shader (the code sets up the blocks the shader carves away from). The main reason for this is that the formula (sin(x)*sin(z)) is hard-coded into the shader. Ideally, I could change just change code. (Actually, ideally I wouldn't have to change the code either; it would read the formula from a text file and everything else would be magically figured out.) The way I see to do the first part: generalize the formula in the shader so that it accepts parameters from the code (ie: a*sin(bx + c) + d).

So here's a thought for "what's next", which attempts to address several other problems I'm having at the moment: code hands block to shader, with 8 parameters. The shader will evaluate a*sin(bx+c)+d * e*sin(fz+g)+h on the block, in modelspace. This will simplify the shader, as it will not need to know anything about where in the world the object is, and make it more flexible (we just want the shader to make the GPU do math work for us; we don't want to simulate state with it).

The simplest use of this is to easily tweak the whole scene's frequency, amplitude, etc. from code. However, another possible (ab)use is stringing together blocks of different frequency or amplitude together to make a more interesting level. One problem that immediately comes to mind is differentiability: if I'm just stringing sections of sine waves together, they certainly won't be differentiable...but the question is, how bad will it look? Given reasonable constraints, will it look "good enough"?

Keeping the current semi-goal of smooth curvy terrain from a height map in mind: could I take a "square" of the height map, look at the differences, and find a chunk of sin(x)*sin(z) that, with appropriate a-h parameters as described above, approximates it? It seems feasible enough (in my tired state) to warrant further investigation.

Saturday, November 14, 2009

How I fixed my problems with long downloads

Turns out my DD-WRT (v24 sp1) router's SPI firewall was blocking packets related to DHCP from my ISP. This caused DHCP connection to reset every 10 minutes, which stalled any downloads in progress and caused internet applications (Skype, online games) to behave oddly.

I fixed this by adding the following line to my firewall startup instructions:
iptables -I INPUT -p udp --sport 67 --dport 68 -j ACCEPT

Open router configuration page (http://10.0.0.1 for me) and go to Administration->Commands. Copy and paste the above into the "Command shell" text box, then click "Save Firewall".

From this thread.

Sunday, October 4, 2009

Cg syntax highlighting in vim


  1. Download cg.vim to ~/.vim/syntax/. (more info here. Note: the file on that page is DOS formatted; my link is to a converted version)

  2. Enable automatic highlighting by adding this to ~/.vimrc:
    au BufNewFile,BufRead *.cg setf cg

Wednesday, September 30, 2009

Clear IE cache from command line

Turns out you can avoid the awkward series of menus to empty Internet Explorer's temporary internet files, history, cookies, etc by typing the following in the command line:
rundll32.exe InetCpl.cpl,ClearMyTracksByProcess 4351

Very useful for automated testing!

More details here.

Wednesday, July 15, 2009

Easy iPhone landscape orientation

Put one of the following in your AppDelegate's applicationDidFinishLaunching method:
  • application.statusBarOrientation = UIInterfaceOrientationLandscapeRight;
  • application.statusBarOrientation = UIInterfaceOrientationLandscapeLeft;

This has several benefits:
  • The status bar, keyboard, and alerts are oriented properly
  • The iPhone simulator will orient itself properly

Sunday, July 12, 2009

Some quick cocoa notes

In documentation such as this: "Convenience Constructors" do not seem to require alloc, like so:
NSDate *now = [NSDate date];

"Initializers", on the other hand, require alloc:
NSDate *since = [[NSDate alloc] initWithTimeInterval:0 sinceDate:someOtherDate];

Monday, June 29, 2009

My Windows Extras

A list of software I use to make me feel more at home in Windows:

AutoHotkey Customize keyboard shortcuts and automate common actions. (Apparently advanced window management is possible...KDE Mover-Sizer is based on this).
CDBurnerXP (iso and gap-less Audio CD burning)
Filezilla (SFTP)
Firefox (web browser, can be extended with plugins)
- Vimperator (vim bindings, link numbering/hints)
- Adblock Plus (blocks ads)
- Custom Download Manager (stop download window from popping up)
- Colorful Tabs (tab colors)
Foobar2000 (minimalistic/functional media player replacement; never mind, I like WinAmp better)
GMail Notifier Plus (checks gmail, displays with Windows 7's jump lists)
GVim (programmer/admin's text editor)
KDE Mover-Sizer (move and resize windows by alt-clicking anywhere in window)
Notepad++ Coder/Admin text editor with a less...unique...control-scheme than GVim. Also, handles working off of UNC shares better (gvim frequently locks up for half a minute or so).
Paint.NET (somewhere between Paint and Photoshop)
Pidgin (AIM, GTalk)
Process Explorer (a much better Task Manager)
PuTTY (SSH)
SMplayer (video player; linux's mplayer w/GUI)
Steam (Games)
Sumatra PDF Viewer (no-nonsense PDF viewer)
TortiseSVN (SVN)
VirtualBox (virtualization: lets you run other OSs at the same time as Windows; supports 3D acceleration!)
WinAmp (watch folders, jump to file, global hotkeys...everything I want in a music player)
WinRAR (zip,rar,tar,etc; nag screen, but never expires)
WMP Keys (global hotkeys for Windows Media Player; since rendered unnecessary WinAmp)

My mac extras

A list of software I use to make me feel more at home in OS X (for next time I reinstall...):

Adium (AIM, GTalk)
Cyberduck (SFTP)
DarwinPorts (UNIX apps for Mac; from source)
Display Sleeper (immediately put iMac display to sleep)
DoubleCommand (fixes some annoying keyboard issues, such as enabling PC-style home/end)
Firefox (web browser, can be extended with plugins)
- Vimperator (vim bindings)
- Adblock Plus (blocks ads)
- Custom Download Manager (stop download window from popping up)
Google Notifier (automatically checks gmail)
Perian (codecs for quicktime, make it usable)
Quicksilver (many-featured launcher, including a plugin for iTunes)
Spark (bind hotkeys to applescripts, iTunes actions, and application launches)
Terminal
- Terminal.app Tab Namer (Change tab names)
- Terminal Colours (fix that unreadable blue, adjust other colors to liking)
- Visor ("quake-style" terminal summoned/dismissed via hotkey)
TinkerTool (misc hidden OS X preferences, including disabling 3D dock effect)
VLC (play/stream video)

Wednesday, June 10, 2009

Global hotkeys in Windows Media Player

The main reason I used to use Winamp was for a feature called "global hotkeys". This let me assign arbitrary keys to play/pause, fast forward, etc, while Winamp was minimized (it even worked while playing full-screen games!) Turns out you can do the same thing (for my purposes, at least) in Windows Media Player with something called WMP Keys. (Instructions on linked page.)

Monday, June 1, 2009

Matrix transformations and gluLookAt in Cg

OpenGL has some nice helper functions for matrix manipulation: glTranslate, glRotate, and glScale.

GlRotate is especially involved, so I made a version in Cg (based on the matrix in the spec):

float4x4 getRotateMatrix(float theta, float3 axis) {
float x = axis.x, y = axis.y, z = axis.z, c = cos(theta), s = sin(theta);
float4x4 matrix = float4x4(
x*x*(1-c)+c, x*y*(1-c)-z*s, x*z*(1-c)+y*s, 0,
y*x*(1-c)+z*s, y*y*(1-c)+c, y*z*(1-c)-x*s, 0,
x*z*(1-c)-y*s, y*z*(1-c)+x*s, z*z*(1-c)+c, 0,
0, 0, 0, 1
);
return matrix;
}


Another especially useful function is gluLookAt, which lets you specify camera position and tell it to look at a specific point. I downloaded the Mesa3D code and made the following Cg function based on it:

float4x4 getLookAt(float3 eye, float3 center, float3 up) {
float3 forward = normalize(center - eye);
float3 side = normalize(cross(forward, up)); /* Side = forward x up */
up = cross(side, forward); /* Recompute up as: up = side x forward */

return float4x4(
side.x, up.x, -forward.x, -eye.x,
side.y, up.y, -forward.y, -eye.y,
side.z, up.z, -forward.z, -eye.z,
0, 0, 0, 1
);
}

Thursday, May 28, 2009

Using opengl, glut, and cg with Visual Studio

These pages describe the process (the first one is out of date, but the changes to directory structure are minor):

OpenGL and GLUT
Cg

In case those pages go away, it boils down to this:

GLUT

  • Get GLUT for Win32

  • Copy...


    • glut32.dll to %WinDir%\System

    • glut32.lib to $(VSDir)\VC\lib

    • glut.h to $(VSDir)\include\GL


  • ...where $(VSDir) is something like C:\Program Files\Microsoft Visual Studio 9.0\VC


Cg


Visual Studio

  • Make a new Win32 Console Application project: File->New Project->Visual C++->Win32->Win32 Console Application

    • In the "Application Settings" page of the wizard, make sure Application type is Console Application and Empty project (under Additional options) is checked.

  • Go to Project->(project name) Settings


    • Set Configuration to All Configurations

    • Expand Configuration Properties

    • In C/C++->General, add $(CG_INC_PATH) to Additional Include Directories

    • In Linker->General, add $(CG_LIB_PATH) to Additional Library Directories

    • In Linker->Input, add opengl32.lib glu32.lib glut32.lib cg.lib cgGL.lib to Additional Dependencies


Friday, May 22, 2009

Changing vertex processing inside glBegin()/glEnd()

It appears you CAN NOT change shaders in the middle of a glBegin()/glEnd() block. That is, the following code will not switch between vert_main and vert_shadow:

glBegin(GL_TRIANGLE_STRIP); {
for (int v = 0; v < 4; v ++) { cgGLBindProgram(vert_main); glVertex3fv(VERTS[FACES[f][v]].xyz); cgGLBindProgram(vert_shadow); glVertex3fv(VERTS[FACES[f][v]].xyz); } } glEnd();


Looks like I *should* have seen this in the documentation: "Only a subset of GL commands can be used between glBegin and glEnd."

OS X as guest under Linux?

Here I will chronicle some attempts to run OS X as a guest OS on Linux.

My preference would be to use Sun's VirtualBox, since it looks pretty slick and is free. First, looks like I'll need an iso. Not sure if this requires special changes to the iso, or if a straight rip from a legit disk will work. I'm going to look for an iso online for now.

Ubuntu on Mac hardware info
https://help.ubuntu.com/community/MacBookAir1-1/Intrepid?action=show&redirect=Macbook_Air

Qemu
An interesting other note: someone on Ubuntu forums claims to have it working with Qemu, although there is no proof or additional info:

"I have a running OS X on Qemulator (Qemu+KQemu)

qemu -M pc -hda /home/juancarlospaco/OSX -soundhw ac97 -m 1024 -cdrom /home/juancarlospaco/10.5.5/10.5.5.iso -net nic,vlan=0 -net user,vlan=0,hostname=OSX -boot d"

stay tuned...

Sunday, April 26, 2009

Lock the screen and turn off iMac display

Here's how I got my iMac to (effectively) lock the screen and sleep the display:
  1. Get Spark (for the keyboard shortcut)
  2. Get SleepDisplay (to sleep the display)
  3. Check "Require password to wake this computer from sleep or screen saver" in System Preferences->Security->General
  4. Create a new AppleScript Action in Spark with the following code:
do shell script "/Applications/SleepDisplay.app/Contents/MacOS/sleepdisplay"
do shell script "/System/Library/Frameworks/ScreenSaver.framework/Resources/ScreenSaverEngine.app/Contents/MacOS/ScreenSaverEngine -module 'Computer Name'"

If you don't need to sleep the iMac display (have an external monitor with a power button), you can do this:
  1. Check "Enable fast user switching" in System Preferences->Accounts->Login Options
# This brings up "switch users", but doesn't keep the display killed
do shell script "/System/Library/CoreServices/Menu\\ Extras/User.menu/Contents/Resources/CGSession -suspend"

"Friendly" terminal placement with applescript

A lot of my work flow involves opening new terminals. Unfortunately, OS X almost always puts its new terminals right on top of its old ones, which is not terribly useful to me. With a bit of Applescript (launched by Spark), I make them launch to the side of the current (active) window. It's a good start, at least.


# Get topmost app
tell application "System Events" to set frntProc to name of every process whose frontmost is true and visible is true
tell application named (item 1 of frntProc) to set currBounds to the bounds of the front window

# Get desktop bounds
tell application "Finder" to set desk to the bounds of the window of the desktop

tell application "Terminal"
activate (do script with command "")

set newBounds to the bounds of the front window

# Get the distances we're working with
set onLeft to (item 1 of currBounds)
set onTop to (item 2 of currBounds)
set onRight to ((item 3 of desk) - (item 3 of currBounds))
set onBottom to ((item 4 of desk) - (item 4 of currBounds))

set newW to ((item 3 of newBounds) - (item 1 of newBounds))
set newH to ((item 4 of newBounds) - (item 2 of newBounds))

if (onRight > newW) then
set the bounds of the front window to {item 3 of currBounds, (item 2 of currBounds) + newH, (item 3 of currBounds) + newW, (item 2 of currBounds) + newH * 2}
else if (onBottom > newH) then
set the bounds of the front window to {item 1 of currBounds, (item 4 of currBounds) + newH, (item 1 of currBounds) + newW, (item 4 of currBounds) + newH * 2}
else if (onLeft > newW) then
set the bounds of the front window to {(item 1 of currBounds) - newW, (item 2 of currBounds) + newH, item 1 of currBounds, (item 2 of currBounds) + newH * 2}
else if (onTop > newH) then
set the bounds of the front window to {item 1 of currBounds, item 2 of currBounds, (item 1 of currBounds) + newW, (item 2 of currBounds) + newH}
end if

end tell

Sunday, April 19, 2009

Launch X apps remotely through ssh

Launch my_X_prog remotely over ssh:
env DISPLAY=:0 ./my_X_prog

Friday, April 17, 2009

for loop with numbers in bash

Lately, I was trying to download back issues of web comics. Bash supports for loops with numbers, but I needed leading zeros. Apparently the seq command can do this. Here's the loop I used:

for i in $(seq --format="%02.f" 1 17); do
echo "wget http://archive.leasticoulddo.com/strips/200904$i.gif";
done

Sunday, April 5, 2009

Several tables side by side (without nesting)

This page shows a technique for putting several tables side by side, and explains some compatibility issues.

Here's the style ([] for posting...should be <>):
[code]
[style type="text/css"]
table{vertical-align:top}
table.inline{display:inline-table}
.inline{display:inline}
[/style]
[/code]

...and how you use it (same deal with []):
[code][table class='inline'][tr][td]blah blah blah...[/td][/tr][/table][/code]

Friday, April 3, 2009

Prevent new fvwm windows from covering gnome panel

You can tell fvwm to put windows where they will cover as few existing pixels as possible with:
Style * MinOverlapPlacement

I like to use fvwm as my wm for gnome. To make the gnome panel act more like it does in gnome:
Style "*panel" NotTitle, !Borders, NoHandles, Icon, Sticky, WindowListSkip, CirculateSkip
(this may be overkill, but it works for me)

To prevent auto-placed windows from covering the gnome panel (or similar windows marked as Icon or with EWMH Struts enabled):
Style * MinOverlapPlacementPenalties 1 5 9999999 1 0.05 9999999
Note: the small values are based on the defaults, according to the man page. The large number was chosen to be larger than any (sane) resolution you might use (ie: 1600x1200=1920000 or 2*1280x1024=2621440). This obsene penalty for Icon or Struts windows ensures they won't be covered by new windows.

Tuesday, March 31, 2009

Copy an existing MySQL table to a new table

From here:

To make a copy of the table recipes which is in a different database called production into a new table called recipes_new in the currently selected database, use these two commands:

CREATE TABLE recipes_new LIKE production.recipes;
INSERT recipes_new SELECT * FROM production.recipes;

The first command creates the new table recipes_new by duplicating the structure of the existing table. The second command copies the data from old to new.

Saturday, March 14, 2009

Read csl_status twitter feeds in ruby (via RSS)

The Cal Poly computer science lab admins started a twitter page with updates about downed servers, etc. The following ruby script grabs the most recent entries (via RSS), and formats the dates purty.


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

$BOLD = "\e[1m"
$NORMAL = "\e[m"

num = ARGV.length > 0 ? ARGV[0].to_i : 1

# Read cls_status twitter RSS feed
source = "http://twitter.com/statuses/user_timeline/19618428.rss"
content = ""
open(source) do |s| content = s.read end
rss = RSS::Parser.parse(content, false)

(0..(num-1)).each do |i|
diff = Time.now - rss.items[i].date
days = diff.to_i / 86400
hrs = (diff % 86400).to_i / 3600
mins,secs = *((diff % 3600).divmod(60))

print "#{$BOLD}"
print "#{days} days " if (days > 0)
print "#{hrs} hrs " if (hrs > 0)
print "#{mins} mins " if (days == 0 and mins > 0)
print "#{mins} secs " if (mins == 0)
puts "ago"

#puts "#{$BOLD}#{rss.items[i].date}"
puts "#{$NORMAL}#{rss.items[i].title}"
#puts rss.items[i].description
#puts rss.items[i].link
end

Cron entry for upcheck on Spot

Note to self: cron entry for "upcheck", which runs every 10 minutes and outputs any errors to a file

0,10,20,30,40,50 * * * * ruby /home/iggames/bin/upcheck.rb >> /home/iggames/bin/upcheck.log

Tuesday, March 10, 2009

wmii-like window movement in FVWM

In the wmii window manager, you use Alt + the vim movement keys (h/j/k/l) to switch windows relative to your current window (ie: Alt+J to select the window below you).

Turns out you can do the same thing in FVWM:
Key K A M Direction North (CurrentDesk) FlipFocus
Key J A M Direction South (CurrentDesk) FlipFocus
Key H A M Direction West (CurrentDesk) FlipFocus
Key L A M Direction East (CurrentDesk) FlipFocus


I'm not exactly sure what FlipFocus does vs just Focus, but it works the way I'd expect. (Selects relative to current window, choosing only among windows on the current desktop)

Saturday, March 7, 2009

The Z-buffer equation

I found an explanation for how OpenGL calculates z values here. It's handy if you want to do your own custom rendering in shaders and match OpenGLs depths for other objects.

Here's a function I wrote to compute it, based on the given distance:

float getDepth(float dist) {
float zNear = 0.1, zFar = 1000; // from main.cpp
float a = zFar / (zFar - zNear);
float b = zFar * zNear / (zNear - zFar);
float z = dist;
return a + b / z;
}

Friday, February 27, 2009

Batch rename files with bash

How to batch rename files in a one-line bash script:

for f in *.txt; do mv ./"$f" "$f.newname"; done

and the other direction:

for f in *.mine; do mv $f `echo $f | sed 's/\(.*\).newname/\1/'`; done

From this post.

Tuesday, February 10, 2009

Changing eclipse "highlight occurences" color

When you click on something in eclipse (say, a variable), it highlights all occurrences of that variable. The default color does not work well for dark themes. The color is changed from:

Window->Preferences->General->Editors->Text Editors->Annotations->(C/C++) Occurrences

Friday, January 23, 2009

error C1019: scalar Boolean expression expected

While working on my GPU raytracer, I've come across the following Cg error a few times: error C1019: scalar Boolean expression expected. Weirdly, it only threw this error on the machines at school (the Cg shader code is compiled at run-time). Though the line numbers don't make this clear, the problem code appears to be this:

float4 val = readFloat4FromTexture();
if (val != float4(1,1,1,1)) {
...
}


I haven't investigated why this works at home and not school (different Cg compiler versions?), but I fixed it by changing to this:

...
if (val.x != 1 && val.y != 1 && val.z != 1 && val.w != 1) {
...
}


I wasn't able to find *anything* about the error on Google or in the Cg documentation, so hopefully this is useful if anyone else has this problem.

Wednesday, January 7, 2009

Getting useful errors from Cg

Since Cg programs are compiled at the program's runtime, you must catch Cg compile and runtime errors from within your program. Here's how:

First, you will need a callback. Cg will call this function whenver there is an error. Example:

void MyErrorCallback(void) {
CGerror error = cgGetError();
const char* errorString = cgGetErrorString(cgGetError());
printf("Cg error: %s\n", errorString);

// check for compiler errors
if (error == CG_COMPILER_ERROR)
printf("%s\n", cgGetLastListing(context));
}


Next, you need to set the callback:
cgSetErrorCallback(MyErrorCallback);

Now you should get more useful output when Cg has problems.

And easy way to make for loops unrollable

Cg will let you use for loops in your shaders, but only if they can be unrolled. Though it loses you the performance benefits of loop unrolling, you can make a for loop unrollable by moving the guard (or "are we done yet?" check) into the loop body.

For example:

int arr[] = {2, 1, 3};
for (int i = 1; i < arr[0]; i ++) {
doStuff(arr[i]);
}

That snippet gives an error like this when you try to compile it:
frag.cg(71) : error C5013: profile does not support "for" statements and "for" could not be unrolled.

Instead, try the following:

int arr[] = {2, 1, 3};
for (int i = 1; i < MAX_LEN; i ++) {
doStuff(arr[i]);
if (i == arr[0])
break;
}


EDIT:
Or better yet, just do this:

int arr[] = {2, 1, 3};
for (int i = 1; i < MAX_LEN && i < arr[0]; i ++) {
doStuff(arr[i]);
if (i == arr[0])
break;
}


Note that I found order to be important (it didn't like arr[0] before MAX_LEN).

Saturday, January 3, 2009

Custom command keybindings in Gnome

Gnome (or, more precisely, Metacity), will let you create 12 custom key bindings. That is, you can set 12 custom commands that are triggered by a given key sequence.

This is done in Configuration Editor (System Tools -> Configuration Editor; enable it in "Edit Menu" if it isn't there). The first custom command is set with /apps/metacity/global_keybindings/run_command_1. The associated keybinding is set with /apps/metacity/keybinding_commands/command_1.