★ A simple 3D object graphics example
posted Wed 4 Oct 2006 by Michael Galloy under IDL, Object graphics
The main problem that programmers new to object graphics have is getting anything to appear on the screen (at least anything they recognize). Once you have your graphics appearing in a window, it’s pretty simple to change their properties, rotate them, make them dance the rhumba, etc.
There are various ways to scale your data into the view volume. This article will show one scaling technique I like for displaying 3D objects: using the [XYZ]COORD_CONV properties of a graphics atom object.
The code for the example is MG_CC_DEMO (doc) and a helper routine MG_LINEAR_FUNCION (doc).
The simplest possible object graphics hierarchy is an IDLgrView containing an IDLgrModel which contains a graphics atom object.
oview = obj_new('IDLgrView')
omodel = obj_new('IDLgrModel')
oview->add, omodel
The surface object has many properties effecting its display. Here, style=2 is a shaded surface, while COLOR and BOTTOM set the color of the top and bottom of the surface.
osurface = obj_new('IDLgrSurface', hanning(20, 20), style=2, $
color=[255, 0, 0], bottom=[100, 0, 0])
omodel->add, osurface
The default lighting model is an ambient light that will cause 3D objects to look flat like a silhouette. I put the light in its own model so that when I rotate the model containing the surface the light will stay fixed. Here, type=2 specifies a directional light coming from [1, 1, 1] and heading towards the origin.
olightmodel = obj_new('IDLgrModel')
oview->add, olightmodel
olight = obj_new('IDLgrLight', type=2, location=[1, 1, 1])
olightmodel->add, olight
The hierarchy is complete, but we need to change some properties to get a more reasonable display. The most important task is to make sure the data space is scaled into the coordinates of the view. The default coordinates of the view vary from -1 to 1 in every dimension. First, we need to know the extent of our data in each dimension.
osurface->getProperty, xrange=xr, yrange=yr, zrange=zr
The two-element arrays xr, yr, and zr contain the minimum and maximum value of their respective variables. A handy routine MG_LINEAR_FUNCTION produces a linear function which scales its first argument into its second argument. (A lot of people use the IDL library routine NORM_COORD to do this. NORM_COORD is like MG_LINEAR_FUNCTION with a second argument that is always [0, 1], so it must be shifted to use the range [-0.5, 0.5] and other ranges require some algebra.)
xc = mg_linear_function(xr, [-0.6, 0.6])
yc = mg_linear_function(yr, [-0.6, 0.6])
zc = mg_linear_function(zr, [-0.6, 0.6])
The two-element arrays xc, yc, and zc are the coefficients of linear functions. These are the appropriate values for the `[XYZ]COORD_CONV properties of the surface.
osurface->setProperty, xcoord_conv=xc, ycoord_conv=yc, zcoord_conv=zc
The default orientation will be looking straight down on the surface. A better orientation will make the shape of the surface more apparent. Remember: the model is responsible for holding the transformation matrix, so use methods on the model to rotate, scale, or translate.
omodel->rotate, [1, 0, 0], -90
omodel->rotate, [0, 1, 0], 30
omodel->rotate, [1, 0, 0], 30
Finally, create a destination, here an IDLgrWindow, and use its draw method.
owindow = obj_new('IDLgrWindow', dimensions=[400, 400])
owindow->draw, oview
Don't forget to destroy the view object when you're done with the object graphics hierarchy. It will in turn destroy the objects that are contained in it. The owindow object will be destroyed when the user closes the window.
obj_destroy, oview

October 6th, 2006 at 4:23 pm
Another way to go about this is to extend
IDLgrModel. I’ve done so with this autoScale method. Its calling syntax is simple:omodel->autoscale, oatomI admit it’s probably more appropriate to subclass
IDLgrModeland implement this method in the subclass, but it’s cool that the above technique is possible in IDL. Another neat quirk of our favorite quirky language!December 20th, 2007 at 10:47 am
Thanks for this easy example. It worked fine but the problem I am having very hard time is any real world IDL 3D example. I have netcdf data and am trying to render a 3D surface view of it, it looks like crap and I can’t figure out how to view it correctly.
IDL has great examples using the hanning and DIST functions, but modifying examples to use real data is proving difficult. Agreed I am learning this but any help appreciated.
December 21st, 2007 at 10:32 am
What don’t you like about you output? I imagine the next biggest issue people have after getting the thing to show on the screen is getting the scale for each dimension (i.e. the “vertical exaggeration”) correct. Is that the issue?