Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlGraphics/GeometryPrimitives.cpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.visualizationlibrary.org                                               */
00005 /*                                                                                    */
00006 /*  Copyright (c) 2005-2011, Michele Bosi                                             */
00007 /*  All rights reserved.                                                              */
00008 /*                                                                                    */
00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
00010 /*  are permitted provided that the following conditions are met:                     */
00011 /*                                                                                    */
00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
00013 /*  list of conditions and the following disclaimer.                                  */
00014 /*                                                                                    */
00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
00017 /*  other materials provided with the distribution.                                   */
00018 /*                                                                                    */
00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
00029 /*                                                                                    */
00030 /**************************************************************************************/
00031 
00032 #include <vlGraphics/GeometryPrimitives.hpp>
00033 #include <vlGraphics/Geometry.hpp>
00034 #include <vlGraphics/DoubleVertexRemover.hpp>
00035 #include <vlGraphics/BezierSurface.hpp>
00036 
00037 using namespace vl;
00038 
00039 //-----------------------------------------------------------------------------
00042 ref<Geometry> vl::makeIcosphere(const vec3& pos, real diameter, int detail, bool remove_doubles)
00043 {
00044   ref<Geometry> geom = new Geometry;
00045   geom->setObjectName("Icosphere");
00046 
00047   ref<ArrayFloat3> coords = new ArrayFloat3;
00048   ref<ArrayFloat3> norms = new ArrayFloat3;
00049 
00050   ref<DrawElementsUInt> polys = new DrawElementsUInt(PT_TRIANGLES);
00051 
00052   const real X = (real)0.525731112119133606;
00053   const real Z = (real)0.850650808352039932;
00054   std::vector< vec3 > verts;
00055   verts.push_back( vec3(-X, 0, Z) );
00056   verts.push_back( vec3(X, 0, Z) );
00057   verts.push_back( vec3(-X, 0, -Z) );
00058   verts.push_back( vec3(X, 0, -Z) );
00059   verts.push_back( vec3(0, Z, X) );
00060   verts.push_back( vec3(0, Z, -X) );
00061   verts.push_back( vec3(0, -Z, X) );
00062   verts.push_back( vec3(0, -Z, -X) );
00063   verts.push_back( vec3(Z, X, 0) );
00064   verts.push_back( vec3(-Z, X, 0) );
00065   verts.push_back( vec3(Z, -X, 0) );
00066   verts.push_back( vec3(-Z, -X, 0) );
00067 
00068   int idxs[] = { 
00069     1,4,0, 4,9,0, 4,5,9, 8,5,4, 1,8,4, 
00070     1,10,8, 10,3,8, 8,3,5, 3,2,5, 3,7,2, 
00071     3,10,7, 10,6,7, 6,11,7, 6,0,11, 6,1,0,
00072     10,1,6, 11,0,9, 2,11,9, 5,2,9, 11,2,7
00073   };
00074 
00075   std::vector<int> indices;
00076   for(int i=0; i<4*5*3; ++i)
00077     indices.push_back(idxs[i]);
00078 
00079   // triangulate the icosahedron
00080   if (detail>8)
00081     detail = 8;
00082   if (detail<0)
00083     detail = 0;
00084   for(int i=0; i<detail; ++i)
00085   {
00086     std::vector<int> indices2;
00087     std::vector< vec3 > verts2;
00088     for( int j=0, idx=0; j<(int)indices.size(); j+=3)
00089     {
00090       indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++);
00091       indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++);
00092       indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++);
00093       indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++);
00094 
00095       vec3 v1 = verts[ indices[j+0] ]; v1.normalize();
00096       vec3 v2 = verts[ indices[j+1] ]; v2.normalize();
00097       vec3 v3 = verts[ indices[j+2] ]; v3.normalize();
00098       vec3 a = (v1 + v2) * 0.5f; a.normalize();
00099       vec3 b = (v2 + v3) * 0.5f; b.normalize();
00100       vec3 c = (v3 + v1) * 0.5f; c.normalize();
00101       verts2.push_back(v1); verts2.push_back( a); verts2.push_back(c);
00102       verts2.push_back( a); verts2.push_back(v2); verts2.push_back(b);
00103       verts2.push_back( a); verts2.push_back( b); verts2.push_back(c);
00104       verts2.push_back( c); verts2.push_back( b); verts2.push_back(v3);
00105     }
00106     verts = verts2;
00107     indices = indices2;
00108   }
00109 
00110   // generate sphere vertices and connection information
00111 
00112   real radius = diameter / 2;
00113 
00114   coords->resize( (int)verts.size() );
00115   norms->resize( (int)verts.size() );
00116   for( int i=0; i<(int)verts.size(); ++i )
00117   {
00118     coords->at(i) = (fvec3)(verts[i]*radius + pos);
00119     vec3 n = verts[i];
00120     n.normalize();
00121     norms->at(i) = (fvec3)n;
00122   }
00123 
00124   polys->indexBuffer()->resize( (int)indices.size() );
00125   for(int i=0; i<(int)indices.size(); ++i)
00126   {
00127     VL_CHECK( indices[i] < (int)coords->size() )
00128     polys->indexBuffer()->at(i) = indices[i];
00129   }
00130 
00131   geom->setVertexArray(coords.get());
00132   geom->setNormalArray(norms.get());
00133   geom->drawCalls()->push_back(polys.get());
00134 
00135   if (remove_doubles)
00136   {
00137     DoubleVertexRemover dvr;
00138     dvr.removeDoubles(geom.get());
00139   }
00140 
00141 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
00142   geom->makeGLESFriendly();
00143 #endif
00144 
00145   return geom;
00146 }
00147 //-----------------------------------------------------------------------------
00148 ref<Geometry> vl::makeTeapot( const vec3& origin, real diameter, int detail)
00149 {
00150   // 32 patches 4x4
00151   static const int patch_idx[] = { 
00152     1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,  15,  16, 
00153     4,   17,  18,  19,  8,   20,  21,  22,  12,  23,  24,  25,  16,  26,  27,  28, 
00154     19,  29,  30,  31,  22,  32,  33,  34,  25,  35,  36,  37,  28,  38,  39,  40, 
00155     31,  41,  42,  1,   34,  43,  44,  5,   37,  45,  46,  9,   40,  47,  48,  13, 
00156     13,  14,  15,  16,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60, 
00157     16,  26,  27,  28,  52,  61,  62,  63,  56,  64,  65,  66,  60,  67,  68,  69, 
00158     28,  38,  39,  40,  63,  70,  71,  72,  66,  73,  74,  75,  69,  76,  77,  78, 
00159     40,  47,  48,  13,  72,  79,  80,  49,  75,  81,  82,  53,  78,  83,  84,  57, 
00160     57,  58,  59,  60,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96, 
00161     60,  67,  68,  69,  88,  97,  98,  99,  92,  100, 101, 102, 96,  103, 104, 105, 
00162     69,  76,  77,  78,  99,  106, 107, 108, 102, 109, 110, 111, 105, 112, 113, 114, 
00163     78,  83,  84,  57,  108, 115, 116, 85,  111, 117, 118, 89,  114, 119, 120, 93, 
00164     121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 
00165     124, 137, 138, 121, 128, 139, 140, 125, 132, 141, 142, 129, 136, 143, 144, 133, 
00166     133, 134, 135, 136, 145, 146, 147, 148, 149, 150, 151, 152, 69,  153, 154, 155, 
00167     136, 143, 144, 133, 148, 156, 157, 145, 152, 158, 159, 149, 155, 160, 161, 69, 
00168     162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 
00169     165, 178, 179, 162, 169, 180, 181, 166, 173, 182, 183, 170, 177, 184, 185, 174, 
00170     174, 175, 176, 177, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 
00171     177, 184, 185, 174, 189, 198, 199, 186, 193, 200, 201, 190, 197, 202, 203, 194, 
00172     204, 204, 204, 204, 207, 208, 209, 210, 211, 211, 211, 211, 212, 213, 214, 215, 
00173     204, 204, 204, 204, 210, 217, 218, 219, 211, 211, 211, 211, 215, 220, 221, 222, 
00174     204, 204, 204, 204, 219, 224, 225, 226, 211, 211, 211, 211, 222, 227, 228, 229, 
00175     204, 204, 204, 204, 226, 230, 231, 207, 211, 211, 211, 211, 229, 232, 233, 212, 
00176     212, 213, 214, 215, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 
00177     215, 220, 221, 222, 237, 246, 247, 248, 241, 249, 250, 251, 245, 252, 253, 254, 
00178     222, 227, 228, 229, 248, 255, 256, 257, 251, 258, 259, 260, 254, 261, 262, 263, 
00179     229, 232, 233, 212, 257, 264, 265, 234, 260, 266, 267, 238, 263, 268, 269, 242, 
00180     270, 270, 270, 270, 279, 280, 281, 282, 275, 276, 277, 278, 271, 272, 273, 274, 
00181     270, 270, 270, 270, 282, 289, 290, 291, 278, 286, 287, 288, 274, 283, 284, 285, 
00182     270, 270, 270, 270, 291, 298, 299, 300, 288, 295, 296, 297, 285, 292, 293, 294, 
00183     270, 270, 270, 270, 300, 305, 306, 279, 297, 303, 304, 275, 294, 301, 302, 271 
00184   };
00185 
00186   // 306 vertex coordinates
00187   static const float coords[] = {
00188     1.4f, 0.0f, 2.4f, 1.4f, -0.784f, 2.4f, 0.784f, -1.4f, 2.4f, 0.0f, -1.4f, 2.4f, 1.3375f, 0.0f, 2.53125f, 
00189     1.3375f, -0.749f, 2.53125f, 0.749f, -1.3375f, 2.53125f, 0.0f, -1.3375f, 2.53125f, 1.4375f, 0.0f, 2.53125f, 
00190     1.4375f, -0.805f, 2.53125f, 0.805f, -1.4375f, 2.53125f, 0.0f, -1.4375f, 2.53125f, 1.5f, 0.0f, 2.4f, 1.5f, 
00191     -0.84f, 2.4f, 0.84f, -1.5f, 2.4f, 0.0f, -1.5f, 2.4f, -0.784f, -1.4f, 2.4f, -1.4f, -0.784f, 2.4f, -1.4f, 
00192     0.0f, 2.4f, -0.749f, -1.3375f, 2.53125f, -1.3375f, -0.749f, 2.53125f, -1.3375f, 0.0f, 2.53125f, -0.805f, 
00193     -1.4375f, 2.53125f, -1.4375f, -0.805f, 2.53125f, -1.4375f, 0.0f, 2.53125f, -0.84f, -1.5f, 2.4f, -1.5f, 
00194     -0.84f, 2.4f, -1.5f, 0.0f, 2.4f, -1.4f, 0.784f, 2.4f, -0.784f, 1.4f, 2.4f, 0.0f, 1.4f, 2.4f, -1.3375f, 
00195     0.749f, 2.53125f, -0.749f, 1.3375f, 2.53125f, 0.0f, 1.3375f, 2.53125f, -1.4375f, 0.805f, 2.53125f, -0.805f, 
00196     1.4375f, 2.53125f, 0.0f, 1.4375f, 2.53125f, -1.5f, 0.84f, 2.4f, -0.84f, 1.5f, 2.4f, 0.0f, 1.5f, 2.4f, 
00197     0.784f, 1.4f, 2.4f, 1.4f, 0.784f, 2.4f, 0.749f, 1.3375f, 2.53125f, 1.3375f, 0.749f, 2.53125f, 0.805f, 
00198     1.4375f, 2.53125f, 1.4375f, 0.805f, 2.53125f, 0.84f, 1.5f, 2.4f, 1.5f, 0.84f, 2.4f, 1.75f, 0.0f, 1.875f, 
00199     1.75f, -0.98f, 1.875f, 0.98f, -1.75f, 1.875f, 0.0f, -1.75f, 1.875f, 2.0f, 0.0f, 1.35f, 2.0f, -1.12f, 1.35f, 
00200     1.12f, -2.0f, 1.35f, 0.0f, -2.0f, 1.35f, 2.0f, 0.0f, 0.9f, 2.0f, -1.12f, 0.9f, 1.12f, -2.0f, 0.9f, 0.0f, 
00201     -2.0f, 0.9f, -0.98f, -1.75f, 1.875f, -1.75f, -0.98f, 1.875f, -1.75f, 0.0f, 1.875f, -1.12f, -2.0f, 1.35f, 
00202     -2.0f, -1.12f, 1.35f, -2.0f, 0.0f, 1.35f, -1.12f, -2.0f, 0.9f, -2.0f, -1.12f, 0.9f, -2.0f, 0.0f, 0.9f, 
00203     -1.75f, 0.98f, 1.875f, -0.98f, 1.75f, 1.875f, 0.0f, 1.75f, 1.875f, -2.0f, 1.12f, 1.35f, -1.12f, 2.0f, 
00204     1.35f, 0.0f, 2.0f, 1.35f, -2.0f, 1.12f, 0.9f, -1.12f, 2.0f, 0.9f, 0.0f, 2.0f, 0.9f, 0.98f, 1.75f, 
00205     1.875f, 1.75f, 0.98f, 1.875f, 1.12f, 2.0f, 1.35f, 2.0f, 1.12f, 1.35f, 1.12f, 2.0f, 0.9f, 2.0f, 1.12f, 0.9f, 
00206     2.0f, 0.0f, 0.45f, 2.0f, -1.12f, 0.45f, 1.12f, -2.0f, 0.45f, 0.0f, -2.0f, 0.45f, 1.5f, 0.0f, 0.225f, 1.5f, 
00207     -0.84f, 0.225f, 0.84f, -1.5f, 0.225f, 0.0f, -1.5f, 0.225f, 1.5f, 0.0f, 0.15f, 1.5f, -0.84f, 0.15f, 0.84f, 
00208     -1.5f, 0.15f, 0.0f, -1.5f, 0.15f, -1.12f, -2.0f, 0.45f, -2.0f, -1.12f, 0.45f, -2.0f, 0.0f, 0.45f, -0.84f, 
00209     -1.5f, 0.225f, -1.5f, -0.84f, 0.225f, -1.5f, 0.0f, 0.225f, -0.84f, -1.5f, 0.15f, -1.5f, -0.84f, 0.15f, 
00210     -1.5f, 0.0f, 0.15f, -2.0f, 1.12f, 0.45f, -1.12f, 2.0f, 0.45f, 0.0f, 2.0f, 0.45f, -1.5f, 0.84f, 0.225f, 
00211     -0.84f, 1.5f, 0.225f, 0.0f, 1.5f, 0.225f, -1.5f, 0.84f, 0.15f, -0.84f, 1.5f, 0.15f, 0.0f, 1.5f, 0.15f, 
00212     1.12f, 2.0f, 0.45f, 2.0f, 1.12f, 0.45f, 0.84f, 1.5f, 0.225f, 1.5f, 0.84f, 0.225f, 0.84f, 1.5f, 0.15f, 1.5f, 
00213     0.84f, 0.15f, -1.6f, 0.0f, 2.025f, -1.6f, -0.3f, 2.025f, -1.5f, -0.3f, 2.25f, -1.5f, 0.0f, 2.25f, -2.3f, 
00214     0.0f, 2.025f, -2.3f, -0.3f, 2.025f, -2.5f, -0.3f, 2.25f, -2.5f, 0.0f, 2.25f, -2.7f, 0.0f, 2.025f, -2.7f, 
00215     -0.3f, 2.025f, -3.0f, -0.3f, 2.25f, -3.0f, 0.0f, 2.25f, -2.7f, 0.0f, 1.8f, -2.7f, -0.3f, 1.8f, -3.0f, -0.3f, 
00216     1.8f, -3.0f, 0.0f, 1.8f, -1.5f, 0.3f, 2.25f, -1.6f, 0.3f, 2.025f, -2.5f, 0.3f, 2.25f, -2.3f, 0.3f, 2.025f, 
00217     -3.0f, 0.3f, 2.25f, -2.7f, 0.3f, 2.025f, -3.0f, 0.3f, 1.8f, -2.7f, 0.3f, 1.8f, -2.7f, 0.0f, 1.575f, -2.7f, 
00218     -0.3f, 1.575f, -3.0f, -0.3f, 1.35f, -3.0f, 0.0f, 1.35f, -2.5f, 0.0f, 1.125f, -2.5f, -0.3f, 1.125f, -2.65f, 
00219     -0.3f, 0.9375f, -2.65f, 0.0f, 0.9375f, -2.0f, -0.3f, 0.9f, -1.9f, -0.3f, 0.6f, -1.9f, 0.0f, 0.6f, -3.0f, 0.3f, 
00220     1.35f, -2.7f, 0.3f, 1.575f, -2.65f, 0.3f, 0.9375f, -2.5f, 0.3f, 1.125f, -1.9f, 0.3f, 0.6f, -2.0f, 0.3f, 0.9f, 
00221     1.7f, 0.0f, 1.425f, 1.7f, -0.66f, 1.425f, 1.7f, -0.66f, 0.6f, 1.7f, 0.0f, 0.6f, 2.6f, 0.0f, 1.425f, 2.6f, 
00222     -0.66f, 1.425f, 3.1f, -0.66f, 0.825f, 3.1f, 0.0f, 0.825f, 2.3f, 0.0f, 2.1f, 2.3f, -0.25f, 2.1f, 2.4f, -0.25f, 
00223     2.025f, 2.4f, 0.0f, 2.025f, 2.7f, 0.0f, 2.4f, 2.7f, -0.25f, 2.4f, 3.3f, -0.25f, 2.4f, 3.3f, 0.0f, 2.4f, 1.7f, 
00224     0.66f, 0.6f, 1.7f, 0.66f, 1.425f, 3.1f, 0.66f, 0.825f, 2.6f, 0.66f, 1.425f, 2.4f, 0.25f, 2.025f, 2.3f, 0.25f, 
00225     2.1f, 3.3f, 0.25f, 2.4f, 2.7f, 0.25f, 2.4f, 2.8f, 0.0f, 2.475f, 2.8f, -0.25f, 2.475f, 3.525f, -0.25f, 2.49375f, 
00226     3.525f, 0.0f, 2.49375f, 2.9f, 0.0f, 2.475f, 2.9f, -0.15f, 2.475f, 3.45f, -0.15f, 2.5125f, 3.45f, 0.0f, 2.5125f, 
00227     2.8f, 0.0f, 2.4f, 2.8f, -0.15f, 2.4f, 3.2f, -0.15f, 2.4f, 3.2f, 0.0f, 2.4f, 3.525f, 0.25f, 2.49375f, 2.8f, 
00228     0.25f, 2.475f, 3.45f, 0.15f, 2.5125f, 2.9f, 0.15f, 2.475f, 3.2f, 0.15f, 2.4f, 2.8f, 0.15f, 2.4f, 0.0f, 0.0f, 
00229     3.15f, 0.0f, -0.002f, 3.15f, 0.002f, 0.0f, 3.15f, 0.8f, 0.0f, 3.15f, 0.8f, -0.45f, 3.15f, 0.45f, -0.8f, 3.15f, 
00230     0.0f, -0.8f, 3.15f, 0.0f, 0.0f, 2.85f, 0.2f, 0.0f, 2.7f, 0.2f, -0.112f, 2.7f, 0.112f, -0.2f, 2.7f, 0.0f, -0.2f, 
00231     2.7f, -0.002f, 0.0f, 3.15f, -0.45f, -0.8f, 3.15f, -0.8f, -0.45f, 3.15f, -0.8f, 0.0f, 3.15f, -0.112f, -0.2f, 2.7f, 
00232     -0.2f, -0.112f, 2.7f, -0.2f, 0.0f, 2.7f, 0.0f, 0.002f, 3.15f, -0.8f, 0.45f, 3.15f, -0.45f, 0.8f, 3.15f, 0.0f, 
00233     0.8f, 3.15f, -0.2f, 0.112f, 2.7f, -0.112f, 0.2f, 2.7f, 0.0f, 0.2f, 2.7f, 0.45f, 0.8f, 3.15f, 0.8f, 0.45f, 3.15f, 
00234     0.112f, 0.2f, 2.7f, 0.2f, 0.112f, 2.7f, 0.4f, 0.0f, 2.55f, 0.4f, -0.224f, 2.55f, 0.224f, -0.4f, 2.55f, 0.0f, 
00235     -0.4f, 2.55f, 1.3f, 0.0f, 2.55f, 1.3f, -0.728f, 2.55f, 0.728f, -1.3f, 2.55f, 0.0f, -1.3f, 2.55f, 1.3f, 0.0f, 
00236     2.4f, 1.3f, -0.728f, 2.4f, 0.728f, -1.3f, 2.4f, 0.0f, -1.3f, 2.4f, -0.224f, -0.4f, 2.55f, -0.4f, -0.224f, 2.55f, 
00237     -0.4f, 0.0f, 2.55f, -0.728f, -1.3f, 2.55f, -1.3f, -0.728f, 2.55f, -1.3f, 0.0f, 2.55f, -0.728f, -1.3f, 2.4f, -1.3f, 
00238     -0.728f, 2.4f, -1.3f, 0.0f, 2.4f, -0.4f, 0.224f, 2.55f, -0.224f, 0.4f, 2.55f, 0.0f, 0.4f, 2.55f, -1.3f, 0.728f, 
00239     2.55f, -0.728f, 1.3f, 2.55f, 0.0f, 1.3f, 2.55f, -1.3f, 0.728f, 2.4f, -0.728f, 1.3f, 2.4f, 0.0f, 1.3f, 2.4f, 
00240     0.224f, 0.4f, 2.55f, 0.4f, 0.224f, 2.55f, 0.728f, 1.3f, 2.55f, 1.3f, 0.728f, 2.55f, 0.728f, 1.3f, 2.4f, 1.3f, 
00241     0.728f, 2.4f, 0.0f, 0.0f, 0.0f, 1.5f, 0.0f, 0.15f, 1.5f, 0.84f, 0.15f, 0.84f, 1.5f, 0.15f, 0.0f, 1.5f, 0.15f, 
00242     1.5f, 0.0f, 0.075f, 1.5f, 0.84f, 0.075f, 0.84f, 1.5f, 0.075f, 0.0f, 1.5f, 0.075f, 1.425f, 0.0f, 0.0f, 1.425f, 
00243     0.798f, 0.0f, 0.798f, 1.425f, 0.0f, 0.0f, 1.425f, 0.0f, -0.84f, 1.5f, 0.15f, -1.5f, 0.84f, 0.15f, -1.5f, 0.0f, 
00244     0.15f, -0.84f, 1.5f, 0.075f, -1.5f, 0.84f, 0.075f, -1.5f, 0.0f, 0.075f, -0.798f, 1.425f, 0.0f, -1.425f, 0.798f, 
00245     0.0f, -1.425f, 0.0f, 0.0f, -1.5f, -0.84f, 0.15f, -0.84f, -1.5f, 0.15f, 0.0f, -1.5f, 0.15f, -1.5f, -0.84f, 0.075f, 
00246     -0.84f, -1.5f, 0.075f, 0.0f, -1.5f, 0.075f, -1.425f, -0.798f, 0.0f, -0.798f, -1.425f, 0.0f, 0.0f, -1.425f, 0.0f, 
00247     0.84f, -1.5f, 0.15f, 1.5f, -0.84f, 0.15f, 0.84f, -1.5f, 0.075f, 1.5f, -0.84f, 0.075f, 0.798f, -1.425f, 0.0f, 1.425f, 
00248     -0.798f, 0.0f
00249   };
00250 
00251   ref<BezierSurface> teapot = new BezierSurface;
00252   const fvec3* verts = (const fvec3*)coords;
00253 
00254   for(int i=0; i<32; ++i)
00255   {
00256     ref<BezierPatch> patch = new BezierPatch(4,4);
00257     for(int j=0; j<16; ++j)
00258     {
00259       int idx = patch_idx[j+16*i]-1;
00260       VL_CHECK(idx < sizeof(coords) / coords[0])
00261       patch->points()[j] = (vec3)verts[ idx ];
00262     }
00263     teapot->patches().push_back(patch.get());
00264   }
00265   teapot->setDetail(detail);
00266   teapot->updateBezierSurface(false);
00267   real s = real(1.0) / teapot->boundingBox().width() * diameter;
00268   mat4 m = mat4::getTranslation( origin )  *
00269            mat4::getRotation(-90, 1, 0, 0) * 
00270            mat4::getScaling(s, s, s)       * 
00271            mat4::getTranslation(-teapot->boundingBox().center());
00272   teapot->transform( m );
00273 
00274   DoubleVertexRemover dvr;
00275   dvr.removeDoubles(teapot.get());
00276 
00277 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
00278   teapot->makeGLESFriendly();
00279 #endif
00280 
00281   return teapot;
00282 }
00283 //-----------------------------------------------------------------------------
00284 ref<Geometry> vl::makeUVSphere( const vec3& origin, real diameter, int phi, int theta)
00285 {
00286   ref<Geometry> geom = new Geometry;
00287   geom->setObjectName("UVSphere");
00288 
00289   diameter = diameter / 2.0f;
00290   ref<ArrayFloat3> vert3 = new ArrayFloat3;
00291   geom->setVertexArray(vert3.get());
00292 
00293   // create vertices
00294   vert3->resize( theta * phi + 2 );
00295   int vert_idx=0;
00296   vert3->at(vert_idx++) = (fvec3)(vec3(0,1*diameter,0) + origin);
00297   for(int i=0; i<theta; ++i)
00298   {
00299     for(int j=0; j<phi; ++j)
00300     {
00301       // vec3 v(1*radius,radius - radius*2*((real)i/(theta-1)),0);
00302       vec3 v(0,1*diameter,0);
00303       v = mat4::getRotation(180.0f/(theta+1)*(i+1),0,0,1) * v;
00304       v = mat4::getRotation(360.0f/phi*j,0,1,0)  * v;
00305       vert3->at(vert_idx++) = (fvec3)(v+origin);
00306     }
00307   }
00308   vert3->at(vert_idx++) = (fvec3)(vec3(0,-1*diameter,0) + origin);
00309 
00310   // side quads
00311 
00312   ref<DrawElementsUInt> quads = new DrawElementsUInt( PT_QUADS );
00313   quads->indexBuffer()->resize( (theta-1)*phi*4 );
00314   geom->drawCalls()->push_back(quads.get());
00315   int idx = 0;
00316   for(int i=0; i<theta-1; ++i)
00317   {
00318     for(int j=0; j<phi; ++j)
00319     {
00320       quads->indexBuffer()->at(idx++) = 1+phi*(i+1)+(j+0)%phi;
00321       quads->indexBuffer()->at(idx++) = 1+phi*(i+1)+(j+1)%phi;
00322       quads->indexBuffer()->at(idx++) = 1+phi*(i+0)+(j+1)%phi;
00323       quads->indexBuffer()->at(idx++) = 1+phi*(i+0)+(j+0)%phi;
00324     }
00325   }
00326 
00327   // top/bottom triangles
00328 
00329   ref<DrawElementsUInt> tris = new DrawElementsUInt( PT_TRIANGLES );
00330 
00331   tris->indexBuffer()->resize( phi*3 + phi*3 );
00332   geom->drawCalls()->push_back(tris.get());
00333   idx = 0;
00334   // top fan
00335   for(int j=0; j<phi; ++j)
00336   {
00337     tris->indexBuffer()->at(idx++) = 0;
00338     tris->indexBuffer()->at(idx++) = 1+(j+0)%phi;
00339     tris->indexBuffer()->at(idx++) = 1+(j+1)%phi;
00340   }
00341   // bottom fan
00342   for(int j=0; j<phi; ++j)
00343   {
00344     tris->indexBuffer()->at(idx++) = (int)geom->vertexArray()->size()-1;
00345     tris->indexBuffer()->at(idx++) = 1+phi*(theta-1)+(j+1)%phi;
00346     tris->indexBuffer()->at(idx++) = 1+phi*(theta-1)+(j+0)%phi;
00347   }
00348 
00349 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
00350   geom->makeGLESFriendly();
00351 #endif
00352 
00353   return geom;
00354 }
00355 //-----------------------------------------------------------------------------
00356 ref<Geometry> vl::makeCylinder( const vec3& origin, real diameter, real height, int phi, int theta, bool top, bool bottom)
00357 {
00358   ref<Geometry> geom = new Geometry;
00359   geom->setObjectName("Cylinder");
00360 
00361   diameter = diameter / 2;
00362   height = height / 2;
00363   ref<ArrayFloat3> vert3 = new ArrayFloat3;
00364   geom->setVertexArray(vert3.get());
00365 
00366   // create vertices
00367   vert3->resize( theta * phi + (top?phi+1:0) + (bottom?phi+1:0) );
00368   int vert_idx=0;
00369   for(int i=0; i<theta; ++i)
00370   {
00371     for(int j=0; j<phi; ++j)
00372     {
00373       vec3 v(1*diameter, 1*height - 2*height*((real)i/(theta-1)), 0);
00374       v = mat4::getRotation(360.0f/phi*j,0,1,0) * v;
00375       vert3->at(vert_idx++) = (fvec3)(v + origin);
00376     }
00377   }
00378 
00379   // side quads
00380 
00381   ref<DrawElementsUInt> quads = new DrawElementsUInt( PT_QUADS );
00382   quads->indexBuffer()->resize( (theta-1)*phi*4 );
00383   geom->drawCalls()->push_back(quads.get());
00384   int idx = 0;
00385   for(int i=0; i<theta-1; ++i)
00386   {
00387     for(int j=0; j<phi; ++j)
00388     {
00389       quads->indexBuffer()->at(idx++) = phi*(i+1)+(j+0)%phi;
00390       quads->indexBuffer()->at(idx++) = phi*(i+1)+(j+1)%phi;
00391       quads->indexBuffer()->at(idx++) = phi*(i+0)+(j+1)%phi;
00392       quads->indexBuffer()->at(idx++) = phi*(i+0)+(j+0)%phi;
00393     }
00394   }
00395 
00396   // top/bottom triangles
00397 
00398   if (top)
00399   {
00400     ref<DrawElementsUInt> tris = new DrawElementsUInt( PT_TRIANGLE_FAN );
00401     tris->indexBuffer()->resize( phi+2 );
00402     geom->drawCalls()->push_back(tris.get());
00403     idx = 0;
00404 
00405     int fan_center = vert_idx;
00406     vert3->at(vert_idx++) = (fvec3)(vec3(0, height, 0)  + origin);
00407     for(int j=0; j<phi; ++j)
00408     {
00409       vec3 v(1*diameter, height, 0);
00410       v = mat4::getRotation(360.0f/phi*j,0,1,0) * v;
00411       vert3->at(vert_idx++) = (fvec3)(v + origin);
00412     }
00413 
00414     // top fan
00415     tris->indexBuffer()->at(idx++) = fan_center;
00416     for(int j=0; j<phi+1; ++j)
00417       tris->indexBuffer()->at(idx++) = 1+fan_center+j%phi;
00418   }
00419 
00420   if (bottom)
00421   {
00422     ref<DrawElementsUInt> tris = new DrawElementsUInt( PT_TRIANGLE_FAN );
00423     tris->indexBuffer()->resize( phi+2 );
00424     geom->drawCalls()->push_back(tris.get());
00425     idx = 0;
00426 
00427     int fan_center = vert_idx;
00428     vert3->at(vert_idx++) = (fvec3)(vec3(0, -height, 0) + origin);
00429     for(int j=0; j<phi; ++j)
00430     {
00431       vec3 v(1*diameter, - height, 0);
00432       v = mat4::getRotation(360.0f/phi*j,0,1,0) * v;
00433       vert3->at(vert_idx++) = (fvec3)(v + origin);
00434     }
00435 
00436     // bottom fan
00437     tris->indexBuffer()->at(idx++) = fan_center;
00438     for(int j=0; j<phi+1; ++j)
00439       tris->indexBuffer()->at(idx++) = 1+fan_center+(phi -1 - j%phi);
00440   }
00441 
00442 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
00443   geom->makeGLESFriendly();
00444 #endif
00445 
00446   return geom;
00447 }
00448 //-----------------------------------------------------------------------------
00449 ref<Geometry> vl::makeTorus( const vec3& origin, real diameter, real thickness, int phi, int theta, float tex_coords )
00450 {
00451   ref<Geometry> geom = new Geometry;
00452   geom->setObjectName("Torus");
00453 
00454   // create vertices
00455   thickness /= 2.0f;
00456   const real radius = diameter / 2.0f - thickness;
00457 
00458   // vertices
00459   ref<ArrayFloat3> vert3 = new ArrayFloat3;
00460   geom->setVertexArray(vert3.get());
00461   vert3->resize( (phi+1) * (theta+1) );
00462 
00463   // normals
00464   ref<ArrayFloat3> norm3 = new ArrayFloat3;
00465   geom->setNormalArray(norm3.get());
00466   norm3->resize( (phi+1) * (theta+1) );
00467 
00468   // texture coordinates
00469   ref<ArrayFloat2> texc2 = new ArrayFloat2;
00470   if (tex_coords)
00471   {
00472     geom->setTexCoordArray(0,texc2.get());
00473     texc2->resize( (phi+1) * (theta+1) );
00474   }
00475 
00476   int vect_idx = 0;
00477   for(int i=0; i<theta+1; ++i)
00478   {
00479     for(int j=0; j<phi+1; ++j)
00480     {
00481       vec3 v(thickness, 0, 0);
00482       vec3 o(radius, 0, 0);
00483       v = mat4::getRotation(360.0f/phi*j,0,1,0) * v;
00484       v = mat4::getRotation(360.0f/theta*i,0,0,1) * v;
00485       o = mat4::getRotation(360.0f/theta*i,0,0,1) * o;
00486 
00487       if (tex_coords)
00488         texc2->at(vect_idx) = fvec2((float)i/theta,(float)j/phi) * tex_coords;
00489 
00490       vert3->at(vect_idx) = (fvec3)(v + o + origin);
00491 
00492       norm3->at(vect_idx) = (fvec3)v.normalize();
00493 
00494       ++vect_idx;
00495     }
00496   }
00497 
00498   ref<DrawElementsUInt> polys = new DrawElementsUInt( PT_QUADS );
00499   geom->drawCalls()->push_back(polys.get());
00500   int idx = 0;
00501   polys->indexBuffer()->resize( theta * phi * 4 );
00502   // create indices
00503   for(int i=0; i<theta; ++i)
00504   {
00505     for(int j=0; j<phi; ++j)
00506     {
00507       int i1 = i+1;
00508       polys->indexBuffer()->at(idx++) = (phi+1)*i +(j+0);
00509       polys->indexBuffer()->at(idx++) = (phi+1)*i +(j+1);
00510       polys->indexBuffer()->at(idx++) = (phi+1)*i1+(j+1);
00511       polys->indexBuffer()->at(idx++) = (phi+1)*i1+(j+0);
00512     }
00513   }
00514 
00515 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
00516   geom->makeGLESFriendly();
00517 #endif
00518 
00519   return geom;
00520 }
00521 //-----------------------------------------------------------------------------
00522 ref<Geometry> vl::makeBox( const AABB& aabb, bool tex_coords )
00523 {
00524   return makeBox( aabb.minCorner(), aabb.maxCorner(), tex_coords );
00525 }
00526 //-----------------------------------------------------------------------------
00527 ref<Geometry> vl::makeBox( const vec3& min, const vec3& max, bool tex_coords )
00528 {
00529   return makeBox( (min+max)*0.5, max.x()-min.x(), max.y()-min.y(), max.z()-min.z(), tex_coords );
00530 }
00531 //-----------------------------------------------------------------------------
00532 ref<Geometry> vl::makeBox( const vec3& origin, real xside, real yside, real zside, bool tex_coords)
00533 {
00534   /*
00535   1--------0 
00536   |\       |\
00537   | 5------|-4
00538   2--------3 |
00539    \|       \| 
00540     6------- 7 
00541   */
00542 
00543   ref<Geometry> geom = new Geometry;
00544   geom->setObjectName("Box");
00545 
00546   ref<ArrayFloat3> vert3 = new ArrayFloat3;
00547   geom->setVertexArray(vert3.get());
00548 
00549   real x=xside/2.0f;
00550   real y=yside/2.0f;
00551   real z=zside/2.0f;
00552 
00553   fvec3 a0( (fvec3)(vec3(+x,+y,+z) + origin) );
00554   fvec3 a1( (fvec3)(vec3(-x,+y,+z) + origin) );
00555   fvec3 a2( (fvec3)(vec3(-x,-y,+z) + origin) );
00556   fvec3 a3( (fvec3)(vec3(+x,-y,+z) + origin) );
00557   fvec3 a4( (fvec3)(vec3(+x,+y,-z) + origin) );
00558   fvec3 a5( (fvec3)(vec3(-x,+y,-z) + origin) );
00559   fvec3 a6( (fvec3)(vec3(-x,-y,-z) + origin) );
00560   fvec3 a7( (fvec3)(vec3(+x,-y,-z) + origin) );
00561 
00562 #if defined(VL_OPENGL)
00563 
00564   fvec3 verts[] = {
00565    a1, a2, a3, a0,
00566    a2, a6, a7, a3,
00567    a6, a5, a4, a7,
00568    a5, a1, a0, a4,
00569    a0, a3, a7, a4,
00570    a5, a6, a2, a1
00571   };
00572 
00573   ref<DrawArrays> polys = new DrawArrays(PT_QUADS, 0, 24);
00574   geom->drawCalls()->push_back( polys.get() );
00575   vert3->resize( 24  );
00576   memcpy(vert3->ptr(), verts, sizeof(verts));
00577 
00578   if(tex_coords)
00579   {
00580     fvec2 texc[] = {
00581       fvec2(0,1), fvec2(0,0), fvec2(1,0), fvec2(1,1),
00582       fvec2(0,1), fvec2(0,0), fvec2(1,0), fvec2(1,1),
00583       fvec2(1,0), fvec2(1,1), fvec2(0,1), fvec2(0,0),
00584       fvec2(0,1), fvec2(0,0), fvec2(1,0), fvec2(1,1),
00585       fvec2(0,0), fvec2(1,0), fvec2(1,1), fvec2(0,1),
00586       fvec2(1,1), fvec2(0,1), fvec2(0,0), fvec2(1,0)
00587     };
00588     ref<ArrayFloat2> tex_array = new ArrayFloat2;
00589     geom->setTexCoordArray(0, tex_array.get());
00590     tex_array->resize( vert3->size() );
00591     memcpy(tex_array->ptr(), texc, sizeof(texc));
00592   }
00593 
00594 #else
00595   
00596   fvec3 verts[] = {
00597     a1, a2, a3, a3, a0, a1,
00598     a2, a6, a7, a7, a3, a2,
00599     a6, a5, a4, a4, a7, a6,
00600     a5, a1, a0, a0, a4, a5,
00601     a0, a3, a7, a7, a4, a0,
00602     a5, a6, a2, a2, a1, a5
00603   };
00604 
00605   ref<DrawArrays> polys = new DrawArrays(PT_TRIANGLES, 0, 36);
00606   geom->drawCalls()->push_back( polys.get() );
00607   vert3->resize( 36 );
00608   memcpy(vert3->ptr(), verts, sizeof(verts));
00609 
00610   if(tex_coords)
00611   {
00612     fvec2 texc[] = {
00613       fvec2(0,1), fvec2(0,0), fvec2(1,0), fvec2(1,0), fvec2(1,1), fvec2(0,1), 
00614       fvec2(0,1), fvec2(0,0), fvec2(1,0), fvec2(1,0), fvec2(1,1), fvec2(0,1), 
00615       fvec2(1,0), fvec2(1,1), fvec2(0,1), fvec2(0,1), fvec2(0,0), fvec2(1,0), 
00616       fvec2(0,1), fvec2(0,0), fvec2(1,0), fvec2(1,0), fvec2(1,1), fvec2(0,1), 
00617       fvec2(0,0), fvec2(1,0), fvec2(1,1), fvec2(1,1), fvec2(0,1), fvec2(0,0), 
00618       fvec2(1,1), fvec2(0,1), fvec2(0,0), fvec2(0,0), fvec2(1,0), fvec2(1,1), 
00619     };
00620     ref<ArrayFloat2> tex_array = new ArrayFloat2;
00621     geom->setTexCoordArray(0, tex_array.get());
00622     tex_array->resize( vert3->size() );
00623     memcpy(tex_array->ptr(), texc, sizeof(texc));
00624   }
00625 
00626 #endif
00627 
00628 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
00629   geom->makeGLESFriendly();
00630 #endif
00631 
00632   return geom;
00633 }
00634 //-----------------------------------------------------------------------------
00635 ref<Geometry> vl::makePyramid( const vec3& origin, real side, real height)
00636 {
00637   ref<Geometry> geom = new Geometry;
00638   geom->setObjectName("Pyramid");
00639 
00640   ref<ArrayFloat3> vert3 = new ArrayFloat3;
00641   geom->setVertexArray(vert3.get());
00642 
00643   real x = side   / 2.0f;
00644   real y = height;
00645   real z = side   / 2.0f;
00646 
00647   fvec3 a0( (fvec3)(vec3(+0,+y,+0) + origin) );
00648   fvec3 a1( (fvec3)(vec3(-x,+0,-z) + origin) );
00649   fvec3 a2( (fvec3)(vec3(-x,-0,+z) + origin) );
00650   fvec3 a3( (fvec3)(vec3(+x,-0,+z) + origin) );
00651   fvec3 a4( (fvec3)(vec3(+x,+0,-z) + origin) );
00652 
00653   ref<DrawArrays> polys = new DrawArrays(PT_TRIANGLES, 0, 6*3);
00654   geom->drawCalls()->push_back( polys.get() );
00655 
00656   vert3->resize(6*3);
00657 
00658   vert3->at(0)  = a4; vert3->at(1)  = a2; vert3->at(2)  = a1; 
00659   vert3->at(3)  = a2; vert3->at(4)  = a4; vert3->at(5)  = a3; 
00660   vert3->at(6)  = a4; vert3->at(7)  = a1; vert3->at(8)  = a0; 
00661   vert3->at(9)  = a1; vert3->at(10) = a2; vert3->at(11) = a0;
00662   vert3->at(12) = a2; vert3->at(13) = a3; vert3->at(14) = a0;
00663   vert3->at(15) = a3; vert3->at(16) = a4; vert3->at(17) = a0;
00664 
00665 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
00666   geom->makeGLESFriendly();
00667 #endif
00668 
00669   return geom;
00670 }
00671 //-----------------------------------------------------------------------------
00672 ref<Geometry> vl::makeCone( const vec3& origin, real diameter, real height, int phi, bool bottom)
00673 {
00674   ref<Geometry> geom = new Geometry;
00675   geom->setObjectName("Cone");
00676 
00677   ref<ArrayFloat3> vert3 = new ArrayFloat3;
00678   geom->setVertexArray( vert3.get() );
00679 
00680   diameter = diameter / 2;
00681 
00682   vert3->resize( phi+1 + (bottom?phi+1:0) );
00683   // create vertices
00684   int vert_idx = 0;
00685   vert3->at(vert_idx++) = (fvec3)(vec3(0, height/2.0f, 0) + origin);
00686   for(int j=0; j<phi; ++j)
00687   {
00688     vec3 v(1*diameter, -height/2.0f, 0);
00689     v = mat4::getRotation(360.0f/phi*j,0,1,0) * v;
00690     vert3->at(vert_idx++) = (fvec3)(v + origin);
00691   }
00692 
00693   // top fan
00694   ref<DrawElementsUInt> top_fan = new DrawElementsUInt(PT_TRIANGLE_FAN);
00695   top_fan->indexBuffer()->resize(phi+2);
00696   geom->drawCalls()->push_back(top_fan.get());
00697   int idx = 0;
00698   top_fan->indexBuffer()->at(idx++) = 0;
00699   for(int j=0; j<phi+1; ++j)
00700     top_fan->indexBuffer()->at(idx++) = 1+j%phi;
00701 
00702   // bottom fan
00703   if (bottom)
00704   {
00705     int fan_center = vert_idx;
00706     vert3->at(vert_idx++) = (fvec3)(vec3(0, -height/2.0f, 0) + origin);
00707     for(int j=0; j<phi; ++j)
00708     {
00709       vec3 v(1*diameter, -height/2.0f, 0);
00710       v = mat4::getRotation(360.0f/phi*j,0,1,0) * v;
00711       vert3->at(vert_idx++) = (fvec3)(v + origin);
00712     }
00713 
00714     ref<DrawElementsUInt> bottom_fan = new DrawElementsUInt(PT_TRIANGLE_FAN);
00715     bottom_fan->indexBuffer()->resize(phi+2);
00716     geom->drawCalls()->push_back(bottom_fan.get());
00717     idx = 0;
00718     bottom_fan->indexBuffer()->at(idx++) = fan_center;
00719     for(int j=0; j<phi+1; ++j)
00720       bottom_fan->indexBuffer()->at(idx++) = fan_center+1+(phi-1-j%phi);
00721   }
00722 
00723 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
00724   geom->makeGLESFriendly();
00725 #endif
00726 
00727   return geom;
00728 }
00729 //-----------------------------------------------------------------------------
00731 ref<Geometry> vl::makeGrid( const vec3& origin, real xside, real zside, int x, int z, bool gen_texcoords, fvec2 uv0, fvec2 uv1)
00732 {
00733   ref<Geometry> geom = new Geometry;
00734   geom->setObjectName("Grid");
00735 
00736   ref<ArrayFloat3> vert3 = new ArrayFloat3;
00737   ref<ArrayFloat2> text2 = new ArrayFloat2;
00738   geom->setVertexArray( vert3.get() );
00739 
00740   VL_CHECK(x>=2)
00741   VL_CHECK(z>=2)
00742   real dx = xside / (x-1);
00743   real dz = zside / (z-1);
00744   xside /= 2.0f;
00745   zside /= 2.0f;
00746 
00747   vert3->resize( x * z );
00748   if (gen_texcoords)
00749   {
00750     geom->setTexCoordArray( 0, text2.get() );
00751     text2->resize( x * z );
00752   }
00753 
00754   // create vertices
00755   int vert_idx = 0;
00756   for(int i=0; i<z; ++i)
00757     for(int j=0; j<x; ++j, ++vert_idx)
00758     {
00759       vert3->at(vert_idx) = (fvec3)(vec3(-xside+j*dx, 0, -zside+i*dz) + origin);
00760       if (gen_texcoords)
00761       {
00762         float tu = (float)j/(x-1); // 0 .. 1
00763         float tv = (float)i/(z-1); // 0 .. 1
00764         text2->at(vert_idx).s() = (1.0f-tu) * uv0.s() + tu * uv1.s();
00765         text2->at(vert_idx).t() = (1.0f-tv) * uv0.t() + tv * uv1.t();
00766       }
00767     }
00768 
00769   // create indices
00770   ref<DrawElementsUInt> polys = new DrawElementsUInt(PT_QUADS);
00771   geom->drawCalls()->push_back(polys.get());
00772   int idx = 0;
00773   polys->indexBuffer()->resize( (z-1)*(x-1)*4 );
00774   for(int i=0; i<z-1; ++i)
00775   {
00776     for(int j=0; j<x-1; ++j)
00777     {
00778       polys->indexBuffer()->at(idx++) = j+0 + x*(i+1);
00779       polys->indexBuffer()->at(idx++) = j+1 + x*(i+1);
00780       polys->indexBuffer()->at(idx++) = j+1 + x*(i+0);
00781       polys->indexBuffer()->at(idx++) = j+0 + x*(i+0);
00782     }
00783   }
00784 
00785 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
00786   geom->makeGLESFriendly();
00787 #endif
00788 
00789   return geom;
00790 }
00791 //-----------------------------------------------------------------------------
00792 ref<Geometry> vl::makePoints( const std::vector< vec3>& pos, const fvec4& color )
00793 {
00794   ref<Geometry> geom = new Geometry;
00795   geom->setObjectName("Points");
00796 
00797   ref<ArrayFloat3> vert3 = new ArrayFloat3;
00798   ref<ArrayFloat4> col4 = new ArrayFloat4;
00799   geom->setVertexArray( vert3.get() );
00800   geom->setColorArray( col4.get() );
00801   vert3->resize( (int)pos.size() );
00802   col4->resize( (int)pos.size() );
00803 
00804   for(unsigned i=0; i<pos.size(); ++i)
00805   {
00806     vert3->at(i) = (fvec3)pos[i];
00807     col4->at(i)  = color;
00808   }
00809 
00810   geom->drawCalls()->push_back( new DrawArrays(PT_POINTS, 0, vert3->size() ));
00811 
00812 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
00813   geom->makeGLESFriendly();
00814 #endif
00815 
00816   return geom;
00817 }
00818 //-----------------------------------------------------------------------------
00819 ref<Geometry> vl::makeIcosahedron( const vec3& origin, real diameter )
00820 {
00821   ref<Geometry> geom = new Geometry;
00822   geom->setObjectName("Icosahedron");
00823 
00824   ref<ArrayFloat3> vert3 = new ArrayFloat3;
00825   geom->setVertexArray(vert3.get());
00826 
00827   // red book 1.4 p89
00828 
00829   const real x = 0.525731112119133606f / 1.0f;
00830   const real z = 0.850650808352039932f / 1.0f;
00831   const real radius = diameter / 2.0f;
00832 
00833   vert3->resize( 12 );
00834 
00835   vert3->at(0) = (fvec3)(origin + vec3(-x, 0.0, +z)*radius);
00836   vert3->at(1) = (fvec3)(origin + vec3(+x, 0.0, +z)*radius);
00837   vert3->at(2) = (fvec3)(origin + vec3(-x, 0.0, -z)*radius);
00838   vert3->at(3) = (fvec3)(origin + vec3(+x, 0.0, -z)*radius);
00839 
00840   vert3->at(4) = (fvec3)(origin + vec3(0.0, +z, +x)*radius);
00841   vert3->at(5) = (fvec3)(origin + vec3(0.0, +z, -x)*radius);
00842   vert3->at(6) = (fvec3)(origin + vec3(0.0, -z, +x)*radius);
00843   vert3->at(7) = (fvec3)(origin + vec3(0.0, -z, -x)*radius);
00844 
00845   vert3->at(8)  = (fvec3)(origin + vec3(+z, +x, 0.0)*radius);
00846   vert3->at(9)  = (fvec3)(origin + vec3(-z, +x, 0.0)*radius);
00847   vert3->at(10) = (fvec3)(origin + vec3(+z, -x, 0.0)*radius);
00848   vert3->at(11) = (fvec3)(origin + vec3(-z, -x, 0.0)*radius);
00849 
00850   unsigned short faces[20][3] = 
00851   {
00852     {1,4,0},  {4,9,0},  {4,5,9},  {8,5,4},  {1,8,4}, 
00853     {1,10,8}, {10,3,8}, {8,3,5},  {3,2,5},  {3,7,2}, 
00854     {3,10,7}, {10,6,7}, {6,11,7}, {6,0,11}, {6,1,0}, 
00855     {10,1,6}, {11,0,9}, {2,11,9}, {5,2,9},  {11,2,7}
00856   };
00857 
00858   ref<DrawElementsUShort> polys = new DrawElementsUShort(PT_TRIANGLES);
00859   geom->drawCalls()->push_back(polys.get());
00860   polys->indexBuffer()->resize(20*3);
00861   memcpy(polys->indexBuffer()->ptr(), faces, sizeof(faces));
00862 
00863 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
00864   geom->makeGLESFriendly();
00865 #endif
00866 
00867   return geom;
00868 }
00869 //-----------------------------------------------------------------------------
00870 ref<Geometry> vl::makeCircle( vec3 origin, real radius, int slices )
00871 {
00872   ref< Geometry > geom = new Geometry;
00873   geom->setObjectName("Circle");
00874 
00875   ref< ArrayFloat3 > points = new ArrayFloat3;
00876   geom->setVertexArray(points.get());
00877   points->resize( slices );
00878   for(int i=0; i<slices; ++i)
00879   {
00880     real t = 360.0f * i / slices;
00881     vec3 v = mat4::getRotation(t,0,1,0) * vec3(radius,0,0) + origin;
00882     points->at(i) = (fvec3)v;
00883   }
00884   geom->drawCalls()->push_back( new DrawArrays(PT_LINE_LOOP, 0, points->size()) );
00885 
00886 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
00887   geom->makeGLESFriendly();
00888 #endif
00889 
00890   return geom;
00891 }
00892 //-----------------------------------------------------------------------------
00893 ref<Geometry> vl::makeCapsule(float radius, float height, int segments, ECapsuleCap top_cap, ECapsuleCap bottom_cap, const fvec4& top_col, const fvec4& bottom_col)
00894 {
00895   float height2 = height / 2.0f;
00896 
00897   ref<Geometry> geom = new Geometry;
00898   geom->setObjectName("Capsule");
00899 
00900   ref<ArrayFloat3> vert_array = new ArrayFloat3;
00901   ref<ArrayFloat4> colr_array = new ArrayFloat4;
00902   geom->setVertexArray(vert_array.get());
00903   geom->setColorArray (colr_array.get());
00904   std::vector<fvec3> verts;
00905   std::vector<fvec4> cols;
00906 
00907   // upper
00908   for(int i=0; i<segments; ++i)
00909   {
00910     float a = (float)i/segments*fPi*2.0f;
00911     fvec3 v(::cos(a)*radius,+height2,::sin(a)*radius);
00912     verts.push_back(v);
00913     cols.push_back(top_col);
00914   }
00915   if (top_col != bottom_col)
00916   {
00917     // mid-upper
00918     for(int i=0; i<segments; ++i)
00919     {
00920       float a = (float)i/segments*fPi*2.0f;
00921       fvec3 v(::cos(a)*radius,0,::sin(a)*radius);
00922       verts.push_back(v);
00923       cols.push_back(top_col);
00924     }
00925     // mid-lower
00926     for(int i=0; i<segments; ++i)
00927     {
00928       float a = (float)i/segments*fPi*2.0f;
00929       fvec3 v(::cos(a)*radius,0,::sin(a)*radius);
00930       verts.push_back(v);
00931       cols.push_back(bottom_col);
00932     }
00933     ref<DrawElementsUInt> de_up = new DrawElementsUInt(PT_QUADS);
00934     ref<DrawElementsUInt> de_lo = new DrawElementsUInt(PT_QUADS);
00935     geom->drawCalls()->push_back(de_up.get());
00936     geom->drawCalls()->push_back(de_lo.get());
00937     de_up->indexBuffer()->resize(segments*4);
00938     de_lo->indexBuffer()->resize(segments*4);
00939     int upup = segments*0;
00940     int uplo = segments*1;
00941     int loup = segments*2;
00942     int lolo = segments*3;
00943     for(int i=0; i<segments; ++i)
00944     {
00945       int i1 = (i+1) % segments;
00946       de_up->indexBuffer()->at(i*4+3) = uplo + i;
00947       de_up->indexBuffer()->at(i*4+2) = uplo + i1;
00948       de_up->indexBuffer()->at(i*4+1) = upup + i1;
00949       de_up->indexBuffer()->at(i*4+0) = upup + i;
00950 
00951       de_lo->indexBuffer()->at(i*4+3) = lolo + i;
00952       de_lo->indexBuffer()->at(i*4+2) = lolo + i1;
00953       de_lo->indexBuffer()->at(i*4+1) = loup + i1;
00954       de_lo->indexBuffer()->at(i*4+0) = loup + i;
00955     }
00956   }
00957   else
00958   {
00959     ref<DrawElementsUInt> de_up = new DrawElementsUInt(PT_QUADS);
00960     geom->drawCalls()->push_back(de_up.get());
00961     de_up->indexBuffer()->resize(segments*4);
00962     int upup = segments*0;
00963     int uplo = segments*1;
00964     for(int i=0; i<segments; ++i)
00965     {
00966       int i1 = (i+1) % segments;
00967       de_up->indexBuffer()->at(i*4+3) = uplo + i;
00968       de_up->indexBuffer()->at(i*4+2) = uplo + i1;
00969       de_up->indexBuffer()->at(i*4+1) = upup + i1;
00970       de_up->indexBuffer()->at(i*4+0) = upup + i;
00971     }
00972   }
00973   // lower
00974   for(int i=0; i<segments; ++i)
00975   {
00976     float a = (float)i/segments*fPi*2.0f;
00977     fvec3 v(::cos(a)*radius,-height2,::sin(a)*radius);
00978     verts.push_back(v);
00979     cols.push_back(bottom_col);
00980   }
00981   // caps
00982   if (top_cap == CC_FlatCap)
00983   {
00984     int start = verts.size();
00985     for(int i=0; i<segments; ++i)
00986     {
00987       float a = (float)i/segments*fPi*2.0f;
00988       fvec3 v(::cos(a)*radius,+height2,::sin(a)*radius);
00989       verts.push_back(v);
00990       cols.push_back(top_col);
00991     }
00992     ref<DrawElementsUInt> de = new DrawElementsUInt(PT_TRIANGLE_FAN);
00993     geom->drawCalls()->push_back(de.get());
00994     de->indexBuffer()->resize(segments);
00995     for(int i=0,j=segments; j--; ++i)
00996       de->indexBuffer()->at(j) = start + i;
00997   }
00998   if (bottom_cap == CC_FlatCap)
00999   {
01000     int start = verts.size();
01001     for(int i=0; i<segments; ++i)
01002     {
01003       float a = (float)i/segments*fPi*2.0f;
01004       fvec3 v(::cos(a)*radius,-height2,::sin(a)*radius);
01005       verts.push_back(v);
01006       cols.push_back(bottom_col);
01007     }
01008     ref<DrawElementsUInt> de = new DrawElementsUInt(PT_TRIANGLE_FAN);
01009     geom->drawCalls()->push_back(de.get());
01010     de->indexBuffer()->resize(segments);
01011     for(int i=0; i<segments; ++i)
01012       de->indexBuffer()->at(i) = start + i;
01013   }
01014   int segments2 = segments/3; if (segments2<2) segments2=2;  
01015   if (top_cap == CC_RoundedCap)
01016   {
01017     int start = verts.size();
01018     for(int j=0; j<segments2; ++j)
01019     {
01020       float aj = (float)j/segments2*fPi/2.0f;
01021       for(int i=0; i<segments; ++i)
01022       {
01023         float a = (float)i/segments*360;
01024         fvec3 v(::cos(aj)*radius,::sin(aj)*radius,0);
01025         verts.push_back(fmat4::getRotation(a,0,1,0) * v + fvec3(0,height2,0));
01026         cols.push_back(top_col);
01027       }
01028     }
01029     // top point
01030     verts.push_back(fvec3(0,+height2+radius,0));
01031     cols.push_back(top_col);
01032 
01033     ref<DrawElementsUInt> de_quads = new DrawElementsUInt(PT_QUADS);
01034     geom->drawCalls()->push_back(de_quads.get());
01035     de_quads->indexBuffer()->resize(segments*(segments2-1)*4);
01036     for(int j=0,idx=0; j<segments2-1; ++j)
01037     {
01038       int uplo = start+segments*j;
01039       int upup = start+segments*(j+1);
01040       for(int i=0; i<segments; ++i)
01041       {
01042         int i1 = (i+1) % segments;
01043         de_quads->indexBuffer()->at(idx++) = uplo + i;
01044         de_quads->indexBuffer()->at(idx++) = uplo + i1;
01045         de_quads->indexBuffer()->at(idx++) = upup + i1;
01046         de_quads->indexBuffer()->at(idx++) = upup + i;
01047       }
01048     }
01049 
01050     ref<DrawElementsUInt> de = new DrawElementsUInt(PT_TRIANGLE_FAN);
01051     geom->drawCalls()->push_back(de.get());
01052     de->indexBuffer()->resize(segments+2);
01053     de->indexBuffer()->at(0) = (GLuint)verts.size()-1;
01054     for(int i=0; i<segments+1; ++i)
01055       de->indexBuffer()->at(i+1) = (GLuint)verts.size()-1-segments+i%segments;
01056   }
01057   if (bottom_cap == CC_RoundedCap)
01058   {
01059     int start = verts.size();
01060     for(int j=0; j<segments2; ++j)
01061     {
01062       float aj = (float)j/segments2*fPi/2.0f;
01063       for(int i=0; i<segments; ++i)
01064       {
01065         float a = -(float)i/segments*360;
01066         fvec3 v(::cos(aj)*radius,-::sin(aj)*radius,0);
01067         verts.push_back(fmat4::getRotation(a,0,1,0) * v + fvec3(0,-height2,0));
01068         cols.push_back(bottom_col);
01069       }
01070     }
01071     // bottom point
01072     verts.push_back(fvec3(0,-height2-radius,0));
01073     cols.push_back(bottom_col);
01074 
01075     ref<DrawElementsUInt> de_quads = new DrawElementsUInt(PT_QUADS);
01076     geom->drawCalls()->push_back(de_quads.get());
01077     de_quads->indexBuffer()->resize(segments*(segments2-1)*4);
01078     for(int j=0,idx=0; j<segments2-1; ++j)
01079     {
01080       int uplo = start+segments*j;
01081       int upup = start+segments*(j+1);
01082       for(int i=0; i<segments; ++i)
01083       {
01084         int i1 = (i+1) % segments;
01085         de_quads->indexBuffer()->at(idx++) = uplo + i;
01086         de_quads->indexBuffer()->at(idx++) = uplo + i1;
01087         de_quads->indexBuffer()->at(idx++) = upup + i1;
01088         de_quads->indexBuffer()->at(idx++) = upup + i;
01089       }
01090     }
01091 
01092     ref<DrawElementsUInt> de = new DrawElementsUInt(PT_TRIANGLE_FAN);
01093     geom->drawCalls()->push_back(de.get());
01094     de->indexBuffer()->resize(segments+2);
01095     de->indexBuffer()->at(0) = (GLuint)verts.size()-1;
01096     for(int i=0; i<segments+1; ++i)
01097       de->indexBuffer()->at(i+1) = (GLuint)verts.size()-1-segments+i%segments;
01098   }
01099 
01100   vert_array->initFrom(verts);
01101   colr_array->initFrom(cols);
01102 
01103 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
01104   geom->makeGLESFriendly();
01105 #endif
01106 
01107   return geom;
01108 }
01109 //-----------------------------------------------------------------------------

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:37.
Permission is granted to use this page to write and publish articles regarding Visualization Library.