Wednesday, October 3, 2007

OpenGL...

As you may have guessed from the oh-so-classy title of this post, I will be talking about OpenGL today.

I'm taking a graphics class this quarter, which entails lots of OpenGL-type things. Thankfully, our teacher has made the class fairly language agnostic, so I am free to use OpenGL from any language of my choosing (i.e. Python). Fortunately for me, there is a Python module which wraps the raw OpenGL/GLUT/GLU calls in all of their ugly C glory.

One thing to know about OpenGL is that when you use it, there is a huge clockwork mechanism that is entirely hidden from you and your program (well... as hidden as anything in C/C++ is). Every time you make a gl call, it returns immediately, many times with a void return. Every single function in OpenGL operates purely in a side-effecting manner. When you make a glVertex3fv(...) call, a vertex is transformed and placed somewhere.

Once you realize this, however, OpenGL is very much like an assembly language for your graphics card. Yes, you have to manually specify the normals for every vertex manually (there are some exceptions), but it does mean you can have a flat surface with some vertices pointing in odd directions (which will cause their polygon to be lit differently). If you had a dense enough mesh, you could conceivably get extremely cheap bumpmaping by randomly perturbing (or perturbing by some pattern) the normals of vertices.

Unfortunately (or fortunately), all of this low-levelness exists in the Python implementation as well. Because of this, your program will be rapidly bouncing back and forth from Python-land to C-land to OpenGL-land and back, which can be a bit slow... Fortunately, OpenGL has some tricks you can use to speed up it's performance in Python. One of these methods is to store Draw Lists of common commands.

For example, say you load in an 8000 vertex model. You could have a 'draw' function that goes through a list (or array) for vertices, and makes the appropriate glVertex call for each one of them. This has the consequence of being RIDICULOUSLY SLOW, but it works. Alternately, you can tell OpenGL that you are going to be compiling a Draw List with:

# This is a class method.  s is the object that the method is executed on
def makeDl(s):

  glNewList(s.dlid, GL_COMPILE)
  glPushMatrix()
  glMatrixMode(GL_MODELVIEW)

  glTranslated(*s.kw['position'])
  glScaled(*s.kw['scale'])
  for t,axis in s.kw['rotation']: glRotated(t, *axis)
  glMaterialfv(GL_FRONT, GL_DIFFUSE, s.kw['mat'])

  # s.fn is a pre-set function which could be anything from a glut primitive
  # call to a method that enumerates the points (and possibly materials) in
  # a mesh.
  s.fn(*s.args)

  glPopMatrix()
  glEndList()
When you want to have OpenGL execute the list, you just make a call to
def draw(s):
  glCallList(s.dlid)

glCallList will pull up the elaborate draw list data structure, hidden somewhere in OpenGL-land, and execute every command in it. This prevents the Python program from becoming a horrible, horrible slideshow :-), especially for large meshes.

I'm still learning bits and pieces of OpenGL to make things faster/better/bigger/more colorful, etc. Right now I'm trying to figure out more complicated materials (i.e. textremapping, other maps (normal, bump, emission, etc.), and shaders), and also how to use things like vertex buffers to let the GPU render stuff while Python chunks along. I'll figure it all out eventually ;-)

Monday, September 3, 2007

How to make pretty pictures...

Greetings (to whomever reads this anyway...)!!!!

So doing GUI development sucks. Like... really sucks a lot. But sometimes you just want to visualize some data, like with a graph, histogram, or whatever. Sure, you could just copy and paste the data into Excel. But we're programmers, and that thought bores us... (And don't say ANYTHING about VBA, or I'll bludgeon you).

So where is an unhappy programmer to turn in this dire situation? PyLab to the rescue! PyLab (also matplotlib) is a MatLab-like interface for graphing data in Python. It has quite a number of backends, and has a very useful shorthand interface.

For Example:
#!/Library/Frameworks/Python.framework/Versions/Current/bin/python
from pylab import *
from matplotlib.finance import quotes_historical_yahoo
from matplotlib.dates import YearLocator, DayLocator, MonthLocator, DateFormatter
from matplotlib.ticker import FuncFormatter
from datetime import date

d1, d2 = date(2006, 9, 17), date(2007, 9, 17)
msft = quotes_historical_yahoo('MSFT', d1, d2)
intl = quotes_historical_yahoo('INTL', d1, d2)

