Composer | Performer | Songwriter | Music Technologist | Intermedia Artist | Producer
A Guide to OpenGL in Max/MSP/Jitter
June 12, 2014 | Hassan Estakhrian
OpenGL is a programming language for rendering 2D and 3D vector graphics. It simulates a three-dimensional world onto a two-dimensional platform and is commonly used for video game development among other things. Jitter supports many OpenGL functions, a few of which will be discussed in the following six tutorials.
To simulate a three-dimensional environment, OpenGL uses three axes- X, Y, and Z. The X-axis runs along the horizontal plane, the Y-axis runs along the vertical plane, and the Z axis runs along the foreground and background, representing the depth (creating the effect of a 3 dimensional space). In the OpenGL world, the zero position for all axes is the center point of the screen with the positive coordinates being right for X, up for Y, and front for Z (towards the viewer). The negatives coordinates are of course the opposite- left, down, and back, respectively. Here is a visual representation of the three axes:
Placing a model in a 3D rendered world
(copy text from opengl_tut_1.doc and select New From Clipboard in Max)
Now that you have a basic understanding for potential coordinates in the openGL three-dimensional environment, let’s place an object in it. To do so, first we must create a place to render our 3D world. Create and connect the following objects sequentially: toggle, qmetro set to 33 milliseconds, trigger with a “bang” and “erase” argument, jit.gl.render. Be sure to send both the “erase” and “bang” messages to jit.gl.render. It is a good idea to provide a name for your rendered space so you can tell other objects to render in that space. Give your jit.gl.render object the name “space”. Also create a jit.window object and give it the same name.
This configuration will re-render your 3D world every 33 milliseconds. View the 3D world by double-clicking on “jit.window space.” A window should pop up with the name “space” in its header.
Now we can proceed to place an object in this 3D world. Create a jit.gl.model object with the argument “space” (so it will render in the appropriate location), and attach the message “read starfish.obj” (this file is included with Max 6). Click the message. You should see a grey starfish appear in the “space” window.
Note that the background (or empty space) in the openGL environment default to a dark grey color. To change this to black in jit.gl.render add the attribute “erase_color 0. 0. 0. 1.” Or for a white background use “erase_color 1. 1. 1. 0.”)
To rotate the starfish model with your cursor, create a jit.gl.handle and name it space. Click and drag the cursor over the starfish and notice that it can be freely rotated.
Notice how there is no depth to the starfish. That is because the same color and lighting is being equally represented at all points on the object causing the model to look flat. Add the attribute “enable_lighting” with the argument of 1 to your jit.gl.model and re-click the “read starfish.obj” message (Note that you need to re-click the read message anytime the attributes and arguments within the jit.gl.model object are altered). Now the starfish should appear more 3D-like.
Add the attribute and argument “smooth_shading 1” to smoothen out the model.
*jit.gl.model supports any obj files. Many free obj files are available to download at tf3dm.com.
Applying color to a model
(copy text from opengl_tut_2.doc and select New From Clipboard in Max)
In jit.gl.model the “material_mode” attribute default is on. It needs to be turned off in order for the “color” attribute to be applied. Add “@material_mode 0” to do so. Now you can change the color of the starfish by adding the “color” attribute followed by four floating point arguments that correspond to RGBA (red, green, blue, alpha). For example if you typed “@color 1. 0. 0. 1.” the starfish would be red. Likewise, if you typed “@color 0. 1. 0. 1.” it would be green.
Probably a better way to test out prospective colors is to create a “pak” object with the argument “color f f f f.” Attach 4 flonums to its 2nd, 3rd, 4th, 5th inlet and connect the outlet to the left inlet of jit.gl.model. This way you can quickly change values and see the results immediately without re-clicking the read message each time you alter the attribute of jit.gl.model.
Rotating, Scaling, and Positioning a Model
(refer to opengl_tut_2)
Possibly one of the most useful tools within Max is the “attrui” object. When hooked up to another object, the attrui displays any attributes that correspond to that particular object. Hooking up an attrui to jit.gl.model, you can quickly see just how many attributes can be applied. Create 3 attrui objects and select rotatexyz, scale, and position. In each attrui, the attribute automatically displays to the set values.
Position defaults to “0. 0. 0.” As discussed earlier, the 3 values correspond to the X, Y, and Z axes. These coordinates places the model in the center of the 3D rendered world. The first value (X axis) will move the model horizontally (left of center for a negative value and right of center for a positive value), the second value (Y axis) will position the object vertically (up for positive and down for negative), and the third value (Z axis) will place the model either towards the foreground (positive value) or the background (negative value).
Scale defaults to “1. 1. 1.” The 3 values also correspond to the X, Y, and Z axes. Changing the first value will either shorten or lengthen the model along the X axis. Likewise for the second and third values (Y and Z axes).
Rotatexyz defaults to “0. 0. 0.” Each parameter corresponds to each axis. The model comes to a full rotation every 360 degrees.
Note that the attrui object will not save your parameter setting for your selected attribute. To save your parameter settings you can type in the attribute with its corresponding values within the jit.gl.model object (ex: “@scale 0.5 0.5 0.5”). Alternatively, you can create a pak object and send “loadmess” with the value to the appropriate inlets or flonum.
Automating a Model
(copy text from opengl_tut_3.doc and select New From Clipboard in Max)
To automate the rotation of the starfish model, first create a pak object with the arguments “rotatexyz f f f” and then attach flonums to the 2nd, 3rd, and 4th inlets. Send the outlet to the inlet of jit.gl.model. Next create a counter object with the arguments “2 0 360.” The 2 tells the counter to count up from the lowest number specified (0) to the highest number specified (360) and then back down. Max refers to this as the palindrome mode. Take the out of the qmetro to the left inlet of the counter. This will trigger the counter every 33 milliseconds which is equal to the time the model is being rendered allowing for a visibly “smooth” motion. Connect the left outlet of the counter to any or all of the flonums attached to the pak object. The starsfish object should be rotating freely.
This technique can easily be applied to other attributes such as position, scale, and color. Just make sure that the values sent from the counter are appropriately scaled to the attributes’ values.
Creating an Automated Backdrop
(copy text from opengl_tut_4.doc and select New From Clipboard in Max)
First we need to create a backdrop to automate. Let’s create a shape and apply a texture to that shape. Here is how it can be done. Create a jit.gl.gridshape object with these attributes and arguments:
The background should now appear grey. The gridshape that was created is a plane and it has been positioned at -20 along the Z axis in the background. Its scale is “14. 10. 1” which is quite large. If it were scaled to its default parameters (1. 1. 1.), it would appear much smaller since it is positioned far in the background. Go ahead and change the scale attribute to “1. 1. 1.” and see how the plane shrinks drastically. Now change the position attribute to “0. 0. 0.” and notice how it eclipse the starfish model because it is now positioned in front of it. Set the attribute parameters back to the above settings (position 0. 0. -20. and scale 14. 10. 1.).
Let’s use an image as a texture on the jit.gl.gridshape. To do this, we must create a jit.gl.texture object and give it a name (“@name back”). Next, let’s connect a jit.matrix to the jit.gl.texture input. Now we need to map an image to jit.matrix by sending it the message “importmovie sunset.jpg, bang.” (this file is included with Max 6). Finally, the texture attribute with the same name given to the jit.gl.texture needs to be added to jit.gl.gridshape (“@texture back”) in order for the texture to be mapped accordingly. Click on the “importmovie sunset.jpg, bang” message and the plane gridshape in the jit.window should now have the imaged applied to it.
Textures can also be applied to jit.gl.model objects in the same fashion.
Audio Controlling Automation
(copy text from opengl_tut_5.doc and select New From Clipboard in Max)
There are of course countless ways to control automation with audio. Here is one way. Start by creating an sfplay~ object with the audiofile attribute followed by the file, “sho0630.aif” (this file is included with Max 6). Connect a loop 1 message and toggle to its left inlet and connect its output to an ezdac~. Make sure to click the “loop 1” message and ezdac~ to activate the audio looper and turn on the audio, respectively. Next, create an avg~ object. This object outputs the average amplitude when a metro object is hooked up to its inlet. Set the metro to 100 milliseconds. Create a “>” object and type inside “0.2”. Whenever the average amplitude over the course of 100 milliseconds reaches 0.2, the “>” will send out a 1 message. Attach a “sel 1” object to the “>” object output and connect the output of the “sel 1” to 3 separate random objects with an argument of 360. These random objects will randomly select 0-359 values and output them to a “pak rotatexyz f f f” object. Connect that “pak” object to a jit.gl.grideshape or jit.gl.model you want to automate (in this example it is being sent to the jit.gl.gridshape plane that is acting as the backdrop in our 3D world. The backdrop should be changing rotation every time the audio reaches the 0.2 amplitude threshold.
(refer to opengl_tut_5.doc)
The viewpoint of the rendered 3D world doesn’t always have to be from the same location. Shapes and models can remain in the same position and the “camera” can move around, change positions, rotate, and look at different points. To control the viewpoint in your 3D universe, create a jit.gl.camera object. Attach three attrui objects to its inlet and select position, rotatexyz, and lookat. Notice how position’s values are default at 0. 0. 2. If it were set to 0. 0. 0., the camera viewpoint would have no visual room to see the center coordinates, much like an eye can’t see an object when it is right up against it. The current coordinate of the Z axis allows for some room to see. Raising the Z value even more brings the camera further back, making the starfish and background appear smaller. The camera can also be rotated in the same fashion as shapes and models with a 360 degree motion for each axis.
Set the position to 0. 0. -50. The camera should see nothing at this point because it has moved passed both the starfish and background plane. Now set the rotatexyz to 180. 0. 0. The background should appear upside-down, but it is not. The camera is the object that is upside-down because it has rotated itself 180 degrees, looking back towards its original position.
The lookat attribute is helpful for looking at specific points in the 3D world, especially when the position values are set to extremes. It can be disorienting and difficult to figure out where in the 3D world the camera is and where to rotate the camera to view the intended source. However, lookat is a fast way to redirect the shot towards its intended source. Notice when the values are changed in lookat it also changes the value of rotatexyz.
At this point, you should have a decent understanding for some of the openGL objects and attributes within Max/MSP/Jitter. For more on openGL in Jitter, check out Jitter Tutorials 30-37 and references below. You can also check out my quasi-video game/multi-media composition, Directional Animal, where I implement these functions.
Elsea, Peter. "OpenGL in Jitter." Tutorials Max/MSP/Jitter. Peter Elsea, 3 Apr. 13. Web. 11 June 2014.
Dobrian, Chris. “Examples [34-37].” Music Technology. Christopher Dobrian, 2 June 2013. Web. 11 June 2014.
"Max 6 Sneak Peek: Jitter OpenGL." YouTube. Cycling '74, 12 Oct. 2011. Web. 11 June 2014.