﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-OpenGL</title><link>http://www.cppblog.com/zmj/</link><description /><language>zh-cn</language><lastBuildDate>Sat, 04 Jul 2009 06:09:13 GMT</lastBuildDate><pubDate>Sat, 04 Jul 2009 06:09:13 GMT</pubDate><ttl>60</ttl><item><title>Project: Polygon Triangulation</title><link>http://www.cppblog.com/zmj/archive/2009/07/03/89139.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Fri, 03 Jul 2009 01:53:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/07/03/89139.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/89139.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/07/03/89139.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/89139.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/89139.html</trackback:ping><description><![CDATA[<p>LINK:http://www.mpi-inf.mpg.de/~kettner/courses/lib_design_03/proj/polygon_triang.html<br><br>Design the interface between data structures that represent simple polygons and generic algorithms that triangulate simple polygons.</p>
<p>The Standard Template Library (STL) [<a href="http://www.mpi-inf.mpg.de/~kettner/courses/lib_design_03/proj/polygon_triang.html#Austern98"><u><font color=#800080>Austern98</font></u></a>, <a href="http://www.mpi-inf.mpg.de/~kettner/courses/lib_design_03/proj/polygon_triang.html#SGI-STL"><u><font color=#800080>SGI-STL</font></u></a>] contains several examples of a similar interface design: Iterators are the interface between sequences of items in container classes and generic algorithms on sequences. However, they (usually) do not modify the container. Among the container classes some modifying functions, e.g., <code>insert</code> or <code>remove</code>, describe a standardized interface for modifying the container classes and can be used for generic algorithms on container classes. This project is expected to design a generic interface in the same spirit for triangulating polygons.</p>
<p>We start with a set of data structures that can represent a simple polygon, and with a set of algorithms that can triangulate it. We suggest to use the Computational Geometry Algorithms Library (CGAL) <a href="http://www.cgal.org/"><u><font color=#0000ff>&lt;www.cgal.org&gt;</font></u></a> [<a href="http://www.mpi-inf.mpg.de/~kettner/courses/lib_design_03/proj/polygon_triang.html#Fabri99"><u><font color=#800080>Fabri99</font></u></a>] as a source of data structures and algorithms in geometry and also as a platform for realizing this project. Possible data structures could be:</p>
<ul>
    <li>A <code>std::list</code> of 2D points.
    <li>The class <code>CGAL::Polygon_2</code>.
    <li>An individual facet of a 3D polyhedral surface, e.g., the class <code>CGAL::Polyhedron_3</code>.
    <li>While working with the triangulation data structure underlying the class <code>CGAL::Triangulation_2</code> one can end up in the situation to triangulate a polygonal hole in the triangulation structure. </li>
</ul>
<p>All these representations would be for simple polygons without holes. An optional extension would be to extend this project to polygons with holes as they can be represented with:</p>
<ul>
    <li>A <code>std::list</code> of <code>std::list</code>'s of 2D points, where the first list is the outer boundary of the polygon and all succeeding lists are the inner boundaries of holes in the polygon, one list per hole.
    <li>The class <code>CGAL::Planar_map_2</code> can contain faces with holes.
    <li>The class <code>CGAL::Nef_polyhedron_2</code> can contain faces with holes. </li>
</ul>
<p>Examples of algorithms that triangulate polygons are:</p>
<ul>
    <li>Ear-cutting algorithm: An <em>ear</em> is a triangle formed by two consecutive edges of the polygon with a convex angle that contains no other point of a polygon. There exist always at least two <em>ears</em> in a polygon. An <em>ear</em> can be cut from the polygon, reducing its size and thus triangulating it.
    <li>A sweep-line algorithm, see [Chapter 3, <a href="http://www.mpi-inf.mpg.de/~kettner/courses/lib_design_03/proj/polygon_triang.html#deBerg00"><u><font color=#800080>deBerg00</font></u></a>].
    <li>The constrained triangulation in CGAL. It creates a triangulation of the convex hull of a set of points respecting a set of constrained edges that have to be present in the triangulation, which would be the polygon boundary edges here. Afterwards the triangles in the polygon interior have to be selected, i.e., distinguished from those outside of the polygon. </li>
</ul>
<p>Clearly iterators can be used in examining the input polygon. The new part will be the modifying part of the algorithms; where do we create and store the result triangles:</p>
<ul>
    <li>For a single polygon we might just write triangles to an output iterator, for example, for storage in a container or for rendering.
    <li>For polygons embedded in a data structure, such as a triangulation or a polyhedral surface, one wants the result triangles to replace the original polygon and to have the proper neighborhood pointers. </li>
</ul>
<p>The goal of the project is to design the interface and to realize some of the data structures and algorithms, possibly based on the already existing CGAL implementations. The task includes:</p>
<ul>
    <li>Analyse the set of operations of each agorithm and how it could be implemented for each data structure considered.
    <li>Find a common set (or several sets) of operations that support the different combinations.
    <li>Implement the interface for the data structures, possibly with adaptors for the existing data structures in CGAL.
    <li>Implement the algorithm based on this interface, maybe also with adaptors to the already existing algorithms in CGAL.
    <li>Test your generic algorithms on the different representations.
    <li>Document the design, for example, in the style of CGAL or using Doxygen. </li>
</ul>
<h3>Prerequisites</h3>
<p>This project requires interest in geometry or graphics and some knowledge of geometric algorithms. Since CGAL will be covered later in the course, it might be necessary to learn about CGAL prior to that.</p>
<h3>References</h3>
<dl>
<dt><a name=Austern98><strong>[Austern98]</strong>
<dd>Mathew H. Austern. <em>Generic Programming and the STL: Using and Extending the C++ Standard Template Library</em>. Addison-Wesley, 1998.
<p>&#160;</p>
<dt><a name=SGI-STL><strong>[SGI-STL]</strong>
<dd>Silicon Graphics Computer Systems, Inc.<em> Standard Template Library Programmer's Guide</em>. <a href="http://www.sgi.com/tech/stl/"><tt><u><font color=#0000ff>http://www.sgi.com/tech/stl/</font></u></tt></a>.
<p>&#160;</p>
<dt><a name=Fabri99><strong>[Fabri99]</strong>
<dd>Andreas Fabri, Geert-Jan Giezeman, Lutz Kettner, Stefan Schirra, and Sven Sch&#246;nherr. <em>On the Design of CGAL, the Computational Geometry Algorithms Library</em>. Software -- Practice and Experience, submitted 1999, to appear. (also available as technical report)
<p>&#160;</p>
<dt><a name=deBerg00><strong>[deBerg00]</strong>
<dd>Mark de Berg, Marc van Kreveld, Mark Overmars, and Otfried Schwarzkopf. <em>Computational Geometry: Algorithms and Applications</em>. Springer, 2nd edition, 2000.</dd></a></dl>
<img src ="http://www.cppblog.com/zmj/aggbug/89139.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-07-03 09:53 <a href="http://www.cppblog.com/zmj/archive/2009/07/03/89139.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Maths - Angle between vectors</title><link>http://www.cppblog.com/zmj/archive/2009/05/31/86258.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Sun, 31 May 2009 05:50:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/05/31/86258.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/86258.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/05/31/86258.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/86258.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/86258.html</trackback:ping><description><![CDATA[LINK: <a href="http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm">http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm</a><br><br>
<div id=main>
<p>How do we calculate the angle between two vectors?</p>
<p><img height=216 src="http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/twod.gif" width=197></p>
<h1>For 2D Vectors</h1>
<p>This is relatively simple because there is only one degree of freedom for 2D rotations. If v1 and v2 are normalised so that |v1|=|v2|=1, then,</p>
<p>angle = acos(v1&#8226;v2)</p>
<p>where:</p>
<ul>
    <li>&#8226; = 'dot' product (see box on right of page).
    <li>acos = arc cos = inverse of cosine function <a href="http://www.euclideanspace.com/maths/geometry/trig/index.htm">see trigonometry page</a>.
    <li>|v1|= magnitude of v1. </li>
</ul>
<p>The only problem is, this won't give all possible values between 0&#176; and 360&#176;, or -180&#176; and +180&#176;. In other words, it won't tell us if v1 is ahead or behind v2, to go from v1 to v2 is the opposite direction from v2 to v1.</p>
<p>In most math libraries acos will usually return a value between 0 and PI (<a href="http://www.euclideanspace.com/maths/geometry/rotations/angles/index.htm">in radians</a>) which is 0&#176; and 180&#176;.</p>
<p>If we want a + or - value to indicate which vector is ahead, then we probably need to use the atan2 function (as explained on <a href="http://www.euclideanspace.com/maths/geometry/trig/inverse/index.htm">this page</a>). using:</p>
<p>angle of 2 relative to 1= atan2(v2.y,v2.x) - atan2(v1.y,v1.x)</p>
<h1>For 3D Vectors </h1>
<h2>Axis Angle Result</h2>
<p>This is easiest to calculate using <a href="http://www.euclideanspace.com/maths/geometry/rotations/axisAngle/index.htm">axis-angle representation</a> because:</p>
<ul>
    <li>the angle is given by acos of the <a href="http://www.euclideanspace.com/maths/algebra/vectors/index.htm">dot product</a> of the two (normalised) vectors: v1&#8226;v2 = |v1||v2| cos(angle)
    <li>the axis is given by the <a href="http://www.euclideanspace.com/maths/algebra/vectors/index.htm">cross product</a> of the two vectors, the length of this axis is given by |v1 x v2| = |v1||v2| sin(angle). </li>
</ul>
<p>as <a href="http://www.euclideanspace.com/maths/algebra/vectors/index.htm">explained here</a></p>
<p>this is taken from this <a href="http://www.euclideanspace.com/physics/kinematics/joints/ik/userForum.htm">discussion</a>.</p>
<p>So, if v1 and v2 are normalised so that |v1|=|v2|=1, then,</p>
<p>angle = acos(v1&#8226;v2)</p>
<p>axis = norm(v1 x v2)</p>
<p>If the vectors are parallel (angle = 0 or 180 degrees) then the length of v1 x v2 will be zero because sin(0)=sin(180)=0. In the zero case the axis does not matter and can be anything because there is no rotation round it. In the 180 degree case the axis can be anything at 90 degrees to the vectors so there is a whole range of possible axies.</p>
<table width=551 border=1>
    <tbody>
        <tr bgColor=#ffff00>
            <td>angle (degrees)</td>
            <td>sin(angle)</td>
            <td>cos(angle)</td>
            <td>v1&#8226;v2</td>
            <td>v1 x v2</td>
        </tr>
        <tr>
            <td>0</td>
            <td>0</td>
            <td>1</td>
            <td>1</td>
            <td>0,0,0</td>
        </tr>
        <tr>
            <td>90</td>
            <td>1</td>
            <td>0</td>
            <td>0</td>
            <td>unit len</td>
        </tr>
        <tr>
            <td>180</td>
            <td>0</td>
            <td>-1</td>
            <td>-1</td>
            <td>0,0,0</td>
        </tr>
        <tr>
            <td>270</td>
            <td>-1</td>
            <td>0</td>
            <td>0</td>
            <td>unit len</td>
        </tr>
    </tbody>
</table>
<h2>Quaternion Result</h2>
<p>One approach might be to define a quaternion which, when multiplied by a vector, rotates it: </p>
<p>p<sub>2</sub>=q * p<sub>1</sub></p>
<p>This almost works <a href="http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/notations/vectorDivision/index.htm">as explained on this page</a>.</p>
<p>However, to rotate a vector, we must use this formula: </p>
<p>p<sub>2</sub>=q * p<sub>1</sub> * conj(q)</p>
<p>where:</p>
<ul>
    <li>p<sub>2</sub> = is a vector representing a point after being rotated
    <li>q = is a quaternion representing a rotation.
    <li>p<sub>1</sub>= is a vector representing a point before being rotated </li>
</ul>
<p>This is a bit messy to solve for q, I am therefore grateful to <a href="http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/minorlogic.htm">minorlogic</a> for the following approach which converts the axis angle result to a quaternion:</p>
<p><img height=216 src="http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/halfa.gif" width=200></p>
<p>The axis angle can be converted to a quaternion as follows, let x,y,z,w be elements of quaternion, these can be expressed in terms of axis angle as <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm">explained here</a>.</p>
<p>angle = arcos(v1&#8226;v2/ |v1||v2|)<br>axis = norm(v1 x v2)<br>s = sin(angle/2) <br>x = axis.x *s <br>y = axis.y *s <br>z = axis.z *s <br>w = cos(angle/2) </p>
<p>We can use this half angle trig formula on <a href="http://www.euclideanspace.com/maths/geometry/trig/index.htm">this page</a>: sin(angle/2) = 0.5 sin(angle) / cos(angle/2)<br></p>
<p>so substituting in quaternion formula gives: <br>s = 0.5 sin(angle) / cos(angle/2)<br>x = norm(v1 x v2).x *s <br>y = norm(v1 x v2).y *s <br>z = norm(v1 x v2).z *s <br>w = cos(angle/2) </p>
<p>multiply x,y,z and w by 2* cos(angle/2) (this will de normalise the quaternion but we can always normalise later)</p>
<p>x = norm(v1 x v2).x * sin(angle)<br>y = norm(v1 x v2).y * sin(angle)<br>z = norm(v1 x v2).z * sin(angle)<br>w = 2 * cos(angle/2) * cos(angle/2)</p>
<p>now substitute half angle trig formula on <a href="http://www.euclideanspace.com/maths/geometry/trig/index.htm">this page</a>: cos(angle/2) = sqrt(0.5*(1 + cos (angle))) </p>
<p>x = norm(v1 x v2).x * sin(angle)<br>y = norm(v1 x v2).y * sin(angle)<br>z = norm(v1 x v2).z * sin(angle)<br>w = 1 + cos (angle)</p>
<p>because |v1 x v2| = |v1||v2| sin(angle) we can normalise (v1 x v2) by dividing it with sin(angle), </p>
<p>also apply v1&#8226;v2 = |v1||v2| cos(angle)so,</p>
<p>x = (v1 x v2).x / |v1||v2|<br>y = (v1 x v2).y/ |v1||v2|<br>z = (v1 x v2).z/ |v1||v2|<br>w = 1 + v1&#8226;v2 / |v1||v2|</p>
<p>If v1 and v2 are already normalised then |v1||v2|=1 so,</p>
<p>x = (v1 x v2).x <br>y = (v1 x v2).y<br>z = (v1 x v2).z<br>w = 1 + v1&#8226;v2</p>
<p>If v1 and v2 are not already normalised then multiply by |v1||v2| gives:</p>
<p>x = (v1 x v2).x<br>y = (v1 x v2).y<br>z = (v1 x v2).z<br>w = |v1||v2| + v1&#8226;v2</p>
</div>
<h2>Matrix Result</h2>
<p>Using the <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm">quaternion to matrix conversion here</a> we get:</p>
<table height=86 width=642 border=1>
    <tbody>
        <tr>
            <td>1 - 2*qy<sup>2</sup> - 2*qz<sup>2</sup></td>
            <td>2*qx*qy - 2*qz*qw</td>
            <td>2*qx*qz + 2*qy*qw</td>
        </tr>
        <tr>
            <td>2*qx*qy + 2*qz*qw</td>
            <td>1 - 2*qx<sup>2</sup> - 2*qz<sup>2</sup></td>
            <td>2*qy*qz - 2*qx*qw</td>
        </tr>
        <tr>
            <td>2*qx*qz - 2*qy*qw</td>
            <td>2*qy*qz + 2*qx*qw</td>
            <td>1 - 2*qx<sup>2</sup> - 2*qy<sup>2</sup></td>
        </tr>
    </tbody>
</table>
<p>so substituting the quaternion results above into the matrix we get:</p>
<table height=86 width="100%" border=1>
    <tbody>
        <tr>
            <td width=377>1 - 2*(v1 x v2).y<sup>2</sup> - 2*(v1 x v2).z<sup>2</sup></td>
            <td width=366>2*(v1 x v2).x*(v1 x v2).y - 2*(v1 x v2).z*(1 + v1&#8226;v2)</td>
            <td width=430>2*(v1 x v2).x*(v1 x v2).z + 2*(v1 x v2).y*(1 + v1&#8226;v2)</td>
        </tr>
        <tr>
            <td width=377>2*(v1 x v2).x*(v1 x v2).y + 2*(v1 x v2).z*(1 + v1&#8226;v2)</td>
            <td width=366>1 - 2*(v1 x v2).x<sup>2</sup> - 2*(v1 x v2).z<sup>2</sup></td>
            <td width=430>2*(v1 x v2).y*(v1 x v2).z - 2*(v1 x v2).x*(1 + v1&#8226;v2)</td>
        </tr>
        <tr>
            <td width=377>2*(v1 x v2).x*(v1 x v2).z - 2*(v1 x v2).y*(1 + v1&#8226;v2)</td>
            <td width=366>2*(v1 x v2).y*(v1 x v2).z + 2*(v1 x v2).x*(1 + v1&#8226;v2)</td>
            <td width=430>1 - 2*(v1 x v2).x<sup>2</sup> - 2*(v1 x v2).y<sup>2</sup></td>
        </tr>
    </tbody>
</table>
<p>Substituting the following expansions:</p>
<p>(v1 x v2).x = v1.y * v2.z - v2.y * v1.z<br>(v1 x v2).y = v1.z * v2.x - v2.z * v1.x<br>(v1 x v2).z = v1.x * v2.y - v2.x * v1.y<br>(v1 x v2).x<sup>2</sup> = v1.y * v2.z * v1.y * v2.z + v2.y * v1.z * v2.y * v1.z - 2 * v2.y * v1.z * v1.y * v2.z<br>(v1 x v2).y<sup>2</sup> = v1.z * v2.x * v1.z * v2.x + v2.z * v1.x * v2.z * v1.x - 2* v2.z * v1.x * v1.z * v2.x<br>(v1 x v2).z<sup>2</sup> = v1.x * v2.y * v1.x * v2.y +v2.x * v1.y * v2.x * v1.y - 2 * v2.x * v1.y * v1.x * v2.y<br>v1&#8226;v2 = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z</p>
<p>This is getting far too complicated ! can anyone help me simplify this?</p>
<table width="100%" border=1>
    <tbody>
        <tr>
            <td bgColor=#66ffff>Thank you again to minorlogic who gave me the following solution:
            <p>Hi ! <br>and i think can help in matrix version.</p>
            <p>you can use :<br><a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/index.htm">http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/index.htm</a></p>
            <p>And will get some thing :</p>
            <p>matrix33 RotAngonst vector3&amp; from, const vector3&amp; to )<br>{<br>from.norm();<br>to.norm(); <br><br>vector3 vs = cross(from, to); // axis multiplied by sin</p>
            <p>vector3 v(vs);<br>v.norm(); // axis of rotation<br>float ca = dot(from, to) ; // cos angle</p>
            <p>vector3 vt(v*(1.0f - ca));</p>
            <p>matrix33 rotM;<br>rotM.M11 = vt.x * v.x + ca;<br>rotM.M22 = vt.y * v.y + ca;<br>rotM.M33 = vt.z * v.z + ca;</p>
            <p>vt.x *= v.y;<br>vt.z *= v.x;<br>vt.y *= v.z;</p>
            <p>rotM.M12 = vt.x - vs.z;<br>rotM.M13 = vt.z + vs.y;<br>rotM.M21 = vt.x + vs.z;<br>rotM.M23 = vt.y - vs.x;<br>rotM.M31 = vt.z - vs.y;<br>rotM.M32 = vt.y + vs.x;<br>return rotM;<br>}</p>
            </td>
        </tr>
    </tbody>
</table>
<h2>Code</h2>
<strong>axis-angle version </strong>
<pre>sfrotation angleBetween(sfvec3f v1,sfvec3f v2) {
float angle;
// turn vectors into unit vectors
n1 = v1.norm();
n2 = v2.norm();
angle = Math.acos( sfvec3f.dot(n1,n2) );
// if no noticable rotation is available return zero rotation
// this way we avoid Cross product artifacts
if( Math.abs(angle) &lt; 0.0001 ) return new sfrotation( 0, 0, 1, 0 );
// in this case there are 2 lines on the same axis
if(Math.abs(angle)-Math.pi) &lt; 0.001){
n1 = n1.Rotx( 0.5f );
// there are an infinite number of normals
// in this case. Anyone of these normals will be
// a valid rotation (180 degrees). so I rotate the curr axis by 0.5 radians this way we get one of these normals
}
sfvec3f axis = n1;
axis.cross(n2);
return new sfrotation(axis.x,axis.y,axis.z,angle);
}
</pre>
<strong>quaternion version</strong>
<pre>/** note v1 and v2 dont have to be nomalised, thanks to minorlogic for telling me about this:
* http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/minorlogic.htm
*/
sfquat angleBetween(sfvec3f v1,sfvec3f v2) {
float d = sfvec3f.dot(v1,v2);
sfvec3f axis = v1;
axis.cross(v2);
float qw = (float)Math.sqrt(v1.len_squared()*v2.len_squared()) + d;
if (qw &lt; 0.0001) { // vectors are 180 degrees apart
return (new sfquat(0,-v1.z,v1.y,v1.x)).norm;
}
sfquat q= new sfquat(qw,axis.x,axis.y,axis.z);
return q.norm();
}
</pre>
<p><strong>matrix version</strong> </p>
<pre>sfmatrix angleBetween(sfvec3f v1,sfvec3f v2) {
// turn vectors into unit vectors
n1 = v1.norm();
n2 = v2.norm(); 	sfvec3f vs = new sfvec3f(n1);
vs.cross(n2); // axis multiplied by sin	sfvec3f v = new sfvec3f(vs);
v = v.norm(); // axis of rotation
float ca = dot(n1, n2) ; // cos angle	sfvec3f vt = new sfvec3f(v);	vt.scale((1.0f - ca);	sfmatrix rotM = new sfmatrix();
rotM.m11 = vt.x * v.x + ca;
rotM.m22 = vt.y * v.y + ca;
rotM.m33 = vt.z * v.z + ca;	vt.x *= v.y;
vt.z *= v.x;
vt.y *= v.z;	rotM.m12 = vt.x - vs.z;
rotM.m13 = vt.z + vs.y;
rotM.m21 = vt.x + vs.z;
rotM.m23 = vt.y - vs.x;
rotM.m31 = vt.z - vs.y;
rotM.m32 = vt.y + vs.x;
return rotM;
}</pre>
<p>see also code from <a href="http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/minorlogic.htm">minorlogic</a></p>
<!-- #EndEditable --><!-- #BeginEditable "sidebar" -->
<div id=sidebar><!-- #BeginLibraryItem "/Library/bobMathVectorDotProduct.lbi" -->
<h2 class=bobMathHeader>Vector Dot Product </h2>
<div class=sidebarBlock>
<p>The dot product operation multiplies two vectors to give a scalar number (not a vector).</p>
<p>It is defined as follows:</p>
<p>Ax * Bx + Ay * By + Az * Bz</p>
<p><img height=207 alt="dot product" src="http://www.euclideanspace.com/maths/algebra/vectors/vecAlgebra/dotProduct.gif" width=332></p>
<p><a href="http://www.euclideanspace.com/maths/algebra/vectors/vecAlgebra/index.htm">This page</a> explains this. </p>
</div>
<!-- #EndLibraryItem -->
<p><a href="http://www.euclideanspace.com/maths/algebra/vectors/index.htm"><img height=150 src="http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/logo150.jpg" width=159 border=0></a></p>
<!-- #BeginLibraryItem "/Library/bobMathVectorCrossProduct.lbi" -->
<h2 class=bobMathHeader>Vector Cross Product </h2>
<div class=sidebarBlock>
<p><img height=171 alt="cross product" src="http://www.euclideanspace.com/maths/algebra/vectors/vecAlgebra/crossProduct.gif" width=220></p>
<p>The vector cross product gives a vector (or more strictly - a <a href="http://www.euclideanspace.com/maths/algebra/vectors/related/bivector/index.htm">bivector</a>) which is perpendicular to both the vectors being multiplied. The resulting vector A &#215; B is defined by:</p>
<p>x = Ay * Bz - By * Az<br>y = Az * Bx - Bz * Ax<br>z = Ax * By - Bx * Ay</p>
<p>where x,y and z are the components of A &#215; B</p>
<p><a href="http://www.euclideanspace.com/maths/algebra/vectors/vecAlgebra/index.htm">This page</a> explains this. </p>
</div>
<!-- #EndLibraryItem --><!-- #BeginLibraryItem "/Library/bobMathGoogleAd.lbi" -->
<div style="HEIGHT: 300px">
<script type=text/javascript><!--
google_ad_client = "pub-1034088308314105";
google_alternate_color = "ffcc00";
google_ad_width = 300;
google_ad_height = 250;
google_ad_format = "300x250_as";
google_ad_type = "text_image";
//2007-02-01: math_middle
google_ad_channel = "8019157248";
google_color_border = "FF4500";
google_color_bg = "FFCC00";
google_color_link = "000000";
google_color_text = "8B4513";
google_color_url = "E0AD12";
//--></script>
<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type=text/javascript>
</script>
<script src="http://pagead2.googlesyndication.com/pagead/expansion_embed.js"></script>
<script src="http://googleads.g.doubleclick.net/pagead/test_domain.js"></script>
<script src="http://pagead2.googlesyndication.com/pagead/render_ads.js"></script>
<script>window.google_render_ad();</script>
<ins style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; VISIBILITY: visible; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 300px; BORDER-TOP-STYLE: none; PADDING-TOP: 0px; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; POSITION: relative; HEIGHT: 250px; BORDER-BOTTOM-STYLE: none"><ins style="PADDING-RIGHT: 0px; DISPLAY: block; PADDING-LEFT: 0px; VISIBILITY: visible; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 300px; BORDER-TOP-STYLE: none; PADDING-TOP: 0px; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; POSITION: relative; HEIGHT: 250px; BORDER-BOTTOM-STYLE: none"><iframe id=google_ads_frame1 style="LEFT: 0px; POSITION: absolute; TOP: 0px" name=google_ads_frame marginWidth=0 marginHeight=0 src="http://googleads.g.doubleclick.net/pagead/ads?client=ca-pub-1034088308314105&amp;dt=1243748259578&amp;lmt=1240908267&amp;alt_color=ffcc00&amp;format=300x250_as&amp;output=html&amp;correlator=1243748259578&amp;channel=8019157248&amp;url=http%3A%2F%2Fwww.euclideanspace.com%2Fmaths%2Falgebra%2Fvectors%2FangleBetween%2Findex.htm&amp;color_bg=FFCC00&amp;color_text=8B4513&amp;color_link=000000&amp;color_url=E0AD12&amp;color_border=FF4500&amp;ad_type=text_image&amp;ref=http%3A%2F%2Fwww.google.cn%2Fsearch%3Fhl%3Dzh-CN%26q%3Dtwo%2Bvector%2Bangle%26meta%3D%26aq%3D0%26oq%3Dtwo%2Bvect&amp;frm=0&amp;ga_vid=1953169293.1243748261&amp;ga_sid=1243748261&amp;ga_hid=911675596&amp;flash=10.0.2.26&amp;w=300&amp;h=250&amp;u_h=768&amp;u_w=1024&amp;u_ah=738&amp;u_aw=1024&amp;u_cd=32&amp;u_tz=270&amp;u_java=true&amp;dtd=M&amp;xpc=ONBQNu889y&amp;p=http%3A//www.euclideanspace.com" frameBorder=0 width=300 scrolling=no height=250 allowTransparency></iframe></ins></ins></div>
<!-- #EndLibraryItem --><!-- #BeginLibraryItem "/Library/bobMathStandards.lbi" -->
<h2 class=bobMathHeader>Standards </h2>
<div class=sidebarBlock>
<p>There are a lot of choices we need to make in mathematics, for example, </p>
<ul>
    <li>Left or right handed coordinate systems.
    <li>Vector shown as row or column.
    <li>Matrix order.
    <li>Direction of x,y and z coordinates.
    <li>Euler angle order
    <li>Direction of positive angles
    <li>Choice of basis for bivectors
    <li>Etc. etc. </li>
</ul>
<p>A lot of these choices are arbitrary as long as we are consistent about it, different authors tend to make different choices and this leads to a lot of confusion. Where standards exist I have tried to follow them (for example x3d and MathML) otherwise I have at least tried to be consistent across the site. I have documented the choices I have made <a href="http://www.euclideanspace.com/maths/standards/index.htm">on this page</a>. </p>
</div>
<!-- #EndLibraryItem --><!-- #BeginLibraryItem "/Library/bobMathTransforms.lbi" -->
<h2 class=bobMathHeader>Transforms </h2>
<div class=sidebarBlock>
<p><img height=153 alt=rotate src="http://www.euclideanspace.com/maths/differential/vectorcalculus/velocityfield.gif" width=158></p>
<p>A transform maps every point in a vector space to a possibly different point.</p>
<p><img height=229 alt=square src="http://www.euclideanspace.com/maths/geometry/transform/square.png" width=250> </p>
<p>When transforming a computer model we transform all the vertices.</p>
<p>To model this using mathematics we can use <a href="http://www.euclideanspace.com/maths/algebra/matrix/transforms/index.htm">matrices</a>, <a href="http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/index.htm">quaternions</a> or other algebras which can represent multidimensional linear equations. </p>
<p><a href="http://www.euclideanspace.com/maths/geometry/transform/index.htm">This page</a> explains this. </p>
</div>
<!-- #EndLibraryItem --><!-- #BeginLibraryItem "/Library/bobProgStartingGames.lbi" -->
<h2 class=bobSoftwareHeader>Beginning Game Writing</h2>
<div class=sidebarBlock>
<p>Here are some pages on this site which aim to help start writing games:</p>
<ul>
    <li><a href="http://www.euclideanspace.com/software/language/beginner/index.htm">What computer language should I use?</a>
    <li><a href="http://www.euclideanspace.com/software/games/index.htm">Games tutorials</a>
    <li><a href="http://www.euclideanspace.com/maths/geometry/rotations/index.htm">Rotation in 3 dimensions</a>
    <li><a href="http://www.euclideanspace.com/threed/games/examples/cars/index.htm">Writing a car racing game</a>
    <li><a href="http://www.euclideanspace.com/threed/games/examples/snooker/index.htm">Writing a snooker game</a> </li>
</ul>
</div>
</div>
<img src ="http://www.cppblog.com/zmj/aggbug/86258.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-05-31 13:50 <a href="http://www.cppblog.com/zmj/archive/2009/05/31/86258.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>An HP TouchSmart Application Development Guidelines Primer (Page 1 of 3) </title><link>http://www.cppblog.com/zmj/archive/2009/05/25/85707.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Mon, 25 May 2009 07:26:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/05/25/85707.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/85707.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/05/25/85707.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/85707.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/85707.html</trackback:ping><description><![CDATA[LINK: <a href="http://www.touchsmartcommunity.com/article/95/An-HP-TouchSmart-Application-Development-Guidelines-Primer/">http://www.touchsmartcommunity.com/article/95/An-HP-TouchSmart-Application-Development-Guidelines-Primer/</a><br><br>
<h2>An introduction to building HP TouchSmart-hosted applications and a step-by-step tutorial for a &#8220;Hello World&#8221;</h2>
<p><strong>Building Your First TouchSmart Application</strong><br><em>A developers guide to the TouchSmart Platform</em> </p>
<h1>Introduction</h1>
<p>The Hewlett-Packard TouchSmart PC is an innovative new PC form-factor which affords users the unique ability to control interactions using only their hands. Through the use of a very stylish &#8220;10 foot&#8221; style user interface, the user can simply touch the integrated screen and perform most essential functions &#8211; viewing photos, listening to music, and surfing the web &#8211; all without using a keyboard or mouse. </p>
<p>The TouchSmart interface can be considered an entirely new user-interface platform &#8211; and now HP has opened up this platform to the entire developer community. With the release of the TouchSmart Application Developer Guidelines you can now build applications which run on this unique platform &#8211; and cater to its expanding user-base. </p>
<p>This article walks you through building your first TouchSmart application, with the goal of creating a basic application template which you can use for all your TouchSmart projects. </p>
<h1>Getting Started </h1>
<p>In order to follow the steps in this document, you will need to be familiar with Windows Presentation Foundation (WPF) and .NET development with C#. This article assumes a basic knowledge of these technologies. Please visit the Microsoft Developer Network (MSDN) at <a href="http://msdn.microsoft.com/"><u><font color=#0000ff>http://msdn.microsoft.com</font></u></a> for more information. </p>
<p>In addition, the following is required: </p>
<ul>
    <li>TouchSmart PC (model IQ504 or IQ506, current at the time of this writing)
    <li>Latest TouchSmart software (available from <a href="http://support.hp.com/"><u><font color=#0000ff>http://support.hp.com</font></u></a>)
    <li>Microsoft Visual Studio 2008, Express (free) or Professional Edition
    <li>HP TouchSmart Application Development Guidelines (available from <a href="http://www.touchsmartcommunity.com/download/60/HP-TouchSmart-Software-Developer-Guidelines/"><u><font color=#0000ff>here</font></u></a>).
    <li>.NET Framework 3.5 (although the same techniques can be used to build an application using Visual Studio 2005 and .NET 3.0) </li>
</ul>
<p>It is recommended you install Visual Studio 2008 on the TouchSmart PC for ease of development, however it is not required. Since the TouchSmart application we are building is simply a Windows Presentation Foundation application it will run on any Vista or Windows XP PC with .NET 3.5. </p>
<h1>Important Background Information </h1>
<p>Before getting started you should know some important background information about a typical TouchSmart application: </p>
<ul>
    <li>To best integrate with the TouchSmart look-and-feel you should develop your application using the Windows Presentation Foundation (WPF)
    <li>The application runs as a separate process with a window that has the frame removed, it is not running within the TouchSmart shell process.
    <li>The TouchSmart shell is responsible for launching your application. Additionally, the TouchSmart shell will control the position and sizing of your window.
    <li>You must create three separate UI layouts for your application. This is not as difficult as it sounds; only one layout is interactive with controls &#8211; the other two layouts are for display only.
    <li>Design your application for a &#8220;10 foot&#8221; viewing experience. Plan to increase font and control sizes if you are converting an existing application.
    <li>Do not use pop-up windows in your application. This is perhaps the most unique requirement in building a TouchSmart application. The Windows &#8220;MessageBox&#8221; and other pop-up windows are not supported and should not be used. The best model to follow is to build your application like it was going to run in a web browser.
    <li>Your application must support 64-bit Vista, as this is the operating system used on the TouchSmart PC. </li>
</ul>
<div class="entry highlightable">
<p>
<h1>Building the HelloTouchSmart Application </h1>
<p>The rest of this article describes how to build a basic TouchSmart enabled application. Over the next few sections, you will build a basic TouchSmart application which you can use as a template for all your TouchSmart projects. </p>
<p>Start by launching Visual Studio 2008 and create a new project. If you have User Account Control (UAC) enabled make sure to launch Visual Studio with Administrator privileges. </p>
<ul>
    <li>On the File menu, select New Project
    <li>Select WPF Application
    <li>Name your project &#8220;HelloTouchSmart&#8221; and click OK
    <li>For Visual Studio 2008 Professional Users, select the path to save your project. Choose &#8220;C:\TouchSmart&#8221;
    <li>For Visual Studio 2008 Express users, you will be prompted to save when you close your project. Choose &#8220;C:\TouchSmart&#8221; as the path to save your project to. </li>
</ul>
<p>1. After the project is created, double-click the Window1.xaml file to open it. You are now going to make some important changes to this file which make it a TouchSmart application: </p>
<ul>
    <li>Edit the Window definition to match the XAML below. The most important aspect of this is making your application appear without a Window frame (using the combination of ShowInTaskbar, WindowStyle, and ResizeMode attributes). Additionally, it is important to position your window off screen (using the Top and Left attributes), since the TouchSmart shell will move it into the correct position as needed. <br><br>
    <pre>&lt;Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Name="HelloTouchSmart"
    Top="{Binding Source={x:Static SystemParameters.VirtualScreenHeight}}"
    Left="{Binding Source={x:Static SystemParameters.VirtualScreenWidth}}"
    Background="Black"
    ShowInTaskbar="False"
    WindowStyle="None"
    ResizeMode="NoResize"&gt;
    </pre>
    <li>Now add some basic text to the window by inserting the following between the elements in the XAML file. Keep in mind text on a TouchSmart UI should be large (at least 18 point), and match the font family used by the TouchSmart shell. <br><br>
    <pre>&lt;TextBlock Text="My first TouchSmart App!" Foreground="White" FontFamily="Segoe UI" FontSize="24"/&gt;
    </pre>
    </li>
</ul>
<p>2. Select Build, then Build Solution to create the HelloTouchSmart application. </p>
<ul>
    <li>Depending on the edition of Visual Studio you are using, the &#8220;HelloTouchSmart.exe&#8221; will be created in either the bin\Debug (Visual Studio Professional) or bin\Release (Visual Studio Express) folders
    <li>It is important to know where the output file is located since we will be registering the application with the TouchSmart shell in the next step. </li>
</ul>
<p>3. Create a new XML file which contains information to register the application with the TouchSmart shell </p>
<ul>
    <li>Select Project then Add New Item
    <li>Select XML File
    <li>Create a file called Register.xml </li>
</ul>
<p>4. The registration XML file needs specific attributes including the full-path to your application. Replace the contents of the file you created in the previous step with the contents below. If you have created your project in a different path make sure you correct the AppPath element below. </p>
<p align=center>
<pre>&lt;AppManagementSetting&gt;
&lt;UserEditable&gt;true&lt;/UserEditable&gt;
&lt;RunAtStartup&gt;true&lt;/RunAtStartup&gt;
&lt;RemoveFromTaskbar&gt;false&lt;/RemoveFromTaskbar&gt;   &lt;AppPath&gt;C:\TouchSmart\HelloTouchSmart\HelloTouchSmart\bin\Release\HelloTouchSmart.exe
&lt;/AppPath&gt;
&lt;AppParameters&gt;chromeless&lt;/AppParameters&gt;
&lt;AllowAttach&gt;true&lt;/AllowAttach&gt;
&lt;Section&gt;Top&lt;/Section&gt;
&lt;Type&gt;InfoView&lt;/Type&gt;
&lt;DisplayName&gt;HelloTouchSmart&lt;/DisplayName&gt;
&lt;IsVisible&gt;true&lt;/IsVisible&gt;
&lt;UserDeleted&gt;false&lt;/UserDeleted&gt;
&lt;InDefaultSet&gt;false&lt;/InDefaultSet&gt;
&lt;IconName /&gt;
&lt;/AppManagementSetting&gt;
</pre>
<p>&#160;</p>
<p>5. Save the XML file. Now it will need to be registered with the TouchSmart shell for your application to start appear in the TouchSmart shell. </p>
<ul>
    <li>Make sure the TouchSmart shell is completely closed (click Close from the TouchSmart shell main screen)
    <li>Start a command window with Admin rights (if UAC is enabled)
    <li>Change the working directory to C:\Program Files(x86)\Hewlett-Packard\TouchSmart\SmartCenter 2.0
    <li>Type the following command line to register your application RegisterSmartCenterApp.exe updateconfig &#8220;C:\TouchSmart\HelloTouchSmart\HelloTouchSmart\Register.xml&#8221;
    <li>You should receive a successful message upon installation. Note you only need to register your application once. </li>
</ul>
<p>6. After finishing these steps you should be greeted with your first TouchSmart application. Congratulations! </p>
<p><img alt="" src="http://www.touchsmartcommunity.com/imagelib/contentitem/95/8b5644ba4a76476f--61957e18-11d6e0ef467--7e871032840638-w580h580.jpg"> </p>
<p>&#160;</p>
</div>
<div class="entry highlightable">
<p>
<h1>Enhancing the HelloTouchSmart Application </h1>
<p>Now that you have a basic idea of how to build a TouchSmart application, the next step is to enhance it take advantage of the three layouts in the TouchSmart shell. </p>
<p>Each TouchSmart application needs to support three different UI views: small, medium, and large. If the user drags an application from the bottom area to the top area, it should switch from a small layout to a medium layout. If the user then clicks on the application in the medium layout it should switch to a large layout. </p>
<p>The small layout typically is an image that represents your application. The artwork should be a high-quality image that blends into the TouchSmart shell as best as possible. </p>
<p>The medium layout typically represents a non-interactive status view of your application. If your application is designed to display content from the web, for instance, this could be recent information your application has downloaded (e.g. most recent photos). </p>
<p>Finally, the large view represents your application. This is where you should expose all functions and features you intend to provide to the user. In the steps below we will enhance our sample to display an icon in the small layout and two different layouts for the medium and large views. </p>
<p>1. Start by closing the TouchSmart shell completely (clicking the Close button in the lower right-hand corner). Currently you will also need to manually &#8220;end task&#8221; the &#8220;HelloTouchSmart.exe&#8221; from the Windows task manager, as it doesn&#8217;t get closed by the TouchSmart shell when you close it. If you don&#8217;t close the application Visual Studio will be unable to build your project. </p>
<p>2. Open the HelloTouchSmart project </p>
<ul>
    <li>Double-click on the Window1.xaml file to open it. First we are going to define the 3 UI layouts.
    <li>We will also need an image in the project. Copy your favorite image (here we copied img35.jpg from the \Windows\Web\Wallpaper folder which is present on every installation of Windows Vista) into the project folder.
    <li>Add the image to your project by selecting Project-&gt;Add Existing Item. Change the file filter to &#8220;Image Files&#8221; then select the image file from your project folder. </li>
</ul>
<p>3. You can define your layout using any of the WPF container elements; however for this example we are going to use the DockPanel. </p>
<ul>
    <li>Remove the TextBlock we defined in the section above.
    <li>Define three new sections between the as follows:<br><br>
    <pre>&lt;DockPanel Name="SmallUI" Background="Black"&gt;
    &lt;Image Stretch="UniformToFill" Source="img35.jpg"/&gt;
    &lt;/DockPanel&gt;
    &lt;DockPanel Name="MediumUI" Background="Black"&gt;
    &lt;TextBlock Text="Medium UI" Foreground="White" FontFamily="Segoe UI"
    FontSize="24"/&gt;
    &lt;/DockPanel&gt;
    &lt;DockPanel Name="LargeUI" Background="Black"&gt;
    &lt;TextBlock Text="Large UI" Foreground="White" FontFamily="Segoe UI"
    FontSize="96"/&gt;
    &lt;/DockPanel&gt;
    </pre>
    </li>
</ul>
<p>4. Compile the application then launch the TouchSmart shell. </p>
<ul>
    <li>There may be cases where the TouchSmart shell won&#8217;t re-launch your application properly.
    <li>If your application doesn&#8217;t appear for any reason (or appears without a UI), click Personalize, find the HelloTouchSmart tile, de-activate it and click OK.
    <li>Click Personalize again, find the HelloTouchSmart tile, activate it and click OK.
    <li>The TouchSmart shell should now launch your application.<br><br><img alt="" src="http://www.touchsmartcommunity.com/imagelib/contentitem/95/8b5644ba4a76476f--61957e18-11d6e0ef467--7e35-1489722165-w580h580.jpg"> </li>
</ul>
<p>5. As you can see our application appears but is only showing the large view. Close the TouchSmart shell and switch back to Visual Studio &#8211; we&#8217;ll fix this issue now. </p>
<ul>
    <li>Remember to &#8220;end task&#8221; HelloTouchSmart.exe from the Windows task manager </li>
</ul>
<p>6. We are now going to add some code to Window1.xaml.cs to handle the resizing and show the appropriate controls. </p>
<ul>
    <li>Double-click on the Window1.xaml.cs file to open it. We will add code to show and hide our three DockPanels based on the size of the UI.
    <li>The size ratios below were derived from the HP TouchSmart Application Development Guidelines.<br><br>
    <pre>public Window1()
    {
    InitializeComponent();
    SizeChanged += new SizeChangedEventHandler(Window1_SizeChanged);
    }
    void Window1_SizeChanged(object sender, SizeChangedEventArgs e)
    {
    double ratio = Math.Max(this.ActualWidth, this.ActualHeight) /
    Math.Max(SystemParameters.PrimaryScreenWidth,
    SystemParameters.PrimaryScreenHeight);
    if (ratio &gt;= 0.68295) //Large
    {
    SmallUI.Visibility = Visibility.Collapsed;
    MediumUI.Visibility = Visibility.Collapsed;
    LargeUI.Visibility = Visibility.Visible;
    }
    else if (ratio &lt;= 0.18) //Small
    {
    SmallUI.Visibility = Visibility.Visible;
    MediumUI.Visibility = Visibility.Collapsed;
    LargeUI.Visibility = Visibility.Collapsed;
    }
    else //Medium
    {
    SmallUI.Visibility = Visibility.Collapsed;
    MediumUI.Visibility = Visibility.Visible;
    LargeUI.Visibility = Visibility.Collapsed;
    }
    }
    </pre>
    <li>Seasoned WPF developers might see a better way to hide/show the panels but for the sake of being clear and concise we are keeping this code fairly simple. Feel free to create your own mechanism that suits your particular need.
    <li>Since the TouchSmart shell simply resizes and positions your window according to its needs you can use any WPF standard event handling and perform necessary adjustments to your user interface. </li>
</ul>
<p>7. One final change is to prevent the application from being accidentally launched by a user. Since the application&#8217;s window appears initially off-screen it is important we only allow the application to be started by the TouchSmart shell. </p>
<ul>
    <li>Change the Window1 constructor to the following: <br><br>
    <pre>public Window1()
    {
    bool okToRun = false;
    foreach (string str in Environment.GetCommandLineArgs())
    {
    if (str.CompareTo("chromeless") == 0)
    {
    okToRun = true;
    }
    }
    if (!okToRun)
    {
    Application.Current.Shutdown();
    }
    else
    {
    InitializeComponent();
    SizeChanged += new SizeChangedEventHandler(Window1_SizeChanged);
    }
    }
    </pre>
    <li>The parameter being checked (chromeless) was actually provided in the registration XML file created in the first part of this article. The TouchSmart shell will pass this parameter to your application on launch. </li>
</ul>
<p>8. Compile and run your application as done in step four. You should now see your application display three distinct user interfaces depending on its placement in the TouchSmart shell. </p>
<p><img alt="" src="http://www.touchsmartcommunity.com/imagelib/contentitem/95/8b5644ba4a76476f--61957e18-11d6e0ef467--7da7235339667-w580h580.jpg"> </p>
<p>You might have noticed the application at this point does not have an icon in the shell. To fix this issue create a compressed &#8220;Windows Vista style&#8221;256x256 PNG icon and embed it in the application executable by selecting Project-&gt;Properties and select your icon from the Application tab. There are several 3rd party tools for creating this specialized type of icon available since the standard version of Visual Studio does not support compressed PNG icons. </p>
<h1>Tips for Debugging </h1>
<p>If you would like to debug your application with the Visual Studio debugger we recommend you attach to the running process by selecting Debug-&gt;Attach to Process. This only works for the Professional Edition of Visual Studio. </p>
<p>To debug with the Express edition, you must change your window style to run as a normal Windows application and remove the check for &#8220;chromeless&#8221; above. </p>
<h1>Summary </h1>
<p>You should now be familiar with how a basic TouchSmart application is put together and have a good starting point for your future projects. Some other important items not covered (but are outlined in the HP TouchSmart Application Development Guidelines) include application skinning and UI notifications. These advanced topics will be covered in a follow-up article, however for now please refer to the HP developer document for more detailed information. </p>
<p>&#160;</p>
</div>
<img src ="http://www.cppblog.com/zmj/aggbug/85707.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-05-25 15:26 <a href="http://www.cppblog.com/zmj/archive/2009/05/25/85707.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Multi-Touch Systems that I Have Known and Loved</title><link>http://www.cppblog.com/zmj/archive/2009/05/22/85381.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Fri, 22 May 2009 06:06:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/05/22/85381.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/85381.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/05/22/85381.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/85381.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/85381.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: LINK: http://www.billbuxton.com/multitouchOverview.htmlBill BuxtonMicrosoft ResearchOriginal: Jan. 12, 2007Version:&nbsp; Feb 12, 2009Keywords / Search TermsMulti-touch, multitouch, input, inter...&nbsp;&nbsp;<a href='http://www.cppblog.com/zmj/archive/2009/05/22/85381.html'>阅读全文</a><img src ="http://www.cppblog.com/zmj/aggbug/85381.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-05-22 14:06 <a href="http://www.cppblog.com/zmj/archive/2009/05/22/85381.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>NextWindow Two-Touch API</title><link>http://www.cppblog.com/zmj/archive/2009/05/20/83449.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Wed, 20 May 2009 03:13:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/05/20/83449.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/83449.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/05/20/83449.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/83449.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/83449.html</trackback:ping><description><![CDATA[LINK: <a href="http://www.nextwindow.com/support/application_notes/api.html">http://www.nextwindow.com/support/application_notes/api.html</a><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://www.touchsmartcommunity.com/forum/thread/198/Multitouch-on-Touch-Smart/">http://www.touchsmartcommunity.com/forum/thread/198/Multitouch-on-Touch-Smart/</a><br><br>
<p>NextWindow's touch Application Program Interface (API) provides programmers with access to touch data generated by a NextWindow touch screen. It also provides derived touch information. For information about the capabilities of NextWindow products and which ones you can interface to using the API, see <a class=links title="NextWindow Latest Technical Information" href="http://www.nextwindow.com/support/latest_tech_info.html"><font color=#0000ff>NextWindow Latest Technical Information</font></a>.</p>
<p>The touch events, data and derived information can be used in any way the application wants.</p>
<p>Communications are via HID-compliant USB.</p>
<p>The API is in the form of a DLL that provides useful functions for application developers.</p>
<p>&nbsp;</p>
<hr>
<h3>Multi-Touch</h3>
<p>Multi-touch simply refers to a touch-sensitive device that can independently detect and optionally resolve the position of two or more touches on screen at the same time. In contrast, a traditional touch screen senses the position of a single touch and hence is not a multi-touch device.</p>
<table class=nw_bodytext id=table3 cellSpacing=0 cellPadding=6 width="100%" border=0>
    <tbody>
        <tr>
            <td vAlign=top width="2%"><img height=10 alt=bullet src="http://www.nextwindow.com/website_graphics/bullet_teal_round_small.gif" width=5 border=0></td>
            <td vAlign=top width="94%">&#8220;Detect&#8221; refers to the ability to sense that a touch has occurred somewhere on screen.</td>
        </tr>
        <tr>
            <td vAlign=top width="2%"><img height=10 alt=bullet src="http://www.nextwindow.com/website_graphics/bullet_teal_round_small.gif" width=5 border=0></td>
            <td vAlign=top width="94%">&#8220;Resolve&#8221; refers to the ability to report the coordinates of the touch position.</td>
        </tr>
    </tbody>
</table>
<p>NextWindow&#8217;s standard optical touch hardware can detect two touches on screen. The firmware can resolve the position of two simultaneous touches (with some limitations).</p>
<p>&nbsp;</p>
<hr>
<h3>NextWindow Multi-Touch API Downloads</h3>
<p><a class=links title="NextWindow's Multi-Touch API" href="http://www.nextwindow.com/support/application_notes/download_files/NWMultiTouchAPI_v1260.zip"><font color=#0000ff>NWMultiTouchAPI_v1260.zip</font></a> contains the following files:</p>
<table class=nw_bodytext cellSpacing=0 cellPadding=6 width="80%" border=1>
    <tbody>
        <tr>
            <td vAlign=top width="23%">NWMultiTouch.dll</td>
            <td vAlign=top width="75%">The DLL file containing the Multi-Touch API.</td>
        </tr>
        <tr>
            <td vAlign=top width="23%">NWMultiTouch.h</td>
            <td vAlign=top width="75%">The Header file containing the function definitions.</td>
        </tr>
        <tr>
            <td vAlign=top width="23%">NWMultiTouchMS.lib</td>
            <td vAlign=top width="75%">The Library file for Microsoft Visual Studio compiler</td>
        </tr>
        <tr>
            <td vAlign=top width="23%">NWMultiTouch.lib</td>
            <td vAlign=top width="75%">The Library file for Borland and other compilers</td>
        </tr>
    </tbody>
</table>
<h5>Note</h5>
<p>NextWindow's DLL is 32-bit. If you are building an application on a 64-bit machine, you need to specify a 32-bit build. To change this setting in Visual C#, change the platform target to x86 under the Build page of Project Settings. See the following Microsoft article for more details.</p>
<p><a class=links href="http://www.nextwindow.com/support/application_notes/%3Cp%3Ehttp:/msdn.microsoft.com/en-us/library/kb4wyys2.aspx"><font color=#0000ff>http://msdn.microsoft.com/en-us/library/kb4wyys2.aspx</font></a></p>
<h5>Example Code</h5>
<p><a class=links title="C# example code" href="http://www.nextwindow.com/support/application_notes/download_files/NWMultiTouchCSharpSample_v1260.zip"><font color=#0000ff>NWMultiTouchCSharpSample_v1260.zip</font></a></p>
<p><a class=links title="C++ example code" href="http://www.nextwindow.com/support/application_notes/download_files/NWMultiTouchCPlusPlusSample_v1260.zip"><font color=#0000ff>NWMultiTouchCPlusPlusSample_v1260.zip</font></a></p>
<h5>Documentation</h5>
<p><a class=links title="NextWindow API  User Guide" href="http://www.nextwindow.com/support/application_notes/download_files/nextwindow_api_user_guide_v17.pdf"><font color=#0000ff>NextWindow USB API User Guide v1.7</font></a> (91 KB pdf file)</p>
<p><a class=links title="NextWindow Multi-Touch" href="http://www.nextwindow.com/pdf/nextwindow_multitouch.pdf"><font color=#0000ff>NextWindow Multi-Touch Whitepaper</font></a> (2722 KB pdf)</p>
<!-- start 10contentbottom -->
<img src ="http://www.cppblog.com/zmj/aggbug/83449.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-05-20 11:13 <a href="http://www.cppblog.com/zmj/archive/2009/05/20/83449.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Coding for Gestures and Flicks on Tablet PC running Vista</title><link>http://www.cppblog.com/zmj/archive/2009/05/19/83399.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Tue, 19 May 2009 09:52:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/05/19/83399.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/83399.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/05/19/83399.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/83399.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/83399.html</trackback:ping><description><![CDATA[LINK: <a href="http://www.therobotgeek.net/articles/gestureblocks.aspx">http://www.therobotgeek.net/articles/gestureblocks.aspx</a><br><br>
<p>For this article, I wanted to demonstrate how to access gestures and flicks using C# code. I'll talk about accessing flicks using the tablet API and accessing gestures using the N-Trig native libraries. Surprisingly I couldn't find much out there that goes into any kind of depth in coding for either of these topics. So it seemed like a good opportunity to present some examples. I've included code for a C# game that uses the gestures for control. I hope you find it fun and useful. </p>
<p>Even though they are called "flicks", a flick is really a single touch gesture and an N-Trig gesture is a double touch gesture.&nbsp; All the examples run on Windows Vista Ultimate 32bit. Windows Vista will only detect up to two fingers on the touch surface. However, Windows 7 promises to allow more than two finger detection. I'll have to try that next. HP is already shipping hardware that is multi-touch enabled on their TouchSmart PCs.&nbsp; The Dell Latitude XT and XT2 tablet PCs are also using the N-Trig hardware for multi-touch. </p>
<br>
<h2>Code to Detect If Running on a Tablet PC</h2>
<p>I found some simple code to determine if your app is running on a tablet PC. It is a native call to GetSystemMetrics which is in User32.dll and you pass in SM_TABLETPC. I've included this code in the Flicks class.&nbsp; You may want your app to auto-detect if it's running on a tablet to determine which features to enable.</p>
<div style="FONT-SIZE: 10pt; BACKGROUND: #e0e0e0; COLOR: black; FONT-FAMILY: Courier New">
<p style="MARGIN: 0px">&nbsp;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; [<span style="COLOR: #2b91af">DllImport</span>(<span style="COLOR: #a31515">"User32.dll"</span>, CharSet = <span style="COLOR: #2b91af">CharSet</span>.Auto)]</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">public</span> <span style="COLOR: blue">static</span> <span style="COLOR: blue">extern</span> <span style="COLOR: blue">int</span> GetSystemMetrics(<span style="COLOR: blue">int</span> nIndex);</p>
<p style="MARGIN: 0px">&nbsp;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">public</span> <span style="COLOR: blue">static</span> <span style="COLOR: blue">bool</span> IsTabletPC()</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">int</span> nResult = GetSystemMetrics(SM_TABLETPC);</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">if</span> (nResult != 0)</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">return</span> <span style="COLOR: blue">true</span>;</p>
<p style="MARGIN: 0px">&nbsp;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">return</span> <span style="COLOR: blue">false</span>;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="MARGIN: 0px">&nbsp;</p>
</div>
<br>
<h2>Accessing Flicks (Single Touch Gestures) or UniGesture </h2>
<p>If you've never heard of flicks before, they are single touch gestures that are triggered based on the speed of the touch across the tablet surface.&nbsp; You can find <a href="http://msdn.microsoft.com/en-us/library/dd356077(VS.85).aspx" target=_blank><u><font color=#0000ff>more detail here.</font></u></a>&nbsp; It currently gives you eight directions that can be programmed at the OS level for use by applications. </p>
<p>I used the tabflicks.h file that I found in the folder - "C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include" This header file is included with the Windows SDK. It contains all the flick structures and macro definitions needed to access flicks. I created a&nbsp; class library project called FlickLib that contains the C# structures, DllImports and code to store and process the data. I also wrote a test WinForm application that shows the usage of the library. </p>
<div style="FONT-SIZE: 10pt; BACKGROUND: #e0e0e0; COLOR: black; FONT-FAMILY: Courier New">
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;&nbsp;97</span>&nbsp;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;&nbsp;98</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: gray">///</span><span style="COLOR: green"> </span><span style="COLOR: gray">&lt;summary&gt;</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;&nbsp;99</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: gray">///</span><span style="COLOR: green"> Override the WndProc method to capture the tablet flick messages</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;100</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: gray">///</span><span style="COLOR: green"> </span><span style="COLOR: gray">&lt;/summary&gt;</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;101</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: gray">///</span><span style="COLOR: green"> </span><span style="COLOR: gray">&lt;param name="msg"&gt;&lt;/param&gt;</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;102</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">protected</span> <span style="COLOR: blue">override</span> <span style="COLOR: blue">void</span> WndProc(<span style="COLOR: blue">ref</span> <span style="COLOR: #2b91af">Message</span> msg)</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;103</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;104</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">try</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;105</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;106</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">if</span> (msg.Msg == <span style="COLOR: #2b91af">Flicks</span>.WM_TABLET_FLICK)</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;107</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;108</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: #2b91af">Flick</span> flick = <span style="COLOR: #2b91af">Flicks</span>.ProcessMessage(msg);</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;109</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">if</span> (flick != <span style="COLOR: blue">null</span>)</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;110</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;111</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">this</span>.txtOutput.Text = <span style="COLOR: blue">string</span>.Format(<span style="COLOR: #a31515">"Point=({0},{1}) {2}\r\n"</span>, </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;112</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; flick.Point.X, </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;113</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; flick.Point.Y, </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;114</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; flick.Data.Direction);</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;115</span>&nbsp;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;116</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: green">// Set to zero to tell WndProc that message has been handled</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;117</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; msg.Result = <span style="COLOR: #2b91af">IntPtr</span>.Zero;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;118</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;119</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;120</span>&nbsp;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;121</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">base</span>.WndProc(<span style="COLOR: blue">ref</span> msg);</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;122</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;123</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">catch</span> (<span style="COLOR: #2b91af">Exception</span> ex)</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;124</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;125</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">this</span>.txtOutput.Text += <span style="COLOR: blue">string</span>.Format(<span style="COLOR: #a31515">"{0}\r\n"</span>, ex.Message);</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;126</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;127</span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af">&nbsp;&nbsp;128</span>&nbsp;</p>
</div>
<p>I override the WndProc method of the WinForm to gain access to the WM_TABLET_FLICK messages sent to the window. The flick data is encoded in the WParam and the LParam of the windows message. I discovered that even though the params are IntPtr type, they are not actually pointers but are the real integer values to be used. I kept getting an Access Violation exception when I was trying to marshal the IntPtr to a structure. The solution was non-obvious. I couldn't find that documented anywhere. But it works correctly now so this is my contribution to the web for anyone trying to solve the same problem. </p>
<p>It is important to note that on line # 117, I set msg.Result = IntPtr.Zero.&nbsp; This tells the base.WndProc method that the message has been handled so ignore it.&nbsp; This is important because the underlying pen flicks can be assigned to actions such as copy and paste.&nbsp; If the message is not flagged as handled, the app will attempt to perform the action.</p>
<p><embed src=http://www.youtube.com/v/P5m0ceAC5p4&amp;hl=en&amp;fs=1 width=480 height=295 type=application/x-shockwave-flash allowfullscreen="true" allowscriptaccess="always"></embed></p>
<em>WinForm Flicks Test C# source code</em> <a href="http://www.therobotgeek.net/downloads/gestureblocks/WinFlickTest.zip"><u><font color=#0000ff>WinFlickTest.zip</font></u></a> <br><br>
<h2>Accessing Double Touch Gestures or DuoGestures </h2>
<p>The N-Trig hardware on the HP TouchSmart tablet provides the ability to detect two (or more) touches on the surface. This allows the tablet to respond on two finger gestures. You can see the current DuoGestures in use from <a href="http://www.n-trig.com/Content.aspx?Page=SupportSDK" target=_blank><u><font color=#0000ff>N-Trig here.</font></u></a> </p>
<p>I've created a class library project called GestureLib which wraps the native libraries from N-Trig so that they can be called using C#. Obviously this will only run on tablets that have the N-Trig hardware. Currently there is the HP TouchSmart tx2 and the Dell Latitude XT &amp; XT2 laptops. I'll be testing and updating code for the HP TouchSmart IQ505 panel that uses the NextWindow hardware. If someone has any other tablets, touch panels and/or UMPC devices, I'd be happy to work together to create a version for that as well. </p>
<div style="FONT-SIZE: 10pt; BACKGROUND: #e0e0e0; COLOR: black; FONT-FAMILY: Courier New">
<p style="MARGIN: 0px">&nbsp;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">private</span> <span style="COLOR: #2b91af">Gestures</span> _myGestures = <span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">Gestures</span>();</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">private</span> <span style="COLOR: blue">int</span> NTR_WM_GESTURE = 0;</p>
<p style="MARGIN: 0px">&nbsp;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: gray">///</span><span style="COLOR: green"> </span><span style="COLOR: gray">&lt;summary&gt;</span></p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: gray">///</span><span style="COLOR: green"> Override OnLoad method to Connect to N-Trig hardware and</span></p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: gray">///</span><span style="COLOR: green"> Register which gestures you want to receive messages for and</span></p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: gray">///</span><span style="COLOR: green"> Register to receive the Window messages in this WinForm</span></p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: gray">///</span><span style="COLOR: green"> </span><span style="COLOR: gray">&lt;/summary&gt;</span></p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: gray">///</span><span style="COLOR: green"> </span><span style="COLOR: gray">&lt;param name="eventArgs"&gt;&lt;/param&gt;</span></p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">protected</span> <span style="COLOR: blue">override</span> <span style="COLOR: blue">void</span> OnLoad(<span style="COLOR: #2b91af">EventArgs</span> eventArgs)</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">try</span></p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">bool</span> bIsConnected = <span style="COLOR: blue">this</span>._myGestures.Connect();</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">if</span> (bIsConnected == <span style="COLOR: blue">true</span>)</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">this</span>.txtOutput.Text += <span style="COLOR: #a31515">"Connected to DuoSense\r\n"</span>;</p>
<p style="MARGIN: 0px">&nbsp;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: #2b91af">TNtrGestures</span> regGestures = <span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">TNtrGestures</span>();</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; regGestures.ReceiveRotate = <span style="COLOR: blue">true</span>;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; regGestures.UseUserRotateSettings = <span style="COLOR: blue">true</span>;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; regGestures.ReceiveFingersDoubleTap = <span style="COLOR: blue">true</span>;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; regGestures.UseUserFingersDoubleTapSettings = <span style="COLOR: blue">true</span>;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; regGestures.ReceiveZoom = <span style="COLOR: blue">true</span>;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; regGestures.UseUserZoomSettings = <span style="COLOR: blue">true</span>;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; regGestures.ReceiveScroll = <span style="COLOR: blue">true</span>;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; regGestures.UseUserScrollSettings = <span style="COLOR: blue">true</span>;</p>
<p style="MARGIN: 0px">&nbsp;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">bool</span> bRegister = <span style="COLOR: blue">this</span>._myGestures.RegisterGestures(<span style="COLOR: blue">this</span>.Handle, regGestures);</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">if</span> (bRegister == <span style="COLOR: blue">true</span>)</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">this</span>.NTR_WM_GESTURE = <span style="COLOR: #2b91af">Gestures</span>.RegisterGestureWinMessage();</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">if</span> (<span style="COLOR: blue">this</span>.NTR_WM_GESTURE != 0)</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">this</span>.txtOutput.Text += <span style="COLOR: blue">string</span>.Format(<span style="COLOR: #a31515">"NTR_WM_GESTURE = {0}\r\n"</span>, <span style="COLOR: blue">this</span>.NTR_WM_GESTURE);</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">else</span></p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">this</span>.txtOutput.Text = <span style="COLOR: #a31515">"Error connecting to DuoSense\r\n"</span>;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">catch</span> (<span style="COLOR: #2b91af">Exception</span> ex)</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">this</span>.txtOutput.Text += <span style="COLOR: blue">string</span>.Format(<span style="COLOR: #a31515">"{0}\r\n"</span>, ex.Message);</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="MARGIN: 0px">&nbsp;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: gray">///</span><span style="COLOR: green"> </span><span style="COLOR: gray">&lt;summary&gt;</span></p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: gray">///</span><span style="COLOR: green"> Override OnClosing method to ensure that we Disconnect from N-Trig hardware</span></p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: gray">///</span><span style="COLOR: green"> </span><span style="COLOR: gray">&lt;/summary&gt;</span></p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: gray">///</span><span style="COLOR: green"> </span><span style="COLOR: gray">&lt;param name="cancelEventArgs"&gt;&lt;/param&gt;</span></p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">protected</span> <span style="COLOR: blue">override</span> <span style="COLOR: blue">void</span> OnClosing(<span style="COLOR: #2b91af">CancelEventArgs</span> cancelEventArgs)</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">this</span>._myGestures.Disconnect();</p>
<p style="MARGIN: 0px">&nbsp;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">base</span>.OnClosing(cancelEventArgs);</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</p>
<p style="MARGIN: 0px">&nbsp;</p>
</div>
<p>Once you look at the code you will note that you have to connect to the N-Trig hardware at the start of the app.&nbsp; I put that call in the OnLoad method.&nbsp; Once you have a handle to the hardware, then you will use that throughout the lifetime of the app.&nbsp; It is stored in the Gestures class.&nbsp; With the handle, you will register which gesture messages you want the window to receive.&nbsp; Once registered, you will start to see NTR_WM_GESTURE message showing up in the WndProc method.&nbsp; I created a ProcessMessage method in the Gestures class that will determine which gesutre type it is and extract the data for the particular gesture. </p>
<p>One thing to note is if you look at the DllImports for the NtrigISV.dll native library you will see that there is name mangling with the method calls. I had to use Dependency Walker to determine the actual names of the methods. So be warned that when N-Trig releases a new version of their DLL that this code will probably break. </p>
<p><embed src=http://www.youtube.com/v/ePsJivlD6io&amp;hl=en&amp;fs=1 width=480 height=295 type=application/x-shockwave-flash allowfullscreen="true" allowscriptaccess="always"></embed></p>
<em>N-Trig Gestures WinForm Test source code</em> <a href="http://www.therobotgeek.net/downloads/gestureblocks/WinGestureTest.zip"><u><font color=#0000ff>WinGestureTest.zip</font></u></a> <br><br>
<h2>Problems with Marshalling Data from C++ to C#</h2>
<p>I had an issue where I was only getting the Zoom messages.&nbsp; My friend, Ben Gavin, helped me solve the problem.&nbsp; It had to do with marshalling the data into the struct.&nbsp; The original C++ struct looks like this: </p>
<div style="FONT-SIZE: 10pt; BACKGROUND: #e0e0e0; COLOR: black; FONT-FAMILY: Courier New">
<p style="MARGIN: 0px">&nbsp;</p>
<p style="MARGIN: 0px"><span style="COLOR: blue">typedef</span> <span style="COLOR: blue">struct</span> _TNtrGestures</p>
<p style="MARGIN: 0px">{&nbsp;&nbsp; </p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; <span style="COLOR: blue">bool</span> ReceiveZoom;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; <span style="COLOR: blue">bool</span> UseUserZoomSettings; </p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; <span style="COLOR: blue">bool</span> ReceiveScroll;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; <span style="COLOR: blue">bool</span> UseUserScrollSettings;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; <span style="COLOR: blue">bool</span> ReceiveFingersDoubleTap;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; <span style="COLOR: blue">bool</span> UseUserFingersDoubleTapSettings;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; <span style="COLOR: blue">bool</span> ReceiveRotate;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; <span style="COLOR: blue">bool</span> UseUserRotateSettings;</p>
<p style="MARGIN: 0px">} TNtrGestures;</p>
<p style="MARGIN: 0px">&nbsp;</p>
</div>
<p>For my original port, I just did a LayoutKind.Sequential and set everything as a bool like below. </p>
<div style="FONT-SIZE: 10pt; BACKGROUND: #e0e0e0; COLOR: black; FONT-FAMILY: Courier New">
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; [<span style="COLOR: #2b91af">StructLayout</span>(<span style="COLOR: #2b91af">LayoutKind</span>.Sequential)]</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; <span style="COLOR: blue">public</span> <span style="COLOR: blue">struct</span> <span style="COLOR: #2b91af">TNtrGestures</span></p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; {</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> ReceiveZoom;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> UseUserZoomSettings;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> ReceiveScroll;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> UseUserScrollSettings;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> ReceiveFingersDoubleTap;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> UseUserFingersDoubleTapSettings;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> ReceiveRotate;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> UseUserRotateSettings;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; }</p>
</div>
<p>Trouble is that <font style="COLOR: blue">bool</font> in C++ is one byte where as a <font style="COLOR: blue">bool</font> in C# is an Int32 or four bytes. Now if the C++ struct was labeled with a BOOL, then it would have been four bytes. So the new declaration of the struct in C# looks like this: </p>
<div style="FONT-SIZE: 10pt; BACKGROUND: #e0e0e0; COLOR: black; FONT-FAMILY: Courier New">
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; [<span style="COLOR: #2b91af">StructLayout</span>(<span style="COLOR: #2b91af">LayoutKind</span>.Explicit)]</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; <span style="COLOR: blue">public</span> <span style="COLOR: blue">struct</span> <span style="COLOR: #2b91af">TNtrGestures</span></p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; {</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; [<span style="COLOR: #2b91af">FieldOffset</span>(0)]<span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> ReceiveZoom;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; [<span style="COLOR: #2b91af">FieldOffset</span>(1)]<span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> UseUserZoomSettings;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; [<span style="COLOR: #2b91af">FieldOffset</span>(2)]<span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> ReceiveScroll;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; [<span style="COLOR: #2b91af">FieldOffset</span>(3)]<span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> UseUserScrollSettings;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; [<span style="COLOR: #2b91af">FieldOffset</span>(4)]<span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> ReceiveFingersDoubleTap;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; [<span style="COLOR: #2b91af">FieldOffset</span>(5)]<span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> UseUserFingersDoubleTapSettings;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; [<span style="COLOR: #2b91af">FieldOffset</span>(6)]<span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> ReceiveRotate;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; [<span style="COLOR: #2b91af">FieldOffset</span>(7)]<span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> UseUserRotateSettings;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; }</p>
</div>
<p>Once I used the FieldOffsetAttribute to set each <font style="COLOR: blue">bool</font> to one byte each, the Rotate messages started to work correctly. Thanks Ben... </p>
<br>
<h2>WPF Gestures Example Code</h2>
<div style="FONT-SIZE: 10pt; BACKGROUND: #e0e0e0; COLOR: black; FONT-FAMILY: Courier New">
<p style="MARGIN: 0px">&nbsp;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: #2b91af">WindowInteropHelper</span> winHelper = <span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">WindowInteropHelper</span>(<span style="COLOR: blue">this</span>);</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: #2b91af">HwndSource</span> hwnd = <span style="COLOR: #2b91af">HwndSource</span>.FromHwnd(winHelper.Handle);</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; hwnd.AddHook(<span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">HwndSourceHook</span>(<span style="COLOR: blue">this</span>.MessageProc));</p>
<p style="MARGIN: 0px">&nbsp;</p>
</div>
<p>Using the same GestureLib class library, I also created an app that shows how to capture the gestures using a WPF application.&nbsp; That was an interesting exercise because I had never gotten a Windows handle from a WPF app.&nbsp; I discovered the WinInteropHelper class that gets the underlying Windows handle. I also had to hook the MessageProc handler to get the messages.&nbsp; The WndProc method is not available to override in WPF.</p>
<em>WPF Gestures Test source code</em> <a href="http://www.therobotgeek.net/downloads/gestureblocks/WpfGestureTest.zip"><u><font color=#800080>WpfGestureTest.zip</font></u></a> <br><br>
<h2>Gesture Blocks - C# Game using Gestures and Flicks</h2>
<p>Just creating test apps is boring and I wanted to create a game example that uses the flicks and gestures for control. I chose to build a simple game that shows off some of the possibilities for touch control. I call the game Gesture Blocks. It will give you a good starting point on using gestures in games. Watch the video to see the gestures in action.</p>
<p><embed src=http://www.youtube.com/v/3AHvY2zpDlM&amp;hl=en&amp;fs=1 width=480 height=295 type=application/x-shockwave-flash allowfullscreen="true" allowscriptaccess="always"></embed></p>
<em>Gesture Blocks Game source code</em> <a href="http://www.therobotgeek.net/downloads/gestureblocks/WinGestureBlocks.zip"><u><font color=#800080>WinGestureBlocks.zip</font></u></a> <br>
<h2>Conclusion</h2>
<p>I hope the code I provided was useful and helpful. I will try to update the examples as issues are resolved. I'm also going to work on some other game examples that continue to show what can be done with gestures. The next project will be to load Windows 7 onto the tablet and write some code for more than DuoGestures. </p>
<br>
<img src ="http://www.cppblog.com/zmj/aggbug/83399.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-05-19 17:52 <a href="http://www.cppblog.com/zmj/archive/2009/05/19/83399.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AUTOCAD二次开发工具</title><link>http://www.cppblog.com/zmj/archive/2009/05/15/83024.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Fri, 15 May 2009 01:54:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/05/15/83024.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/83024.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/05/15/83024.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/83024.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/83024.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ARX(AutoCAD Runtime eXtension实时运行扩展)作为继AutoLISP、ADS后的第三代开发工具，采用全新的面向对象编程技术。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1985年6月推出的AutoCAD2.17版本使用AutoLISP作为AUTOCA...&nbsp;&nbsp;<a href='http://www.cppblog.com/zmj/archive/2009/05/15/83024.html'>阅读全文</a><img src ="http://www.cppblog.com/zmj/aggbug/83024.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-05-15 09:54 <a href="http://www.cppblog.com/zmj/archive/2009/05/15/83024.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>arx &amp; c++ 开发技巧讲解</title><link>http://www.cppblog.com/zmj/archive/2009/05/14/82918.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Thu, 14 May 2009 01:57:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/05/14/82918.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/82918.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/05/14/82918.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/82918.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/82918.html</trackback:ping><description><![CDATA[<div class=postText>
<p>以下是做CAD二次開發一年多來的一些讀書筆記﹕<br>节选于《AutoCAD高级开发技术：ARX编程及应用》</p>
<p>跟大家分享<br>一．图块设计技术: </p>
<p>在AutoCAD数据库中，以各图块实际上市存储在块表记录里的实体集合。每个图块从一格AcDbBlockBegin对象开始，紧接着是一个或多个AcDbEntity对象，最后以AcDbBolckEnd对象结束，按其所属关系得层次结构分为三层：第一层为块表，是属于数据库管理的根对象；第二层为块表记录，是属于块表管理的对象；第三层为组成图块的实体对象，是属于块表记录管理的基本对象。因而，在AutoCAD数据库中，定义图块的第一个过程式向块表中加入一条新的块表记录，然后将组成图块的实体对象写入该块表记录中。</p>
<p>1.AutoCAD数据库中图块的引用<br>在AutoCAD系统中插入已定义的块并不是将块中所有实体复制到数据库中，而是通过块引用机制向块表记录增加一个AcDbBlockReference类引用对象。所谓的块引用实际上是用户用Insert命令或ARX引用程序向AutoCAD数据库中插入的图块。在ARX应用程序中，利用定义的AcDbBlockReference类实例及相应的成员函数可以设置插入块的有关特性，如插入点、旋转角以及XYZ方向的比例系数等。插入不带属性的简单图块的编程技术相对比较简单，做法如下：<br>A．创建一个指向AcDbBlockReference类对象实例的指针。<br>B．调用该类的成员函数setBlockTableRecord()设置引用图块的ID号。<br>C．调用该类的成员函数setPosition(),setRotation()和setScaleFactors()分别设置块引用的插入点、旋转角和XYZ方向的比例系数等。<br>D．打开当前图形模型空间的块表，利用getBlockTable()函数获得指向当前图形的块表指针。<br>E．调用appendAcDbEntity()函数将块引用加入当前数据库模型空间块表记录中。</p>
<p>2. 属性块的引用：<br>在块定义中的附加属性信息必须通过调用AcDbBlockReference类的成员函数appendAttribute()才能加入到块引用中。<br>定义属性块时，属性实质上是附加于构成图块的某一实体上的一个或多个非图形信息。因此，在插入属性时必须检索出属性块定义时的所有附加信息，然后将其附加于块引用的相应实体上，这就需要遍历块中的全部实体。<br>通过属性块的ID号打开其块表记录，从而获得指向块表记录的指针。程序代码为:<br>AcDbBlockTableRecord *pBlockDef; //定义指向块表记录的指针<br>acdbOpenObject(pBlockDef,blockid,AcDb::kForRead); //获得指向块表记录的指针<br>参数blockid为属性的ID号，然后，定义一个用于遍历块表记录的浏览器，获得指向块表记录的浏览器指针，如：<br>AcDbBlockTableIterator *pIterator; //定义指向块表记录浏览器的指针<br>pBlockDef-&gt;newIterator(pIterator); //获得指向块表记录的浏览器指针<br>成员函数newIterator()用于创建块表记录的浏览器对象，参数pIterator为指向块表记录的浏览器指针。在此基础上建立一个循环结构，用于遍历图块中的全部实体，得到指向某一实体的指针，其结构如下：<br>AcDbEntity *pEnt; //定义指向实体的指针<br>AcDbAttributeDefinition *pAttdef; //定义指向属性定义的指针<br>For (pIterator-&gt;state(); !pterator-&gt;done(); pIterator-&gt;step())<br>{<br>pIterator-&gt;getEntity(pEnt,AcDb::kForRead); //得到指向实体的指针<br>pAttdef = AcDbAttributeDefinition::cast(pEnt); //得到指向属性定义的指针<br>//处理属性插入的代码<br>&#8230;&#8230;<br>pEnt-&gt;close(); //关闭尸体对象<br>}<br>实体属性的插入代码的执行机理如下：<br>1）. 创建AcDbAttribute类对象，获得指向该对象的指针。<br>如： AcDbAttribute *pAtt = new AcDbAttribute;<br>2）. 设置新建的AcDbAttribute类对象的属性值及特性,如属性位置,字高,旋转角度,属性文本等.<br>3) . 调用appendAttribute()函数将属性附加于pBlkRef指向的块引用中。<br>如： pBlkRef-&gt;appendAttribute(attid,pAtt);<br>其中，pBlkRef为指向块引用的指针，pAtt为前面创建的AcDbAttribute类对象的指针。</p>
<p>3. AutoCAD数据库中图块的检索<br>对于AutoCAD数据库来说，图块的检索主要包括用户定义的有名块和图形中已插入的块引用两个方面。<br>1）. 先介绍当前图形数据库中块的检索技术：<br>用ads_tblnext()函数可以得到当前图形的数据库中表示块定义得链表，将改链表存储于结果缓冲区类型的变量中，利用结果缓冲区中的联合体成员就可以获得块名、基点等信息。重复调用ads_tblnext()函数将遍历整个数据库链表中的所有块表记录，从而得到全部已定义的图块信息。<br>2) . 用户定义数据库中块的检索：<br>对于在ARX应用中定义的其他数据库，只能用ARX库的函数才能检索出该数据库中所定义的图块，程序的主要设计技术如下：<br>A. 利用AcDbBlockTable类的成员函数newIterator()创建块表浏览器.<br>如： pBTable-&gt;newiterator(pBIterator);<br>pBTable为AcDbBlockTable类指针；pBIterator为AcDbBlockTableIterator类块表浏览器指针.<br>B. 利用循环结构和块表浏览器遍历块表。<br>C．利用AcDbBlockTableIterator类成员函数getRecord()获得块表记录。<br>如：pIterator-&gt;getRecord(pBTRecord,AcDb::kForRead);<br>D. 利用块表记录类的成员函数getName()得到块名。<br>4. 块中实体的检索：<br>在检索任意数据库中的图块时，主要是利用块表浏览器遍历块表，从而获得图块名。而在获得块名的前提下，利用ARX库提供的块表记录浏览器遍历块表记录中的所有实体，从而实现对块中实体的检索。方法为：<br>A．用一种合适的方式获得图块名，得到指向该图快的块表记录。<br>B．生成块表记录浏览器。<br>C．遍历块中的多有实体，得到检索结果。</p>
<p>现在知道图框的名字是A3，要求遍历图框中属性：pBlkRef为AcDbBlockReference实体。<br>AcDbObjectIterator *pBlkRefAttItr=pBlkRef-&gt;attributeIterator();<br>for (pBlkRefAttItr-&gt;start(); !pBlkRefAttItr-&gt;done();pBlkRefAttItr-&gt;step())<br>{<br>AcDbObjectId attObjId;<br>attObjId = pBlkRefAttItr-&gt;objectId();</p>
<p>AcDbAttribute *pAtt = NULL;<br>Acad::ErrorStatus es = acdbOpenObject(pAtt, attObjId, AcDb::kForRead);<br>if (es != Acad::eOk) <br>{<br>acutPrintf("\nFailed to open attribute");<br>delete pBlkRefAttItr;<br>continue;<br>}<br>if (strcmp(pAtt-&gt;tag(),"TITLE:") == 0)<br>{<br>CString title = pAtt-&gt;textString();<br>if (strcmp(title,"PROGRESS(D)") == 0)<br>{ //操作<br>}<br>else if (strcmp(title,"PROGRESS(P)") == 0)<br>{<br>//操作<br>}<br>}<br>pAtt-&gt;close();<br>}</p>
<p>二．容器对象：符号表的操作和使用技术<br>符号表的操作主要分为向符号表中加入一条符号表记录，符号表记录的检索和符号表记录中对象的处理等，每一种操作都是通过相应的符号表类提供的成员函数来实现的。<br>1.层表的操作和使用技术：<br>A． 创建新层：<br>1). 以写的方式调用getSymbolTable()函数打开当前数据库的层表，获得指向该表的指针。<br>2) 调用构造函数AcDbLayerTableRecord()创建层表建立对象。<br>3) 设置层名。<br>4) 设置层的有关属性。<br>5) 调用add()函数将层表记录加入到层表中。<br>6) 关闭层表和层表记录。</p>
<p>2. 层的属性设置和查询函数<br>层的属性包括：颜色、冻结状态、锁定状态、开关状态、在新视口中层的冻结状态和线型，下面列出的设置和查询函数均是AcDbLayerTableRecord类的成员函数。<br>A．设置颜色：setColor(const AcCmColor color);<br>B．设置冻结状态：setIsFrozen(bool frozen);<br>如果参数frozen为true表层冻结；frozen为false表层冻结。<br>C．设置锁定状态：setIsLocked(bool locked);<br>如果参数locked为true表层锁定；locked为false表层解锁。<br>D．设置开关状态：setIsOff(bool off)；<br>如果参数off为true表层关闭；off为false表层打开。<br>E．设置在新视口中层的冻结状态：setVPDFLT(bool frozen)；<br>如果参数frozen为true表在新视口中层将冻结；frozen为false表在新视口中层解冻。<br>F．设置线型：setLinetypeObjectId(AcDbObjectId id)；<br>在调用构造函数AcDbLayerTableRecord()创建层表记录时，上述参数的缺省值为：<br>Color为7(white),isFrozen为false，isLocked为false，isoff为false，VPDFLT为false，线型的ID号为NULL。</p>
<p>3. 层属性的修改和查询实例的基本方法：<br>A．以读方式打开层表，获得指向层表的指针。<br>B．调用层表类的成员函数getAt()，以写的方式获得指定层名的层表记录指针。<br>C．调用属性设置函数修改属性或调用属性查询函数获得属性；</p>
<p>4. 数据库中层的检索的基本方法：<br>A．利用AcDbLayerTable类的成员函数newIterator()创建层表浏览器。<br>B．利用循环结构和块表浏览器遍历块表。<br>C．利用AcDbLayerTableIterator类的成员函数getRecord()获得块表记录。<br>D．利用成员函数getName()得到层名。</p>
<p>5. 设置图形数据库的当前层：<br>调用AcDbDatabase类的成员函数setClayer()设置图形数据库的当前层，其函数原型为：<br>Acad::ErrorStatus setClayer(AcDbObjectId objId);<br>函数的参数为层表的ID号。获得层表记录ID号的主要方法有：<br>1) 将新建的层表记录加入层表时，用下面的形式调用add()函数：<br>AcDbLayerTable::add(AcDbObjectId &amp; layerID,AcDbLayerTableRecord *pRecord);<br>在关闭层表和层表记录的代码后，加入&#8220;acdbCurDwg()-&gt;setClayer(layerID);&#8221;设置当前层。<br>2) 若层已经存在，则可利用获得指定符号表ID号的形式调用getAt()函数：<br>AcDbLayerTable:: getAt(const char* entryName, AcDbObjectId&amp; recordId, bool getErasedRecord = false) const;<br>然后调用加入&#8220;acdbCurDwg()-&gt;setClayer(layerID);&#8221;设置当前层。<br>6. 定义字体样式<br>AutoCAD数据库的字体样式是字体样式中的一条记录，其缺省的字体样式名为STANDARD，字体文件名为txt.shx。用STYLE定义一个新的字体样式包括建立样式名，选择字体文件和确定字体效果三步操作。用户新定义的字体样式是作为一条字体样式表记录加入字体样式表中。<br>A．以写方式调用getTextStyleTable()哈数打开当前图形数据库的字体样式表，获得指向该表的指针。<br>B．调用构造函数AcDbTextStyleRecord()创建字体样式表记录对象。<br>C．设置字体样式名和字体文件名。<br>D．设置字体的效果，包括倒置、反向、垂直、宽度比例和倾斜角的设置。<br>E．调用add()函数将字体样式表记录加入字体样式表中。<br>F．关闭字体样式表和字体样式表记录。</p>
<p>7. 尺寸标注样式和尺寸变量<br>尺寸标注样式是AutoCAD数据库中尺寸标注样式表的一条记录，其缺省的尺寸标注样式名为STANDSRD，该样式由系统自动建立。尺寸变量是确定组成尺寸标注线、尺寸界线、尺寸文字以及箭头的样式、大小和它们之间相对位置等的变量。<br>对标注样式名为STANDARD的尺寸变量进行修改，首先要打开当前图形数据库的尺寸标注样式表，并调用getAt()函数获得指向尺寸标注样式表记录STANDARD的指针，然后调用AcDbDimStyleTableRecord类成员函数设置尺寸变量。<br>建立新的尺寸标注样式与建立图层和定义字体样式基本相同。，其步骤为：<br>A．以写的方式调用getDimStyleTable()函数打开当前图形数据库的尺寸标注样式表，获得指向该表的指针.<br>B．调用构造函数AcDbDimStyleRecord()创建尺寸标注样式表记录对象。<br>C．设置尺寸标注样式名。<br>D．调用AcDbDimStyleRecord类的成员函数设置尺寸变量。<br>E．调用add()函数将尺寸标注样式表记录加入到尺寸标注样式中。<br>F．关闭尺寸标注样式表和尺寸标注样式表记录。</p>
<p>8. 符号表记录的建立：<br>9种符号表作为AutoCAD数据库中的根对象和容器，包含的下级对象为相应的符号表记录。符号表本身只能由AutoCAD系统建立而不能由应用程序创建，应用程序只能创建符号表记录。如块表中的块表记录，层表中的层表记录，字体样式表中的字体样式记录等，虽然各种具体的符号表记录名称不同，但建立的基本方法相同。归纳主要以下几步：<br>A．以写的方式调用get##BASE_NAME##Table()函数打开数据库的## BASE_NAME##表，获得指向该表的指针。<br>B．调用构造函数AcDb##BASE_NAME##Record()创建相应的符号表记录对象。<br>C．调用setName()函数设置相应的符号表记录名。<br>D．調用符号记录表的成员函数设置其属性。<br>E．调用add()函数将所创建立的符号表记录加入其符号表。<br>F．关闭符号表和符号表记录。</p>
<p>9. 符号表记录的编辑：<br>对于符号表的符号表记录，可以通过符号表记录类的成员函数对其属性进行编辑，如更改字体样式表的字型文件、文字的字高和宽度比例等。符号表记录的编辑实现技术可以分三步：<br>A．以读的方式调用get##BASE_NAME##Table()函数打开数据库的##BASE_NAME##表，获得指向该表的指针。<br>B．调用符号表类的成员函数getAt()获得符号表记录指针。<br>C．调用相应的符号表记录成员函数修改其属性。</p>
<p>10.符号表记录的查询：<br>符号表记录的查询主要利用符号表浏览器和循环结构实现，步骤如下：<br>A．利用AcDb##BASE_NAME##Table类的成员函数newIterator()创建符号表浏览器。<br>B．利用循环结构和块表浏览器遍历块表。<br>C．利用AcDb##BASE_NAME##TableIterator类的成员函数getRecord()获得符号表记录。<br>D．利用成员函数getName()得到符号表记录名。<br>例子：<br>AcDb##BASE_NAME##Table *pTable;<br>acdbHostApplicationServices()-&gt;workingDatabase()<br>-&gt;get##BASE_NAME##Table (pTable,AcDb::kForRead);</p>
<p>AcDb##BASE_NAME##TableIterator *pIter;<br>pTable -&gt;newIterator(pIter);<br>pTable -&gt;close();</p>
<p>AcDb##BASE_NAME##TableRecord *pRecord;<br>for (pIter -&gt;start();!pIter -&gt;done();pIter -&gt;step())<br>{<br>pIter -&gt;getRecord(pRecord,AcDb::kForWrite);<br>char *m_name;<br>pRecord -&gt;getName(m_name);<br>//添加相应的操作<br>free(m_Layername);<br>pRecord -&gt;close();<br>}<br>delete pLayerIter;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>三．对象字典的操作<br>对象字典和符号表均是AutoCAD图形数据库中的容器对象。在9种符号表中，每一种符号表只能用来存储特定的对象，如块表用来存储块表记录，层表用来存储层表记录等，而对象字典却不受此限制，它可以存储任何类型的对象，包括其他对象字典、数据库对象和应用程序创建的对象。因此，所谓的对象字典实际上是一种通用的对象容器。</p>
<p>1. 组字典的操作使用技术:<br>组是实体等数据库对象的有序集合，是组字典的成员。从层次关系来看，组是管理其所包含对象的容器，而组字典则是管理组对象的容器。一个组实际上可以认为是一个选择集，但又不同于一般的选择集，它是組字典中一個有名的常驻对象。当组中的一个实体被删除时，该实体自动地从组中移出；当恢复被删除的是天时，该实体又自动地加入到该组中。使用组可以简化操作，容易实现对一批对象的颜色、层和线型等属性的统一修改。<br>组字典中可以包含若干个组，每个组通过其组名来区分。<br>A．直接从数据库中获得指向组字典的指针：<br>Acad::ErrorStatus getGroupDictionary（AcDbDictionary*&amp; pDict，AcDb::OpenMode mode);<br>B．从对象字典中获得组字典的指针：<br>由于组字典是对象字典中的一个名为&#8220;ACAD_GROUP&#8221;的成员，因此先获得数据库中指向对象字典的指针，然后调用getAt()函数获得指向组字典的指针。<br>AcDbDictionary *pNamedObj,*pGroupDict;<br>acdbCurDwg()-&gt;getNamedObjectsDictionary(pNamedObj,AcDb::kForRead);<br>pNamedObj-&gt;getAt("ACAD_GROUP",(AcDbObject *&amp;)pGroupDict,AcDb::kForWrite);</p>
<p>2. 将组加入组字典中：<br>setAt(const char* srchKey,AcDbObject *newValue,AcDbObjectId&amp; retObjId);<br>各参数的意义为：srchKey为组名，用字符串表示；newValue为加入到组字典中的新组的指针；retObjId为函数返回的已加入组字典中的组对象的ID号。如果在组字典中已有同名的组存在，则将被新加入的组取代。调用该函数时，必须先创建组对象，将指向组对象的指针和定义的组名作为输入参数，并获得加入组字典中的组对象ID号。<br>其中组对象为AcDbGroup类。具体的操作查相关的类函数即可！</p>
<p>3.建立多线样式：<br>多线是指多条互相平行的直线，各条线的线型、颜色和他们之间的间距等属性可互不相同。多条的这些属性由多线样式定义。定义一个多线样式的步骤为：<br>A．通过getMLStyleDictionary()函数获得指向图形数据库中的多线样式字典的指针。<br>B．用多线样式的构造函数AcDbMlineStyle()创建多线样式对象。<br>C．利用AcDbDictionary类的成员函数setAt()将所建立的多线样式加入字典中。<br>D．调用有关函数设置多线样式的属性，如设置多次按名称、元素特性和多线特性等。</p>
<p>4.用户对象字典的操作和使用技术：<br>在AutoCAD数据库中，对象字典是字典类数据库对象的总称。按其层次关系可分为两类，一是由AutoCAD数据库直接管理的第一层对象字典；二是由第一层对象字典管理的第二层对象字典。为了便于区别，我们把第一层对象字典成为有名对象字典，用户在应用程序中定义的字典成为用户字典。前面提到的组字典、多线样式字典和用户对象字典均属于第二层对象字典，其中组字典和多线字典是系统自动生成的对象字典。<br>对象字典的第三层为字典中的对象。如：组诗组字典中的对象，多线样式是多线样式字典中的对象，在用户对象字典中可以包含任何类型的对象，如实体对象、自定义对象和数据库对象等。有名对象字典中的各用户对象字典之间，通过其字名来表示；用户字典中的对象利用其对象名来区分。<br>4.1 用户对象字典的定义和字典对象的查询：<br>在有名对象字典中定义一个用户对象字典的实质是创建一个AcDbDictionary类对象，并将其加入有名对象字典中，其步骤为：第一,调用AcDbDatabase类的成员函数getNameObjectDictionary()得到有名对象字典的地址(即指针)；第二，定义新的用户对象字典并加入有名对象字典中。<br>例子：<br>AcDbDictionary *pNamedObj; //定义有名对象字典<br>acdbCurDwg()-&gt;getNamedObjectsDictionary(pNamedObj,AcDb::kForWrite);<br>AcDbDictionary *pDict = new AcDbDictionary; //定义用户对象字典<br>AcDbObjectId eid;<br>pNamedObj-&gt;setAt("Name",pDict,eid);<br>而在用户字典中对象查询的第一步是建立字典浏览器遍历对象字典：<br>AcDbDictionaryIterator *pDictIter = pDict-&gt;newIterator();<br>字典对象查询的第二步是得到指向对象的指针：<br>pDictIter-&gt;getObject(pObj,AcDb::kForRead);<br>在获得对象指针的前提下，可以利用对象的成员函数进行查询、检索和编辑等操作。<br>另外，用户字典中的对象名可以用AcDbDictionaryIterator类的成员函数name()获得。而该对象名表示的对象类名可以用&#8220;pObj-&gt;isA()-&gt;name()&#8221;形式获得。<br>需要注意的是：将块表记录中的实体对象加入用户字典，并不是将实体复制到字典中，而是在字典中存储其对象的指针。因此，当块表记录中的实体被删除后，在字典中相应的对象名和指针也不再存在。</p>
<p>4.2 用户对象字典：扩展记录的加入和查询。<br>扩展记录属于AcDbxrecord类的对象，可用来定义任何类型的数据。扩展记录的数据项采用结果缓冲区链表的形式定义，每一项由DXF组码和相应的组值构成。扩展记录是一个在应用程序中定义的数据库对象，属于有名对象字典的下级对象或某一对象的扩展字典和其他扩展记录的下级对象。<br>在ARX中创建扩展记录的主要步骤如下：<br>1.获得数据库中指向有名对象字典的指针。<br>2.建立一个新的用户脆响字典，并加入有名对象字典中。<br>3.创建新的扩展记录，并加入用户对象字典中，如：<br>AcDbXrecord *pXrec = new AcDbXrecord;<br>pDict-&gt;setAt("XREC1", pXrec, xrecObjId);<br>4.用ads_buildlist()函数构造由扩展记录数据项组成的缓冲区链表，其一般形式为：<br>ads_buildlist(&lt;组码1&gt;，&lt;组值1&gt;，&lt;组码2&gt;，&lt;组值2&gt;，&#8230;&#8230;，0)；<br>5. 调用AcDbXrecord的成员函数setFromRbChain()设置扩展记录所指向的链表指针。</p>
<p>三．ARX应用程序中的尺寸标注技术<br>1. 尺寸对象的组成和常用的尺寸标注类：<br>尺寸标注也是AutoCAD数据库中块表记录中的一种对象。一个完整的尺寸对象由尺寸标注线，尺寸界线，尺寸箭头和尺寸文字构成。<br>在AutoCAD数据库中，AcDbDimension类为尺寸标注的基类，其派生类主要有对齐标注(AcDbAlignedDimension),两线定角标注(AcDb2LineAngularDimension),三点定角标注(AcDb3PointAngularDimension),直径标注(AcDbDiametricDimension),半径标注(AcDbRadialDimension),坐标尺寸标注(AcDbOrdinateDimension),定角标注(AcDbRotatedDimension)等。<br>尺寸标注类是实体类(AcDbEntity)的派生类，其主要成员函数的原型为：<br>1.设置尺寸文字位置：<br>Acad::ErrorStatus setTextPosition(const AcGePoint3d&amp; unnamed);<br>2. 设置尺寸标注样式：<br>Acad::ErrorStatus setDimensionStyle(AcDbObjectId unnamed);<br>3. 设置尺寸文字：<br>Acad::ErrorStatus setDimensionText(const char* unnamed);<br>4. 设置尺寸文字旋转角度：<br>Acad::ErrorStatus setTextRotation(double unnamed);<br>5. 查询尺寸文字：<br>Char* dimensionText()const;<br>6. 查询尺寸文字位置：<br>AcGePoint3d textPosition()const;<br>7. 查询尺寸文字旋转角度<br>double textRotation()const;<br>2.尺寸标注的鼠标拖动技术：<br>实现尺寸标注线和尺寸文字为字的鼠标拖动的关键是跟踪鼠标的移动，并根据鼠标的位置动态显示尺寸标注。用ads_grread()憾事跟踪鼠标的移动，其函数原型为：<br>Int ads_grread(int track,int *type,struct resbuf *result);<br>参数track为控制位，其值为1则将鼠标的坐标存入result中；type表示输入的种类，如按鼠标左键，则type=3；<br>尺寸标注的鼠标拖动原理为：<br>首先，设置ads_grread()函数控制位track=1,在循环结构中用ads_grread()函数追踪鼠标的移动，获得当前鼠标位置的x,y坐标。用ads_grread(track,&amp;type,&amp;result)形式调用，则点的x和y坐标值可分别用result.resval.rpoint[X]和result.resval.rpoint[Y]形式获得。其次，以写方式打开尺寸标注对象，用获得的X，Y坐标设置尺寸标注线和尺寸位置，并关闭对象。循环执行，实现尺寸步标注对象的拖动。如果按鼠标左键拾取一个点，则type=3，结束循环。<br>例子：公差标注设置函数：<br>void SetDimtpAndDimtm(double tp,double tm)<br>{<br>AcDbDimStyleTable *pDimStyleTbl;<br>acdbCurDwg()-&gt;getDimStyleTable(pDimStyleTbl,AcDb::kForRead);<br>AcDbDimStyleTableRecord *pDimStyleTblRcd;<br>pDimStyleTbl-&gt;getAt("",pDimStyleTblRcd,AcDb::kForWrite);<br>if (fabs(tp) == fabs(tm))<br>{<br>pDimStyleTblRcd-&gt;setDimtfac(1.0)<br>}<br>else pDimStyleTblRcd-&gt;setDimtfac(0.5);<br>if (tp == 0.0 &amp;&amp; tm == 0.0)<br>{<br>pDimStyleTblRcd-&gt;setDimtol(0);<br>}<br>else<br>{<br>pDimStyleTblRcd-&gt;setDimtp(tp);<br>pDimStyleTblRcd-&gt;setDimtol(1);<br>pDimStyleTblRcd-&gt;setDimtm(tm);<br>}<br>pDimStyleTblRcd-&gt;close();<br>pDimStyleTbl-&gt;close();<br>}</p>
<p>3.图案填充函数介绍：<br>图案填充函数AcDbHatCh也是实体立体(AcDbEntity)的派生类，与尺寸标注类似，图案填充也是 AutoCAD数据库中块表记录中的一种对象。<br>生成图案填充对象的步骤为：<br>A．调用图案填充类的构造函数创建AcDbHatch类对象。<br>B．调用AcDbHatch类的成员函数设置填充图案的法向矢量，关联，标高，缩放比例，填充图案，填充方式和填充边界等属性。<br>C．调用evaluateHatch()显示填充图案。<br>D．将AcDbHatch类对象写入当前图形数据库的块表记录中。</p>
<p>4.ARX应用程序中视图管理技术和应用：<br>视图和视口是AutoCAD环境中图形显示中经常涉及到的基本概念。图形屏幕上用于显示图形的一个矩形区域称为视口，可以把整个图形屏幕作为一个视口，也可以把整个视图屏幕设置成多个视口。当前视口中显示的复杂图形按不同的窗口大小设置，并以视图名为表示在图形数据库中保存。在需要时，显示指定视图以满足对图形编辑和浏览的需要。<br>视图的管理包括视图的定义，显示，属性设置和查询等功能。在AutoCAD的交互环境中，用户可以使用VIEW命令对视图进行命名，保存，恢复和删除。在ARX应用程序中，主要是通过使图表类及视图表记录类的成员函数实现视图的管理功能。<br>视图类作为视图表(AcDbViewTable)中的一条视图记录(AcDbViewTableRecord)保存在AutoCAD数据库中。把当前视口中指定窗口每得图形定义为一个新的视图的操作等价于向数据库中添加一个AcDbViewTableRecord类对象。其实现步骤为：<br>A．调用视图标记录类的构造函数创建AcDbViewTableRecord类对象；<br>B．调用AcDbViewTableRecord类的成员函数设置视图名，视图中心点，视图高度和宽度等属性；<br>C．获得当前图形数据库中的视图表指针，将AcDbViewTableRecord类对象添加到数据库中。<br>视图的查询首先要获得当前图形数据库中指定视图师表记录的指针，然后调用相应的成员函数得到该视图的属性。</p>
<p>四．ARX中的实体造型技术和应用<br>三维造型包括线框模型、表面模型和实体模型三种形式，其中三维实体具有体的特征。能夠較全面地反映形体的物理特征。在机械CAD中，利用实体造型技术用户不仅可以通过并、交、差布尔运算生成所需的机械零部件模型，而且还能够对形体进行剖切成剖视图以进行体积、重心和惯性矩等物性计算和分析，进而在实体模型的基础上生成NC代码，在ARX应用程序中，并不是直接使用AutoCAD系统本身提供的有关实体造型和编辑命令，而是通过直接生成数据库对象及调用AcDb3dSolid类的成员函数来进行实体造型。<br>1.基本三维实体生成方法：<br>在AutoCAD数据库中，三维实体属于AcDb3dSolid类对象，该类是AcDbEntity类的派生类。<br>对于一个具体的几何实体，即ACIS对象来说，AcDb3dSolid实体是一个容器和接口。<br>通过AcDb3dSolid类的成员函数可以生成各种基本的三维实体以及实现实体的布尔运算。生成三维实体的基本步骤为：<br>A．调用AcDb3dSolid类的构造函数创建一个容器对象：<br>如：AcDb3dSolid *p3dObj = new AcDb3dSolid;<br>B.调用AcDb3dSolid类的成员函数创建基本三维实体对象。其一般形式为：<br>指向AcDb3dSolid类对象的指针-〉创建基本三维实体对象成员函数。<br>B．将AcDb3dSolid类对象写入当前图形数据库的块表记录中，其代码设计方法与二维对象的添加完全相同。</p>
<p>&nbsp;</p>
<p>ARX程序的消息响应：<br>ARX程序实质上是一动态库，它直接与AutoCAD进行对话，即AutoCAD发送各种消息给ARX程序，ARX程序负责对各种消息作出相应的处理。<br>kInitAppMsg:<br>当ARX程序被加载时发送该消息，用以建立AutoCAD和应用程序之间的对话。<br>kUnloadAppMsg:<br>当ARX程序卸载时(不论是用户卸载应用程序，还是由AutoCAD终止退出)发送该消息，关闭文件以及执行必要的清理工作。<br>kOleUnloadAppMsg:<br>发送该消息确定应用程序是否可以卸载，即该应用程序的ActiveX对象或接口是否被其他应用程序所引用。<br>kLoadDwgMsg:<br>当打开一幅图形时发送消息，此时AutoCAD的图形编辑环境进行了初始化，并且，应用程序可以调用ARX的全局函数，而acedCommand()函数除外。<br>kUnLoadDwgMsg:<br>当用户退出当前的图形编辑时发送该消息。</p>
<p>下面的代码将实例生成由 某一图层上所有的实体组成的选择集：<br>struct resbuf *plb;<br>char sbuf[32];<br>ads_name ss1;<br>plb = acutNewRb(8) //图层DXF组码是8<br>strcpy(sbuf,&#8221;PARTS&#8221;); //图层名为PARTS<br>plb-&gt;resval.rstring = sbuf;<br>plb-&gt;rbnext = NULL;<br>acedSSGet(&#8220;X&#8221;,NULL,NULL,plb,ss1);<br>acutRelRb(plb); //don&#8217;t forget<br>下面的例子是选择&#8220;PARTS&#8221;图层上的所有圆，这是一个利用acutBuildList()函数构造结果缓冲区表后再传给acedSSGet()函数的实例：<br>ads_name ss1;<br>struct resbuf *rb1;<br>rb1 = acutBuildList(RTDXFO,&#8221;CIRCLE&#8221;,8,&#8221;PARTS&#8221;,RTNONE);<br>acedSSGet(&#8220;X&#8221;,NULL,NULL,rb1,ss1);<br>acutRelRb(plb); //don&#8217;t forget</p>
<p>&nbsp;</p>
<p>以上經為個人筆記﹐愿與大家分享﹐共同進步﹗<br>如有錯誤﹐敬請指出﹗ </p>
</div>
<p class=postfoot>posted on 2006-02-08 14:09 <a href="http://www.cppblog.com/mzty/"><u><font color=#0000ff>梦在天涯</font></u></a> 阅读(2287) <a href="http://www.cppblog.com/mzty/archive/2006/02/08/3128.html#Post"><u><font color=#800080>评论(2)</font></u></a> &nbsp;<a href="http://www.cppblog.com/mzty/admin/EditPosts.aspx?postid=3128"><u><font color=#0000ff>编辑</font></u></a>&nbsp;<a href="http://www.cppblog.com/mzty/AddToFavorite.aspx?id=3128"><u><font color=#0000ff>收藏</font></u></a> <a href="http://www.cppblog.com/mzty/services/trackbacks/3128.aspx"><u><font color=#0000ff>引用</font></u></a> 所属分类: <a href="http://www.cppblog.com/mzty/category/1624.html"><u><font color=#0000ff>ARX/DBX</font></u></a> </p>
<img src ="http://www.cppblog.com/zmj/aggbug/82918.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-05-14 09:57 <a href="http://www.cppblog.com/zmj/archive/2009/05/14/82918.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Gesture recognition</title><link>http://www.cppblog.com/zmj/archive/2009/05/12/82685.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Tue, 12 May 2009 06:41:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/05/12/82685.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/82685.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/05/12/82685.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/82685.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/82685.html</trackback:ping><description><![CDATA[LINK: <a href="http://wiki.nuigroup.com/Gesture_recognition">http://wiki.nuigroup.com/Gesture_recognition</a><br><br>
<table class=toc id=toc summary=Contents>
    <tbody>
        <tr>
            <td>
            <div id=toctitle>
            <h2>Contents</h2>
            <span class=toctoggle>[<a class=internal id=togglelink href="javascript:toggleToc()"><u><font color=#0000ff>hide</font></u></a>]</span></div>
            <ul>
                <li class=toclevel-1><a href="http://wiki.nuigroup.com/Gesture_recognition#Background"><u><font color=#800080><span class=tocnumber>1</span> <span class=toctext>Background</span></font></u></a>
                <li class=toclevel-1><a href="http://wiki.nuigroup.com/Gesture_recognition#Gesture_Definition_Markup_Langauge"><u><font color=#800080><span class=tocnumber>2</span> <span class=toctext>Gesture Definition Markup Langauge</span></font></u></a>
                <ul>
                    <li class=toclevel-2><a href="http://wiki.nuigroup.com/Gesture_recognition#Tap_Gesture"><u><font color=#800080><span class=tocnumber>2.1</span> <span class=toctext>Tap Gesture</span></font></u></a>
                    <li class=toclevel-2><a href="http://wiki.nuigroup.com/Gesture_recognition#Double_Tap_Gesture"><u><font color=#800080><span class=tocnumber>2.2</span> <span class=toctext>Double Tap Gesture</span></font></u></a>
                    <li class=toclevel-2><a href="http://wiki.nuigroup.com/Gesture_recognition#Move_Gesture"><u><font color=#800080><span class=tocnumber>2.3</span> <span class=toctext>Move Gesture</span></font></u></a>
                    <li class=toclevel-2><a href="http://wiki.nuigroup.com/Gesture_recognition#Zoom_Gesture"><u><font color=#800080><span class=tocnumber>2.4</span> <span class=toctext>Zoom Gesture</span></font></u></a>
                    <li class=toclevel-2><a href="http://wiki.nuigroup.com/Gesture_recognition#Rotate_Gesture"><u><font color=#800080><span class=tocnumber>2.5</span> <span class=toctext>Rotate Gesture</span></font></u></a> </li>
                </ul>
                <li class=toclevel-1><a href="http://wiki.nuigroup.com/Gesture_recognition#GestureLib_-_A_Gesture_Recognition_Engine"><u><font color=#800080><span class=tocnumber>3</span> <span class=toctext>GestureLib - A Gesture Recognition Engine</span></font></u></a>
                <ul>
                    <li class=toclevel-2><a href="http://wiki.nuigroup.com/Gesture_recognition#Why_GestureLib.3F"><u><font color=#800080><span class=tocnumber>3.1</span> <span class=toctext>Why GestureLib?</span></font></u></a>
                    <li class=toclevel-2><a href="http://wiki.nuigroup.com/Gesture_recognition#Proposed_Processing"><u><font color=#800080><span class=tocnumber>3.2</span> <span class=toctext>Proposed Processing</span></font></u></a> </li>
                </ul>
                </li>
            </ul>
            </td>
        </tr>
    </tbody>
</table>
<script type=text/javascript> if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); } </script>
<a name=Background></a>
<h2><span class=mw-headline>Background</span></h2>
<p>Touchlib does a fine job of picking out contacts within the input surface. At the moment, there is no formal way of defining how those blob contacts are translated into intended user actions. Some of this requires application assistance to provide context, but some of it is down to pattern matching the appearance, movement and loss of individual blobs or combined blobs. </p>
<p>What I'm attempting to describe here, and for others to contribute to, is a way of </p>
<p><br></p>
<ol>
    <li>Describing a standard library of gestures suitable for the majority of applications
    <li>A library of code that supports the defined gestures, and generates events to the application layer </li>
</ol>
<p><br>By using an XML dialect to describe gestures, it means that individual applications can specify their range of supported gestures to the Gesture Engine. Custom gestures can be supported. </p>
<p>By loosely coupling gesture recognition to the application, we can allow people to build different types of input device and plug them all into the same applications where appropriate. </p>
<p>In the early stages of development, we are all doing our own thing with minimal overlap. Over time we will realise the benefits of various approaches, and by using some standardised interfaces, we can mix and match to take advantage of the tools that work best for our applications. Hard coded interfaces or internal gesture recognition will tie you down and potentially make your application obsolete as things move on. </p>
<p><strong>I'd really appreciate some feedback on this - this is just my take on how to move this forward a little at this stage.</strong> </p>
<a name=Gesture_Definition_Markup_Langauge></a>
<h2><span class=mw-headline>Gesture Definition Markup Langauge</span></h2>
<p>GDML is a proposed XML dialect that describes how events on the input surface are built up to create distinct gestures. </p>
<a name=Tap_Gesture></a>
<h3><span class=mw-headline>Tap Gesture</span></h3>
<div dir=ltr style="TEXT-ALIGN: left">
<div class=source-xml style="FONT-FAMILY: monospace">
<pre><span class=sc3><span class=re1><strong>&lt;gdml<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;gesture</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"tap"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;comment<span class=re2>&gt;</span></strong></span></span>
A 'tap' is considered to be equivalent to the single click event in a
normal windows/mouse environment.
<span class=sc3><span class=re1><strong>&lt;/comment<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;sequence<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;acquisition</strong></span><font color=#009900> </font><span class=re0><font color=#000066>type</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"blob"</font></span><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;update<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;range</strong></span><font color=#009900> </font><span class=re0><font color=#000066>max</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"10"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;size</strong></span><font color=#009900> </font><span class=re0><font color=#000066>maxDiameter</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"10"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;duration</strong></span><font color=#009900> </font><span class=re0><font color=#000066>max</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"250"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/update<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;loss<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;event</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"tap"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"x"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"y"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"size"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/event<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/loss<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/sequence<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/gesture<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/gdml<span class=re2>&gt;</span></strong></span></span></pre>
</div>
</div>
<p>The <em>gesture</em> element defines the start of a gesture, and in this case gives it the name 'tap'. </p>
<p>The <em>sequence</em> element defines the start of a sequence of events that will be tracked. This gesture is considered valid whilst the events sequence remains valid. </p>
<p>The <em>acquisition</em> element defines that an acquisition event should be seen (fingerDown in Touchlib). This tag is designed to be extensible to input events other than blob, such as fiduciary markers, real world objects or perhaps facial recognition for input systems that are able to distinguish such features. </p>
<p>The <em>update</em> element defines the allowed parameters for the object once acquired. If the defined parameters become invalid during tracking of the gesture, the gesture is no longer valid. </p>
<p>The <em>range</em> element validates that the current X and Y coordinates of the object are within the specified distance of the original X and Y coordinates. <em>range</em> should ultimately support other validations, such as 'min'. </p>
<p>The <em>size</em> element validates that the object diameter is within the specified range. Again, min and other validations of size could be defined. Size allows you to distinguish between finger and palm sized touch events for example. </p>
<p>The <em>duration</em> element defines that the object should only exist for the specified time period (milliseconds). If the touch remains longer than this period, its not a 'tap', but perhaps a 'move' or 'hold' gesture. </p>
<p>The <em>loss</em> element defines what should occur when the object is lost from the input device. </p>
<p>The <em>event</em> element defines that the gesture library should generate a 'tap' event to the application layer, providing the x, y, and size variables. </p>
<a name=Double_Tap_Gesture></a>
<h3><span class=mw-headline>Double Tap Gesture</span></h3>
<div dir=ltr style="TEXT-ALIGN: left">
<div class=source-xml style="FONT-FAMILY: monospace">
<pre><span class=sc3><span class=re1><strong>&lt;gesture</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"doubleTap"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;comment<span class=re2>&gt;</span></strong></span></span>
A 'doubleTap' gesture is equivalent to the double click event in a normal
windows/mouse environment.
<span class=sc3><span class=re1><strong>&lt;/comment<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;sequence<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;gestureRef</strong></span><font color=#009900> </font><span class=re0><font color=#000066>id</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"A"</font></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"tap"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;duration</strong></span><font color=#009900> </font><span class=re0><font color=#000066>max</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"250"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;gestureRef</strong></span><font color=#009900> </font><span class=re0><font color=#000066>id</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"B"</font></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"tap"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;onEvent</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"acquisition"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;range</strong></span><font color=#009900> </font><span class=re0><font color=#000066>objects</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"A,B"</font></span><font color=#009900> </font><span class=re0><font color=#000066>max</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"10"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/onEvent<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;onEvent</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"tap"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;range</strong></span><font color=#009900> </font><span class=re0><font color=#000066>objects</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"A,B"</font></span><font color=#009900> </font><span class=re0><font color=#000066>max</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"10"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;event</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"doubleTap"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"x"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"y"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"size"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/event<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/onEvent<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/gestureRef<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/sequence<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/gesture<span class=re2>&gt;</span></strong></span></span></pre>
</div>
</div>
<p>This example shows how more complex gestures can be built from simple gestures. A double tap gesture is in effect, two single taps with a short space between. The taps should be within a defined range of each other, so that they are not confused with taps in different regions of the display. </p>
<p>Note that the gesture is not considered invalid if a tap is generated in another area of the display. GestureLib will discard it and another tap within the permitted range will complete the sequence. </p>
<p>In the case of double tap, an initial tap gesture is captured. A timer is then evaluated, such that the gesture is no longer valid if the specified duration expires. However, if a second tap is initiated, it is checked to make sure that it is within range of the first. <em>range</em> is provided with references to the objects that need comparing (allowing for other more complex gestures to validate subcomponents of the gesture). This is done at the point of acquisition of the second object. </p>
<p>Once the second tap is complete and the event raised, range is again validated, and an event generated to inform the application of the gesture. </p>
<a name=Move_Gesture></a>
<h3><span class=mw-headline>Move Gesture</span></h3>
<div dir=ltr style="TEXT-ALIGN: left">
<div class=source-xml style="FONT-FAMILY: monospace">
<pre><span class=sc3><span class=re1><strong>&lt;gesture</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"move"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;comment<span class=re2>&gt;</span></strong></span></span>
A 'move' is considered to be a sustained finger down incorporating
movement away from the point of origin (with potential return during
the transition).
<span class=sc3><span class=re1><strong>&lt;/comment<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;sequence<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;aquisition</strong></span><font color=#009900> </font><span class=re0><font color=#000066>type</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"blob"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;update<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;range</strong></span><font color=#009900> </font><span class=re0><font color=#000066>min</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"5"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;event</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"move"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"x"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"y"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"size"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/event<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/update<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;loss<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;event</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"moveComplete"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"x"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"y"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"size"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/event<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/loss<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/sequence<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/gesture<span class=re2>&gt;</span></strong></span></span></pre>
</div>
</div>
<a name=Zoom_Gesture></a>
<h3><span class=mw-headline>Zoom Gesture</span></h3>
<div dir=ltr style="TEXT-ALIGN: left">
<div class=source-xml style="FONT-FAMILY: monospace">
<pre><span class=sc3><span class=re1><strong>&lt;gesture</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"zoom"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;comment<span class=re2>&gt;</span></strong></span></span>
A 'zoom' is considered to be two objects that move towards or away from
each other in the same plane.
<span class=sc3><span class=re1><strong>&lt;/comment<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;sequence<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;compound<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;gestureRef</strong></span><font color=#009900> </font><span class=re0><font color=#000066>id</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"A"</font></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"move"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;gestureRef</strong></span><font color=#009900> </font><span class=re0><font color=#000066>id</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"B"</font></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"move"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/compound<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;onEvent</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"move"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;plane</strong></span><font color=#009900> </font><span class=re0><font color=#000066>objects</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"A,B"</font></span><font color=#009900> </font><span class=re0><font color=#000066>maxVariance</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"5"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;event</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"zoom"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"plane.distance"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"plane.centre"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/event<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/onEvent<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;onEvent</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"moveComplete"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;plane</strong></span><font color=#009900> </font><span class=re0><font color=#000066>objects</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"A,B"</font></span><font color=#009900> </font><span class=re0><font color=#000066>maxVariance</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"5"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;event</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"zoomComplete"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"plane.distance"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"plane.centre"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/event<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/onEvent<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/sequence<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/gesture<span class=re2>&gt;</span></strong></span></span></pre>
</div>
</div>
<p>A zoom gesture is a compound of two move gestures. </p>
<p>The <em>compound</em> element defines that the events occur in parallel rather than series. </p>
<p>The <em>plane</em> element calculates the line between the two objects, and checks the maximum variance in the angle from its initial (so you can distinguish between a zoom and a rotate, for example). </p>
<p>'move' events from either object are translated into zoom events to the application. </p>
<a name=Rotate_Gesture></a>
<h3><span class=mw-headline>Rotate Gesture</span></h3>
<div dir=ltr style="TEXT-ALIGN: left">
<div class=source-xml style="FONT-FAMILY: monospace">
<pre><span class=sc3><span class=re1><strong>&lt;gesture</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"rotate"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;comment<span class=re2>&gt;</span></strong></span></span>
A 'rotate' is considered to be two objects moving around a central axis
<span class=sc3><span class=re1><strong>&lt;/comment<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;sequence<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;compound<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;gestureRef</strong></span><font color=#009900> </font><span class=re0><font color=#000066>id</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"A"</font></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"move"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;gestureRef</strong></span><font color=#009900> </font><span class=re0><font color=#000066>id</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"B"</font></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"move"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/compound<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;onEvent</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"move"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;axis</strong></span><font color=#009900> </font><span class=re0><font color=#000066>objects</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"A,B"</font></span><font color=#009900> </font><span class=re0><font color=#000066>range</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"5"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;event</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"rotate"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"axis.avgX"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"axis.avgY"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"axis.angleMax"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/event<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/onEvent<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;onEvent</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"moveComplete"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;axis</strong></span><font color=#009900> </font><span class=re0><font color=#000066>objects</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"A,B"</font></span><font color=#009900> </font><span class=re0><font color=#000066>range</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"5"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;event</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"rotateComplete"</font></span><span class=re2><strong>&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"axis.avgX"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"axis.avgY"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;var</strong></span><font color=#009900> </font><span class=re0><font color=#000066>name</font></span><font color=#009900>=</font><span class=st0><font color=#ff0000>"axis.angleMax"</font></span><font color=#009900> </font><span class=re2><strong>/&gt;</strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/event<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/onEvent<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/sequence<span class=re2>&gt;</span></strong></span></span>
<span class=sc3><span class=re1><strong>&lt;/gesture<span class=re2>&gt;</span></strong></span></span></pre>
</div>
</div>
<p>The <em>axis</em> element calculates the midpoint between two objects and compares current position against the initial. </p>
<a name=GestureLib_-_A_Gesture_Recognition_Engine></a>
<h2><span class=mw-headline>GestureLib - A Gesture Recognition Engine</span></h2>
<p><strong>GestureLib does not currently exist!</strong> </p>
<p>The purpose of GestureLib is to provide an interface between Touchlib (or any other blob/object tracking software), and the application layer. GestureLib analyses object events generated by Touchlib, and creates Gesture related events to the application for processing. </p>
<p>GestureLib reads gesture definitions defined in GDML, and the operates a pattern matching principle to those gestures to determine which gestures are in progress. </p>
<a name=Why_GestureLib.3F></a>
<h3><span class=mw-headline>Why GestureLib?</span></h3>
<p>My feeling is that this functionality should be separated from Touchlib, a) for the sake of clarity, and b) because its quite likely that working solutions for a high performance multi-touch environment will require distributed processing. i.e. one system doing blob tracking, another doing gesture recognition, and a further system for the application. If you can get all of your components within the same machine, then excellent, but modularity gives a great deal of flexibility and scalability. </p>
<a name=Proposed_Processing></a>
<h3><span class=mw-headline>Proposed Processing</span></h3>
<p>When a object is acquired, GestureLib sends an event to the application layer providing the basic details of the acquired object, such as coordinates and size. The application can then provide context to GestureLib about the gestures that are allowed in this context. </p>
<p>For example, take a photo light table type application. This will have a background canvas (which might support zoom and pan/move gestures), and image objects arranged on the canvas. When the user touches a single photo, the application can inform GestureLib that the applicable gestures for this object are 'tap', 'move' and 'zoom'. </p>
<p>GestureLib now starts tracking further incoming events knowing that for this particular object, only three gestures are possible. Based on the allowable parameters for the defined gestures, GestureLib is then able to determine over time which unique gesture is valid. For example if a finger appears, it could be a tap, move or potentially a zoom if another finger appears. If the finger is quickly released, only a tap gesture is possible (assuming that a move must contain a minimum time or distance parameter). If the finger moves outside the permitted range for a tap, tap can be excluded, and matching continues with only move or zoom. Zoom is invalid until another finger appears, but would have an internal timeout that means the introduction of another finger later in the sequence can be treated as a separate gesture (perhaps another user, or the same user interacting with another part of the application). </p>
<p>Again, the application can be continually advised of touch events so that it can continue to provide context, without needing to do the math to figure out the exact gesture. </p>
<!--
NewPP limit report
Preprocessor node count: 26/1000000
Post-expand include size: 0/2097152 bytes
Template argument size: 0/2097152 bytes
--><!-- Saved in parser cache with key db1629_wiki-wiki_:pcache:idhash:116-0!1!0!!en!2!edit=0 and timestamp 20090511212724 -->
<div class=printfooter>Retrieved from "<a href="http://wiki.nuigroup.com/Gesture_Recognition"><u><font color=#0000ff>http://wiki.nuigroup.com/Gesture_Recognition</font></u></a>"</div>
<div id=catlinks>
<p class=catlinks><a title=Special:Categories href="http://wiki.nuigroup.com/Special:Categories"><u><font color=#0000ff>Category</font></u></a>: <span dir=ltr><a class=new title=Category:Software::Projects href="http://wiki.nuigroup.com/index.php?title=Category:Software::Projects&amp;action=edit"><u><font color=#0000ff>Software::Projects</font></u></a></span></p>
</div>
<img src ="http://www.cppblog.com/zmj/aggbug/82685.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-05-12 14:41 <a href="http://www.cppblog.com/zmj/archive/2009/05/12/82685.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Touchlib compiling instructions (Windows)</title><link>http://www.cppblog.com/zmj/archive/2009/05/11/82586.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Mon, 11 May 2009 08:46:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/05/11/82586.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/82586.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/05/11/82586.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/82586.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/82586.html</trackback:ping><description><![CDATA[LINK: http://www.multigesture.net/articles/touchlib-compiling-instructions/<br><br>
<div class=post-content>
<p><strong>Hardware:</strong><br>A webcam (USB or a Firewire)</p>
<p><strong>Software:</strong><br><em>Microsoft Visual Studio 2005</em><br><a href="http://msdn2.microsoft.com/en-us/vstudio/aa973782.aspx" jQuery1242031359870="3"><font color=#0000ff><u>MS Visual Studio 2005</u></font></a><br><a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=BB4A75AB-E2D4-4C96-B39D-37BAF6B5B1DC" jQuery1242031359870="4"><font color=#0000ff><u>MS Visual Studio 2005 SP1</u></font></a><br><a href="http://go.microsoft.com/?linkid=6366078" jQuery1242031359870="5"><u><font color=#0000ff>MS Visual Studio 2005 SP1 Update for Windows Vista</font></u></a> (only needed when using vista)</p>
<p><em>TortoiseSVN</em><br><a href="http://tortoisesvn.net/downloads" jQuery1242031359870="6"><u><font color=#0000ff>TortoiseSVN latest binaries</font></u></a></p>
<p><em>Miscallenous Libraries</em><br><a href="http://sourceforge.net/project/showfiles.php?group_id=22870&amp;package_id=16937&amp;release_id=456897" jQuery1242031359870="7"><u><font color=#0000ff>OpenCV</font></u></a> (download OpenCV_1.0.exe)<br><a href="http://sourceforge.net/projects/dsvideolib/" jQuery1242031359870="8"><u><font color=#0000ff>DSVideoLib</font></u></a> (download dsvideolib-0.0.8c)<br><a href="http://sourceforge.net/projects/videowrapper/" jQuery1242031359870="9"><u><font color=#0000ff>VideoWrapper </font></u></a>(download&nbsp; <span class="sfx_qalogger_element sfx_qalogger_clickable">VideoWraper_0.2.5.zip</span>)<br><a href="http://www.xmission.com/~nate/glut.html" jQuery1242031359870="10"><u><font color=#0000ff>GLUT</font></u></a> (download glut-3.7.6-bin.zip)<br><a href="http://www.audiomulch.com/~rossb/code/oscpack/" jQuery1242031359870="11"><u><font color=#0000ff>OSCpack</font></u></a> (download oscpack_1_0_2.zip)<br><a href="http://www.cs.cmu.edu/~iwan/1394/download.html" jQuery1242031359870="12"><u><font color=#800080>CMU 1394 Digital Camera Driver</font></u></a> (download 1394camera645.exe)<br><span style="TEXT-DECORATION: line-through">Windows Server 2003 R2 SDK (aka Platform SDK) <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=0BAF2B35-C656-4969-ACE8-E4C0C0716ADB&amp;displaylang=en" jQuery1242031359870="13"><u><font color=#0000ff>Web Install</font></u></a>, <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=484269E2-3B89-47E3-8EB7-1F2BE6D7123A&amp;displaylang=en" jQuery1242031359870="14"><u><font color=#0000ff>Full download</font></u></a> or <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=E15438AC-60BE-41BD-AA14-7F1E0F19CA0D&amp;displaylang=en" jQuery1242031359870="15"><u><font color=#0000ff>ISO</font></u></a></span><br>The platform SDK has been replaced by the Windows SDK:<br>Download the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=E6E1C3DF-A74F-4207-8586-711EBE331CDC&amp;displaylang=en" jQuery1242031359870="16"><u><font color=#0000ff>Web Install</font></u></a> or <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=F26B1AA4-741A-433A-9BE5-FA919850BDBF&amp;displaylang=en" jQuery1242031359870="17"><font color=#0000ff><u>DVD ISO image</u></font></a><br><a href="http://msdn2.microsoft.com/en-us/xna/aa937788.aspx" jQuery1242031359870="18"><u><font color=#0000ff>DirectX SDK</font></u></a> (download August 2008 or newer)</p>
<h3>Installation instructions</h3>
<ol>
    <li>First install <em>Visual Studio 2005</em>
    <li>Install the the <em>Visual Studio 2005</em> SP1 update - Vista users: Rightclick on the setup and run as administrator.<br>(Also be sure to have a few gigabytes spare on your C:\)
    <li>If you&#8217;re using Windows Vista you will need to install the <em>SP1 update for Vista</em> aswell, again in administrator mode.<br>(Windows XP users can continue reading).
    <li>Now it is time to install the libraries, start with installing OpenCV 1.0. Just use the recommend path and let it set the environment variables.
    <li>Next, create a directory called <strong>C:\_libraries</strong> and unzip the content of <em>dsvideolib</em>, <em>VideoWrapper</em>, <em>GLUT </em>and <em>OSCpack </em>to this directory.<br><a class=thickbox title=touchlib1.jpg href="http://www.multigesture.net/wp-content/gallery/blog_posts/touchlib1.jpg" jQuery1242031359870="2"><img title=touchlib1.jpg alt=touchlib1.jpg src="http://www.multigesture.net/wp-content/gallery/blog_posts/thumbs/thumbs_touchlib1.jpg"></a>
    <li>Install the CMU 1394 Digital Camera Driver (yes, even if you dont have/use a firewire camera)<br>During the setup Check &#8220;Development Files&#8221; and &#8220;Program Shortcuts&#8221;.
    <li>Install the Platform SDK, typical settings should be fine.<br>(I used the ISO to install this, if you use the webinstaller be sure to download the right platform).
    <li>Install the DirectX SDK.
    <li>Install TortoisSVN. </li>
</ol>
<h3>Setting environment variables</h3>
<p>Depending on your setup you might need to change a few directory location values.<em><br></em></p>
<ol>
    <li>Press the right mouse button on &#8220;My Computer&#8221; and choose: Properties &gt; Advanced &gt; Environmental Variables
    <li>To add an entry, click &#8220;new&#8221; at the System Variables.
    <li>Add the OpenCV root directory:<br>name: &#8220;OPENCV_HOME&#8221;<br>value: &#8220;C:\Program Files\OpenCV&#8221;
    <li>Add the DSVideoLib:<br>name: &#8220;DSVL_HOME&#8221;<br>value: &#8220;C:\_libraries\dsvl-0.0.8c&#8221;
    <li>Add the VideoWrapper<br>name: &#8220;VIDEOWRAPPER_HOME&#8221;<br>value: &#8220;C:\_libraries\VideoWraper_0.2.5&#8243;
    <li>Add the OSCpack<br>name: &#8220;OSCPACK_HOME&#8221;<br>value: &#8220;C:\_libraries\oscpack_1_0_2\oscpack&#8221;
    <li>Add the CMU driver location<br>name: &#8220;CMU_PATH&#8221;<br>value: &#8220;C:\Program Files\CMU\1394Camera&#8221; </li>
</ol>
<h3>Checkout touchlib svn</h3>
<ol>
    <li>Create a directory called C:\multitouch in windows explorer
    <li>Click the right mouse button and choose SVN Checkout
    <li>Enter &#8220;http://touchlib.googlecode.com/svn/trunk/&#8221; as the URL of the repository
    <li>Enter &#8220;C:\multitouch\touchlib&#8221; as checkout directory
    <li>Click OK (confirm creation of the directory)
    <li>Downloading the files might take a while because of the demo movies which are included. (rev. 395 is 121,14 MBytes) </li>
</ol>
<h3>Visual studio settings</h3>
<p>We are almost done with setting up the enviroment, there are just a few steps left before we can compile Touchlib.</p>
<ol>
    <li>Open up &#8220;solution.sln&#8221; in the &#8220;C:\multitouch\touchlib\build\VC8&#8243; directory.
    <li>Choose Tools &gt; Options
    <li>On the left choose Project and Solutions &gt; VC++ Directories
    <li>On the right change &#8220;Show directories for:&#8221; to &#8220;Include files&#8221;
    <li>Add the directory &#8220;C:\Program Files\Microsoft SDKs\Windows\v6.1\Samples\Multimedia\DirectShow\BaseClasses&#8221;
    <li>Add the directory &#8220;C:\Program Files\Microsoft SDKs\Windows\v6.1\Include&#8221;
    <li>Add the directory &#8220;C:\Program Files\Microsoft DirectX SDK (March 2009)\Include&#8221;
    <li>Add the directory &#8220;C:\_libraries\glut-3.7.6-bin&#8221;
    <li>Change &#8220;Show directories for:&#8221; to &#8220;Library files&#8221;
    <li>Add the directory &#8220;C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib&#8221;
    <li>Add the directory &#8220;C:\Program Files\Microsoft DirectX SDK (March 2009)\Lib\x86&#8243;
    <li>Add the directory &#8220;C:\_libraries\glut-3.7.6-bin&#8221;
    <li>Click OK
    <li>In the menu choose Build &gt; Build Touchlib
    <li>When it has compiled Touchlib, Build &gt; Build solution
    <li>The End <img class=wp-smiley alt=:) src="http://www.multigesture.net/wp-includes/images/smilies/icon_smile.gif"> </li>
</ol>
<p><strong>* last update on 13-04-2009 (Latest windows sdk + dx sdk)</strong></p>
</div>
<!-- You can start editing here. -->
<h3 id=comments>19 Responses to &#8220;Touchlib compiling instructions (Windows)&#8221;</h3>
<ol class=commentlist>
    <li class=alt id=comment-375><cite><a class=url href="http://mymultitouch.wordpress.com/" rel="external nofollow" jQuery1242031359870="19"><u><font color=#0000ff>rbedi100</font></u></a></cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-375"><u><font color=#800080>August 31st, 2008 at 3:06 am</font></u></a> </small>
    <p>Hi,<br>Thanks for the great instructions on compiling touchlib, but one question-do I need Visual Studio 05, or will Visual C++ Express, Dev C++, or another compiler work as well? Thx,<br>rbedi100</p>
    <li class="" id=comment-386><cite>sasha237</cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-386"><u><font color=#800080>September 7th, 2008 at 7:22 pm</font></u></a> </small>
    <p>Also it works with Visual Studio 2008. Thanks.</p>
    <li class=alt id=comment-389><cite>mr b</cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-389"><u><font color=#800080>September 13th, 2008 at 6:10 pm</font></u></a> </small>
    <p>hi just wandering is the touchlib software free, and does it means you can use a camera too to control it.</p>
    <li class="" id=comment-390><cite><a class=url href="http://www.multigesture.net/" rel="external nofollow"><u><font color=#0000ff>Laurence Muller</font></u></a></cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-390"><u><font color=#800080>September 13th, 2008 at 11:42 pm</font></u></a> </small>
    <p>@rbedi100:<br>I&#8217;m not sure if it will work on Visual Studio Express or other &#8216;free&#8217; IDE&#8217;s.</p>
    <p>@mr b:<br>The software is free and released under GPL2. You can control the camera parameters if needed.</p>
    <li class=alt id=comment-497><cite>Richard Z</cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-497"><u><font color=#800080>October 25th, 2008 at 11:07 am</font></u></a> </small>
    <p>Hi, i have done as this tutorial, but when i compile the touchlib ,there are lots of errors in &#8220;C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\intsafe.h(1278) : error C2061 ..&#8221; .<br>and when i compile &#8220;configapp&#8221;,it&#8217;s succes!<br>is my intsafe.h file have sth wrong?<br>thank you!</p>
    <li class="" id=comment-835><cite><a class=url href="http://www.multigesture.net/" rel="external nofollow"><u><font color=#0000ff>Laurence Muller</font></u></a></cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-835"><u><font color=#800080>October 31st, 2008 at 11:42 am</font></u></a> </small>
    <p>@Richard Z:<br>Strange error, are you using visual studio 2005 (or express?)?</p>
    <p>I guess you&#8217;ve set the include directories properly?<br>C:\Program Files\Microsoft SDKs\Windows\v6.1\Samples\Multimedia\DirectShow\BaseClasses</p>
    <p>and</p>
    <p>C:\Program Files\Microsoft SDKs\Windows\v6.1\Include</p>
    <p>with this library directory:</p>
    <p>C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib</p>
    <li class=alt id=comment-1296><cite>zousong</cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-1296"><u><font color=#800080>December 30th, 2008 at 11:59 am</font></u></a> </small>
    <p>Hi, i have done as this tutorial, but when i compile the touchlib .compling can pass but i have a link problem:<br>and i use visual studio 2005 express<br>1&gt;DSVLCaptureFilter.obj : error LNK2019: unresolved external symbol __imp__CoInitialize@4 referenced in function &#8220;public: __thiscall DSVLCaptureFilter::DSVLCaptureFilter(char *)&#8221; (??0DSVLCaptureFilter@@QAE@PAD@Z)</p>
    <li class="" id=comment-1381><cite><a class=url href="http://www.multigesture.net/" rel="external nofollow"><u><font color=#0000ff>Laurence Muller</font></u></a></cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-1381"><u><font color=#800080>January 12th, 2009 at 4:27 pm</font></u></a> </small>
    <p>@zousong:<br>It seems like it can not find the DSVL.lib file, check your path settings in the environmental variables:</p>
    <p>It should be this:<br>name: &#8220;DSVL_HOME&#8221;<br>value: &#8220;C:\_libraries\dsvl-0.0.8c&#8221;</p>
    <li class=alt id=comment-2471><cite>Ghanshyam</cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-2471"><u><font color=#800080>March 14th, 2009 at 8:57 am</font></u></a> </small>
    <p>I m not getting the directry as<br>1.C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include<br>2.C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Samples\Multimedia\DirectShow\BaseClasses</p>
    <p>HOw to add these directries&#8230;plz suggest me.thanks</p>
    <li class="" id=comment-2479><cite>ghanshyam</cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-2479"><u><font color=#800080>March 14th, 2009 at 4:31 pm</font></u></a> </small>
    <p>dear Harry van der Veen<br>i want to install touch lib on window xp.<br>i used the Touchlib compiling instructions Multigesture_net.htm.<br>but afterall we r getting the same error as </p>
    <p>Error 23 error C2065: &#8216;m_pSchedule&#8217; : undeclared identifier c:\program files\microsoft sdks\windows\v6.1\samples\multimedia\directshow\baseclasses\refclock.h 139 </p>
    <p>Error 79 error C2327: &#8216;CBaseReferenceClock::LPCTSTR&#8217; : is not a type name, static, or enumerator c:\program files\microsoft sdks\windows\v6.1\samples\multimedia\directshow\baseclasses\sysclock.h 25 </p>
    <p>plz suggest me as poss as.<br>thanking u</p>
    <li class=alt id=comment-2693><cite>Aung Sithu</cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-2693"><u><font color=#800080>March 26th, 2009 at 5:11 am</font></u></a> </small>
    <p>@ghanshyam</p>
    <p>You need to have the baseclasses directory (samples/multimedia/directshow) <strong>before</strong> the sdk include directory.</p>
    <li class="" id=comment-2695><cite>Aung Sithu</cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-2695"><u><font color=#800080>March 26th, 2009 at 5:18 am</font></u></a> </small>
    <p><em>Ghanshyam Says:<br>March 14th, 2009 at 8:57 am</p>
    <p>I m not getting the directry as<br>1.C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include<br>2.C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Samples\Multimedia\DirectShow\BaseClasses </em></p>
    <p><strong><br>Mine look like this:<br>C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\Multimedia\DirectShow\BaseClasses<br>and<br>C:\Program Files\Microsoft SDKs\Windows\v6.0\Include<br></strong></p>
    <li class=alt id=comment-2849><cite>Tan</cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-2849"><u><font color=#800080>April 10th, 2009 at 8:17 am</font></u></a> </small>
    <p>Thanx for the great instruction&#8230;</p>
    <p>I followed your steps but am getting the errors below. Please advice.</p>
    <p>Compiling&#8230;<br>cl : Command line warning D9035 : option &#8216;Wp64&#8242; has been deprecated and will be removed in a future release<br>DSVLCaptureFilter.cpp<br>c:\documents and settings\g\desktop\new folder\multitouch\google\touchlib-src-win32-20071106\touchlib\include\dsvlcapturefilter.h(9) : fatal error C1083: Cannot open include file: &#8217;streams.h&#8217;: No such file or directory<br>FilterFactory.cpp<br>c:\documents and settings\g\desktop\new folder\multitouch\google\touchlib-src-win32-20071106\touchlib\include\videowrapperfilter.h(8) : fatal error C1083: Cannot open include file: &#8217;streams.h&#8217;: No such file or directory<br>VideoWrapperFilter.cpp<br>c:\documents and settings\g\desktop\new folder\multitouch\google\touchlib-src-win32-20071106\touchlib\include\videowrapperfilter.h(8) : fatal error C1083: Cannot open include file: &#8217;streams.h&#8217;: No such file or directory<br>Generating Code&#8230;</p>
    <li class="" id=comment-2876><cite>Yenni</cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-2876"><u><font color=#800080>April 13th, 2009 at 5:41 am</font></u></a> </small>
    <p>To Tan :</p>
    <p>Just include iostream instead</p>
    <p>To Laurence Muller :<br>Thank you for the instructions</p>
    <p>To Anyone please : </p>
    <p>Does anyone see an error in the code below? i keep getting an error at &#8216;_AUX_RGBImageRec *Image;&#8217; . The code below is from textures.h. And the error am getting is : error C2143: syntax error : missing &#8216;;&#8217; before &#8216;*&#8217;. Am sure its sumtin stupid, i just dont see it tho.</p>
    <p>#include </p>
    <p>class COGLTexture<br>{<br>public:<br>COGLTexture();<br>~COGLTexture();<br>#ifdef WIN32<br>_AUX_RGBImageRec *Image;<br>#endif<br>unsigned int GetID();<br>void LoadFromFile(char *filename);<br>void SetActive();<br>int GetWidth();<br>int GetHeight();<br>private:<br>int Width, Height;<br>unsigned int ID;<br>bool bInitialized;<br>};</p>
    <li class=alt id=comment-2879><cite>LucasM</cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-2879"><u><font color=#800080>April 13th, 2009 at 11:53 am</font></u></a> </small>
    <p>It seems that the most recent windows SDK (v6.1) no longer supports glaux.h which is required by the demo projects in touchlib. Looking a bit around on internet it seems that it should no longer be used. To solve the problem I copied glaux.h and glaux.lib from the previous SDK (for Windows Server 2003 R2).</p>
    <li class="" id=comment-2882><cite>Yenni</cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-2882"><u><font color=#800080>April 13th, 2009 at 6:08 pm</font></u></a> </small>
    <p>correction , the first line is: #include</p>
    <li class=alt id=comment-2883><cite>Yenni</cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-2883"><u><font color=#800080>April 13th, 2009 at 6:09 pm</font></u></a> </small>
    <p>GL/gl.h</p>
    <li class="" id=comment-2918><cite>LBDL</cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-2918"><u><font color=#800080>April 17th, 2009 at 8:02 pm</font></u></a> </small>
    <p>Hi I am getting a lot of compile errors with refclock.h<br>I am using VS2008 btw but that should make no odds&#8230;<br>any clues<br>Error 44 error C2061: syntax error : identifier &#8216;CAMSchedule&#8217; c:\program files\microsoft sdks\windows\v6.1\samples\multimedia\directshow\baseclasses\refclock.h 80 touchlib<br>for example<br>I am trying to build touchlib</p>
    <li class=alt id=comment-2944><cite>xlmeng</cite> Says: <br><small class=commentmetadata><a title="" href="http://www.multigesture.net/articles/touchlib-compiling-instructions/#comment-2944"><u><font color=#800080>April 21st, 2009 at 5:22 am</font></u></a> </small>
    <p>I had the same problem as LBDL&#8217;s. Found the solution here:<br><a href="http://social.msdn.microsoft.com/forums/en-US/windowsdirectshowdevelopment/thread/5da8f0b8-d2a9-4caf-81e1-7f5788fa1c00/" rel=nofollow jQuery1242031359870="20"><u><font color=#0000ff>http://social.msdn.microsoft.com/forums/en-US/windowsdirectshowdevelopment/thread/5da8f0b8-d2a9-4caf-81e1-7f5788fa1c00/</font></u></a><br>The solution work for xp and vista</p>
    </li>
</ol>
<img src ="http://www.cppblog.com/zmj/aggbug/82586.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-05-11 16:46 <a href="http://www.cppblog.com/zmj/archive/2009/05/11/82586.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MultiTouch资料收集</title><link>http://www.cppblog.com/zmj/archive/2009/05/07/82168.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Thu, 07 May 2009 09:37:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/05/07/82168.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/82168.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/05/07/82168.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/82168.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/82168.html</trackback:ping><description><![CDATA[LINK:http://www.cnblogs.com/RunOnTheWay/<br><br>0.不会飞的鱼 - <a href="http://isaaq.javaeye.com/blog/296853"><u><font color=#108ac6>实战Multitouch(1)</font></u></a><br><a href="http://isaaq.javaeye.com/blog/296853">http://isaaq.javaeye.com/blog/296853</a><br>
<p>1. （介绍后加）</p>
<p><a href="http://link.brightcove.com/services/player/bcpid1875256036?bctid=20915830001"><font color=#0000cc>http://link.brightcove.com/services/player/bcpid1875256036?bctid=20915830001</font></a></p>
<p>2. 超大型多点触摸墙，完美展示多点触摸的魅力</p>
<p><a href="http://www.mt2a.com/viewthread.php?tid=70&amp;extra=page%3D1"><font color=#0000cc>http://www.mt2a.com/viewthread.php?tid=70&amp;extra=page%3D1</font></a></p>
<p>3. mt2a论坛</p>
<p><a href="http://www.mt2a.com/"><font color=#0000cc>http://www.mt2a.com/</font></a></p>
<p>4. 一个OpenCV 机器视觉爱好者的blog</p>
<p><a href="http://blog.csdn.net/hunnish"><font color=#0000cc>http://blog.csdn.net/hunnish</font></a></p>
<p>5. TouchLib 官方网站</p>
<p><a href="http://nuigroup.com/touchlib/"><font color=#0000cc>http://nuigroup.com/touchlib/</font></a></p>
<p>6. DameTouch的视频空间（优酷）</p>
<p><a class="pLink fPLink" id=spaceUrl href="http://u.youku.com/DamoTouch" target=_blank><font color=#0000cc>http://u.youku.com/DamoTouch</font></a>&nbsp;</p>
<p>7. 《世界构建者》（World Builder）</p>
<p>&lt;embed src="http://player.youku.com/player.php/sid/XNzY0NjIyNDQ=/v.swf" quality="high" width="480" height="400" align="center" allowScriptAccess="sameDomain" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&nbsp;</p>
<p>8. TouchLess 微软的无需接触的触摸技术</p>
<p><a href="http://vimeo.com/1893407?pg=embed&amp;sec=1893407"><font color=#0000cc>http://vimeo.com/1893407?pg=embed&amp;sec=1893407</font></a></p>
<p><a href="http://www.codeplex.com/touchless"><font color=#0000cc>http://www.codeplex.com/touchless</font></a></p>
<p>9. 一种实现原理</p>
<p><img height=248 alt="" src="http://images.cnblogs.com/cnblogs_com/runontheway/966aca07a169dfde7b894783.jpg" width=468 border=0></p>
<img src ="http://www.cppblog.com/zmj/aggbug/82168.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-05-07 17:37 <a href="http://www.cppblog.com/zmj/archive/2009/05/07/82168.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sparsh-ui </title><link>http://www.cppblog.com/zmj/archive/2009/05/07/82167.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Thu, 07 May 2009 09:11:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/05/07/82167.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/82167.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/05/07/82167.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/82167.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/82167.html</trackback:ping><description><![CDATA[LINK:http://code.google.com/p/sparsh-ui/<br>
<table id=mt cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <th onclick="if (!cancelBubble) _go('/p/sparsh-ui/');">
            <div class="tab active">
            <div class=box-inner><a onclick=cancelBubble=true; href="http://code.google.com/p/sparsh-ui/"><font color=#000000>Project&nbsp;Home</font></a> </div>
            </div>
            </th>
            <td>&nbsp;&nbsp;</td>
            <th onclick="if (!cancelBubble) _go('/p/sparsh-ui/downloads/list');">
            <div class="tab inactive">
            <div class=round4></div>
            <div class=round2></div>
            <div class=round1></div>
            <div class=box-inner><a onclick=cancelBubble=true; href="http://code.google.com/p/sparsh-ui/downloads/list"><font color=#000000>Downloads</font></a> </div>
            </div>
            </th>
            <td>&nbsp;&nbsp;</td>
            <th onclick="if (!cancelBubble) _go('/p/sparsh-ui/w/list');">
            <div class="tab inactive">
            <div class=round4></div>
            <div class=round2></div>
            <div class=round1></div>
            <div class=box-inner><a onclick=cancelBubble=true; href="http://code.google.com/p/sparsh-ui/w/list"><font color=#000000>Wiki</font></a> </div>
            </div>
            </th>
            <td>&nbsp;&nbsp;</td>
            <th onclick="if (!cancelBubble) _go('/p/sparsh-ui/issues/list');">
            <div class="tab inactive">
            <div class=round4></div>
            <div class=round2></div>
            <div class=round1></div>
            <div class=box-inner><a onclick=cancelBubble=true; href="http://code.google.com/p/sparsh-ui/issues/list"><font color=#000000>Issues</font></a> </div>
            </div>
            </th>
            <td>&nbsp;&nbsp;</td>
            <th onclick="if (!cancelBubble) _go('/p/sparsh-ui/source/checkout');">
            <div class="tab inactive">
            <div class=round4></div>
            <div class=round2></div>
            <div class=round1></div>
            <div class=box-inner><a onclick=cancelBubble=true; href="http://code.google.com/p/sparsh-ui/source/checkout"><font color=#000000>Source</font></a> </div>
            </div>
            </th>
            <td>&nbsp;&nbsp;</td>
            <td width="100%">&nbsp;</td>
        </tr>
    </tbody>
</table>
<table class=st cellSpacing=0 cellPadding=0 width="100%" align=center border=0>
    <tbody>
        <tr>
            <td>
            <div class=st1>
            <div class=isf><span class=inst1><a href="http://code.google.com/p/sparsh-ui/"><strong><font color=#0000cc>Summary</font></strong></a> </span>| <span class=inst2><a href="http://code.google.com/p/sparsh-ui/updates/list"><u><font color=#0000cc>Updates</font></u></a> </span></div>
            </div>
            </td>
            <td class=bevel-right vAlign=top align=right height=4>
            <div class=round4></div>
            <div class=round2></div>
            <div class=round1></div>
            </td>
        </tr>
    </tbody>
</table>
<script type=text/javascript>
var cancelBubble = false;
function _go(url) { document.location = url; }
</script>
<div id=maincol><!-- IE -->
<style type=text/css>
#downloadbox {
padding: 6px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
#downloadbox a {
margin: 6px 0 0 3em;
display: block;
padding-left: 18px;
background: url(http://www.gstatic.com/codesite/ph/images/dl_arrow.gif) no-repeat bottom left;
}
#owners a, #members a { white-space: nowrap; }
</style>
<div style="FLOAT: right; MARGIN: 0px 0px 1em 2em; WIDTH: 25em">
<div class=pmeta_bubble_bg>
<div class=round4></div>
<div class=round2></div>
<div class=round1></div>
<div class=box-inner>
<table class=pmeta cellPadding=5>
    <tbody>
        <tr>
            <th><span style="WHITE-SPACE: nowrap">Code license:</span></th>
            <td><a href="http://www.gnu.org/licenses/lgpl.html" rel=nofollow><u><font color=#0000cc>GNU Lesser General Public License</font></u></a> </td>
        </tr>
        <tr>
            <th>Labels:</th>
            <td id=project_labels><a href="http://code.google.com/hosting/search?q=label:multitouch"><u><font color=#0000cc>multitouch</font></u></a>, <a href="http://code.google.com/hosting/search?q=label:touch"><u><font color=#0000cc>touch</font></u></a>, <a href="http://code.google.com/hosting/search?q=label:gesture"><u><font color=#0000cc>gesture</font></u></a> </td>
        </tr>
    </tbody>
</table>
</div>
<div class=round1></div>
<div class=round2></div>
<div class=round4></div>
</div>
<div style="TABLE-LAYOUT: fixed; BACKGROUND: #ddf8cc; MARGIN-BOTTOM: 5px">
<div class=round4></div>
<div class=round2></div>
<div class=round1></div>
<div class=box-inner>
<div id=downloadbox><a style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BACKGROUND: none transparent scroll repeat 0% 0%; FLOAT: right; PADDING-BOTTOM: 0px; PADDING-TOP: 0px" href="http://code.google.com/p/sparsh-ui/downloads/list">Show all</a> <strong>Featured downloads:</strong><br><a href="http://sparsh-ui.googlecode.com/files/CppGestureServer1.0.0b.zip">CppGestureServer1.0.0b.zip</a> <a href="http://sparsh-ui.googlecode.com/files/FingerPaint.jar">FingerPaint.jar</a> <a href="http://sparsh-ui.googlecode.com/files/JavaGestureServer1.0.0b.jar">JavaGestureServer1.0.0b.jar</a> <a href="http://sparsh-ui.googlecode.com/files/JavaGestureServer1.0.0b.zip">JavaGestureServer1.0.0b.zip</a> <a href="http://sparsh-ui.googlecode.com/files/SparshCPPWindowsInstaller.zip">SparshCPPWindowsInstaller.zip</a> <a href="http://sparsh-ui.googlecode.com/files/Sparsh_Windows_Complete_Set.zip">Sparsh_Windows_Complete_Set.zip</a> <a href="http://sparsh-ui.googlecode.com/files/TouchLibSparshAdapterSetup.zip">TouchLibSparshAdapterSetup.zip</a> <a href="http://sparsh-ui.googlecode.com/files/WindowsTouchSimulator.zip">WindowsTouchSimulator.zip</a> </div>
</div>
<div class=round1></div>
<div class=round2></div>
<div class=round4></div>
</div>
<div style="TABLE-LAYOUT: fixed; BACKGROUND: #ddf8cc; MARGIN-BOTTOM: 5px">
<div class=round4></div>
<div class=round2></div>
<div class=round1></div>
<div class=box-inner>
<div id=wikibox style="PADDING-RIGHT: 6px; PADDING-LEFT: 6px; PADDING-BOTTOM: 6px; OVERFLOW: hidden; PADDING-TOP: 6px; WHITE-SPACE: nowrap; TEXT-OVERFLOW: ellipsis"><a style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BACKGROUND: none transparent scroll repeat 0% 0%; FLOAT: right; PADDING-BOTTOM: 0px; PADDING-TOP: 0px" href="http://code.google.com/p/sparsh-ui/w/list">Show all</a> <strong>Featured wiki pages:</strong><br><a style="DISPLAY: block; MARGIN: 6px 0px 0px 3em" href="http://code.google.com/p/sparsh-ui/wiki/GettingStarted">GettingStarted</a> <a style="DISPLAY: block; MARGIN: 6px 0px 0px 3em" href="http://code.google.com/p/sparsh-ui/wiki/SparshUI_Developer_Guide">SparshUI_Developer_Guide</a> <a style="DISPLAY: block; MARGIN: 6px 0px 0px 3em" href="http://code.google.com/p/sparsh-ui/wiki/SparshUI_Device_Adapter">SparshUI_Device_Adapter</a> </div>
</div>
<div class=round1></div>
<div class=round2></div>
<div class=round4></div>
</div>
<div class=pmeta_bubble_bg>
<div class=round4></div>
<div class=round2></div>
<div class=round1></div>
<div class=box-inner>
<table class=pmeta cellPadding=5>
    <tbody>
        <tr>
            <th>Links:</th>
            <td>
            <ul id=url_links>
                <li><a href="http://www.vrac.iastate.edu/" rel=nofollow><u><font color=#0000cc>Iowa State University VRAC</font></u></a>
                <li><a href="http://www.hci.iastate.edu/" rel=nofollow><u><font color=#0000cc>Iowa State University Human Computer Interaction Graduate Program</font></u></a>
                <li><a href="http://www.vrac.iastate.edu/uav/touchtable" rel=nofollow><u><font color=#0000cc>VRAC TouchTable Videos</font></u></a> </li>
            </ul>
            </td>
        </tr>
        <tr>
            <th>Feeds:</th>
            <td>
            <ul>
                <li><a href="http://code.google.com/p/sparsh-ui/feeds"><u><font color=#0000cc>Project feeds</font></u></a> </li>
            </ul>
            </td>
        </tr>
        <tr>
            <th>Groups:</th>
            <td>
            <ul id=group_links>
                <li><a href="http://groups.google.com/group/sparsh-ui" rel=nofollow><u><font color=#0000cc>Sparsh-UI Developers' Group</font></u></a> </li>
            </ul>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div class=round1></div>
<div class=round2></div>
<div class=round4></div>
</div>
<div class=pmeta_bubble_bg>
<div class=round4></div>
<div class=round2></div>
<div class=round1></div>
<div class=box-inner><a style="PADDING-RIGHT: 6px; PADDING-LEFT: 6px; FLOAT: right; PADDING-BOTTOM: 6px; PADDING-TOP: 6px" href="http://code.google.com/p/support/wiki/HowToJoinAProject">How to join?</a>
<table class=pmeta style="PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; PADDING-TOP: 3px" cellPadding=3>
    <tbody>
        <tr>
            <th colSpan=2>Project owners:</th>
        </tr>
        <tr>
            <td style="WIDTH: 4em">&nbsp;</td>
            <td id=owners><a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/stephen.b.gilbert/"><u><font color=#0000cc>stephen.b.gilbert</font></u></a>, <a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/mail.rsp/"><u><font color=#0000cc>mail.rsp</font></u></a>, <a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/jroltgen/"><u><font color=#0000cc>jroltgen</font></u></a>, <a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/antross/"><u><font color=#0000cc>antross</font></u></a>, <a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/Peter.WM.Wong/"><u><font color=#0000cc>Peter.WM.Wong</font></u></a>, <a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/aronbierbaum/"><u><font color=#0000cc>aronbierbaum</font></u></a>, <a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/abierbaum/"><u><font color=#0000cc>abierbaum</font></u></a>, <a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/rob.g.evans/"><u><font color=#0000cc>rob.g.evans</font></u></a>, <a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/Britlyn.Designs/"><u><font color=#0000cc>Britlyn.Designs</font></u></a>, <a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/snandakumar/"><u><font color=#0000cc>snandakumar</font></u></a>, <a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/ankitpatel5/"><u><font color=#0000cc>ankitpatel5</font></u></a>, <a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/a.polkinghorn/"><u><font color=#0000cc>a.polkinghorn</font></u></a>, <a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/lucas.bonansea/"><u><font color=#0000cc>lucas.bonansea</font></u></a>, <a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/mikeoren/"><u><font color=#0000cc>mikeoren</font></u></a> </td>
        </tr>
        <tr>
            <th style="PADDING-TOP: 6px" colSpan=2>Project members:</th>
        </tr>
        <tr>
            <td></td>
            <td id=members><a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/augomat/"><u><font color=#0000cc>augomat</font></u></a>, <a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/bith42/"><u><font color=#0000cc>bith42</font></u></a>, <a style="WHITE-SPACE: nowrap" href="http://code.google.com/u/TonyMilosch/"><u><font color=#0000cc>TonyMilosch</font></u></a> </td>
        </tr>
    </tbody>
</table>
</div>
<div class=round1></div>
<div class=round2></div>
<div class=round4></div>
</div>
</div>
<div id=wikicontent style="PADDING-RIGHT: 3em; PADDING-LEFT: 0px; PADDING-BOTTOM: 1.2em; PADDING-TOP: 0px">
<p><img src="http://sparsh-ui.googlecode.com/svn/trunk/doc/images/sparsh_logo_small.png"> </p>
<h3><a name=Project_Goal>Project Goal</h3>
<p>Iowa State University's Virtual Reality Applications Center (VRAC) is developing a multitouch API for enabling users to create multi-touch applications easily on a variety of hardware platforms. The API supports custom hardware drivers and is platform independent. </p>
<h3><a name=Project_Components>Project Components</h3>
<p><strong>Gesture Server:</strong> The Sparsh-UI Gesture Server is the main piece of the application. It handles gesture processing and passes touchpoints and/or gesture information to the client application. The Gesture Server supports basic gestures such as drag, scale, and rotate, and is extensible to support an infinite number of user-written custom gestures. </p>
<p><strong>Input Device Driver:</strong> A device driver is needed for a device to communicate with the Gesture Server. The Touchtable team at VRAC has developed device drivers for an optical FTIR system, an infrared bezel, as well as several other devices. The driver should be capable of passing touchpoint iformation to the Gesture Server. </p>
<p><strong>Gesture Adapter:</strong> A client adapter is needed for each GUI framework the Gesture Server intends to communicate with. The Touchtable team at VRAC is currently working on a Java Swing adapter, with plans to implement other frameworks in the near future. </p>
<p><img src="http://sparsh-ui.googlecode.com/svn/trunk/doc/images/Sparsh_poster_2.jpg"> </p>
<p><img src="http://sparsh-ui.googlecode.com/svn/trunk/doc/images/Sparsh_poster_3.jpg"> </p>
<h3><a name=Contact_Information>Contact Information</h3>
<p>For information about using Sparsh-UI, join our sparsh-ui developer group from the link on the right-hand side of this page, or contact Stephen Gilbert at (gilbert at iastate dot edu). </p>
</div>
</a></div>
<img src ="http://www.cppblog.com/zmj/aggbug/82167.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-05-07 17:11 <a href="http://www.cppblog.com/zmj/archive/2009/05/07/82167.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Touchlib Homepage</title><link>http://www.cppblog.com/zmj/archive/2009/05/07/82165.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Thu, 07 May 2009 09:00:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/05/07/82165.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/82165.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/05/07/82165.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/82165.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/82165.html</trackback:ping><description><![CDATA[LINK:http://www.whitenoiseaudio.com/touchlib/<br>
<p align=center><img height=240 alt="touch img" src="http://www.whitenoiseaudio.com/touchlib/touchimg.jpg" width=320></p>
<p class=style1><em>What is Touchlib? </em></p>
<p>Touchlib is our library for creating multi-touch interaction surfaces. It handles tracking blobs of infrared light for you and sends your programs multitouch events, such as 'finger down', 'finger moved', and 'finger released'. It includes a configuration app and a few demos to get you started. It interaces with most major types of webcams and video capture devices. It currently works only under windows but efforts are being made to port it to other platforms. </p>
<p class=style1><em>Who Should Use Touchlib? </em></p>
<p>Touchlib only comes with simple demo applications. If you want to use touchlib you must be prepared to make your own apps. There are a few ways to do this. You can build applications in C++ and take advantage of touchlib's simple programming interface. Touchlib does not provide you with any graphical or front end abilities - it simply passes you touch events. The graphics are up to you. If you like, take a look at the example apps which use OpenGL GLUT. </p>
<p>If you don't want to have to compile touchlib, <a href="http://www.whitenoiseaudio.com/touchlib/touchlibBins.zip"><u><font color=#0000ff>binaries are available</font></u></a>. </p>
<p>As of the current version, touchlib now can broadcast events in the <a href="http://www.tuio.org/"><u><font color=#0000ff>TUIO</font></u></a> protocol (which uses OSC). This makes touchlib compatible with several other applications that support this protocol, such as <a href="http://vvvv.org/"><u><font color=#0000ff>vvvv</font></u></a>, <a href="http://www.processing.org/"><u><font color=#0000ff>Processing</font></u></a>, <a href="http://puredata.info/"><u><font color=#0000ff>PureData</font></u></a>, etc.. This also makes it possible to use touchlib for blob detection / tracking and something like vvvv or Processing to write appliactions. Of course the other option is to do all your blob detection and processing in vvvv or processing. It's up to you. Supporting the TUIO protocol also enables a distributed architecture where one machine can be devoted to detection and tracking and another machine can handle the application. </p>
<p>If you don't like touchlib and want to program your own system, the latest version of OpenCV (1.0) now has support for blob detection and tracking. This might be a good starting point. </p>
<p class=style1><em>My Mindmap </em></p>
<p>My mindmap for the touchscreen is available <a href="http://touchlib.googlecode.com/svn/multitouch/TouchScreen.mm"><u><font color=#0000ff>here</font></u></a>. This contains info on what parts you'll need for the construction of the screen, where to find them and some very basic instructions for how to build a screen. It also includes some more links. I hope it's useful for some of the people reading this who are interested in doing their own screens. You'll need <a href="http://freemind.sourceforge.net/wiki/index.php/Main_Page"><u><font color=#0000ff>Freemind</font></u></a> (which is coincidentally, free), in order to view it. I'm a big fan of freemind for planning out projects and getting ideas down. It's hierarchical nature allows you to organize and hide parts you are not interested in. It can also link to images, other mindmaps and web pages.</p>
<p class=style1><em>FAQ</em></p>
<p><a href="http://www.whitenoiseaudio.com/touchlib/faq.html"><u><font color=#0000ff>Frequently asked questions about the construction of the screen can be found here. </font></u></a></p>
<p><em>Where to get the source to Touchlib, our multitouch table library: </em></p>
<p>All our source code is available on our Google Code site at <a href="http://code.google.com/p/touchlib/"><u><font color=#800080>http://code.google.com/p/touchlib/</font></u></a> . You can acces the repsitory using Subversion. If you are using windows, get TortoiseSVN. Use Tortoise to access the repository and download all the files (much easier than going thru the web interface). If you are interested in porting touchlib to linux or the mac, please <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#97;&#100;&#109;&#105;&#110;&#32;&#97;&#116;&#32;&#119;&#104;&#105;&#116;&#101;&#110;&#111;&#105;&#115;&#101;&#97;&#117;&#100;&#105;&#111;&#32;&#99;&#111;&#109;"><u><font color=#0000ff>email me</font></u></a>. The system was written in such a way that it should be easy to port and does not depend heavily on any windows specific api's. </p>
<p><a href="http://www.whitenoiseaudio.com/touchlib/touchlibBins.zip"><u><font color=#0000ff>Binaries are available here</font></u></a>. </p>
<p>Touchlib is written in C++ (the BlobTracking / Analysis is all written by yours truly) and has a Visual Studio 2005 Solution ready to compile. No docs are available right now and it's windows only (though it should be possible to make everything compile under other OS's with a little work). It currently depends on OpenCV, DirectShow (you'll need the Microsoft Platform SDK), VideoWrapper and the DSVideoLib. The source code includes our main library which you can link into your application to start capturing touch events. It has support for most major camera/webcam types. It also includes a basic config app which will need to be run in order to calibrate your camera, and has a couple example apps. Alternately, I've heard other people have used things like <a href="http://vvvv.org/"><u><font color=#0000ff>vvvv</font></u></a>, <a href="http://www.infomus.dist.unige.it/eywindex.html"><u><font color=#0000ff>EyesWeb</font></u></a>, <a href="http://www.processing.org/"><u><font color=#0000ff>processing</font></u></a> and <a href="http://www.cycling74.com/products/maxmsp"><u><font color=#0000ff>Max/MSP</font></u></a> in order to do blob tracking / processing and make applications. You can check out some of the demo apps if you want to see how it works. Pong or the config app should be fairly easy to follow. Setting up a bare minimum multitouch app should only take a dozen lines of code or less. </p>
<p>DL Links for dependencies:</p>
<ul>
    <li><a href="http://sourceforge.net/projects/opencvlibrary/"><u><font color=#0000ff>OpenCV</font></u></a> - I used Beta 5. Hopefully it is compatible with newer versions (RC 1 is available now).
    <li><a href="http://sourceforge.net/projects/dsvideolib/"><u><font color=#0000ff>DSVideoLib</font></u></a>
    <li><a href="http://sourceforge.net/projects/videowrapper"><u><font color=#0000ff>VideoWrapper</font></u></a>
    <li><a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&amp;displaylang=en"><u><font color=#0000ff>Platform SDK</font></u></a>
    <li>Also <a href="http://www.xmission.com/~nate/glut.html"><u><font color=#0000ff>GLUT</font></u></a> was used for most of the applications.
    <li>The DirectX SDK is also required
    <li><a href="http://www.audiomulch.com/~rossb/code/oscpack/"><u><font color=#0000ff>OSCPack</font></u></a> for the OSC application </li>
</ul>
<p>You'll need to configure a few environment variables to get everything compiled. They are:</p>
<ul>
    <li>DSVL_HOME - dsvideolib root directory
    <li>VIDEOWRAPPER_HOME - root directory of the video wrapper library
    <li>OPENCV_HOME - root directory of OpenCV
    <li>OSCPACK_HOME - root directory of oscpack </li>
</ul>
<p class=style1><em>The config app</em></p>
<p>In order to calibrate the touchlib library for your camera and projector, you'll need to run the config app. Here's how it works. You'll need to set up your computer so that the main monitor is the video projector so that the app comes up on that screen. Run the config app. Press 'b' at any time to recapture the background. Tweak the sliders until you get the desired results. The last step (rectify) should just have light coming from your finger tips (no background noise, etc). When you are satisfied press 'enter'. This will launch the app in full screen mode and you'll see a grid of points (green pluses). Now you can press 'c' to start calibrating. The current point should turn red. Press on your FTIR screen where the point is. Hopefully a press is detected (you can check by looking in the debug window). Press 'space' to calibrate the next point. You'll continue through until all points are calibrated. Note that the screen may not indicate where you are pressing. When you are all done, you can press 'ESC' to quit. All your changes (slider tweaks and calibration points) are saved to the config.xml file. Now when you run any touchlib app it will be calibrated. Note that any changes to where the projector is pointing or your webcam will require a re-calibration. </p>
<p class=style1><em>Testing</em></p>
<p>Alternate config files are available if you want to test the library using an .AVI for input (instead of the webcam). Replace the config.xml with 5point_avi.xml or 2point_avi.xml. You can edit those files to use a different AVI if you like (you can record a new one using your camera - but you may need to tweak some of the other settings in the config too). </p>
<p class=style1><em>Links</em></p>
<p><span class=style1><font size=4><strong>NEW:</strong> We now have an official community site for building FTIR tables. </font><a href="http://www.nuigroup.com/"><u><font color=#0000ff size=4>Access the site here</font></u></a></span> . The site includes forums, a wiki, news and more. </p>
<p>Other tables and info. </p>
<ul>
    <li><a href="http://www.whitenoiseaudio.com/blog/"><u><font color=#800080>My Blog</font></u></a> - read updates about my progress with the screen
    <li><a href="http://dundee.cs.queensu.ca/wiki/index.php/Building_a_Multi-Touch_Sensitive_Table"><u><font color=#0000ff>A HowTo</font></u></a> for building FTIR screens
    <li><a href="http://tecfa.unige.ch/perso/staf/nova/blog/2005/01/10/space-and-place-a-list-fo-interactive-tables/"><u><font color=#0000ff>Pasta and Vinegar: Interactive tables</font></u></a>
    <li><a href="http://reactivision.sourceforge.net/"><u><font color=#0000ff>Reactivision software</font></u></a>
    <li><a href="http://www.tuio.org/"><u><font color=#0000ff>TUIO protocol</font></u></a>
    <li>Some <a href="http://zima.ch/tangent/?page_id=6"><u><font color=#0000ff>nice info</font></u></a> on the Tangent table.
    <li><a href="http://del.icio.us/tag/multitouch?setcount=100"><u><font color=#0000ff>Links on del.icio.us</font></u></a> tagged with multitouch
    <li><a href="http://www.mortalspaces.com/diytouchpanels/"><u><font color=#0000ff>DIY Multitouch</font></u></a> - A bunch of links and info on various multitouch techniques.
    <li><a href="http://www.k2.t.u-tokyo.ac.jp/members/alvaro/Khronos/"><u><font color=#0000ff>Khronos Projector</font></u></a> - Uses infrared + a stretchy lycra surface and detects the depressions on the surface.
    <li><a href="http://www.media.mit.edu/resenv/classes/MAS965/readings/SmartSkin.pdf"><u><font color=#0000ff>Smartskin</font></u></a> - uses capacitance testing to detect conductive objects, such as skin. Sounds like the best choice for a small form factor. Could fit over or be integrated with an LCD monitor.
    <li><a href="http://hct.ece.ubc.ca/publications/pdf/vogt-chen-hoskinsin-fels-SIGGRAPH2004.pdf#search=%22smartskin%20touch%20pad%22"><u><font color=#0000ff>Malleable touch surface</font></u></a>
    <li><a href="http://haha.nu/amazing/as-rigid-as-possible-shape-manipulation/"><u><font color=#0000ff>Here's one of the demos</font></u></a> featured on Han's multitouch screen, in more detail. Rigid shape manipulation.
    <li><a href="http://www.techeblog.com/index.php/tech-gadget/warcraft-iii-multi-touch-panel"><u><font color=#0000ff>Warcraft 3 multitouch</font></u></a>. Nice. I'd like to be able to get this running on my screen (even if it's only single touch)
    <li><a href="http://www.physorg.com/news9575.html"><u><font color=#0000ff>this interesting item</font></u></a>: the Entertaible
    <li><a href="http://cs.nyu.edu/~jhan/ftirtouch/"><u><font color=#0000ff>Jeff Han's page</font></u></a>. The one that started it all </li>
</ul>
<p class=style1><em>Other</em></p>
<p>IRC: #ftir on irc.freenode.net </p>
<img src ="http://www.cppblog.com/zmj/aggbug/82165.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-05-07 17:00 <a href="http://www.cppblog.com/zmj/archive/2009/05/07/82165.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GDAL API Tutorial</title><link>http://www.cppblog.com/zmj/archive/2009/04/30/81564.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Thu, 30 Apr 2009 06:39:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/04/30/81564.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/81564.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/04/30/81564.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/81564.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/81564.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: http://www.gdal.org/gdal_tutorial.htmlOpening the FileBefore opening a GDAL supported raster datastore it is necessary to register drivers. There is a driver for each supported format. Normally th...&nbsp;&nbsp;<a href='http://www.cppblog.com/zmj/archive/2009/04/30/81564.html'>阅读全文</a><img src ="http://www.cppblog.com/zmj/aggbug/81564.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-04-30 14:39 <a href="http://www.cppblog.com/zmj/archive/2009/04/30/81564.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>BOOLEAN OPERATIONS</title><link>http://www.cppblog.com/zmj/archive/2009/04/03/78801.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Fri, 03 Apr 2009 03:37:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/04/03/78801.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/78801.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/04/03/78801.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/78801.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/78801.html</trackback:ping><description><![CDATA[LINK: <a href="http://www.we-r-here.com/cad/tutorials/level_3/3-11.htm">http://www.we-r-here.com/cad/tutorials/level_3/3-11.htm</a><br><br>First, to explain the funny name : "It was named after George Boole, who first defined an algebraic system of logic in the mid 19th century."
<p align=justify>Working in 3D usually involves the use of solid objects. At times you may need to combine multiple parts into one, or remove sections from a solid. AutoCAD has some commands that make this easy for you. These are the boolean operations as well as some other helpful commands for solids editing.:</p>
<table cellSpacing=0 cellPadding=4 width=482 align=center border=1>
    <tbody>
        <tr bgColor=#ffffcc>
            <td vAlign=top width=74>
            <p align=center><strong>COMMAND </strong></p>
            </td>
            <td vAlign=top width=98>
            <p align=center><strong>INPUT</strong></p>
            </td>
            <td vAlign=top width=50>
            <p align=center><strong>ICON </strong></p>
            </td>
            <td vAlign=top width=218>
            <p align=center><strong>DESCRIPTION </strong></p>
            </td>
        </tr>
        <tr>
            <td vAlign=center align=middle width=74>
            <p>UNION<br>(Boolean)</p>
            </td>
            <td class=style8 vAlign=center align=middle width=98>UNI </td>
            <td vAlign=center width=50>
            <p align=center><font color=#000066 size=2><a href="http://www.we-r-here.com/cad/tutorials/level_3/3-11.htm#union"><img height=40 alt="Box Icon" src="http://www.we-r-here.com/cad/tutorials/level_3/images/unionicon.gif" width=41 border=0></a></font> </p>
            </td>
            <td vAlign=top width=218>
            <p align=justify>Joins two or more solids into creating one based on the total geometry of all. </p>
            </td>
        </tr>
        <tr>
            <td vAlign=center align=middle width=74>
            <p>SUBTRACT<br>(Boolean)</p>
            </td>
            <td class=style8 vAlign=center align=middle width=98>SU</td>
            <td vAlign=center width=50>
            <p align=center><font color=#000066 size=2><a href="http://www.we-r-here.com/cad/tutorials/level_3/3-11.htm#sub"><img height=40 alt="Sphere Icon" src="http://www.we-r-here.com/cad/tutorials/level_3/images/subtracticon.gif" width=41 border=0></a></font> </p>
            </td>
            <td vAlign=top width=218>
            <p align=justify>Subtracts one or more solids from another creating a solid based on the remaining geometry. </p>
            </td>
        </tr>
        <tr>
            <td vAlign=center align=middle width=74>
            <p>INTERSECT<br>(Boolean)</p>
            </td>
            <td class=style8 vAlign=center align=middle width=98>IN </td>
            <td vAlign=center width=50>
            <p align=center><font color=#000066 size=2><a href="http://www.we-r-here.com/cad/tutorials/level_3/3-11.htm#int"><img height=40 alt="Cylinder Icon" src="http://www.we-r-here.com/cad/tutorials/level_3/images/intersecticon.gif" width=41 border=0></a></font> </p>
            </td>
            <td vAlign=top width=218>
            <p align=justify>Creates a single solid from one more solids based on the intersected geometry. </p>
            </td>
        </tr>
        <tr>
            <td vAlign=center align=middle width=74>
            <p>EXTRUDE FACE </p>
            </td>
            <td class=style8 vAlign=center align=middle width=98>SOLID EDIT </td>
            <td vAlign=center width=50>
            <p><font color=#000066 size=2><a href="http://www.we-r-here.com/cad/tutorials/level_3/3-11.htm#extface"><img height=35 alt="Cone Icon" src="http://www.we-r-here.com/cad/tutorials/level_3/images/extrude_face_icon.gif" width=35 border=0></a></font> </p>
            </td>
            <td vAlign=top width=218>
            <p align=justify>Allows you to increase the size of a solid by extruding out one of its faces. </p>
            </td>
        </tr>
        <tr>
            <td vAlign=center align=middle width=74>
            <p>SLICE</p>
            </td>
            <td class=style8 vAlign=center align=middle width=98>SLICE</td>
            <td vAlign=center width=50><a href="http://www.we-r-here.com/cad/tutorials/level_3/3-11.htm#slice"><img height=38 alt="Slice Icon" src="http://www.we-r-here.com/cad/tutorials/level_3/images/slice_icon.gif" width=39 border=0></a></td>
            <td vAlign=top width=218>
            <p>Slices a solid along a cutting plane. </p>
            </td>
        </tr>
        <tr>
            <td vAlign=center align=middle>
            <p>3D ALIGN </p>
            </td>
            <td class=style8 vAlign=center align=middle>3DALIGN</td>
            <td vAlign=center><a href="http://www.we-r-here.com/cad/tutorials/level_3/3-11.htm#3da"><img height=40 alt="3D Align Icon" src="http://www.we-r-here.com/cad/tutorials/level_3/images/3dalignicon.gif" width=41 border=0></a></td>
            <td vAlign=top>
            <p>Aligns 2 3D Objects in 3D space. </p>
            </td>
        </tr>
    </tbody>
</table>
<p align=justify>The boolean commands work only on solids or regions. They are easy to work with <em>IF</em> you follow the command line prompts. Here is an example of each.</p>
<p align=justify>Start these exercises by drawing a box 5W X 7L X 3H and a cylinder 3 units in diameter so that the center of the circle is on the midpoint of the block.</p>
<p align=left><a name=union></a><strong>UNION</strong></p>
<p align=justify>Below left, there is a box and a cylinder. These are two separate objects. If you want to combine them into one object, you have to use the union command.</p>
<table width=500 align=center border=0>
    <tbody>
        <tr>
            <td vAlign=center align=middle width=245><font face="Arial, Helvetica, sans-serif" color=#000066><img height=184 alt="Before Union" src="http://www.we-r-here.com/cad/tutorials/level_3/images/boolean.gif" width=220></font></td>
            <td vAlign=center align=middle width=245><font face="Arial, Helvetica, sans-serif" color=#000066><img height=184 alt="After Union" src="http://www.we-r-here.com/cad/tutorials/level_3/images/union.gif" width=220></font></td>
        </tr>
        <tr>
            <td colSpan=2>
            <p align=center>The UNION command combines one or more solid objects into one object.</p>
            </td>
        </tr>
    </tbody>
</table>
<p><font face="Arial, Helvetica, sans-serif">Here are the command line prompts and the resulting object:</font></p>
<p><span class=style8><font face="Courier New"><strong><font color=#0000ff>Command: </font><span class=style33><font color=#660000>UNION</font></span></strong></font></span><font face="Arial, Helvetica, sans-serif"> &lt;ENTER&gt;</font><span class=style8><font face="Arial, Helvetica, sans-serif"><br></font><strong><font face="Courier New"><span class=style39><font color=#0000ff>Select objects: </font></span><span class=style33><font color=#660000>&lt;</font></span></font></strong></span><span class=style40><font face="Courier New" color=#660000><strong>SELECT THE BLOCK&gt;</strong></font></span><font face="Courier New"><strong><span class=style38><font color=#0000ff> 1 found<br>Select objects: </font></span><span class=style40><font color=#660000>&lt;SELECT THE CYLINDER&gt;</font></span><span class=style38><font color=#0000ff> 1 found</font></span></strong><br><span class=style8><strong><font color=#0000ff>Select objects:</font></strong></span></font> &lt;ENTER&gt;</p>
<p>NOTE: The object that you select <strong>first</strong> will determine the properties of the unioned object when it is created.</p>
<p align=left><strong><a id=sub name=sub></a>SUBTRACT</strong></p>
<p align=justify>The subtract command is used to cut away, or remove the volume of one object from another. It is important to check the command line when using this command. Remember that AutoCAD always asks for the object that you are subtracting <strong>FROM</strong> first, then it asks for the objects to subtract. Here is an example:</p>
<table width=500 align=center border=0>
    <tbody>
        <tr>
            <td vAlign=center align=middle width=245><font face="Arial, Helvetica, sans-serif" color=#000066><img height=184 alt="Before Subtract" src="http://www.we-r-here.com/cad/tutorials/level_3/images/boolean.gif" width=220></font></td>
            <td vAlign=center align=middle width=245><font face="Arial, Helvetica, sans-serif" color=#000066><img height=184 alt="After Subtract" src="http://www.we-r-here.com/cad/tutorials/level_3/images/subtract.gif" width=220></font></td>
        </tr>
        <tr>
            <td colSpan=2>
            <p align=justify>The SUBTRACT command removes the volume of one or more solid objects from an object.</p>
            </td>
        </tr>
    </tbody>
</table>
<p><span class=style38><strong><font face="Courier New" color=#0000ff>Command: </font><font color=#660000><font face="Courier New"><span class="style13 style33">SUBTRACT</span><br></font></font><font face="Courier New"><font color=#0000ff>Select solids and regions to subtract from...<br>Select objects: </font><span class="style13 style33"><font color=#660000>&lt;SELECT THE BLOCK&gt;</font></span><font color=#0000ff> 1 found </font></font></strong></span>&lt;ENTER&gt;<span class=style38><strong><br><font face="Courier New"><font color=#0000ff>Select objects: Select solids and regions to subtract...<br>Select objects: </font><span class="style13 style33"><font color=#660000>&lt;SELECT THE CYLINDER&gt;</font></span><font color=#0000ff> 1 found </font></font></strong></span>&lt;ENTER&gt;<span class=style38><strong><br><font face="Courier New" color=#0000ff>Select objects: </font></strong></span>&lt;ENTER&gt; </p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000066 size=+1><strong><a id=int name=int></a></strong></font><strong>INTERSECT</strong></p>
<p align=justify>This command creates a new solid from the intersecting volume of two or more solids or regions. AutoCAD will find where the two objects have an volume of interference and retain that area and discard the rest. Here is an example of this command shown below:</p>
<table width=500 align=center border=0>
    <tbody>
        <tr>
            <td vAlign=center align=middle width=245><font face="Arial, Helvetica, sans-serif" color=#000066><img height=184 alt="Before Intersect" src="http://www.we-r-here.com/cad/tutorials/level_3/images/boolean.gif" width=220></font></td>
            <td vAlign=center align=middle width=245><font face="Arial, Helvetica, sans-serif" color=#000066><img height=184 alt="After Intersect" src="http://www.we-r-here.com/cad/tutorials/level_3/images/intersect.gif" width=220></font></td>
        </tr>
        <tr>
            <td colSpan=2>
            <p>The INTERSECT command combines the volume of one or more solid objects at the areas of interference to create one solid object.</p>
            </td>
        </tr>
    </tbody>
</table>
<p><font face="Courier New"><span class=style8><strong><font color=#0000ff>Command: </font></strong></span><span class=style40><strong><font color=#660000>INTERSECT</font></strong></span></font><span class=style8><strong><font face="Courier New"><font color=#0000ff> <br>Select objects: </font><span class=style33><font color=#660000>&lt;SELECT THE BLOCK&gt;</font></span></font><font face="Courier New"><font color=#0000ff> 1 found<br>Select objects: </font><span class=style33><font color=#660000>&lt;SELECT THE CYLINDER&gt;</font></span></font><font face="Courier New" color=#0000ff> 1 found<br>Select objects: </font></strong></span>&lt;ENTER&gt;</p>
<p align=justify>Try these commands with various 3D solid objects to get familiar with them. Draw the block in <a href="http://www.we-r-here.com/cad/tutorials/level_3/3-2.htm"><u><font color=#0000ff>Lesson 3-2</font></u></a>. Draw the outline of the block, extrude it - then draw the circle and extrude it. Then subtract the circle from the block.</p>
<p align=justify>These commands will allow you do a lot of 3D work, using only the extrude and these boolean commands. Of course, there are some other ways to edit 3D solids.</p>
<hr SIZE=2>
<p align=justify><strong><a id=slice name=slice></a>SLICE </strong></p>
<p align=justify>This command does exactly what the name implies. You can slice a 3D solid just like you were using a knife.</p>
<p align=justify>Start with the basic block and cylinder shape you used in the examples above.</p>
<table width=500 align=center border=0>
    <tbody>
        <tr>
            <td vAlign=center align=middle width=245><font face="Arial, Helvetica, sans-serif" color=#000066><img height=184 alt="Slice Pickpoints" src="http://www.we-r-here.com/cad/tutorials/level_3/images/slice_01.gif" width=220></font></td>
            <td vAlign=center align=middle width=245><font face="Arial, Helvetica, sans-serif" color=#000066><img height=184 alt="Slice Result" src="http://www.we-r-here.com/cad/tutorials/level_3/images/slice_result.gif" width=220></font></td>
        </tr>
        <tr>
            <td colSpan=2>
            <p>The INTERSECT command combines the volume of one or more solid objects at the areas of interference to create one solid object.</p>
            </td>
        </tr>
    </tbody>
</table>
<p class=style8 align=justify>Command: <span class=style33><font color=#660000>SLICE</font></span> <br>Select objects: 1 found<br>Select objects: Specify first point on slicing plane by <br>[Object/Zaxis/View/XY/YZ/ZX/3points] &lt;3points&gt;: <font color=#660000><span class="style13 style33">PICK POINT 1</span><br></font>Specify second point on plane: <font color=#660000><span class="style13 style33">PICK POINT 2 </span><br></font>Specify third point on plane: <font color=#660000><span class="style13 style33">PICK POINT 3</span><br></font>Specify a point on desired side of the plane or [keep Both sides]: <span class=style33><font color=#660000>&lt;Pick on the side towards the cylinder&gt; </font></span></p>
<p align=justify>This is a very useful command - think of it as a trim in 3D. Make sure you have your Osnaps on for this command and that you pick the correct points. In a complex 3D drawing, this can be tough to see.</p>
<p align=justify><strong><a name=extface></a>EXTRUDE FACE</strong></p>
<p align=justify>Just as there is a "trim"-like command in 3D - there is also a "stretch". This is a new command in recent versions. <img onmouseup="MM_popupMsg('If you have an older version, just copy the object over the required distance . \r\rand then union the 2 objects.')" height=24 alt="More Info" src="http://www.we-r-here.com/cad/tutorials/level_2/images/help.jpg" width=24 align=top></p>
<p align=justify>I usually start this command by clicking on the menu item Modify &gt; Solids Editing &gt; Extrude Faces. There is also an icon for it on the Solids Editing menu. </p>
<p align=justify>The command is quite easy to use, but you need to be careful on which face you select.</p>
<p align=justify>Try to extend one edge of the block by 1 inch. Start the command and pick the face on the side (on the bottom line). You'll notice that the bottom face highlights as well. Next type <span class=style8><strong><font face="Courier New" color=#0000ff>R</font></strong></span> and pick the bottom face to remove it. Then follow the command line to finish the command.</p>
<p class=style8 align=left>Command: <font color=#660000><span class=style33>_solidedit</span><br></font>Solids editing automatic checking: SOLIDCHECK=1<br>Enter a solids editing option [<span class=style33><font color=#660000>F</font></span>ace/Edge/Body/Undo/eXit] &lt;eXit&gt;: _face<br>Enter a face editing option<br>[<span class=style33><font color=#660000>E</font></span>xtrude/Move/Rotate/Offset/Taper/Delete/Copy/coLor/Undo/eXit] &lt;eXit&gt;: _extrude<br>Select faces or [Undo/Remove]: <span class=style33><font color=#660000>(PICK BOTTOM LINE OF SIDE FACE)</font></span> 2 faces found.<br>Select faces or [Undo/Remove/ALL]: <font color=#660000><span class=style33>R</span><br></font>Remove faces or [Undo/Add/ALL]: <span class=style33><font color=#660000>(PICK AN EDGE ON THE BOTTOM FACE)</font></span>2 faces found, 1 removed.<br>Remove faces or [Undo/Add/ALL]: <span class=style47><font color=#663300>(ENTER)</font></span> <br>Specify height of extrusion or [Path]: <span class=style33><font color=#660000>1 (ENTER)</font></span> <br>Specify angle of taper for extrusion &lt;0&gt;: <font color=#660000><span class=style33>(ENTER)</span><br></font>Solid validation started.<br>Solid validation completed.<br>Enter a face editing option<br>[Extrude/Move/Rotate/Offset/Taper/Delete/Copy/coLor/Undo/eXit] &lt;eXit&gt;: <span class=style33><font color=#660000>(ENTER)</font></span></p>
<p align=justify>You should end up with this:</p>
<p align=center><img alt="Extrude Face Result" src="http://www.we-r-here.com/cad/tutorials/level_3/images/extrude_face_result.gif">&nbsp; </p>
<p align=left>Another way of editing faces in AutoCAD 2007 is to use grips to extrude the faces, just like you would on a 2D object. Here is an image below that shows some of the grips available.This option is only available on the basic shapes shown in lesson <a href="http://www.we-r-here.com/cad/tutorials/level_3/3-10.htm"><u><font color=#800080>3-10</font></u></a>. </p>
<p align=center><img title="3D Grips in AutoCAD 2007" height=334 alt="3D Grips in AutoCAD 2007" src="http://www.we-r-here.com/cad/tutorials/level_3/images/3dgrips.gif" width=491></p>
<p align=justify><strong><a name=3da></a>3D ALIGN</strong></p>
<p align=justify>Sometimes, you may find it faster or easier to draw something separately and then move and align it into place. The command to use this in 3D is (funnily enough) <span class=style8><strong><font face="Courier New" color=#0000ff>3DALIGN</font></strong></span>. </p>
<p align=justify>This is a simple example, but will show you the method.</p>
<p align=justify>Draw a box that is 5 x 5 x 6 tall. Next draw a cylinder that is 3 in diameter and 1 tall. It should look like this:</p>
<p align=justify><img title="3D Align in AutoCAD 2007" height=422 alt="3D Align in AutoCAD 2007" src="http://www.we-r-here.com/cad/tutorials/level_3/images/3dalign1.gif" width=512></p>
<p align=justify>The goal will be to align the cylinder on the front face of the box where the dotted line is.</p>
<p align=justify>Turn on your quadrant Osnaps. Start the <span class=style8><strong><font face="Courier New" color=#0000ff>3DALIGN</font></strong></span> command. You will first be asked to select the objects - select the cylinder and press enter.</p>
<p align=justify>Now you will be asked to select the 3 points as indicated below: the centre and 2 quadrants. Now the cylinder will be "stuck" to your cursor as AutoCAD asks where it needs to go.</p>
<p align=justify>Line the cylinder up with the box by using object tracking to locate the centre of the face on the box first. Then pick on the midpoints to line up the cylinder to the box. After you pick the 3rd point, the cylinder should move into place and end the command.</p>
<p align=justify>Here's a view of the points that were picked incase you had trouble.</p>
<p align=justify><img title="3D Align in AutoCAD 2007" height=422 alt="3D Align in AutoCAD 2007" src="http://www.we-r-here.com/cad/tutorials/level_3/images/3dalign2.gif" width=512></p>
<p align=justify>The finished 'alignment job' should look like this after using the hide command. </p>
<p align=justify><img height=392 alt="3d Align in AutoCAD 2007" src="http://www.we-r-here.com/cad/tutorials/level_3/images/3dalign3.gif" width=337 titlt="3d Align in AutoCAD 2007"></p>
<p align=justify><strong>Review:</strong><br><br>After learning how to draw some basic 3D solids, you can see that using equally basic editing commands you can have a lot of options. Before advancing, review these commands by drawing simple 3D shapes and editing them.</p>
<p align=justify>With the commands explained on these pages, you will be able draw most of the shapes you will need in 3D. There are other options, but get very familiar with these 3D editing options before moving on. The drawings done in the sample drawing section were done almost exclusively with the commands taught in Lessons 3-7 to 3-11. You approach will make the project easy or difficult. Think of the various ways to draw an object before starting. You could save days with some forethought. </p>
<p align=justify><strong>Extra Practice:</strong> Draw <a href="http://www.we-r-here.com/cad/tutorials/level_3/images/extra_3-001.gif" target=_blank><strong><u><font color=#0000ff>this object</font></u></strong></a> as a 3D solid using primitive solids and boolean operations. </p>
<p align=justify><strong>Extra Practice:</strong> Draw <a href="http://www.we-r-here.com/cad/tutorials/level_3/images/extra_3-011.gif" target=_blank><strong><u><font color=#0000ff>this object</font></u></strong></a> as a 3D solid using primitive solids and boolean operations.</p>
<img src ="http://www.cppblog.com/zmj/aggbug/78801.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-04-03 11:37 <a href="http://www.cppblog.com/zmj/archive/2009/04/03/78801.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Point-Plane Distance</title><link>http://www.cppblog.com/zmj/archive/2009/03/24/77741.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Tue, 24 Mar 2009 09:18:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/03/24/77741.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/77741.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/03/24/77741.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/77741.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/77741.html</trackback:ping><description><![CDATA[LINK: <a href="http://mathworld.wolfram.com/Point-PlaneDistance.html">http://mathworld.wolfram.com/Point-PlaneDistance.html</a><br>
<table width="100%">
    <tbody>
        <tr>
            <td vAlign=top align=left width="100%">
            <table cellSpacing=0 cellPadding=0 border=0>
                <tbody>
                    <tr>
                        <td class=title vAlign=baseline><span class=nowrap>Point-Plane Distance</span></td>
                    </tr>
                    <tr>
                        <td vAlign=top><span class=nowrap><img height=3 alt="" src="http://mathworld.wolfram.com/images/entries/underline.gif" width="100%"><img height=3 alt="" src="http://mathworld.wolfram.com/images/entries/underline.gif" width=20></span></td>
                        <td><img height=15 alt="" src="http://mathworld.wolfram.com/images/spacer.gif"></td>
                    </tr>
                </tbody>
            </table>
            <!-- End Title --></td>
        </tr>
        <tr vAlign=top>
            <td><!-- Begin Total Content --><!-- Begin Content -->
            <div align=center><img height=291 alt=PointPlaneDistance src="http://mathworld.wolfram.com/images/eps-gif/PointPlaneDistance_1000.gif" width=372> </div>
            <p class=Text>Given a <a class=Hyperlink href="http://mathworld.wolfram.com/Plane.html"><u><font color=#0000ff>plane</font></u></a> </p>
            <div>
            <table style="PADDING-LEFT: 50px" cellSpacing=0 cellPadding=0 width="100%" align=center>
                <tbody>
                    <tr>
                        <td align=left><img class=numberedequation height=14 alt=" ax+by+cz+d=0 " src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/NumberedEquation1.gif" width=125 border=0></td>
                        <td align=right width=3>
                        <div class=eqnum id=eqn1>(1) </div>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p class=Text>and a point <img class=inlineformula height=16 alt=x_0=(x_0,y_0,z_0) src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline1.gif" width=92 border=0>, the <a class=Hyperlink href="http://mathworld.wolfram.com/Normal.html"><u><font color=#0000ff>normal</font></u></a> to the <a class=Hyperlink href="http://mathworld.wolfram.com/Plane.html"><u><font color=#0000ff>plane</font></u></a> is given by </p>
            <div>
            <table style="PADDING-LEFT: 50px" cellSpacing=0 cellPadding=0 width="100%" align=center>
                <tbody>
                    <tr>
                        <td align=left><img class=numberedequation height=54 alt=" v=[a; b; c], " src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/NumberedEquation2.gif" width=51 border=0></td>
                        <td align=right width=3>
                        <div class=eqnum id=eqn2>(2) </div>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p class=Text>and a <a class=Hyperlink href="http://mathworld.wolfram.com/Vector.html"><u><font color=#0000ff>vector</font></u></a> from the plane to the point is given by </p>
            <div>
            <table style="PADDING-LEFT: 50px" cellSpacing=0 cellPadding=0 width="100%" align=center>
                <tbody>
                    <tr>
                        <td align=left><img class=numberedequation height=56 alt=" w=-[x-x_0; y-y_0; z-z_0]. " src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/NumberedEquation3.gif" width=92 border=0></td>
                        <td align=right width=3>
                        <div class=eqnum id=eqn3>(3) </div>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p class=Text><a class=Hyperlink href="http://mathworld.wolfram.com/Projection.html"><u><font color=#0000ff>Projecting</font></u></a> <img class=inlineformula height=14 alt=w src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline2.gif" width=10 border=0> onto <img class=inlineformula height=14 alt=v src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline3.gif" width=7 border=0> gives the distance <img class=inlineformula height=14 alt=D src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline4.gif" width=10 border=0> from the point to the plane as </p>
            <table style="PADDING-LEFT: 50px" cellSpacing=0 cellPadding=0 width="100%" align=center border=0>
                <tbody>
                    <tr>
                        <td align=right width=1><img class=displayformula height=14 alt=D src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline5.gif" width=10 border=0></td>
                        <td align=middle width=14><img class=displayformula height=14 alt== src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline6.gif" width=9 border=0></td>
                        <td align=left><img class=displayformula height=21 alt=|proj_(v)w| src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline7.gif" width=48 border=0></td>
                        <td align=right width=10>
                        <div class=eqnum id=eqn4>(4) </div>
                        </td>
                    </tr>
                    <tr>
                        <td align=right width=1><img class=displayformula height=14 alt="" src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline8.gif" width=12 border=0></td>
                        <td align=middle width=14><img class=displayformula height=14 alt== src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline9.gif" width=9 border=0></td>
                        <td align=left><img class=displayformula height=36 alt=(|v&#183;w|)/(|v|) src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline10.gif" width=35 border=0></td>
                        <td align=right width=10>
                        <div class=eqnum id=eqn5>(5) </div>
                        </td>
                    </tr>
                    <tr>
                        <td align=right width=1><img class=displayformula height=14 alt="" src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline11.gif" width=12 border=0></td>
                        <td align=middle width=14><img class=displayformula height=14 alt== src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline12.gif" width=9 border=0></td>
                        <td align=left><img class=displayformula height=48 alt=(|a(x-x_0)+b(y-y_0)+c(z-z_0)|)/(sqrt(a^2+b^2+c^2)) src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline13.gif" width=197 border=0></td>
                        <td align=right width=10>
                        <div class=eqnum id=eqn6>(6) </div>
                        </td>
                    </tr>
                    <tr>
                        <td align=right width=1><img class=displayformula height=14 alt="" src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline14.gif" width=12 border=0></td>
                        <td align=middle width=14><img class=displayformula height=14 alt== src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline15.gif" width=9 border=0></td>
                        <td align=left><img class=displayformula height=48 alt=(|ax+by+cz-ax_0-by_0-cz_0|)/(sqrt(a^2+b^2+c^2)) src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline16.gif" width=202 border=0></td>
                        <td align=right width=10>
                        <div class=eqnum id=eqn7>(7) </div>
                        </td>
                    </tr>
                    <tr>
                        <td align=right width=1><img class=displayformula height=14 alt="" src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline17.gif" width=12 border=0></td>
                        <td align=middle width=14><img class=displayformula height=14 alt== src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline18.gif" width=9 border=0></td>
                        <td align=left><img class=displayformula height=48 alt=(|ax_0+by_0+cz_0+d|)/(sqrt(a^2+b^2+c^2)). src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline19.gif" width=134 border=0></td>
                        <td align=right width=10>
                        <div class=eqnum id=eqn8>(8) </div>
                        </td>
                    </tr>
                </tbody>
            </table>
            <p class=Text>Dropping the absolute value signs gives the signed distance, </p>
            <div>
            <table style="PADDING-LEFT: 50px" cellSpacing=0 cellPadding=0 width="100%" align=center>
                <tbody>
                    <tr>
                        <td align=left><img class=numberedequation height=48 alt=" D=(ax_0+by_0+cz_0+d)/(sqrt(a^2+b^2+c^2)), " src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/NumberedEquation4.gif" width=155 border=0></td>
                        <td align=right width=3>
                        <div class=eqnum id=eqn9>(9) </div>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p class=Text>which is positive if <img class=inlineformula height=16 alt=x_0 src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline20.gif" width=13 border=0> is on the same side of the plane as the normal vector <img class=inlineformula height=14 alt=v src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline21.gif" width=7 border=0> and negative if it is on the opposite side. </p>
            <p class=Text>This can be expressed particularly conveniently for a plane specified in <a class=Hyperlink href="http://mathworld.wolfram.com/HessianNormalForm.html"><u><font color=#0000ff>Hessian normal form</font></u></a> by the simple equation </p>
            <div>
            <table style="PADDING-LEFT: 50px" cellSpacing=0 cellPadding=0 width="100%" align=center>
                <tbody>
                    <tr>
                        <td align=left><img class=numberedequation height=18 alt=" D=n^^&#183;x_0+p, " src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/NumberedEquation5.gif" width=82 border=0></td>
                        <td align=right width=3>
                        <div class=eqnum id=eqn10>(10) </div>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p class=Text>where <img class=inlineformula height=16 alt=n^^=v/|v| src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline22.gif" width=53 border=0> is the unit normal vector. Therefore, the distance of the plane from the origin is simply given by <img class=inlineformula height=14 alt=p src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline23.gif" width=8 border=0> (Gellert <em>et al. </em>1989, p.&nbsp;541). </p>
            <p class=Text>Given three points <img class=inlineformula height=16 alt=x_i src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline24.gif" width=11 border=0> for <img class=inlineformula height=14 alt=i=1 src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline25.gif" width=28 border=0>, 2, 3, compute the unit normal </p>
            <div>
            <table style="PADDING-LEFT: 50px" cellSpacing=0 cellPadding=0 width="100%" align=center>
                <tbody>
                    <tr>
                        <td align=left><img class=numberedequation height=38 alt=" n^^=((x_2-x_1)x(x_3-x_1))/(|(x_2-x_1)x(x_3-x_1)|). " src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/NumberedEquation6.gif" width=147 border=0></td>
                        <td align=right width=3>
                        <div class=eqnum id=eqn11>(11) </div>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p class=Text>Then the distance from a point <img class=inlineformula height=16 alt=x_0 src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline26.gif" width=13 border=0> to the plane containing the three points is given by </p>
            <div>
            <table style="PADDING-LEFT: 50px" cellSpacing=0 cellPadding=0 width="100%" align=center>
                <tbody>
                    <tr>
                        <td align=left><img class=numberedequation height=18 alt=" D_i=n^^&#183;(x_0-x_i), " src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/NumberedEquation7.gif" width=97 border=0></td>
                        <td align=right width=3>
                        <div class=eqnum id=eqn12>(12) </div>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p class=Text>where <img class=inlineformula height=16 alt=x_i src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/Inline27.gif" width=11 border=0> is any of the three points. Expanding out the coordinates shows that </p>
            <div>
            <table style="PADDING-LEFT: 50px" cellSpacing=0 cellPadding=0 width="100%" align=center>
                <tbody>
                    <tr>
                        <td align=left><img class=numberedequation height=16 alt=" D=D_1=D_2=D_3, " src="http://mathworld.wolfram.com/images/equations/Point-PlaneDistance/NumberedEquation8.gif" width=111 border=0></td>
                        <td align=right width=3>
                        <div class=eqnum id=eqn13>(13) </div>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p class=Text>as it must since all points are in the same plane, although this is far from obvious based on the above vector equation. </p>
            <!-- End Content --><!-- Begin See Also -->
            <form name=SearchLinks action=http://mathworld.wolfram.com/search/ method=get>
                <p class=CrossRefs><span class=crosslinkheader>SEE ALSO:</span> <a class=Hyperlink href="http://mathworld.wolfram.com/HessianNormalForm.html"><u><font color=#0000ff>Hessian Normal Form</font></u></a>, <a class=Hyperlink href="http://mathworld.wolfram.com/Plane.html"><u><font color=#0000ff>Plane</font></u></a>, <a class=Hyperlink href="http://mathworld.wolfram.com/Point.html"><u><font color=#0000ff>Point</font></u></a>, <a class=Hyperlink href="http://mathworld.wolfram.com/ProjectionTheorem.html"><u><font color=#0000ff>Projection Theorem</font></u></a> </p>
            </form>
            <!-- End See Also --><!-- Begin CrossURL --><!-- End CrossURL --><!-- Begin Contributor --><!-- End Contributor --><!-- Begin References -->
            <p><img height=3 alt="" src="http://mathworld.wolfram.com/images/entries/underline.gif" width=300> </p>
            <span class=crosslinkheader>REFERENCES:</span>
            <p class=Reference>Gellert, W.; Gottwald, S.; Hellwich, M.; K&#228;stner, H.; and K&#252;nstner, H. (Eds.). <em><a class=Hyperlink href="http://www.amazon.com/exec/obidos/ASIN/0442205902/ref=nosim/weisstein-20"><u><font color=#0000ff>VNR Concise Encyclopedia of Mathematics, 2nd ed.</font></u></a></em> New York: Van Nostrand Reinhold, 1989. </p>
            <!-- End References --><!-- Begin CiteAs -->
            <div><img height=3 alt="" src="http://mathworld.wolfram.com/images/entries/underline.gif" width=300><br><br><br><span class=crosslinkheader>CITE THIS AS:</span><br>
            <p class=citation><a href="http://mathworld.wolfram.com/about/author.html"><u><font color=#0000ff>Weisstein, Eric W.</font></u></a> "Point-Plane Distance." From <a href="http://mathworld.wolfram.com/"><em><u><font color=#800080>MathWorld</font></u></em></a>--A Wolfram Web Resource. <a href="http://mathworld.wolfram.com/Point-PlaneDistance.html"><u><font color=#800080>http://mathworld.wolfram.com/Point-PlaneDistance.html</font></u></a> </p>
            </div>
            <!-- End CiteAs --><!-- End Total Content --></td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/zmj/aggbug/77741.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-03-24 17:18 <a href="http://www.cppblog.com/zmj/archive/2009/03/24/77741.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Polygon Area</title><link>http://www.cppblog.com/zmj/archive/2009/03/09/75956.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Mon, 09 Mar 2009 01:14:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/03/09/75956.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/75956.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/03/09/75956.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/75956.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/75956.html</trackback:ping><description><![CDATA[LINK:http://mathworld.wolfram.com/PolygonArea.html<br>
<table width="100%">
    <tbody>
        <tr>
            <td vAlign=top align=left width="100%">
            <table cellSpacing=0 cellPadding=0 border=0>
                <tbody>
                    <tr>
                        <td class=title vAlign=baseline><span class=nowrap>Polygon Area</span></td>
                    </tr>
                    <tr>
                        <td vAlign=top><span class=nowrap><img height=3 alt="" src="http://mathworld.wolfram.com/images/entries/underline.gif" width="100%"><img height=3 alt="" src="http://mathworld.wolfram.com/images/entries/underline.gif" width=20></span></td>
                        <td><img height=15 alt="" src="http://mathworld.wolfram.com/images/spacer.gif"></td>
                    </tr>
                </tbody>
            </table>
            <!-- End Title --></td>
        </tr>
        <tr vAlign=top>
            <td><!-- Begin Total Content --><a onclick="downloadNotebook('http://mathworld.wolfram.com/notebooks/PlaneGeometry/PolygonArea.nb');return false;" href="http://mathworld.wolfram.com/notebooks/PlaneGeometry/PolygonArea.nb"><img height=26 alt="DOWNLOAD Mathematica Notebook" src="http://mathworld.wolfram.com/images/entries/dnld-nb.gif" width=119 border=0></a> <!-- Begin Content -->
            <div align=center><img height=124 alt=PolygonArea src="http://mathworld.wolfram.com/images/eps-gif/PolygonArea_1000.gif" width=282> </div>
            <p class=Text>The (signed) <a class=Hyperlink href="http://mathworld.wolfram.com/Area.html"><u><font color=#0000ff>area</font></u></a> of a planar non-self-intersecting <a class=Hyperlink href="http://mathworld.wolfram.com/Polygon.html"><u><font color=#0000ff>polygon</font></u></a> with <a class=Hyperlink href="http://mathworld.wolfram.com/PolygonVertex.html"><u><font color=#0000ff>vertices</font></u></a> <img class=inlineformula height=14 alt=(x_1,y_1) src="http://mathworld.wolfram.com/images/equations/PolygonArea/Inline1.gif" width=42 border=0>, ..., <img class=inlineformula height=16 alt=(x_n,y_n) src="http://mathworld.wolfram.com/images/equations/PolygonArea/Inline2.gif" width=42 border=0> is </p>
            <div>
            <table style="PADDING-LEFT: 50px" cellSpacing=0 cellPadding=0 width="100%" align=center>
                <tbody>
                    <tr>
                        <td align=left><img class=numberedequation height=37 alt=" A=1/2(|x_1 x_2; y_1 y_2|+|x_2 x_3; y_2 y_3|+...+|x_n x_1; y_n y_1|), " src="http://mathworld.wolfram.com/images/equations/PolygonArea/NumberedEquation1.gif" width=260 border=0></td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p class=Text>where <img class=inlineformula height=14 alt=|M| src="http://mathworld.wolfram.com/images/equations/PolygonArea/Inline3.gif" width=18 border=0> denotes a <a class=Hyperlink href="http://mathworld.wolfram.com/Determinant.html"><u><font color=#0000ff>determinant</font></u></a>. This can be written </p>
            <div>
            <table style="PADDING-LEFT: 50px" cellSpacing=0 cellPadding=0 width="100%" align=center>
                <tbody>
                    <tr>
                        <td align=left><img class=numberedequation height=23 alt=" A=1/2(x_1y_2-x_2y_1+x_2y_3-x_3y_2+...+x_(n-1)y_n-x_ny_(n-1)+x_ny_1-x_1y_n), " src="http://mathworld.wolfram.com/images/equations/PolygonArea/NumberedEquation2.gif" width=439 border=0></td>
                    </tr>
                </tbody>
            </table>
            </div>
            <p class=Text>where the signs can be found from the diagram above. </p>
            <p class=Text>Note that the <a class=Hyperlink href="http://mathworld.wolfram.com/Area.html"><u><font color=#0000ff>area</font></u></a> of a <a class=Hyperlink href="http://mathworld.wolfram.com/ConvexPolygon.html"><u><font color=#0000ff>convex polygon</font></u></a> is defined to be <a class=Hyperlink href="http://mathworld.wolfram.com/Positive.html"><u><font color=#0000ff>positive</font></u></a> if the points are arranged in a counterclockwise order, and <a class=Hyperlink href="http://mathworld.wolfram.com/Negative.html"><u><font color=#0000ff>negative</font></u></a> if they are in clockwise order (Beyer 1987). </p>
            <!-- End Content --><!-- Begin See Also -->
            <form name=SearchLinks action=http://mathworld.wolfram.com/search/ method=get>
                <p class=CrossRefs><span class=crosslinkheader>SEE ALSO:</span> <a class=Hyperlink href="http://mathworld.wolfram.com/Area.html"><u><font color=#0000ff>Area</font></u></a>, <a class=Hyperlink href="http://mathworld.wolfram.com/ConvexPolygon.html"><u><font color=#0000ff>Convex Polygon</font></u></a>, <a class=Hyperlink href="http://mathworld.wolfram.com/Polygon.html"><u><font color=#0000ff>Polygon</font></u></a>, <a class=Hyperlink href="http://mathworld.wolfram.com/TriangleArea.html"><u><font color=#0000ff>Triangle Area</font></u></a> </p>
            </form>
            <!-- End See Also --><!-- Begin CrossURL --><!-- End CrossURL --><!-- Begin Contributor --><!-- End Contributor --><!-- Begin References -->
            <p><img height=3 alt="" src="http://mathworld.wolfram.com/images/entries/underline.gif" width=300> </p>
            <span class=crosslinkheader>REFERENCES:</span>
            <p class=Reference>Beyer, W.&nbsp;H. (Ed.). <em><a class=Hyperlink href="http://www.amazon.com/exec/obidos/ASIN/1584882913/ref=nosim/weisstein-20"><u><font color=#0000ff>CRC Standard Mathematical Tables, 28th ed.</font></u></a></em> Boca Raton, FL: CRC Press, pp.&nbsp;123-124, 1987. </p>
            <!-- End References --><!-- Begin CiteAs -->
            <div><img height=3 alt="" src="http://mathworld.wolfram.com/images/entries/underline.gif" width=300><br><br><br><span class=crosslinkheader>CITE THIS AS:</span><br>
            <p class=citation><a href="http://mathworld.wolfram.com/about/author.html"><u><font color=#0000ff>Weisstein, Eric W.</font></u></a> "Polygon Area." From <a href="http://mathworld.wolfram.com/"><em><u><font color=#0000ff>MathWorld</font></u></em></a>--A Wolfram Web Resource. <a href="http://mathworld.wolfram.com/PolygonArea.html"><u><font color=#800080>http://mathworld.wolfram.com/PolygonArea.html</font></u></a> </p>
            </div>
            <!-- End CiteAs --><!-- End Total Content --></td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/zmj/aggbug/75956.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-03-09 09:14 <a href="http://www.cppblog.com/zmj/archive/2009/03/09/75956.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程，多显示场景图形设计：一种新的过程模型</title><link>http://www.cppblog.com/zmj/archive/2009/03/05/75678.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Thu, 05 Mar 2009 14:51:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/03/05/75678.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/75678.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/03/05/75678.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/75678.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/75678.html</trackback:ping><description><![CDATA[<h2 id=WelcometotheOpenSceneGraphwebsite>多线程，多显示场景图形设计：一种新的过程模型</h2>
<div class="wiki-toc trac-nav">
<ul>
    <li style="PADDING-LEFT: 1em">
    <h4><strong><a class=wiki href="http://www.osgchina.org/projects/osgChina/wiki/About.php"><font color=#0000ff><u>关于</u></font></a></strong></h4>
    <li style="PADDING-LEFT: 1em"><strong><a class=wiki href="http://www.osgchina.org/projects/osgChina/wiki/Screenshots.php"><u><font color=#0000ff>案例截图</font></u></a></strong>
    <li style="PADDING-LEFT: 1em"><strong><a class=wiki href="http://www.osgchina.org/projects/osgChina/wiki/News.php"><u><font color=#0000ff>新闻</font></u></a></strong>
    <li style="PADDING-LEFT: 1em"><strong><a class=wiki href="http://www.osgchina.org/projects/osgChina/wiki/Support.php"><u><font color=#800080>中文教程</font></u></a></strong>
    <li style="PADDING-LEFT: 2em"><a class=wiki href="http://www.osgchina.org/projects/osgChina/wiki/Support/install.php"><u><font color=#0000ff>安装编译</font></u></a>
    <li style="PADDING-LEFT: 2em"><a class=wiki href="http://www.osgchina.org/projects/osgChina/wiki/Support/example.php"><u><font color=#0000ff>例子解析</font></u></a>
    <li class=active style="PADDING-LEFT: 2em"><a class=wiki href="http://www.osgchina.org/projects/osgChina/wiki/Support/paperE2C.php"><u><font color=#800080>论文翻译</font></u></a>
    <li style="PADDING-LEFT: 2em"><a class=wiki href="http://www.osgchina.org/projects/osgChina/wiki/Support/3rd.php"><u><font color=#0000ff>扩展/插件</font></u></a>
    <li style="PADDING-LEFT: 1em"><strong><a class=wiki href="http://www.osgchina.org/projects/osgChina/wiki/Community.php"><u><font color=#0000ff>社区</font></u></a></strong>
    <li style="PADDING-LEFT: 1em"><strong><a class=wiki href="http://www.osgchina.org/projects/osgChina/wiki/Links.php"><u><font color=#0000ff>相关链接</font></u></a></strong> </li>
</ul>
</div>
<div>
<p>作者：<a href="http://www.osgchina.org/projects/osgcn/wikicn/Communitycn/Peoplecn/DonBurns.php"><u><font color=#0000ff>Don Burns</font></u></a>，2001<br>译者：<a href="http://www.osgchina.org/projects/osgChina/team/people/array.php"><u><font color=#0000ff>王锐</font></u></a>，2008<br>
<h3>新的设想</h3>
<p><br>场景图形的主要目的是改善场景优化，渲染状态排序和各种其它操作的性能，降低图形渲染引擎的负荷，并实现复杂场景的&#8220;实时&#8221;渲染。实时渲染的目标是以足够高的帧速（符合人眼的交互要求）渲染场景。飞行模拟程序通过窗口输出（out-the-window）的图像生成频率要求为60Hz或者更高，这样显示的内容才不会发生异常。而30Hz，20Hz或者15Hz的频率则是&#8220;可交互&#8221;的，即，视口可以交由用户进行操控，并在合适的时间响应用户的输入。基于这些目标，我们需要参照帧速60Hz的仿真要求实现我们的设计。我们假定帧速率恒定，且图形子系统针对垂直消隐时间（vertical blanking time，即电子枪扫描完一帧之后返回原点的时间）与渲染交换缓冲区（rendering buffer swap）执行同步的能力恒定。此外，我们还假定多显示的系统已经实现了同步锁相（genlock），至少实现了帧锁相（frame lock，借助硬件使每个显示屏上的帧实现同步），这样就可以实现垂直回描边界（vertical retrace boundary，即电子枪扫描完一帧之后返回的边界）在所有图形子系统上的同步。</p>
<h3>多任务，多显示，单系统绘图的传统方法</h3>
<p><br>使用场景图形实现实时渲染的&#8220;传统&#8221;方法是实现多个阶段，即：APP（用户阶段），CULL（拣选阶段），DRAW（绘制阶段）。APP阶段用于更新所有的动态用户数据，包括相机的位置，以及运动对象的位置和属性变化。CULL必须跟随在APP之后，这一阶段中，首先参照视口锥截体（viewing frustum）中的可见对象，其次参照用于渲染性能的渲染状态，对场景进行排序。CULL阶段更新摄像机位置的依赖数据，并为其后的DRAW阶段构建一个&#8220;显示列表&#8221;（display list）。DRAW阶段仅仅是遍历整个显示列表，并执行OpenGL的各种调用，将数据传递给图形子系统进行处理。 <img height=186 src="http://www.osgchina.org/projects/osgChina/wiki/img/support/paperE2C/pro1.JPG" width=654> </p>
<p>在一个具备多个图形子系统的系统中，有必要为每个图形子系统设置CULL和DRAW 阶段，因为在假定各个视口锥截体均不同的前提下，只有CULL阶段能够为每个子系统构建唯一的&#8220;显示列表&#8221;。而APP阶段则不必设置多个，因为每个视口均会共享同一个APP阶段更新的动态数据。 </p>
<p>鉴于此，一个具备多图形子系统的系统，要实现多任务的机制，则需要定义过程如下：一个单处理器的系统需要顺序地执行各个阶段（例如，APP，CULL_0，DRAW_0，CULL_1，DRAW_1，CULL_2，DRAW_2），而一帧的时间也就相当于这些阶段耗费的总时间。因此，我们需要实现的任务主要有两个：（1）唯一的APP任务，（2）每个图形子系统各自的CULL/DRAW任务。</p>
<p><img height=288 src="http://www.osgchina.org/projects/osgChina/wiki/img/support/paperE2C/pro2.JPG" width=506> </p>
<p><br>在多处理器系统中，如果处理器树木足够多的话，那么每一个任务都可以在某一个处理器上并行地执行。此外，CULL/DRAW任务也可以分离为两个任务并行地运行。 </p>
<p>并行多处理器环境的模型实现主要有两个目标。（1）分离并行化（Task Division Parallelization）：将一个大型的任务分解成多个可以并行运行的小型任务，以削减运行时间；（2）集成并行化（Task Aggregation Parallelization）：将一个任务N次倍乘后，并行地运行它的每个实例，而不增加运行时间。将CULL/DRAW阶段从APP阶段分离出来，然后将CULL和DRAW分离成独立并行的任务，这是一个&#8220;分离并行化&#8221;的例子。将多个CULL/DRAW组合的任务添加给各个图形子系统，这是一个&#8220;集成并行化&#8221;的例子。 </p>
<p>并行地运行各个阶段可能会带来一些问题。首先，各个阶段必须顺序地处理数据。换句话说，APP阶段完成对数据的处理之后，CULL阶段才可以开始使用这些数据。同样，DRAW阶段也不可以在CULL完成数据生成之前使用这些数据。不过，APP阶段不需要等待CULL和DRAW阶段的工作完成，就可以开始下一帧的数据处理工作，因此，系统管线流程的设计如下图所示:</p>
<p><img height=427 src="http://www.osgchina.org/projects/osgChina/wiki/img/support/paperE2C/pro3.JPG" width=654> </p>
<p>此外，各个阶段之间共享的数据也需要进行保护和缓存。由之前的阶段写入的数据，不可以被同时发生的其它并行阶段读取。这样场景图形软件就需要引入复杂的数据管理功能。 </p>
<p>以上所述是SGI Iris Performer在九十年代提出的一种框架结构。在当时它是合适的，但是现在已经有些过时。</p>
<p><br>实时且具备窗口输出（out-the-window）的飞行模拟系统需要60Hz的帧速率，也就是说，每个阶段只有16.667毫秒的时间来完成其任务。1990年，SGI开始开发实时图形系统，它所使用的处理器速度是现在处理器的1/60。由于图形系统与图形处理器的能力成比例相关，APP和CULL阶段所需的时间负荷并不是相同的。上图所示的系统设计中，APP和CULL阶段被假定可能占用整整一帧的时间进行处理。</p>
<p><br>后来，系统频宽的增长降低了基于本地的图形分配的消耗，而DRAW阶段需要分离成两个独立的执行线程：一个在主机上运行，另一个在图形子系统上运行。这一改变将在后面的部分详述。</p>
<p><br>最后一个需要提及的话题是等待时间（latency，即获得系统任何形式响应所需的最小时间）。飞行模拟系统可以允许有大约三帧的视觉反应延迟时间。这一时间延迟是符合真实人体行为研究的结果的，因此我们不得不参照上述过程模型的要求进行折衷的设计。</p>
<p>
<h3>新的实现方案</h3>
<p><br>在目前的硬件条件（以60Hz为帧速率标准）下运行的大多数应用程序，其CULL预阶段（即APP阶段）和CULL阶段的处理时间分别限制在少于1毫秒和少于3-5毫秒的范围内。这样的话，各个阶段要各自占用完整的一帧，或者占用一个完整的CPU时间，恐怕是浪费且不切实的。下面的图表反映了这一事实。</p>
<p><br>有一种提议是，交由CULL预阶段和CULL阶段来执行复杂的任务，以增加了它们的运行时间。但是，大多数执行复杂操作的应用程序任务，其更好的实现方案是与帧的实现部分同步运行。</p>
<p><br>首先我们考虑单处理器，单图形子系统的系统模型。当CULL预阶段和CULL阶段的计算需求降低时，各阶段的运行相位可以如图进行设计： </p>
<p>&#160;</p>
<p><img height=267 src="http://www.osgchina.org/projects/osgChina/wiki/img/support/paperE2C/pro4.JPG" width=654></p>
<p>这一方案的好的方面是，所有的三个阶段可以在一帧执行，响应时间也只有一帧。不利的方面是，DRAW阶段分配的时间较以前大大减少，其启动时间也在一帧的中部位置。使用场景图形的另一个益处是，CULL阶段可以去除不可见的场景，以降低主机图形子系统的带宽压力，同时它还负责按照状态变化值对所有对象进行排序，以优化图形流水线的性能。</p>
<p><br>由于系统带宽和图形性能的不断提高，那些运行在老式硬件平台下的应用程序，其需求可能较以前有所降低。分配给渲染的时间也许是充足的。这样的话，场景图形系统也就不必再考虑数据保护和管理上的特殊需要了。</p>
<p><br>现在我们考虑多图形子系统，多处理器的系统模型。为了使用多处理器系统的优势，我们需要设置一个主线程，用于运行CULL预阶段的任务，并为每个图形子系统设置CULL/DRAW线程。为此，我们要针对数据管理考虑以下两个方面：<br>（1）CULL预阶段的公共数据写入。<br>（2）CULL阶段生成的内部数据，分别复制到各个CULL/DRAW阶段中。<br>然后，我们才可以安全地执行各个阶段，如下图所示：</p>
<p><img height=344 src="http://www.osgchina.org/projects/osgChina/wiki/img/support/paperE2C/pro5.JPG" width=654></p>
<p>我们已经解决了集成并行化所存在的问题，但是还没有解决DRAW阶段少于一帧时间的问题。我们必须将CULL和DRAW阶段分割成不同的处理线程来实现这一目标。因此我们需要考虑如何保护和缓存数据，这些数据由CULL阶段生成，由DRAW阶段处理。下面的部分将讨论这一主题，其阶段图如下所示。</p>
<p><img height=460 src="http://www.osgchina.org/projects/osgChina/wiki/img/support/paperE2C/pro6.JPG" width=654></p>
<p>对于硬件厂商来说，上图所示的情景一定是十分诱人的，因为它使用了7个CPU来控制3个图形子系统。而且还有一种说法是，如果保留CPU 0来执行操作系统任务，从CPU 1开始执行仿真任务，那么我们还需要第八个CPU。但是，对于工程人员来说，上图中存在了太多的空闲空间。同时，我们还增加了每一帧的响应时间。不过这还是好过旧式模型的三帧的响应时间。</p>
<p><br>
<h3>主机绘制 vs. 图形子系统绘制</h3>
<p><br>到这里为止，我们一直都把DRAW作为一个独立的阶段，或者一个独立的线程（进程）进行介绍。在旧式的系统上，由于绘制（DRAW）过程受到主机向图形子系统传输的带宽和图形处理速度的影响，这一工作模型应当说是合理的。但是如今，我们需要认识到，当DRAW阶段运行于主机的某个专有CPU上时，它同时与图形子系统上的另一个并行处理器产生交互。OpenGL程序所做的仅仅是封装了OpenGL协议（以数据和信息流的方式），并传递给图形子系统，后者处理数据和信息流的内容并执行实际的矩阵变换，并实现结果的渲染。主机的绘制（DRAW）过程略微提前于图形子系统的绘制过程开始，并略微提前（有时可能会大幅提前）结束处理。通过使用基于主机的计时工具来进行图形基准测试，即可获得这一结论。</p>
<p><br>下图所示为主机DRAW（也称作分派）阶段和图形子系统DRAW阶段的实时运作流程 </p>
<p>&#160;</p>
<p><img height=396 src="http://www.osgchina.org/projects/osgChina/wiki/img/support/paperE2C/pro7.JPG" width=654></p>
<p>从上图可以看出，一帧时间内，主机DRAW（分派）过程在帧的边界开始。而主机DRAW分派OpenGL调用和图形子系统开始处理这些调用之间的时间区域，被称作分派时间（Dispatch latency）。黄色的条带表示图形子系统完成数据流的读入和处理，完成矩阵变换，渲染，并执行渲染缓存的交换所需的时间。由于交换缓存在下一次垂直回描（vertical retrace）消隐之前不会开始，因此图形子系统在这段时间里处于空闲。</p>
<p><br>注意，由于DRAW分派过程在图形子系统的处理完成之前已经结束。为了实现应用程序与图形子系统的同步，大多数主流的图形软件都会选择在下一帧之前等待一个指示&#8220;交换缓存已经执行&#8221;的信号。这可以说是一个优化主机运行时间的机会。</p>
<p><br>综上，再考虑到主机和图形系统的并行特性，我们可以设想如下图所示的过程模型。</p>
<p><img height=344 src="http://www.osgchina.org/projects/osgChina/wiki/img/support/paperE2C/pro8.JPG" width=654></p>
<p>在这个模型中，我们根据图形子系统垂直回描信号的精确时间，规划主机上的帧调度工作。不过，我们可以控制时间产生轻微的摆动，这样就可能在垂直回描之前，在主机上开始 新的一帧。当垂直回描信号产生，同时图形子系统的处理重置之时，我们在主机上完成CULL预阶段，CULL阶段，并向下传递由主机DRAW过程生成的OpenGL协议。这一工作的起始时间与图形子系统的帧边界尽量贴近。注意，CULL和DRAW（分派）位于同一线程中，执行串行处理。其结果是，原本用于等待垂直回描信号而浪费的主机时间，现在得到了有效的节约。</p>
<p><br>这一模型意味着场景图形的内存管理计算强度得到了改善，同时给图形系统的DRAW阶段提供了最大的渲染时间。此外，响应时间也降低到少于两帧。</p>
<p><br>-----------------------------------------------------------------------------------------------------------</p>
<p>
<h3>开放场景图形多处理器模型的设计</h3>
<p><br>开放场景图形多处理器（Open Scene Graph Multi Processor）模型的设计如图所示。 </p>
<p>&#160;</p>
<p><img height=407 src="http://www.osgchina.org/projects/osgChina/wiki/img/support/paperE2C/pro9.JPG" width=654></p>
<p>图中所示的矩形块表示的是一种抽象的概念，它不是与硬件紧密结合的，也无法直接加以实现。模型的实现方法将在本文中陆续给出。红色的字体表示模型配置文档和实现时所用到的专有名词。线和箭头表示数据在系统中的流向，最终完成在显示器上的渲染。</p>
<h3><br>主线程（Main Thread）</h3>
<p><br>主线程是运行CULL预阶段的进程或线程。其内容包括了用于运行此线程的CPU。我们假设主线程在它被触发的主机上开始运行。我们使用配置管理器来启动并初始化上图的每一项内容，而主线程则运行在配置管理器所运行的主机上。</p>
<h3><br>拣选/绘制线程</h3>
<p><br>拣选（CULL）/绘制（DRAW）可以作为一个线程来执行，也可以像之前章节所述的那样，运行于不同的线程上。它可以指定两个参数：一个是系统运行的主机名称，另一个是在该主机上负责调度线程的CPU序号。如果CPU的数目为复数（不大于2），那么我们假设拣选/绘制线程可以作为不同的线程来运行。</p>
<h3><br>渲染表面</h3>
<p><br>渲染表面描述了最终渲染结果显示的屏幕空间。其中定义了<br>&#183;主机（Host）：执行显示的系统所在的主机名称；<br>&#183;显示设备（Display）：即图形子系统，此处假设在XWindow系统下使用显示设备；<br>&#183;屏幕（Screen）：此处假设在XWindow系统下使用屏幕；<br>&#183;窗口（Window）：此处假设在XWindow系统下使用窗口；<br>&#183;视口（Viewport）：视口指的是窗口内的一个矩形区域，用于安置渲染的最终结果。<br>以上所述在配置文档中均为实际的实现细节。</p>
<h3><br>配置</h3>
<p><br>上面所述的内容可以按照三个独立的环境进行配置。<br>（1）单系统映像（Single System Image）<br>如果主机域名始终保持不变，那么我们的系统将在同一个主机上进行初始化。然后我们就可以根据CPU域的定义来设置线程的参数。<br>（2）图像集群（Graphics Cluster）<br>如果CULL/DRAW阶段所在的主机域与CULL预阶段所在的主机域不同，那么在CULL/DRAW的主机上需要启动一个CULL预阶段的代理器，它用于执行CULL预阶段（另一台主机上）生成的动态数据集的同步。如果数据同步没有完成，那么这个代理器会阻塞CULL阶段的运行。<br>（3）WireGL设置<br>渲染表面包括一个&#8220;主机&#8221;域。它可以用于实现WireGL（一种集群渲染系统）的执行，以处理主机DRAW阶段传递的OpenGL协议。这种配置调度的方便之处在于，它允许上述配置之间互相&#8220;混合搭配&#8221;（mix-and-match）。例如，某个应用程序可以在三个本地图形子系统上运行其窗口输出的渲染，同时为仿真工作站（Instructor Operator Station）提供多集群的显示，并在WireGL集群系统上实现各个显示结果的最终合成。</p>
<h3><br>多处理器（MP）模型</h3>
<p><br>前面的章节叙述了两种类型的MP模型，用于实现多任务，多显示的开放场景图形系统 的实现。其不同点可以归结为CULL/DRAW作为一个线程还是分开处理的问题。如果考虑到同一主机上，存在移相的帧的调度，那么把CULL/DRAW分别进行处理可能就是不妥的。此外，忽略其带来的优越性的话，上述实现方法所引入的内存管理问题也可能导致性能降低。</p>
<p><br>不过，我们仍然会在这里依次讨论这两种模型。</p>
<h3><br>MP模型A - 数据流</h3>
<p><br>如前面的章节所述，这里我们假设一个单一的，基于主机的APP/CULL/DRAW流水线，注意这里可能存在多个CULL/DRAW过程。</p>
<p><img height=216 src="http://www.osgchina.org/projects/osgChina/wiki/img/support/paperE2C/pro13.JPG" width=608></p>
<p>这个模型中假设有一个基于主机的可微调的帧调度机制，一个单一的线程来执行CULL/DRAW。时间线A，B，C表示下一幅图中数据流的活动时间。</p>
<p><img height=263 src="http://www.osgchina.org/projects/osgChina/wiki/img/support/paperE2C/pro14.JPG" width=641></p>
<p>如前文所述，CULL预阶段负责更新场景图形中的动态数据。这些动态数据包括摄像机位置，场景中的移动物体位置，时间戳，帧数，消耗时间，以及其它一些数据管理的参量。我们假设这些数据已经被正确分配，且都是应用程序可以访问的公共量。当CULL预阶段结束时，它向CULL阶段发送一个信号，使其进入运行状态。CULL负责读取更新的动态数据，并生成内部的数据（应用程序无法访问它们），供DRAW阶段使用。这些数据是串行进行处理的。DRAW阶段将遍历这些内部数据并传递相应的OpenGL调用。</p>
<p><br>这个模型较为简练，它只需要简单地实现主机上帧发生相移（phase shifted）时调度的实时性即可。OpenSceneGraph本身已经包括了多显示系统中，对多重渲染上下文（rendering context）的支持。</p>
<p><br>当CULL/DRAW作为一个线程运行时，不需要做特殊的更改。</p>
<h3><br>MP模型B - 数据流</h3>
<p><br>下面我们讨论CULL/DRAW分别在不同线程上运行的情况。注意，下图中并没有包括图形子系统的DRAW部分。此模型假设不存在相移，且主机已经处理了与图形子系统的同步问题。</p>
<p><img height=216 src="http://www.osgchina.org/projects/osgChina/wiki/img/support/paperE2C/pro12.JPG" width=654></p>
<p>此模型的数据流程如下图所示。</p>
<p><img height=346 src="http://www.osgchina.org/projects/osgChina/wiki/img/support/paperE2C/pro15.JPG" width=593></p>
<p>上图与单线程CULL/DRAW过程图的区别在于，从CULL传递到DRAW的内部数据需要经过双缓存的过程。CULL生成的数据将被写入&#8220;缓存0&#8221;，此时DRAW从&#8220;缓存1&#8221;读取数据。到达CULL和DRAW线程的同步点时，执行两个缓存的交换。</p>
<p><br>这种方法需要编写内部数据的双重缓存，以及CULL和DRAW线程的同步位置实现代码。</p>
<h3><br>总结</h3>
<p><br>OpenSceneGraph的设计用于实现多任务，多处理器和多显示的功能。它的实现方法是先进的，并且充分利用了现有硬件环境的优势。开放场景图形（Open Scene Graph）已经在SGI的MPK上测试成功，执行结果令人满意。开放场景图形的开发者迫切希望实现一个跨 平台的，灵活、透明地执行于图形集群（graphics cluster）上的解决方案。在了解了目前的困难之后，相信一款多显示，多处理器的实时开放场景图形系统将会在不久之后诞生。<br>---------------------------------------------------------------------------------------------------------------------<br>原文参见：<a href="http://andesengineering.com/OSG_ProducerArticles/OSGMP/index.html"><u><font color=#0000ff>http://andesengineering.com/OSG_ProducerArticles/OSGMP/index.html</font></u></a></p>
</div>
<img src ="http://www.cppblog.com/zmj/aggbug/75678.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-03-05 22:51 <a href="http://www.cppblog.com/zmj/archive/2009/03/05/75678.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>.dwg</title><link>http://www.cppblog.com/zmj/archive/2009/02/25/74858.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Wed, 25 Feb 2009 01:46:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/02/25/74858.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/74858.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/02/25/74858.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/74858.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/74858.html</trackback:ping><description><![CDATA[<a href="http://en.wikipedia.org/wiki/.dwg">http://en.wikipedia.org/wiki/.dwg</a><br>
<p><strong>DWG</strong> ("drawing") is a format used for storing two and three dimensional design data and metadata. It is the native format for several <a class=mw-redirect title=CAD href="http://en.wikipedia.org/wiki/CAD"><u><font color=#0000ff>CAD</font></u></a> packages including <a title=AutoCAD href="http://en.wikipedia.org/wiki/AutoCAD"><u><font color=#0000ff>AutoCAD</font></u></a>, <a class=mw-redirect title="IntelliCAD Technology Consortium" href="http://en.wikipedia.org/wiki/IntelliCAD_Technology_Consortium"><u><font color=#0000ff>Intellicad</font></u></a><sup class="noprint Template-Fact"><span title="This claim needs references to reliable sources&nbsp;since July 2008" style="WHITE-SPACE: nowrap">[<em><a title="Wikipedia:Citation needed" href="http://en.wikipedia.org/wiki/Wikipedia:Citation_needed"><u><font color=#0000ff>citation needed</font></u></a></em>]</span></sup> (and its variants), <a title=Caddie href="http://en.wikipedia.org/wiki/Caddie"><u><font color=#0000ff>Caddie</font></u></a> and DWG is supported non-natively<sup class=reference id=cite_ref-1><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-1"><u><font color=#800080><span>[</span>2<span>]</span></font></u></a></sup> by many other <a class=mw-redirect title=CAD href="http://en.wikipedia.org/wiki/CAD"><u><font color=#0000ff>CAD</font></u></a> applications.</p>
<table class=toc id=toc summary=Contents>
    <tbody>
        <tr>
            <td>
            <div id=toctitle>
            <h2>Contents</h2>
            <span class=toctoggle>[<a class=internal id=togglelink href="javascript:toggleToc()"><u><font color=#0000ff>hide</font></u></a>]</span></div>
            <ul>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/.dwg#History_of_the_DWG_format"><u><font color=#800080><span class=tocnumber>1</span> <span class=toctext>History of the DWG format</span></font></u></a>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/.dwg#Legal_issues"><u><font color=#800080><span class=tocnumber>2</span> <span class=toctext>Legal issues</span></font></u></a>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/.dwg#Free_viewers"><u><font color=#800080><span class=tocnumber>3</span> <span class=toctext>Free viewers</span></font></u></a>
                <ul>
                    <li class=toclevel-2><a href="http://en.wikipedia.org/wiki/.dwg#Free_for_unlimited_time"><u><font color=#800080><span class=tocnumber>3.1</span> <span class=toctext>Free for unlimited time</span></font></u></a> </li>
                </ul>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/.dwg#References"><u><font color=#800080><span class=tocnumber>4</span> <span class=toctext>References</span></font></u></a>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/.dwg#See_also"><u><font color=#800080><span class=tocnumber>5</span> <span class=toctext>See also</span></font></u></a>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/.dwg#External_links"><u><font color=#800080><span class=tocnumber>6</span> <span class=toctext>External links</span></font></u></a> </li>
            </ul>
            </td>
        </tr>
    </tbody>
</table>
<script type=text/javascript>
//<![cdata[
if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); }
//]]&gt;
</script>
<p><a id=History_of_the_DWG_format name=History_of_the_DWG_format></a></p>
<h2><span class=editsection>[<a title="Edit section: History of the DWG format" href="http://en.wikipedia.org/w/index.php?title=.dwg&amp;action=edit&amp;section=1"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>History of the DWG format</span></h2>
<p>DWG (denoted by the .dwg <a title="Filename extension" href="http://en.wikipedia.org/wiki/Filename_extension"><u><font color=#0000ff>filename extension</font></u></a>) was the native <a title="File format" href="http://en.wikipedia.org/wiki/File_format"><u><font color=#0000ff>file format</font></u></a> for the Interact <a class=mw-redirect title=CAD href="http://en.wikipedia.org/wiki/CAD"><u><font color=#0000ff>CAD</font></u></a> package, developed by Mike Riddle in the late 1970s<sup class=reference id=cite_ref-2><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-2"><u><font color=#800080><span>[</span>3<span>]</span></font></u></a></sup>, and subsequently <a title="Software license" href="http://en.wikipedia.org/wiki/Software_license"><u><font color=#0000ff>licensed</font></u></a> by <a title=Autodesk href="http://en.wikipedia.org/wiki/Autodesk"><u><font color=#0000ff>Autodesk</font></u></a> in 1982 as the basis for <a title=AutoCAD href="http://en.wikipedia.org/wiki/AutoCAD"><font color=#0000ff><u>AutoCAD</u></font></a><sup class=reference id=cite_ref-3><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-3"><u><font color=#800080><span>[</span>4<span>]</span></font></u></a></sup><sup class=reference id=cite_ref-4><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-4"><u><font color=#800080><span>[</span>5<span>]</span></font></u></a></sup><sup class=reference id=cite_ref-5><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-5"><u><font color=#800080><span>[</span>6<span>]</span></font></u></a></sup>. From 1982 to 2007, Autodesk created versions of AutoCAD which wrote no less than 18 major variants of the DWG file format, none of which are publicly documented<sup class=reference id=cite_ref-6><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-6"><u><font color=#800080><span>[</span>7<span>]</span></font></u></a></sup>.</p>
<p>The DWG format is probably the most widely used format for CAD drawings. Autodesk estimates that in 1998 there were in excess of two billion DWG files in existence.<sup class=reference id=cite_ref-7><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-7"><u><font color=#800080><span>[</span>8<span>]</span></font></u></a></sup></p>
<p>There are several claims to control of the DWG format.<sup class=reference id=cite_ref-8><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-8"><u><font color=#800080><span>[</span>9<span>]</span></font></u></a></sup> It is Autodesk who designs, defines, and iterates the DWG format as the native format for their CAD applications. Autodesk sells a read/write library, called RealDWG,<sup class=reference id=cite_ref-autogenerated1_9-0><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-autogenerated1-9"><u><font color=#800080><span>[</span>10<span>]</span></font></u></a></sup> under selective licensing terms for use in non-competitive applications. Several companies<sup class="noprint Template-Fact"><span title="This claim needs references to reliable sources&nbsp;since July 2008" style="WHITE-SPACE: nowrap">[<em><a title="Wikipedia:Citation needed" href="http://en.wikipedia.org/wiki/Wikipedia:Citation_needed"><u><font color=#0000ff>citation needed</font></u></a></em>]</span></sup> have attempted to reverse engineer Autodesk's DWG format, and offer software libraries to read and write Autodesk DWG files. The most successful is Open Design Alliance,<sup class=reference id=cite_ref-10><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-10"><u><font color=#800080><span>[</span>11<span>]</span></font></u></a></sup> a non-profit consortium created in 1998 by a number of software developers (including competitors to Autodesk), released a read/write/view library called the <a class=mw-redirect title=OpenDWG href="http://en.wikipedia.org/wiki/OpenDWG"><u><font color=#0000ff>OpenDWG</font></u></a> Toolkit, which was based on the MarComp AUTODIRECT libraries.<sup class=reference id=cite_ref-11><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-11"><u><font color=#800080><span>[</span>12<span>]</span></font></u></a></sup> (ODA has since rewritten and updated that code.)<sup class="noprint Template-Fact"><span title="This claim needs references to reliable sources&nbsp;since July 2008" style="WHITE-SPACE: nowrap">[<em><a title="Wikipedia:Citation needed" href="http://en.wikipedia.org/wiki/Wikipedia:Citation_needed"><u><font color=#0000ff>citation needed</font></u></a></em>]</span></sup> There are no open-source DWG libraries currently available, and neither RealDWG<sup class=reference id=cite_ref-autogenerated1_9-1><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-autogenerated1-9"><u><font color=#800080><span>[</span>10<span>]</span></font></u></a></sup> nor DWGdirect are licensed on terms that are compatible with the <a title="GNU General Public License" href="http://en.wikipedia.org/wiki/GNU_General_Public_License"><u><font color=#0000ff>gnu gpl</font></u></a>, or similar <a class=mw-redirect title="Free software licenses" href="http://en.wikipedia.org/wiki/Free_software_licenses"><u><font color=#0000ff>free software license</font></u></a>.</p>
<p>In 1998, Autodesk added <a title="File verification" href="http://en.wikipedia.org/wiki/File_verification"><u><font color=#0000ff>file verification</font></u></a> to AutoCAD R14.01, through a function called DWGCHECK. This function was supported by an encrypted checksum and product code (called a "watermark" by Autodesk), written into DWG files created by the program.<sup class=reference id=cite_ref-12><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-12"><u><font color=#800080><span>[</span>13<span>]</span></font></u></a></sup><sup class=reference id=cite_ref-13><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-13"><u><font color=#800080><span>[</span>14<span>]</span></font></u></a></sup> In 2006, in response to Autodesk users experiencing bugs and incompatibilities in files written by reverse-engineered DWG read/write libraries, Autodesk modified AutoCAD 2007, to include "TrustedDWG technology", a function which would embed a text string within DWG files written by the program: "Autodesk DWG. This file is a Trusted DWG last saved by an Autodesk application or Autodesk licensed application."<sup class=reference id=cite_ref-14><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-14"><u><font color=#800080><span>[</span>15<span>]</span></font></u></a></sup> This helped Autodesk software users ensure that the files they were opening were created by an Autodesk, or RealDWG application, reducing risk of incompatibilities.<sup class=reference id=cite_ref-15><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-15"><u><font color=#800080><span>[</span>16<span>]</span></font></u></a></sup> AutoCAD would pop up a message, warning of potential stability problems, if a user opened a 2007 version DWG file which did not include this text string.</p>
<p>In 2008 The <a title="Free Software Foundation" href="http://en.wikipedia.org/wiki/Free_Software_Foundation"><u><font color=#0000ff>Free Software Foundation</font></u></a> asserted the need for an open replacement for the DWG format by placing 'Replacement for OpenDWG libraries'<sup class=reference id=cite_ref-16><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-16"><u><font color=#800080><span>[</span>17<span>]</span></font></u></a></sup> in 9th place on their High Priority Free Software Projects list.</p>
<p>In 2008 Autodesk and Bentley agreed on exchange of software libraries, including Autodesk RealDWG, to improve the ability to read and write the companies' respective DWG and DGN formats in mixed environments with greater fidelity. In addition, the two companies will facilitate work process interoperability between their AEC applications through supporting the reciprocal use of available Application Programming Interfaces (APIs). <sup class=reference id=cite_ref-17><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-17"><u><font color=#800080><span>[</span>18<span>]</span></font></u></a></sup></p>
<p><a id=Legal_issues name=Legal_issues><u><font color=#800080></font></u></a></p>
<h2><span class=editsection>[<a title="Edit section: Legal issues" href="http://en.wikipedia.org/w/index.php?title=.dwg&amp;action=edit&amp;section=2"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>Legal issues</span></h2>
<p>On 22 November 2006, Autodesk sued the Open Design Alliance alleging that its DWGdirect libraries infringed Autodesk's trademark for the word "Autodesk", by writing the TrustedDWG code (including the word "AutoCAD") into DWG files it created. In April 2007, the suit was dropped, with Autodesk modifying the warning message in AutoCAD 2008 (to make it more benign), and the Open Design Alliance removing support for the TrustedDWG code from its DWGdirect libraries.<sup class=reference id=cite_ref-18><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-18"><u><font color=#800080><span>[</span>19<span>]</span></font></u></a></sup></p>
<p>In 2006, Autodesk applied for a US <a title=Trademark href="http://en.wikipedia.org/wiki/Trademark"><u><font color=#0000ff>trademark</font></u></a> on "DWG", as applied to software (as distinct to its application as a file format name.) <sup class=reference id=cite_ref-19><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-19"><u><font color=#800080><span>[</span>20<span>]</span></font></u></a></sup>. In a non-final action in May, 2007, the examining attorney refused to register the mark, as it is "merely descriptive" of the use of DWG as a file format name (for which Autodesk does not claim any trademark rights.) In September, 2007, Autodesk responded, claiming that DWG has gained a "secondary meaning," separate from its use as a file format name.<sup class=reference id=cite_ref-20><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-20"><u><font color=#800080><span>[</span>21<span>]</span></font></u></a></sup>. As of June 22, 2008, Autodesk's #78852798 application received an Office Action notifying the suspension of the procedure, stating the facts are that:</p>
<table class=cquote style="MARGIN: auto; BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-COLLAPSE: collapse; BACKGROUND-COLOR: transparent; BORDER-BOTTOM-STYLE: none">
    <tbody>
        <tr>
            <td style="PADDING-RIGHT: 10px; PADDING-LEFT: 10px; FONT-WEIGHT: bold; FONT-SIZE: 35px; PADDING-BOTTOM: 10px; COLOR: #b2b7f2; PADDING-TOP: 10px; FONT-FAMILY: 'Times New Roman',serif; TEXT-ALIGN: left" vAlign=top width=20>&#8220;</td>
            <td style="PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 4px; PADDING-TOP: 4px" vAlign=top>
            <p>1. DWG is a file format.<br>2. Applicant is not the exclusive source of files with the format name DWG.<br>3. Applicant does not control the use of DWG by others, either as a trademark or as a file format name.<br>4. The submitted survey does not reflect recognition of DWG as a trademark, since no distinction was made between use as a trademark and use as the name of a file format.<br><br>Thus, the requirement for a disclaimer of DWG is continued and the Section 2(f) evidence is deemed insufficient to establish distinctiveness.</p>
            </td>
            <td style="PADDING-RIGHT: 10px; PADDING-LEFT: 10px; FONT-WEIGHT: bold; FONT-SIZE: 36px; PADDING-BOTTOM: 10px; COLOR: #b2b7f2; PADDING-TOP: 10px; FONT-FAMILY: 'Times New Roman',serif; TEXT-ALIGN: right" vAlign=bottom width=20>&#8221;</td>
        </tr>
    </tbody>
</table>
<p>As early as 1996, Autodesk has disclaimed exclusive use of the DWG mark in US trademark filings.<sup class=reference id=cite_ref-21><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-21"><u><font color=#800080><span>[</span>22<span>]</span></font></u></a></sup></p>
<p><a id=Free_viewers name=Free_viewers><u><font color=#800080></font></u></a></p>
<h2><span class=editsection>[<a title="Edit section: Free viewers" href="http://en.wikipedia.org/w/index.php?title=.dwg&amp;action=edit&amp;section=3"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>Free viewers</span></h2>
<p>There are no <a title="Open source" href="http://en.wikipedia.org/wiki/Open_source"><u><font color=#0000ff>open source</font></u></a> viewers for DWG files since the licensing of the libraries needed by lx-viewer<sup class=reference id=cite_ref-22><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_note-22"><u><font color=#800080><span>[</span>23<span>]</span></font></u></a></sup> now restricts their use to members of the <a title="Open Design Alliance" href="http://en.wikipedia.org/wiki/Open_Design_Alliance"><u><font color=#0000ff>Open Design Alliance</font></u></a>.</p>
<p><a id=Free_for_unlimited_time name=Free_for_unlimited_time></a></p>
<h3><span class=editsection>[<a title="Edit section: Free for unlimited time" href="http://en.wikipedia.org/w/index.php?title=.dwg&amp;action=edit&amp;section=4"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>Free for unlimited time</span></h3>
<ul>
    <li><a class="external text" title=http://lx-viewer.sourceforge.net/ href="http://lx-viewer.sourceforge.net/" rel=nofollow><u><font color=#0000ff>Linux Drawing Viewer / Lx-Viewer</font></u></a> only for members of the <a title="Open Design Alliance" href="http://en.wikipedia.org/wiki/Open_Design_Alliance"><u><font color=#0000ff>Open Design Alliance</font></u></a>
    <li><a class="external text" title=http://www.autodesk.com href="http://www.autodesk.com/" rel=nofollow><u><font color=#0000ff>Autodesk</font></u></a> makes <a class="external text" title=http://www.autodesk.com/designreview href="http://www.autodesk.com/designreview" rel=nofollow><u><font color=#0000ff>Design Review 2008</font></u></a> (41 MB) (cannot view DWG files natively, requires DWG TrueView) and <a class="external text" title=http://www.autodesk.com/dwgtrueview href="http://www.autodesk.com/dwgtrueview" rel=nofollow><u><font color=#0000ff>DWG TrueView 2008</font></u></a> (120 MB). For Windows XP/Vista, also 64-bit.
    <li><a class="external text" title=http://www.caddiesoftware.com/modules.php?name=Products&amp;file=pro href="http://www.caddiesoftware.com/modules.php?name=Products&amp;file=pro" rel=nofollow><u><font color=#0000ff>Caddie</font></u></a> (Free version plots and edits but does not save)
    <li><a class="external text" title=http://www.edrawingsviewer.com/pages/products/eDrawingsViewerpage.html href="http://www.edrawingsviewer.com/pages/products/eDrawingsViewerpage.html" rel=nofollow><u><font color=#0000ff>eDrawings Viewer</font></u></a> by SolidWorks, 11.8 Mb. For Windows NT/2000/XP &amp; Mac OS X 10.4+
    <li><a class="external text" title=http://www.bentley.com/en-US/Products/Bentley+View/ href="http://www.bentley.com/en-US/Products/Bentley+View/" rel=nofollow><u><font color=#0000ff>Bentley View</font></u></a> by Bentley, 58.2 Mb. For Windows 98/ME/NT/2000/XP.
    <li><a title=VariCAD href="http://en.wikipedia.org/wiki/VariCAD"><u><font color=#0000ff>VariCAD Viewer</font></u></a> is a CAD/CAM file viewer able to render DWG files. It is the only such application which runs on the <a title=Linux href="http://en.wikipedia.org/wiki/Linux"><u><font color=#0000ff>Linux</font></u></a> <a title="Operating system" href="http://en.wikipedia.org/wiki/Operating_system"><u><font color=#0000ff>operating system</font></u></a>. </li>
</ul>
<p>Note: DWG Trueview requires that a survey be filled out before download. Design Review has an optional survey.</p>
<p><a id=References name=References></a></p>
<h2><span class=editsection>[<a title="Edit section: References" href="http://en.wikipedia.org/w/index.php?title=.dwg&amp;action=edit&amp;section=5"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>References</span></h2>
<div class="references-small references-column-count references-column-count-2" style="moz-column-count: 2; column-count: 2">
<ol class=references>
    <li id=cite_note-cadMIME-0><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-cadMIME_0-0"><u><font color=#800080>^</font></u></a></strong> <cite class=web style="FONT-STYLE: normal"><a class="external text" title=http://filext.com/file-extension/DWG href="http://filext.com/file-extension/DWG" rel=nofollow><u><font color=#0000ff>"File Extension .DWG Details"</font></u></a>. <em>FILExt - The File Extension Source</em>. Computer Knowledge<span class=printonly>. <a class="external free" title=http://filext.com/file-extension/DWG href="http://filext.com/file-extension/DWG" rel=nofollow><u><font color=#0000ff>http://filext.com/file-extension/DWG</font></u></a></span><span class=reference-accessdate>. Retrieved on 2007-07-12</span>.</cite><span class=Z3988 title=ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=File+Extension+.DWG+Details&amp;rft.atitle=FILExt+-+The+File+Extension+Source&amp;rft.pub=Computer+Knowledge&amp;rft_id=http%3A%2F%2Ffilext.com%2Ffile-extension%2FDWG&amp;rfr_id=info:sid/en.wikipedia.org:.dwg><span style="DISPLAY: none">&nbsp;</span></span>
    <li id=cite_note-1><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-1"><u><font color=#800080>^</font></u></a></strong> Non-natively: i.e., the file format is supported by translation from or to another file formats.
    <li id=cite_note-2><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-2"><u><font color=#800080>^</font></u></a></strong> <a class="external text" title=http://www.retrothing.com/2007/05/mike_riddles_pr.html href="http://www.retrothing.com/2007/05/mike_riddles_pr.html" rel=nofollow><u><font color=#0000ff>Mike Riddle's Prehistoric AutoCAD - Retro Thing</font></u></a>
    <li id=cite_note-3><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-3"><u><font color=#800080>^</font></u></a></strong> <a class="external text" title=http://www.fourmilab.ch/autofile/www/subsection2_3_12_1.html#SECTION00312100000000000000 href="http://www.fourmilab.ch/autofile/www/subsection2_3_12_1.html#SECTION00312100000000000000" rel=nofollow><u><font color=#0000ff>Existing products</font></u></a>
    <li id=cite_note-4><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-4"><u><font color=#800080>^</font></u></a></strong> <a class="external text" title=http://www.fourmilab.ch/autofile/www/f/246.html href="http://www.fourmilab.ch/autofile/www/f/246.html" rel=nofollow><u><font color=#0000ff>The Autodesk File: Footnote</font></u></a>
    <li id=cite_note-5><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-5"><u><font color=#800080>^</font></u></a></strong> <a class="external text" title=http://www.digibarn.com/stories/mike-riddle/index.html href="http://www.digibarn.com/stories/mike-riddle/index.html" rel=nofollow><u><font color=#0000ff>DigiBarn Stories: Mike Riddle &amp; the Story of AutoCAD, EasyCAD, FastCAD &amp; more</font></u></a>
    <li id=cite_note-6><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-6"><u><font color=#800080>^</font></u></a></strong> <a class="external text" title=http://betaprograms.autodesk.com/history/autocad_release_history.htm href="http://betaprograms.autodesk.com/history/autocad_release_history.htm" rel=nofollow><u><font color=#0000ff>Autodesk</font></u></a>
    <li id=cite_note-7><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-7"><u><font color=#800080>^</font></u></a></strong> <cite class=web id=CITEREFAutodesk.2C_Inc. style="FONT-STYLE: normal">Autodesk, Inc.. <a class="external text" title=http://web.archive.org/web/19980119080401/http://www.autodesk.com/products/autocad/dwgoem/unplgfq2.htm href="http://web.archive.org/web/19980119080401/http://www.autodesk.com/products/autocad/dwgoem/unplgfq2.htm" rel=nofollow><u><font color=#0000ff>"DWG Unplugged"</font></u></a>. Archived from <a class="external text" title=http://www.autodesk.com/products/autocad/dwgoem/unplgfq2.htm href="http://www.autodesk.com/products/autocad/dwgoem/unplgfq2.htm" rel=nofollow><u><font color=#0000ff>the original</font></u></a> on 1998-01-19<span class=printonly>. <a class="external free" title=http://web.archive.org/web/19980119080401/http://www.autodesk.com/products/autocad/dwgoem/unplgfq2.htm href="http://web.archive.org/web/19980119080401/http://www.autodesk.com/products/autocad/dwgoem/unplgfq2.htm" rel=nofollow><u><font color=#0000ff>http://web.archive.org/web/19980119080401/http://www.autodesk.com/products/autocad/dwgoem/unplgfq2.htm</font></u></a></span>. "With over two billion AutoCAD&#174; DWG files worldwide..."</cite><span class=Z3988 title=ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=DWG+Unplugged&amp;rft.atitle=&amp;rft.aulast=Autodesk%2C+Inc.&amp;rft.au=Autodesk%2C+Inc.&amp;rft_id=http%3A%2F%2Fweb.archive.org%2Fweb%2F19980119080401%2Fhttp%3A%2F%2Fwww.autodesk.com%2Fproducts%2Fautocad%2Fdwgoem%2Funplgfq2.htm&amp;rfr_id=info:sid/en.wikipedia.org:.dwg><span style="DISPLAY: none">&nbsp;</span></span>
    <li id=cite_note-8><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-8"><u><font color=#800080>^</font></u></a></strong> <a class="external text" title=http://worldcadaccess.typepad.com/blog/2007/12/dwg-the-registr.html href="http://worldcadaccess.typepad.com/blog/2007/12/dwg-the-registr.html" rel=nofollow><u><font color=#0000ff>DWG: The Registration Attempts &amp; Successes from WorldCAD Access</font></u></a>
    <li id=cite_note-autogenerated1-9>^ <a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-autogenerated1_9-0"><sup><em><strong><u><font color=#800080>a</font></u></strong></em></sup></a> <a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-autogenerated1_9-1"><sup><em><strong><u><font color=#800080>b</font></u></strong></em></sup></a> <a class="external text" title=http://www.autodesk.com/realdwg href="http://www.autodesk.com/realdwg" rel=nofollow><u><font color=#0000ff>Autodesk - Developer Center - RealDWG</font></u></a>
    <li id=cite_note-10><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-10"><u><font color=#800080>^</font></u></a></strong> Originally, OpenDWG Alliance. <cite class=web style="FONT-STYLE: normal"><a class="external text" title=http://www.opendesign.com href="http://www.opendesign.com/" rel=nofollow><u><font color=#0000ff>"Open Design Alliance"</font></u></a><span class=printonly>. <a class="external free" title=http://www.opendesign.com href="http://www.opendesign.com/" rel=nofollow><u><font color=#0000ff>http://www.opendesign.com</font></u></a></span>.</cite><span class=Z3988 title=ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=Open+Design+Alliance&amp;rft.atitle=&amp;rft_id=http%3A%2F%2Fwww.opendesign.com&amp;rfr_id=info:sid/en.wikipedia.org:.dwg><span style="DISPLAY: none">&nbsp;</span></span>
    <li id=cite_note-11><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-11"><u><font color=#800080>^</font></u></a></strong> <a class="external free" title=http://www.opendwg.org/node/86 href="http://www.opendwg.org/node/86" rel=nofollow><u><font color=#0000ff>http://www.opendwg.org/node/86</font></u></a>
    <li id=cite_note-12><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-12"><u><font color=#800080>^</font></u></a></strong> <a class="external text" title=http://autodesk.blogs.com/between_the_lines/2005/06/how_to_tell_if_.html href="http://autodesk.blogs.com/between_the_lines/2005/06/how_to_tell_if_.html" rel=nofollow><u><font color=#0000ff>Between the Lines: How to identify some problem DWG files</font></u></a>
    <li id=cite_note-13><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-13"><u><font color=#800080>^</font></u></a></strong> <a class="external free" title=http://www.opendesign.com/dwg2007update.asp href="http://www.opendesign.com/dwg2007update.asp" rel=nofollow><u><font color=#0000ff>http://www.opendesign.com/dwg2007update.asp</font></u></a>
    <li id=cite_note-14><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-14"><u><font color=#800080>^</font></u></a></strong> This "TrustedDWG code" is encoded into DWG files in a fashion that is not humanly readable. This may be validated by using a binary editor to search a DWG file.
    <li id=cite_note-15><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-15"><u><font color=#800080>^</font></u></a></strong> Autodesk originally used the term "Trusted DWG", with an embedded space. They modified it removing the space, prior to filing a US trademark application in September, 2006. See <a class="external free" title=http://tarr.uspto.gov/servlet/tarr?regser=serial&amp;entry=77009317 href="http://tarr.uspto.gov/servlet/tarr?regser=serial&amp;entry=77009317" rel=nofollow><u><font color=#0000ff>http://tarr.uspto.gov/servlet/tarr?regser=serial&amp;entry=77009317</font></u></a>
    <li id=cite_note-16><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-16"><u><font color=#800080>^</font></u></a></strong> <a class="external text" title=http://www.fsf.org/campaigns/priority.html#opendwgreplacement href="http://www.fsf.org/campaigns/priority.html#opendwgreplacement" rel=nofollow><u><font color=#0000ff>FSF promotes need for open DWG packages</font></u></a>
    <li id=cite_note-17><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-17"><u><font color=#800080>^</font></u></a></strong> <cite class=web style="FONT-STYLE: normal"><a class="external text" title=http://pressreleases.autodesk.com/index.php?s=press_releases&amp;item=436%3C%2Ftd%3E href="http://pressreleases.autodesk.com/index.php?s=press_releases&amp;item=436%3C%2Ftd%3E" rel=nofollow><u><font color=#0000ff>"Autodesk and Bentley to Advance AEC Software Interoperability"</font></u></a>. 2008-07-08<span class=printonly>. <a class="external free" title=http://pressreleases.autodesk.com/index.php?s=press_releases&amp;item=436%3C%2Ftd%3E href="http://pressreleases.autodesk.com/index.php?s=press_releases&amp;item=436%3C%2Ftd%3E" rel=nofollow><u><font color=#0000ff>http://pressreleases.autodesk.com/index.php?s=press_releases&amp;item=436%3C%2Ftd%3E</font></u></a></span><span class=reference-accessdate>. Retrieved on 2009-01-01</span>.</cite><span class=Z3988 title=ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=bookitem&amp;rft.btitle=Autodesk+and+Bentley+to+Advance+AEC+Software+Interoperability&amp;rft.atitle=&amp;rft.date=2008-07-08&amp;rft_id=http%3A%2F%2Fpressreleases.autodesk.com%2Findex.php%3Fs%3Dpress_releases%26item%3D436%253C%252Ftd%253E&amp;rfr_id=info:sid/en.wikipedia.org:.dwg><span style="DISPLAY: none">&nbsp;</span></span>
    <li id=cite_note-18><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-18"><u><font color=#800080>^</font></u></a></strong> <a class="external text" title=http://www.cadcourt.com/Docket/206cv01637.aspx href="http://www.cadcourt.com/Docket/206cv01637.aspx" rel=nofollow><u><font color=#0000ff>Autodesk v. ODA</font></u></a>
    <li id=cite_note-19><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-19"><u><font color=#800080>^</font></u></a></strong> <a class="external text" title=http://tarr.uspto.gov/servlet/tarr?regser=serial&amp;entry=78852808 href="http://tarr.uspto.gov/servlet/tarr?regser=serial&amp;entry=78852808" rel=nofollow><u><font color=#0000ff>Latest Status Info</font></u></a>
    <li id=cite_note-20><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-20"><u><font color=#800080>^</font></u></a></strong> <a class="external text" title=http://portal.uspto.gov/external/portal/tow?SRCH=Y&amp;isSubmitted=true&amp;details=&amp;SELECT=US+Serial+No&amp;TEXT=78852798# href="http://portal.uspto.gov/external/portal/tow?SRCH=Y&amp;isSubmitted=true&amp;details=&amp;SELECT=US+Serial+No&amp;TEXT=78852798#" rel=nofollow><u><font color=#0000ff>United States Patent &amp; Trademark Office</font></u></a>
    <li id=cite_note-21><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-21"><u><font color=#800080>^</font></u></a></strong> <a class="external text" title=http://tarr.uspto.gov/servlet/tarr?regser=serial&amp;entry=75156366 href="http://tarr.uspto.gov/servlet/tarr?regser=serial&amp;entry=75156366" rel=nofollow><u><font color=#0000ff>Latest Status Info</font></u></a>
    <li id=cite_note-22><strong><a title="" href="http://en.wikipedia.org/wiki/.dwg#cite_ref-22"><u><font color=#800080>^</font></u></a></strong> <a class="external text" title=http://lx-viewer.sourceforge.net/ href="http://lx-viewer.sourceforge.net/" rel=nofollow><u><font color=#0000ff>Linux Drawing Viewer - DWG and DXF support</font></u></a> </li>
</ol>
</div>
<p><a id=See_also name=See_also></a></p>
<h2><span class=editsection>[<a title="Edit section: See also" href="http://en.wikipedia.org/w/index.php?title=.dwg&amp;action=edit&amp;section=6"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>See also</span></h2>
<ul>
    <li><a title="AutoCAD DXF" href="http://en.wikipedia.org/wiki/AutoCAD_DXF"><u><font color=#0000ff>DXF</font></u></a>, Autodesk's Drawing Exchange Format
    <li><a title=DWF href="http://en.wikipedia.org/wiki/DWF"><u><font color=#0000ff>DWF</font></u></a>, Autodesk's Design Web Format
    <li><a class=mw-redirect title=OpenDWG href="http://en.wikipedia.org/wiki/OpenDWG"><u><font color=#0000ff>OpenDWG</font></u></a>
    <li><a title=IntelliCAD href="http://en.wikipedia.org/wiki/IntelliCAD"><u><font color=#0000ff>IntelliCAD</font></u></a>
    <li><a title=AutoCAD href="http://en.wikipedia.org/wiki/AutoCAD"><u><font color=#0000ff>AutoCAD</font></u></a>
    <li><a title=Caddie href="http://en.wikipedia.org/wiki/Caddie"><u><font color=#0000ff>Caddie</font></u></a>, Low cost DWG based AEC CAD software with digital terrain modelling and photorealistic rendering
    <li><a class=mw-redirect title=CAD href="http://en.wikipedia.org/wiki/CAD"><u><font color=#0000ff>CAD</font></u></a>
    <li><a class=mw-redirect title="Comparison of CAD software" href="http://en.wikipedia.org/wiki/Comparison_of_CAD_software"><u><font color=#0000ff>Comparison of CAD software</font></u></a> includes software which supports the DWG format.
    <li><a title="Comparison of CAD, CAM and CAE file viewers" href="http://en.wikipedia.org/wiki/Comparison_of_CAD,_CAM_and_CAE_file_viewers"><u><font color=#0000ff>Comparison of CAD, CAM and CAE file viewers</font></u></a> includes viewers for the <strong class=selflink>DWG</strong> format. </li>
</ul>
<p><a id=External_links name=External_links></a></p>
<h2><span class=editsection>[<a title="Edit section: External links" href="http://en.wikipedia.org/w/index.php?title=.dwg&amp;action=edit&amp;section=7"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>External links</span></h2>
<ul>
    <li>The <a class="external text" title=http://www.opendesign.com/guestfiles href="http://www.opendesign.com/guestfiles" rel=nofollow><u><font color=#0000ff>EveryDWG File Converter</font></u></a> is a Windows application from the <a title="Open Design Alliance" href="http://en.wikipedia.org/wiki/Open_Design_Alliance"><u><font color=#0000ff>Open Design Alliance</font></u></a> that converts files back and forth between DWG and DXF formats. It also runs with <a title="Wine (software)" href="http://en.wikipedia.org/wiki/Wine_(software)"><u><font color=#0000ff>Wine</font></u></a> on <a title=Linux href="http://en.wikipedia.org/wiki/Linux"><u><font color=#0000ff>Linux</font></u></a>
    <li><a class="external text" title=http://aecnews.com/articles/1237.aspx href="http://aecnews.com/articles/1237.aspx" rel=nofollow><u><font color=#0000ff>Fighting over DWG: BricsCad and Autodesk Announcements Prove the Value of OpenDWG</font></u></a> is an article published in 2005 on the <a class="external text" title=http://aecnews.com href="http://aecnews.com/" rel=nofollow><u><font color=#0000ff>aecnews.com</font></u></a> website
    <li><a class="external text" title=http://www.autodwg.com href="http://www.autodwg.com/" rel=nofollow><u><font color=#0000ff>AutoDWG</font></u></a> has utilities for converting between the <strong class=selflink>DWG</strong>, <a title=DWF href="http://en.wikipedia.org/wiki/DWF"><u><font color=#0000ff>DWF</font></u></a>, <a class=mw-redirect title=DXF href="http://en.wikipedia.org/wiki/DXF"><u><font color=#0000ff>DXF</font></u></a>, <a class=mw-redirect title=PDF href="http://en.wikipedia.org/wiki/PDF"><u><font color=#0000ff>PDF</font></u></a> and <a title="Adobe Flash" href="http://en.wikipedia.org/wiki/Adobe_Flash"><u><font color=#0000ff>Adobe Flash</font></u></a> formats.
    <li><a class="external text" title=http://anydwg.com href="http://anydwg.com/" rel=nofollow><u><font color=#0000ff>Any DWG Converter</font></u></a> provides converters for converting <strong class=selflink>DWG</strong> to <a class=mw-redirect title=DXF href="http://en.wikipedia.org/wiki/DXF"><u><font color=#0000ff>DXF</font></u></a>, <a class=mw-redirect title=PDF href="http://en.wikipedia.org/wiki/PDF"><u><font color=#0000ff>PDF</font></u></a>, <a title=DWF href="http://en.wikipedia.org/wiki/DWF"><u><font color=#0000ff>DWF</font></u></a> and <a class=mw-redirect title=Images href="http://en.wikipedia.org/wiki/Images"><u><font color=#0000ff>Images</font></u></a> formats. </li>
</ul>
<img src ="http://www.cppblog.com/zmj/aggbug/74858.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-02-25 09:46 <a href="http://www.cppblog.com/zmj/archive/2009/02/25/74858.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>翻译：osgFX - 开发者简明手册</title><link>http://www.cppblog.com/zmj/archive/2009/02/13/73720.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Fri, 13 Feb 2009 07:08:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/02/13/73720.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/73720.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/02/13/73720.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/73720.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/73720.html</trackback:ping><description><![CDATA[LINK:&nbsp;&nbsp;&nbsp;<a href="http://cg.cnblogs.com/default.aspx?page=6&amp;paging=1">&nbsp;&nbsp;http://cg.cnblogs.com/default.aspx?page=6&amp;paging=1</a><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://bbs.vrchina.net/viewthread.php?tid=3472">http://bbs.vrchina.net/viewthread.php?tid=3472</a><br>osgFX - 开发者简明手册 <br>Marco Jez <br>2003年9月 <br><br>osgFX是一个OpenSceneGraph的附加库，是一个用于实现一致、完备、可重用的特殊效果的构架工具，其效果可以添加到OSG的节点中。它同时还包含了一系列预定义好的特殊效果。 <br><br>osgFX概述 <br>所谓&#8220;特效&#8221;指的是装载于单个对象中的一系列可视的属性和行为。要实现一个真正可用的特效，相应的特效类应当具备一个公有的接口，以修改各种配置和微调量。 <br>特效也可以被理解成是提出问题（对象应当是什么样子）与解决问题（应当设置哪些属性和其它调节量）之间的&#8220;桥梁&#8221;。从C++代码来看，特效具现了osgFX::Effect类的实例。或者说，是这个类的派生类的实例，因为osgFX::Effect直接派生自osg::Node，因此它是抽象类。 <br>对于OSG而言，特效就是一个Node节点。它与其它节点类的特性完全相同，因此可以关联到场景图形中的任意位置。 <br>特效功能图如图1所示。 <br>Effect类是一个多子节点的组节点。它使用addChild()方法和其它节点关联。 <br>在特效类中设置的可视属性将被关联到它的子节点上，与此相类似，Transform节点也会将坐标变换的信息应用到其子节点上。Effect中的各种属性不会在其子节点以外生效。 <br><br>如果用户想要将某一种特效应用到自己的图形子树上，那么需要遵循下面的步骤： <br>1、创建所需特效的实例，例如，osgFX::Scribe； <br>2、必要的话，使用特效类的方法设置特效属性； <br>3、调用Effect::addChild()方法，将图形子树与特效节点相关联； <br>4、将特效节点与场景图形关联。 <br><br>下面的例子中使用了刻线（scribe）特效： <br>osg::ref_ptr&lt;osg::Node&gt; my_node = osgDB::readNodeFile(&#8220;cow.osg&#8221;); <br>osg::ref_ptr&lt;osgFX::Scribe&gt; scribe_fx = new osgFX::Scribe; <br>scribe_fx-&gt;addChild(my_node.get()); <br>scribe_fx-&gt;setEnabled(true); <br>root-&gt;addChild(scribe_fx.get()); <br>代码执行的结果如图2所示。 <br><br>深入学习：技法和通道 <br>技法就是实现特效的某一种可能方法。 <br>由于图形硬件设备种类繁多，OpenGL也在不断扩展，因此不太可能用一种通用的方法来实现复杂的效果：针对不同的硬件和OpenGL环境，用户需要采用不同的实现手段来实现某个特效。 <br>一种特效的产生往往可以采用一种或几种技法，每一种技法都采用不同的方式来尝试实现相同的效果。 <br>缺省情况下，Effect类使用私有的StateAttribute对象来实时演算和验证各种技法，并选择最好的一种。 <br>特效的开发者可以自行定义各种技法的优先级，从而要求OSG首先验证用户所选的技法。 <br>Effect类会选择在实时的所有活动渲染设备中，可通过验证的优先级最高的技法，以为己用。 <br>如果需要的话，用户可以在任何时刻重载这一缺省特性。 <br>Effect类的技法功能图表如图3所示。 <br><br>多通道渲染的意思是，每次都使用不同的可视属性，多次绘制同一对象后，合并所有通道获得的最终图像。 <br>某些技法可能需要不止一个通道来实现所需的输出结果。 <br>技法类为每个渲染通道都创建一个StateSet对象，然后交由osgFX管理多通道的渲染工作。 <br>Effect类的通道功能图表如图4所示。 <br><br>扩展osgFX <br>创建一个新的特效的基本步骤如下。 <br>1、特效都是从osgFX::Effect派生而来的，因此用户可以自由创建自己的派生类，例如命名它为TestFx。 <br>2、具现抽象方法，例如effectName()，effectDescription()等，可能需要用到META_Effect宏。 <br>3、向系统注册新的特效类，即创建一个Registry::Proxy的静态实例： <br>osgFX::Registry::Proxy proxy(new TestFx); <br>4、具现保护成员中的抽象方法define_techniques()，以便创建所需的特效技法。 <br>为了实现某个技法，用户需要编写一个继承自osgFX::Technique的类；且这个类应当是私有的。 <br>在用户特效类的define_techniques()方法中，创建上述用户技法类的实例，并使用Effect::addTechnique()按照优先级降序的顺序将其添加到特效类中。 <br>为新建的技法提供一个验证手段。最简单（但不是最灵活的）的方法是重载Technique::getRequiredExtensions()方法，并指定这个技法所需的OpenGL扩展函数。 <br>具现Technique::define_passes()方法，以便创建渲染通道。 <br>渲染通道的内部实现，是将其作为一个Group对象与一个StateSet相关联。特效类的子节点在运行时将自动被添加到通道节点上。 <br>技法类的define_passes()方法为每个渲染通道创建了一个StateSet对象，并调用Technique::addPass()将其添加到技法类中。通道节点将自动生成并连接到渲染状态之上。 <br><br>以下为创建一个特效类所需的基本代码： <br>Class TestFX (public) <br>{ <br>&#8230;&#8230; <br>META_Effect(&#8230;&#8230;); <br>bool define_techniques() <br>{ <br>addTechnique(new FirstTechnique); <br>// 也可以继续添加别的技法实例。 <br>} <br>&#8230;&#8230; <br>} <br><br>Class FirstTechnique (private) <br>{ <br>&#8230;&#8230; <br>void getRequiredExtensions(&#8230;&#8230;) const <br>{ <br>// 指定所需的GL扩展功能。 <br>} <br>void define_passes() <br>{ <br>osg::ref_ptr&lt;osg::StateSet&gt; ss1 = new osg::StateSet; <br>// 添加渲染属性到ss1之后&#8230;&#8230; <br>addPass(ss1.get()); <br><br>osg::ref_ptr&lt;osg::StateSet&gt; ss2 = new osg::StateSet; <br>// 添加渲染属性到ss2之后&#8230;&#8230; <br>addPass(ss2.get()); <br>} <br>&#8230;&#8230; <br>} <br><br>总结： <br>1、继承osgFX::Effect并创建特效类（例如TestFx），为其添加名字和描述信息，并使用注册代理（registry proxy）注册到系统中； <br>2、为用户所需的每个技法创建私有类，并定义它们的验证手段； <br>3、在TestFx::define_techniques()中创建一个技法类的实例，并调用addTechnique()将其添加到特效中； <br>4、在每个技法类的define_passes()方法中，创建一个或多个StateSet对象（每个渲染通道创建一个），并调用addPass()将其添加到技法中。例子程序 <br><br>osgfxbrowser的效果如图5~8所示。对于目前已提供的特效，简介如下： <br><br>刻线（Scribe） <br>这是一个双通道的特效；第一个通道以通常的方式渲染图形，而第二个通道使用线框模式，用户设置好光照和材质之后，即可使用指定的颜色进行渲染。这个特效中使用了PolygonOffset渲染属性类来避免多边形斑驳（Z-fighting）的现象，它所需的OpenGL版本至少为1.1。各向异性光照（Anisotropic Lighting） <br>这种特效使用单一通道，它使用了一种各向异性的光照来替代OpenGL的标准光照模型。几何体顶点的颜色在这里不是直接进行计算的，而是纹理映射到用户指定的光照图板的结果。这里需要使用顶点着色器（vertex program）来计算纹理坐标S和T的值：S = N &#183; H；T = N &#183; L。（其中的数学运算为点乘）这里N表示顶点的法线，L表示光到顶点的向量，H表示中间向量。这种特效很好地演示了State::getInitialViewMatrix()方法的使用，它可以直接获取视口的初始矩阵并实现直接与视口相关的特效，而不需要任何假借的工作。 <br>该特效需要ARB_vertex_program扩展的支持。 <br><br>卡通渲染（Cartoon） <br>这种特效实现了一种名为卡通着色（Cel-Shading）的技法，从而产生一种卡通式的（非真实感的）的渲染效果。它需要两个通道支持；第一个用于绘制实体表面，第二个用于绘制轮廓线。该特效需要使用顶点着色器来设置纹理坐标，以便在运行时生成的纹理单元0上实现一种尖锐的光照效果。 <br>该特效需要ARB_vertex_program扩展或者OpenGL着色语言的支持。 <br><br>基于立方映射图的镜面高光（Cubemap-based Specular Highlights） <br>这种特效在片断层级（fragment level）上（而不是OpenGL通常的顶点层级）应用了镜面高光，它使用了立方映射图和反射纹理生成（reflective texgen）的技术。首先要计算出纹理矩阵以实现立方映射图的自动旋转；这样无论从观察的方向和光照位置上来说，镜面光的效果都将是始终不变的。用户可以选择使用何种光照来计算纹理矩阵。 <br>该特效需要GL_ARB_texture_env_add扩展以及任意一种立方映射图扩展（GL_EXT_texture_cube_map，GL_ARB_texture_cube_map，或者OpenGL 1.3）的支持。 <br><br>凹凸贴图（Bump Mapping） <br>这种特效可以创建一种凹凸不平的表面效果。其子节点必须使用两种纹理，其一是漫反射颜色，另一个是法线贴图（可以使用nVIDIA的法线贴图生成器或者其它工具，根据高度图自动生成）。此外，还需要创建正切空间（tangent-space）的基向量并将其关联到每个Geometry几何体上；这一步骤可以调用BumpMapping::prepareChildren()方法来迅速完成。注意Geometry对象的漫反射颜色和法线贴图纹理都必须提前定义好对应的UV贴图。 <br>该特效推荐使用一种运用了ARB顶点和片断着色器的技法，另外还定义了一种不使用片断着色器的技法。后者无法处理环境和镜面组件的运算，因此在运行时很受限制。
<img src ="http://www.cppblog.com/zmj/aggbug/73720.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-02-13 15:08 <a href="http://www.cppblog.com/zmj/archive/2009/02/13/73720.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>3D中的方位和角位移的C++实现 </title><link>http://www.cppblog.com/zmj/archive/2009/01/20/72372.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Tue, 20 Jan 2009 06:49:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/01/20/72372.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/72372.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/01/20/72372.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/72372.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/72372.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 3D中的方位和角位移的C++实现（1） 　数学理论基础请参阅3D中的方位和角位移。处理变换是一件非常令人头疼的事，矩阵更是棘手。如果你曾经编写过关于矩阵的代码并且没有用设计良好的类，你会发现经常要处理负号、转置矩阵或翻转连接顺序以使其能正常工作。下面这几个类正是为了消除在编程中经常遇到的这类问题而设计的。例如，很少需要直接访问矩阵或四元数中的元素，因此特意限制了可用操作的数目以...&nbsp;&nbsp;<a href='http://www.cppblog.com/zmj/archive/2009/01/20/72372.html'>阅读全文</a><img src ="http://www.cppblog.com/zmj/aggbug/72372.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-01-20 14:49 <a href="http://www.cppblog.com/zmj/archive/2009/01/20/72372.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Simulating Cloth for 3D Games</title><link>http://www.cppblog.com/zmj/archive/2009/01/13/71893.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Tue, 13 Jan 2009 06:28:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2009/01/13/71893.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/71893.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2009/01/13/71893.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/71893.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/71893.html</trackback:ping><description><![CDATA[<a href="http://software.intel.com/en-us/articles/simulating-cloth-for-3d-games/">http://software.intel.com/en-us/articles/simulating-cloth-for-3d-games/</a><br>
<div class=sectionHeading>Introduction</div>
<p>We all live in the real world where things behave according to the laws of physics that we learned about in high school or college. Because of this, we're all expert critics about what looks right or more often wrong in many 3D games. We complain when a character's feet slide across the ground or when we can pick out the repeating pattern in the animation of a flag blowing in the wind. Adding realistic physical simulation to a game to improve these effects can be a giant effort and the rewards for the time invested haven't proven to be worthwhile, yet.<br><br>Often, though, it's possible to incrementally add elements to a game that can provide increased realism without extremely high risks. Improving the animation behavior of simple cloth objects like flags in the wind and billowing sails is one area where realism increases without the 18 month development risk of introducing a full-fledged physics engine. Not that I don't want to see more games with all-out physics happening, but I think there are some simple things that can be done with cloth objects in the meantime to improve realism and save modelers time.<br><br>At the Game Developers Conference in March 2000, I presented my implementation of two techniques for simulating cloth. I was pointed to another, more recent, technique by someone who attended the class. In this paper I'll recap what I presented about at the conference and include information about the newer technique. Hopefully you'll be able to take the ideas I present here and add some level of support for cloth simulation into your title.<br><br><strong>2. Background</strong><br><br>Various researchers have come up with different techniques for simulating cloth and other deformable surfaces. The technique that is used by all three methods presented here, and by far the most common, is the idea of a mass-spring system. Simply put, a continuous cloth surface is discretized into a finite number of particles much like a sphere is divided into a group of vertices and triangles for drawing with 3D hardware. The particles are then connected in an orderly fashion with springs. Each particle is connected with springs to its four neighbors along both the horizontal and vertical axes. These springs are called "stretch'" springs because they prevent the cloth from stretching too much. Additional springs are added from each particle to its four neighbors along the diagonal directions. These "shear" springs resist any shearing movement of the cloth. Finally, each spring is connected to the four neighbors along both the horizontal and vertical axes but skipping over the closest particles. These springs are called "bend" springs and prevent the cloth from folding in on itself too easily.<br><br>.<img height=264 alt="" src="http://software.intel.com/file/3652" width=315 border=0><br><em>Figure 1 - Stretch (blue), Shear (green), and Bend (red) springs</em><br><br><strong>Figure 1</strong> shows a representation of a mass-spring system using the previously mentioned stretch, shear, and bend springs. When rendering this surface, the masses and springs themselves are not typically drawn but are used to generate triangle vertices. The nature of the cloth simulation problem involves solving for the positions of the particles at each frame of a simulation. The positions are affected by the springs keeping the particles together as well as by external forces acting on the particles like gravity, wind, or forces due to collisions with other objects or the cloth with itself.<br><br>In the next section we'll look at the problem that we're trying to solve to realistically animate a cloth patch. Much of this will be very familiar to anyone who has already experimented with cloth simulation. Feel free to skip to Section 4 if you just want details on the various implementations I tried.</p>
<!--page break-->
<hr>
<div class=sectionHeading>The Cloth Problem</div>
<p>Like any other physical simulation problem, we ultimately want to find new positions and velocities for objects (cloth particles in our case) using Newton's classic law: <img height=22 alt="" src="http://software.intel.com/file/3665" width=53 border=0> or more directly <img height=25 alt="" src="http://software.intel.com/file/3666" width=40 border=0>. This says that we can find the acceleration (<img height=18 alt="" src="http://software.intel.com/file/3667" width=13 border=0>) on a particle by taking the total force (<img height=21 alt="" src="http://software.intel.com/file/3668" width=17 border=0>) acting on the particle and dividing by the mass (<em>m</em>) of the particle. Using Newton's laws of motion, we can solve the differential equations <img height=24 alt="" src="http://software.intel.com/file/3669" width=42 border=0>and <img height=25 alt="" src="http://software.intel.com/file/3670" width=41 border=0>to find the velocity (<img height=18 alt="" src="http://software.intel.com/file/3671" width=13 border=0>) and position (<img height=21 alt="" src="http://software.intel.com/file/3672" width=16 border=0>) of the particle. For simple forces, it may be possible to analytically solve these equations, but realistically, we'll need to do numerical integration of the acceleration to find new velocities and integrate those to find the new positions. In Sections 3.1 through 3.3 we'll take a high level look at explicit integration, implicit integration, and adding post-integration deformation constraints for solving the equations of motion for cloth particles. Many excellent in-depth articles have been written about various aspects of physics simulation including cloth simulation. I'd highly recommend the articles by Jeff Lander<sup style="FONT-SIZE: 11px">i, ii</sup>, and Chris Hecker<sup style="FONT-SIZE: 11px">iii</sup> if you haven't already read them.<br><br><br><strong>3.1. Explicit Integration</strong><br><br>One of the simplest ways to numerically integrate the differential equations of motion is to use the tried-and-true method known as Euler's method. For a given initial position, <img height=24 alt="" src="http://software.intel.com/file/3673" width=20 border=0>, and velocity, <img height=24 alt="" src="http://softwarecommunity.intel.com/userfiles/en-US/image/teamsite/18005_image89.gif" width=16 border=0>, at time <img height=24 alt="" src="http://software.intel.com/file/3675" width=14 border=0>and a time step, <img height=18 alt="" src="http://software.intel.com/file/3676" width=20 border=0>, we can calculate a new position, <img height=22 alt="" src="http://software.intel.com/file/3677" width=18 border=0>, and velocity, <img height=22 alt="" src="http://software.intel.com/file/3678" width=14 border=0>, using a Taylor series expansion of the above differential equations and then dropping some terms (which may introduce error, <img height=14 alt="" src="http://software.intel.com/file/3679" width=12 border=0>):<br><br><img height=26 alt="" src="http://software.intel.com/file/3680" width=189 border=0> (1.1)<br><br><img height=28 alt="" src="http://software.intel.com/file/3681" width=200 border=0> (1.2)<br><br>Unfortunately, Euler's method takes no notice of quickly changing derivatives and so does not work very well for the stiff differential equations that result from the strong springs connecting cloth particles. Provot<sup style="FONT-SIZE: 11px">iv</sup> introduced one method to overcome this problem and Desbrun<sup style="FONT-SIZE: 11px">v</sup> later expanded on this. We'll examine these in more depth in Section 3.3. Until then, let's look at implicit integration.<br><br><strong>3.2. Implicit Integration</strong><br><br>Given the problem with Euler's method for stiff differential equations and knowing that the problem still exists for other similar "explicit" integration methods, some researchers have worked with what are known as "implicit" integration methods. Baraff and Witkin<sup style="FONT-SIZE: 11px">vi</sup> presented a thorough examination of using implicit integration methods for the cloth problem. Implicit integration sets up a system of equations and then solves for a solution such that the derivatives are consistent both at the beginning and the end of the time step. In essence, rather than looking at the acceleration at the beginning of the time step, it finds an acceleration at the end of the time step that would point back to the initial position and velocity.<br><br>The formulation I'm using here is from the Baraff and Witkin paper except I've used <img height=21 alt="" src="http://software.intel.com/file/3672" width=16 border=0> to represent the position of the particles rather than <img height=18 alt="" src="http://software.intel.com/file/3682" width=13 border=0>. The system of equations is<br><br><img height=53 alt="" src="http://software.intel.com/file/3683" width=213 border=0> (1.3)<br><br>Here M<sup style="FONT-SIZE: 11px">-1</sup> is the inverse of a matrix with the mass of the individual particles along the diagonal. If all the particles are the same mass, we can just divide by the scalar mass, <em>m</em>. Like was done in the explicit case, we use a Taylor series expansion of the differential equations to form the approximating discrete system:<br><br><img height=50 alt="" src="http://software.intel.com/file/3684" width=238 border=0> (1.4)<br><br>The top row of this system is trivial to find once we've found the bottom row, so by plugging the top row into the bottom row, we get the linear system:<br><br><img height=28 alt="" src="http://software.intel.com/file/3653" width=257 border=0><br><br><strong>3.3. Deformation Constraints</strong><br><br>When using either explicit integration or implicit integration to determine new positions and velocities for the cloth particles, it is possible to further improve upon the solution using deformation constraints after the integration process. Provot proposed this method in his paper and Desbrun further combined this with a partial implicit integration technique to achieve good performance with large time steps.<br><br>The technique is very simple and easy to implement. Once an integration of positions and velocities has been done, a correction is applied iteratively. The correction is formed by assuming that the particles moved in the correct direction but that they may have moved too far. Particles are then pulled together along the correct direction until they are within the limits of the deformation constraints. The process can be applied multiple times until convergence is reached within some tolerance or there is no time left for the process to be able to maintain a given frame rate. Using deformation constraints can take a normally unstable system and stabilize it quite well. I've found that using a fixed number of iterations typically works well.<br><br>Now that we've taken a brief look at integration techniques and how to improve upon the results, let's have a look at the implementations I did. The source code for my implementations can be downloaded and used in your application or just examined for ideas.</p>
<p><a href="http://www.intel.com/cd/ids/developer/asmo-na/eng/41050.htm" target=_blank><u><font color=#0000ff>Click here to download source code</font></u></a> (366kb zip)</p>
<!--page break-->
<hr>
<div class=sectionHeading>Implementation</div>
<p>I tried implementing a simple cloth patch using three techniques: explicit integration with deformation constraints, implicit integration, and semi-implicit integration with deformation constraints. The sample application depicted in <strong>Figure 2</strong> shows a simple cloth patch that can be suspended by any or all of its four corners.<br><br><img height=251 alt="" src="http://software.intel.com/file/3662" width=335 border=0><br><em>Figure 2 - Cloth Sample Application</em><br><br>Gravity pulls downward on the particles and stretch, shear, and bend springs keep the particles together as a cloth patch. A wireframe version of the cloth is shown in <strong>Figure 3</strong>. Two triangles are produced for every four particles forming a grid square.<br><br><img height=320 alt="" src="http://software.intel.com/file/3663" width=427 border=0><br><em>Figure 3 - Wireframe view of cloth patch</em><br><br>I'll discuss the implementation specifics here with a simple analysis of the results in Section 5.<br><a name=basics></a><br><br><strong>4.1. Basics</strong><br><br>For the three implementations, I shared a lot of code. Everything is written in C++ with a rough attempt at modularizing the cloth specific code into a set of physics/cloth related classes. I used a 3D application wizard to create the framework and then added the cloth specific stuff. Information about the 3D AppWizard, for those interested, can be found in the article <a href="http://software.intel.com/en-us/articles/creating-a-custom-appwizard-for-3d-development"><u><font color=#0000ff>Creating A Custom Appwizard for 3D Development</font></u></a>.<br><br>When wading through the source code, you'll find that there are quite a few files. Most of the files that pertain to the cloth simulation are in the files that begin with "Physics_". In addition to these I also created a "ClothObject" class with corresponding filenames which is instantiated and manipulated from the "ClothSample" class.<br><br>I experimented with performance with both single-precision and double-precision floating point numbers. To easily change this, I created a <em>typedef</em> in Physics.h for a "Physics_t" type that is used anywhere you would normally use "float" or "double". I found (expectedly) that performance slowed when using double-precision numbers and I didn't notice any improved stability. Your mileage may vary especially if you add support for collision detection and response.</p>
<!--page break-->
<hr>
<div class=sectionHeading>Mass-Spring System</div>
<p>The mass-spring system is implemented as a particle system. This basically means that I don't do any handling of torque or moments of inertia. Within the <em>Physics_ParticleSystem</em> class, I allocate necessary information for the various integration schemes and I allocate large vectors for holding the positions, velocities, forces, etc. of the individual particles. I maintain a linked list of forces that act on the particles. With this implementation there's no way of dynamically changing the number of particles in the system (although forces can be added and removed). For the implicit integration scheme, I allocate some sparse, symmetric matrices to hold the derivatives of the forces and temporary results. For the semi-implicit scheme, I allocate some dense, symmetric matrices to hold the Hessian matrix and inverse matrix, W, for filtering the linear component of the forces.<br><br>Regardless of which integration scheme is used we'll use the same overall update algorithm. Pseudo-code for updating the cloth is shown in <strong>Figure 4</strong>. This routine, <em>Update</em>, is called once per frame and in my implementation uses a fixed time step. Ideally, you'll want to use a variable time step. Remember that doing so can have an impact on performance, especially in the semi-implicit implementation of Desbrun's algorithm because a matrix inversion would be done at each frame where the step size changed. Clearing the accumulators is a no-brainer so I'll just dive into the other three steps of the algorithm in further detail.<br><br><strong>4.2.1. Calculating forces and derivatives</strong><br><br>My implementation only has two types of forces, a spring force and a gravity force. Both are derived from a <em>Physics_Force</em> base class. During the update routine of the particle system, each force is enumerated and told to apply itself to the fo rce and force derivative accumulators. Force derivatives are only needed when using the implicit integration scheme (actually, they're needed for the semi-implicit integration scheme, but are handled differently).<br><br>The gravity force is simple and just adds a constant (the direction and magnitude of gravity: 0,-9.8,0 in my case) to the "external" force accumulator. I maintain separate "internal" and "external" accumulators to support the split integration scheme proposed by Desbrun. The downside to this is that I would really need a separate spring force for handling user supplied force to the cloth because the spring force as implemented assumes that it is acting internally to the cloth only.<br><br>The spring force is a simple, linear spring with damping. I derived the force from a condition function as was done in the Baraff/Witkin paper. Unlike the Baraff/Witkin paper's use of separate condition functions for stretching, shearing and bending on a per triangle basis, I use just one condition function for a linear spring connecting two particles. The condition function I used was <img height=26 alt="" src="http://software.intel.com/file/3658" width=146 border=0>where <em>p</em><sub>0</sub> and <em>p</em><sub>1</sub> are the two particles affected by the spring and <em>dist</em> is the rest distance of the spring. Forces were calculated as derivatives of the energy function formed by the condition function: <img height=29 alt="" src="http://software.intel.com/file/3659" width=116 border=0>.<br>The Desbrun paper uses the time step and spring constant to apply damping but I apply damping as derived by the Baraff/Witkin paper. The damping constant I use is a small multiple of the spring constant.<br><br><strong>4.2.2. Integrating forces and updating positions and velocities</strong><br><br>By far, the trickiest code to understand is that for integrating the forces to determine new velocities and positions for the cloth particles. We'll start with the simplest case, the explicit integration scheme with deformation constraints.</p>
<p><strong>4.2.2.1. Explicit integration with deformation constraints</strong></p>
<p>Using explicit Euler integration is a straightforward application of equations. The acceleration is found by dividing the force for each particle by the particles mass (actually, we store 1/mass and then do a multiplication). Then, the acceleration is multiplied by the time step to update the velocities. The new velocities are multiplied by the time step to update the positions. The new positions are actually stored in a temporary location so that the deformation constraints can be applied. To apply the deformation constraints, each spring force is asked to "fixup" its associated particles. Basically, if the length of the spring has exceeded a maximum value (determined as a multiple of the rest length of the spring), then the particles are pulled closer together. Finally, we take the fixed-up temporary positions, subtract the starting positions and divide by the time step to get the actual velocities needed to achieve the end state. Then we copy the temporary positions to the actual positions vector and we're ready to render.</p>
<p><strong>4.2.2.2. Implicit integration</strong></p>
<p>At the other end of the spectrum in terms of difficulty is doing full implicit integration using equation (1.6). For this, we form a large, linear system of equations and then use an iterative solution method called the pre-conditioned conjugate gradient method. The Baraff/Witkin paper goes into details on this and explains the use of a filtering process for constraining particles. In my implementation, I inlined the filtering function everywhere it was used. I won't go into the ugly details of the conjugate gradient method, but I will explain briefly some of the tricks I used to improve performance. For one, the large sparse matrices that get formed are all symmetric, so I cut storage requirements almost in half by only storing the upper triangle of the matrices. In doing so, I had to think carefully about the matrix-vector multiply routines. Secondly, in cases where we would actually be using a matrix but one that only had non-zero elements along the diagonal, I just stored the matrix as a vector. I added some specialized routines to the <em>Physics_LargeVector</em> class for "inverting" the vector which just replaced each element with one over the element. Finally, I didn't do any dynamic allocation of the temporary sparse matrices because the overhead would have been too severe. So I ended up keeping some temporary matrices as private members of the <em>Physics_ParticleSystem</em> class.</p>
<p><strong>4.2.2.3. Semi-implicit integration with deformation constraints</strong></p>
<p>The last integration method I tried was a semi-implicit method as described by Desbrun. Desbrun divided the internal forces acting on the cloth into linear components and non-linear components. The linear components could then be easily integrated using implicit integration without having to solve a linear system. Instead, a large constant matrix is inverted once and then just a matrix multiply is required to do the integration. The non-linear components are approximated as torque changes on a global scale when using his technique. In addition, deformation constraints are used to prevent overly large stretching. As mentioned previously, I created a <em>Physics_SymmetricMatrix</em> class for storing the Hessian matrix of the linear portion of the internal cloth forces. The Hessian matrix is used in place of <img height=26 alt="" src="http://software.intel.com/file/3660" width=18 border=0>from equation (1.6) and because of the linear nature imposed by Desbrun's splitting of the forces, <img height=25 alt="" src="http://software.intel.com/file/3660" width=18 border=0>is zero. Due to the splitting of the problem into a linear and non-linear portion, we don't need to solve a linear system as we did in the Baraff/Witkin implementation. Rather, we can just "filter" the internal forces by multiplying by the inverse matrix <img height=26 alt="" src="http://software.intel.com/file/3661" width=78 border=0>where <em>I</em> is the identity matrix, <em>dt</em> is the time step, <em>m</em> is the mass of a particle, and <em>H</em> is the Hessian matrix. We then need to compensate for errors in torque introduced by the splitting. I'd refer the reader to the Desbrun article for more information about the technique. As in the explicit integration scheme, once we've integrated the forces and obtained new velocities and positions (again stored in a temporary vector) we can apply the deformation constraints. See above for details.</p>
<!--page break-->
<hr>
<div class=sectionHeading>Extra Tidbits</div>
<p>While the above explanations of the update loops give the core information about how the cloth patch animates, there is some secondary information that is useful to know when looking through the code. I'll go through several different areas and unless otherwise noted, the text refers to all three update methodologies.<br><br>Each particle in the mesh can belong to at most six triangles. I generate a normal for each triangle and then add these and normalize to get the normal at each particle. This process doesn't seem to consume much time, but if every processor cycle is critical, you can choose to average less than six normals.<br><br>For the semi-implicit implemenation, I need to form the Hessian matrix that corresponds to the way the particles are connected by the springs. I do this once, upfront, because the spring constants don't change and so the Hessian matrix doesn't change. For each spring, it's <em>Prepare Matrices</em> method is called. This method sets the appropriate elements in the Hessian matrix that the spring affects. <em>Prepare Matrices</em> also is called to "touch" elements of the sparse matrices that will be used by the implicit implementation. This enables the memory allocation to happen only once.<br><br>I incorporated a <em>very</em> simplistic collision detection for the cloth with the ground plane. If you use the number keys (0,1,2,3) to toggle constraints on the corners, you can get the cloth to move downward. When it hits the floor, I stop all movement in the downward direction and fix the particles to the plane of the floor. There's no friction, so it's not very realistic. For the implicit implementation, I imposed constraints and particle adjustments as describe by Baraff and Witkin, however things tend to jump unstably as the cloth hits the floor. It's possible a smaller time step is needed but I didn't investigate further.<br><br>Both the explicit and semi-implicit routines use particles with infinite mass to constrain them. Because of this, the <em>Fixup</em> routine for applying the deformation constraints looks at the inverse mass of each particle and only moves the particle if its mass is non-infinite (which means the inverse mass is non-zero).<br><br>While running the demo the following keys affect the behavior of the cloth:</p>
<ul>
    <li>P - Pauses the animation of the cloth
    <li>W - Toggles wireframe so you can see the triangles
    <li>X - Exits the demo
    <li>F - Toggles to fullscreen mode
    <li>H - Brings up a help menu showing these keys
    <li>R - Resets the cloth to its initial position - horizontal to the floor and a bit above it
    <li>0, 1, 2, 3 - Toggles constraints for the four corners of the cloth </li>
</ul>
<p>&nbsp;</p>
<p>Finally, the configuration of the cloth simulation (number of particles, strength of springs, time step, etc.) is contained in <em>Cloth.ini</em>. I added comments for each entry in the file so look there if you want to play around with things. By default the integration method is explicit.</p>
<!--page break-->
<hr>
<div class=sectionHeading>Which Method is Best?</div>
<p>Since I've covered three different techniques for updating the cloth, I'm sure you're wondering what the best m ethod is. Well, for the case I tried the explicit implementation is clearly the fastest as the results in <strong>Figure 5</strong> show. This table was generated from running the sample code on an Intel&#174; Pentium&#174; III processor-based system running at 600 Mhz with Microsoft Windows* 98 and DirectX* 7.0. The graphics card was a Matrox* G-400 with the resolution set to 1024x768 @ 60Hz and the color depth set to 16-bit. I used a fixed time step of 0.02 seconds which would be appropriate for a frame rate of 50 frames per second.<br><br><img height=198 alt="" src="http://software.intel.com/file/3664" width=335 border=0><br><em>Figure 5 - Performance results for various cloth sizes</em><br><br>Some interesting things to note about the performance that isn't shown in the figure are:</p>
<ul>
    <li>Initialization time for the implicit method can be fairly large as the sparse matrices are allocated.
    <li>Initialization time for the semi-implicit method can be considerably larger than that for the implicit method because a large matrix (1089x1089 in the 33x33 patch case) needs to be inverted. The same amount of computation would be required any time the time step changed.
    <li>The implicit method is the only one that uses the actual spring strengths to hold the cloth together. Because of this, it may be necessary to increase the spring constants when using the implicit method.
    <li>Desbrun claimed being able to vary the strength of the spring constant by a factor of 10<sup style="FONT-SIZE: 11px">6</sup> without causing instability. I was only able to achieve a factor of 10<sup style="FONT-SIZE: 11px">5</sup> which makes me think that other simulation specifics (like particle masses) may have been different.
    <li>For the explicit and semi-implicit cases I needed to make the mass of the particles fairly large to achieve stability with a time step of 0.02 seconds. This could cause the cloth to have unusual properties if incorporated with other physics simulation involving inertia and collisions. In your game you may want to maintain separate masses for the updating of the cloth and the interaction of the cloth with the world.
    <li>Because I haven't implemented real collision detection it's uncertain how collision with other objects will affect the stability and hence the performance of the various implementations.
    <li>I maintained a linked list of spring forces that needed to be applied and then have their deformation constraints applied. Performance could be improved by storing these in an array that could be more quickly walked through. </li>
</ul>
<p>&nbsp;</p>
<p>Even though explicit integration seems to work best for my test case, the benefits of implicit integration should not be overlooked. Implicit integration can stably handle extremely large forces without blowing up. Explicit integration schemes cannot make such a claim. And while deformation constraints can be used with explicit integration to provide realistic looking cloth, implicit integration would have to be used if a more physically accurate simulation of cloth was required.</p>
<!--page break-->
<hr>
<div class=sectionHeading>Conclusion</div>
<p>I breezed through some of the math and background with the hope that the accompanying source code would be even more valuable than a theoretical explanation which can be found in other more academic papers. Feel fr ee to take parts of the code and incorporate it in your title. There's a lot more that can be done than what I've presented here. Start simple and add a wind force and remember that it should affect triangles created by the particles not the particles themselves. Or try adding a user controllable mouse force to drag the cloth around. Depending on whether you want to use cloth simulation for eye candy in your game (like flags blowing in the wind or the sail on a ship) or as a key element, you'll probably need collision detection at some point. Keep in mind that cloth-cloth collision detection can be difficult to do efficiently.<br><br>Well, I've taken a brief look at real-time simulation of realistic looking cloth and hopefully have presented something of use to you in your game development. I look forward to seeing new games that incorporate various aspects of physics simulation with cloth simulation as one of them.</p>
<p><a href="http://www.intel.com/cd/ids/developer/asmo-na/eng/41050.htm" target=_blank><u><font color=#0000ff>Click here to download source code</font></u></a> (366kb zip)</p>
<!--page break-->
<hr>
<div class=sectionHeading>References</div>
<p>i Jeff Lander. Lone Game Developer Battles Physics Simulator. On <a href="http://www.gamasutra.com/" target=_blank><u><font color=#0000ff>www.gamasutra.com</font></u></a>*, February 2000.<br><br>ii Jeff Lander. Graphic Content: Devil in the Blue-Faceted Dress: Real-time Cloth Animation. In <em>Game Developer Magazine</em>. May 1999.<br><br>iii Chris Hecker. Physics Articles at <a href="http://chrishecker.com/Rigid_Body_Dynamics"><u><font color=#0000ff>http://chrishecker.com/Rigid_Body_Dynamics</font></u></a>* originally published in <em>Game Developer Magazine</em>. October 1996 through June 1997.<br><br>iv Xavier Provot. Deformation Constraints in a Mass-Spring Model to Describe Rigid Cloth Behavior. In <em>Graphics Interface</em>, pages 147-155, 1995.<br><br>v Mathieu Desbrun, Peter Schroder and Alan Barr. Interactive Animation of Structured Deformable Objects. In <em>Graphics Interface '99</em>. June 1999.<br><br>vi D. Baraff and A. Witkin. Large Steps in Cloth Simulation. <em>Computer Graphics (Proc. SIGGRAPH)</em>, pages 43-54, 1998.</p>
<!--page break-->
<img src ="http://www.cppblog.com/zmj/aggbug/71893.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2009-01-13 14:28 <a href="http://www.cppblog.com/zmj/archive/2009/01/13/71893.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Shadow Techniques for Relief Texture Mapped Objects</title><link>http://www.cppblog.com/zmj/archive/2008/12/22/70074.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Mon, 22 Dec 2008 08:26:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2008/12/22/70074.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/70074.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2008/12/22/70074.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/70074.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/70074.html</trackback:ping><description><![CDATA[<a href="http://www.gamasutra.com/view/feature/2420/book_excerpt_shadow_techniques_.php">http://www.gamasutra.com/view/feature/2420/book_excerpt_shadow_techniques_.php</a><br>
<p>The following is an excerpt from <em>Advanced Game Development with Programmable Graphics Hardware</em> (ISBN 1-56881-240-X) published by A K Peters, Ltd. </p>
<p>-- </p>
<span style="CLEAR: right; MARGIN-TOP: 0px; PADDING-LEFT: 13px; FLOAT: right; PADDING-BOTTOM: 15px; PADDING-TOP: 0px">
<script language=JavaScript>
var axel = Math.random();
var num = axel * 100000000000000000 + "?";
NS4 = document.layers;
if (NS4) {origWidth = innerWidth;origHeight = innerHeight;}
function reDo() {if (innerWidth != origWidth || innerHeight != origHeight) location.reload();}
if (NS4) onresize = reDo;
</script>
<script language=Javascript1.1>
document.write('<iframe SRC="http://as.cmpnet.com/html.ng/site=game&affiliate=gamasutra&pagepos=jumbobox&target=&ord='+ num +'"  width="300" height="250" frameborder="no" border="0" marginwidth="0" marginheight="0" SCROLLING="no">');
document.write('
<script LANGUAGE="Javascript1.1" SRC="http://as.cmpnet.com/js.ng/Params.richmedia=yes&site=game&affiliate=gamasutra&pagepos=jumbobox&target=&ord='+ num +'"><\/script>');
document.write('</iframe>');
</script>
<iframe border=0 marginWidth=0 marginHeight=0 src="http://as.cmpnet.com/html.ng/site=game&amp;affiliate=gamasutra&amp;pagepos=jumbobox&amp;target=&amp;ord=14440541298996080?" frameBorder=no width=300 scrolling=no height=250>
<script LANGUAGE="Javascript1.1" SRC="http://as.cmpnet.com/js.ng/Params.richmedia=yes&site=game&affiliate=gamasutra&pagepos=jumbobox&target=&ord=14440541298996080?"></script>
</iframe></span>
<p>Integrating shadows to the relief map objects is an important feature in fully integrating the effect into a game scenario. The corrected depth option (see Chapter 5), which ensures that the depth values stored in <em>Z</em>-buffer include the displaced depth from the relief map, makes it possible to implement correct shadow effects for such objects. We consider the use of stencil shadows and shadow maps in this context. We can implement three types of shadows: shadows from relief object to the world, from the world to relief object and from relief object to itself (self-shadows). </p>
<p>Let us first consider what can be achieved using stencil volume shadows. When generating the shadow volumes, we can only use the polygons from the original mesh to generate the volume. This means that the shadows from relief objects to the world will not show the displaced geometry of the relief texture, but will reflect the shape of the original triangle mesh without the displaced pixels (Figure 1). </p>
<table height=334 cellSpacing=0 cellPadding=0 width=142 align=right border=0>
    <tbody>
        <tr>
            <td vAlign=top width=11 bgColor=#ccc999 height=3 rowSpan=2>
            <div align=right><img height=11 alt="" src="http://www.gamasutra.com/redesign/images/corner_top_left.gif" width=10 align=top> </div>
            </td>
            <td vAlign=top bgColor=#ccc999 colSpan=3 height=3 rowSpan=2><br><img height=288 alt="" src="http://www.gamasutra.com/features/20051003/figure4-23.jpg" width=307> </td>
            <td vAlign=top align=right width=10 bgColor=#ccc999 height=3><img height=11 alt="" src="http://www.gamasutra.com/redesign/images/corner_top_right.gif" width=10 align=top></td>
        </tr>
        <tr>
            <td vAlign=bottom align=right width=10 bgColor=#ccc999 rowSpan=2><img height=11 alt="" src="http://www.gamasutra.com/redesign/images/corner_bottom_right.gif" width=10 align=bottom></td>
        </tr>
        <tr vAlign=top>
            <td vAlign=bottom align=left width=11 bgColor=#ccc999 height=2><img height=11 alt="" src="http://www.gamasutra.com/redesign/images/corner_bottom_left.gif" width=10 align=bottom></td>
            <td vAlign=top bgColor=#ccc999 colSpan=3 height=2>
            <p><strong>Figure 1. A relief mapped object cannot produce correct object to world shadows using shadow volumes. </strong></p>
            </td>
        </tr>
    </tbody>
</table>
<p>However, as we have the corrected depth stored in <em>Z</em>-buffer when rendering the lighting pass we can have shadows volumes from the world projected onto the relief objects correctly, and they will follow the displaced geometry properly. Self-shadows (relief object to itself) are not possible with stencil shadows. </p>
<p>Thus, using relief maps in conjunction with shadow volumes, we have the following: </p>
<ul>
    <li><strong>Relief object to world:</strong> correct silhouette or displacement visible in shadows is not possible.
    <li><strong>World to relief object:</strong> shadows can project on displaced pixels correctly.
    <li><strong>Relief object to relief object:</strong> not possible. </li>
</ul>
<p>Relief mapped objects integrate much better into shadow map algorithms. Using a shadow map, we can resolve all three cases; as for any other object, we render the relief mapped object into the shadow map. As the shadow map only needs depth values, the shader, used when rendering the object to the shadow map, does not need to calculate lighting. Also if no self-shadows are desired, we could simplify the ray intersect function to invoke only the linear search (as in this case we only need to know if a pixel has an intersection and we do not need the exact intersection point). The shader used when rendering relief objects to a shadow map is given in Listing 4.4, and an example is shown in Figure 2. </p>
<table height=334 cellSpacing=0 cellPadding=0 width=142 align=center border=0>
    <tbody>
        <tr>
            <td vAlign=top width=11 bgColor=#ccc999 height=3 rowSpan=2>
            <div align=right><img height=11 alt="" src="http://www.gamasutra.com/redesign/images/corner_top_left.gif" width=10 align=top> </div>
            </td>
            <td vAlign=top bgColor=#ccc999 colSpan=3 height=3 rowSpan=2><br><img height=288 alt="" src="http://www.gamasutra.com/features/20051003/figure4-24.jpg" width=307> </td>
            <td vAlign=top align=right width=10 bgColor=#ccc999 height=3><img height=11 alt="" src="http://www.gamasutra.com/redesign/images/corner_top_right.gif" width=10 align=top></td>
        </tr>
        <tr>
            <td vAlign=bottom align=right width=10 bgColor=#ccc999 rowSpan=2><img height=11 alt="" src="http://www.gamasutra.com/redesign/images/corner_bottom_right.gif" width=10 align=bottom></td>
        </tr>
        <tr vAlign=top>
            <td vAlign=bottom align=left width=11 bgColor=#ccc999 height=2><img height=11 alt="" src="http://www.gamasutra.com/redesign/images/corner_bottom_left.gif" width=10 align=bottom></td>
            <td vAlign=top bgColor=#ccc999 colSpan=3 height=2>
            <p><strong>Figure 2. Using relief mapped objects in conjunction with shadow maps. Shadows from relief object to world. </strong></p>
            </td>
        </tr>
    </tbody>
</table>
<p>To project shadows from the world to the relief map objects, we need to pass the shadow map texture and light matrix (light frustum view/projection/bias multiplied by inverse camera view matrix). Then, just before calculating the final colour in the shader we project the displaced pixel position into the light space and compare the depth map at that position to the pixel depth in light space. </p>
<p><strong>#ifdef RM_SHADOWS<br></strong><strong>&nbsp;&nbsp;// transform pixel position to shadow map space<br>&nbsp;&nbsp;sm= mul (viewinverse_lightviewprojbias,position); &nbsp;&nbsp;<br>&nbsp; sm/=sm.w; <br>&nbsp;&nbsp;if (sm.z&gt; f1tex2D (shadowmap,sm.xy)) <br>&nbsp;&nbsp;&nbsp;&nbsp;att=0; // set attenuation to 0<br>#endif</strong> </p>
<table height=334 cellSpacing=0 cellPadding=0 width=142 align=center border=0>
    <tbody>
        <tr>
            <td vAlign=top width=11 bgColor=#ccc999 height=3 rowSpan=2>
            <div align=right><img height=11 alt="" src="http://www.gamasutra.com/redesign/images/corner_top_left.gif" width=10 align=top> </div>
            </td>
            <td vAlign=top bgColor=#ccc999 colSpan=3 height=3 rowSpan=2><br>
            <table cellSpacing=1 width=275 border=0>
                <tbody>
                    <tr>
                        <td><img height=288 alt="" src="http://www.gamasutra.com/features/20051003/figure4-25-left.jpg" width=260></td>
                        <td><img height=288 alt="" src="http://www.gamasutra.com/features/20051003/figure4-25-right.jpg" width=260></td>
                    </tr>
                </tbody>
            </table>
            </td>
            <td vAlign=top align=right width=10 bgColor=#ccc999 height=3><img height=11 alt="" src="http://www.gamasutra.com/redesign/images/corner_top_right.gif" width=10 align=top></td>
        </tr>
        <tr>
            <td vAlign=bottom align=right width=10 bgColor=#ccc999 rowSpan=2><img height=11 alt="" src="http://www.gamasutra.com/redesign/images/corner_bottom_right.gif" width=10 align=bottom></td>
        </tr>
        <tr vAlign=top>
            <td vAlign=bottom align=left width=11 bgColor=#ccc999 height=2><img height=11 alt="" src="http://www.gamasutra.com/redesign/images/corner_bottom_left.gif" width=10 align=bottom></td>
            <td vAlign=top bgColor=#ccc999 colSpan=3 height=2>
            <p><strong>Figure 3. Shadows from world to relief objects. Left image shows normal mapping, and right image, relief mapping (notice how the shadow boundary follows the displaced relief correctly). </strong></p>
            </td>
        </tr>
    </tbody>
</table>
<p>An example of this approach is shown in Figure 3. This is compared with a conventional render using a normal map in conjunction with a shadow map. Thus, using relief maps in conjunction with shadow maps, we can implement the following: </p>
<ul>
    <li><strong>Relief object to world:</strong> good silhouette and displacement visible in <br>shadows.
    <li><strong>World to relief object:</strong> Shadows can project on displaced pixels correctly.
    <li><strong>Relief object to relief object:</strong> possible if full linear/binary search and <br>depth correct used when rendering to shadow map. </li>
</ul>
<p><strong>Listing 4.4 <br></strong>Using relief mapped objects in conjunction with shadow maps. </p>
<p><strong>float ray_intersect_rm_shadow(<br>&nbsp;&nbsp;<strong>&nbsp;&nbsp;</strong></strong><strong>in sampler2D reliefmap, <br>&nbsp;&nbsp;&nbsp;&nbsp;in float2 tx, <br>&nbsp;&nbsp;&nbsp;&nbsp;in float3 v, <br>&nbsp;&nbsp;&nbsp;&nbsp;in float f, <br>&nbsp;&nbsp;&nbsp;&nbsp;in float tmax) <br>{<br>&nbsp;&nbsp;const int linear_search_steps=10; </strong></p>
<p><strong>&nbsp;&nbsp;float t=0.0; <br>&nbsp;&nbsp;float best_t=tmax+0.001; <br>&nbsp;&nbsp;float size=best_t/linear_search_steps; </strong></p>
<p><strong>&nbsp;&nbsp;// search for first point inside object</strong><strong><br>&nbsp; for ( int i=0;i&lt;linear_search_steps-1;i++ )<br>&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;t+=size; <br>&nbsp;&nbsp;&nbsp;&nbsp;float3 p=ray_position(t,tx,v,f); <br>&nbsp;&nbsp;&nbsp;&nbsp;float4 tex= tex2D (reliefmap,p.xy); <br>&nbsp;&nbsp;&nbsp;&nbsp;if (best_t&gt;tmax) <br>&nbsp;&nbsp;&nbsp;&nbsp;if (p.z&gt;tex.w) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; best_t=t; <br>&nbsp;&nbsp;} </strong></p>
<p><strong>&nbsp;&nbsp;return best_t; <br>} </strong></p>
<p><strong>f2s main_frag_relief_shadow( <br>&nbsp;&nbsp;&nbsp;&nbsp;v2f IN, <br>&nbsp;&nbsp;&nbsp;&nbsp;uniform sampler2D rmtex: TEXUNIT0 , // rm texture map <br>&nbsp;&nbsp;&nbsp;&nbsp;uniform float4 planes, &nbsp;&nbsp;&nbsp;&nbsp;// near and far plane info <br>&nbsp;&nbsp;&nbsp;&nbsp;uniform float tile, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// tile factor <br>&nbsp;&nbsp;&nbsp;&nbsp;uniform float depth) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// depth factor<br></strong><strong>{ <br>&nbsp;&nbsp;&nbsp;&nbsp;f2s OUT; </strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;// view vector in eye space<br>&nbsp;&nbsp;&nbsp;&nbsp;</strong><strong>float3 view= normalize (IN.vpos); </strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;// view vector in tangent space<br>&nbsp;&nbsp;&nbsp;&nbsp;</strong><strong>float3 v= normalize ( float3 ( dot (view,IN.tangent.xyz), <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dot (view,IN.binormal.xyz), dot (-view,IN.normal))); </strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;// mapping scale from object to texture space<br>&nbsp;&nbsp;&nbsp;&nbsp;</strong><strong>float2 mapping= float2 (IN.tangent.w,IN.binormal.w)/tile; </strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;// quadric coefficients transformed to texture space<br>&nbsp;&nbsp;&nbsp;&nbsp;</strong><strong>float2 quadric=IN.curvature.xy*mapping.xy*mapping.xy/depth; </strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;// view vector in texture space<br>&nbsp;&nbsp;&nbsp;&nbsp;</strong><strong>v.xy/=mapping; <br>&nbsp;&nbsp;&nbsp;&nbsp;v.z/=depth; <br></strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;// quadric applied to view vector coodinates<br>&nbsp;&nbsp;&nbsp;&nbsp;</strong><strong>float f=quadric.x*v.x*v.x+quadric.y*v.y*v.y; </strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;// compute max distance for search min(t(z=0),t(z=1))<br>&nbsp;&nbsp;&nbsp;&nbsp;</strong><strong>float d=v.z*v.z-4*f; <br>&nbsp;&nbsp;&nbsp;&nbsp;float tmax=100; <br>&nbsp;&nbsp;&nbsp;&nbsp;if (d&gt;0) &nbsp;&nbsp;&nbsp;&nbsp;// t when z=1<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong><strong>tmax=(-v.z+ sqrt (d))/(-2*f); <br>&nbsp;&nbsp;&nbsp;&nbsp;d=v.z/f; &nbsp;&nbsp;&nbsp;&nbsp;// t when z=0 <br>&nbsp;&nbsp;&nbsp;&nbsp;if (d&gt;0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong><strong>tmax= min (tmax,d); </strong></p>
<p><strong>#ifndef RM_DEPTHCORRECT<br></strong><strong>&nbsp;&nbsp;// no depth correct, use simple ray_intersect<br></strong><strong>&nbsp;&nbsp;float t=ray_intersect_rm_shadow(rmtex,IN. texcoord*tile,v,f,tmax); <br>&nbsp;&nbsp;if (t&gt;tmax) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;discard ; // no intesection, discard fragment <br>#else<br></strong><strong>&nbsp;&nbsp;&nbsp;&nbsp;// with depth correct, use full ray_intersect<br></strong><strong>&nbsp;&nbsp;&nbsp;&nbsp;float t=ray_intersect_rm(rmtex,IN.texcoord*tile,v,f,tmax); <br>&nbsp;&nbsp;&nbsp;&nbsp;if (t&gt;tmax) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;discard ; // no intesection, discard fragment</strong> </p>
<p><strong>&nbsp;&nbsp;</strong><strong>&nbsp;&nbsp;</strong><strong>// compute displaced pixel position in view space<br>&nbsp;&nbsp;&nbsp;&nbsp;</strong><strong>float3 p=IN.vpos.xyz+view*t; </strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;// a=-far/(far-near) <br>&nbsp;&nbsp;&nbsp;&nbsp;// b=-far*near/(far-near) <br>&nbsp;&nbsp;&nbsp;&nbsp;// Z=(a*z+b)/-z<br>&nbsp;&nbsp;&nbsp;&nbsp;</strong><strong>OUT.depth=((planes.x*p.z+planes.y)/-p.z);<br></strong><strong>#endif </strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;return OUT;<br></strong><strong>}</strong> </p>
<img src ="http://www.cppblog.com/zmj/aggbug/70074.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2008-12-22 16:26 <a href="http://www.cppblog.com/zmj/archive/2008/12/22/70074.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Shadow mapping</title><link>http://www.cppblog.com/zmj/archive/2008/12/22/70070.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Mon, 22 Dec 2008 06:49:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2008/12/22/70070.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/70070.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2008/12/22/70070.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/70070.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/70070.html</trackback:ping><description><![CDATA[<a href="http://en.wikipedia.org/wiki/Shadow_map">http://en.wikipedia.org/wiki/Shadow_map</a><br>
<div id=bodyContent>
<h3 id=siteSub>From Wikipedia, the free encyclopedia</h3>
<div id=contentSub>&nbsp;&nbsp;(Redirected from <a title="Shadow map" href="http://en.wikipedia.org/w/index.php?title=Shadow_map&amp;redirect=no"><u><font color=#0000ff>Shadow map</font></u></a>)</div>
<div id=jump-to-nav>Jump to: <a href="http://en.wikipedia.org/wiki/Shadow_map#column-one"><u><font color=#800080>navigation</font></u></a>, <a href="http://en.wikipedia.org/wiki/Shadow_map#searchInput"><u><font color=#800080>search</font></u></a></div>
<!-- start content -->
<div class="thumb tright">
<div class=thumbinner style="WIDTH: 182px"><a class=image title="Scene with shadow mapping" href="http://en.wikipedia.org/wiki/Image:7fin.png"><span class=thumbimage style="BORDER-RIGHT: #ccc 1px solid; BORDER-TOP: #ccc 1px solid; DISPLAY: inline-block; FONT-SIZE: 0px; BACKGROUND-IMAGE: none; VERTICAL-ALIGN: middle; BORDER-LEFT: #ccc 1px solid; CURSOR: hand; BORDER-BOTTOM: #ccc 1px solid"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/wikipedia/en/thumb/3/32/7fin.png/180px-7fin.png'); WIDTH: 1px; HEIGHT: 1px"><u><font color=#800080></font></u></span></span></a>
<div class=thumbcaption>
<div class=magnify><a class=internal title=Enlarge href="http://en.wikipedia.org/wiki/Image:7fin.png"><span class="" style="BORDER-TOP-WIDTH: 2px; DISPLAY: inline-block; BORDER-LEFT-WIDTH: 2px; FONT-SIZE: 0px; BORDER-LEFT-COLOR: #0000ff; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 2px; BORDER-BOTTOM-COLOR: #0000ff; VERTICAL-ALIGN: middle; CURSOR: hand; BORDER-TOP-COLOR: #0000ff; BORDER-RIGHT-WIDTH: 2px; BORDER-RIGHT-COLOR: #0000ff"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/skins/common/images/magnify-clip.png'); WIDTH: 1px; HEIGHT: 1px"><u><font color=#800080></font></u></span></span></a></div>
Scene with shadow mapping</div>
</div>
</div>
<div class="thumb tright">
<div class=thumbinner style="WIDTH: 182px"><a class=image title="Scene with no shadows" href="http://en.wikipedia.org/wiki/Image:3noshadow.png"><span class=thumbimage style="BORDER-RIGHT: #ccc 1px solid; BORDER-TOP: #ccc 1px solid; DISPLAY: inline-block; FONT-SIZE: 0px; BACKGROUND-IMAGE: none; VERTICAL-ALIGN: middle; BORDER-LEFT: #ccc 1px solid; CURSOR: hand; BORDER-BOTTOM: #ccc 1px solid"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/wikipedia/en/thumb/7/74/3noshadow.png/180px-3noshadow.png'); WIDTH: 1px; HEIGHT: 1px"></span></span></a>
<div class=thumbcaption>
<div class=magnify><a class=internal title=Enlarge href="http://en.wikipedia.org/wiki/Image:3noshadow.png"><span class="" style="BORDER-TOP-WIDTH: 2px; DISPLAY: inline-block; BORDER-LEFT-WIDTH: 2px; FONT-SIZE: 0px; BORDER-LEFT-COLOR: #0000ff; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 2px; BORDER-BOTTOM-COLOR: #0000ff; VERTICAL-ALIGN: middle; CURSOR: hand; BORDER-TOP-COLOR: #0000ff; BORDER-RIGHT-WIDTH: 2px; BORDER-RIGHT-COLOR: #0000ff"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/skins/common/images/magnify-clip.png'); WIDTH: 1px; HEIGHT: 1px"></span></span></a></div>
Scene with no shadows</div>
</div>
</div>
<p><strong>Shadow mapping</strong> or <strong>projective shadowing</strong> is a process by which <a title=Shadow href="http://en.wikipedia.org/wiki/Shadow"><u><font color=#0000ff>shadows</font></u></a> are added to <a title="3D computer graphics" href="http://en.wikipedia.org/wiki/3D_computer_graphics"><u><font color=#0000ff>3D computer graphics</font></u></a>. This concept was introduced by <a title="Lance Williams" href="http://en.wikipedia.org/wiki/Lance_Williams"><u><font color=#0000ff>Lance Williams</font></u></a> in 1978, in a paper entitled "Casting curved shadows on curved surfaces". Since then, it has been used both in pre-rendered scenes, in realtime, and even in many console and high-end PC games. Shadow mapping is used by <a title=Pixar href="http://en.wikipedia.org/wiki/Pixar"><u><font color=#0000ff>Pixar</font></u></a>'s <a title=RenderMan href="http://en.wikipedia.org/wiki/RenderMan"><u><font color=#0000ff>RenderMan</font></u></a>, and likewise, shadow mapping has been used in such films as <em><a title="Toy Story" href="http://en.wikipedia.org/wiki/Toy_Story"><u><font color=#0000ff>Toy Story</font></u></a></em>.</p>
<p>Shadows are created by testing whether a <a title=Pixel href="http://en.wikipedia.org/wiki/Pixel"><u><font color=#0000ff>pixel</font></u></a> is visible from the light source, by comparing it to a <a title=Z-buffering href="http://en.wikipedia.org/wiki/Z-buffering"><u><font color=#0000ff>z-buffer</font></u></a> or <em>depth</em> image of the light's view, stored in the form of a <a title="Texture mapping" href="http://en.wikipedia.org/wiki/Texture_mapping"><u><font color=#0000ff>texture</font></u></a>.</p>
<table class=toc id=toc summary=Contents>
    <tbody>
        <tr>
            <td>
            <div id=toctitle>
            <h2>Contents</h2>
            <span class=toctoggle>[<a class=internal id=togglelink href="javascript:toggleToc()"><u><font color=#0000ff>hide</font></u></a>]</span></div>
            <ul>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Shadow_map#Principle_of_a_shadow_and_a_shadow_map"><u><font color=#800080><span class=tocnumber>1</span> <span class=toctext>Principle of a shadow and a shadow map</span></font></u></a>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Shadow_map#Algorithm_overview"><u><font color=#800080><span class=tocnumber>2</span> <span class=toctext>Algorithm overview</span></font></u></a>
                <ul>
                    <li class=toclevel-2><a href="http://en.wikipedia.org/wiki/Shadow_map#Creating_the_shadow_map"><u><font color=#800080><span class=tocnumber>2.1</span> <span class=toctext>Creating the shadow map</span></font></u></a>
                    <li class=toclevel-2><a href="http://en.wikipedia.org/wiki/Shadow_map#Shading_the_scene"><u><font color=#800080><span class=tocnumber>2.2</span> <span class=toctext>Shading the scene</span></font></u></a>
                    <ul>
                        <li class=toclevel-3><a href="http://en.wikipedia.org/wiki/Shadow_map#Light_space_coordinates"><u><font color=#800080><span class=tocnumber>2.2.1</span> <span class=toctext>Light space coordinates</span></font></u></a>
                        <li class=toclevel-3><a href="http://en.wikipedia.org/wiki/Shadow_map#Depth_map_test"><u><font color=#800080><span class=tocnumber>2.2.2</span> <span class=toctext>Depth map test</span></font></u></a>
                        <li class=toclevel-3><a href="http://en.wikipedia.org/wiki/Shadow_map#Drawing_the_scene"><u><font color=#800080><span class=tocnumber>2.2.3</span> <span class=toctext>Drawing the scene</span></font></u></a> </li>
                    </ul>
                    </li>
                </ul>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Shadow_map#See_also"><u><font color=#800080><span class=tocnumber>3</span> <span class=toctext>See also</span></font></u></a>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Shadow_map#External_links"><u><font color=#800080><span class=tocnumber>4</span> <span class=toctext>External links</span></font></u></a>
                <ul>
                    <li class=toclevel-2><a href="http://en.wikipedia.org/wiki/Shadow_map#Further_reading"><u><font color=#800080><span class=tocnumber>4.1</span> <span class=toctext>Further reading</span></font></u></a> </li>
                </ul>
                </li>
            </ul>
            </td>
        </tr>
    </tbody>
</table>
<script type=text/javascript>
//<![cdata[
if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); }
//]]&gt;
</script>
<p><a id=Principle_of_a_shadow_and_a_shadow_map name=Principle_of_a_shadow_and_a_shadow_map></a></p>
<h2><span class=editsection>[<a title="Edit section: Principle of a shadow and a shadow map" href="http://en.wikipedia.org/w/index.php?title=Shadow_mapping&amp;action=edit&amp;section=1"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>Principle of a shadow and a shadow map</span></h2>
<p>If you looked out from a source of light, all of the objects you can see would appear in light. Anything behind those objects, however, would be in shadow. This is the basic principle used to create a shadow map. The light's view is rendered, storing the depth of every surface it sees (the shadow map). Next, the regular scene is rendered comparing the depth of every point drawn (as if it were being seen by the light, rather than the eye) to this depth map.</p>
<p>For real-time shadows, this technique is less accurate than <a title="Shadow volume" href="http://en.wikipedia.org/wiki/Shadow_volume"><u><font color=#0000ff>shadow volumes</font></u></a>, but the shadow map can sometimes be a faster alternative depending on how much fill time is required for either technique in a particular application. As well, shadow maps do not require the use of an additional <a title="Stencil buffer" href="http://en.wikipedia.org/wiki/Stencil_buffer"><u><font color=#0000ff>stencil buffer</font></u></a>, and can sometimes be modified to produce shadows with a soft edge. However, unlike shadow volumes, the accuracy of a shadow map is limited by its resolution.</p>
<p><a id=Algorithm_overview name=Algorithm_overview></a></p>
<h2><span class=editsection>[<a title="Edit section: Algorithm overview" href="http://en.wikipedia.org/w/index.php?title=Shadow_mapping&amp;action=edit&amp;section=2"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>Algorithm overview</span></h2>
<p>Rendering a shadowed scene involves two major drawing steps. The first produces the shadow map itself, and the second applies it to the scene. Depending on the implementation (and number of lights), this may require two or more drawing passes.</p>
<p><a id=Creating_the_shadow_map name=Creating_the_shadow_map></a></p>
<h3><span class=editsection>[<a title="Edit section: Creating the shadow map" href="http://en.wikipedia.org/w/index.php?title=Shadow_mapping&amp;action=edit&amp;section=3"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>Creating the shadow map</span></h3>
<div class="thumb tright">
<div class=thumbinner style="WIDTH: 152px"><a class=image title="Scene rendered from the light view." href="http://en.wikipedia.org/wiki/Image:1light.png"><span class=thumbimage style="BORDER-RIGHT: #ccc 1px solid; BORDER-TOP: #ccc 1px solid; DISPLAY: inline-block; FONT-SIZE: 0px; BACKGROUND-IMAGE: none; VERTICAL-ALIGN: middle; BORDER-LEFT: #ccc 1px solid; CURSOR: hand; BORDER-BOTTOM: #ccc 1px solid"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/wikipedia/en/thumb/b/bf/1light.png/150px-1light.png'); WIDTH: 1px; HEIGHT: 1px"></span></span></a>
<div class=thumbcaption>
<div class=magnify><a class=internal title=Enlarge href="http://en.wikipedia.org/wiki/Image:1light.png"><span class="" style="BORDER-TOP-WIDTH: 2px; DISPLAY: inline-block; BORDER-LEFT-WIDTH: 2px; FONT-SIZE: 0px; BORDER-LEFT-COLOR: #0000ff; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 2px; BORDER-BOTTOM-COLOR: #0000ff; VERTICAL-ALIGN: middle; CURSOR: hand; BORDER-TOP-COLOR: #0000ff; BORDER-RIGHT-WIDTH: 2px; BORDER-RIGHT-COLOR: #0000ff"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/skins/common/images/magnify-clip.png'); WIDTH: 1px; HEIGHT: 1px"></span></span></a></div>
Scene rendered from the light view.</div>
</div>
</div>
<div class="thumb tright">
<div class=thumbinner style="WIDTH: 152px"><a class=image title="Scene from the light view, depth map." href="http://en.wikipedia.org/wiki/Image:2shadowmap.png"><span class=thumbimage style="BORDER-RIGHT: #ccc 1px solid; BORDER-TOP: #ccc 1px solid; DISPLAY: inline-block; FONT-SIZE: 0px; BACKGROUND-IMAGE: none; VERTICAL-ALIGN: middle; BORDER-LEFT: #ccc 1px solid; CURSOR: hand; BORDER-BOTTOM: #ccc 1px solid"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/wikipedia/commons/thumb/2/23/2shadowmap.png/150px-2shadowmap.png'); WIDTH: 1px; HEIGHT: 1px"></span></span></a>
<div class=thumbcaption>
<div class=magnify><a class=internal title=Enlarge href="http://en.wikipedia.org/wiki/Image:2shadowmap.png"><span class="" style="BORDER-TOP-WIDTH: 2px; DISPLAY: inline-block; BORDER-LEFT-WIDTH: 2px; FONT-SIZE: 0px; BORDER-LEFT-COLOR: #0000ff; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 2px; BORDER-BOTTOM-COLOR: #0000ff; VERTICAL-ALIGN: middle; CURSOR: hand; BORDER-TOP-COLOR: #0000ff; BORDER-RIGHT-WIDTH: 2px; BORDER-RIGHT-COLOR: #0000ff"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/skins/common/images/magnify-clip.png'); WIDTH: 1px; HEIGHT: 1px"></span></span></a></div>
Scene from the light view, depth map.</div>
</div>
</div>
<p>The first step renders the scene from the light's point of view. For a point light source, the view should be a <a class=mw-redirect title="Perspective projection" href="http://en.wikipedia.org/wiki/Perspective_projection"><u><font color=#0000ff>perspective projection</font></u></a> as wide as its desired angle of effect (it will be a sort of square spotlight). For directional light (e.g. that from the <a title=Sun href="http://en.wikipedia.org/wiki/Sun"><u><font color=#0000ff>Sun</font></u></a>), an <a title="Orthographic projection" href="http://en.wikipedia.org/wiki/Orthographic_projection"><u><font color=#0000ff>orthographic projection</font></u></a> should be used.</p>
<p>From this rendering, the depth buffer is extracted and saved. Because only the depth information is relevant, it is usual to avoid updating the color buffers and disable all lighting and texture calculations for this rendering, in order to save drawing time. This <strong>depth map</strong> is often stored as a texture in graphics memory.</p>
<p>This depth map must be updated any time there are changes to either the light or the objects in the scene, but can be reused in other situations, such as those where only the viewing camera moves. (If there are multiple lights, a separate depth map must be used for each light.)</p>
<p>In many implementations it is practical to render only a subset of the objects in the scene to the shadow map in order to save some of the time it takes to redraw the map. Also, a depth offset which shifts the objects away from the light may be applied to the shadow map rendering in an attempt to resolve <a title=Z-fighting href="http://en.wikipedia.org/wiki/Z-fighting"><u><font color=#0000ff>stitching</font></u></a> problems where the depth map value is close to the depth of a surface being drawn (i.e. the shadow casting surface) in the next step. Alternatively, culling front faces and only rendering the back of objects to the shadow map is sometimes used for a similar result.</p>
<p><a id=Shading_the_scene name=Shading_the_scene></a></p>
<h3><span class=editsection>[<a title="Edit section: Shading the scene" href="http://en.wikipedia.org/w/index.php?title=Shadow_mapping&amp;action=edit&amp;section=4"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>Shading the scene</span></h3>
<p>The second step is to draw the scene from the usual <a class=mw-redirect title="Perspective projection" href="http://en.wikipedia.org/wiki/Perspective_projection"><u><font color=#0000ff>camera</font></u></a> viewpoint, applying the shadow map. This process has three major components, the first is to find the coordinates of the object as seen from the light, the second is the test which compares that coordinate against the depth map, and finally, once accomplished, the object must be drawn either in shadow or in light.</p>
<p><a id=Light_space_coordinates name=Light_space_coordinates></a></p>
<h4><span class=editsection>[<a title="Edit section: Light space coordinates" href="http://en.wikipedia.org/w/index.php?title=Shadow_mapping&amp;action=edit&amp;section=5"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>Light space coordinates</span></h4>
<div class="thumb tright">
<div class=thumbinner style="WIDTH: 152px"><a class=image title="Visualization of the depth map projected onto the scene" href="http://en.wikipedia.org/wiki/Image:4overmap.png"><span class=thumbimage style="BORDER-RIGHT: #ccc 1px solid; BORDER-TOP: #ccc 1px solid; DISPLAY: inline-block; FONT-SIZE: 0px; BACKGROUND-IMAGE: none; VERTICAL-ALIGN: middle; BORDER-LEFT: #ccc 1px solid; CURSOR: hand; BORDER-BOTTOM: #ccc 1px solid"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/wikipedia/en/thumb/9/9c/4overmap.png/150px-4overmap.png'); WIDTH: 1px; HEIGHT: 1px"></span></span></a>
<div class=thumbcaption>
<div class=magnify><a class=internal title=Enlarge href="http://en.wikipedia.org/wiki/Image:4overmap.png"><span class="" style="BORDER-TOP-WIDTH: 2px; DISPLAY: inline-block; BORDER-LEFT-WIDTH: 2px; FONT-SIZE: 0px; BORDER-LEFT-COLOR: #0000ff; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 2px; BORDER-BOTTOM-COLOR: #0000ff; VERTICAL-ALIGN: middle; CURSOR: hand; BORDER-TOP-COLOR: #0000ff; BORDER-RIGHT-WIDTH: 2px; BORDER-RIGHT-COLOR: #0000ff"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/skins/common/images/magnify-clip.png'); WIDTH: 1px; HEIGHT: 1px"></span></span></a></div>
Visualization of the depth map projected onto the scene</div>
</div>
</div>
<p>In order to test a point against the depth map, its position in the scene coordinates must be transformed into the equivalent position as seen by the light. This is accomplished by a <a title="Matrix multiplication" href="http://en.wikipedia.org/wiki/Matrix_multiplication"><u><font color=#0000ff>matrix multiplication</font></u></a>. The location of the object on the screen is determined by the usual <a title="Coordinate transformation" href="http://en.wikipedia.org/wiki/Coordinate_transformation"><u><font color=#0000ff>coordinate transformation</font></u></a>, but a second set of coordinates must be generated to locate the object in light space.</p>
<p>The matrix used to transform the world coordinates into the light's viewing coordinates is the same as the one used to render the shadow map in the first step (under <a title=OpenGL href="http://en.wikipedia.org/wiki/OpenGL"><u><font color=#0000ff>OpenGL</font></u></a> this is the product of the modelview and projection matrices). This will produce a set of <a title="Homogeneous coordinates" href="http://en.wikipedia.org/wiki/Homogeneous_coordinates"><u><font color=#0000ff>homogeneous coordinates</font></u></a> that need a perspective division (<em>see <a title="3D projection" href="http://en.wikipedia.org/wiki/3D_projection"><u><font color=#0000ff>3D projection</font></u></a></em>) to become <em>normalized device coordinates</em>, in which each component (<em>x</em>, <em>y</em>, or <em>z</em>) falls between -1 and 1 (if it is visible from the light view). Many implementations (such as OpenGL and <a title=Direct3D href="http://en.wikipedia.org/wiki/Direct3D"><u><font color=#0000ff>Direct3D</font></u></a>) require an additional <em>scale and bias</em> matrix multiplication to map those -1 to 1 values to 0 to 1, which are more usual coordinates for depth map (texture map) lookup. This scaling can be done before the perspective division, and is easily folded into the previous transformation calculation by multiplying that matrix with the following:</p>
<p><span class=tex style="DISPLAY: inline-block; FONT-SIZE: 0px; BORDER-LEFT-COLOR: black; BACKGROUND-IMAGE: none; BORDER-BOTTOM-COLOR: black; VERTICAL-ALIGN: middle; BORDER-TOP-COLOR: black; BORDER-RIGHT-COLOR: black"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/math/7/c/e/7ced35c6602473fc2f64bac729fe45f1.png'); WIDTH: 1px; HEIGHT: 1px"></span></span></p>
<p>If done with a <a title=Shader href="http://en.wikipedia.org/wiki/Shader"><u><font color=#0000ff>shader</font></u></a>, or other graphics hardware extension, this transformation is usually applied at the vertex level, and the generated value is interpolated between other vertices, and passed to the fragment level.</p>
<p><a id=Depth_map_test name=Depth_map_test></a></p>
<h4><span class=editsection>[<a title="Edit section: Depth map test" href="http://en.wikipedia.org/w/index.php?title=Shadow_mapping&amp;action=edit&amp;section=6"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>Depth map test</span></h4>
<div class="thumb tright">
<div class=thumbinner style="WIDTH: 152px"><a class=image title="Depth map test failures." href="http://en.wikipedia.org/wiki/Image:5failed.png"><span class=thumbimage style="BORDER-RIGHT: #ccc 1px solid; BORDER-TOP: #ccc 1px solid; DISPLAY: inline-block; FONT-SIZE: 0px; BACKGROUND-IMAGE: none; VERTICAL-ALIGN: middle; BORDER-LEFT: #ccc 1px solid; CURSOR: hand; BORDER-BOTTOM: #ccc 1px solid"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/wikipedia/en/thumb/e/e2/5failed.png/150px-5failed.png'); WIDTH: 1px; HEIGHT: 1px"></span></span></a>
<div class=thumbcaption>
<div class=magnify><a class=internal title=Enlarge href="http://en.wikipedia.org/wiki/Image:5failed.png"><span class="" style="BORDER-TOP-WIDTH: 2px; DISPLAY: inline-block; BORDER-LEFT-WIDTH: 2px; FONT-SIZE: 0px; BORDER-LEFT-COLOR: #0000ff; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 2px; BORDER-BOTTOM-COLOR: #0000ff; VERTICAL-ALIGN: middle; CURSOR: hand; BORDER-TOP-COLOR: #0000ff; BORDER-RIGHT-WIDTH: 2px; BORDER-RIGHT-COLOR: #0000ff"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/skins/common/images/magnify-clip.png'); WIDTH: 1px; HEIGHT: 1px"></span></span></a></div>
Depth map test failures.</div>
</div>
</div>
<p>Once the light-space coordinates are found, the <em>x</em> and <em>y</em> values usually correspond to a location in the depth map texture, and the <em>z</em> value corresponds to its associated depth, which can now be tested against the depth map.</p>
<p>If the <em>z</em> value is greater than the value stored in the depth map at the appropriate (<em>x</em>,<em>y</em>) location, the object is considered to be behind an occluding object, and should be marked as a <em>failure</em>, to be drawn in shadow by the drawing process. Otherwise it should be drawn lighted.</p>
<p>If the (<em>x</em>,<em>y</em>) location falls outside the depth map, the programmer must either decide that the surface should be lit or shadowed by default (usually lit).</p>
<p>In a <a title=Shader href="http://en.wikipedia.org/wiki/Shader"><u><font color=#0000ff>shader</font></u></a> implementation, this test would be done at the fragment level. Also, care needs to be taken when selecting the type of texture map storage to be used by the hardware: if interpolation cannot be done, the shadow will appear to have a sharp jagged edge (an effect that can be reduced with greater shadow map resolution).</p>
<p>It is possible to modify the depth map test to produce shadows with a soft edge by using a range of values (based on the proximity to the edge of the shadow) rather than simply pass or fail.</p>
<p>The shadow mapping technique can also be modified to draw a texture onto the lit regions, simulating the effect of a <a title="Video projector" href="http://en.wikipedia.org/wiki/Video_projector"><u><font color=#0000ff>projector</font></u></a>. The picture above, captioned "visualization of the depth map projected onto the scene" is an example of such a process.</p>
<p><a id=Drawing_the_scene name=Drawing_the_scene></a></p>
<h4><span class=editsection>[<a title="Edit section: Drawing the scene" href="http://en.wikipedia.org/w/index.php?title=Shadow_mapping&amp;action=edit&amp;section=7"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>Drawing the scene</span></h4>
<div class="thumb tright">
<div class=thumbinner style="WIDTH: 152px"><a class=image title="Final scene, rendered with ambient shadows." href="http://en.wikipedia.org/wiki/Image:7fin.png"><span class=thumbimage style="BORDER-RIGHT: #ccc 1px solid; BORDER-TOP: #ccc 1px solid; DISPLAY: inline-block; FONT-SIZE: 0px; BACKGROUND-IMAGE: none; VERTICAL-ALIGN: middle; BORDER-LEFT: #ccc 1px solid; CURSOR: hand; BORDER-BOTTOM: #ccc 1px solid"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/wikipedia/en/thumb/3/32/7fin.png/150px-7fin.png'); WIDTH: 1px; HEIGHT: 1px"></span></span></a>
<div class=thumbcaption>
<div class=magnify><a class=internal title=Enlarge href="http://en.wikipedia.org/wiki/Image:7fin.png"><span class="" style="BORDER-TOP-WIDTH: 2px; DISPLAY: inline-block; BORDER-LEFT-WIDTH: 2px; FONT-SIZE: 0px; BORDER-LEFT-COLOR: #0000ff; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 2px; BORDER-BOTTOM-COLOR: #0000ff; VERTICAL-ALIGN: middle; CURSOR: hand; BORDER-TOP-COLOR: #0000ff; BORDER-RIGHT-WIDTH: 2px; BORDER-RIGHT-COLOR: #0000ff"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/skins/common/images/magnify-clip.png'); WIDTH: 1px; HEIGHT: 1px"></span></span></a></div>
Final scene, rendered with ambient shadows.</div>
</div>
</div>
<p>Drawing the scene with shadows can be done in several different ways. If programmable <a title=Shader href="http://en.wikipedia.org/wiki/Shader"><u><font color=#0000ff>shaders</font></u></a> are available, the depth map test may be performed by a fragment shader which simply draws the object in shadow or lighted depending on the result, drawing the scene in a single pass (after an initial earlier pass to generate the shadow map).</p>
<p>If shaders are not available, performing the depth map test must usually be implemented by some hardware extension (such as <a class="external text" title=http://www.opengl.org/registry/specs/ARB/shadow.txt href="http://www.opengl.org/registry/specs/ARB/shadow.txt" rel=nofollow><em><u><font color=#0000ff>GL_ARB_shadow</font></u></em></a>), which usually do not allow a choice between two lighting models (lighted and shadowed), and necessitate more rendering passes:</p>
<ol>
    <li>Render the entire scene in shadow. For the most common lighting models (<em>see <a class=mw-redirect title="Phong reflection model" href="http://en.wikipedia.org/wiki/Phong_reflection_model"><u><font color=#0000ff>Phong reflection model</font></u></a></em>) this should technically be done using only the ambient component of the light, but this is usually adjusted to also include a dim diffuse light to keep curved surfaces from appearing flat in shadow.
    <li>Enable the depth map test, and render the scene lit. Areas where the depth map test fails will not be overwritten, and remain shadowed.
    <li>An additional pass may be used for each additional light, using additive <a class=mw-redirect title="Alpha blending" href="http://en.wikipedia.org/wiki/Alpha_blending"><u><font color=#0000ff>blending</font></u></a> to combine their effect with the lights already drawn. (Each of these passes requires an additional previous pass to generate the associated shadow map.) </li>
</ol>
<p>The example pictures in this article used the <a title=OpenGL href="http://en.wikipedia.org/wiki/OpenGL"><u><font color=#0000ff>OpenGL</font></u></a> extension <a class="external text" title=http://www.opengl.org/registry/specs/ARB/shadow_ambient.txt href="http://www.opengl.org/registry/specs/ARB/shadow_ambient.txt" rel=nofollow><em><u><font color=#800080>GL_ARB_shadow_ambient</font></u></em></a> to accomplish the shadow map process in two passes.</p>
<p><a id=See_also name=See_also></a></p>
<h2><span class=editsection>[<a title="Edit section: See also" href="http://en.wikipedia.org/w/index.php?title=Shadow_mapping&amp;action=edit&amp;section=8"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>See also</span></h2>
<ul>
    <li><a title="Shadow volume" href="http://en.wikipedia.org/wiki/Shadow_volume"><u><font color=#0000ff>Shadow volume</font></u></a>, another shadowing technique
    <li><a title="Ray casting" href="http://en.wikipedia.org/wiki/Ray_casting"><u><font color=#0000ff>Ray casting</font></u></a>, a slower technique often used in <a title="Ray tracing" href="http://en.wikipedia.org/wiki/Ray_tracing"><u><font color=#0000ff>ray tracing</font></u></a>
    <li><a title="Photon mapping" href="http://en.wikipedia.org/wiki/Photon_mapping"><u><font color=#0000ff>Photon mapping</font></u></a>, a much slower technique capable of very realistic lighting
    <li><a title=Radiosity href="http://en.wikipedia.org/wiki/Radiosity"><u><font color=#0000ff>Radiosity</font></u></a>, another very slow but very realistic technique </li>
</ul>
<p><a id=External_links name=External_links></a></p>
<h2><span class=editsection>[<a title="Edit section: External links" href="http://en.wikipedia.org/w/index.php?title=Shadow_mapping&amp;action=edit&amp;section=9"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>External links</span></h2>
<ul>
    <li><a class="external text" title=http://developer.nvidia.com/attach/8456 href="http://developer.nvidia.com/attach/8456" rel=nofollow><u><font color=#0000ff>Hardware Shadow Mapping</font></u></a>, <a class=mw-redirect title=NVIDIA href="http://en.wikipedia.org/wiki/NVIDIA"><u><font color=#0000ff>nVidia</font></u></a>
    <li><a class="external text" title=http://developer.nvidia.com/attach/6769 href="http://developer.nvidia.com/attach/6769" rel=nofollow><u><font color=#0000ff>Shadow Mapping with Today's OpenGL Hardware</font></u></a>, nVidia
    <li><a class="external text" title=http://www.riemers.net/Tutorials/DirectX/Csharp3/index.php href="http://www.riemers.net/Tutorials/DirectX/Csharp3/index.php" rel=nofollow><u><font color=#0000ff>Riemer's step-by-step tutorial implementing Shadow Mapping with HLSL and DirectX</font></u></a> </li>
</ul>
<p><a id=Further_reading name=Further_reading></a></p>
<h3><span class=editsection>[<a title="Edit section: Further reading" href="http://en.wikipedia.org/w/index.php?title=Shadow_mapping&amp;action=edit&amp;section=10"><u><font color=#0000ff>edit</font></u></a>]</span> <span class=mw-headline>Further reading</span></h3>
<ul>
    <li><a class="external text" title=http://people.csail.mit.edu/ericchan/papers/smoothie/ href="http://people.csail.mit.edu/ericchan/papers/smoothie/" rel=nofollow><u><font color=#0000ff>Rendering Fake Soft Shadows with Smoothies</font></u></a> Eric Chan, Fredo Durand, <a title="Marco Corbetta" href="http://en.wikipedia.org/wiki/Marco_Corbetta"><u><font color=#0000ff>Marco Corbetta</font></u></a>
    <li><a class="external text" title=http://www.whdeboer.com/papers/smooth_penumbra_trans.pdf href="http://www.whdeboer.com/papers/smooth_penumbra_trans.pdf" rel=nofollow><u><font color=#0000ff>Smooth Penumbra Transitions with Shadow Maps</font></u></a> Willem H. de Boer
    <li><a class="external text" title=http://appsrv.cse.cuhk.edu.hk/~fzhang/pssm_project href="http://appsrv.cse.cuhk.edu.hk/~fzhang/pssm_project" rel=nofollow><u><font color=#0000ff>Parallel-Split Shadow Maps on Programmable GPUs</font></u></a> Fan Zhang, Hanqiu Sun, Oskari Nyman
    <li><a class="external text" title=http://www.comp.nus.edu.sg/~tants/tsm.html href="http://www.comp.nus.edu.sg/~tants/tsm.html" rel=nofollow><u><font color=#0000ff>Anti-aliasing and Continuity with Trapezoidal Shadow Maps</font></u></a> Tobias Martin, Tiow-Seng Tan
    <li><a class="external text" title=http://www.cs.unc.edu/~zhangh/shadow.html href="http://www.cs.unc.edu/~zhangh/shadow.html" rel=nofollow><u><font color=#0000ff>Forward shadow mapping</font></u></a> does the shadow test in eye-space rather than light-space to keep texture access more sequential. </li>
</ul>
<!--
NewPP limit report
Preprocessor node count: 14/1000000
Post-expand include size: 0/2048000 bytes
Template argument size: 0/2048000 bytes
Expensive parser function count: 0/500
--><!-- Saved in parser cache with key enwiki:pcache:idhash:2798171-0!1!0!default!!en!2 and timestamp 20081129103046 -->
<div class=printfooter>Retrieved from "<a href="http://en.wikipedia.org/wiki/Shadow_mapping"><u><font color=#0000ff>http://en.wikipedia.org/wiki/Shadow_mapping</font></u></a>"</div>
<div class=catlinks id=catlinks>
<div id=mw-normal-catlinks><a title=Special:Categories href="http://en.wikipedia.org/wiki/Special:Categories"><u><font color=#0000ff>Category</font></u></a>: <span dir=ltr><a title="Category:3D computer graphics" href="http://en.wikipedia.org/wiki/Category:3D_computer_graphics"><u><font color=#0000ff>3D computer graphics</font></u></a></span></div>
</div>
<!-- end content -->
<div class=visualClear></div>
</div>
<img src ="http://www.cppblog.com/zmj/aggbug/70070.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2008-12-22 14:49 <a href="http://www.cppblog.com/zmj/archive/2008/12/22/70070.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The Mechanics of Robust Stencil Shadows</title><link>http://www.cppblog.com/zmj/archive/2008/12/04/68559.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Thu, 04 Dec 2008 06:23:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2008/12/04/68559.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/68559.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2008/12/04/68559.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/68559.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/68559.html</trackback:ping><description><![CDATA[<a href="http://www.gamasutra.com/features/20021011/lengyel_01.htm">http://www.gamasutra.com/features/20021011/lengyel_01.htm</a><br>
<h1>The Mechanics of Robust Stencil Shadows</h1>
<!-- #EndEditable --><!-- #BeginEditable "main%20content" -->
<p>The idea of using the stencil buffer to generate shadows has been around for over a decade, but only recently has 3D graphics hardware advanced to the point where using the stencil algorithm on a large scale has become practical. Not long ago, there existed some unsolved problems pertaining to stencil shadows that prevented the algorithm from working correctly under various conditions. Advances have now been made, however, so that stencil shadows can be robustly implemented to handle arbitrarily positioned point lights and infinite directional lights having any desired spatial relationship with the camera. This article presents the intricacies of the entire stencil shadow algorithm and covers every mathematical detail of its efficient implementation.
<h2>Algorithm Overview</h2>
<p>The basic concept of the stencil shadow algorithm is to use the stencil buffer as a masking mechanism to prevent pixels in shadow from being drawn during the rendering pass for a particular light source. This is accomplished by rendering an invisible shadow volume for each shadow-casting object in a scene using stencil operations that leave nonzero values in the stencil buffer wherever light is blocked. Once the stencil buffer has been filled with the appropriate mask, a lighting pass only illuminates pixels where the value in the stencil buffer is zero.
<p>As shown in Figure 1, an object&#8217;s shadow volume encloses the region of space for which light is blocked by the object. This volume is constructed by finding the edges in the object&#8217;s triangle mesh representing the boundary between lit triangles and unlit triangles and extruding those edges away from the light source. Such a collection of edges is called the object&#8217;s silhouette with respect to the light source. The shadow volume is rendered into the stencil buffer using operations that modify the stencil value at each pixel depending on whether the depth test passes or fails. Of course, this requires that the depth buffer has already been initialized to the correct values by a previous rendering pass. Thus, the scene is first rendered using a shader that applies surface attributes that do not depend on any light source, such as ambient illumination, emission, and environment mapping.
<p>&nbsp;
<table height=274 cellSpacing=0 cellPadding=0 width=74 align=center border=0>
    <tbody>
        <tr>
            <td vAlign=top width=5 bgColor=#ccc999 height=3 rowSpan=2>
            <div align=right><img height=11 src="http://www.gamasutra.com/redesign/images/corner_top_left.gif" width=10 align=top> </div>
            </td>
            <td vAlign=top bgColor=#ccc999 colSpan=3 height=3 rowSpan=2><br><img height=315 src="http://www.gamasutra.com/features/20021011/fig_01.gif" width=472> </td>
            <td vAlign=top align=right width=5 bgColor=#ccc999 height=3><img height=11 src="http://www.gamasutra.com/redesign/images/corner_top_right.gif" width=10 align=top></td>
        </tr>
        <tr>
            <td vAlign=bottom align=right width=15 bgColor=#ccc999 rowSpan=2><img height=11 src="http://www.gamasutra.com/redesign/images/corner_bottom_right.gif" width=10 align=bottom></td>
        </tr>
        <tr vAlign=top>
            <td vAlign=bottom align=left width=10 bgColor=#ccc999 height=16><img height=11 src="http://www.gamasutra.com/redesign/images/corner_bottom_left.gif" width=10 align=bottom></td>
            <td vAlign=top bgColor=#ccc999 colSpan=3 height=16>
            <p align=center><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>Figure 1. An object&#8217;s shadow volume encloses the region of space for which light is blocked by the object.<br></font></strong></font></p>
            </td>
        </tr>
    </tbody>
</table>
<p>The original stencil algorithm renders the shadow volume in two stages. In the first stage, the front faces of the shadow volume (with respect to the camera) are rendered using a stencil operation that increments the value in the stencil buffer whenever the depth test passes. In the second stage, the back faces of the shadow volume are rendered using a stencil operation that decrements the value in the stencil buffer whenever the depth test passes. As illustrated in Figure 2, this technique leaves nonzero values in the stencil buffer wherever the shadow volume intersects any surface in the scene, including the surface of the object casting the shadow.
<p>&nbsp;
<table height=274 cellSpacing=0 cellPadding=0 width=74 align=center border=0>
    <tbody>
        <tr>
            <td vAlign=top width=5 bgColor=#ccc999 height=3 rowSpan=2>
            <div align=right><img height=11 src="http://www.gamasutra.com/redesign/images/corner_top_left.gif" width=10 align=top> </div>
            </td>
            <td vAlign=top bgColor=#ccc999 colSpan=3 height=3 rowSpan=2><br><img height=479 src="http://www.gamasutra.com/features/20021011/fig_02.gif" width=400> </td>
            <td vAlign=top align=right width=5 bgColor=#ccc999 height=3><img height=11 src="http://www.gamasutra.com/redesign/images/corner_top_right.gif" width=10 align=top></td>
        </tr>
        <tr>
            <td vAlign=bottom align=right width=15 bgColor=#ccc999 rowSpan=2><img height=11 src="http://www.gamasutra.com/redesign/images/corner_bottom_right.gif" width=10 align=bottom></td>
        </tr>
        <tr vAlign=top>
            <td vAlign=bottom align=left width=10 bgColor=#ccc999 height=16><img height=11 src="http://www.gamasutra.com/redesign/images/corner_bottom_left.gif" width=10 align=bottom></td>
            <td vAlign=top bgColor=#ccc999 colSpan=3 height=16>
            <p align=center><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>Figure 2. Numbers at the ends of rays emanating from the camera position C represent the values left in the stencil buffer for a variety of cases. The stencil value is incremented when front faces of the shadow volume pass the depth test, and the stencil value is decremented when back faces of the shadow volume pass the depth test. The stencil value does not change when the depth test fails.<br></font></strong></font></p>
            </td>
        </tr>
    </tbody>
</table>
<p>There are two major problems with the method just described. The first is that no matter what finite distance we extrude an object&#8217;s silhouette away from a light source, it is still possible that it is not far enough to cast a shadow on every object in the scene that should intersect the shadow volume. The example shown in Figure 3 demonstrates how this problem arises when a light source is very close to a shadow-casting object. Fortunately, this problem can be elegantly solved by using a special projection matrix and extruding shadow volumes all the way to infinity.
<p>&nbsp;
<table height=274 cellSpacing=0 cellPadding=0 width=74 align=center border=0>
    <tbody>
        <tr>
            <td vAlign=top width=5 bgColor=#ccc999 height=3 rowSpan=2>
            <div align=right><img height=11 src="http://www.gamasutra.com/redesign/images/corner_top_left.gif" width=10 align=top> </div>
            </td>
            <td vAlign=top bgColor=#ccc999 colSpan=3 height=3 rowSpan=2><br><img height=399 src="http://www.gamasutra.com/features/20021011/fig_03.gif" width=150> </td>
            <td vAlign=top align=right width=5 bgColor=#ccc999 height=3><img height=11 src="http://www.gamasutra.com/redesign/images/corner_top_right.gif" width=10 align=top></td>
        </tr>
        <tr>
            <td vAlign=bottom align=right width=15 bgColor=#ccc999 rowSpan=2><img height=11 src="http://www.gamasutra.com/redesign/images/corner_bottom_right.gif" width=10 align=bottom></td>
        </tr>
        <tr vAlign=top>
            <td vAlign=bottom align=left width=10 bgColor=#ccc999 height=16><img height=11 src="http://www.gamasutra.com/redesign/images/corner_bottom_left.gif" width=10 align=bottom></td>
            <td vAlign=top bgColor=#ccc999 colSpan=3 height=16>
            <p align=center><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>Figure 3. No matter what finite distance an object&#8217;s silhouette is extruded away from a light source, moving the light close enough to the object can result in a shadow volume that cannot reach other objects in the scene.<br></font></strong></font></p>
            </td>
        </tr>
    </tbody>
</table>
<p>The second problem shows up when the camera lies inside the shadow volume or the shadow volume is clipped by the near plane. Either of these occurrences can leave incorrect values in the stencil buffer causing the wrong surfaces to be illuminated. The solution to this problem is to add caps to the shadow volume geometry, making it a closed surface, and using different stencil operations. The two caps added to the shadow volume are derived from the object&#8217;s triangle mesh as follows. A front cap is constructed using the unmodified vertices of triangles facing toward the light source. A back cap is constructed by projecting the vertices of triangles facing away from the light source to infinity. For the resulting closed shadow volume, we render back faces (with respect to the camera) using a stencil operation that increments the stencil value whenever the depth test fails, and we render front faces using a stencil operation that decrements the stencil value whenever the depth test fails. As shown in Figure 4, this technique leaves nonzero values in the stencil buffer for any surface intersecting the shadow volume for arbitrary camera positions. Rendering shadow volumes in this manner is more expensive than using the original technique, but we can determine when it&#8217;s safe to use the less-costly depth-pass method without having to worry about capping our shadow volumes.
<p>&nbsp;
<table height=112 cellSpacing=0 cellPadding=0 width=74 align=center border=0>
    <tbody>
        <tr>
            <td vAlign=top width=5 bgColor=#ccc999 height=3 rowSpan=2>
            <div align=right><img height=11 src="http://www.gamasutra.com/redesign/images/corner_top_left.gif" width=10 align=top> </div>
            </td>
            <td vAlign=top bgColor=#ccc999 colSpan=3 height=3 rowSpan=2><br><img height=377 src="http://www.gamasutra.com/features/20021011/fig_04.gif" width=450> </td>
            <td vAlign=top align=right width=5 bgColor=#ccc999 height=3><img height=11 src="http://www.gamasutra.com/redesign/images/corner_top_right.gif" width=10 align=top></td>
        </tr>
        <tr>
            <td vAlign=bottom align=right width=15 bgColor=#ccc999 rowSpan=2><img height=11 src="http://www.gamasutra.com/redesign/images/corner_bottom_right.gif" width=10 align=bottom></td>
        </tr>
        <tr vAlign=top>
            <td vAlign=bottom align=left width=10 bgColor=#ccc999 height=16><img height=11 src="http://www.gamasutra.com/redesign/images/corner_bottom_left.gif" width=10 align=bottom></td>
            <td vAlign=top bgColor=#ccc999 colSpan=3 height=16>
            <p align=center><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>Figure 4. Using a capped shadow volume and depth-fail stencil operations allows the camera to be inside the shadow volume. The stencil value is incremented when back faces of the shadow volume fail the depth test, and the stencil value is decremented when front faces of the shadow volume fail the depth test. The stencil value does not change when the depth test passes.<br></font></strong></font></p>
            </td>
        </tr>
    </tbody>
</table>
<p>The details of everything just described are discussed throughout the remainder of this article. In summary, the rendering algorithm for a single frame runs through the following steps.
<blockquote><strong>A</strong> Clear the frame buffer and perform an ambient rendering pass. Render the visible scene using any surface shading attribute that does not depend on any particular light source.</blockquote>
<blockquote><strong>B</strong> Choose a light source and determine what objects may cast shadows into the visible region of the world. If this is not the first light to be rendered, clear the stencil buffer.</blockquote>
<blockquote><strong>C</strong> For each object, calculate the silhouette representing the boundary between triangles facing toward the light source and triangles facing away from the light source. Construct a shadow volume by extruding the silhouette away from the light source.</blockquote>
<blockquote><strong>D</strong> Render the shadow volume using specific stencil operations that leave nonzero values in the stencil buffer where surfaces are in shadow.</blockquote>
<blockquote><strong>E</strong> Perform a lighting pass using the stencil test to mask areas that are not illuminated by the light source.</blockquote>
<blockquote><strong>F</strong> Repeat steps B through E for every light source that may illuminate the visible region of the world.</blockquote>
<p>For a scene illuminated by <em>n</em> lights, this algorithm requires at least <em>n</em>+1 rendering passes. More than <em>n</em>+1 passes may be necessary if surface shading calculations for a single light source cannot be accomplished in a single pass. To efficiently render a large scene containing many lights, one must be careful during each pass to render only objects that could potentially be illuminated by a particular light source. An additional optimization using the scissor rectangle can also save a significant amount of rasterization work -- this optimization is discussed in the last section of this article.
<div align=center>
<p>______________________________________________________</p>
<p align=right><font face="Verdana, Arial, Helvetica, sans-serif" size=-2><img height=9 src="http://www.gamasutra.com/db_area/images/layout/99_icon_arrow.gif" width=6></font><font face="Verdana, Arial, Helvetica, sans-serif" color=#0000ff><strong><a href="http://www.gamasutra.com/features/20021011/lengyel_02.htm"><u>Infinite View Frustums</u></a></strong></font></p>
</div>
<blockquote></blockquote>
<div align=right></div>
<blockquote></blockquote><!-- #EndEditable -->
<img src ="http://www.cppblog.com/zmj/aggbug/68559.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2008-12-04 14:23 <a href="http://www.cppblog.com/zmj/archive/2008/12/04/68559.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Inside Direct3D: Stencil Buffers</title><link>http://www.cppblog.com/zmj/archive/2008/12/03/68438.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Wed, 03 Dec 2008 01:46:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2008/12/03/68438.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/68438.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2008/12/03/68438.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/68438.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/68438.html</trackback:ping><description><![CDATA[<p><a href="http://gamasutra.com/features/20000807/kovach_01.htm">http://gamasutra.com/features/20000807/kovach_01.htm</a><font face=Verdana size=5><br>Inside Direct3D: Stencil Buffers</font><br></p>
<p align=left><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>One aspect of advanced rendering we haven't discussed yet is stenciling, a technique that can be useful for developing commercial applications. If you want your 3D applications to stand apart from the crowd, you'd be wise to combine stenciling with the texturing techniques you learned about in earlier chapters. This chapter will detail how to use stenciling and show you the different types of effects you can generate with it.<br><br>Many 3D games and simulations on the market use cinema-quality special effects to add to their dramatic impact. You can use stencil buffers to create effects such as composites, decals, dissolves, fades, outlines, silhouettes, swipes, and shadows. Stencil buffers determine whether the pixels in an image are drawn. To perform this function, stencil buffers let you enable or disable drawing to the render-target surface on a pixel-by-pixel basis. This means your software can "mask" portions of the rendered image so that they aren't displayed.<br><br>When the stenciling feature is enabled, Microsoft Direct3D performs a stencil test for each pixel that it plans to write to the render-target surface. The stencil test uses a stencil reference value, a stencil mask, a comparison function, and a pixel value from the stencil buffer that corresponds to the current pixel in the target surface. Here are the specific steps used in this test: </font>
<ol>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>Perform a bitwise AND operation of the stencil reference value with the stencil mask.</font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>Perform a bitwise AND operation on the stencil-buffer value for the current pixel with the stencil mask.</font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>Compare the results of Step 1 and Step 2 by using the comparison function. </font></li>
</ol>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>By controlling the comparison function, the stencil mask, the stencil reference value, and the action taken when the stencil test passes or fails, you can control how the stencil buffer works. As long as the test succeeds, the current pixel will be written to the target. The default comparison behavior (the value that the D3DCMPFUNC enumerated type defines for D3DCMP_ALWAYS) is to write the pixel without considering the contents of the stencil buffer. You can change the comparison function to any function you want by setting the value of the D3DRENDERSTATE_STENCILFUNC render state and passing one of the members of the D3DCMPFUNC enumerated type.<br><br><strong>Creating a Stencil Buffer</strong><br><br>Before creating a stencil buffer, you need to determine what stenciling capabilities the target system supports. To do this, call the <em>IDirect3DDevice7::GetCaps</em> method. The <em>dwStencilCaps</em> flags specify the stencil-buffer operations that the device supports. The reported flags are valid for all three stencil-buffer operation render states: D3DRENDERSTATE_STENCILFAIL, D3DRENDERSTATE_STENCILPASS, and D3DRENDERSTATE_STENCILZFAIL. Direct3D defines the following flags for <em>dwStencilCaps: </em></font><font face="Arial, Helvetica, sans-serif">
<ul>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILCAPS_DECR</strong> Indicates that the D3DSTENCILOP_DECR operation is supported<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILCAPS_DECRSAT</strong> Indicates that the D3DSTENCILOP_DECRSAT operation is supported<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILCAPS_INCR</strong> Indicates that the <br>D3DSTENCILOP_INCR operation is supported<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILCAPS_INCRSAT</strong> Indicates that the D3DSTENCILOP_INCRSAT operation is supported<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILCAPS_INVERT</strong> Indicates that the D3DSTENCILOP_INVERT operation is supported<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILCAPS_KEEP</strong> Indicates that the D3DSTENCILOP_KEEP operation is supported<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILCAPS_REPLACE</strong> Indicates that the D3DSTENCILOP_REPLACE operation is supported<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILCAPS_ZERO</strong> Indicates that the D3DSTENCILOP_ZERO operation is supported<em><br></em></font></li>
</ul>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>Direct3D embeds the stencil-buffer information with the depth-buffer data. To determine what formats of depth buffers and stencil buffers the target system's hardware supports, call the <em>IDirect3D7::EnumZBufferFormats</em> method, which has the following declaration:<br><br>HRESULT IDirect3D7::EnumZBufferFormats (<br>&nbsp;&nbsp;&nbsp;&nbsp;REFCLSID riidDevice,<br>&nbsp;&nbsp;&nbsp;&nbsp;LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback,<br>&nbsp;&nbsp;&nbsp;&nbsp;LPVOID lpContext<br>);</font></p>
<p></font>
<table cellSpacing=3 cellPadding=3 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td bgColor=#000000>
            <div align=center><strong><font face="Arial, Helvetica, sans-serif" color=#ffffff size=-1>Parameter</font></strong></div>
            </td>
            <td bgColor=#000000>
            <div align=center><strong><font face="Arial, Helvetica, sans-serif" color=#ffffff size=-1>Description</font></strong></div>
            </td>
        </tr>
        <tr>
            <td bgColor=#cccc99><em><font face="Arial, Helvetica, sans-serif">riidDevice</font></em></td>
            <td bgColor=#cccc99><font face="Arial, Helvetica, sans-serif">A reference to a globally unique identifier (GUID) for the device whose depth-buffer formats you want enumerated</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff><em><font face="Arial, Helvetica, sans-serif">IpEnumCallback</font></em></td>
            <td bgColor=#ffffff><font face="Arial, Helvetica, sans-serif">The address of a <em>D3DEnumPixelFormatsCallback </em>function you want called for each supported depth-buffer format</font></td>
        </tr>
        <tr>
            <td bgColor=#cccc99><em><font face="Arial, Helvetica, sans-serif">IpContext</font></em></td>
            <td bgColor=#cccc99><font face="Arial, Helvetica, sans-serif">Application-defined data that is passed to the callback function</font></td>
        </tr>
    </tbody>
</table>
</p>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>If the method succeeds, it returns the value D3D_OK. If it fails, the method returns one of these four values: </font>
<ul>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>DDERR_INVALIDOBJECT<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>DDERR_INVALIDPARAMS<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>DDER_NOZBUFFERHW<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>DDERR_OUTOFMEMORY</font> </li>
</ul>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>The code in <a href="http://gamasutra.com/features/20000807/kovach_l1.htm"><u><font color=#0000ff>listing 1</font></u></a><a name=1></a> determines what stencil buffer formats are available and what operations are supported and then creates a stencil buffer. As you can see, this code notes whether the stencil buffer supports more than 1-bit -- some stenciling techniques must be handled differently if only a 1-bit stencil buffer is available.<br></font></p>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>Clearing a Stencil Buffer<br></strong><br>The<em> IDirect3DDevice7</em> interface includes the <em>Clear</em> method, which you can use to simultaneously clear the render target's color buffer, depth buffer, and stencil buffer. Here's the declaration for the <em>IDirect3DDevice7::Clear</em> method:</font></p>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>&nbsp;&nbsp;&nbsp;&nbsp;HRESULT IDirect3DDevice7::Clear(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD dwCount,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LPD3DRECT lpRects,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD dwFlags, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D3DVALUE dvZ, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD dwStencil<br>&nbsp;&nbsp;&nbsp;&nbsp;); </font></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=3 cellPadding=3 width="97%" align=center border=0>
    <tbody>
        <tr>
            <td bgColor=#000000>
            <div align=center><font color=#ffffff><strong><font face="Arial, Helvetica, sans-serif" size=-1>Parameter</font></strong></font></div>
            </td>
            <td bgColor=#000000>
            <div align=center><font color=#ffffff><strong><font face="Arial, Helvetica, sans-serif" size=-1>Description</font></strong></font></div>
            </td>
        </tr>
        <tr bgColor=#cccc99>
            <td><font face="Arial, Helvetica, sans-serif">dwCount</font></td>
            <td><font face="Arial, Helvetica, sans-serif">The number of rectangles in the array at lpRects.</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff>
            <div align=center><font face="Arial, Helvetica, sans-serif">IpRects</font></div>
            </td>
            <td bgColor=#ffffff><font face="Arial, Helvetica, sans-serif">An array of D3DRECT structures defining the rectangles to be cleared. You can set a rectangle to the dimensions of the render-target surface to clear the entire surface. Each of these rectangles uses screen coordinates that correspond to points on the render-target surface. The coordinates are clipped to the bounds of the viewport rectangle.</font></td>
        </tr>
        <tr bgColor=#cccc99>
            <td><font face="Arial, Helvetica, sans-serif">dwFlags</font></td>
            <td><font face="Arial, Helvetica, sans-serif">Flags indicating which surfaces should be cleared. This parameter can be any combination of the following flags, but at least one flag must be used:</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff>&nbsp;</td>
            <td bgColor=#ffffff><font face="Arial, Helvetica, sans-serif"><strong>D3DCLEAR_TARGET </strong>Clear the render-target surface to the color in the dwColor parameter. <strong>D3DCLEAR_STENCIL</strong> Clear the stencil buffer to the value in the dwStencil parameter.</font></td>
        </tr>
        <tr>
            <td bgColor=#cccc99>&nbsp;</td>
            <td bgColor=#cccc99><font face="Arial, Helvetica, sans-serif">D3DCLEAR_ZBUFFER Clear the depth buffer to the value in the dvZ parameter.</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff><font face="Arial, Helvetica, sans-serif">dwColor</font></td>
            <td bgColor=#ffffff><font face="Arial, Helvetica, sans-serif"><strong>D3DCLEAR_ZBUFFER</strong> Clear the depth buffer to the value in the dvZ parameter..</font></td>
        </tr>
        <tr>
            <td bgColor=#cccc99 height=25><font face="Arial, Helvetica, sans-serif">dvZ</font></td>
            <td bgColor=#cccc99 height=25><font face="Arial, Helvetica, sans-serif">A 32-bit RGBA color value to which the render-target surface will be cleared.</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff height=96><font face="Arial, Helvetica, sans-serif">dwStencil</font></td>
            <td bgColor=#ffffff height=96><font face="Arial, Helvetica, sans-serif">The new z value that this method stores in the depth buffer. This parameter can range from 0.0 to 1.0, inclusive. The value of 0.0 represents the nearest distance to the viewer, and 1.0 represents the farthest distance.</font></td>
        </tr>
        <tr>
            <td bgColor=#cccc99>&nbsp;</td>
            <td bgColor=#cccc99><font face="Arial, Helvetica, sans-serif">The integer value to store in each stencil-buffer entry. This parameter can range from 0 to 2n-1 inclusive, in which n is the bit depth of the stencil buffer.</font></td>
        </tr>
    </tbody>
</table>
</p>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>The <em>IDirect3DDevice7::Clear</em> method still accepts the older D3DCLEAR_TARGET flag, which clears the render target using an RGBA color you provide in the <em>dwColor</em> parameter. This method also still accepts the D3DCLEAR_ZBUFFER flag, which clears the depth buffer to a depth you specify in <em>dvZ</em> (in which 0.0 is the closest distance and 1.0 is the farthest). DirectX 6 introduced the D3DCLEAR_STENCIL flag, which you can use to reset the stencil bits to the value you specify in the <em>dwStencil </em>parameter. This value can be an integer ranging from 0 to 2n-1, in which n is the bit depth of the stencil buffer. <br><br></font></p>
<h4 align=center><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>________________________________________________________</font></h4>
<p align=right><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><img height=9 src="http://gamasutra.com/db_area/images/layout/99_icon_arrow.gif" width=6><a href="http://gamasutra.com/features/20000807/kovach_02.htm"><strong><u><font color=#800080>Configuring the Stenciling State</font></u></strong></a></font></p>
<p><!-- #EndEditable --><br><font face=Verdana>Configuring the Stenciling State</font><br><font face=Verdana size=2>You control the various settings for the stencil buffer using the <em>IDirect3DDevice7::</em><br><em>SetRenderState</em> method. </font><a href="http://gamasutra.com/features/20000807/kovach_l2.htm"><u><font face=Verdana color=#0000ff size=2>Listing 2</font></u></a><a name=2></a><font face=Verdana size=2> shows the stencil-related members of the D3DRENDERSTATETYPE enumerated type. </font></p>
<p><font face=Verdana size=2>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;These are the definitions for the stencil-related render states: </font><font face="Arial, Helvetica, sans-serif">
<ul>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DRENDERSTATE_STENCILENABLE </strong>Use this member to enable or disable stenciling. To enable stenciling, use this member with TRUE; to disable stenciling, use it with FALSE. The default value is FALSE.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DRENDERSTATE_STENCILFAIL </strong>Use this member to indicate the stencil operation to perform if the stencil test fails. The stencil operation can be one of the members of the D3DSTENCILOP enumerated type. The default value is D3DSTENCILOP_KEEP.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DRENDERSTATE_STENCILZFAIL </strong>Use this member to indicate the stencil operation to perform if the stencil test passes and the depth test (z-test) fails. The operation can be one of the members of the D3DSTENCILOP enumerated type. The default value is D3DSTENCILOP_KEEP.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DRENDERSTATE_STENCILPASS </strong>Use this member to indicate the stencil operation to perform if both the stencil test and the depth test (z-test) pass. The operation can be one of the members of the D3DSTENCILOP enumerated type. The default value is D3DSTENCILOP_KEEP.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DRENDERSTATE_STENCILFUNC </strong>Use this member to indicate the comparison function for the stencil test. The comparison function can be one of the members of the D3DCMPFUNC enumerated type. The default value is D3DCMP_ALWAYS. This function compares the reference value to a stencil-buffer entry and applies only to the bits in the reference value and stencil-buffer entry that are set in the stencil mask. (The D3DRENDERSTATE_STENCILMASK render state sets the stencil mask.) If the comparison is true, the stencil test passes.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DRENDERSTATE_STENCILREF </strong>Use this member to indicate the integer reference value for the stencil test. The default value is 0.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DRENDERSTATE_STENCILMASK </strong>Use this member to specify the mask to apply to the reference value and each stencil-buffer entry to determine the significant bits for the stencil test. The default mask is 0xFFFFFFFF.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DRENDERSTATE_STENCILWRITEMASK </strong>Use this member to specify the mask to apply to values written into the stencil buffer. The default mask is 0xFFFFFFFF. <br><br></font></li>
</ul>
</font>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>The D3DSTENCILOP enumerated type describes the stencil operations for the D3DRENDERSTATE_STENCILFAIL, D3DRENDERSTATE_STENCILZFAIL, and D3DRENDERSTATE_STENCILPASS render states. Here's the definition of D3DSTENCILOP: </font></p>
<font face="Arial, Helvetica, sans-serif">
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>&nbsp;&nbsp;typedef enum _D3DSTENCILOP {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DSTENCILOP_KEEP &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 1,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DSTENCILOP_ZERO &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 2,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DSTENCILOP_REPLACE &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;= 3,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DSTENCILOP_INCRSAT &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;= 4,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DSTENCILOP_DECRSAT &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 5,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DSTENCILOP_INVERT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 6,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DSTENCILOP_INCR &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 7,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DSTENCILOP_DECR &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 8,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DSTENCILOP_FORCE_DWORD &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0x7fffffff<br>&nbsp;&nbsp;} D3DSTENCILOP;</font></p>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;These members serve the following purposes: </font>
<ul>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILOP_KEEP</strong> Indicates that you don't want the entry in the stencil buffer updated. This is the default operation.<br><strong><br></strong></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILOP_ZERO</strong> Sets the stencil-buffer entry to 0.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILOP_REPLACE</strong> Replaces the stencil-buffer entry with the reference value.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILOP_INCRSAT</strong> Increments the stencil-buffer entry, clamping to the maximum value.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILOP_DECRSAT </strong>Decrements the stencil-buffer entry, clamping to 0.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILOP_INVERT</strong> Inverts the bits in the stencil-buffer entry.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILOP_INCR</strong> Increments the stencil-buffer entry, wrapping to 0 if the new value exceeds the maximum value.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILOP_DECR</strong> Decrements the stencil-buffer entry, wrapping to the maximum value if the new value is less than 0.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>D3DSTENCILOP_FORCE_DWORD</strong> Forces this enumeration to be compiled to 32 bits; this value isn't used.</font> </li>
</ul>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>Let's walk through some code that uses the stencil buffer while rendering a scene. This code is from a sample that shows how to draw shadows. For now, don't worry about how all this code generates shadows-the algorithm is described later in the chapter.</font></p>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>The shadow-rendering code starts out by disabling the depth buffer and enabling the stencil buffer:</font></p>
</font>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>&nbsp;&nbsp;&nbsp;&nbsp;//--------------------------------------------------<br>&nbsp;&nbsp;&nbsp;&nbsp;// Name: RenderShadow<br>&nbsp;&nbsp;&nbsp;&nbsp;// Desc: <br>&nbsp;&nbsp;&nbsp;&nbsp;//------------------------------------------------<br>&nbsp;&nbsp;&nbsp;&nbsp;HRESULT CMyD3DApplication::RenderShadow()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Turn off depth buffer and turn on <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stencil buffer.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_pd3dDevice-&gt;SetRenderState(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D3DRENDERSTATE_ZWRITEENABLE,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FALSE );<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_pd3dDevice-&gt;SetRenderState(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D3DRENDERSTATE_STENCILENABLE,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TRUE );</font></p>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>Next the code sets the comparison function that performs the stencil test by calling the <em>IDirect3DDevice7::SetRenderState</em> method and setting the first parameter to D3DRENDERSTATE_STENCILFUNC. The second parameter is set to a member of the D3DCMPFUNC enumerated type. In this code, we want to update the stencil buffer everywhere a primitive is rendered, so we use D3DCMP_ALWAYS:</font></p>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>&nbsp;&nbsp;&nbsp;&nbsp; //<br>&nbsp;&nbsp;&nbsp;&nbsp;// Set up stencil comparison function, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reference value, and&nbsp;masks.<br>&nbsp;&nbsp;&nbsp;&nbsp;// Stencil test passes if ((ref &amp; mask) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmpfn (stencil &amp; mask))<br>&nbsp;&nbsp;&nbsp;&nbsp;// is true.<br>&nbsp;&nbsp;&nbsp;&nbsp;//<br>&nbsp;&nbsp;&nbsp;&nbsp;m_pd3dDevice-&gt;SetRenderState(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D3DRENDERSTATE_STENCILFUNC,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DCMP_ALWAYS );<br></font></p>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>In this sample, we don't want the stencil buffer to change if either the stencil buffer test or the depth buffer test fails, so we set the appropriate states to D3DSTENCILOP_KEEP:<br><br>&nbsp;&nbsp;&nbsp;&nbsp; m_pd3dDevice-&gt;SetRenderState(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D3DRENDERSTATE_STENCILZFAIL,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DSTENCILOP_KEEP );<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_pd3dDevice-&gt;SetRenderState(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D3DRENDERSTATE_STENCILFAIL,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DSTENCILOP_KEEP );<br><br>The settings in <a href="http://gamasutra.com/features/20000807/kovach_l3.htm"><u><font color=#0000ff>listing 3</font></u></a><a name=3></a> are different depending on whether a 1-bit or a multibit stencil buffer is present. If the stencil buffer has only 1 bit, the value 1 is stored in the stencil buffer whenever the stencil test passes. Otherwise, an increment operation (either D3DSTENCILOP_INCR or D3DSTENCILOP_INCRSAT) is applied if the stencil test passes. At this point, the stencil state is configured and the code is ready to render some primitives.</font></p>
<p>
<p align=center><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>________________________________________________________</font></p>
<p align=right><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><img height=9 src="http://gamasutra.com/db_area/images/layout/99_icon_arrow.gif" width=6><a href="http://gamasutra.com/features/20000807/kovach_03.htm"><strong><u><font color=#800080>Creating Effects</font></u></strong></a></font></p>
<p><!-- #EndEditable --><font face=Verdana>Creating Effects</font><br><font face=Verdana size=2>Now that you've seen how to create stencil buffers and configure how they work, let's look at some of the effects you can render with them. The following sections describe several ways Microsoft recommends using stencil buffers. Each of these approaches produces impressive results, but a few of them have drawbacks.<br></font><strong><br><em><font face=Verdana size=2>Composites</font></em></strong><br><br><font face=Verdana size=2>You can use stencil buffers for compositing 2D or 3D images onto a 3D scene. By using a mask in the stencil buffer to occlude a portion of the render-target surface, you can write stored 2D information (such as text or bitmaps). You can also render 3D primitives -- or for that matter a complete scene -- to the area of the render-target surface that you specify in a stencil mask.<br><br>Developers often use this effect to composite several scenes in simulations and games. Many driving games feature a rear view mirror that displays the scene behind the driver. You can composite this second 3D scene with the driver's view forward by using a stencil to block the portion to which you want the mirror image rendered. You can also use composites to create 2D "cockpits" for vehicle simulations by combining a 2D, bitmapped image of the cockpit with the final, rendered 3D scene.<br></font><em><strong><br><font face=Verdana size=2>Decals</font></strong></em><br><br><font face=Verdana size=2>You can use decals to control which pixels form a primitive image you draw to a render-target surface. When you apply a texture to an object (for example, applying scratch marks to a floor), you need the texture (the scratch marks) to appear immediately on top of the object (the floor). Because the z values of the scratch marks and the floor are equal, the depth buffer might not yield consistent results, meaning that some pixels in the back primitive might be rendered on top of those in the front primitive. This overlap, which is commonly known as z-fighting or flimmering, can cause the final image to shimmer as you animate from one frame to the next.<br><br>You can prevent flimmering by using a stencil to mask the section of the back primitive on which you want the decal to appear. You can then turn off z-buffering and render the image of the front primitive into the masked area of the render-target surface.<br></font><em><strong><br><font face=Verdana size=2>Dissolves</font></strong></em><br><br><font face=Verdana size=2>You can use dissolves to gradually replace an image by displaying a series of frames that transition from one image to another. In Chapter 8, you saw how to use multiple-texture blending to create this effect by gradually blending two textures together. Stencil buffers allow you to produce similar dissolves, except that a stencil-based dissolve looks more pixelated than a multiple-texture blending one. However, stencil buffers let you use texture-blending capabilities for other effects while performing a dissolve. This capability enables you to efficiently produce more complex effects than you could by using texture blending alone.<br><br>A stencil buffer can perform a dissolve by controlling which pixels you draw from two different images to the render-target surface. You can perform a dissolve by defining a base stencil mask for the first frame and altering it incrementally or by defining a series of stencil masks and copying them into the stencil buffer on successive frames.<br><br>To start a dissolve, set the stencil function and stencil mask so that most of the pixels from the starting image pass the stencil test and most of the ending image's pixels fail. For each subsequent frame, update the stencil mask to allow fewer pixels in the starting image to pass the test and more pixels in the ending image to pass. By controlling the stencil mask, you can create a variety of dissolve effects.<br><br>Although this approach can produce some fantastic effects, it can be a bit slow on some systems. You should test the performance on your target systems to verify that this approach works efficiently for your application.<br></font><em><strong><br><font face=Verdana size=2>Fades</font></strong></em><br><br><font face=Verdana size=2>You can fade in or out using a form of dissolving. To perform this effect, use any dissolve pattern you want. To fade in, use a stencil buffer to dissolve from a black or white image to a rendered 3D scene. To fade out, start with a rendered 3D scene and dissolve to black or white. As with dissolves, you should check the performance of fades on the target systems to verify that their speed and appearance is acceptable.<br></font><em><strong><br><font face=Verdana size=2>Outlines</font></strong></em><br><br><font face=Verdana size=2>You can apply a stencil mask to a primitive that's the same shape but slightly smaller than the primitive. The resulting image will contain only the primitive's outline. You can then fill this stencil-masked area of the primitive with a color or set of colors to produce an outline around the image.<br></font><em><strong><br><font face=Verdana size=2>Silhouettes</font></strong></em><br><br><font face=Verdana size=2>When you set the stencil mask to the same size and shape as the primitive you're rendering, Direct3D produces a final image containing a "black hole" where the primitive should be. By coloring this hole, you can produce a silhouette of the primitive.<br></font><em><strong><br><font face=Verdana size=2>Swipes</font></strong></em><br><br><font face=Verdana size=2>A swipe makes an image appear as though it's sliding into the scene over another image. You can use stencil masks to disable the writing of pixels from the starting image and enable the writing of pixels from the ending image. To perform a swipe, you can define a series of stencil masks that Direct3D will load into the stencil buffer in a succession of frames, or you can change the starting stencil mask for a series of successive frames. Both methods cause the final image to look as though it's gradually sliding on top of the starting image from right to left, left to right, top to bottom, and so on.<br><br>To handle a swipe, remember to read the pixels from the ending image in the reverse order in which you're performing the swipe. For example, if you're performing a swipe from left to right, you need to read pixels from the ending image from right to left. As with dissolves, this effect can render somewhat slowly. Therefore, you should test its performance on your target systems.<br></font><em><strong><br><font face=Verdana size=2>Shadows</font></strong></em><br><br><font face=Verdana size=2>Shadow volumes, which allow an arbitrarily shaped object to cast a shadow onto another arbitrarily shaped object, can produce some incredibly realistic effects. To create shadows with stencil buffers, take an object you want to cast a shadow. Using this object and the light source, build a set of polygonal faces (a shadow volume) to represent the shadow.<br><br>You can compute the shadow volume by projecting the vertices of the shadow-casting object onto a plane that's perpendicular to the direction of light from the light source, finding the 2D convex hull of the projected vertices (that is, a polygon that "wraps around" all the projected vertices), and extruding the 2D convex hull in the light direction to form the 3D shadow volume. The shadow volume must extend far enough so that it covers any objects that will be shadowed. To simplify computation, you might want the shadow caster to be a convex object.<br><br>To render a shadow, you must first render the geometry and then render the shadow volume without writing to the depth buffer or the color buffer. Use alpha blending to avoid having to write to the color buffer. Each place that the shadow volume appears will be marked in the stencil buffer. You can then reverse the cull and render the backfaces of the shadow volume, unmarking all the pixels that are covered in the stencil buffer. All these pixels will have passed the z-test, so they'll be visible behind the shadow volume. Therefore, they won't be in shadow. The pixels that are still marked are the ones lying inside the front and back boundaries of the shadow volume-these pixels will be in shadow. You can blend these pixels with a large black rectangle that covers the viewport to generate the shadow.<br></font><strong><br><font face=Verdana size=2>The ShadowVol and ShadowVol2 Demos</font></strong><br><br><font face=Verdana size=2>The ShadowVol sample on the companion CD in the \mssdk\Samples\Multimedia\D3dim\Src\ShadowVol directory contains a project that shows how to create and use stencil buffers to implement shadow volumes. The code illustrates how to use shadow volumes to cast the shadow of an arbitrarily shaped object onto another arbitrarily shaped object. The ShadowVol2 sample, which the Microsoft DirectX 7 SDK setup program on the companion CD installs in the \mssdk\Samples\Multimedia\D3dim\Src\ShadowVol2 directory on your hard disk, provides some additional capabilities for producing shadows with stencils.<br><br>The sample application provides these features in its Shadow Modes menu: </font></p>
<ul>
    <li><font size=2><font face=Verdana><strong>Draw Shadows:</strong> Allows you to turn on and off shadow rendering.<br><br></font></font><font face="Arial, Helvetica, sans-serif">
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>Show Shadow Volumes:</strong> Draws the shadow volumes used to compute the shadows rather than drawing the shadows themselves.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>Draw Shadow Volume Caps:</strong> When you turn this item off, some "extra" shadows might become visible where the far caps of the cylindrical shadow volumes happen to be visible.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>1-Bit Stencil Buffer Mode: </strong>Tells the code to use a different algorithm that uses only 1 bit of stencil buffer, which won't allow overlapping shadows. If the device supports only 1-bit stencils, you'll be forced to use this mode.<br><br></font>
    <li><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>Z-Order Shadow Vols in 1-Bit Stencil Buffer Mode:</strong> The shadow volumes must be rendered front to back, which means that if you don't check this option, rendering might be incorrect.</font> </li>
</ul>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>Figure 12-1, Figure 12-2, and Figure 12-3 show three views of the scene generated by the ShadowVol2 sample application. You can see the shadows in Figures 12-1 and 12-3; Figure 12-2 illustrates the shadow volumes.</font></p>
</font>
<p>&nbsp;</p>
<p>
<table cellSpacing=3 cellPadding=3 width="42%" align=center border=0>
    <tbody>
        <tr bgColor=#cccc99>
            <td>
            <div align=left><font face="Arial, Helvetica, sans-serif">&lt;&lt;"F12xi01.eps"&gt;&gt; </font></div>
            </td>
        </tr>
        <tr bgColor=#000000>
            <td>
            <div align=center><font face="Arial, Helvetica, sans-serif"><strong><font face="Verdana, Arial, Helvetica, sans-serif" color=#ffffff size=-1>Figure 12-1. <em>Shadow cast</em></font></strong></font></div>
            </td>
        </tr>
    </tbody>
</table>
<font face="Verdana, Arial, Helvetica, sans-serif" size=-1><br></font>
<table cellSpacing=3 cellPadding=3 width="48%" align=center border=0>
    <tbody>
        <tr bgColor=#cccc99>
            <td><font face="Arial, Helvetica, sans-serif">&lt;&lt;"F12xi02.eps"&gt;&gt;</font></td>
        </tr>
        <tr bgColor=#000000>
            <td>
            <div align=center><font face="Arial, Helvetica, sans-serif" size=-1><strong><font face="Verdana, Arial, Helvetica, sans-serif" color=#ffffff>Figure 12-2. Shadow volumes</font></strong></font></div>
            </td>
        </tr>
    </tbody>
</table>
<font face="Verdana, Arial, Helvetica, sans-serif" size=-1><br></font>
<table cellSpacing=3 cellPadding=3 width="75%" align=center border=0>
    <tbody>
        <tr bgColor=#cccc99>
            <td>
            <div align=left><font face="Arial, Helvetica, sans-serif">&lt;&lt;"F12xi03.eps"&gt;&gt;</font></div>
            </td>
        </tr>
        <tr bgColor=#000000>
            <td>
            <div align=center><font face="Arial, Helvetica, sans-serif"><strong><font face="Verdana, Arial, Helvetica, sans-serif" color=#ffffff size=-1>Figure 12-3. Another view of the rendered shadows</font></strong></font></div>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1><strong>The Code So Far</strong><br><br>In this chapter, we didn't add any new code to the RoadRage project. To see these effects in action, refer to the ShadowVol and ShadowVol2 demo projects included in the DirectX samples.<br><strong><br>Conclusion</strong><br><br>In this chapter, you learned about stencil buffers and the exciting effects they can produce. In today's market, making your code stand out is a requisite if you want it to sell your applications and keep your users coming back for more. Incorporating strategic stencil-buffer effects into the introduction and into the body of a 3D real-time game might help you win over even the most discriminating game players.<br></font></p>
<p><font face="Verdana, Arial, Helvetica, sans-serif" size=-1>In Chapter 13, we'll discuss how to load and animate 3D models. Creating animated, lifelike characters that your users can interact with is one of the most powerful capabilities you can add to any game.<br><br><strong>Peter Kovach has been involved in computer software and hardware development since the mid-1970s. After 11 years in various levels of development and project management, he was eager to being pushing the envelope in 3D virtual world development. He currently words at Medtronic, where he is the project lead developming programmable, implantable medical devices that use a next-generation graphical user interface. </strong></font></p>
<img src ="http://www.cppblog.com/zmj/aggbug/68438.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zmj/" target="_blank">zmj</a> 2008-12-03 09:46 <a href="http://www.cppblog.com/zmj/archive/2008/12/03/68438.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Collision detection</title><link>http://www.cppblog.com/zmj/archive/2008/11/22/67634.html</link><dc:creator>zmj</dc:creator><author>zmj</author><pubDate>Sat, 22 Nov 2008 15:25:00 GMT</pubDate><guid>http://www.cppblog.com/zmj/archive/2008/11/22/67634.html</guid><wfw:comment>http://www.cppblog.com/zmj/comments/67634.html</wfw:comment><comments>http://www.cppblog.com/zmj/archive/2008/11/22/67634.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zmj/comments/commentRss/67634.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zmj/services/trackbacks/67634.html</trackback:ping><description><![CDATA[<a href="http://en.wikipedia.org/wiki/Collision_detection">http://en.wikipedia.org/wiki/Collision_detection</a><br>
<h1 class=firstHeading>Collision detection</h1>
<div id=bodyContent>
<h3 id=siteSub>From Wikipedia, the free encyclopedia</h3>
<div id=contentSub></div>
<div id=jump-to-nav>Jump to: <a href="http://en.wikipedia.org/wiki/Collision_detection#column-one"><font color=#5a3696>navigation</font></a>, <a href="http://en.wikipedia.org/wiki/Collision_detection#searchInput"><font color=#5a3696>search</font></a></div>
<!-- start content -->
<div class=dablink>For collision detection on networks see <a class=mw-redirect title=CSMA/CD href="http://en.wikipedia.org/wiki/CSMA/CD"><font color=#002bb8>CSMA/CD</font></a></div>
<p>In <a class=mw-redirect title="Physical simulation" href="http://en.wikipedia.org/wiki/Physical_simulation"><font color=#002bb8>physical simulations</font></a>, <a title="Video game" href="http://en.wikipedia.org/wiki/Video_game"><font color=#002bb8>video games</font></a> and <a title="Computational geometry" href="http://en.wikipedia.org/wiki/Computational_geometry"><font color=#002bb8>computational geometry</font></a>, <strong>collision detection</strong> involves algorithms for checking for <a title=Collision href="http://en.wikipedia.org/wiki/Collision"><font color=#002bb8>collision</font></a>, i.e. intersection, of two given solids. Simulating what happens once a collision is detected is sometimes referred to as "collision response", for which see <a title="Physics engine" href="http://en.wikipedia.org/wiki/Physics_engine"><font color=#002bb8>physics engine</font></a> and <a title="Ragdoll physics" href="http://en.wikipedia.org/wiki/Ragdoll_physics"><font color=#002bb8>ragdoll physics</font></a>. Collision detection algorithms are a basic component of 3D video games. Without them, characters could go through walls and other obstacles.</p>
<table class=toc id=toc summary=Contents>
    <tbody>
        <tr>
            <td>
            <div id=toctitle>
            <h2>Contents</h2>
            <span class=toctoggle><font size=2>[</font><a class=internal id=togglelink href="javascript:toggleToc()"><font color=#002bb8 size=2>hide</font></a><font size=2>]</font></span></div>
            <ul>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Collision_detection#Overview"><font color=#5a3696><span class=tocnumber>1</span> <span class=toctext>Overview</span></font></a>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Collision_detection#Collision_detection_in_physical_simulation"><font color=#5a3696><span class=tocnumber>2</span> <span class=toctext>Collision detection in physical simulation</span></font></a>
                <ul>
                    <li class=toclevel-2><a href="http://en.wikipedia.org/wiki/Collision_detection#A_posteriori_versus_a_priori"><font color=#5a3696><span class=tocnumber>2.1</span> <span class=toctext>A posteriori versus a priori</span></font></a> </li>
                </ul>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Collision_detection#Optimization"><font color=#5a3696><span class=tocnumber>3</span> <span class=toctext>Optimization</span></font></a>
                <ul>
                    <li class=toclevel-2><a href="http://en.wikipedia.org/wiki/Collision_detection#Exploiting_temporal_coherence"><font color=#5a3696><span class=tocnumber>3.1</span> <span class=toctext>Exploiting temporal coherence</span></font></a>
                    <li class=toclevel-2><a href="http://en.wikipedia.org/wiki/Collision_detection#Pairwise_pruning"><font color=#5a3696><span class=tocnumber>3.2</span> <span class=toctext>Pairwise pruning</span></font></a>
                    <li class=toclevel-2><a href="http://en.wikipedia.org/wiki/Collision_detection#Exact_pairwise_collision_detection"><font color=#5a3696><span class=tocnumber>3.3</span> <span class=toctext>Exact pairwise collision detection</span></font></a>
                    <li class=toclevel-2><a href="http://en.wikipedia.org/wiki/Collision_detection#A_priori_pruning"><font color=#5a3696><span class=tocnumber>3.4</span> <span class=toctext>A priori pruning</span></font></a>
                    <li class=toclevel-2><a href="http://en.wikipedia.org/wiki/Collision_detection#Spatial_partitioning"><font color=#5a3696><span class=tocnumber>3.5</span> <span class=toctext>Spatial partitioning</span></font></a> </li>
                </ul>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Collision_detection#Video_games"><font color=#5a3696><span class=tocnumber>4</span> <span class=toctext>Video games</span></font></a>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Collision_detection#Open_Source_Collision_Detection"><font color=#5a3696><span class=tocnumber>5</span> <span class=toctext>Open Source Collision Detection</span></font></a>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Collision_detection#References"><font color=#5a3696><span class=tocnumber>6</span> <span class=toctext>References</span></font></a>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Collision_detection#See_also"><font color=#5a3696><span class=tocnumber>7</span> <span class=toctext>See also</span></font></a>
                <li class=toclevel-1><a href="http://en.wikipedia.org/wiki/Collision_detection#External_links"><font color=#5a3696><span class=tocnumber>8</span> <span class=toctext>External links</span></font></a> </li>
            </ul>
            </td>
        </tr>
    </tbody>
</table>
<script type=text/javascript>
//<![cdata[
if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); }
//]]&gt;
</script>
<p><a id=Overview name=Overview></a></p>
<h2><span class=editsection>[<a title="Edit section: Overview" href="http://en.wikipedia.org/w/index.php?title=Collision_detection&amp;action=edit&amp;section=1"><font color=#002bb8>edit</font></a>]</span> <span class=mw-headline>Overview</span></h2>
<div class="thumb tright">
<div class=thumbinner style="WIDTH: 202px"><a class=image title="Billiards balls hitting each other are a classic example applicable within the science of collision detection." href="http://en.wikipedia.org/wiki/Image:Billiards_balls.jpg"><img class=thumbimage height=150 alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Billiards_balls.jpg/200px-Billiards_balls.jpg" width=200 border=0></a>
<div class=thumbcaption>
<div class=magnify><a class=internal title=Enlarge href="http://en.wikipedia.org/wiki/Image:Billiards_balls.jpg"><span class="" style="BORDER-TOP-WIDTH: 2px; DISPLAY: inline-block; BORDER-LEFT-WIDTH: 2px; FONT-SIZE: 0px; BORDER-LEFT-COLOR: #0000ff; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 2px; BORDER-BOTTOM-COLOR: #0000ff; VERTICAL-ALIGN: middle; CURSOR: hand; BORDER-TOP-COLOR: #0000ff; BORDER-RIGHT-WIDTH: 2px; BORDER-RIGHT-COLOR: #0000ff"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://en.wikipedia.org/skins-1.5/common/images/magnify-clip.png'); WIDTH: 1px; HEIGHT: 1px"></span></span></a></div>
Billiards balls hitting each other are a classic example applicable within the science of collision detection.</div>
</div>
</div>
<p>In physical simulation, we wish to conduct experiments, such as playing <a class=mw-redirect title=Billiards href="http://en.wikipedia.org/wiki/Billiards"><font color=#002bb8>billiards</font></a>. The <a title=Physics href="http://en.wikipedia.org/wiki/Physics"><font color=#002bb8>physics</font></a> of bouncing billiard balls are well understood, under the umbrella of <a class=mw-redirect title="Rigid body motion" href="http://en.wikipedia.org/wiki/Rigid_body_motion"><font color=#002bb8>rigid body motion</font></a> and <a title="Elastic collision" href="http://en.wikipedia.org/wiki/Elastic_collision"><font color=#002bb8>elastic collisions</font></a>. An initial description of the situation would be given, with a very precise physical description of the billiard table and balls, as well as initial positions of all the balls. Given a certain impulsion on the cue ball (probably resulting from a player hitting the ball with his cue stick), we want to calculate the trajectories, precise motion, and eventual resting places of all the balls with a <a title="Computer program" href="http://en.wikipedia.org/wiki/Computer_program"><font color=#002bb8>computer program</font></a>. A program to simulate this game would consist of several portions, one of which would be responsible for calculating the precise impacts between the billiard balls. This particular example also turns out to be <a title="Numerical stability" href="http://en.wikipedia.org/wiki/Numerical_stability"><font color=#002bb8>numerically unstable</font></a>: a small error in any calculation will cause drastic changes in the final position of the billiard balls.</p>
<p>Video games have similar requirements, with some crucial differences. While physical simulation needs to simulate real-world physics as precisely as possible, video games need to simulate real-world physics in an <em>acceptable</em> way, in <a title="Real-time computing" href="http://en.wikipedia.org/wiki/Real-time_computing"><font color=#002bb8>real time</font></a> and robustly. Compromises are allowed, so long as the resulting simulation is satisfying to the game player.</p>
<p><a id=Collision_detection_in_physical_simulation name=Collision_detection_in_physical_simulation></a></p>
<h2><span class=editsection>[<a title="Edit section: Collision detection in physical simulation" href="http://en.wikipedia.org/w/index.php?title=Collision_detection&amp;action=edit&amp;section=2"><font color=#002bb8>edit</font></a>]</span> <span class=mw-headline>Collision detection in physical simulation</span></h2>
<p>Physical simulators differ in the way they react on a collision. Some use the softness of the material to calculate a force, which will resolve the collision in the following time steps like it is in reality. Due to the low softness of some materials this is very CPU intensive. Some simulators estimate the time of collision by linear interpolation, <a title="Rollback (data management)" href="http://en.wikipedia.org/wiki/Rollback_(data_management)"><font color=#002bb8>roll back</font></a> the simulation, and calculate the collision by the more abstract methods of <a class=mw-redirect title="Conservation laws" href="http://en.wikipedia.org/wiki/Conservation_laws"><font color=#002bb8>conservation laws</font></a>.</p>
<p>Some iterate the linear interpolation (<a title="Newton's method" href="http://en.wikipedia.org/wiki/Newton%27s_method"><font color=#002bb8>Newton's method</font></a>) to calculate the time of collision with a much higher precision than the rest of the simulation. Collision detection utilizes time coherence to allow ever finer time steps without much increasing CPU demand, such as in <a title="Air traffic control" href="http://en.wikipedia.org/wiki/Air_traffic_control"><font color=#002bb8>air traffic control</font></a>.</p>
<p>After an inelastic collision, special states of sliding and resting can occur and, for example, the <a title="Open Dynamics Engine" href="http://en.wikipedia.org/wiki/Open_Dynamics_Engine"><font color=#002bb8>Open Dynamics Engine</font></a> uses constrains to simulate them. Constrains avoid inertia and thus instability. Implementation of rest by means of a <a title="Scene graph" href="http://en.wikipedia.org/wiki/Scene_graph"><font color=#002bb8>scene graph</font></a> avoids drift.</p>
<p>In other words, physical simulators usually function one of two ways, where the collision is detected <a title="A priori and a posteriori (philosophy)" href="http://en.wikipedia.org/wiki/A_priori_and_a_posteriori_(philosophy)"><em><font color=#002bb8>a posteriori</font></em></a> (after the collision occurs) or <a title="A priori and a posteriori (philosophy)" href="http://en.wikipedia.org/wiki/A_priori_and_a_posteriori_(philosophy)"><em><font color=#002bb8>a priori</font></em></a> (before the collision occurs). In addition to the <em>a posteriori</em> and <em>a priori</em> distinction, almost all modern collision detection algorithms are broken into a hierarchy of algorithms.</p>
<p><a id=A_posteriori_versus_a_priori name=A_posteriori_versus_a_priori></a></p>
<h3><span class=editsection>[<a title="Edit section: A posteriori versus a priori" href="http://en.wikipedia.org/w/index.php?title=Collision_detection&amp;action=edit&amp;section=3"><font color=#002bb8>edit</font></a>]</span> <span class=mw-headline>A posteriori versus a priori</span></h3>
<p>In the <em>a posteriori</em> case, we advance the physical simulation by a small time step, then check if any objects are intersecting, or are somehow so close to each other that we deem them to be intersecting. At each simulation step, a list of all intersecting bodies is created, and the positions and trajectories of these objects are somehow "fixed" to account for the collision. We say that this method is <em>a posteriori</em> because we typically miss the actual instant of collision, and only catch the collision after it has actually happened.</p>
<p>In the <em>a priori</em> methods, we write a collision detection algorithm which will be able to predict very precisely the trajectories of the physical bodies. The instants of collision are calculated with high precision, and the physical bodies never actually interpenetrate. We call this <em>a priori</em> because we calculate the instants of collision before we update the configuration of the physical bodies.</p>
<p>The main benefits of the <em>a posteriori</em> methods are as follows. In this case, the collision detection algorithm need not be aware of the myriad physical variables; a simple list of physical bodies is fed to the algorithm, and the program returns a list of intersecting bodies. The collision detection algorithm doesn't need to understand friction, elastic collisions, or worse, nonelastic collisions and deformable bodies. In addition, the <em>a posteriori</em> algorithms are in effect one dimension simpler than the <em>a priori</em> algorithms. Indeed, an <em>a priori</em> algorithm must deal with the time variable, which is absent from the <em>a posteriori</em> problem.</p>
<p>On the other hand, <em>a posteriori</em> algorithms cause problems in the "fixing" step, where intersections (which aren't physically correct) need to be corrected. In fact, there are some<sup class="noprint Inline-Template"><span title="The material in the vicinity of this tag may use weasel words or too-vague attribution." style="WHITE-SPACE: nowrap">[<em><a title="Wikipedia:Avoid weasel words" href="http://en.wikipedia.org/wiki/Wikipedia:Avoid_weasel_words"><font color=#002bb8>who?</font></a></em>]</span></sup> who believe that such an algorithm is inherently flawed and unstable<sup class="noprint Template-Fact"><span title="This claim needs references to reliable sources&nbsp;since August 2008" style="WHITE-SPACE: nowrap">[<em><a title="Wikipedia:Citation needed" href="http://en.wikipedia.org/wiki/Wikipedia:Citation_needed"><font color=#002bb8>citation needed</font></a></em>]</span></sup>.</p>
<p>The benefits of the <em>a priori</em> algorithms are increased fidelity and stability. It is difficult (but not completely impossible) to separate the physical simulation from the collision detection algorithm. However, in all but the simplest cases, the problem of determining ahead of time when two bodies will collide (given some initial data) has no closed form solution -- a numerical <a title="Root-finding algorithm" href="http://en.wikipedia.org/wiki/Root-finding_algorithm"><font color=#002bb8>root finder</font></a> is usually involved.</p>
<p>Some objects are in <em>resting contact</em>, that is, in collision, but neither bouncing off, nor interpenetrating, such as a vase resting on a table. In all cases, resting contact requires special treatment: If two objects collide (<em>a posteriori</em>) or slide (<em>a priori</em>) and their relative motion is below a threshold, friction becomes <a title=Stiction href="http://en.wikipedia.org/wiki/Stiction"><font color=#002bb8>stiction</font></a> and both objects are arranged in the same branch of the <a title="Scene graph" href="http://en.wikipedia.org/wiki/Scene_graph"><font color=#002bb8>scene graph</font></a>; however, some believe that it poses special problems in <em>a posteriori</em> algorithm<sup class="noprint Template-Fact"><span title="This claim needs references to reliable sources&nbsp;since February 2007" style="WHITE-SPACE: nowrap">[<em><a title="Wikipedia:Citation needed" href="http://en.wikipedia.org/wiki/Wikipedia:Citation_needed"><font color=#002bb8>citation needed</font></a></em>]</span></sup>.</p>
<p><a id=Optimization name=Optimization></a></p>
<h2><span class=editsection>[<a title="Edit section: Optimization" href="http://en.wikipedia.org/w/index.php?title=Collision_detection&amp;action=edit&amp;section=4"><font color=#002bb8>edit</font></a>]</span> <span class=mw-headline>Optimization</span></h2>
<p>The obvious approaches to collision detection for multiple objects are very slow. Checking every object against every other object will, of course, work, but is too inefficient to be used when the number of objects is at all large. Checking objects with complex geometry against each other in the obvious way, by checking each face against each other face, is itself quite slow. Thus, considerable research has been applied to speeding up the problem.</p>
<p><a id=Exploiting_temporal_coherence name=Exploiting_temporal_coherence></a></p>
<h3><span class=editsection>[<a title="Edit section: Exploiting temporal coherence" href="http://en.wikipedia.org/w/index.php?title=Collision_detection&amp;action=edit&amp;section=5"><font color=#002bb8>edit</font></a>]</span> <span class=mw-headline>Exploiting temporal coherence</span></h3>
<p>In many applications, the configuration of physical bodies from one time step to the next changes very little. Many of the objects may not move at all. Algorithms have been designed so that the calculations done in a preceding time step can be reused in the current time step, resulting in faster algorithms.</p>
<p>At the coarse level of collision detection, the objective is to find pairs of objects which might potentially intersect. Those pairs will require further analysis. An early high performance algorithm for this was developed by M. C. Lin at U.C. Berkley <a class="external autonumber" title=http://www.cs.berkeley.edu/~jfc/mirtich/collDet.html href="http://www.cs.berkeley.edu/~jfc/mirtich/collDet.html" rel=nofollow><font color=#3366bb>[1]</font></a>, who suggested using <a class=mw-redirect title="Axis-aligned bounding box" href="http://en.wikipedia.org/wiki/Axis-aligned_bounding_box"><font color=#002bb8>axis-aligned bounding boxes</font></a> for all n bodies in the scene.</p>
<p>Each box is represented by the product of three intervals (i.e., a box would be <span class=tex style="DISPLAY: inline-block; FONT-SIZE: 0px; BORDER-LEFT-COLOR: black; BACKGROUND-IMAGE: none; BORDER-BOTTOM-COLOR: black; VERTICAL-ALIGN: middle; BORDER-TOP-COLOR: black; BORDER-RIGHT-COLOR: black"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/math/1/f/3/1f371e2f64c44695e65b9c0c22f1c682.png'); WIDTH: 1px; HEIGHT: 1px"></span></span>.) A common algorithm for collision detection of bounding boxes is <a title="Sweep and prune" href="http://en.wikipedia.org/wiki/Sweep_and_prune"><font color=#002bb8>sweep and prune</font></a>. We observe that two such boxes, <span class=tex style="DISPLAY: inline-block; FONT-SIZE: 0px; BORDER-LEFT-COLOR: black; BACKGROUND-IMAGE: none; BORDER-BOTTOM-COLOR: black; VERTICAL-ALIGN: middle; BORDER-TOP-COLOR: black; BORDER-RIGHT-COLOR: black"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/math/2/b/d/2bd2da79778a74d1869d3a6a3b58eaa0.png'); WIDTH: 1px; HEIGHT: 1px"></span></span>and <span class=tex style="DISPLAY: inline-block; FONT-SIZE: 0px; BORDER-LEFT-COLOR: black; BACKGROUND-IMAGE: none; BORDER-BOTTOM-COLOR: black; VERTICAL-ALIGN: middle; BORDER-TOP-COLOR: black; BORDER-RIGHT-COLOR: black"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/math/2/9/d/29d807c3dca041bdc0d0927d8e07ef32.png'); WIDTH: 1px; HEIGHT: 1px"></span></span>intersect if, and only if, <span class=texhtml><em>I</em><sub>1</sub></span> intersects <span class=texhtml><em>J</em><sub>1</sub></span>, <span class=texhtml><em>I</em><sub>2</sub></span> intersects <span class=texhtml><em>J</em><sub>2</sub></span> and <span class=texhtml><em>I</em><sub>3</sub></span> intersects <span class=texhtml><em>J</em><sub>3</sub></span>. We suppose that, from one time step to the next, <span class=texhtml><em>I</em><sub><em>k</em></sub></span> and <span class=texhtml><em>J</em><sub><em>k</em></sub></span> intersect, then it is very likely that at the next time step, they will still intersect. Likewise, if they did not intersect in the previous time step, then they are very likely to continue not to.</p>
<p>So we reduce the problem to that of tracking, from frame to frame, which intervals do intersect. We have three lists of intervals (one for each axis) and all lists are the same length (since each list has length <span class=texhtml><em>n</em></span>, the number of bounding boxes.) In each list, each interval is allowed to intersect all other intervals in the list. So for each list, we will have an <span class=tex style="DISPLAY: inline-block; FONT-SIZE: 0px; BORDER-LEFT-COLOR: black; BACKGROUND-IMAGE: none; BORDER-BOTTOM-COLOR: black; VERTICAL-ALIGN: middle; BORDER-TOP-COLOR: black; BORDER-RIGHT-COLOR: black"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/math/6/0/7/607acaa73c762411b20745149a11e90b.png'); WIDTH: 1px; HEIGHT: 1px"></span></span><a class=mw-redirect title="Matrix (math)" href="http://en.wikipedia.org/wiki/Matrix_(math)"><font color=#002bb8>matrix</font></a> <span class=texhtml><em>M</em> = (<em>m</em><sub><em>i</em><em>j</em></sub>)</span> of zeroes and ones: <span class=texhtml><em>m</em><sub><em>i</em><em>j</em></sub></span> is 1 if intervals <span class=texhtml><em>i</em></span> and <span class=texhtml><em>j</em></span> intersect, and 0 if they do not intersect.</p>
<p>By our assumption, the matrix <span class=texhtml><em>M</em></span> associated to a list of intervals will remain essentially unchanged from one time step to the next. To exploit this, the list of intervals is actually maintained as a list of labeled endpoints. Each element of the list has the coordinate of an endpoint of an interval, as well as a unique integer identifying that interval. Then, we <a title="Sorting algorithm" href="http://en.wikipedia.org/wiki/Sorting_algorithm"><font color=#002bb8>sort</font></a> the list by coordinates, and update the matrix <span class=texhtml><em>M</em></span> as we go. It's not so hard to believe that this algorithm will work relatively quickly if indeed the configuration of bounding boxes does not change significantly from one time step to the next.</p>
<p>In the case of deformable bodies such as cloth simulation, it may not be possible to use a more specific pairwise pruning algorithm as discussed below, and an <em>n</em>-body pruning algorithm is the best that can be done.</p>
<p>If an upper bound can be placed on the velocity of the physical bodies in a scene, then pairs of objects can be pruned based on their initial distance and the size of the time step.</p>
<p><a id=Pairwise_pruning name=Pairwise_pruning></a></p>
<h3><span class=editsection>[<a title="Edit section: Pairwise pruning" href="http://en.wikipedia.org/w/index.php?title=Collision_detection&amp;action=edit&amp;section=6"><font color=#002bb8>edit</font></a>]</span> <span class=mw-headline>Pairwise pruning</span></h3>
<p>Once we've selected a pair of physical bodies for further investigation, we need to check for collisions more carefully. However, in many applications, individual objects (if they are not too deformable) are described by a set of smaller primitives, mainly triangles. So now, we have two sets of triangles, <span class=tex style="DISPLAY: inline-block; FONT-SIZE: 0px; BORDER-LEFT-COLOR: black; BACKGROUND-IMAGE: none; BORDER-BOTTOM-COLOR: black; VERTICAL-ALIGN: middle; BORDER-TOP-COLOR: black; BORDER-RIGHT-COLOR: black"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/math/b/1/5/b150f86ec8067e3bff0c182258256c37.png'); WIDTH: 1px; HEIGHT: 1px"></span></span>and <span class=tex style="DISPLAY: inline-block; FONT-SIZE: 0px; BORDER-LEFT-COLOR: black; BACKGROUND-IMAGE: none; BORDER-BOTTOM-COLOR: black; VERTICAL-ALIGN: middle; BORDER-TOP-COLOR: black; BORDER-RIGHT-COLOR: black"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/math/f/8/2/f82aabbf434b2ba44f156e032b739562.png'); WIDTH: 1px; HEIGHT: 1px"></span></span>(for simplicity, we will assume that each set has the same number of triangles.)</p>
<p>The obvious thing to do is to check all triangles <span class=texhtml><em>S</em><sub><em>j</em></sub></span> against all triangles <span class=texhtml><em>T</em><sub><em>k</em></sub></span> for collisions, but this involves <span class=texhtml><em>n</em><sup>2</sup></span> comparisons, which is highly inefficient. If possible, it is desirable to use a pruning algorithm to reduce the number of pairs of triangles we need to check.</p>
<p>The most widely used family of algorithms is known as the <em>hierarchical bounding volumes</em> method. As a preprocessing step, for each object (in our example, <span class=texhtml><em>S</em></span> and <span class=texhtml><em>T</em></span>) we will calculate a hierarchy of bounding volumes. Then, at each time step, when we need to check for collisions between <span class=texhtml><em>S</em></span> and <span class=texhtml><em>T</em></span>, the hierarchical bounding volumes are used to reduce the number of pairs of triangles under consideration. For the sake of simplicity, we will give an example using bounding spheres, although it has been noted that spheres are undesirable in many cases.<sup class="noprint Template-Fact"><span title="This claim needs references to reliable sources&nbsp;since June 2008" style="WHITE-SPACE: nowrap">[<em><a title="Wikipedia:Citation needed" href="http://en.wikipedia.org/wiki/Wikipedia:Citation_needed"><font color=#002bb8>citation needed</font></a></em>]</span></sup></p>
<p>If <span class=texhtml><em>E</em></span> is a set of triangles, we can precalculate a bounding sphere <span class=texhtml><em>B</em>(<em>E</em>)</span>. There are many ways of choosing <span class=texhtml><em>B</em>(<em>E</em>)</span>, we only assume that <span class=texhtml><em>B</em>(<em>E</em>)</span> is a sphere that completely contains <span class=texhtml><em>E</em></span> and is as small as possible.</p>
<p>Ahead of time, we can compute <span class=texhtml><em>B</em>(<em>S</em>)</span> and <span class=texhtml><em>B</em>(<em>T</em>)</span>. Clearly, if these two spheres do not intersect (and that is very easy to test,) then neither do <span class=texhtml><em>S</em></span> and <span class=texhtml><em>T</em></span>. This is not much better than an <em>n</em>-body pruning algorithm, however.</p>
<p>If <span class=tex style="DISPLAY: inline-block; FONT-SIZE: 0px; BORDER-LEFT-COLOR: black; BACKGROUND-IMAGE: none; BORDER-BOTTOM-COLOR: black; VERTICAL-ALIGN: middle; BORDER-TOP-COLOR: black; BORDER-RIGHT-COLOR: black"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/math/4/a/5/4a5f9e8499dc0a3907fc05b75ec01609.png'); WIDTH: 1px; HEIGHT: 1px"></span></span>is a set of triangles, then we can split it into two halves <span class=tex style="DISPLAY: inline-block; FONT-SIZE: 0px; BORDER-LEFT-COLOR: black; BACKGROUND-IMAGE: none; BORDER-BOTTOM-COLOR: black; VERTICAL-ALIGN: middle; BORDER-TOP-COLOR: black; BORDER-RIGHT-COLOR: black"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/math/4/e/d/4ed433aa71ab0b41dee53ea50e57ed06.png'); WIDTH: 1px; HEIGHT: 1px"></span></span>and <span class=tex style="DISPLAY: inline-block; FONT-SIZE: 0px; BORDER-LEFT-COLOR: black; BACKGROUND-IMAGE: none; BORDER-BOTTOM-COLOR: black; VERTICAL-ALIGN: middle; BORDER-TOP-COLOR: black; BORDER-RIGHT-COLOR: black"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/math/3/0/7/3079eae29bfea791f1b60a4b690ecd75.png'); WIDTH: 1px; HEIGHT: 1px"></span></span>. We can do this to <span class=texhtml><em>S</em></span> and <span class=texhtml><em>T</em></span>, and we can calculate (ahead of time) the bounding spheres <span class=texhtml><em>B</em>(<em>L</em>(<em>S</em>)),<em>B</em>(<em>R</em>(<em>S</em>))</span> and <span class=texhtml><em>B</em>(<em>L</em>(<em>T</em>)),<em>B</em>(<em>R</em>(<em>T</em>))</span>. The hope here is that these bounding spheres are much smaller than <span class=texhtml><em>B</em>(<em>S</em>)</span> and <span class=texhtml><em>B</em>(<em>T</em>)</span>. And, if, for instance, <span class=texhtml><em>B</em>(<em>S</em>)</span> and <span class=texhtml><em>B</em>(<em>L</em>(<em>T</em>))</span> do not intersect, then there is no sense in checking any triangle in <span class=texhtml><em>S</em></span> against any triangle in <span class=texhtml><em>L</em>(<em>T</em>)</span>.</p>
<p>As a precomputation, we can take each physical body (represented by a set of triangles) and recursively decompose it into a <a title="Binary tree" href="http://en.wikipedia.org/wiki/Binary_tree"><font color=#002bb8>binary tree</font></a>, where each node <span class=texhtml><em>N</em></span> represents a set of triangles, and its two children represent <span class=texhtml><em>L</em>(<em>N</em>)</span> and <span class=texhtml><em>R</em>(<em>N</em>)</span>. At each node in the tree, as a we can precompute the bounding sphere <span class=texhtml><em>B</em>(<em>N</em>)</span>.</p>
<p>When the time comes for testing a pair of objects for collision, their bounding sphere tree can be used to eliminate many pairs of triangles.</p>
<p>Many variants of the algorithms are obtained by choosing something other than a sphere for <span class=texhtml><em>B</em>(<em>T</em>)</span>. If one chooses <a class=mw-redirect title="Axis-aligned bounding box" href="http://en.wikipedia.org/wiki/Axis-aligned_bounding_box"><font color=#002bb8>axis-aligned bounding boxes</font></a>, one gets AABBTrees. <a class=mw-redirect title="Oriented bounding box" href="http://en.wikipedia.org/wiki/Oriented_bounding_box"><font color=#5a3696>Oriented bounding box</font></a> trees are called OBBTrees. Some trees are easier to update if the underlying object changes. Some trees can accommodate higher order primitives such as <a title="Spline (mathematics)" href="http://en.wikipedia.org/wiki/Spline_(mathematics)"><font color=#002bb8>splines</font></a> instead of simple triangles.</p>
<p><a id=Exact_pairwise_collision_detection name=Exact_pairwise_collision_detection></a></p>
<h3><span class=editsection>[<a title="Edit section: Exact pairwise collision detection" href="http://en.wikipedia.org/w/index.php?title=Collision_detection&amp;action=edit&amp;section=7"><font color=#002bb8>edit</font></a>]</span> <span class=mw-headline>Exact pairwise collision detection</span></h3>
<p>Once we're done pruning, we are left with a number of candidate pairs to check for exact collision detection.</p>
<p>A basic observation is that for any two <a title="Convex set" href="http://en.wikipedia.org/wiki/Convex_set"><font color=#002bb8>convex</font></a> objects which are disjoint, one can find a plane in space so that one object lies completely on one side of that plane, and the other object lies on the opposite side of that plane. This allows the development of very fast collision detection algorithms for convex objects.</p>
<p>Early work in this area involved "<a title="Separating axis theorem" href="http://en.wikipedia.org/wiki/Separating_axis_theorem"><font color=#002bb8>separating plane</font></a>" methods. Two triangles collide essentially only when they can not be separated by a plane going through three vertices. That is, if the triangles are <span class=texhtml><em>v</em><sub>1</sub>,<em>v</em><sub>2</sub>,<em>v</em><sub>3</sub></span> and <span class=texhtml><em>v</em><sub>4</sub>,<em>v</em><sub>5</sub>,<em>v</em><sub>6</sub></span> where each <span class=texhtml><em>v</em><sub><em>j</em></sub></span> is a vector in <span class=tex style="DISPLAY: inline-block; FONT-SIZE: 0px; BORDER-LEFT-COLOR: black; BACKGROUND-IMAGE: none; BORDER-BOTTOM-COLOR: black; VERTICAL-ALIGN: middle; BORDER-TOP-COLOR: black; BORDER-RIGHT-COLOR: black"><span style="DISPLAY: inline-block; FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://upload.wikimedia.org/math/c/3/5/c35ed5f43a2953196b55e5207a2c959e.png'); WIDTH: 1px; HEIGHT: 1px"></span></span>, then we can take three vertices, <span class=texhtml><em>v</em><sub><em>i</em></sub>,<em>v</em><sub><em>j</em></sub>,<em>v</em><sub><em>k</em></sub></span>, find a plane going through all three vertices, and check to see if this is a separating plane. If any such plane is a separating plane, then the triangles are deemed to be disjoint. On the other hand, if none of these planes are separating planes, then the triangles are deemed to intersect. There are twenty such planes.</p>
<p>If the triangles are coplanar, this test is not entirely successful. One can either add some extra planes, for instance, planes that are normal to triangle edges, to fix the problem entirely. In other cases, objects that meet at a flat face must necessarily also meet at an angle elsewhere, hence the overall collision detection will be able to find the collision.</p>
<p>Better methods have since been developed. Very fast algorithms are available for finding the closest points on the surface of two convex polyhedral objects. Early work by M. C. Lin <sup class=reference id=cite_ref-0><a title="" href="http://en.wikipedia.org/wiki/Collision_detection#cite_note-0"><font color=#5a3696><span>[</span>1<span>]</span></font></a></sup> used a variation on the <a title="Simplex algorithm" href="http://en.wikipedia.org/wiki/Simplex_algorithm"><font color=#002bb8>simplex algorithm</font></a> from <a title="Linear programming" href="http://en.wikipedia.org/wiki/Linear_programming"><font color=#002bb8>linear programming</font></a>. The <a class=mw-redirect title="Gilbert-Johnson-Keerthi distance algorithm" href="http://en.wikipedia.org/wiki/Gilbert-Johnson-Keerthi_distance_algorithm"><font color=#002bb8>Gilbert-Johnson-Keerthi distance algorithm</font></a> has superseded that approach. These algorithms approach constant time when applied repeatedly to pairs of stationary or slow-moving objects, when used with starting points from the previous collision check.</p>
<p>The end result of all this algorithmic work is that collision detection can be done efficiently for thousands of moving objects in real time on typical personal computers and game consoles.</p>
<p><a id=A_priori_pruning name=A_priori_pruning></a></p>
<h3><span class=editsection>[<a title="Edit section: A priori pruning" href="http://en.wikipedia.org/w/index.php?title=Collision_detection&amp;action=edit&amp;section=8"><font color=#002bb8>edit</font></a>]</span> <span class=mw-headline>A priori pruning</span></h3>
<p>Where most of the objects involved are fixed, as is typical of video games, a priori methods using precomputation can be used to speed up execution.</p>
<p>Pruning is also desirable here, both <em>n</em>-body pruning and pairwise pruning, but the algorithms must take time and the types of motions used in the underlying physical system into consideration.</p>
<p>When it comes to the exact pairwise collision detection, this is highly trajectory dependent, and one almost has to use a numerical <a title="Root-finding algorithm" href="http://en.wikipedia.org/wiki/Root-finding_algorithm"><font color=#002bb8>root-finding algorithm</font></a> to compute the instant of impact.</p>
<p>As an example, consider two triangles moving in time <span class=texhtml><em>v</em><sub>1</sub>(<em>t</em>),<em>v</em><sub>2</sub>(<em>t</em>),<em>v</em><sub>3</sub>(<em>t</em>)</span> and <span class=texhtml><em>v</em><sub>4</sub>(<em>t</em>),<em>v</em><sub>5</sub>(<em>t</em>),<em>v</em><sub>6</sub>(<em>t</em>)</span>. At any point in time, the two triangles can be checked for intersection using the twenty planes previously mentioned. However, we can do better, since these twenty planes can all be tracked in time. If <span class=texhtml><em>P</em>(<em>u</em>,<em>v</em>,<em>w</em>)</span> is the plane going through points <span class=texhtml><em>u</em>,<em>v</em>,<em>w</em></span> in <span class=tex style="DISPLAY: inline-block; FONT-SIZE: 0px; BORDER