ax = subplot(111)
plot_date([x[0] for x in msft], [x[1] for x in msft], fmt="b-")
plot_date([x[0] for x in intl], [x[1] for x in intl], fmt="g-")

ax.xaxis.set_major_locator(YearLocator())
ax.xaxis.set_major_formatter(DateFormatter("%Y"))
for tick in ax.xaxis.get_major_ticks():
   tick.set_pad(20.)

ax.xaxis.set_minor_locator(MonthLocator())
ax.xaxis.set_minor_formatter(DateFormatter("%b"))

ax.yaxis.set_major_formatter(FuncFormatter(lambda x,y: "$%d"%x))

ax.format_xdata = DateFormatter('%Y-%m-%d')
ax.format_ydata = lambda x: '$%1.2f' % x

grid(1)
legend(('MSFT', 'INTEL'))
ylabel('Opening Price')
show()
Produces:

Sunday, September 2, 2007

VIMTip from a while back

I figured out how to get vim to interact reliably with the clipboard to allow users to copy and paste from vim on an intra-line level. The only tricks I had seen before restricted copy+pasting to the line level (blah). So here's a link to the vimtip. On OS X, it looks something like:
vmap <C-c> y:call system("pbcopy", getreg("\""))<CR>
nmap <C-v> :call setreg("\"",system("pbpaste"))<CR>p
This basically sets it up so that when you select any shape in visual mode (visual-blocks too), pressing Ctrl-C (not Cmd), will send that chunk of text the system clipboard.

There is also a mechanic for making it work with Linux as well. I've toyed with the idea of making it copy on every y/d/c/s as well, but I do that enough that it would destroy the system clipboard every time I used vim :P. Oh well.

Saturday, September 1, 2007

Syntax highlighting, UML, etc.

So immediately on getting this blog, I noticed that I needed to immediately remedy the lack of syntax highlighting. After a little bit of poking around the blagoweb, I found this nifty little set of javascript. It has the added bonus that it puts all the processing requirements on you, my dear readers :-). Poking around in the files reveals that the highlight definition files are very human readable (assuming you speak regular expressions), and highly customizable. I added number highlighting to the original script, because I like to see when there are magic numbers lurking in my code.

Also in my travels recently, I have come across UMLGraph, which is sheer awesomeness. It basically allows you to write a Java skeleton of your program, and generate a nice, readable (ha) dot file of the UML object layout. Saves me from having to remember which arrows are supposed to point to which objects in which directions with the proper dash-ed-ness of the lines. The package also has the ability to generate pic files for process trees. Wish I knew about this when I was doing CSC305!!

Also, this is a really cool blogging site... it lets you get access to the HTML template for the blog, as well as all posts, etc., and insert arbitrary javascript/css/whatever I want. I already adjusted the template width to allow for the syntax highlighter to display 80 column code and to install the syntax highlighter. There probably aren't any server-side extensions though... that would just be asking for trouble. But since I can make arbitrary links, there's nothing to prevent me from linking to my own webserver.

Last but not least, Vimperator has to be the coolest extension for firefox in existance. No VIM keybindings on text entry boxes (yet), but it allows complete control of firefox using (more or less) standard VIM keybindings. Very useful. The new QuickMarks feature is pretty awesome too. It allows you to associate a letter with any URL, and then access that URL by pressing 'go'+<key>. For example, I have viperphish-code.blogger.com set to 'l', and to get here, I just press 'gol' ('gnl' if I want to open it in a new tab). 'f' is facebook, 'p' is pandora.com, 'b' is biblegateway.com etc. Super cool.^[:wq

First post!

Hullo all...

So I've decided to make a new blog dedicated to all of the programming-related stuff that I come across, including new utility programs, toolkits, programming tricks ("techniques" :P ). I really don't know how often I will update it, but I've often found myself in a position where I want to show/remember stuff to other people/myself.

So, to commemorate this new blog, I will leave you with the following:
main(){long long l=0XA3F018063B030074LL,m=0X87EA9EA9,p=0X64039820;char*s=" l";
for(;m;p/=2,m/=4,l>>=4)putchar(s[(p&1)+1]+(p>>16&1?-1:1)*(l&15)+((m&3)-2)**s);}
Compile with gcc 4.*