<?xml version='1.0' encoding='UTF-8'?>

<?xml-stylesheet href="./_c74_tut.xsl" type="text/xsl"?>
<chapter name="Tutorial 30: Drawing 3D text">
<setdocpatch name="30j3DText" patch="30j3DText.maxpat"/>

<previous name="jitterchapter29">Using the Alpha Channel</previous>
<next name="jitterchapter31">Rendering Destinations</next>
<parent name="jitindex">Jitter Tutorials</parent>



<h1>Tutorial 30: Drawing 3D text</h1>
<p>This tutorial shows you how to draw and position 3D text in a <o>jit.window</o> object using the <o>jit.gl.text3d</o> and <o>jit.gl.render</o> objects. Along the way, we will cover the basics of drawing OpenGL graphics using the <o>jit.gl.render</o> object. </p>

<p>The <o>jit.gl.text3d</o> object is one of the many Jitter OpenGL drawing objects that work in conjunction with the <o>jit.gl.render</o> object. OpenGL is a cross-platform standard for drawing 2D and 3D graphics, designed to describe images so that they can be drawn by graphics coprocessors. These coprocessors, also known Graphics Processor Units or GPUs, speed up drawing operations enormously, allowing complex scenes made of textured polygons to be animated in real time. OpenGL graphics can help you create faster visual displays or interfaces without bogging down your computer&#x2019;s CPU.</p>


<p>In the lower left of the patch, there is a <o>jit.window</o> object named <m>hello</m>. This window will be the destination for our OpenGL drawing.</p>

<bullet>Click on the <o>toggle</o> labeled <i>Start Rendering</i>.</bullet>
<p>The toggle starts the <o>qmetro</o> object,which sends <m>bang</m> messages to a <o>trigger</o> object. For each <m>bang</m> received at its inlet, the <o>trigger</o> object sends the message <m>erase</m> out its right outlet, and then a <m>bang</m> message out its left outlet. These messages are sent to the <o>jit.gl.render </o><m>hello</m> object.</p>

<h2>Creating a Drawing Context</h2>
<p>All OpenGL graphics in Jitter are drawn with the aid of <o>jit.gl.render</o> objects. Each <o>jit.gl.render</o> object must refer to a named <i>destination</i> for drawing. You can specify this destination using an initial argument to <o>jit.gl.render</o>. So in this case, <o>jit.gl.render </o> <m>hello</m> creates a <o>jit.gl.render</o> object that will draw to the destination window that we have named <m>hello</m>. </p>

<div>
<techdetail>It&#x2019;s important to note that <m>hello</m> is not the name of the <o>jit.gl.render</o> object&#x2014;only its destination.</techdetail>
</div>
<p>We refer to this combination of a <o>jit.gl.render</o> object and a named destination as a <i>drawing context</i>. A drawing context is required for OpenGL rendering. The objects on the left side of this patch are sufficient to build a valid drawing context, and so when you click on the toggle, the message <m>jit.gl.render: building GL on window &#x2018;hello&#x2019;</m> appears in the Max Console. This tells you that the context is being created.</p>

<illustration><img src="images/jitterchapter30a.png"/>A <o>jit.gl.render</o> object and a named destination create a drawing context</illustration>

<bluebox>
	Note: Max version 7 introduced a new object&#x2014; <o>jit.world</o> which contains a complete drawing context: <o>qmetro</o>, <o>jit.gl.render</o> and <o>jit.window</o> with the escape key linked to fullscrteen display. All you need supply is a <o>toggle</o> and a name.
</bluebox>

<h2>GL Objects in the Context</h2>
<bullet>Click on the <o>message</o> box reading <m>Hello\, Jitter!.</m></bullet>
<div>
<techdetail><i>Technical Detail:</i> The <o>qmetro</o> object is needed in this patch because, unlike most previous tutorial patches, there are no <o>jit.matrix</o> objects present. In complex patches, the drawing or matrix calculations being repeatedly triggered by a <o>metro</o> object may not complete before the next <m>bang</m> is scheduled to arrive. In this example, this situation would occur if the text took more than 40 milliseconds to render. Normally, the Max scheduler would place this <m>bang</m> on its queue&#x2014;a list of pending messages. Max is not normally allowed to drop messages from the queue. So in this patch, if each <m>bang</m> generated a sequence of events that take longer than 40 milliseconds, and no dropping of messages was allowed, the queue would eventually <i>overflow</i>, or run out of space to store additional pending messages. Then the scheduler would stop, and so would your show! This is probably not what you had in mind. The <o>qmetro</o> object (which is really just a combination of a <o>metro</o> object and the <o>jit.qball</o> object&#x2014;see <link type="tutorial" module="jit" name="jitterchapter16">Tutorial 16</link>) helps you avoid this situation by dropping any <m>bang</m> messages that are still pending during a calculation. If a <m>bang</m> is scheduled to occur while the rest of the patch is rendering, it will be placed in a queue. If that <m>bang</m> still hasn't been passed to the rest of the patch by the time the next <m>bang</m> occurs, the first <m>bang</m> will be <i>usurped</i> by the second, which will be placed next in the queue. And so on.</techdetail><br/>

<techdetail>Let&#x2019;s say the output of a <o>metro</o> object set to output a bang every 10 milliseconds is sent to a <o>jit.movie</o> object, followed by some effects that take 100 milliseconds per frame to draw. So the <o>jit.movie</o> object will receive 10 <m>bang</m> messages during the time the effects are being calculated. The <o>jit.movie</o> object knows in this case that the processing is not yet complete, and instead of sending out ten <m>jit_matrix</m> messages next time it has a chance, it drops all but one. While the <o>jit.movie</o> and <o>jit.matrix</o> objects have this capability built in, the <o>jit.gl.render</o> object does not. This is because the <o>jit.gl.render</o> object will often need matching groups of messages in order to draw a frame properly. In this example, the <m>erase</m> message is needed to clear the screen, and the <m>bang</m> message draws the text. If an <m>erase</m> message was dropped to avoid overflowing the queue, multiple <m>bang</m> messages might be processed in a row, and multiple copies of the text would be drawn at once, which is not what we want to do. As patches get more complex, different kinds of visual artifacts might result. So, the <o>qmetro</o> object is provided to let the designer of the patch decide what messages to drop from the queue. In this example, as in most cases, simply substituting <o>qmetro</o> objects for <o>metro</o> objects insures that the drawing will always look correct, and the queue will never overflow.</techdetail>
</div>

<h2>Common 3D Attributes</h2>
<p>All Jitter OpenGL objects (which all begin with "jit.gl") share a common set of attributes that allow them to be positioned in 3D space, colored, and otherwise modified&#x2014;the <i>GL group</i> (ob3d). Drawing 3D graphics can be a fairly complex task. The ob3d group simplifies this by insuring that the messages you learn to draw one 3D object will work with all of them, whenever possible. These common attributes are fully documented in the <i>GL group</i> section of the <i>Object Reference</i>  of any jit.gl object. To introduce the 3D group here, we will demonstrate the position, rotation, scale and axes attributes by manipulating the <o>jit.gl.text3d</o> object. </p>

<p>We can add a set of spatial axes to the <o>jit.gl.text3d</o> object to make our spatial manipulations easier to see and understand&#x2014;it's both easier to see how the text object is oriented, and also to see additional information about exactly where the object&#x2019;s origin is.</p>

<bullet>Click on the <o>toggle</o> connected to the <o>message</o> box reading <m>axes $1</m> in order to see the 3d object&#x2019;s axes.</bullet>
<illustration><img src="images/jitterchapter30b.png"/>The 3D text at the origin</illustration>


<p>The <i>x axis,</i> drawn in in red, points to the right. Zero is at the center of the screen, and increasing x values move in the direction of the right of the screen. The <i>y axis</i>, drawn in green, points upwards, and the <i>z axis, </i><i>drawn in blue,</i> points out of the screen towards you (since it is pointed directly toward you, you will only see a small blue dot). These axes represent the object&#x2019;s local coordinate system as it moves through the world. When a GL group object is first created, its local coordinate system is not rotated, translated, or scaled&#x2014;it has the same coordinate system as the rest of the 3D world, by default</p>

<p>The text &#x201C;Hello, Jitter!&#x201D; is displayed in the <o>jit.window</o> object's display area, but it starts at the center of the screen, so the final part is cut off. Let&#x2019;s move the text to the left. </p>

<bullet>Set the <o>number</o> box labeled <i>x</i> in the <i>Common 3D attributes</i> section of the patch to the value <m>&#x2013;1</m>.</bullet><br/>
<p>The Number box sends a floating-point value to the <o>pak</o> object, which sends the message <m>position</m> followed by three numbers to the <o>jit.gl.text3d</o> object. As you change the value in the number box, you can see the text slide to the left until all of it is visible on the screen. </p>

<illustration><img src="images/jitterchapter30c.png"/>Changing the position attribute</illustration>

<p>We have just changed the position attribute of the <o>jit.gl.text3d</o> object. The <m>position</m> message can be followed by three number arguments that set the position of the object in three dimensions. If fewer than three numbers follow the position message, the axes are filled in the order [x, y, z], and the position of the object on the unspecified axes is set to 0. For example, sending the message <m>position 5</m>. will set the position of a GL group object to the location [5, 0, 0].</p>

<p>The operation of changing an object&#x2019;s position is called <i>translation</i><b>.</b></p>

<p>Now, let&#x2019;s rotate the text. </p>

<bullet>Set the <o>number</o> boxes labeled <i>x</i>, <i>y</i> and <i>z</i> directly above the <o>pak </o> <m>rotate</m> object in the <i>Common 3D attributes</i> section of the patch to the value <m>1</m>. This sets the axis of rotation.</bullet>
<bullet>Drag the number box labeled <m>angle</m> to the value <m>320</m>. You will see the text rotate around the axis into the position shown in this screenshot.</bullet>

<illustration><img src="images/jitterchapter30d.png"/>The 3D text after translation and rotation</illustration>

<p>Sending the message <m>rotate</m> followed by from one to four numbers sets the rotation attribute of an GL group object. The first number is an amount of rotation in degrees, counterclockwise around the object&#x2019;s axis of rotation. The other three numbers specify this axis of rotation as an [x, y, z] vector. As with the <m>position</m> attribute, some values following the rotation attribute can be dropped and default values will be understood. If the rotation message is followed by only one number, that number is understood to mean the angle in degrees, and the axis of rotation is [0, 0, 1]. This rotates the object around the z axis, or in other words, in the x-y plane of the screen. If two or more numbers accompany the rotation message, the first one always specifies the rotation angle, and following ones specify the vector of rotation in the order in which they appear.</p>

<bullet>Set the <o>number</o> box labeled <i>x</i> directly above the <o>pak </o> <m>scale</m> object to <m>0.25</m>. This scales the 3D text to quarter size along its local <i>x</i> axis.</bullet>

<illustration><img src="images/jitterchapter30e.png"/>The 3D text after translation, rotation and scaling</illustration>

<p>Note that the red axis scales along with the object. The dots along the line are now twice as close together as they were before the scale operation. The axes are always drawn in the GL group&#x2019;s local coordinate system, which in this case has been translated, rotated, and scaled with respect to the world coordinate system in the <o>jit.gl.render</o> object. </p>

<p>It's important to consider the order of operations when performing geometry transforms. You can set the rotate, position and scale attributes of an object independently in any order you wish. But each time it is drawn, the object is transformed in the following order:</p>
<ol>
<li>Scaling</li>
<li>Rotation</li>
<li>Translation</li>
</ol>
<p>Keeping this order is essential so that the attributes behave predictably. If rotation occurred before scaling, for example, a <m>scale 0.5</m> message would scale the object not just in its x coordinate, but in some combination of x, y and z depending on the rotation of the object.</p>

<p>The following example shows the difference that performing operations in different orders makes.</p>

<illustration><img src="images/jitterchapter30f.png"/>The order of operations makes all the difference</illustration>

<h2>Summary</h2>
<p>Creating a draw context is the first step to using OpenGL graphics in Jitter. A draw context consists of a named destination, such as a window, and a <o>jit.gl.render</o> object drawing to that destination. </p>

<p>A variety of Jitter objects exist which draw OpenGL graphics in cooperation with <o>jit.gl.render</o>; their names all start with &#x201C;jit.gl.&#x201D; The <o>jit.gl.text3d</o> object is one example. All the Jitter OpenGL objects share a common set of attributes for moving them in 3D space. This group of objects is referred to as the <i>GL group</i>.</p>

	<seealsolist>
		<seealso display="Video and Graphics Tutorial 4: Adding 3D Objects" module="Video and Graphics" name="jitterchapter00f_Adding 3D Objects" type="tutorial" />
		<seealso display="GL Contexts" module="core" name="jitter_gl_contexts" type="vignette" />		
		<seealso name="jit.gl.model">Read and draw Wavefront .obj models</seealso>
		<seealso name="jit.gl.plato">Generate platonic solids</seealso>
		<seealso name="jit.gl.render">Render Open GL</seealso>
		<seealso name="jit.gl.text3d">Write vector text</seealso>
		<seealso name="jit.window">Display data in a Window</seealso>
		<seealso name="qmetro">Queue-based metronome</seealso>
	</seealsolist>
	</chapter>
